gecko-dev/mailnews/news/src/nsNntpIncomingServer.cpp
sspitzer%netscape.com 0e33b45466 comment out some dumps, printfs.
get unsubscribe working for news.
get ready to fix the problem of selecting a non-subscribable server and hitting subscribe.
2000-05-15 21:44:34 +00:00

840 lines
24 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Seth Spitzer <sspitzer@netscape.com>
* David Bienvenu <bienvenu@netscape.com>
*/
#include "nsNntpIncomingServer.h"
#include "nsXPIDLString.h"
#include "nsIPref.h"
#include "nsIFileLocator.h"
#include "nsFileLocations.h"
#include "nsIMsgNewsFolder.h"
#include "nsIFolder.h"
#include "nsIFileSpec.h"
#include "nsFileStream.h"
#include "nsCOMPtr.h"
#include "nsINntpService.h"
#include "nsINNTPProtocol.h"
#include "nsRDFCID.h"
#include "nsMsgNewsCID.h"
#include "nsNNTPProtocol.h"
#define NEW_NEWS_DIR_NAME "News"
#define PREF_MAIL_NEWSRC_ROOT "mail.newsrc_root"
// this platform specific junk is so the newsrc filenames we create
// will resemble the migrated newsrc filenames.
#if defined(XP_UNIX) || defined(XP_BEOS)
#define NEWSRC_FILE_PREFIX "newsrc-"
#define NEWSRC_FILE_SUFFIX ""
#else
#define NEWSRC_FILE_PREFIX ""
#define NEWSRC_FILE_SUFFIX ".rc"
#endif /* XP_UNIX || XP_BEOS */
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
static NS_DEFINE_IID(kIFileLocatorIID, NS_IFILELOCATOR_IID);
static NS_DEFINE_CID(kFileLocatorCID, NS_FILELOCATOR_CID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static NS_DEFINE_CID(kNntpServiceCID, NS_NNTPSERVICE_CID);
static NS_DEFINE_CID(kSubscribableServerCID, NS_SUBSCRIBABLESERVER_CID);
NS_IMPL_ADDREF_INHERITED(nsNntpIncomingServer, nsMsgIncomingServer)
NS_IMPL_RELEASE_INHERITED(nsNntpIncomingServer, nsMsgIncomingServer)
NS_INTERFACE_MAP_BEGIN(nsNntpIncomingServer)
NS_INTERFACE_MAP_ENTRY(nsINntpIncomingServer)
NS_INTERFACE_MAP_ENTRY(nsIUrlListener)
NS_INTERFACE_MAP_ENTRY(nsISubscribableServer)
NS_INTERFACE_MAP_END_INHERITING(nsMsgIncomingServer)
nsNntpIncomingServer::nsNntpIncomingServer()
{
NS_INIT_REFCNT();
mNewsrcHasChanged = PR_FALSE;
mGroupsEnumerator = nsnull;
NS_NewISupportsArray(getter_AddRefs(m_connectionCache));
mHostInfoLoaded = PR_FALSE;
mHostInfoHasChanged = PR_FALSE;
}
nsNntpIncomingServer::~nsNntpIncomingServer()
{
nsresult rv;
if (mGroupsEnumerator) {
delete mGroupsEnumerator;
mGroupsEnumerator = nsnull;
}
rv = CloseCachedConnections();
NS_ASSERTION(NS_SUCCEEDED(rv), "CloseCachedConnections failed");
}
NS_IMPL_SERVERPREF_BOOL(nsNntpIncomingServer, NotifyOn, "notify.on");
NS_IMPL_SERVERPREF_BOOL(nsNntpIncomingServer, MarkOldRead, "mark_old_read");
NS_IMPL_SERVERPREF_BOOL(nsNntpIncomingServer, Abbreviate, "abbreviate");
NS_IMPL_SERVERPREF_INT(nsNntpIncomingServer, MaxArticles, "max_articles");
NS_IMETHODIMP
nsNntpIncomingServer::GetNewsrcFilePath(nsIFileSpec **aNewsrcFilePath)
{
nsresult rv;
rv = GetFileValue("newsrc.file", aNewsrcFilePath);
if (NS_SUCCEEDED(rv) && *aNewsrcFilePath) return rv;
nsCOMPtr<nsIFileSpec> path;
rv = GetNewsrcRootPath(getter_AddRefs(path));
if (NS_FAILED(rv)) return rv;
nsXPIDLCString hostname;
rv = GetHostName(getter_Copies(hostname));
if (NS_FAILED(rv)) return rv;
// set the leaf name to "dummy", and then call MakeUnique with a suggested leaf name
rv = path->AppendRelativeUnixPath("dummy");
if (NS_FAILED(rv)) return rv;
nsCAutoString newsrcFileName = NEWSRC_FILE_PREFIX;
newsrcFileName.Append(hostname);
newsrcFileName.Append(NEWSRC_FILE_SUFFIX);
rv = path->MakeUniqueWithSuggestedName((const char *)newsrcFileName);
if (NS_FAILED(rv)) return rv;
rv = SetNewsrcFilePath(path);
if (NS_FAILED(rv)) return rv;
*aNewsrcFilePath = path;
NS_ADDREF(*aNewsrcFilePath);
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::SetNewsrcFilePath(nsIFileSpec *spec)
{
nsresult rv;
if (!spec) {
return NS_ERROR_FAILURE;
}
PRBool exists;
rv = spec->Exists(&exists);
if (!exists) {
rv = spec->Touch();
if (NS_FAILED(rv)) return rv;
}
return SetFileValue("newsrc.file", spec);
}
NS_IMETHODIMP
nsNntpIncomingServer::GetLocalStoreType(char **type)
{
NS_ENSURE_ARG_POINTER(type);
*type = nsCRT::strdup("news");
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::SetNewsrcRootPath(nsIFileSpec *aNewsrcRootPath)
{
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv);
if (NS_SUCCEEDED(rv) && prefs) {
rv = prefs->SetFilePref(PREF_MAIL_NEWSRC_ROOT,aNewsrcRootPath, PR_FALSE /* set default */);
return rv;
}
else {
return NS_ERROR_FAILURE;
}
}
NS_IMETHODIMP
nsNntpIncomingServer::GetNewsrcRootPath(nsIFileSpec **aNewsrcRootPath)
{
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = prefs->GetFilePref(PREF_MAIL_NEWSRC_ROOT, aNewsrcRootPath);
if (NS_SUCCEEDED(rv)) return rv;
NS_WITH_SERVICE(nsIFileLocator, locator, kFileLocatorCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = locator->GetFileLocation(nsSpecialFileSpec::App_NewsDirectory50, aNewsrcRootPath);
if (NS_FAILED(rv)) return rv;
rv = SetNewsrcRootPath(*aNewsrcRootPath);
return rv;
}
NS_IMETHODIMP
nsNntpIncomingServer::WriteNewsrcFile()
{
nsresult rv;
PRBool newsrcHasChanged;
rv = GetNewsrcHasChanged(&newsrcHasChanged);
if (NS_FAILED(rv)) return rv;
#ifdef DEBUG_NEWS
nsXPIDLCString hostname;
rv = GetHostName(getter_Copies(hostname));
if (NS_FAILED(rv)) return rv;
#endif /* DEBUG_NEWS */
if (newsrcHasChanged) {
#ifdef DEBUG_NEWS
printf("write newsrc file for %s\n", (const char *)hostname);
#endif
nsCOMPtr <nsIFileSpec> newsrcFile;
rv = GetNewsrcFilePath(getter_AddRefs(newsrcFile));
if (NS_FAILED(rv)) return rv;
nsFileSpec newsrcFileSpec;
rv = newsrcFile->GetFileSpec(&newsrcFileSpec);
if (NS_FAILED(rv)) return rv;
nsIOFileStream newsrcStream(newsrcFileSpec, (PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE));
nsCOMPtr<nsIEnumerator> subFolders;
nsCOMPtr<nsIFolder> rootFolder;
rv = GetRootFolder(getter_AddRefs(rootFolder));
if (NS_FAILED(rv)) return rv;
nsCOMPtr <nsIMsgNewsFolder> newsFolder = do_QueryInterface(rootFolder, &rv);
if (NS_FAILED(rv)) return rv;
nsXPIDLCString optionLines;
rv = newsFolder->GetOptionLines(getter_Copies(optionLines));
if (NS_SUCCEEDED(rv) && ((const char *)optionLines)) {
newsrcStream << (const char *)optionLines;
#ifdef DEBUG_NEWS
printf("option lines:\n%s",(const char *)optionLines);
#endif /* DEBUG_NEWS */
}
#ifdef DEBUG_NEWS
else {
printf("no option lines to write out\n");
}
#endif /* DEBUG_NEWS */
nsXPIDLCString unsubscribedLines;
rv = newsFolder->GetUnsubscribedNewsgroupLines(getter_Copies(unsubscribedLines));
if (NS_SUCCEEDED(rv) && ((const char *)unsubscribedLines)) {
newsrcStream << (const char *)unsubscribedLines;
#ifdef DEBUG_NEWS
printf("unsubscribedLines:\n%s",(const char *)unsubscribedLines);
#endif /* DEBUG_NEWS */
}
#ifdef DEBUG_NEWS
else {
printf("no unsubscribed lines to write out\n");
}
#endif /* DEBUG_NEWS */
rv = rootFolder->GetSubFolders(getter_AddRefs(subFolders));
if (NS_FAILED(rv)) return rv;
nsAdapterEnumerator *simpleEnumerator = new nsAdapterEnumerator(subFolders);
if (simpleEnumerator == nsnull) return NS_ERROR_OUT_OF_MEMORY;
PRBool moreFolders;
while (NS_SUCCEEDED(simpleEnumerator->HasMoreElements(&moreFolders)) && moreFolders) {
nsCOMPtr<nsISupports> child;
rv = simpleEnumerator->GetNext(getter_AddRefs(child));
if (NS_SUCCEEDED(rv) && child) {
newsFolder = do_QueryInterface(child, &rv);
if (NS_SUCCEEDED(rv) && newsFolder) {
nsXPIDLCString newsrcLine;
rv = newsFolder->GetNewsrcLine(getter_Copies(newsrcLine));
if (NS_SUCCEEDED(rv) && ((const char *)newsrcLine)) {
newsrcStream << (const char *)newsrcLine;
#ifdef DEBUG_NEWS
printf("writing to newsrc file:\n");
printf("%s",(const char *)newsrcLine);
#endif /* DEBUG_NEWS */
}
}
}
}
delete simpleEnumerator;
newsrcStream.close();
rv = SetNewsrcHasChanged(PR_FALSE);
if (NS_FAILED(rv)) return rv;
}
#ifdef DEBUG_NEWS
else {
printf("no need to write newsrc file for %s, it was not dirty\n", (const char *)hostname);
}
#endif /* DEBUG_NEWS */
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::SetNewsrcHasChanged(PRBool aNewsrcHasChanged)
{
mNewsrcHasChanged = aNewsrcHasChanged;
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::GetNewsrcHasChanged(PRBool *aNewsrcHasChanged)
{
if (!aNewsrcHasChanged) return NS_ERROR_NULL_POINTER;
*aNewsrcHasChanged = mNewsrcHasChanged;
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::CloseCachedConnections()
{
// iterate through the connection cache for a connection that can handle this url.
PRUint32 cnt;
nsCOMPtr<nsISupports> aSupport;
nsCOMPtr<nsINNTPProtocol> connection;
if (m_connectionCache)
{
nsresult rv = m_connectionCache->Count(&cnt);
if (NS_FAILED(rv)) return rv;
for (PRUint32 i = 0; i < cnt; i++)
{
aSupport = getter_AddRefs(m_connectionCache->ElementAt(i));
connection = do_QueryInterface(aSupport);
if (connection)
rv = connection->CloseConnection();
}
}
return WriteNewsrcFile();
}
NS_IMPL_SERVERPREF_INT(nsNntpIncomingServer, MaximumConnectionsNumber,
"max_cached_connections");
PRBool
nsNntpIncomingServer::ConnectionTimeOut(nsINNTPProtocol* aConnection)
{
PRBool retVal = PR_FALSE;
if (!aConnection) return retVal;
nsresult rv;
PRTime cacheTimeoutLimits;
LL_I2L(cacheTimeoutLimits, 170 * 1000000); // 170 seconds in microseconds
PRTime lastActiveTimeStamp;
rv = aConnection->GetLastActiveTimeStamp(&lastActiveTimeStamp);
PRTime elapsedTime;
LL_SUB(elapsedTime, PR_Now(), lastActiveTimeStamp);
PRTime t;
LL_SUB(t, elapsedTime, cacheTimeoutLimits);
if (LL_GE_ZERO(t))
{
nsCOMPtr<nsINNTPProtocol> aProtocol(do_QueryInterface(aConnection,
&rv));
if (NS_SUCCEEDED(rv) && aProtocol)
{
m_connectionCache->RemoveElement(aConnection);
retVal = PR_TRUE;
}
}
return retVal;
}
nsresult
nsNntpIncomingServer::CreateProtocolInstance(nsINNTPProtocol ** aNntpConnection, nsIURI *url,
nsIMsgWindow *aMsgWindow)
{
// create a new connection and add it to the connection cache
// we may need to flag the protocol connection as busy so we don't get
// a race
// condition where someone else goes through this code
nsNNTPProtocol * protocolInstance = new nsNNTPProtocol(url, aMsgWindow);
if (!protocolInstance)
return NS_ERROR_OUT_OF_MEMORY;
// nsresult rv = nsComponentManager::CreateInstance(kImapProtocolCID, nsnull,
// NS_GET_IID(nsINntpProtocol),
// (void **) &protocolInstance);
nsresult rv = protocolInstance->QueryInterface(NS_GET_IID(nsINNTPProtocol), (void **) aNntpConnection);
// take the protocol instance and add it to the connectionCache
if (NS_SUCCEEDED(rv) && *aNntpConnection)
m_connectionCache->AppendElement(*aNntpConnection);
return rv;
}
NS_IMETHODIMP
nsNntpIncomingServer::GetNntpConnection(nsIURI * aUri, nsIMsgWindow *aMsgWindow,
nsINNTPProtocol ** aNntpConnection)
{
nsresult rv = NS_OK;
nsCOMPtr<nsINNTPProtocol> connection;
nsCOMPtr<nsINNTPProtocol> freeConnection;
PRBool isBusy = PR_FALSE;
PRInt32 maxConnections = 2; // default to be 2
rv = GetMaximumConnectionsNumber(&maxConnections);
if (NS_FAILED(rv) || maxConnections == 0)
{
maxConnections = 2;
rv = SetMaximumConnectionsNumber(maxConnections);
}
else if (maxConnections < 1)
{ // forced to use at least 1
maxConnections = 1;
rv = SetMaximumConnectionsNumber(maxConnections);
}
*aNntpConnection = nsnull;
// iterate through the connection cache for a connection that can handle this url.
PRUint32 cnt;
nsCOMPtr<nsISupports> aSupport;
rv = m_connectionCache->Count(&cnt);
if (NS_FAILED(rv)) return rv;
for (PRUint32 i = 0; i < cnt && !isBusy; i++)
{
aSupport = getter_AddRefs(m_connectionCache->ElementAt(i));
connection = do_QueryInterface(aSupport);
if (connection)
rv = connection->IsBusy(&isBusy);
if (NS_FAILED(rv))
{
connection = null_nsCOMPtr();
continue;
}
if (!freeConnection && !isBusy && connection)
{
freeConnection = connection;
}
}
if (ConnectionTimeOut(connection))
connection = null_nsCOMPtr();
if (ConnectionTimeOut(freeConnection))
freeConnection = null_nsCOMPtr();
// if we got here and we have a connection, then we should return it!
if (!isBusy && connection)
{
*aNntpConnection = freeConnection;
freeConnection->Initialize(aUri, aMsgWindow);
NS_IF_ADDREF(*aNntpConnection);
}
else // have no queueing mechanism - just create the protocol instance.
{
rv = CreateProtocolInstance(aNntpConnection, aUri, aMsgWindow);
}
return rv;
}
/* void RemoveConnection (in nsINNTPProtocol aNntpConnection); */
NS_IMETHODIMP nsNntpIncomingServer::RemoveConnection(nsINNTPProtocol *aNntpConnection)
{
if (aNntpConnection)
m_connectionCache->RemoveElement(aNntpConnection);
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::PerformExpand(nsIMsgWindow *aMsgWindow)
{
nsresult rv;
#ifdef DEBUG_NEWS
printf("PerformExpand for nntp\n");
#endif
nsCOMPtr<nsINntpService> nntpService = do_GetService(kNntpServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
if (!nntpService) return NS_ERROR_FAILURE;
rv = nntpService->UpdateCounts(this, aMsgWindow);
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::GetNumGroupsNeedingCounts(PRInt32 *aNumGroupsNeedingCounts)
{
nsresult rv;
nsCOMPtr<nsIEnumerator> subFolders;
nsCOMPtr<nsIFolder> rootFolder;
rv = GetRootFolder(getter_AddRefs(rootFolder));
if (NS_FAILED(rv)) return rv;
PRBool hasSubFolders = PR_FALSE;
rv = rootFolder->GetHasSubFolders(&hasSubFolders);
if (NS_FAILED(rv)) return rv;
if (!hasSubFolders) {
*aNumGroupsNeedingCounts = 0;
return NS_OK;
}
rv = rootFolder->GetSubFolders(getter_AddRefs(subFolders));
if (NS_FAILED(rv)) return rv;
if (mGroupsEnumerator) {
delete mGroupsEnumerator;
mGroupsEnumerator = nsnull;
}
mGroupsEnumerator = new nsAdapterEnumerator(subFolders);
if (mGroupsEnumerator == nsnull) return NS_ERROR_OUT_OF_MEMORY;
PRUint32 count = 0;
rv = rootFolder->Count(&count);
if (NS_FAILED(rv)) return rv;
*aNumGroupsNeedingCounts = (PRInt32) count;
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::GetFirstGroupNeedingCounts(nsISupports **aFirstGroupNeedingCounts)
{
nsresult rv;
if (!aFirstGroupNeedingCounts) return NS_ERROR_NULL_POINTER;
PRBool moreFolders;
if (!mGroupsEnumerator) return NS_ERROR_FAILURE;
rv = mGroupsEnumerator->HasMoreElements(&moreFolders);
if (NS_FAILED(rv)) return rv;
if (!moreFolders) {
*aFirstGroupNeedingCounts = nsnull;
delete mGroupsEnumerator;
mGroupsEnumerator = nsnull;
return NS_OK;
}
rv = mGroupsEnumerator->GetNext(aFirstGroupNeedingCounts);
if (NS_FAILED(rv)) return rv;
if (!*aFirstGroupNeedingCounts) return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::DisplaySubscribedGroup(nsIMsgNewsFolder *aMsgFolder, PRInt32 aFirstMessage, PRInt32 aLastMessage, PRInt32 aTotalMessages)
{
nsresult rv;
if (!aMsgFolder) return NS_ERROR_NULL_POINTER;
#ifdef DEBUG_NEWS
printf("DisplaySubscribedGroup(...,%ld,%ld,%ld)\n",aFirstMessage,aLastMessage,aTotalMessages);
#endif
rv = aMsgFolder->UpdateSummaryFromNNTPInfo(aFirstMessage,aLastMessage,aTotalMessages);
return rv;
}
NS_IMETHODIMP
nsNntpIncomingServer::PerformBiff()
{
#ifdef DEBUG_NEWS
printf("PerformBiff for nntp\n");
#endif
return PerformExpand(nsnull);
}
NS_IMETHODIMP
nsNntpIncomingServer::GetServerRequiresPasswordForBiff(PRBool *_retval)
{
if (!_retval) return NS_ERROR_NULL_POINTER;
*_retval = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::OnStartRunningUrl(nsIURI *url)
{
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::OnStopRunningUrl(nsIURI *url, nsresult exitCode)
{
nsresult rv;
rv = UpdateSubscribedInSubscribeDS();
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsISubscribeListener> listener;
rv = GetSubscribeListener(getter_AddRefs(listener));
if (NS_FAILED(rv)) return rv;
if (!listener) return NS_ERROR_FAILURE;
rv = listener->OnStopPopulating();
if (NS_FAILED(rv)) return rv;
rv = StopPopulatingSubscribeDS();
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::ContainsNewsgroup(const char *name, PRBool *containsGroup)
{
nsresult rv;
NS_ASSERTION(name && PL_strlen(name),"no name");
if (!name || !containsGroup) return NS_ERROR_NULL_POINTER;
if (!nsCRT::strlen(name)) return NS_ERROR_FAILURE;
nsCOMPtr<nsIFolder> folder;
rv = GetRootFolder(getter_AddRefs(folder));
if (NS_FAILED(rv)) return rv;
if (!folder) return NS_ERROR_FAILURE;
nsCOMPtr<nsIMsgFolder> msgfolder = do_QueryInterface(folder, &rv);
if (NS_FAILED(rv)) return rv;
if (!msgfolder) return NS_ERROR_FAILURE;
rv = msgfolder->ContainsChildNamed(name, containsGroup);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::SubscribeToNewsgroup(const char *name)
{
nsresult rv;
NS_ASSERTION(name && PL_strlen(name),"no name");
if (!name) return NS_ERROR_NULL_POINTER;
if (!nsCRT::strlen(name)) return NS_ERROR_FAILURE;
nsCOMPtr<nsIFolder> folder;
rv = GetRootFolder(getter_AddRefs(folder));
if (NS_FAILED(rv)) return rv;
if (!folder) return NS_ERROR_FAILURE;
nsCOMPtr<nsIMsgFolder> msgfolder = do_QueryInterface(folder, &rv);
if (NS_FAILED(rv)) return rv;
if (!msgfolder) return NS_ERROR_FAILURE;
nsAutoString newsgroupName; newsgroupName.AssignWithConversion(name);
rv = msgfolder->CreateSubfolder(newsgroupName.GetUnicode());
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::PopulateSubscribeDatasource(nsIMsgWindow *aMsgWindow)
{
nsresult rv;
#ifdef DEBUG_sspitzer
printf("in PopulateSubscribeDatasource()\n");
#endif
rv = StartPopulatingSubscribeDS();
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsINntpService> nntpService = do_GetService(kNntpServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
if (!nntpService) return NS_ERROR_FAILURE;
rv = nntpService->BuildSubscribeDatasource(this, aMsgWindow);
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::AddNewsgroupToSubscribeDS(const char *aName)
{
NS_ASSERTION(mInner,"not initialized");
if (!mInner) return NS_ERROR_FAILURE;
return AddToSubscribeDS(aName);
}
NS_IMETHODIMP
nsNntpIncomingServer::SetIncomingServer(nsIMsgIncomingServer *aServer)
{
NS_ASSERTION(mInner,"not initialized");
if (!mInner) return NS_ERROR_FAILURE;
return mInner->SetIncomingServer(aServer);
}
NS_IMETHODIMP
nsNntpIncomingServer::SetDelimiter(char aDelimiter)
{
NS_ASSERTION(mInner,"not initialized");
if (!mInner) return NS_ERROR_FAILURE;
return mInner->SetDelimiter(aDelimiter);
}
NS_IMETHODIMP
nsNntpIncomingServer::SetAsSubscribedInSubscribeDS(const char *aName)
{
NS_ASSERTION(mInner,"not initialized");
if (!mInner) return NS_ERROR_FAILURE;
return mInner->SetAsSubscribedInSubscribeDS(aName);
}
NS_IMETHODIMP
nsNntpIncomingServer::UpdateSubscribedInSubscribeDS()
{
NS_ASSERTION(mInner,"not initialized");
if (!mInner) return NS_ERROR_FAILURE;
return mInner->UpdateSubscribedInSubscribeDS();
}
NS_IMETHODIMP
nsNntpIncomingServer::AddToSubscribeDS(const char *aName)
{
NS_ASSERTION(mInner,"not initialized");
if (!mInner) return NS_ERROR_FAILURE;
return mInner->AddToSubscribeDS(aName);
}
NS_IMETHODIMP
nsNntpIncomingServer::SetPropertiesInSubscribeDS(const char *uri, const char *aName, nsIRDFResource *aResource)
{
NS_ASSERTION(mInner,"not initialized");
if (!mInner) return NS_ERROR_FAILURE;
return mInner->SetPropertiesInSubscribeDS(uri,aName,aResource);
}
NS_IMETHODIMP
nsNntpIncomingServer::FindAndAddParentToSubscribeDS(const char *uri, const char *serverUri, const char *aName, nsIRDFResource *aChildResource)
{
NS_ASSERTION(mInner,"not initialized");
if (!mInner) return NS_ERROR_FAILURE;
return mInner->FindAndAddParentToSubscribeDS(uri,serverUri,aName,aChildResource);
}
NS_IMETHODIMP
nsNntpIncomingServer::StopPopulatingSubscribeDS()
{
nsresult rv;
NS_ASSERTION(mInner,"not initialized");
if (!mInner) return NS_ERROR_FAILURE;
rv = mInner->StopPopulatingSubscribeDS();
if (NS_FAILED(rv)) return rv;
mInner = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::StartPopulatingSubscribeDS()
{
nsresult rv;
NS_ASSERTION(mInner,"not initialized");
if (!mInner) return NS_ERROR_FAILURE;
rv = SetIncomingServer(this);
if (NS_FAILED(rv)) return rv;
rv = SetDelimiter('.');
if (NS_FAILED(rv)) return rv;
return mInner->StartPopulatingSubscribeDS();
}
NS_IMETHODIMP
nsNntpIncomingServer::SetSubscribeListener(nsISubscribeListener *aListener)
{
nsresult rv;
mInner = do_CreateInstance(kSubscribableServerCID,&rv);
if (NS_FAILED(rv)) return rv;
if (!mInner) return NS_ERROR_FAILURE;
return mInner->SetSubscribeListener(aListener);
}
NS_IMETHODIMP
nsNntpIncomingServer::GetSubscribeListener(nsISubscribeListener **aListener)
{
NS_ASSERTION(mInner,"not initialized");
if (!mInner) return NS_ERROR_FAILURE;
return mInner->GetSubscribeListener(aListener);
}
NS_IMETHODIMP
nsNntpIncomingServer::Subscribe(const char *aName)
{
#ifdef DEBUG_NEWS
printf("subscribe to news group: %s\n",aName);
#endif
return SubscribeToNewsgroup(aName);
}
NS_IMETHODIMP
nsNntpIncomingServer::Unsubscribe(const char *aName)
{
nsresult rv;
#ifdef DEBUG_NEWS
printf("unsubscribe to news group: %s\n",aName);
#endif
nsCOMPtr<nsIFolder> rootFolder;
rv = GetRootFolder(getter_AddRefs(rootFolder));
if (NS_FAILED(rv)) return rv;
if (!rootFolder) return NS_ERROR_FAILURE;
nsCOMPtr <nsIMsgFolder> serverFolder = do_QueryInterface(rootFolder, &rv);
if (NS_FAILED(rv)) return rv;
if (!serverFolder) return NS_ERROR_FAILURE;
nsCOMPtr <nsIFolder> subFolder;
rv = serverFolder->FindSubFolder(aName, getter_AddRefs(subFolder));
if (NS_FAILED(rv)) return rv;
nsCOMPtr <nsIMsgFolder> newsgroupFolder = do_QueryInterface(subFolder, &rv);
if (NS_FAILED(rv)) return rv;
if (!newsgroupFolder) return NS_ERROR_FAILURE;
rv = serverFolder->PropagateDelete(newsgroupFolder, PR_TRUE /* delete storage */);
if (NS_FAILED(rv)) return rv;
/* since we've unsubscribed to a newsgroup, the newsrc needs to be written out */
rv = SetNewsrcHasChanged(PR_TRUE);
if (NS_FAILED(rv)) return rv;
return NS_OK;
}