Composer Publishing fixes: Add support to not upload images (b=134001,r=akkana, sr=kin), Don't save site data if not successfully published (b=132604, r=akkana, sr=kin), improve error handling (b=126258, r=andreww, sr=dveditz), Make 'CheckAndSaveDocument' do publishing for remote url (b=126450, r=brade, sr=kin), Save command should publish if remote file (b=132634, r=brade,sr=kin), Fix FTP publishing (b=133823, r=brade, sr=kin) all are: a=asa, adt1.0.0+

This commit is contained in:
cmanske%netscape.com 2002-04-04 15:14:32 +00:00
Родитель a7a0d0cd80
Коммит d84a792769
5 изменённых файлов: 561 добавлений и 265 удалений

Просмотреть файл

@ -354,7 +354,10 @@ var nsSaveCommand =
var docUrl = GetDocumentUrl(); var docUrl = GetDocumentUrl();
var scheme = GetScheme(docUrl); var scheme = GetScheme(docUrl);
if (scheme && scheme != "file") if (scheme && scheme != "file")
{
goDoCommand("cmd_publish"); goDoCommand("cmd_publish");
return true;
}
FinishHTMLSource(); FinishHTMLSource();
result = SaveDocument(IsUrlAboutBlank(docUrl), false, editorShell.contentsMIMEType); result = SaveDocument(IsUrlAboutBlank(docUrl), false, editorShell.contentsMIMEType);
@ -445,10 +448,17 @@ var nsPublishCommand =
{ {
isCommandEnabled: function(aCommand, dummy) isCommandEnabled: function(aCommand, dummy)
{ {
return window.editorShell && window.editorShell.documentEditable if (window.editorShell && window.editorShell.documentEditable)
&& (window.editorShell.documentModified || {
IsUrlAboutBlank(GetDocumentUrl()) || // Always allow publishing when editing a local document,
window.gHTMLSourceChanged); // otherwise the document modified state would prevent that
// when you first open any local file.
var docUrl = GetDocumentUrl();
return window.editorShell.documentModified || window.gHTMLSourceChanged
|| IsUrlAboutBlank(docUrl) || GetScheme(docUrl) == "file";
}
return false;
}, },
doCommand: function(aCommand) doCommand: function(aCommand)
@ -472,9 +482,9 @@ var nsPublishCommand =
// Try to get publish data from the document url // Try to get publish data from the document url
publishData = CreatePublishDataFromUrl(docUrl); publishData = CreatePublishDataFromUrl(docUrl);
// If none, use default publishing site // If none, use default publishing site? Need a pref for this
if (!publishData) //if (!publishData)
publishData = GetPublishDataFromSiteName(GetDefaultPublishSiteName(), filename); // publishData = GetPublishDataFromSiteName(GetDefaultPublishSiteName(), filename);
} }
if (showPublishDialog || !publishData) if (showPublishDialog || !publishData)
@ -561,12 +571,13 @@ function GetSuggestedFileName(aDocumentURLString, aMIMEType, aHTMLDoc)
{ {
var docURI = null; var docURI = null;
try { try {
docURI = Components.classes["@mozilla.org/network/standard-url;1"].createInstance(Components.interfaces.nsIURI);
docURI.spec = aDocumentURLString; var ioService = GetIOService();
var docURL = docURI.QueryInterface(Components.interfaces.nsIURL); docURI = ioService.newURI(aDocumentURLString, window.editorShell.GetDocumentCharacterSet(), null);
docURI = docURI.QueryInterface(Components.interfaces.nsIURL);
// grab the file name // grab the file name
var url = docURL.fileBaseName; var url = docURI.fileBaseName;
if (url) if (url)
return url+extension; return url+extension;
} catch(e) {} } catch(e) {}
@ -585,8 +596,7 @@ function GetSuggestedFileName(aDocumentURLString, aMIMEType, aHTMLDoc)
} }
// if we still don't have a file name, let's just go with "untitled" // if we still don't have a file name, let's just go with "untitled"
// shouldn't this come out of a string bundle? I'm shocked localizers haven't complained! return GetString("untitled") + extension;
return "untitled" + extension;
} }
// returns file picker result // returns file picker result
@ -631,8 +641,7 @@ function PromptForSaveLocation(aDoSaveAsText, aEditorType, aMIMEType, ahtmlDocum
var isLocalFile = true; var isLocalFile = true;
try { try {
var docURI = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIURI); var docURI = ioService.newURI(aDocumentURLString, window.editorShell.GetDocumentCharacterSet(), null);
docURI.spec = aDocumentURLString;
isLocalFile = docURI.schemeIs("file"); isLocalFile = docURI.schemeIs("file");
} }
catch (e) {} catch (e) {}
@ -789,6 +798,7 @@ function GetOutputFlags(aMimeType, aWrapColumn)
} }
// returns number of column where to wrap // returns number of column where to wrap
const nsIPlaintextEditor = Components.interfaces.nsIPlaintextEditor;
function GetWrapColumn() function GetWrapColumn()
{ {
var wrapCol = 72; var wrapCol = 72;
@ -812,9 +822,9 @@ function GetPromptService()
return promptService; return promptService;
} }
const gShowDebugOutputStateChange = false; const gShowDebugOutputStateChange = true;
const gShowDebugOutputProgress = false; const gShowDebugOutputProgress = false;
const gShowDebugOutputStatusChange = false; const gShowDebugOutputStatusChange = true;
const gShowDebugOutputLocationChange = false; const gShowDebugOutputLocationChange = false;
const gShowDebugOutputSecurityChange = false; const gShowDebugOutputSecurityChange = false;
@ -852,6 +862,8 @@ var gEditorOutputProgressListener =
dump(" STATE_IS_NETWORK "); dump(" STATE_IS_NETWORK ");
dump("\n * requestSpec="+requestSpec+", pubSpec="+pubSpec+", aStatus="+aStatus+"\n"); dump("\n * requestSpec="+requestSpec+", pubSpec="+pubSpec+", aStatus="+aStatus+"\n");
DumpDebugStatus(aStatus);
} }
// Detect start of file upload of any file: // Detect start of file upload of any file:
@ -870,61 +882,85 @@ var gEditorOutputProgressListener =
} }
} }
// Detect end of file upload of HTML file: // Detect end of file upload of any file:
if ((aStateFlags & nsIWebProgressListener.STATE_STOP) && requestSpec) if ((aStateFlags & nsIWebProgressListener.STATE_STOP) && requestSpec)
{ {
// Show final status in progress dialog when we receive the STOP // New: Stop at the first bad aStatus, rather than waiting for STATE_IS_NETWORK message
// notification for the destination file try {
if (gProgressDialog) // check http channel for response: 200 range is ok; other ranges are not
var httpChannel = aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
var httpResponse = httpChannel.responseStatus;
if (httpResponse < 200 || httpResponse >= 300)
aStatus = httpResponse; // not a real error but enough to pass check below
} catch(e) {}
// Notify progress dialog when we receive the STOP
// notification for a file if there was an error
// or for a successful finish only if
// destination url is contains the publishing location
if (gProgressDialog &&
(aStatus != 0
|| requestSpec && requestSpec.indexOf(gPublishData.publishUrl) == 0))
{ {
try { try {
gProgressDialog.SetProgressFinished(GetFilename(requestSpec), aStatus); gProgressDialog.SetProgressFinished(GetFilename(requestSpec), aStatus);
} catch(e) { } catch(e) {}
dump(" Exception error calling SetProgressFinished\n");
}
} }
if (aStatus)
{
// Cancel the publish
gPersistObj.cancelSave();
//XXX TODO: we should provide more meaningful errors (if possible)
var failedStr = GetString("PublishFailed");
// XXX We don't have error codes in IDL !!!
// Give better error messages for cases we know about:
if (aStatus == 2152398868) // Bad directory
{
var requestFilename = requestSpec ? GetFilename(requestSpec) : "";
var dir = (gPublishData.filename == requestFilename) ?
gPublishData.docDir : gPublishData.otherDir;
failedStr = GetString("PublishDirFailed").replace(/%dir%/, gPublishData.docDir);
if (gProgressDialog)
gProgressDialog.SetStatusMessage(failedStr);
// Remove directory from saved prefs
RemovePublishSubdirectoryFromPrefs(gPublishData, dir);
}
// Do not do any commands after failure
gCommandAfterPublishing = null;
// Show error in progress dialog and let user close it
if (gProgressDialog)
{
try {
// Tell dialog final status value so it can show appropriate message
gProgressDialog.SetProgressFinished(null, aStatus);
} catch (e) {
dump(" **** EXCEPTION ERROR CALLING ProgressDialog.SetProgressFinished\n");
AlertWithTitle(GetString("Publish"), failedStr);
}
}
else
{
// In case we ever get final alert with no dialog
AlertWithTitle(GetString("Publish"), failedStr);
// Final cleanup
FinishPublishing();
}
return; // we don't want to change location or reset mod count, etc.
}
if ((aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK)) if ((aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK))
{ {
// FINISHED ALL PUBLISHING // All files are finished uploading
try { // Publishing succeeded...
// check http channel for response: 200 range is ok; other ranges are not
var httpChannel = aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
var httpResponse = httpChannel.responseStatus;
if (httpResponse < 200 || httpResponse >= 300)
aStatus = httpResponse; // not a real error but enough to pass check below
} catch(e) {}
if (aStatus)
{
// Cancel the publish
gPersistObj.cancelSave();
//XXX TODO: we should provide more meaningful errors (if possible)
var failedStr = GetString("PublishFailed");
// Show error in progress dialog and let user close it
if (gProgressDialog)
{
try {
// Tell dialog final status value so it can show appropriate message
gProgressDialog.SetProgressFinished(null, aStatus);
} catch (e) {
dump(" **** EXCEPTION ERROR CALLING ProgressDialog.SetProgressFinished\n");
AlertWithTitle(GetString("Publish"), failedStr);
}
}
else
{
// In case we ever get final alert with no dialog
AlertWithTitle(GetString("Publish"), failedStr);
// Final cleanup
FinishPublishing();
}
return; // we don't want to change location or reset mod count, etc.
}
try { try {
// Get the new docUrl from the "browse location" in case "publish location" was FTP // Get the new docUrl from the "browse location" in case "publish location" was FTP
var urlstring = GetDocUrlFromPublishData(gPublishData); var urlstring = GetDocUrlFromPublishData(gPublishData);
@ -937,18 +973,26 @@ var gEditorOutputProgressListener =
// Set UI based on whether we're editing a remote or local url // Set UI based on whether we're editing a remote or local url
SetSaveAndPublishUI(urlstring); SetSaveAndPublishUI(urlstring);
// Save publishData to prefs
if (publishData.savePublishData)
SavePublishDataToPrefs(publishData);
else
SavePassword();
} catch (e) {} } catch (e) {}
// Ask progress dialog to close, // Save publishData to prefs
// "false" = don't force it if user checked checkbox to keep it open if (gPublishData)
{
if (gPublishData.savePublishData)
{
// We published successfully, so we can safely
// save docDir and otherDir to prefs
gPublishData.saveDirs = true;
SavePublishDataToPrefs(gPublishData);
}
else
SavePassword(gPublishData);
}
// Ask progress dialog to close, but it may not
// if user checked checkbox to keep it open
if (gProgressDialog) if (gProgressDialog)
gProgressDialog.CloseDialog(false); gProgressDialog.RequestCloseDialog();
else else
FinishPublishing(); FinishPublishing();
} }
@ -977,9 +1021,6 @@ var gEditorOutputProgressListener =
else if(gPersistObj.currentState == gPersistObj.PERSIST_STATE_FINISHED) else if(gPersistObj.currentState == gPersistObj.PERSIST_STATE_FINISHED)
{ {
dump(" PERSISTER HAS FINISHED SAVING DATA\n\n\n"); dump(" PERSISTER HAS FINISHED SAVING DATA\n\n\n");
// Allow editing again
// XXXX WE REALLY SHOULDN'T DO THIS!!!
// SetDocumentEditable(true);
} }
} }
} }
@ -1005,37 +1046,8 @@ var gEditorOutputProgressListener =
dump("***** request: " + channel.URI.spec + "\n"); dump("***** request: " + channel.URI.spec + "\n");
} }
catch (e) { dump(" couldn't get request\n"); } catch (e) { dump(" couldn't get request\n"); }
if (aStatus == 2152398852) DumpDebugStatus(aStatus);
dump("***** status is UNKNOWN_TYPE\n");
else if (aStatus == 2152398853)
dump("***** status is DESTINATION_NOT_DIR\n");
else if (aStatus == 2152398854)
dump("***** status is TARGET_DOES_NOT_EXIST\n");
else if (aStatus == 2152398856)
dump("***** status is ALREADY_EXISTS\n");
else if (aStatus == 2152398858)
dump("***** status is DISK_FULL\n");
else if (aStatus == 2152398860)
dump("***** status is NOT_DIRECTORY\n");
else if (aStatus == 2152398861)
dump("***** status is IS_DIRECTORY\n");
else if (aStatus == 2152398862)
dump("***** status is IS_LOCKED\n");
else if (aStatus == 2152398863)
dump("***** status is TOO_BIG\n");
else if (aStatus == 2152398865)
dump("***** status is NAME_TOO_LONG\n");
else if (aStatus == 2152398866)
dump("***** status is NOT_FOUND\n");
else if (aStatus == 2152398867)
dump("***** status is READ_ONLY\n");
else if (aStatus == 2152398868)
dump("***** status is DIR_NOT_EMPTY\n");
else if (aStatus == 2152398869)
dump("***** status is ACCESS_DENIED\n");
else
dump("***** status is " + aStatus + "\n");
if (gPersistObj) if (gPersistObj)
{ {
@ -1074,23 +1086,9 @@ var gEditorOutputProgressListener =
// nsIPrompt // nsIPrompt
alert : function(dlgTitle, text) alert : function(dlgTitle, text)
{ {
// If Progress dialog is up, put message in there instead of Alert AlertWithTitle(dlgTitle, text, gProgressDialog ? gProgressDialog : window);
if (gProgressDialog)
{
try {
gProgressDialog.SetStatusMessage(failedStr);
} catch (e) {
dump(" nsIPrompt::Alert EXCEPTION ERROR CALLING ProgressDialog.SetStatusMessage\n");
AlertWithTitle(dlgTitle, text);
}
}
else
{
AlertWithTitle(dlgTitle, text);
CancelPublishing();
}
}, },
alertCheck : function(dialogTitle, text, checkBoxLabel, checkValue) alertCheck : function(dialogTitle, text, checkBoxLabel, checkObj)
{ {
AlertWithTitle(dialogTitle, text); AlertWithTitle(dialogTitle, text);
}, },
@ -1098,14 +1096,14 @@ var gEditorOutputProgressListener =
{ {
return ConfirmWithTitle(dlgTitle, text, null, null); return ConfirmWithTitle(dlgTitle, text, null, null);
}, },
confirmCheck : function(dlgTitle, text, checkBoxLabel, checkValue) confirmCheck : function(dlgTitle, text, checkBoxLabel, checkObj)
{ {
var promptServ = GetPromptService(); var promptServ = GetPromptService();
if (!promptServ) if (!promptServ)
return; return;
promptServ.confirmEx(window, dlgTitle, text, nsIPromptService.STD_OK_CANCEL_BUTTONS, promptServ.confirmEx(window, dlgTitle, text, nsIPromptService.STD_OK_CANCEL_BUTTONS,
"", "", "", checkBoxLabel, checkValue, outButtonPressed); "", "", "", checkBoxLabel, checkObj, outButtonPressed);
}, },
confirmEx : function(dlgTitle, text, btnFlags, btn0Title, btn1Title, btn2Title, checkBoxLabel, checkVal, outBtnPressed) confirmEx : function(dlgTitle, text, btnFlags, btn0Title, btn1Title, btn2Title, checkBoxLabel, checkVal, outBtnPressed)
{ {
@ -1117,34 +1115,47 @@ var gEditorOutputProgressListener =
btn0Title, btn1Title, btn2Title, btn0Title, btn1Title, btn2Title,
checkBoxLabel, checkVal, outBtnPressed); checkBoxLabel, checkVal, outBtnPressed);
}, },
prompt : function(dlgTitle, text, inoutText, checkBoxLabel, checkValue) prompt : function(dlgTitle, text, inoutText, checkBoxLabel, checkObj)
{ {
var promptServ = GetPromptService(); var promptServ = GetPromptService();
if (!promptServ) if (!promptServ)
return false; return false;
return promptServ.prompt(window, dlgTitle, text, inoutText, checkBoxLabel, checkValue); return promptServ.prompt(window, dlgTitle, text, inoutText, checkBoxLabel, checkObj);
}, },
promptPassword : function(dlgTitle, text, password, checkBoxLabel, checkValue) promptPassword : function(dlgTitle, text, pwObj, checkBoxLabel, savePWObj)
{ {
var promptServ = GetPromptService(); var promptServ = GetPromptService();
if (!promptServ) if (!promptServ)
return false; return false;
var ret = false;
try {
// Note difference with nsIAuthPrompt::promptPassword, which has
// just "in" savePassword param, while nsIPrompt is "inout"
// Initialize with user's previous preference for this site
if (gPublishData)
savePWObj.value = gPublishData.savePassword;
ret = promptServ.promptPassword(gProgressDialog ? gProgressDialog : window,
dlgTitle, text, pwObj, checkBoxLabel, savePWObj);
if (!ret)
setTimeout(CancelPublishing,0);
if (ret && gPublishData)
UpdateUsernamePasswordFromPrompt(gPublishData, gPublishData.username, pwObj.value, savePWObj.value);
} catch(e) {}
var ret = promptServ.promptPassword(window, dlgTitle, text, password, checkBoxLabel, checkValue);
if (!ret)
setTimeout("CancelPublishing()",0);
return ret; return ret;
}, },
promptUsernameAndPassword : function(dlgTitle, text, login, pw, checkBoxLabel, checkValue) promptUsernameAndPassword : function(dlgTitle, text, userObj, pwObj, checkBoxLabel, savePWObj)
{ {
var promptServ = GetPromptService(); var ret = PromptUsernameAndPassword(dlgTitle, text, savePWObj, userObj, pwObj);
if (!promptServ)
return false;
var ret = promptServ.promptUsernameAndPassword(window, dlgTitle, text, login, pw, checkBoxLabel, checkValue);
if (!ret) if (!ret)
setTimeout("CancelPublishing()",0); setTimeout(CancelPublishing,0);
return ret; return ret;
}, },
select : function(dlgTitle, text, count, selectList, outSelection) select : function(dlgTitle, text, count, selectList, outSelection)
@ -1163,11 +1174,11 @@ var gEditorOutputProgressListener =
if (!promptServ) if (!promptServ)
return false; return false;
var saveCheck = {value:savePW}; var savePWObj = {value:savePW};
var ret = promptServ.prompt(gProgressDialog ? gProgressDialog : window, var ret = promptServ.prompt(gProgressDialog ? gProgressDialog : window,
dlgTitle, text, defaultText, pwrealm, saveCheck); dlgTitle, text, defaultText, pwrealm, savePWObj);
if (!ret) if (!ret)
setTimeout("CancelPublishing()",0); setTimeout(CancelPublishing,0);
return ret; return ret;
}, },
@ -1175,7 +1186,7 @@ var gEditorOutputProgressListener =
{ {
var ret = PromptUsernameAndPassword(dlgTitle, text, savePW, userObj, pwObj); var ret = PromptUsernameAndPassword(dlgTitle, text, savePW, userObj, pwObj);
if (!ret) if (!ret)
setTimeout("CancelPublishing()",0); setTimeout(CancelPublishing,0);
return ret; return ret;
}, },
@ -1187,16 +1198,23 @@ var gEditorOutputProgressListener =
if (!promptServ) if (!promptServ)
return false; return false;
var saveCheck = {value:savePW}; // Note difference with nsIPrompt::promptPassword, which has
// "inout" savePassword param, while nsIAuthPrompt is just "in"
// Also nsIAuth doesn't supply "checkBoxLabel"
// Initialize with user's previous preference for this site
var savePWObj = {value:savePW};
// Initialize with user's previous preference for this site // Initialize with user's previous preference for this site
if (gPublishData) if (gPublishData)
saveCheck.value = gPublishData.savePassword; savePWObj.value = gPublishData.savePassword;
ret = promptServ.promptPassword(gProgressDialog ? gProgressDialog : window, ret = promptServ.promptPassword(gProgressDialog ? gProgressDialog : window,
dlgTitle, text, pwObj, GetString("SavePassword"), saveCheck); dlgTitle, text, pwObj, GetString("SavePassword"), savePWObj);
if (!ret)
setTimeout(CancelPublishing,0);
if (ret && gPublishData) if (ret && gPublishData)
UpdateUsernamePasswordFromPrompt(gPublishData, gPublishData.username, pwObj.value, saveCheck.value); UpdateUsernamePasswordFromPrompt(gPublishData, gPublishData.username, pwObj.value, savePWObj.value);
} catch(e) {} } catch(e) {}
return ret; return ret;
@ -1216,29 +1234,63 @@ function PromptUsernameAndPassword(dlgTitle, text, savePW, userObj, pwObj)
if (!promptServ) if (!promptServ)
return false; return false;
var saveCheck = {value:savePW}; var savePWObj = {value:savePW};
// Initialize with user's previous preference for this site // Initialize with user's previous preference for this site
if (gPublishData) if (gPublishData)
{ {
// HTTP put uses this dialog if either username or password is bad, // HTTP put uses this dialog if either username or password is bad,
// so prefill username input field with the previous value for modification // so prefill username input field with the previous value for modification
saveCheck.value = gPublishData.savePassword; savePWObj.value = gPublishData.savePassword;
if (!userObj.value) if (!userObj.value)
userObj.value = gPublishData.username; userObj.value = gPublishData.username;
} }
ret = promptServ.promptUsernameAndPassword(gProgressDialog ? gProgressDialog : window, ret = promptServ.promptUsernameAndPassword(gProgressDialog ? gProgressDialog : window,
dlgTitle, text, userObj, pwObj, dlgTitle, text, userObj, pwObj,
GetString("SavePassword"), saveCheck); GetString("SavePassword"), savePWObj);
if (ret && gPublishData) if (ret && gPublishData)
UpdateUsernamePasswordFromPrompt(gPublishData, userObj.value, pwObj.value, saveCheck.value); UpdateUsernamePasswordFromPrompt(gPublishData, userObj.value, pwObj.value, savePWObj.value);
} catch (e) {} } catch (e) {}
return ret; return ret;
} }
function DumpDebugStatus(aStatus)
{
if (aStatus == 2152398852)
dump("***** status is UNKNOWN_TYPE\n");
else if (aStatus == 2152398853)
dump("***** status is DESTINATION_NOT_DIR\n");
else if (aStatus == 2152398854)
dump("***** status is TARGET_DOES_NOT_EXIST\n");
else if (aStatus == 2152398856)
dump("***** status is ALREADY_EXISTS\n");
else if (aStatus == 2152398858)
dump("***** status is DISK_FULL\n");
else if (aStatus == 2152398860)
dump("***** status is NOT_DIRECTORY\n");
else if (aStatus == 2152398861)
dump("***** status is IS_DIRECTORY\n");
else if (aStatus == 2152398862)
dump("***** status is IS_LOCKED\n");
else if (aStatus == 2152398863)
dump("***** status is TOO_BIG\n");
else if (aStatus == 2152398865)
dump("***** status is NAME_TOO_LONG\n");
else if (aStatus == 2152398866)
dump("***** status is NOT_FOUND\n");
else if (aStatus == 2152398867)
dump("***** status is READ_ONLY\n");
else if (aStatus == 2152398868)
dump("***** status is DIR_NOT_EMPTY\n");
else if (aStatus == 2152398869)
dump("***** status is ACCESS_DENIED\n");
else
dump("***** status is " + aStatus + "\n");
}
// Update any data that the user supplied in a prompt dialog // Update any data that the user supplied in a prompt dialog
function UpdateUsernamePasswordFromPrompt(publishData, username, password, savePassword) function UpdateUsernamePasswordFromPrompt(publishData, username, password, savePassword)
{ {
@ -1424,9 +1476,11 @@ function SaveDocument(aSaveAs, aSaveCopy, aMimeType)
return success; return success;
} }
//------------------------------- Publishing //------------------------------- Publishing
var gPublishData; var gPublishData;
var gProgressDialog; var gProgressDialog;
var gCommandAfterPublishing = null;
function Publish(publishData) function Publish(publishData)
{ {
@ -1442,21 +1496,25 @@ function Publish(publishData)
if (!gPublishData.docURI) if (!gPublishData.docURI)
return false; return false;
gPublishData.otherFilesURI = CreateURIFromPublishData(publishData, false); if (gPublishData.publishOtherFiles)
gPublishData.otherFilesURI = CreateURIFromPublishData(publishData, false);
else
gPublishData.otherFilesURI = null;
if (gShowDebugOutputStateChange) if (gShowDebugOutputStateChange)
{ {
dump("\n *** publishData: PublishUrl="+publishData.publishUrl+", BrowseUrl="+publishData.browseUrl+ dump("\n *** publishData: PublishUrl="+publishData.publishUrl+", BrowseUrl="+publishData.browseUrl+
", Username="+publishData.username+", Dir="+publishData.docDir+ ", Username="+publishData.username+", Dir="+publishData.docDir+
", Filename="+publishData.filename+"\n"); ", Filename="+publishData.filename+"\n");
dump(" * gPublishData.docURI.spec="+gPublishData.docURI.spec+"\n"); // dump(" * gPublishData.docURI.spec w/o pass="+StripPassword(gPublishData.docURI.spec)+", PublishOtherFiles="+gPublishData.publishOtherFiles+"\n");
dump(" * gPublishData.docURI.spec w/o pass="+gPublishData.docURI.spec+", PublishOtherFiles="+gPublishData.publishOtherFiles+"\n");
} }
// XXX Missing username or password will make FTP fail // XXX Missing username will make FTP fail
// and it won't call us for prompt dialog (bug 132320), // and it won't call us for prompt dialog (bug 132320)
// so we should do the prompt before trying to publish // (It does prompt if just password is missing)
if (GetScheme(publishData.publishUrl) == "ftp" && // So we should do the prompt ourselves before trying to publish
(!publishData.username || !publishData.password)) if (GetScheme(publishData.publishUrl) == "ftp" && !publishData.username)
{ {
var message = GetString("PromptFTPUsernamePassword").replace(/%host%/, GetHost(publishData.publishUrl)); var message = GetString("PromptFTPUsernamePassword").replace(/%host%/, GetHost(publishData.publishUrl));
var savePWobj = {value:publishData.savePassword}; var savePWobj = {value:publishData.savePassword};
@ -1469,8 +1527,11 @@ function Publish(publishData)
gPublishData.docURI.username = publishData.username; gPublishData.docURI.username = publishData.username;
gPublishData.docURI.password = publishData.password; gPublishData.docURI.password = publishData.password;
gPublishData.otherFilesURI.username = publishData.username; if (gPublishData.otherFilesURI)
gPublishData.otherFilesURI.password = publishData.password; {
gPublishData.otherFilesURI.username = publishData.username;
gPublishData.otherFilesURI.password = publishData.password;
}
} }
try { try {
@ -1481,7 +1542,7 @@ function Publish(publishData)
// Start progress monitoring // Start progress monitoring
gProgressDialog = gProgressDialog =
window.openDialog("chrome://editor/content/EditorPublishProgress.xul", "_blank", window.openDialog("chrome://editor/content/EditorPublishProgress.xul", "_blank",
"chrome,dependent", gPublishData, gPersistObj); "chrome,dependent,titlebar", gPublishData, gPersistObj);
} catch (e) {} } catch (e) {}
@ -1506,12 +1567,14 @@ function CancelPublishing()
gPersistObj.cancelSave(); // Cancel all networking transactions gPersistObj.cancelSave(); // Cancel all networking transactions
} catch (e) {} } catch (e) {}
// If canceling publishing do not do any commands after this
gCommandAfterPublishing = null;
if (gProgressDialog) if (gProgressDialog)
{ {
// Close Progress dialog // Close Progress dialog
// "true" will force close,
// (this will call FinishPublishing()) // (this will call FinishPublishing())
gProgressDialog.CloseDialog(true); gProgressDialog.CloseDialog();
} }
else else
FinishPublishing(); FinishPublishing();
@ -1522,7 +1585,14 @@ function FinishPublishing()
SetDocumentEditable(true); SetDocumentEditable(true);
gProgressDialog = null; gProgressDialog = null;
gPublishData = null; gPublishData = null;
window._content.focus();
if (gCommandAfterPublishing)
{
// Be sure to null out the global now incase of trouble when executing command
var command = gCommandAfterPublishing;
gCommandAfterPublishing = null;
goDoCommand(command);
}
} }
// Create a nsIURI object filled in with all required publishing info // Create a nsIURI object filled in with all required publishing info
@ -1533,18 +1603,14 @@ function CreateURIFromPublishData(publishData, doDocUri)
var URI; var URI;
try { try {
URI = Components.classes["@mozilla.org/network/standard-url;1"].createInstance(Components.interfaces.nsIURI);
if (!URI)
return null;
var spec = publishData.publishUrl; var spec = publishData.publishUrl;
if (doDocUri) if (doDocUri)
spec += FormatDirForPublishing(publishData.docDir) + publishData.filename; spec += FormatDirForPublishing(publishData.docDir) + publishData.filename;
else else
spec += FormatDirForPublishing(publishData.otherDir); spec += FormatDirForPublishing(publishData.otherDir);
URI.spec = spec; var ioService = GetIOService();
URI = ioService.newURI(spec, window.editorShell.GetDocumentCharacterSet(), null);
if (publishData.username) if (publishData.username)
URI.username = publishData.username; URI.username = publishData.username;
@ -1566,20 +1632,25 @@ function GetDocUrlFromPublishData(publishData)
var url; var url;
var docScheme = GetScheme(GetDocumentUrl()); var docScheme = GetScheme(GetDocumentUrl());
if (docScheme == "ftp" || !publishData.browseUrl) // Always use the "HTTP" address if available
// XXX Should we do some more validation here for bad urls???
// Let's at least check for a scheme!
if (!GetScheme(publishData.browseUrl))
url = publishData.publishUrl; url = publishData.publishUrl;
else else
url = publishData.browseUrl; url = publishData.browseUrl;
url += FormatDirForPublishing(publishData.docDir) + publishData.filename; url += FormatDirForPublishing(publishData.docDir) + publishData.filename;
if (GetScheme(url) == "ftp")
url = InsertUsernameIntoUrl(url, publishData.username);
return url; return url;
} }
// Depending on editing local vs. remote files: // Depending on editing local vs. remote files:
// 1. Switch the "Save" and "Publish" buttons on toolbars, // * Switch the "Save" and "Publish" buttons on toolbars,
// 2. Hide "Save" menuitem if editing remote // * Shift accel+S keybinding to Save or Publish commands
// 3. Shift accel+S keybinding to Save or Publish commands
// Note: A new, unsaved file is treated as a local file // Note: A new, unsaved file is treated as a local file
// (XXX Have a pref to treat as remote for user's who mostly edit remote?) // (XXX Have a pref to treat as remote for user's who mostly edit remote?)
function SetSaveAndPublishUI(urlstring) function SetSaveAndPublishUI(urlstring)
@ -1616,8 +1687,9 @@ function SetSaveAndPublishUI(urlstring)
SetElementHidden(publishButton, false); SetElementHidden(publishButton, false);
} }
SetElementHidden(menuItem1, true); // Use this to hide "Save" menuitem if editing remote, Hide "Publish" if editing local
SetElementHidden(menuItem2, false); // SetElementHidden(menuItem1, true);
// SetElementHidden(menuItem2, false);
var key = document.getElementById("savekb"); var key = document.getElementById("savekb");
if (key && command) if (key && command)
@ -1628,6 +1700,9 @@ function SetSaveAndPublishUI(urlstring)
menuItem1.removeAttribute("key"); menuItem1.removeAttribute("key");
menuItem2.setAttribute("key","savekb"); menuItem2.setAttribute("key","savekb");
} }
// Be sure enabled state of toolbar button is correct
goUpdateCommand(command);
} }
function SetDocumentEditable(isDocEditable) function SetDocumentEditable(isDocEditable)
@ -1639,11 +1714,11 @@ function SetDocumentEditable(isDocEditable)
window.editorShell.editor.flags = isDocEditable ? window.editorShell.editor.flags = isDocEditable ?
flags &= ~nsIPlaintextEditor.eEditorReadonlyMask : flags &= ~nsIPlaintextEditor.eEditorReadonlyMask :
flags | nsIPlaintextEditor.eEditorReadonlyMask; flags | nsIPlaintextEditor.eEditorReadonlyMask;
// update all commands
window.updateCommands("create");
} catch(e) {} } catch(e) {}
// update all commands
window._content.focus();
window.updateCommands("create");
} }
} }
@ -1731,7 +1806,7 @@ function CloseWindow()
{ {
// Check to make sure document is saved. "true" means allow "Don't Save" button, // Check to make sure document is saved. "true" means allow "Don't Save" button,
// so user can choose to close without saving // so user can choose to close without saving
if (CheckAndSaveDocument(GetString("BeforeClosing"), true)) if (CheckAndSaveDocument("cmd_close", true))
{ {
if (window.InsertCharWindow) if (window.InsertCharWindow)
SwitchInsertCharToAnotherEditorOrClose(); SwitchInsertCharToAnotherEditorOrClose();
@ -1773,7 +1848,7 @@ var nsPreviewCommand =
{ {
// Don't continue if user canceled during prompt for saving // Don't continue if user canceled during prompt for saving
// DocumentHasBeenSaved will test if we have a URL and suppress "Don't Save" button if not // DocumentHasBeenSaved will test if we have a URL and suppress "Don't Save" button if not
if (!CheckAndSaveDocument(GetString("BeforePreview"), DocumentHasBeenSaved())) if (!CheckAndSaveDocument("cmd_preview", DocumentHasBeenSaved()))
return; return;
// Check if we saved again just in case? // Check if we saved again just in case?
@ -1807,7 +1882,7 @@ var nsPreviewCommand =
// Be sure browser contains real source content, not cached // Be sure browser contains real source content, not cached
// setTimeout is needed because the "browser" created by openDialog // setTimeout is needed because the "browser" created by openDialog
// needs time to finish else BrowserReloadSkipCache doesn't exist // needs time to finish else BrowserReloadSkipCache doesn't exist
setTimeout( function(browser) { browser.BrowserReloadSkipCache(); }, 0, browser ); setTimeout( function(browser) { browser.BrowserReloadSkipCache(); }, 10, browser );
browser.focus(); browser.focus();
} }
} catch (ex) {} } catch (ex) {}
@ -1828,7 +1903,7 @@ var nsSendPageCommand =
{ {
// Don't continue if user canceled during prompt for saving // Don't continue if user canceled during prompt for saving
// DocumentHasBeenSaved will test if we have a URL and suppress "Don't Save" button if not // DocumentHasBeenSaved will test if we have a URL and suppress "Don't Save" button if not
if (!CheckAndSaveDocument(GetString("SendPageReason"), DocumentHasBeenSaved())) if (!CheckAndSaveDocument("cmd_editSendPage", DocumentHasBeenSaved()))
return; return;
// Check if we saved again just in case? // Check if we saved again just in case?
@ -1920,7 +1995,7 @@ var nsFindCommand =
{ {
try { try {
window.openDialog("chrome://editor/content/EdReplace.xul", "_blank", window.openDialog("chrome://editor/content/EdReplace.xul", "_blank",
"chrome,dependent", ""); "chrome,dependent,titlebar", "");
} }
catch(ex) { catch(ex) {
dump("*** Exception: couldn't open Replace Dialog\n"); dump("*** Exception: couldn't open Replace Dialog\n");
@ -2008,8 +2083,7 @@ var nsValidateCommand =
// then just validate the current url. // then just validate the current url.
if (editorShell.documentModified || gHTMLSourceChanged) if (editorShell.documentModified || gHTMLSourceChanged)
{ {
if (!CheckAndSaveDocument(GetString("BeforeValidate"), if (!CheckAndSaveDocument("cmd_validate", false))
false))
return; return;
// Check if we saved again just in case? // Check if we saved again just in case?

Просмотреть файл

@ -441,11 +441,13 @@ function DocumentHasBeenSaved()
return true; return true;
} }
function CheckAndSaveDocument(reasonToSave, allowDontSave) function CheckAndSaveDocument(command, allowDontSave)
{ {
// if we don't have an editorShell or an editorDocument, bail try {
if (!window.editorShell && !window.editorShell.editorDocument) // if we don't have an editorShell or an editorDocument, bail
return true; if (!window.editorShell && !window.editorShell.editorDocument)
return true;
} catch (e) { return true; }
var document = editorShell.editorDocument; var document = editorShell.editorDocument;
if (!editorShell.documentModified && !gHTMLSourceChanged) if (!editorShell.documentModified && !gHTMLSourceChanged)
@ -455,11 +457,33 @@ function CheckAndSaveDocument(reasonToSave, allowDontSave)
// and therefore need to be visible (to prevent user confusion) // and therefore need to be visible (to prevent user confusion)
window.focus(); window.focus();
var scheme = GetScheme(GetDocumentUrl());
var doPublish = (scheme && scheme != "file");
var strID;
switch (command)
{
case "cmd_close":
strID = "BeforeClosing";
break;
case "cmd_preview":
strID = "BeforePreview";
break;
case "cmd_editSendPage":
strID = "SendPageReason";
break;
case "cmd_validate":
strID = "BeforeValidate";
break;
}
var reasonToSave = strID ? GetString(strID) : "";
var title = window.editorShell.editorDocument.title; var title = window.editorShell.editorDocument.title;
if (!title) if (!title)
title = GetString("untitled"); title = GetString("untitled");
var dialogTitle = GetString("SaveDocument"); var dialogTitle = GetString(doPublish ? "PublishPage" : "SaveDocument");
var dialogMsg = GetString("SaveFilePrompt"); var dialogMsg = GetString("SaveFilePrompt");
dialogMsg = (dialogMsg.replace(/%title%/,title)).replace(/%reason%/,reasonToSave); dialogMsg = (dialogMsg.replace(/%title%/,title)).replace(/%reason%/,reasonToSave);
@ -467,16 +491,29 @@ function CheckAndSaveDocument(reasonToSave, allowDontSave)
promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService); promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
var result = {value:0}; var result = {value:0};
var promptFlags = var promptFlags = promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1;
(promptService.BUTTON_TITLE_SAVE * promptService.BUTTON_POS_0) + var button1Title = null;
(promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1) + var button3Title = null;
(allowDontSave
? (promptService.BUTTON_TITLE_DONT_SAVE * promptService.BUTTON_POS_2) if (doPublish)
: 0); {
promptService.confirmEx( promptFlags += promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0;
window, dialogTitle, dialogMsg, promptFlags, button1Title = GetString("Publish");
null, null, null, null, {value:0}, result button3Title = GetString("DontPublish");
); }
else
{
promptFlags += promptService.BUTTON_TITLE_SAVE * promptService.BUTTON_POS_0;
}
// If allowing "Don't..." button, add that
if (allowDontSave)
promptFlags += doPublish ?
(promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_2)
: (promptService.BUTTON_TITLE_DONT_SAVE * promptService.BUTTON_POS_2);
promptService.confirmEx(window, dialogTitle, dialogMsg, promptFlags,
button1Title, null, button3Title, null, {value:0}, result);
if (result.value == 0) if (result.value == 0)
{ {
@ -484,6 +521,17 @@ function CheckAndSaveDocument(reasonToSave, allowDontSave)
if (gHTMLSourceChanged) if (gHTMLSourceChanged)
FinishHTMLSource(); FinishHTMLSource();
if (doPublish)
{
// We save the command the user wanted to do in a global
// and return as if user canceled because publishing is asynchronous
// This command will be fired when publishing finishes
gCommandAfterPublishing = command;
goDoCommand("cmd_publish");
return false;
}
// Save to local disk
var success = SaveDocument(false, false, editorShell.contentsMIMEType); var success = SaveDocument(false, false, editorShell.contentsMIMEType);
return success; return success;
} }
@ -520,7 +568,7 @@ function EditorCanClose()
// Returns FALSE only if user cancels save action // Returns FALSE only if user cancels save action
// "true" means allow "Don't Save" button // "true" means allow "Don't Save" button
var canClose = CheckAndSaveDocument(GetString("BeforeClosing"), true); var canClose = CheckAndSaveDocument("cmd_close", true);
// This is our only hook into closing via the "X" in the caption // This is our only hook into closing via the "X" in the caption
// or "Quit" (or other paths?) // or "Quit" (or other paths?)
@ -1583,7 +1631,7 @@ function BuildRecentMenu(savePrefs)
// Current page is the "0" item in the list we save in prefs, // Current page is the "0" item in the list we save in prefs,
// but we don't include it in the menu. // but we don't include it in the menu.
var curTitle = window.editorShell.editorDocument.title; var curTitle = window.editorShell.editorDocument.title;
var curUrl = GetDocumentUrl(); var curUrl = StripPassword(GetDocumentUrl());
var historyCount = 10; var historyCount = 10;
try { historyCount = gPrefs.getIntPref("editor.history.url_maximum"); } catch(e) {} try { historyCount = gPrefs.getIntPref("editor.history.url_maximum"); } catch(e) {}
var titleArray = new Array(historyCount); var titleArray = new Array(historyCount);
@ -1607,13 +1655,17 @@ function BuildRecentMenu(savePrefs)
// Continue if URL pref is missing because // Continue if URL pref is missing because
// a URL not found during loading may have been removed // a URL not found during loading may have been removed
if (!url) // Also skip "data:" URL
if (!url || GetScheme(url) == "data")
continue; continue;
var scheme = GetScheme(url); // Never show password in menu!
// Skip over current and "data:" URL url = StripPassword(url);
if (url != curUrl && scheme && scheme != "data")
// Skip over current URL
if (url != curUrl)
{ {
// Build the menu // Build the menu
AppendRecentMenuitem(popup, title, url, menuIndex); AppendRecentMenuitem(popup, title, url, menuIndex);
menuIndex++; menuIndex++;
@ -1690,6 +1742,14 @@ function AppendRecentMenuitem(menupopup, title, url, menuIndex)
} }
} }
function EditorInitFileMenu()
{
// Disable "Save" menuitem when editing remote url. User should use "Save As"
var scheme = GetScheme(GetDocumentUrl());
if (scheme && scheme != "file")
SetElementEnabledById("saveMenuitem", false);
}
function EditorInitFormatMenu() function EditorInitFormatMenu()
{ {
try { try {

Просмотреть файл

@ -290,7 +290,7 @@
so we use our own id, label, and accesskey but connect to the same global key and broadcaster node so we use our own id, label, and accesskey but connect to the same global key and broadcaster node
--> -->
<menu id="fileMenu" label="&fileMenu.label;" accesskey="&filemenu.accesskey;"> <menu id="fileMenu" label="&fileMenu.label;" accesskey="&filemenu.accesskey;">
<menupopup id="menu_FilePopup"> <menupopup id="menu_FilePopup" onpopupshowing="EditorInitFileMenu();">
<menu id="menu_New"> <menu id="menu_New">
<menupopup id="menu_NewPopup"> <menupopup id="menu_NewPopup">
<!-- From globalOverlay.xul --> <!-- From globalOverlay.xul -->

Просмотреть файл

@ -48,8 +48,11 @@ const gMac = "Mac";
/************* Message dialogs ***************/ /************* Message dialogs ***************/
function AlertWithTitle(title, message) function AlertWithTitle(title, message, parentWindow)
{ {
if (!parentWindow)
parentWindow = window;
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(); var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService); promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
@ -59,7 +62,7 @@ function AlertWithTitle(title, message)
title = GetString("Alert"); title = GetString("Alert");
// "window" is the calling dialog window // "window" is the calling dialog window
promptService.alert(window, title, message); promptService.alert(parentWindow, title, message);
} }
} }

Просмотреть файл

@ -157,7 +157,9 @@ function CreatePublishDataFromUrl(docUrl)
browseUrl : pubUrl, browseUrl : pubUrl,
docDir : "", docDir : "",
otherDir : "", otherDir : "",
publishOtherFiles : true,
dirList : [""], dirList : [""],
saveDirs : false,
notInSiteData : true notInSiteData : true
} }
@ -183,22 +185,11 @@ function GetPublishDataFromSiteName(siteName, docUrlOrFilename)
if (siteNameList[i] == siteName) if (siteNameList[i] == siteName)
{ {
var publishData = GetPublishData_internal(publishBranch, siteName); var publishData = GetPublishData_internal(publishBranch, siteName);
var filename = docUrlOrFilename; if (GetScheme(docUrlOrFilename))
var scheme = GetScheme(docUrlOrFilename); FillInMatchingPublishData(publishData, docUrlOrFilename);
if (scheme) else
{ publishData.filename = docUrlOrFilename;
// Separate into the base url and filename
var lastSlash = docUrlOrFilename.lastIndexOf("\/");
var url = docUrlOrFilename.slice(0, lastSlash);
filename = docUrlOrFilename.slice(lastSlash+1);
// Get length of the publish url that matches this docUrl
var len = GetMatchingPublishUrlLength(publishData, url);
if (len)
// The remainder is a subdirectory within the site
publishData.docDir = FormatDirForPublishing(url.slice(len));
}
publishData.filename = filename;
return publishData; return publishData;
} }
} }
@ -233,8 +224,10 @@ function GetPublishData_internal(publishBranch, siteName)
return null; return null;
var savePassword = false; var savePassword = false;
var publishOtherFiles = true;
try { try {
savePassword = publishBranch.getBoolPref(prefPrefix+"save_password"); savePassword = publishBranch.getBoolPref(prefPrefix+"save_password");
publishOtherFiles = publishBranch.getBoolPref(prefPrefix+"publish_other_files");
} catch (e) {} } catch (e) {}
var publishData = { var publishData = {
@ -245,11 +238,27 @@ function GetPublishData_internal(publishBranch, siteName)
publishUrl : publishUrl, publishUrl : publishUrl,
browseUrl : GetPublishStringPref(publishBranch, prefPrefix+"browse_url"), browseUrl : GetPublishStringPref(publishBranch, prefPrefix+"browse_url"),
docDir : FormatDirForPublishing(GetPublishStringPref(publishBranch, prefPrefix+"doc_dir")), docDir : FormatDirForPublishing(GetPublishStringPref(publishBranch, prefPrefix+"doc_dir")),
otherDir : FormatDirForPublishing(GetPublishStringPref(publishBranch, prefPrefix+"other_dir")) otherDir : FormatDirForPublishing(GetPublishStringPref(publishBranch, prefPrefix+"other_dir")),
publishOtherFiles : publishOtherFiles,
saveDirs : false
} }
// Get password from PasswordManager // Get password from PasswordManager
publishData.password = GetSavedPassword(publishData); publishData.password = GetSavedPassword(publishData);
// If password was found, user must have checked "Save password"
// checkbox in prompt outside of publishing, so override the pref we stored
if (publishData.password)
{
if (!savePassword)
{
try {
publishPrefsBranch.setBoolPref(prefPrefix+"save_password", true);
} catch (e) {}
}
publishData.savePassword = true;
}
// Build history list of directories // Build history list of directories
// Always supply the root dir // Always supply the root dir
publishData.dirList = [""]; publishData.dirList = [""];
@ -352,14 +361,22 @@ function SavePublishDataToPrefs(publishData)
{ {
var siteName = GetPublishStringPref(publishBranch, "site_name."+i); var siteName = GetPublishStringPref(publishBranch, "site_name."+i);
if (siteName == publishData.siteName) if (siteName == publishData.siteName)
{
// Delete prefs for an existing site
try {
publishBranch.deleteBranch("site_data." + siteName + ".");
} catch (e) {}
break; break;
}
} }
var ret = SavePublishData_Internal(publishBranch, publishData, i); var ret = SavePublishData_Internal(publishBranch, publishData, i);
if (ret) if (ret)
{ {
SavePrefFile(); SavePrefFile();
// Clear signal to save these data // Clear signal to save these data
if (publishData.notInSiteData) if ("notInSiteData" in publishData && publishData.notInSiteData)
publishData.notInSiteData = false; publishData.notInSiteData = false;
} }
return ret; return ret;
@ -376,23 +393,38 @@ function SavePublishData_Internal(publishPrefsBranch, publishData, siteIndex)
FixupUsernamePasswordInPublishData(publishData); FixupUsernamePasswordInPublishData(publishData);
var prefPrefix = "site_data." + publishData.siteName + "." var prefPrefix = "site_data." + publishData.siteName + "."
SetPublishStringPref(publishPrefsBranch, prefPrefix+"url", publishData.publishUrl); SetPublishStringPref(publishPrefsBranch, prefPrefix+"url", publishData.publishUrl);
SetPublishStringPref(publishPrefsBranch, prefPrefix+"browse_url", publishData.browseUrl); SetPublishStringPref(publishPrefsBranch, prefPrefix+"browse_url", publishData.browseUrl);
SetPublishStringPref(publishPrefsBranch, prefPrefix+"username", publishData.username); SetPublishStringPref(publishPrefsBranch, prefPrefix+"username", publishData.username);
try { try {
publishPrefsBranch.setBoolPref(prefPrefix+"save_password", publishData.savePassword); publishPrefsBranch.setBoolPref(prefPrefix+"save_password", publishData.savePassword);
publishPrefsBranch.setBoolPref(prefPrefix+"publish_other_files", publishData.publishOtherFiles);
} catch (e) {} } catch (e) {}
// Save password using PasswordManager // Save password using PasswordManager
// (If publishData.savePassword = false, this clears existing password) // (If publishData.savePassword = false, this clears existing password)
SavePassword(publishData); SavePassword(publishData);
SetPublishStringPref(publishPrefsBranch, prefPrefix+"doc_dir", publishData.docDir); SetPublishStringPref(publishPrefsBranch, prefPrefix+"doc_dir",
if (publishData.otherDir) FormatDirForPublishing(publishData.docDir));
SetPublishStringPref(publishPrefsBranch, prefPrefix+"other_dir", publishData.otherDir);
// Save array of directories in each site if (publishData.publishOtherFiles && publishData.otherDir)
SetPublishStringPref(publishPrefsBranch, prefPrefix+"other_dir",
FormatDirForPublishing(publishData.otherDir));
if ("saveDirs" in publishData && publishData.saveDirs)
{
if (publishData.docDir)
AppendNewDirToList(publishData, publishData.docDir);
if (publishData.publishOtherFiles && publishData.otherDir
&& publishData.otherDir != publishData.docDir)
AppendNewDirToList(publishData, publishData.otherDir);
}
// Save array of subdirectories with site
if (publishData.dirList.length) if (publishData.dirList.length)
{ {
publishData.dirList.sort(); publishData.dirList.sort();
@ -409,6 +441,89 @@ function SavePublishData_Internal(publishPrefsBranch, publishData, siteIndex)
} }
} }
} }
return true;
}
function AppendNewDirToList(publishData, newDir)
{
newDir = FormatDirForPublishing(newDir);
if (!publishData || !newDir)
return;
if (!publishData.dirList)
{
publishData.dirList = [newDir];
return;
}
// Check if already in the list
for (var i = 0; i < publishData.dirList.length; i++)
{
// Don't add if already in the list
if (newDir == publishData.dirList[i])
return;
}
// Add to end of list
publishData.dirList[publishData.dirList.length] = newDir;
}
function RemovePublishSubdirectoryFromPrefs(publishData, removeDir)
{
removeDir = FormatDirForPublishing(removeDir);
if (!publishData || !publishData.siteName || !removeDir)
return false;
var publishBranch = GetPublishPrefsBranch();
if (!publishBranch)
return false;
var prefPrefix = "site_data." + publishData.siteName + ".";
// Remove dir from the default dir prefs
if (publishData.docDir == removeDir)
{
publishData.docDir = "";
SetPublishStringPref(publishBranch, prefPrefix+"doc_dir", "");
}
if (publishData.otherDir == removeDir)
{
publishData.otherDir = "";
SetPublishStringPref(publishBranch, prefPrefix+"other_dir", "");
}
prefPrefix += "dir.";
// Delete entire subdir list
try {
publishBranch.deleteBranch(prefPrefix);
} catch (e) {}
// Rebuild prefs, skipping over site to remove
if (publishData.dirList.length)
{
var dirIndex = 0;
var docDirInList = false;
var otherDirInList = false;
for (var i = 0; i < publishData.dirList.length; i++)
{
var dir = publishData.dirList[i];
if (dir == removeDir)
{
// Remove item from the dirList array
publishData.dirList.splice(i, 1);
--i;
}
else if (dir && dir != "/") // skip empty or root dir
{
// Save to prefs
SetPublishStringPref(publishBranch, prefPrefix + dirIndex, dir);
dirIndex++;
}
}
}
SavePrefFile();
return true; return true;
} }
@ -533,55 +648,74 @@ function FindSiteIndexAndDocDir(publishSiteData, docUrl, dirObj)
if (!publishSiteData || !docUrl || GetScheme(docUrl) == "file") if (!publishSiteData || !docUrl || GetScheme(docUrl) == "file")
return -1; return -1;
// Remove filename from docUrl
// (Check for terminal "/" so docUrl param can be a directory path)
if (docUrl.charAt(docUrl.length-1) != "/")
{
var lastSlash = docUrl.lastIndexOf("/");
docUrl = docUrl.slice(0, lastSlash+1);
}
var siteIndex = -1; var siteIndex = -1;
var siteUrlLen = 0; var siteUrlLen = 0;
var urlLen = docUrl.length;
for (var i = 0; i < publishSiteData.length; i++) for (var i = 0; i < publishSiteData.length; i++)
{ {
// Site publish or browse url needs to be contained in document URL, // Site publish or browse url needs to be contained in document URL,
// but that may also have a directory after the site base URL // but that may also have a directory after the site base URL
// So we must examine all records to find the site URL that best // So we must examine all records to find the site URL that best
// matches the document URL (XXX is this right?) // matches the document URL: the longest-matching substring (XXX is this right?)
var len = GetMatchingPublishUrlLength(publishSiteData[i], docUrl); var lenObj = {value:0};
var tempData = publishSiteData[i];
// Check if this site matches docUrl (returns length of match if found)
var len = FillInMatchingPublishData(tempData, docUrl);
if (len > siteUrlLen) if (len > siteUrlLen)
{ {
siteIndex = i; siteIndex = i;
siteUrlLen = len; siteUrlLen = len;
if (dirObj)
dirObj.value = tempData.docDir;
// Continue to find the site with longest-matching publishUrl
} }
} }
// Get directory name from the end of url
if (dirObj && siteIndex >= 0 && urlLen > siteUrlLen)
dirObj.value = FormatDirForPublishing(docUrl.slice(siteUrlLen));
return siteIndex; return siteIndex;
} }
// Look for a matching publish url within the document url // Look for a matching publish url within the document url
// (We need to look at both "publishUrl" and "browseUrl" in case we are editing // (We need to look at both "publishUrl" and "browseUrl" in case we are editing
// an http: document but using ftp: to publish.) // an http: document but using ftp: to publish.)
// Return the length of that matching portion // If match is found:
// Used to find the optimum publishing site within all site data // Fill in the filename and subirectory based on the docUrl and
// and to extract remaining directory from the end of a document url // return the length of the docUrl with username+password stripped out
function GetMatchingPublishUrlLength(publishData, docUrl) function FillInMatchingPublishData(publishData, docUrl)
{ {
if (publishData && docUrl) if (!publishData || !docUrl)
return 0;
// Separate docUrl into the base url and filename
var lastSlash = docUrl.lastIndexOf("\/");
var baseUrl = docUrl.slice(0, lastSlash+1);
var filename = docUrl.slice(lastSlash+1);
// Strip username+password from docUrl because these
// are stored separately in publishData, never embedded in the publishUrl
// If both docUrl and publishData contain usernames,
// we must match that as well as the url
var username = {value:""};
baseUrl = StripUsernamePassword(baseUrl, username);
username = username.value;
var matchedLength = 0;
var pubUrlFound = baseUrl.indexOf(publishData.publishUrl) == 0;
var browseUrlFound = baseUrl.indexOf(publishData.browseUrl) == 0;
if ((pubUrlFound || browseUrlFound)
&& (!username || !publishData.username || username == publishData.username))
{ {
var pubUrlFound = docUrl.indexOf(publishData.publishUrl) == 0; // We found a match
var browseUrlFound = docUrl.indexOf(publishData.browseUrl) == 0; matchedLength = pubUrlFound ? publishData.publishUrl.length
if (pubUrlFound || browseUrlFound) : publishData.browseUrl.length;
return pubUrlFound ? publishData.publishUrl.length : publishData.browseUrl.length;
publishData.filename = filename;
// Subdirectory within the site is whats left in baseUrl after the matched portion
publishData.docDir = FormatDirForPublishing(baseUrl.slice(matchedLength));
} }
return 0; return matchedLength;
} }
// Prefs that don't exist will through an exception, // Prefs that don't exist will through an exception,
@ -707,7 +841,7 @@ function GetPasswordManagerInternal()
function GetSavedPassword(publishData) function GetSavedPassword(publishData)
{ {
if (!publishData || !publishData.savePassword) if (!publishData)
return ""; return "";
var passwordManagerInternal = GetPasswordManagerInternal(); var passwordManagerInternal = GetPasswordManagerInternal();
if (!passwordManagerInternal) if (!passwordManagerInternal)
@ -716,12 +850,13 @@ function GetSavedPassword(publishData)
var host = {value:""}; var host = {value:""};
var user = {value:""}; var user = {value:""};
var password = {value:""}; var password = {value:""};
var url = GetUrlForPasswordManager(publishData);
try { try {
passwordManagerInternal.findPasswordEntry passwordManagerInternal.findPasswordEntry
(publishData.publishUrl, publishData.username, "", host, user, password); (url, publishData.username, "", host, user, password);
return password.value; return password.value;
} catch (e) { } catch (e) {}
}
return ""; return "";
} }
@ -734,20 +869,44 @@ function SavePassword(publishData)
var passwordManager = GetPasswordManager(); var passwordManager = GetPasswordManager();
if (passwordManager) if (passwordManager)
{ {
var url = GetUrlForPasswordManager(publishData);
// Remove existing entry // Remove existing entry
// (Note: there is no method to update a password for an existing entry) // (Note: there is no method to update a password for an existing entry)
try { try {
passwordManager.removeUser(publishData.publishUrl, publishData.username); passwordManager.removeUser(url, publishData.username);
} catch (e) {} } catch (e) {}
// If SavePassword is true, add new password // If SavePassword is true, add new password
if (publishData.savePassword) if (publishData.savePassword)
{ {
try { try {
passwordManager.addUser(publishData.publishUrl, publishData.username, publishData.password); passwordManager.addUser(url, publishData.username, publishData.password);
} catch (e) {} } catch (e) {}
} }
return true; return true;
} }
return false; return false;
} }
function GetUrlForPasswordManager(publishData)
{
if (!publishData || !publishData.publishUrl)
return false;
var url;
// For FTP, we must embed the username into the url for a site address
// XXX Maybe we should we do this for HTTP as well???
if (publishData.username && GetScheme(publishData.publishUrl) == "ftp")
url = InsertUsernameIntoUrl(publishData.publishUrl, publishData.username);
else
url = publishData.publishUrl;
// Strip off terminal "/"
var len = url.length;
if (len && url.charAt(len-1) == "\/")
url = url.slice(0, len-1);
return url;
}