diff --git a/mozilla/embedding/components/ui/helperAppDlg/nsHelperAppDlg.js b/mozilla/embedding/components/ui/helperAppDlg/nsHelperAppDlg.js index 7c8f5d0c7c4..72ac3c7548f 100644 --- a/mozilla/embedding/components/ui/helperAppDlg/nsHelperAppDlg.js +++ b/mozilla/embedding/components/ui/helperAppDlg/nsHelperAppDlg.js @@ -126,6 +126,15 @@ nsHelperAppDialog.prototype = { .getInterface( Components.interfaces.nsIDOMWindowInternal ); picker.init( parent, windowTitle, nsIFilePicker.modeSave ); picker.defaultString = aDefaultFile; + if (aSuggestedFileExtension) { + // aSuggestedFileExtension includes the period, so strip it + picker.defaultExtension = aSuggestedFileExtension.substring(1); + } else { + try { + picker.defaultExtension = this.mLauncher.MIMEInfo.primaryExtension; + } catch (ex) { + } + } var wildCardExtension = "*"; if ( aSuggestedFileExtension ) { diff --git a/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp b/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp index 6924487d8c6..a8b0c726335 100644 --- a/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -93,7 +93,7 @@ static PRBool PR_CALLBACK DeleteEntry(nsHashKey *aKey, void *aData, void* closur static nsDefaultMimeTypeEntry defaultMimeEntries [] = { { TEXT_PLAIN, "txt,text", "Text File", 'TEXT', 'ttxt' }, - { TEXT_HTML, "htm,html,shtml,ehtml", "HyperText Markup Language", 'TEXT', 'MOSS' }, + { TEXT_HTML, "html,htm,shtml,ehtml", "HyperText Markup Language", 'TEXT', 'MOSS' }, { TEXT_RDF, "rdf", "Resource Description Framework", 'TEXT','ttxt' }, { TEXT_XUL, "xul", "XML-Based User Interface Language", 'TEXT', 'ttxt' }, { TEXT_XML, "xml,xsl,xbl", "Extensible Markup Language", 'TEXT', 'ttxt' }, diff --git a/mozilla/widget/public/nsIFilePicker.idl b/mozilla/widget/public/nsIFilePicker.idl index 812826bd2d7..43318809fb2 100644 --- a/mozilla/widget/public/nsIFilePicker.idl +++ b/mozilla/widget/public/nsIFilePicker.idl @@ -73,9 +73,20 @@ interface nsIFilePicker : nsISupports void appendFilter(in wstring title, in wstring filter); - /* what is this? */ + /** + * The filename that should be suggested to the user as a default. + * + * @throws NS_ERROR_FAILURE on attempts to get + */ attribute wstring defaultString; + /** + * The extension that should be associated with files of the type we + * want to work with. On some platforms, this extension will be + * automatically appended to filenames the user enters, if needed. + */ + attribute wstring defaultExtension; + /** * The filter which is currently selected in the File Picker dialog * diff --git a/mozilla/widget/src/beos/nsFilePicker.cpp b/mozilla/widget/src/beos/nsFilePicker.cpp index ba7441e94c3..523b06e9ce4 100644 --- a/mozilla/widget/src/beos/nsFilePicker.cpp +++ b/mozilla/widget/src/beos/nsFilePicker.cpp @@ -257,6 +257,22 @@ NS_IMETHODIMP nsFilePicker::GetDefaultString(PRUnichar **aString) return NS_ERROR_FAILURE; } +//------------------------------------------------------------------------- +// +// The default extension to use for files +// +//------------------------------------------------------------------------- +NS_IMETHODIMP nsFilePicker::GetDefaultExtension(PRUnichar **aExtension) +{ + *aExtension = nsnull; + return NS_OK; +} + +NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const PRUnichar *aExtension) +{ + return NS_OK; +} + //------------------------------------------------------------------------- // // Set the display directory diff --git a/mozilla/widget/src/beos/nsFilePicker.h b/mozilla/widget/src/beos/nsFilePicker.h index 3c210c8100d..a28632e0120 100644 --- a/mozilla/widget/src/beos/nsFilePicker.h +++ b/mozilla/widget/src/beos/nsFilePicker.h @@ -50,6 +50,8 @@ public: // nsIFilePicker (less what's in nsBaseFilePicker) NS_IMETHOD GetDefaultString(PRUnichar * *aDefaultString); NS_IMETHOD SetDefaultString(const PRUnichar * aDefaultString); + NS_IMETHOD GetDefaultExtension(PRUnichar * *aDefaultExtension); + NS_IMETHOD SetDefaultExtension(const PRUnichar * aDefaultExtension); NS_IMETHOD GetDisplayDirectory(nsILocalFile * *aDisplayDirectory); NS_IMETHOD SetDisplayDirectory(nsILocalFile * aDisplayDirectory); NS_IMETHOD GetFile(nsILocalFile * *aFile); diff --git a/mozilla/widget/src/cocoa/nsFilePicker.cpp b/mozilla/widget/src/cocoa/nsFilePicker.cpp index cc9eb1badc7..aa271599f58 100644 --- a/mozilla/widget/src/cocoa/nsFilePicker.cpp +++ b/mozilla/widget/src/cocoa/nsFilePicker.cpp @@ -699,6 +699,22 @@ NS_IMETHODIMP nsFilePicker::GetDefaultString(PRUnichar **aString) return NS_ERROR_FAILURE; } +//------------------------------------------------------------------------- +// +// The default extension to use for files +// +//------------------------------------------------------------------------- +NS_IMETHODIMP nsFilePicker::GetDefaultExtension(PRUnichar **aExtension) +{ + *aExtension = nsnull; + return NS_OK; +} + +NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const PRUnichar *aExtension) +{ + return NS_OK; +} + //------------------------------------------------------------------------- // // Set the display directory diff --git a/mozilla/widget/src/cocoa/nsFilePicker.h b/mozilla/widget/src/cocoa/nsFilePicker.h index d908d9b45ae..52073c8f2d6 100644 --- a/mozilla/widget/src/cocoa/nsFilePicker.h +++ b/mozilla/widget/src/cocoa/nsFilePicker.h @@ -48,6 +48,8 @@ public: // nsIFilePicker (less what's in nsBaseFilePicker) NS_IMETHOD GetDefaultString(PRUnichar * *aDefaultString); NS_IMETHOD SetDefaultString(const PRUnichar * aDefaultString); + NS_IMETHOD GetDefaultExtension(PRUnichar * *aDefaultExtension); + NS_IMETHOD SetDefaultExtension(const PRUnichar * aDefaultExtension); NS_IMETHOD GetDisplayDirectory(nsILocalFile * *aDisplayDirectory); NS_IMETHOD SetDisplayDirectory(nsILocalFile * aDisplayDirectory); NS_IMETHOD GetFile(nsILocalFile * *aFile); diff --git a/mozilla/widget/src/mac/nsFilePicker.cpp b/mozilla/widget/src/mac/nsFilePicker.cpp index 58aa4e9cee0..bd4b24de108 100644 --- a/mozilla/widget/src/mac/nsFilePicker.cpp +++ b/mozilla/widget/src/mac/nsFilePicker.cpp @@ -932,6 +932,22 @@ NS_IMETHODIMP nsFilePicker::GetDefaultString(PRUnichar **aString) return NS_ERROR_FAILURE; } +//------------------------------------------------------------------------- +// +// The default extension to use for files +// +//------------------------------------------------------------------------- +NS_IMETHODIMP nsFilePicker::GetDefaultExtension(PRUnichar **aExtension) +{ + *aExtension = nsnull; + return NS_OK; +} + +NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const PRUnichar *aExtension) +{ + return NS_OK; +} + //------------------------------------------------------------------------- // // Set the display directory diff --git a/mozilla/widget/src/mac/nsFilePicker.h b/mozilla/widget/src/mac/nsFilePicker.h index d52770274ef..2fadd203c41 100644 --- a/mozilla/widget/src/mac/nsFilePicker.h +++ b/mozilla/widget/src/mac/nsFilePicker.h @@ -48,6 +48,8 @@ public: // nsIFilePicker (less what's in nsBaseFilePicker) NS_IMETHOD GetDefaultString(PRUnichar * *aDefaultString); NS_IMETHOD SetDefaultString(const PRUnichar * aDefaultString); + NS_IMETHOD GetDefaultExtension(PRUnichar * *aDefaultExtension); + NS_IMETHOD SetDefaultExtension(const PRUnichar * aDefaultExtension); NS_IMETHOD GetDisplayDirectory(nsILocalFile * *aDisplayDirectory); NS_IMETHOD SetDisplayDirectory(nsILocalFile * aDisplayDirectory); NS_IMETHOD GetFile(nsILocalFile * *aFile); diff --git a/mozilla/widget/src/os2/nsFilePicker.cpp b/mozilla/widget/src/os2/nsFilePicker.cpp index f063b3d05f5..d1a6689b76d 100644 --- a/mozilla/widget/src/os2/nsFilePicker.cpp +++ b/mozilla/widget/src/os2/nsFilePicker.cpp @@ -325,6 +325,22 @@ NS_IMETHODIMP nsFilePicker::GetDefaultString(PRUnichar **aString) return NS_ERROR_FAILURE; } +//------------------------------------------------------------------------- +// +// The default extension to use for files +// +//------------------------------------------------------------------------- +NS_IMETHODIMP nsFilePicker::GetDefaultExtension(PRUnichar **aExtension) +{ + *aExtension = nsnull; + return NS_OK; +} + +NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const PRUnichar *aExtension) +{ + return NS_OK; +} + //------------------------------------------------------------------------- // // Set the display directory diff --git a/mozilla/widget/src/os2/nsFilePicker.h b/mozilla/widget/src/os2/nsFilePicker.h index 95a2a47af3a..41a119bd42a 100644 --- a/mozilla/widget/src/os2/nsFilePicker.h +++ b/mozilla/widget/src/os2/nsFilePicker.h @@ -47,6 +47,8 @@ public: // nsIFilePicker (less what's in nsBaseFilePicker) NS_IMETHOD GetDefaultString(PRUnichar * *aDefaultString); NS_IMETHOD SetDefaultString(const PRUnichar * aDefaultString); + NS_IMETHOD GetDefaultExtension(PRUnichar * *aDefaultExtension); + NS_IMETHOD SetDefaultExtension(const PRUnichar * aDefaultExtension); NS_IMETHOD GetDisplayDirectory(nsILocalFile * *aDisplayDirectory); NS_IMETHOD SetDisplayDirectory(nsILocalFile * aDisplayDirectory); NS_IMETHOD GetFile(nsILocalFile * *aFile); diff --git a/mozilla/widget/src/windows/nsFilePicker.cpp b/mozilla/widget/src/windows/nsFilePicker.cpp index 94820e9e445..42cd4d03b4b 100644 --- a/mozilla/widget/src/windows/nsFilePicker.cpp +++ b/mozilla/widget/src/windows/nsFilePicker.cpp @@ -44,6 +44,8 @@ NS_IMPL_ISUPPORTS1(nsFilePicker, nsIFilePicker) char nsFilePicker::mLastUsedDirectory[MAX_PATH+1] = { 0 }; +#define MAX_EXTENSION_LENGTH 10 + //------------------------------------------------------------------------- // // nsFilePicker constructor @@ -147,6 +149,8 @@ NS_IMETHODIMP nsFilePicker::Show(PRInt16 *retval) ofn.lStructSize = sizeof(ofn); + char extensionBuffer[MAX_EXTENSION_LENGTH+1] = ""; + PRInt32 l = (mFilterList.Length()+2)*2; char *filterBuffer = (char*) nsMemory::Alloc(l); int len = WideCharToMultiByte(CP_ACP, 0, @@ -160,7 +164,7 @@ NS_IMETHODIMP nsFilePicker::Show(PRInt16 *retval) if (initialDir && *initialDir) { ofn.lpstrInitialDir = initialDir; } - + ofn.lpstrTitle = title; ofn.lpstrFilter = filterBuffer; ofn.nFilterIndex = mSelectedType; @@ -170,24 +174,38 @@ NS_IMETHODIMP nsFilePicker::Show(PRInt16 *retval) ofn.Flags = OFN_NOCHANGEDIR | OFN_SHAREAWARE | OFN_LONGNAMES | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY; - // Get file extension from suggested filename - // to detect if we are saving an html file - //XXX: nsIFile SHOULD HAVE A GetExtension() METHOD! - PRInt32 extIndex = mDefault.RFind("."); - if ( extIndex >= 0) { - nsAutoString ext; - mDefault.Right(ext, mDefault.Length() - extIndex); - // Should we test for ".cgi", ".asp", ".jsp" and other - // "generated" html pages? + if (!mDefaultExtension.IsEmpty()) { + // Someone was cool and told us what to do + char *convertedExt = ConvertToFileSystemCharset(mDefaultExtension.get()); + if (!convertedExt) { + mDefaultExtension.ToCString(extensionBuffer, MAX_EXTENSION_LENGTH); + } + else { + PL_strncpyz(extensionBuffer, convertedExt, MAX_EXTENSION_LENGTH+1); + nsMemory::Free( convertedExt ); + } + ofn.lpstrDefExt = extensionBuffer; + } + else { + // Get file extension from suggested filename + // to detect if we are saving an html file + //XXX: nsIFile SHOULD HAVE A GetExtension() METHOD! + PRInt32 extIndex = mDefault.RFind("."); + if ( extIndex >= 0) { + nsAutoString ext; + mDefault.Right(ext, mDefault.Length() - extIndex); + // Should we test for ".cgi", ".asp", ".jsp" and other + // "generated" html pages? - if ( ext.EqualsIgnoreCase(".htm") || - ext.EqualsIgnoreCase(".html") || - ext.EqualsIgnoreCase(".shtml") ) { - // This is supposed to append ".htm" if user doesn't supply an extension - //XXX Actually, behavior is sort of weird: - // often appends ".html" even if you have an extension - // It obeys your extension if you put quotes around name - ofn.lpstrDefExt = htmExt; + if ( ext.EqualsIgnoreCase(".htm") || + ext.EqualsIgnoreCase(".html") || + ext.EqualsIgnoreCase(".shtml") ) { + // This is supposed to append ".htm" if user doesn't supply an extension + //XXX Actually, behavior is sort of weird: + // often appends ".html" even if you have an extension + // It obeys your extension if you put quotes around name + ofn.lpstrDefExt = htmExt; + } } } @@ -355,6 +373,25 @@ NS_IMETHODIMP nsFilePicker::GetDefaultString(PRUnichar **aString) return NS_ERROR_FAILURE; } +//------------------------------------------------------------------------- +// +// The default extension to use for files +// +//------------------------------------------------------------------------- +NS_IMETHODIMP nsFilePicker::GetDefaultExtension(PRUnichar **aExtension) +{ + *aExtension = ToNewUnicode(mDefaultExtension); + if (!*aExtension) + return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; +} + +NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const PRUnichar *aExtension) +{ + mDefaultExtension = aExtension; + return NS_OK; +} + //------------------------------------------------------------------------- // // Set the filter index diff --git a/mozilla/widget/src/windows/nsFilePicker.h b/mozilla/widget/src/windows/nsFilePicker.h index e895205f307..94fd3d8e8dc 100644 --- a/mozilla/widget/src/windows/nsFilePicker.h +++ b/mozilla/widget/src/windows/nsFilePicker.h @@ -47,6 +47,8 @@ public: // nsIFilePicker (less what's in nsBaseFilePicker) NS_IMETHOD GetDefaultString(PRUnichar * *aDefaultString); NS_IMETHOD SetDefaultString(const PRUnichar * aDefaultString); + NS_IMETHOD GetDefaultExtension(PRUnichar * *aDefaultExtension); + NS_IMETHOD SetDefaultExtension(const PRUnichar * aDefaultExtension); NS_IMETHOD GetDisplayDirectory(nsILocalFile * *aDisplayDirectory); NS_IMETHOD SetDisplayDirectory(nsILocalFile * aDisplayDirectory); NS_IMETHOD GetFilterIndex(PRInt32 *aFilterIndex); @@ -73,6 +75,7 @@ protected: PRInt16 mMode; nsCString mFile; nsString mDefault; + nsString mDefaultExtension; nsString mFilterList; nsIUnicodeEncoder* mUnicodeEncoder; nsIUnicodeDecoder* mUnicodeDecoder; diff --git a/mozilla/xpfe/communicator/resources/content/contentAreaUtils.js b/mozilla/xpfe/communicator/resources/content/contentAreaUtils.js index a9388587451..1026e29cc87 100644 --- a/mozilla/xpfe/communicator/resources/content/contentAreaUtils.js +++ b/mozilla/xpfe/communicator/resources/content/contentAreaUtils.js @@ -232,7 +232,9 @@ function foundHeaderInfo(aSniffer, aData) var defaultFileName = getDefaultFileName(aData.fileName, aSniffer.suggestedFileName, aSniffer.uri); - fp.defaultString = getNormalizedLeafName(defaultFileName, contentType); + var defaultExtension = getDefaultExtension(defaultFileName, aSniffer.uri, contentType); + fp.defaultExtension = defaultExtension; + fp.defaultString = getNormalizedLeafName(defaultFileName, defaultExtension); if (fp.show() == Components.interfaces.nsIFilePicker.returnCancel || !fp.file) return; @@ -243,7 +245,6 @@ function foundHeaderInfo(aSniffer, aData) prefs.setComplexValue("dir", nsILocalFile, directory); fp.file.leafName = validateFileName(fp.file.leafName); - fp.file.leafName = getNormalizedLeafName(fp.file.leafName, contentType); // 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. @@ -510,36 +511,64 @@ function validateFileName(aFileName) return aFileName.replace(re, "_"); } -function getNormalizedLeafName(aFile, aContentType) +function getNormalizedLeafName(aFile, aDefaultExtension) { - // Fix up the file name we're saving to so that if the user enters - // no extension, an appropriate one is appended. - var leafName = aFile; - - var mimeInfo = getMIMEInfoForType(aContentType); - if (mimeInfo) { - var extCount = { }; - var extList = { }; - mimeInfo.GetFileExtensions(extCount, extList); - - const stdURLContractID = "@mozilla.org/network/standard-url;1"; - const stdURLIID = Components.interfaces.nsIURI; - var uri = Components.classes[stdURLContractID].createInstance(stdURLIID); - var url = uri.QueryInterface(Components.interfaces.nsIURL); - url.filePath = aFile; - - if (aContentType == "text/html") { - if ((url.fileExtension && - url.fileExtension != "htm" && url.fileExtension != "html") || - (!url.fileExtension)) - return leafName + ".html"; - } - - if (!url.fileExtension) - return leafName + "." + extList.value[0]; + 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) +{ + // This mirrors some code in nsExternalHelperAppService::DoContent + // Use the filename first and then the URI if that fails + + var mimeInfo = getMIMEInfoForType(aContentType); + + // 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; + + if (ext && 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.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; + } } - - return leafName; } function isDocumentType(aContentType) diff --git a/mozilla/xpfe/components/filepicker/src/nsFilePicker.js b/mozilla/xpfe/components/filepicker/src/nsFilePicker.js index 95212721ebd..871f9fdf968 100644 --- a/mozilla/xpfe/components/filepicker/src/nsFilePicker.js +++ b/mozilla/xpfe/components/filepicker/src/nsFilePicker.js @@ -100,6 +100,10 @@ nsFilePicker.prototype = { set defaultString(a) { this.mDefaultString = a; }, get defaultString() { return this.mDefaultString; }, + /* attribute wstring defaultExtension */ + set defaultExtension(ext) { }, + get defaultExtension() { return ""; }, + /* attribute long filterIndex; */ set filterIndex(a) { this.mFilterIndex = a; }, get filterIndex() { return this.mFilterIndex; }, diff --git a/mozilla/xpfe/components/filepicker/src/nsFilePicker.js.in b/mozilla/xpfe/components/filepicker/src/nsFilePicker.js.in index 95212721ebd..871f9fdf968 100644 --- a/mozilla/xpfe/components/filepicker/src/nsFilePicker.js.in +++ b/mozilla/xpfe/components/filepicker/src/nsFilePicker.js.in @@ -100,6 +100,10 @@ nsFilePicker.prototype = { set defaultString(a) { this.mDefaultString = a; }, get defaultString() { return this.mDefaultString; }, + /* attribute wstring defaultExtension */ + set defaultExtension(ext) { }, + get defaultExtension() { return ""; }, + /* attribute long filterIndex; */ set filterIndex(a) { this.mFilterIndex = a; }, get filterIndex() { return this.mFilterIndex; },