2 * Copyright (C) 2001, 2002 The Mir-coders group
\r
4 * This file is part of Mir.
\r
6 * Mir is free software; you can redistribute it and/or modify
\r
7 * it under the terms of the GNU General Public License as published by
\r
8 * the Free Software Foundation; either version 2 of the License, or
\r
9 * (at your option) any later version.
\r
11 * Mir is distributed in the hope that it will be useful,
\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 * GNU General Public License for more details.
\r
16 * You should have received a copy of the GNU General Public License
\r
17 * along with Mir; if not, write to the Free Software
\r
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
20 * In addition, as a special exception, The Mir-coders gives permission to link
\r
21 * the code of this program with the com.oreilly.servlet library, any library
\r
22 * licensed under the Apache Software License, The Sun (tm) Java Advanced
\r
23 * Imaging library (JAI), The Sun JIMI library (or with modified versions of
\r
24 * the above that use the same license as the above), and distribute linked
\r
25 * combinations including the two. You must obey the GNU General Public
\r
26 * License in all respects for all of the code used other than the above
\r
27 * mentioned libraries. If you modify this file, you may extend this exception
\r
28 * to your version of the file, but you are not obligated to do so. If you do
\r
29 * not wish to do so, delete this exception statement from your version.
\r
32 package mircoders.media;
\r
34 import java.util.GregorianCalendar;
\r
35 import java.util.Iterator;
\r
36 import java.util.Map;
\r
38 import javax.servlet.ServletContext;
\r
40 import mir.config.MirPropertiesConfiguration;
\r
41 import mir.entity.Entity;
\r
42 import mir.entity.EntityList;
\r
43 import mir.log.LoggerWrapper;
\r
44 import mir.media.MediaHelper;
\r
45 import mir.media.MirMedia;
\r
47 import mir.misc.FileHandler;
\r
48 import mir.misc.StringUtil;
\r
49 import mir.storage.Database;
\r
50 import mir.storage.StorageObjectExc;
\r
51 import mir.storage.StorageObjectFailure;
\r
52 import mircoders.storage.DatabaseMediaType;
\r
54 import com.oreilly.servlet.multipart.FilePart;
\r
58 * MediaRequest.java -
\r
59 * Takes an HTTPServletRequest from a mutltipart form and finds the files
\r
60 * uploaded via the com.oreilly.servlet.multipart package. Finally the
\r
61 * appropriate media objects are set.
\r
64 * @version $Id: MediaRequest.java,v 1.17 2003/03/09 03:53:11 zapata Exp $
\r
68 public class MediaRequest implements FileHandler
\r
70 private String _user;
\r
71 private EntityList _returnList = new EntityList();
\r
72 private boolean _publish;
\r
73 private LoggerWrapper logger;
\r
75 public MediaRequest(String user, boolean publish) {
\r
78 logger = new LoggerWrapper("Media.Request");
\r
81 public EntityList getEntityList() {
\r
86 * parses the files in the uploaded media and creates media Entity's out of
\r
87 * them. Produces them if the "produce" argument is true. The "publish"
\r
88 * parameter determines if it should publish per default in the case where no
\r
89 * is_published parameter (from the upload form) is supplied. (for backwards
\r
92 public void setFile(FilePart filePart, int fileNum, Map mediaValues) throws FileHandlerExc, FileHandlerFailure {
\r
94 String mediaId=null;
\r
95 MirMedia mediaHandler;
\r
96 Database mediaStorage = null;
\r
99 String fileName = filePart.getFileName();
\r
101 //get the content-type from what the client browser
\r
102 //sends us. (the "Oreilly method")
\r
103 String contentType = filePart.getContentType();
\r
105 //theLog.printInfo("FROM BROWSER: "+contentType);
\r
107 //if the client browser sent us unknown (text/plain is default)
\r
108 //or if we got application/octet-stream, it's possible that
\r
109 //the browser is in error, better check against the file extension
\r
110 if (contentType.equals("text/plain") ||
\r
111 contentType.equals("application/octet-stream")) {
\r
113 * Fallback to finding the mime-type through the standard ServletApi
\r
114 * ServletContext getMimeType() method.
\r
116 * This is a way to get the content-type via the .extension,
\r
117 * we could maybe use a magic method as an additional method of
\r
118 * figuring out the content-type, by looking at the header (first
\r
119 * few bytes) of the file. (like the file(1) command). We could
\r
120 * also call the "file" command through Runtime. This is an
\r
121 * option that I almost prefer as it is already implemented and
\r
122 * exists with an up-to-date map on most modern Unix like systems.
\r
123 * I haven't found a really nice implementation of the magic method
\r
124 * in pure java yet.
\r
126 * The first method we try thought is the "Oreilly method". It
\r
127 * relies on the content-type that the client browser sends and
\r
128 * that sometimes is application-octet stream with
\r
129 * broken/mis-configured browsers.
\r
131 * The map file we use for the extensions is the standard web-app
\r
132 * deployment descriptor file (web.xml). See Mir's web.xml or see
\r
133 * your Servlet containers (most likely Tomcat) documentation.
\r
134 * So if you support a new media type you have to make sure that
\r
135 * it is in this file -mh
\r
137 ServletContext ctx = MirPropertiesConfiguration.getContext();
\r
138 contentType = ctx.getMimeType(fileName);
\r
139 if (contentType==null)
\r
140 contentType = "text/plain"; // rfc1867 says this is the default
\r
142 //theLog.printInfo("CONTENT TYPE IS: "+contentType);
\r
144 if (contentType.equals("text/plain") ||
\r
145 contentType.equals("application/octet-stream")) {
\r
146 _throwBadContentType(fileName, contentType);
\r
149 // call the routines that escape html
\r
150 for (Iterator i=mediaValues.keySet().iterator(); i.hasNext(); ){
\r
151 String k=(String)i.next();
\r
152 String v=(String)mediaValues.get(k);
\r
154 if (k.equals("description")) {
\r
155 String tmp = StringUtil.deleteForbiddenTags(v);
\r
156 mediaValues.put(k,StringUtil.deleteHTMLTableTags(tmp));
\r
158 //we don't want people fucking with the author/title, etc..
\r
159 mediaValues.put(k,StringUtil.removeHTMLTags(v));
\r
164 String mediaTitle = (String)mediaValues.get("media_title"+fileNum);
\r
165 if ( (mediaTitle == null) || (mediaTitle.length() == 0)) {
\r
166 // uncomment the next line and comment out the exception throw
\r
167 // if you'd rather just assign missing media titles automatically
\r
168 // mediaTitle="media item "+fileNum;
\r
169 // throw new FileHandlerUserException("Missing field: media title "+mediaTitle+fileNum);
\r
172 // TODO: need to add all the extra fields that can be present in the
\r
173 // admin upload form. -mh
\r
174 mediaValues.put("title", mediaTitle);
\r
175 mediaValues.put("date", StringUtil.date2webdbDate(
\r
176 new GregorianCalendar()));
\r
177 mediaValues.put("to_publisher", _user);
\r
178 //mediaValues.put("to_media_folder", "7"); // op media_folder
\r
179 mediaValues.put("is_produced", "0");
\r
181 // icky backwards compatibility code -mh
\r
182 if (_publish == true) {
\r
183 mediaValues.put("is_published", "1");
\r
185 if (!mediaValues.containsKey("is_published"))
\r
186 mediaValues.put("is_published", "0");
\r
189 // @todo this should probably be moved to DatabaseMediaType -mh
\r
190 String[] cTypeSplit = StringUtil.split(contentType, "/");
\r
191 String wc = " mime_type LIKE '"+cTypeSplit[0]+"%'";
\r
193 DatabaseMediaType mediaTypeStor = DatabaseMediaType.getInstance();
\r
194 EntityList mediaTypesList = mediaTypeStor.selectByWhereClause(wc);
\r
196 String mediaTypeId = null;
\r
198 //if we didn't find an entry matching the
\r
199 //content-type int the table.
\r
200 if (mediaTypesList.size() == 0) {
\r
201 _throwBadContentType(fileName, contentType);
\r
204 Entity mediaType = null;
\r
205 Entity mediaType2 = null;
\r
207 // find out if we an exact content-type match if so take it.
\r
208 // otherwise try to match majortype/*
\r
209 // @todo this should probably be moved to DatabaseMediaType -mh
\r
210 for(int j=0;j<mediaTypesList.size();j++) {
\r
211 if(contentType.equals(
\r
212 mediaTypesList.elementAt(j).getValue("mime_type")))
\r
213 mediaType = mediaTypesList.elementAt(j);
\r
214 else if ((mediaTypesList.elementAt(j).getValue("mime_type")).equals(
\r
215 cTypeSplit[0]+"/*") )
\r
216 mediaType2= mediaTypesList.elementAt(j);
\r
219 if ( (mediaType == null) && (mediaType2 == null) ) {
\r
220 _throwBadContentType(fileName, contentType);
\r
221 } else if( (mediaType == null) && (mediaType2 != null) ) {
\r
222 mediaType = mediaType2;
\r
225 //get the class names from the media_type table.
\r
226 mediaTypeId = mediaType.getId();
\r
227 // ############### @todo: merge these and the getURL call into one
\r
228 // getURL helper call that just takes the Entity as a parameter
\r
229 // along with media_type
\r
231 mediaHandler = MediaHelper.getHandler(mediaType);
\r
232 mediaStorage = MediaHelper.getStorage(mediaType, "mircoders.storage.Database");
\r
234 catch (Throwable e) {
\r
235 throw new FileHandlerFailure(e);
\r
237 mediaValues.put("to_media_type",mediaTypeId);
\r
239 //load the classes via reflection
\r
241 Entity mediaEnt = null;
\r
244 mediaEnt = (Entity)mediaStorage.getEntityClass().newInstance();
\r
246 catch (Throwable e) {
\r
247 throw new FileHandlerFailure("MediaRequest.setFile: "+e.toString(), e);
\r
250 mediaEnt.setStorage(mediaStorage);
\r
251 mediaEnt.setValues(mediaValues);
\r
252 mediaId = mediaEnt.insert();
\r
254 //save and store the media data/metadata
\r
256 mediaHandler.set(filePart.getInputStream(), mediaEnt, mediaType);
\r
258 catch (Throwable e) {
\r
259 throw new FileHandlerFailure("MediaRequest.setFile: "+e.toString(), e);
\r
262 _returnList.add(mediaEnt);
\r
264 catch (StorageObjectFailure e) {
\r
265 // first try to delete it.. don't catch exception as we've already..
\r
267 mediaStorage.delete(mediaId);
\r
269 catch (Exception e2) {
\r
271 throw new FileHandlerFailure("MediaRequest.setFile: "+e.toString(), e);
\r
273 catch (Throwable e) {
\r
274 throw new FileHandlerFailure("MediaRequest.setFile: "+e.toString(), e);
\r
275 } //end try/catch block
\r
277 } // method setFile()
\r
279 private void _throwBadContentType (String fileName, String contentType) throws FileHandlerExc, FileHandlerFailure {
\r
281 throw new UnsupportedMediaFormatExc(
\r
282 "The file you uploaded is of the following mime-type: " + contentType +
\r
283 ", we do not support this mime-type. "
\r
284 + "Error One or more files of unrecognized type. Sorry");
\r
286 catch (Throwable t) {
\r
287 throw new FileHandlerFailure(t);
\r