forked from I2P_Developers/i2p.i2p
* SusiMail:
- Show sender name in folder view - Add support for configured sender name - Add HTML escaping of '&' - Fix Folder sorting so UP is up and DOWN is down - Use replace() instead of replaceAll() where appropriate - Fix capture by show page after back button
This commit is contained in:
@@ -51,13 +51,17 @@ public class Folder<O extends Object> {
|
||||
public static final String PAGESIZE = "pager.pagesize";
|
||||
public static final int DEFAULT_PAGESIZE = 10;
|
||||
|
||||
public static final boolean DOWN = false;
|
||||
public static final boolean UP = true;
|
||||
public enum SortOrder {
|
||||
/** lowest to highest */
|
||||
DOWN,
|
||||
/** reverse sort, highest to lowest */
|
||||
UP;
|
||||
}
|
||||
|
||||
private int pages, pageSize, currentPage;
|
||||
private O[] unsortedElements, elements;
|
||||
private final Hashtable<String, Comparator<O>> sorter;
|
||||
private boolean sortingDirection;
|
||||
private SortOrder sortingDirection;
|
||||
Comparator<O> currentSorter;
|
||||
|
||||
public Folder()
|
||||
@@ -65,7 +69,7 @@ public class Folder<O extends Object> {
|
||||
pages = 1;
|
||||
currentPage = 1;
|
||||
sorter = new Hashtable<String, Comparator<O>>();
|
||||
sortingDirection = UP;
|
||||
sortingDirection = SortOrder.DOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,14 +236,9 @@ public class Folder<O extends Object> {
|
||||
if( elements != null ) {
|
||||
int pageSize = getPageSize();
|
||||
int offset = ( currentPage - 1 ) * pageSize;
|
||||
int step = 1;
|
||||
if( sortingDirection == DOWN ) {
|
||||
offset = elements.length - offset - 1;
|
||||
step = -1;
|
||||
}
|
||||
for( int i = 0; i < pageSize && offset >= 0 && offset < elements.length; i++ ) {
|
||||
list.add( elements[offset] );
|
||||
offset += step;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
return list.iterator();
|
||||
@@ -303,6 +302,8 @@ public class Folder<O extends Object> {
|
||||
public void sortBy( String id )
|
||||
{
|
||||
currentSorter = sorter.get( id );
|
||||
if (sortingDirection == SortOrder.UP)
|
||||
currentSorter = Collections.reverseOrder(currentSorter);
|
||||
sort();
|
||||
}
|
||||
|
||||
@@ -318,12 +319,7 @@ public class Folder<O extends Object> {
|
||||
if( elements != null ) {
|
||||
int pageSize = getPageSize();
|
||||
int offset = ( currentPage - 1 ) * pageSize;
|
||||
int step = 1;
|
||||
if( sortingDirection == DOWN ) {
|
||||
offset = elements.length - offset - 1;
|
||||
step = -1;
|
||||
}
|
||||
offset += x * step;
|
||||
offset += x;
|
||||
if( offset >= 0 && offset < elements.length )
|
||||
result = elements[offset];
|
||||
}
|
||||
@@ -332,10 +328,11 @@ public class Folder<O extends Object> {
|
||||
|
||||
/**
|
||||
* Sets the sorting direction of the folder.
|
||||
* Does not re-sort. Caller must call sortBy()
|
||||
*
|
||||
* @param direction @link UP or @link DOWN
|
||||
*/
|
||||
public void setSortingDirection( boolean direction )
|
||||
public void setSortingDirection(SortOrder direction)
|
||||
{
|
||||
sortingDirection = direction;
|
||||
}
|
||||
@@ -347,9 +344,6 @@ public class Folder<O extends Object> {
|
||||
*/
|
||||
public O getFirstElement()
|
||||
{
|
||||
/*
|
||||
* sorting direction is taken into account from getElement
|
||||
*/
|
||||
return elements == null ? null : getElement( 0 );
|
||||
}
|
||||
|
||||
@@ -360,9 +354,6 @@ public class Folder<O extends Object> {
|
||||
*/
|
||||
public O getLastElement()
|
||||
{
|
||||
/*
|
||||
* sorting direction is taken into account from getElement
|
||||
*/
|
||||
return elements == null ? null : getElement( elements.length - 1 );
|
||||
}
|
||||
|
||||
@@ -384,7 +375,6 @@ public class Folder<O extends Object> {
|
||||
|
||||
/**
|
||||
* Retrieves the next element in the sorted array.
|
||||
* Sorting direction is taken into account.
|
||||
*
|
||||
* @param element
|
||||
* @return The next element
|
||||
@@ -396,7 +386,7 @@ public class Folder<O extends Object> {
|
||||
int i = getIndexOf( element );
|
||||
|
||||
if( i != -1 && elements != null ) {
|
||||
i += sortingDirection == UP ? 1 : -1;
|
||||
i++;
|
||||
if( i >= 0 && i < elements.length )
|
||||
result = elements[i];
|
||||
}
|
||||
@@ -405,7 +395,6 @@ public class Folder<O extends Object> {
|
||||
|
||||
/**
|
||||
* Retrieves the previous element in the sorted array.
|
||||
* Sorting direction is taken into account.
|
||||
*
|
||||
* @param element
|
||||
* @return The previous element
|
||||
@@ -417,14 +406,14 @@ public class Folder<O extends Object> {
|
||||
int i = getIndexOf( element );
|
||||
|
||||
if( i != -1 && elements != null ) {
|
||||
i += sortingDirection == DOWN ? 1 : -1;
|
||||
i--;
|
||||
if( i >= 0 && i < elements.length )
|
||||
result = elements[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Retrieves element at index i. Depends on sorting direction.
|
||||
* Retrieves element at index i.
|
||||
*
|
||||
* @param i
|
||||
* @return Element at index i
|
||||
@@ -434,8 +423,6 @@ public class Folder<O extends Object> {
|
||||
O result = null;
|
||||
|
||||
if( elements != null ) {
|
||||
if( sortingDirection == DOWN )
|
||||
i = elements.length - i - 1;
|
||||
result = elements[i];
|
||||
}
|
||||
return result;
|
||||
@@ -459,7 +446,6 @@ public class Folder<O extends Object> {
|
||||
|
||||
/**
|
||||
* Returns true, if elements.equals( lastElementOfTheSortedArray ).
|
||||
* The sorting direction influences which element is taken for comparison.
|
||||
*
|
||||
* @param element
|
||||
*/
|
||||
@@ -467,12 +453,11 @@ public class Folder<O extends Object> {
|
||||
{
|
||||
if( elements == null )
|
||||
return false;
|
||||
return elements[ sortingDirection == DOWN ? 0 : elements.length - 1 ].equals( element );
|
||||
return elements[elements.length - 1].equals( element );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if elements.equals( firstElementOfTheSortedArray ).
|
||||
* The sorting direction influences which element is taken for comparison.
|
||||
*
|
||||
* @param element
|
||||
*/
|
||||
@@ -480,6 +465,6 @@ public class Folder<O extends Object> {
|
||||
{
|
||||
if( elements == null )
|
||||
return false;
|
||||
return elements[ sortingDirection == UP ? 0 : elements.length - 1 ].equals( element );
|
||||
return elements[0].equals( element );
|
||||
}
|
||||
}
|
||||
|
@@ -55,17 +55,20 @@ class Mail {
|
||||
private static final String unknown = "unknown";
|
||||
|
||||
private int size;
|
||||
public String sender, reply, subject, dateString,
|
||||
formattedSender, formattedSubject,
|
||||
public String sender, // as received, trimmed only, not HTML escaped
|
||||
reply, subject, dateString,
|
||||
formattedSender, // address only, enclosed with <>, not HTML escaped
|
||||
formattedSubject,
|
||||
formattedDate, // US Locale, UTC
|
||||
localFormattedDate, // Current Locale, local time zone
|
||||
shortSender, shortSubject,
|
||||
shortSender, // Either name or address but not both, HTML escaped, double-quotes removed, truncated with with hellip
|
||||
shortSubject, // HTML escaped, truncated with hellip
|
||||
quotedDate; // Current Locale, local time zone, longer format
|
||||
public final String uidl;
|
||||
public Date date;
|
||||
private ReadBuffer header, body;
|
||||
private MailPart part;
|
||||
String[] to, cc;
|
||||
String[] to, cc; // addresses only, enclosed by <>
|
||||
|
||||
public String error;
|
||||
|
||||
@@ -165,7 +168,9 @@ class Mail {
|
||||
}
|
||||
return addresses == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first email address portion, enclosed by <>
|
||||
* @param address
|
||||
*/
|
||||
public static String getAddress(String address )
|
||||
@@ -181,6 +186,16 @@ class Mail {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A little misnamed. Adds all addresses from the comma-separated
|
||||
* line in text to the recipients list.
|
||||
*
|
||||
* @param text comma-separated
|
||||
* @param recipients out param
|
||||
* @param ok will be returned
|
||||
* @return true if ALL e-mail addresses are valid AND the in parameter was true
|
||||
*/
|
||||
public static boolean getRecipientsFromList( ArrayList<String> recipients, String text, boolean ok )
|
||||
{
|
||||
if( text != null && text.length() > 0 ) {
|
||||
@@ -203,6 +218,15 @@ class Mail {
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all items from the list
|
||||
* to the builder, separated by tabs.
|
||||
*
|
||||
* @param text comma-separated
|
||||
* @param buf out param
|
||||
* @param prefix prepended to the addresses
|
||||
*/
|
||||
public static void appendRecipients( StringBuilder buf, ArrayList<String> recipients, String prefix )
|
||||
{
|
||||
for( String recipient : recipients ) {
|
||||
@@ -212,6 +236,7 @@ class Mail {
|
||||
buf.append( "\r\n" );
|
||||
}
|
||||
}
|
||||
|
||||
public void parseHeaders()
|
||||
{
|
||||
DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||
@@ -258,11 +283,18 @@ class Mail {
|
||||
if( line.startsWith( "From:" ) ) {
|
||||
sender = line.substring( 5 ).trim();
|
||||
formattedSender = getAddress( sender );
|
||||
shortSender = formattedSender.trim();
|
||||
if( shortSender.length() > 40 ) {
|
||||
shortSender = shortSender.substring( 0, 37 ).trim() + "…";
|
||||
}
|
||||
shortSender = sender.replace("\"", "").trim();
|
||||
int lt = shortSender.indexOf('<');
|
||||
if (lt > 0)
|
||||
shortSender = shortSender.substring(0, lt).trim();
|
||||
else if (lt < 0 && shortSender.contains("@"))
|
||||
shortSender = '<' + shortSender + '>'; // add missing <> (but thunderbird doesn't...)
|
||||
boolean trim = shortSender.length() > 40;
|
||||
if (trim)
|
||||
shortSender = shortSender.substring( 0, 37 ).trim();
|
||||
shortSender = html.encode( shortSender );
|
||||
if (trim)
|
||||
shortSender += "…"; // must be after html encode
|
||||
}
|
||||
else if( line.startsWith( "Date:" ) ) {
|
||||
dateString = line.substring( 5 ).trim();
|
||||
@@ -282,9 +314,12 @@ class Mail {
|
||||
subject = line.substring( 8 ).trim();
|
||||
formattedSubject = subject;
|
||||
shortSubject = formattedSubject;
|
||||
if( formattedSubject.length() > 60 )
|
||||
shortSubject = formattedSubject.substring( 0, 57 ).trim() + "…";
|
||||
boolean trim = formattedSubject.length() > 60;
|
||||
if (trim)
|
||||
shortSubject = formattedSubject.substring( 0, 57 ).trim();
|
||||
shortSubject = html.encode( shortSubject );
|
||||
if (trim)
|
||||
shortSubject += "…"; // must be after html encode
|
||||
}
|
||||
else if( line.toLowerCase(Locale.US).startsWith( "reply-to:" ) ) {
|
||||
reply = getAddress( line.substring( 9 ).trim() );
|
||||
|
@@ -167,6 +167,7 @@ public class WebMail extends HttpServlet
|
||||
|
||||
private static final String CONFIG_SENDER_FIXED = "sender.fixed";
|
||||
private static final String CONFIG_SENDER_DOMAIN = "sender.domain";
|
||||
private static final String CONFIG_SENDER_NAME = "sender.name";
|
||||
|
||||
private static final String CONFIG_COMPOSER_COLS = "composer.cols";
|
||||
private static final String CONFIG_COMPOSER_ROWS = "composer.rows";
|
||||
@@ -244,7 +245,9 @@ public class WebMail extends HttpServlet
|
||||
return (b == null) ? 0 : 1;
|
||||
if (b == null)
|
||||
return -1;
|
||||
return collator.compare(a.formattedSender, b.formattedSender);
|
||||
String as = a.sender.replace("\"", "").replace("<", "").replace(">", "");
|
||||
String bs = b.sender.replace("\"", "").replace("<", "").replace(">", "");
|
||||
return collator.compare(as, bs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -578,7 +581,7 @@ public class WebMail extends HttpServlet
|
||||
static String quoteHTML( String line )
|
||||
{
|
||||
if( line != null )
|
||||
line = line.replaceAll( "<", "<" ).replaceAll( ">", ">" );
|
||||
line = line.replace("&", "&").replace( "<", "<" ).replace( ">", ">" );
|
||||
else
|
||||
line = "";
|
||||
return line;
|
||||
@@ -689,7 +692,8 @@ public class WebMail extends HttpServlet
|
||||
sessionObject.folder.addSorter( SORT_SUBJECT, new SubjectSorter( sessionObject.mailCache ) );
|
||||
sessionObject.folder.addSorter( SORT_DATE, new DateSorter( sessionObject.mailCache ) );
|
||||
sessionObject.folder.addSorter( SORT_SIZE, new SizeSorter( sessionObject.mailCache ) );
|
||||
sessionObject.folder.setSortingDirection( Folder.DOWN );
|
||||
// reverse sort, latest mail first
|
||||
sessionObject.folder.setSortingDirection(Folder.SortOrder.UP);
|
||||
sessionObject.folder.sortBy(SORT_DATE);
|
||||
sessionObject.reallyDelete = false;
|
||||
Debug.debug(Debug.DEBUG, "CONNECTED, YAY");
|
||||
@@ -816,6 +820,22 @@ public class WebMail extends HttpServlet
|
||||
if( sessionObject.state == STATE_SHOW ) {
|
||||
if( buttonPressed( request, LIST ) ) {
|
||||
sessionObject.state = STATE_LIST;
|
||||
} else if (buttonPressed( request, CANCEL ) ||
|
||||
buttonPressed( request, PREVPAGE ) || // All these buttons are not shown but we could be lost
|
||||
buttonPressed( request, NEXTPAGE ) ||
|
||||
buttonPressed( request, FIRSTPAGE ) ||
|
||||
buttonPressed( request, LASTPAGE ) ||
|
||||
buttonPressed( request, SETPAGESIZE ) ||
|
||||
buttonPressed( request, MARKALL ) ||
|
||||
buttonPressed( request, CLEAR ) ||
|
||||
buttonPressed( request, INVERT ) ||
|
||||
buttonPressed( request, SORT_ID ) ||
|
||||
buttonPressed( request, SORT_SENDER ) ||
|
||||
buttonPressed( request, SORT_SUBJECT ) ||
|
||||
buttonPressed( request, SORT_DATE ) ||
|
||||
buttonPressed( request, SORT_SIZE ) ||
|
||||
buttonPressed( request, REFRESH )) {
|
||||
sessionObject.state = STATE_LIST;
|
||||
}
|
||||
}
|
||||
/*
|
||||
@@ -865,9 +885,9 @@ public class WebMail extends HttpServlet
|
||||
if (part != null) {
|
||||
if( reply || replyAll ) {
|
||||
if( mail.reply != null && Mail.validateAddress( mail.reply ) )
|
||||
sessionObject.replyTo = Mail.getAddress( mail.reply );
|
||||
sessionObject.replyTo = mail.reply;
|
||||
else if( mail.sender != null && Mail.validateAddress( mail.sender ) )
|
||||
sessionObject.replyTo = Mail.getAddress( mail.sender );
|
||||
sessionObject.replyTo = mail.sender;
|
||||
sessionObject.subject = "Re: " + mail.formattedSubject;
|
||||
StringWriter text = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter( text );
|
||||
@@ -1274,11 +1294,10 @@ public class WebMail extends HttpServlet
|
||||
String str = request.getParameter( sort_id );
|
||||
if( str != null ) {
|
||||
if( str.equalsIgnoreCase("up")) {
|
||||
sessionObject.folder.setSortingDirection( Folder.UP );
|
||||
sessionObject.folder.setSortingDirection(Folder.SortOrder.UP);
|
||||
sessionObject.folder.sortBy( sort_id );
|
||||
}
|
||||
if( str.equalsIgnoreCase("down")) {
|
||||
sessionObject.folder.setSortingDirection( Folder.DOWN );
|
||||
} else if( str.equalsIgnoreCase("down")) {
|
||||
sessionObject.folder.setSortingDirection(Folder.SortOrder.DOWN);
|
||||
sessionObject.folder.sortBy( sort_id );
|
||||
}
|
||||
}
|
||||
@@ -1550,7 +1569,7 @@ public class WebMail extends HttpServlet
|
||||
name = part.name;
|
||||
else
|
||||
name = "part" + part.hashCode();
|
||||
String name2 = name.replaceAll( "\\.", "_" );
|
||||
String name2 = name.replace( "\\.", "_" );
|
||||
response.setContentType( "application/zip; name=\"" + name2 + ".zip\"" );
|
||||
response.addHeader( "Content-Disposition:", "attachment; filename=\"" + name2 + ".zip\"" );
|
||||
ZipEntry entry = new ZipEntry( name );
|
||||
@@ -1740,8 +1759,23 @@ public class WebMail extends HttpServlet
|
||||
String fixed = Config.getProperty( CONFIG_SENDER_FIXED, "true" );
|
||||
|
||||
if( from == null || !fixed.equalsIgnoreCase("false")) {
|
||||
String user = sessionObject.user;
|
||||
String name = Config.getProperty(CONFIG_SENDER_NAME);
|
||||
if (name != null) {
|
||||
name = name.trim();
|
||||
if (name.contains(" "))
|
||||
from = '"' + name + "\" ";
|
||||
else
|
||||
from = name + ' ';
|
||||
} else {
|
||||
from = "";
|
||||
}
|
||||
if (user.contains("@")) {
|
||||
String domain = Config.getProperty( CONFIG_SENDER_DOMAIN, "mail.i2p" );
|
||||
from = "<" + sessionObject.user + "@" + domain + ">";
|
||||
from += '<' + user + '@' + domain + '>';
|
||||
} else {
|
||||
from += '<' + user + '>';
|
||||
}
|
||||
}
|
||||
|
||||
String to = request.getParameter( NEW_TO, sessionObject.replyTo != null ? sessionObject.replyTo : "" );
|
||||
|
@@ -50,7 +50,10 @@ public class HTML implements Encoding {
|
||||
*/
|
||||
public String encode(String str) throws EncodingException
|
||||
{
|
||||
return str.replaceAll( "<", "<" ).replaceAll( ">", ">" ).replaceAll( "\r{0,1}\n", "<br>\r\n" );
|
||||
return str.replace("&", "&") // must be first
|
||||
.replace( "<", "<" )
|
||||
.replace( ">", ">" )
|
||||
.replaceAll( "\r{0,1}\n", "<br>\r\n" );
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@@ -263,7 +263,7 @@ public class SMTPClient {
|
||||
}
|
||||
if (ok) {
|
||||
if( body.indexOf( "\r\n.\r\n" ) != -1 )
|
||||
body = body.replaceAll( "\r\n.\r\n", "\r\n..\r\n" );
|
||||
body = body.replace( "\r\n.\r\n", "\r\n..\r\n" );
|
||||
socket.getOutputStream().write(DataHelper.getUTF8(body));
|
||||
socket.getOutputStream().write(DataHelper.getASCII("\r\n.\r\n"));
|
||||
int result = sendCmd(null);
|
||||
|
@@ -2,6 +2,11 @@
|
||||
* SusiMail:
|
||||
- Add persistent cache
|
||||
- Fix encoding in sent mails on non-UTF8 platforms
|
||||
- Show sender name in folder view
|
||||
- Add support for configured sender name
|
||||
- Add HTML escaping of '&'
|
||||
- Fix Folder sorting so UP is up and DOWN is down
|
||||
- Fix capture by show page after back button
|
||||
|
||||
2014-04-21 zzz
|
||||
* SusiMail:
|
||||
|
Reference in New Issue
Block a user