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