jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeUtility.java
changeset 33547 e4c76ac38b12
parent 28326 2b9860c0d68a
child 43852 93a527059d8a
equal deleted inserted replaced
33390:d131f4b8433a 33547:e4c76ac38b12
     1 /*
     1 /*
     2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
   508             return etext;
   508             return etext;
   509 
   509 
   510         // Encoded words found. Start decoding ...
   510         // Encoded words found. Start decoding ...
   511 
   511 
   512         st = new StringTokenizer(etext, lwsp, true);
   512         st = new StringTokenizer(etext, lwsp, true);
   513         StringBuffer sb = new StringBuffer();  // decode buffer
   513         StringBuilder sb = new StringBuilder();  // decode buffer
   514         StringBuffer wsb = new StringBuffer(); // white space buffer
   514         StringBuilder wsb = new StringBuilder(); // white space buffer
   515         boolean prevWasEncoded = false;
   515         boolean prevWasEncoded = false;
   516 
   516 
   517         while (st.hasMoreTokens()) {
   517         while (st.hasMoreTokens()) {
   518             char c;
   518             char c;
   519             String s = st.nextToken();
   519             String s = st.nextToken();
   646             b64 = false;
   646             b64 = false;
   647         else
   647         else
   648             throw new UnsupportedEncodingException(
   648             throw new UnsupportedEncodingException(
   649                         "Unknown transfer encoding: " + encoding);
   649                         "Unknown transfer encoding: " + encoding);
   650 
   650 
   651         StringBuffer outb = new StringBuffer(); // the output buffer
   651         StringBuilder outb = new StringBuilder(); // the output buffer
   652         doEncode(string, b64, jcharset,
   652         doEncode(string, b64, jcharset,
   653                  // As per RFC 2047, size of an encoded string should not
   653                  // As per RFC 2047, size of an encoded string should not
   654                  // exceed 75 bytes.
   654                  // exceed 75 bytes.
   655                  // 7 = size of "=?", '?', 'B'/'Q', '?', "?="
   655                  // 7 = size of "=?", '?', 'B'/'Q', '?', "?="
   656                  75 - 7 - charset.length(), // the available space
   656                  75 - 7 - charset.length(), // the available space
   660         return outb.toString();
   660         return outb.toString();
   661     }
   661     }
   662 
   662 
   663     private static void doEncode(String string, boolean b64,
   663     private static void doEncode(String string, boolean b64,
   664                 String jcharset, int avail, String prefix,
   664                 String jcharset, int avail, String prefix,
   665                 boolean first, boolean encodingWord, StringBuffer buf)
   665                 boolean first, boolean encodingWord, StringBuilder buf)
   666                         throws UnsupportedEncodingException {
   666                         throws UnsupportedEncodingException {
   667 
   667 
   668         // First find out what the length of the encoded version of
   668         // First find out what the length of the encoded version of
   669         // 'string' would be.
   669         // 'string' would be.
   670         byte[] bytes = string.getBytes(jcharset);
   670         byte[] bytes = string.getBytes(jcharset);
   810      * produce such incorrect encodings.
   810      * produce such incorrect encodings.
   811      */
   811      */
   812     private static String decodeInnerWords(String word)
   812     private static String decodeInnerWords(String word)
   813                                 throws UnsupportedEncodingException {
   813                                 throws UnsupportedEncodingException {
   814         int start = 0, i;
   814         int start = 0, i;
   815         StringBuffer buf = new StringBuffer();
   815         StringBuilder buf = new StringBuilder();
   816         while ((i = word.indexOf("=?", start)) >= 0) {
   816         while ((i = word.indexOf("=?", start)) >= 0) {
   817             buf.append(word.substring(start, i));
   817             buf.append(word.substring(start, i));
   818             int end = word.indexOf("?=", i);
   818             int end = word.indexOf("?=", i);
   819             if (end < 0)
   819             if (end < 0)
   820                 break;
   820                 break;
   860         boolean needQuoting = false;
   860         boolean needQuoting = false;
   861         for (int i = 0; i < len; i++) {
   861         for (int i = 0; i < len; i++) {
   862             char c = word.charAt(i);
   862             char c = word.charAt(i);
   863             if (c == '"' || c == '\\' || c == '\r' || c == '\n') {
   863             if (c == '"' || c == '\\' || c == '\r' || c == '\n') {
   864                 // need to escape them and then quote the whole string
   864                 // need to escape them and then quote the whole string
   865                 StringBuffer sb = new StringBuffer(len + 3);
   865                 StringBuilder sb = new StringBuilder(len + 3);
   866                 sb.append('"');
   866                 sb.append('"');
   867                 sb.append(word.substring(0, i));
   867                 sb.append(word.substring(0, i));
   868                 int lastc = 0;
   868                 int lastc = 0;
   869                 for (int j = i; j < len; j++) {
   869                 for (int j = i; j < len; j++) {
   870                     char cc = word.charAt(j);
   870                     char cc = word.charAt(j);
   883                 // These characters cause the string to be quoted
   883                 // These characters cause the string to be quoted
   884                 needQuoting = true;
   884                 needQuoting = true;
   885         }
   885         }
   886 
   886 
   887         if (needQuoting) {
   887         if (needQuoting) {
   888             StringBuffer sb = new StringBuffer(len + 2);
   888             StringBuilder sb = new StringBuilder(len + 2);
   889             sb.append('"').append(word).append('"');
   889             sb.append('"').append(word).append('"');
   890             return sb.toString();
   890             return sb.toString();
   891         } else
   891         } else
   892             return word;
   892             return word;
   893     }
   893     }
   925         // if the string fits now, just return it
   925         // if the string fits now, just return it
   926         if (used + s.length() <= 76)
   926         if (used + s.length() <= 76)
   927             return s;
   927             return s;
   928 
   928 
   929         // have to actually fold the string
   929         // have to actually fold the string
   930         StringBuffer sb = new StringBuffer(s.length() + 4);
   930         StringBuilder sb = new StringBuilder(s.length() + 4);
   931         char lastc = 0;
   931         char lastc = 0;
   932         while (used + s.length() > 76) {
   932         while (used + s.length() > 76) {
   933             int lastspace = -1;
   933             int lastspace = -1;
   934             for (int i = 0; i < s.length(); i++) {
   934             for (int i = 0; i < s.length(); i++) {
   935                 if (lastspace != -1 && used + i > 76)
   935                 if (lastspace != -1 && used + i > 76)
   967      */
   967      */
   968     /*public*/ static String unfold(String s) {
   968     /*public*/ static String unfold(String s) {
   969         if (!foldText)
   969         if (!foldText)
   970             return s;
   970             return s;
   971 
   971 
   972         StringBuffer sb = null;
   972         StringBuilder sb = null;
   973         int i;
   973         int i;
   974         while ((i = indexOfAny(s, "\r\n")) >= 0) {
   974         while ((i = indexOfAny(s, "\r\n")) >= 0) {
   975             int start = i;
   975             int start = i;
   976             int l = s.length();
   976             int l = s.length();
   977             i++;                // skip CR or NL
   977             i++;                // skip CR or NL
   984                 if (i < l && ((c = s.charAt(i)) == ' ' || c == '\t')) {
   984                 if (i < l && ((c = s.charAt(i)) == ' ' || c == '\t')) {
   985                     i++;        // skip whitespace
   985                     i++;        // skip whitespace
   986                     while (i < l && ((c = s.charAt(i)) == ' ' || c == '\t'))
   986                     while (i < l && ((c = s.charAt(i)) == ' ' || c == '\t'))
   987                         i++;
   987                         i++;
   988                     if (sb == null)
   988                     if (sb == null)
   989                         sb = new StringBuffer(s.length());
   989                         sb = new StringBuilder(s.length());
   990                     if (start != 0) {
   990                     if (start != 0) {
   991                         sb.append(s.substring(0, start));
   991                         sb.append(s.substring(0, start));
   992                         sb.append(' ');
   992                         sb.append(' ');
   993                     }
   993                     }
   994                     s = s.substring(i);
   994                     s = s.substring(i);
   995                     continue;
   995                     continue;
   996                 }
   996                 }
   997                 // it's not a continuation line, just leave it in
   997                 // it's not a continuation line, just leave it in
   998                 if (sb == null)
   998                 if (sb == null)
   999                     sb = new StringBuffer(s.length());
   999                     sb = new StringBuilder(s.length());
  1000                 sb.append(s.substring(0, i));
  1000                 sb.append(s.substring(0, i));
  1001                 s = s.substring(i);
  1001                 s = s.substring(i);
  1002             } else {
  1002             } else {
  1003                 // there's a backslash at "start - 1"
  1003                 // there's a backslash at "start - 1"
  1004                 // strip it out, but leave in the line break
  1004                 // strip it out, but leave in the line break
  1005                 if (sb == null)
  1005                 if (sb == null)
  1006                     sb = new StringBuffer(s.length());
  1006                     sb = new StringBuilder(s.length());
  1007                 sb.append(s.substring(0, start - 1));
  1007                 sb.append(s.substring(0, start - 1));
  1008                 sb.append(s.substring(start, i));
  1008                 sb.append(s.substring(start, i));
  1009                 s = s.substring(i);
  1009                 s = s.substring(i);
  1010             }
  1010             }
  1011         }
  1011         }
  1049     public static String javaCharset(String charset) {
  1049     public static String javaCharset(String charset) {
  1050         if (mime2java == null || charset == null)
  1050         if (mime2java == null || charset == null)
  1051             // no mapping table, or charset parameter is null
  1051             // no mapping table, or charset parameter is null
  1052             return charset;
  1052             return charset;
  1053 
  1053 
  1054         String alias = (String)mime2java.get(charset.toLowerCase());
  1054         String alias = mime2java.get(charset.toLowerCase());
  1055         return alias == null ? charset : alias;
  1055         return alias == null ? charset : alias;
  1056     }
  1056     }
  1057 
  1057 
  1058     /**
  1058     /**
  1059      * Convert a java charset into its MIME charset name. <p>
  1059      * Convert a java charset into its MIME charset name. <p>
  1071     public static String mimeCharset(String charset) {
  1071     public static String mimeCharset(String charset) {
  1072         if (java2mime == null || charset == null)
  1072         if (java2mime == null || charset == null)
  1073             // no mapping table or charset param is null
  1073             // no mapping table or charset param is null
  1074             return charset;
  1074             return charset;
  1075 
  1075 
  1076         String alias = (String)java2mime.get(charset.toLowerCase());
  1076         String alias = java2mime.get(charset.toLowerCase());
  1077         return alias == null ? charset : alias;
  1077         return alias == null ? charset : alias;
  1078     }
  1078     }
  1079 
  1079 
  1080     private static String defaultJavaCharset;
  1080     private static String defaultJavaCharset;
  1081     private static String defaultMIMECharset;
  1081     private static String defaultMIMECharset;
  1138         return defaultMIMECharset;
  1138         return defaultMIMECharset;
  1139     }
  1139     }
  1140 
  1140 
  1141     // Tables to map MIME charset names to Java names and vice versa.
  1141     // Tables to map MIME charset names to Java names and vice versa.
  1142     // XXX - Should eventually use J2SE 1.4 java.nio.charset.Charset
  1142     // XXX - Should eventually use J2SE 1.4 java.nio.charset.Charset
  1143     private static Hashtable mime2java;
  1143     private static Hashtable<String, String> mime2java;
  1144     private static Hashtable java2mime;
  1144     private static Hashtable<String, String> java2mime;
  1145 
  1145 
  1146     static {
  1146     static {
  1147         java2mime = new Hashtable(40);
  1147         java2mime = new Hashtable<String, String>(40);
  1148         mime2java = new Hashtable(10);
  1148         mime2java = new Hashtable<String, String>(10);
  1149 
  1149 
  1150         try {
  1150         try {
  1151             // Use this class's classloader to load the mapping file
  1151             // Use this class's classloader to load the mapping file
  1152             // XXX - we should use SecuritySupport, but it's in another package
  1152             // XXX - we should use SecuritySupport, but it's in another package
  1153             InputStream is =
  1153             InputStream is =
  1227             mime2java.put("us-ascii", "ISO-8859-1");
  1227             mime2java.put("us-ascii", "ISO-8859-1");
  1228             mime2java.put("x-us-ascii", "ISO-8859-1");
  1228             mime2java.put("x-us-ascii", "ISO-8859-1");
  1229         }
  1229         }
  1230     }
  1230     }
  1231 
  1231 
  1232     private static void loadMappings(LineInputStream is, Hashtable table) {
  1232     private static void loadMappings(LineInputStream is, Hashtable<String, String> table) {
  1233         String currLine;
  1233         String currLine;
  1234 
  1234 
  1235         while (true) {
  1235         while (true) {
  1236             try {
  1236             try {
  1237                 currLine = is.readLine();
  1237                 currLine = is.readLine();