Example #1
0
def make_launcher(filename, dropins_dir=DROPINS_DIR):
    dropins = find_dropins(filename, dropins_dir)
    if not dropins:
        return Gio.DesktopAppInfo.new_from_filename(filename)

    desktop_entry = load_desktop_entry_with_dropins(filename, dropins)

    data = GLib.Bytes(ini_to_string(desktop_entry).encode('utf-8'))
    keyfile = GLib.KeyFile()
    keyfile.load_from_bytes(data, 0)
    return Gio.DesktopAppInfo.new_from_keyfile(keyfile)
Example #2
0
    def makeKeyFile(self, file_path, kwargs):
        if 'KeyFile' in kwargs:
            return kwargs['KeyFile']

        keyfile = GLib.KeyFile()

        if file_path is not None:
            keyfile.load_from_file(file_path, util.KEY_FILE_FLAGS)

        util.fillKeyFile(keyfile, kwargs)
        return keyfile
Example #3
0
    def writeMenu(self, menu, **kwargs):
        if menu is not None:
            file_id = os.path.split(menu.get_desktop_file_path())[1]
            file_path = menu.get_desktop_file_path()
            keyfile = GLib.KeyFile()
            keyfile.load_from_file(file_path, util.KEY_FILE_FLAGS)
        elif menu is None and 'Name' not in kwargs:
            raise Exception('New menus need a name')
        else:
            file_id = util.getUniqueFileId(kwargs['Name'], '.directory')
            keyfile = GLib.KeyFile()

        util.fillKeyFile(keyfile, kwargs)

        contents, length = keyfile.to_data()

        f = open(os.path.join(util.getUserDirectoryPath(), file_id), 'w')
        f.write(contents)
        f.close()
        return file_id
def extract_appimage_version(basename, appimg_io: t.IO):
    """
    Saves 'data' to a temporary file with the given basename, executes it (in a sandbox)
    with --appimage-extract to unpack it, and scrapes the version number out of the
    first .desktop file it finds.
    """

    with tempfile.TemporaryDirectory() as tmpdir:
        appimage_path = os.path.join(tmpdir, basename)

        header = ELFFile(appimg_io).header
        offset = header["e_shoff"] + header["e_shnum"] * header["e_shentsize"]
        appimg_io.seek(offset)

        log.info("Writing %s to %s with offset %i", basename, appimage_path,
                 offset)

        with open(appimage_path, "wb") as fp:
            chunk = appimg_io.read(1024**2)
            while chunk:
                fp.write(chunk)
                chunk = appimg_io.read(1024**2)

        bwrap = check_bwrap()
        bwrap_args = [
            "--bind",
            tmpdir,
            tmpdir,
            "--die-with-parent",
            "--new-session",
        ]

        args = ["unsquashfs", "-no-progress", appimage_path]

        log.debug("$ %s", " ".join(args))
        p = run_command(
            args,
            cwd=tmpdir,
            env=clear_env(os.environ),
            bwrap=bwrap,
            bwrap_args=bwrap_args,
        )

        if p.returncode != 0:
            log.error("AppImage extraction failed\n%s", p.stderr)
            p.check_returncode()

        for desktop in glob.glob(
                os.path.join(tmpdir, "squashfs-root", "*.desktop")):
            kf = GLib.KeyFile()
            kf.load_from_file(desktop, GLib.KeyFileFlags.NONE)
            return kf.get_string(GLib.KEY_FILE_DESKTOP_GROUP,
                                 "X-AppImage-Version")
Example #5
0
def _get_repofile_repo_url(path):
    kf = GLib.KeyFile()

    try:
        if kf.load_from_file(str(path), GLib.KeyFileFlags.NONE):
            url = kf.get_string("Flatpak Repo", "Url")

            return url
    except GLib.Error as e:
        print(e.message)

    return None
Example #6
0
    def _get_keyfile():
        """Load keyfile from CONFIG_FILE

        Returns:
            keyfile containing settings
        """
        _keyfile = GLib.KeyFile()
        try:
            _keyfile.load_from_file(CONFIG_FILE, GLib.KeyFileFlags.KEEP_COMMENTS)
        except GLib.Error as error:
            error_message(error)
        finally:
            return _keyfile
Example #7
0
    def _get_permissions(self):
        if self._permissions is not None:
            return self._permissions

        info = GLib.KeyFile()
        info.load_from_file(self.FLATPAK_INFO, GLib.KeyFileFlags.NONE)
        permissions = info.get_value("Context", "filesystems")

        if permissions is not None:
            self._permissions = set(permissions.split(";"))
        else:
            self._permissions = set()

        return self._permissions
Example #8
0
def load_password(app):
    key_file = GLib.KeyFile()

    try:
        key_file.load_from_file(app.current.get_path(),
                GLib.KeyFileFlags.NONE)
    except Exception as e:
        log('error loading key_file: {}', e)
        return False

    try:
        not_after = int(key_file.get_string('Ask', 'NotAfter'))
    except Exception as e:
        log('error loading Ask.NotAfter: {}', e)
        return False

    now = time.clock_gettime(1)
    if not_after > 0 and not_after < now:
        return False

    try:
        app.socket = key_file.get_string('Ask', 'Socket')
    except Exception as e:
        log('error loading Ask.Socket: {}', e)
        return False

    try:
        message = key_file.get_string('Ask',
                'Message').encode('utf-8').decode('unicode-escape')
    except Exception as e:
        message = 'Please Enter System Password!'
    app.status_icon.set_property('tooltip_text', message)

    try:
        icon = key_file.get_string('Ask', 'Icon')
    except Exception as e:
        icon = 'dialog-password'
    app.status_icon.set_property('icon_name', icon)

    n = Notify.Notification.new(app.status_icon.get_property('title'),
            message, icon)
    n.set_timeout(5000)
    n.connect('closed',
            lambda *_: app.status_icon.set_property('visible', True))
    n.add_action('enter_pw', 'Enter password', status_icon_activate, app)
    n.show()
    app.notification = n
    return True
Example #9
0
    def _load_keyfile(self):
        self.keyfile = GLib.KeyFile()

        try:
            self.keyfile.load_from_file(self.path.as_posix(),
                                        GLib.KeyFileFlags.NONE)
        except GLib.Error as e:
            if e.code == GLib.FileError.NOENT:
                logging.debug("Auth: No group code file, making one.")
                self.path.touch()
            else:
                logging.debug(
                    "Auth: Could not load existing keyfile (%s): %s" %
                    (CONFIG_FOLDER, e.message))
                self.path.unlink()
                self.path.touch()
Example #10
0
    def _has_permission_for(self, permission):
        # not using flatpak, so access to all
        if not os.path.exists(self.FLATPAK_INFO):
            return True

        info = GLib.KeyFile()
        info.load_from_file(self.FLATPAK_INFO, GLib.KeyFileFlags.NONE)
        permissions = info.get_value("Context", "filesystems")

        if permissions is None:
            return False
        if f"!{permission}" in permissions:
            return False
        if permission in permissions:
            return True

        return False
def extract_appimage_version(basename, data):
    """
    Saves 'data' to a temporary file with the given basename, executes it (in a sandbox)
    with --appimage-extract to unpack it, and scrapes the version number out of the
    first .desktop file it finds.
    """
    with tempfile.TemporaryDirectory() as tmpdir:
        appimage_path = os.path.join(tmpdir, basename)
        with open(appimage_path, "wb") as fp:
            fp.write(data)

        args = []
        bwrap = _check_bwrap()
        unappimage = _check_unappimage()

        if bwrap:
            args.extend(
                [
                    "--bind",
                    tmpdir,
                    tmpdir,
                    "--die-with-parent",
                    "--new-session",
                    "--unshare-all",
                ]
            )

        if unappimage:
            args.extend(["unappimage", appimage_path])
        else:
            os.chmod(appimage_path, 0o755)
            args.extend([appimage_path, "--appimage-extract"])

        log.debug("$ %s", " ".join(args))
        p = run_command(args, cwd=tmpdir, bwrap=bwrap)

        if p.returncode != 0:
            log.error("--appimage-extract failed\n%s", p.stderr)
            p.check_returncode()

        for desktop in glob.glob(os.path.join(tmpdir, "squashfs-root", "*.desktop")):
            kf = GLib.KeyFile()
            kf.load_from_file(desktop, GLib.KeyFileFlags.NONE)
            return kf.get_string(GLib.KEY_FILE_DESKTOP_GROUP, "X-AppImage-Version")
Example #12
0
    def copyItem(self, item, new_parent, before=None, after=None):
        dom = self.__getMenu(new_parent).dom
        file_path = item.get_desktop_file_path()
        keyfile = GLib.KeyFile()
        keyfile.load_from_file(file_path, util.KEY_FILE_FLAGS)
        util.fillKeyFile(keyfile, dict(Categories=[], Hidden=False))

        file_id = util.getUniqueFileId(os.path.basename(file_path).split(".desktop", 1)[0], ".desktop")
        out_path = os.path.join(util.getUserItemPath(), file_id)

        contents = keyfile.to_data()[0]

        with open(out_path, 'w') as f:
            f.write(contents)

        self.__addItem(new_parent, file_id, dom)
        self.__positionItem(new_parent, ('Item', file_id), before, after)
        self.__addUndo([self.__getMenu(new_parent), ('Item', file_id)])
        self.save()
        return file_id
Example #13
0
    def __find_thumbnailers(self):
        path_list = GLib.get_system_data_dirs()
        path_list.append(GLib.get_user_data_dir())
        file_list = []
        for path in path_list:
            file_list.extend(
                glob.glob(os.path.join(path, "thumbnailers", "*.thumbnailer")))

        for filename in file_list:
            kf = GLib.KeyFile()
            try:
                kf.load_from_file(filename, GLib.KeyFileFlags.NONE)
                cmd = kf.get_string("Thumbnailer Entry", "Exec")
                mime_types = kf.get_string_list("Thumbnailer Entry",
                                                "MimeType")
            except GLib.GError:
                continue
            if cmd and mime_types:
                for mime_type in mime_types:
                    self.all_mime_types[mime_type] = cmd
def find_best_matching_config_file():
    '''Get a GKeyFile structure for the first config file.

    This searches all three config directories in priority order, similar
    to the way that eos-companion-app-configuration-manager does it.
    '''
    keyfile = GLib.KeyFile()

    for config_file_candidate_path in COMPANION_APP_CONFIG_FILES:
        try:
            keyfile.load_from_file(config_file_candidate_path,
                                   GLib.KeyFileFlags.NONE)
        except GLib.Error as error:
            if error.matches(GLib.file_error_quark(), GLib.FileError.NOENT):
                continue

            raise error

        return keyfile

    return None
Example #15
0
    def copyItem(self, item, new_parent, before=None, after=None):
        dom = self.dom
        file_path = item.get_desktop_file_path()
        keyfile = GLib.KeyFile()
        keyfile.load_from_file(file_path, util.KEY_FILE_FLAGS)

        util.fillKeyFile(keyfile, dict(Categories=[], Hidden=False))

        app_info = item.get_app_info()
        file_id = util.getUniqueFileId(
            app_info.get_name().replace(os.sep, '-'), '.desktop')
        out_path = os.path.join(util.getUserItemPath(), file_id)

        contents, length = keyfile.to_data()

        with open(out_path, 'w') as f:
            f.write(contents)

        self.addItem(new_parent, file_id, dom)
        self.positionItem(new_parent, ('Item', file_id), before, after)
        self.save()
        return file_id
Example #16
0
    def __init__(self):
        GObject.Object.__init__(self)
        self.hostname = util.get_hostname()
        self.code = None
        self.ident = None

        self.cert_server = None

        self.keyfile = GLib.KeyFile()

        try:
            self.keyfile.load_from_file(
                os.path.join(CONFIG_FOLDER, CONFIG_FILE_NAME),
                GLib.KeyFileFlags.NONE)
        except GLib.Error as e:
            if e.code == GLib.FileError.NOENT:
                print("No group code file, making one.")
                pass
            else:
                print("Could not load existing settings: %s" % e.message)

        self.code = self.get_group_code()
Example #17
0
    def __init__(self):
        GObject.Object.__init__(self)
        self.hostname = util.get_hostname()
        self.code = None
        self.ident = None

        self.cert_server = None
        self.requests_lock = threading.Lock()
        self.requests = {}

        self.clean_cert_folder()

        self.keyfile = GLib.KeyFile()

        try:
            self.keyfile.load_from_file(os.path.join(CONFIG_FOLDER, CONFIG_FILE_NAME), GLib.KeyFileFlags.NONE)
        except GLib.Error as e:
            if e.code == GLib.FileError.NOENT:
                logging.debug("Auth: No group code file, making one.")
                pass
            else:
                logging.debug("Auth: Could not load existing keyfile (%s): %s" %(CONFIG_FOLDER, e.message))

        self.code = self.get_group_code()
Example #18
0
    def __init__(self):
        GObject.Object.__init__(self)

        # Builder
        self.ui = Gtk.Builder()
        self.ui.add_from_file(data_file("settings.ui"))

        # Dialog
        self.dialog = self.ui.get_object('settings_dialog')
        self.dialog.set_modal(True)

        self.listbox = self.ui.get_object('listbox')
        self.listbox.connect("row-activated", self.on_listbox_row_activated)

        # Preview window
        self.preview_window = self.ui.get_object('preview_window')

        self.preview_window_scroll = self.ui.get_object('preview_scroll')

        # CSS files
        self.css_files = [
            f for f in os.listdir(css_dir())
            if is_css(os.path.join(css_dir(), f))
        ]
        self.update_css_list()

        # Spin
        self.margin = self.ui.get_object('margin_spin')

        # Buttons
        self.save_button = self.ui.get_object('save_button')
        self.cancel_button = self.ui.get_object('cancel_button')

        # Switches
        self.auto_switch = self.ui.get_object('auto_switch')
        self.preview_switch = self.ui.get_object('attached_switch')

        # Signals
        self.connect_signals()

        # Settings file
        file_exists = check_config_file()

        self.key_file = GLib.KeyFile()
        self.key_file.load_from_file(config_file(), GLib.KeyFileFlags.NONE)

        # Update dialog preferences
        if file_exists:
            self.auto_switch.set_active(
                self.key_file.get_boolean("Config", "AutoPreview"))
            self.preview_switch.set_active(
                self.key_file.get_boolean("Config", "ShowPreviewWindow"))
            self.margin.set_value(self.key_file.get_integer(
                "Config", "Margin"))
        else:
            self.key_file.set_boolean("Config", "AutoPreview", False)
            self.key_file.set_boolean("Config", "ShowPreviewWindow", False)
            self.key_file.set_integer("Config", "Margin",
                                      self.margin.get_value_as_int())
            self.key_file.set_string("Config", "CSS", css_file("github.css"))
            self.key_file.save_to_file(config_file())
Example #19
0
 def copyItem(self, item):
     dom = self.dom
     file_path = item.get_desktop_file_path()
     copy_buffer = GLib.KeyFile()
     copy_buffer.load_from_file(file_path, util.KEY_FILE_FLAGS)
     return (copy_buffer, None)
Example #20
0
from xdg.IniFile import IniFile

path = '/usr/share/applications'
apps = [
    os.path.join(path, f) for f in os.listdir(path) if f.endswith('.desktop')
]
print "Test parsing %s desktop files" % len(apps)

start = time.time()
for app in apps:
    res = IniFile(app)
end = time.time()
print "xdg.IniFile:", end - start

IniFile.parse = parse

start = time.time()
for app in apps:
    res = IniFile(app)
end = time.time()
print "Patched xdg.IniFile:", end - start

from gi.repository import GLib

start = time.time()
for app in apps:
    kf = GLib.KeyFile()
    res = kf.load_from_file(app, 0)
end = time.time()
print "GLib.KeyFile:", end - start
Example #21
0
def set_s_config(key, value):
    conf = GLib.KeyFile()
    conf.load_from_file(CONF_FILE, GLib.KeyFileFlags.NONE)
    conf.set_string(GROUP, key, value)
    conf.save_to_file(CONF_FILE)
Example #22
0
 def load(self):
     self.keyfile = GLib.KeyFile()
     try:
         self.keyfile.load_from_file(self.item_path, util.KEY_FILE_FLAGS)
     except GLib.GError:
         pass
Example #23
0
def validate_desktop_file(desktop_file):  # noqa
    """Validate a known-bad desktop file in the same way GMenu/glib does, to
    give a user real information about why certain files are broken."""

    # This is a reimplementation of the validation logic in glib2's
    # gio/gdesktopappinfo.c:g_desktop_app_info_load_from_keyfile.
    # gnome-menus appears also to try to do its own validation in
    # libmenu/desktop-entries.c:desktop_entry_load, however
    # g_desktop_app_info_new_from_filename will not return a valid
    # GDesktopAppInfo in the first place if something is wrong with the
    # desktop file

    try:

        # Looks like load_from_file is not a class method??
        keyfile = GLib.KeyFile()
        keyfile.load_from_file(desktop_file, GLib.KeyFileFlags.NONE)

    except Exception as e:
        # Translators: This error is displayed when a desktop file cannot
        # be correctly read by MenuLibre. A (possibly untranslated) error
        # code is displayed.
        return _('Unable to load desktop file due to the following error:'
                 ' %s') % e

    # File is at least a valid keyfile, so can start the real desktop
    # validation
    # Start group validation
    try:
        start_group = keyfile.get_start_group()
    except GLib.Error:
        start_group = None

    if start_group != GLib.KEY_FILE_DESKTOP_GROUP:
        # Translators: This error is displayed when the first group in a
        # failing desktop file is incorrect. "Start group" can be safely
        # translated.
        return (_('Start group is invalid - currently \'%s\', should be '
                  '\'%s\'') % (start_group, GLib.KEY_FILE_DESKTOP_GROUP))

    # Type validation
    try:
        type_key = keyfile.get_string(start_group,
                                      GLib.KEY_FILE_DESKTOP_KEY_TYPE)
    except GLib.Error:
        # Translators: This error is displayed when a required key is
        # missing in a failing desktop file.
        return _('%s key not found') % 'Type'

    if type_key != GLib.KEY_FILE_DESKTOP_TYPE_APPLICATION:
        # Translators: This error is displayed when a failing desktop file
        # has an invalid value for the provided key.
        return (_('%s value is invalid - currently \'%s\', should be \'%s\'') %
                ('Type', type_key, GLib.KEY_FILE_DESKTOP_TYPE_APPLICATION))

    # Validating 'try exec' if its present
    # Invalid TryExec is a valid state. "If the file is not present or if it
    # is not executable, the entry may be ignored (not be used in menus, for
    # example)."
    try:
        try_exec = keyfile.get_string(start_group,
                                      GLib.KEY_FILE_DESKTOP_KEY_TRY_EXEC)
    except GLib.Error:
        pass

    else:
        try:
            if len(try_exec) > 0 and find_program(try_exec) is None:
                return False
        except Exception as e:
            return False

    # Validating executable
    try:
        exec_key = keyfile.get_string(start_group,
                                      GLib.KEY_FILE_DESKTOP_KEY_EXEC)
    except GLib.Error:
        return False  # LP: #1788814, Exec key is not required

    try:
        if find_program(exec_key) is None:
            return (_('%s program \'%s\' has not been found in the PATH') %
                    ('Exec', exec_key))
    except Exception as e:
        return (_('%s program \'%s\' is not a valid shell command '
                  'according to GLib.shell_parse_argv, error: %s') %
                ('Exec', exec_key, e))

    # Translators: This error is displayed for a failing desktop file where
    # errors were detected but the file seems otherwise valid.
    return _('Unknown error. Desktop file appears to be valid.')
Example #24
0
    def build(self, filename):

        # check the package has .desktop files
        print 'SOURCE\t', filename
        pkg = fedoraAppstreamPkg.AppstreamPkg(filename)
        if not pkg.contains_desktop_file:
            print 'IGNORE\t', filename, '\t', "no desktop files"
            return

        for b in self.blacklisted_packages:
            if fnmatch.fnmatch(pkg.name, b):
                print 'IGNORE\t', filename, '\t', "package is blacklisted:", pkg.name
                return

        # set up state
        if not os.path.exists('./appstream'):
            os.makedirs('./appstream')
        if not os.path.exists('./icons'):
            os.makedirs('./icons')
        # remove tmp
        if os.path.exists('./tmp'):
            shutil.rmtree('./tmp')
        os.makedirs('./tmp')

        # decompress main file and search for desktop files
        self.decompress(pkg)
        files = glob.glob("./tmp/usr/share/applications/*.desktop")
        files.sort()

        # we only need to install additional files if we're not running on
        # the builders
        decompress_files = [filename]
        for c in self.common_packages:
            if fnmatch.fnmatch(pkg.name, c[0]):
                extra_files = glob.glob("./packages/%s*.rpm" % c[1])
                for f in extra_files:
                    extra_pkg = fedoraAppstreamPkg.AppstreamPkg(f)
                    print "INFO\tAdding extra package %s for %s" % (
                        extra_pkg.name, pkg.name)
                    self.decompress(extra_pkg, extra=True)

        # open the AppStream file for writing
        has_header = False
        xml_output_file = './appstream/' + pkg.name + '.xml'
        xml = open(xml_output_file, 'w')

        # process each desktop file in the original package
        for f in files:
            config = GLib.KeyFile()
            config.load_from_file(f, GLib.KeyFileFlags.KEEP_TRANSLATIONS)

            # optional
            names = {}
            categories = None
            descriptions = {}
            comments = {}
            homepage_url = pkg.homepage_url
            icon = None
            keywords = None
            icon_fullpath = None
            skip = False
            DG = GLib.KEY_FILE_DESKTOP_GROUP
            keys, _ = config.get_keys(DG)
            for k in keys:
                if k == GLib.KEY_FILE_DESKTOP_KEY_NO_DISPLAY and config.get_boolean(
                        DG, k):
                    print 'IGNORE\t', f, '\t', "not included in the menu"
                    skip = True
                    break
                elif k == GLib.KEY_FILE_DESKTOP_KEY_TYPE and \
                     config.get_string(DG, k) != GLib.KEY_FILE_DESKTOP_TYPE_APPLICATION:
                    print 'IGNORE\t', f, '\t', "not an application"
                    skip = True
                    break
                elif k.startswith(GLib.KEY_FILE_DESKTOP_KEY_NAME):
                    m = re.match(
                        GLib.KEY_FILE_DESKTOP_KEY_NAME + '\[([^\]]+)\]', k)
                    if m:
                        names[m.group(1)] = config.get_string(DG, k)
                    else:
                        names['C'] = config.get_string(DG, k)
                elif k.startswith(GLib.KEY_FILE_DESKTOP_KEY_COMMENT):
                    m = re.match(
                        GLib.KEY_FILE_DESKTOP_KEY_COMMENT + '\[([^\]]+)\]', k)
                    if m:
                        comments[m.group(1)] = config.get_string(DG, k)
                    else:
                        comments['C'] = config.get_string(DG, k)
                elif k == GLib.KEY_FILE_DESKTOP_KEY_ICON:
                    icon = config.get_string(DG, k)
                elif k == GLib.KEY_FILE_DESKTOP_KEY_CATEGORIES:
                    categories = config.get_string_list(DG, k)
                elif k == 'Keywords':
                    keywords = config.get_string_list(DG, k)

            if skip:
                continue

            # Do not include apps without a Name
            if not 'C' in names:
                print 'IGNORE\t', f, '\t', "no Name"
                continue

            # Do not include apps without a Comment
            if not 'C' in comments:
                print 'IGNORE\t', f, '\t', "no Comment"
                continue

            if not icon:
                print 'IGNORE\t', f, '\t', "Icon unspecified"
                continue

            # We blacklist some apps by categories
            blacklisted = False
            if categories:
                for c in categories:
                    for b in self.blacklisted_categories:
                        if fnmatch.fnmatch(c, b):
                            print 'IGNORE\t', f, '\tcategory is blacklisted:', c
                            blacklisted = True
                            break
            if blacklisted:
                continue

            # check icon exists
            if icon not in self.stock_icons:
                try:
                    icon_fullpath = get_icon_filename(icon)
                except Exception as e:
                    print 'IGNORE\t', f, '\t', "icon is corrupt:", icon, str(e)
                    continue
                if not os.path.exists(icon_fullpath):
                    print 'IGNORE\t', f, '\t', "icon does not exist:", icon
                    continue

            print 'PROCESS\t', f

            basename = f.split("/")[-1]
            app_id = basename.replace('.desktop', '')

            # do we have to add any categories
            if categories:
                if self.categories_add.has_key(app_id):
                    cats_to_add = self.categories_add[app_id]
                    if cats_to_add:
                        # check it's not been added upstream
                        for cat in cats_to_add:
                            if cat in categories:
                                print 'WARNING\t' + app_id + ' now includes category ' + cat
                            else:
                                print 'INFO\tFor ' + app_id + ' manually adding category', cat
                        categories.extend(cats_to_add)

            # application is blacklisted
            for b in self.blacklisted_ids:
                if fnmatch.fnmatch(app_id, b):
                    print 'IGNORE\t', f, '\t', "application is blacklisted:", app_id
                    blacklisted = True
                    break
            if blacklisted:
                continue

            # do we have an AppData file?
            appdata_file = './tmp/usr/share/appdata/' + app_id + '.appdata.xml'
            appdata_extra_file = './appdata-extra/' + app_id + '.appdata.xml'
            if os.path.exists(appdata_file) and os.path.exists(
                    appdata_extra_file):
                print 'DELETE\t', appdata_extra_file, 'as upstream AppData file exists'
                os.remove(appdata_extra_file)

            # just use the extra file in places of the missing upstream one
            if os.path.exists(appdata_extra_file):
                appdata_file = appdata_extra_file

            # need to extract details
            if os.path.exists(appdata_file):
                data = fedoraAppstreamData.AppstreamData()
                data.extract(appdata_file)

                # check the id matches
                if data.get_id() != app_id:
                    raise StandardError('The AppData id does not match: ' +
                                        app_id)

                # check the licence is okay
                if data.get_licence() != 'CC0':
                    raise StandardError('The AppData licence is not okay: ' +
                                        app_id)

                # get optional bits
                tmp = data.get_url()
                if tmp:
                    homepage_url = tmp
                descriptions = data.get_descriptions()

            # write header
            if not has_header:
                print 'WRITING\t', xml_output_file
                xml.write("<?xml version=\"1.0\"?>\n")
                xml.write("<applications version=\"0.1\">\n")
                has_header = True

            # write content
            xml.write("  <application>\n")
            xml.write("    <id type=\"desktop\">%s</id>\n" % basename)
            xml.write("    <pkgname>%s</pkgname>\n" % pkg.name)
            xml.write("    <name>%s</name>\n" % sanitise_xml(names['C']))
            for lang in names:
                if lang != 'C':
                    xml.write("    <name xml:lang=\"%s\">%s</name>\n" %
                              (sanitise_xml(lang), sanitise_xml(names[lang])))
            xml.write("    <summary>%s</summary>\n" %
                      sanitise_xml(comments['C']))
            for lang in comments:
                if lang != 'C':
                    xml.write(
                        "    <summary xml:lang=\"%s\">%s</summary>\n" %
                        (sanitise_xml(lang), sanitise_xml(comments[lang])))
            if icon_fullpath:
                xml.write("    <icon type=\"cached\">%s</icon>\n" % app_id)
            else:
                xml.write("    <icon type=\"stock\">%s</icon>\n" % icon)
            if categories:
                xml.write("    <appcategories>\n")
                # check for a common problem
                if 'AudioVideo' in categories:
                    if not 'Audio' in categories and not 'Video' in categories:
                        print 'WARNING\t', f, '\tHas AudioVideo but not Audio or Video'
                        categories.extend(['Audio', 'Video'])
                for cat in categories:
                    if cat in self.cat_blacklist:
                        continue
                    if cat.startswith('X-'):
                        continue
                    xml.write("      <appcategory>%s</appcategory>\n" % cat)
                xml.write("    </appcategories>\n")
            if keywords:
                xml.write("    <keywords>\n")
                for keyword in keywords:
                    xml.write("      <keyword>%s</keyword>\n" %
                              sanitise_xml(keyword))
                xml.write("    </keywords>\n")
            if homepage_url:
                xml.write("    <url type=\"homepage\">%s</url>\n" %
                          sanitise_xml(homepage_url))
            if 'C' in descriptions:
                xml.write("    <description>%s</description>\n" %
                          sanitise_xml(descriptions['C']))
                for lang in descriptions:
                    if lang != 'C':
                        xml.write(
                            "    <description xml:lang=\"%s\">%s</description>\n"
                            % (sanitise_xml(lang),
                               sanitise_xml(descriptions[lang])))
            xml.write("  </application>\n")

            # copy icon
            if icon_fullpath:
                output_file = './icons/' + app_id + '.png'
                icon_file = open(icon_fullpath, 'rb')
                icon_data = icon_file.read()
                icon_file.close()
                icon_file = open(output_file, 'wb')
                icon_file.write(icon_data)
                icon_file.close()
                print 'WRITING\t', output_file

        # create AppStream XML
        xml.write("</applications>\n")
        xml.close()
        if not has_header:
            os.remove(xml_output_file)

        # create AppStream icon tar
        if has_header:
            output_file = "./appstream/%s-icons.tar" % pkg.name
            print 'WRITING\t', output_file
            tar = tarfile.open(output_file, "w")
            files = glob.glob("./icons/*.png")
            for f in files:
                tar.add(f, arcname=f.split('/')[-1])
            tar.close()

        # remove tmp
        if not os.getenv('APPSTREAM_DEBUG'):
            shutil.rmtree('./tmp')
            shutil.rmtree('./icons')
Example #25
0
#
# Released under terms on waqf public license.
#
# Curlew is free software; you can redistribute it and/or modify it 
# under the terms of the latest version waqf public license as published by 
# ojuba.org.
#
# Curlew is distributed in the hope that it will be useful, but WITHOUT 
# ANY WARRANTY; without even the implied warranty 
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#        
# The latest version of the license can be found on:
# http://waqf.ojuba.org/license

from gi.repository import GLib

from modules.consts import CONF_FILE, USR_FFILE, CONF_PATH
from os.path import exists
import os

# Create ".curlew" folder if not exist
if not exists(CONF_PATH): os.mkdir(CONF_PATH)

# Create empty config file (curlew.cfg).
if not exists(CONF_FILE):
    conf = GLib.KeyFile()
    conf.set_string('configs', 'formats_file', USR_FFILE)
    conf.save_to_file(CONF_FILE)
    conf.unref()

Example #26
0
import os
import gi
from os.path import exists, join, dirname, realpath
from gi.repository import GLib

cfg = GLib.KeyFile()

HOME = os.getenv("HOME")
CONFIG_PATH = join(HOME, '.config/keepassgtk')
CONFIG_FILE = join(CONFIG_PATH, 'config.conf')

#
# Create Config (First Run)
#

def configure():
    if not exists(CONFIG_PATH):
        create_config_dir(CONFIG_PATH)

    if not exists(CONFIG_FILE):
        create_config_file(CONFIG_FILE)


def create_config_dir(path):
    os.mkdir(path)


def create_config_file(filename):
    create_config_entry_string('settings', 'theme-variant', 'white')
    cfg.save_to_file(filename)
Example #27
0
 def get_formats_file(self):
     conf = GLib.KeyFile()
     conf.load_from_file(CONF_FILE, GLib.KeyFileFlags.NONE)
     frmts_file = conf.get_string('configs', 'formats_file')
     conf.unref()
     return frmts_file
Example #28
0
 def on_item_tree_drag_data_received(self, treeview, context, x, y, selection, info, etime):
     items = treeview.get_model()
     types_before = (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.INTO_OR_BEFORE)
     types_into = (Gtk.TreeViewDropPosition.INTO_OR_BEFORE, Gtk.TreeViewDropPosition.INTO_OR_AFTER)
     types_after = (Gtk.TreeViewDropPosition.AFTER, Gtk.TreeViewDropPosition.INTO_OR_AFTER)
     if str(selection.get_target()) == 'MOZO_ITEM_ROW':
         drop_info = treeview.get_dest_row_at_pos(x, y)
         before = None
         after = None
         if self.drag_data is None:
             return False
         item = self.drag_data
         # by default we assume, that the items stays in the same menu
         destination = item.get_parent()
         if drop_info:
             path, position = drop_info
             target = items[path][3]
             # move the item to the directory, if the item was dropped into it
             if isinstance(target, MateMenu.TreeDirectory) and (position in types_into):
                 # append the selected item to the choosen menu
                 destination = target
             elif position in types_before:
                 before = target
             elif position in types_after:
                 after = target
             else:
                 # this does not happen
                 pass
         else:
             path = (len(items) - 1,)
             after = items[path][3]
         if isinstance(item, MateMenu.TreeEntry):
             self.editor.moveItem(item, destination, before, after)
         elif isinstance(item, MateMenu.TreeDirectory):
             if not self.editor.moveMenu(item, destination, before, after):
                 self.loadUpdates()
         elif isinstance(item, MateMenu.TreeSeparator):
             self.editor.moveSeparator(item, destination, before, after)
         context.finish(True, True, etime)
     elif str(selection.get_target()) == 'text/plain':
         if selection.data is None:
             return False
         menus, iter = self.tree.get_object('menu_tree').get_selection().get_selected()
         parent = menus[iter][2]
         drop_info = treeview.get_dest_row_at_pos(x, y)
         before = None
         after = None
         if drop_info:
             path, position = drop_info
             if position in types_before:
                 before = items[path][3]
             else:
                 after = items[path][3]
         else:
             path = (len(items) - 1,)
             after = items[path][3]
         file_path = urllib.unquote(selection.data).strip()
         if not file_path.startswith('file:'):
             return
         myfile = Gio.File(uri=file_path)
         file_info = myfile.query_info(Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)
         content_type = file_info.get_content_type()
         if content_type == 'application/x-desktop':
             input_stream = myfile.read()
             keyfile = GLib.KeyFile()
             keyfile.load_from_data(input_stream.read())
             self.editor.createItem(parent, before, after, KeyFile=keyfile)
         elif content_type in ('application/x-shellscript', 'application/x-executable'):
             self.editor.createItem(parent, before, after,
                                    Name=os.path.split(file_path)[1].strip(),
                                    Exec=file_path.replace('file://', '').strip(),
                                    Terminal=False)
     self.drag_data = None
Example #29
0
    def __init__(self, argv=None):
        name = os.path.basename(sys.argv[0])

        if name.endswith('.py'):
            name = name[:-3]

        parser = argparse.ArgumentParser()
        parser.add_argument('--id',
                            default=name,
                            help='identity of launched game (default: %s)' %
                            name)
        parser.add_argument('arguments',
                            nargs='*',
                            help='arguments for the launched game')
        self.args = parser.parse_args(argv)

        self.id = self.args.id
        self.keyfile = GLib.KeyFile()
        self.keyfile.load_from_file(
            os.path.join(GDP_DIR, self.id + '.desktop'),
            GLib.KeyFileFlags.NONE)

        self.name = self.keyfile.get_string(GLib.KEY_FILE_DESKTOP_GROUP,
                                            GLib.KEY_FILE_DESKTOP_KEY_NAME)
        logger.debug('Name: %s', self.name)
        GLib.set_application_name(self.name)

        self.icon_name = self.keyfile.get_string(
            GLib.KEY_FILE_DESKTOP_GROUP, GLib.KEY_FILE_DESKTOP_KEY_ICON)
        logger.debug('Icon: %s', self.icon_name)

        if 'GDP_UNINSTALLED' in os.environ:
            import yaml
            self.data = yaml.load(open('%s/launch-%s.yaml' %
                                       (GDP_DIR, self.id),
                                       encoding='utf-8'),
                                  Loader=yaml.CSafeLoader)
        else:
            self.data = json.load(
                open('%s/launch-%s.json' % (GDP_DIR, self.id),
                     encoding='utf-8'))

        self.binary_only = self.data['binary_only']
        logger.debug('Binary-only: %r', self.binary_only)
        self.required_files = list(map(expand, self.data['required_files']))
        logger.debug('Checked files: %r', sorted(self.required_files))

        self.dot_directory = expand(
            self.data.get('dot_directory', '${XDG_DATA_HOME}/' + self.id))
        logger.debug('Dot directory: %s', self.dot_directory)

        self.base_directories = list(
            map(expand, self.data.get('base_directories',
                                      '/usr/lib/' + self.id)))
        logger.debug('Base directories: %r', self.base_directories)

        self.library_path = self.data.get('library_path', [])
        logger.debug('Library path: %r', self.library_path)

        self.working_directory = expand(
            self.data.get('working_directory', None))
        logger.debug('Working directory: %s', self.working_directory)

        self.argv = list(map(expand, self.data.get('argv', False)))
        logger.debug('Arguments: %r', self.argv)

        self.exit_status = 1
Example #30
0
def _pkginfo_from_file_thread(cache, file, callback):
    fp_sys = get_fp_sys()

    path = file.get_path()

    if path == None:
        print("Installer: flatpak - no valid .flatpakref path provided")
        return None

    ref = None
    pkginfo = None
    remote_name = None

    with open(path) as f:
        contents = f.read()

        b = contents.encode("utf-8")
        gb = GLib.Bytes(b)

        try:
            kf = GLib.KeyFile()
            if kf.load_from_file(path, GLib.KeyFileFlags.NONE):
                name = kf.get_string("Flatpak Ref", "Name")
                url = kf.get_string("Flatpak Ref", "Url")

                try:
                    branch = kf.get_string("Flatpak Ref", "Branch")
                except GLib.Error as e:
                    if e.code == GLib.KeyFileError.KEY_NOT_FOUND:
                        print(
                            "Installer: flatpak - flatpakref file doesn't have a Branch key, maybe nightly or testing."
                        )
                        branch = None

                remote_name = _get_remote_name_by_url(fp_sys, url)

                if name and remote_name:
                    ref = Flatpak.RemoteRef(remote_name=remote_name,
                                            kind=Flatpak.RefKind.APP,
                                            arch=Flatpak.get_default_arch(),
                                            branch=branch,
                                            name=name)
                    print(
                        "Installer: flatpak - using existing remote '%s' for flatpakref file install"
                        % remote_name)
                else:  #If Flatpakref is not installed already
                    try:
                        print(
                            "Installer: flatpak - trying to install new remote for flatpakref file"
                        )
                        ref = fp_sys.install_ref_file(gb, None)
                        fp_sys.drop_caches(None)

                        remote_name = ref.get_remote_name()
                        print("Installer: flatpak - added remote '%s'" %
                              remote_name)
                    except GLib.Error as e:
                        if e.code != Gio.DBusError.ACCESS_DENIED:  # user cancelling auth prompt for adding a remote
                            print(
                                "Installer: could not add new remote to system: %s"
                                % e.message)
                            dialogs.show_flatpak_error(e.message)
        except GLib.Error as e:
            print("Installer: flatpak - could not parse flatpakref file: %s" %
                  e.message)
            dialogs.show_flatpak_error(e.message)

        if ref:
            try:
                remote = fp_sys.get_remote_by_name(remote_name, None)

                # Add the ref's remote if it doesn't already exist
                _process_remote(cache, fp_sys, remote,
                                Flatpak.get_default_arch())

                # Add the ref to the cache, so we can work with it like any other in mintinstall
                pkginfo = _add_package_to_cache(cache, ref, remote.get_url(),
                                                False)

                # Fetch the appstream info for the ref
                global _as_pools

                with _as_pool_lock:
                    if remote_name not in _as_pools.keys():
                        _load_appstream_pool(_as_pools, remote)

                # Some flatpakref files will have a pointer to a runtime .flatpakrepo file
                # We need to process and possibly add that remote as well.

                kf = GLib.KeyFile()
                if kf.load_from_file(path, GLib.KeyFileFlags.NONE):
                    try:
                        url = kf.get_string("Flatpak Ref", "RuntimeRepo")
                    except GLib.Error:
                        url = None

                    if url:
                        # Fetch the .flatpakrepo file
                        r = requests.get(url, stream=True)

                        file = tempfile.NamedTemporaryFile(delete=False)

                        with file as fd:
                            for chunk in r.iter_content(chunk_size=128):
                                fd.write(chunk)

                        # Get the true runtime url from the repo file
                        runtime_repo_url = _get_repofile_repo_url(file.name)

                        if runtime_repo_url:
                            existing = False

                            path = Path(file.name)
                            runtime_remote_name = Path(url).stem

                            # Check if the remote is already installed
                            for remote in fp_sys.list_remotes(None):
                                # See comments below in _remote_from_repo_file_thread about get_noenumerate() use.
                                if remote.get_url(
                                ) == runtime_repo_url and not remote.get_noenumerate(
                                ):
                                    print(
                                        "Installer: flatpak - runtime remote '%s' already in system, skipping"
                                        % runtime_remote_name)
                                    existing = True
                                    break

                            if not existing:
                                print(
                                    "Installer: Adding additional runtime remote named '%s' at '%s'"
                                    % (runtime_remote_name, runtime_repo_url))

                                cmd_v = [
                                    'flatpak', 'remote-add', '--from',
                                    runtime_remote_name, file.name
                                ]

                                add_repo_proc = subprocess.Popen(cmd_v)
                                retcode = add_repo_proc.wait()

                                fp_sys.drop_caches(None)
                        os.unlink(file.name)
            except GLib.Error as e:
                print("Installer: could not process .flatpakref file: %s" %
                      e.message)
                dialogs.show_flatpak_error(e.message)

    GLib.idle_add(callback, pkginfo, priority=GLib.PRIORITY_DEFAULT)