diff --git a/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java b/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java index bc5320d0d8..2cc3932889 100644 --- a/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java +++ b/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java @@ -25,10 +25,12 @@ import android.os.Handler; import android.text.TextUtils; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.paging.PagedList; import androidx.preference.PreferenceManager; import com.sun.mail.iap.Argument; +import com.sun.mail.iap.ProtocolException; import com.sun.mail.iap.Response; import com.sun.mail.imap.IMAPFolder; import com.sun.mail.imap.IMAPMessage; @@ -38,11 +40,12 @@ import com.sun.mail.imap.protocol.IMAPResponse; import java.io.File; import java.io.IOException; -import java.nio.charset.StandardCharsets; +import java.io.Serializable; import java.text.Normalizer; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.concurrent.ExecutorService; import javax.mail.FetchProfile; @@ -61,6 +64,7 @@ import javax.mail.search.FlagTerm; import javax.mail.search.FromStringTerm; import javax.mail.search.OrTerm; import javax.mail.search.RecipientStringTerm; +import javax.mail.search.SearchException; import javax.mail.search.SearchTerm; import javax.mail.search.SubjectTerm; @@ -71,7 +75,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback 0 && state.index >= state.matches.size())) { state.matches = db.message().matchMessages( account, folder, - "%" + find + "%", - seen, flagged, snoozed, encrypted, attachments, + criteria.query == null ? null : "%" + criteria.query + "%", + criteria.with_unseen, + criteria.with_flagged, + criteria.with_hidden, + criteria.with_encrypted, + criteria.with_attachments, SEARCH_LIMIT, state.offset); Log.i("Boundary device folder=" + folder + - " query=" + query + - " seen=" + seen + - " flagged=" + flagged + - " snoozed=" + snoozed + - " encrypted=" + encrypted + - " attachments=" + attachments + + " criteria=" + criteria + " offset=" + state.offset + " size=" + state.matches.size()); state.offset += Math.min(state.matches.size(), SEARCH_LIMIT); @@ -260,25 +243,20 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback 0 && responses[responses.length - 1].isOK()) { - Log.i("Boundary UTF8 search=" + query); + Log.i("Boundary raw search=" + criteria.query); List msgnums = new ArrayList<>(); for (Response response : responses) @@ -442,37 +380,68 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback 0) - Log.e("Search response=" + responses[responses.length - 1]); - - // Assume no UTF-8 support - String search = query.replace("ß", "ss"); // Eszett - search = Normalizer.normalize(search, Normalizer.Form.NFD) - .replaceAll("[^\\p{ASCII}]", ""); - - Log.i("Boundary ASCII search=" + search); - SearchTerm term = new FromStringTerm(search); - term = new OrTerm(term, new RecipientStringTerm(Message.RecipientType.TO, search)); - term = new OrTerm(term, new RecipientStringTerm(Message.RecipientType.CC, search)); - term = new OrTerm(term, new SubjectTerm(search)); - if (search_text) - term = new OrTerm(term, new BodyTerm(search)); - if (keywords) - term = new OrTerm(term, new FlagTerm( - new Flags(MessageHelper.sanitizeKeyword(search)), true)); + Log.i("Boundary search=" + criteria); + + List or = new ArrayList<>(); + List and = new ArrayList<>(); + if (criteria.query != null) { + String search = criteria.query; + + if (!protocol.supportsUtf8()) { + search = search.replace("ß", "ss"); // Eszett + search = Normalizer.normalize(search, Normalizer.Form.NFD) + .replaceAll("[^\\p{ASCII}]", ""); + } + + // Yahoo! does not support keyword search, but uses the flags $Forwarded $Junk $NotJunk + boolean keywords = false; + for (String keyword : browsable.keywords) + if (!keyword.startsWith("$")) { + keywords = true; + break; + } + + if (criteria.in_senders) + or.add(new FromStringTerm(search)); + if (criteria.in_receipients) { + or.add(new RecipientStringTerm(Message.RecipientType.TO, search)); + or.add(new RecipientStringTerm(Message.RecipientType.CC, search)); + } + if (criteria.in_subject) + or.add(new SubjectTerm(search)); + if (criteria.in_keywords && keywords) + or.add(new FlagTerm(new Flags(MessageHelper.sanitizeKeyword(search)), true)); + if (criteria.in_message) + or.add(new BodyTerm(search)); + } + + if (criteria.with_unseen) + and.add(new FlagTerm(new Flags(Flags.Flag.SEEN), false)); + if (criteria.with_flagged) + and.add(new FlagTerm(new Flags(Flags.Flag.FLAGGED), true)); + + SearchTerm term = null; + + if (or.size() > 0) + term = new OrTerm(or.toArray(new SearchTerm[0])); + + if (and.size() > 0) + if (term == null) + term = new AndTerm(and.toArray(new SearchTerm[0])); + else + term = new AndTerm(term, new AndTerm(and.toArray(new SearchTerm[0]))); + + if (term == null) + throw new SearchException(); return state.ifolder.search(term); } } catch (MessagingException ex) { - Log.e(ex); - return ex; + throw new ProtocolException("Search", ex); } } }); - if (result instanceof MessagingException) - throw (MessagingException) result; - state.imessages = (Message[]) result; } Log.i("Boundary server found messages=" + state.imessages.length); @@ -541,7 +510,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback