Changeset ddf7fba0


Ignore:
Timestamp:
Feb 9, 2018 3:17:04 PM (4 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
768921b
Parents:
3d25a9f
Message:

SusiMail?:

  • Don't show the 'no charset' warning

Filename encoding fixes:

  • Fix encoding to be hex upper case
  • Move encoding to new util class
  • Encode in sent mail
  • Implement decoding in received mail

Error message and debug tweaks
Output remainder of header line after decode fail

Location:
apps/susimail/src/src/i2p/susi
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • apps/susimail/src/src/i2p/susi/util/HexTable.java

    r3d25a9f rddf7fba0  
    2929public class HexTable {
    3030       
     31        /**
     32         *  Three character strings, upper case, e.g. "=0A"
     33         */
    3134        public static final String[] table = new String[256];
    3235       
     
    5861                }
    5962        }
     63
     64/****
     65        public static void main(String[] args) {
     66                for( int i = 0; i < 256; i++ ) {
     67                        System.out.println(i + ": " + table[i]);
     68                }
     69        }
     70****/
    6071}
  • apps/susimail/src/src/i2p/susi/webmail/MailPart.java

    r3d25a9f rddf7fba0  
    2929import i2p.susi.util.DummyOutputStream;
    3030import i2p.susi.util.EOFOnMatchInputStream;
     31import i2p.susi.util.FilenameUtil;
    3132import i2p.susi.util.LimitInputStream;
    3233import i2p.susi.util.ReadBuffer;
     
    9394                buffer = readBuffer;
    9495               
    95                 parts = new ArrayList<MailPart>();
     96                parts = new ArrayList<MailPart>(4);
    9697
    9798                if (hdrlines != null) {
     
    135136                                x_disposition = getFirstAttribute( headerLines[i] ).toLowerCase(Locale.US);
    136137                                String str;
    137                                 str = getHeaderLineAttribute( headerLines[i], "filename" );
    138                                 if( str != null )
    139                                         x_name = str;
     138                                str = getHeaderLineAttribute(headerLines[i], "filename*");
     139                                if (str != null) {
     140                                        x_name = FilenameUtil.decodeFilenameRFC5987(str);
     141                                } else {
     142                                        str = getHeaderLineAttribute(headerLines[i], "filename");
     143                                        if (str != null)
     144                                                x_name = str;
     145                                }
    140146                        }
    141147                        else if( hlc.startsWith( "content-type: " ) ) {
  • apps/susimail/src/src/i2p/susi/webmail/WebMail.java

    r3d25a9f rddf7fba0  
    3030import i2p.susi.util.EscapeHTMLOutputStream;
    3131import i2p.susi.util.EscapeHTMLWriter;
     32import i2p.susi.util.FilenameUtil;
    3233import i2p.susi.util.Folder;
    3334import i2p.susi.util.Folder.SortOrder;
     
    703704                                        charset = "ISO-8859-1";
    704705                                        // don't show this in text mode which is used to include the mail in the reply or forward
    705                                         if (html)
    706                                                 reason = _t("Warning: no charset found, fallback to US-ASCII.") + br;
     706                                        // Too common, don't show this at all.
     707                                        //if (html)
     708                                        //      reason = _t("Warning: no charset found, fallback to US-ASCII.") + br;
    707709                                }
    708710                                try {
     
    928930                                                mailbox.setNewMailListener(sessionObject);
    929931                                        } else {
    930                                                 sessionObject.error += mailbox.lastError();
     932                                                sessionObject.error += mailbox.lastError() + '\n';
    931933                                                Debug.debug(Debug.DEBUG, "LOGIN FAIL, REMOVING SESSION");
    932934                                                HttpSession session = request.getSession();
     
    12841286                        mailbox.refresh();
    12851287                        String error = mailbox.lastError();
    1286                         sessionObject.error += error;
     1288                        sessionObject.error += error + '\n';
    12871289                        sessionObject.mailCache.getMail(MailCache.FetchMode.HEADER);
    12881290                        // get through cache so we have the disk-only ones too
     
    14881490               
    14891491                if( part.hashCode() == hashCode )
    1490 {
    14911492                        return part;
    1492 }
    14931493               
    14941494                if( part.multipart || part.message ) {
     
    21312131                                }
    21322132                        }
    2133                         String name2 = sanitizeFilename(name);
    2134                         String name3 = encodeFilenameRFC5987(name);
     2133                        String name2 = FilenameUtil.sanitizeFilename(name);
     2134                        String name3 = FilenameUtil.encodeFilenameRFC5987(name);
    21352135                        if (isRaw) {
    21362136                                try {
     
    21942194                else
    21952195                        name = "message.eml";
    2196                 String name2 = sanitizeFilename(name);
    2197                 String name3 = encodeFilenameRFC5987(name);
     2196                String name2 = FilenameUtil.sanitizeFilename(name);
     2197                String name3 = FilenameUtil.encodeFilenameRFC5987(name);
    21982198                InputStream in = null;
    21992199                try {
     
    22122212                        if (in != null) try { in.close(); } catch (IOException ioe) {}
    22132213                }
    2214         }
    2215 
    2216         /**
    2217          * Convert the UTF-8 to ASCII suitable for inclusion in a header
    2218          * and for use as a cross-platform filename.
    2219          * Replace chars likely to be illegal in filenames,
    2220          * and non-ASCII chars, with _
    2221          *
    2222          * Ref: RFC 6266, RFC 5987, i2psnark Storage.ILLEGAL
    2223          *
    2224          * @since 0.9.18
    2225          */
    2226         private static String sanitizeFilename(String name) {
    2227                 name = name.trim();
    2228                 StringBuilder buf = new StringBuilder(name.length());
    2229                 for (int i = 0; i < name.length(); i++) {
    2230                         char c = name.charAt(i);
    2231                         // illegal filename chars
    2232                         if (c <= 32 || c >= 0x7f ||
    2233                             c == '<' || c == '>' || c == ':' || c == '"' ||
    2234                             c == '/' || c == '\\' || c == '|' || c == '?' ||
    2235                             c == '*')
    2236                                 buf.append('_');
    2237                         else
    2238                                 buf.append(c);
    2239                 }
    2240                 return buf.toString();
    2241         }
    2242 
    2243         /**
    2244          * Encode the UTF-8 suitable for inclusion in a header
    2245          * as a RFC 5987/6266 filename* value, and for use as a cross-platform filename.
    2246          * Replace chars likely to be illegal in filenames with _
    2247          *
    2248          * Ref: RFC 6266, RFC 5987, i2psnark Storage.ILLEGAL
    2249          *
    2250          * @since 0.9.33
    2251          */
    2252         private static String encodeFilenameRFC5987(String name) {
    2253                 name = name.trim();
    2254                 StringBuilder buf = new StringBuilder(name.length());
    2255                 buf.append("utf-8''");
    2256                 for (int i = 0; i < name.length(); i++) {
    2257                         char c = name.charAt(i);
    2258                         // illegal filename chars
    2259                         if (c < 32 || (c >= 0x7f && c <= 0x9f) ||
    2260                             c == '<' || c == '>' || c == ':' || c == '"' ||
    2261                             c == '/' || c == '\\' || c == '|' || c == '?' ||
    2262                             c == '*' ||
    2263                             // unicode newlines
    2264                             c == 0x2028 || c == 0x2029) {
    2265                                 buf.append('_');
    2266                         } else if (c == ' ' || c == '\'' || c == '%' ||          // not in 5987 attr-char
    2267                                    c == '(' || c == ')' || c == '@' ||           // 2616 separators
    2268                                    c == ',' || c == ';' || c == '[' || c == ']' ||
    2269                                    c == '=' || c == '{' || c == '}') {
    2270                                 // single byte encoding
    2271                                 buf.append('%');
    2272                                 buf.append(Integer.toHexString(c));
    2273                         } else if (c < 0x7f) {
    2274                                 // single byte char, as-is
    2275                                 buf.append(c);
    2276                         } else {
    2277                                 // multi-byte encoding
    2278                                 byte[] utf = DataHelper.getUTF8(String.valueOf(c));
    2279                                 for (int j = 0; j < utf.length; j++) {
    2280                                         int b = utf[j] & 0xff;
    2281                                         buf.append('%');
    2282                                         if (b < 16)
    2283                                                 buf.append(0);
    2284                                         buf.append(Integer.toHexString(b));
    2285                                 }
    2286                         }
    2287                 }
    2288                 return buf.toString();
    22892214        }
    22902215
  • apps/susimail/src/src/i2p/susi/webmail/encoding/EncodingFactory.java

    r3d25a9f rddf7fba0  
    5959                                        Encoding e = (Encoding) (c.getDeclaredConstructor().newInstance());
    6060                                        encodings.put( e.getName(), e );
    61                                         Debug.debug( Debug.DEBUG, "Registered " + e.getClass().getName() );
     61                                        //Debug.debug( Debug.DEBUG, "Registered " + e.getClass().getName() );
    6262                                }
    6363                                catch (Exception e) {
  • apps/susimail/src/src/i2p/susi/webmail/encoding/HeaderLine.java

    r3d25a9f rddf7fba0  
    293293                                //      net.i2p.util.HexDump.dump(encodedWord, 0, offset));
    294294                                if (f4 == 0) {
    295                                         // at most 1 byte is pushed back, the rest is discarded
     295                                        // at most 1 byte is pushed back
    296296                                        if (f1 == 0) {
    297297                                                // This is normal
    298298                                                continue;
    299299                                        } else if (f2 == 0) {
     300                                                // =? but no more ?
     301                                                // output what we buffered
    300302                                                Debug.debug(Debug.DEBUG, "2nd '?' not found");
     303                                                for (int i = 0; i < offset; i++) {
     304                                                        out.write(encodedWord[i] & 0xff);
     305                                                }
    301306                                                continue;
    302307                                        } else if (f3 == 0) {
     308                                                // discard what we buffered
    303309                                                Debug.debug(Debug.DEBUG, "3rd '?' not found");
    304310                                                continue;
     
    327333                                                        // System.err.println( "decode(" + (f3 + 1) + "," + ( f4 - f3 - 1 ) + ")" );
    328334                                                        ReadBuffer tmpIn = new ReadBuffer(encodedWord, f3 + 1, f4 - f3 - 1);
    329                                                         MemoryBuffer tmp = new MemoryBuffer(DECODE_MAX);
     335                                                        // decoded won't be longer than encoded
     336                                                        MemoryBuffer tmp = new MemoryBuffer(f4 - f3 - 1);
    330337                                                        try {
    331338                                                                e.decode(tmpIn, tmp);
  • apps/susimail/src/src/i2p/susi/webmail/pop3/POP3MailBox.java

    r3d25a9f rddf7fba0  
    11791179                                        }
    11801180                                } catch (IOException e) {
    1181                                         Debug.debug( Debug.DEBUG, "error closing: " + e);
     1181                                        //Debug.debug( Debug.DEBUG, "error closing: " + e);
    11821182                                } finally {
    11831183                                        if (socket != null) {
  • apps/susimail/src/src/i2p/susi/webmail/smtp/SMTPClient.java

    r3d25a9f rddf7fba0  
    3030import i2p.susi.webmail.encoding.EncodingException;
    3131import i2p.susi.webmail.encoding.EncodingFactory;
     32import i2p.susi.util.FilenameUtil;
    3233
    3334import java.io.BufferedWriter;
     
    348349                                                if (encoding == null)
    349350                                                        throw new EncodingException( _t("No Encoding found for {0}", encodeTo));
     351                                                // ref: https://blog.nodemailer.com/2017/01/27/the-mess-that-is-attachment-filenames/
     352                                                // ref: RFC 2231
     353                                                // split Content-Disposition into 3 lines to maximize room
     354                                                // TODO filename*0* for long names...
     355                                                String name = attachment.getFileName();
     356                                                String name2 = FilenameUtil.sanitizeFilename(name);
     357                                                String name3 = FilenameUtil.encodeFilenameRFC5987(name);
    350358                                                out.write("\r\n--" + boundary +
    351359                                                          "\r\nContent-type: " + attachment.getContentType() +
    352                                                           "\r\nContent-Disposition: attachment; filename=\"" + attachment.getFileName() +
    353                                                           "\"\r\nContent-Transfer-Encoding: " + attachment.getTransferEncoding() +
     360                                                          "\r\nContent-Disposition: attachment;\r\n\tfilename=\"" + name2 +
     361                                                          "\";\r\n\tfilename*=" + name3 +
     362                                                          "\r\nContent-Transfer-Encoding: " + attachment.getTransferEncoding() +
    354363                                                          "\r\n\r\n");
    355364                                                InputStream in = null;
Note: See TracChangeset for help on using the changeset viewer.