/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
/**
* Helper class to get mimetype
*
* @author jcompagner
*/
@SuppressWarnings("nls")
public class MimeTypes
{
public static String getContentType(byte[] data)
{
return getContentType(data, null);
}
public static String getContentType(byte[] data, String name)
{
if (data == null)
{
return null;
}
byte[] header = new byte[11];
System.arraycopy(data, 0, header, 0, Math.min(data.length, header.length));
int c1 = header[0] & 0xff;
int c2 = header[1] & 0xff;
int c3 = header[2] & 0xff;
int c4 = header[3] & 0xff;
int c5 = header[4] & 0xff;
int c6 = header[5] & 0xff;
int c7 = header[6] & 0xff;
int c8 = header[7] & 0xff;
int c9 = header[8] & 0xff;
int c10 = header[9] & 0xff;
int c11 = header[10] & 0xff;
if (c1 == 0xCA && c2 == 0xFE && c3 == 0xBA && c4 == 0xBE)
{
return "application/java-vm";
}
if (c1 == 0xD0 && c2 == 0xCF && c3 == 0x11 && c4 == 0xE0 && c5 == 0xA1 && c6 == 0xB1 && c7 == 0x1A && c8 == 0xE1)
{
// if the name is set then check if it can be validated by name, because it could be a xls or powerpoint
String contentType = guessContentTypeFromName(name);
if (contentType != null)
{
return contentType;
}
return "application/msword";
}
if (c1 == 0x25 && c2 == 0x50 && c3 == 0x44 && c4 == 0x46 && c5 == 0x2d && c6 == 0x31 && c7 == 0x2e)
{
return "application/pdf";
}
if (c1 == 0x38 && c2 == 0x42 && c3 == 0x50 && c4 == 0x53 && c5 == 0x00 && c6 == 0x01)
{
return "image/photoshop";
}
if (c1 == 0x25 && c2 == 0x21 && c3 == 0x50 && c4 == 0x53)
{
return "application/postscript";
}
if (c1 == 0xff && c2 == 0xfb && c3 == 0x30)
{
return "audio/mp3";
}
if (c1 == 0x49 && c2 == 0x44 && c3 == 0x33)
{
return "audio/mp3";
}
if (c1 == 0xAC && c2 == 0xED)
{
// next two bytes are version number, currently 0x00 0x05
return "application/x-java-serialized-object";
}
if (c1 == '<')
{
if (c2 == '!' ||
((c2 == 'h' && (c3 == 't' && c4 == 'm' && c5 == 'l' || c3 == 'e' && c4 == 'a' && c5 == 'd') || (c2 == 'b' && c3 == 'o' && c4 == 'd' && c5 == 'y'))) ||
((c2 == 'H' && (c3 == 'T' && c4 == 'M' && c5 == 'L' || c3 == 'E' && c4 == 'A' && c5 == 'D') || (c2 == 'B' && c3 == 'O' && c4 == 'D' && c5 == 'Y'))))
{
return "text/html";
}
if (c2 == '?' && c3 == 'x' && c4 == 'm' && c5 == 'l' && c6 == ' ')
{
return "application/xml";
}
}
// big and little endian UTF-16 encodings, with byte order mark
if (c1 == 0xfe && c2 == 0xff)
{
if (c3 == 0 && c4 == '<' && c5 == 0 && c6 == '?' && c7 == 0 && c8 == 'x')
{
return "application/xml";
}
}
if (c1 == 0xff && c2 == 0xfe)
{
if (c3 == '<' && c4 == 0 && c5 == '?' && c6 == 0 && c7 == 'x' && c8 == 0)
{
return "application/xml";
}
}
if (c1 == 'B' && c2 == 'M')
{
return "image/bmp";
}
if (c1 == 0x49 && c2 == 0x49 && c3 == 0x2a && c4 == 0x00)
{
return "image/tiff";
}
if (c1 == 0x4D && c2 == 0x4D && c3 == 0x00 && c4 == 0x2a)
{
return "image/tiff";
}
if (c1 == 'G' && c2 == 'I' && c3 == 'F' && c4 == '8')
{
return "image/gif";
}
if (c1 == '#' && c2 == 'd' && c3 == 'e' && c4 == 'f')
{
return "image/x-bitmap";
}
if (c1 == '!' && c2 == ' ' && c3 == 'X' && c4 == 'P' && c5 == 'M' && c6 == '2')
{
return "image/x-pixmap";
}
if (c1 == 137 && c2 == 80 && c3 == 78 && c4 == 71 && c5 == 13 && c6 == 10 && c7 == 26 && c8 == 10)
{
return "image/png";
}
if (c1 == 0xFF && c2 == 0xD8 && c3 == 0xFF)
{
if (c4 == 0xE0)
{
return "image/jpeg";
}
/**
* File format used by digital cameras to store images. Exif Format can be read by any application supporting JPEG. Exif Spec can be found at:
* http://www.pima.net/standards/it10/PIMA15740/Exif_2-1.PDF
*/
if ((c4 == 0xE1) && (c7 == 'E' && c8 == 'x' && c9 == 'i' && c10 == 'f' && c11 == 0))
{
return "image/jpeg";
}
if (c4 == 0xEE)
{
return "image/jpg";
}
}
/**
* According to http://www.opendesign.com/files/guestdownloads/OpenDesign_Specification_for_.dwg_files.pdf
* first 6 bytes are of type "AC1018" (for example) and the next 5 bytes are 0x00.
*/
if ((c1 == 0x41 && c2 == 0x43) && (c7 == 0x00 && c8 == 0x00 && c9 == 0x00 && c10 == 0x00 && c11 == 0x00))
{
return "application/acad";
}
if (c1 == 0x2E && c2 == 0x73 && c3 == 0x6E && c4 == 0x64)
{
return "audio/basic"; // .au
// format,
// big
// endian
}
if (c1 == 0x64 && c2 == 0x6E && c3 == 0x73 && c4 == 0x2E)
{
return "audio/basic"; // .au
// format,
// little
// endian
}
if (c1 == 'R' && c2 == 'I' && c3 == 'F' && c4 == 'F')
{
/*
* I don't know if this is official but evidence suggests that .wav files start with "RIFF" - brown
*/
return "audio/x-wav";
}
if (c1 == 'P' && c2 == 'K')
{
// its application/zip but this could be a open office thing if name is given
String contentType = guessContentTypeFromName(name);
if (contentType != null)
{
return contentType;
}
return "application/zip";
}
return guessContentTypeFromName(name);
}
private static final Map<String, String> mimeTypes = new HashMap<String, String>();
public static String guessContentTypeFromName(String name)
{
if (name == null) return null;
int lastIndex = name.lastIndexOf('.');
if (lastIndex != -1)
{
String extention = name.substring(lastIndex + 1).toLowerCase();
if (mimeTypes.size() == 0)
{
HashMap<String, String> tempMap = new HashMap<String, String>();
InputStream is = MimeTypes.class.getResourceAsStream("mime.types.properties");
try
{
Properties properties = new Properties();
properties.load(is);
for (Object key : properties.keySet())
{
String property = properties.getProperty((String)key);
StringTokenizer st = new StringTokenizer(property, " ");
while (st.hasMoreTokens())
{
tempMap.put(st.nextToken(), (String)key);
}
}
}
catch (IOException e)
{
Debug.error(e);
}
finally
{
try
{
is.close();
}
catch (IOException e)
{
Debug.error(e);
}
}
synchronized (mimeTypes)
{
mimeTypes.putAll(tempMap);
}
}
return mimeTypes.get(extention);
}
return null;
}
}