Search in sources :

Example 1 with ParseException

use of org.apache.jsieve.parser.generated.ParseException in project zm-mailbox by Zimbra.

the class RuleManager method setRules.

/**
     * Saves the filter rules.
     *
     * @param entry the account/domain/cos/server for which the rules are to be saved
     * @param script the sieve script, or <code>null</code> or empty string if
     * all rules should be deleted
     * @param sieveScriptAttrName
     * @param rulesCacheKey
     * @throws ServiceException
     */
private static void setRules(Entry entry, String script, String sieveScriptAttrName, String rulesCacheKey) throws ServiceException {
    if (entry instanceof Account) {
        ZimbraLog.filter.debug("Setting filter rules for account %s:\n%s", ((Account) entry).getName(), script);
    } else if (entry instanceof Domain) {
        ZimbraLog.filter.debug("Setting filter rules for domian %s:\n%s", ((Domain) entry).getName(), script);
    } else if (entry instanceof Cos) {
        ZimbraLog.filter.debug("Setting filter rules for cos %s:\n%s", ((Cos) entry).getName(), script);
    } else if (entry instanceof Server) {
        ZimbraLog.filter.debug("Setting filter rules for server %s:\n%s", ((Server) entry).getName(), script);
    }
    if (script == null) {
        script = "";
    }
    try {
        Node node = parse(script);
        // evaluate against dummy mail adapter to catch more errors
        SIEVE_FACTORY.evaluate(new DummyMailAdapter(), node);
        // save
        Map<String, Object> attrs = new HashMap<String, Object>();
        attrs.put(sieveScriptAttrName, script);
        Provisioning.getInstance().modifyAttrs(entry, attrs);
        entry.setCachedData(rulesCacheKey, node);
    } catch (ParseException e) {
        ZimbraLog.filter.error("Unable to parse script:\n" + script);
        throw ServiceException.PARSE_ERROR("parsing Sieve script", e);
    } catch (TokenMgrError e) {
        ZimbraLog.filter.error("Unable to parse script:\n" + script);
        throw ServiceException.PARSE_ERROR("parsing Sieve script", e);
    } catch (SieveException e) {
        ZimbraLog.filter.error("Unable to evaluate script:\n" + script);
        throw ServiceException.PARSE_ERROR("evaluating Sieve script", e);
    }
}
Also used : Account(com.zimbra.cs.account.Account) Server(com.zimbra.cs.account.Server) HashMap(java.util.HashMap) Cos(com.zimbra.cs.account.Cos) Node(org.apache.jsieve.parser.generated.Node) TokenMgrError(org.apache.jsieve.parser.generated.TokenMgrError) SieveException(org.apache.jsieve.exception.SieveException) ParseException(org.apache.jsieve.parser.generated.ParseException) Domain(com.zimbra.cs.account.Domain)

Example 2 with ParseException

use of org.apache.jsieve.parser.generated.ParseException in project zm-mailbox by Zimbra.

the class ApplyFilterRules method handle.

@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    Account account = getRequestedAccount(zsc);
    if (!canAccessAccount(zsc, account))
        throw ServiceException.PERM_DENIED("cannot access account");
    // Get rules.
    String fullScript = getRules(account);
    if (StringUtil.isNullOrEmpty(fullScript)) {
        throw ServiceException.INVALID_REQUEST("Account has no filter rules defined.", null);
    }
    List<Element> ruleElements = request.getElement(MailConstants.E_FILTER_RULES).listElements(MailConstants.E_FILTER_RULE);
    if (ruleElements.size() == 0) {
        String msg = String.format("No %s elements specified.", MailConstants.E_FILTER_RULE);
        throw ServiceException.INVALID_REQUEST(msg, null);
    }
    // Concatenate script parts and create a new script to run on existing messages.
    StringBuilder buf = new StringBuilder();
    for (Element ruleEl : ruleElements) {
        String name = ruleEl.getAttribute(MailConstants.A_NAME);
        String singleRule = RuleManager.getRuleByName(fullScript, name);
        if (singleRule == null) {
            String msg = String.format("Could not find a rule named '%s'", name);
            throw ServiceException.INVALID_REQUEST(msg, null);
        }
        buf.append(singleRule).append("\n");
    }
    String partialScript = buf.toString();
    ZimbraLog.filter.debug("Applying partial script to existing messages: %s", partialScript);
    Node node = null;
    try {
        node = RuleManager.parse(partialScript);
    } catch (ParseException e) {
        throw ServiceException.FAILURE("Unable to parse Sieve script: " + partialScript, e);
    }
    // Get the ids of the messages to filter.
    Element msgEl = request.getOptionalElement(MailConstants.E_MSG);
    String query = getElementText(request, MailConstants.E_QUERY);
    if (msgEl != null && query != null) {
        String msg = String.format("Cannot specify both %s and %s elements.", MailConstants.E_MSG, MailConstants.E_QUERY);
        throw ServiceException.INVALID_REQUEST(msg, null);
    }
    Mailbox mbox = getRequestedMailbox(zsc);
    List<Integer> messageIds = new ArrayList<Integer>();
    List<Integer> affectedIds = new ArrayList<Integer>();
    OperationContext octxt = getOperationContext(zsc, context);
    if (msgEl != null) {
        String[] ids = msgEl.getAttribute(MailConstants.A_IDS).split(",");
        for (String id : ids) {
            messageIds.add(Integer.valueOf(id));
        }
    } else if (query != null) {
        ZimbraQueryResults results = null;
        try {
            results = mbox.index.search(octxt, query, EnumSet.of(MailItem.Type.MESSAGE), SortBy.NONE, Integer.MAX_VALUE);
            while (results.hasNext()) {
                ZimbraHit hit = results.getNext();
                messageIds.add(hit.getItemId());
            }
        } catch (Exception e) {
            String msg = String.format("Unable to run search for query: '%s'", query);
            throw ServiceException.INVALID_REQUEST(msg, e);
        } finally {
            Closeables.closeQuietly(results);
        }
    } else {
        String msg = String.format("Must specify either the %s or %s element.", MailConstants.E_MSG, MailConstants.E_QUERY);
        throw ServiceException.INVALID_REQUEST(msg, null);
    }
    int max = account.getFilterBatchSize();
    if (messageIds.size() > max) {
        throw ServiceException.INVALID_REQUEST("Attempted to apply filter rules to " + messageIds.size() + " messages, which exceeded the limit of " + max, null);
    }
    ZimbraLog.filter.info("Applying filter rules to %s existing messages.", messageIds.size());
    long sleepInterval = account.getFilterSleepInterval();
    // Apply filter rules.
    for (int i = 0; i < messageIds.size(); i++) {
        if (i > 0 && sleepInterval > 0) {
            try {
                Thread.sleep(sleepInterval);
            } catch (InterruptedException e) {
            }
        }
        int id = messageIds.get(i);
        try {
            mbox.getMessageById(octxt, id);
            if (RuleManager.applyRulesToExistingMessage(octxt, mbox, id, node)) {
                affectedIds.add(id);
            }
        } catch (NoSuchItemException e) {
            // Message was deleted since the search was done (bug 41609).
            ZimbraLog.filter.info("Skipping message %d: %s.", id, e.toString());
        } catch (ServiceException e) {
            ZimbraLog.filter.warn("Unable to filter message %d.", id, e);
        }
    }
    // Send response.
    Element response = zsc.createElement(getResponseElementName());
    if (affectedIds.size() > 0) {
        response.addElement(MailConstants.E_MSG).addAttribute(MailConstants.A_IDS, StringUtil.join(",", affectedIds));
    }
    return response;
}
Also used : OperationContext(com.zimbra.cs.mailbox.OperationContext) ZimbraHit(com.zimbra.cs.index.ZimbraHit) Account(com.zimbra.cs.account.Account) Element(com.zimbra.common.soap.Element) Node(org.apache.jsieve.parser.generated.Node) ArrayList(java.util.ArrayList) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) ServiceException(com.zimbra.common.service.ServiceException) ParseException(org.apache.jsieve.parser.generated.ParseException) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) Mailbox(com.zimbra.cs.mailbox.Mailbox) ServiceException(com.zimbra.common.service.ServiceException) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) ZimbraQueryResults(com.zimbra.cs.index.ZimbraQueryResults) ParseException(org.apache.jsieve.parser.generated.ParseException)

Example 3 with ParseException

use of org.apache.jsieve.parser.generated.ParseException in project zm-mailbox by Zimbra.

the class RuleManager method parse.

/**
     * Parses the sieve script and returns the root to the resulting node tree.
     */
public static Node parse(String script) throws ParseException {
    ByteArrayInputStream sin;
    try {
        sin = new ByteArrayInputStream(script.getBytes("UTF-8"));
    } catch (UnsupportedEncodingException e) {
        throw new ParseException(e.getMessage());
    }
    Node node = null;
    try {
        node = SIEVE_FACTORY.parse(sin);
    } catch (TokenMgrError e) {
        // filter string without any undefined escape sequences.
        try {
            sin = new ByteArrayInputStream(ignoreBackslash(script).getBytes("UTF-8"));
        } catch (UnsupportedEncodingException uee) {
            throw new ParseException(uee.getMessage());
        }
        node = SIEVE_FACTORY.parse(sin);
    }
    return node;
}
Also used : ByteArrayInputStream(java.io.ByteArrayInputStream) Node(org.apache.jsieve.parser.generated.Node) UnsupportedEncodingException(java.io.UnsupportedEncodingException) TokenMgrError(org.apache.jsieve.parser.generated.TokenMgrError) ParseException(org.apache.jsieve.parser.generated.ParseException)

Example 4 with ParseException

use of org.apache.jsieve.parser.generated.ParseException in project zm-mailbox by Zimbra.

the class RuleManager method getRulesAsXML.

private static List<FilterRule> getRulesAsXML(Account account, FilterType filterType) throws ServiceException {
    Node node;
    try {
        node = getRulesNode(account, filterType, false);
    } catch (ParseException e) {
        throw ServiceException.PARSE_ERROR("parsing Sieve script", e);
    } catch (TokenMgrError e) {
        throw ServiceException.PARSE_ERROR("parsing Sieve script", e);
    }
    String sieveScriptAttrName = null;
    if (filterType == FilterType.INCOMING) {
        sieveScriptAttrName = Provisioning.A_zimbraMailSieveScript;
    } else {
        sieveScriptAttrName = Provisioning.A_zimbraMailOutgoingSieveScript;
    }
    SieveToSoap sieveToSoap = new SieveToSoap(getRuleNames(account.getAttr(sieveScriptAttrName)));
    sieveToSoap.accept(node);
    return sieveToSoap.toFilterRules();
}
Also used : Node(org.apache.jsieve.parser.generated.Node) TokenMgrError(org.apache.jsieve.parser.generated.TokenMgrError) ParseException(org.apache.jsieve.parser.generated.ParseException)

Example 5 with ParseException

use of org.apache.jsieve.parser.generated.ParseException in project zm-mailbox by Zimbra.

the class RuleManager method tagDeleted.

private static void tagDeleted(Account account, String tagName, String sieveScriptAttrName, String rulesCacheKey) throws ServiceException {
    String script = getRules(account, sieveScriptAttrName);
    if (script != null) {
        Node node;
        try {
            node = parse(script);
        } catch (ParseException e) {
            ZimbraLog.filter.warn("Unable to update %s after tag '%s' was deleted.", sieveScriptAttrName, tagName, e);
            return;
        }
        TagDeleted deleted = new TagDeleted(tagName);
        deleted.accept(node);
        if (deleted.modified()) {
            // Kind of a hacky way to convert a Node tree to a script.  We
            // convert to XML first, and then to a String.  Unfortunately
            // jSieve 0.2 doesn't have an API that generates a script from
            // a Node tree.
            List<String> ruleNames = getRuleNames(script);
            SieveToSoap sieveToSoap = new SieveToSoap(ruleNames);
            sieveToSoap.accept(node);
            SoapToSieve soapToSieve = new SoapToSieve(sieveToSoap.toFilterRules());
            String newScript = soapToSieve.getSieveScript();
            setRules(account, newScript, sieveScriptAttrName, rulesCacheKey);
            ZimbraLog.filter.info("Updated %s after tag %s was deleted.", sieveScriptAttrName, tagName);
            ZimbraLog.filter.debug("Old rules:\n%s, new rules:\n%s", script, newScript);
        }
    }
}
Also used : Node(org.apache.jsieve.parser.generated.Node) ParseException(org.apache.jsieve.parser.generated.ParseException)

Aggregations

Node (org.apache.jsieve.parser.generated.Node)8 ParseException (org.apache.jsieve.parser.generated.ParseException)8 TokenMgrError (org.apache.jsieve.parser.generated.TokenMgrError)4 Account (com.zimbra.cs.account.Account)2 ServiceException (com.zimbra.common.service.ServiceException)1 Element (com.zimbra.common.soap.Element)1 Cos (com.zimbra.cs.account.Cos)1 Domain (com.zimbra.cs.account.Domain)1 Server (com.zimbra.cs.account.Server)1 ZimbraHit (com.zimbra.cs.index.ZimbraHit)1 ZimbraQueryResults (com.zimbra.cs.index.ZimbraQueryResults)1 NoSuchItemException (com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException)1 Mailbox (com.zimbra.cs.mailbox.Mailbox)1 OperationContext (com.zimbra.cs.mailbox.OperationContext)1 ZimbraSoapContext (com.zimbra.soap.ZimbraSoapContext)1 ByteArrayInputStream (java.io.ByteArrayInputStream)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 SieveException (org.apache.jsieve.exception.SieveException)1