7 /* maybe_get_filename_extension
9 * file_name_s: string filename, may be null.
11 * returns null or extension part of file_name_s.
13 function maybe_get_filename_extension (file_name_s) {
14 var url = Components.classes["@mozilla.org/network/standard-url;1"]
15 .createInstance(Components.interfaces.nsIURL);
16 url.filePath = file_name_s;
17 if (url.fileExtension == '')
19 return url.fileExtension;
23 function maybe_get_url_extension (url_o) {
25 var url = url_o.QueryInterface(Components.interfaces.nsIURL);
26 if (url.fileExtension == '')
28 return url.fileExtension;
34 /* maybe_get_preferred_filename_extension
36 * file_name_s: string filename, may be null.
38 * content_type: string content type, may be null.
40 * returns null, the default extension for the given
41 * content type, or the extension part of file_name_s.
43 function maybe_get_preferred_filename_extension (file_name_s, content_type)
45 var ext = maybe_get_filename_extension (file_name_s);
50 // throws if content_type is an empty string
51 mimeInfo = Components.classes["@mozilla.org/mime;1"]
52 .getService(Components.interfaces.nsIMIMEService)
53 .getFromTypeAndExtension(content_type, ext);
54 primary = mimeInfo.primaryExtension;
57 if (ext && mimeInfo && mimeInfo.extensionExists (ext))
66 function maybe_get_preferred_url_extension (url_o, content_type) {
67 var ext = maybe_get_url_extension (url_o);
72 mimeInfo = Components.classes["@mozilla.org/mime;1"]
73 .getService(Components.interfaces.nsIMIMEService)
74 .getFromTypeAndExtension(content_type, null);
75 primary = mimeInfo.primaryExtension;
78 if (ext && mimeInfo && mimeInfo.extensionExists (ext))
86 function get_default_extension (file_name_s, url_o, content_type) {
87 if (content_type == "text/plain" ||
88 content_type == "application/octet-stream" ||
89 url_o.scheme == "ftp")
93 return (maybe_get_preferred_filename_extension (file_name_s, content_type) ||
94 maybe_get_preferred_url_extension (url_o, content_type));
97 function get_charset_for_save(aDocument)
100 return aDocument.characterSet;
105 function maybe_filename_from_content_disposition (aContentDisposition, charset) {
106 if (aContentDisposition) {
107 const mhp = Components.classes["@mozilla.org/network/mime-hdrparam;1"]
108 .getService(Components.interfaces.nsIMIMEHeaderParam);
109 var dummy = { value: null }; // Need an out param...
113 fileName = mhp.getParameter(aContentDisposition, "filename", charset, true, dummy);
116 fileName = mhp.getParameter(aContentDisposition, "name", charset, true, dummy);
127 function maybe_filename_from_uri(uri) {
129 var url = uri.QueryInterface(Components.interfaces.nsIURL);
130 if (url.fileName != "") {
131 // 2) Use the actual file name, if present
132 var textToSubURI = Cc["@mozilla.org/intl/texttosuburi;1"].getService(Ci.nsITextToSubURI);
133 return textToSubURI.unEscapeURIForUI(url.originCharset || "UTF-8", url.fileName);
136 // This is something like a data: and so forth URI... no filename here.
141 function maybe_filename_from_title(title) {
143 var docTitle = title.replace(/^\s+|\s+$/g, "");
144 if (docTitle && docTitle.length > 0) {
145 // 3) Use the document title
152 function maybe_filename_from_url_last_directory (aURI) {
153 // 5) If this is a directory, use the last directory name
155 var path = aURI.path.match(/\/([^\/]+)\/$/);
156 if (path && path.length > 1)
164 function maybe_filename_from_url_host (aURI) {
165 if (aURI && 'host' in aURI)
170 function maybe_filename_from_localization_default () {
172 return getStringBundle().GetStringFromName("DefaultSaveFileName");
178 function generate_filename_safely_default (filename) {
179 return filename.replace (/[\/]+/g, '_');
182 function generate_filename_safely_darwin (filename) {
183 return filename.replace(/[\:\/]+/g, '_');
186 function generate_filename_safely_winnt (filename)
188 filename = filename.replace (/[\"]+/g, "'");
189 filename = filename.replace (/[\*\:\?]+/g, ' ');
190 filename = filename.replace (/[\<]+/g, '(');
191 filename = filename.replace (/[\>]+/g, ')');
192 filename = filename.replace (/[\\\/\|]+/g, '_');
197 var generate_filename_safely_fn = null;
201 generate_filename_safely_fn = generate_filename_safely_darwin;
204 generate_filename_safely_fn = generate_filename_safely_winnt;
207 generate_filename_safely_fn = generate_filename_safely_default;
212 * spec may be a string (URI), a load spec, or an nsIDOMDocument
214 * extension may be null, in which case an extension is suggested as well
216 function suggest_file_name(spec, extension) {
221 if (spec instanceof Ci.nsIDOMDocument)
222 spec = {document: spec};
224 var file_name = load_spec_filename(spec);
226 document = load_spec_document(spec);
227 uri = load_spec_uri(spec);
228 content_type = load_spec_mime_type(spec);
231 file_name = generate_filename_safely_fn(
232 maybe_filename_from_content_disposition(document && get_document_content_disposition(document),
233 get_charset_for_save(document)) ||
234 ((spec.suggest_filename_from_uri != false) && maybe_filename_from_uri(uri)) ||
235 maybe_filename_from_title(load_spec_title(spec)) ||
236 maybe_filename_from_url_last_directory(uri) ||
237 maybe_filename_from_url_host(uri) ||
238 maybe_filename_from_localization_default() ||
242 var base_name = file_name.replace(/\.[^.]*$/, "");
244 var file_ext = extension || load_spec_filename_extension(spec);
247 file_ext = get_default_extension(file_name, uri, content_type);
248 if (file_ext == "") {
249 let x = file_name.lastIndexOf(".");
253 file_ext = file_name.substring(x+1);
255 if (!file_ext && (/^http(s?)/i).test(uri.scheme) && !content_type ||
256 content_type == "application/octet-stream")
260 if (file_ext != null && file_ext.length > 0)
261 return base_name + "." + file_ext;
266 function suggest_save_path_from_file_name(file_name, buffer) {
267 var cwd = (buffer && buffer.cwd) || default_directory.path;
268 var file = get_file(cwd);
269 file.append(file_name);