* SusiMail:

- Add icons for attachments and spam
     (from Silk icons, same license as others)
   - Add checks for POST for XSS prevention
This commit is contained in:
zzz
2014-04-25 03:42:18 +00:00
parent 945d455f33
commit c2dab16c8c
5 changed files with 52 additions and 18 deletions

View File

@@ -62,6 +62,10 @@
<!-- set if unset --> <!-- set if unset -->
<property name="workspace.changes.tr" value="" /> <property name="workspace.changes.tr" value="" />
<copy file="src/susimail.properties" todir="src/WEB-INF/classes" /> <copy file="src/susimail.properties" todir="src/WEB-INF/classes" />
<mkdir dir="src/WEB-INF/classes/icons" />
<copy todir="src/WEB-INF/classes/icons" >
<fileset dir="src/icons" />
</copy>
<war destfile="susimail.war" webxml="src/WEB-INF/web.xml" <war destfile="susimail.war" webxml="src/WEB-INF/web.xml"
basedir="src/" excludes="WEB-INF/web.xml LICENSE src/**/*"> basedir="src/" excludes="WEB-INF/web.xml LICENSE src/**/*">
<manifest> <manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

View File

@@ -70,6 +70,7 @@ class Mail {
private MailPart part; private MailPart part;
String[] to, cc; // addresses only, enclosed by <> String[] to, cc; // addresses only, enclosed by <>
private boolean isNew, isSpam; private boolean isNew, isSpam;
public String contentType;
public String error; public String error;
@@ -154,6 +155,14 @@ class Mail {
this.isNew = isNew; this.isNew = isNew;
} }
public boolean hasAttachment() {
// this isn't right but good enough to start
// if part != null query parts instead?
return contentType != null &&
!contentType.contains("text/plain") &&
!contentType.contains("multipart/alternative");
}
/** /**
* *
* @param address E-mail address to be validated * @param address E-mail address to be validated
@@ -348,6 +357,11 @@ class Mail {
} else if(line.equals( "X-Spam-Flag: YES" )) { } else if(line.equals( "X-Spam-Flag: YES" )) {
// TODO trust.spam.headers config // TODO trust.spam.headers config
isSpam = true; isSpam = true;
} else if(line.toLowerCase(Locale.US).startsWith("content-type:" )) {
// this is duplicated in MailPart but
// we want to know if we have attachments, even if
// we haven't fetched the body
contentType = line.substring(13).trim();
} }
} }
} }

View File

@@ -399,7 +399,7 @@ public class WebMail extends HttpServlet
MailCache mc = mailCache; MailCache mc = mailCache;
Folder<String> f = folder; Folder<String> f = folder;
if (mc != null && f != null) { if (mc != null && f != null) {
if (mc.getMail(true)) { if (MailCache.FETCH_HEADER) {
String[] uidls = mc.getUIDLs(); String[] uidls = mc.getUIDLs();
f.setElements(uidls); f.setElements(uidls);
} }
@@ -702,7 +702,7 @@ public class WebMail extends HttpServlet
if (!offline) { if (!offline) {
// prime the cache, request all headers at once // prime the cache, request all headers at once
// otherwise they are pulled one at a time by sortBy() below // otherwise they are pulled one at a time by sortBy() below
mc.getMail(true); mc.getMail(MailCache.FETCH_HEADER);
} }
// get through cache so we have the disk-only ones too // get through cache so we have the disk-only ones too
String[] uidls = mc.getUIDLs(); String[] uidls = mc.getUIDLs();
@@ -767,25 +767,27 @@ public class WebMail extends HttpServlet
} }
/** /**
* Process all buttons, which possibly change internal state. * Process all buttons, which possibly change internal state.
* Also processes ?show=x for a GET
* *
* @param sessionObject * @param sessionObject
* @param request * @param request
* @param isPOST disallow button pushes if false
*/ */
private static void processStateChangeButtons(SessionObject sessionObject, RequestWrapper request ) private static void processStateChangeButtons(SessionObject sessionObject, RequestWrapper request, boolean isPOST )
{ {
/* /*
* LOGIN/LOGOUT * LOGIN/LOGOUT
*/ */
if( sessionObject.state == STATE_AUTH ) if( sessionObject.state == STATE_AUTH && isPOST )
processLogin( sessionObject, request ); processLogin( sessionObject, request );
if( sessionObject.state != STATE_AUTH ) if( sessionObject.state != STATE_AUTH && isPOST )
processLogout( sessionObject, request ); processLogout( sessionObject, request );
/* /*
* compose dialog * compose dialog
*/ */
if( sessionObject.state == STATE_NEW ) { if( sessionObject.state == STATE_NEW && isPOST ) {
// We have to make sure to get the state right even if // We have to make sure to get the state right even if
// the user hit the back button previously // the user hit the back button previously
if( buttonPressed( request, SEND ) ) { if( buttonPressed( request, SEND ) ) {
@@ -824,7 +826,7 @@ public class WebMail extends HttpServlet
/* /*
* message dialog * message dialog
*/ */
if( sessionObject.state == STATE_SHOW ) { if( sessionObject.state == STATE_SHOW && isPOST ) {
if( buttonPressed( request, LIST ) ) { if( buttonPressed( request, LIST ) ) {
sessionObject.state = STATE_LIST; sessionObject.state = STATE_LIST;
} else if (buttonPressed( request, CANCEL ) || } else if (buttonPressed( request, CANCEL ) ||
@@ -849,7 +851,7 @@ public class WebMail extends HttpServlet
* buttons on both folder and message dialog * buttons on both folder and message dialog
*/ */
if( sessionObject.state == STATE_SHOW || sessionObject.state == STATE_LIST ) { if( sessionObject.state == STATE_SHOW || sessionObject.state == STATE_LIST ) {
if( buttonPressed( request, NEW ) ) { if( isPOST && buttonPressed( request, NEW ) ) {
sessionObject.state = STATE_NEW; sessionObject.state = STATE_NEW;
} }
@@ -979,8 +981,10 @@ public class WebMail extends HttpServlet
} }
} }
} }
/* /*
* folder view * folder view
* SHOW is the one parameter that's a link, not a button, so we allow it for GET
*/ */
if( sessionObject.state == STATE_LIST || sessionObject.state == STATE_SHOW) { if( sessionObject.state == STATE_LIST || sessionObject.state == STATE_SHOW) {
/* /*
@@ -1039,7 +1043,7 @@ public class WebMail extends HttpServlet
if( buttonPressed( request, REFRESH ) ) { if( buttonPressed( request, REFRESH ) ) {
sessionObject.mailbox.refresh(); sessionObject.mailbox.refresh();
sessionObject.error += sessionObject.mailbox.lastError(); sessionObject.error += sessionObject.mailbox.lastError();
sessionObject.mailCache.getMail(true); sessionObject.mailCache.getMail(MailCache.FETCH_HEADER);
// get through cache so we have the disk-only ones too // get through cache so we have the disk-only ones too
String[] uidls = sessionObject.mailCache.getUIDLs(); String[] uidls = sessionObject.mailCache.getUIDLs();
if (uidls != null) if (uidls != null)
@@ -1360,13 +1364,15 @@ public class WebMail extends HttpServlet
ua.startsWith("Vodafone")); ua.startsWith("Vodafone"));
} }
/** /**
* The entry point for all web page loads
* *
* @param httpRequest * @param httpRequest
* @param response * @param response
* @param isPOST disallow button pushes if false
* @throws IOException * @throws IOException
* @throws ServletException * @throws ServletException
*/ */
private void processRequest( HttpServletRequest httpRequest, HttpServletResponse response ) private void processRequest( HttpServletRequest httpRequest, HttpServletResponse response, boolean isPOST )
throws IOException, ServletException throws IOException, ServletException
{ {
String theme = Config.getProperty(CONFIG_THEME, DEFAULT_THEME); String theme = Config.getProperty(CONFIG_THEME, DEFAULT_THEME);
@@ -1418,7 +1424,7 @@ public class WebMail extends HttpServlet
processComposeButtons( sessionObject, request ); processComposeButtons( sessionObject, request );
int oldState = sessionObject.state; int oldState = sessionObject.state;
processStateChangeButtons( sessionObject, request ); processStateChangeButtons( sessionObject, request, isPOST );
int newState = sessionObject.state; int newState = sessionObject.state;
if (oldState != newState) if (oldState != newState)
Debug.debug(Debug.DEBUG, "STATE CHANGE from " + oldState + " to " + newState); Debug.debug(Debug.DEBUG, "STATE CHANGE from " + oldState + " to " + newState);
@@ -1430,11 +1436,14 @@ public class WebMail extends HttpServlet
// Debug.debug(Debug.DEBUG, "Changed idle from " + oldIdle + " to " + newIdle); // Debug.debug(Debug.DEBUG, "Changed idle from " + oldIdle + " to " + newIdle);
//} //}
if( sessionObject.state != STATE_AUTH ) if( sessionObject.state != STATE_AUTH ) {
processGenericButtons( sessionObject, request ); if (isPOST)
processGenericButtons( sessionObject, request );
}
if( sessionObject.state == STATE_LIST ) { if( sessionObject.state == STATE_LIST ) {
processFolderButtons( sessionObject, request ); if (isPOST)
processFolderButtons( sessionObject, request );
for( Iterator<String> it = sessionObject.folder.currentPageIterator(); it != null && it.hasNext(); ) { for( Iterator<String> it = sessionObject.folder.currentPageIterator(); it != null && it.hasNext(); ) {
String uidl = it.next(); String uidl = it.next();
Mail mail = sessionObject.mailCache.getMail( uidl, MailCache.FETCH_HEADER ); Mail mail = sessionObject.mailCache.getMail( uidl, MailCache.FETCH_HEADER );
@@ -1446,7 +1455,8 @@ public class WebMail extends HttpServlet
} }
if( sessionObject.state == STATE_SHOW ) { if( sessionObject.state == STATE_SHOW ) {
processMessageButtons( sessionObject, request ); if (isPOST)
processMessageButtons( sessionObject, request );
// If the last message has just been deleted then // If the last message has just been deleted then
// sessionObject.state = STATE_LIST and // sessionObject.state = STATE_LIST and
// sessionObject.showUIDL = null // sessionObject.showUIDL = null
@@ -1734,6 +1744,7 @@ public class WebMail extends HttpServlet
} }
return ok; return ok;
} }
/** /**
* *
*/ */
@@ -1741,8 +1752,9 @@ public class WebMail extends HttpServlet
public void doGet( HttpServletRequest request, HttpServletResponse response ) public void doGet( HttpServletRequest request, HttpServletResponse response )
throws IOException, ServletException throws IOException, ServletException
{ {
processRequest( request, response ); processRequest( request, response, false );
} }
/** /**
* *
*/ */
@@ -1750,8 +1762,9 @@ public class WebMail extends HttpServlet
public void doPost( HttpServletRequest request, HttpServletResponse response ) public void doPost( HttpServletRequest request, HttpServletResponse response )
throws IOException, ServletException throws IOException, ServletException
{ {
processRequest( request, response ); processRequest( request, response, true );
} }
/** /**
* *
* @param out * @param out
@@ -1948,7 +1961,10 @@ public class WebMail extends HttpServlet
// ", clear=" + sessionObject.clear ); // ", clear=" + sessionObject.clear );
out.println( "<tr class=\"list" + bg + "\"><td><input type=\"checkbox\" class=\"optbox\" name=\"check" + i + "\" value=\"1\"" + out.println( "<tr class=\"list" + bg + "\"><td><input type=\"checkbox\" class=\"optbox\" name=\"check" + i + "\" value=\"1\"" +
( idChecked ? "checked" : "" ) + ">" + "</td><td>" + ( idChecked ? "checked" : "" ) + ">" + "</td><td>" +
link + mail.shortSender + "</a></td><td>&nbsp;</td><td>" + link + mail.shortSubject + "</a></td><td>&nbsp;</td><td>" + link + mail.shortSender + "</a></td><td>" +
(mail.hasAttachment() ? "<img src=\"/susimail/icons/attach.png\" alt=\"\">" : "&nbsp;") + "</td><td>" +
link + mail.shortSubject + "</a></td><td>" +
(mail.isSpam() ? "<img src=\"/susimail/icons/flag_red.png\" alt=\"\">" : "&nbsp;") + "</td><td>" +
// don't let date get split across lines // don't let date get split across lines
mail.localFormattedDate.replace(" ", "&nbsp;") + "</td><td>&nbsp;</td><td align=\"right\">" + mail.localFormattedDate.replace(" ", "&nbsp;") + "</td><td>&nbsp;</td><td align=\"right\">" +
((mail.getSize() > 0) ? (DataHelper.formatSize2(mail.getSize()) + 'B') : "???") + "</td></tr>" ); ((mail.getSize() > 0) ? (DataHelper.formatSize2(mail.getSize()) + 'B') : "???") + "</td></tr>" );