89d8237f20ac972d8993aa8be288680e67bed2c0
[mir.git] / source / mircoders / servlet / ServletModuleOpenIndy.java
1 /*
2  * Copyright (C) 2001, 2002  The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with the com.oreilly.servlet library, any library
22  * licensed under the Apache Software License, The Sun (tm) Java Advanced
23  * Imaging library (JAI), The Sun JIMI library (or with modified versions of
24  * the above that use the same license as the above), and distribute linked
25  * combinations including the two.  You must obey the GNU General Public
26  * License in all respects for all of the code used other than the above
27  * mentioned libraries.  If you modify this file, you may extend this exception
28  * to your version of the file, but you are not obligated to do so.  If you do
29  * not wish to do so, delete this exception statement from your version.
30  */
31
32 package mircoders.servlet;
33
34 import java.io.*;
35 import java.lang.*;
36 import java.sql.*;
37 import java.util.*;
38 import java.net.*;
39 import java.lang.reflect.*;
40 import javax.servlet.*;
41 import javax.servlet.http.*;
42
43 import freemarker.template.*;
44 import com.oreilly.servlet.multipart.*;
45 import com.oreilly.servlet.*;
46
47 import org.xml.sax.InputSource;
48 import org.xml.sax.XMLReader;
49
50 import org.apache.fop.apps.Driver;
51 import org.apache.fop.apps.Version;
52 import org.apache.fop.apps.XSLTInputHandler;
53
54 import org.apache.log.*;
55
56 import mir.servlet.*;
57 import mir.module.*;
58 import mir.misc.*;
59 import mir.entity.*;
60 import mir.storage.*;
61 import mir.media.*;
62
63 import mircoders.entity.*;
64 import mircoders.storage.*;
65 import mircoders.module.*;
66 import mircoders.producer.*;
67 import mircoders.media.MediaRequest;
68
69 /*
70  *  ServletModuleOpenIndy -
71  *   is the open-access-servlet, which is responsible for
72  *    adding comments to articles &
73  *    open-postings to the newswire
74  *
75  * @author $Author: mh $
76  * @version $Revision: 1.38.2.4 $ $Date: 2002/12/10 10:19:03 $
77  *
78  */
79
80 public class ServletModuleOpenIndy extends ServletModule
81 {
82
83   private String        commentFormTemplate, commentFormDoneTemplate,
84                         commentFormDupeTemplate;
85   private String        postingFormTemplate, postingFormDoneTemplate,
86                         postingFormDupeTemplate;
87   private ModuleContent contentModule;
88   private ModuleImages  imageModule;
89   private ModuleTopics  themenModule;
90   private String        directOp ="yes";
91   private String        passwdProtection ="yes";
92   // Singelton / Kontruktor
93   private static ServletModuleOpenIndy instance = new ServletModuleOpenIndy();
94   public static ServletModule getInstance() { return instance; }
95
96   private ServletModuleOpenIndy() {
97     try {
98       theLog = Logfile.getInstance(MirConfig.getProp("Home") + MirConfig.getProp("ServletModule.OpenIndy.Logfile"));
99       commentFormTemplate = MirConfig.getProp("ServletModule.OpenIndy.CommentTemplate");
100       commentFormDoneTemplate = MirConfig.getProp("ServletModule.OpenIndy.CommentDoneTemplate");
101       commentFormDupeTemplate = MirConfig.getProp("ServletModule.OpenIndy.CommentDupeTemplate");
102       postingFormTemplate = MirConfig.getProp("ServletModule.OpenIndy.PostingTemplate");
103       postingFormDoneTemplate = MirConfig.getProp("ServletModule.OpenIndy.PostingDoneTemplate");
104       postingFormDupeTemplate = MirConfig.getProp("ServletModule.OpenIndy.PostingDupeTemplate");
105       directOp = MirConfig.getProp("DirectOpenposting").toLowerCase();
106                         passwdProtection = MirConfig.getProp("PasswdProtection").toLowerCase();
107       mainModule = new ModuleComment(DatabaseComment.getInstance());
108       contentModule = new ModuleContent(DatabaseContent.getInstance());
109       themenModule = new ModuleTopics(DatabaseTopics.getInstance());
110       imageModule = new ModuleImages(DatabaseImages.getInstance());
111       defaultAction="addposting";
112                         
113     }
114     catch (StorageObjectException e) {
115         theLog.printError("servletmoduleopenindy could not be initialized");
116     }
117   }
118
119
120   /**
121    *  Method for making a comment
122    */
123
124   public void addcomment(HttpServletRequest req, HttpServletResponse res) throws ServletModuleException
125   {
126     String aid = req.getParameter("aid"); // the article id the comment will belong to
127     if (aid!=null && !aid.equals(""))
128     {
129                         SimpleHash mergeData = new SimpleHash();
130
131                         // onetimepasswd
132                         if(passwdProtection.equals("yes")){
133                                 String passwd = this.createOneTimePasswd();
134                                 System.out.println(passwd);
135                                 HttpSession session = req.getSession(false);
136                                 session.setAttribute("passwd",passwd);
137                                 mergeData.put("passwd", passwd);
138                         }
139                         
140       mergeData.put("aid", aid);
141       deliver(req, res, mergeData, commentFormTemplate);
142     }
143     else throw new ServletModuleException("aid not set!");
144   }
145
146   /**
147    *  Method for inserting a comment into the Database and delivering
148    *  the commentDone Page
149    */
150
151   public void inscomment(HttpServletRequest req, HttpServletResponse res)
152         throws ServletModuleException,ServletModuleUserException
153   {
154     String aid = req.getParameter("to_media"); // the article id the comment will belong to
155     if (aid!=null && !aid.equals(""))
156     {
157       // ok, collecting data from form
158       try {
159         HashMap withValues = getIntersectingValues(req, DatabaseComment.getInstance());
160        
161         //no html in comments(for now)
162         for (Iterator i=withValues.keySet().iterator(); i.hasNext(); ){
163             String k=(String)i.next();
164             String v=(String)withValues.get(k);
165             
166             withValues.put(k,StringUtil.removeHTMLTags(v));
167         }
168         withValues.put("is_published","1");
169                                 
170                                 //checking the onetimepasswd
171                                 if(passwdProtection.equals("yes")){
172                                         HttpSession session = req.getSession(false);
173                                         String sessionPasswd = (String)session.getAttribute("passwd");
174                                         if ( sessionPasswd == null){
175                                                 throw new ServletModuleUserException("Lost password");
176                                         }
177                                         String passwd = req.getParameter("passwd");
178                                         if ( passwd == null || (!sessionPasswd.equals(passwd))) {
179                                                 throw new ServletModuleUserException("Missing password");
180                                         }
181                                         session.invalidate();
182                                 }
183                                 
184         // inserting into database
185         String id = mainModule.add(withValues);
186         theLog.printDebugInfo("id: "+id);
187         //insert was not successfull
188         if(id==null){
189           deliver(req, res, new SimpleHash(), commentFormDupeTemplate);
190         }
191         
192         // producing new page
193         new ProducerContent().handle(null, null, true, false, aid);
194
195         // sync the server
196         int exitValue = Helper.rsync();
197         theLog.printDebugInfo("rsync:"+exitValue);
198
199         // redirecting to url
200         // should implement back to article
201         SimpleHash mergeData = new SimpleHash();
202         deliver(req, res, mergeData, commentFormDoneTemplate);
203       }
204       catch (StorageObjectException e) { throw new ServletModuleException(e.toString());}
205       catch (ModuleException e) { throw new ServletModuleException(e.toString());}
206
207     }
208     else throw new ServletModuleException("aid not set!");
209
210   }
211
212   /**
213    *  Method for delivering the form-Page for open posting
214    */
215
216   public void addposting(HttpServletRequest req, HttpServletResponse res)
217     throws ServletModuleException {
218     SimpleHash mergeData = new SimpleHash();
219                 
220                 // onetimepasswd
221                 if(passwdProtection.equals("yes")){
222                         String passwd = this.createOneTimePasswd();
223                         System.out.println(passwd);
224                         HttpSession session = req.getSession(false);
225                         session.setAttribute("passwd",passwd);
226                         mergeData.put("passwd", passwd);
227                 }
228                         
229     String maxMedia = MirConfig.getProp("ServletModule.OpenIndy.MaxMediaUploadItems");
230     String numOfMedia = req.getParameter("medianum");
231     if(numOfMedia==null||numOfMedia.equals("")){
232       numOfMedia="1";
233     } else if(Integer.parseInt(numOfMedia) > Integer.parseInt(maxMedia)) {
234       numOfMedia = maxMedia;
235     }
236     
237     int mediaNum = Integer.parseInt(numOfMedia);
238     SimpleList mediaFields = new SimpleList();
239     for(int i =0; i<mediaNum;i++){
240       Integer mNum = new Integer(i+1);
241       mediaFields.add(mNum.toString());
242     }
243     mergeData.put("medianum",numOfMedia);
244     mergeData.put("mediafields",mediaFields);
245     
246     
247     SimpleHash extraInfo = new SimpleHash();
248     try{
249       SimpleList popUpData = DatabaseLanguage.getInstance().getPopupData();
250       extraInfo.put("languagePopUpData", popUpData );
251       extraInfo.put("themenPopupData", themenModule.getTopicsAsSimpleList());
252     } catch (Exception e) {
253       theLog.printError("languagePopUpData or getTopicslist failed "
254                         +e.toString());
255       throw new ServletModuleException("OpenIndy -- failed getting language or topics: "+e.toString());
256     }
257       
258     deliver(req, res, mergeData, extraInfo, postingFormTemplate);
259   }
260
261   /**
262    *  Method for inserting an open posting into the Database and delivering
263    *  the postingDone Page
264    */
265
266   public void insposting(HttpServletRequest req, HttpServletResponse res)
267     throws ServletModuleException, ServletModuleUserException
268   {
269     SimpleHash mergeData = new SimpleHash();
270     boolean setMedia=false;
271                 boolean setTopic = false;
272
273     try {
274
275       WebdbMultipartRequest mp = null;
276       EntityList mediaList = null;
277       try {
278         // new MediaRequest, "1" is the id for the openPosting user
279         MediaRequest mediaReq = new MediaRequest("1", true, true);
280         mp = new WebdbMultipartRequest(req, (FileHandler)mediaReq);
281         mediaList = mediaReq.getEntityList();
282       } catch (FileHandlerUserException e) {
283         throw new ServletModuleUserException(e.getMsg());
284       }
285           
286       HashMap withValues = mp.getParameters();
287                                                         
288                         //checking the onetimepasswd
289                         if(passwdProtection.equals("yes")){
290                                 HttpSession session = req.getSession(false);
291                                 String sessionPasswd = (String)session.getAttribute("passwd");
292                                 if ( sessionPasswd == null){
293                                         throw new ServletModuleUserException("Lost password");
294                                 }
295                                 String passwd = (String)withValues.get("passwd");
296                                 if ( passwd == null || (!sessionPasswd.equals(passwd))) {
297                                         throw new ServletModuleUserException("Missing password");
298                                 }
299                                 session.invalidate();
300                         }
301
302       if ((((String)withValues.get("title")).length() == 0) ||
303           (((String)withValues.get("description")).length() == 0) ||
304           (((String)withValues.get("content_data")).length() == 0))
305             throw new ServletModuleUserException("Missing field");
306       
307       // call the routines that escape html
308
309       for (Iterator i=withValues.keySet().iterator(); i.hasNext(); ){
310         String k=(String)i.next();
311         String v=(String)withValues.get(k);
312         
313         if (k.equals("content_data")){
314           //this doesn't quite work yet, so for now, just delete the really
315           //bad ones.
316           //withValues.put(k,StringUtil.approveHTMLTags(v));
317           withValues.put(k,StringUtil.deleteForbiddenTags(v));
318         } else if (k.equals("description")) {
319           withValues.put(k,StringUtil.deleteForbiddenTags(v));
320           withValues.put(k,StringUtil.deleteHTMLTableTags(v));
321         } else {
322           //we don't want people fucking with the author/title, etc..
323           withValues.put(k,StringUtil.removeHTMLTags(v));
324         }
325
326         
327       }
328
329       withValues.put("date", StringUtil.date2webdbDate(new GregorianCalendar()));
330       withValues.put("publish_path", StringUtil.webdbDate2path((String)withValues.get("date")));
331       withValues.put("is_produced", "0");
332       // by default stuff is published, they can be un-published through the
333       // admin interface.
334       withValues.put("is_published","1");
335       // if op direct article-type == newswire
336       if (directOp.equals("yes")) withValues.put("to_article_type","1");
337       
338       // owner is openposting user
339       withValues.put("to_publisher","1");
340       if (withValues.get("creator").toString().equals(""))
341         withValues.put("creator","Anonym");
342
343       // inserting  content into database
344       String cid = contentModule.add(withValues);
345       theLog.printDebugInfo("id: "+cid);
346       //insert was not successfull
347       if(cid==null){
348         //How do we know that it was not succesful cause of a
349         //dupe, what if it failed cause of "No space left on device"?
350         //Or is there something I am missing? Wouldn't it be better
351         //to have an explicit dupe check and then insert? I have no
352         //idea what I am talking about. this comment is in case
353         //I forget to explicitely ask. -mh
354         deliver(req, res, mergeData, postingFormDupeTemplate);
355       }
356
357       String[] to_topicsArr = mp.getParameterValues("to_topic");
358       
359                         if (to_topicsArr != null && to_topicsArr.length > 0) {
360         try{
361           DatabaseContentToTopics.getInstance().setTopics(cid,to_topicsArr);
362           setTopic = true;
363         } catch (Exception e) {
364           theLog.printError("setting content_x_topic failed");
365           contentModule.deleteById(cid);
366           throw new ServletModuleException("smod - openindy :: insposting: setting content_x_topic failed: "+e.toString());
367         } //end try
368       } //end if
369        
370       //if we're here all is ok... associate the media to the article
371       for(int i=0;i<mediaList.size();i++) {
372         Entity mediaEnt = (Entity)mediaList.elementAt(i);
373         DatabaseContentToMedia.getInstance().addMedia(cid,mediaEnt.getId());
374       }
375
376       // producing openpostinglist
377       new ProducerOpenPosting().handle(null,null,false,false);
378       // producing new page
379       new ProducerContent().handle(null, null, false, false,cid);
380       //if direct op producing startpage
381       if (directOp.equals("yes")) new ProducerStartPage().handle(null,null);
382       
383                         //produce the topicPages if set
384                         //should be more intelligent
385                         //if(setTopic==true) new ProducerTopics().handle(null,null);
386                         
387       // sync the server
388       //should be configureable
389       int exitValue = Helper.rsync();
390       theLog.printDebugInfo("rsync: "+exitValue);
391
392     }
393     catch (FileHandlerException e) { throw new ServletModuleException("MediaException: "+ e.toString());}
394     catch (IOException e) { throw new ServletModuleException("IOException: "+ e.toString());}
395     catch (StorageObjectException e) { throw new ServletModuleException("StorageObjectException" + e.toString());}
396     catch (ModuleException e) { throw new ServletModuleException("ModuleException"+e.toString());}
397
398     deliver(req, res, mergeData, postingFormDoneTemplate);
399   }
400
401   /*
402    * Method for dynamically generating a pdf from a fo file
403    */
404   public void getpdf(HttpServletRequest req, HttpServletResponse res)
405     throws ServletModuleException, ServletModuleUserException {
406     String ID_REQUEST_PARAM = "id";
407     
408     String generateFO=MirConfig.getProp("GenerateFO");
409     String generatePDF=MirConfig.getProp("GeneratePDF");
410
411     //don't do anything if we are not making FO files, or if we are
412     //pregenerating PDF's
413     if (generateFO.equals("yes") && generatePDF.equals("no")){
414       //fop complains unless you do the logging this way
415       Logger log = null;
416       Hierarchy hierarchy = Hierarchy.getDefaultHierarchy();
417       log = hierarchy.getLoggerFor("fop");
418       log.setPriority(Priority.WARN);
419     
420       String producerStorageRoot=MirConfig.getProp("Producer.StorageRoot");
421       String producerDocRoot=MirConfig.getProp("Producer.DocRoot");
422       String templateDir=MirConfig.getPropWithHome("HTMLTemplateProcessor.Dir");
423       String xslSheet=templateDir + "/" 
424         + MirConfig.getProp("Producer.PrintableContent.html2foStyleSheetName");
425       try {
426         String idParam = req.getParameter(ID_REQUEST_PARAM);
427         if (idParam != null) {
428           EntityContent contentEnt =
429             (EntityContent)contentModule.getById(idParam);
430           String publishPath = contentEnt.getValue("publish_path");
431           String foFile = producerStorageRoot + producerDocRoot + "/" 
432                           + publishPath + "/" + idParam + ".fo";
433           XSLTInputHandler input = new XSLTInputHandler(new File(foFile), 
434                                                        new File(xslSheet));
435           
436           ByteArrayOutputStream out = new ByteArrayOutputStream();
437           res.setContentType("application/pdf");
438
439           Driver driver = new Driver();
440           driver.setLogger(log);
441           driver.setRenderer(Driver.RENDER_PDF);
442           driver.setOutputStream(out);
443           driver.render(input.getParser(), input.getInputSource());
444
445           byte[] content = out.toByteArray();
446           res.setContentLength(content.length);
447           res.getOutputStream().write(content);
448           res.getOutputStream().flush();
449         } else {
450           throw new ServletModuleUserException("Missing id parameter.");
451         }
452       } catch (Exception ex) {
453         throw new ServletModuleException(ex.toString());
454       }
455     } else {
456       throw new ServletModuleUserException("Can't generate a PDF because the config tells me not to.");
457     }
458   }
459   
460   private void _throwBadContentType (String fileName, String contentType)
461     throws ServletModuleUserException {
462
463     theLog.printDebugInfo("Wrong file type uploaded!: " + fileName+" "
464                           +contentType);
465     throw new ServletModuleUserException("The file you uploaded is of the "
466         +"following mime-type: "+contentType
467         +", we do not support this mime-type. "
468         +"Error One or more files of unrecognized type. Sorry");
469   }
470         
471         protected String createOneTimePasswd(){
472                 Random r = new Random();
473                 int random = r.nextInt();
474                 long l = System.currentTimeMillis();
475                 l = (l*l*l*l)/random;
476                 if(l<0) l = l * -1;
477                 String returnString = ""+l;
478                 return returnString.substring(5);
479         }
480       
481 }
482
483
484