/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "MimeTypeRegistry.h"
#include "StringHash.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#if PLATFORM(CG)
#include <ApplicationServices/ApplicationServices.h>
#endif
#if PLATFORM(MAC)
#include "WebCoreSystemInterface.h"
#endif
#if PLATFORM(QT)
#include <qimagereader.h>
#endif
namespace WebCore
{
static WTF::HashSet<String>* supportedImageResourceMIMETypes;
static WTF::HashSet<String>* supportedImageMIMETypes;
static WTF::HashSet<String>* supportedNonImageMIMETypes;
void cleanupMimeTypes()
{
if( supportedImageResourceMIMETypes ) {
supportedImageResourceMIMETypes->clear();
delete supportedImageResourceMIMETypes;
supportedImageResourceMIMETypes = 0;
}
if( supportedImageMIMETypes ) {
supportedImageMIMETypes->clear();
delete supportedImageMIMETypes;
supportedImageMIMETypes = 0;
}
if( supportedNonImageMIMETypes ) {
supportedNonImageMIMETypes->clear();
delete supportedNonImageMIMETypes;
supportedNonImageMIMETypes = 0;
}
}
#if PLATFORM(CG)
extern String getMIMETypeForUTI(const String& uti);
#endif
static void initialiseSupportedImageMIMETypes()
{
#if PLATFORM(CG)
CFArrayRef supportedTypes = CGImageSourceCopyTypeIdentifiers();
int cnt = CFArrayGetCount(supportedTypes);
for(int i = 0; i < cnt; i++) {
CFStringRef supportedType = (CFStringRef)CFArrayGetValueAtIndex(supportedTypes, i);
String mimeType=getMIMETypeForUTI(supportedType);
if (!mimeType.isEmpty()) {
supportedImageMIMETypes->add(mimeType);
supportedImageResourceMIMETypes->add(mimeType);
}
CFRelease(supportedType);
}
CFRelease(supportedTypes);
// On Tiger, com.microsoft.bmp doesn't have a MIME type in the registry.
supportedImageMIMETypes->add("image/bmp");
supportedImageResourceMIMETypes->add("image/bmp");
// We only get one MIME type per UTI, hence our need to add these manually
supportedImageMIMETypes->add("image/pjpeg");
supportedImageResourceMIMETypes->add("image/pjpeg");
// We don't want to try to treat all binary data as an image
supportedImageMIMETypes->remove("application/octet-stream");
supportedImageResourceMIMETypes->remove("application/octet-stream");
// Don't treat pdf/postscript as images directly
supportedImageMIMETypes->remove("application/pdf");
supportedImageMIMETypes->remove("application/postscript");
#elif PLATFORM(QT)
QList<QByteArray> formats = QImageReader::supportedImageFormats();
for (size_t i = 0; i < formats.size(); ++i) {
#if ENABLE(SVG)
/*
* Qt has support for SVG, but we want to use KSVG2
*/
if (formats.at(i).toLower().startsWith("svg"))
continue;
#endif
String mimeType = MIMETypeRegistry::getMIMETypeForExtension(formats.at(i).constData());
supportedImageMIMETypes->add(mimeType);
supportedImageResourceMIMETypes->add(mimeType);
}
#else
// assume that all implementations at least support the following standard
// image types:
static const char* types[] = {
"image/jpeg",
"image/png",
"image/gif",
"image/bmp",
"image/x-icon", // ico
#if PLATFORM(SYMBIAN)
"image/vnd.wap.wbmp",
"image/jp2",
"image/jpg",
"image/pjpeg",
"image/tiff",
"image/vnd.nokia.ota-bitmap",
"image/vnd.wap.wbmp",
"image/x-bmp",
"image/x-epoc-mbm",
"image/x-ms-bmp",
"image/x-wmf",
#endif
"image/x-xbitmap" // xbm
};
for (size_t i = 0; i < sizeof(types)/sizeof(types[0]); ++i) {
supportedImageMIMETypes->add(types[i]);
supportedImageResourceMIMETypes->add(types[i]);
}
#endif
}
static void initialiseSupportedNonImageMimeTypes()
{
static const char* types[] = {
"text/html",
"text/xml",
"text/xsl",
"text/plain",
"text/",
"application/x-javascript",
"application/xml",
"application/xhtml+xml",
"application/rss+xml",
"application/atom+xml",
#if PLATFORM(MAC)
"application/x-webarchive",
#endif
"multipart/x-mixed-replace"
#if ENABLE(SVG)
, "image/svg+xml"
#endif
#if ENABLE(FTPDIR)
, "application/x-ftp-directory"
#endif
};
for (size_t i = 0; i < sizeof(types)/sizeof(types[0]); ++i)
supportedNonImageMIMETypes->add(types[i]);
}
static void initialiseMIMETypeRegistry()
{
supportedImageResourceMIMETypes = new WTF::HashSet<String>();
supportedImageMIMETypes = new WTF::HashSet<String>();
supportedNonImageMIMETypes = new WTF::HashSet<String>();
initialiseSupportedNonImageMimeTypes();
initialiseSupportedImageMIMETypes();
}
String MIMETypeRegistry::getMIMETypeForPath(const String& path)
{
int pos = path.reverseFind('.');
if(pos >= 0) {
String extension = path.substring(pos + 1);
return getMIMETypeForExtension(extension);
}
#if PLATFORM(SYMBIAN)
return getDefaultMIMETypeForPath(path);
#else
return "application/octet-stream";
#endif
}
bool MIMETypeRegistry::isSupportedImageMIMEType(const String& mimeType)
{
if (!supportedImageMIMETypes)
initialiseMIMETypeRegistry();
return !mimeType.isEmpty() && supportedImageMIMETypes->contains(mimeType);
}
bool MIMETypeRegistry::isSupportedImageResourceMIMEType(const String& mimeType)
{
if (!supportedImageResourceMIMETypes)
initialiseMIMETypeRegistry();
return !mimeType.isEmpty() && supportedImageResourceMIMETypes->contains(mimeType);
}
bool MIMETypeRegistry::isSupportedNonImageMIMEType(const String& mimeType)
{
if (!supportedNonImageMIMETypes)
initialiseMIMETypeRegistry();
return !mimeType.isEmpty() && supportedNonImageMIMETypes->contains(mimeType);
}
bool MIMETypeRegistry::isJavaAppletMIMEType(const String& mimeType)
{
// Since this set is very limited and is likely to remain so we won't bother with the overhead
// of using a hash set.
// Any of the MIME types below may be followed by any number of specific versions of the JVM,
// which is why we use startsWith()
return mimeType.startsWith("application/x-java-applet", false)
|| mimeType.startsWith("application/x-java-bean", false)
|| mimeType.startsWith("application/x-java-vm", false);
}
HashSet<String> &MIMETypeRegistry::getSupportedImageMIMETypes()
{
if (!supportedImageMIMETypes)
initialiseMIMETypeRegistry();
return *supportedImageMIMETypes;
}
HashSet<String> &MIMETypeRegistry::getSupportedImageResourceMIMETypes()
{
if (!supportedImageResourceMIMETypes)
initialiseMIMETypeRegistry();
return *supportedImageResourceMIMETypes;
}
HashSet<String> &MIMETypeRegistry::getSupportedNonImageMIMETypes()
{
if (!supportedNonImageMIMETypes)
initialiseMIMETypeRegistry();
return *supportedNonImageMIMETypes;
}
}