• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.webkit;
18 
19 import android.text.TextUtils;
20 import java.util.regex.Pattern;
21 import libcore.net.MimeUtils;
22 
23 /**
24  * Two-way map that maps MIME-types to file extensions and vice versa.
25  *
26  * <p>See also {@link java.net.URLConnection#guessContentTypeFromName}
27  * and {@link java.net.URLConnection#guessContentTypeFromStream}. This
28  * class and {@code URLConnection} share the same MIME-type database.
29  */
30 public class MimeTypeMap {
31     private static final MimeTypeMap sMimeTypeMap = new MimeTypeMap();
32 
MimeTypeMap()33     private MimeTypeMap() {
34     }
35 
36     /**
37      * Returns the file extension or an empty string iff there is no
38      * extension. This method is a convenience method for obtaining the
39      * extension of a url and has undefined results for other Strings.
40      * @param url
41      * @return The file extension of the given url.
42      */
getFileExtensionFromUrl(String url)43     public static String getFileExtensionFromUrl(String url) {
44         if (!TextUtils.isEmpty(url)) {
45             int fragment = url.lastIndexOf('#');
46             if (fragment > 0) {
47                 url = url.substring(0, fragment);
48             }
49 
50             int query = url.lastIndexOf('?');
51             if (query > 0) {
52                 url = url.substring(0, query);
53             }
54 
55             int filenamePos = url.lastIndexOf('/');
56             String filename =
57                 0 <= filenamePos ? url.substring(filenamePos + 1) : url;
58 
59             // if the filename contains special characters, we don't
60             // consider it valid for our matching purposes:
61             if (!filename.isEmpty() &&
62                 Pattern.matches("[a-zA-Z_0-9\\.\\-\\(\\)\\%]+", filename)) {
63                 int dotPos = filename.lastIndexOf('.');
64                 if (0 <= dotPos) {
65                     return filename.substring(dotPos + 1);
66                 }
67             }
68         }
69 
70         return "";
71     }
72 
73     /**
74      * Return true if the given MIME type has an entry in the map.
75      * @param mimeType A MIME type (i.e. text/plain)
76      * @return True iff there is a mimeType entry in the map.
77      */
hasMimeType(String mimeType)78     public boolean hasMimeType(String mimeType) {
79         return MimeUtils.hasMimeType(mimeType);
80     }
81 
82     /**
83      * Return the MIME type for the given extension.
84      * @param extension A file extension without the leading '.'
85      * @return The MIME type for the given extension or null iff there is none.
86      */
getMimeTypeFromExtension(String extension)87     public String getMimeTypeFromExtension(String extension) {
88         return MimeUtils.guessMimeTypeFromExtension(extension);
89     }
90 
91     // Static method called by jni.
mimeTypeFromExtension(String extension)92     private static String mimeTypeFromExtension(String extension) {
93         return MimeUtils.guessMimeTypeFromExtension(extension);
94     }
95 
96     /**
97      * Return true if the given extension has a registered MIME type.
98      * @param extension A file extension without the leading '.'
99      * @return True iff there is an extension entry in the map.
100      */
hasExtension(String extension)101     public boolean hasExtension(String extension) {
102         return MimeUtils.hasExtension(extension);
103     }
104 
105     /**
106      * Return the registered extension for the given MIME type. Note that some
107      * MIME types map to multiple extensions. This call will return the most
108      * common extension for the given MIME type.
109      * @param mimeType A MIME type (i.e. text/plain)
110      * @return The extension for the given MIME type or null iff there is none.
111      */
getExtensionFromMimeType(String mimeType)112     public String getExtensionFromMimeType(String mimeType) {
113         return MimeUtils.guessExtensionFromMimeType(mimeType);
114     }
115 
116     /**
117      * If the given MIME type is null, or one of the "generic" types (text/plain
118      * or application/octet-stream) map it to a type that Android can deal with.
119      * If the given type is not generic, return it unchanged.
120      *
121      * @param mimeType MIME type provided by the server.
122      * @param url URL of the data being loaded.
123      * @param contentDisposition Content-disposition header given by the server.
124      * @return The MIME type that should be used for this data.
125      */
remapGenericMimeType(String mimeType, String url, String contentDisposition)126     /* package */ String remapGenericMimeType(String mimeType, String url,
127             String contentDisposition) {
128         // If we have one of "generic" MIME types, try to deduce
129         // the right MIME type from the file extension (if any):
130         if ("text/plain".equals(mimeType) ||
131                 "application/octet-stream".equals(mimeType)) {
132 
133             // for attachment, use the filename in the Content-Disposition
134             // to guess the mimetype
135             String filename = null;
136             if (contentDisposition != null) {
137                 filename = URLUtil.parseContentDisposition(contentDisposition);
138             }
139             if (filename != null) {
140                 url = filename;
141             }
142             String extension = getFileExtensionFromUrl(url);
143             String newMimeType = getMimeTypeFromExtension(extension);
144             if (newMimeType != null) {
145                 mimeType = newMimeType;
146             }
147         } else if ("text/vnd.wap.wml".equals(mimeType)) {
148             // As we don't support wml, render it as plain text
149             mimeType = "text/plain";
150         } else {
151             // It seems that xhtml+xml and vnd.wap.xhtml+xml mime
152             // subtypes are used interchangeably. So treat them the same.
153             if ("application/vnd.wap.xhtml+xml".equals(mimeType)) {
154                 mimeType = "application/xhtml+xml";
155             }
156         }
157         return mimeType;
158     }
159 
160     /**
161      * Get the singleton instance of MimeTypeMap.
162      * @return The singleton instance of the MIME-type map.
163      */
getSingleton()164     public static MimeTypeMap getSingleton() {
165         return sMimeTypeMap;
166     }
167 }
168