NS_IMETHODIMP nsMsgBrkMBoxStore::CreateFolder(nsIMsgFolder *aParent, const nsAString &aFolderName, nsIMsgFolder **aResult) { NS_ENSURE_ARG_POINTER(aParent); NS_ENSURE_ARG_POINTER(aResult); if (aFolderName.IsEmpty()) return NS_MSG_ERROR_INVALID_FOLDER_NAME; nsCOMPtr<nsIFile> path; nsCOMPtr<nsIMsgFolder> child; nsresult rv = aParent->GetFilePath(getter_AddRefs(path)); if (NS_FAILED(rv)) return rv; //Get a directory based on our current path. rv = CreateDirectoryForFolder(path); if (NS_FAILED(rv)) return rv; // Now we have a valid directory or we have returned. // Make sure the new folder name is valid nsAutoString safeFolderName(aFolderName); NS_MsgHashIfNecessary(safeFolderName); path->Append(safeFolderName); bool exists; path->Exists(&exists); if (exists) //check this because localized names are different from disk names return NS_MSG_FOLDER_EXISTS; path->Create(nsIFile::NORMAL_FILE_TYPE, 0600); //GetFlags and SetFlags in AddSubfolder will fail because we have no db at // this point but mFlags is set. rv = aParent->AddSubfolder(safeFolderName, getter_AddRefs(child)); if (!child || NS_FAILED(rv)) { path->Remove(false); return rv; } // Create an empty database for this mail folder, set its name from the user nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv); if (msgDBService) { nsCOMPtr<nsIMsgDatabase> unusedDB; rv = msgDBService->OpenFolderDB(child, true, getter_AddRefs(unusedDB)); if (rv == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING) rv = msgDBService->CreateNewDB(child, getter_AddRefs(unusedDB)); if ((NS_SUCCEEDED(rv) || rv == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE) && unusedDB) { //need to set the folder name nsCOMPtr<nsIDBFolderInfo> folderInfo; rv = unusedDB->GetDBFolderInfo(getter_AddRefs(folderInfo)); if (NS_SUCCEEDED(rv)) folderInfo->SetMailboxName(safeFolderName); unusedDB->SetSummaryValid(true); unusedDB->Close(true); aParent->UpdateSummaryTotals(true); } else { path->Remove(false); rv = NS_MSG_CANT_CREATE_FOLDER; } } child.forget(aResult); return rv; }
NS_IMETHODIMP nsMsgMaildirStore::CopyFolder(nsIMsgFolder *aSrcFolder, nsIMsgFolder *aDstFolder, bool aIsMoveFolder, nsIMsgWindow *aMsgWindow, nsIMsgCopyServiceListener *aListener) { NS_ENSURE_ARG_POINTER(aSrcFolder); NS_ENSURE_ARG_POINTER(aDstFolder); nsString folderName; aSrcFolder->GetName(folderName); nsAutoString safeFolderName(folderName); NS_MsgHashIfNecessary(safeFolderName); nsCOMPtr<nsIMsgLocalMailFolder> localSrcFolder(do_QueryInterface(aSrcFolder)); aSrcFolder->ForceDBClosed(); nsCOMPtr<nsIFile> oldPath; nsresult rv = aSrcFolder->GetFilePath(getter_AddRefs(oldPath)); NS_ENSURE_SUCCESS(rv,rv); nsCOMPtr<nsIFile> summaryFile; GetSummaryFileLocation(oldPath, getter_AddRefs(summaryFile)); nsCOMPtr<nsIFile> newPath; rv = aDstFolder->GetFilePath(getter_AddRefs(newPath)); NS_ENSURE_SUCCESS(rv, rv); // create target directory based on our current path bool isServer; aDstFolder->GetIsServer(&isServer); rv = CreateDirectoryForFolder(newPath, isServer); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIFile> origPath; oldPath->Clone(getter_AddRefs(origPath)); rv = oldPath->CopyTo(newPath, EmptyString()); NS_ENSURE_SUCCESS(rv, rv); //will fail if a file by that name exists // Copy to dir can fail if file does not exist. If copy fails, we test // if the file exists or not, if it does not that's ok, we continue // without copying it. If it fails and file exist and is not zero sized // there is real problem. rv = summaryFile->CopyTo(newPath, EmptyString()); if (!NS_SUCCEEDED(rv)) { // Test if the file is not empty bool exists; int64_t fileSize; summaryFile->Exists(&exists); summaryFile->GetFileSize(&fileSize); if (exists && fileSize > 0) NS_ENSURE_SUCCESS(rv, rv); // Yes, it should have worked! // else case is file is zero sized, no need to copy it, // not an error // else case is file does not exist - not an error } nsCOMPtr<nsIMsgFolder> newMsgFolder; rv = aDstFolder->AddSubfolder(safeFolderName, getter_AddRefs(newMsgFolder)); NS_ENSURE_SUCCESS(rv, rv); newMsgFolder->SetPrettyName(folderName); uint32_t flags; aSrcFolder->GetFlags(&flags); newMsgFolder->SetFlags(flags); bool changed = false; rv = aSrcFolder->MatchOrChangeFilterDestination(newMsgFolder, true, &changed); if (changed) aSrcFolder->AlertFilterChanged(aMsgWindow); nsCOMPtr<nsISimpleEnumerator> enumerator; rv = aSrcFolder->GetSubFolders(getter_AddRefs(enumerator)); NS_ENSURE_SUCCESS(rv, rv); // Copy subfolders to the new location nsresult copyStatus = NS_OK; nsCOMPtr<nsIMsgLocalMailFolder> localNewFolder(do_QueryInterface(newMsgFolder, &rv)); if (NS_SUCCEEDED(rv)) { bool hasMore; while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore && NS_SUCCEEDED(copyStatus)) { nsCOMPtr<nsISupports> item; enumerator->GetNext(getter_AddRefs(item)); nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(item)); if (!folder) continue; copyStatus = localNewFolder->CopyFolderLocal(folder, false, aMsgWindow, aListener); // Test if the call succeeded, if not we have to stop recursive call if (NS_FAILED(copyStatus)) { // Copy failed we have to notify caller to handle the error and stop // moving the folders. In case this happens to the topmost level of // recursive call, then we just need to break from the while loop and // go to error handling code. if (!aIsMoveFolder) return copyStatus; break; } } } if (aIsMoveFolder && NS_SUCCEEDED(copyStatus)) { if (localNewFolder) { nsCOMPtr<nsISupports> srcSupport(do_QueryInterface(aSrcFolder)); localNewFolder->OnCopyCompleted(srcSupport, true); } // Notify that the folder that was dragged and dropped has been created. // No need to do this for its subfolders - isMoveFolder will be true for folder. aDstFolder->NotifyItemAdded(newMsgFolder); nsCOMPtr<nsIMsgFolder> msgParent; aSrcFolder->GetParent(getter_AddRefs(msgParent)); aSrcFolder->SetParent(nullptr); if (msgParent) { // The files have already been moved, so delete storage false msgParent->PropagateDelete(aSrcFolder, false, aMsgWindow); oldPath->Remove(true); nsCOMPtr<nsIMsgDatabase> srcDB; // we need to force closed the source db aSrcFolder->Delete(); nsCOMPtr<nsIFile> parentPath; rv = msgParent->GetFilePath(getter_AddRefs(parentPath)); NS_ENSURE_SUCCESS(rv,rv); AddDirectorySeparator(parentPath); nsCOMPtr<nsISimpleEnumerator> children; parentPath->GetDirectoryEntries(getter_AddRefs(children)); bool more; // checks if the directory is empty or not if (children && NS_SUCCEEDED(children->HasMoreElements(&more)) && !more) parentPath->Remove(true); } } else { // This is the case where the copy of a subfolder failed. // We have to delete the newDirectory tree to make a "rollback". // Someone should add a popup to warn the user that the move was not // possible. if (aIsMoveFolder && NS_FAILED(copyStatus)) { nsCOMPtr<nsIMsgFolder> msgParent; newMsgFolder->ForceDBClosed(); newMsgFolder->GetParent(getter_AddRefs(msgParent)); newMsgFolder->SetParent(nullptr); if (msgParent) { msgParent->PropagateDelete(newMsgFolder, false, aMsgWindow); newMsgFolder->Delete(); newMsgFolder->ForceDBClosed(); AddDirectorySeparator(newPath); newPath->Remove(true); //berkeley mailbox } return NS_ERROR_FAILURE; } } return NS_OK; }
NS_IMETHODIMP nsMsgBrkMBoxStore::RenameFolder(nsIMsgFolder *aFolder, const nsAString & aNewName, nsIMsgFolder **aNewFolder) { NS_ENSURE_ARG_POINTER(aFolder); NS_ENSURE_ARG_POINTER(aNewFolder); uint32_t numChildren; aFolder->GetNumSubFolders(&numChildren); nsString existingName; aFolder->GetName(existingName); nsCOMPtr<nsIFile> oldPathFile; nsresult rv = aFolder->GetFilePath(getter_AddRefs(oldPathFile)); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIMsgFolder> parentFolder; rv = aFolder->GetParent(getter_AddRefs(parentFolder)); if (!parentFolder) return NS_ERROR_NULL_POINTER; nsCOMPtr<nsISupports> parentSupport = do_QueryInterface(parentFolder); nsCOMPtr<nsIFile> oldSummaryFile; rv = aFolder->GetSummaryFile(getter_AddRefs(oldSummaryFile)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIFile> dirFile; oldPathFile->Clone(getter_AddRefs(dirFile)); if (numChildren > 0) { rv = CreateDirectoryForFolder(dirFile); NS_ENSURE_SUCCESS(rv, rv); } nsAutoString safeName(aNewName); NS_MsgHashIfNecessary(safeName); nsAutoCString oldLeafName; oldPathFile->GetNativeLeafName(oldLeafName); nsCOMPtr<nsIFile> parentPathFile; parentFolder->GetFilePath(getter_AddRefs(parentPathFile)); NS_ENSURE_SUCCESS(rv,rv); bool isDirectory = false; parentPathFile->IsDirectory(&isDirectory); if (!isDirectory) { nsAutoString leafName; parentPathFile->GetLeafName(leafName); leafName.AppendLiteral(FOLDER_SUFFIX); rv = parentPathFile->SetLeafName(leafName); NS_ENSURE_SUCCESS(rv, rv); } aFolder->ForceDBClosed(); //save off dir name before appending .msf rv = oldPathFile->MoveTo(nullptr, safeName); if (NS_FAILED(rv)) return rv; nsString dbName(safeName); dbName += NS_LITERAL_STRING(SUMMARY_SUFFIX); oldSummaryFile->MoveTo(nullptr, dbName); if (numChildren > 0) { // rename "*.sbd" directory nsAutoString newNameDirStr(safeName); newNameDirStr += NS_LITERAL_STRING(".sbd"); dirFile->MoveTo(nullptr, newNameDirStr); } return parentFolder->AddSubfolder(safeName, aNewFolder); }
NS_IMETHODIMP nsMsgMaildirStore::CreateFolder(nsIMsgFolder *aParent, const nsAString &aFolderName, nsIMsgFolder **aResult) { NS_ENSURE_ARG_POINTER(aParent); NS_ENSURE_ARG_POINTER(aResult); if (aFolderName.IsEmpty()) return NS_MSG_ERROR_INVALID_FOLDER_NAME; nsCOMPtr <nsIFile> path; nsresult rv = aParent->GetFilePath(getter_AddRefs(path)); NS_ENSURE_SUCCESS(rv, rv); // Get a directory based on our current path bool isServer; aParent->GetIsServer(&isServer); rv = CreateDirectoryForFolder(path, isServer); NS_ENSURE_SUCCESS(rv, rv); // Make sure the new folder name is valid nsAutoString safeFolderName(aFolderName); NS_MsgHashIfNecessary(safeFolderName); path->Append(safeFolderName); rv = CreateMaildir(path); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIMsgFolder> child; // GetFlags and SetFlags in AddSubfolder will fail because we have no db at // this point but mFlags is set. rv = aParent->AddSubfolder(safeFolderName, getter_AddRefs(child)); if (!child || NS_FAILED(rv)) { path->Remove(true); // recursive return rv; } // Create an empty database for this mail folder, set its name from the user nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv); if (msgDBService) { nsCOMPtr<nsIMsgDatabase> unusedDB; rv = msgDBService->OpenFolderDB(child, true, getter_AddRefs(unusedDB)); if (rv == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING) rv = msgDBService->CreateNewDB(child, getter_AddRefs(unusedDB)); if ((NS_SUCCEEDED(rv) || rv == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE) && unusedDB) { //need to set the folder name nsCOMPtr<nsIDBFolderInfo> folderInfo; rv = unusedDB->GetDBFolderInfo(getter_AddRefs(folderInfo)); if (NS_SUCCEEDED(rv)) folderInfo->SetMailboxName(safeFolderName); unusedDB->SetSummaryValid(true); unusedDB->Close(true); aParent->UpdateSummaryTotals(true); } else { PR_LOG(MailDirLog, PR_LOG_ALWAYS, ("CreateFolder - failed creating db for new folder\n")); path->Remove(true); // recursive rv = NS_MSG_CANT_CREATE_FOLDER; } } child.swap(*aResult); return rv; }