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