search fix
[mir.git] / source / mircoders / servlet / ServletModuleOpenIndy.java
1 /*\r
2  * Copyright (C) 2001, 2002  The Mir-coders group\r
3  *\r
4  * This file is part of Mir.\r
5  *\r
6  * Mir is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 2 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Mir is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with Mir; if not, write to the Free Software\r
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19  *\r
20  * In addition, as a special exception, The Mir-coders gives permission to link\r
21  * the code of this program with the com.oreilly.servlet library, any library\r
22  * licensed under the Apache Software License, The Sun (tm) Java Advanced\r
23  * Imaging library (JAI), The Sun JIMI library (or with modified versions of\r
24  * the above that use the same license as the above), and distribute linked\r
25  * combinations including the two.  You must obey the GNU General Public\r
26  * License in all respects for all of the code used other than the above\r
27  * mentioned libraries.  If you modify this file, you may extend this exception\r
28  * to your version of the file, but you are not obligated to do so.  If you do\r
29  * not wish to do so, delete this exception statement from your version.\r
30  */\r
31 \r
32 package mircoders.servlet;\r
33 \r
34 import java.io.ByteArrayOutputStream;\r
35 import java.io.File;\r
36 import java.io.FileNotFoundException;\r
37 import java.io.FileReader;\r
38 import java.io.IOException;\r
39 import java.io.PrintWriter;\r
40 import java.io.StringWriter;\r
41 import java.util.ArrayList;\r
42 import java.util.Arrays;\r
43 import java.util.Collections;\r
44 import java.util.Date;\r
45 import java.util.Enumeration;\r
46 import java.util.GregorianCalendar;\r
47 import java.util.HashMap;\r
48 import java.util.Iterator;\r
49 import java.util.List;\r
50 import java.util.ListIterator;\r
51 import java.util.Map;\r
52 import java.util.Random;\r
53 import java.util.Set;\r
54 import java.util.Vector;\r
55 import javax.servlet.http.HttpServletRequest;\r
56 import javax.servlet.http.HttpServletResponse;\r
57 import javax.servlet.http.HttpSession;\r
58 \r
59 import org.apache.commons.net.smtp.SMTPClient;\r
60 import org.apache.commons.net.smtp.SMTPReply;\r
61 import org.apache.fop.apps.Driver;\r
62 import org.apache.fop.apps.XSLTInputHandler;\r
63 import org.apache.log.Hierarchy;\r
64 import org.apache.log.Priority;\r
65 import org.apache.lucene.analysis.standard.StandardAnalyzer;\r
66 import org.apache.lucene.document.Document;\r
67 import org.apache.lucene.queryParser.QueryParser;\r
68 import org.apache.lucene.search.Hits;\r
69 import org.apache.lucene.search.IndexSearcher;\r
70 import org.apache.lucene.search.Query;\r
71 import org.apache.lucene.search.Searcher;\r
72 import org.apache.struts.util.MessageResources;\r
73 import mir.entity.Entity;\r
74 import mir.entity.EntityList;\r
75 import mir.generator.Generator;\r
76 import mir.log.LoggerWrapper;\r
77 import mir.misc.FileHandler;\r
78 import mir.misc.StringUtil;\r
79 import mir.misc.WebdbMultipartRequest;\r
80 import mir.servlet.ServletModule;\r
81 import mir.servlet.ServletModuleExc;\r
82 import mir.servlet.ServletModuleFailure;\r
83 import mir.servlet.ServletModuleUserExc;\r
84 import mir.storage.StorageObjectFailure;\r
85 import mir.util.ExceptionFunctions;\r
86 import mir.util.HTTPRequestParser;\r
87 import mir.util.StringRoutines;\r
88 import mircoders.entity.EntityComment;\r
89 import mircoders.entity.EntityContent;\r
90 import mircoders.global.MirGlobal;\r
91 import mircoders.media.MediaRequest;\r
92 import mircoders.media.UnsupportedMediaFormatExc;\r
93 import mircoders.module.ModuleComment;\r
94 import mircoders.module.ModuleContent;\r
95 import mircoders.module.ModuleImages;\r
96 import mircoders.module.ModuleTopics;\r
97 import mircoders.search.AudioSearchTerm;\r
98 import mircoders.search.ContentSearchTerm;\r
99 import mircoders.search.ImagesSearchTerm;\r
100 import mircoders.search.KeywordSearchTerm;\r
101 import mircoders.search.TextSearchTerm;\r
102 import mircoders.search.TopicSearchTerm;\r
103 import mircoders.search.UnIndexedSearchTerm;\r
104 import mircoders.search.VideoSearchTerm;\r
105 import mircoders.storage.DatabaseComment;\r
106 import mircoders.storage.DatabaseContent;\r
107 import mircoders.storage.DatabaseContentToMedia;\r
108 import mircoders.storage.DatabaseContentToTopics;\r
109 import mircoders.storage.DatabaseImages;\r
110 import mircoders.storage.DatabaseLanguage;\r
111 import mircoders.storage.DatabaseTopics;\r
112 \r
113 /*\r
114  *  ServletModuleOpenIndy -\r
115  *   is the open-access-servlet, which is responsible for\r
116  *    adding comments to articles &\r
117  *    open-postings to the newswire\r
118  *\r
119  * @author mir-coders group\r
120  * @version $Id: ServletModuleOpenIndy.java,v 1.70 2003/04/02 22:15:03 zapata Exp $\r
121  *\r
122  */\r
123 \r
124 public class ServletModuleOpenIndy extends ServletModule\r
125 {\r
126 \r
127   private String        commentFormTemplate, commentFormDoneTemplate, commentFormDupeTemplate;\r
128   private String        postingFormTemplate, postingFormDoneTemplate, postingFormDupeTemplate;\r
129   private String        searchResultsTemplate;\r
130   private String        prepareMailTemplate,sentMailTemplate;\r
131   private ModuleContent contentModule;\r
132   private ModuleComment commentModule;\r
133   private ModuleImages  imageModule;\r
134   private ModuleTopics  topicsModule;\r
135   private String        directOp ="yes";\r
136   // Singelton / Kontruktor\r
137   private static ServletModuleOpenIndy instance = new ServletModuleOpenIndy();\r
138   public static ServletModule getInstance() { return instance; }\r
139 \r
140   private ServletModuleOpenIndy() {\r
141     super();\r
142     try {\r
143       logger = new LoggerWrapper("ServletModule.OpenIndy");\r
144 \r
145       commentFormTemplate = configuration.getString("ServletModule.OpenIndy.CommentTemplate");\r
146       commentFormDoneTemplate = configuration.getString("ServletModule.OpenIndy.CommentDoneTemplate");\r
147       commentFormDupeTemplate = configuration.getString("ServletModule.OpenIndy.CommentDupeTemplate");\r
148       postingFormTemplate = configuration.getString("ServletModule.OpenIndy.PostingTemplate");\r
149       postingFormDoneTemplate = configuration.getString("ServletModule.OpenIndy.PostingDoneTemplate");\r
150       postingFormDupeTemplate = configuration.getString("ServletModule.OpenIndy.PostingDupeTemplate");\r
151       searchResultsTemplate = configuration.getString("ServletModule.OpenIndy.SearchResultsTemplate");\r
152       prepareMailTemplate = configuration.getString("ServletModule.OpenIndy.PrepareMailTemplate");\r
153       sentMailTemplate = configuration.getString("ServletModule.OpenIndy.SentMailTemplate");\r
154       directOp = configuration.getString("DirectOpenposting").toLowerCase();\r
155       mainModule = new ModuleComment(DatabaseComment.getInstance());\r
156       contentModule = new ModuleContent(DatabaseContent.getInstance());\r
157       topicsModule = new ModuleTopics(DatabaseTopics.getInstance());\r
158       imageModule = new ModuleImages(DatabaseImages.getInstance());\r
159       defaultAction="addposting";\r
160     }\r
161     catch (StorageObjectFailure e) {\r
162       logger.error("servletmoduleopenindy could not be initialized: " + e.getMessage());\r
163     }\r
164   }\r
165 \r
166   /**\r
167    * Method to return an "apology" when open postings are disabled\r
168    *\r
169    * @param aRequest\r
170    * @param aResponse\r
171    * @throws ServletModuleExc\r
172    * @throws ServletModuleUserExc\r
173    * @throws ServletModuleFailure\r
174    */\r
175   public void openPostingDisabled(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure {\r
176     deliver(aRequest, aResponse, (Map) null, null,\r
177        configuration.getString("ServletModule.OpenIndy.PostingDisabledTemplate"));\r
178   }\r
179 \r
180 \r
181   /**\r
182    *  Method for making a comment\r
183    */\r
184 \r
185   public void addcomment(HttpServletRequest req, HttpServletResponse res) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure\r
186   {\r
187     if (MirGlobal.abuse().getOpenPostingDisabled()) {\r
188       openPostingDisabled(req, res);\r
189 \r
190       return;\r
191     }\r
192 \r
193     String aid = req.getParameter("aid"); // the article id the comment will belong to\r
194 /*\r
195     String language = req.getParameter("language");\r
196  */\r
197 \r
198     if (aid!=null && !aid.equals("")) {\r
199       try {\r
200         Map mergeData = new HashMap();\r
201 \r
202         // onetimepasswd\r
203         if (MirGlobal.abuse().getOpenPostingPassword()) {\r
204           String passwd = this.createOneTimePasswd();\r
205           HttpSession session = req.getSession(false);\r
206           session.setAttribute("passwd", passwd);\r
207           mergeData.put("passwd", passwd);\r
208         }\r
209         else {\r
210           mergeData.put("passwd", (String) null);\r
211         }\r
212 /*\r
213         if (language != null) {\r
214           HttpSession session = req.getSession(false);\r
215           session.setAttribute("Locale", new Locale(language, ""));\r
216           session.setAttribute("language", language);\r
217         }\r
218 */\r
219         mergeData.put("aid", aid);\r
220 \r
221         Map extraInfo = new HashMap();\r
222         extraInfo.put("languagePopUpData", DatabaseLanguage.getInstance().getPopupData());\r
223 \r
224         deliver(req, res, mergeData, extraInfo, commentFormTemplate);\r
225       }\r
226       catch (Throwable t) {\r
227         throw new ServletModuleFailure("ServletModuleOpenIndy.addcomment: " + t.getMessage(), t);\r
228       }\r
229     }\r
230     else throw new ServletModuleExc("aid not set!");\r
231   }\r
232 \r
233   /**\r
234    *  Method for inserting a comment into the Database and delivering\r
235    *  the commentDone Page\r
236    */\r
237 \r
238   public void inscomment(HttpServletRequest req, HttpServletResponse res)\r
239     throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure\r
240   {\r
241     if (MirGlobal.abuse().getOpenPostingDisabled()) {\r
242       openPostingDisabled(req, res);\r
243 \r
244       return;\r
245     }\r
246 \r
247     String aid = req.getParameter("to_media"); // the article id the comment will belong to\r
248     if (aid!=null && !aid.equals(""))\r
249       {\r
250         // ok, collecting data from form\r
251         try {\r
252           Map withValues = getIntersectingValues(req, DatabaseComment.getInstance());\r
253 \r
254           //no html in comments(for now)\r
255           for (Iterator i=withValues.keySet().iterator(); i.hasNext(); ){\r
256             String k=(String)i.next();\r
257             String v=(String)withValues.get(k);\r
258 \r
259             withValues.put(k,StringUtil.removeHTMLTags(v));\r
260           }\r
261           withValues.put("is_published","1");\r
262           withValues.put("to_comment_status","1");\r
263 \r
264           //checking the onetimepasswd\r
265           HttpSession session = req.getSession(false);\r
266           String sessionPasswd = (String) session.getAttribute("passwd");\r
267           if ( sessionPasswd != null){\r
268             String passwd = req.getParameter("passwd");\r
269             if ( passwd == null || passwd.length()==0) {\r
270               throw new ServletModuleUserExc("comment.error.missingpassword", new String[] {});\r
271             }\r
272             if (!sessionPasswd.equals(passwd)) {\r
273               throw new ServletModuleUserExc("comment.error.invalidpassword", new String[] {});\r
274             }\r
275             session.invalidate();\r
276           }\r
277 \r
278           String id = mainModule.add(withValues);\r
279 \r
280           if(id==null){\r
281             deliver(req, res, (Map) null, null, commentFormDupeTemplate);\r
282           }\r
283           else {\r
284             MirGlobal.abuse().logComment(req.getRemoteAddr(), id, new Date(), (String) req.getHeader("User-Agent"));\r
285 \r
286             DatabaseContent.getInstance().setUnproduced("id="+aid);\r
287 \r
288             try {\r
289               EntityComment comment = (EntityComment) DatabaseComment.getInstance().selectById(id);\r
290               MirGlobal.abuse().checkComment(comment, req, res);\r
291               MirGlobal.localizer().openPostings().afterCommentPosting(comment);\r
292             }\r
293             catch (Throwable t) {\r
294               throw new ServletModuleExc(t.getMessage());\r
295             }\r
296           }\r
297 \r
298           // redirecting to url\r
299           // should implement back to article\r
300           Map mergeData = new HashMap();\r
301           deliver(req, res, mergeData, null, commentFormDoneTemplate);\r
302         }\r
303         catch (Throwable e) {\r
304           throw new ServletModuleFailure(e);\r
305         }\r
306       }\r
307     else throw new ServletModuleExc("aid not set!");\r
308 \r
309   }\r
310 \r
311   /**\r
312    *  Method for delivering the form-Page for open posting\r
313    */\r
314 \r
315   public void addposting(HttpServletRequest req, HttpServletResponse res)\r
316       throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure\r
317   {\r
318     try {\r
319       if (MirGlobal.abuse().getOpenPostingDisabled()) {\r
320         openPostingDisabled(req, res);\r
321 \r
322         return;\r
323       }\r
324 \r
325       Map mergeData = new HashMap();\r
326 \r
327       // onetimepasswd\r
328       if (MirGlobal.abuse().getOpenPostingPassword()) {\r
329         String passwd = this.createOneTimePasswd();\r
330         HttpSession session = req.getSession(false);\r
331         session.setAttribute("passwd", passwd);\r
332         mergeData.put("passwd", passwd);\r
333       }\r
334       else {\r
335         mergeData.put("passwd", (String)null);\r
336       }\r
337 \r
338       String maxMedia = configuration.getString("ServletModule.OpenIndy.MaxMediaUploadItems");\r
339       String defaultMedia = configuration.getString("ServletModule.OpenIndy.DefaultMediaUploadItems");\r
340       String numOfMedia = req.getParameter("medianum");\r
341 \r
342       if (numOfMedia == null || numOfMedia.equals("")) {\r
343         numOfMedia = defaultMedia;\r
344       }\r
345       else if (Integer.parseInt(numOfMedia) > Integer.parseInt(maxMedia)) {\r
346         numOfMedia = maxMedia;\r
347       }\r
348 \r
349       int mediaNum = Integer.parseInt(numOfMedia);\r
350       List mediaFields = new Vector();\r
351       for (int i = 0; i < mediaNum; i++) {\r
352         Integer mNum = new Integer(i + 1);\r
353         mediaFields.add(mNum.toString());\r
354       }\r
355       mergeData.put("medianum", numOfMedia);\r
356       mergeData.put("mediafields", mediaFields);\r
357       mergeData.put("to_topic", null);\r
358 \r
359       Map extraInfo = new HashMap();\r
360       extraInfo.put("languagePopUpData", DatabaseLanguage.getInstance().getPopupData());\r
361       extraInfo.put("themenPopupData", topicsModule.getTopicsAsSimpleList());\r
362 \r
363       extraInfo.put("topics", topicsModule.getTopicsList());\r
364       deliver(req, res, mergeData, extraInfo, postingFormTemplate);\r
365     }\r
366     catch (Throwable t) {\r
367       throw new ServletModuleFailure(t);\r
368     }\r
369   }\r
370 \r
371   /**\r
372    *  Method for inserting an open posting into the Database and delivering\r
373    *  the postingDone Page\r
374    */\r
375 \r
376   public void insposting(HttpServletRequest req, HttpServletResponse res) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure\r
377   {\r
378     if (MirGlobal.abuse().getOpenPostingDisabled()) {\r
379       openPostingDisabled(req, res);\r
380 \r
381       return;\r
382     }\r
383 \r
384     Map mergeData = new HashMap();\r
385     boolean setMedia=false;\r
386     boolean setTopic = false;\r
387 \r
388     try {\r
389 \r
390       WebdbMultipartRequest mp = null;\r
391       EntityList mediaList = null;\r
392       try {\r
393         // new MediaRequest, "1" is the id for the openPosting user\r
394         MediaRequest mediaReq = new MediaRequest("1", true);\r
395         mp = new WebdbMultipartRequest(req, (FileHandler)mediaReq);\r
396         mediaList = mediaReq.getEntityList();\r
397       }\r
398       catch (Throwable e) {\r
399         throw new ServletModuleFailure(e);\r
400       }\r
401 \r
402       Map withValues = mp.getParameters();\r
403 \r
404       //checking the onetimepasswd\r
405       HttpSession session = req.getSession(false);\r
406       String sessionPasswd = (String) session.getAttribute("passwd");\r
407       if (sessionPasswd != null){\r
408         String passwd = (String) withValues.get("passwd");\r
409 \r
410         logger.debug("session password = " + sessionPasswd + ", form password = " + passwd);\r
411 \r
412         if ( passwd == null || passwd.length()==0) {\r
413           throw new ServletModuleUserExc("posting.error.missingpassword", new String[] {});\r
414         }\r
415         if (!sessionPasswd.equals(passwd)) {\r
416           throw new ServletModuleUserExc("posting.error.invalidpassword", new String[] {});\r
417         }\r
418         session.invalidate();\r
419       }\r
420 \r
421       if ((((String)withValues.get("title")).length() == 0) ||\r
422           (((String)withValues.get("description")).length() == 0) ||\r
423           (((String)withValues.get("content_data")).length() == 0))\r
424         throw new ServletModuleUserExc("posting.error.missingfield", new String[] {});\r
425 \r
426       // call the routines that escape html\r
427 \r
428       for (Iterator i=withValues.keySet().iterator(); i.hasNext(); ){\r
429         String k=(String)i.next();\r
430         String v=(String)withValues.get(k);\r
431 \r
432         if (k.equals("content_data")){\r
433           //this doesn't quite work yet, so for now, all html goes\r
434           //withValues.put(k,StringUtil.approveHTMLTags(v));\r
435           withValues.put(k,StringUtil.deleteForbiddenTags(v));\r
436         }\r
437         else if (k.equals("description")) {\r
438           String tmp = StringUtil.deleteForbiddenTags(v);\r
439           withValues.put(k,StringUtil.deleteHTMLTableTags(tmp));\r
440         }\r
441         else {\r
442           withValues.put(k,StringUtil.removeHTMLTags(v));\r
443         }\r
444 \r
445       }\r
446 \r
447       withValues.put("date", StringUtil.date2webdbDate(new GregorianCalendar()));\r
448       withValues.put("publish_path", StringUtil.webdbDate2path((String)withValues.get("date")));\r
449       withValues.put("is_produced", "0");\r
450       withValues.put("is_published","1");\r
451       if (directOp.equals("yes"))\r
452         withValues.put("to_article_type","1");\r
453 \r
454       withValues.put("to_publisher","1");\r
455 \r
456       // inserting  content into database\r
457       String cid = contentModule.add(withValues);\r
458       logger.debug("id: "+cid);\r
459       //insert was not successfull\r
460       if(cid==null){\r
461 \r
462         //How do we know that it was not succesful cause of a\r
463         //dupe, what if it failed cause of "No space left on device"?\r
464         //Or is there something I am missing? Wouldn't it be better\r
465         //to have an explicit dupe check and then insert? I have no\r
466         //idea what I am talking about. this comment is in case\r
467         //I forget to explicitely ask. -mh\r
468         deliver(req, res, mergeData, null, postingFormDupeTemplate);\r
469         return;\r
470       }\r
471 \r
472       MirGlobal.abuse().logArticle(req.getRemoteAddr(), cid, new Date(), (String) req.getHeader("User-Agent"));\r
473 \r
474       String[] to_topicsArr = mp.getParameterValues("to_topic");\r
475 \r
476       if (to_topicsArr != null && to_topicsArr.length > 0) {\r
477         try{\r
478           DatabaseContentToTopics.getInstance().setTopics(cid,to_topicsArr);\r
479           setTopic = true;\r
480         }\r
481         catch (Throwable e) {\r
482           logger.error("setting content_x_topic failed");\r
483           contentModule.deleteById(cid);\r
484           throw new ServletModuleFailure("smod - openindy :: insposting: setting content_x_topic failed: "+e.toString(), e);\r
485         } //end try\r
486       } //end if\r
487 \r
488       //if we're here all is ok... associate the media to the article\r
489       for(int i=0;i<mediaList.size();i++) {\r
490         Entity mediaEnt = (Entity)mediaList.elementAt(i);\r
491         DatabaseContentToMedia.getInstance().addMedia(cid,mediaEnt.getId());\r
492       }\r
493 \r
494       EntityContent article = (EntityContent) contentModule.getById(cid);\r
495 \r
496       try {\r
497         MirGlobal.abuse().checkArticle(article, req, res);\r
498         MirGlobal.localizer().openPostings().afterContentPosting(article);\r
499       }\r
500       catch (Throwable t) {\r
501         logger.error("Error while post-processing article: " + t.getMessage());\r
502       }\r
503     }\r
504     catch (Throwable e) {\r
505       Throwable cause = ExceptionFunctions.traceCauseException(e);\r
506 \r
507       if (cause instanceof UnsupportedMediaFormatExc) {\r
508         throw new ServletModuleUserExc("media.unsupportedformat", new String[] {} );\r
509       }\r
510       throw new ServletModuleFailure(e);\r
511     }\r
512 \r
513     deliver(req, res, mergeData, null, postingFormDoneTemplate);\r
514   }\r
515 \r
516   /**\r
517    * Method for preparing and sending a content as an email message\r
518    */\r
519 \r
520   public void mail(HttpServletRequest req, HttpServletResponse res)\r
521       throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure\r
522   {\r
523     String aid = req.getParameter("mail_aid");\r
524     if (aid == null){\r
525       throw new ServletModuleExc("An article id must be specified in requests to email an article.  Something therefore went badly wrong....");\r
526     }\r
527 \r
528     String to = req.getParameter("mail_to");\r
529     String from = req.getParameter("mail_from");\r
530     String from_name = req.getParameter("mail_from_name");\r
531     String comment = req.getParameter("mail_comment");\r
532     String mail_language = req.getParameter("mail_language");\r
533 \r
534     Map mergeData = new HashMap();\r
535 \r
536     if (to == null || from == null || from_name == null|| to.equals("") || from.equals("") || from_name.equals("") || mail_language == null || mail_language.equals("")){\r
537 \r
538       for (Enumeration theParams = req.getParameterNames(); theParams.hasMoreElements() ;) {\r
539         String pName=(String)theParams.nextElement();\r
540         if (pName.startsWith("mail_")){\r
541           mergeData.put( pName,req.getParameter(pName) );\r
542         }\r
543       }\r
544 \r
545       deliver(req, res, mergeData, null, prepareMailTemplate);\r
546     }\r
547     else {\r
548       //run checks on to and from and mail_language to make sure no monkey business occurring\r
549       if (mail_language.indexOf('.') != -1 || mail_language.indexOf('/') != -1 ) {\r
550         throw new ServletModuleExc("Invalid language");\r
551       }\r
552       if (to.indexOf('\n') != -1\r
553           || to.indexOf('\r') != -1\r
554           || to.indexOf(',') != -1) {\r
555         throw new ServletModuleUserExc("email.error.invalidtoaddress", new String[] {to});\r
556       }\r
557       if (from.indexOf('\n') != -1 || from.indexOf('\r') != -1 || from.indexOf(',') != -1 ) {\r
558         throw new ServletModuleUserExc("email.error.invalidfromaddress", new String[] {from});\r
559       }\r
560 \r
561 \r
562       EntityContent contentEnt;\r
563       try{\r
564         contentEnt = (EntityContent)contentModule.getById(aid);\r
565       }\r
566       catch (Throwable e){\r
567         throw new ServletModuleFailure("Couldn't get content for article "+aid + ": " + e.getMessage(), e);\r
568       }\r
569       String producerStorageRoot=configuration.getString("Producer.StorageRoot");\r
570       String producerDocRoot=configuration.getString("Producer.DocRoot");\r
571       String publishPath = contentEnt.getValue("publish_path");\r
572       String txtFilePath = producerStorageRoot + producerDocRoot + "/" + mail_language +\r
573                                                                                                          publishPath + "/" + aid + ".txt";\r
574 \r
575 \r
576       File inputFile = new File(txtFilePath);\r
577       String content;\r
578 \r
579       try{\r
580         FileReader in = new FileReader(inputFile);\r
581         StringWriter out = new StringWriter();\r
582         int c;\r
583         while ((c = in.read()) != -1)\r
584           out.write(c);\r
585         in.close();\r
586         content= out.toString();\r
587       }\r
588       catch (FileNotFoundException e){\r
589         throw new ServletModuleFailure("No text file found in " + txtFilePath, e);\r
590       }\r
591       catch (IOException e){\r
592         throw new ServletModuleFailure("Problem reading file in " + txtFilePath, e);\r
593       }\r
594       // add some headers\r
595       content = "To: " + to + "\nReply-To: "+ from + "\n" + content;\r
596       // put in the comment where it should go\r
597       if (comment != null) {\r
598         String commentTextToInsert = "\n\nAttached comment from " + from_name + ":\n" + comment;\r
599         try {\r
600           content=StringRoutines.performRegularExpressionReplacement(content,"!COMMENT!",commentTextToInsert);\r
601         }\r
602         catch (Throwable e){\r
603           throw new ServletModuleFailure("Problem doing regular expression replacement " + e.toString(), e);\r
604         }\r
605       }\r
606       else{\r
607         try {\r
608           content=StringRoutines.performRegularExpressionReplacement(content,"!COMMENT!","");\r
609         }\r
610         catch (Throwable e){\r
611           throw new ServletModuleFailure("Problem doing regular expression replacement " + e.toString(), e);\r
612         }\r
613       }\r
614 \r
615       SMTPClient client=new SMTPClient();\r
616       try {\r
617         int reply;\r
618         client.connect(configuration.getString("ServletModule.OpenIndy.SMTPServer"));\r
619 \r
620         reply = client.getReplyCode();\r
621 \r
622         if (!SMTPReply.isPositiveCompletion(reply)) {\r
623           client.disconnect();\r
624           throw new ServletModuleExc("SMTP server refused connection.");\r
625         }\r
626 \r
627         client.sendSimpleMessage(configuration.getString("ServletModule.OpenIndy.EmailIsFrom"), to, content);\r
628 \r
629         client.disconnect();\r
630         //mission accomplished\r
631         deliver(req, res, mergeData, null, sentMailTemplate);\r
632       }\r
633       catch(IOException e) {\r
634         if(client.isConnected()) {\r
635           try {\r
636             client.disconnect();\r
637           } catch(IOException f) {\r
638             // do nothing\r
639           }\r
640         }\r
641         throw new ServletModuleFailure(e);\r
642       }\r
643     }\r
644   }\r
645 \r
646   /**\r
647    * Method for querying a lucene index\r
648    *\r
649    * @param req\r
650    * @param res\r
651    * @throws ServletModuleExc\r
652    * @throws ServletModuleUserExc\r
653    * @throws ServletModuleFailure\r
654    */\r
655 \r
656   public void search(HttpServletRequest req, HttpServletResponse res)\r
657       throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure {\r
658     try {\r
659       final String[] search_variables = { "search_content", "search_boolean", "search_creator",\r
660           "search_topic", "search_hasImages", "search_hasAudio", "search_hasVideo", "search_sort",\r
661           "search_submit", "search_back", "search_forward" };\r
662       HTTPRequestParser requestParser = new HTTPRequestParser(req);\r
663 \r
664       int increment=10;\r
665 \r
666       HttpSession session = req.getSession(false);\r
667 \r
668       String queryString="";\r
669 \r
670       Map mergeData = new HashMap();\r
671 \r
672       KeywordSearchTerm dateTerm = new KeywordSearchTerm("date_formatted","search_date","webdb_create_formatted","webdb_create_formatted","webdb_create_formatted");\r
673       UnIndexedSearchTerm whereTerm = new UnIndexedSearchTerm("","","","where","where");\r
674       TextSearchTerm creatorTerm = new TextSearchTerm("creator","search_creator","creator","creator","creator");\r
675       TextSearchTerm titleTerm = new TextSearchTerm("title","search_content","title","title","title");\r
676       TextSearchTerm descriptionTerm =  new TextSearchTerm("description","search_content","description","description","description");\r
677       ContentSearchTerm contentTerm = new ContentSearchTerm("content_data","search_content","content","","");\r
678       TopicSearchTerm topicTerm = new TopicSearchTerm();\r
679       ImagesSearchTerm imagesTerm = new ImagesSearchTerm();\r
680       AudioSearchTerm audioTerm = new AudioSearchTerm();\r
681       VideoSearchTerm videoTerm = new VideoSearchTerm();\r
682 \r
683       //make the query available to subsequent iterations\r
684 \r
685       Iterator j = Arrays.asList(search_variables).iterator();\r
686       while (j.hasNext()) {\r
687         String variable = (String) j.next();\r
688 \r
689         mergeData.put(variable, requestParser.getParameter(variable));\r
690       }\r
691 \r
692       try{\r
693         mergeData.put("topics", topicsModule.getTopicsAsSimpleList());\r
694       }\r
695       catch(Throwable e) {\r
696         logger.debug("Can't get topics: " + e.toString());\r
697       }\r
698 \r
699       String searchBackValue = req.getParameter("search_back");\r
700       String searchForwardValue = req.getParameter("search_forward");\r
701 \r
702       if (searchBackValue != null){\r
703         int totalHits = ((Integer) session.getAttribute("numberOfHits")).intValue();\r
704         int newPosition=((Integer)session.getAttribute("positionInResults")).intValue()-increment;\r
705         if (newPosition<0)\r
706           newPosition=0;\r
707         if (newPosition >= totalHits)\r
708           newPosition=totalHits-1;\r
709         session.setAttribute("positionInResults",new Integer(newPosition));\r
710       }\r
711       else {\r
712         if (searchForwardValue != null){\r
713           int totalHits = ((Integer) session.getAttribute("numberOfHits")).intValue();\r
714           int newPosition=((Integer)session.getAttribute("positionInResults")).intValue()+increment;\r
715           if (newPosition<0)\r
716             newPosition=0;\r
717           if (newPosition >= totalHits)\r
718             newPosition=totalHits-1;\r
719 \r
720           session.setAttribute("positionInResults",new Integer(newPosition));\r
721         }\r
722         else {\r
723           String indexPath=configuration.getString("IndexPath");\r
724 \r
725 \r
726           String creatorFragment = creatorTerm.makeTerm(req);\r
727           if (creatorFragment != null){\r
728             queryString = queryString + " +" + creatorFragment;\r
729           }\r
730 \r
731           // search title, description, and content for something\r
732           // the contentTerm uses param "search_boolean" to combine its terms\r
733           String contentFragment = contentTerm.makeTerm(req);\r
734           if (contentFragment != null){\r
735             logger.debug("contentFragment: " + contentFragment);\r
736             queryString = queryString + " +" + contentFragment;\r
737           }\r
738 \r
739           String topicFragment = topicTerm.makeTerm(req);\r
740           if (topicFragment != null){\r
741             queryString = queryString + " +" + topicFragment;\r
742           }\r
743 \r
744           String imagesFragment = imagesTerm.makeTerm(req);\r
745           if (imagesFragment != null){\r
746             queryString = queryString + " +" + imagesFragment;\r
747           }\r
748 \r
749           String audioFragment = audioTerm.makeTerm(req);\r
750           if (audioFragment != null){\r
751             queryString = queryString + " +" + audioFragment;\r
752           }\r
753 \r
754           String videoFragment = videoTerm.makeTerm(req);\r
755           if (videoFragment != null){\r
756             queryString = queryString + " +" + videoFragment;\r
757           }\r
758 \r
759           if (queryString == null || queryString == ""){\r
760             queryString = "";\r
761           }\r
762           else{\r
763             try{\r
764               Searcher searcher = null;\r
765               try {\r
766                 searcher = new IndexSearcher(indexPath);\r
767               }\r
768               catch(IOException e) {\r
769                 logger.debug("Can't open indexPath: " + indexPath);\r
770                 throw new ServletModuleExc("Problem with Search Index! : "+ e.toString());\r
771               }\r
772 \r
773               Query query = null;\r
774               try {\r
775                 query = QueryParser.parse(queryString, "content", new StandardAnalyzer());\r
776               }\r
777               catch(Exception e) {\r
778                 searcher.close();\r
779                 logger.debug("Query don't parse: " + queryString);\r
780                 throw new ServletModuleExc("Problem with Query String! (was '"+queryString+"')");\r
781               }\r
782 \r
783               Hits hits = null;\r
784               try {\r
785                 hits = searcher.search(query);\r
786               }\r
787               catch(IOException e) {\r
788                 searcher.close();\r
789                 logger.debug("Can't get hits: " + e.toString());\r
790                 throw new ServletModuleExc("Problem getting hits!");\r
791               }\r
792 \r
793               int start = 0;\r
794               int end = hits.length();\r
795 \r
796               String sortBy=req.getParameter("search_sort");\r
797               if (sortBy == null || sortBy.equals("")){\r
798                 throw new ServletModuleExc("Please let me sort by something!(missing search_sort)");\r
799               }\r
800 \r
801               // here is where the documents will go for storage across sessions\r
802               ArrayList theDocumentsSorted = new ArrayList();\r
803 \r
804               if (sortBy.equals("score")){\r
805                 for(int i = start; i < end; i++) {\r
806                   theDocumentsSorted.add(hits.doc(i));\r
807                 }\r
808               }\r
809               else{\r
810                 // then we'll sort by date!\r
811                 Map dateToPosition = new HashMap(end,1.0F); //we know how big it will be\r
812                 for(int i = start; i < end; i++) {\r
813                   String creationDate=(hits.doc(i)).get("creationDate");\r
814                   // do a little dance in case two contents created at the same second!\r
815                   if (dateToPosition.containsKey(creationDate)){\r
816                     ((ArrayList) (dateToPosition.get(creationDate))).add(new Integer(i));\r
817                   }\r
818                   else{\r
819                     ArrayList thePositions = new ArrayList();\r
820                     thePositions.add(new Integer(i));\r
821                     dateToPosition.put(creationDate,thePositions);\r
822                   }\r
823                 }\r
824                 Set keys = dateToPosition.keySet();\r
825                 ArrayList keyList= new ArrayList(keys);\r
826                 Collections.sort(keyList);\r
827                 if (sortBy.equals("date_desc")){\r
828                   Collections.reverse(keyList);\r
829                 }\r
830                 else{\r
831                   if (!sortBy.equals("date_asc")){\r
832                     throw new ServletModuleExc("don't know how to sort by: "+ sortBy);\r
833                   }\r
834                 }\r
835                 ListIterator keyTraverser = keyList.listIterator();\r
836                 while (keyTraverser.hasNext()){\r
837                   ArrayList positions = (ArrayList)dateToPosition.get((keyTraverser.next()));\r
838                   ListIterator positionsTraverser=positions.listIterator();\r
839                   while (positionsTraverser.hasNext()){\r
840                     theDocumentsSorted.add(hits.doc(((Integer)(positionsTraverser.next())).intValue()));\r
841                   }\r
842                 }\r
843               }\r
844 \r
845               try{\r
846                 searcher.close();\r
847               }\r
848               catch (IOException e){\r
849                 logger.debug("Can't close searcher: " + e.toString());\r
850                 throw new ServletModuleFailure("Problem closing searcher(normal):" + e.getMessage(), e);\r
851               }\r
852 \r
853 \r
854               session.removeAttribute("numberOfHits");\r
855               session.removeAttribute("theDocumentsSorted");\r
856               session.removeAttribute("positionInResults");\r
857 \r
858               session.setAttribute("numberOfHits",new Integer(end));\r
859               session.setAttribute("theDocumentsSorted",theDocumentsSorted);\r
860               session.setAttribute("positionInResults",new Integer(0));\r
861 \r
862             }\r
863             catch (IOException e){\r
864               logger.debug("Can't close searcher: " + e.toString());\r
865               throw new ServletModuleFailure("Problem closing searcher: " + e.getMessage(), e);\r
866             }\r
867           }\r
868         }\r
869       }\r
870 \r
871       try {\r
872         ArrayList theDocs = (ArrayList)session.getAttribute("theDocumentsSorted");\r
873         if (theDocs != null){\r
874 \r
875           mergeData.put("numberOfHits", ((Integer)session.getAttribute("numberOfHits")).toString());\r
876           List theHits = new Vector();\r
877           int pIR=((Integer)session.getAttribute("positionInResults")).intValue();\r
878           int terminus;\r
879           int numHits=((Integer)session.getAttribute("numberOfHits")).intValue();\r
880 \r
881           if (!(pIR+increment>=numHits)){\r
882             mergeData.put("hasNext","y");\r
883           }\r
884           else {\r
885             mergeData.put("hasNext", null);\r
886           }\r
887           if (pIR>0){\r
888             mergeData.put("hasPrevious","y");\r
889           }\r
890           else {\r
891             mergeData.put("hasPrevious", null);\r
892           }\r
893 \r
894           if ((pIR+increment)>numHits){\r
895             terminus=numHits;\r
896           }\r
897           else {\r
898             terminus=pIR+increment;\r
899           }\r
900           for(int i = pIR; i < terminus; i++) {\r
901             Map h = new HashMap();\r
902             Document theHit = (Document)theDocs.get(i);\r
903             whereTerm.returnMeta(h,theHit);\r
904             creatorTerm.returnMeta(h,theHit);\r
905             titleTerm.returnMeta(h,theHit);\r
906             descriptionTerm.returnMeta(h,theHit);\r
907             dateTerm.returnMeta(h,theHit);\r
908             imagesTerm.returnMeta(h,theHit);\r
909             audioTerm.returnMeta(h,theHit);\r
910             videoTerm.returnMeta(h,theHit);\r
911             theHits.add(h);\r
912           }\r
913           mergeData.put("hits",theHits);\r
914         }\r
915       }\r
916       catch (Throwable e) {\r
917         logger.error("Can't iterate over hits: " + e.toString());\r
918 \r
919         throw new ServletModuleFailure("Problem getting hits: " + e.getMessage(), e);\r
920       }\r
921 \r
922       mergeData.put("queryString",queryString);\r
923 \r
924       deliver(req, res, mergeData, null, searchResultsTemplate);\r
925     }\r
926     catch (NullPointerException n){\r
927       throw new ServletModuleFailure("Null Pointer: "+n.toString(), n);\r
928     }\r
929   }\r
930 \r
931   /*\r
932    * Method for dynamically generating a pdf from a fo file\r
933    */\r
934   public void getpdf(HttpServletRequest req, HttpServletResponse res)\r
935       throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure {\r
936     String ID_REQUEST_PARAM = "id";\r
937     String language = req.getParameter("language");\r
938     String generateFO=configuration.getString("GenerateFO");\r
939     String generatePDF=configuration.getString("GeneratePDF");\r
940 \r
941 \r
942     //don't do anything if we are not making FO files, or if we are\r
943     //pregenerating PDF's\r
944     if (generateFO.equals("yes") && generatePDF.equals("no")){\r
945       //fop complains unless you do the logging this way\r
946       org.apache.log.Logger log = null;\r
947       Hierarchy hierarchy = Hierarchy.getDefaultHierarchy();\r
948       log = hierarchy.getLoggerFor("fop");\r
949       log.setPriority(Priority.WARN);\r
950 \r
951       String producerStorageRoot=configuration.getString("Producer.StorageRoot");\r
952       String producerDocRoot=configuration.getString("Producer.DocRoot");\r
953       //      String templateDir=MirConfig.getPropWithHome("HTMLTemplateProcessor.Dir");\r
954       String xslSheet=configuration.getString("Producer.HTML2FOStyleSheet");\r
955       try {\r
956         String idParam = req.getParameter(ID_REQUEST_PARAM);\r
957         if (idParam != null) {\r
958           EntityContent contentEnt =\r
959             (EntityContent)contentModule.getById(idParam);\r
960           String publishPath = StringUtil.webdbDate2path(contentEnt.getValue("date"));\r
961           String foFile;\r
962 \r
963           if (language == null){\r
964             foFile = producerStorageRoot + producerDocRoot + "/"\r
965               + publishPath  + idParam + ".fo";\r
966           }\r
967           else{\r
968             foFile = producerStorageRoot + producerDocRoot + "/"\r
969               + language + publishPath  + idParam + ".fo";\r
970           }\r
971           logger.debug("USING FILES" + foFile + " and " + xslSheet);\r
972           XSLTInputHandler input = new XSLTInputHandler(new File(foFile),\r
973                                                         new File(xslSheet));\r
974 \r
975           ByteArrayOutputStream out = new ByteArrayOutputStream();\r
976           res.setContentType("application/pdf");\r
977 \r
978           Driver driver = new Driver();\r
979           driver.setLogger(log);\r
980           driver.setRenderer(Driver.RENDER_PDF);\r
981           driver.setOutputStream(out);\r
982           driver.render(input.getParser(), input.getInputSource());\r
983 \r
984           byte[] content = out.toByteArray();\r
985           res.setContentLength(content.length);\r
986           res.getOutputStream().write(content);\r
987           res.getOutputStream().flush();\r
988         }\r
989         else {\r
990           throw new ServletModuleExc("Missing id.");\r
991         }\r
992       }\r
993       catch (Throwable t) {\r
994         logger.error(t.toString());\r
995 \r
996         throw new ServletModuleFailure(t);\r
997       }\r
998     }\r
999     else {\r
1000       throw new ServletModuleExc("Can't generate a PDF because the config tells me not to.");\r
1001     }\r
1002   }\r
1003 \r
1004   protected String createOneTimePasswd(){\r
1005     Random r = new Random();\r
1006     int random = r.nextInt();\r
1007     long l = System.currentTimeMillis();\r
1008     l = (l*l*l*l)/random;\r
1009     if(l<0) l = l * -1;\r
1010     String returnString = ""+l;\r
1011 \r
1012     return returnString.substring(5);\r
1013   }\r
1014 \r
1015 \r
1016   /* this is an overwritten method of ServletModule in order\r
1017      to use different bundles for open and admin */\r
1018 /*  public void deliver(HttpServletRequest req, HttpServletResponse res,\r
1019                       TemplateModelRoot rtm, TemplateModelRoot popups,\r
1020                       String templateFilename) throws ServletModuleFailure\r
1021   {\r
1022   }\r
1023 */\r
1024   public void deliver(HttpServletRequest aRequest, HttpServletResponse aResponse, Map aData, Map anExtra, String aGenerator)\r
1025       throws ServletModuleFailure {\r
1026     try {\r
1027       deliver(aResponse.getWriter(), aRequest, aResponse, aData, anExtra, aGenerator);\r
1028     }\r
1029     catch (Throwable t) {\r
1030       throw new ServletModuleFailure(t);\r
1031     }\r
1032   }\r
1033 \r
1034   public void deliver(PrintWriter anOutputWriter, HttpServletRequest aRequest, HttpServletResponse aResponse, Map aData, Map anExtra, String aGenerator)\r
1035       throws ServletModuleFailure {\r
1036     try {\r
1037       Map responseData = ServletHelper.makeGenerationData(getLocale(aRequest), "bundles.open");\r
1038       responseData.put("data", aData);\r
1039       responseData.put("extra", anExtra);\r
1040 \r
1041 \r
1042       Generator generator = MirGlobal.localizer().generators().makeOpenPostingGeneratorLibrary().makeGenerator(aGenerator);\r
1043       generator.generate(anOutputWriter, responseData, logger.asPrintWriter(logger.INFO_MESSAGE));\r
1044 \r
1045       anOutputWriter.close();\r
1046     }\r
1047     catch (Throwable e) {\r
1048       logger.error("Error while generating " + aGenerator + ": " + e.getMessage());\r
1049 \r
1050       throw new ServletModuleFailure(e);\r
1051     }\r
1052   }\r
1053 \r
1054   public void handleError(HttpServletRequest aRequest, HttpServletResponse aResponse,PrintWriter out, Throwable anException) {\r
1055     try {\r
1056       logger.error("error: " + anException);\r
1057       Map data = new HashMap();\r
1058 \r
1059       data.put("errorstring", anException.getMessage());\r
1060       data.put("date", StringUtil.date2readableDateTime(new GregorianCalendar()));\r
1061 \r
1062       deliver(out, aRequest, aResponse, data, null, configuration.getString("ServletModule.OpenIndy.ErrorTemplate"));\r
1063     }\r
1064     catch (Throwable e) {\r
1065       throw new ServletModuleFailure(e);\r
1066     }\r
1067   }\r
1068 \r
1069   public void handleUserError(HttpServletRequest aRequest, HttpServletResponse aResponse,\r
1070                                PrintWriter out, ServletModuleUserExc anException) {\r
1071     try {\r
1072       logger.warn("user error: " + anException.getMessage());\r
1073       Map data = new HashMap();\r
1074 \r
1075       MessageResources messages = MessageResources.getMessageResources("bundles.open");\r
1076       data.put("errorstring",\r
1077               messages.getMessage(getLocale(aRequest), anException.getMessage(), anException.getParameters())\r
1078           );\r
1079       data.put("date", StringUtil.date2readableDateTime(new GregorianCalendar()));\r
1080 \r
1081       deliver(out, aRequest, aResponse, data, null, configuration.getString("ServletModule.OpenIndy.UserErrorTemplate"));\r
1082     }\r
1083     catch (Throwable e) {\r
1084       throw new ServletModuleFailure(e);\r
1085     }\r
1086   }\r
1087 \r
1088 \r
1089 }\r
1090 \r
1091 \r
1092 \r