Exemple #1
0
    def __build_condition(self, condition, parent, tag=None):
        """Translate a condition to a valid sievelib Command.

        :param list condition: condition's definition
        :param ``Command`` parent: the parent
        :param str tag: tag to use instead of the one included into :keyword:`condition`
        :rtype: Command
        :return: the generated command
        """
        #print("condition, parent, tag", condition, parent, tag)
        #condition = condition[2:] + condition[:2]
        if tag is None:
            tag = condition[0]
        #print("condition, parent, tag", condition, parent, tag)
        cmd = get_command_instance("header", parent)
        #print("tag",tag)
        #print("cond",condition)
        #print("cmd",cmd)
        cmd.check_next_arg("tag", tag)
        #cmd.check_next_arg("string", condition[0])#.strip('"'))
        cmd.check_next_arg("string", self.__quote_if_necessary(condition[1]))
        cmd.check_next_arg("string", self.__quote_if_necessary(condition[2]))
        #cmd.check_next_arg("string", condition[2].strip('"'))
        #print("Cmd++",cmd)
        #cmd.tosieve()
        return cmd
Exemple #2
0
    def __command(self, ttype, tvalue):
        """Command parsing method

        Entry point for command parsing. Here is expected behaviour:
         * Handle command beginning if detected,
         * Call the appropriate sub-method (specified by __cstate) to
           handle the body,
         * Handle command ending or block opening if detected.

        Syntax:
            identifier arguments (";" / block)

        :param ttype: current token type
        :param tvalue: current token value
        :return: False if an error is encountered, True otherwise
        """
        if self.__cstate is None:
            if ttype == "right_cbracket":
                self.__up()
                self.__opened_blocks -= 1
                self.__cstate = None
                return True

            if ttype != "identifier":
                return False
            command = get_command_instance(tvalue.decode("ascii"),
                                           self.__curcommand)
            if command.get_type() == "test":
                raise ParseError("%s may not appear as a first command" %
                                 command.name)
            if command.get_type() == "control" and command.accept_children \
               and command.has_arguments():
                self.__set_expected("identifier")
            if self.__curcommand is not None:
                if not self.__curcommand.addchild(command):
                    raise ParseError("%s unexpected after a %s" %
                                     (tvalue, self.__curcommand.name))
            self.__curcommand = command
            self.__cstate = self.__arguments

            return True

        if self.__cstate(ttype, tvalue):
            return True

        if ttype == "left_cbracket":
            self.__opened_blocks += 1
            self.__cstate = None
            return True

        if ttype == "semicolon":
            self.__cstate = None
            if not self.__check_command_completion(testsemicolon=False):
                return False
            self.__curcommand.complete_cb()
            self.__up()
            return True
        return False
Exemple #3
0
    def __command(self, ttype, tvalue):
        """Command parsing method

        Entry point for command parsing. Here is expected behaviour:
         * Handle command beginning if detected,
         * Call the appropriate sub-method (specified by __cstate) to
           handle the body,
         * Handle command ending or block opening if detected.

        Syntax:
            identifier arguments (";" / block)

        :param ttype: current token type
        :param tvalue: current token value
        :return: False if an error is encountered, True otherwise
        """
        if self.__cstate is None:
            if ttype == "right_cbracket":
                self.__up()
                self.__opened_blocks -= 1
                self.__cstate = None
                return True

            if ttype != "identifier":
                return False
            command = get_command_instance(
                tvalue.decode("ascii"), self.__curcommand)
            if command.get_type() == "test":
                raise ParseError(
                    "%s may not appear as a first command" % command.name)
            if command.get_type() == "control" and command.accept_children \
               and command.has_arguments():
                self.__set_expected("identifier")
            if self.__curcommand is not None:
                if not self.__curcommand.addchild(command):
                    raise ParseError("%s unexpected after a %s" %
                                     (tvalue, self.__curcommand.name))
            self.__curcommand = command
            self.__cstate = self.__arguments

            return True

        if self.__cstate(ttype, tvalue):
            return True

        if ttype == "left_cbracket":
            self.__opened_blocks += 1
            self.__cstate = None
            return True

        if ttype == "semicolon":
            self.__cstate = None
            if not self.__check_command_completion(testsemicolon=False):
                return False
            self.__curcommand.complete_cb()
            self.__up()
            return True
        return False
Exemple #4
0
    def __gen_require_command(self):
        """Internal method to create a RequireCommand based on requirements

        Called just before this object is going to be dumped.
        """
        if not len(self.requires):
            return None
        reqcmd = get_command_instance("require")
        reqcmd.check_next_arg("stringlist", self.requires)
        return reqcmd
Exemple #5
0
    def __gen_require_command(self):
        """Internal method to create a RequireCommand based on requirements

        Called just before this object is going to be dumped.
        """
        if not len(self.requires):
            return None
        reqcmd = commands.get_command_instance("require")
        reqcmd.check_next_arg("stringlist", self.requires)
        return reqcmd
Exemple #6
0
    def disablefilter(self, name):
        """Disable a filter

        Instead of commenting the filter, we just surround it with a
        "if false { }" test.

        :param name: the filter's name
        :return: True if filter was disabled, False otherwise
        """
        ifcontrol = get_command_instance("if")
        falsecmd = get_command_instance("false", ifcontrol)
        ifcontrol.check_next_arg("test", falsecmd)
        for f in self.filters:
            if f["name"] != name:
                continue
            ifcontrol.addchild(f["content"])
            f["content"] = ifcontrol
            f["enabled"] = False
            return True
        return False
Exemple #7
0
    def disablefilter(self, name):
        """Disable a filter

        Instead of commenting the filter, we just surround it with a
        "if false { }" test.

        :param name: the filter's name
        :return: True if filter was disabled, False otherwise
        """
        name = self._unicode_filter_name(name)
        ifcontrol = get_command_instance("if")
        falsecmd = get_command_instance("false", ifcontrol)
        ifcontrol.check_next_arg("test", falsecmd)
        for f in self.filters:
            if f["name"] != name:
                continue
            ifcontrol.addchild(f["content"])
            f["content"] = ifcontrol
            f["enabled"] = False
            return True
        return False
Exemple #8
0
    def __build_condition(self, condition, parent, tag=None):
        """Translate a condition to a valid sievelib Command.

        :param list condition: condition's definition
        :param ``Command`` parent: the parent
        :param str tag: tag to use instead of the one included into :keyword:`condition`
        :rtype: Command
        :return: the generated command
        """
        if tag is None:
            tag = condition[1]
        cmd = commands.get_command_instance("header", parent)
        cmd.check_next_arg("tag", tag)
        cmd.check_next_arg("string", self.__quote_if_necessary(condition[0]))
        cmd.check_next_arg("string", self.__quote_if_necessary(condition[2]))
        return cmd
Exemple #9
0
    def __build_condition(self, condition, parent, tag=None):
        """Translate a condition to a valid sievelib Command.

        :param list condition: condition's definition
        :param ``Command`` parent: the parent
        :param str tag: tag to use instead of the one included into :keyword:`condition`
        :rtype: Command
        :return: the generated command
        """
        if tag is None:
            tag = condition[1]
        cmd = commands.get_command_instance("header", parent)
        cmd.check_next_arg("tag", tag)
        cmd.check_next_arg("string", self.__quote_if_necessary(condition[0]))
        cmd.check_next_arg("string", self.__quote_if_necessary(condition[2]))
        return cmd
Exemple #10
0
    def __arguments(self, ttype, tvalue):
        """Arguments parsing method

        Entry point for command arguments parsing. The parser must
        call this method for each parsed command (either a control,
        action or test).

        Syntax:
            *argument [ test / test-list ]

        :param ttype: current token type
        :param tvalue: current token value
        :return: False if an error is encountered, True otherwise
        """
        if ttype == "identifier":
            test = get_command_instance(tvalue.decode("ascii"),
                                        self.__curcommand)
            self.__curcommand.check_next_arg("test", test)
            self.__expected = test.get_expected_first()
            self.__curcommand = test
            return self.__check_command_completion(testsemicolon=False)

        if ttype == "left_parenthesis":
            self.__push_expected_bracket("right_parenthesis", b')')
            self.__set_expected("identifier")
            return True

        if ttype == "comma":
            self.__set_expected("identifier")
            return True

        if ttype == "right_parenthesis":
            self.__pop_expected_bracket(ttype, tvalue)
            self.__up()
            return True

        if self.__argument(ttype, tvalue):
            return self.__check_command_completion(testsemicolon=False)

        return False
Exemple #11
0
    def __arguments(self, ttype, tvalue):
        """Arguments parsing method

        Entry point for command arguments parsing. The parser must
        call this method for each parsed command (either a control,
        action or test).

        Syntax:
            *argument [ test / test-list ]

        :param ttype: current token type
        :param tvalue: current token value
        :return: False if an error is encountered, True otherwise
        """
        if ttype == "identifier":
            test = get_command_instance(tvalue, self.__curcommand)
            self.__curcommand.check_next_arg("test", test)
            self.__expected = test.get_expected_first()
            self.__curcommand = test
            return self.__check_command_completion(testsemicolon=False)

        if ttype == "left_parenthesis":
            self.__set_expected("identifier")
            return True

        if ttype == "comma":
            self.__set_expected("identifier")
            return True

        if ttype == "right_parenthesis":
            self.__up()
            return True

        if self.__argument(ttype, tvalue):
            return self.__check_command_completion(testsemicolon=False)

        return False
Exemple #12
0
    def __create_filter(self, conditions, actions, matchtype="anyof"):
        """Create a new filter

        A filter is composed of:
         * a name
         * one or more conditions (tests) combined together using ``matchtype``
         * one or more actions

        A condition must be given as a 3-uple of the form::

          (test's name, operator, value)

        An action must be given as a 2-uple of the form::

          (action's name, value)

        It uses the "header" test to generate the sieve syntax
        corresponding to the given conditions.

        :param conditions: the list of conditions
        :param actions: the list of actions
        :param matchtype: "anyof" or "allof"
        """
        ifcontrol = get_command_instance("if")
        mtypeobj = get_command_instance(matchtype, ifcontrol)
        for c in conditions:
            if c[0].startswith("not"):
                negate = True
                cname = c[0].replace("not", "", 1)
            else:
                negate = False
                cname = c[0]
            if cname in ("true", "false"):
                cmd = get_command_instance(c[0], ifcontrol)
            elif cname == "size":
                cmd = get_command_instance("size", ifcontrol)
                cmd.check_next_arg("tag", c[1])
                cmd.check_next_arg("number", c[2])
            elif cname == "exists":
                cmd = get_command_instance("exists", ifcontrol)
                cmd.check_next_arg(
                    "stringlist",
                    "[%s]" % (",".join('"%s"' % val for val in c[1:])))
            else:
                if c[1].startswith(':not'):
                    cmd = self.__build_condition(c, ifcontrol,
                                                 c[1].replace("not", "", 1))
                    not_cmd = get_command_instance("not", ifcontrol)
                    not_cmd.check_next_arg("test", cmd)
                    cmd = not_cmd
                else:
                    cmd = self.__build_condition(c, ifcontrol)
            if negate:
                not_cmd = get_command_instance("not", ifcontrol)
                not_cmd.check_next_arg("test", cmd)
                cmd = not_cmd
            mtypeobj.check_next_arg("test", cmd)
        ifcontrol.check_next_arg("test", mtypeobj)

        for actdef in actions:
            action = get_command_instance(actdef[0], ifcontrol, False)
            if action.is_extension:
                self.require(actdef[0])
            for arg in actdef[1:]:
                self.check_if_arg_is_extension(arg)
                if arg.startswith(":"):
                    atype = "tag"
                else:
                    atype = "string"
                    arg = self.__quote_if_necessary(arg)
                action.check_next_arg(atype, arg, check_extension=False)
            ifcontrol.addchild(action)
        return ifcontrol
Exemple #13
0
    def __create_filter(self, conditions, actions, matchtype="anyof"):
        """Create a new filter

        A filter is composed of:
         * a name
         * one or more conditions (tests) combined together using ``matchtype``
         * one or more actions

        A condition must be given as a 3-uple of the form::

          (test's name, operator, value)

        An action must be given as a 2-uple of the form::

          (action's name, value)

        It uses the "header" test to generate the sieve syntax
        corresponding to the given conditions.

        :param conditions: the list of conditions
        :param actions: the list of actions
        :param matchtype: "anyof" or "allof"
        """
        ifcontrol = commands.get_command_instance("if")
        mtypeobj = commands.get_command_instance(matchtype, ifcontrol)
        for c in conditions:
            if c[0].startswith("not"):
                negate = True
                cname = c[0].replace("not", "", 1)
            else:
                negate = False
                cname = c[0]
            if cname in ("true", "false"):
                cmd = commands.get_command_instance(c[0], ifcontrol)
            elif cname == "size":
                cmd = commands.get_command_instance("size", ifcontrol)
                cmd.check_next_arg("tag", c[1])
                cmd.check_next_arg("number", c[2])
            elif cname == "exists":
                cmd = commands.get_command_instance("exists", ifcontrol)
                cmd.check_next_arg(
                    "stringlist",
                    "[%s]" % (",".join('"%s"' % val for val in c[1:]))
                )
            elif cname == "envelope":
                cmd = commands.get_command_instance(
                    "envelope", ifcontrol, False)
                self.require("envelope")
                if c[1].startswith(":not"):
                    comp_tag = c[1].replace("not", "")
                    negate = True
                else:
                    comp_tag = c[1]
                cmd.check_next_arg("tag", comp_tag)
                cmd.check_next_arg(
                    "stringlist",
                    "[{}]".format(",".join('"{}"'.format(val) for val in c[2]))
                )
                cmd.check_next_arg(
                    "stringlist",
                    "[{}]".format(",".join('"{}"'.format(val) for val in c[3]))
                )
            elif cname == "body":
                cmd = commands.get_command_instance("body", ifcontrol, False)
                self.require(cmd.extension)
                cmd.check_next_arg("tag", c[1])
                if c[2].startswith(":not"):
                    comp_tag = c[2].replace("not", "")
                    negate = True
                else:
                    comp_tag = c[2]
                cmd.check_next_arg("tag", comp_tag)
                cmd.check_next_arg(
                    "stringlist",
                    "[%s]" % (",".join('"%s"' % val for val in c[3:]))
                )
            elif cname == "currentdate":
                cmd = commands.get_command_instance(
                    "currentdate", ifcontrol, False)
                self.require(cmd.extension)
                cmd.check_next_arg("tag", c[1])
                cmd.check_next_arg("string", self.__quote_if_necessary(c[2]))
                if c[3].startswith(":not"):
                    comp_tag = c[3].replace("not", "")
                    negate = True
                else:
                    comp_tag = c[3]
                cmd.check_next_arg("tag", comp_tag, check_extension=False)
                next_arg_pos = 4
                if comp_tag == ":value":
                    self.require("relational")
                    cmd.check_next_arg(
                        "string", self.__quote_if_necessary(c[next_arg_pos]))
                    next_arg_pos += 1
                cmd.check_next_arg(
                    "string", self.__quote_if_necessary(c[next_arg_pos]))
                next_arg_pos += 1
                cmd.check_next_arg(
                    "stringlist",
                    "[%s]" %
                    (",".join('"%s"' % val for val in c[next_arg_pos:]))
                )
            else:
                # header command fallback
                if c[1].startswith(':not'):
                    cmd = self.__build_condition(
                        c, ifcontrol, c[1].replace("not", "", 1))
                    negate = True
                else:
                    cmd = self.__build_condition(c, ifcontrol)
            if negate:
                not_cmd = commands.get_command_instance("not", ifcontrol)
                not_cmd.check_next_arg("test", cmd)
                cmd = not_cmd
            mtypeobj.check_next_arg("test", cmd)
        ifcontrol.check_next_arg("test", mtypeobj)

        for actdef in actions:
            action = commands.get_command_instance(actdef[0], ifcontrol, False)
            if action.extension is not None:
                self.require(action.extension)
            for arg in actdef[1:]:
                self.check_if_arg_is_extension(arg)
                if arg.startswith(":"):
                    atype = "tag"
                else:
                    atype = "string"
                    arg = self.__quote_if_necessary(arg)
                action.check_next_arg(atype, arg, check_extension=False)
            ifcontrol.addchild(action)
        return ifcontrol
Exemple #14
0
    def __create_filter(self, conditions, actions, matchtype="anyof"):
        """Create a new filter

        A filter is composed of:
         * a name
         * one or more conditions (tests) combined together using ``matchtype``
         * one or more actions

        A condition must be given as a 3-uple of the form::

          (test's name, operator, value)

        An action must be given as a 2-uple of the form::

          (action's name, value)

        It uses the "header" test to generate the sieve syntax
        corresponding to the given conditions.

        :param conditions: the list of conditions
        :param actions: the list of actions
        :param matchtype: "anyof" or "allof"
        """
        ifcontrol = get_command_instance("if")
        mtypeobj = get_command_instance(matchtype, ifcontrol)
        for c in conditions:
            if c[0].startswith("not"):
                negate = True
                cname = c[0].replace("not", "", 1)
            else:
                negate = False
                cname = c[0]
            if cname in ("true", "false"):
                cmd = get_command_instance(c[0], ifcontrol)
            elif cname == "size":
                cmd = get_command_instance("size", ifcontrol)
                cmd.check_next_arg("tag", c[1])
                cmd.check_next_arg("number", c[2])
            elif cname == "exists":
                cmd = get_command_instance("exists", ifcontrol)
                cmd.check_next_arg(
                    "stringlist",
                    "[%s]" % (",".join('"%s"' % val for val in c[1:]))
                )
            else:
                if c[1].startswith(':not'):
                    cmd = self.__build_condition(c, ifcontrol, c[1].replace("not", "", 1))
                    not_cmd = get_command_instance("not", ifcontrol)
                    not_cmd.check_next_arg("test", cmd)
                    cmd = not_cmd
                else:
                    cmd = self.__build_condition(c, ifcontrol)
            if negate:
                not_cmd = get_command_instance("not", ifcontrol)
                not_cmd.check_next_arg("test", cmd)
                cmd = not_cmd
            mtypeobj.check_next_arg("test", cmd)
        ifcontrol.check_next_arg("test", mtypeobj)

        for actdef in actions:
            action = get_command_instance(actdef[0], ifcontrol, False)
            if action.is_extension:
                self.require(actdef[0])
            for arg in actdef[1:]:
                action.check_next_arg("string", self.__quote_if_necessary(arg))
            ifcontrol.addchild(action)
        return ifcontrol