Experiment: search attachment content

This commit is contained in:
M66B
2023-08-09 18:54:37 +02:00
parent 9276018795
commit b03f0ebe6b
10 changed files with 199 additions and 21 deletions

View File

@@ -2427,6 +2427,7 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
criteria.in_subject = false;
criteria.in_keywords = false;
criteria.in_message = false;
criteria.in_attachments = false;
criteria.in_notes = false;
}

View File

@@ -525,6 +525,7 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
criteria.in_subject = false;
criteria.in_keywords = false;
criteria.in_message = false;
criteria.in_attachments = false;
criteria.in_notes = false;
criteria.with_unseen = true;
FragmentMessages.search(
@@ -539,6 +540,7 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
criteria.in_subject = false;
criteria.in_keywords = false;
criteria.in_message = false;
criteria.in_attachments = false;
criteria.in_notes = false;
criteria.with_flagged = true;
FragmentMessages.search(

View File

@@ -39,6 +39,7 @@ import com.sun.mail.imap.protocol.IMAPProtocol;
import com.sun.mail.imap.protocol.IMAPResponse;
import com.sun.mail.imap.protocol.SearchSequence;
import com.sun.mail.util.MessageRemovedIOException;
import com.twitter.elephantbird.util.StreamSearcher;
import org.json.JSONArray;
import org.json.JSONException;
@@ -46,9 +47,12 @@ import org.json.JSONObject;
import org.jsoup.nodes.Document;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.Normalizer;
import java.util.ArrayList;
@@ -341,6 +345,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
//criteria.in_subject,
//criteria.in_keywords,
//criteria.in_message,
//criteria.in_attachments,
//criteria.in_notes,
//criteria.in_headers,
criteria.with_unseen,
@@ -866,6 +871,37 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
Log.e(ex);
}
if (criteria.in_attachments && !TextUtils.isEmpty(criteria.query))
try {
DB db = DB.getInstance(context);
List<EntityAttachment> attachments = db.attachment().getAttachments(message.id);
if (attachments != null)
for (EntityAttachment attachment : attachments) {
File file = attachment.getFile(context);
if (file.exists() && file.length() > 0) {
byte[] sample = new byte[(int) Math.min(4096, file.length())];
try (InputStream is = new FileInputStream(file)) {
Helper.readBuffer(is, sample);
}
Charset detected = CharsetHelper.detect(sample, null);
if (detected == null)
detected = StandardCharsets.ISO_8859_1;
Log.i("Searching for " + criteria.query +
" as " + detected +
" in " + file.getName() + ":" + file.length());
try (InputStream is = new FileInputStream(file)) {
StreamSearcher searcher = new StreamSearcher(criteria.query.getBytes(detected));
if (searcher.search(is) > 0)
return true;
}
}
}
} catch (Throwable ex) {
Log.e(ex);
}
return false;
}
@@ -987,6 +1023,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
boolean in_subject = true;
boolean in_keywords = true;
boolean in_message = true;
boolean in_attachments = false;
boolean in_notes = true;
boolean in_headers = false;
boolean in_html = false;
@@ -1272,6 +1309,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
this.in_subject == other.in_subject &&
this.in_keywords == other.in_keywords &&
this.in_message == other.in_message &&
this.in_attachments == other.in_attachments &&
this.in_notes == other.in_notes &&
this.in_headers == other.in_headers &&
this.in_html == other.in_html &&
@@ -1300,6 +1338,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
json.put("in_subject", in_subject);
json.put("in_keywords", in_keywords);
json.put("in_message", in_message);
json.put("in_attachments", in_attachments);
json.put("in_notes", in_notes);
json.put("in_headers", in_headers);
json.put("in_html", in_html);
@@ -1347,6 +1386,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
criteria.in_subject = json.optBoolean("in_subject");
criteria.in_keywords = json.optBoolean("in_keywords");
criteria.in_message = json.optBoolean("in_message");
criteria.in_attachments = json.optBoolean("in_attachments");
criteria.in_notes = json.optBoolean("in_notes");
criteria.in_headers = json.optBoolean("in_headers");
criteria.in_html = json.optBoolean("in_html");
@@ -1395,6 +1435,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
" subject=" + in_subject +
" keywords=" + in_keywords +
" message=" + in_message +
" attachment=" + in_attachments +
" notes=" + in_notes +
" headers=" + in_headers +
" html=" + in_html +

View File

@@ -225,19 +225,7 @@ public class CharsetHelper {
try {
byte[] octets = text.getBytes(StandardCharsets.ISO_8859_1);
byte[] sample;
if (octets.length < MAX_SAMPLE_SIZE)
sample = octets;
else {
sample = new byte[MAX_SAMPLE_SIZE];
System.arraycopy(octets, 0, sample, 0, MAX_SAMPLE_SIZE);
}
Log.i("compact_enc_det sample=" + sample.length);
DetectResult detected = jni_detect_charset(sample,
ref == null ? StandardCharsets.ISO_8859_1.name() : ref.name(),
Locale.getDefault().getLanguage());
DetectResult detected = _detect(octets, ref);
if (TextUtils.isEmpty(detected.charset)) {
Log.e("compact_enc_det result=" + detected);
@@ -262,7 +250,34 @@ public class CharsetHelper {
}
}
private static class DetectResult {
public static Charset detect(byte[] octets, Charset ref) {
try {
DetectResult detected = _detect(octets, ref);
if (TextUtils.isEmpty(detected.charset))
return null;
return Charset.forName(detected.charset);
} catch (Throwable ex) {
Log.w(ex);
return null;
}
}
private static DetectResult _detect(byte[] octets, Charset ref) {
byte[] sample;
if (octets.length < MAX_SAMPLE_SIZE)
sample = octets;
else {
sample = new byte[MAX_SAMPLE_SIZE];
System.arraycopy(octets, 0, sample, 0, MAX_SAMPLE_SIZE);
}
Log.i("compact_enc_det sample=" + sample.length);
return jni_detect_charset(sample,
ref == null ? StandardCharsets.ISO_8859_1.name() : ref.name(),
Locale.getDefault().getLanguage());
}
public static class DetectResult {
String charset;
int sample_size;
int bytes_consumed;

View File

@@ -114,6 +114,7 @@ public class FragmentDialogSearch extends FragmentDialogBase {
CheckBox cbKeywords = dview.findViewById(R.id.cbKeywords);
CheckBox cbMessage = dview.findViewById(R.id.cbMessage);
TextView tvSearchTextUnsupported = dview.findViewById(R.id.tvSearchTextUnsupported);
CheckBox cbAttachments = dview.findViewById(R.id.cbAttachments);
CheckBox cbNotes = dview.findViewById(R.id.cbNotes);
CheckBox cbHeaders = dview.findViewById(R.id.cbHeaders);
CheckBox cbHtml = dview.findViewById(R.id.cbHtml);
@@ -123,7 +124,7 @@ public class FragmentDialogSearch extends FragmentDialogBase {
CheckBox cbFlagged = dview.findViewById(R.id.cbFlagged);
CheckBox cbHidden = dview.findViewById(R.id.cbHidden);
CheckBox cbEncrypted = dview.findViewById(R.id.cbEncrypted);
CheckBox cbAttachments = dview.findViewById(R.id.cbAttachments);
CheckBox cbWithAttachments = dview.findViewById(R.id.cbWithAttachments);
Spinner spMessageSize = dview.findViewById(R.id.spMessageSize);
Button btnBefore = dview.findViewById(R.id.btnBefore);
Button btnAfter = dview.findViewById(R.id.btnAfter);
@@ -430,6 +431,7 @@ public class FragmentDialogSearch extends FragmentDialogBase {
criteria.in_subject = cbSubject.isChecked();
criteria.in_keywords = cbKeywords.isChecked();
criteria.in_message = cbMessage.isChecked();
criteria.in_attachments = cbAttachments.isChecked();
criteria.in_notes = cbNotes.isChecked();
criteria.in_headers = cbHeaders.isChecked();
criteria.in_html = cbHtml.isChecked();
@@ -437,7 +439,7 @@ public class FragmentDialogSearch extends FragmentDialogBase {
criteria.with_flagged = cbFlagged.isChecked();
criteria.with_hidden = cbHidden.isChecked();
criteria.with_encrypted = cbEncrypted.isChecked();
criteria.with_attachments = cbAttachments.isChecked();
criteria.with_attachments = cbWithAttachments.isChecked();
if (!criteria.fts) {
int pos = spMessageSize.getSelectedItemPosition();