Source Code Cross Referenced for WebMailSession.java in  » Web-Mail » jwebmail-0.7 » net » wastl » webmail » server » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Mail » jwebmail 0.7 » net.wastl.webmail.server 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* CVS ID: $Id: WebMailSession.java,v 1.1.1.1 2002/10/02 18:42:53 wastl Exp $ */
0002:        package net.wastl.webmail.server;
0003:
0004:        import java.net.*;
0005:        import java.io.*;
0006:        import java.util.*;
0007:        import java.text.*;
0008:        import javax.mail.*;
0009:        import javax.mail.event.*;
0010:        import javax.mail.internet.*;
0011:        import net.wastl.webmail.misc.*;
0012:        import net.wastl.webmail.xml.*;
0013:        import net.wastl.webmail.ui.html.Fancyfier;
0014:        import net.wastl.webmail.server.http.HTTPRequestHeader;
0015:        import net.wastl.webmail.exceptions.*; // Modified by exce, start
0016:        import org.bulbul.webmail.util.TranscodeUtil; // Modified by exce, end
0017:
0018:        //import org.w3c.tidy.Tidy;
0019:
0020:        import org.w3c.dom.*;
0021:
0022:        // HTML parser:
0023:        import org.xml.sax.InputSource;
0024:
0025:        //import org.cyberneko.html.parsers.DOMParser;
0026:
0027:        /*
0028:         * WebMailSession.java
0029:         *
0030:         * Created: Thu Feb  4 12:59:30 1999
0031:         *
0032:         * Copyright (C) 1999-2001 Sebastian Schaffert
0033:         * 
0034:         * This program is free software; you can redistribute it and/or
0035:         * modify it under the terms of the GNU General Public License
0036:         * as published by the Free Software Foundation; either version 2
0037:         * of the License, or (at your option) any later version.
0038:         * 
0039:         * This program is distributed in the hope that it will be useful,
0040:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0041:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0042:         * GNU General Public License for more details.
0043:         * 
0044:         * You should have received a copy of the GNU General Public License
0045:         * along with this program; if not, write to the Free Software
0046:         * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
0047:         */
0048:
0049:        /**
0050:         * A user session for WebMail.
0051:         * Contains the state of the actual user (loads it from disk).
0052:         * Has a unique session-ID.
0053:         *
0054:         *
0055:         * @author Sebastian Schaffert
0056:         * @version $Revision: 1.1.1.1 $
0057:         */
0058:        /* 9/24/2000 devink - updated for challenge/response auth */
0059:        public class WebMailSession implements  HTTPSession {
0060:
0061:            /** When has the session been last accessed? */
0062:            private long last_access;
0063:            /** The session-ID for this session */
0064:            private String session_code;
0065:            /** Parent WebMailServer */
0066:            private WebMailServer parent;
0067:            /** State of the current users configuration */
0068:            private XMLUserData user;
0069:
0070:            private XMLUserModel model;
0071:
0072:            /** Connections to Mailboxes */
0073:            private Hashtable connections;
0074:
0075:            /** Connections to hosts */
0076:            private Hashtable stores;
0077:
0078:            /** javax.mail Mailsession */
0079:            private Session mailsession;
0080:
0081:            private InetAddress remote;
0082:
0083:            /* Files attached to messages will be stored here. We will have to take care of
0084:               possible memory problems! */
0085:            private Hashtable mime_parts_decoded;
0086:
0087:            private boolean sent;
0088:
0089:            private String remote_agent;
0090:            private String remote_accepts;
0091:
0092:            private int attachments_size = 0;
0093:
0094:            private String last_login;
0095:
0096:            /** Save the login password. It will be used for the second try password if
0097:             * opening a folder fails.
0098:             */
0099:            private String login_password;
0100:
0101:            private Object sess = null;
0102:
0103:            private Hashtable folders;
0104:
0105:            protected Vector need_expunge_folders;
0106:
0107:            protected boolean is_logged_out = false;
0108:
0109:            public WebMailSession(WebMailServer parent, Object parm,
0110:                    HTTPRequestHeader h) throws UserDataException,
0111:                    InvalidPasswordException, WebMailException {
0112:                try {
0113:                    Class srvltreq = Class
0114:                            .forName("javax.servlet.http.HttpServletRequest");
0115:                    if (srvltreq.isInstance(parm)) {
0116:                        javax.servlet.http.HttpServletRequest req = (javax.servlet.http.HttpServletRequest) parm;
0117:                        this .sess = req.getSession(false);
0118:                        session_code = ((javax.servlet.http.HttpSession) sess)
0119:                                .getId();
0120:
0121:                        try {
0122:                            remote = InetAddress.getByName(req.getRemoteHost());
0123:                        } catch (UnknownHostException e) {
0124:                            try {
0125:                                remote = InetAddress.getByName(req
0126:                                        .getRemoteAddr());
0127:                            } catch (Exception ex) {
0128:                                try {
0129:                                    remote = InetAddress.getByName("localhost");
0130:                                } catch (Exception ex2) {
0131:                                }
0132:                            }
0133:                        }
0134:                    } else {
0135:                        throw new Exception(
0136:                                "Servlet class found but not running as servlet");
0137:                    }
0138:                } catch (Throwable t) {
0139:                    this .remote = (InetAddress) parm;
0140:                    session_code = Helper.calcSessionCode(remote, h);
0141:                }
0142:                doInit(parent, h);
0143:
0144:            }
0145:
0146:            /**
0147:             * This method does the actual initialisation
0148:             *
0149:             * devink 7/15/2000 - added TwoPassAuthenticationException 
0150:             *                  - updated call to getUserData(), to use my new one.
0151:             * devink 9/24/2000 - reverted back to old getUserData call
0152:             */
0153:            protected void doInit(WebMailServer parent, HTTPRequestHeader h) 
0154:	 throws UserDataException, InvalidPasswordException, WebMailException {
0155:	setLastAccess();
0156:	this .parent=parent;
0157:	remote_agent=h.getHeader("User-Agent").replace('\n',' ');
0158:	remote_accepts=h.getHeader("Accept").replace('\n',' ');
0159:	parent.getStorage().log(Storage.LOG_INFO,"WebMail: New Session ("+session_code+")");
0160:	user=WebMailServer.getStorage().getUserData(h.getContent("login"),h.getContent("vdom"),h.getContent("password"),true);       
0161:	last_login=user.getLastLogin();
0162:	user.login();
0163:	login_password=h.getContent("password");
0164:	model=parent.getStorage().createXMLUserModel(user);
0165:	connections=new Hashtable();
0166:	stores=new Hashtable();
0167:	folders=new Hashtable();
0168:	mailsession=Session.getDefaultInstance(System.getProperties(),null);
0169:
0170:	/* If the user logs in for the first time we want all folders subscribed */
0171:	if(user.getLoginCount().equals("1")) {
0172:	    Enumeration enum=user.mailHosts();
0173:	    while(enum.hasMoreElements()) {
0174:		String id=(String)enum.nextElement();
0175:		if(user.getMailHost(id).getName().equals("Default")) {
0176:		    try {
0177:			setSubscribedAll(id,true);
0178:		    } catch(MessagingException ex) {
0179:			ex.printStackTrace();
0180:		    }
0181:		    break;
0182:		}
0183:	    }
0184:	}
0185:	setEnv();
0186:    }
0187:
0188:            public XMLUserModel getUserModel() {
0189:                return model;
0190:            }
0191:
0192:            public Document getModel() {
0193:                return model.getRoot();
0194:            }
0195:
0196:            /**
0197:             * Calculate session-ID for a session.
0198:             *
0199:             * @param a Adress of the remote host
0200:             * @param h Requestheader of the remote user agent
0201:             * @returns Session-ID
0202:             */
0203:            public String calcCode(InetAddress a, HTTPRequestHeader h) {
0204:                if (sess == null) {
0205:                    return Helper.calcSessionCode(a, h);
0206:                } else {
0207:                    try {
0208:                        Class srvltreq = Class
0209:                                .forName("javax.servlet.http.HttpSession");
0210:                        if (srvltreq.isInstance(sess)) {
0211:                            return ((javax.servlet.http.HttpSession) sess)
0212:                                    .getId();
0213:                        } else {
0214:                            return "error";
0215:                        }
0216:                    } catch (Throwable t) {
0217:                        return "error";
0218:                    }
0219:                }
0220:            }
0221:
0222:            /**
0223:             * Login to this session.
0224:             * Establishes connections to a userīs Mailhosts
0225:             *
0226:             * @param h RequestHeader with content from Login-POST operation.
0227:             * @deprecated Use login() instead, no need for parameters and exception handling
0228:             */
0229:            public void login(HTTPRequestHeader h)
0230:                    throws InvalidPasswordException {
0231:                //user.login(h.getContent("password"));
0232:                login();
0233:            }
0234:
0235:            /**
0236:             * Login this session.
0237:             *
0238:             * Updates access time, sets initial environment and connects all configured mailboxes.
0239:             */
0240:            public void login() {
0241:                setLastAccess();
0242:                setEnv();
0243:                connectAll();
0244:            }
0245:
0246:            /**
0247:             * Return a locale-specific string resource
0248:             */
0249:            public String getStringResource(String key) {
0250:                return parent.getStorage().getStringResource(key,
0251:                        user.getPreferredLocale());
0252:            }
0253:
0254:            /**
0255:             * Create a Message List.
0256:             * Fetches a list of headers in folder foldername for part list_part.
0257:             * The messagelist will be stored in the "MESSAGES" environment.
0258:             *
0259:             * @param foldername folder for which a message list should be built
0260:             * @param list_part part of list to display (1 = last xx messages, 2 = total-2*xx - total-xx messages)
0261:             */
0262:            public void createMessageList(String folderhash, int list_part)
0263:                    throws NoSuchFolderException {
0264:
0265:                long time_start = System.currentTimeMillis();
0266:                TimeZone tz = TimeZone.getDefault();
0267:                DateFormat df = DateFormat.getDateTimeInstance(
0268:                        DateFormat.DEFAULT, DateFormat.SHORT, user
0269:                                .getPreferredLocale());
0270:                df.setTimeZone(tz);
0271:
0272:                try {
0273:
0274:                    Folder folder = getFolder(folderhash);
0275:                    Element xml_folder = model.getFolder(folderhash);
0276:                    Element xml_current = model.setCurrentFolder(folderhash);
0277:                    Element xml_messagelist = model.getMessageList(xml_folder);
0278:
0279:                    if (folder == null) {
0280:                        throw new NoSuchFolderException(folderhash);
0281:                    }
0282:
0283:                    long fetch_start = System.currentTimeMillis();
0284:
0285:                    if (!folder.isOpen()) {
0286:                        folder.open(Folder.READ_ONLY);
0287:                    } else {
0288:                        folder.close(false);
0289:                        folder.open(Folder.READ_ONLY);
0290:                    }
0291:
0292:                    /* Calculate first and last message to show */
0293:                    int total_messages = folder.getMessageCount();
0294:                    int new_messages = folder.getNewMessageCount();
0295:                    int show_msgs = user.getMaxShowMessages();
0296:
0297:                    xml_messagelist.setAttribute("total", total_messages + "");
0298:                    xml_messagelist.setAttribute("new", new_messages + "");
0299:
0300:                    // 	    System.err.println("Total: "+total_messages);
0301:
0302:                    /* Handle small messagelists correctly */
0303:                    if (total_messages < show_msgs) {
0304:                        show_msgs = total_messages;
0305:                    }
0306:                    /* Don't accept list-parts smaller than 1 */
0307:                    if (list_part < 1) {
0308:                        list_part = 1;
0309:                    }
0310:                    for (int k = 0; k < list_part; k++) {
0311:                        total_messages -= show_msgs;
0312:                    }
0313:                    /* Handle beginning of message list */
0314:                    if (total_messages < 0) {
0315:                        total_messages = 0;
0316:                    }
0317:                    int first = total_messages + 1;
0318:                    int last = total_messages + show_msgs;
0319:                    /* Set environment variable */
0320:                    setEnv();
0321:                    xml_current.setAttribute("first_msg", first + "");
0322:                    xml_current.setAttribute("last_msg", last + "");
0323:                    xml_current.setAttribute("list_part", list_part + "");
0324:
0325:                    /* Fetch headers */
0326:                    FetchProfile fp = new FetchProfile();
0327:                    fp.add(FetchProfile.Item.ENVELOPE);
0328:                    fp.add(FetchProfile.Item.FLAGS);
0329:                    fp.add(FetchProfile.Item.CONTENT_INFO);
0330:                    // 	    System.err.println("Last: "+last+", first: "+first);
0331:                    Message[] msgs = folder.getMessages(first, last);
0332:                    //System.err.println(msgs.length + " messages fetching...");
0333:                    folder.fetch(msgs, fp);
0334:                    long fetch_stop = System.currentTimeMillis();
0335:
0336:                    Hashtable header = new Hashtable(15);
0337:
0338:                    Flags.Flag[] sf;
0339:                    String from, to, cc, bcc, replyto, subject;
0340:                    String messageid;
0341:
0342:                    for (int i = msgs.length - 1; i >= 0; i--) {
0343:                        // 		if(((MimeMessage)msgs[i]).getMessageID() == null) {
0344:                        // 		    folder.close(false);
0345:                        // 		    folder.open(Folder.READ_WRITE);
0346:                        // 		    ((MimeMessage)msgs[i]).setHeader("Message-ID","<"+user.getLogin()+"."+System.currentTimeMillis()+".jwebmail@"+user.getDomain()+">");
0347:                        // 		    ((MimeMessage)msgs[i]).saveChanges();
0348:                        // 		    folder.close(false);
0349:                        // 		    folder.open(Folder.READ_ONLY);
0350:                        // 		}
0351:
0352:                        try {
0353:                            StringTokenizer tok = new StringTokenizer(
0354:                                    ((MimeMessage) msgs[i]).getMessageID(),
0355:                                    "<>");
0356:                            messageid = tok.nextToken();
0357:                        } catch (NullPointerException ex) {
0358:                            // For mail servers that don't generate a Message-ID (Outlook et al)
0359:                            messageid = user.getLogin() + "." + i
0360:                                    + ".jwebmail@" + user.getDomain();
0361:                        }
0362:
0363:                        XMLMessage xml_message = model.getMessage(xml_folder,
0364:                                msgs[i].getMessageNumber() + "", messageid);
0365:
0366:                        /* Addresses */
0367:                        from = "";
0368:                        replyto = "";
0369:                        to = "";
0370:                        cc = "";
0371:                        bcc = "";
0372:                        try {
0373:                            from = MimeUtility.decodeText(Helper
0374:                                    .joinAddress(msgs[i].getFrom()));
0375:                            replyto = MimeUtility.decodeText(Helper
0376:                                    .joinAddress(msgs[i].getReplyTo()));
0377:                            to = MimeUtility
0378:                                    .decodeText(Helper
0379:                                            .joinAddress(msgs[i]
0380:                                                    .getRecipients(Message.RecipientType.TO)));
0381:                            cc = MimeUtility
0382:                                    .decodeText(Helper
0383:                                            .joinAddress(msgs[i]
0384:                                                    .getRecipients(Message.RecipientType.CC)));
0385:                            bcc = MimeUtility
0386:                                    .decodeText(Helper
0387:                                            .joinAddress(msgs[i]
0388:                                                    .getRecipients(Message.RecipientType.BCC)));
0389:                        } catch (UnsupportedEncodingException e) {
0390:                            parent.getStorage().log(Storage.LOG_WARN,
0391:                                    "Unsupported Encoding: " + e.getMessage());
0392:                        }
0393:                        if (from == "")
0394:                            from = getStringResource("unknown sender");
0395:                        if (to == "")
0396:                            to = getStringResource("unknown recipient");
0397:
0398:                        /* Flags */
0399:                        sf = msgs[i].getFlags().getSystemFlags();
0400:                        String basepath = parent.getBasePath();
0401:
0402:                        for (int j = 0; j < sf.length; j++) {
0403:                            if (sf[j] == Flags.Flag.RECENT)
0404:                                xml_message.setAttribute("recent", "true");
0405:                            if (sf[j] == Flags.Flag.SEEN)
0406:                                xml_message.setAttribute("seen", "true");
0407:                            if (sf[j] == Flags.Flag.DELETED)
0408:                                xml_message.setAttribute("deleted", "true");
0409:                            if (sf[j] == Flags.Flag.ANSWERED)
0410:                                xml_message.setAttribute("answered", "true");
0411:                            if (sf[j] == Flags.Flag.DRAFT)
0412:                                xml_message.setAttribute("draft", "true");
0413:                            if (sf[j] == Flags.Flag.FLAGGED)
0414:                                xml_message.setAttribute("flagged", "true");
0415:                            if (sf[j] == Flags.Flag.USER)
0416:                                xml_message.setAttribute("user", "true");
0417:                        }
0418:                        if (msgs[i] instanceof  MimeMessage
0419:                                && ((MimeMessage) msgs[i]).getContentType()
0420:                                        .toUpperCase().startsWith("MULTIPART/")) {
0421:                            xml_message.setAttribute("attachment", "true");
0422:                        }
0423:
0424:                        if (msgs[i] instanceof  MimeMessage) {
0425:                            int size = ((MimeMessage) msgs[i]).getSize();
0426:                            size /= 1024;
0427:                            xml_message.setAttribute("size", (size > 0 ? size
0428:                                    + "" : "<1")
0429:                                    + " kB");
0430:                        }
0431:
0432:                        /* Subject */
0433:                        subject = "";
0434:                        if (msgs[i].getSubject() != null) {
0435:                            try {
0436:                                subject = MimeUtility.decodeText(msgs[i]
0437:                                        .getSubject());
0438:                            } catch (UnsupportedEncodingException ex) {
0439:                                parent.getStorage().log(
0440:                                        Storage.LOG_WARN,
0441:                                        "Unsupported Encoding: "
0442:                                                + ex.getMessage());
0443:                            }
0444:                        }
0445:                        if (subject == null || subject.equals("")) {
0446:                            subject = getStringResource("no subject");
0447:                        }
0448:
0449:                        /* Set all of what we found into the DOM */
0450:                        xml_message.setHeader("FROM", from);
0451:                        try {
0452:                            // Modified by exce, start.
0453:                            // hmm, why decode subject twice? Though it doesn't matter..
0454:                            // Modified by exce, end.
0455:                            xml_message.setHeader("SUBJECT", MimeUtility
0456:                                    .decodeText(subject));
0457:                        } catch (UnsupportedEncodingException e) {
0458:                            parent.getStorage().log(Storage.LOG_WARN,
0459:                                    "Unsupported Encoding: " + e.getMessage());
0460:                        }
0461:                        xml_message.setHeader("TO", to);
0462:                        xml_message.setHeader("CC", cc);
0463:                        xml_message.setHeader("BCC", bcc);
0464:                        xml_message.setHeader("REPLY-TO", replyto);
0465:
0466:                        /* Date */
0467:                        Date d = msgs[i].getSentDate();
0468:                        String ds = "";
0469:                        if (d != null) {
0470:                            ds = df.format(d);
0471:                        }
0472:                        xml_message.setHeader("DATE", ds);
0473:                    }
0474:                    long time_stop = System.currentTimeMillis();
0475:                    // try {
0476:                    // XMLCommon.writeXML(model.getRoot(),new FileOutputStream("/tmp/wmdebug"),"");
0477:                    // } catch(IOException ex) {}
0478:
0479:                    parent.getStorage().log(
0480:                            Storage.LOG_DEBUG,
0481:                            "Construction of message list took "
0482:                                    + (time_stop - time_start)
0483:                                    + " ms. Time for IMAP transfer was "
0484:                                    + (fetch_stop - fetch_start) + " ms.");
0485:                    folder.close(false);
0486:                } catch (NullPointerException e) {
0487:                    e.printStackTrace();
0488:                    throw new NoSuchFolderException(folderhash);
0489:                } catch (MessagingException ex) {
0490:                    ex.printStackTrace();
0491:                }
0492:            }
0493:
0494:            /**
0495:             * This indicates standard getMessage behaviour: Fetch the message from the IMAP server and store it in the 
0496:             * current UserModel.
0497:             * @see getMessage(String,int,int)
0498:             */
0499:            public static final int GETMESSAGE_MODE_STANDARD = 0;
0500:
0501:            /** 
0502:             * Set this mode in getMessage to indicate that the message is requested to generate a reply message and 
0503:             * should therefore be set as the current "work" message.
0504:             * @see getMessage(String,int,int)
0505:             */
0506:            public static final int GETMESSAGE_MODE_REPLY = 1;
0507:
0508:            /**
0509:             * Set this mode in getMessage to indicate that the message is to be forwarded to someone else and a "work"
0510:             * message should be generated.
0511:             * @see getMessage(String,int,int)
0512:             */
0513:            public static final int GETMESSAGE_MODE_FORWARD = 2;
0514:
0515:            /**
0516:             * This is a wrapper to call getMessage with standard mode.
0517:             * @see getMessage(String,int,int)
0518:             */
0519:            public void getMessage(String folderhash, int msgnum)
0520:                    throws NoSuchFolderException {
0521:                getMessage(folderhash, msgnum, GETMESSAGE_MODE_STANDARD);
0522:            }
0523:
0524:            /**
0525:             * Fetch a message from a folder.
0526:             * Will put the messages parameters in the sessions environment
0527:             *
0528:             * @param foldername Name of the folder were the message should be fetched from
0529:             * @param msgnum Number of the message to fetch
0530:             * @param mode there are three different modes: standard, reply and forward. reply and forward will enter the message
0531:             *             into the current work element of the user and set some additional flags on the message if the user
0532:             *             has enabled this option.
0533:             * @see net.wastl.webmail.server.WebMailSession.GETMESSAGE_MODE_STANDARD
0534:             * @see net.wastl.webmail.server.WebMailSession.GETMESSAGE_MODE_REPLY
0535:             * @see net.wastl.webmail.server.WebMailSession.GETMESSAGE_MODE_FORWARD
0536:             */
0537:            public void getMessage(String folderhash, int msgnum, int mode)
0538:                    throws NoSuchFolderException {
0539:                // security reasons:
0540:                // attachments=null;
0541:
0542:                try {
0543:                    TimeZone tz = TimeZone.getDefault();
0544:                    DateFormat df = DateFormat.getDateTimeInstance(
0545:                            DateFormat.DEFAULT, DateFormat.SHORT, user
0546:                                    .getPreferredLocale());
0547:                    df.setTimeZone(tz);
0548:                    Folder folder = getFolder(folderhash);
0549:                    Element xml_folder = model.getFolder(folderhash);
0550:
0551:                    if (folder == null) {
0552:                        throw new NoSuchFolderException("No such folder: "
0553:                                + folderhash);
0554:                    }
0555:
0556:                    if (folder.isOpen()
0557:                            && folder.getMode() == Folder.READ_WRITE) {
0558:                        folder.close(false);
0559:                        folder.open(Folder.READ_ONLY);
0560:                    } else if (!folder.isOpen()) {
0561:                        folder.open(Folder.READ_ONLY);
0562:                    }
0563:
0564:                    MimeMessage m = (MimeMessage) folder.getMessage(msgnum);
0565:
0566:                    String messageid;
0567:                    try {
0568:                        StringTokenizer tok = new StringTokenizer(m
0569:                                .getMessageID(), "<>");
0570:                        messageid = tok.nextToken();
0571:                    } catch (NullPointerException ex) {
0572:                        // For mail servers that don't generate a Message-ID (Outlook et al)
0573:                        messageid = user.getLogin() + "." + msgnum
0574:                                + ".jwebmail@" + user.getDomain();
0575:                    }
0576:
0577:                    Element xml_current = model.setCurrentMessage(messageid);
0578:                    XMLMessage xml_message = model.getMessage(xml_folder, m
0579:                            .getMessageNumber()
0580:                            + "", messageid);
0581:
0582:                    /* Check whether we already cached this message (not only headers but complete)*/
0583:                    boolean cached = xml_message.messageCompletelyCached();
0584:                    /* If we cached the message, we don't need to fetch it again */
0585:                    if (!cached) {
0586:                        //Element xml_header=model.getHeader(xml_message);
0587:
0588:                        try {
0589:                            String from = MimeUtility.decodeText(Helper
0590:                                    .joinAddress(m.getFrom()));
0591:                            String replyto = MimeUtility.decodeText(Helper
0592:                                    .joinAddress(m.getReplyTo()));
0593:                            String to = MimeUtility
0594:                                    .decodeText(Helper
0595:                                            .joinAddress(m
0596:                                                    .getRecipients(Message.RecipientType.TO)));
0597:                            String cc = MimeUtility
0598:                                    .decodeText(Helper
0599:                                            .joinAddress(m
0600:                                                    .getRecipients(Message.RecipientType.CC)));
0601:                            String bcc = MimeUtility
0602:                                    .decodeText(Helper
0603:                                            .joinAddress(m
0604:                                                    .getRecipients(Message.RecipientType.BCC)));
0605:                            Date date_orig = m.getSentDate();
0606:                            String date = getStringResource("no date");
0607:                            if (date_orig != null) {
0608:                                date = df.format(date_orig);
0609:                            }
0610:                            String subject = "";
0611:                            if (m.getSubject() != null) {
0612:                                subject = MimeUtility
0613:                                        .decodeText(m.getSubject());
0614:                            }
0615:                            if (subject == null || subject.equals("")) {
0616:                                subject = getStringResource("no subject");
0617:                            }
0618:
0619:                            try {
0620:                                Flags.Flag[] sf = m.getFlags().getSystemFlags();
0621:                                for (int j = 0; j < sf.length; j++) {
0622:                                    if (sf[j] == Flags.Flag.RECENT)
0623:                                        xml_message.setAttribute("recent",
0624:                                                "true");
0625:                                    if (sf[j] == Flags.Flag.SEEN)
0626:                                        xml_message
0627:                                                .setAttribute("seen", "true");
0628:                                    if (sf[j] == Flags.Flag.DELETED)
0629:                                        xml_message.setAttribute("deleted",
0630:                                                "true");
0631:                                    if (sf[j] == Flags.Flag.ANSWERED)
0632:                                        xml_message.setAttribute("answered",
0633:                                                "true");
0634:                                    if (sf[j] == Flags.Flag.DRAFT)
0635:                                        xml_message.setAttribute("draft",
0636:                                                "true");
0637:                                    if (sf[j] == Flags.Flag.FLAGGED)
0638:                                        xml_message.setAttribute("flagged",
0639:                                                "true");
0640:                                    if (sf[j] == Flags.Flag.USER)
0641:                                        xml_message
0642:                                                .setAttribute("user", "true");
0643:                                }
0644:                            } catch (NullPointerException ex) {
0645:                            }
0646:                            if (m.getContentType().toUpperCase().startsWith(
0647:                                    "MULTIPART/")) {
0648:                                xml_message.setAttribute("attachment", "true");
0649:                            }
0650:
0651:                            int size = m.getSize();
0652:                            size /= 1024;
0653:                            xml_message.setAttribute("size", (size > 0 ? size
0654:                                    + "" : "<1")
0655:                                    + " kB");
0656:
0657:                            /* Set all of what we found into the DOM */
0658:                            xml_message.setHeader("FROM", from);
0659:                            xml_message.setHeader("SUBJECT", Fancyfier
0660:                                    .apply(subject));
0661:                            xml_message.setHeader("TO", to);
0662:                            xml_message.setHeader("CC", cc);
0663:                            xml_message.setHeader("BCC", bcc);
0664:                            xml_message.setHeader("REPLY-TO", replyto);
0665:                            xml_message.setHeader("DATE", date);
0666:
0667:                            /* Decode MIME contents recursively */
0668:                            xml_message.removeAllParts();
0669:                            parseMIMEContent(m, xml_message, messageid);
0670:
0671:                        } catch (UnsupportedEncodingException e) {
0672:                            parent.getStorage().log(
0673:                                    Storage.LOG_WARN,
0674:                                    "Unsupported Encoding in parseMIMEContent: "
0675:                                            + e.getMessage());
0676:                            System.err
0677:                                    .println("Unsupported Encoding in parseMIMEContent: "
0678:                                            + e.getMessage());
0679:                        }
0680:                    }
0681:                    /* Set seen flag (Maybe make that threaded to improve performance) */
0682:                    if (user.wantsSetFlags()) {
0683:                        if (folder.isOpen()
0684:                                && folder.getMode() == Folder.READ_ONLY) {
0685:                            folder.close(false);
0686:                            folder.open(Folder.READ_WRITE);
0687:                        } else if (!folder.isOpen()) {
0688:                            folder.open(Folder.READ_WRITE);
0689:                        }
0690:                        folder.setFlags(msgnum, msgnum, new Flags(
0691:                                Flags.Flag.SEEN), true);
0692:                        folder.setFlags(msgnum, msgnum, new Flags(
0693:                                Flags.Flag.RECENT), false);
0694:                        if ((mode & GETMESSAGE_MODE_REPLY) == GETMESSAGE_MODE_REPLY) {
0695:                            folder.setFlags(msgnum, msgnum, new Flags(
0696:                                    Flags.Flag.ANSWERED), true);
0697:                        }
0698:                    }
0699:                    folder.close(false);
0700:
0701:                    /* In this part we determine whether the message was requested so that it may be used for
0702:                       further editing (replying or forwarding). In this case we set the current "work" message to the
0703:                       message we just fetched and then modifiy it a little (quote, add a "Re" to the subject, etc). */
0704:                    XMLMessage work = null;
0705:                    if ((mode & GETMESSAGE_MODE_REPLY) == GETMESSAGE_MODE_REPLY
0706:                            || (mode & GETMESSAGE_MODE_FORWARD) == GETMESSAGE_MODE_FORWARD) {
0707:                        //System.err.println("Setting work message!");
0708:                        work = model.setWorkMessage(xml_message);
0709:
0710:                        String newmsgid = WebMailServer.generateMessageID(user
0711:                                .getUserName());
0712:
0713:                        if (work != null
0714:                                && (mode & GETMESSAGE_MODE_REPLY) == GETMESSAGE_MODE_REPLY) {
0715:                            String from = work.getHeader("FROM");
0716:                            work.setHeader("FROM", user.getEmail());
0717:                            work.setHeader("TO", from);
0718:                            work.prepareReply(
0719:                                    getStringResource("reply subject prefix"),
0720:                                    getStringResource("reply subject postfix"),
0721:                                    getStringResource("reply message prefix"),
0722:                                    getStringResource("reply message postfix"));
0723:
0724:                        } else if (work != null
0725:                                && (mode & GETMESSAGE_MODE_FORWARD) == GETMESSAGE_MODE_FORWARD) {
0726:                            String from = work.getHeader("FROM");
0727:                            work.setHeader("FROM", user.getEmail());
0728:                            work.setHeader("TO", "");
0729:                            work.setHeader("CC", "");
0730:                            work
0731:                                    .prepareForward(
0732:                                            getStringResource("forward subject prefix"),
0733:                                            getStringResource("forward subject postfix"),
0734:                                            getStringResource("forward message prefix"),
0735:                                            getStringResource("forward message postfix"));
0736:
0737:                            /* Copy all references to MIME parts to the new message id */
0738:                            Enumeration attids = getMimeParts(work
0739:                                    .getAttribute("msgid"));
0740:                            while (attids.hasMoreElements()) {
0741:                                String key = (String) attids.nextElement();
0742:                                StringTokenizer tok2 = new StringTokenizer(key,
0743:                                        "/");
0744:                                tok2.nextToken();
0745:                                String newkey = tok2.nextToken();
0746:                                mime_parts_decoded.put(newmsgid + "/" + newkey,
0747:                                        mime_parts_decoded.get(key));
0748:                            }
0749:                        }
0750:
0751:                        /* Clear the msgnr and msgid fields at last */
0752:                        work.setAttribute("msgnr", "0");
0753:                        work.setAttribute("msgid", newmsgid);
0754:                        prepareCompose();
0755:                    }
0756:                } catch (MessagingException ex) {
0757:                    ex.printStackTrace();
0758:                }
0759:            }
0760:
0761:            /**
0762:               Use depth-first search to go through MIME-Parts recursively.
0763:             
0764:               @param p Part to begin with
0765:             */
0766:            protected void parseMIMEContent(Part p, XMLMessagePart parent_part, String msgid) throws MessagingException {
0767:	StringBuffer content=new StringBuffer(1000);
0768:        XMLMessagePart xml_part;
0769:	try {
0770:	    if(p.getContentType().toUpperCase().startsWith("TEXT/HTML")) {
0771:		/* The part is a text in HTML format. We will try to use "Tidy" to create a well-formated
0772:		   XHTML DOM from it and then remove JavaScript and other "evil" stuff.
0773:		   For replying to such a message, it will be useful to just remove all of the tags and display
0774:		   only the text.
0775:		*/
0776:
0777:
0778:		xml_part=parent_part.createPart("html");
0779:
0780:		/* Here we create a DOM tree. */
0781:		//Tidy tidy=new Tidy();
0782:		//tidy.setUpperCaseTags(true);
0783:		//Document htmldoc=tidy.parseDOM(p.getInputStream(),null);
0784:		org.cyberneko.html.parsers.DOMParser parser = 
0785:		    new org.cyberneko.html.parsers.DOMParser();
0786:		parser.parse(new InputSource(p.getInputStream()));
0787:		Document htmldoc = parser.getDocument();
0788:
0789:		//XMLCommon.debugXML(htmldoc);
0790:
0791:		/* Now let's look for all the malicious JavaScript and other <SCRIPT> tags,
0792:		   URLS containing the "javascript:" and tags containing "onMouseOver" and such
0793:		   stuff. */
0794:		//		if(user.getBoolVar("filter javascript")) new JavaScriptCleaner(htmldoc);
0795:		new JavaScriptCleaner(htmldoc);
0796:
0797:		//XMLCommon.debugXML(htmldoc);
0798:		/* HTML doesn't allow us to do such fancy stuff like different quote colors,
0799:		   perhaps this will be implemented in the future */
0800:
0801:		/* So we just add this HTML document to the message part, which will deal with 
0802:		   removing headers and tags that we don't need */
0803:		xml_part.addContent(htmldoc);
0804:
0805:	    } else if(p.getContentType().toUpperCase().startsWith("TEXT") ||
0806:	       p.getContentType().toUpperCase().startsWith("MESSAGE")) {
0807:		/* The part is a standard message part in some incarnation of text (html or plain).
0808:		   We should decode it and take care of some extra issues like recognize quoted parts,
0809:		   filter JavaScript parts and replace smileys with smiley-icons if the user has
0810:		   set wantsFancy() */
0811:
0812:		xml_part=parent_part.createPart("text");
0813:		// TODO:
0814:		System.err.println("text hit");
0815:
0816:		BufferedReader in;
0817:		if(p instanceof  MimeBodyPart) {
0818:		    int size=p.getSize();
0819:		    MimeBodyPart mpb=(MimeBodyPart)p;
0820:		    InputStream is=mpb.getInputStream();
0821:					
0822:		    /* Workaround for Java or Javamail Bug */
0823:		    is=new BufferedInputStream(is);
0824:		    ByteStore ba=ByteStore.getBinaryFromIS(is,size);
0825:		    in=new BufferedReader(new InputStreamReader(new ByteArrayInputStream(ba.getBytes())));
0826:		    /* End of workaround */
0827:		    size=is.available();
0828:					
0829:		} else {
0830:		    in=new BufferedReader(new InputStreamReader(p.getInputStream()));
0831:		}
0832:		
0833:
0834:		//System.err.println("Content-Type: "+p.getContentType());
0835:
0836:
0837:		String token="";
0838:		int quote_level=0, old_quotelevel=0;
0839:		boolean javascript_mode=false;
0840:		/* Read in the message part line by line */
0841:		while((token=in.readLine()) != null) {
0842:		    /* First decode all language and MIME dependant stuff */
0843:		    // Default to ISO-8859-1 (Western Latin 1)
0844:		    String charset="ISO-8859-1";
0845:
0846:		    // Check whether the part contained a charset in the content-type header
0847:		    StringTokenizer tok2=new StringTokenizer(p.getContentType(),";=");
0848:		    String blah=tok2.nextToken();
0849:		    if(tok2.hasMoreTokens()) {
0850:			blah=tok2.nextToken().trim();
0851:			if(blah.toLowerCase().equals("charset") && tok2.hasMoreTokens()) {
0852:			    charset=tok2.nextToken().trim();
0853:			}
0854:		    }
0855:
0856:		    try {
0857:		      token=new String(token.getBytes(),charset);
0858:		    } catch(UnsupportedEncodingException ex1) {
0859:	              parent.getStorage().log(Storage.LOG_INFO,"Java Engine does not support charset "+charset+". Trying to convert from MIME ...");
0860:		      
0861:		      try {
0862:		      	charset=MimeUtility.javaCharset(charset);
0863:		        token=new String(token.getBytes(),charset);
0864:		
0865:                      } catch(UnsupportedEncodingException ex) {
0866:	              parent.getStorage().log(Storage.LOG_WARN,"Converted charset ("+charset+") does not work. Using default charset (ouput may contain errors)");
0867:		        token=new String(token.getBytes());
0868:		      }
0869:		    }
0870:		    
0871:		    /* Here we figure out which quote level this line has, simply by counting how many
0872:		       ">" are in front of the line, ignoring all whitespaces. */
0873:		    int current_quotelevel=Helper.getQuoteLevel(token);
0874:			
0875:
0876:		    /* When we are in a different quote level than the last line, we append all we got
0877:		       so far to the part with the old quotelevel and begin with a clean String buffer */
0878:		    if(current_quotelevel != old_quotelevel) {
0879:			xml_part.addContent(content.toString(),old_quotelevel);
0880:			old_quotelevel = current_quotelevel;
0881:			content=new StringBuffer(1000);
0882:		    }
0883:
0884:		    if(user.wantsBreakLines()) {
0885:			Enumeration enum=Helper.breakLine(token,user.getMaxLineLength(),current_quotelevel);
0886:			
0887:			while(enum.hasMoreElements()) {
0888:			    String s=(String)enum.nextElement();
0889:			    if(user.wantsShowFancy()) {
0890:				content.append(Fancyfier.apply(s)).append("\n");
0891:			    } else {
0892:				content.append(s).append("\n");
0893:			    }
0894:			}
0895:		    } else {
0896:			if(user.wantsShowFancy()) {
0897:			    content.append(Fancyfier.apply(token)).append("\n");
0898:			} else {
0899:			    content.append(token).append("\n");
0900:			}
0901:		    }			
0902:		}
0903:		xml_part.addContent(content.toString(),old_quotelevel);		
0904:		// Modified by exce, start
0905:		// Why the following code???
0906:		content=new StringBuffer(1000);
0907:		// Modified by exce, end.
0908:	    } else if(p.getContentType().toUpperCase().startsWith("MULTIPART/ALTERNATIVE")) {
0909:		/* This is a multipart/alternative part. That means that we should pick one of
0910:		   the formats and display it for this part. Our current precedence list is
0911:		   to choose HTML first and then to choose plain text. */
0912:		MimeMultipart m=(MimeMultipart)p.getContent();
0913:		String[] preferred={"TEXT/HTML","TEXT"};
0914:		boolean found=false;
0915:		int alt=0;
0916:		// Walk though our preferred list of encodings. If we have found a fitting part,
0917:		// decode it and replace it for the parent (this is what we really want with an 
0918:		// alternative!)
0919:		// Modified by exce, start
0920:		/**
0921:	    findalt: while(!found && alt < preferred.length) {
0922:		for(int i=0;i<m.getCount();i++) {
0923:		    Part p2=m.getBodyPart(i);
0924:		    if(p2.getContentType().toUpperCase().startsWith(preferred[alt])) {
0925:			parseMIMEContent(p2,parent_part,msgid);
0926:			found=true;
0927:			break findalt;
0928:		    }
0929:		}
0930:		alt++;
0931:	    }
0932:	    **/
0933:		/**
0934:		 * When user try to reply a mail, there may be 3 conditions:
0935:		 * 1. only TEXT exists.
0936:		 * 2. both HTML and TEXT exist.
0937:		 * 3. only HTML exists.
0938:		 *
0939:		 * We have to choose which part should we quote, that is, we must
0940:		 * decide the prority of parts to quote. Since quoting HTML is not
0941:		 * easy and precise (consider a html: <body><div><b>some text..</b>
0942:		 * </div></body>. Even we try to get text node under <body>, we'll
0943:		 * just get nothing, because "some text..." is marked up by
0944:		 * <div><b>. There is no easy way to retrieve text from html 
0945:		 * unless we parse the html to analyse its semantics.
0946:		 * 
0947:		 * Here is our policy for alternative part:
0948:		 * 1. Displays HTML but hides TEXT.
0949:		 * 2. When replying this mail, try to quote TEXT part. If no TEXT
0950:		 *    part exists, quote HTML in best effort(use 
0951:		 *    XMLMessagePart.quoteContent() by Sebastian Schaffert.)
0952:		 */
0953:		while (alt < preferred.length) {
0954:		    for(int i=0;i<m.getCount();i++) {
0955:			Part p2=m.getBodyPart(i);
0956:			if(p2.getContentType().toUpperCase().startsWith(preferred[alt])) {
0957:			    System.err.println("Processing: " + p2.getContentType());
0958:			    parseMIMEContent(p2,parent_part,msgid);
0959:			    found=true;
0960:			    break;
0961:			}
0962:		    }
0963:		    /**
0964:		     * If we've selected HTML part from alternative part, the TEXT
0965:		     * part should be hidden from display but keeping in XML for
0966:		     * later quoting operation.
0967:		     *
0968:		     * Of course, this requires some modification on showmessage.xsl.
0969:		     */
0970:		    if (found && (alt == 1)) {
0971:			Node textPartNode = parent_part.getPartElement().getLastChild();
0972:			NamedNodeMap attributes = textPartNode.getAttributes();
0973:			boolean hit = false;
0974:
0975:			for (int i = 0; i < attributes.getLength(); ++i) {
0976:			    Node attr = attributes.item(i);
0977:			    // If type=="TEXT", add a hidden attribute.
0978:			    if (attr.getNodeName().toUpperCase().equals("TYPE") && 
0979:				attr.getNodeValue().toUpperCase().equals("TEXT")) {
0980:				((Element)textPartNode).setAttribute("hidden", "true");
0981:			    }
0982:			}
0983:		    }
0984:		    alt++;
0985:		}
0986:		// Modified by exce, end
0987:		if(!found) {
0988:		    // If we didn't find one of our preferred encodings, choose the first one
0989:		    // simply pass the parent part because replacement is what we really want with
0990:		    // an alternative.
0991:		    parseMIMEContent(m.getBodyPart(0),parent_part,msgid);
0992:		}
0993:
0994:	    } else if(p.getContentType().toUpperCase().startsWith("MULTIPART/")) {
0995:		/* This is a standard multipart message. We should recursively walk thorugh all of 
0996:		   the parts and decode them, appending as children to the current part */
0997:
0998:		xml_part=parent_part.createPart("multi");
0999:
1000:		MimeMultipart m=(MimeMultipart)p.getContent();
1001:		for(int i=0;i<m.getCount();i++) {
1002:		    parseMIMEContent(m.getBodyPart(i),xml_part,msgid);
1003:		}
1004:	    } else {
1005:		/* Else treat the part as a binary part that the user should either download or
1006:		   get displayed immediately in case of an image */
1007:		InputStream in=null;
1008:		String type="";
1009:		if(p.getContentType().toUpperCase().startsWith("IMAGE/JPG") ||
1010:		   p.getContentType().toUpperCase().startsWith("IMAGE/JPEG")) {
1011:		    type="jpg";
1012:		    xml_part=parent_part.createPart("image");
1013:		} else if(p.getContentType().toUpperCase().startsWith("IMAGE/GIF")) {
1014:		    type="gif";
1015:		    xml_part=parent_part.createPart("image");
1016:		} else if(p.getContentType().toUpperCase().startsWith("IMAGE/PNG")) {
1017:		    type="png";
1018:		    xml_part=parent_part.createPart("image");
1019:		} else {
1020:		    xml_part=parent_part.createPart("binary");
1021:		}
1022:		int size=p.getSize();
1023:		if(p instanceof  MimeBodyPart) {
1024:		    MimeBodyPart mpb=(MimeBodyPart)p;
1025: 		    System.err.println("MIME Body part (image), Encoding: "+mpb.getEncoding());
1026:		    InputStream is=mpb.getInputStream();
1027:					
1028:		    /* Workaround for Java or Javamail Bug */
1029:		    in=new BufferedInputStream(is);
1030:		    ByteStore ba=ByteStore.getBinaryFromIS(in,size);
1031:		    in=new ByteArrayInputStream(ba.getBytes());
1032:		    /* End of workaround */
1033:		    size=in.available();
1034:					
1035:		} else {
1036:		    System.err.println("*** No MIME Body part!! ***");
1037:		    in=p.getInputStream();
1038:		}
1039:				
1040:		ByteStore data=ByteStore.getBinaryFromIS(in,size);
1041:		if(mime_parts_decoded==null) {
1042:		    mime_parts_decoded=new Hashtable();
1043:		}
1044:		String name=p.getFileName();
1045:		if(name == null || name.equals("")) {
1046:		    name="unknown."+type;
1047:		}
1048:		// Modified by exce, start
1049:		/**
1050:		 * As described in FileAttacher.java line #95 and
1051:		 * SendMessage.java line #390, we use MimeUtility.decodeText() to
1052:		 * decode attachment file name.
1053:		 */
1054:		try {
1055:			name = MimeUtility.decodeText(name);
1056:		} catch (Exception e) {
1057:			System.err.println(e);
1058:		}
1059:		// Modified by exce, end
1060:		// Eliminate space characters. Should do some more things in the future
1061:		name=name.replace(' ','_');
1062:		data.setContentType(p.getContentType());
1063:		data.setContentEncoding("BINARY");
1064:		mime_parts_decoded.put(msgid+"/"+name,data);
1065:
1066:		// Modified by exce, start
1067:		/**
1068:		 * For multibytes language system, we have to separate filename into 
1069:		 * 2 format: one for display (UTF-8 encoded), another for encode the
1070:		 * url of hyperlink.
1071:		 * `filename' is for display, while `hrefFileName' is for hyperlink. 
1072:		 * To make use of these two attributes, `showmessage.xsl' is slightly
1073:		 * modified.
1074:		 */
1075:		data.setName(name);
1076:		xml_part.setAttribute("filename",name);
1077:		// Transcode name into UTF-8 bytes then make a new ISO8859_1 string to encode URL.
1078:		xml_part.setAttribute("hrefFileName", URLEncoder.encode(new String(name.getBytes("UTF-8"), "ISO8859_1")));
1079:		// Modified by exce, end
1080:		xml_part.setAttribute("size",size+"");
1081:		String description=p.getDescription()==null?"":p.getDescription();
1082:		xml_part.setAttribute("description",description);
1083:		StringTokenizer tok=new StringTokenizer(p.getContentType(),";");
1084:		xml_part.setAttribute("content-type",tok.nextToken().toLowerCase());
1085:	    }
1086:	} catch(java.io.IOException ex) {
1087:	    ex.printStackTrace();
1088:	} catch(MessagingException ex) {
1089:	    throw ex;
1090:	} catch(Exception ex) {
1091:	    ex.printStackTrace();
1092:	}
1093:    }
1094:
1095:            public ByteStore getMIMEPart(String msgid, String name) {
1096:                if (mime_parts_decoded != null) {
1097:                    return (ByteStore) mime_parts_decoded.get(msgid + "/"
1098:                            + name);
1099:                } else {
1100:                    return null;
1101:                }
1102:            }
1103:
1104:            public Enumeration getMimeParts(String msgid) {
1105:	if(mime_parts_decoded == null) {
1106:	    mime_parts_decoded=new Hashtable();
1107:	}
1108:	Enumeration enum=mime_parts_decoded.keys();
1109:        Vector v=new Vector();
1110:	while(enum.hasMoreElements()) {
1111:	    String key=(String)enum.nextElement();
1112:	    if(key.startsWith(msgid)) {		
1113:		v.addElement(key);
1114:	    }
1115:	}
1116:	return v.elements();
1117:    }
1118:
1119:            public void clearWork() {
1120:                clearAttachments();
1121:                model.clearWork();
1122:            }
1123:
1124:            public void prepareCompose() {
1125:                model.getWorkMessage().getFirstMessageTextPart().addContent(
1126:                        "\n--\n", 0);
1127:                model.getWorkMessage().getFirstMessageTextPart().addContent(
1128:                        user.getSignature(), 0);
1129:            }
1130:
1131:            /**
1132:             * This method removes all of the attachments of the current "work" message
1133:             */
1134:            public void clearAttachments() {
1135:	attachments_size=0;
1136:	
1137:	XMLMessage xml_message=model.getWorkMessage();
1138:
1139:	String msgid=xml_message.getAttribute("msgid");
1140:
1141:	Enumeration enum=getMimeParts(msgid);
1142:	attachments_size=0;
1143:	while(enum.hasMoreElements()) {
1144:	    mime_parts_decoded.remove((String)enum.nextElement());
1145:	}
1146:    }
1147:
1148:            /**
1149:             * This method returns a table of attachments for the current "work" message
1150:             */
1151:            public Hashtable getAttachments() {
1152:	Hashtable hash=new Hashtable();
1153:	XMLMessage xml_message=model.getWorkMessage();
1154:
1155:	String msgid=xml_message.getAttribute("msgid");
1156:
1157:	Enumeration enum=getMimeParts(msgid);
1158:	while(enum.hasMoreElements()) {
1159:	    String key=(String)enum.nextElement();
1160:	    String filename=key.substring(msgid.length()+1);
1161:	    hash.put(filename,mime_parts_decoded.get(key));
1162:	}
1163:	
1164:	return hash;
1165:    }
1166:
1167:            /**
1168:             * This method returns the attachment with the given name of the current "work" message
1169:             */
1170:            public ByteStore getAttachment(String key) {
1171:                XMLMessage xml_message = model.getWorkMessage();
1172:                String msgid = xml_message.getAttribute("msgid");
1173:
1174:                return getMIMEPart(msgid, key);
1175:            }
1176:
1177:            /**
1178:             * Add an attachment to the current work message.
1179:             * @param name Name of the attachment (e.g. filename)
1180:             * @param bs The contents of the attachment, as a ByteStore object
1181:             * @param description A short description of the contents (will be used as the "Description:" header
1182:             */
1183:            public void addWorkAttachment(String name, ByteStore bs, String description) throws WebMailException {
1184:	XMLMessage xml_message=model.getWorkMessage();
1185:	XMLMessagePart xml_multipart=xml_message.getFirstMessageMultiPart();
1186:
1187:	String msgid=xml_message.getAttribute("msgid");
1188:
1189:	bs.setDescription(description);
1190:
1191:	Enumeration enum=getMimeParts(msgid);
1192:	attachments_size=0;
1193:	while(enum.hasMoreElements()) {
1194:	    ByteStore b=(ByteStore)mime_parts_decoded.get((String)enum.nextElement());
1195:	    attachments_size+=b.getSize();
1196:	}
1197:
1198:	int max_size=0;
1199:	try {
1200:	    max_size=Integer.parseInt( parent.getStorage().getConfig("MAX ATTACH SIZE"));
1201:	} catch(NumberFormatException e) {
1202:	    parent.getStorage().log(Storage.LOG_WARN,"Invalid setting for parameter \"MAX ATTACH SIZE\". Must be a number!");
1203:	}
1204:				
1205:	if(attachments_size+bs.getSize() > max_size) {
1206:	    throw new WebMailException("Attachments are too big. The sum of the sizes may not exceed "+max_size+" bytes.");
1207:	} else {
1208:	    mime_parts_decoded.put(msgid+"/"+name,bs);
1209:	    attachments_size+=bs.getSize();
1210:	    XMLMessagePart xml_part=xml_multipart.createPart("binary");
1211:	    
1212:	    xml_part.setAttribute("filename",name);
1213:	    xml_part.setAttribute("size",bs.getSize()+"");
1214:	    xml_part.setAttribute("description",description);
1215:	    xml_part.setAttribute("content-type",bs.getContentType().toLowerCase());
1216:	}
1217:	setEnv();
1218:	//XMLCommon.debugXML(model.getRoot());
1219:    }
1220:
1221:            /**
1222:             * Remove the attachment with the given name from the current work message.
1223:             */
1224:            public void removeWorkAttachment(String name) {
1225:	XMLMessage xml_message=model.getWorkMessage();
1226:	XMLMessagePart xml_multipart=xml_message.getFirstMessageMultiPart();
1227:
1228:	String msgid=xml_message.getAttribute("msgid");
1229:
1230:	mime_parts_decoded.remove(msgid+"/"+name);
1231:
1232:	Enumeration enum=getMimeParts(msgid);
1233:	attachments_size=0;
1234:	while(enum.hasMoreElements()) {
1235:	    ByteStore b=(ByteStore)mime_parts_decoded.get((String)enum.nextElement());
1236:	    attachments_size+=b.getSize();
1237:	}
1238:	
1239:	enum=xml_multipart.getParts();
1240:	XMLMessagePart oldpart=null;
1241:	while(enum.hasMoreElements()) {
1242:	    XMLMessagePart tmp=(XMLMessagePart)enum.nextElement();
1243:	    if(tmp.getAttribute("filename") != null &&
1244:	       tmp.getAttribute("filename").equals(name)) {
1245:		oldpart=tmp;
1246:		break;
1247:	    }
1248:	}
1249:	if(oldpart != null) {
1250:	    xml_multipart.removePart(oldpart);
1251:	}
1252:	setEnv();
1253:	//XMLCommon.debugXML(model.getRoot());
1254:    }
1255:
1256:            /**
1257:             * Store a message in the environment for further processing.
1258:             */
1259:            public void storeMessage(HTTPRequestHeader head) {
1260:	XMLMessage xml_message=model.getWorkMessage();
1261:	XMLMessagePart xml_textpart=xml_message.getFirstMessageTextPart();
1262:	
1263:	/* Store the already typed message if necessary/possible */
1264:	if(head.isContentSet("BODY")) {
1265:	    StringBuffer content=new StringBuffer();
1266:		// Modified by exce, start
1267:		/**
1268:		 * Because the data transfered through HTTP should be ISO8859_1,
1269:		 * HTTPRequestHeader is also ISO8859_1 encoded. Furthermore, the 
1270:		 * string we used in brwoser is UTF-8 encoded, hence we have to 
1271:		 * transcode the stored variables from ISO8859_1 to UTF-8 so that
1272:		 * the client browser displays correctly.
1273:		 */
1274:		String bodyString;
1275:		try {
1276:			bodyString = new String(head.getContent("BODY").getBytes("ISO8859_1"), "UTF-8");
1277:		} catch (UnsupportedEncodingException e) {
1278:			e.printStackTrace();
1279:			bodyString = head.getContent("BODY");
1280:		}
1281:		
1282:	    // If the user enabled "break line", then do it!
1283:	    if(user.wantsBreakLines()) {
1284:		// StringTokenizer tok=new StringTokenizer(head.getContent("BODY"),"\n");
1285:		StringTokenizer tok=new StringTokenizer(bodyString,"\n");
1286:		while(tok.hasMoreTokens()) {
1287:		    String line=tok.nextToken();		
1288:		    Enumeration enum=Helper.breakLine(line,user.getMaxLineLength(),
1289:						      Helper.getQuoteLevel(line));
1290:		    while(enum.hasMoreElements()) {	       
1291:			content.append((String)enum.nextElement()).append('\n');
1292:		    }
1293:		}
1294:	    } else {
1295:		// content.append(head.getContent("BODY"));
1296:		content.append(bodyString);
1297:		// Modified by exce, end
1298:	    }	
1299:	    xml_textpart.removeAllContent();
1300:	    xml_textpart.addContent(content.toString(),0);
1301:	}
1302:
1303:	if(head.isContentSet("TO")) {
1304:		// Modified by exce, start
1305:	    // xml_message.setHeader("TO",head.getContent("TO"));
1306:	    try {
1307:			xml_message.setHeader("TO", new String(head.getContent("TO").getBytes("ISO8859_1"), "UTF-8"));
1308:		} catch (UnsupportedEncodingException e) {
1309:			e.printStackTrace();
1310:			xml_message.setHeader("TO",head.getContent("TO"));
1311:		}
1312:		// Modified by exce, end
1313:	}
1314:	if(head.isContentSet("CC")) {
1315:		// Modified by exce, start
1316:	    // xml_message.setHeader("CC",head.getContent("CC"));
1317:	    try {
1318:			xml_message.setHeader("CC", new String(head.getContent("CC").getBytes("ISO8859_1"), "UTF-8"));
1319:		} catch (UnsupportedEncodingException e) {
1320:			e.printStackTrace();
1321:			xml_message.setHeader("CC",head.getContent("CC"));
1322:		}
1323:		// Modified by exce, end
1324:	}
1325:	if(head.isContentSet("BCC")) {
1326:		// Modified by exce, start
1327:	    // xml_message.setHeader("BCC",head.getContent("BCC"));
1328:	    try {
1329:			xml_message.setHeader("BCC", new String(head.getContent("BCC").getBytes("ISO8859_1"), "UTF-8"));
1330:		} catch (UnsupportedEncodingException e) {
1331:			e.printStackTrace();
1332:			xml_message.setHeader("BCC",head.getContent("BCC"));
1333:		}
1334:		// Modified by exce, end
1335:	}
1336:	if(head.isContentSet("REPLY-TO")) {
1337:		// Modified by exce, start
1338:	    // xml_message.setHeader("REPLY-TO",head.getContent("REPLY-TO"));
1339:	    try {
1340:			xml_message.setHeader("REPLY-TO", new String(head.getContent("REPLY-TO").getBytes("ISO8859_1"), "UTF-8"));
1341:		} catch (UnsupportedEncodingException e) {
1342:			e.printStackTrace();
1343:			xml_message.setHeader("REPLY-TO",head.getContent("REPLY-TO"));
1344:		}
1345:		// Modified by exce, end
1346:	}
1347:	if(head.isContentSet("SUBJECT")) {
1348:		// Modified by exce, start
1349:	    // xml_message.setHeader("SUBJECT",head.getContent("SUBJECT"));
1350:	    try {
1351:			xml_message.setHeader("SUBJECT", new String(head.getContent("SUBJECT").getBytes("ISO8859_1"), "UTF-8"));
1352:		} catch (UnsupportedEncodingException e) {
1353:			e.printStackTrace();
1354:			xml_message.setHeader("SUBJECT",head.getContent("SUBJECT"));
1355:		}
1356:		// Modified by exce, end
1357:	}
1358:	setEnv();
1359:    }
1360:            /**
1361:             * Connect to all Mailhosts
1362:             * @deprecated Should use refreshFolderInformation now.
1363:             */
1364:            public void connectAll() {
1365:                refreshFolderInformation();
1366:            }
1367:
1368:            /**
1369:               Get a childfolder of a rootfolder for a specified hash value
1370:             */
1371:            public Folder getChildFolder(Folder root, String folderhash) {
1372:                return getFolder(folderhash);
1373:            }
1374:
1375:            /**
1376:             * Get the folder with the given hashvalue.
1377:             * @returns Folder with the given hashvalue
1378:             */
1379:            public Folder getFolder(String folderhash) {
1380:                return (Folder) folders.get(folderhash);
1381:            }
1382:
1383:            /**
1384:             * This method tries to generate a unique folder identifier for the given folder.
1385:             * This method generates an MD5 sum over the complete folder URL, if possible.
1386:             * @see getFolderTree
1387:             * @see net.wastl.webmail.misc.MD5
1388:             */
1389:            protected String generateFolderHash(Folder folder) {
1390:                String id = Integer.toHexString(folder.hashCode());
1391:                // If possible, use the MD5-Sum for the folder ID because it is persistant over sessions
1392:                try {
1393:                    MD5 md5 = new MD5(folder.getURLName());
1394:                    id = md5.asHex();
1395:                } catch (MessagingException ex) {
1396:                }
1397:
1398:                return id;
1399:            }
1400:
1401:            /**
1402:             * Construct the folder subtree for the given folder and append it to xml_parent.
1403:             * 
1404:             * @param folder the folder where we begin
1405:             * @param xml_parent the XML Element where the gathered information will be appended
1406:             * @param subscribed_only Only list subscribed folders
1407:             * @returns maximum depth of the folder tree (needed to calculate the necessary columns in a table)
1408:             */
1409:            protected int getFolderTree(Folder folder, Element xml_parent,
1410:                    boolean subscribed_only) {
1411:                int depth = 1;
1412:
1413:                String id = generateFolderHash(folder);
1414:
1415:                boolean holds_folders = false, holds_messages = false;
1416:                Element xml_folder;
1417:                try {
1418:                    holds_folders = (folder.getType() & Folder.HOLDS_FOLDERS) == Folder.HOLDS_FOLDERS;
1419:                    holds_messages = (folder.getType() & Folder.HOLDS_MESSAGES) == Folder.HOLDS_MESSAGES;
1420:                    xml_folder = model.createFolder(id, folder.getName(),
1421:                            holds_folders, holds_messages);
1422:                    if (folder.isSubscribed()) {
1423:                        xml_folder.setAttribute("subscribed", "true");
1424:                    } else {
1425:                        xml_folder.setAttribute("subscribed", "false");
1426:                    }
1427:                } catch (MessagingException ex) {
1428:                    xml_folder = model.createFolder(id, folder.getName(),
1429:                            holds_folders, holds_messages);
1430:                    xml_folder.setAttribute("error", ex.getMessage());
1431:                }
1432:
1433:                folders.put(id, folder);
1434:
1435:                try {
1436:                    /* This folder can contain messages */
1437:                    if (holds_messages) {
1438:
1439:                        Element messagelist = model.createMessageList();
1440:
1441:                        int total_messages = folder.getMessageCount();
1442:                        int new_messages = folder.getNewMessageCount();
1443:
1444:                        if ((total_messages == -1 || new_messages == -1)
1445:                                || !folder.isOpen()) {
1446:                            folder.open(Folder.READ_ONLY);
1447:                            total_messages = folder.getMessageCount();
1448:                            new_messages = folder.getNewMessageCount();
1449:                        }
1450:                        folder.close(false);
1451:
1452:                        messagelist.setAttribute("total", total_messages + "");
1453:                        messagelist.setAttribute("new", new_messages + "");
1454:                        xml_folder.appendChild(messagelist);
1455:                    }
1456:                } catch (MessagingException ex) {
1457:                    xml_folder.setAttribute("error", ex.getMessage());
1458:                }
1459:
1460:                try {
1461:                    /* There are subfolders, get them! */
1462:                    if (holds_folders) {
1463:                        Folder[] subfolders;
1464:
1465:                        /* If the user only wanted to see subscribed folders, call listSubscribed 
1466:                           otherwise call list() */
1467:                        if (subscribed_only) {
1468:                            try {
1469:                                subfolders = folder.listSubscribed();
1470:                            } catch (MessagingException ex) {
1471:                                System.err.println("Subscribe not supported");
1472:                                subfolders = folder.list();
1473:                            }
1474:                        } else {
1475:                            subfolders = folder.list();
1476:                        }
1477:                        int max_tree_depth = 0;
1478:
1479:                        /* Recursiveley add subfolders to the XML model */
1480:                        for (int i = 0; i < subfolders.length; i++) {
1481:                            int tree_depth = getFolderTree(subfolders[i],
1482:                                    xml_folder, subscribed_only);
1483:                            if (tree_depth > max_tree_depth) {
1484:                                max_tree_depth = tree_depth;
1485:                            }
1486:                        }
1487:                        depth += max_tree_depth;
1488:                    }
1489:                } catch (MessagingException ex) {
1490:                    xml_folder.setAttribute("error", ex.getMessage());
1491:                }
1492:
1493:                xml_parent.appendChild(xml_folder);
1494:                return depth;
1495:            }
1496:
1497:            public void refreshFolderInformation() {
1498:                refreshFolderInformation(false);
1499:            }
1500:
1501:            /**
1502:             * Refresh Information about folders.
1503:             * Tries to connect folders that are not yet connected.
1504:             */
1505:            public void refreshFolderInformation(boolean subscribed_only) {
1506:                setEnv();
1507:                if (folders == null)
1508:                    folders = new Hashtable();
1509:                Folder cur_folder = null;
1510:                String cur_mh_id = "";
1511:                Enumeration mailhosts = user.mailHosts();
1512:                int max_depth = 0;
1513:                while (mailhosts.hasMoreElements()) {
1514:                    cur_mh_id = (String) mailhosts.nextElement();
1515:
1516:                    MailHostData mhd = user.getMailHost(cur_mh_id);
1517:
1518:                    URLName url = new URLName(mhd.getHostURL());
1519:
1520:                    Element mailhost = model.createMailhost(mhd.getName(), mhd
1521:                            .getID(), url.toString());
1522:
1523:                    int depth = 0;
1524:
1525:                    try {
1526:
1527:                        cur_folder = getRootFolder(cur_mh_id);
1528:
1529:                        /* Cannot unsubscribe root folder! */
1530:                        try {
1531:                            cur_folder.setSubscribed(true);
1532:                        } catch (MessagingException ex) {
1533:                            // Only IMAP supports subscription
1534:                        }
1535:
1536:                        /* Here we try to determine the remote IMAP or POP host. There is no problem if this fails
1537:                           (it will most likely for POP3), so the exception is caught and not handled */
1538:                        try {
1539:                            // Washington University
1540:                            if (cur_folder.getFolder(
1541:                                    "~" + mhd.getLogin() + "/mail").exists()) {
1542:                                /* Washington University stores user mailboxes as
1543:                                 * ~user/mail/... */
1544:                                depth = getFolderTree(cur_folder
1545:                                        .getFolder("INBOX"), mailhost,
1546:                                        subscribed_only);
1547:                                if (depth > max_depth) {
1548:                                    max_depth = depth;
1549:                                }
1550:                                depth = getFolderTree(cur_folder.getFolder("~"
1551:                                        + mhd.getLogin() + "/mail"), mailhost,
1552:                                        subscribed_only);
1553:                            }
1554:                            /* Cyrus, Courier & Co have their folders beneath the INBOX */
1555:                            else if (cur_folder.getFolder("INBOX").exists()) {
1556:                                depth = getFolderTree(cur_folder
1557:                                        .getFolder("INBOX"), mailhost,
1558:                                        subscribed_only);
1559:                            }
1560:                        } /* If it didn't work it failed in the "if" statement, since "getFolderTree" doesn't throw exceptions
1561:                        	     so what we want to do is to simply construct the folder tree for INBOX */
1562:                        catch (MessagingException ex) {
1563:                            depth = getFolderTree(
1564:                                    cur_folder.getFolder("INBOX"), mailhost,
1565:                                    subscribed_only);
1566:                        }
1567:                    }
1568:                    // Here a more serious exception has been caught (Connection failed)
1569:                    catch (MessagingException ex) {
1570:                        mailhost.setAttribute("error", ex.getMessage());
1571:                        parent.getStorage().log(
1572:                                Storage.LOG_WARN,
1573:                                "Error connecting to mailhost ("
1574:                                        + url.toString() + "): "
1575:                                        + ex.getMessage());
1576:                    }
1577:
1578:                    if (depth > max_depth) {
1579:                        max_depth = depth;
1580:                    }
1581:
1582:                    model.addMailhost(mailhost);
1583:
1584:                }
1585:
1586:                model.setStateVar("max folder depth", (1 + max_depth) + "");
1587:            }
1588:
1589:            public void refreshFolderInformation(String folderhash) {
1590:                Folder folder = getFolder(folderhash);
1591:                Element xml_folder = model.getFolder(folderhash);
1592:
1593:                if (xml_folder.getAttribute("holds_messages").toLowerCase()
1594:                        .equals("true")) {
1595:                    try {
1596:                        Element messagelist = model.createMessageList();
1597:
1598:                        int total_messages = folder.getMessageCount();
1599:                        int new_messages = folder.getNewMessageCount();
1600:
1601:                        if ((total_messages == -1 || new_messages == -1)
1602:                                && !folder.isOpen()) {
1603:                            folder.open(Folder.READ_ONLY);
1604:                            total_messages = folder.getMessageCount();
1605:                            new_messages = folder.getNewMessageCount();
1606:                        }
1607:                        if (folder.isOpen())
1608:                            folder.close(false);
1609:
1610:                        messagelist.setAttribute("total", total_messages + "");
1611:                        messagelist.setAttribute("new", new_messages + "");
1612:
1613:                        model.removeMessageList(xml_folder);
1614:                        xml_folder.appendChild(messagelist);
1615:
1616:                    } catch (MessagingException ex) {
1617:                        xml_folder.setAttribute("error", ex.getMessage());
1618:                    }
1619:                }
1620:
1621:            }
1622:
1623:            /**
1624:             * Try to subscribe to a folder (i.e. unhide it)
1625:             */
1626:            public void subscribeFolder(String folderhash) {
1627:                Folder folder = getFolder(folderhash);
1628:
1629:                // Only IMAP supports subscription...
1630:                try {
1631:                    folder.setSubscribed(true);
1632:                } catch (MessagingException ex) {
1633:                    //System.err.println("Folder subscription not supported");
1634:                }
1635:            }
1636:
1637:            /**
1638:             * Try to unsubscribe from a folder (i.e. hide it)
1639:             */
1640:            public void unsubscribeFolder(String folderhash) {
1641:                Folder folder = getFolder(folderhash);
1642:
1643:                // Only IMAP supports subscription...
1644:                try {
1645:                    folder.setSubscribed(false);
1646:                } catch (MessagingException ex) {
1647:                    //System.err.println("Folder subscription not supported");
1648:                }
1649:            }
1650:
1651:            /**
1652:             * Subscribe all folders for a Mailhost 
1653:             * Do it the non-recursive way: Uses a simple Queue :-)
1654:             */
1655:            public void setSubscribedAll(String id, boolean subscribed)
1656:                    throws MessagingException {
1657:                Folder folder = getRootFolder(id);
1658:                Queue q = new Queue();
1659:                q.queue(folder);
1660:                // Only IMAP supports subscription...
1661:                try {
1662:                    while (!q.isEmpty()) {
1663:                        folder = (Folder) q.next();
1664:
1665:                        folder.setSubscribed(subscribed);
1666:                        Folder[] list = folder.list();
1667:                        for (int i = 0; i < list.length; i++) {
1668:                            q.queue(list[i]);
1669:                        }
1670:                    }
1671:                } catch (MessagingException ex) {
1672:                }
1673:            }
1674:
1675:            /**
1676:               Disconnect from all Mailhosts
1677:             */
1678:            public void disconnectAll() {
1679:                Enumeration e = user.mailHosts();
1680:                while (e.hasMoreElements()) {
1681:                    String name = (String) e.nextElement();
1682:                    disconnect(name);
1683:                }
1684:                e = stores.keys();
1685:                while (e.hasMoreElements()) {
1686:                    String name = (String) e.nextElement();
1687:                    Store st = (Store) stores.get(name);
1688:                    try {
1689:                        st.close();
1690:                        parent.getStorage().log(
1691:                                Storage.LOG_INFO,
1692:                                "Mail: Connection to " + st.toString()
1693:                                        + " closed.");
1694:                    } catch (Exception ex) {
1695:                        parent.getStorage().log(
1696:                                Storage.LOG_WARN,
1697:                                "Mail: Failed to close connection to "
1698:                                        + st.toString() + ". Reason: "
1699:                                        + ex.getMessage());
1700:                    }
1701:                    stores.remove(name);
1702:                }
1703:                folders = null;
1704:            }
1705:
1706:            public Folder getRootFolder(String name) throws MessagingException {
1707:                if (connections != null && connections.containsKey(name)) {
1708:                    return (Folder) connections.get(name);
1709:                } else {
1710:                    return connect(name);
1711:                }
1712:            }
1713:
1714:            protected Store connectStore(String host, String protocol,
1715:                    String login, String password) throws MessagingException {
1716:                /* Check whether the domain of this user allows to connect to the host */
1717:                WebMailVirtualDomain vdom = parent.getStorage()
1718:                        .getVirtualDomain(user.getDomain());
1719:                if (!vdom.isAllowedHost(host)) {
1720:                    throw new MessagingException(
1721:                            "You are not allowed to connect to this host");
1722:                }
1723:
1724:                /* Check if this host is already connected. Use connection if true, create a new one if false. */
1725:                Store st = (Store) stores.get(host + "-" + protocol);
1726:                if (st == null) {
1727:                    st = mailsession.getStore(protocol);
1728:                    stores.put(host + "-" + protocol, st);
1729:                }
1730:
1731:                /* Maybe this is a new store or this store has been disconnected. Reconnect if this is the case. */
1732:                if (!st.isConnected()) {
1733:                    try {
1734:                        st.connect(host, login, password);
1735:                        parent.getStorage().log(Storage.LOG_INFO,
1736:                                "Mail: Connection to " + st.toString() + ".");
1737:                    } catch (AuthenticationFailedException ex) {
1738:                        /* If login fails, try the login_password */
1739:                        if (!login_password.equals(password)
1740:                                && parent.getStorage().getConfig(
1741:                                        "FOLDER TRY LOGIN PASSWORD")
1742:                                        .toUpperCase().equals("YES")) {
1743:                            st.connect(host, login, login_password);
1744:                            parent
1745:                                    .getStorage()
1746:                                    .log(
1747:                                            Storage.LOG_INFO,
1748:                                            "Mail: Connection to "
1749:                                                    + st.toString()
1750:                                                    + ", second attempt with login password succeeded.");
1751:                        } else {
1752:                            throw ex;
1753:                        }
1754:                    }
1755:                }
1756:                return st;
1757:            }
1758:
1759:            /**
1760:               Connect to mailhost "name"
1761:             */
1762:            public Folder connect(String name) throws MessagingException {
1763:                MailHostData m = user.getMailHost(name);
1764:                URLName url = new URLName(m.getHostURL());
1765:
1766:                Store st = connectStore(url.getHost(), url.getProtocol(), m
1767:                        .getLogin(), m.getPassword());
1768:
1769:                //System.err.println("Default folder: "+st.getDefaultFolder().toString());
1770:
1771:                Folder f = st.getDefaultFolder();
1772:                connections.put(name, f);
1773:                parent.getStorage().log(
1774:                        Storage.LOG_INFO,
1775:                        "Mail: Folder " + f.toString() + " opened at store "
1776:                                + st.toString() + ".");
1777:                return f;
1778:            }
1779:
1780:            /**
1781:               Disconnect from mailhost "name"
1782:             */
1783:            public void disconnect(String name) {
1784:                try {
1785:                    Folder f = (Folder) connections.get(name);
1786:                    if (f != null && f.isOpen()) {
1787:                        f.close(true);
1788:                        Store st = ((Folder) connections.get(name)).getStore();
1789:                        //st.close();
1790:                        parent.getStorage().log(
1791:                                Storage.LOG_INFO,
1792:                                "Mail: Disconnected from folder "
1793:                                        + f.toString() + " at store "
1794:                                        + st.toString() + ".");
1795:                    } else {
1796:                        parent.getStorage().log(Storage.LOG_WARN,
1797:                                "Mail: Folder " + name + " was null???.");
1798:                    }
1799:                } catch (MessagingException ex) {
1800:                    // Should not happen
1801:                    ex.printStackTrace();
1802:                } catch (NullPointerException ex) {
1803:                    // This happens when deleting a folder with an error
1804:                    ex.printStackTrace();
1805:                } finally {
1806:                    connections.remove(name);
1807:                }
1808:            }
1809:
1810:            /**
1811:             * Terminate this session.
1812:             *
1813:             * This will expunge deleted messages, close all mailbox connections, save the user data and then
1814:             * remove this session from the session list, effectively destroying this session.
1815:             */
1816:            public void logout() {
1817:                if (!is_logged_out) {
1818:                    is_logged_out = true;
1819:                    expungeFolders();
1820:                    disconnectAll();
1821:                    user.logout();
1822:                    saveData();
1823:                    parent.getStorage()
1824:                            .log(
1825:                                    Storage.LOG_INFO,
1826:                                    "WebMail: Session " + getSessionCode()
1827:                                            + " logout.");
1828:                    // Make sure the session is invalidated
1829:                    if (sess != null) {
1830:                        try {
1831:                            Class srvltreq = Class
1832:                                    .forName("javax.servlet.http.HttpSession");
1833:                            if (srvltreq.isInstance(sess)) {
1834:                                ((javax.servlet.http.HttpSession) sess)
1835:                                        .invalidate();
1836:                            }
1837:                        } catch (Throwable t) {
1838:                        }
1839:                    }
1840:                    if (parent.getSession(getSessionCode()) != null) {
1841:                        parent.removeSession(this );
1842:                    }
1843:                } else {
1844:                    System.err
1845:                            .println("WARNING: Session was already logged out. Ignoring logout request.");
1846:                }
1847:            }
1848:
1849:            /**
1850:             * Check whether this session is already logged out.
1851:             * Useful to avoid loops.
1852:             */
1853:            public boolean isLoggedOut() {
1854:                return is_logged_out;
1855:            }
1856:
1857:            /**
1858:             * Return the session id that was generated for this session.
1859:             */
1860:            public String getSessionCode() {
1861:                return session_code;
1862:            }
1863:
1864:            /**
1865:             * Return the last access time of this session
1866:             *
1867:             * @see TimeableConnection
1868:             */
1869:            public long getLastAccess() {
1870:                return last_access;
1871:            }
1872:
1873:            /**
1874:             * Update the last access time.
1875:             * Sets the last access time to the current time.
1876:             *
1877:             * @see TimeableConnection
1878:             */
1879:            public void setLastAccess() {
1880:                last_access = System.currentTimeMillis();
1881:                //System.err.println("Setting last access to session: "+last_access);
1882:            }
1883:
1884:            /**
1885:             * Handle a timeout for this session.
1886:             * This calls the logout method, effectively terminating this session.
1887:             *
1888:             * @see TimeableConnection
1889:             * @see logout()
1890:             */
1891:            public void timeoutOccured() {
1892:                parent.getStorage().log(Storage.LOG_WARN,
1893:                        "WebMail: Session " + getSessionCode() + " timeout.");
1894:                logout();
1895:            }
1896:
1897:            public long getTimeout() {
1898:                long i = 600000;
1899:                try {
1900:                    i = Long.parseLong(parent.getStorage().getConfig(
1901:                            "session timeout"));
1902:                } catch (NumberFormatException ex) {
1903:                    ex.printStackTrace();
1904:                }
1905:                return i;
1906:            }
1907:
1908:            public Locale getLocale() {
1909:                return user.getPreferredLocale();
1910:            }
1911:
1912:            public void saveData() {
1913:                parent.getStorage().saveUserData(user.getUserName(),
1914:                        user.getDomain());
1915:            }
1916:
1917:            protected static int[] getSelectedMessages(HTTPRequestHeader head,
1918:                    int max) {
1919:                //	System.err.print(" - select messages...");
1920:
1921:                Enumeration e = head.getContent().keys();
1922:                int _msgs[] = new int[max];
1923:                int j = 0;
1924:
1925:                while (e.hasMoreElements()) {
1926:                    String s = (String) e.nextElement();
1927:                    if (s.startsWith("CH") && head.getContent(s).equals("on")) {
1928:                        try {
1929:                            _msgs[j] = Integer.parseInt(s.substring(3));
1930:                            //    System.err.print(_msgs[j]+" ");
1931:                            j++;
1932:                        } catch (NumberFormatException ex) {
1933:                            ex.printStackTrace();
1934:                        }
1935:                    }
1936:                }
1937:                //System.err.println();
1938:
1939:                int msgs[] = new int[j];
1940:                for (int i = 0; i < j; i++) {
1941:                    msgs[i] = _msgs[i];
1942:                }
1943:                return msgs;
1944:            }
1945:
1946:            /** 
1947:             * Expunge all folders that have messages waiting to be deleted
1948:             */
1949:            public void expungeFolders() {
1950:	if(need_expunge_folders != null) {
1951:	    Enumeration enum=need_expunge_folders.elements();
1952:	    while(enum.hasMoreElements()) {
1953:		String hash=(String)enum.nextElement();
1954:		if(user.wantsSetFlags()) {
1955:		    Folder f=getFolder(hash);
1956:		    try {
1957:			if(f.isOpen()) {
1958:			    f.close(false);
1959:			}
1960:			f.open(Folder.READ_WRITE);
1961:			// POP3 doesn't support expunge!
1962:			try {
1963:			    f.expunge();
1964:			} catch(MessagingException ex) {}
1965:			f.close(true);
1966:		    } catch(MessagingException ex) {
1967:			// XXXX
1968:			ex.printStackTrace();
1969:		    }
1970:		}
1971:	    }
1972:	}
1973:    }
1974:
1975:            /**
1976:               Change the Flags of the messages the user selected.
1977:             
1978:             */
1979:            public void setFlags(String folderhash, HTTPRequestHeader head)
1980:                    throws MessagingException {
1981:
1982:                if (head.isContentSet("copymovemsgs")
1983:                        && head.getContent("COPYMOVE").equals("COPY")) {
1984:                    copyMoveMessage(folderhash, head.getContent("TO"), head,
1985:                            false);
1986:                } else if (head.isContentSet("copymovemsgs")
1987:                        && head.getContent("COPYMOVE").equals("MOVE")) {
1988:                    copyMoveMessage(folderhash, head.getContent("TO"), head,
1989:                            true);
1990:                } else if (head.isContentSet("flagmsgs")) {
1991:
1992:                    System.err.println("setting message flags");
1993:                    Folder folder = getFolder(folderhash);
1994:
1995:                    //System.err.println("Processing Request Header...");
1996:
1997:                    /* Get selected messages */
1998:                    int msgs[] = getSelectedMessages(head, folder
1999:                            .getMessageCount());
2000:
2001:                    //System.err.println(" - get flags...");
2002:
2003:                    /* Get selected flags */
2004:                    Flags fl = new Flags(Flags.Flag.USER);
2005:                    if (head.getContent("MESSAGE FLAG").equals("DELETED")) {
2006:                        fl = new Flags(Flags.Flag.DELETED);
2007:                        if (need_expunge_folders == null) {
2008:                            need_expunge_folders = new Vector();
2009:                        }
2010:                        need_expunge_folders.addElement(folderhash);
2011:                    } else if (head.getContent("MESSAGE FLAG").equals("SEEN")) {
2012:                        fl = new Flags(Flags.Flag.SEEN);
2013:                    } else if (head.getContent("MESSAGE FLAG").equals("RECENT")) {
2014:                        fl = new Flags(Flags.Flag.RECENT);
2015:                    } else if (head.getContent("MESSAGE FLAG").equals(
2016:                            "ANSWERED")) {
2017:                        fl = new Flags(Flags.Flag.ANSWERED);
2018:                    } else if (head.getContent("MESSAGE FLAG").equals("DRAFT")) {
2019:                        fl = new Flags(Flags.Flag.DRAFT);
2020:                    }
2021:
2022:                    boolean value = true;
2023:                    if (head.getContent("MARK").equals("UNMARK")) {
2024:                        value = false;
2025:                    }
2026:
2027:                    //System.err.println("Done!");
2028:                    //System.err.println("Setting flags...");
2029:
2030:                    if (user.wantsSetFlags()) {
2031:                        if (folder.isOpen()
2032:                                && folder.getMode() == Folder.READ_ONLY) {
2033:                            folder.close(false);
2034:                            folder.open(Folder.READ_WRITE);
2035:                        } else if (!folder.isOpen()) {
2036:                            folder.open(Folder.READ_WRITE);
2037:                        }
2038:                        folder.setFlags(msgs, fl, value);
2039:                        if (user.getBoolVar("autoexpunge")) {
2040:                            folder.close(true);
2041:                            if (need_expunge_folders != null) {
2042:                                need_expunge_folders.removeElement(folderhash);
2043:                            }
2044:                        } else {
2045:                            folder.close(false);
2046:                        }
2047:                    }
2048:
2049:                    refreshFolderInformation(folderhash);
2050:
2051:                }
2052:            }
2053:
2054:            /**
2055:             * Copy or move the selected messages from folder fromfolder to folder tofolder.
2056:             */
2057:            public void copyMoveMessage(String fromfolder, String tofolder,
2058:                    HTTPRequestHeader head, boolean move)
2059:                    throws MessagingException {
2060:                Folder from = getFolder(fromfolder);
2061:                Folder to = getFolder(tofolder);
2062:                if (user.wantsSetFlags()) {
2063:                    if (from.isOpen() && from.getMode() == Folder.READ_ONLY) {
2064:                        from.close(false);
2065:                        from.open(Folder.READ_WRITE);
2066:                    } else if (!from.isOpen()) {
2067:                        from.open(Folder.READ_WRITE);
2068:                    }
2069:                    if (to.isOpen() && to.getMode() == Folder.READ_ONLY) {
2070:                        to.close(false);
2071:                        to.open(Folder.READ_WRITE);
2072:                    } else if (!to.isOpen()) {
2073:                        to.open(Folder.READ_WRITE);
2074:                    }
2075:                } else {
2076:                    if (!from.isOpen()) {
2077:                        from.open(Folder.READ_ONLY);
2078:                    }
2079:                    if (to.isOpen() && to.getMode() == Folder.READ_ONLY) {
2080:                        to.close(false);
2081:                        to.open(Folder.READ_WRITE);
2082:                    } else if (!to.isOpen()) {
2083:                        to.open(Folder.READ_WRITE);
2084:                    }
2085:                }
2086:                int m[] = getSelectedMessages(head, from.getMessageCount());
2087:                Message msgs[] = from.getMessages(m);
2088:                from.copyMessages(msgs, to);
2089:                if (move && user.wantsSetFlags()) {
2090:                    from.setFlags(m, new Flags(Flags.Flag.DELETED), true);
2091:                    if (user.getBoolVar("autoexpunge")) {
2092:                        from.close(true);
2093:                        to.close(true);
2094:                    } else {
2095:                        if (need_expunge_folders == null) {
2096:                            need_expunge_folders = new Vector();
2097:                        }
2098:                        need_expunge_folders.addElement(fromfolder);
2099:                        from.close(false);
2100:                        to.close(false);
2101:                    }
2102:                } else {
2103:                    from.close(false);
2104:                    if (user.getBoolVar("autoexpunge")) {
2105:                        to.close(true);
2106:                    } else {
2107:                        to.close(false);
2108:                    }
2109:                }
2110:                refreshFolderInformation(fromfolder);
2111:                refreshFolderInformation(tofolder);
2112:            }
2113:
2114:            /**
2115:             * Change a user's configuration. 
2116:             * Header fields given in the requestheader are parsed and turned into user options (probably should not be in WebMailSession
2117:             * but in a plugin or something; this is very hacky).
2118:             */
2119:            public void changeSetup(HTTPRequestHeader head)
2120:                    throws WebMailException {
2121:
2122:                Enumeration contentkeys = head.getContentKeys();
2123:                user.resetBoolVars();
2124:                while (contentkeys.hasMoreElements()) {
2125:                    String key = ((String) contentkeys.nextElement())
2126:                            .toLowerCase();
2127:                    if (key.startsWith("intvar")) {
2128:                        try {
2129:                            long value = Long.parseLong(head.getContent(key));
2130:                            user.setIntVar(key.substring(7), value);
2131:                        } catch (NumberFormatException ex) {
2132:                            System.err
2133:                                    .println("Warning: Remote provided illegal intvar in request header: \n("
2134:                                            + key
2135:                                            + ","
2136:                                            + head.getContent(key)
2137:                                            + ")");
2138:                        }
2139:                    } else if (key.startsWith("boolvar")) {
2140:                        boolean value = head.getContent(key).toUpperCase()
2141:                                .equals("ON");
2142:                        user.setBoolVar(key.substring(8), value);
2143:                    }
2144:                }
2145:
2146:                // Modified by exce, start
2147:                /**
2148:                 * As described in line #1088, we have to transcode these strings. 
2149:                 * We only allow SIGNATURE and FULLNAME to contain locale-specific 
2150:                 * characters.
2151:                 */
2152:                // user.setSignature(head.getContent("SIGNATURE"));
2153:                // user.setFullName(head.getContent("FULLNAME"));
2154:                try {
2155:                    user.setSignature(new String(head.getContent("SIGNATURE")
2156:                            .getBytes("ISO8859_1"), "UTF-8"));
2157:                    user.setFullName(new String(head.getContent("FULLNAME")
2158:                            .getBytes("ISO8859_1"), "UTF-8"));
2159:                } catch (UnsupportedEncodingException e) {
2160:                    e.printStackTrace();
2161:                    user.setSignature(head.getContent("SIGNATURE"));
2162:                    user.setFullName(head.getContent("FULLNAME"));
2163:                }
2164:                // Modified by exce, end
2165:                user.setEmail(head.getContent("EMAIL"));
2166:                if (!head.getContent("PASSWORD").equals("")) {
2167:                    net.wastl.webmail.server.Authenticator auth = parent
2168:                            .getStorage().getAuthenticator();
2169:                    if (auth.canChangePassword()) {
2170:                        auth.changePassword(user, head.getContent("PASSWORD"),
2171:                                head.getContent("VERIFY"));
2172:                    } else {
2173:                        throw new InvalidDataException(
2174:                                getStringResource("EX NO CHANGE PASSWORD"));
2175:                    }
2176:                }
2177:                user.setPreferredLocale(head.getContent("LANGUAGE"));
2178:                user.setTheme(head.getContent("THEME"));
2179:                if (head.isContentSet("SENTFOLDER")) {
2180:                    System.err.println("SENTFOLDER="
2181:                            + head.getContent("SENTFOLDER"));
2182:                    user.setSentFolder(head.getContent("SENTFOLDER"));
2183:                }
2184:
2185:                // Not sure if this is really necessary:
2186:                //refreshFolderInformation(true);
2187:                setEnv();
2188:                model.update();
2189:            }
2190:
2191:            /**
2192:             * Add the mailbox with the given parameters to this user's configuration. Subscribe all folders on startup (the
2193:             * user can later unsubscribe them) and update the model.
2194:             *
2195:             * @param name Name for the mailbox (used for identification within the session)
2196:             * @param protocol The protocol used for this mailbox (most likely IMAP or POP3)
2197:             * @param host The hostname of the host this mailbox lives on
2198:             * @param login Login name the user provided for the host
2199:             * @param password Password the user provided to the given login
2200:             */
2201:            public void addMailbox(String name, String protocol, String host, String login, String password) 
2202:	throws MessagingException {
2203:	disconnectAll();
2204:	String host_url=protocol+"://"+host;
2205:	user.addMailHost(name,
2206:			 host_url,
2207:			 login,
2208:			 password);	
2209:	Enumeration enum=user.mailHosts();
2210:	while(enum.hasMoreElements()) {
2211:	    String id=(String)enum.nextElement();
2212:	    if(user.getMailHost(id).getName().equals(name)) {
2213:		setSubscribedAll(id,true);
2214:		break;
2215:	    }
2216:	}
2217:	model.update();
2218:    }
2219:
2220:            /**
2221:             * Remove the mailbox with the given name.
2222:             * Will first disconnect all mailboxes, remove the given mailbox and then update the model.
2223:             *
2224:             * @param name Name of the mailbox that is to be removed.
2225:             */
2226:            public void removeMailbox(String name) {
2227:                disconnectAll();
2228:                user.removeMailHost(name);
2229:                model.update();
2230:                // Should be called from FolderSetup Plugin
2231:                //refreshFolderInformation(true);
2232:            }
2233:
2234:            public void setAddToFolder(String id) {
2235:                model.setStateVar("add to folder", id);
2236:            }
2237:
2238:            public void addFolder(String toid, String name,
2239:                    boolean holds_messages, boolean holds_folders)
2240:                    throws MessagingException {
2241:
2242:                Folder parent = getFolder(toid);
2243:                Folder folder = parent.getFolder(name);
2244:                if (!folder.exists()) {
2245:                    int type = 0;
2246:                    if (holds_messages) {
2247:                        type += Folder.HOLDS_MESSAGES;
2248:                    }
2249:                    if (holds_folders) {
2250:                        type += Folder.HOLDS_FOLDERS;
2251:                    }
2252:                    folder.create(type);
2253:                }
2254:                // Should be called from FolderSetup Plugin
2255:                //refreshFolderInformation();
2256:            }
2257:
2258:            public void removeFolder(String id, boolean recurse)
2259:                    throws MessagingException {
2260:                Folder folder = getFolder(id);
2261:                folder.close(false);
2262:                folder.delete(recurse);
2263:
2264:                // Should be called from FolderSetup Plugin
2265:                //refreshFolderInformation();
2266:            }
2267:
2268:            public String getEnv(String key) {
2269:                return "";
2270:            }
2271:
2272:            public void setEnv(String key, String value) {
2273:            }
2274:
2275:            public void setException(Exception ex) {
2276:                model.setException(ex);
2277:            }
2278:
2279:            public void setEnv() {
2280:                // This will soon replace "ENV":
2281:                model.setStateVar("base uri", parent.getBasePath());
2282:                model.setStateVar("img base uri", parent.getImageBasePath()
2283:                        + "/" + user.getPreferredLocale().getLanguage() + "/"
2284:                        + user.getTheme());
2285:
2286:                model.setStateVar("webmail version", parent.getVersion());
2287:                model.setStateVar("operating system", System
2288:                        .getProperty("os.name")
2289:                        + " "
2290:                        + System.getProperty("os.version")
2291:                        + "/"
2292:                        + System.getProperty("os.arch"));
2293:                model.setStateVar("java virtual machine", System
2294:                        .getProperty("java.vendor")
2295:                        + " "
2296:                        + System.getProperty("java.vm.name")
2297:                        + " "
2298:                        + System.getProperty("java.version"));
2299:
2300:                model.setStateVar("last login", user.getLastLogin());
2301:                model.setStateVar("first login", user.getFirstLogin());
2302:                model.setStateVar("session id", session_code);
2303:                model.setStateVar("date",
2304:                        formatDate(System.currentTimeMillis()));
2305:                model.setStateVar("max attach size", parent.getStorage()
2306:                        .getConfig("MAX ATTACH SIZE"));
2307:                model.setStateVar("current attach size", "" + attachments_size);
2308:
2309:                // Add all languages to the state
2310:                model.removeAllStateVars("language");
2311:                String lang = parent.getConfig("languages");
2312:                StringTokenizer tok = new StringTokenizer(lang, " ");
2313:                while (tok.hasMoreTokens()) {
2314:                    String t = tok.nextToken();
2315:                    model.addStateVar("language", t);
2316:                    model.removeAllStateVars("themes_" + t);
2317:                    StringTokenizer tok2 = new StringTokenizer(parent
2318:                            .getConfig("THEMES_" + t.toUpperCase()), " ");
2319:                    while (tok2.hasMoreElements()) {
2320:                        model.addStateVar("themes_" + t, (String) tok2
2321:                                .nextToken());
2322:                    }
2323:                }
2324:
2325:                model.removeAllStateVars("protocol");
2326:                Provider[] stores = parent.getStoreProviders();
2327:                for (int i = 0; i < stores.length; i++) {
2328:                    model.addStateVar("protocol", stores[i].getProtocol());
2329:                }
2330:
2331:                model
2332:                        .setStateVar("themeset", "themes_"
2333:                                + user.getPreferredLocale().getLanguage()
2334:                                        .toLowerCase());
2335:            }
2336:
2337:            public UserData getUser() {
2338:                return user;
2339:            }
2340:
2341:            public String getUserName() {
2342:                return user.getLogin();
2343:            }
2344:
2345:            public InetAddress getRemoteAddress() {
2346:                return remote;
2347:            }
2348:
2349:            public Hashtable getActiveConnections() {
2350:                return connections;
2351:            }
2352:
2353:            public void setSent(boolean b) {
2354:                sent = b;
2355:            }
2356:
2357:            public boolean isSent() {
2358:                return sent;
2359:            }
2360:
2361:            private String formatDate(long date) {
2362:                TimeZone tz = TimeZone.getDefault();
2363:                DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG,
2364:                        DateFormat.DEFAULT, getLocale());
2365:                df.setTimeZone(tz);
2366:                String now = df.format(new Date(date));
2367:                return now;
2368:            }
2369:
2370:            public void handleTransportException(SendFailedException e) {
2371:                model.setStateVar("send status", e.getNextException()
2372:                        .getMessage());
2373:                model.setStateVar("valid sent addresses", Helper.joinAddress(e
2374:                        .getValidSentAddresses()));
2375:                model.setStateVar("valid unsent addresses", Helper
2376:                        .joinAddress(e.getValidUnsentAddresses()));
2377:                model.setStateVar("invalid addresses", Helper.joinAddress(e
2378:                        .getInvalidAddresses()));
2379:                sent = true;
2380:            }
2381:
2382:        } // WebMailSession
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.