/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.webkit;
import android.text.TextUtils;
import java.util.regex.Pattern;
import libcore.net.MimeUtils;
/**
* Two-way map that maps MIME-types to file extensions and vice versa.
*
* <p>See also {@link java.net.URLConnection#guessContentTypeFromName}
* and {@link java.net.URLConnection#guessContentTypeFromStream}. This
* class and {@code URLConnection} share the same MIME-type database.
*/
public class MimeTypeMap {
private static final MimeTypeMap sMimeTypeMap = new MimeTypeMap();
private MimeTypeMap() {
}
/**
* Returns the file extension or an empty string iff there is no
* extension. This method is a convenience method for obtaining the
* extension of a url and has undefined results for other Strings.
* @param url
* @return The file extension of the given url.
*/
public static String getFileExtensionFromUrl(String url) {
if (!TextUtils.isEmpty(url)) {
int fragment = url.lastIndexOf('#');
if (fragment > 0) {
url = url.substring(0, fragment);
}
int query = url.lastIndexOf('?');
if (query > 0) {
url = url.substring(0, query);
}
int filenamePos = url.lastIndexOf('/');
String filename =
0 <= filenamePos ? url.substring(filenamePos + 1) : url;
// if the filename contains special characters, we don't
// consider it valid for our matching purposes:
if (!filename.isEmpty() &&
Pattern.matches("[a-zA-Z_0-9\\.\\-\\(\\)\\%]+", filename)) {
int dotPos = filename.lastIndexOf('.');
if (0 <= dotPos) {
return filename.substring(dotPos + 1);
}
}
}
return "";
}
/**
* Return true if the given MIME type has an entry in the map.
* @param mimeType A MIME type (i.e. text/plain)
* @return True iff there is a mimeType entry in the map.
*/
public boolean hasMimeType(String mimeType) {
return MimeUtils.hasMimeType(mimeType);
}
/**
* Return the MIME type for the given extension.
* @param extension A file extension without the leading '.'
* @return The MIME type for the given extension or null iff there is none.
*/
public String getMimeTypeFromExtension(String extension) {
return MimeUtils.guessMimeTypeFromExtension(extension);
}
// Static method called by jni.
private static String mimeTypeFromExtension(String extension) {
return MimeUtils.guessMimeTypeFromExtension(extension);
}
/**
* Return true if the given extension has a registered MIME type.
* @param extension A file extension without the leading '.'
* @return True iff there is an extension entry in the map.
*/
public boolean hasExtension(String extension) {
return MimeUtils.hasExtension(extension);
}
/**
* Return the registered extension for the given MIME type. Note that some
* MIME types map to multiple extensions. This call will return the most
* common extension for the given MIME type.
* @param mimeType A MIME type (i.e. text/plain)
* @return The extension for the given MIME type or null iff there is none.
*/
public String getExtensionFromMimeType(String mimeType) {
return MimeUtils.guessExtensionFromMimeType(mimeType);
}
/**
* If the given MIME type is null, or one of the "generic" types (text/plain
* or application/octet-stream) map it to a type that Android can deal with.
* If the given type is not generic, return it unchanged.
*
* @param mimeType MIME type provided by the server.
* @param url URL of the data being loaded.
* @param contentDisposition Content-disposition header given by the server.
* @return The MIME type that should be used for this data.
*/
/* package */ String remapGenericMimeType(String mimeType, String url,
String contentDisposition) {
// If we have one of "generic" MIME types, try to deduce
// the right MIME type from the file extension (if any):
if ("text/plain".equals(mimeType) ||
"application/octet-stream".equals(mimeType)) {
// for attachment, use the filename in the Content-Disposition
// to guess the mimetype
String filename = null;
if (contentDisposition != null) {
filename = URLUtil.parseContentDisposition(contentDisposition);
}
if (filename != null) {
url = filename;
}
String extension = getFileExtensionFromUrl(url);
String newMimeType = getMimeTypeFromExtension(extension);
if (newMimeType != null) {
mimeType = newMimeType;
}
} else if ("text/vnd.wap.wml".equals(mimeType)) {
// As we don't support wml, render it as plain text
mimeType = "text/plain";
} else {
// It seems that xhtml+xml and vnd.wap.xhtml+xml mime
// subtypes are used interchangeably. So treat them the same.
if ("application/vnd.wap.xhtml+xml".equals(mimeType)) {
mimeType = "application/xhtml+xml";
}
}
return mimeType;
}
/**
* Get the singleton instance of MimeTypeMap.
* @return The singleton instance of the MIME-type map.
*/
public static MimeTypeMap getSingleton() {
return sMimeTypeMap;
}
}