fixing html whitelist bug
[mir.git] / source / mircoders / servlet / ServletModuleUploadedMedia.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.config.MirPropertiesConfiguration;
34 import mir.entity.Entity;
35 import mir.entity.adapter.EntityAdapter;
36 import mir.entity.adapter.EntityAdapterEngine;
37 import mir.log.LoggerWrapper;
38 import mir.media.MediaHandler;
39 import mir.servlet.ServletModule;
40 import mir.servlet.ServletModuleExc;
41 import mir.servlet.ServletModuleFailure;
42 import mir.servlet.ServletModuleUserExc;
43 import mir.session.UploadedFile;
44 import mir.util.*;
45 import mircoders.entity.EntityComment;
46 import mircoders.entity.EntityContent;
47 import mircoders.entity.EntityUploadedMedia;
48 import mircoders.media.MediaHelper;
49 import mircoders.media.MediaUploadProcessor;
50 import mircoders.media.UnsupportedMediaTypeExc;
51 import mircoders.storage.DatabaseComment;
52 import mircoders.storage.DatabaseContent;
53 import org.apache.commons.fileupload.FileItem;
54
55 import javax.servlet.ServletContext;
56 import javax.servlet.ServletOutputStream;
57 import javax.servlet.http.HttpServletRequest;
58 import javax.servlet.http.HttpServletResponse;
59 import java.io.InputStream;
60 import java.util.*;
61
62 /**
63  *
64  * <p>Title: </p>
65  * <p>Description: </p>
66  * <p>Copyright: Copyright (c) 2003</p>
67  * <p>Company: </p>
68  * @author the mir coders
69  * @version 1.0
70  */
71
72 public abstract class ServletModuleUploadedMedia extends ServletModule {
73   protected String moduleName = "UploadedMedia";
74
75   public static ServletModule getInstance() {
76     return null;
77   }
78
79   public ServletModuleUploadedMedia() {
80     super();
81
82     definition = "uploadedMedia";
83     logger = new LoggerWrapper("ServletModule.UploadedMedia");
84   }
85
86   public void insert(HttpServletRequest aRequest, HttpServletResponse aResponse)
87           throws ServletModuleExc, ServletModuleUserExc {
88
89     try {
90       HTTPParsedRequest parsedRequest = new HTTPParsedRequest(aRequest,
91           configuration.getString("Mir.DefaultEncoding"),
92           configuration.getInt("MaxMediaUploadSize")*1024,
93           configuration.getString("TempDir"));
94
95       Map mediaValues = new HashMap();
96
97       mediaValues.put("to_publisher", ServletHelper.getUser(aRequest).getId());
98
99       Iterator i = mainModule.getStorageObject().getFieldNames().iterator();
100       while (i.hasNext()) {
101         String field = (String) i.next();
102         String value = parsedRequest.getParameter(field);
103         if (value!=null)
104           mediaValues.put(field, value);
105       }
106
107       List mediaList = new ArrayList();
108
109       i = parsedRequest.getFiles().iterator();
110       while (i.hasNext()) {
111         UploadedFile file = new mir.session.CommonsUploadedFileAdapter((FileItem) i.next());
112
113         String suffix = file.getFieldName().substring(5);
114         mediaValues.put("title", parsedRequest.getParameter("media_title" + suffix));
115
116         mediaList.add(MediaUploadProcessor.processMediaUpload(file, mediaValues));
117       }
118
119       String articleid = parsedRequest.getParameter("articleid");
120       String commentid = parsedRequest.getParameter("commentid");
121
122       if (articleid!=null) {
123         EntityContent entContent = (EntityContent) DatabaseContent.getInstance().selectById(articleid);
124
125         i = mediaList.iterator();
126
127         while (i.hasNext()) {
128           String id = ((EntityUploadedMedia) i.next()).getId();
129
130           entContent.attach(id);
131           logAdminUsage(aRequest, id, "object attached to article " + articleid);
132         }
133
134         (ServletModuleContent.getInstance()).editObject(aRequest, aResponse, articleid);
135
136
137         return;
138       }
139
140       if (commentid!=null) {
141         EntityComment comment = (EntityComment) DatabaseComment.getInstance().selectById(commentid);
142
143         i=mediaList.iterator();
144
145         while (i.hasNext()) {
146           String id = ((EntityUploadedMedia) i.next()).getId();
147
148           comment.attach(id);
149
150           logAdminUsage(aRequest, id, "object attached to comment " + commentid);
151         }
152
153         (ServletModuleComment.getInstance()).editObject(aRequest, aResponse, commentid);
154
155         return;
156       }
157
158       logAdminUsage(aRequest, "", mediaList.size() + " objects added");
159
160       returnUploadedMediaList(aRequest, aResponse, mediaList, 1, mediaList.size(), "", null, null);
161     }
162     catch (Throwable t) {
163       Throwable cause = ExceptionFunctions.traceCauseException(t);
164
165       if (cause instanceof UnsupportedMediaTypeExc) {
166         throw new ServletModuleUserExc("media.error.unsupportedformat", new String[] {});
167       }
168       throw new ServletModuleFailure("ServletModuleUploadedMedia.insert: " + t.toString(), t);
169     }
170   }
171
172   public void update(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
173
174     try {
175       HTTPParsedRequest parsedRequest = new HTTPParsedRequest(aRequest,
176           configuration.getString("Mir.DefaultEncoding"),
177           configuration.getInt("MaxMediaUploadSize")*1024,
178           configuration.getString("TempDir"));
179       Map mediaValues = new HashMap();
180
181       Iterator i = mainModule.getStorageObject().getFieldNames().iterator();
182       while (i.hasNext()) {
183         String field = (String) i.next();
184         String value = parsedRequest.getParameter(field);
185         if (value!=null)
186           mediaValues.put(field, value);
187       }
188
189       mediaValues.put("to_publisher", ServletHelper.getUser(aRequest).getId());
190       mediaValues.put("is_produced", "0");
191       if (!mediaValues.containsKey("is_published"))
192         mediaValues.put("is_published", "0");
193
194       String id = mainModule.set(mediaValues);
195       logger.debug("update: media ID = " + id);
196       logAdminUsage(aRequest, id, "object modified");
197
198       editUploadedMediaObject(id, aRequest, aResponse);
199     }
200     catch (Throwable e) {
201       throw new ServletModuleFailure("upload -- exception " + e.toString(), e);
202     }
203
204   }
205
206   public void returnUploadedMediaList(HttpServletRequest aRequest, HttpServletResponse aResponse,
207                                       Object aList, int aFrom, int aTo,
208                                       String aThisUrl, String aNextUrl, String aPreviousUrl) throws ServletModuleExc {
209
210     try {
211       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
212       Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] {getLocale(aRequest), getFallbackLocale(aRequest)});
213
214       responseData.put("searchfield", requestParser.getParameterWithDefault("searchfield", ""));
215       responseData.put("searchtext", requestParser.getParameterWithDefault("searchtext", ""));
216       responseData.put("searchispublished", requestParser.getParameterWithDefault("searchispublished", ""));
217       responseData.put("searchmediafolder", requestParser.getParameterWithDefault("searchmediafolder", ""));
218       responseData.put("articleid", requestParser.getParameter("articleid"));
219       responseData.put("commentid", requestParser.getParameter("commentid"));
220
221       responseData.put("thisurl", aThisUrl);
222       responseData.put("nexturl", aNextUrl);
223       responseData.put("prevurl", aPreviousUrl);
224       responseData.put("returnurl", requestParser.getParameter("returnurl"));
225
226
227       responseData.put("from", Integer.toString(aFrom));
228       responseData.put("to", Integer.toString(aTo));
229
230       responseData.put("medialist", aList);
231
232       addExtraData(responseData);
233       ServletHelper.generateResponse(aResponse.getWriter(), responseData, listGenerator);
234     }
235     catch (Throwable t) {
236       throw new ServletModuleFailure(t);
237     }
238   }
239
240   public void returnUploadedMediaList(HttpServletRequest aRequest, HttpServletResponse aResponse,
241                                       String aWhereClause, String anOrderByClause, int anOffset) throws ServletModuleExc {
242
243     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
244     URLBuilder urlBuilder = new URLBuilder();
245     String nextPageUrl = null;
246     String previousPageUrl = null;
247     String thisUrl = null;
248
249     try {
250       List list =
251          EntityAdapterEngine.retrieveAdapterList(model, definition, aWhereClause, anOrderByClause, nrEntitiesPerListPage, anOffset);
252
253       urlBuilder.setValue("module", moduleName);
254       urlBuilder.setValue("do", "list");
255       urlBuilder.setValue("where", aWhereClause);
256       urlBuilder.setValue("order", anOrderByClause);
257
258       urlBuilder.setValue("articleid", requestParser.getParameter("articleid"));
259       urlBuilder.setValue("commentid", requestParser.getParameter("commentid"));
260       urlBuilder.setValue("searchfield", requestParser.getParameter("searchfield"));
261       urlBuilder.setValue("searchtext", requestParser.getParameter("searchtext"));
262       urlBuilder.setValue("searchispublished", requestParser.getParameter("searchispublished"));
263       urlBuilder.setValue("searchmediafolder", requestParser.getParameter("searchmediafolder"));
264       urlBuilder.setValue("returnurl", requestParser.getParameter("returnurl"));
265       urlBuilder.setValue("where", aWhereClause);
266       urlBuilder.setValue("order", anOrderByClause);
267
268       urlBuilder.setValue("offset", anOffset);
269       thisUrl = urlBuilder.getQuery();
270
271       if (list.size() >= nrEntitiesPerListPage) {
272         urlBuilder.setValue("offset", anOffset + nrEntitiesPerListPage);
273         nextPageUrl = urlBuilder.getQuery();
274       }
275
276       if (anOffset > 0) {
277         urlBuilder.setValue("offset", Math.max(anOffset - nrEntitiesPerListPage, 0));
278         previousPageUrl = urlBuilder.getQuery();
279       }
280
281       returnUploadedMediaList(aRequest, aResponse, list,
282               anOffset+1, anOffset+nrEntitiesPerListPage, thisUrl,
283               nextPageUrl, previousPageUrl);
284     }
285     catch (Throwable e) {
286       throw new ServletModuleFailure(e);
287     }
288   }
289
290   public void search(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
291     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
292
293     SQLQueryBuilder queryBuilder = new SQLQueryBuilder();
294
295     String searchField = requestParser.getParameter("searchfield");
296     String searchText = requestParser.getParameter("searchtext");
297     String searchIsPublished = requestParser.getParameter("searchispublished");
298     String searchMediaFolder = requestParser.getParameter("searchmediafolder");
299
300     queryBuilder.appendDescendingOrder("webdb_create");
301
302     if (searchIsPublished!=null)
303       if (searchIsPublished.equals("0")) {
304         queryBuilder.appendAndCondition("is_published='f'");
305       }
306       else if (searchIsPublished.equals("1")) {
307         queryBuilder.appendAndCondition("is_published='t'");
308       }
309
310     if (searchField!=null && searchText!=null && searchText.length()>0) {
311         queryBuilder.appendAndCondition(
312           "lower(" + searchField + ") like " +
313           "'%" + JDBCStringRoutines.escapeStringLiteral(searchText.toLowerCase()) + "%'");
314     }
315
316     if (searchMediaFolder!=null && searchMediaFolder.length()>0) {
317       queryBuilder.appendAndCondition("to_media_folder="+Integer.parseInt(searchMediaFolder));
318     }
319
320     returnUploadedMediaList(aRequest, aResponse,
321             queryBuilder.getWhereClause(), queryBuilder.getOrderByClause(), requestParser.getIntegerWithDefault("offset", 0));
322   }
323
324   public void list(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
325     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
326
327     returnUploadedMediaList(aRequest, aResponse,
328        requestParser.getParameterWithDefault("where", ""),
329        requestParser.getParameterWithDefault("order", "webdb_create desc"),
330        requestParser.getIntegerWithDefault("offset", 0));
331   }
332
333
334   public void add(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
335     try {
336       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
337       Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] {getLocale(aRequest), getFallbackLocale(aRequest)});
338
339       int nrMedia = requestParser.getIntegerWithDefault("nrmedia", 1);
340       int maxNrMedia=configuration.getInt("ServletModule.OpenIndy.MaxMediaUploadItems", 20);
341
342       List fields = mainModule.getStorageObject().getFieldNames();
343       Map media = new HashMap();
344       Iterator i = fields.iterator();
345       while (i.hasNext()) {
346         media.put(i.next(), null);
347       }
348       media.put("to_media_folder", new Integer(7));
349       responseData.put("uploadedmedia", media);
350
351       responseData.put("new", Boolean.TRUE);
352       responseData.put("articleid", requestParser.getParameter("articleid"));
353       responseData.put("commentid", requestParser.getParameter("commentid"));
354       responseData.put("returnurl", requestParser.getParameter("returnurl"));
355
356       if (nrMedia<=0)
357         nrMedia=1;
358       if (nrMedia>maxNrMedia)
359         nrMedia=maxNrMedia;
360
361       List mediaFields = new ArrayList();
362       for (int j=0; j<nrMedia; j++)
363         mediaFields.add(new Integer(j));
364
365       responseData.put("nrmedia", new Integer(nrMedia));
366       responseData.put("mediafields", mediaFields);
367
368       responseData.put("edittemplate", editGenerator);
369       responseData.put("module", moduleName);
370
371       addExtraData(responseData);
372
373       ServletHelper.generateResponse(aResponse.getWriter(), responseData, "uploadedmedia.template");
374     }
375     catch (Exception e) {
376       throw new ServletModuleFailure(e);
377     }
378   }
379
380   public void edit(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
381     editUploadedMediaObject(aRequest.getParameter("id"), aRequest, aResponse);
382   }
383
384   private void editUploadedMediaObject(String idParam, HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
385     if (idParam != null && !idParam.equals("")) {
386       try {
387         Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] {getLocale(aRequest), getFallbackLocale(aRequest)});
388         EntityAdapter object =
389             model.makeEntityAdapter(definition, mainModule.getById(idParam));
390         HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
391         responseData.put("uploadedmedia", object);
392         responseData.put("new", Boolean.FALSE);
393         responseData.put("articleid", null);
394         responseData.put("commentid", null);
395         responseData.put("returnurl", requestParser.getParameter("returnurl"));
396         responseData.put("thisurl", null);
397
398         responseData.put("edittemplate", editGenerator);
399         responseData.put("module", moduleName);
400
401         addExtraData(responseData);
402
403         ServletHelper.generateResponse(aResponse.getWriter(), responseData, "uploadedmedia.template");
404       }
405       catch (Throwable e) {
406         throw new ServletModuleFailure(e);
407       }
408     }
409     else {
410       throw new ServletModuleExc("ServletmoduleUploadedMedia :: editUploadedMediaObject without id");
411     }
412   }
413
414   public void getMedia(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
415     String idParam = aRequest.getParameter("id");
416
417     if (idParam!=null && !idParam.equals("")) {
418       try {
419         EntityUploadedMedia entity = (EntityUploadedMedia) mainModule.getById(idParam);
420         Entity mediaType = entity.getMediaType();
421         MediaHandler mediaHandler;
422
423         ServletContext ctx = MirPropertiesConfiguration.getContext();
424         String fName = entity.getId()+"."+mediaType.getFieldValue("name");
425
426         mediaHandler = MediaHelper.getHandler(mediaType);
427         InputStream in = mediaHandler.getMedia(entity, mediaType);
428
429         aResponse.setContentType(ctx.getMimeType(fName));
430         //important that before calling this aResponse.getWriter was not called first
431         ServletOutputStream out = aResponse.getOutputStream();
432
433         int read ;
434         byte[] buf = new byte[8 * 1024];
435         while((read = in.read(buf)) != -1) {
436           out.write(buf, 0, read);
437         }
438         in.close();
439         out.close();
440       }
441       catch (Throwable e) {
442         throw new ServletModuleFailure(e);
443       }
444     }
445     else logger.error("id not specified.");
446     // no exception allowed
447   }
448
449
450   /**
451    * @param aRequest
452    * @param aResponse
453    * @throws ServletModuleExc
454    */
455   public void getIcon(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
456     getThumbnail(aRequest, aResponse);
457   }
458
459   public void getThumbnail(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
460     String id = aRequest.getParameter("id");
461
462     if (id!=null && !id.equals("")) {
463       try {
464         EntityUploadedMedia mediaEntity = (EntityUploadedMedia) mainModule.getById(id);
465         Entity mediaType = mediaEntity.getMediaType();
466         MediaHandler mediaHandler;
467
468         mediaHandler = MediaHelper.getHandler(mediaType);
469         InputStream thumbnailInputStream = mediaHandler.getThumbnail(mediaEntity);
470
471         if (thumbnailInputStream==null)
472           throw new ServletModuleExc("no icon available");
473
474         aResponse.setContentType(mediaHandler.getThumbnailMimeType(mediaEntity, mediaType));
475
476         ServletOutputStream out = aResponse.getOutputStream();
477         try {
478           int read;
479           byte[] buf = new byte[8 * 1024];
480
481           while ((read = thumbnailInputStream.read(buf)) != -1) {
482             out.write(buf, 0, read);
483           }
484
485           thumbnailInputStream.close();
486         }
487         finally {
488           out.close();
489         }
490       }
491       catch (Throwable e) {
492         logger.error("getIcon: " + e.toString());
493       }
494     }
495     else logger.error("getIcon: id not specified.");
496   }
497
498   protected void addExtraData(Map aTarget) throws ServletModuleExc, ServletModuleFailure {
499     try {
500       aTarget.put("mediafolders", EntityAdapterEngine.retrieveAdapterList(model, "mediaFolder", "", "", -1, 0));
501     }
502     catch (Throwable t) {
503       throw new ServletModuleFailure(t);
504     }
505   }
506
507   public void showarticles(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
508     String idParam = aRequest.getParameter("id");
509     if (idParam!=null && !idParam.equals("")) {
510       try {
511         // TODO rewrite as relational sql
512         ServletModuleContent.getInstance().returnList(
513             aRequest,
514             aResponse,
515             "exists (select * from content_x_media where content_id=content.id and media_id='" +
516                   JDBCStringRoutines.escapeStringLiteral( idParam ) + "')", "", 0);
517       }
518       catch (Throwable t) {
519         throw new ServletModuleFailure(t);
520       }
521     }
522     else logger.error("showarticles: id not specified.");
523   }
524
525   public void showcomments(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
526   {
527     String idParam = aRequest.getParameter("id");
528     if (idParam!=null && !idParam.equals("")) {
529       try {
530         // TODO rewrite as relational sql
531         ServletModuleComment.getInstance().returnList(
532             aRequest,
533             aResponse,
534             "exists (select * from comment_x_media where comment_id=comment.id and media_id='" + JDBCStringRoutines.escapeStringLiteral( idParam ) + "')", "", 0);
535       }
536       catch (Throwable t) {
537         throw new ServletModuleFailure(t);
538       }
539     }
540     else logger.error("showcomments: id not specified.");
541   }
542 }