Changeset 003d865c


Ignore:
Timestamp:
Dec 23, 2017 1:16:48 PM (2 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
bf193b3
Parents:
4b95824
Message:

SusiMail?: Fix filenames for inline attachments
Support RFC 5987/6266 for attachment and save-as filenames
Add alt tags for images

File:
1 edited

Legend:

Unmodified
Added
Removed
  • apps/susimail/src/src/i2p/susi/webmail/WebMail.java

    r4b95824 r003d865c  
    715715                                        if (type != null && type.startsWith("image/")) {
    716716                                                // we at least show images safely...
     717                                                String name = mailPart.filename;
     718                                                if (name == null) {
     719                                                        name = mailPart.name;
     720                                                        if (name == null)
     721                                                                name = mailPart.description;
     722                                                }
     723                                                name = quoteHTML(name);
    717724                                                out.println("<img src=\"" + myself + '?' + RAW_ATTACHMENT + '=' +
    718725                                                         mailPart.hashCode() +
    719                                                          "&amp;" + B64UIDL + '=' + Base64.encode(mailPart.uidl) + "\">");
     726                                                         "&amp;" + B64UIDL + '=' + Base64.encode(mailPart.uidl) +
     727                                                         "\" alt=\"" + name + "\">");
    720728                                        } else if (type != null && (
    721729                                                // type list from snark
     
    20782086                        if(content == null)
    20792087                                return false;
     2088                        String name = part.filename;
     2089                        if (name == null) {
     2090                                name = part.name;
     2091                                if (name == null) {
     2092                                        name = part.description;
     2093                                        if (name == null)
     2094                                                name = "part" + part.hashCode();
     2095                                }
     2096                        }
     2097                        String name2 = sanitizeFilename(name);
     2098                        String name3 = encodeFilenameRFC5987(name);
    20802099                        if (isRaw) {
    20812100                                try {
     2101                                        response.addHeader("Content-Disposition", "inline; filename=\"" + name2 + "\"; " +
     2102                                                           "filename*=" + name3);
    20822103                                        if (part.type != null)
    20832104                                                response.setContentType(part.type);
     
    20932114                                try {
    20942115                                        zip = new ZipOutputStream( response.getOutputStream() );
    2095                                         String name;
    2096                                         if( part.filename != null )
    2097                                                 name = part.filename;
    2098                                         else if( part.name != null )
    2099                                                 name = part.name;
    2100                                         else
    2101                                                 name = "part" + part.hashCode();
    2102                                         String name2 = sanitizeFilename(name);
    21032116                                        response.setContentType( "application/zip; name=\"" + name2 + ".zip\"" );
    2104                                         response.addHeader( "Content-Disposition", "attachment; filename=\"" + name2 + ".zip\"" );
     2117                                        response.addHeader("Content-Disposition", "attachment; filename=\"" + name2 + ".zip\"; " +
     2118                                                           "filename*=" + name3 + ".zip");
    21052119                                        ZipEntry entry = new ZipEntry( name );
    21062120                                        zip.putNextEntry( entry );
     
    21362150                if(content == null)
    21372151                        return false;
    2138                 String name = mail.subject != null ? sanitizeFilename(mail.subject) : "message";
     2152                String name;
     2153                if (mail.subject != null)
     2154                        name = mail.subject.trim() + ".eml";
     2155                else
     2156                        name = "message.eml";
     2157                String name2 = sanitizeFilename(name);
     2158                String name3 = encodeFilenameRFC5987(name);
    21392159                try {
    21402160                        response.setContentType("message/rfc822");
    21412161                        response.setContentLength(content.length);
    21422162                        // cache-control?
    2143                         response.addHeader( "Content-Disposition", "attachment; filename=\"" + name + ".eml\"" );
     2163                        response.addHeader("Content-Disposition", "attachment; filename=\"" + name2 + "\"; " +
     2164                                           "filename*=" + name3);
    21442165                        response.getOutputStream().write(content.content, content.offset, content.length);
    21452166                        return true;
     
    21512172
    21522173        /**
    2153          * Convert the UTF-8 to ISO-8859-1 suitable for inclusion in a header.
    2154          * This will result in a bunch of ??? for non-Western languages.
     2174         * Convert the UTF-8 to ASCII suitable for inclusion in a header
     2175         * and for use as a cross-platform filename.
     2176         * Replace chars likely to be illegal in filenames,
     2177         * and non-ASCII chars, with _
    21552178         *
    2156          * @param sessionObject
    2157          * @param response
    2158          * @return success
     2179         * Ref: RFC 6266, RFC 5987, i2psnark Storage.ILLEGAL
     2180         *
    21592181         * @since 0.9.18
    21602182         */
    21612183        private static String sanitizeFilename(String name) {
    2162                 try {
    2163                         name = new String(name.getBytes("ISO-8859-1"), "ISO-8859-1");
    2164                 } catch( UnsupportedEncodingException uee ) {}
    2165                 // strip control chars?
    2166                 name = name.replace('"', '_');
    2167                 return name;
     2184                name = name.trim();
     2185                StringBuilder buf = new StringBuilder(name.length());
     2186                for (int i = 0; i < name.length(); i++) {
     2187                        char c = name.charAt(i);
     2188                        // illegal filename chars
     2189                        if (c <= 32 || c >= 0x7f ||
     2190                            c == '<' || c == '>' || c == ':' || c == '"' ||
     2191                            c == '/' || c == '\\' || c == '|' || c == '?' ||
     2192                            c == '*')
     2193                                buf.append('_');
     2194                        else
     2195                                buf.append(c);
     2196                }
     2197                return buf.toString();
     2198        }
     2199
     2200        /**
     2201         * Encode the UTF-8 suitable for inclusion in a header
     2202         * as a RFC 5987/6266 filename* value, and for use as a cross-platform filename.
     2203         * Replace chars likely to be illegal in filenames with _
     2204         *
     2205         * Ref: RFC 6266, RFC 5987, i2psnark Storage.ILLEGAL
     2206         *
     2207         * @since 0.9.33
     2208         */
     2209        private static String encodeFilenameRFC5987(String name) {
     2210                name = name.trim();
     2211                StringBuilder buf = new StringBuilder(name.length());
     2212                buf.append("utf-8''");
     2213                for (int i = 0; i < name.length(); i++) {
     2214                        char c = name.charAt(i);
     2215                        // illegal filename chars
     2216                        if (c < 32 || (c >= 0x7f && c <= 0x9f) ||
     2217                            c == '<' || c == '>' || c == ':' || c == '"' ||
     2218                            c == '/' || c == '\\' || c == '|' || c == '?' ||
     2219                            c == '*' ||
     2220                            // unicode newlines
     2221                            c == 0x2028 || c == 0x2029) {
     2222                                buf.append('_');
     2223                        } else if (c == ' ' || c == '\'' || c == '%' ||          // not in 5987 attr-char
     2224                                   c == '(' || c == ')' || c == '@' ||           // 2616 separators
     2225                                   c == ',' || c == ';' || c == '[' || c == ']' ||
     2226                                   c == '=' || c == '{' || c == '}') {
     2227                                // single byte encoding
     2228                                buf.append('%');
     2229                                buf.append(Integer.toHexString(c));
     2230                        } else if (c < 0x7f) {
     2231                                // single byte char, as-is
     2232                                buf.append(c);
     2233                        } else {
     2234                                // multi-byte encoding
     2235                                byte[] utf = DataHelper.getUTF8(String.valueOf(c));
     2236                                for (int j = 0; j < utf.length; j++) {
     2237                                        int b = utf[j] & 0xff;
     2238                                        buf.append('%');
     2239                                        if (b < 16)
     2240                                                buf.append(0);
     2241                                        buf.append(Integer.toHexString(b));
     2242                                }
     2243                        }
     2244                }
     2245                return buf.toString();
    21682246        }
    21692247
Note: See TracChangeset for help on using the changeset viewer.