📄 mimeutility.java
字号:
try { String decodedWord; if (word.length() > 0) { // Extract the bytes from word ByteArrayInputStream bis = new ByteArrayInputStream(ASCIIUtility.getBytes(word)); // Get the appropriate decoder InputStream is; if (encoding.equalsIgnoreCase("B")) is = new BASE64DecoderStream(bis); else if (encoding.equalsIgnoreCase("Q")) is = new QDecoderStream(bis); else throw new UnsupportedEncodingException( "unknown encoding: " + encoding); // For b64 & q, size of decoded word <= size of word. So // the decoded bytes must fit into the 'bytes' array. This // is certainly more efficient than writing bytes into a // ByteArrayOutputStream and then pulling out the byte[] // from it. int count = bis.available(); byte[] bytes = new byte[count]; // count is set to the actual number of decoded bytes count = is.read(bytes, 0, count); // Finally, convert the decoded bytes into a String using // the specified charset decodedWord = count <= 0 ? "" : new String(bytes, 0, count, charset); } else { // no characters to decode, return empty string decodedWord = ""; } if (pos + 2 < eword.length()) { // there's still more text in the string String rest = eword.substring(pos + 2); if (!decodeStrict) rest = decodeInnerWords(rest); decodedWord += rest; } return decodedWord; } catch (UnsupportedEncodingException uex) { // explicitly catch and rethrow this exception, otherwise // the below IOException catch will swallow this up! throw uex; } catch (IOException ioex) { // Shouldn't happen. throw new ParseException(ioex.toString()); } catch (IllegalArgumentException iex) { /* An unknown charset of the form ISO-XXX-XXX, will cause * the JDK to throw an IllegalArgumentException ... Since the * JDK will attempt to create a classname using this string, * but valid classnames must not contain the character '-', * and this results in an IllegalArgumentException, rather than * the expected UnsupportedEncodingException. Yikes */ throw new UnsupportedEncodingException(charset); } } /** * Look for encoded words within a word. The MIME spec doesn't * allow this, but many broken mailers, especially Japanese mailers, * produce such incorrect encodings. */ private static String decodeInnerWords(String word) throws UnsupportedEncodingException { int start = 0, i; StringBuffer buf = new StringBuffer(); while ((i = word.indexOf("=?", start)) >= 0) { buf.append(word.substring(start, i)); // find first '?' after opening '=?' - end of charset int end = word.indexOf('?', i + 2); if (end < 0) break; // find next '?' after that - end of encoding end = word.indexOf('?', end + 1); if (end < 0) break; // find terminating '?=' end = word.indexOf("?=", end + 1); if (end < 0) break; String s = word.substring(i, end + 2); try { s = decodeWord(s); } catch (ParseException pex) { // ignore it, just use the original string } buf.append(s); start = end + 2; } if (start == 0) return word; if (start < word.length()) buf.append(word.substring(start)); return buf.toString(); } /** * A utility method to quote a word, if the word contains any * characters from the specified 'specials' list.<p> * * The <code>HeaderTokenizer</code> class defines two special * sets of delimiters - MIME and RFC 822. <p> * * This method is typically used during the generation of * RFC 822 and MIME header fields. * * @param word word to be quoted * @param specials the set of special characters * @return the possibly quoted word * @see javax.mail.internet.HeaderTokenizer#MIME * @see javax.mail.internet.HeaderTokenizer#RFC822 */ public static String quote(String word, String specials) { int len = word.length(); /* * Look for any "bad" characters, Escape and * quote the entire string if necessary. */ boolean needQuoting = false; for (int i = 0; i < len; i++) { char c = word.charAt(i); if (c == '"' || c == '\\' || c == '\r' || c == '\n') { // need to escape them and then quote the whole string StringBuffer sb = new StringBuffer(len + 3); sb.append('"'); sb.append(word.substring(0, i)); int lastc = 0; for (int j = i; j < len; j++) { char cc = word.charAt(j); if ((cc == '"') || (cc == '\\') || (cc == '\r') || (cc == '\n')) if (cc == '\n' && lastc == '\r') ; // do nothing, CR was already escaped else sb.append('\\'); // Escape the character sb.append(cc); lastc = cc; } sb.append('"'); return sb.toString(); } else if (c < 040 || c >= 0177 || specials.indexOf(c) >= 0) // These characters cause the string to be quoted needQuoting = true; } if (needQuoting) { StringBuffer sb = new StringBuffer(len + 2); sb.append('"').append(word).append('"'); return sb.toString(); } else return word; } /** * Fold a string at linear whitespace so that each line is no longer * than 76 characters, if possible. If there are more than 76 * non-whitespace characters consecutively, the string is folded at * the first whitespace after that sequence. The parameter * <code>used</code> indicates how many characters have been used in * the current line; it is usually the length of the header name. <p> * * Note that line breaks in the string aren't escaped; they probably * should be. * * @param used characters used in line so far * @param s the string to fold * @return the folded string * @since JavaMail 1.4 */ public static String fold(int used, String s) { if (!foldText) return s; int end; char c; // Strip trailing spaces and newlines for (end = s.length() - 1; end >= 0; end--) { c = s.charAt(end); if (c != ' ' && c != '\t' && c != '\r' && c != '\n') break; } if (end != s.length() - 1) s = s.substring(0, end + 1); // if the string fits now, just return it if (used + s.length() <= 76) return s; // have to actually fold the string StringBuffer sb = new StringBuffer(s.length() + 4); char lastc = 0; while (used + s.length() > 76) { int lastspace = -1; for (int i = 0; i < s.length(); i++) { if (lastspace != -1 && used + i > 76) break; c = s.charAt(i); if (c == ' ' || c == '\t') if (!(lastc == ' ' || lastc == '\t')) lastspace = i; lastc = c; } if (lastspace == -1) { // no space, use the whole thing sb.append(s); s = ""; used = 0; break; } sb.append(s.substring(0, lastspace)); sb.append("\r\n"); lastc = s.charAt(lastspace); sb.append(lastc); s = s.substring(lastspace + 1); used = 1; } sb.append(s); return sb.toString(); } /** * Unfold a folded header. Any line breaks that aren't escaped and * are followed by whitespace are removed. * * @param s the string to unfold * @return the unfolded string * @since JavaMail 1.4 */ public static String unfold(String s) { if (!foldText) return s; StringBuffer sb = null; int i; while ((i = indexOfAny(s, "\r\n")) >= 0) { int start = i; int l = s.length(); i++; // skip CR or NL if (i < l && s.charAt(i - 1) == '\r' && s.charAt(i) == '\n') i++; // skip LF if (start == 0 || s.charAt(start - 1) != '\\') { char c; // if next line starts with whitespace, skip all of it // XXX - always has to be true? if (i < l && ((c = s.charAt(i)) == ' ' || c == '\t')) { i++; // skip whitespace while (i < l && ((c = s.charAt(i)) == ' ' || c == '\t')) i++; if (sb == null) sb = new StringBuffer(s.length()); if (start != 0) { sb.append(s.substring(0, start)); sb.append(' '); } s = s.substring(i); continue; } // it's not a continuation line, just leave it in if (sb == null) sb = new StringBuffer(s.length()); sb.append(s.substring(0, i)); s = s.substring(i); } else { // there's a backslash at "start - 1" // strip it out, but leave in the line break if (sb == null) sb = new StringBuffer(s.length()); sb.append(s.substring(0, start - 1)); sb.append(s.substring(start, i)); s = s.substring(i); } } if (sb != null) { sb.append(s); return sb.toString(); } else return s; } /** * Return the first index of any of the characters in "any" in "s", * or -1 if none are found. * * This should be a method on String. */ private static int indexOfAny(String s, String any) { return indexOfAny(s, any, 0); } private static int indexOfAny(String s, String any, int start) { try { int len = s.length(); for (int i = start; i < len; i++) { if (any.indexOf(s.charAt(i)) >= 0) return i; } return -1; } catch (StringIndexOutOfBoundsException e) { return -1; } } /** * Convert a MIME charset name into a valid Java charset name. <p> * * @param charset the MIME charset name * @return the Java charset equivalent. If a suitable mapping is * not available, the passed in charset is itself returned. */ public static String javaCharset(String charset) { if (mime2java == null || charset == null) // no mapping table, or charset parameter is null return charset; String alias = (String)mime2java.get(charset.toLowerCase(Locale.ENGLISH)); return alias == null ? charset : alias; } /** * Convert a java charset into its MIME charset name. <p> * * Note that a future version of JDK (post 1.2) might provide * this functionality, in which case, we may deprecate this * method then. * * @param charset the JDK charset * @return the MIME/IANA equivalent. If a mapping * is not possible, the passed in charset itself * is returned. * @since JavaMail 1.1 */ public static String mimeCharset(String charset) { if (java2mime == null || charset == null) // no mapping table or charset param is null return charset; String alias = (String)java2mime.get(charset.toLowerCase(Locale.ENGLISH)); return alias == null ? charset : alias; } private static String defaultJavaCharset; private static String defaultMIMECharset; /** * Get the default charset corresponding to the system's current * default locale. If the System property <code>mail.mime.charset</code> * is set, a system charset corresponding to this MIME charset will be * returned. <p> * * @return the default charset of the system's default locale, * as a Java charset. (NOT a MIME charset) * @since JavaMail 1.1 */ public static String getDefaultJavaCharset() { if (defaultJavaCharset == null) { /* * If mail.mime.charset is set, it controls the default * Java charset as well. */ String mimecs = null; try { mimecs = System.getProperty("mail.mime.charset"); } catch (SecurityException ex) { } // ignore it if (mimecs != null && mimecs.length() > 0) { defaultJavaCharset = javaCharset(mimecs); return defaultJavaCharset; } try { defaultJavaCharset = System.getProperty("file.encoding", "8859_1"); } catch (SecurityException sex) { class NullInputStream extends InputStream { public int read() { return 0; } } InputStreamReader reader = new InputStreamReader(new NullInputStream()); defaultJavaCharset = reader.getEncoding(); if (defaultJavaCharset == null) defaultJavaCharset = "8859_1"; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -