2 * (C) Copyright 2007 John J. Foerch
3 * (C) Copyright 2007-2008 Jeremy Maitin-Shepard.
5 * Portions of this file were derived from Mozilla,
6 * (C) Copyright 1998-2007 Mozilla Foundation.
8 * Use, modification, and distribution are subject to the terms specified in the
12 /* maybe_get_filename_extension
14 * file_name_s: string filename, may be null.
16 * returns null or extension part of file_name_s.
18 function maybe_get_filename_extension (file_name_s) {
19 var url = Components.classes["@mozilla.org/network/standard-url;1"]
20 .createInstance(Components.interfaces.nsIURL);
21 url.filePath = file_name_s;
22 if (url.fileExtension == '')
24 return url.fileExtension;
28 function maybe_get_url_extension (url_o) {
30 var url = url_o.QueryInterface(Components.interfaces.nsIURL);
31 if (url.fileExtension == '')
33 return url.fileExtension;
39 /* maybe_get_preferred_filename_extension
41 * file_name_s: string filename, may be null.
43 * content_type: string content type, may be null.
45 * returns null, the default extension for the given
46 * content type, or the extension part of file_name_s.
48 function maybe_get_preferred_filename_extension (file_name_s, content_type)
50 var ext = maybe_get_filename_extension (file_name_s);
55 // throws if content_type is an empty string
56 mimeInfo = Components.classes["@mozilla.org/mime;1"]
57 .getService(Components.interfaces.nsIMIMEService)
58 .getFromTypeAndExtension(content_type, ext);
59 primary = mimeInfo.primaryExtension;
62 if (ext && mimeInfo && mimeInfo.extensionExists (ext))
71 function maybe_get_preferred_url_extension (url_o, content_type) {
72 var ext = maybe_get_url_extension (url_o);
77 mimeInfo = Components.classes["@mozilla.org/mime;1"]
78 .getService(Components.interfaces.nsIMIMEService)
79 .getFromTypeAndExtension(content_type, null);
80 primary = mimeInfo.primaryExtension;
83 if (ext && mimeInfo && mimeInfo.extensionExists (ext))
91 function get_default_extension (file_name_s, url_o, content_type) {
92 if (content_type == "text/plain" ||
93 content_type == "application/octet-stream" ||
94 url_o.scheme == "ftp")
98 return (maybe_get_preferred_filename_extension (file_name_s, content_type) ||
99 maybe_get_preferred_url_extension (url_o, content_type));
102 function get_charset_for_save(aDocument)
105 return aDocument.characterSet;
110 function maybe_filename_from_content_disposition (aContentDisposition, charset) {
111 if (aContentDisposition) {
112 const mhp = Components.classes["@mozilla.org/network/mime-hdrparam;1"]
113 .getService(Components.interfaces.nsIMIMEHeaderParam);
114 var dummy = { value: null }; // Need an out param...
118 fileName = mhp.getParameter(aContentDisposition, "filename", charset, true, dummy);
121 fileName = mhp.getParameter(aContentDisposition, "name", charset, true, dummy);
132 function maybe_filename_from_uri(uri) {
134 var url = uri.QueryInterface(Components.interfaces.nsIURL);
135 if (url.fileName != "") {
136 // 2) Use the actual file name, if present
137 var textToSubURI = Cc["@mozilla.org/intl/texttosuburi;1"].getService(Ci.nsITextToSubURI);
138 return textToSubURI.unEscapeURIForUI(url.originCharset || "UTF-8", url.fileName);
141 // This is something like a data: and so forth URI... no filename here.
146 function maybe_filename_from_title(title) {
148 var docTitle = title.replace(/^\s+|\s+$/g, "");
149 if (docTitle && docTitle.length > 0) {
150 // 3) Use the document title
157 function maybe_filename_from_url_last_directory (aURI) {
158 // 5) If this is a directory, use the last directory name
160 var path = aURI.path.match(/\/([^\/]+)\/$/);
161 if (path && path.length > 1)
169 function maybe_filename_from_url_host (aURI) {
170 if (aURI && 'host' in aURI)
175 function maybe_filename_from_localization_default () {
177 return getStringBundle().GetStringFromName("DefaultSaveFileName");
183 function generate_filename_safely_default (filename) {
184 return filename.replace (/[\/]+/g, '_');
187 function generate_filename_safely_darwin (filename) {
188 return filename.replace(/[\:\/]+/g, '_');
191 function generate_filename_safely_winnt (filename)
193 filename = filename.replace (/[\"]+/g, "'");
194 filename = filename.replace (/[\*\:\?]+/g, ' ');
195 filename = filename.replace (/[\<]+/g, '(');
196 filename = filename.replace (/[\>]+/g, ')');
197 filename = filename.replace (/[\\\/\|]+/g, '_');
202 var generate_filename_safely_fn = null;
206 generate_filename_safely_fn = generate_filename_safely_darwin;
209 generate_filename_safely_fn = generate_filename_safely_winnt;
212 generate_filename_safely_fn = generate_filename_safely_default;
217 * spec may be a string (URI), a load spec, or an nsIDOMDocument
219 * extension may be null, in which case an extension is suggested as well
221 function suggest_file_name(spec, extension) {
226 if (spec instanceof Ci.nsIDOMDocument)
227 spec = {document: spec};
229 var file_name = load_spec_filename(spec);
231 document = load_spec_document(spec);
232 uri = load_spec_uri(spec);
233 content_type = load_spec_mime_type(spec);
236 file_name = generate_filename_safely_fn(
237 maybe_filename_from_content_disposition(document && get_document_content_disposition(document),
238 get_charset_for_save(document)) ||
239 ((spec.suggest_filename_from_uri != false) && maybe_filename_from_uri(uri)) ||
240 maybe_filename_from_title(load_spec_title(spec)) ||
241 maybe_filename_from_url_last_directory(uri) ||
242 maybe_filename_from_url_host(uri) ||
243 maybe_filename_from_localization_default() ||
247 var base_name = file_name.replace(/\.[^.]*$/, "");
249 var file_ext = extension || load_spec_filename_extension(spec);
252 file_ext = get_default_extension(file_name, uri, content_type);
253 if (file_ext == "") {
254 let x = file_name.lastIndexOf(".");
258 file_ext = file_name.substring(x+1);
260 if (!file_ext && (/^http(s?)/i).test(uri.scheme) && !content_type ||
261 content_type == "application/octet-stream")
265 if (file_ext != null && file_ext.length > 0)
266 return base_name + "." + file_ext;
271 function suggest_save_path_from_file_name(file_name, buffer) {
272 var cwd = (buffer && buffer.cwd) || default_directory.path;
273 var file = get_file(cwd);
274 file.append(file_name);