diff --git a/mailnews/base/src/Makefile.in b/mailnews/base/src/Makefile.in index 1a8ccb56282..198c3534e94 100644 --- a/mailnews/base/src/Makefile.in +++ b/mailnews/base/src/Makefile.in @@ -37,6 +37,7 @@ CPPSRCS = \ nsMsgGroupRecord.cpp \ nsMsgRFC822Parser.cpp \ nsMsgFolder.cpp \ + nsMsgRDFFolder.cpp \ $(NULL) include $(topsrcdir)/config/config.mk diff --git a/mailnews/base/src/makefile.win b/mailnews/base/src/makefile.win index 38fd2ed0a36..4438ef7c871 100644 --- a/mailnews/base/src/makefile.win +++ b/mailnews/base/src/makefile.win @@ -30,8 +30,9 @@ CPPSRCS= nsMsgRFC822Parser.cpp \ nsUInt32Array.cpp\ nsMsgKeyArray.cpp\ nsMsgFolder.cpp \ - nsMsgPtrArray.cpp \ + nsMsgPtrArray.cpp \ nsMsgGroupRecord.cpp \ + nsMsgRDFFolder.cpp \ $(NULL) CPP_OBJS= .\$(OBJDIR)\nsMsgRFC822Parser.obj \ @@ -40,6 +41,7 @@ CPP_OBJS= .\$(OBJDIR)\nsMsgRFC822Parser.obj \ .\$(OBJDIR)\nsMsgFolder.obj \ .\$(OBJDIR)\nsMsgPtrArray.obj \ .\$(OBJDIR)\nsMsgGroupRecord.obj \ + .\$(OBJDIR)\nsMsgRDFFolder.obj \ $(NULL) diff --git a/mailnews/base/src/nsMsgFolder.cpp b/mailnews/base/src/nsMsgFolder.cpp index 90347694315..a3ee99ad8c1 100644 --- a/mailnews/base/src/nsMsgFolder.cpp +++ b/mailnews/base/src/nsMsgFolder.cpp @@ -21,18 +21,16 @@ #include "nsIRDFNode.h" #include "nsIRDFResourceFactory.h" #include "nsMsgFolderFlags.h" +#include "prprf.h" /* use these macros to define a class IID for our component. */ static NS_DEFINE_IID(kIMsgFolderIID, NS_IMSGFOLDER_IID); +static NS_DEFINE_IID(kIMsgMailFolderIID, NS_IMSGMAILFOLDER_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); -static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID); -static NS_DEFINE_IID(kIRDFNodeIID, NS_IRDFNODE_IID); -static NS_DEFINE_IID(kIRDFResourceFactoryIID, NS_IRDFRESOURCEFACTORY_IID); -nsMsgFolder::nsMsgFolder(const char* uri) +nsMsgFolder::nsMsgFolder() { NS_INIT_REFCNT(); - mURI = PL_strdup(uri); mFlags = 0; mName = nsnull; @@ -94,10 +92,6 @@ nsMsgFolder::QueryInterface(REFNSIID iid, void** result) iid.Equals(kISupportsIID)) { *result = NS_STATIC_CAST(nsIMsgFolder*, this); } - else if(iid.Equals(kIRDFResourceIID) || - iid.Equals(kIRDFNodeIID)) { - *result = NS_STATIC_CAST(nsIRDFResource*, this); - } if(*result != nsnull) { @@ -108,60 +102,25 @@ nsMsgFolder::QueryInterface(REFNSIID iid, void** result) return NS_NOINTERFACE; } -NS_IMETHODIMP nsMsgFolder::EqualsNode(nsIRDFNode* node, PRBool* result) const +NS_IMETHODIMP nsMsgFolder::GetType(FolderType *type) { - nsresult rv; - nsIRDFResource* resource; - if (NS_SUCCEEDED(node->QueryInterface(kIRDFResourceIID, (void**) &resource))) - { - rv = EqualsResource(resource, result); - NS_RELEASE(resource); - } - else { - *result = PR_FALSE; - rv = NS_OK;\ - } - return rv; -} - -NS_IMETHODIMP nsMsgFolder::GetValue(const char* *uri) const -{ - if (!uri) + if(!type) return NS_ERROR_NULL_POINTER; - *uri = mURI; + + *type = FOLDER_UNKNOWN; + return NS_OK; } -NS_IMETHODIMP nsMsgFolder::EqualsResource(const nsIRDFResource* resource, PRBool* result) const +NS_IMETHODIMP nsMsgFolder::BuildFolderURL(char **url) { - if (!resource || !result) return NS_ERROR_NULL_POINTER; - - const char *uri; - if(NS_SUCCEEDED(resource->GetValue(&uri))) + if(*url) { - return EqualsString(uri, result); - } - - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP nsMsgFolder::EqualsString(const char* uri, PRBool* result) const -{ - if (!uri || !result) - return NS_ERROR_NULL_POINTER; - *result = (PL_strcmp(uri, mURI) == 0); - return NS_OK; -} - -NS_IMETHODIMP nsMsgFolder::GetType(FolderType *type) -{ - if(type) - { - *type = FOLDER_UNKNOWN; + *url = NULL; return NS_OK; } else - return NS_ERROR_NULL_POINTER; + return NS_ERROR_NULL_POINTER; } #ifdef HAVE_DB @@ -1181,7 +1140,7 @@ NS_IMETHODIMP nsMsgFolder::GetExpansionArray(const nsISupportsArray *expansionAr return NS_OK; } -#ifdef HAVE_FLAGS +#ifdef HAVE_PANE NS_IMETHODIMP nsMsgFolder::SetFlagInAllFolderPanes(PRUInt32 which) { @@ -1272,12 +1231,41 @@ NS_IMETHODIMP nsMsgFolder::GetAllowsPosting(PRBool *allowsPosting) return NS_OK; } -#ifdef HAVE_FLAGS NS_IMETHODIMP nsMsgFolder::DisplayRecipients(PRBool *displayRecipients) { + nsresult rv; -} + *displayRecipients = PR_FALSE; + + if (mFlags & MSG_FOLDER_FLAG_SENTMAIL && !(mFlags & MSG_FOLDER_FLAG_INBOX)) + *displayRecipients = PR_TRUE; + else if (mFlags & MSG_FOLDER_FLAG_QUEUE) + *displayRecipients = PR_TRUE; + else + { + // Only mail folders can be FCC folders + if (mFlags & MSG_FOLDER_FLAG_MAIL || mFlags & MSG_FOLDER_FLAG_IMAPBOX) + { + // There's one FCC folder for sent mail, and one for sent news + nsIMsgFolder *fccFolders[2]; + int numFccFolders = 0; +#ifdef HAVE_MASTER + m_master->GetFolderTree()->GetFoldersWithFlag (MSG_FOLDER_FLAG_SENTMAIL, fccFolders, 2, &numFccFolders); #endif + for (int i = 0; i < numFccFolders; i++) + { + PRBool isParent; + if(NS_SUCCEEDED(rv = fccFolders[i]->IsParentOf(this, PR_TRUE, &isParent))) + { + if (isParent) + *displayRecipients = PR_TRUE; + } + NS_RELEASE(fccFolders[i]); + } + } + } + return NS_OK; +} #ifdef HAVE_SEMAPHORE NS_IMETHODIMP nsMsgFolder::AcquireSemaphore (void *semHolder) @@ -1415,59 +1403,684 @@ NS_IMETHODIMP nsMsgFolder::GetHostName(char **hostName) } -/** - * This class creates resources for message folder URIs. It should be - * registered for the "mailnewsfolder:" prefix. - */ -class nsMsgFolderResourceFactoryImpl : public nsIRDFResourceFactory +nsMsgMailFolder::nsMsgMailFolder() { -public: - nsMsgFolderResourceFactoryImpl(void); - virtual ~nsMsgFolderResourceFactoryImpl(void); - - NS_DECL_ISUPPORTS - - NS_IMETHOD CreateResource(const char* aURI, nsIRDFResource** aResult); -}; - -nsMsgFolderResourceFactoryImpl::nsMsgFolderResourceFactoryImpl(void) -{ - NS_INIT_REFCNT(); + mHaveReadNameFromDB = PR_FALSE; + mPathName = nsnull; } -nsMsgFolderResourceFactoryImpl::~nsMsgFolderResourceFactoryImpl(void) +nsMsgMailFolder::~nsMsgMailFolder() { + } -NS_IMPL_ISUPPORTS(nsMsgFolderResourceFactoryImpl, kIRDFResourceFactoryIID); +NS_IMPL_ADDREF(nsMsgMailFolder) +NS_IMPL_RELEASE(nsMsgMailFolder) NS_IMETHODIMP -nsMsgFolderResourceFactoryImpl::CreateResource(const char* aURI, nsIRDFResource** aResult) +nsMsgMailFolder::QueryInterface(REFNSIID iid, void** result) { - if (! aResult) - return NS_ERROR_NULL_POINTER; + if (! result) + return NS_ERROR_NULL_POINTER; - nsMsgFolder *folder = new nsMsgFolder(aURI); - if (! folder) - return NS_ERROR_OUT_OF_MEMORY; + *result = nsnull; + if(iid.Equals(kIMsgFolderIID) || + iid.Equals(kISupportsIID)) { + *result = NS_STATIC_CAST(nsIMsgFolder*, this); + } + else if(iid.Equals(kIMsgMailFolderIID)) + { + *result = NS_STATIC_CAST(nsIMsgMailFolder*, this); + } - folder->QueryInterface(kIRDFResourceIID, (void**)aResult); - return NS_OK; + if(*result != nsnull) + { + AddRef(); + return NS_OK; + } + + return NS_NOINTERFACE; +} + +NS_IMETHODIMP nsMsgMailFolder::GetType(FolderType *type) +{ + if(!type) + return NS_ERROR_NULL_POINTER; + + *type = FOLDER_MAIL; + + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::BuildFolderURL(char **url) +{ + const char *urlScheme = "mailbox:"; + + if(!url) + return NS_ERROR_NULL_POINTER; + + *url = PR_smprintf("%s%s", urlScheme, mPathName); + return NS_OK; + +} + +NS_IMETHODIMP nsMsgMailFolder::CreateSubfolder(const char *leafNameFromUser, nsIMsgFolder **outFolder, PRInt32 *outPos) +{ +#ifdef HAVE_PORT + MsgERR status = 0; + *ppOutFolder = NULL; + *pOutPos = 0; + XP_StatStruct stat; + + + // Only create a .sbd pathname if we're not in the root folder. The root folder + // e.g. c:\netscape\mail has to behave differently than subfolders. + if (m_depth > 1) + { + // Look around in our directory to get a subdirectory, creating it + // if necessary + XP_BZERO (&stat, sizeof(stat)); + if (0 == XP_Stat (m_pathName, &stat, xpMailSubdirectory)) + { + if (!S_ISDIR(stat.st_mode)) + status = MK_COULD_NOT_CREATE_DIRECTORY; // a file .sbd already exists + } + else { + status = XP_MakeDirectory (m_pathName, xpMailSubdirectory); + if (status == -1) + status = MK_COULD_NOT_CREATE_DIRECTORY; + } + } + + char *leafNameForDisk = CreatePlatformLeafNameForDisk(leafNameFromUser,m_master, this); + if (!leafNameForDisk) + status = MK_OUT_OF_MEMORY; + + if (0 == status) //ok so far + { + // Now that we have a suitable parent directory created/identified, + // we can create the new mail folder inside the parent dir. Again, + + char *newFolderPath = (char*) XP_ALLOC(XP_STRLEN(m_pathName) + XP_STRLEN(leafNameForDisk) + XP_STRLEN(".sbd/") + 1); + if (newFolderPath) + { + XP_STRCPY (newFolderPath, m_pathName); + if (m_depth == 1) + XP_STRCAT (newFolderPath, "/"); + else + XP_STRCAT (newFolderPath, ".sbd/"); + XP_STRCAT (newFolderPath, leafNameForDisk); + + if (0 != XP_Stat (newFolderPath, &stat, xpMailFolder)) + { + XP_File file = XP_FileOpen(newFolderPath, xpMailFolder, XP_FILE_WRITE_BIN); + if (file) + { + // Create an empty database for this mail folder, set its name from the user + MailDB *unusedDb = NULL; + MailDB::Open(newFolderPath, TRUE, &unusedDb, TRUE); + if (unusedDb) + { + //need to set the folder name + + MSG_FolderInfoMail *newFolder = BuildFolderTree (newFolderPath, m_depth + 1, m_subFolders, m_master); + if (newFolder) + { + // so we don't show ??? in totals + newFolder->SummaryChanged(); + *ppOutFolder = newFolder; + *pOutPos = m_subFolders->FindIndex (0, newFolder); + } + else + status = MK_OUT_OF_MEMORY; + unusedDb->SetFolderInfoValid(newFolderPath,0,0); + unusedDb->Close(); + } + else + { + XP_FileClose(file); + file = NULL; + XP_FileRemove (newFolderPath, xpMailFolder); + status = MK_MSG_CANT_CREATE_FOLDER; + } + if (file) + { + XP_FileClose(file); + file = NULL; + } + } + else + status = MK_MSG_CANT_CREATE_FOLDER; + } + else + status = MK_MSG_FOLDER_ALREADY_EXISTS; + FREEIF(newFolderPath); + } + else + status = MK_OUT_OF_MEMORY; + } + FREEIF(leafNameForDisk); + return status; +#endif //HAVE_PORT + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::RemoveSubFolder (const nsIMsgFolder *which) +{ + // Let the base class do list management + nsMsgFolder::RemoveSubFolder (which); + + // Derived class is responsible for managing the subdirectory +#ifdef HAVE_PORT + if (0 == m_subFolders->GetSize()) + XP_RemoveDirectory (m_pathName, xpMailSubdirectory); +#endif + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::Delete () +{ +#ifdef HAVE_PORT + MessageDB *db; + // remove the summary file + MsgERR status = CloseDatabase (m_pathName, &db); + if (0 == status) + { + if (db != NULL) + db->Close(); // decrement ref count, so it will leave cache + XP_FileRemove (m_pathName, xpMailFolderSummary); + } + + if ((0 == status) && (GetType() == FOLDER_MAIL)) + { + // remove the mail folder file + status = XP_FileRemove (m_pathName, xpMailFolder); + + // if the delete seems to have failed, but the file doesn't + // exist, that's not really an error condition, is it now? + if (status) + { + XP_StatStruct fileStat; + if (0 == XP_Stat(m_pathName, &fileStat, xpMailFolder)) + status = 0; + } + } + + + if (0 != status) + status = MK_UNABLE_TO_DELETE_FILE; + return status; +#endif + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::Rename (const char *newName) +{ +#ifdef HAVE_PORT + // change the leaf name (stored separately) + MsgERR status = MSG_FolderInfo::Rename (newUserLeafName); + if (status == 0) + { + char *baseDir = XP_STRDUP(m_pathName); + if (baseDir) + { + char *base_slash = XP_STRRCHR (baseDir, '/'); + if (base_slash) + *base_slash = '\0'; + } + + char *leafNameForDisk = CreatePlatformLeafNameForDisk(newUserLeafName,m_master, baseDir); + if (!leafNameForDisk) + status = MK_OUT_OF_MEMORY; + + if (0 == status) + { + // calculate the new path name + char *newPath = (char*) XP_ALLOC(XP_STRLEN(m_pathName) + XP_STRLEN(leafNameForDisk) + 1); + XP_STRCPY (newPath, m_pathName); + char *slash = XP_STRRCHR (newPath, '/'); + if (slash) + XP_STRCPY (slash + 1, leafNameForDisk); + + // rename the mail summary file, if there is one + MessageDB *db = NULL; + status = CloseDatabase (m_pathName, &db); + + XP_StatStruct fileStat; + if (!XP_Stat(m_pathName, &fileStat, xpMailFolderSummary)) + status = XP_FileRename(m_pathName, xpMailFolderSummary, newPath, xpMailFolderSummary); + if (0 == status) + { + if (db) + { + if (ReopenDatabase (db, newPath) == 0) + { + //need to set mailbox name + } + } + else + { + MailDB *mailDb = NULL; + MailDB::Open(newPath, TRUE, &mailDb, TRUE); + if (mailDb) + { + //need to set mailbox name + mailDb->Close(); + } + } + } + + // rename the mail folder file, if its local + if ((status == 0) && (GetType() == FOLDER_MAIL)) + status = XP_FileRename (m_pathName, xpMailFolder, newPath, xpMailFolder); + + if (status == 0) + { + // rename the subdirectory if there is one + if (m_subFolders->GetSize() > 0) + status = XP_FileRename (m_pathName, xpMailSubdirectory, newPath, xpMailSubdirectory); + + // tell all our children about the new pathname + if (status == 0) + { + int startingAt = XP_STRLEN (newPath) - XP_STRLEN (leafNameForDisk) + 1; // add one for trailing '/' + status = PropagateRename (leafNameForDisk, startingAt); + } + } + } + FREEIF(baseDir); + } + return status; +#endif + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::Adopt(const nsIMsgFolder *srcFolder, PRInt32 *outPos) +{ +#ifdef HAVE_PORT + MsgERR err = eSUCCESS; + XP_ASSERT (srcFolder->GetType() == GetType()); // we can only adopt the same type of folder + MSG_FolderInfoMail *mailFolder = (MSG_FolderInfoMail*) srcFolder; + + if (srcFolder == this) + return MK_MSG_CANT_COPY_TO_SAME_FOLDER; + + if (ContainsChildNamed(mailFolder->GetName())) + return MK_MSG_FOLDER_ALREADY_EXISTS; + + // If we aren't already a directory, create the directory and set the flag bits + if (0 == m_subFolders->GetSize()) + { + XP_Dir dir = XP_OpenDir (m_pathName, xpMailSubdirectory); + if (dir) + XP_CloseDir (dir); + else + { + XP_MakeDirectory (m_pathName, xpMailSubdirectory); + dir = XP_OpenDir (m_pathName, xpMailSubdirectory); + if (dir) + XP_CloseDir (dir); + else + err = MK_COULD_NOT_CREATE_DIRECTORY; + } + if (eSUCCESS == err) + { + m_flags |= MSG_FOLDER_FLAG_DIRECTORY; + m_flags |= MSG_FOLDER_FLAG_ELIDED; + } + } + + // Recurse the tree to adopt srcFolder's children + err = mailFolder->PropagateAdopt (m_pathName, m_depth); + + // Add the folder to our tree in the right sorted position + if (eSUCCESS == err) + { + XP_ASSERT(m_subFolders->FindIndex(0, srcFolder) == -1); + *pOutPos = m_subFolders->Add (srcFolder); + } + + return err; +#endif + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::GetName(char** name) +{ + if(!name) + return NS_ERROR_NULL_POINTER; + + if (!mHaveReadNameFromDB) + { + if (mDepth == 1) + { + SetName("Local Mail"); + mHaveReadNameFromDB = TRUE; + } + else + { + //Need to read the name from the database + } + } + *name = mName; + + + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::GetPrettyName(char ** prettyName) +{ + if (mDepth == 1) { + // Depth == 1 means we are on the mail server level + // override the name here to say "Local Mail" + FolderType type; + GetType(&type); + if (type == FOLDER_MAIL) + *prettyName = PL_strdup("Local Mail"); + else + return nsMsgFolder::GetPrettyName(prettyName); + } + else + return nsMsgFolder::GetPrettyName(prettyName); + + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::GenerateUniqueSubfolderName(const char *prefix, + const nsIMsgFolder *otherFolder, + char** name) +{ + if(!name) + return NS_ERROR_NULL_POINTER; + + /* only try 256 times */ + for (int count = 0; (count < 256); count++) + { + PRInt32 prefixSize = PL_strlen(prefix); + + //allocate string big enough for prefix, 256, and '\0' + char *uniqueName = (char*)PR_MALLOC(prefixSize + 4); + PR_snprintf(uniqueName, prefixSize + 4, "%s%d",prefix,count); + PRBool containsChild; + PRBool otherContainsChild = PR_FALSE; + + ContainsChildNamed(uniqueName, &containsChild); + if(otherFolder) + { + ((nsIMsgFolder*)otherFolder)->ContainsChildNamed(uniqueName, &otherContainsChild); + } + + if (!containsChild && !otherContainsChild) + { + *name = uniqueName; + return NS_OK; + } + else + PR_FREEIF(uniqueName); + } + *name = nsnull; + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::UpdateSummaryTotals() +{ + //We need to read this info from the database + + // If we asked, but didn't get any, stop asking + if (mNumUnreadMessages == -1) + mNumUnreadMessages = -2; + + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::GetExpungedBytesCount(PRInt32 *count) +{ + if(!count) + return NS_ERROR_NULL_POINTER; + + *count = mExpungedBytes; + + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::GetDeletable (PRBool *deletable) +{ + if(!deletable) + return NS_ERROR_NULL_POINTER; + + // These are specified in the "Mail/News Windows" UI spec + + if (mFlags & MSG_FOLDER_FLAG_TRASH) + { + PRBool moveToTrash; + GetDeleteIsMoveToTrash(&moveToTrash); + if(moveToTrash) + *deletable = PR_TRUE; // allow delete of trash if we don't use trash + } + else if (mDepth == 1) + *deletable = PR_FALSE; + else if (mFlags & MSG_FOLDER_FLAG_INBOX || + mFlags & MSG_FOLDER_FLAG_DRAFTS || + mFlags & MSG_FOLDER_FLAG_TRASH || + mFlags & MSG_FOLDER_FLAG_TEMPLATES) + *deletable = PR_FALSE; + else *deletable = PR_TRUE; + + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::GetCanCreateChildren (PRBool *canCreateChildren) +{ + if(!canCreateChildren) + return NS_ERROR_NULL_POINTER; + + *canCreateChildren = PR_TRUE; + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::GetCanBeRenamed (PRBool *canBeRenamed) +{ + if(!canBeRenamed) + return NS_ERROR_NULL_POINTER; + + // The root mail folder can't be renamed + if (mDepth < 2) + *canBeRenamed = PR_FALSE; + + // Here's a weird case necessitated because we don't have a separate + // preference for any folder name except the FCC folder (Sent). Others + // are known by name, and as such, can't be renamed. I guess. + else if (mFlags & MSG_FOLDER_FLAG_TRASH || + mFlags & MSG_FOLDER_FLAG_DRAFTS || + mFlags & MSG_FOLDER_FLAG_QUEUE || + mFlags & MSG_FOLDER_FLAG_INBOX || + mFlags & MSG_FOLDER_FLAG_TEMPLATES) + *canBeRenamed = PR_FALSE; + else + *canBeRenamed = PR_TRUE; + + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::GetRequiresCleanup(PRBool *requiresCleanup) +{ +#ifdef HAVE_PORT + if (m_expungedBytes > 0) + { + int32 purgeThreshhold = m_master->GetPrefs()->GetPurgeThreshhold(); + XP_Bool purgePrompt = m_master->GetPrefs()->GetPurgeThreshholdEnabled();; + return (purgePrompt && m_expungedBytes / 1000L > purgeThreshhold); + } + return FALSE; +#endif + return NS_OK; +} + + + +NS_IMETHODIMP nsMsgMailFolder::GetRelativePathName (char **pathName) +{ + if(!pathName) + return NS_ERROR_NULL_POINTER; + *pathName = mPathName; + return NS_OK; +} + + +NS_IMETHODIMP nsMsgMailFolder::GetSizeOnDisk(PRInt32 size) +{ +#ifdef HAVE_PORT + int32 ret = 0; + XP_StatStruct st; + + if (!XP_Stat(GetPathname(), &st, xpMailFolder)) + ret += st.st_size; + + if (!XP_Stat(GetPathname(), &st, xpMailFolderSummary)) + ret += st.st_size; + + return ret; +#endif + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::GetUserName(char** userName) +{ +#ifdef HAVE_PORT + return NET_GetPopUsername(); +#endif + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::GetHostName(char** hostName) +{ +#ifdef HAVE_PORT + XP_Bool serverIsIMAP = m_master->GetPrefs()->GetMailServerIsIMAP4(); + if (serverIsIMAP) + { + MSG_IMAPHost *defaultIMAPHost = m_master->GetIMAPHostTable()->GetDefaultHost(); + return (defaultIMAPHost) ? defaultIMAPHost->GetHostName() : 0; + } + else + return m_master->GetPrefs()->GetPopHost(); +#endif + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::UserNeedsToAuthenticateForFolder(PRBool displayOnly, PRBool *authenticate) +{ +#ifdef HAVE_PORT + XP_Bool ret = FALSE; + if (m_master->IsCachePasswordProtected() && !m_master->IsUserAuthenticated() && !m_master->AreLocalFoldersAuthenticated()) + { + char *savedPassword = GetRememberedPassword(); + if (savedPassword && XP_STRLEN(savedPassword)) + ret = TRUE; + FREEIF(savedPassword); + } + return ret; +#endif + + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::RememberPassword(const char *password) +{ +#ifdef HAVE_DB + MailDB *mailDb = NULL; + MailDB::Open(m_pathName, TRUE, &mailDb); + if (mailDb) + { + mailDb->SetCachedPassword(password); + mailDb->Close(); + } +#endif + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::GetRememberedPassword(char ** password) +{ +#ifdef HAVE_PORT + XP_Bool serverIsIMAP = m_master->GetPrefs()->GetMailServerIsIMAP4(); + char *savedPassword = NULL; + if (serverIsIMAP) + { + MSG_IMAPHost *defaultIMAPHost = m_master->GetIMAPHostTable()->GetDefaultHost(); + if (defaultIMAPHost) + { + MSG_FolderInfo *hostFolderInfo = defaultIMAPHost->GetHostFolderInfo(); + MSG_FolderInfo *defaultHostIMAPInbox = NULL; + if (hostFolderInfo->GetFoldersWithFlag(MSG_FOLDER_FLAG_INBOX, &defaultHostIMAPInbox, 1) == 1 + && defaultHostIMAPInbox != NULL) + { + savedPassword = defaultHostIMAPInbox->GetRememberedPassword(); + } + } + } + else + { + MSG_FolderInfo *offlineInbox = NULL; + if (m_flags & MSG_FOLDER_FLAG_INBOX) + { + char *retPassword = NULL; + MailDB *mailDb = NULL; + MailDB::Open(m_pathName, FALSE, &mailDb, FALSE); + if (mailDb) + { + mailDb->GetCachedPassword(cachedPassword); + retPassword = XP_STRDUP(cachedPassword); + mailDb->Close(); + + } + return retPassword; + } + if (m_master->GetLocalMailFolderTree()->GetFoldersWithFlag(MSG_FOLDER_FLAG_INBOX, &offlineInbox, 1) && offlineInbox) + savedPassword = offlineInbox->GetRememberedPassword(); + } + return savedPassword; +#endif + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::GetPathName(char * *aPathName) +{ + if(!aPathName) + return NS_ERROR_NULL_POINTER; + + if(mPathName) + *aPathName = PL_strdup(mPathName); + else + *aPathName = nsnull; + + return NS_OK; +} + +NS_IMETHODIMP nsMsgMailFolder::SetPathName(char * aPathName) +{ + if(mPathName) + PR_FREEIF(mPathName); + + if(aPathName) + mPathName = PL_strdup(aPathName); + else + mPathName = nsnull; + + return NS_OK; } nsresult -NS_NewRDFMsgFolderResourceFactory(nsIRDFResourceFactory** aResult) +NS_NewMsgMailFolder(nsIMsgFolder** aResult) { if (! aResult) return NS_ERROR_NULL_POINTER; - nsMsgFolderResourceFactoryImpl* factory = - new nsMsgFolderResourceFactoryImpl(); + nsMsgMailFolder* folder = + new nsMsgMailFolder(); - if (! factory) + if (! folder) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(factory); - *aResult = factory; + NS_ADDREF(folder); + *aResult = folder; return NS_OK; -} +} \ No newline at end of file diff --git a/mailnews/base/src/nsMsgFolder.h b/mailnews/base/src/nsMsgFolder.h index 04ca7b017c4..e07a61c8d9f 100644 --- a/mailnews/base/src/nsMsgFolder.h +++ b/mailnews/base/src/nsMsgFolder.h @@ -35,24 +35,13 @@ class nsMsgFolder: public nsIMsgFolder { -private: - char * mURI; public: - nsMsgFolder(const char* uri); + nsMsgFolder(); virtual ~nsMsgFolder(); /* this macro defines QueryInterface, AddRef and Release for this class */ NS_DECL_ISUPPORTS - //nsIRDFNode - NS_IMETHOD EqualsNode(nsIRDFNode* node, PRBool* result) const; - - //nsIRDFResource - NS_IMETHOD GetValue(const char* *uri) const; - NS_IMETHOD EqualsResource(const nsIRDFResource* resource, PRBool* result) const; - NS_IMETHOD EqualsString(const char* uri, PRBool* result) const; - - NS_IMETHOD GetType(FolderType *type); // Gets the URL that represents the given message. Returns a newly @@ -108,6 +97,9 @@ public: NS_IMETHOD GetName(char **name); NS_IMETHOD SetName(const char *name); NS_IMETHOD GetPrettiestName(char **name); + + NS_IMETHOD BuildFolderURL(char ** url); + NS_IMETHOD GetNameFromPathName(const char *pathName, char ** name); NS_IMETHOD HasSubFolders(PRBool *hasSubFolders); NS_IMETHOD GetNumSubFolders(PRInt32 *numSubFolders); @@ -226,9 +218,7 @@ public: NS_IMETHOD GetKnowsSearchNntpExtension(PRBool *knowsExtension); NS_IMETHOD GetAllowsPosting(PRBool *allowsPosting); -#ifdef HAVE_FLAGS NS_IMETHOD DisplayRecipients(PRBool *displayRecipients); -#endif #ifdef HAVE_SEMAPHORE MsgERR AcquireSemaphore (void *semHolder); @@ -306,4 +296,78 @@ public: }; +class nsMsgMailFolder : public nsMsgFolder, public nsIMsgMailFolder +{ +public: + nsMsgMailFolder(); + ~nsMsgMailFolder(); + + NS_DECL_ISUPPORTS + + NS_IMETHOD GetType(FolderType *type); + +#ifdef HAVE_DB + virtual MsgERR BeginCopyingMessages (MSG_FolderInfo *dstFolder, + MessageDB *sourceDB, + IDArray *srcArray, + MSG_UrlQueue *urlQueue, + int32 srcCount, + MessageCopyInfo *copyInfo); + + + virtual int FinishCopyingMessages (MWContext *context, + MSG_FolderInfo * srcFolder, + MSG_FolderInfo *dstFolder, + MessageDB *sourceDB, + IDArray **ppSrcArray, + int32 srcCount, + msg_move_state *state); +#endif + + NS_IMETHOD CreateSubfolder(const char *leafNameFromUser, nsIMsgFolder **outFolder, PRInt32 *outPos); + + NS_IMETHOD RemoveSubFolder (const nsIMsgFolder *which); + NS_IMETHOD Delete (); + NS_IMETHOD Rename (const char *newName); + NS_IMETHOD Adopt(const nsIMsgFolder *srcFolder, PRInt32 *outPos); + + // this override pulls the value from the db + NS_IMETHOD GetName(char** name); // Name of this folder (as presented to user). + NS_IMETHOD GetPrettyName(char ** prettyName); // Override of the base, for top-level mail folder + + NS_IMETHOD BuildFolderURL(char **url); + + NS_IMETHOD GenerateUniqueSubfolderName(const char *prefix, const nsIMsgFolder *otherFolder, char** name); + + NS_IMETHOD UpdateSummaryTotals() ; + + NS_IMETHOD GetExpungedBytesCount(PRInt32 *count); + NS_IMETHOD GetDeletable (PRBool *deletable); + NS_IMETHOD GetCanCreateChildren (PRBool *canCreateChildren) ; + NS_IMETHOD GetCanBeRenamed (PRBool *canBeRenamed); + NS_IMETHOD GetRequiresCleanup(PRBool *requiresCleanup); + + + NS_IMETHOD GetRelativePathName (char **pathName); + + + NS_IMETHOD GetSizeOnDisk(PRInt32 size); + + NS_IMETHOD GetUserName(char** userName); + NS_IMETHOD GetHostName(char** hostName); + NS_IMETHOD UserNeedsToAuthenticateForFolder(PRBool displayOnly, PRBool *authenticate); + NS_IMETHOD RememberPassword(const char *password); + NS_IMETHOD GetRememberedPassword(char ** password); + + //nsIMsgMailFolder + NS_IMETHOD GetPathName(char * *aPathName); + NS_IMETHOD SetPathName(char * aPathName); + +protected: + char* mPathName; + PRInt32 mExpungedBytes; + PRBool mHaveReadNameFromDB; + PRBool mGettingMail; +}; + #endif diff --git a/mailnews/base/src/nsMsgRDFFolder.cpp b/mailnews/base/src/nsMsgRDFFolder.cpp new file mode 100644 index 00000000000..fbbd6a5bf0b --- /dev/null +++ b/mailnews/base/src/nsMsgRDFFolder.cpp @@ -0,0 +1,198 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1999 Netscape Communications Corporation. All Rights + * Reserved. + */ + + +#include "nsMsgRDFFolder.h" +#include "nsIRDFResourceFactory.h" +#include "prmem.h" +#include "plstr.h" + + +static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID); +static NS_DEFINE_IID(kIRDFNodeIID, NS_IRDFNODE_IID); +static NS_DEFINE_IID(kIRDFResourceFactoryIID, NS_IRDFRESOURCEFACTORY_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kIMsgRDFFolderIID, NS_IMSGRDFFOLDER_IID); + +nsMsgRDFFolder::nsMsgRDFFolder(const char* uri) +{ + NS_INIT_REFCNT(); + mURI = PL_strdup(uri); + mFolder = nsnull; + +} + +nsMsgRDFFolder::~nsMsgRDFFolder() +{ + PR_FREEIF(mURI); + + if(mFolder) + NS_RELEASE(mFolder); + +} + +NS_IMPL_ADDREF(nsMsgRDFFolder) +NS_IMPL_RELEASE(nsMsgRDFFolder) + +NS_IMETHODIMP +nsMsgRDFFolder::QueryInterface(REFNSIID iid, void** result) +{ + if (! result) + return NS_ERROR_NULL_POINTER; + + *result = nsnull; + if(iid.Equals(kIRDFResourceIID) || + iid.Equals(kIRDFNodeIID) || + iid.Equals(kIMsgRDFFolderIID) || + iid.Equals(kISupportsIID)) { + *result = NS_STATIC_CAST(nsIMsgRDFFolder*, this); + } + + if(*result != nsnull) + { + AddRef(); + return NS_OK; + } + + return NS_NOINTERFACE; +} + +NS_IMETHODIMP nsMsgRDFFolder::EqualsNode(nsIRDFNode* node, PRBool* result) const +{ + nsresult rv; + nsIRDFResource* resource; + if (NS_SUCCEEDED(node->QueryInterface(kIRDFResourceIID, (void**) &resource))) + { + rv = EqualsResource(resource, result); + NS_RELEASE(resource); + } + else { + *result = PR_FALSE; + rv = NS_OK;\ + } + return rv; +} + +NS_IMETHODIMP nsMsgRDFFolder::GetValue(const char* *uri) const +{ + if (!uri) + return NS_ERROR_NULL_POINTER; + *uri = mURI; + return NS_OK; +} + +NS_IMETHODIMP nsMsgRDFFolder::EqualsResource(const nsIRDFResource* resource, PRBool* result) const +{ + if (!resource || !result) return NS_ERROR_NULL_POINTER; + + const char *uri; + if(NS_SUCCEEDED(resource->GetValue(&uri))) + { + return EqualsString(uri, result); + } + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP nsMsgRDFFolder::EqualsString(const char* uri, PRBool* result) const +{ + if (!uri || !result) + return NS_ERROR_NULL_POINTER; + *result = (PL_strcmp(uri, mURI) == 0); + return NS_OK; +} + +NS_IMETHODIMP nsMsgRDFFolder::GetFolder(nsIMsgFolder * *aFolder) +{ + if(!aFolder) + return NS_ERROR_NULL_POINTER; + + NS_ADDREF(mFolder); + *aFolder = mFolder; + return NS_OK; +} + +NS_IMETHODIMP nsMsgRDFFolder::SetFolder(nsIMsgFolder * aFolder) +{ + if(aFolder) + { + NS_ADDREF(aFolder); + if(mFolder) + NS_RELEASE(mFolder); + mFolder = aFolder; + } + return NS_OK; +} + +/** + * This class creates resources for message folder URIs. It should be + * registered for the "mailnewsfolder:" prefix. + */ +class nsMsgFolderResourceFactoryImpl : public nsIRDFResourceFactory +{ +public: + nsMsgFolderResourceFactoryImpl(void); + virtual ~nsMsgFolderResourceFactoryImpl(void); + + NS_DECL_ISUPPORTS + + NS_IMETHOD CreateResource(const char* aURI, nsIRDFResource** aResult); +}; + +nsMsgFolderResourceFactoryImpl::nsMsgFolderResourceFactoryImpl(void) +{ + NS_INIT_REFCNT(); +} + +nsMsgFolderResourceFactoryImpl::~nsMsgFolderResourceFactoryImpl(void) +{ +} + +NS_IMPL_ISUPPORTS(nsMsgFolderResourceFactoryImpl, kIRDFResourceFactoryIID); + +NS_IMETHODIMP +nsMsgFolderResourceFactoryImpl::CreateResource(const char* aURI, nsIRDFResource** aResult) +{ + if (! aResult) + return NS_ERROR_NULL_POINTER; + + nsMsgRDFFolder *folder = new nsMsgRDFFolder(aURI); + if (! folder) + return NS_ERROR_OUT_OF_MEMORY; + + folder->QueryInterface(kIRDFResourceIID, (void**)aResult); + return NS_OK; +} + +nsresult +NS_NewRDFMsgFolderResourceFactory(nsIRDFResourceFactory** aResult) +{ + if (! aResult) + return NS_ERROR_NULL_POINTER; + + nsMsgFolderResourceFactoryImpl* factory = + new nsMsgFolderResourceFactoryImpl(); + + if (! factory) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(factory); + *aResult = factory; + return NS_OK; +} + diff --git a/mailnews/base/src/nsMsgRDFFolder.h b/mailnews/base/src/nsMsgRDFFolder.h new file mode 100644 index 00000000000..2e6dd42e1f3 --- /dev/null +++ b/mailnews/base/src/nsMsgRDFFolder.h @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1999 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "nsIMsgRDFFolder.h" + +class nsMsgRDFFolder : public nsIMsgRDFFolder +{ +private: + char * mURI; + nsIMsgFolder *mFolder; +public: + nsMsgRDFFolder(const char* uri); + virtual ~nsMsgRDFFolder(); + + /* this macro defines QueryInterface, AddRef and Release for this class */ + NS_DECL_ISUPPORTS + + //nsIRDFNode + NS_IMETHOD EqualsNode(nsIRDFNode* node, PRBool* result) const; + + //nsIRDFResource + NS_IMETHOD GetValue(const char* *uri) const; + NS_IMETHOD EqualsResource(const nsIRDFResource* resource, PRBool* result) const; + NS_IMETHOD EqualsString(const char* uri, PRBool* result) const; + + //nsIMsgRDFFolder + NS_IMETHOD GetFolder(nsIMsgFolder * *aFolder); + NS_IMETHOD SetFolder(nsIMsgFolder * aFolder); + + +}; \ No newline at end of file