2 * Copyright (C) 2001, 2002 The Mir-coders group
4 * This file is part of Mir.
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.
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.
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
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.
32 package mircoders.servlet;
39 import java.lang.reflect.*;
40 import javax.servlet.*;
41 import javax.servlet.http.*;
43 import freemarker.template.*;
44 import com.oreilly.servlet.multipart.*;
45 import com.oreilly.servlet.*;
47 import org.xml.sax.InputSource;
48 import org.xml.sax.XMLReader;
50 import org.apache.fop.apps.Driver;
51 import org.apache.fop.apps.Version;
52 import org.apache.fop.apps.XSLTInputHandler;
54 import org.apache.log.*;
63 import mircoders.entity.*;
64 import mircoders.storage.*;
65 import mircoders.module.*;
66 import mircoders.producer.*;
67 import mircoders.media.MediaRequest;
70 * ServletModuleOpenIndy -
71 * is the open-access-servlet, which is responsible for
72 * adding comments to articles &
73 * open-postings to the newswire
75 * @author $Author: mh $
76 * @version $Revision: 1.38.2.2 $ $Date: 2002/11/01 05:38:21 $
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.
84 * A new temporary file (for JAI) parameter is necessary and is in the config.properties file.
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.
93 * Revision 1.38.2.1 2002/09/01 21:31:44 mh
96 * Revision 1.38 2002/07/21 22:50:14 mh
97 * cleanup coding style of getpdf() method
99 * Revision 1.37 2002/07/21 22:41:45 mh
100 * make use of new MediaRequest class. A big cleanup and optimization.
102 * Revision 1.36 2002/06/29 15:45:20 mh
108 public class ServletModuleOpenIndy extends ServletModule
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; }
124 private ServletModuleOpenIndy() {
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";
142 catch (StorageObjectException e) {
143 theLog.printError("servletmoduleopenindy could not be initialized");
149 * Method for making a comment
152 public void addcomment(HttpServletRequest req, HttpServletResponse res) throws ServletModuleException
154 String aid = req.getParameter("aid"); // the article id the comment will belong to
155 if (aid!=null && !aid.equals(""))
157 SimpleHash mergeData = new SimpleHash();
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);
168 mergeData.put("aid", aid);
169 deliver(req, res, mergeData, commentFormTemplate);
171 else throw new ServletModuleException("aid not set!");
175 * Method for inserting a comment into the Database and delivering
176 * the commentDone Page
179 public void inscomment(HttpServletRequest req, HttpServletResponse res)
180 throws ServletModuleException,ServletModuleUserException
182 String aid = req.getParameter("to_media"); // the article id the comment will belong to
183 if (aid!=null && !aid.equals(""))
185 // ok, collecting data from form
187 HashMap withValues = getIntersectingValues(req, DatabaseComment.getInstance());
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);
194 withValues.put(k,StringUtil.removeHTMLTags(v));
196 withValues.put("is_published","1");
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");
205 String passwd = req.getParameter("passwd");
206 if ( passwd == null || (!sessionPasswd.equals(passwd))) {
207 throw new ServletModuleUserException("Missing password");
209 session.invalidate();
212 // inserting into database
213 String id = mainModule.add(withValues);
214 theLog.printDebugInfo("id: "+id);
215 //insert was not successfull
217 deliver(req, res, new SimpleHash(), commentFormDupeTemplate);
220 // producing new page
221 new ProducerContent().handle(null, null, true, false, aid);
224 int exitValue = Helper.rsync();
225 theLog.printDebugInfo("rsync:"+exitValue);
227 // redirecting to url
228 // should implement back to article
229 SimpleHash mergeData = new SimpleHash();
230 deliver(req, res, mergeData, commentFormDoneTemplate);
232 catch (StorageObjectException e) { throw new ServletModuleException(e.toString());}
233 catch (ModuleException e) { throw new ServletModuleException(e.toString());}
236 else throw new ServletModuleException("aid not set!");
241 * Method for delivering the form-Page for open posting
244 public void addposting(HttpServletRequest req, HttpServletResponse res)
245 throws ServletModuleException {
246 SimpleHash mergeData = new SimpleHash();
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);
257 String maxMedia = MirConfig.getProp("ServletModule.OpenIndy.MaxMediaUploadItems");
258 String numOfMedia = req.getParameter("medianum");
259 if(numOfMedia==null||numOfMedia.equals("")){
261 } else if(Integer.parseInt(numOfMedia) > Integer.parseInt(maxMedia)) {
262 numOfMedia = maxMedia;
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());
271 mergeData.put("medianum",numOfMedia);
272 mergeData.put("mediafields",mediaFields);
275 SimpleHash extraInfo = new SimpleHash();
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 "
283 throw new ServletModuleException("OpenIndy -- failed getting language or topics: "+e.toString());
286 deliver(req, res, mergeData, extraInfo, postingFormTemplate);
290 * Method for inserting an open posting into the Database and delivering
291 * the postingDone Page
294 public void insposting(HttpServletRequest req, HttpServletResponse res)
295 throws ServletModuleException, ServletModuleUserException
297 SimpleHash mergeData = new SimpleHash();
298 boolean setMedia=false;
299 boolean setTopic = false;
303 WebdbMultipartRequest mp = null;
304 EntityList mediaList = null;
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());
314 HashMap withValues = mp.getParameters();
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");
323 String passwd = (String)withValues.get("passwd");
324 if ( passwd == null || (!sessionPasswd.equals(passwd))) {
325 throw new ServletModuleUserException("Missing password");
327 session.invalidate();
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");
335 // call the routines that escape html
337 for (Iterator i=withValues.keySet().iterator(); i.hasNext(); ){
338 String k=(String)i.next();
339 String v=(String)withValues.get(k);
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));
346 withValues.put(k,StringUtil.removeHTMLTags(v));
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
356 withValues.put("is_published","1");
357 // if op direct article-type == newswire
358 if (directOp.equals("yes")) withValues.put("to_article_type","1");
360 // owner is openposting user
361 withValues.put("to_publisher","1");
362 if (withValues.get("creator").toString().equals(""))
363 withValues.put("creator","Anonym");
365 // inserting content into database
366 String cid = contentModule.add(withValues);
367 theLog.printDebugInfo("id: "+cid);
368 //insert was not successfull
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);
379 String[] to_topicsArr = mp.getParameterValues("to_topic");
381 if (to_topicsArr != null && to_topicsArr.length > 0) {
383 DatabaseContentToTopics.getInstance().setTopics(cid,to_topicsArr);
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());
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());
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);
405 //produce the topicPages if set
406 //should be more intelligent
407 //if(setTopic==true) new ProducerTopics().handle(null,null);
410 //should be configureable
411 int exitValue = Helper.rsync();
412 theLog.printDebugInfo("rsync: "+exitValue);
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());}
420 deliver(req, res, mergeData, postingFormDoneTemplate);
424 * Method for dynamically generating a pdf from a fo file
426 public void getpdf(HttpServletRequest req, HttpServletResponse res)
427 throws ServletModuleException, ServletModuleUserException {
428 String ID_REQUEST_PARAM = "id";
430 String generateFO=MirConfig.getProp("GenerateFO");
431 String generatePDF=MirConfig.getProp("GeneratePDF");
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
438 Hierarchy hierarchy = Hierarchy.getDefaultHierarchy();
439 log = hierarchy.getLoggerFor("fop");
440 log.setPriority(Priority.WARN);
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");
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),
458 ByteArrayOutputStream out = new ByteArrayOutputStream();
459 res.setContentType("application/pdf");
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());
467 byte[] content = out.toByteArray();
468 res.setContentLength(content.length);
469 res.getOutputStream().write(content);
470 res.getOutputStream().flush();
472 throw new ServletModuleUserException("Missing id parameter.");
474 } catch (Exception ex) {
475 throw new ServletModuleException(ex.toString());
478 throw new ServletModuleUserException("Can't generate a PDF because the config tells me not to.");
482 private void _throwBadContentType (String fileName, String contentType)
483 throws ServletModuleUserException {
485 theLog.printDebugInfo("Wrong file type uploaded!: " + fileName+" "
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");
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;
499 String returnString = ""+l;
500 return returnString.substring(5);