1 21 22 27 28 package javax.mail.internet; 29 30 import java.util.*; 31 import java.io.*; 32 33 52 53 public class ParameterList { 54 55 60 private Map list = new LinkedHashMap(); 62 private static boolean encodeParameters = false; 63 private static boolean decodeParameters = false; 64 private static boolean decodeParametersStrict = false; 65 66 static { 67 try { 68 String s = System.getProperty("mail.mime.encodeparameters"); 69 encodeParameters = s != null && s.equalsIgnoreCase("true"); 71 s = System.getProperty("mail.mime.decodeparameters"); 72 decodeParameters = s != null && s.equalsIgnoreCase("true"); 74 s = System.getProperty("mail.mime.decodeparameters.strict"); 75 decodeParametersStrict = s != null && s.equalsIgnoreCase("true"); 77 } catch (SecurityException sex) { 78 } 80 } 81 82 92 private static class Value { 93 String value; 94 String encodedValue; 95 } 96 97 100 private static class ParamEnum implements Enumeration { 101 private Iterator it; 102 103 ParamEnum(Iterator it) { 104 this.it = it; 105 } 106 107 public boolean hasMoreElements() { 108 return it.hasNext(); 109 } 110 111 public Object nextElement() { 112 return it.next(); 113 } 114 } 115 116 119 public ParameterList() { 120 } 121 122 132 public ParameterList(String s) throws ParseException { 133 HeaderTokenizer h = new HeaderTokenizer (s, HeaderTokenizer.MIME); 134 HeaderTokenizer.Token tk; 135 int type; 136 String name; 137 138 for (;;) { 139 tk = h.next(); 140 type = tk.getType(); 141 142 if (type == HeaderTokenizer.Token.EOF) return; 144 145 if ((char)type == ';') { 146 tk = h.next(); 148 if (tk.getType() == HeaderTokenizer.Token.EOF) 150 return; 151 if (tk.getType() != HeaderTokenizer.Token.ATOM) 153 throw new ParseException ("Expected parameter name, " + 154 "got \"" + tk.getValue() + "\""); 155 name = tk.getValue().toLowerCase(); 156 157 tk = h.next(); 159 if ((char)tk.getType() != '=') 160 throw new ParseException ("Expected '=', " + 161 "got \"" + tk.getValue() + "\""); 162 163 tk = h.next(); 165 type = tk.getType(); 166 if (type != HeaderTokenizer.Token.ATOM && 168 type != HeaderTokenizer.Token.QUOTEDSTRING) 169 throw new ParseException ("Expected parameter value, " + 170 "got \"" + tk.getValue() + "\""); 171 172 String value = tk.getValue(); 173 if (decodeParameters && name.endsWith("*")) { 174 name = name.substring(0, name.length() - 1); 175 list.put(name, decodeValue(value)); 176 } else 177 list.put(name, value); 178 } else 179 throw new ParseException ("Expected ';', " + 180 "got \"" + tk.getValue() + "\""); 181 } 182 } 183 184 189 public int size() { 190 return list.size(); 191 } 192 193 202 public String get(String name) { 203 String value; 204 Object v = list.get(name.trim().toLowerCase()); 205 if (v instanceof Value) 206 value = ((Value)v).value; 207 else 208 value = (String )v; 209 return value; 210 } 211 212 219 public void set(String name, String value) { 220 list.put(name.trim().toLowerCase(), value); 221 } 222 223 235 public void set(String name, String value, String charset) { 236 if (encodeParameters) { 237 Value ev = encodeValue(value, charset); 238 if (ev != null) 240 list.put(name.trim().toLowerCase(), ev); 241 else 242 set(name, value); 243 } else 244 set(name, value); 245 } 246 247 253 public void remove(String name) { 254 list.remove(name.trim().toLowerCase()); 255 } 256 257 263 public Enumeration getNames() { 264 return new ParamEnum(list.keySet().iterator()); 265 } 266 267 273 public String toString() { 274 return toString(0); 275 } 276 277 291 public String toString(int used) { 292 StringBuffer sb = new StringBuffer (); 293 Iterator e = list.keySet().iterator(); 294 295 while (e.hasNext()) { 296 String name = (String )e.next(); 297 String value; 298 Object v = list.get(name); 299 if (v instanceof Value) { 300 value = ((Value)v).encodedValue; 301 name += '*'; 302 } else 303 value = (String )v; 304 value = quote(value); 305 sb.append("; "); 306 used += 2; 307 int len = name.length() + value.length() + 1; 308 if (used + len > 76) { sb.append("\r\n\t"); used = 8; } 312 sb.append(name).append('='); 313 used += name.length() + 1; 314 if (used + value.length() > 76) { String s = MimeUtility.fold(used, value); 317 sb.append(s); 318 int lastlf = s.lastIndexOf('\n'); 319 if (lastlf >= 0) used += s.length() - lastlf - 1; 321 else 322 used += s.length(); 323 } else { 324 sb.append(value); 325 used += value.length(); 326 } 327 } 328 329 return sb.toString(); 330 } 331 332 private String quote(String value) { 334 return MimeUtility.quote(value, HeaderTokenizer.MIME); 335 } 336 337 private static final char hex[] = { 338 '0','1', '2', '3', '4', '5', '6', '7', 339 '8','9', 'A', 'B', 'C', 'D', 'E', 'F' 340 }; 341 342 347 private Value encodeValue(String value, String charset) { 348 if (MimeUtility.checkAscii(value) == MimeUtility.ALL_ASCII) 349 return null; 351 byte[] b; try { 353 b = value.getBytes(MimeUtility.javaCharset(charset)); 354 } catch (UnsupportedEncodingException ex) { 355 return null; 356 } 357 StringBuffer sb = new StringBuffer (b.length + charset.length() + 2); 358 sb.append(charset).append("''"); 359 for (int i = 0; i < b.length; i++) { 360 char c = (char)(b[i] & 0xff); 361 if (c <= ' ' || c >= 0x7f || c == '*' || c == '\'' || c == '%' || 363 HeaderTokenizer.MIME.indexOf(c) >= 0) { 364 sb.append('%').append(hex[c>>4]).append(hex[c&0xf]); 365 } else 366 sb.append(c); 367 } 368 Value v = new Value(); 369 v.value = value; 370 v.encodedValue = sb.toString(); 371 return v; 372 } 373 374 377 private Value decodeValue(String value) throws ParseException { 378 Value v = new Value(); 379 v.encodedValue = value; 380 v.value = value; try { 382 int i = value.indexOf('\''); 383 if (i <= 0) { 384 if (decodeParametersStrict) 385 throw new ParseException ( 386 "Missing charset in encoded value: " + value); 387 return v; } 389 String charset = value.substring(0, i); 390 int li = value.indexOf('\'', i + 1); 391 if (li < 0) { 392 if (decodeParametersStrict) 393 throw new ParseException ( 394 "Missing language in encoded value: " + value); 395 return v; } 397 String lang = value.substring(i + 1, li); 398 value = value.substring(li + 1); 399 400 408 byte[] b = new byte[value.length()]; 409 int bi; 410 for (i = 0, bi = 0; i < value.length(); i++) { 411 char c = value.charAt(i); 412 if (c == '%') { 413 String hex = value.substring(i + 1, i + 3); 414 c = (char)Integer.parseInt(hex, 16); 415 i += 2; 416 } 417 b[bi++] = (byte)c; 418 } 419 v.value = new String (b, 0, bi, MimeUtility.javaCharset(charset)); 420 } catch (NumberFormatException nex) { 421 if (decodeParametersStrict) 422 throw new ParseException (nex.toString()); 423 } catch (UnsupportedEncodingException uex) { 424 if (decodeParametersStrict) 425 throw new ParseException (uex.toString()); 426 } catch (StringIndexOutOfBoundsException ex) { 427 if (decodeParametersStrict) 428 throw new ParseException (ex.toString()); 429 } 430 return v; 431 } 432 } 433 | Popular Tags |