bug fixes
[mir.git] / source / mircoders / localizer / basic / MirBasicEmailArticleHandler.java
1 /*
2  * Copyright (C) 2001, 2002 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with  any library licensed under the Apache Software License,
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23  * (or with modified versions of the above that use the same license as the above),
24  * and distribute linked combinations including the two.  You must obey the
25  * GNU General Public License in all respects for all of the code used other than
26  * the above mentioned libraries.  If you modify this file, you may extend this
27  * exception to your version of the file, but you are not obligated to do so.
28  * If you do not wish to do so, delete this exception statement from your version.
29  */
30 package mircoders.localizer.basic;
31
32 import java.io.IOException;
33 import java.io.PrintWriter;
34 import java.io.StringWriter;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Locale;
38 import java.util.Map;
39 import java.util.Vector;
40
41
42 import org.apache.commons.net.smtp.SMTPClient;
43 import org.apache.commons.net.smtp.SMTPReply;
44 import org.apache.struts.util.MessageResources;
45
46 import mir.config.MirPropertiesConfiguration;
47 import mir.generator.Generator;
48 import mir.generator.GeneratorHelper;
49 import mir.log.LoggerWrapper;
50 import mir.session.HTTPAdapters.HTTPRequestAdapter;
51 import mir.session.Request;
52 import mir.session.Response;
53 import mir.session.Session;
54 import mir.session.SessionExc;
55 import mir.session.SessionFailure;
56 import mir.session.SessionHandler;
57 import mir.session.ValidationError;
58 import mir.session.ValidationHelper;
59 import mir.util.StringRoutines;
60
61 import mircoders.entity.EntityContent;
62 import mircoders.global.CacheKey;
63 import mircoders.global.MirGlobal;
64 import mircoders.module.ModuleContent;
65 import mircoders.storage.DatabaseContent;
66
67
68 /**
69  *
70  * <p>Title: Tenative session handler for emailing postings </p>
71  * <p>Description: </p>
72  * <p>Copyright: Copyright (c) 2003</p>
73  * <p>Company: </p>
74  * @author john
75  * @version 1.0
76  */
77
78
79 public class MirBasicEmailArticleHandler implements SessionHandler {
80   protected LoggerWrapper logger;
81   protected MirPropertiesConfiguration configuration;
82
83   public MirBasicEmailArticleHandler() {
84     logger = new LoggerWrapper("Localizer.EmailArticle");
85     try {
86       configuration = MirPropertiesConfiguration.instance();
87     }
88     catch (Throwable t) {
89       logger.fatal("Cannot load configuration: " + t.toString());
90       
91       throw new RuntimeException("Cannot load configuration: " + t.toString());
92     }
93   }
94   
95   public void processRequest(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure {
96     if (aSession.getAttribute("initialRequest") == null) {
97       aSession.setAttribute("initialRequest", "no");
98       initialRequest(aRequest, aSession, aResponse);
99     }
100     else {
101       subsequentRequest(aRequest, aSession, aResponse);
102     }
103   }
104   
105   protected void initialRequest(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure {
106     initializeSession(aRequest, aSession);
107     makeInitialResponse(aRequest, aSession, aResponse);
108   }
109   
110   protected void initializeSession(Request aRequest, Session aSession) throws SessionExc, SessionFailure {
111     /* do nothing for now */
112     
113   }
114   
115   protected void makeInitialResponse(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure {
116     /* if you do not supply an aid to this handler, it should return an error page */
117     /* if you supply a non-functioning/non-published  aid to this handler, it should return an error page, but at a
118        later stage, because we don't check the db until we are potentially populating the cache*/
119     /* otherwise you get to address an article and add some comments */
120     String articleID = aRequest.getParameter("mail_aid");
121     if (articleID == null){
122       throw new SessionExc("makeInitialResponse: article id not set!");
123     }
124     else {
125       aSession.setAttribute("email.aid",articleID);
126       aResponse.setResponseValue("errors", null);
127       
128       String mail_language = configuration.getString("Mir.Login.DefaultLanguage", "en");        
129       aResponse.setResponseValue("mail_language",mail_language);
130       aResponse.setResponseValue("mail_to","");
131       aResponse.setResponseValue("mail_from","");
132       aResponse.setResponseValue("mail_from_name","");
133       aResponse.setResponseValue("mail_comment","");
134       
135       aResponse.setResponseGenerator(configuration.getString("Localizer.OpenSession.email.PrepareTemplate"));
136
137       
138     }
139   }
140   
141   protected boolean shouldSendMail(Request aRequest, Session aSession, Response aResponse,List aValidationErrors) throws SessionExc, SessionFailure{
142     if (validate(aRequest,aSession,aResponse,aValidationErrors)){
143       String to=aRequest.getParameter("mail_to");
144       if (to.indexOf('@') == -1
145           || to.indexOf('\n') != -1
146           || to.indexOf('\r') != -1
147           || to.indexOf(',') != -1) {
148         throw new SessionExc("Invalid to address"); // we might want to see this in a log, so it is not a validation error 
149       }
150       else return true; // go for it
151     }
152     else{
153       return false; //validation failed, but not in a potentially abusive way
154     }
155     
156   }
157   
158     
159
160
161
162   protected boolean validate(Request aRequest, Session aSession, Response aResponse,List aValidationErrors) throws SessionExc, SessionFailure{
163     
164     if (ValidationHelper.testFieldEntered(aRequest, "mail_to", "validationerror.missing", aValidationErrors))
165       aResponse.setResponseValue("mail_to",aRequest.getParameter("mail_to"));
166     if (ValidationHelper.testFieldEntered(aRequest, "mail_from", "validationerror.missing", aValidationErrors))
167       aResponse.setResponseValue("mail_from",aRequest.getParameter("mail_from"));
168     if (ValidationHelper.testFieldEntered(aRequest, "mail_from_name", "validationerror.missing", aValidationErrors))
169       aResponse.setResponseValue("mail_from_name",aRequest.getParameter("mail_from_name"));
170     if (ValidationHelper.testFieldEntered(aRequest, "mail_language", "validationerror.missing", aValidationErrors))
171       aResponse.setResponseValue("mail_language",aRequest.getParameter("mail_language"));
172
173     return (aValidationErrors==null || aValidationErrors.size() == 0);
174   }
175
176   protected String getEmailText(String aid,String language) throws SessionExc{
177     String theText;
178     CacheKey theCacheKey=new CacheKey("email",aid+language);
179
180     if (MirGlobal.mruCache().hasObject(theCacheKey)){
181       logger.info("fetching email text for article "+aid+" from cache");
182       theText = (String) MirGlobal.mruCache().getObject(theCacheKey);
183     }
184     else {
185       try {
186         ModuleContent contentModule = new ModuleContent(DatabaseContent.getInstance());
187         EntityContent contentEnt = (EntityContent) contentModule.getById(aid);
188         
189         Map articleData = new HashMap();
190         articleData.put("article", MirGlobal.localizer().dataModel().adapterModel().makeEntityAdapter("content", contentEnt));
191         articleData.put("languagecode", language);
192         Map responseData = GeneratorHelper.makeBasicGenerationData(new Locale[] {new Locale(language,""),new Locale(configuration.getString("Mir.Admin.FallbackLanguage", "en"), "")},"bundles.open","bundles.open");
193         responseData.put("data",articleData);
194         
195         String emailAnArticleTemplate = configuration.getString("Localizer.OpenSession.email.MailTemplate");
196         
197         Generator generator = MirGlobal.localizer().generators().makeOpenPostingGeneratorLibrary().makeGenerator(emailAnArticleTemplate);
198         
199         StringWriter theEmailStringWriter = new StringWriter();
200         PrintWriter theEmailPrintWriter = new PrintWriter(theEmailStringWriter);
201         generator.generate(theEmailPrintWriter, responseData, logger);
202         
203         theEmailStringWriter.close();
204
205         theText = theEmailStringWriter.toString();
206         MirGlobal.mruCache().storeObject(theCacheKey, theText);
207       }
208       catch (Throwable e) {
209         throw new SessionExc("Couldn't get content for article " + aid + language + ": " + e.getMessage());
210       }
211     }
212
213     return theText;
214   }
215
216   protected String getExtraEmailHeaders(Request aRequest,String to,String from) throws SessionExc {
217     
218     String headers = "To: " + to + "\nReply-To: "+ from+"\n";;
219     if (configuration.getString("Localizer.OpenSession.email.includeSenderIP","no").equals("yes"))
220       headers= headers+"X-Originating-IP: "+ ((HTTPRequestAdapter)aRequest).getRequest().getRemoteAddr() + "\n";
221     
222     return headers;
223   }
224
225   protected String interpolateComment(String emailText,String comment,String from_name,String language) throws SessionExc{
226       if (comment != null) {
227         MessageResources messages = MessageResources.getMessageResources("bundles.open");
228         String commentTextToInsert=messages.getMessage(new Locale(language,""),"email.comment.intro", from_name)+"\n";
229         
230         try {
231           emailText=StringRoutines.performRegularExpressionReplacement(emailText,"!COMMENT!",commentTextToInsert);
232         }
233         catch (Throwable e){
234           throw new SessionExc("Problem doing regular expression replacement :" + e.toString());
235         }
236       }
237       else{
238         try {
239         emailText=StringRoutines.performRegularExpressionReplacement(emailText,"!COMMENT!","");
240         }
241         catch (Throwable e){
242           throw new SessionExc("Problem doing regular expression replacement " + e.toString());
243         }
244       }
245       return emailText;
246   }
247   
248   protected boolean doTheSMTP(String aMessage,String aTo,String aFrom) throws SessionExc{
249    SMTPClient client=new SMTPClient();
250    try {
251      int reply;
252      client.connect(configuration.getString("ServletModule.OpenIndy.SMTPServer"));
253      reply = client.getReplyCode();
254      
255      if (!SMTPReply.isPositiveCompletion(reply)) {
256        client.disconnect();
257         throw new SessionExc("SMTP server refused connection.");
258      }
259      boolean trueIfItWorked = client.sendSimpleMessage(configuration.getString("ServletModule.OpenIndy.EmailIsFrom"), aTo, aMessage);
260      client.disconnect();
261      // mission accomplished??
262      if (! trueIfItWorked)
263        throw new SessionExc(client.getReplyString());
264      else
265        return trueIfItWorked;
266    }
267    catch(IOException e) {
268       if(client.isConnected()) {
269         try {
270           client.disconnect();
271         } catch(IOException f) {
272           // do nothing
273         }
274       }
275       throw new SessionExc(e.getMessage());
276    } 
277   }
278   
279   protected boolean sendMail(Request aRequest,Session aSession,Response aResponse) throws SessionExc,SessionFailure {
280     String aid=aRequest.getParameter("mail_aid");
281     String to=aRequest.getParameter("mail_to");
282     String from=aRequest.getParameter("mail_from");
283     String from_name=aRequest.getParameter("mail_from_name");
284     String language=aRequest.getParameter("mail_language");
285     String comment=aRequest.getParameter("mail_comment");
286     
287     String theEmailText=getEmailText((String) aSession.getAttribute("email.aid"),language);
288     String headers=getExtraEmailHeaders(aRequest,to,from);
289     theEmailText=interpolateComment(theEmailText,comment,from_name,language);
290     String message=headers+"\n"+theEmailText;
291
292     return doTheSMTP(message,to,from);
293        
294   }
295
296
297   protected void subsequentRequest(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure {
298     List validationErrors = new Vector();
299     if (shouldSendMail(aRequest,aSession,aResponse,validationErrors)){
300       
301       sendMail(aRequest,aSession,aResponse);
302       aResponse.setResponseGenerator(configuration.getString("Localizer.OpenSession.email.DoneTemplate"));
303     }
304     else {
305       aResponse.setResponseValue("mail_comment",aRequest.getParameter("mail_comment"));  //everything else is required 
306       aResponse.setResponseValue("errors",validationErrors);
307       aResponse.setResponseGenerator(configuration.getString("Localizer.OpenSession.email.PrepareTemplate"));
308     }
309     
310   }
311   
312       /*
313       String mail_language = aRequest.getParameter("mail_language");
314       if (mail_language == null)
315         mail_language = configuration.getString("Mir.Login.DefaultLanguage", "en");     
316        
317       aResponse.setResponseValue("mail_language",mail_language);
318       */
319
320
321
322
323 }