Example #1
0
    def __init__(self):
        self._debug = EventCollector("MDBmanager")
        exists = True
        if not (os.path.isfile(path_db() + MDBmanager.__DbName)):
            self._debug.warning("Db not found!")
            exists = False
        try:
            self.db = sqlite3.connect(path_db() + MDBmanager.__DbName)
            if not exists:
                self._debug.success("Writing the basic information in a new db")
                self.db.execute("CREATE TABLE INSTALLED ("
                                "NAME CHAR(20) PRIMARY KEY NOT NULL,"
                                "SIGNED CHAR(32) NOT NULL,"
                                "VERSION REAL NOT NULL,"
                                "AUTHOR CHAR(200),"
                                "ABOUT TEXT,"
                                "TAG TEXT,"
                                "TAGGED TEXT,"
                                "MODULES TEXT,"
                                "BASE TEXT,"
                                "LIB TEXT,"
                                "APPDATA TEXT,"
                                "MANP TEXT);")
        except:
            self._debug.error("Db connection Error!")
            raise DbIOError()

        self._debug.success("Opened database successfully")
        self.__selfinit()
Example #2
0
class MDBmanager(object):
    __DbName = "Installed.DB"

    def __init__(self):
        self._debug = EventCollector("MDBmanager")
        exists = True
        if not (os.path.isfile(path_db() + MDBmanager.__DbName)):
            self._debug.warning("Db not found!")
            exists = False
        try:
            self.db = sqlite3.connect(path_db() + MDBmanager.__DbName)
            if not exists:
                self._debug.success("Writing the basic information in a new db")
                self.db.execute("CREATE TABLE INSTALLED ("
                                "NAME CHAR(20) PRIMARY KEY NOT NULL,"
                                "SIGNED CHAR(32) NOT NULL,"
                                "VERSION REAL NOT NULL,"
                                "AUTHOR CHAR(200),"
                                "ABOUT TEXT,"
                                "TAG TEXT,"
                                "TAGGED TEXT,"
                                "MODULES TEXT,"
                                "BASE TEXT,"
                                "LIB TEXT,"
                                "APPDATA TEXT,"
                                "MANP TEXT);")
        except:
            self._debug.error("Db connection Error!")
            raise DbIOError()

        self._debug.success("Opened database successfully")
        self.__selfinit()

    @staticmethod
    def listtostring(_list):
        """Convert list to String with separator"""
        tmp = ""
        if not _list:
            return str()
        for elem in _list:
            tmp = tmp + elem + ","
        idx = len(tmp) - 1
        if tmp[idx] == ",":
            tmp = tmp[:idx]
        return tmp

    @staticmethod
    def stringtolist(_str):
        return split(_str, ",")

    def install(self, pack):
        self.__selfinit()
        try:
            self.__unpack(pack)
            if self.__manifestdecoder():
                rtncoll = self.__collisiondetector()
                if rtncoll:
                    if self.__installer(rtncoll):
                        self.db.execute(
                            "INSERT INTO INSTALLED (NAME,SIGNED,VERSION,AUTHOR,ABOUT,TAG,TAGGED,LIB,MODULES,BASE,APPDATA,MANP) VALUES ('%s', '%s' ,'%f' ,'%s','%s','%s','%s','%s','%s','%s','%s','%s');"
                            % (self.name, self.signed, self.version, self.author, self.about, self.tag, self.tagged,
                               MDBmanager.listtostring(self.lib), MDBmanager.listtostring(self.modules),
                               MDBmanager.listtostring(self.base), MDBmanager.listtostring(self.appdata),
                               MDBmanager.listtostring(self.manp)))
                        self.db.commit()
                        psuccess("Installation complete!", ec=self._debug)
                    else:
                        perror("Installation failed!", ec=self._debug)
                else:
                    perror("Installation aborted!", ec=self._debug)
            else:
                perror("Installation failed, manifest misconfigured!", ec=self._debug)
            try:
                shutil.rmtree(path_tinst())
            except shutil.Error:
                perror("Can't delete Temp folder!")
        except FileNotFoundError as e:
            self._debug.error(pack + " not found! Process Aborted!")
            raise e

    def uninstall(self, name):
        pinfo("Uninstalling " + name + "...", ec=self._debug)
        data = self.db.execute("SELECT LIB,MODULES,BASE,APPDATA,MANP FROM INSTALLED WHERE NAME='%s';" % name).fetchone()
        if data is None:
            self._debug.error(name + " not found!")
            raise DbKeyError()
        self.__moduninstaller(MDBmanager.stringtolist(data[0]), path_lib())
        self.__moduninstaller(MDBmanager.stringtolist(data[1]), path_modules())
        self.__moduninstaller(MDBmanager.stringtolist(data[2]), path_base())
        self.__moduninstaller(MDBmanager.stringtolist(data[3]), path_appdata())
        self.__moduninstaller(MDBmanager.stringtolist(data[4]), path_man())
        self.db.execute("DELETE FROM INSTALLED WHERE NAME='%s';" % name)
        self.db.commit()
        psuccess("Uninstall complete!", ec=self._debug)
        return

    def entry_exists(self, idname):
        exists = self.db.execute("SELECT COUNT(*) FROM INSTALLED WHERE NAME = '%s';" % idname).fetchone()
        return bool(exists[0])

    def search(self, tag):
        tmp = list()
        tag = self.db.execute("SELECT TAGGED FROM INSTALLED WHERE INSTR(tag,'%s');" % tag).fetchall()
        for row in tag:
            spl = split(row[0], ",")
            for mod in spl:
                tmp.append(mod)
        return tuple(tmp)

    def get_tag(self):
        tmp = list()
        tag = self.db.execute("SELECT TAG FROM INSTALLED;").fetchall()
        for row in tag:
            _list = MDBmanager.stringtolist(row[0])
            for elem in _list:
                if elem not in tmp:
                    tmp.append(elem)
        return tuple(tmp)

    def get_pack_name_from_module(self, modname):
        rtn = None
        packname = self.db.execute("SELECT NAME FROM INSTALLED WHERE INSTR(MODULES,'%s');" % modname).fetchone()
        if packname is not None:
            rtn = packname[0]
        return rtn

    def get_module_from_pack_name(self, packname):
        if self.entry_exists(packname):
            module = self.db.execute("SELECT TAGGED FROM INSTALLED WHERE NAME='%s';" % packname).fetchone()
            return MDBmanager.stringtolist(module[0])
        else:
            raise DbKeyError

    def get_pack_version(self, packname):
        if self.entry_exists(packname):
            version = self.db.execute("SELECT VERSION FROM INSTALLED WHERE NAME='%s';" % packname).fetchone()
            return version[0]
        else:
            raise DbKeyError

    def get_base_from_pack_name(self, packname):
        if self.entry_exists(packname):
            base = self.db.execute("SELECT BASE FROM INSTALLED WHERE NAME='%s';" % packname).fetchone()
            return MDBmanager.stringtolist(base[0])
        else:
            raise DbKeyError

    def get_lib_from_pack_name(self, packname):
        if self.entry_exists(packname):
            lib = self.db.execute("SELECT LIB FROM INSTALLED WHERE NAME='%s';" % packname).fetchone()
            return MDBmanager.stringtolist(lib[0])
        else:
            raise DbKeyError

    def get_manp_from_pack_name(self, packname):
        if self.entry_exists(packname):
            manp = self.db.execute("SELECT MANP FROM INSTALLED WHERE NAME='%s';" % packname).fetchone()
            return MDBmanager.stringtolist(manp[0])
        else:
            raise DbKeyError

    def get_pack_author(self, packname):
        if self.entry_exists(packname):
            author = self.db.execute("SELECT AUTHOR FROM INSTALLED WHERE NAME='%s';" % packname).fetchone()
            return author[0]
        else:
            raise DbKeyError

    def get_pack_about(self, packname):
        if self.entry_exists(packname):
            about = self.db.execute("SELECT ABOUT FROM INSTALLED WHERE NAME='%s';" % packname).fetchone()
            return about[0]
        else:
            raise DbKeyError

    def get_installed_pack(self):
        tmp = list()
        tag = self.db.execute("SELECT NAME FROM INSTALLED;").fetchall()
        for row in tag:
            for data in row:
                tmp.append(data)
        return tuple(tmp)

    def get_installed_modules(self):
        tmp = list()
        tag = self.db.execute("SELECT TAGGED FROM INSTALLED;").fetchall()
        for row in tag:
            spl = split(row[0], ",")
            for mod in spl:
                tmp.append(mod)
        return tuple(tmp)

    def __unpack(self, path):
        """Unpacking installer bundle"""
        self._debug.info("Unpacking " + path + "...")
        with zipfile.ZipFile(path, "r") as bundle:
            bundle.extractall(path_tinst())
        self._debug.success("Unpacking done!")
        return

    def __manifestdecoder(self):
        """Manifest decoder"""
        self._debug.info("Checking manifest.ifest in: " + path_tinst())  #
        manifest = path_tinst() + "manifest.ifest"
        if os.path.isfile(manifest):
            pinfo("Decoding package manifest...", ec=self._debug)
            with open(manifest, "r") as manF:
                for line in manF:
                    if not "#" in line:
                        regex = re.search("(Name:)(.+)", line, re.M | re.I)
                        if regex:
                            self.name = regex.group(2)
                        regex = re.search("(Signed:)(.+)", line, re.M | re.I)
                        if regex:
                            self.signed = regex.group(2)
                        regex = re.search("(Version:)([0-9]+\.[0-9]+)", line, re.M | re.I)
                        if regex:
                            try:
                                self.version = float(regex.group(2))
                            except TypeError:
                                perror("Field version not recognized!", ec=self._debug)
                                return False
                        regex = re.search("(Author:)(.+)", line, re.M | re.I)
                        if regex:
                            self.author = regex.group(2)
                        regex = re.search("(About:)(.+)", line, re.M | re.I)
                        if regex:
                            self.about = regex.group(2)
                        regex = re.search("(Tag:)(.+)", line, re.M | re.I)
                        if regex:
                            self.tag = (regex.group(2))
                        regex = re.search("(Modules:)(.+)", line, re.M | re.I)
                        if regex:
                            self.modules += MDBmanager.stringtolist(regex.group(2))
                        regex = re.search("(Base:)(.+)", line, re.M | re.I)
                        if regex:
                            self.base += MDBmanager.stringtolist(regex.group(2))
                        regex = re.search("(Lib:)(.+)", line, re.M | re.I)
                        if regex:
                            self.lib += MDBmanager.stringtolist(regex.group(2))
                        regex = re.search("(AppData:)(.+)", line, re.M | re.I)
                        if regex:
                            self.appdata += MDBmanager.stringtolist(regex.group(2))
                        regex = re.search("(Manp:)(.+)", line, re.M | re.I)
                        if regex:
                            self.manp += MDBmanager.stringtolist(regex.group(2))
            if not self.modules:
                self.tag = str()
            if not self.name:
                perror("Package name missing!", ec=self._debug)
                return False
            if not self.signed:
                perror("The package does not have a signature!", ec=self._debug)
                return False
            if self.version == -1:
                perror("Missing package version!", ec=self._debug)
                return False
            if not self.modules and not self.base and not self.lib and not self.manp:
                perror("Empty package or misconfigured, nothing to install!", ec=self._debug)
                return False
            psuccess("Decoding successfully completed!", ec=self._debug)
            return True
        else:
            perror("Manifest not found, process aborted!", ec=self._debug)
            return False

    def __collisiondetector(self):
        self._debug.info("Searching collisions...")  #
        data = self.db.execute("SELECT SIGNED FROM INSTALLED WHERE NAME='%s';" % self.name).fetchone()
        if data is not None:
            self._debug.warning("Collisions detected!")  #
            if data[0] == self.signed:
                self._debug.info("Signatures matching!")  #
                pinfo("Update package %s in progress..." % self.name)
                pinfo("Checking package version...", ec=self._debug)
                version = self.get_pack_version(self.name)
                if self.version < version:
                    perror("The package version is older than the one currently installed!", ec=self._debug)
                    return CDK_Error
                elif self.version == version:
                    pwarning("The version of the installed package matches that of the package to be installed!",
                             ec=self._debug)
                    return CDK_Error
                self.db.execute("DELETE FROM INSTALLED WHERE SIGNED='%s';" % self.signed)
                return CDK_Update
            else:
                self._debug.error("Wrong signature, process aborted!")  #
                return CDK_Error
        self._debug.success("... All OK!")  #
        return CDK_New_Pack

    def __modinstaller(self, src, dst, colldata, tag=False):
        if len(src):
            pinfo("New entry for " + dst + ":\n" + str(src), ec=self._debug)
            for i in range(len(src)):
                file = path_tinst() + src[i]
                if os.path.isfile(file):
                    fexists = os.path.isfile(dst + src[i])
                    if fexists and (colldata == CDK_Update) or not fexists:
                        shutil.copy2(file, dst)
                        if tag:
                            self.tagged += src[i].replace(".py", "") + ","
                    else:
                        perror("The package has a file with a name that already exists, installation canceled", ec=self._debug)
                        raise MinstErr
                else:
                    dexists = os.path.isdir(dst + src[i])
                    if dexists and (colldata == CDK_Update) or not dexists:
                        try:
                            shutil.rmtree(dst + src[i])
                        except FileNotFoundError:
                            pass
                        shutil.move(file, dst)
                        # Searching files for tag
                        if tag:
                            for rtag in os.listdir(dst+src[i]):
                                if os.path.isfile(dst + src[i] + os.sep + rtag) and not rtag.startswith("_"):
                                    self.tagged += src[i]+"."+rtag.replace(".py", "")+","
                    else:
                        perror("The package has a directory with a name that already exists, installation canceled",
                               ec=self._debug)
                        return MinstErr
        return 0

    def __moduninstaller(self, mod, src):
        for entry in mod:
            pinfo("Deleting " + entry + " from: " + str(src), ec=self._debug)
            try:
                if os.path.isfile(src + entry):
                    os.remove(src + entry)
                elif os.path.isdir(src + entry):
                    shutil.rmtree(src + entry)
            except BaseException as e:
                perror(str(e))
                self._debug.error(str(e))
        return

    def __installer(self, colldata):
        self._debug.info("Installing...")
        try:
            self.__modinstaller(self.modules, path_modules(), colldata, True)
            self.__modinstaller(self.base, path_base(), colldata)
            self.__modinstaller(self.lib, path_lib(), colldata)
            self.__modinstaller(self.appdata, path_appdata(), colldata)
            self.__modinstaller(self.manp, path_man(), colldata)
        except MinstErr:
            return False
        except BaseException as e:
            perror(str(e) + "\tRollBack!", ec=self._debug)
            self.__moduninstaller(self.modules, path_modules())
            self.__moduninstaller(self.base, path_base())
            self.__moduninstaller(self.lib, path_lib())
            self.__moduninstaller(self.appdata, path_appdata())
            self.__moduninstaller(self.manp, path_man())
            return False
        return True

    def __selfinit(self):
        self.name = None
        self.signed = None
        self.version = -1
        self.author = None
        self.about = None
        self.tag = str()
        self.tagged = str()
        self.modules = []
        self.base = []
        self.lib = []
        self.appdata = []
        self.manp = []
        return