Пример #1
0
 def merge_file(self, filename, child, parent):
     # check for infinite loops
     if filename in self._merged_files:
         if debug:
             raise ParsingError('Infinite MergeFile loop detected',
                                filename)
         else:
             return
     self._merged_files.add(filename)
     # load file
     try:
         tree = etree.parse(filename)
     except IOError:
         if self.debug:
             raise ParsingError('File not found', filename)
         else:
             return
     except:
         if self.debug:
             raise ParsingError('Not a valid .menu file', filename)
         else:
             return
     root = tree.getroot()
     # append file
     for child in root:
         self.parse_node(child, filename, parent)
         break
Пример #2
0
def __mergeFile(filename, child, parent):
    # check for infinite loops
    if filename in tmp["mergeFiles"]:
        if debug:
            raise ParsingError('Infinite MergeFile loop detected', filename)
        else:
            return

    tmp["mergeFiles"].append(filename)

    # load file
    try:
        doc = xml.dom.minidom.parse(filename)
    except IOError:
        if debug:
            raise ParsingError('File not found', filename)
        else:
            return
    except xml.parsers.expat.ExpatError:
        if debug:
            raise ParsingError('Not a valid .menu file', filename)
        else:
            return

    # append file
    for child in doc.childNodes:
        if child.nodeType == ELEMENT_NODE:
            __parse(child,filename,parent)
            break
Пример #3
0
    def parse(self, filename=None):
        """Parse a list of recently used files.
        
        filename defaults to ``~/.recently-used``.
        """
        if not filename:
            filename = os.path.join(os.getenv("HOME"), ".recently-used")

        try:
            doc = xml.dom.minidom.parse(filename)
        except IOError:
            raise ParsingError('File not found', filename)
        except xml.parsers.expat.ExpatError:
            raise ParsingError('Not a valid .menu file', filename)

        self.filename = filename

        for child in doc.childNodes:
            if child.nodeType == xml.dom.Node.ELEMENT_NODE:
                if child.tagName == "RecentFiles":
                    for recent in child.childNodes:
                        if recent.nodeType == xml.dom.Node.ELEMENT_NODE:    
                            if recent.tagName == "RecentItem":
                                self.__parseRecentItem(recent)

        self.sort()
Пример #4
0
def parse(filename=None):
    """Load an applications.menu file.
    
    filename : str, optional
      The default is ``$XDG_CONFIG_DIRS/menus/${XDG_MENU_PREFIX}applications.menu``.
    """
    # convert to absolute path
    if filename and not os.path.isabs(filename):
        filename = __getFileName(filename)

    # use default if no filename given
    if not filename: 
        # Upstream's default, we leave it as default in case someone produces
        # their own applications.menu and is depending on it.
        candidate = os.environ.get('XDG_MENU_PREFIX', '') + "applications.menu"
        filename = __getFileName(candidate)
        # Since applications.menu isn't provided in Debian, we'll fallback to
        # debian.menu, typically in /etc/xdg/menus/debian-menu.menu
        # (Closes: #654978)
        if not filename:
            candidate = os.environ.get('XDG_MENU_PREFIX', '') + \
                                                            "debian-menu.menu"
            filename = __getFileName(candidate)
        
    if not filename:
        raise ParsingError('File not found', "/etc/xdg/menus/%s" % candidate)

    # check if it is a .menu file
    if not os.path.splitext(filename)[1] == ".menu":
        raise ParsingError('Not a .menu file', filename)

    # create xml parser
    try:
        doc = xml.dom.minidom.parse(filename)
    except xml.parsers.expat.ExpatError:
        raise ParsingError('Not a valid .menu file', filename)

    # parse menufile
    tmp["Root"] = ""
    tmp["mergeFiles"] = []
    tmp["DirectoryDirs"] = []
    tmp["cache"] = MenuEntryCache()

    __parse(doc, filename, tmp["Root"])
    __parsemove(tmp["Root"])
    __postparse(tmp["Root"])

    tmp["Root"].Doc = doc
    tmp["Root"].Filename = filename

    # generate the menu
    __genmenuNotOnlyAllocated(tmp["Root"])
    __genmenuOnlyAllocated(tmp["Root"])

    # and finally sort
    sort(tmp["Root"])

    return tmp["Root"]
Пример #5
0
def parse(filename=None):
    """Load an applications.menu file.
    
    filename : str, optional
      The default is ``$XDG_CONFIG_DIRS/menus/${XDG_MENU_PREFIX}applications.menu``.
    """
    # convert to absolute path
    if filename and not os.path.isabs(filename):
        filename = __getFileName(filename)

    # use default if no filename given
    if not filename:
        candidate = os.environ.get('XDG_MENU_PREFIX', '') + "applications.menu"
        filename = __getFileName(candidate)

    if not filename:
        raise ParsingError('File not found', "/etc/xdg/menus/%s" % candidate)

    # check if it is a .menu file
    if not os.path.splitext(filename)[1] == ".menu":
        raise ParsingError('Not a .menu file', filename)

    # create xml parser
    try:
        doc = xml.dom.minidom.parse(filename)
    except xml.parsers.expat.ExpatError:
        raise ParsingError('Not a valid .menu file', filename)

    # parse menufile
    tmp["Root"] = ""
    tmp["mergeFiles"] = []
    tmp["DirectoryDirs"] = []
    tmp["cache"] = MenuEntryCache()

    __parse(doc, filename, tmp["Root"])
    __parsemove(tmp["Root"])
    __postparse(tmp["Root"])

    tmp["Root"].Doc = doc
    tmp["Root"].Filename = filename

    # generate the menu
    __genmenuNotOnlyAllocated(tmp["Root"])
    __genmenuOnlyAllocated(tmp["Root"])

    # and finally sort
    sort(tmp["Root"])

    return tmp["Root"]
Пример #6
0
    def write(self, filename=None):
        """Write the list of recently used files to disk.
        
        If the instance is already associated with a file, filename can be
        omitted to save it there again.
        """
        if not filename and not self.filename:
            raise ParsingError('File not found', filename)
        elif not filename:
            filename = self.filename

        with open(filename, "w") as f:
            fcntl.lockf(f, fcntl.LOCK_EX)
            f.write('<?xml version="1.0"?>\n')
            f.write("<RecentFiles>\n")

            for r in self.RecentFiles:
                f.write("  <RecentItem>\n")
                f.write("    <URI>%s</URI>\n" % xml.sax.saxutils.escape(r.URI))
                f.write("    <Mime-Type>%s</Mime-Type>\n" % r.MimeType)
                f.write("    <Timestamp>%s</Timestamp>\n" % r.Timestamp)
                if r.Private == True:
                    f.write("    <Private/>\n")
                if len(r.Groups) > 0:
                    f.write("    <Groups>\n")
                    for group in r.Groups:
                        f.write("      <Group>%s</Group>\n" % group)
                    f.write("    </Groups>\n")
                f.write("  </RecentItem>\n")

            f.write("</RecentFiles>\n")
            fcntl.lockf(f, fcntl.LOCK_UN)
Пример #7
0
    def parse(self, menu=None, filename=None, root=False):
        if root:
            setRootMode(True)

        if isinstance(menu, Menu):
            self.menu = menu
        elif menu:
            self.menu = self.parser.parse(menu)
        else:
            self.menu = self.parser.parse()

        if root:
            self.filename = self.menu.Filename
        elif filename:
            self.filename = filename
        else:
            self.filename = os.path.join(xdg_config_dirs[0], "menus",
                                         os.path.split(self.menu.Filename)[1])

        try:
            self.tree = etree.parse(self.filename)
        except IOError:
            root = etree.fromtring("""
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" "http://standards.freedesktop.org/menu-spec/menu-1.0.dtd">
    <Menu>
        <Name>Applications</Name>
        <MergeFile type="parent">%s</MergeFile>
    </Menu>
""" % self.menu.Filename)
            self.tree = etree.ElementTree(root)
        except ParsingError:
            raise ParsingError('Not a valid .menu file', self.filename)

        #FIXME: is this needed with etree ?
        self.__remove_whitespace_nodes(self.tree)
Пример #8
0
    def parse(self, filename=None):
        """Load an applications.menu file.

        filename : str, optional
          The default is ``$XDG_CONFIG_DIRS/menus/${XDG_MENU_PREFIX}applications.menu``.
        """
        # convert to absolute path
        if filename and not os.path.isabs(filename):
            filename = _get_menu_file_path(filename)
        # use default if no filename given
        if not filename:
            candidate = os.environ.get('XDG_MENU_PREFIX',
                                       '') + "applications.menu"
            filename = _get_menu_file_path(candidate)
        if not filename:
            raise ParsingError('File not found',
                               "/etc/xdg/menus/%s" % candidate)
        # check if it is a .menu file
        if not filename.endswith(".menu"):
            raise ParsingError('Not a .menu file', filename)
        # create xml parser
        try:
            tree = etree.parse(filename)
        except:
            raise ParsingError('Not a valid .menu file', filename)

        # parse menufile
        self._merged_files = set()
        self._directory_dirs = set()
        self.cache = MenuEntryCache()

        menu = self.parse_menu(tree.getroot(), filename)
        menu.tree = tree
        menu.filename = filename

        self.handle_moves(menu)
        self.post_parse(menu)

        # generate the menu
        self.generate_not_only_allocated(menu)
        self.generate_only_allocated(menu)

        # and finally sort
        menu.sort()

        return menu
Пример #9
0
    def new(self, filename):
        """Make this instance into a new desktop entry.
        
        If filename has a .desktop extension, Type is set to Application. If it
        has a .directory extension, Type is Directory.
        """
        if os.path.splitext(filename)[1] == ".desktop":
            type = "Application"
        elif os.path.splitext(filename)[1] == ".directory":
            type = "Directory"
        else:
            raise ParsingError("Unknown extension", filename)

        self.content = dict()
        self.addGroup(self.defaultGroup)
        self.set("Type", type)
        self.filename = filename
Пример #10
0
    def write(self, filename=None, trusted=False):
        if not filename and not self.filename:
            raise ParsingError("File not found", "")

        if filename:
            self.filename = filename
        else:
            filename = self.filename

        if os.path.dirname(filename) and not os.path.isdir(
                os.path.dirname(filename)):
            os.makedirs(os.path.dirname(filename))

        with io.open(filename, 'w', encoding='utf-8') as fp:

            # An executable bit signifies that the desktop file is
            # trusted, but then the file can be executed. Add hashbang to
            # make sure that the file is opened by something that
            # understands desktop files.
            if trusted:
                fp.write(u("#!/usr/bin/env xdg-open\n"))

            if self.defaultGroup:
                fp.write(u("[%s]\n") % self.defaultGroup)
                for (key, value) in self.content[self.defaultGroup].items():
                    fp.write(u("%s=%s\n") % (key, value))
                fp.write(u("\n"))
            for (name, group) in self.content.items():
                if name != self.defaultGroup:
                    fp.write(u("[%s]\n") % name)
                    for (key, value) in group.items():
                        fp.write(u("%s=%s\n") % (key, value))
                    fp.write(u("\n"))

        # Add executable bits to the file to show that it's trusted.
        if trusted:
            oldmode = os.stat(filename).st_mode
            mode = oldmode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
            os.chmod(filename, mode)

        self.tainted = False
Пример #11
0
    def parse(self, filename, headers=None):
        '''Parse an INI file.
        
        headers -- list of headers the parser will try to select as a default header
        '''
        # for performance reasons
        content = self.content

        if not os.path.isfile(filename):
            raise ParsingError("File not found", filename)

        try:
            # The content should be UTF-8, but legacy files can have other
            # encodings, including mixed encodings in one file. We don't attempt
            # to decode them, but we silence the errors.
            fd = io.open(filename, 'r', encoding='utf-8', errors='replace')
        except IOError as e:
            if debug:
                raise e
            else:
                return

        # parse file
        with fd:
            for line in fd:
                line = line.strip()
                # empty line
                if not line:
                    continue
                # comment
                elif line[0] == '#':
                    continue
                # new group
                elif line[0] == '[':
                    currentGroup = line.lstrip("[").rstrip("]")
                    if debug and self.hasGroup(currentGroup):
                        raise DuplicateGroupError(currentGroup, filename)
                    else:
                        content[currentGroup] = {}
                # key
                else:
                    try:
                        key, value = line.split("=", 1)
                    except ValueError:
                        raise ParsingError("Invalid line: " + line, filename)

                    key = key.strip(
                    )  # Spaces before/after '=' should be ignored
                    try:
                        if debug and self.hasKey(key, currentGroup):
                            raise DuplicateKeyError(key, currentGroup,
                                                    filename)
                        else:
                            content[currentGroup][key] = value.strip()
                    except (IndexError, UnboundLocalError):
                        raise ParsingError(
                            "Parsing error on key, group missing", filename)

        self.filename = filename
        self.tainted = False

        # check header
        if headers:
            for header in headers:
                if header in content:
                    self.defaultGroup = header
                    break
            else:
                raise ParsingError("[%s]-Header missing" % headers[0],
                                   filename)