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)
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
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")
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
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
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
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
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()
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")
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
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
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
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()
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()
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())
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)
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
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)
def load(self): self.keyfile = GLib.KeyFile() try: self.keyfile.load_from_file(self.item_path, util.KEY_FILE_FLAGS) except GLib.GError: pass
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.')
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')
# # 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()
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)
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
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
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
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)