* anti-abuse upgrade: filters now stored in the database (experimental)
[mir.git] / source / mircoders / servlet / ServletModuleContent.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  any library licensed under the Apache Software License,
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23  * (or with modified versions of the above that use the same license as the above),
24  * and distribute linked combinations including the two.  You must obey the
25  * GNU General Public License in all respects for all of the code used other than
26  * the above mentioned libraries.  If you modify this file, you may extend this
27  * exception to your version of the file, but you are not obligated to do so.
28  * If you do not wish to do so, delete this exception statement from your version.
29  */
30
31 package mircoders.servlet;
32
33 import mir.entity.adapter.EntityAdapter;
34 import mir.entity.adapter.EntityAdapterModel;
35 import mir.entity.adapter.EntityIteratorAdapter;
36 import mir.generator.Generator;
37 import mir.log.LoggerWrapper;
38 import mir.misc.StringUtil;
39 import mir.servlet.ServletModule;
40 import mir.servlet.ServletModuleExc;
41 import mir.servlet.ServletModuleFailure;
42 import mir.util.*;
43 import mircoders.entity.EntityContent;
44 import mircoders.entity.EntityUsers;
45 import mircoders.global.MirGlobal;
46 import mircoders.module.ModuleContent;
47 import mircoders.storage.DatabaseContent;
48 import mircoders.storage.DatabaseContentToTopics;
49
50 import javax.servlet.http.HttpServletRequest;
51 import javax.servlet.http.HttpServletResponse;
52 import java.util.*;
53
54 /**
55  * Article admin interface code
56  */
57
58 public class ServletModuleContent extends ServletModule
59 {
60   private static ServletModuleContent instance = new ServletModuleContent();
61   public static ServletModule getInstance() { return instance; }
62   private static ModuleContent contentModule;
63
64   private ServletModuleContent() {
65     super();
66     propagatedParameters.add("selectarticleurl");
67
68     logger = new LoggerWrapper("ServletModule.Content");
69
70     try {
71       definition = "content";
72       contentModule = new ModuleContent();
73       mainModule = contentModule;
74     }
75     catch (Throwable e) {
76       logger.fatal("ServletModuleContent could not be initialized: " + e.toString());
77     }
78   }
79
80   public void search(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleFailure {
81     try {
82       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
83       SQLQueryBuilder queryBuilder = new SQLQueryBuilder();
84       String searchField = requestParser.getParameterWithDefault("searchfield", "");
85       String searchValue = requestParser.getParameterWithDefault("searchvalue", "").trim();
86       String searchOrder = requestParser.getParameterWithDefault("searchorder", "");
87       String searchispublished = requestParser.getParameterWithDefault("searchispublished", "");
88       String searchArticleType = requestParser.getParameterWithDefault("searcharticletype", "");
89
90       if (searchValue.length()>0) {
91         if (searchField.equals("id"))
92           queryBuilder.appendAndCondition(
93             "id='"+JDBCStringRoutines.escapeStringLiteral(searchValue)+"'");
94         else if (searchField.equals("contents"))
95           queryBuilder.appendAndCondition(
96             "(lower(content_data) like " + "'%" + JDBCStringRoutines.escapeStringLiteral(searchValue.toLowerCase()) + "%')"+
97             " or (lower(description) like " + "'%" + JDBCStringRoutines.escapeStringLiteral(searchValue.toLowerCase()) + "%')");
98         else
99           queryBuilder.appendAndCondition(
100             "lower("+ searchField + ") like " +
101             "'%" + JDBCStringRoutines.escapeStringLiteral(searchValue.toLowerCase()) + "%'");
102       }
103
104       if (searchispublished.length()>0) {
105         if (searchispublished.equals("0"))
106           queryBuilder.appendAndCondition("is_published='f'");
107         else
108           queryBuilder.appendAndCondition("is_published='t'");
109       }
110
111       if (searchArticleType.length()>0) {
112         queryBuilder.appendAndCondition("to_article_type="+Integer.parseInt(searchArticleType));
113       }
114
115       if (searchOrder.length()>0) {
116         if (searchOrder.equals("datedesc"))
117           queryBuilder.appendDescendingOrder("webdb_create");
118         else if (searchOrder.equals("dateasc"))
119           queryBuilder.appendAscendingOrder("webdb_create");
120         else if (searchOrder.equals("title"))
121           queryBuilder.appendAscendingOrder("title");
122         else if (searchOrder.equals("creator"))
123           queryBuilder.appendAscendingOrder("creator");
124       }
125
126       returnList(aRequest, aResponse, queryBuilder.getWhereClause(), queryBuilder.getOrderByClause(), 0);
127     }
128     catch (Throwable e) {
129       throw new ServletModuleFailure(e);
130     }
131   }
132
133   public void add(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
134     editObject(aRequest, aResponse, null);
135   }
136
137   public void insert(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
138     try {
139       Map withValues = getIntersectingValues(aRequest, DatabaseContent.getInstance());
140
141       String now = StringUtil.date2webdbDate(new GregorianCalendar());
142       withValues.put("date", now);
143       withValues.put("publish_path", StringUtil.webdbDate2path(now));
144       withValues.put("to_publisher", ServletHelper.getUser(aRequest).getId());
145       withValues.put("is_produced", "0");
146       if (!withValues.containsKey("is_published"))
147         withValues.put("is_published","0");
148       if (!withValues.containsKey("is_html"))
149         withValues.put("is_html","0");
150
151       String webdbCreate = (String) withValues.get("webdb_create");
152       if (webdbCreate==null || webdbCreate.trim().length()==0)
153         withValues.remove("webdb_create");
154
155       String id = mainModule.add(withValues);
156       logAdminUsage(aRequest, id, "object added");
157
158       DatabaseContentToTopics.getInstance().setTopics(id, aRequest.getParameterValues("to_topic"));
159
160       editObject(aRequest, aResponse, id);
161     }
162     catch (Throwable e) {
163       throw new ServletModuleFailure(e);
164     }
165   }
166
167   public void edit(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
168     String idParam = aRequest.getParameter("id");
169     if (idParam == null)
170       throw new ServletModuleExc("Invalid call: id not supplied ");
171     editObject(aRequest, aResponse, idParam);
172   }
173
174   /**
175    * Attaches media to an article
176    *
177    */
178   public void attach(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
179     String  mediaIdParam = aRequest.getParameter("mid");
180     String  articleId = aRequest.getParameter("articleid");
181
182     if (articleId == null || mediaIdParam==null)
183       throw new ServletModuleExc("smod content :: attach :: articleid/mid missing");
184
185     if (!MirGlobal.accessControl().article().mayEditArticle(ServletHelper.getUser(aRequest), articleId))
186       throw new ServletModuleExc("Article has been locked");
187
188     try {
189       EntityContent entContent = (EntityContent) mainModule.getById(articleId);
190       entContent.attach(mediaIdParam);
191     }
192     catch(Throwable e) {
193       throw new ServletModuleFailure(e);
194     }
195
196     logAdminUsage(aRequest, articleId, "media " + mediaIdParam + " attached");
197
198     editObject(aRequest, aResponse, articleId);
199   }
200
201   /**
202    * Deattaches media from an article
203    */
204   public void dettach(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
205   {
206     String  articleId = aRequest.getParameter("articleid");
207     String  midParam = aRequest.getParameter("mid");
208     if (articleId == null)
209       throw new ServletModuleExc("smod content :: dettach :: articleid missing");
210     if (midParam == null)
211       throw new ServletModuleExc("smod content :: dettach :: mid missing");
212
213     if (!MirGlobal.accessControl().article().mayEditArticle(ServletHelper.getUser(aRequest), articleId))
214       throw new ServletModuleExc("Article has been locked");
215
216     try {
217       EntityContent entContent = (EntityContent)mainModule.getById(articleId);
218       entContent.dettach(articleId, midParam);
219     }
220     catch(Throwable e) {
221       throw new ServletModuleFailure(e);
222     }
223
224     logAdminUsage(aRequest, articleId, "media " + midParam + " deattached");
225
226     editObject(aRequest, aResponse, articleId);
227   }
228
229   /**
230    * Locks an article
231    */
232   public void lock(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
233   {
234     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
235
236     String idParam = requestParser.getParameter("id");
237     if (idParam == null)
238       throw new ServletModuleExc("Wrong call: (id) is missing");
239
240     EntityUsers user = ServletHelper.getUser(aRequest);
241
242     if (!MirGlobal.accessControl().article().mayLockArticle(user, idParam))
243       throw new ServletModuleExc("Unable to lock");
244
245     contentModule.lockArticle(idParam, user.getId(), false);
246
247     editObject(aRequest, aResponse, idParam);
248   }
249
250   /**
251    * Unlocks an article
252    */
253   public void unlock(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
254   {
255     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
256
257     String idParam = requestParser.getParameter("id");
258     if (idParam == null)
259       throw new ServletModuleExc("Wrong call: (id) is missing");
260
261     EntityUsers user = ServletHelper.getUser(aRequest);
262
263     if (!MirGlobal.accessControl().article().mayUnlockArticle(user, idParam))
264       throw new ServletModuleExc("Unable to unlock");
265
266     contentModule.unlockArticle(idParam, user.getId(), false);
267
268     editObject(aRequest, aResponse, idParam);
269   }
270
271   /**
272    * Forcelocks an article
273    */
274   public void forcelock(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
275   {
276     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
277
278     String idParam = requestParser.getParameter("id");
279     if (idParam == null)
280       throw new ServletModuleExc("Wrong call: (id) is missing");
281
282     EntityUsers user = ServletHelper.getUser(aRequest);
283
284     if (!MirGlobal.accessControl().article().mayForceLockArticle(user, idParam))
285       throw new ServletModuleExc("Unable to force lock");
286
287     contentModule.lockArticle(idParam, user.getId(), true);
288
289     editObject(aRequest, aResponse, idParam);
290   }
291
292   /**
293    * Stores an article
294    */
295   public void update(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
296   {
297     try {
298       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
299
300       String idParam = requestParser.getParameter("id");
301       if (idParam == null)
302         throw new ServletModuleExc("Wrong call: (id) is missing");
303
304       if (!MirGlobal.accessControl().article().mayEditArticle(ServletHelper.getUser(aRequest), idParam))
305         throw new ServletModuleExc("Article has been locked");
306
307       Map withValues = getIntersectingValues(aRequest, DatabaseContent.getInstance());
308
309       withValues.put("is_produced", "0");
310       if (!withValues.containsKey("is_published"))
311         withValues.put("is_published","0");
312       if (!withValues.containsKey("is_html"))
313         withValues.put("is_html","0");
314
315       String webdbCreate = (String) withValues.get("webdb_create");
316       if (webdbCreate==null || webdbCreate.trim().length()==0)
317         withValues.remove("webdb_create");
318
319       String id = mainModule.set(withValues);
320
321       logAdminUsage(aRequest, id, "object modified");
322
323       DatabaseContentToTopics.getInstance().setTopics(aRequest.getParameter("id"), aRequest.getParameterValues("to_topic"));
324
325       if (MirGlobal.accessControl().article().mayUnlockArticle(ServletHelper.getUser(aRequest), idParam) &&
326          (requestParser.getParameterWithDefault("unlock", "0").equals("1"))) {
327         contentModule.unlockArticle(id, ServletHelper.getUser(aRequest).getId(), false);
328       }
329
330       editObject(aRequest, aResponse, idParam);
331     }
332     catch (Throwable e) {
333       throw new ServletModuleFailure(e);
334     }
335   }
336
337
338   /**
339    * Returns the basic article editing form.
340    *
341    * @param id identifier of the article. <code>null</code>, means show an
342    *     empty form to add a new article.
343    */
344   public void editObject(HttpServletRequest aRequest, HttpServletResponse aResponse, String id)
345       throws ServletModuleExc {
346     try {
347       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
348       Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)});
349       EntityAdapterModel model = MirGlobal.localizer().dataModel().adapterModel();
350       Map article;
351       URLBuilder urlBuilder = new URLBuilder();
352
353       urlBuilder.setValue("module", "Content");
354       urlBuilder.setValue("do", "edit");
355       urlBuilder.setValue("id", id);
356       urlBuilder.setValue("returnurl", requestParser.getParameter("returnurl"));
357
358       if (id!=null) {
359         responseData.put("new", Boolean.FALSE);
360         article = model.makeEntityAdapter("content", mainModule.getById(id));
361
362         EntityUsers user = ServletHelper.getUser(aRequest);
363
364         responseData.put("mayEdit", new Boolean(MirGlobal.accessControl().article().mayEditArticle(user, id)));
365         responseData.put("mayLock", new Boolean(MirGlobal.accessControl().article().mayLockArticle(user, id)));
366         responseData.put("mayForceLock", new Boolean(MirGlobal.accessControl().article().mayForceLockArticle(user, id)));
367         responseData.put("mayUnlock", new Boolean(MirGlobal.accessControl().article().mayUnlockArticle(user, id)));
368       }
369       else {
370         List fields = DatabaseContent.getInstance().getFieldNames();
371         responseData.put("new", Boolean.TRUE);
372         article = new HashMap();
373         Iterator i = fields.iterator();
374         while (i.hasNext()) {
375           article.put(i.next(), null);
376         }
377
378         article.put("to_topics", null);
379
380         MirGlobal.localizer().adminInterface().initializeArticle(article);
381
382         responseData.put("mayEdit", Boolean.TRUE);
383         responseData.put("mayLock", Boolean.FALSE);
384         responseData.put("mayForceLock", Boolean.FALSE);
385         responseData.put("mayUnlock", Boolean.FALSE);
386       }
387       responseData.put("article", article);
388
389       List topicsList = new ArrayList();
390
391       String[] topicCategories = configuration.getStringArray("Mir.Localizer.Admin.TopicLists");
392
393       if (topicCategories.length==0 ) {
394         Map categoryMap = new HashMap();
395         categoryMap.put("key", "topic");
396         categoryMap.put("listtype", "0");
397         categoryMap.put("listparameter", "3");
398         categoryMap.put("items",
399                         new EntityIteratorAdapter("", "title",
400             20, MirGlobal.localizer().dataModel().adapterModel(), "topic"));
401         topicsList.add(categoryMap);
402       }
403       else {
404         for (int i = 0; i < topicCategories.length; i++) {
405           try {
406             Map categoryMap = new HashMap();
407             List parts = StringRoutines.splitString(topicCategories[i], ":");
408             String key = null;
409             String listtype = "0";
410             String listparameter = "5";
411             String where = "";
412             String order = "";
413
414             if (parts.size() > 0)
415               key = (String) parts.get(0);
416             if (parts.size() > 1)
417               listtype = (String) parts.get(1);
418             if (parts.size() > 2)
419               listparameter = (String) parts.get(2);
420             if (parts.size() > 3)
421               where = (String) parts.get(3);
422             if (parts.size() > 4)
423               order = (String) parts.get(4);
424
425             if (key != null) {
426               categoryMap.put("key", key);
427               categoryMap.put("listtype", listtype);
428               categoryMap.put("listparameter", listparameter);
429               categoryMap.put("items",
430                               new EntityIteratorAdapter(where, order,
431                   20, MirGlobal.localizer().dataModel().adapterModel(), "topic"));
432               topicsList.add(categoryMap);
433             }
434           }
435           catch (Throwable t) {
436             logger.error("error while preparing topics: " + t.toString());
437           }
438         }
439       }
440
441       responseData.put("topics", topicsList);
442
443       responseData.put("returnurl", requestParser.getParameter("returnurl"));
444       responseData.put("thisurl", urlBuilder.getQuery());
445
446       ServletHelper.generateResponse(aResponse.getWriter(), responseData, editGenerator);
447     }
448     catch (Throwable e) {
449       throw new ServletModuleFailure(e);
450     }
451   }
452
453   public void selectparent(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
454     try {
455       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
456       URLBuilder urlBuilder = new URLBuilder();
457
458       urlBuilder.setValue("module", "Content");
459       urlBuilder.setValue("do", "setparent");
460       urlBuilder.setValue("childid", requestParser.getParameter("id"));
461       urlBuilder.setValue("returnurl", requestParser.getParameter("returnurl"));
462
463       returnList(aRequest, aResponse, "", "", 0,
464           Collections.singletonMap("selectarticleurl", urlBuilder.getQuery()));
465     }
466     catch (Throwable e) {
467       throw new ServletModuleFailure(e);
468     }
469   }
470
471   public void listchildren(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
472     try {
473       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
474       String articleId = requestParser.getParameter("article_id");
475
476       if (articleId == null)
477         throw new ServletModuleExc("ServletModuleContent.listchildren: article_id not set!");
478
479       returnList(aRequest, aResponse, "to_content = " + articleId, "webdb_create desc", 0, null);
480     }
481     catch (Throwable e) {
482       throw new ServletModuleFailure(e);
483     }
484   }
485
486   public void setparent(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
487   {
488     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
489     String articleId = requestParser.getParameter("childid");
490     String parentId  = requestParser.getParameter("id");
491     String returnUrl = requestParser.getParameter("returnurl");
492
493     if (!MirGlobal.accessControl().article().mayEditArticle(ServletHelper.getUser(aRequest), articleId))
494       throw new ServletModuleExc("Article has been locked");
495
496     try {
497       EntityContent article = (EntityContent) mainModule.getById(articleId);
498       article.setFieldValue("to_content", parentId);
499       article.setProduced(false);
500       article.update();
501       logAdminUsage(aRequest, articleId, "parent set to " + parentId);
502     }
503     catch(Throwable e) {
504       logger.error("ServletModuleContent.setparent: " + e.getMessage());
505       throw new ServletModuleFailure(e);
506     }
507
508     ServletHelper.redirect(aResponse, returnUrl);
509   }
510
511   public void clearparent(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
512   {
513     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
514     String articleId = requestParser.getParameter("id");
515     String returnUrl = requestParser.getParameter("returnurl");
516
517     try {
518       EntityContent article = (EntityContent) mainModule.getById(articleId);
519       article.setFieldValue("to_content", "");
520       article.setProduced(false);
521       article.update();
522       logAdminUsage(aRequest, articleId, "parent cleared");
523     }
524     catch(Throwable e) {
525       e.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE));
526       logger.error("ServletModuleContent.clearparent: " + e.getMessage());
527
528       throw new ServletModuleFailure("ServletModuleContent.clearparent: " + e.getMessage(), e);
529     }
530
531     ServletHelper.redirect(aResponse, returnUrl);
532   }
533
534   public void showPreview(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
535     try {
536       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
537       String articleId = requestParser.getParameter("id");
538       EntityAdapter article = model.makeEntityAdapter("content", mainModule.getById(articleId));
539       String preview = requestParser.getParameterWithDefault("preview", "default");
540
541       Map generationValues = new HashMap();
542       Generator generator =
543           MirGlobal.localizer().adminInterface().prepareArticlePreview(preview, article, generationValues);
544
545       generator.generate(aResponse.getWriter(), generationValues, logger);
546     }
547     catch (Exception e) {
548       throw new ServletModuleFailure(e);
549     }
550   }
551 }