Search in sources :

Example 11 with TagArgument

use of org.apache.jsieve.TagArgument in project zm-mailbox by Zimbra.

the class SieveVisitor method acceptTest.

private void acceptTest(Node node, RuleProperties props) throws ServiceException {
    visitTest(node, VisitPhase.begin, props);
    String nodeName = getNodeName(node);
    if ("not".equalsIgnoreCase(nodeName)) {
        props.isNegativeTest = true;
        accept(node, props);
    } else {
        if ("allof".equalsIgnoreCase(nodeName)) {
            props.condition = Sieve.Condition.allof;
            visitRule(node, VisitPhase.begin, props);
            accept(node, props);
            visitRule(node, VisitPhase.end, props);
        } else if ("anyof".equalsIgnoreCase(nodeName)) {
            props.condition = Sieve.Condition.anyof;
            visitRule(node, VisitPhase.begin, props);
            accept(node, props);
            visitRule(node, VisitPhase.end, props);
        } else if ("header".equalsIgnoreCase(nodeName) || "mime_header".equalsIgnoreCase(nodeName)) {
            boolean caseSensitive = false;
            List<String> headers;
            String value;
            Sieve.ValueComparison valueComparison = null;
            boolean isCount = false;
            Sieve.StringComparison comparison = null;
            Sieve.Comparator comparator = null;
            int headersArgIndex = 0;
            // There can be up to two tag arguments
            SieveNode firstTagArgNode, secondTagArgNode;
            firstTagArgNode = (SieveNode) getNode(node, 0, 0);
            if (firstTagArgNode.getValue() instanceof TagArgument) {
                String argStr = stripLeadingColon(firstTagArgNode.getValue().toString());
                try {
                    if ("count".equals(argStr) || "value".equals(argStr)) {
                        if ("count".equals(argStr)) {
                            isCount = true;
                        }
                        valueComparison = Sieve.ValueComparison.valueOf(getValue(node, 0, 1, 0, 0));
                        headersArgIndex += 2;
                        secondTagArgNode = (SieveNode) getNode(node, 0, 2);
                        if (secondTagArgNode.getValue() instanceof TagArgument) {
                            comparator = Sieve.Comparator.fromString(getValue(node, 0, 3, 0, 0));
                            headersArgIndex += 2;
                        }
                    } else {
                        // assume that the first tag arg is match-type arg
                        comparison = Sieve.StringComparison.valueOf(argStr);
                        headersArgIndex++;
                        secondTagArgNode = (SieveNode) getNode(node, 0, 1);
                        if (secondTagArgNode.getValue() instanceof TagArgument) {
                            caseSensitive = Sieve.Comparator.ioctet == Sieve.Comparator.fromString(getValue(node, 0, 2, 0, 0));
                            headersArgIndex += 2;
                        }
                    }
                } catch (IllegalArgumentException e) {
                    // so the first tag arg is not match-type arg, it must be :comparator arg then
                    caseSensitive = Sieve.Comparator.ioctet == Sieve.Comparator.fromString(getValue(node, 0, 1, 0, 0));
                    headersArgIndex += 2;
                    secondTagArgNode = (SieveNode) getNode(node, 0, 2);
                    if (secondTagArgNode.getValue() instanceof TagArgument) {
                        argStr = stripLeadingColon(secondTagArgNode.getValue().toString());
                        comparison = Sieve.StringComparison.fromString(argStr);
                        headersArgIndex++;
                    }
                }
            }
            headers = getMultiValue(node, 0, headersArgIndex, 0);
            value = getValue(node, 0, headersArgIndex + 1, 0, 0);
            validateCountComparator(isCount, comparator);
            if ("header".equalsIgnoreCase(nodeName)) {
                if (valueComparison != null) {
                    visitHeaderTest(node, VisitPhase.begin, props, headers, valueComparison, isCount, value);
                    accept(node, props);
                    visitHeaderTest(node, VisitPhase.end, props, headers, valueComparison, isCount, value);
                } else {
                    visitHeaderTest(node, VisitPhase.begin, props, headers, comparison, caseSensitive, value);
                    accept(node, props);
                    visitHeaderTest(node, VisitPhase.end, props, headers, comparison, caseSensitive, value);
                }
            } else {
                visitMimeHeaderTest(node, VisitPhase.begin, props, headers, comparison, caseSensitive, value);
                accept(node, props);
                visitMimeHeaderTest(node, VisitPhase.end, props, headers, comparison, caseSensitive, value);
            }
        } else if ("address".equalsIgnoreCase(nodeName) || "envelope".equalsIgnoreCase(nodeName)) {
            Sieve.AddressPart part = Sieve.AddressPart.all;
            Sieve.StringComparison comparison = Sieve.StringComparison.is;
            boolean caseSensitive = false;
            List<String> headers;
            String value;
            int nextArgIndex = 0;
            boolean isCount = false;
            Sieve.ValueComparison valueComparison = null;
            Sieve.Comparator comparator = null;
            SieveNode firstTagArgNode;
            firstTagArgNode = (SieveNode) getNode(node, 0, 0);
            if (firstTagArgNode.getValue() instanceof TagArgument) {
                String firstArgStr = firstTagArgNode.getValue().toString();
                if (":count".equals(firstArgStr) || ":value".equals(firstArgStr)) {
                    if (":count".equals(firstArgStr)) {
                        isCount = true;
                    }
                    valueComparison = Sieve.ValueComparison.valueOf(getValue(node, 0, 1, 0, 0));
                    nextArgIndex += 2;
                }
            }
            SieveNode argNode = (SieveNode) getNode(node, 0, nextArgIndex);
            // There can be up to three tag arguments
            for (int i = 0; i < 3 && argNode.getValue() instanceof TagArgument; i++) {
                TagArgument tagArg = (TagArgument) argNode.getValue();
                if (tagArg.isComparator()) {
                    comparator = Sieve.Comparator.fromString(getValue(node, 0, nextArgIndex + 1, 0, 0));
                    caseSensitive = Sieve.Comparator.ioctet == comparator;
                    nextArgIndex += 2;
                } else {
                    String argStr = stripLeadingColon(argNode.getValue().toString());
                    try {
                        // first assume that the next tag arg is match-type arg
                        comparison = Sieve.StringComparison.valueOf(argStr);
                    } catch (IllegalArgumentException e) {
                        // so the next tag arg is not match-type arg, it must be address-part arg then
                        part = Sieve.AddressPart.fromString(argStr);
                    }
                    nextArgIndex++;
                }
                argNode = (SieveNode) getNode(node, 0, nextArgIndex);
            }
            headers = getMultiValue(node, 0, nextArgIndex, 0);
            value = getValue(node, 0, nextArgIndex + 1, 0, 0);
            validateCountComparator(isCount, comparator);
            if ("envelope".equalsIgnoreCase(nodeName)) {
                if (valueComparison != null) {
                    visitEnvelopeTest(node, VisitPhase.begin, props, headers, part, valueComparison, isCount, value);
                    accept(node, props);
                    visitEnvelopeTest(node, VisitPhase.end, props, headers, part, valueComparison, isCount, value);
                } else {
                    visitEnvelopeTest(node, VisitPhase.begin, props, headers, part, comparison, caseSensitive, value);
                    accept(node, props);
                    visitEnvelopeTest(node, VisitPhase.end, props, headers, part, comparison, caseSensitive, value);
                }
            } else {
                if (valueComparison != null) {
                    visitAddressTest(node, VisitPhase.begin, props, headers, part, valueComparison, isCount, value);
                    accept(node, props);
                    visitAddressTest(node, VisitPhase.end, props, headers, part, valueComparison, isCount, value);
                } else {
                    visitAddressTest(node, VisitPhase.begin, props, headers, part, comparison, caseSensitive, value);
                    accept(node, props);
                    visitAddressTest(node, VisitPhase.end, props, headers, part, comparison, caseSensitive, value);
                }
            }
        } else if ("exists".equalsIgnoreCase(nodeName)) {
            String header = getValue(node, 0, 0, 0, 0);
            visitHeaderExistsTest(node, VisitPhase.begin, props, header);
            accept(node, props);
            visitHeaderExistsTest(node, VisitPhase.end, props, header);
        } else if ("size".equalsIgnoreCase(nodeName)) {
            String s = stripLeadingColon(getValue(node, 0, 0));
            Sieve.NumberComparison comparison = Sieve.NumberComparison.fromString(s);
            SieveNode sizeNode = (SieveNode) getNode(node, 0, 1);
            String sizeString = sizeNode.getFirstToken().toString();
            int size;
            try {
                size = FilterUtil.parseSize(sizeString);
            } catch (NumberFormatException e) {
                throw ServiceException.INVALID_REQUEST("Invalid size value " + sizeString, e);
            }
            visitSizeTest(node, VisitPhase.begin, props, comparison, size, sizeString);
            accept(node, props);
            visitSizeTest(node, VisitPhase.end, props, comparison, size, sizeString);
        } else if ("date".equalsIgnoreCase(nodeName)) {
            String s = stripLeadingColon(getValue(node, 0, 0));
            Sieve.DateComparison comparison = Sieve.DateComparison.fromString(s);
            String dateString = getValue(node, 0, 1, 0, 0);
            Date date = Sieve.DATE_PARSER.parse(dateString);
            if (date == null) {
                throw ServiceException.PARSE_ERROR("Invalid date value: " + dateString, null);
            }
            visitDateTest(node, VisitPhase.begin, props, comparison, date);
            accept(node, props);
            visitDateTest(node, VisitPhase.end, props, comparison, date);
        } else if ("body".equalsIgnoreCase(nodeName)) {
            boolean caseSensitive = false;
            String value;
            if (getNode(node, 0, 1).jjtGetNumChildren() == 0) {
                // must be :comparator
                if (!":comparator".equals(getValue(node, 0, 1)))
                    throw ServiceException.PARSE_ERROR("Expected :comparator argument", null);
                caseSensitive = Sieve.Comparator.ioctet == Sieve.Comparator.fromString(getValue(node, 0, 2, 0, 0));
                value = getValue(node, 0, 3, 0, 0);
            } else {
                value = getValue(node, 0, 1, 0, 0);
            }
            visitBodyTest(node, VisitPhase.begin, props, caseSensitive, value);
            accept(node, props);
            visitBodyTest(node, VisitPhase.end, props, caseSensitive, value);
        } else if ("attachment".equalsIgnoreCase(nodeName)) {
            visitAttachmentTest(node, VisitPhase.begin, props);
            accept(node, props);
            visitAttachmentTest(node, VisitPhase.end, props);
        } else if ("addressbook".equalsIgnoreCase(nodeName)) {
            StringBuilder format = new StringBuilder();
            Node argNode = getNode(node, 0, 1, 0);
            int argNodeLen = argNode.jjtGetNumChildren();
            for (int i = 0; i < argNodeLen; i++) {
                if (i > 0) {
                    format.append(",");
                }
                format.append(getValue(argNode, i));
            }
            String header = format.toString();
            visitAddressBookTest(node, VisitPhase.begin, props, header);
            accept(node, props);
            visitAddressBookTest(node, VisitPhase.end, props, header);
        } else if ("contact_ranking".equalsIgnoreCase(nodeName)) {
            String header = getValue(node, 0, 1, 0, 0);
            visitContactRankingTest(node, VisitPhase.begin, props, header);
            accept(node, props);
            visitContactRankingTest(node, VisitPhase.end, props, header);
        } else if ("me".equalsIgnoreCase(nodeName)) {
            String header = getValue(node, 0, 1, 0, 0);
            visitMeTest(node, VisitPhase.begin, props, header);
            accept(node, props);
            visitMeTest(node, VisitPhase.end, props, header);
        } else if ("invite".equalsIgnoreCase(nodeName)) {
            List<String> methods = Collections.emptyList();
            if (getNode(node, 0).jjtGetNumChildren() > 0) {
                // Arguments node has children.
                methods = getMultiValue(node, 0, 1, 0);
            }
            visitInviteTest(node, VisitPhase.begin, props, methods);
            accept(node, props);
            visitInviteTest(node, VisitPhase.end, props, methods);
        } else if ("current_time".equalsIgnoreCase(nodeName)) {
            String s = stripLeadingColon(getValue(node, 0, 0));
            Sieve.DateComparison comparison = Sieve.DateComparison.fromString(s);
            String timeString = getValue(node, 0, 1, 0, 0);
            visitCurrentTimeTest(node, VisitPhase.begin, props, comparison, timeString);
            accept(node, props);
            visitCurrentTimeTest(node, VisitPhase.end, props, comparison, timeString);
        } else if ("current_day_of_week".equalsIgnoreCase(nodeName)) {
            List<String> days = getMultiValue(node, 0, 1, 0);
            visitCurrentDayOfWeekTest(node, VisitPhase.begin, props, days);
            accept(node, props);
            visitCurrentDayOfWeekTest(node, VisitPhase.end, props, days);
        } else if ("conversation".equalsIgnoreCase(nodeName)) {
            String where = getValue(node, 0, 1, 0, 0);
            visitConversationTest(node, VisitPhase.begin, props, where);
            accept(node, props);
            visitConversationTest(node, VisitPhase.end, props, where);
        } else if ("facebook".equalsIgnoreCase(nodeName)) {
            visitFacebookTest(node, VisitPhase.begin, props);
            accept(node, props);
            visitFacebookTest(node, VisitPhase.end, props);
        } else if ("linkedin".equalsIgnoreCase(nodeName)) {
            visitLinkedInTest(node, VisitPhase.begin, props);
            accept(node, props);
            visitLinkedInTest(node, VisitPhase.end, props);
        } else if ("socialcast".equalsIgnoreCase(nodeName)) {
            visitSocialcastTest(node, VisitPhase.begin, props);
            accept(node, props);
            visitSocialcastTest(node, VisitPhase.end, props);
        } else if ("twitter".equalsIgnoreCase(nodeName)) {
            visitTwitterTest(node, VisitPhase.begin, props);
            accept(node, props);
            visitTwitterTest(node, VisitPhase.end, props);
        } else if ("list".equalsIgnoreCase(nodeName)) {
            visitListTest(node, VisitPhase.begin, props);
            accept(node, props);
            visitListTest(node, VisitPhase.end, props);
        } else if ("bulk".equalsIgnoreCase(nodeName)) {
            visitBulkTest(node, VisitPhase.begin, props);
            accept(node, props);
            visitBulkTest(node, VisitPhase.end, props);
        } else if ("importance".equalsIgnoreCase(nodeName)) {
            FilterTest.Importance importance = FilterTest.Importance.fromString(getValue(node, 0, 0, 0, 0));
            visitImportanceTest(node, VisitPhase.begin, props, importance);
            accept(node, props);
            visitImportanceTest(node, VisitPhase.end, props, importance);
        } else if ("flagged".equalsIgnoreCase(nodeName)) {
            Sieve.Flag flag = Sieve.Flag.fromString(getValue(node, 0, 0, 0, 0));
            visitFlaggedTest(node, VisitPhase.begin, props, flag);
            accept(node, props);
            visitFlaggedTest(node, VisitPhase.end, props, flag);
        } else if ("true".equalsIgnoreCase(nodeName)) {
            visitTrueTest(node, VisitPhase.begin, props);
            accept(node, props);
            visitTrueTest(node, VisitPhase.end, props);
        } else if ("community_requests".equalsIgnoreCase(nodeName)) {
            visitCommunityRequestsTest(node, VisitPhase.begin, props);
            accept(node, props);
            visitCommunityRequestsTest(node, VisitPhase.end, props);
        } else if ("community_content".equalsIgnoreCase(nodeName)) {
            visitCommunityContentTest(node, VisitPhase.begin, props);
            accept(node, props);
            visitCommunityContentTest(node, VisitPhase.end, props);
        } else if ("community_connections".equalsIgnoreCase(nodeName)) {
            visitCommunityConnectionsTest(node, VisitPhase.begin, props);
            accept(node, props);
            visitCommunityConnectionsTest(node, VisitPhase.end, props);
        } else {
            ZimbraLog.filter.debug("Ignoring unrecognized test type '%s'.", nodeName);
            accept(node, props);
        }
        // Done processing the current test.  Reset the negative test flag for
        // the next test (bug 46007).
        props.isNegativeTest = false;
    }
    visitTest(node, VisitPhase.end, props);
}
Also used : Node(org.apache.jsieve.parser.generated.Node) SieveNode(org.apache.jsieve.parser.SieveNode) TagArgument(org.apache.jsieve.TagArgument) ArrayList(java.util.ArrayList) List(java.util.List) Sieve(com.zimbra.common.filter.Sieve) Date(java.util.Date) SieveNode(org.apache.jsieve.parser.SieveNode) FilterTest(com.zimbra.soap.mail.type.FilterTest)

Example 12 with TagArgument

use of org.apache.jsieve.TagArgument in project zm-mailbox by Zimbra.

the class NotifyMethodCapabilityTest method executeBasic.

@Override
protected boolean executeBasic(MailAdapter mail, Arguments arguments, SieveContext context) throws SieveException {
    String comparator = ASCII_CASEMAP_COMPARATOR;
    String matchType = IS_TAG;
    String uri = null;
    String capability = null;
    List<String> keys = null;
    ListIterator<Argument> argumentsIter = arguments.getArgumentList().listIterator();
    boolean stop = false;
    /*
         * Test notify_method_capability
         * Usage:  notify_method_capability [COMPARATOR] [MATCH-TYPE]
         *         <notification-uri: string>
         *         <notification-capability: string>
         *         <key-list: string-list>
         */
    while (!stop && argumentsIter.hasNext()) {
        Argument argument = argumentsIter.next();
        if (argument instanceof TagArgument) {
            final String tag = ((TagArgument) argument).getTag();
            if (comparator == null && COMPARATOR_TAG.equalsIgnoreCase(tag)) {
                // The next argument must be a stringlist
                if (argumentsIter.hasNext()) {
                    argument = argumentsIter.next();
                    if (argument instanceof StringListArgument) {
                        List<String> stringList = ((StringListArgument) argument).getList();
                        if (stringList.size() != 1) {
                            throw context.getCoordinate().syntaxException("Expecting exactly one String");
                        }
                        comparator = stringList.get(0);
                    } else {
                        throw context.getCoordinate().syntaxException("Expecting a StringList");
                    }
                }
            } else // [MATCH-TYPE]?
            if (matchType == null && (IS_TAG.equalsIgnoreCase(tag) || CONTAINS_TAG.equalsIgnoreCase(tag) || MATCHES_TAG.equalsIgnoreCase(tag) || COUNT_TAG.equalsIgnoreCase(tag) || VALUE_TAG.equalsIgnoreCase(tag))) {
                matchType = tag;
            } else {
                throw context.getCoordinate().syntaxException("Found unexpected TagArgument: \"" + tag + "\"");
            }
        } else {
            // Stop when a non-tag argument is encountered
            argumentsIter.previous();
            stop = true;
        }
    }
    // The next argument MUST be a string of notification-uri
    if (argumentsIter.hasNext()) {
        final Argument argument = argumentsIter.next();
        if (argument instanceof StringListArgument) {
            uri = ((StringListArgument) argument).getList().get(0);
        }
    }
    if (null == uri) {
        throw context.getCoordinate().syntaxException("Expecting a String of uri");
    }
    // The next argument MUST be a string of notification-capability
    if (argumentsIter.hasNext()) {
        final Argument argument = argumentsIter.next();
        if (argument instanceof StringListArgument) {
            capability = ((StringListArgument) argument).getList().get(0);
        }
    }
    if (null == capability) {
        throw context.getCoordinate().syntaxException("Expecting a String of capability");
    }
    // The next argument MUST be a string-list of keys
    if (argumentsIter.hasNext()) {
        final Argument argument = argumentsIter.next();
        if (argument instanceof StringListArgument) {
            keys = ((StringListArgument) argument).getList();
        }
    }
    if (null == keys) {
        throw context.getCoordinate().syntaxException("Expecting a StringList of keys");
    } else {
        for (String key : keys) {
            if (!CAPABILITY_YES.equalsIgnoreCase(key) && !CAPABILITY_NO.equalsIgnoreCase(key) && !CAPABILITY_MAYBE.equalsIgnoreCase(key)) {
                throw context.getCoordinate().syntaxException("Invalid key value: [" + key + "]");
            }
        }
    }
    if (argumentsIter.hasNext()) {
        throw context.getCoordinate().syntaxException("Found unexpected arguments");
    }
    return test(comparator, matchType, uri, capability, keys);
}
Also used : TagArgument(org.apache.jsieve.TagArgument) Argument(org.apache.jsieve.Argument) StringListArgument(org.apache.jsieve.StringListArgument) TagArgument(org.apache.jsieve.TagArgument) StringListArgument(org.apache.jsieve.StringListArgument)

Example 13 with TagArgument

use of org.apache.jsieve.TagArgument in project zm-mailbox by Zimbra.

the class SetVariable method validateArguments.

@Override
protected void validateArguments(Arguments arguments, SieveContext context) throws SieveException {
    List<Argument> args = arguments.getArgumentList();
    // RFC 5229
    //  ":lower" / ":upper" / ":lowerfirst" / ":upperfirst" /
    //  ":quotewildcard" / ":length"
    //    set "name" "Ethelbert"
    //    set "a" "juMBlEd lETteRS";             => "juMBlEd lETteRS"
    //    set :length "b" "${a}";                => "15"
    //    set :lower "b" "${a}";                 => "jumbled letters"
    //    set :upperfirst "b" "${a}";            => "JuMBlEd lETteRS"
    //    set :upperfirst :lower "b" "${a}";     => "Jumbled letters"
    //    set :quotewildcard "b" "Rock*";        => "Rock\*"
    // RFC 5435
    //  ":encodeurl"
    //    set :encodeurl "body_param" "Safe body&evil=evilbody"; => "safe+body%26evil%3Devilbody"
    int varArgCount = 0;
    String key = null;
    String[] operations = new String[OPERATIONS_IDX];
    if (args.size() >= 2) {
        for (Argument arg : arguments.getArgumentList()) {
            if (arg instanceof TagArgument) {
                TagArgument tag = (TagArgument) arg;
                String tagValue = tag.getTag();
                if (!isValidModifier(tagValue)) {
                    throw new SyntaxException("Invalid variable modifier:" + tagValue);
                } else {
                    int index = getIndex(tagValue);
                    if (StringUtil.isNullOrEmpty(operations[index])) {
                        operations[index] = tagValue.toLowerCase();
                    } else {
                        throw new SyntaxException("Cannot use two or more modifiers of the same" + " precedence in a single \"set\" action. Modifiers used: " + tagValue + " and " + operations[index]);
                    }
                }
            } else {
                String argument = ((StringListArgument) arg).getList().get(0);
                ZimbraLog.filter.debug("set variable argument: " + argument);
                if (varArgCount == 0) {
                    key = argument;
                }
                ++varArgCount;
            }
        }
        if (varArgCount != 2) {
            throw new SyntaxException("Exactly 2 arguments permitted. Found " + varArgCount);
        } else {
            if (!(isValidIdentifier(key))) {
                throw new SyntaxException("Variable identifier is invalid, got identifier " + key);
            }
        }
    } else {
        throw new SyntaxException("Minimum 2 arguments are needed. Usage: set :upperfirst \"b\" \"hello\";. Arguments found: " + arguments);
    }
}
Also used : TagArgument(org.apache.jsieve.TagArgument) Argument(org.apache.jsieve.Argument) StringListArgument(org.apache.jsieve.StringListArgument) SyntaxException(org.apache.jsieve.exception.SyntaxException) TagArgument(org.apache.jsieve.TagArgument)

Example 14 with TagArgument

use of org.apache.jsieve.TagArgument in project zm-mailbox by Zimbra.

the class StringTest method executeBasic.

/*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.jsieve.tests.AbstractTest#executeBasic(org.apache.jsieve.mail.
     * MailAdapter, org.apache.jsieve.Arguments, org.apache.jsieve.SieveContext)
     */
@Override
protected boolean executeBasic(MailAdapter mail, Arguments arguments, SieveContext context) throws SieveException {
    if (mail instanceof DummyMailAdapter) {
        return true;
    }
    if (!(mail instanceof ZimbraMailAdapter)) {
        return false;
    }
    ZimbraMailAdapter mailAdapter = (ZimbraMailAdapter) mail;
    String matchType = null;
    String comparator = null;
    String operator = null;
    List<String> sourceValues = null;
    List<String> keyValues = null;
    boolean nextArgumentIsRelationalSign = false;
    ListIterator<Argument> argumentsIter = arguments.getArgumentList().listIterator();
    boolean stop = false;
    //         <source: string-list> <key-list: string-list>
    while (!stop && argumentsIter.hasNext()) {
        Argument argument = argumentsIter.next();
        if (argument instanceof TagArgument) {
            final String tag = ((TagArgument) argument).getTag();
            // [COMPARATOR]?
            if (comparator == null && COMPARATOR_TAG.equalsIgnoreCase(tag)) {
                // The next argument must be a stringlist
                if (argumentsIter.hasNext()) {
                    argument = argumentsIter.next();
                    if (argument instanceof StringListArgument) {
                        List<String> stringList = ((StringListArgument) argument).getList();
                        if (stringList.size() != 1) {
                            throw context.getCoordinate().syntaxException("Expecting exactly one String");
                        }
                        comparator = stringList.get(0);
                    } else {
                        throw context.getCoordinate().syntaxException("Expecting a StringList");
                    }
                }
            } else // [MATCH-TYPE]?
            if (matchType == null && (IS_TAG.equalsIgnoreCase(tag) || CONTAINS_TAG.equalsIgnoreCase(tag) || MATCHES_TAG.equalsIgnoreCase(tag) || COUNT_TAG.equalsIgnoreCase(tag) || VALUE_TAG.equalsIgnoreCase(tag))) {
                matchType = tag;
                nextArgumentIsRelationalSign = true;
            } else {
                throw context.getCoordinate().syntaxException("Found unexpected TagArgument: \"" + tag + "\"");
            }
        } else {
            if (nextArgumentIsRelationalSign && argument instanceof StringListArgument) {
                String symbol = ((StringListArgument) argument).getList().get(0);
                if (matchType != null && (GT_OP.equalsIgnoreCase(symbol) || GE_OP.equalsIgnoreCase(symbol) || LT_OP.equalsIgnoreCase(symbol) || LE_OP.equalsIgnoreCase(symbol) || EQ_OP.equalsIgnoreCase(symbol) || NE_OP.equalsIgnoreCase(symbol))) {
                    operator = symbol;
                } else {
                    argumentsIter.previous();
                    stop = true;
                }
                nextArgumentIsRelationalSign = false;
            } else {
                // Stop when a non-tag argument is encountered
                argumentsIter.previous();
                stop = true;
            }
        }
    }
    // The next argument MUST be a string-list of header names
    if (argumentsIter.hasNext()) {
        final Argument argument = argumentsIter.next();
        if (argument instanceof StringListArgument) {
            List<String> sourceStringList = ((StringListArgument) argument).getList();
            if (null == sourceStringList || 0 == sourceStringList.size()) {
                throw context.getCoordinate().syntaxException("Expecting a StringListof header names");
            }
            sourceValues = new ArrayList<String>();
            for (String source : sourceStringList) {
                sourceValues.add(FilterUtil.replaceVariables(mailAdapter, source));
            }
        }
    }
    // The next argument MUST be a string-list of keys
    if (argumentsIter.hasNext()) {
        final Argument argument = argumentsIter.next();
        if (argument instanceof StringListArgument) {
            List<String> keyStringList = ((StringListArgument) argument).getList();
            if (null == keyStringList || 0 == keyStringList.size()) {
                throw context.getCoordinate().syntaxException("Expecting a StringList of keys");
            }
            keyValues = new ArrayList<String>();
            for (String key : keyStringList) {
                keyValues.add(FilterUtil.replaceVariables(mailAdapter, key));
            }
        }
    }
    if (argumentsIter.hasNext()) {
        throw context.getCoordinate().syntaxException("Found unexpected arguments");
    }
    if (null == matchType) {
        matchType = IS_TAG;
    }
    if (null == comparator) {
        if (matchType.equalsIgnoreCase(VALUE_TAG) || matchType.equalsIgnoreCase(COUNT_TAG)) {
            comparator = ASCII_NUMERIC_COMPARATOR;
        } else {
            comparator = ASCII_CASEMAP_COMPARATOR;
        }
    }
    boolean result = match(mail, comparator, matchType, operator, sourceValues, keyValues, context);
    if (result) {
        if (matchType.equals(MatchTypeTags.MATCHES_TAG)) {
            try {
                HeaderTest.evaluateVarExp(mailAdapter, sourceValues, HeaderTest.SourceType.LITERAL, keyValues);
            } catch (MessagingException e) {
                throw new SieveException("Exception occured while evaluating variable expression.", e);
            }
        }
    }
    return result;
}
Also used : SieveException(org.apache.jsieve.exception.SieveException) Argument(org.apache.jsieve.Argument) StringListArgument(org.apache.jsieve.StringListArgument) TagArgument(org.apache.jsieve.TagArgument) MessagingException(javax.mail.MessagingException) TagArgument(org.apache.jsieve.TagArgument) DummyMailAdapter(com.zimbra.cs.filter.DummyMailAdapter) StringListArgument(org.apache.jsieve.StringListArgument) ZimbraMailAdapter(com.zimbra.cs.filter.ZimbraMailAdapter)

Example 15 with TagArgument

use of org.apache.jsieve.TagArgument in project zm-mailbox by Zimbra.

the class NotifyMailto method execute.

/**
     * Execute RFC Compliant notify
     * @param mail The ZimbraMailAdapter
     * @param arguments The Sieve Arguments
     * @param context The Sieve Context
     * @throws SyntaxException
     */
private Object execute(MailAdapter mail, Arguments arguments, SieveContext context) throws SyntaxException {
    if (!(mail instanceof ZimbraMailAdapter)) {
        return null;
    }
    ZimbraMailAdapter mailAdapter = (ZimbraMailAdapter) mail;
    /*
         * RFC 5435 3.1. Notify Action
         * usage: notify [":from" string]
         *        [":importance" <"1" / "2" / "3">]
         *        [":options" string-list]
         *        [":message" string]
         *        <method: string>
         */
    String from = null;
    int importance = 0;
    String message = null;
    String method = null;
    String mailto = null;
    Map<String, String> options = null;
    Map<String, List<String>> mailtoParams = null;
    ListIterator<Argument> argumentsIter = arguments.getArgumentList().listIterator();
    boolean stop = false;
    // Tag processing
    while (!stop && argumentsIter.hasNext()) {
        Argument argument = argumentsIter.next();
        if (argument instanceof TagArgument) {
            final String tag = ((TagArgument) argument).getTag();
            if (from == null && NOTIFY_FROM.equals(tag)) {
                // The next argument must be a string
                if (argumentsIter.hasNext()) {
                    argument = argumentsIter.next();
                    if (argument instanceof StringListArgument) {
                        List<String> stringList = ((StringListArgument) argument).getList();
                        if (stringList.size() != 1) {
                            throw new SyntaxException("Expecting exactly one String for " + NOTIFY_FROM);
                        }
                        String email = FilterUtil.replaceVariables(mailAdapter, (String) stringList.get(0));
                        // Validate email address using javax.mail.internet.InternetAddress
                        try {
                            InternetAddress addr = new InternetAddress(email);
                            addr.validate();
                            from = email;
                        } catch (AddressException ex) {
                            // if the :from addr is not valid, the FilterUtil.notifyMailto() method takes
                            // care of the From header before composing the notification message.
                            ZimbraLog.filter.info("The value of the \":from\" [" + email + "] is not valid");
                        }
                    } else {
                        throw new SyntaxException("Expecting a StringList for " + NOTIFY_FROM);
                    }
                } else {
                    throw new SyntaxException("Expecting a parameter for " + NOTIFY_FROM);
                }
            } else if (importance == 0 && NOTIFY_IMPORTANCE.equals(tag)) {
                // The next argument must be a number
                if (argumentsIter.hasNext()) {
                    argument = argumentsIter.next();
                    if (argument instanceof StringListArgument) {
                        List<String> stringList = ((StringListArgument) argument).getList();
                        if (stringList.size() != 1) {
                            throw new SyntaxException("Expecting exactly one String for " + NOTIFY_IMPORTANCE);
                        }
                        String strImportance = (String) stringList.get(0);
                        FilterUtil.replaceVariables(mailAdapter, strImportance);
                        importance = Integer.parseInt(strImportance);
                        if (!(importance == 1 || importance == 2 || importance == 3)) {
                            throw new SyntaxException("Expecting an integer number (1, 2, 3) for " + NOTIFY_IMPORTANCE);
                        }
                    } else {
                        throw new SyntaxException("Expecting a StringList for " + NOTIFY_IMPORTANCE);
                    }
                } else {
                    throw new SyntaxException("Expecting a parameter for " + NOTIFY_IMPORTANCE);
                }
            } else if (options == null && NOTIFY_OPTIONS.equals(tag)) {
                // The next argument must be a string-list of options "<optionname>=<value>[,<optionname>=<value]*"
                if (argumentsIter.hasNext()) {
                    argument = argumentsIter.next();
                    if (argument instanceof StringListArgument) {
                        List<String> listOptions = ((StringListArgument) argument).getList();
                        if (listOptions.size() == 0) {
                            throw new SyntaxException("Expecting exactly one String for " + NOTIFY_OPTIONS);
                        }
                        options = new HashMap<String, String>();
                        for (String option : listOptions) {
                            String[] token = option.split("=");
                            String key = null;
                            String value = null;
                            if (token.length == 2) {
                                key = token[0];
                                value = token[1];
                            } else if (token.length == 1) {
                                key = token[0];
                                value = "";
                            } else {
                                key = "";
                                value = "";
                            }
                            key = FilterUtil.replaceVariables(mailAdapter, key);
                            value = FilterUtil.replaceVariables(mailAdapter, value);
                            options.put(key, value);
                        }
                    } else {
                        throw new SyntaxException("Expecting a StringList for " + NOTIFY_OPTIONS);
                    }
                } else {
                    throw new SyntaxException("Expecting a parameter for " + NOTIFY_OPTIONS);
                }
            } else if (message == null && NOTIFY_MESSAGE.equals(tag)) {
                // The next argment must be a string
                if (argumentsIter.hasNext()) {
                    argument = argumentsIter.next();
                    if (argument instanceof StringListArgument) {
                        List<String> stringList = ((StringListArgument) argument).getList();
                        if (stringList.size() != 1) {
                            throw new SyntaxException("Expecting exactly one String for " + NOTIFY_MESSAGE);
                        }
                        message = FilterUtil.replaceVariables(mailAdapter, (String) stringList.get(0));
                    } else {
                        throw new SyntaxException("Expecting a StringList for " + NOTIFY_MESSAGE);
                    }
                } else {
                    throw new SyntaxException("Expecting a parameter for " + NOTIFY_MESSAGE);
                }
            }
        } else {
            // Stop when a non-tag argument is encountered
            argumentsIter.previous();
            stop = true;
        }
    }
    // The next argument MUST be a <method: string>
    if (argumentsIter.hasNext()) {
        Argument argument = argumentsIter.next();
        if (argument instanceof StringListArgument) {
            List<String> stringList = ((StringListArgument) argument).getList();
            if (stringList.size() != 1) {
                throw new SyntaxException("Expecting exactly one String");
            }
            method = (String) stringList.get(0);
        } else {
            throw new SyntaxException("Expecting a StringList");
        }
    }
    if (method == null) {
        throw context.getCoordinate().syntaxException("Expecting a method string");
    } else {
        method = FilterUtil.replaceVariables(mailAdapter, method);
    }
    mailtoParams = new HashMap<String, List<String>>();
    try {
        URL url = new URL(method);
        mailto = FilterUtil.replaceVariables(mailAdapter, url.getPath());
        String query = url.getQuery();
        if (!StringUtil.isNullOrEmpty(query)) {
            String[] params = query.split("&");
            for (String param : params) {
                String[] token = param.split("=");
                if (token.length > 2) {
                    throw new SyntaxException("'mailto' method syntax error: too many parameters");
                } else {
                    if (StringUtils.isEmpty(token[0])) {
                        throw new SyntaxException("'mailto' method syntax error: empty parameter name");
                    }
                    FilterUtil.headerNameHasSpace(token[0]);
                }
                // If the value or parameter name is URL encoded, it should be
                // decoded.  If it is not even URL encoded, more or less decoding
                // the string does not do harm the contents.
                String headerName = null;
                String headerValue = null;
                try {
                    headerName = URLDecoder.decode(token[0].toLowerCase(), "UTF-8");
                } catch (UnsupportedEncodingException e) {
                // No exception should be thrown because the charset is always "UTF-8"
                } catch (IllegalArgumentException e) {
                    headerName = token[0].toLowerCase();
                }
                if (token.length == 1) {
                    // The value must be empty
                    headerValue = "";
                } else {
                    headerValue = token[1];
                }
                try {
                    headerValue = URLDecoder.decode(headerValue, "UTF-8");
                } catch (UnsupportedEncodingException e) {
                // No exception should be thrown because the charset is always "UTF-8"
                } catch (IllegalArgumentException e) {
                // Use token[1] as is
                }
                if (!mailtoParams.containsKey(headerName)) {
                    // Create a new entry for a header
                    List<String> value = new ArrayList<String>();
                    value.add(headerValue);
                    mailtoParams.put(headerName, value);
                } else {
                    // Some headers, such as to or cc fields, can be specified multiple times
                    mailtoParams.get(headerName).add(headerValue);
                }
            }
        }
    } catch (MalformedURLException e) {
        throw new SyntaxException("'mailto' method syntax error", e);
    }
    mail.addAction(new ActionNotifyMailto(from, options, importance, message, mailto, mailtoParams));
    return null;
}
Also used : InternetAddress(javax.mail.internet.InternetAddress) MalformedURLException(java.net.MalformedURLException) Argument(org.apache.jsieve.Argument) StringListArgument(org.apache.jsieve.StringListArgument) TagArgument(org.apache.jsieve.TagArgument) ArrayList(java.util.ArrayList) UnsupportedEncodingException(java.io.UnsupportedEncodingException) StringListArgument(org.apache.jsieve.StringListArgument) URL(java.net.URL) SyntaxException(org.apache.jsieve.exception.SyntaxException) TagArgument(org.apache.jsieve.TagArgument) AddressException(javax.mail.internet.AddressException) ArrayList(java.util.ArrayList) List(java.util.List) ZimbraMailAdapter(com.zimbra.cs.filter.ZimbraMailAdapter)

Aggregations

TagArgument (org.apache.jsieve.TagArgument)17 Argument (org.apache.jsieve.Argument)16 StringListArgument (org.apache.jsieve.StringListArgument)15 SyntaxException (org.apache.jsieve.exception.SyntaxException)12 ZimbraMailAdapter (com.zimbra.cs.filter.ZimbraMailAdapter)8 DummyMailAdapter (com.zimbra.cs.filter.DummyMailAdapter)4 ServiceException (com.zimbra.common.service.ServiceException)3 Date (java.util.Date)3 List (java.util.List)3 ZimbraSieveException (com.zimbra.cs.filter.ZimbraSieveException)2 ParseException (java.text.ParseException)2 ArrayList (java.util.ArrayList)2 Calendar (java.util.Calendar)2 TimeZone (java.util.TimeZone)2 Sieve (com.zimbra.common.filter.Sieve)1 FilterTest (com.zimbra.soap.mail.type.FilterTest)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 MalformedURLException (java.net.MalformedURLException)1 URL (java.net.URL)1 DateFormat (java.text.DateFormat)1