bug fix in content type finding logic. this really ought to go in another file
[mir.git] / source / mircoders / servlet / ServletModuleUploadedMedia.java
1 package mircoders.servlet;
2
3 import freemarker.template.SimpleHash;
4 import mir.entity.Entity;
5 import mir.entity.EntityList;
6 import mir.media.MediaHelper;
7 import mir.media.MirMedia;
8 import mir.media.MirMediaException;
9 import mir.media.MirMediaUserException;
10 import mir.misc.FileUtil;
11 import mir.misc.MpRequest;
12 import mir.misc.StringUtil;
13 import mir.misc.WebdbMultipartRequest;
14 import mir.module.ModuleException;
15 import mir.servlet.ServletModule;
16 import mir.servlet.ServletModuleException;
17 import mir.servlet.ServletModuleUserException;
18 import mir.storage.Database;
19 import mir.storage.StorageObjectException;
20 import mircoders.entity.EntityUsers;
21 import mircoders.storage.DatabaseMediaType;
22 import mircoders.storage.DatabaseMediafolder;
23
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26 import javax.servlet.http.HttpSession;
27 import java.io.IOException;
28 import java.net.URLEncoder;
29 import java.util.GregorianCalendar;
30 import java.util.HashMap;
31
32 /*
33  *  ServletModuleBilder -
34  *  liefert HTML fuer Bilder
35  *
36  *
37  * @author RK
38  */
39
40 public abstract class ServletModuleUploadedMedia
41         extends mir.servlet.ServletModule {
42
43   //private static DatabaseRights dbRights;
44
45   public static ServletModule getInstance() {
46     return null;
47   }
48
49   public void insert(HttpServletRequest req, HttpServletResponse res)
50           throws ServletModuleException, ServletModuleUserException {
51     try {
52       WebdbMultipartRequest mp = new WebdbMultipartRequest(req);
53       HashMap parameters = mp.getParameters();
54       EntityUsers user = _getUser(req);
55       String mediaId = null;
56       MpRequest mpReq = (MpRequest) mp.requestList.get(0);
57       String mediaTypeId; //= null;
58       MirMedia mediaHandler;
59       Database mediaStorage;
60
61       // get the content-type from what the client browser
62       // sends us. (the "Oreilly method")
63       String contentType = mpReq.getContentType();
64       String fileName = mpReq.getFilename();
65       theLog.printInfo("CONTENT-TYPE FROM BROWSER: " + contentType);
66
67       // if the client browser sent us unknown (text/plain is default)
68       // or if we got application/octet-stream, it's possible that
69       // the browser is in error, better check against the file extension
70       if (contentType.equals("text/plain") ||
71               contentType.equals("application/octet-stream")) {
72         /**
73          * This is just a temporary way to get the content-type via
74          * the .extension , we could maybe use a magic method, by looking
75          * at the header (first few bytes) of the file. (like the file(1)
76          * command).
77          * The Oreilly method  relies on the content-type that the client
78          * browser sends and that sometimes is application-octet stream with
79          * broken/mis-configured browsers.
80          *
81          * The map file should be Mir/content-types.properties, it's the
82          * default Sun Java file with some additional entries that it did
83          * not have. So if you support a new media type you have to make
84          * sure that it is in this file -mh
85          */
86         contentType = FileUtil.guessContentTypeFromName(fileName);
87         if (contentType == null)
88           contentType = "text/plain"; // rfc1867 says this is the default
89       }
90       theLog.printInfo("CONTENT TYPE IS: " + contentType);
91
92       if (contentType.equals("text/plain") ||
93               contentType.equals("application/octet-stream")) {
94         _throwBadContentType(fileName, contentType);
95       }
96
97       parameters.put("date", StringUtil.date2webdbDate(new GregorianCalendar()));
98       parameters.put("to_publisher", user.getId());
99
100       //the where clause to find the media_type entry from the content-type.
101       //we use the media type entry to lookup the media Handler/Storage classes
102       // @todo this should probably be moved to DatabaseMediaType or
103       // somewhere else appropriate -mh
104       String[] contentTypeSplit = StringUtil.split(contentType, "/");
105       String wc = " mime_type LIKE '" + contentTypeSplit[0] + "%'";
106       DatabaseMediaType mediaTypeStor = DatabaseMediaType.getInstance();
107       EntityList mediaTypesList = mediaTypeStor.selectByWhereClause(wc);
108
109       // if we didn't find an entry matching the
110       // content-type in the table.
111       if (mediaTypesList.size() == 0) {
112         _throwBadContentType(fileName, contentType);
113       }
114       Entity mediaType = null;
115       Entity mediaType2 = null;
116
117       // find out if we an exact content-type match if so take it.
118       // otherwise try to match majortype/*
119       // @todo this should probably be moved to DatabaseMediaType -mh
120       for(int j=0;j<mediaTypesList.size();j++) {
121         if(contentType.equals(
122                         mediaTypesList.elementAt(j).getValue("mime_type")))
123           mediaType = mediaTypesList.elementAt(j);
124         else if ((mediaTypesList.elementAt(j).getValue("mime_type")).equals(
125                   contentTypeSplit[0]+"/*"))
126           mediaType2= mediaTypesList.elementAt(j); 
127       }
128
129       if ( (mediaType == null) && (mediaType2 == null) ) {
130         _throwBadContentType(fileName, contentType);
131       }
132       else if( (mediaType == null) && (mediaType2 != null) )
133         mediaType = mediaType2;
134
135
136       // get the class names from the media_type table.
137       mediaTypeId = mediaType.getId();
138       try {
139         // ############### @todo: merge these and the getURL call into one
140         // getURL helper call that just takes the Entity as a parameter
141         // along with media_type
142         mediaHandler = MediaHelper.getHandler(mediaType);
143         mediaStorage = MediaHelper.getStorage(mediaType,
144                                               "mircoders.storage.Database");
145       }
146       catch (Exception e) {
147         theLog.printError("getting media handler failed: " + e.toString());
148         throw new MirMediaException("getting media handler failed: "
149                                     + e.toString());
150       }
151
152       parameters.put("to_media_type", mediaTypeId);
153       //load the classes via reflection
154       Entity mediaEnt = null;
155       try {
156         mediaEnt = (Entity) mediaStorage.getEntityClass().newInstance();
157         mediaEnt.setStorage(mediaStorage);
158         mediaEnt.setValues(parameters);
159         // unfortunatly we have to insert it first because of the way
160         // Image setting works right now. that should change soon. -mh
161         mediaId = mediaEnt.insert();
162         //save and store the media data/metadata
163         mediaHandler.set(mpReq.getMedia(), mediaEnt, mediaType);
164
165         //were done with mpReq at this point, dereference it.
166         //as it contains mucho mem. -mh 01.10.2001
167         mpReq = null;
168
169         //we got this far, associate the media to the article
170         mediaEnt.setValueForProperty("is_published", "1");
171         mediaEnt.update();
172       }
173       catch (Exception e) {
174         try {
175           mediaStorage.delete(mediaId);
176         }
177         catch (Exception e2) {
178           // dont't do anything here as the error was setting the media,
179           // this just means that the entity may not have been inserted yet
180         }
181         theLog.printError("setting media failed: " + e.toString());
182         throw new MirMediaException("setting media failed: " + e.toString());
183       }
184
185       _edit(mediaId, req, res);
186     }
187     catch (MirMediaException e) {
188       throw new ServletModuleException(
189               "upload -- media handling exception " + e.toString());
190     }
191     catch (IOException e) {
192       throw new ServletModuleException("upload -- ioexception " + e.toString());
193     }
194     catch (StorageObjectException e) {
195       throw new ServletModuleException("StorageObjectException" + e.toString());
196     }
197
198   }
199
200   private void _throwBadContentType (String fileName, String contentType)
201     throws ServletModuleUserException {
202
203     theLog.printDebugInfo("Wrong file type uploaded!: " + fileName+" "
204                           +contentType);
205     throw new ServletModuleUserException("The file you uploaded is of the "
206         +"following mime-type: "+contentType
207         +", we do not support this mime-type. "
208         +"Error One or more files of unrecognized type. Sorry");
209   }
210  
211
212   public void update(HttpServletRequest req, HttpServletResponse res) throws ServletModuleException {
213
214     try {
215       WebdbMultipartRequest mp = new WebdbMultipartRequest(req);
216       HashMap parameters = mp.getParameters();
217
218       EntityUsers user = _getUser(req);
219       parameters.put("to_publisher", user.getId());
220       parameters.put("is_produced", "0");
221       if (!parameters.containsKey("is_published"))
222         parameters.put("is_published", "0");
223
224       String id = mainModule.set(parameters);
225       theLog.printError("media ID" + id);
226       _edit(id, req, res);
227     }
228     catch (IOException e) {
229       throw new ServletModuleException("upload -- ioexception " + e.toString());
230     }
231     catch (ModuleException e) {
232       throw new ServletModuleException("upload -- moduleexception " + e.toString());
233     }
234
235   }
236
237
238   public void list(HttpServletRequest req, HttpServletResponse res)
239           throws ServletModuleException {
240     // Parameter auswerten
241     SimpleHash mergeData = new SimpleHash();
242     SimpleHash popups = new SimpleHash();
243
244     String query_text = req.getParameter("query_text");
245     mergeData.put("query_text", query_text);
246     if (query_text != null) mergeData.put("query_text_encoded", URLEncoder.encode(query_text));
247     String query_field = req.getParameter("query_field");
248     mergeData.put("query_field", query_field);
249     String query_is_published = req.getParameter("query_is_published");
250     mergeData.put("query_is_published", query_is_published);
251     String query_media_folder = req.getParameter("query_media_folder");
252     mergeData.put("query_media_folder", query_media_folder);
253     String offset = req.getParameter("offset");
254     if (offset == null || offset.equals("")) offset = "0";
255     mergeData.put("offset", offset);
256
257     String order = req.getParameter("order");
258     if (order == null) order = "webdb_lastchange desc";
259
260     // if in connection mode to content
261     String cid = req.getParameter("cid");
262     mergeData.put("cid", cid);
263
264
265     // sql basteln
266     String whereClause = "";
267     boolean isFirst = true;
268     if (query_text != null && !query_text.equalsIgnoreCase("")) {
269       whereClause += "lower(" + query_field + ") like lower('%" + query_text + "%')";
270       isFirst = false;
271     }
272     if (query_is_published != null && !query_is_published.equals("")) {
273       if (isFirst == false) whereClause += " and ";
274       whereClause += "is_published='" + query_is_published + "'";
275       isFirst = false;
276     }
277     if (query_media_folder != null && !query_media_folder.equals("")) {
278       if (isFirst == false) whereClause += " and ";
279       whereClause += "to_media_folder='" + query_media_folder + "'";
280     }
281     //theLog.printDebugInfo("sql-whereclause: " + whereClause + " order: " + order + " offset: " + offset);
282
283     // fetch und ausliefern
284     try {
285       if (query_text != null || query_is_published != null || query_media_folder != null) {
286         EntityList theList = mainModule.getByWhereClause(whereClause, order, (new Integer(offset)).intValue(), 10);
287         if (theList != null) {
288           mergeData.put("contentlist", theList);
289           if (theList.getOrder() != null) {
290             mergeData.put("order", theList.getOrder());
291             mergeData.put("order_encoded", URLEncoder.encode(theList.getOrder()));
292           }
293           mergeData.put("count", (new Integer(theList.getCount())).toString());
294           mergeData.put("from", (new Integer(theList.getFrom())).toString());
295           mergeData.put("to", (new Integer(theList.getTo())).toString());
296           if (theList.hasNextBatch())
297             mergeData.put("next", (new Integer(theList.getNextBatch())).toString());
298           if (theList.hasPrevBatch())
299             mergeData.put("prev", (new Integer(theList.getPrevBatch())).toString());
300         }
301       }
302       //fetch the popups
303       popups.put("mediafolderPopupData", DatabaseMediafolder.getInstance().getPopupData());
304       // raus damit
305       deliver(req, res, mergeData, popups, templateListString);
306     }
307     catch (ModuleException e) {
308       throw new ServletModuleException(e.toString());
309     }
310     catch (Exception e) {
311       throw new ServletModuleException(e.toString());
312     }
313   }
314
315
316   public void add(HttpServletRequest req, HttpServletResponse res)
317           throws ServletModuleException {
318     try {
319       SimpleHash mergeData = new SimpleHash();
320       mergeData.put("new", "1");
321       SimpleHash popups = new SimpleHash();
322       popups.put("mediafolderPopupData", DatabaseMediafolder.getInstance().getPopupData());
323       deliver(req, res, mergeData, popups, templateObjektString);
324     }
325     catch (Exception e) {
326       throw new ServletModuleException(e.toString());
327     }
328   }
329
330   public void edit(HttpServletRequest req, HttpServletResponse res)
331           throws ServletModuleException {
332     String idParam = req.getParameter("id");
333     _edit(idParam, req, res);
334   }
335
336   private void _edit(String idParam, HttpServletRequest req, HttpServletResponse res)
337           throws ServletModuleException {
338     if (idParam != null && !idParam.equals("")) {
339       try {
340         SimpleHash popups = new SimpleHash();
341         popups.put("mediafolderPopupData", DatabaseMediafolder.getInstance().getPopupData());
342         deliver(req, res, mainModule.getById(idParam), popups,
343                 templateObjektString);
344       }
345       catch (ModuleException e) {
346         throw new ServletModuleException(e.toString());
347       }
348       catch (StorageObjectException e) {
349         throw new ServletModuleException(e.toString());
350       }
351     }
352     else {
353       throw new ServletModuleException("ServletmoduleUploadedMedia :: _edit without id");
354     }
355   }
356
357
358   /** @todo should be in ServletModule.java */
359   private EntityUsers _getUser(HttpServletRequest req) {
360     HttpSession session = req.getSession(false);
361     return (EntityUsers) session.getAttribute("login.uid");
362   }
363
364 }
365
366