1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <set>
6 #include <string>
7
8 #include "chrome/browser/download/download_extensions.h"
9
10 #include "base/string_util.h"
11 #include "net/base/mime_util.h"
12 #include "net/base/net_util.h"
13
14 namespace download_util {
15
16 // For file extensions taken from mozilla:
17
18 /* ***** BEGIN LICENSE BLOCK *****
19 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
20 *
21 * The contents of this file are subject to the Mozilla Public License Version
22 * 1.1 (the "License"); you may not use this file except in compliance with
23 * the License. You may obtain a copy of the License at
24 * http://www.mozilla.org/MPL/
25 *
26 * Software distributed under the License is distributed on an "AS IS" basis,
27 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
28 * for the specific language governing rights and limitations under the
29 * License.
30 *
31 * The Original Code is Mozilla Communicator client code, released
32 * March 31, 1998.
33 *
34 * The Initial Developer of the Original Code is
35 * Netscape Communications Corporation.
36 * Portions created by the Initial Developer are Copyright (C) 1998-1999
37 * the Initial Developer. All Rights Reserved.
38 *
39 * Contributor(s):
40 * Doug Turner <dougt@netscape.com>
41 * Dean Tessman <dean_tessman@hotmail.com>
42 * Brodie Thiesfield <brofield@jellycan.com>
43 * Jungshik Shin <jshin@i18nl10n.com>
44 *
45 * Alternatively, the contents of this file may be used under the terms of
46 * either of the GNU General Public License Version 2 or later (the "GPL"),
47 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
48 * in which case the provisions of the GPL or the LGPL are applicable instead
49 * of those above. If you wish to allow use of your version of this file only
50 * under the terms of either the GPL or the LGPL, and not to allow others to
51 * use your version of this file under the terms of the MPL, indicate your
52 * decision by deleting the provisions above and replace them with the notice
53 * and other provisions required by the GPL or the LGPL. If you do not delete
54 * the provisions above, a recipient may use your version of this file under
55 * the terms of any one of the MPL, the GPL or the LGPL.
56 *
57 * ***** END LICENSE BLOCK ***** */
58
59 static const struct Executables {
60 const char* extension;
61 DownloadDangerLevel level;
62 } g_executables[] = {
63 { "class", Dangerous },
64 { "htm", AllowOnUserGesture },
65 { "html", AllowOnUserGesture },
66 { "jar", Dangerous },
67 { "jnlp", Dangerous },
68 { "pdf", AllowOnUserGesture },
69 { "pdfxml", AllowOnUserGesture },
70 { "mars", AllowOnUserGesture },
71 { "fdf", AllowOnUserGesture },
72 { "xfdf", AllowOnUserGesture },
73 { "xdp", AllowOnUserGesture },
74 { "xfd", AllowOnUserGesture },
75 { "pl", AllowOnUserGesture },
76 { "py", AllowOnUserGesture },
77 { "rb", AllowOnUserGesture },
78 { "shtm", AllowOnUserGesture },
79 { "shtml", AllowOnUserGesture },
80 { "svg", AllowOnUserGesture },
81 { "swf", AllowOnUserGesture },
82 { "xht", AllowOnUserGesture },
83 { "xhtm", AllowOnUserGesture },
84 { "xhtml", AllowOnUserGesture },
85 { "xml", AllowOnUserGesture },
86 { "xsl", AllowOnUserGesture },
87 { "xslt", AllowOnUserGesture },
88 #if defined(OS_WIN)
89 { "ad", AllowOnUserGesture },
90 { "ade", AllowOnUserGesture },
91 { "adp", AllowOnUserGesture },
92 { "app", AllowOnUserGesture },
93 { "application", AllowOnUserGesture },
94 { "asp", AllowOnUserGesture },
95 { "asx", AllowOnUserGesture },
96 { "bas", AllowOnUserGesture },
97 { "bat", AllowOnUserGesture },
98 { "chi", AllowOnUserGesture },
99 { "chm", AllowOnUserGesture },
100 { "cmd", AllowOnUserGesture },
101 { "com", AllowOnUserGesture },
102 { "cpl", AllowOnUserGesture },
103 { "crt", AllowOnUserGesture },
104 { "dll", Dangerous },
105 { "drv", Dangerous },
106 { "exe", AllowOnUserGesture },
107 { "fxp", AllowOnUserGesture },
108 { "grp", Dangerous },
109 { "hlp", AllowOnUserGesture },
110 { "hta", AllowOnUserGesture },
111 { "htt", AllowOnUserGesture },
112 { "inf", AllowOnUserGesture },
113 { "ins", AllowOnUserGesture },
114 { "isp", AllowOnUserGesture },
115 { "js", AllowOnUserGesture },
116 { "jse", AllowOnUserGesture },
117 { "lnk", AllowOnUserGesture },
118 { "mad", AllowOnUserGesture },
119 { "maf", AllowOnUserGesture },
120 { "mag", AllowOnUserGesture },
121 { "mam", AllowOnUserGesture },
122 { "maq", AllowOnUserGesture },
123 { "mar", AllowOnUserGesture },
124 { "mas", AllowOnUserGesture },
125 { "mat", AllowOnUserGesture },
126 { "mau", AllowOnUserGesture },
127 { "mav", AllowOnUserGesture },
128 { "maw", AllowOnUserGesture },
129 { "mda", AllowOnUserGesture },
130 { "mdb", AllowOnUserGesture },
131 { "mde", AllowOnUserGesture },
132 { "mdt", AllowOnUserGesture },
133 { "mdw", AllowOnUserGesture },
134 { "mdz", AllowOnUserGesture },
135 { "mht", AllowOnUserGesture },
136 { "mhtml", AllowOnUserGesture },
137 { "mmc", AllowOnUserGesture },
138 { "msc", AllowOnUserGesture },
139 { "msh", AllowOnUserGesture },
140 { "mshxml", AllowOnUserGesture },
141 { "msi", AllowOnUserGesture },
142 { "msp", AllowOnUserGesture },
143 { "mst", AllowOnUserGesture },
144 { "ocx", AllowOnUserGesture },
145 { "ops", AllowOnUserGesture },
146 { "pcd", AllowOnUserGesture },
147 { "pif", AllowOnUserGesture },
148 { "plg", AllowOnUserGesture },
149 { "prf", AllowOnUserGesture },
150 { "prg", AllowOnUserGesture },
151 { "pst", AllowOnUserGesture },
152 { "reg", AllowOnUserGesture },
153 { "scf", AllowOnUserGesture },
154 { "scr", AllowOnUserGesture },
155 { "sct", AllowOnUserGesture },
156 { "shb", AllowOnUserGesture },
157 { "shs", AllowOnUserGesture },
158 { "sys", Dangerous },
159 { "url", AllowOnUserGesture },
160 { "vb", AllowOnUserGesture },
161 { "vbe", AllowOnUserGesture },
162 { "vbs", AllowOnUserGesture },
163 { "vsd", AllowOnUserGesture },
164 { "vsmacros", AllowOnUserGesture },
165 { "vss", AllowOnUserGesture },
166 { "vst", AllowOnUserGesture },
167 { "vsw", AllowOnUserGesture },
168 { "ws", AllowOnUserGesture },
169 { "wsc", AllowOnUserGesture },
170 { "wsf", AllowOnUserGesture },
171 { "wsh", AllowOnUserGesture },
172 { "xbap", Dangerous },
173 #elif defined(OS_MACOSX)
174 // TODO(thakis): Figure out what makes sense here -- crbug.com/19096
175 { "app", AllowOnUserGesture },
176 { "dmg", AllowOnUserGesture },
177 #elif defined(OS_POSIX)
178 // TODO(estade): lengthen this list.
179 { "bash", AllowOnUserGesture },
180 { "csh", AllowOnUserGesture },
181 { "deb", AllowOnUserGesture },
182 { "exe", AllowOnUserGesture },
183 { "ksh", AllowOnUserGesture },
184 { "rpm", AllowOnUserGesture },
185 { "sh", AllowOnUserGesture },
186 { "tcsh", AllowOnUserGesture },
187 #endif
188 };
189
GetFileDangerLevel(const FilePath & path)190 DownloadDangerLevel GetFileDangerLevel(const FilePath& path) {
191 return GetFileExtensionDangerLevel(path.Extension());
192 }
193
GetFileExtensionDangerLevel(const FilePath::StringType & extension)194 DownloadDangerLevel GetFileExtensionDangerLevel(
195 const FilePath::StringType& extension) {
196 if (extension.empty())
197 return NotDangerous;
198 if (!IsStringASCII(extension))
199 return NotDangerous;
200 #if defined(OS_WIN)
201 std::string ascii_extension = WideToASCII(extension);
202 #elif defined(OS_POSIX)
203 std::string ascii_extension = extension;
204 #endif
205
206 // Strip out leading dot if it's still there
207 if (ascii_extension[0] == FilePath::kExtensionSeparator)
208 ascii_extension.erase(0, 1);
209
210 for (size_t i = 0; i < arraysize(g_executables); ++i) {
211 if (LowerCaseEqualsASCII(ascii_extension, g_executables[i].extension))
212 return g_executables[i].level;
213 }
214 return NotDangerous;
215 }
216
IsFileSafe(const FilePath & path)217 bool IsFileSafe(const FilePath& path) {
218 return GetFileDangerLevel(path) == NotDangerous;
219 }
220
221 static const char* kExecutableWhiteList[] = {
222 // JavaScript is just as powerful as EXE.
223 "text/javascript",
224 "text/javascript;version=*",
225 "text/html",
226 // Registry files can cause critical changes to the MS OS behavior.
227 // Addition of this mimetype also addresses bug 7337.
228 "text/x-registry",
229 "text/x-sh",
230 // Some sites use binary/octet-stream to mean application/octet-stream.
231 // See http://code.google.com/p/chromium/issues/detail?id=1573
232 "binary/octet-stream"
233 };
234
235 static const char* kExecutableBlackList[] = {
236 // These application types are not executable.
237 "application/*+xml",
238 "application/xml"
239 };
240
IsExecutableMimeType(const std::string & mime_type)241 bool IsExecutableMimeType(const std::string& mime_type) {
242 for (size_t i = 0; i < arraysize(kExecutableWhiteList); ++i) {
243 if (net::MatchesMimeType(kExecutableWhiteList[i], mime_type))
244 return true;
245 }
246 for (size_t i = 0; i < arraysize(kExecutableBlackList); ++i) {
247 if (net::MatchesMimeType(kExecutableBlackList[i], mime_type))
248 return false;
249 }
250 // We consider only other application types to be executable.
251 return net::MatchesMimeType("application/*", mime_type);
252 }
253
254
255 } // namespace download_util
256