From a16d17c422f5c3fe4e33a1ac545487c8468dc800 Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Mon, 24 Nov 2014 18:36:16 +0000
Subject: [PATCH] SusiMail: Add save-as button Fix encoding for filename in
 Content-Disposition header New icon from Silk, same license as the others

---
 apps/susimail/src/icons/drive_edit.png        | Bin 0 -> 714 bytes
 .../src/src/i2p/susi/webmail/Mail.java        |   8 ++
 .../src/src/i2p/susi/webmail/WebMail.java     |  85 +++++++++++++++++-
 .../themes/susimail/dark/susimail.css         |   5 ++
 .../themes/susimail/light/susimail.css        |   6 ++
 5 files changed, 102 insertions(+), 2 deletions(-)
 create mode 100644 apps/susimail/src/icons/drive_edit.png

diff --git a/apps/susimail/src/icons/drive_edit.png b/apps/susimail/src/icons/drive_edit.png
new file mode 100644
index 0000000000000000000000000000000000000000..7923fada4bed2af85dfce000bcc9b9ef6793897d
GIT binary patch
literal 714
zcmV;*0yX`KP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!TuDShR5;6}
zQ_pJ?Q4s##Zg#hAezs|oCSr9<#gtNtiuE8>NDEf2-s&}Y^ic31co00R|9}S-FA@q~
z1q;#;e^rr&XrtIjwGF1}(zLNg!zP<;)}57vSQHN(80NjleBU?o-Wz5Z26kf{c4@Zy
zBArgpZf|dgO^2@Qs8*{D*EFr+l}d$TEE0)~5{^*|CitW%it(<lE-PuLHMc1U0^;#F
zGMUWi)YMeWs=!pd?(uk_C<-J=YJi%7w9aO;aJgKNWtl{;na44fN~J7yuh)xWvG_;1
z)CvI^W8irnZPf+v%TK^N22t90inXoUO_oe1X9Iyim=Xz8S8a~u+>aPq3QK719D!Rt
zgstUQNX^{WYy>KmO33H))&)^=tyTkFCPmsiYYBvUG&l|%N8$5Fh)jdi)eU#&9vcya
zNr{LEWVU3L%yGY8*w?y(qr)xm^p2ylHVv_jA@g<-Rh>ihotZ|e)GIj=)SdPn!V<=Y
z1$g?-qMW+}CVYe7aDrEJsO+D>X32n!2<jjzITQ+65rsE6(l5c?cOK={+u#HpT2Y4b
zY#xjD)9|<Ytv_NB&<hYj{le7TbGZB}d;{m8DR;q(2Fl;}Vf{q{#evK4OYH~-gI1L+
z8jU_S`ya3WGHfIfKGqGL`QYt%iFTi8g7@NUJb?$Fg4k5KM#ZMs4BI(O4{wbblb7xx
zJ$(hal{rW~L(tdrxpt91HF)*)`~MD8dP&i>504-Zjlga{h}HSj&$6nW`5U+~3(a=n
wM2C8~*KZr{mthE%IdwgMapK0pmw!#;FKVxMw^?5FRsaA107*qoM6N<$f)5QvuK)l5

literal 0
HcmV?d00001

diff --git a/apps/susimail/src/src/i2p/susi/webmail/Mail.java b/apps/susimail/src/src/i2p/susi/webmail/Mail.java
index 95e0829bfe..8632ac9c41 100644
--- a/apps/susimail/src/src/i2p/susi/webmail/Mail.java
+++ b/apps/susimail/src/src/i2p/susi/webmail/Mail.java
@@ -88,6 +88,10 @@ class Mail {
 		error = "";
 	}
 
+	/**
+         *  This may or may not contain the body also.
+         *  @return may be null
+         */
 	public synchronized ReadBuffer getHeader() {
 		return header;
 	}
@@ -103,6 +107,10 @@ class Mail {
 		return header != null;
 	}
 
+	/**
+         *  This contains the header also.
+         *  @return may be null
+         */
 	public synchronized ReadBuffer getBody() {
 		return body;
 	}
diff --git a/apps/susimail/src/src/i2p/susi/webmail/WebMail.java b/apps/susimail/src/src/i2p/susi/webmail/WebMail.java
index c3dbd78c3a..ad665e0b6e 100644
--- a/apps/susimail/src/src/i2p/susi/webmail/WebMail.java
+++ b/apps/susimail/src/src/i2p/susi/webmail/WebMail.java
@@ -116,6 +116,7 @@ public class WebMail extends HttpServlet
 	private static final String LOGOUT = "logout";
 	private static final String RELOAD = "reload";
 	private static final String SAVE = "save";
+	private static final String SAVE_AS = "saveas";
 	private static final String REFRESH = "refresh";
 	private static final String CONFIGURE = "configure";
 	private static final String NEW = "new";
@@ -1298,6 +1299,33 @@ public class WebMail extends HttpServlet
 		return isRaw;
 	}
 
+
+	/**
+	 * Process save-as link in message view
+	 *
+	 * @param sessionObject
+	 * @param request
+	 * @return If true, we sent the file or 404, do not send any other response
+	 * @since 0.9.18
+	 */
+	private static boolean processSaveAsLink(SessionObject sessionObject, RequestWrapper request, HttpServletResponse response)
+	{
+		String str = request.getParameter(SAVE_AS);
+		if( str == null )
+			return false;
+		Mail mail = sessionObject.mailCache.getMail( sessionObject.showUIDL, MailCache.FetchMode.ALL );
+		if( mail != null ) {
+			if (sendMailSaveAs(sessionObject, mail, response))
+				return true;
+		}
+		// error if we get here
+		sessionObject.error += _("Message not found.");
+		try {
+			response.sendError(404, _("Message not found."));
+		} catch (IOException ioe) {}
+		return true;
+	}
+
 	/**
 	 * @param hashCode
 	 * @return the part or null
@@ -1631,6 +1659,10 @@ public class WebMail extends HttpServlet
 					// download or raw view sent, or 404
 					return;
 				}
+				if (processSaveAsLink(sessionObject, request, response)) {
+					// download or sent, or 404
+					return;
+				}
 				// If the last message has just been deleted then
 				// sessionObject.state = STATE_LIST and
 				// sessionObject.showUIDL = null
@@ -1790,7 +1822,7 @@ public class WebMail extends HttpServlet
 						name = part.name;
 					else
 						name = "part" + part.hashCode();
-					String name2 = name.replace( "\\.", "_" );
+					String name2 = sanitizeFilename(name);
 					response.setContentType( "application/zip; name=\"" + name2 + ".zip\"" );
 					response.addHeader( "Content-Disposition:", "attachment; filename=\"" + name2 + ".zip\"" );
 					ZipEntry entry = new ZipEntry( name );
@@ -1809,6 +1841,54 @@ public class WebMail extends HttpServlet
 		}
 		return shown;
 	}
+
+	/**
+	 * Send the mail to be saved by the browser
+	 *
+	 * @param sessionObject
+	 * @param response
+	 * @return success
+	 * @since 0.9.18
+	 */
+	private static boolean sendMailSaveAs(SessionObject sessionObject, Mail mail,
+						 HttpServletResponse response)
+	{
+		ReadBuffer content = mail.getBody();
+
+		if(content == null)
+			return false;
+		String name = mail.subject != null ? sanitizeFilename(mail.subject) : "message";
+		try {
+			response.setContentType("message/rfc822");
+			response.setContentLength(content.length);
+			// cache-control?
+			response.addHeader( "Content-Disposition:", "attachment; filename=\"" + name + ".eml\"" );
+			response.getOutputStream().write(content.content, content.offset, content.length);
+			return true;
+		} catch (IOException e) {
+			e.printStackTrace();
+			return false;
+		}
+	}
+
+	/**
+	 * Convert the UTF-8 to ISO-8859-1 suitable for inclusion in a header.
+	 * This will result in a bunch of ??? for non-Western languages.
+	 *
+	 * @param sessionObject
+	 * @param response
+	 * @return success
+	 * @since 0.9.18
+	 */
+	private static String sanitizeFilename(String name) {
+		try {
+			name = new String(name.getBytes("ISO-8859-1"), "ISO-8859-1");
+		} catch( UnsupportedEncodingException uee ) {}
+		// strip control chars?
+		name = name.replace('"', '_');
+		return name;
+	}
+
 	/**
 	 * @param sessionObject
 	 * @param request
@@ -2255,7 +2335,8 @@ public class WebMail extends HttpServlet
 		out.println( button( NEW, _("New") ) + spacer +
 			button( REPLY, _("Reply") ) +
 			button( REPLYALL, _("Reply All") ) +
-			button( FORWARD, _("Forward") ) + spacer);
+			button( FORWARD, _("Forward") ) + spacer +
+			button( SAVE_AS, _("Save As") ) + spacer);
 		if (sessionObject.reallyDelete)
 			out.println(button2(DELETE, _("Delete")));
 		else
diff --git a/installer/resources/themes/susimail/dark/susimail.css b/installer/resources/themes/susimail/dark/susimail.css
index a46a0e586f..0d49e6540c 100644
--- a/installer/resources/themes/susimail/dark/susimail.css
+++ b/installer/resources/themes/susimail/dark/susimail.css
@@ -252,6 +252,11 @@ input.configure {
      min-height: 22px;
 }
 
+input.saveas {
+     background: #000 url('/susimail/icons/drive_edit.png') no-repeat 2px center;
+     min-height: 22px;
+}
+
 input[type=file], input.new_upload {
      background: #000 url('/themes/console/images/add.png') no-repeat 2px center;
      min-height: 22px;
diff --git a/installer/resources/themes/susimail/light/susimail.css b/installer/resources/themes/susimail/light/susimail.css
index afb2d082ad..df3d749fa2 100644
--- a/installer/resources/themes/susimail/light/susimail.css
+++ b/installer/resources/themes/susimail/light/susimail.css
@@ -274,6 +274,12 @@ input.configure {
      min-height: 22px;
 }
 
+input.saveas {
+     background: #ddf url('/susimail/icons/drive_edit.png') no-repeat 4px center;
+     padding: 2px 3px 2px 24px;
+     min-height: 22px;
+}
+
 input[type=file], input.new_upload {
      background: #ddf url('/themes/console/images/add.png') no-repeat 4px center;
      padding: 2px 3px 2px 24px;
-- 
GitLab