google-images.js: fix two regexp uses
[conkeror.git] / modules / suggest-file-name.js
blob5857fd66337a8f7fa4e086b3394fa0a98223b6c0
1 /**
2  * (C) Copyright 2007,2010 John J. Foerch
3  * (C) Copyright 2007-2008 Jeremy Maitin-Shepard.
4  *
5  * Portions of this file were derived from Mozilla,
6  * (C) Copyright 1998-2007 Mozilla Foundation.
7  *
8  * Use, modification, and distribution are subject to the terms specified in the
9  * COPYING file.
10 **/
12 in_module(null);
14 /**
15  * maybe_get_filename_extension
16  *
17  * file_name_s: string filename, may be null.
18  *
19  * returns null or extension part of file_name_s.
20  */
21 function maybe_get_filename_extension (file_name_s) {
22     var url = Cc["@mozilla.org/network/standard-url;1"]
23         .createInstance(Ci.nsIURL);
24     url.filePath = file_name_s;
25     if (url.fileExtension == '')
26         return null;
27     return url.fileExtension;
31 function maybe_get_url_extension (url_o) {
32     try {
33         var url = url_o.QueryInterface(Ci.nsIURL);
34         if (url.fileExtension == '')
35             return null;
36         return url.fileExtension;
37     } catch (e) {
38         return null;
39     }
42 /**
43  * maybe_get_preferred_filename_extension
44  *
45  * file_name_s: string filename, may be null.
46  *
47  * content_type: string content type, may be null.
48  *
49  * returns null, the default extension for the given
50  * content type, or the extension part of file_name_s.
51  */
52 function maybe_get_preferred_filename_extension (file_name_s, content_type) {
53     var ext = maybe_get_filename_extension (file_name_s);
54     var mimeInfo = null;
55     var primary = null;
56     if (content_type) {
57         try {
58             // throws if content_type is an empty string
59             mimeInfo = Cc["@mozilla.org/mime;1"]
60                 .getService(Ci.nsIMIMEService)
61                 .getFromTypeAndExtension(content_type, ext);
62             primary = mimeInfo.primaryExtension;
63         } catch (e) { }
64     }
65     if (ext && mimeInfo && mimeInfo.extensionExists(ext))
66         return ext;
67     else if (primary)
68         return primary;
69     else
70         return ext;
74 function maybe_get_preferred_url_extension (url_o, content_type) {
75     var ext = maybe_get_url_extension(url_o);
76     var mimeInfo = null;
77     var primary = null;
78     if (content_type) {
79         try {
80             mimeInfo = Cc["@mozilla.org/mime;1"]
81                 .getService(Ci.nsIMIMEService)
82                 .getFromTypeAndExtension(content_type, null);
83             primary = mimeInfo.primaryExtension;
84         } catch (e) { }
85     }
86     if (ext && mimeInfo && mimeInfo.extensionExists(ext))
87         return ext;
88     else if (primary)
89         return primary;
90     else
91         return ext;
94 function get_default_extension (file_name_s, url_o, content_type) {
95     if (content_type == "text/plain" ||
96         content_type == "application/octet-stream" ||
97         url_o.scheme == "ftp")
98     {
99         return "";
100     }
101     return (maybe_get_preferred_filename_extension(file_name_s, content_type) ||
102             maybe_get_preferred_url_extension(url_o, content_type));
105 function get_charset_for_save (doc) {
106     if (doc)
107         return doc.characterSet;
108     return null;
111 function maybe_filename_from_content_disposition (spec) {
112     var document = load_spec_document(spec);
113     var content_disposition = (document && get_document_content_disposition(document));
114     var charset = get_charset_for_save(document);
115     if (content_disposition) {
116         const mhp = Cc["@mozilla.org/network/mime-hdrparam;1"]
117             .getService(Ci.nsIMIMEHeaderParam);
118         var dummy = { value: null };  // Need an out param...
120         var filename = null;
121         try {
122             filename = mhp.getParameter(content_disposition, "filename", charset, true, dummy);
123         } catch (e) {
124             try {
125                 filename = mhp.getParameter(content_disposition, "name", charset, true, dummy);
126             } catch (e) { }
127         }
128         if (filename)
129             return filename;
130         else
131             return null;
132     }
133     return null;
136 function maybe_filename_from_uri (spec) {
137     var uri = load_spec_uri(spec);
138     try {
139         var url = uri.QueryInterface(Ci.nsIURL);
140         if (url.fileName != "") {
141             // 2) Use the actual file name, if present
142             var text_to_sub_uri = Cc["@mozilla.org/intl/texttosuburi;1"].
143                 getService(Ci.nsITextToSubURI);
144             return text_to_sub_uri.unEscapeURIForUI(url.originCharset ||
145                                                     "UTF-8", url.fileName);
146         }
147     } catch (e) {
148         // This is something like a data: and so forth URI... no filename here.
149     }
150     return null;
154  * maybe_filename_from_title returns a filename from the load-spec's title
155  * property if and only if the load-spec has neither a document nor an
156  * element property.  In those cases, defer to generating the filename
157  * from the uri.
158  */
159 function maybe_filename_from_title (spec) {
160     if (load_spec_document(spec) || load_spec_element(spec))
161         return null;
162     var title = load_spec_title(spec);
163     if (title) {
164         title = trim_whitespace(title);
165         if (title)
166             return title + ".";
167     }
168     return null;
171 function maybe_filename_from_url_last_directory (spec) {
172     var uri = load_spec_uri(spec);
173     try {
174         var path = uri.path.match(/\/([^\/]+)\/$/);
175         if (path && path.length > 1)
176             return path[1] + ".";
177         return null;
178     } catch (e) {
179         return null;
180     }
183 function maybe_filename_from_url_host (spec) {
184     var uri = load_spec_uri(spec);
185     if (uri && 'host' in uri) {
186         try {
187             return uri.host + ".";
188         } catch (e) {}
189     }
190     return null;
193 function maybe_filename_from_localization_default () {
194     try {
195         return getStringBundle().GetStringFromName("DefaultSaveFileName");
196     } catch (e) {
197         return null;
198     }
203  * Sanitize filename for various platforms.
204  */
206 function generate_filename_safely_default (filename) {
207     return filename.replace(/[\/]+/g, '_');
210 function generate_filename_safely_darwin (filename) {
211     return filename.replace(/[\:\/]+/g, '_');
214 function generate_filename_safely_winnt (filename) {
215     filename = filename.replace(/[\"]+/g,     "'");
216     filename = filename.replace(/[\*\:\?]+/g, ' ');
217     filename = filename.replace(/[\<]+/g,     '(');
218     filename = filename.replace(/[\>]+/g,     ')');
219     filename = filename.replace(/[\\\/\|]+/g, '_');
220     return filename;
224 define_variable("generate_filename_safely_fn",
225     ({ Darwin: generate_filename_safely_darwin,
226        WINNT: generate_filename_safely_winnt }[get_os()]
227      || generate_filename_safely_default),
228     "Function to sanitize the filenames generated by suggest_file_name "+
229     "for the current platform.");
233  * spec may be a string (URI), a load spec, or an nsIDOMDocument
235  * extension may be null, in which case an extension is suggested as well
236  */
237 function suggest_file_name (spec, extension) {
238     if (typeof spec == "string" || spec instanceof Ci.nsIDOMDocument)
239         spec = load_spec(spec);
241     var file_name = load_spec_filename(spec);
242     var uri = load_spec_uri(spec);
243     var content_type = load_spec_mime_type(spec);
245     if (! file_name) {
246         file_name = generate_filename_safely_fn(
247             maybe_filename_from_content_disposition(spec) ||
248             maybe_filename_from_title(spec) ||
249             maybe_filename_from_uri(spec) ||
250             maybe_filename_from_url_last_directory(spec) ||
251             maybe_filename_from_url_host(spec) ||
252             maybe_filename_from_localization_default() ||
253             "index");
254     }
255     var base_name = file_name.replace(/\.[^.]*$/, "");
257     var file_ext = extension || load_spec_filename_extension(spec);
259     if (! file_ext) {
260         file_ext = get_default_extension(file_name, uri, content_type);
261         if (file_ext == "") {
262             let x = file_name.lastIndexOf(".");
263             if (x == -1)
264                 file_ext = null;
265             else
266                 file_ext = file_name.substring(x+1);
267         }
268         if (!file_ext && (/^http(s?)/i).test(uri.scheme) && !content_type ||
269             content_type == "application/octet-stream")
270         {
271             file_ext = "html";
272         }
273     }
275     if (file_ext != null && file_ext.length > 0)
276         return base_name + "." + file_ext;
277     else
278         return base_name;
281 function suggest_save_path_from_file_name (file_name, buffer) {
282     var cwd = with_current_buffer(buffer, function (I) I.local.cwd);
283     var file = cwd.clone();
284     file.append(file_name);
285     return file.path;
288 provide("suggest-file-name");