forked from I2P_Developers/i2p.i2p
SusiMail: Improve speed of subject sorter
Use ID instead of hashcode for mailparts, so attachments are bookmarkable Recognize fw:
This commit is contained in:
@@ -45,6 +45,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
@@ -179,7 +180,7 @@ class Mail {
|
|||||||
// TODO just fail?
|
// TODO just fail?
|
||||||
if (headerLines == null)
|
if (headerLines == null)
|
||||||
headerLines = new String[0];
|
headerLines = new String[0];
|
||||||
part = new MailPart(uidl, rb, in, in, headerLines);
|
part = new MailPart(uidl, new AtomicInteger(), rb, in, in, headerLines);
|
||||||
rb.readComplete(true);
|
rb.readComplete(true);
|
||||||
// may only be available after reading and calling readComplete()
|
// may only be available after reading and calling readComplete()
|
||||||
size = rb.getLength();
|
size = rb.getLength();
|
||||||
|
@@ -44,6 +44,7 @@ import java.io.OutputStream;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
|
|
||||||
@@ -79,6 +80,7 @@ class MailPart {
|
|||||||
* @since 0.9.33
|
* @since 0.9.33
|
||||||
*/
|
*/
|
||||||
public final String uidl;
|
public final String uidl;
|
||||||
|
private final int intID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param readBuffer has zero offset for top-level MailPart.
|
* @param readBuffer has zero offset for top-level MailPart.
|
||||||
@@ -88,9 +90,10 @@ class MailPart {
|
|||||||
* @param hdrlines non-null for top-level MailPart, where they
|
* @param hdrlines non-null for top-level MailPart, where they
|
||||||
* were already parsed in Mail. Null otherwise
|
* were already parsed in Mail. Null otherwise
|
||||||
*/
|
*/
|
||||||
public MailPart(String uidl, Buffer readBuffer, InputStream in, ReadCounter counter, String[] hdrlines) throws IOException
|
public MailPart(String uidl, AtomicInteger id, Buffer readBuffer, InputStream in, ReadCounter counter, String[] hdrlines) throws IOException
|
||||||
{
|
{
|
||||||
this.uidl = uidl;
|
this.uidl = uidl;
|
||||||
|
intID = id.getAndIncrement();
|
||||||
buffer = readBuffer;
|
buffer = readBuffer;
|
||||||
|
|
||||||
parts = new ArrayList<MailPart>(4);
|
parts = new ArrayList<MailPart>(4);
|
||||||
@@ -219,7 +222,7 @@ class MailPart {
|
|||||||
match = DataHelper.getASCII("\r\n--" + boundary);
|
match = DataHelper.getASCII("\r\n--" + boundary);
|
||||||
eofin = new EOFOnMatchInputStream(in, counter, match);
|
eofin = new EOFOnMatchInputStream(in, counter, match);
|
||||||
}
|
}
|
||||||
MailPart newPart = new MailPart(uidl, buffer, eofin, eofin, null);
|
MailPart newPart = new MailPart(uidl, id, buffer, eofin, eofin, null);
|
||||||
parts.add( newPart );
|
parts.add( newPart );
|
||||||
tmpEnd = (int) eofin.getRead();
|
tmpEnd = (int) eofin.getRead();
|
||||||
if (!eofin.wasFound()) {
|
if (!eofin.wasFound()) {
|
||||||
@@ -233,7 +236,7 @@ class MailPart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( message ) {
|
else if( message ) {
|
||||||
MailPart newPart = new MailPart(uidl, buffer, in, counter, null);
|
MailPart newPart = new MailPart(uidl, id, buffer, in, counter, null);
|
||||||
// TODO newPart doesn't save message headers we might like to display,
|
// TODO newPart doesn't save message headers we might like to display,
|
||||||
// like From, To, and Subject
|
// like From, To, and Subject
|
||||||
parts.add( newPart );
|
parts.add( newPart );
|
||||||
@@ -251,6 +254,15 @@ class MailPart {
|
|||||||
// Debug.debug(Debug.DEBUG, "New " + this);
|
// Debug.debug(Debug.DEBUG, "New " + this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A value unique across all the parts of this Mail,
|
||||||
|
* and constant across restarts, so it may be part of a bookmark.
|
||||||
|
*
|
||||||
|
* @since 0.9.34
|
||||||
|
*/
|
||||||
|
public int getID() { return intID; }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swallow "\r\n" or "--\r\n".
|
* Swallow "\r\n" or "--\r\n".
|
||||||
* We don't have any pushback if this goes wrong.
|
* We don't have any pushback if this goes wrong.
|
||||||
|
@@ -132,9 +132,9 @@ public class WebMail extends HttpServlet
|
|||||||
* hidden params
|
* hidden params
|
||||||
*/
|
*/
|
||||||
private static final String SUSI_NONCE = "susiNonce";
|
private static final String SUSI_NONCE = "susiNonce";
|
||||||
private static final String B64UIDL = "b64uidl";
|
private static final String B64UIDL = "msg";
|
||||||
private static final String PREV_B64UIDL = "prevb64uidl";
|
private static final String PREV_B64UIDL = "prevmsg";
|
||||||
private static final String NEXT_B64UIDL = "nextb64uidl";
|
private static final String NEXT_B64UIDL = "nextmsg";
|
||||||
private static final String PREV_PAGE_NUM = "prevpagenum";
|
private static final String PREV_PAGE_NUM = "prevpagenum";
|
||||||
private static final String NEXT_PAGE_NUM = "nextpagenum";
|
private static final String NEXT_PAGE_NUM = "nextpagenum";
|
||||||
private static final String CURRENT_SORT = "currentsort";
|
private static final String CURRENT_SORT = "currentsort";
|
||||||
@@ -349,6 +349,8 @@ public class WebMail extends HttpServlet
|
|||||||
* @author susi
|
* @author susi
|
||||||
*/
|
*/
|
||||||
private static class SubjectSorter extends SorterBase {
|
private static class SubjectSorter extends SorterBase {
|
||||||
|
private static final String xre = _t("Re:").toLowerCase(Locale.US);
|
||||||
|
private static final String xfwd = _t("Fwd:").toLowerCase(Locale.US);
|
||||||
private final Comparator<Object> collator = Collator.getInstance();
|
private final Comparator<Object> collator = Collator.getInstance();
|
||||||
|
|
||||||
public SubjectSorter( MailCache mailCache )
|
public SubjectSorter( MailCache mailCache )
|
||||||
@@ -359,31 +361,29 @@ public class WebMail extends HttpServlet
|
|||||||
protected int compare(Mail a, Mail b) {
|
protected int compare(Mail a, Mail b) {
|
||||||
String as = a.subject;
|
String as = a.subject;
|
||||||
String bs = b.subject;
|
String bs = b.subject;
|
||||||
if (as.toLowerCase().startsWith("re:")) {
|
String aslc = as.toLowerCase(Locale.US);
|
||||||
|
String bslc = bs.toLowerCase(Locale.US);
|
||||||
|
if (aslc.startsWith("re:") || aslc.startsWith("fw:")) {
|
||||||
as = as.substring(3).trim();
|
as = as.substring(3).trim();
|
||||||
} else if (as.toLowerCase().startsWith("fwd:")) {
|
} else if (aslc.startsWith("fwd:")) {
|
||||||
as = as.substring(4).trim();
|
as = as.substring(4).trim();
|
||||||
} else {
|
} else {
|
||||||
String xre = _t("Re:").toLowerCase();
|
if (aslc.startsWith(xre)) {
|
||||||
if (as.toLowerCase().startsWith(xre)) {
|
|
||||||
as = as.substring(xre.length()).trim();
|
as = as.substring(xre.length()).trim();
|
||||||
} else {
|
} else {
|
||||||
String xfwd = _t("Fwd:").toLowerCase();
|
if (aslc.startsWith(xfwd))
|
||||||
if (as.toLowerCase().startsWith(xfwd))
|
|
||||||
as = as.substring(xfwd.length()).trim();
|
as = as.substring(xfwd.length()).trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bs.toLowerCase().startsWith("re:")) {
|
if (bslc.startsWith("re:") || bslc.startsWith("fw:")) {
|
||||||
bs = bs.substring(3).trim();
|
bs = bs.substring(3).trim();
|
||||||
} else if (bs.toLowerCase().startsWith("fwd:")) {
|
} else if (bslc.startsWith("fwd:")) {
|
||||||
bs = bs.substring(4).trim();
|
bs = bs.substring(4).trim();
|
||||||
} else {
|
} else {
|
||||||
String xre = _t("Re:").toLowerCase();
|
if (bslc.startsWith(xre)) {
|
||||||
if (bs.toLowerCase().startsWith(xre)) {
|
|
||||||
bs = bs.substring(xre.length()).trim();
|
bs = bs.substring(xre.length()).trim();
|
||||||
} else {
|
} else {
|
||||||
String xfwd = _t("Fwd:").toLowerCase();
|
if (bslc.startsWith(xfwd))
|
||||||
if (bs.toLowerCase().startsWith(xfwd))
|
|
||||||
bs = bs.substring(xfwd.length()).trim();
|
bs = bs.substring(xfwd.length()).trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -618,7 +618,7 @@ public class WebMail extends HttpServlet
|
|||||||
|
|
||||||
if( html ) {
|
if( html ) {
|
||||||
out.println( "<!-- " );
|
out.println( "<!-- " );
|
||||||
out.println( "Debug: Showing Mail Part at level " + level + " with hash code " + mailPart.hashCode());
|
out.println( "Debug: Showing Mail Part at level " + level + " with ID " + mailPart.getID());
|
||||||
out.println( "Debug: Mail Part headers follow");
|
out.println( "Debug: Mail Part headers follow");
|
||||||
for( int i = 0; i < mailPart.headerLines.length; i++ ) {
|
for( int i = 0; i < mailPart.headerLines.length; i++ ) {
|
||||||
// fix Content-Type: multipart/alternative; boundary="----------8CDE39ECAF2633"
|
// fix Content-Type: multipart/alternative; boundary="----------8CDE39ECAF2633"
|
||||||
@@ -642,7 +642,7 @@ public class WebMail extends HttpServlet
|
|||||||
if (chosen.equals(subPart))
|
if (chosen.equals(subPart))
|
||||||
continue;
|
continue;
|
||||||
out.println( "<!-- " );
|
out.println( "<!-- " );
|
||||||
out.println( "Debug: Not showing alternative Mail Part at level " + (level + 1) + " with hash code " + subPart.hashCode());
|
out.println( "Debug: Not showing alternative Mail Part at level " + (level + 1) + " with ID " + subPart.getID());
|
||||||
out.println( "Debug: Mail Part headers follow");
|
out.println( "Debug: Mail Part headers follow");
|
||||||
for( int i = 0; i < subPart.headerLines.length; i++ ) {
|
for( int i = 0; i < subPart.headerLines.length; i++ ) {
|
||||||
out.println( subPart.headerLines[i].replace("--", "--") );
|
out.println( subPart.headerLines[i].replace("--", "--") );
|
||||||
@@ -751,7 +751,7 @@ public class WebMail extends HttpServlet
|
|||||||
}
|
}
|
||||||
name = quoteHTML(name);
|
name = quoteHTML(name);
|
||||||
out.println("<img src=\"" + myself + '?' + RAW_ATTACHMENT + '=' +
|
out.println("<img src=\"" + myself + '?' + RAW_ATTACHMENT + '=' +
|
||||||
mailPart.hashCode() +
|
mailPart.getID() +
|
||||||
"&" + B64UIDL + '=' + Base64.encode(mailPart.uidl) +
|
"&" + B64UIDL + '=' + Base64.encode(mailPart.uidl) +
|
||||||
"\" alt=\"" + name + "\">");
|
"\" alt=\"" + name + "\">");
|
||||||
} else if (type != null && (
|
} else if (type != null && (
|
||||||
@@ -765,14 +765,15 @@ public class WebMail extends HttpServlet
|
|||||||
type.equals("application/x-7z-compressed") || type.equals("application/x-rar-compressed") ||
|
type.equals("application/x-7z-compressed") || type.equals("application/x-rar-compressed") ||
|
||||||
type.equals("application/x-tar") || type.equals("application/x-bzip2") ||
|
type.equals("application/x-tar") || type.equals("application/x-bzip2") ||
|
||||||
type.equals("application/pdf") || type.equals("application/x-bittorrent") ||
|
type.equals("application/pdf") || type.equals("application/x-bittorrent") ||
|
||||||
|
type.equals("application/pgp-encrypted") ||
|
||||||
type.equals("application/pgp-signature"))) {
|
type.equals("application/pgp-signature"))) {
|
||||||
out.println( "<a href=\"" + myself + '?' + RAW_ATTACHMENT + '=' +
|
out.println( "<a href=\"" + myself + '?' + RAW_ATTACHMENT + '=' +
|
||||||
mailPart.hashCode() +
|
mailPart.getID() +
|
||||||
"&" + B64UIDL + '=' + Base64.encode(mailPart.uidl) + "\">" +
|
"&" + B64UIDL + '=' + Base64.encode(mailPart.uidl) + "\">" +
|
||||||
_t("Download attachment {0}", ident) + "</a>");
|
_t("Download attachment {0}", ident) + "</a>");
|
||||||
} else {
|
} else {
|
||||||
out.println( "<a target=\"_blank\" href=\"" + myself + '?' + DOWNLOAD + '=' +
|
out.println( "<a target=\"_blank\" href=\"" + myself + '?' + DOWNLOAD + '=' +
|
||||||
mailPart.hashCode() +
|
mailPart.getID() +
|
||||||
"&" + B64UIDL + '=' + Base64.encode(mailPart.uidl) + "\">" +
|
"&" + B64UIDL + '=' + Base64.encode(mailPart.uidl) + "\">" +
|
||||||
_t("Download attachment {0}", ident) + "</a>" +
|
_t("Download attachment {0}", ident) + "</a>" +
|
||||||
" (" + _t("File is packed into a zipfile for security reasons.") + ')');
|
" (" + _t("File is packed into a zipfile for security reasons.") + ')');
|
||||||
@@ -788,7 +789,7 @@ public class WebMail extends HttpServlet
|
|||||||
}
|
}
|
||||||
if( html ) {
|
if( html ) {
|
||||||
out.println( "<!-- " );
|
out.println( "<!-- " );
|
||||||
out.println( "Debug: End of Mail Part at level " + level + " with hash code " + mailPart.hashCode());
|
out.println( "Debug: End of Mail Part at level " + level + " with ID " + mailPart.getID());
|
||||||
out.println( "-->" );
|
out.println( "-->" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1167,6 +1168,9 @@ public class WebMail extends HttpServlet
|
|||||||
if (!(sessionObject.subject.startsWith("Fwd:") ||
|
if (!(sessionObject.subject.startsWith("Fwd:") ||
|
||||||
sessionObject.subject.startsWith("fwd:") ||
|
sessionObject.subject.startsWith("fwd:") ||
|
||||||
sessionObject.subject.startsWith("FWD:") ||
|
sessionObject.subject.startsWith("FWD:") ||
|
||||||
|
sessionObject.subject.startsWith("Fw:") ||
|
||||||
|
sessionObject.subject.startsWith("fw:") ||
|
||||||
|
sessionObject.subject.startsWith("FW:") ||
|
||||||
sessionObject.subject.startsWith(_t("Fwd:")))) {
|
sessionObject.subject.startsWith(_t("Fwd:")))) {
|
||||||
sessionObject.subject = _t("Fwd:") + ' ' + sessionObject.subject;
|
sessionObject.subject = _t("Fwd:") + ' ' + sessionObject.subject;
|
||||||
}
|
}
|
||||||
@@ -1437,9 +1441,9 @@ public class WebMail extends HttpServlet
|
|||||||
}
|
}
|
||||||
if( str != null ) {
|
if( str != null ) {
|
||||||
try {
|
try {
|
||||||
int hashCode = Integer.parseInt( str );
|
int id = Integer.parseInt( str );
|
||||||
Mail mail = sessionObject.mailCache.getMail(showUIDL, MailCache.FetchMode.ALL);
|
Mail mail = sessionObject.mailCache.getMail(showUIDL, MailCache.FetchMode.ALL);
|
||||||
MailPart part = mail != null ? getMailPartFromHashCode( mail.getPart(), hashCode ) : null;
|
MailPart part = mail != null ? getMailPartFromID(mail.getPart(), id) : null;
|
||||||
if( part != null ) {
|
if( part != null ) {
|
||||||
if (sendAttachment(sessionObject, part, response, isRaw))
|
if (sendAttachment(sessionObject, part, response, isRaw))
|
||||||
return true;
|
return true;
|
||||||
@@ -1484,21 +1488,20 @@ public class WebMail extends HttpServlet
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursive.
|
* Recursive.
|
||||||
* FIXME can't be bookmarked.
|
* @param id as retrieved from getID()
|
||||||
* @param hashCode
|
|
||||||
* @return the part or null
|
* @return the part or null
|
||||||
*/
|
*/
|
||||||
private static MailPart getMailPartFromHashCode( MailPart part, int hashCode )
|
private static MailPart getMailPartFromID(MailPart part, int id)
|
||||||
{
|
{
|
||||||
if( part == null )
|
if( part == null )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if( part.hashCode() == hashCode )
|
if (part.getID() == id)
|
||||||
return part;
|
return part;
|
||||||
|
|
||||||
if( part.multipart || part.message ) {
|
if( part.multipart || part.message ) {
|
||||||
for( MailPart p : part.parts ) {
|
for( MailPart p : part.parts ) {
|
||||||
MailPart subPart = getMailPartFromHashCode( p, hashCode );
|
MailPart subPart = getMailPartFromID(p, id);
|
||||||
if( subPart != null )
|
if( subPart != null )
|
||||||
return subPart;
|
return subPart;
|
||||||
}
|
}
|
||||||
@@ -2132,7 +2135,7 @@ public class WebMail extends HttpServlet
|
|||||||
if (name == null) {
|
if (name == null) {
|
||||||
name = part.description;
|
name = part.description;
|
||||||
if (name == null)
|
if (name == null)
|
||||||
name = "part" + part.hashCode();
|
name = "part" + part.getID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String name2 = FilenameUtil.sanitizeFilename(name);
|
String name2 = FilenameUtil.sanitizeFilename(name);
|
||||||
@@ -2679,7 +2682,7 @@ public class WebMail extends HttpServlet
|
|||||||
"</p>");
|
"</p>");
|
||||||
}
|
}
|
||||||
Mail mail = sessionObject.mailCache.getMail(showUIDL, MailCache.FetchMode.ALL);
|
Mail mail = sessionObject.mailCache.getMail(showUIDL, MailCache.FetchMode.ALL);
|
||||||
if(!RELEASE && mail != null && mail.hasBody() && mail.getBody().getLength() < 4096) {
|
if(!RELEASE && mail != null && mail.hasBody() && mail.getBody().getLength() < 16384) {
|
||||||
out.println( "<!--" );
|
out.println( "<!--" );
|
||||||
out.println( "Debug: Mail header and body follow");
|
out.println( "Debug: Mail header and body follow");
|
||||||
Buffer body = mail.getBody();
|
Buffer body = mail.getBody();
|
||||||
|
Reference in New Issue
Block a user