Mir goes GPL
[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.1 $ $Date: 2002/09/01 21:31:44 $
77  *
78  * $Log: ServletModuleOpenIndy.java,v $
79  * Revision 1.38.2.1  2002/09/01 21:31:44  mh
80  * Mir goes GPL
81  *
82  * Revision 1.38  2002/07/21 22:50:14  mh
83  * cleanup coding style of getpdf() method
84  *
85  * Revision 1.37  2002/07/21 22:41:45  mh
86  * make use of new MediaRequest class. A big cleanup and optimization.
87  *
88  * Revision 1.36  2002/06/29 15:45:20  mh
89  * cvs macros
90  *
91  *
92  */
93
94 public class ServletModuleOpenIndy extends ServletModule
95 {
96
97   private String        commentFormTemplate, commentFormDoneTemplate,
98                         commentFormDupeTemplate;
99   private String        postingFormTemplate, postingFormDoneTemplate,
100                         postingFormDupeTemplate;
101   private ModuleContent contentModule;
102   private ModuleImages  imageModule;
103   private ModuleTopics  themenModule;
104   private String        directOp ="yes";
105   private String        passwdProtection ="yes";
106   // Singelton / Kontruktor
107   private static ServletModuleOpenIndy instance = new ServletModuleOpenIndy();
108   public static ServletModule getInstance() { return instance; }
109
110   private ServletModuleOpenIndy() {
111     try {
112       theLog = Logfile.getInstance(MirConfig.getProp("Home") + MirConfig.getProp("ServletModule.OpenIndy.Logfile"));
113       commentFormTemplate = MirConfig.getProp("ServletModule.OpenIndy.CommentTemplate");
114       commentFormDoneTemplate = MirConfig.getProp("ServletModule.OpenIndy.CommentDoneTemplate");
115       commentFormDupeTemplate = MirConfig.getProp("ServletModule.OpenIndy.CommentDupeTemplate");
116       postingFormTemplate = MirConfig.getProp("ServletModule.OpenIndy.PostingTemplate");
117       postingFormDoneTemplate = MirConfig.getProp("ServletModule.OpenIndy.PostingDoneTemplate");
118       postingFormDupeTemplate = MirConfig.getProp("ServletModule.OpenIndy.PostingDupeTemplate");
119       directOp = MirConfig.getProp("DirectOpenposting").toLowerCase();
120                         passwdProtection = MirConfig.getProp("PasswdProtection").toLowerCase();
121       mainModule = new ModuleComment(DatabaseComment.getInstance());
122       contentModule = new ModuleContent(DatabaseContent.getInstance());
123       themenModule = new ModuleTopics(DatabaseTopics.getInstance());
124       imageModule = new ModuleImages(DatabaseImages.getInstance());
125       defaultAction="addposting";
126                         
127     }
128     catch (StorageObjectException e) {
129         theLog.printError("servletmoduleopenindy could not be initialized");
130     }
131   }
132
133
134   /**
135    *  Method for making a comment
136    */
137
138   public void addcomment(HttpServletRequest req, HttpServletResponse res) throws ServletModuleException
139   {
140     String aid = req.getParameter("aid"); // the article id the comment will belong to
141     if (aid!=null && !aid.equals(""))
142     {
143                         SimpleHash mergeData = new SimpleHash();
144
145                         // onetimepasswd
146                         if(passwdProtection.equals("yes")){
147                                 String passwd = this.createOneTimePasswd();
148                                 System.out.println(passwd);
149                                 HttpSession session = req.getSession(false);
150                                 session.setAttribute("passwd",passwd);
151                                 mergeData.put("passwd", passwd);
152                         }
153                         
154       mergeData.put("aid", aid);
155       deliver(req, res, mergeData, commentFormTemplate);
156     }
157     else throw new ServletModuleException("aid not set!");
158   }
159
160   /**
161    *  Method for inserting a comment into the Database and delivering
162    *  the commentDone Page
163    */
164
165   public void inscomment(HttpServletRequest req, HttpServletResponse res)
166         throws ServletModuleException,ServletModuleUserException
167   {
168     String aid = req.getParameter("to_media"); // the article id the comment will belong to
169     if (aid!=null && !aid.equals(""))
170     {
171       // ok, collecting data from form
172       try {
173         HashMap withValues = getIntersectingValues(req, DatabaseComment.getInstance());
174        
175         //no html in comments(for now)
176         for (Iterator i=withValues.keySet().iterator(); i.hasNext(); ){
177             String k=(String)i.next();
178             String v=(String)withValues.get(k);
179             
180             withValues.put(k,StringUtil.removeHTMLTags(v));
181         }
182         withValues.put("is_published","1");
183                                 
184                                 //checking the onetimepasswd
185                                 if(passwdProtection.equals("yes")){
186                                         HttpSession session = req.getSession(false);
187                                         String sessionPasswd = (String)session.getAttribute("passwd");
188                                         if ( sessionPasswd == null){
189                                                 throw new ServletModuleUserException("Lost password");
190                                         }
191                                         String passwd = req.getParameter("passwd");
192                                         if ( passwd == null || (!sessionPasswd.equals(passwd))) {
193                                                 throw new ServletModuleUserException("Missing password");
194                                         }
195                                         session.invalidate();
196                                 }
197                                 
198         // inserting into database
199         String id = mainModule.add(withValues);
200         theLog.printDebugInfo("id: "+id);
201         //insert was not successfull
202         if(id==null){
203           deliver(req, res, new SimpleHash(), commentFormDupeTemplate);
204         }
205         
206         // producing new page
207         new ProducerContent().handle(null, null, true, false, aid);
208
209         // sync the server
210         int exitValue = Helper.rsync();
211         theLog.printDebugInfo("rsync:"+exitValue);
212
213         // redirecting to url
214         // should implement back to article
215         SimpleHash mergeData = new SimpleHash();
216         deliver(req, res, mergeData, commentFormDoneTemplate);
217       }
218       catch (StorageObjectException e) { throw new ServletModuleException(e.toString());}
219       catch (ModuleException e) { throw new ServletModuleException(e.toString());}
220
221     }
222     else throw new ServletModuleException("aid not set!");
223
224   }
225
226   /**
227    *  Method for delivering the form-Page for open posting
228    */
229
230   public void addposting(HttpServletRequest req, HttpServletResponse res)
231     throws ServletModuleException {
232     SimpleHash mergeData = new SimpleHash();
233                 
234                 // onetimepasswd
235                 if(passwdProtection.equals("yes")){
236                         String passwd = this.createOneTimePasswd();
237                         System.out.println(passwd);
238                         HttpSession session = req.getSession(false);
239                         session.setAttribute("passwd",passwd);
240                         mergeData.put("passwd", passwd);
241                 }
242                         
243     String maxMedia = MirConfig.getProp("ServletModule.OpenIndy.MaxMediaUploadItems");
244     String numOfMedia = req.getParameter("medianum");
245     if(numOfMedia==null||numOfMedia.equals("")){
246       numOfMedia="1";
247     } else if(Integer.parseInt(numOfMedia) > Integer.parseInt(maxMedia)) {
248       numOfMedia = maxMedia;
249     }
250     
251     int mediaNum = Integer.parseInt(numOfMedia);
252     SimpleList mediaFields = new SimpleList();
253     for(int i =0; i<mediaNum;i++){
254       Integer mNum = new Integer(i+1);
255       mediaFields.add(mNum.toString());
256     }
257     mergeData.put("medianum",numOfMedia);
258     mergeData.put("mediafields",mediaFields);
259     
260     
261     SimpleHash extraInfo = new SimpleHash();
262     try{
263       SimpleList popUpData = DatabaseLanguage.getInstance().getPopupData();
264       extraInfo.put("languagePopUpData", popUpData );
265       extraInfo.put("themenPopupData", themenModule.getTopicsAsSimpleList());
266     } catch (Exception e) {
267       theLog.printError("languagePopUpData or getTopicslist failed "
268                         +e.toString());
269       throw new ServletModuleException("OpenIndy -- failed getting language or topics: "+e.toString());
270     }
271       
272     deliver(req, res, mergeData, extraInfo, postingFormTemplate);
273   }
274
275   /**
276    *  Method for inserting an open posting into the Database and delivering
277    *  the postingDone Page
278    */
279
280   public void insposting(HttpServletRequest req, HttpServletResponse res)
281     throws ServletModuleException, ServletModuleUserException
282   {
283     SimpleHash mergeData = new SimpleHash();
284     boolean setMedia=false;
285                 boolean setTopic = false;
286
287     try {
288       WebdbMultipartRequest mp = new WebdbMultipartRequest(req);
289
290       EntityList mediaList = null;
291       try {
292         // new MediaRequest, "1" is the id for the openPosting user
293         mediaList = new MediaRequest(mp, "1").getMedia(true, true);
294       } catch (MirMediaUserException e) {
295         throw new ServletModuleUserException(e.getMsg());
296       }
297           
298       HashMap withValues = mp.getParameters();
299                                                         
300                         //checking the onetimepasswd
301                         if(passwdProtection.equals("yes")){
302                                 HttpSession session = req.getSession(false);
303                                 String sessionPasswd = (String)session.getAttribute("passwd");
304                                 if ( sessionPasswd == null){
305                                         throw new ServletModuleUserException("Lost password");
306                                 }
307                                 String passwd = (String)withValues.get("passwd");
308                                 if ( passwd == null || (!sessionPasswd.equals(passwd))) {
309                                         throw new ServletModuleUserException("Missing password");
310                                 }
311                                 session.invalidate();
312                         }
313
314       if ((((String)withValues.get("title")).length() == 0) ||
315           (((String)withValues.get("description")).length() == 0) ||
316           (((String)withValues.get("content_data")).length() == 0))
317             throw new ServletModuleUserException("Missing field");
318       
319       // call the routines that escape html
320
321       for (Iterator i=withValues.keySet().iterator(); i.hasNext(); ){
322         String k=(String)i.next();
323         String v=(String)withValues.get(k);
324         
325         if (k.equals("content_data")){
326           //this doesn't quite work yet, so for now, all html goes
327           //withValues.put(k,StringUtil.approveHTMLTags(v));
328           //withValues.put(k,StringUtil.removeHTMLTags(v));
329         } else {
330           withValues.put(k,StringUtil.removeHTMLTags(v));
331         }
332         
333       }
334
335       withValues.put("date", StringUtil.date2webdbDate(new GregorianCalendar()));
336       withValues.put("publish_path", StringUtil.webdbDate2path((String)withValues.get("date")));
337       withValues.put("is_produced", "0");
338       // by default stuff is published, they can be un-published through the
339       // admin interface.
340       withValues.put("is_published","1");
341       // if op direct article-type == newswire
342       if (directOp.equals("yes")) withValues.put("to_article_type","1");
343       
344       // owner is openposting user
345       withValues.put("to_publisher","1");
346       if (withValues.get("creator").toString().equals(""))
347         withValues.put("creator","Anonym");
348
349       // inserting  content into database
350       String cid = contentModule.add(withValues);
351       theLog.printDebugInfo("id: "+cid);
352       //insert was not successfull
353       if(cid==null){
354         //How do we know that it was not succesful cause of a
355         //dupe, what if it failed cause of "No space left on device"?
356         //Or is there something I am missing? Wouldn't it be better
357         //to have an explicit dupe check and then insert? I have no
358         //idea what I am talking about. this comment is in case
359         //I forget to explicitely ask. -mh
360         deliver(req, res, mergeData, postingFormDupeTemplate);
361       }
362
363       String[] to_topicsArr = mp.getParameterValues("to_topic");
364       
365                         if (to_topicsArr != null && to_topicsArr.length > 0) {
366         try{
367           DatabaseContentToTopics.getInstance().setTopics(cid,to_topicsArr);
368           setTopic = true;
369         } catch (Exception e) {
370           theLog.printError("setting content_x_topic failed");
371           contentModule.deleteById(cid);
372           throw new ServletModuleException("smod - openindy :: insposting: setting content_x_topic failed: "+e.toString());
373         } //end try
374       } //end if
375        
376       //if we're here all is ok... associate the media to the article
377       for(int i=0;i<mediaList.size();i++) {
378         Entity mediaEnt = (Entity)mediaList.elementAt(i);
379         DatabaseContentToMedia.getInstance().addMedia(cid,mediaEnt.getId());
380       }
381
382       // producing openpostinglist
383       new ProducerOpenPosting().handle(null,null,false,false);
384       // producing new page
385       new ProducerContent().handle(null, null, false, false,cid);
386       //if direct op producing startpage
387       if (directOp.equals("yes")) new ProducerStartPage().handle(null,null);
388       
389                         //produce the topicPages if set
390                         //should be more intelligent
391                         //if(setTopic==true) new ProducerTopics().handle(null,null);
392                         
393       // sync the server
394       //should be configureable
395       int exitValue = Helper.rsync();
396       theLog.printDebugInfo("rsync: "+exitValue);
397
398     }
399     catch (MirMediaException e) { throw new ServletModuleException("MediaException: "+ e.toString());}
400     catch (IOException e) { throw new ServletModuleException("IOException: "+ e.toString());}
401     catch (StorageObjectException e) { throw new ServletModuleException("StorageObjectException" + e.toString());}
402     catch (ModuleException e) { throw new ServletModuleException("ModuleException"+e.toString());}
403
404     deliver(req, res, mergeData, postingFormDoneTemplate);
405   }
406
407   /*
408    * Method for dynamically generating a pdf from a fo file
409    */
410   public void getpdf(HttpServletRequest req, HttpServletResponse res)
411     throws ServletModuleException, ServletModuleUserException {
412     String ID_REQUEST_PARAM = "id";
413     
414     String generateFO=MirConfig.getProp("GenerateFO");
415     String generatePDF=MirConfig.getProp("GeneratePDF");
416
417     //don't do anything if we are not making FO files, or if we are
418     //pregenerating PDF's
419     if (generateFO.equals("yes") && generatePDF.equals("no")){
420       //fop complains unless you do the logging this way
421       Logger log = null;
422       Hierarchy hierarchy = Hierarchy.getDefaultHierarchy();
423       log = hierarchy.getLoggerFor("fop");
424       log.setPriority(Priority.WARN);
425     
426       String producerStorageRoot=MirConfig.getProp("Producer.StorageRoot");
427       String producerDocRoot=MirConfig.getProp("Producer.DocRoot");
428       String templateDir=MirConfig.getPropWithHome("HTMLTemplateProcessor.Dir");
429       String xslSheet=templateDir + "/" 
430         + MirConfig.getProp("Producer.PrintableContent.html2foStyleSheetName");
431       try {
432         String idParam = req.getParameter(ID_REQUEST_PARAM);
433         if (idParam != null) {
434           EntityContent contentEnt =
435             (EntityContent)contentModule.getById(idParam);
436           String publishPath = contentEnt.getValue("publish_path");
437           String foFile = producerStorageRoot + producerDocRoot + "/" 
438                           + publishPath + "/" + idParam + ".fo";
439           XSLTInputHandler input = new XSLTInputHandler(new File(foFile), 
440                                                        new File(xslSheet));
441           
442           ByteArrayOutputStream out = new ByteArrayOutputStream();
443           res.setContentType("application/pdf");
444
445           Driver driver = new Driver();
446           driver.setLogger(log);
447           driver.setRenderer(Driver.RENDER_PDF);
448           driver.setOutputStream(out);
449           driver.render(input.getParser(), input.getInputSource());
450
451           byte[] content = out.toByteArray();
452           res.setContentLength(content.length);
453           res.getOutputStream().write(content);
454           res.getOutputStream().flush();
455         } else {
456           throw new ServletModuleUserException("Missing id parameter.");
457         }
458       } catch (Exception ex) {
459         throw new ServletModuleException(ex.toString());
460       }
461     } else {
462       throw new ServletModuleUserException("Can't generate a PDF because the config tells me not to.");
463     }
464   }
465   
466   private void _throwBadContentType (String fileName, String contentType)
467     throws ServletModuleUserException {
468
469     theLog.printDebugInfo("Wrong file type uploaded!: " + fileName+" "
470                           +contentType);
471     throw new ServletModuleUserException("The file you uploaded is of the "
472         +"following mime-type: "+contentType
473         +", we do not support this mime-type. "
474         +"Error One or more files of unrecognized type. Sorry");
475   }
476         
477         protected String createOneTimePasswd(){
478                 Random r = new Random();
479                 int random = r.nextInt();
480                 long l = System.currentTimeMillis();
481                 l = (l*l*l*l)/random;
482                 if(l<0) l = l * -1;
483                 String returnString = ""+l;
484                 return returnString.substring(5);
485         }
486       
487 }
488
489
490