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