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