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;
34 import java.io.ByteArrayOutputStream;
36 import java.io.FileNotFoundException;
37 import java.io.FileReader;
38 import java.io.IOException;
39 import java.io.PrintWriter;
40 import java.io.StringWriter;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.Collections;
44 import java.util.Date;
45 import java.util.Enumeration;
46 import java.util.GregorianCalendar;
47 import java.util.HashMap;
48 import java.util.Iterator;
49 import java.util.List;
50 import java.util.ListIterator;
52 import java.util.Random;
54 import java.util.Vector;
55 import java.util.Locale;
56 import javax.servlet.http.HttpServletRequest;
57 import javax.servlet.http.HttpServletResponse;
58 import javax.servlet.http.HttpSession;
60 import org.apache.commons.net.smtp.SMTPClient;
61 import org.apache.commons.net.smtp.SMTPReply;
62 import org.apache.fop.apps.Driver;
63 import org.apache.fop.apps.XSLTInputHandler;
64 import org.apache.log.Hierarchy;
65 import org.apache.log.Priority;
66 import org.apache.lucene.analysis.standard.StandardAnalyzer;
67 import org.apache.lucene.document.Document;
68 import org.apache.lucene.queryParser.QueryParser;
69 import org.apache.lucene.search.Hits;
70 import org.apache.lucene.search.IndexSearcher;
71 import org.apache.lucene.search.Query;
72 import org.apache.lucene.search.Searcher;
73 import org.apache.struts.util.MessageResources;
74 import mir.entity.Entity;
75 import mir.entity.EntityList;
76 import mir.generator.Generator;
77 import mir.log.LoggerWrapper;
78 import mir.misc.FileHandler;
79 import mir.misc.StringUtil;
80 import mir.misc.WebdbMultipartRequest;
81 import mir.servlet.ServletModule;
82 import mir.servlet.ServletModuleExc;
83 import mir.servlet.ServletModuleFailure;
84 import mir.servlet.ServletModuleUserExc;
85 import mir.storage.StorageObjectFailure;
86 import mir.util.ExceptionFunctions;
87 import mir.util.HTTPRequestParser;
88 import mir.util.StringRoutines;
89 import mircoders.entity.EntityComment;
90 import mircoders.entity.EntityContent;
91 import mircoders.global.MirGlobal;
92 import mircoders.media.MediaRequest;
93 import mircoders.media.UnsupportedMediaFormatExc;
94 import mircoders.module.ModuleComment;
95 import mircoders.module.ModuleContent;
96 import mircoders.module.ModuleImages;
97 import mircoders.module.ModuleTopics;
98 import mircoders.search.AudioSearchTerm;
99 import mircoders.search.ContentSearchTerm;
100 import mircoders.search.ImagesSearchTerm;
101 import mircoders.search.KeywordSearchTerm;
102 import mircoders.search.TextSearchTerm;
103 import mircoders.search.TopicSearchTerm;
104 import mircoders.search.UnIndexedSearchTerm;
105 import mircoders.search.VideoSearchTerm;
106 import mircoders.storage.DatabaseComment;
107 import mircoders.storage.DatabaseContent;
108 import mircoders.storage.DatabaseContentToMedia;
109 import mircoders.storage.DatabaseContentToTopics;
110 import mircoders.storage.DatabaseImages;
111 import mircoders.storage.DatabaseLanguage;
112 import mircoders.storage.DatabaseTopics;
115 * ServletModuleOpenIndy -
116 * is the open-access-servlet, which is responsible for
117 * adding comments to articles &
118 * open-postings to the newswire
120 * @author mir-coders group
121 * @version $Id: ServletModuleOpenIndy.java,v 1.72 2003/04/10 03:31:47 zapata Exp $
125 public class ServletModuleOpenIndy extends ServletModule
128 private String commentFormTemplate, commentFormDoneTemplate, commentFormDupeTemplate;
129 private String postingFormTemplate, postingFormDoneTemplate, postingFormDupeTemplate;
130 private String searchResultsTemplate;
131 private String prepareMailTemplate,sentMailTemplate;
132 private ModuleContent contentModule;
133 private ModuleComment commentModule;
134 private ModuleImages imageModule;
135 private ModuleTopics topicsModule;
136 private String directOp ="yes";
137 // Singelton / Kontruktor
138 private static ServletModuleOpenIndy instance = new ServletModuleOpenIndy();
139 public static ServletModule getInstance() { return instance; }
141 private ServletModuleOpenIndy() {
144 logger = new LoggerWrapper("ServletModule.OpenIndy");
146 commentFormTemplate = configuration.getString("ServletModule.OpenIndy.CommentTemplate");
147 commentFormDoneTemplate = configuration.getString("ServletModule.OpenIndy.CommentDoneTemplate");
148 commentFormDupeTemplate = configuration.getString("ServletModule.OpenIndy.CommentDupeTemplate");
149 postingFormTemplate = configuration.getString("ServletModule.OpenIndy.PostingTemplate");
150 postingFormDoneTemplate = configuration.getString("ServletModule.OpenIndy.PostingDoneTemplate");
151 postingFormDupeTemplate = configuration.getString("ServletModule.OpenIndy.PostingDupeTemplate");
152 searchResultsTemplate = configuration.getString("ServletModule.OpenIndy.SearchResultsTemplate");
153 prepareMailTemplate = configuration.getString("ServletModule.OpenIndy.PrepareMailTemplate");
154 sentMailTemplate = configuration.getString("ServletModule.OpenIndy.SentMailTemplate");
155 directOp = configuration.getString("DirectOpenposting").toLowerCase();
156 mainModule = new ModuleComment(DatabaseComment.getInstance());
157 contentModule = new ModuleContent(DatabaseContent.getInstance());
158 topicsModule = new ModuleTopics(DatabaseTopics.getInstance());
159 imageModule = new ModuleImages(DatabaseImages.getInstance());
160 defaultAction="addposting";
162 catch (StorageObjectFailure e) {
163 logger.error("servletmoduleopenindy could not be initialized: " + e.getMessage());
168 * Method to return an "apology" when open postings are disabled
172 * @throws ServletModuleExc
173 * @throws ServletModuleUserExc
174 * @throws ServletModuleFailure
176 public void openPostingDisabled(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure {
177 deliver(aRequest, aResponse, (Map) null, null,
178 configuration.getString("ServletModule.OpenIndy.PostingDisabledTemplate"));
183 * Method for making a comment
186 public void addcomment(HttpServletRequest req, HttpServletResponse res) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure
188 if (MirGlobal.abuse().getOpenPostingDisabled()) {
189 openPostingDisabled(req, res);
194 String aid = req.getParameter("aid"); // the article id the comment will belong to
196 String language = req.getParameter("language");
199 if (aid!=null && !aid.equals("")) {
201 Map mergeData = new HashMap();
204 if (MirGlobal.abuse().getOpenPostingPassword()) {
205 String passwd = this.createOneTimePasswd();
206 HttpSession session = req.getSession(false);
207 session.setAttribute("passwd", passwd);
208 mergeData.put("passwd", passwd);
211 mergeData.put("passwd", (String) null);
214 if (language != null) {
215 HttpSession session = req.getSession(false);
216 session.setAttribute("Locale", new Locale(language, ""));
217 session.setAttribute("language", language);
220 mergeData.put("aid", aid);
222 Map extraInfo = new HashMap();
223 extraInfo.put("languagePopUpData", DatabaseLanguage.getInstance().getPopupData());
225 deliver(req, res, mergeData, extraInfo, commentFormTemplate);
227 catch (Throwable t) {
228 throw new ServletModuleFailure("ServletModuleOpenIndy.addcomment: " + t.getMessage(), t);
231 else throw new ServletModuleExc("aid not set!");
235 * Method for inserting a comment into the Database and delivering
236 * the commentDone Page
239 public void inscomment(HttpServletRequest req, HttpServletResponse res)
240 throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure
242 if (MirGlobal.abuse().getOpenPostingDisabled()) {
243 openPostingDisabled(req, res);
248 String aid = req.getParameter("to_media"); // the article id the comment will belong to
249 if (aid!=null && !aid.equals(""))
251 // ok, collecting data from form
253 Map withValues = getIntersectingValues(req, DatabaseComment.getInstance());
255 //no html in comments(for now)
256 for (Iterator i=withValues.keySet().iterator(); i.hasNext(); ){
257 String k=(String)i.next();
258 String v=(String)withValues.get(k);
260 withValues.put(k,StringUtil.removeHTMLTags(v));
262 withValues.put("is_published","1");
263 withValues.put("to_comment_status","1");
265 //checking the onetimepasswd
266 HttpSession session = req.getSession(false);
267 String sessionPasswd = (String) session.getAttribute("passwd");
268 if ( sessionPasswd != null){
269 String passwd = req.getParameter("passwd");
270 if ( passwd == null || passwd.length()==0) {
271 throw new ServletModuleUserExc("comment.error.missingpassword", new String[] {});
273 if (!sessionPasswd.equals(passwd)) {
274 throw new ServletModuleUserExc("comment.error.invalidpassword", new String[] {});
276 session.invalidate();
279 String id = mainModule.add(withValues);
282 deliver(req, res, (Map) null, null, commentFormDupeTemplate);
285 MirGlobal.abuse().logComment(req.getRemoteAddr(), id, new Date(), (String) req.getHeader("User-Agent"));
287 DatabaseContent.getInstance().setUnproduced("id="+aid);
290 EntityComment comment = (EntityComment) DatabaseComment.getInstance().selectById(id);
291 MirGlobal.abuse().checkComment(comment, req, res);
292 MirGlobal.localizer().openPostings().afterCommentPosting(comment);
294 catch (Throwable t) {
295 throw new ServletModuleExc(t.getMessage());
299 // redirecting to url
300 // should implement back to article
301 Map mergeData = new HashMap();
302 deliver(req, res, mergeData, null, commentFormDoneTemplate);
304 catch (Throwable e) {
305 throw new ServletModuleFailure(e);
308 else throw new ServletModuleExc("aid not set!");
313 * Method for delivering the form-Page for open posting
316 public void addposting(HttpServletRequest req, HttpServletResponse res)
317 throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure
320 if (MirGlobal.abuse().getOpenPostingDisabled()) {
321 openPostingDisabled(req, res);
326 Map mergeData = new HashMap();
329 if (MirGlobal.abuse().getOpenPostingPassword()) {
330 String passwd = this.createOneTimePasswd();
331 HttpSession session = req.getSession(false);
332 session.setAttribute("passwd", passwd);
333 mergeData.put("passwd", passwd);
336 mergeData.put("passwd", (String)null);
339 String maxMedia = configuration.getString("ServletModule.OpenIndy.MaxMediaUploadItems");
340 String defaultMedia = configuration.getString("ServletModule.OpenIndy.DefaultMediaUploadItems");
341 String numOfMedia = req.getParameter("medianum");
343 if (numOfMedia == null || numOfMedia.equals("")) {
344 numOfMedia = defaultMedia;
346 else if (Integer.parseInt(numOfMedia) > Integer.parseInt(maxMedia)) {
347 numOfMedia = maxMedia;
350 int mediaNum = Integer.parseInt(numOfMedia);
351 List mediaFields = new Vector();
352 for (int i = 0; i < mediaNum; i++) {
353 Integer mNum = new Integer(i + 1);
354 mediaFields.add(mNum.toString());
356 mergeData.put("medianum", numOfMedia);
357 mergeData.put("mediafields", mediaFields);
358 mergeData.put("to_topic", null);
360 Map extraInfo = new HashMap();
361 extraInfo.put("languagePopUpData", DatabaseLanguage.getInstance().getPopupData());
362 extraInfo.put("themenPopupData", topicsModule.getTopicsAsSimpleList());
364 extraInfo.put("topics", topicsModule.getTopicsList());
365 deliver(req, res, mergeData, extraInfo, postingFormTemplate);
367 catch (Throwable t) {
368 throw new ServletModuleFailure(t);
373 * Method for inserting an open posting into the Database and delivering
374 * the postingDone Page
377 public void insposting(HttpServletRequest req, HttpServletResponse res) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure
379 if (MirGlobal.abuse().getOpenPostingDisabled()) {
380 openPostingDisabled(req, res);
385 Map mergeData = new HashMap();
386 boolean setMedia=false;
387 boolean setTopic = false;
391 WebdbMultipartRequest mp = null;
392 EntityList mediaList = null;
394 // new MediaRequest, "1" is the id for the openPosting user
395 MediaRequest mediaReq = new MediaRequest("1", true);
396 mp = new WebdbMultipartRequest(req, (FileHandler)mediaReq);
397 mediaList = mediaReq.getEntityList();
399 catch (Throwable e) {
400 throw new ServletModuleFailure(e);
403 Map withValues = mp.getParameters();
405 //checking the onetimepasswd
406 HttpSession session = req.getSession(false);
407 String sessionPasswd = (String) session.getAttribute("passwd");
408 if (sessionPasswd != null){
409 String passwd = (String) withValues.get("passwd");
411 logger.debug("session password = " + sessionPasswd + ", form password = " + passwd);
413 if ( passwd == null || passwd.length()==0) {
414 throw new ServletModuleUserExc("posting.error.missingpassword", new String[] {});
416 if (!sessionPasswd.equals(passwd)) {
417 throw new ServletModuleUserExc("posting.error.invalidpassword", new String[] {});
419 session.invalidate();
422 if ((((String)withValues.get("title")).length() == 0) ||
423 (((String)withValues.get("description")).length() == 0) ||
424 (((String)withValues.get("content_data")).length() == 0))
425 throw new ServletModuleUserExc("posting.error.missingfield", new String[] {});
427 // call the routines that escape html
429 for (Iterator i=withValues.keySet().iterator(); i.hasNext(); ){
430 String k=(String)i.next();
431 String v=(String)withValues.get(k);
433 if (k.equals("content_data")){
434 //this doesn't quite work yet, so for now, all html goes
435 //withValues.put(k,StringUtil.approveHTMLTags(v));
436 withValues.put(k,StringUtil.deleteForbiddenTags(v));
438 else if (k.equals("description")) {
439 String tmp = StringUtil.deleteForbiddenTags(v);
440 withValues.put(k,StringUtil.deleteHTMLTableTags(tmp));
443 withValues.put(k,StringUtil.removeHTMLTags(v));
448 withValues.put("date", StringUtil.date2webdbDate(new GregorianCalendar()));
449 withValues.put("publish_path", StringUtil.webdbDate2path((String)withValues.get("date")));
450 withValues.put("is_produced", "0");
451 withValues.put("is_published","1");
452 if (directOp.equals("yes"))
453 withValues.put("to_article_type","1");
455 withValues.put("to_publisher","1");
457 // inserting content into database
458 String cid = contentModule.add(withValues);
459 logger.debug("id: "+cid);
460 //insert was not successfull
463 //How do we know that it was not succesful cause of a
464 //dupe, what if it failed cause of "No space left on device"?
465 //Or is there something I am missing? Wouldn't it be better
466 //to have an explicit dupe check and then insert? I have no
467 //idea what I am talking about. this comment is in case
468 //I forget to explicitely ask. -mh
469 deliver(req, res, mergeData, null, postingFormDupeTemplate);
473 MirGlobal.abuse().logArticle(req.getRemoteAddr(), cid, new Date(), (String) req.getHeader("User-Agent"));
475 String[] to_topicsArr = mp.getParameterValues("to_topic");
477 if (to_topicsArr != null && to_topicsArr.length > 0) {
479 DatabaseContentToTopics.getInstance().setTopics(cid,to_topicsArr);
482 catch (Throwable e) {
483 logger.error("setting content_x_topic failed");
484 contentModule.deleteById(cid);
485 throw new ServletModuleFailure("smod - openindy :: insposting: setting content_x_topic failed: "+e.toString(), e);
489 //if we're here all is ok... associate the media to the article
490 for(int i=0;i<mediaList.size();i++) {
491 Entity mediaEnt = (Entity)mediaList.elementAt(i);
492 DatabaseContentToMedia.getInstance().addMedia(cid,mediaEnt.getId());
495 EntityContent article = (EntityContent) contentModule.getById(cid);
498 MirGlobal.abuse().checkArticle(article, req, res);
499 MirGlobal.localizer().openPostings().afterContentPosting(article);
501 catch (Throwable t) {
502 logger.error("Error while post-processing article: " + t.getMessage());
505 catch (Throwable e) {
506 Throwable cause = ExceptionFunctions.traceCauseException(e);
508 if (cause instanceof UnsupportedMediaFormatExc) {
509 throw new ServletModuleUserExc("media.unsupportedformat", new String[] {} );
511 throw new ServletModuleFailure(e);
514 deliver(req, res, mergeData, null, postingFormDoneTemplate);
518 * Method for preparing and sending a content as an email message
521 public void mail(HttpServletRequest req, HttpServletResponse res)
522 throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure
524 String aid = req.getParameter("mail_aid");
526 throw new ServletModuleExc("An article id must be specified in requests to email an article. Something therefore went badly wrong....");
529 String to = req.getParameter("mail_to");
530 String from = req.getParameter("mail_from");
531 String from_name = req.getParameter("mail_from_name");
532 String comment = req.getParameter("mail_comment");
533 String mail_language = req.getParameter("mail_language");
535 Map mergeData = new HashMap();
537 if (to == null || from == null || from_name == null|| to.equals("") || from.equals("") || from_name.equals("") || mail_language == null || mail_language.equals("")){
539 for (Enumeration theParams = req.getParameterNames(); theParams.hasMoreElements() ;) {
540 String pName=(String)theParams.nextElement();
541 if (pName.startsWith("mail_")){
542 mergeData.put( pName,req.getParameter(pName) );
546 deliver(req, res, mergeData, null, prepareMailTemplate);
549 //run checks on to and from and mail_language to make sure no monkey business occurring
550 if (mail_language.indexOf('.') != -1 || mail_language.indexOf('/') != -1 ) {
551 throw new ServletModuleExc("Invalid language");
553 if (to.indexOf('\n') != -1
554 || to.indexOf('\r') != -1
555 || to.indexOf(',') != -1) {
556 throw new ServletModuleUserExc("email.error.invalidtoaddress", new String[] {to});
558 if (from.indexOf('\n') != -1 || from.indexOf('\r') != -1 || from.indexOf(',') != -1 ) {
559 throw new ServletModuleUserExc("email.error.invalidfromaddress", new String[] {from});
563 EntityContent contentEnt;
565 contentEnt = (EntityContent)contentModule.getById(aid);
568 throw new ServletModuleFailure("Couldn't get content for article "+aid + ": " + e.getMessage(), e);
570 String producerStorageRoot=configuration.getString("Producer.StorageRoot");
571 String producerDocRoot=configuration.getString("Producer.DocRoot");
572 String publishPath = contentEnt.getValue("publish_path");
573 String txtFilePath = producerStorageRoot + producerDocRoot + "/" + mail_language +
574 publishPath + "/" + aid + ".txt";
577 File inputFile = new File(txtFilePath);
581 FileReader in = new FileReader(inputFile);
582 StringWriter out = new StringWriter();
584 while ((c = in.read()) != -1)
587 content= out.toString();
589 catch (FileNotFoundException e){
590 throw new ServletModuleFailure("No text file found in " + txtFilePath, e);
592 catch (IOException e){
593 throw new ServletModuleFailure("Problem reading file in " + txtFilePath, e);
596 content = "To: " + to + "\nReply-To: "+ from + "\n" + content;
597 // put in the comment where it should go
598 if (comment != null) {
599 String commentTextToInsert = "\n\nAttached comment from " + from_name + ":\n" + comment;
601 content=StringRoutines.performRegularExpressionReplacement(content,"!COMMENT!",commentTextToInsert);
604 throw new ServletModuleFailure("Problem doing regular expression replacement " + e.toString(), e);
609 content=StringRoutines.performRegularExpressionReplacement(content,"!COMMENT!","");
612 throw new ServletModuleFailure("Problem doing regular expression replacement " + e.toString(), e);
616 SMTPClient client=new SMTPClient();
619 client.connect(configuration.getString("ServletModule.OpenIndy.SMTPServer"));
621 reply = client.getReplyCode();
623 if (!SMTPReply.isPositiveCompletion(reply)) {
625 throw new ServletModuleExc("SMTP server refused connection.");
628 client.sendSimpleMessage(configuration.getString("ServletModule.OpenIndy.EmailIsFrom"), to, content);
631 //mission accomplished
632 deliver(req, res, mergeData, null, sentMailTemplate);
634 catch(IOException e) {
635 if(client.isConnected()) {
638 } catch(IOException f) {
642 throw new ServletModuleFailure(e);
648 * Method for querying a lucene index
652 * @throws ServletModuleExc
653 * @throws ServletModuleUserExc
654 * @throws ServletModuleFailure
657 public void search(HttpServletRequest req, HttpServletResponse res)
658 throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure {
660 final String[] search_variables = { "search_content", "search_boolean", "search_creator",
661 "search_topic", "search_hasImages", "search_hasAudio", "search_hasVideo", "search_sort",
662 "search_submit", "search_back", "search_forward" };
663 HTTPRequestParser requestParser = new HTTPRequestParser(req);
667 HttpSession session = req.getSession(false);
669 String queryString="";
671 Map mergeData = new HashMap();
673 KeywordSearchTerm dateTerm = new KeywordSearchTerm("date_formatted","search_date","webdb_create_formatted","webdb_create_formatted","webdb_create_formatted");
674 UnIndexedSearchTerm whereTerm = new UnIndexedSearchTerm("","","","where","where");
675 TextSearchTerm creatorTerm = new TextSearchTerm("creator","search_creator","creator","creator","creator");
676 TextSearchTerm titleTerm = new TextSearchTerm("title","search_content","title","title","title");
677 TextSearchTerm descriptionTerm = new TextSearchTerm("description","search_content","description","description","description");
678 ContentSearchTerm contentTerm = new ContentSearchTerm("content_data","search_content","content","","");
679 TopicSearchTerm topicTerm = new TopicSearchTerm();
680 ImagesSearchTerm imagesTerm = new ImagesSearchTerm();
681 AudioSearchTerm audioTerm = new AudioSearchTerm();
682 VideoSearchTerm videoTerm = new VideoSearchTerm();
684 //make the query available to subsequent iterations
686 Iterator j = Arrays.asList(search_variables).iterator();
687 while (j.hasNext()) {
688 String variable = (String) j.next();
690 mergeData.put(variable, requestParser.getParameter(variable));
694 mergeData.put("topics", topicsModule.getTopicsAsSimpleList());
697 logger.debug("Can't get topics: " + e.toString());
700 String searchBackValue = req.getParameter("search_back");
701 String searchForwardValue = req.getParameter("search_forward");
703 if (searchBackValue != null){
704 int totalHits = ((Integer) session.getAttribute("numberOfHits")).intValue();
705 int newPosition=((Integer)session.getAttribute("positionInResults")).intValue()-increment;
708 if (newPosition >= totalHits)
709 newPosition=totalHits-1;
710 session.setAttribute("positionInResults",new Integer(newPosition));
713 if (searchForwardValue != null){
714 int totalHits = ((Integer) session.getAttribute("numberOfHits")).intValue();
715 int newPosition=((Integer)session.getAttribute("positionInResults")).intValue()+increment;
718 if (newPosition >= totalHits)
719 newPosition=totalHits-1;
721 session.setAttribute("positionInResults",new Integer(newPosition));
724 String indexPath=configuration.getString("IndexPath");
727 String creatorFragment = creatorTerm.makeTerm(req);
728 if (creatorFragment != null){
729 queryString = queryString + " +" + creatorFragment;
732 // search title, description, and content for something
733 // the contentTerm uses param "search_boolean" to combine its terms
734 String contentFragment = contentTerm.makeTerm(req);
735 if (contentFragment != null){
736 logger.debug("contentFragment: " + contentFragment);
737 queryString = queryString + " +" + contentFragment;
740 String topicFragment = topicTerm.makeTerm(req);
741 if (topicFragment != null){
742 queryString = queryString + " +" + topicFragment;
745 String imagesFragment = imagesTerm.makeTerm(req);
746 if (imagesFragment != null){
747 queryString = queryString + " +" + imagesFragment;
750 String audioFragment = audioTerm.makeTerm(req);
751 if (audioFragment != null){
752 queryString = queryString + " +" + audioFragment;
755 String videoFragment = videoTerm.makeTerm(req);
756 if (videoFragment != null){
757 queryString = queryString + " +" + videoFragment;
760 if (queryString == null || queryString == ""){
765 Searcher searcher = null;
767 searcher = new IndexSearcher(indexPath);
769 catch(IOException e) {
770 logger.debug("Can't open indexPath: " + indexPath);
771 throw new ServletModuleExc("Problem with Search Index! : "+ e.toString());
776 query = QueryParser.parse(queryString, "content", new StandardAnalyzer());
780 logger.debug("Query don't parse: " + queryString);
781 throw new ServletModuleExc("Problem with Query String! (was '"+queryString+"')");
786 hits = searcher.search(query);
788 catch(IOException e) {
790 logger.debug("Can't get hits: " + e.toString());
791 throw new ServletModuleExc("Problem getting hits!");
795 int end = hits.length();
797 String sortBy=req.getParameter("search_sort");
798 if (sortBy == null || sortBy.equals("")){
799 throw new ServletModuleExc("Please let me sort by something!(missing search_sort)");
802 // here is where the documents will go for storage across sessions
803 ArrayList theDocumentsSorted = new ArrayList();
805 if (sortBy.equals("score")){
806 for(int i = start; i < end; i++) {
807 theDocumentsSorted.add(hits.doc(i));
811 // then we'll sort by date!
812 Map dateToPosition = new HashMap(end,1.0F); //we know how big it will be
813 for(int i = start; i < end; i++) {
814 String creationDate=(hits.doc(i)).get("creationDate");
815 // do a little dance in case two contents created at the same second!
816 if (dateToPosition.containsKey(creationDate)){
817 ((ArrayList) (dateToPosition.get(creationDate))).add(new Integer(i));
820 ArrayList thePositions = new ArrayList();
821 thePositions.add(new Integer(i));
822 dateToPosition.put(creationDate,thePositions);
825 Set keys = dateToPosition.keySet();
826 ArrayList keyList= new ArrayList(keys);
827 Collections.sort(keyList);
828 if (sortBy.equals("date_desc")){
829 Collections.reverse(keyList);
832 if (!sortBy.equals("date_asc")){
833 throw new ServletModuleExc("don't know how to sort by: "+ sortBy);
836 ListIterator keyTraverser = keyList.listIterator();
837 while (keyTraverser.hasNext()){
838 ArrayList positions = (ArrayList)dateToPosition.get((keyTraverser.next()));
839 ListIterator positionsTraverser=positions.listIterator();
840 while (positionsTraverser.hasNext()){
841 theDocumentsSorted.add(hits.doc(((Integer)(positionsTraverser.next())).intValue()));
849 catch (IOException e){
850 logger.debug("Can't close searcher: " + e.toString());
851 throw new ServletModuleFailure("Problem closing searcher(normal):" + e.getMessage(), e);
855 session.removeAttribute("numberOfHits");
856 session.removeAttribute("theDocumentsSorted");
857 session.removeAttribute("positionInResults");
859 session.setAttribute("numberOfHits",new Integer(end));
860 session.setAttribute("theDocumentsSorted",theDocumentsSorted);
861 session.setAttribute("positionInResults",new Integer(0));
864 catch (IOException e){
865 logger.debug("Can't close searcher: " + e.toString());
866 throw new ServletModuleFailure("Problem closing searcher: " + e.getMessage(), e);
873 ArrayList theDocs = (ArrayList)session.getAttribute("theDocumentsSorted");
874 if (theDocs != null){
876 mergeData.put("numberOfHits", ((Integer)session.getAttribute("numberOfHits")).toString());
877 List theHits = new Vector();
878 int pIR=((Integer)session.getAttribute("positionInResults")).intValue();
880 int numHits=((Integer)session.getAttribute("numberOfHits")).intValue();
882 if (!(pIR+increment>=numHits)){
883 mergeData.put("hasNext","y");
886 mergeData.put("hasNext", null);
889 mergeData.put("hasPrevious","y");
892 mergeData.put("hasPrevious", null);
895 if ((pIR+increment)>numHits){
899 terminus=pIR+increment;
901 for(int i = pIR; i < terminus; i++) {
902 Map h = new HashMap();
903 Document theHit = (Document)theDocs.get(i);
904 whereTerm.returnMeta(h,theHit);
905 creatorTerm.returnMeta(h,theHit);
906 titleTerm.returnMeta(h,theHit);
907 descriptionTerm.returnMeta(h,theHit);
908 dateTerm.returnMeta(h,theHit);
909 imagesTerm.returnMeta(h,theHit);
910 audioTerm.returnMeta(h,theHit);
911 videoTerm.returnMeta(h,theHit);
914 mergeData.put("hits",theHits);
917 catch (Throwable e) {
918 logger.error("Can't iterate over hits: " + e.toString());
920 throw new ServletModuleFailure("Problem getting hits: " + e.getMessage(), e);
923 mergeData.put("queryString",queryString);
925 deliver(req, res, mergeData, null, searchResultsTemplate);
927 catch (NullPointerException n){
928 throw new ServletModuleFailure("Null Pointer: "+n.toString(), n);
933 * Method for dynamically generating a pdf from a fo file
935 public void getpdf(HttpServletRequest req, HttpServletResponse res)
936 throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure {
937 String ID_REQUEST_PARAM = "id";
938 String language = req.getParameter("language");
939 String generateFO=configuration.getString("GenerateFO");
940 String generatePDF=configuration.getString("GeneratePDF");
943 //don't do anything if we are not making FO files, or if we are
944 //pregenerating PDF's
945 if (generateFO.equals("yes") && generatePDF.equals("no")){
946 //fop complains unless you do the logging this way
947 org.apache.log.Logger log = null;
948 Hierarchy hierarchy = Hierarchy.getDefaultHierarchy();
949 log = hierarchy.getLoggerFor("fop");
950 log.setPriority(Priority.WARN);
952 String producerStorageRoot=configuration.getString("Producer.StorageRoot");
953 String producerDocRoot=configuration.getString("Producer.DocRoot");
954 // String templateDir=MirConfig.getPropWithHome("HTMLTemplateProcessor.Dir");
955 String xslSheet=configuration.getString("Producer.HTML2FOStyleSheet");
957 String idParam = req.getParameter(ID_REQUEST_PARAM);
958 if (idParam != null) {
959 EntityContent contentEnt =
960 (EntityContent)contentModule.getById(idParam);
961 String publishPath = StringUtil.webdbDate2path(contentEnt.getValue("date"));
964 if (language == null){
965 foFile = producerStorageRoot + producerDocRoot + "/"
966 + publishPath + idParam + ".fo";
969 foFile = producerStorageRoot + producerDocRoot + "/"
970 + language + publishPath + idParam + ".fo";
972 logger.debug("USING FILES" + foFile + " and " + xslSheet);
973 XSLTInputHandler input = new XSLTInputHandler(new File(foFile),
976 ByteArrayOutputStream out = new ByteArrayOutputStream();
977 res.setContentType("application/pdf");
979 Driver driver = new Driver();
980 driver.setLogger(log);
981 driver.setRenderer(Driver.RENDER_PDF);
982 driver.setOutputStream(out);
983 driver.render(input.getParser(), input.getInputSource());
985 byte[] content = out.toByteArray();
986 res.setContentLength(content.length);
987 res.getOutputStream().write(content);
988 res.getOutputStream().flush();
991 throw new ServletModuleExc("Missing id.");
994 catch (Throwable t) {
995 logger.error(t.toString());
997 throw new ServletModuleFailure(t);
1001 throw new ServletModuleExc("Can't generate a PDF because the config tells me not to.");
1005 protected String createOneTimePasswd(){
1006 Random r = new Random();
1007 int random = r.nextInt();
1008 long l = System.currentTimeMillis();
1009 l = (l*l*l*l)/random;
1011 String returnString = ""+l;
1013 return returnString.substring(5);
1017 /* this is an overwritten method of ServletModule in order
1018 to use different bundles for open and admin */
1019 /* public void deliver(HttpServletRequest req, HttpServletResponse res,
1020 TemplateModelRoot rtm, TemplateModelRoot popups,
1021 String templateFilename) throws ServletModuleFailure
1025 public void deliver(HttpServletRequest aRequest, HttpServletResponse aResponse, Map aData, Map anExtra, String aGenerator)
1026 throws ServletModuleFailure {
1028 deliver(aResponse.getWriter(), aRequest, aResponse, aData, anExtra, aGenerator);
1030 catch (Throwable t) {
1031 throw new ServletModuleFailure(t);
1035 public void deliver(PrintWriter anOutputWriter, HttpServletRequest aRequest, HttpServletResponse aResponse, Map aData, Map anExtra, String aGenerator)
1036 throws ServletModuleFailure {
1038 Map responseData = ServletHelper.makeGenerationData(new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}, "bundles.open");
1039 responseData.put("data", aData);
1040 responseData.put("extra", anExtra);
1043 Generator generator = MirGlobal.localizer().generators().makeOpenPostingGeneratorLibrary().makeGenerator(aGenerator);
1044 generator.generate(anOutputWriter, responseData, logger.asPrintWriter(logger.INFO_MESSAGE));
1046 anOutputWriter.close();
1048 catch (Throwable e) {
1049 logger.error("Error while generating " + aGenerator + ": " + e.getMessage());
1051 throw new ServletModuleFailure(e);
1055 public void handleError(HttpServletRequest aRequest, HttpServletResponse aResponse,PrintWriter out, Throwable anException) {
1057 logger.error("error: " + anException);
1058 Map data = new HashMap();
1060 data.put("errorstring", anException.getMessage());
1061 data.put("date", StringUtil.date2readableDateTime(new GregorianCalendar()));
1063 deliver(out, aRequest, aResponse, data, null, configuration.getString("ServletModule.OpenIndy.ErrorTemplate"));
1065 catch (Throwable e) {
1066 throw new ServletModuleFailure(e);
1070 public void handleUserError(HttpServletRequest aRequest, HttpServletResponse aResponse,
1071 PrintWriter out, ServletModuleUserExc anException) {
1073 logger.warn("user error: " + anException.getMessage());
1074 Map data = new HashMap();
1076 MessageResources messages = MessageResources.getMessageResources("bundles.open");
1077 data.put("errorstring",
1078 messages.getMessage(getLocale(aRequest), anException.getMessage(), anException.getParameters())
1080 data.put("date", StringUtil.date2readableDateTime(new GregorianCalendar()));
1082 deliver(out, aRequest, aResponse, data, null, configuration.getString("ServletModule.OpenIndy.UserErrorTemplate"));
1084 catch (Throwable e) {
1085 throw new ServletModuleFailure(e);