/* * 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. * *

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; } }