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.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
@@ -179,7 +180,7 @@ class Mail {
|
||||
// TODO just fail?
|
||||
if (headerLines == null)
|
||||
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);
|
||||
// may only be available after reading and calling readComplete()
|
||||
size = rb.getLength();
|
||||
|
@@ -44,6 +44,7 @@ import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import net.i2p.data.DataHelper;
|
||||
|
||||
@@ -79,6 +80,7 @@ class MailPart {
|
||||
* @since 0.9.33
|
||||
*/
|
||||
public final String uidl;
|
||||
private final int intID;
|
||||
|
||||
/**
|
||||
* @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
|
||||
* 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;
|
||||
intID = id.getAndIncrement();
|
||||
buffer = readBuffer;
|
||||
|
||||
parts = new ArrayList<MailPart>(4);
|
||||
@@ -219,7 +222,7 @@ class MailPart {
|
||||
match = DataHelper.getASCII("\r\n--" + boundary);
|
||||
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 );
|
||||
tmpEnd = (int) eofin.getRead();
|
||||
if (!eofin.wasFound()) {
|
||||
@@ -233,7 +236,7 @@ class MailPart {
|
||||
}
|
||||
}
|
||||
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,
|
||||
// like From, To, and Subject
|
||||
parts.add( newPart );
|
||||
@@ -251,6 +254,15 @@ class MailPart {
|
||||
// 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".
|
||||
* We don't have any pushback if this goes wrong.
|
||||
|
@@ -132,9 +132,9 @@ public class WebMail extends HttpServlet
|
||||
* hidden params
|
||||
*/
|
||||
private static final String SUSI_NONCE = "susiNonce";
|
||||
private static final String B64UIDL = "b64uidl";
|
||||
private static final String PREV_B64UIDL = "prevb64uidl";
|
||||
private static final String NEXT_B64UIDL = "nextb64uidl";
|
||||
private static final String B64UIDL = "msg";
|
||||
private static final String PREV_B64UIDL = "prevmsg";
|
||||
private static final String NEXT_B64UIDL = "nextmsg";
|
||||
private static final String PREV_PAGE_NUM = "prevpagenum";
|
||||
private static final String NEXT_PAGE_NUM = "nextpagenum";
|
||||
private static final String CURRENT_SORT = "currentsort";
|
||||
@@ -349,6 +349,8 @@ public class WebMail extends HttpServlet
|
||||
* @author susi
|
||||
*/
|
||||
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();
|
||||
|
||||
public SubjectSorter( MailCache mailCache )
|
||||
@@ -359,31 +361,29 @@ public class WebMail extends HttpServlet
|
||||
protected int compare(Mail a, Mail b) {
|
||||
String as = a.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();
|
||||
} else if (as.toLowerCase().startsWith("fwd:")) {
|
||||
} else if (aslc.startsWith("fwd:")) {
|
||||
as = as.substring(4).trim();
|
||||
} else {
|
||||
String xre = _t("Re:").toLowerCase();
|
||||
if (as.toLowerCase().startsWith(xre)) {
|
||||
if (aslc.startsWith(xre)) {
|
||||
as = as.substring(xre.length()).trim();
|
||||
} else {
|
||||
String xfwd = _t("Fwd:").toLowerCase();
|
||||
if (as.toLowerCase().startsWith(xfwd))
|
||||
if (aslc.startsWith(xfwd))
|
||||
as = as.substring(xfwd.length()).trim();
|
||||
}
|
||||
}
|
||||
if (bs.toLowerCase().startsWith("re:")) {
|
||||
if (bslc.startsWith("re:") || bslc.startsWith("fw:")) {
|
||||
bs = bs.substring(3).trim();
|
||||
} else if (bs.toLowerCase().startsWith("fwd:")) {
|
||||
} else if (bslc.startsWith("fwd:")) {
|
||||
bs = bs.substring(4).trim();
|
||||
} else {
|
||||
String xre = _t("Re:").toLowerCase();
|
||||
if (bs.toLowerCase().startsWith(xre)) {
|
||||
if (bslc.startsWith(xre)) {
|
||||
bs = bs.substring(xre.length()).trim();
|
||||
} else {
|
||||
String xfwd = _t("Fwd:").toLowerCase();
|
||||
if (bs.toLowerCase().startsWith(xfwd))
|
||||
if (bslc.startsWith(xfwd))
|
||||
bs = bs.substring(xfwd.length()).trim();
|
||||
}
|
||||
}
|
||||
@@ -618,7 +618,7 @@ public class WebMail extends HttpServlet
|
||||
|
||||
if( html ) {
|
||||
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");
|
||||
for( int i = 0; i < mailPart.headerLines.length; i++ ) {
|
||||
// fix Content-Type: multipart/alternative; boundary="----------8CDE39ECAF2633"
|
||||
@@ -642,7 +642,7 @@ public class WebMail extends HttpServlet
|
||||
if (chosen.equals(subPart))
|
||||
continue;
|
||||
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");
|
||||
for( int i = 0; i < subPart.headerLines.length; i++ ) {
|
||||
out.println( subPart.headerLines[i].replace("--", "--") );
|
||||
@@ -751,7 +751,7 @@ public class WebMail extends HttpServlet
|
||||
}
|
||||
name = quoteHTML(name);
|
||||
out.println("<img src=\"" + myself + '?' + RAW_ATTACHMENT + '=' +
|
||||
mailPart.hashCode() +
|
||||
mailPart.getID() +
|
||||
"&" + B64UIDL + '=' + Base64.encode(mailPart.uidl) +
|
||||
"\" alt=\"" + name + "\">");
|
||||
} 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-tar") || type.equals("application/x-bzip2") ||
|
||||
type.equals("application/pdf") || type.equals("application/x-bittorrent") ||
|
||||
type.equals("application/pgp-encrypted") ||
|
||||
type.equals("application/pgp-signature"))) {
|
||||
out.println( "<a href=\"" + myself + '?' + RAW_ATTACHMENT + '=' +
|
||||
mailPart.hashCode() +
|
||||
mailPart.getID() +
|
||||
"&" + B64UIDL + '=' + Base64.encode(mailPart.uidl) + "\">" +
|
||||
_t("Download attachment {0}", ident) + "</a>");
|
||||
} else {
|
||||
out.println( "<a target=\"_blank\" href=\"" + myself + '?' + DOWNLOAD + '=' +
|
||||
mailPart.hashCode() +
|
||||
mailPart.getID() +
|
||||
"&" + B64UIDL + '=' + Base64.encode(mailPart.uidl) + "\">" +
|
||||
_t("Download attachment {0}", ident) + "</a>" +
|
||||
" (" + _t("File is packed into a zipfile for security reasons.") + ')');
|
||||
@@ -788,7 +789,7 @@ public class WebMail extends HttpServlet
|
||||
}
|
||||
if( html ) {
|
||||
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( "-->" );
|
||||
}
|
||||
}
|
||||
@@ -1167,6 +1168,9 @@ public class WebMail extends HttpServlet
|
||||
if (!(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 = _t("Fwd:") + ' ' + sessionObject.subject;
|
||||
}
|
||||
@@ -1437,9 +1441,9 @@ public class WebMail extends HttpServlet
|
||||
}
|
||||
if( str != null ) {
|
||||
try {
|
||||
int hashCode = Integer.parseInt( str );
|
||||
int id = Integer.parseInt( str );
|
||||
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 (sendAttachment(sessionObject, part, response, isRaw))
|
||||
return true;
|
||||
@@ -1484,21 +1488,20 @@ public class WebMail extends HttpServlet
|
||||
|
||||
/**
|
||||
* Recursive.
|
||||
* FIXME can't be bookmarked.
|
||||
* @param hashCode
|
||||
* @param id as retrieved from getID()
|
||||
* @return the part or null
|
||||
*/
|
||||
private static MailPart getMailPartFromHashCode( MailPart part, int hashCode )
|
||||
private static MailPart getMailPartFromID(MailPart part, int id)
|
||||
{
|
||||
if( part == null )
|
||||
return null;
|
||||
|
||||
if( part.hashCode() == hashCode )
|
||||
if (part.getID() == id)
|
||||
return part;
|
||||
|
||||
if( part.multipart || part.message ) {
|
||||
for( MailPart p : part.parts ) {
|
||||
MailPart subPart = getMailPartFromHashCode( p, hashCode );
|
||||
MailPart subPart = getMailPartFromID(p, id);
|
||||
if( subPart != null )
|
||||
return subPart;
|
||||
}
|
||||
@@ -2132,7 +2135,7 @@ public class WebMail extends HttpServlet
|
||||
if (name == null) {
|
||||
name = part.description;
|
||||
if (name == null)
|
||||
name = "part" + part.hashCode();
|
||||
name = "part" + part.getID();
|
||||
}
|
||||
}
|
||||
String name2 = FilenameUtil.sanitizeFilename(name);
|
||||
@@ -2679,7 +2682,7 @@ public class WebMail extends HttpServlet
|
||||
"</p>");
|
||||
}
|
||||
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( "Debug: Mail header and body follow");
|
||||
Buffer body = mail.getBody();
|
||||
|
Reference in New Issue
Block a user