001: //The contents of this file are subject to the Mozilla Public License Version 1.1
002: //(the "License"); you may not use this file except in compliance with the
003: //License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
004: //
005: //Software distributed under the License is distributed on an "AS IS" basis,
006: //WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
007: //for the specific language governing rights and
008: //limitations under the License.
009: //
010: //The Original Code is "The Columba Project"
011: //
012: //The Initial Developers of the Original Code are Frederik Dietz and Timo Stich.
013: //Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
014: //
015: //All Rights Reserved.
016: package org.columba.mail.parser;
017:
018: import java.util.ArrayList;
019: import java.util.Hashtable;
020: import java.util.List;
021: import java.util.Map;
022: import java.util.logging.Logger;
023: import java.util.regex.Matcher;
024: import java.util.regex.Pattern;
025:
026: import org.columba.ristretto.io.CharSequenceSource;
027: import org.columba.ristretto.message.Address;
028: import org.columba.ristretto.message.BasicHeader;
029: import org.columba.ristretto.parser.HeaderParser;
030: import org.columba.ristretto.parser.ParserException;
031:
032: public class MailUrlParser {
033: /** JDK 1.4+ logging framework logger, used for logging. */
034: private static final Logger LOG = Logger
035: .getLogger("org.columba.mail.parser");
036:
037: private static final Pattern mailtoPattern = Pattern.compile(
038: "mailto:([^?]*)\\??(.*)", Pattern.CASE_INSENSITIVE);
039: private static final Pattern headerPattern = Pattern
040: .compile("&?([^=]+)=([^&]+)");
041:
042: public static Map parse(String in) throws ParserException {
043: Hashtable result = new Hashtable();
044: StringBuffer temp = new StringBuffer();
045:
046: Matcher matcher = mailtoPattern.matcher(in);
047:
048: if (matcher.matches()) {
049: if (matcher.group(1) != null) {
050: temp.append("To: ");
051: temp.append(decodeHTML(matcher.group(1)));
052: temp.append("\r\n");
053: }
054:
055: if (matcher.group(2) != null) {
056: matcher = headerPattern.matcher(matcher.group(2));
057: while (matcher.find()) {
058: String key = matcher.group(1).toLowerCase();
059:
060: if (key.equals("to") || key.equals("cc")
061: || key.equals("bcc")
062: || key.equals("subject")) {
063: temp.append(matcher.group(1));
064: temp.append(": ");
065: temp.append(decodeHTML(matcher.group(2)));
066: temp.append("\r\n");
067: } else if (key.equals("body")) {
068: result
069: .put("body", decodeHTML(matcher
070: .group(2)));
071: } else {
072: LOG.warning("Unsafe header in mailto-URL: "
073: + matcher.group());
074: }
075: }
076: }
077:
078: BasicHeader header = new BasicHeader(HeaderParser
079: .parse(new CharSequenceSource(temp)));
080:
081: // Convert to MessageOptions
082: Address[] addresses = header.getTo();
083:
084: List addressList = new ArrayList();
085:
086: for (int i = 0; i < addresses.length; i++) {
087: addressList.add(addresses[i].toString());
088: }
089: result.put("to", addressList.toArray(new String[0]));
090:
091: addresses = header.getCc();
092: if (addresses.length > 0) {
093: addressList.clear();
094: for (int i = 0; i < addresses.length; i++) {
095: addressList.add(addresses[i].toString());
096: }
097: result.put("cc", addressList.toArray(new String[0]));
098: }
099:
100: addresses = header.getBcc();
101: if (addresses.length > 0) {
102: addressList.clear();
103: for (int i = 0; i < addresses.length; i++) {
104: addressList.add(addresses[i].toString());
105: }
106: result.put("bcc", addressList.toArray(new String[0]));
107: }
108:
109: if (header.getSubject() != null) {
110: result.put("subject", header.getSubject());
111: }
112:
113: }
114:
115: return result;
116: }
117:
118: private static String decodeHTML(String in) {
119: StringBuffer result = new StringBuffer(in.length());
120: int pos = 0;
121: int nextpos = in.indexOf('%', pos);
122:
123: while (nextpos != -1) {
124: result.append(in.substring(pos, nextpos));
125: result.append((char) Integer.parseInt(in.substring(
126: nextpos + 1, nextpos + 3), 16));
127:
128: pos = nextpos + 3;
129: nextpos = in.indexOf('%', pos);
130: }
131:
132: result.append(in.substring(pos));
133:
134: return result.toString();
135: }
136:
137: }
|