/** * Determine whether or not a given focused DOMWindow is in the content * area. **/ function openNewTabWith(href, linkNode, event, securityCheck, postData) { if (securityCheck) urlSecurityCheck(href, document); var prefSvc = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); prefSvc = prefSvc.getBranch(null); // should we open it in a new tab? var loadInBackground = true; try { loadInBackground = prefSvc.getBoolPref("browser.tabs.loadInBackground"); } catch(ex) { } if (event && event.shiftKey) loadInBackground = !loadInBackground; // As in openNewWindowWith(), we want to pass the charset of the // current document over to a new tab. var wintype = document.firstChild.getAttribute('windowtype'); var originCharset; if (wintype == "navigator:browser") { originCharset = window._content.document.characterSet; } // open link in new tab var browser = top.document.getElementById("content"); var theTab = browser.addTab(href, getReferrer(document), originCharset, postData); if (!loadInBackground) browser.selectedTab = theTab; if (linkNode) markLinkVisited(href, linkNode); } function openNewWindowWith(href, linkNode, securityCheck, postData) { if (securityCheck) urlSecurityCheck(href, document); // if and only if the current window is a browser window and it has a document with a character // set, then extract the current charset menu setting from the current document and use it to // initialize the new browser window... var charsetArg = null; var wintype = document.firstChild.getAttribute('windowtype'); if (wintype == "navigator:browser") charsetArg = "charset=" + window._content.document.characterSet; var referrer = getReferrer(document); window.openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no", href, charsetArg, referrer, postData); if (linkNode) markLinkVisited(href, linkNode); } function markLinkVisited(href, linkNode) { var globalHistory = Components.classes["@mozilla.org/browser/global-history;2"] .getService(Components.interfaces.nsIGlobalHistory2); var uri = makeURL(href); if (!globalHistory.isVisited(uri)) { globalHistory.addURI(uri, false, true, null); var oldHref = linkNode.getAttribute("href"); if (typeof oldHref == "string") { // Use setAttribute instead of direct assignment. // (bug 217195, bug 187195) linkNode.setAttribute("href", ""); linkNode.setAttribute("href", oldHref); } else { // Converting to string implicitly would be a // minor security hole (similar to bug 202994). } } } function urlSecurityCheck(url, doc) { // URL Loading Security Check var focusedWindow = doc.commandDispatcher.focusedWindow; var sourceURL = getContentFrameURI(focusedWindow); const nsIScriptSecurityManager = Components.interfaces.nsIScriptSecurityManager; var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"] .getService(nsIScriptSecurityManager); try { secMan.checkLoadURIStr(sourceURL, url, nsIScriptSecurityManager.STANDARD); } catch (e) { throw "Load of " + url + " denied."; } } function isContentFrame(aFocusedWindow) { if (!aFocusedWindow) return false; var focusedTop = Components.lookupMethod(aFocusedWindow, 'top') .call(aFocusedWindow); return (focusedTop == window.content); } function getContentFrameURI(aFocusedWindow) { var contentFrame = isContentFrame(aFocusedWindow) ? aFocusedWindow : window.content; if (contentFrame) return Components.lookupMethod(contentFrame, 'location').call(contentFrame).href; else return null; } function getReferrer(doc) { var focusedWindow = doc.commandDispatcher.focusedWindow; var sourceURL = getContentFrameURI(focusedWindow); if (sourceURL) { try { return makeURL(sourceURL); } catch (e) { } } return null; } const kSaveAsType_Complete = 0; // Save document with attached objects const kSaveAsType_URL = 1; // Save document or URL by itself const kSaveAsType_Text = 2; // Save document, converting to plain text. // Clientelle: (Make sure you don't break any of these) // - File -> Save Page/Frame As... // - Context -> Save Page/Frame As... // - Context -> Save Link As... // - Context -> Save Image As... // - Alt-Click links in web pages // - Alt-Click links in the UI // // Try saving each of these types: // - A complete webpage using File->Save Page As, and Context->Save Page As // - A webpage as HTML only using the above methods // - A webpage as Text only using the above methods // - An image with an extension (e.g. .jpg) in its file name, using // Context->Save Image As... // - An image without an extension (e.g. a banner ad on cnn.com) using // the above method. // - A linked document using Save Link As... // - A linked document using Alt-click Save Link As... // function saveURL(aURL, aFileName, aFilePickerTitleKey, aShouldBypassCache, aSkipPrompt, aReferrer) { saveInternal(aURL, null, aFileName, aFilePickerTitleKey, aShouldBypassCache, aSkipPrompt, aReferrer); } function saveDocument(aDocument, aSkipPrompt) { // In both cases here, we want to use cached data because the // document is currently visible. if (aDocument) saveInternal(aDocument.location.href, aDocument, false, aSkipPrompt); else saveInternal(_content.location.href, null, false, aSkipPrompt); } function saveInternal(aURL, aDocument, aFileName, aFilePickerTitleKey, aShouldBypassCache, aSkipPrompt, aReferrer) { if (aSkipPrompt == undefined) aSkipPrompt = false; var data = { url: aURL, fileName: aFileName, filePickerTitle: aFilePickerTitleKey, document: aDocument, bypassCache: aShouldBypassCache, window: window, referrer: aReferrer }; var sniffer = new nsHeaderSniffer(aURL, foundHeaderInfo, data, aSkipPrompt); } function foundHeaderInfo(aSniffer, aData, aSkipPrompt) { var contentType = aSniffer.contentType; var contentEncodingType = aSniffer.contentEncodingType; var shouldDecode = false; // Are we allowed to decode? try { const helperAppService = Components.classes["@mozilla.org/uriloader/external-helper-app-service;1"]. getService(Components.interfaces.nsIExternalHelperAppService); var url = aSniffer.uri.QueryInterface(Components.interfaces.nsIURL); var urlExt = url.fileExtension; if (helperAppService.applyDecodingForExtension(urlExt, contentEncodingType)) { shouldDecode = true; } } catch (e) { } var isDocument = aData.document != null && isDocumentType(contentType); if (!isDocument && !shouldDecode && contentEncodingType) { // The data is encoded, we are not going to decode it, and this is not a // document save so we won't be doing a "save as, complete" (which would // break if we reset the type here). So just set our content type to // correspond to the outermost encoding so we get extensions and the like // right. contentType = contentEncodingType; } var file = null; var saveAsType = kSaveAsType_URL; try { file = aData.fileName.QueryInterface(Components.interfaces.nsILocalFile); } catch (e) { var saveAsTypeResult = { rv: 0 }; file = getTargetFile(aData, aSniffer, contentType, isDocument, aSkipPrompt, saveAsTypeResult); if (!file) return; saveAsType = saveAsTypeResult.rv; } // If we're saving a document, and are saving either in complete mode or // as converted text, pass the document to the web browser persist component. // If we're just saving the HTML (second option in the list), send only the URI. var source = (isDocument && saveAsType != kSaveAsType_URL) ? aData.document : aSniffer.uri; var persistArgs = { source : source, contentType : (isDocument && saveAsType == kSaveAsType_Text) ? "text/plain" : contentType, target : makeFileURL(file), postData : aData.document ? getPostData() : null, bypassCache : aData.bypassCache }; var persist = makeWebBrowserPersist(); // Calculate persist flags. const nsIWBP = Components.interfaces.nsIWebBrowserPersist; const flags = nsIWBP.PERSIST_FLAGS_NO_CONVERSION | nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES; if (aData.bypassCache) persist.persistFlags = flags | nsIWBP.PERSIST_FLAGS_BYPASS_CACHE; else persist.persistFlags = flags | nsIWBP.PERSIST_FLAGS_FROM_CACHE; if (shouldDecode) persist.persistFlags &= ~nsIWBP.PERSIST_FLAGS_NO_CONVERSION; // Create download and initiate it (below) var dl = Components.classes["@mozilla.org/download;1"].createInstance(Components.interfaces.nsIDownload); if (isDocument && saveAsType != kSaveAsType_URL) { // Saving a Document, not a URI: var filesFolder = null; if (persistArgs.contentType != "text/plain") { // Create the local directory into which to save associated files. filesFolder = file.clone(); var nameWithoutExtension = filesFolder.leafName; nameWithoutExtension = nameWithoutExtension.substring(0, nameWithoutExtension.lastIndexOf(".")); var filesFolderLeafName = getStringBundle().formatStringFromName("filesFolder", [nameWithoutExtension], 1); filesFolder.leafName = filesFolderLeafName; } var encodingFlags = 0; if (persistArgs.contentType == "text/plain") { encodingFlags |= nsIWBP.ENCODE_FLAGS_FORMATTED; encodingFlags |= nsIWBP.ENCODE_FLAGS_ABSOLUTE_LINKS; encodingFlags |= nsIWBP.ENCODE_FLAGS_NOFRAMES_CONTENT; } else { encodingFlags |= nsIWBP.ENCODE_FLAGS_ENCODE_BASIC_ENTITIES; } const kWrapColumn = 80; dl.init(aSniffer.uri, persistArgs.target, null, null, null, persist); persist.saveDocument(persistArgs.source, persistArgs.target, filesFolder, persistArgs.contentType, encodingFlags, kWrapColumn); } else { dl.init(source, persistArgs.target, null, null, null, persist); var referrer = aData.referrer || getReferrer(document) persist.saveURI(source, null, referrer, persistArgs.postData, null, persistArgs.target); } } function getTargetFile(aData, aSniffer, aContentType, aIsDocument, aSkipPrompt, aSaveAsTypeResult) { aSaveAsTypeResult.rv = kSaveAsType_Complete; // Determine what the 'default' string to display in the File Picker dialog // should be. var defaultFileName = getDefaultFileName(aData.fileName, aSniffer.suggestedFileName, aSniffer.uri, aData.document); var defaultExtension = getDefaultExtension(defaultFileName, aSniffer.uri, aContentType); var defaultString = getNormalizedLeafName(defaultFileName, defaultExtension); const prefSvcContractID = "@mozilla.org/preferences-service;1"; const prefSvcIID = Components.interfaces.nsIPrefService; var prefs = Components.classes[prefSvcContractID].getService(prefSvcIID).getBranch("browser.download."); const nsILocalFile = Components.interfaces.nsILocalFile; // ben 07/31/2003: // |browser.download.defaultFolder| holds the default download folder for // all files when the user has elected to have all files automatically // download to a folder. The values of |defaultFolder| can be either their // desktop, their downloads folder (My Documents\My Downloads) or some other // location of their choosing (which is mapped to |browser.download.dir| // This pref is _unset_ when the user has elected to be asked about where // to place every download - this will force the prompt to ask the user // where to put saved files. var dir = null; try { dir = prefs.getComplexValue("defaultFolder", nsILocalFile); } catch (e) { } var file; if (!aSkipPrompt || !dir) { // If we're asking the user where to save the file, root the Save As... // dialog on they place they last picked. try { dir = prefs.getComplexValue("lastDir", nsILocalFile); } catch (e) { // No default download location. Default to desktop. var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties); function getDesktopKey() { #ifdef XP_WIN return "DeskP"; #endif #ifdef XP_MACOSX return "UsrDsk"; #endif #ifdef XP_OS2 return "Desk"; #endif return "Home"; } dir = fileLocator.get(getDesktopKey(), Components.interfaces.nsILocalFile); } var fp = makeFilePicker(); var titleKey = aData.filePickerTitle || "SaveLinkTitle"; var bundle = getStringBundle(); fp.init(window, bundle.GetStringFromName(titleKey), Components.interfaces.nsIFilePicker.modeSave); var urlExt = null; try { var url = aSniffer.uri.QueryInterface(Components.interfaces.nsIURL); urlExt = url.fileExtension; } catch (e) { } appendFiltersForContentType(fp, aContentType, urlExt, aIsDocument ? MODE_COMPLETE : MODE_FILEONLY); if (dir) fp.displayDirectory = dir; if (aIsDocument) { try { fp.filterIndex = prefs.getIntPref("save_converter_index"); } catch (e) { } } fp.defaultExtension = defaultExtension; fp.defaultString = defaultString; if (fp.show() == Components.interfaces.nsIFilePicker.returnCancel || !fp.file) return null; var useDownloadDir = false; try { useDownloadDir = prefs.getBoolPref("useDownloadDir"); } catch(ex) { } var directory = fp.file.parent.QueryInterface(nsILocalFile); prefs.setComplexValue("lastDir", nsILocalFile, directory); fp.file.leafName = validateFileName(fp.file.leafName); aSaveAsTypeResult.rv = fp.filterIndex; file = fp.file; if (aIsDocument) prefs.setIntPref("save_converter_index", aSaveAsTypeResult.rv); } else { // ben 07/31/2003: // We don't nullcheck dir here because dir should never be null if we get here // unless something is badly wrong, and if it is, I want to know about it in // bugs. dir.append(defaultString); file = dir; // Since we're automatically downloading, we don't get the file picker's // logic to check for existing files, so we need to do that here. // // Note - this code is identical to that in // browser/components/downloads/content/nsHelperAppDlg.js. // If you are updating this code, update that code too! We can't share code // here since that code is called in a js component. while (file.exists()) { var parts = /.+-(\d+)(\..*)?$/.exec(file.leafName); if (parts) { file.leafName = file.leafName.replace(/((\d+)\.)|((\d+)$)/, function (str, dot, dotNum, noDot, noDotNum, pos, s) { return (parseInt(str) + 1) + (dot ? "." : ""); }); } else { file.leafName = file.leafName.replace(/\.|$/, "-1$&"); } } } return file; } function nsHeaderSniffer(aURL, aCallback, aData, aSkipPrompt) { this.mCallback = aCallback; this.mData = aData; this.mSkipPrompt = aSkipPrompt; this.uri = makeURL(aURL); this.linkChecker = Components.classes["@mozilla.org/network/urichecker;1"] .createInstance(Components.interfaces.nsIURIChecker); this.linkChecker.init(this.uri); var flags; if (aData.bypassCache) { flags = Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE; } else { flags = Components.interfaces.nsIRequest.LOAD_FROM_CACHE; } this.linkChecker.loadFlags = flags; this.linkChecker.asyncCheck(this, null); } nsHeaderSniffer.prototype = { // ---------- nsISupports methods ---------- QueryInterface: function (iid) { if (!iid.equals(Components.interfaces.nsIRequestObserver) && !iid.equals(Components.interfaces.nsISupports) && !iid.equals(Components.interfaces.nsIInterfaceRequestor)) { throw Components.results.NS_ERROR_NO_INTERFACE; } return this; }, // ---------- nsIInterfaceRequestor methods ---------- getInterface : function(iid) { if (iid.equals(Components.interfaces.nsIAuthPrompt)) { // use the window watcher service to get a nsIAuthPrompt impl var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"] .getService(Components.interfaces.nsIWindowWatcher); return ww.getNewAuthPrompter(window); } Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE; return null; }, // ---------- nsIRequestObserver methods ---------- onStartRequest: function (aRequest, aContext) { }, onStopRequest: function (aRequest, aContext, aStatus) { try { if (aStatus == 0) { // NS_BINDING_SUCCEEDED, so there's something there var linkChecker = aRequest.QueryInterface(Components.interfaces.nsIURIChecker); var channel = linkChecker.baseChannel; this.contentType = channel.contentType; try { var httpChannel = channel.QueryInterface(Components.interfaces.nsIHttpChannel); var encodedChannel = channel.QueryInterface(Components.interfaces.nsIEncodedChannel); this.contentEncodingType = null; // There may be content-encodings on the channel. Multiple content // encodings are allowed, eg "Content-Encoding: gzip, uuencode". This // header would mean that the content was first gzipped and then // uuencoded. The encoding enumerator returns MIME types // corresponding to each encoding starting from the end, so the first // thing it returns corresponds to the outermost encoding. var encodingEnumerator = encodedChannel.contentEncodings; if (encodingEnumerator && encodingEnumerator.hasMore()) { try { this.contentEncodingType = encodingEnumerator.getNext(); } catch (e) { } } this.mContentDisposition = httpChannel.getResponseHeader("content-disposition"); } catch (e) { } if (!this.contentType || this.contentType == "application/x-unknown-content-type") { // We didn't get a type from the server. Fall back on other type detection mechanisms throw "Unknown Type"; } } else { dump("Error saving link aStatus = 0x" + aStatus.toString(16) + "\n"); var bundle = getStringBundle(); var errorTitle = bundle.GetStringFromName("saveLinkErrorTitle"); var errorMsg = bundle.GetStringFromName("saveLinkErrorMsg"); const promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService); promptService.alert(this.mData.window, errorTitle, errorMsg); return; } } catch (e) { if (this.mData.document) { this.contentType = this.mData.document.contentType; } else { var type = getMIMETypeForURI(this.uri); if (type) this.contentType = type; } } this.mCallback(this, this.mData, this.mSkipPrompt); }, // ------------------------------------------------ get promptService() { var promptSvc; try { promptSvc = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(); promptSvc = promptSvc.QueryInterface(Components.interfaces.nsIPromptService); } catch (e) {} return promptSvc; }, get suggestedFileName() { var fileName = ""; if (this.mContentDisposition) { const mhpContractID = "@mozilla.org/network/mime-hdrparam;1" const mhpIID = Components.interfaces.nsIMIMEHeaderParam; const mhp = Components.classes[mhpContractID].getService(mhpIID); var dummy = { value: null }; // To make JS engine happy. var charset = getCharsetforSave(null); try { fileName = mhp.getParameter(this.mContentDisposition, "filename", charset, true, dummy); } catch (e) { try { fileName = mhp.getParameter(this.mContentDisposition, "name", charset, true, dummy); } catch (e) { } } } fileName = fileName.replace(/^"|"$/g, ""); return fileName; } }; const MODE_COMPLETE = 0; const MODE_FILEONLY = 1; function appendFiltersForContentType(aFilePicker, aContentType, aFileExtension, aSaveMode) { var bundle = getStringBundle(); switch (aContentType) { case "text/html": if (aSaveMode == MODE_COMPLETE) aFilePicker.appendFilter(bundle.GetStringFromName("WebPageCompleteFilter"), "*.htm; *.html"); aFilePicker.appendFilter(bundle.GetStringFromName("WebPageHTMLOnlyFilter"), "*.htm; *.html"); if (aSaveMode == MODE_COMPLETE) aFilePicker.appendFilters(Components.interfaces.nsIFilePicker.filterText); break; default: var mimeInfo = getMIMEInfoForType(aContentType, aFileExtension); if (mimeInfo) { var extEnumerator = mimeInfo.getFileExtensions(); var extString = ""; var defaultDesc = ""; var plural = false; while (extEnumerator.hasMore()) { if (defaultDesc) { defaultDesc += ", "; plural = true; } var extension = extEnumerator.getNext(); if (extString) extString += "; "; // If adding more than one extension, // separate by semi-colon extString += "*." + extension; defaultDesc += extension.toUpperCase(); } if (extString) { var desc = mimeInfo.Description; if (!desc) { var key = plural ? "unknownDescriptionFilesPluralFilter" : "unknownDescriptionFilesFilter"; desc = getStringBundle().formatStringFromName(key, [defaultDesc], 1); } aFilePicker.appendFilter(desc, extString); } else { aFilePicker.appendFilters(Components.interfaces.nsIFilePicker.filterAll); } } else aFilePicker.appendFilters(Components.interfaces.nsIFilePicker.filterAll); break; } } function getPostData() { try { var sessionHistory = getWebNavigation().sessionHistory; var entry = sessionHistory.getEntryAtIndex(sessionHistory.index, false); entry = entry.QueryInterface(Components.interfaces.nsISHEntry); return entry.postData; } catch (e) { } return null; } //XXXPch: that that be removed. function getStringBundle() { const bundleURL = "chrome://browser/locale/contentAreaCommands.properties"; const sbsContractID = "@mozilla.org/intl/stringbundle;1"; const sbsIID = Components.interfaces.nsIStringBundleService; const sbs = Components.classes[sbsContractID].getService(sbsIID); const lsContractID = "@mozilla.org/intl/nslocaleservice;1"; const lsIID = Components.interfaces.nsILocaleService; const ls = Components.classes[lsContractID].getService(lsIID); var appLocale = ls.getApplicationLocale(); return sbs.createBundle(bundleURL, appLocale); } function makeWebBrowserPersist() { const persistContractID = "@mozilla.org/embedding/browser/nsWebBrowserPersist;1"; const persistIID = Components.interfaces.nsIWebBrowserPersist; return Components.classes[persistContractID].createInstance(persistIID); } function makeURL(aURL) { var ioService = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService); return ioService.newURI(aURL, null, null); } function makeFileURL(aFile) { var ioService = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService); return ioService.newFileURI(aFile); } function makeFilePicker() { const fpContractID = "@mozilla.org/filepicker;1"; const fpIID = Components.interfaces.nsIFilePicker; return Components.classes[fpContractID].createInstance(fpIID); } function getMIMEService() { const mimeSvcContractID = "@mozilla.org/mime;1"; const mimeSvcIID = Components.interfaces.nsIMIMEService; const mimeSvc = Components.classes[mimeSvcContractID].getService(mimeSvcIID); return mimeSvc; } function getMIMETypeForURI(aURI) { try { return getMIMEService().getTypeFromURI(aURI); } catch (e) { } return null; } function getMIMEInfoForType(aMIMEType, aExtension) { try { return getMIMEService().getFromTypeAndExtension(aMIMEType, aExtension); } catch (e) { } return null; } function getDefaultFileName(aDefaultFileName, aNameFromHeaders, aDocumentURI, aDocument) { if (aNameFromHeaders) // 1) Use the name suggested by the HTTP headers return validateFileName(aNameFromHeaders); try { var url = aDocumentURI.QueryInterface(Components.interfaces.nsIURL); if (url.fileName != "") { // 2) Use the actual file name, if present return validateFileName(decodeURIComponent(url.fileName)); } } catch (e) { try { // the file name might be non ASCII // try unescape again with a characterSet var textToSubURI = Components.classes["@mozilla.org/intl/texttosuburi;1"] .getService(Components.interfaces.nsITextToSubURI); var charset = getCharsetforSave(aDocument); return validateFileName(textToSubURI.unEscapeURIForUI(charset, url.fileName)); } catch (e) { // This is something like a wyciwyg:, data:, and so forth // URI... no usable filename here. } } if (aDocument) { var docTitle = validateFileName(aDocument.title).replace(/^\s+|\s+$/g, ""); if (docTitle != "") { // 3) Use the document title return docTitle; } } if (aDefaultFileName) // 4) Use the caller-provided name, if any return validateFileName(aDefaultFileName); // 5) If this is a directory, use the last directory name var re = /\/([^\/]+)\/$/; var path = aDocumentURI.path.match(re); if (path && path.length > 1) { return validateFileName(path[1]); } try { if (aDocumentURI.host) // 6) Use the host. return aDocumentURI.host; } catch (e) { // Some files have no information at all, like Javascript generated pages } try { // 7) Use the default file name return getStringBundle().GetStringFromName("DefaultSaveFileName"); } catch (e) { //in case localized string cannot be found } // 8) If all else fails, use "index" return "index"; } function validateFileName(aFileName) { var re = /[\/]+/g; if (navigator.appVersion.indexOf("Windows") != -1) { re = /[\\\/\|]+/g; aFileName = aFileName.replace(/[\"]+/g, "'"); aFileName = aFileName.replace(/[\*\:\?]+/g, " "); aFileName = aFileName.replace(/[\<]+/g, "("); aFileName = aFileName.replace(/[\>]+/g, ")"); } else if (navigator.appVersion.indexOf("Macintosh") != -1) re = /[\:\/]+/g; return aFileName.replace(re, "_"); } function getNormalizedLeafName(aFile, aDefaultExtension) { if (!aDefaultExtension) return aFile; // Fix up the file name we're saving to to include the default extension const stdURLContractID = "@mozilla.org/network/standard-url;1"; const stdURLIID = Components.interfaces.nsIURL; var url = Components.classes[stdURLContractID].createInstance(stdURLIID); url.filePath = aFile; if (url.fileExtension != aDefaultExtension) { return aFile + "." + aDefaultExtension; } return aFile; } function getDefaultExtension(aFilename, aURI, aContentType) { if (aContentType == "text/plain" || aContentType == "application/octet-stream" || aURI.scheme == "ftp") return ""; // temporary fix for bug 120327 // First try the extension from the filename const stdURLContractID = "@mozilla.org/network/standard-url;1"; const stdURLIID = Components.interfaces.nsIURL; var url = Components.classes[stdURLContractID].createInstance(stdURLIID); url.filePath = aFilename; var ext = url.fileExtension; // This mirrors some code in nsExternalHelperAppService::DoContent // Use the filename first and then the URI if that fails var mimeInfo = getMIMEInfoForType(aContentType, ext); if (ext && mimeInfo && mimeInfo.extensionExists(ext)) { return ext; } // Well, that failed. Now try the extension from the URI var urlext; try { url = aURI.QueryInterface(Components.interfaces.nsIURL); urlext = url.fileExtension; } catch (e) { } if (urlext && mimeInfo && mimeInfo.extensionExists(urlext)) { return urlext; } else { try { return mimeInfo.primaryExtension; } catch (e) { // Fall back on the extensions in the filename and URI for lack // of anything better. return ext || urlext; } } } function isDocumentType(aContentType) { switch (aContentType) { case "text/html": return true; case "text/xml": case "application/xhtml+xml": case "application/xml": return false; // XXX Disables Save As Complete until it works for XML } return false; } function getCharsetforSave(aDocument) { if (aDocument) return aDocument.characterSet; if (document.commandDispatcher.focusedWindow) return document.commandDispatcher.focusedWindow.document.characterSet; return window._content.document.characterSet; return false; } # -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- # ***** BEGIN LICENSE BLOCK ***** # Version: NPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Netscape Public License # Version 1.1 (the "License"); you may not use this file except in # compliance with the License. You may obtain a copy of the License at # http://www.mozilla.org/NPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is mozilla.org code. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 1998 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Ben Goodger (Save File) # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the NPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the NPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK *****