fix for ##48409. prevent mac from crashing when using the subscribe dialog.

I was recursing over the internal tree to generate the hostinfo.dat.
win32 and linux were ok, but all hell broke loose on the mac.
256K of stack is not enough for my approach.  I've switched
to keep a duplicate list of the groups on the server.  also fix some minor
subscribe issues.

sr=bienvenu
This commit is contained in:
sspitzer%netscape.com 2001-05-01 08:50:07 +00:00
parent a4b4bdd587
commit 9cdfaf0347
8 changed files with 70 additions and 216 deletions

View File

@ -40,13 +40,6 @@ interface nsISubscribeListener : nsISupports {
void OnDonePopulating();
};
[scriptable, uuid(f0e703ba-1dd1-11b2-9dfd-d5be7140b673)]
interface nsISubscribeDumpListener : nsISupports {
void startDumping();
void dumpItem(in string name);
void doneDumping();
};
[scriptable, uuid(6f9d2e82-1dd2-11b2-bbed-bbea41ca33a7)]
interface nsISubscribableServer : nsISupports {
attribute nsISubscribeListener subscribeListener;
@ -83,9 +76,5 @@ interface nsISubscribableServer : nsISupports {
void getChildren(in string path, in nsISupportsArray array);
// if path is null, use the root
void getFirstChildURI(in string path, out string result);
// used for writing out the SubscribeTree
void setDumpListener(in nsISubscribeDumpListener dumpListener);
void dumpTree();
};

View File

@ -197,22 +197,6 @@ nsSubscribableServer::SetState(const char *path, PRBool state, PRBool *stateChan
return rv;
}
void
nsSubscribableServer::BuildPathFromNode(SubscribeTreeNode *node, nsCAutoString &path)
{
if (node == mTreeRoot) return;
if (node->parent) {
BuildPathFromNode(node->parent, path);
if (node->parent != mTreeRoot) {
path += mDelimiter;
}
}
path += node->name;
return;
}
void
nsSubscribableServer::BuildURIFromNode(SubscribeTreeNode *node, nsCAutoString &uri)
{
@ -437,44 +421,7 @@ nsSubscribableServer::SetShowFullName(PRBool showFullName)
mShowFullName = showFullName;
return NS_OK;
}
nsresult
nsSubscribableServer::DumpSubtree(SubscribeTreeNode *node)
{
nsresult rv = NS_OK;
if (node) {
NS_ASSERTION(mDumpListener, "calling DumpTree(), no listener");
if (mDumpListener) {
if (node->isSubscribable) {
nsCAutoString path;
BuildPathFromNode(node, path);
rv = mDumpListener->DumpItem((const char *)path);
NS_ENSURE_SUCCESS(rv,rv);
}
#ifdef DEBUG_seth
else {
printf("skipping %s, it is not subscribable\n",node->name);
}
#endif
}
// recursively dump the children
if (node->lastChild) {
rv = DumpSubtree(node->lastChild);
NS_ENSURE_SUCCESS(rv,rv);
}
// recursively dump the siblings
if (node->prevSibling) {
rv = DumpSubtree(node->prevSibling);
NS_ENSURE_SUCCESS(rv,rv);
}
}
return NS_OK;
}
nsresult
nsSubscribableServer::FreeSubtree(SubscribeTreeNode *node)
{
@ -812,7 +759,7 @@ nsSubscribableServer::GetChildren(const char *path, nsISupportsArray *array)
uriPrefix += mDelimiter;
}
// we inserted them in z to a order.
// we inserted them in reverse alphabetical order.
// so pull them out in reverse to get the right order
// in the subscribe dialog
SubscribeTreeNode *current = node->lastChild;
@ -845,26 +792,4 @@ nsSubscribableServer::CommitSubscribeChanges()
{
NS_ASSERTION(PR_FALSE,"override this.");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsSubscribableServer::DumpTree()
{
nsresult rv;
NS_ASSERTION(mDumpListener, "calling DumpTree(), no listener");
if (mDumpListener) {
mDumpListener->StartDumping();
rv = DumpSubtree(mTreeRoot);
NS_ENSURE_SUCCESS(rv,rv);
mDumpListener->DoneDumping();
}
return NS_OK;
}
NS_IMETHODIMP
nsSubscribableServer::SetDumpListener(nsISubscribeDumpListener *dumpListener)
{
mDumpListener = dumpListener;
return NS_OK;
}
}

View File

@ -80,8 +80,6 @@ private:
nsCOMPtr <nsIRDFService> mRDFService;
nsCOMPtr <nsISubscribeDumpListener> mDumpListener;
SubscribeTreeNode *mTreeRoot;
nsresult FreeSubtree(SubscribeTreeNode *node);
nsresult CreateNode(SubscribeTreeNode *parent, const char *name, SubscribeTreeNode **result);
@ -91,10 +89,8 @@ private:
nsresult NotifyChange(SubscribeTreeNode *subjectNode, nsIRDFResource *property, PRBool value);
nsresult Notify(nsIRDFResource *subject, nsIRDFResource *property, nsIRDFNode *object, PRBool isAssert, PRBool isChange);
void BuildURIFromNode(SubscribeTreeNode *node, nsCAutoString &uri);
void BuildPathFromNode(SubscribeTreeNode *node, nsCAutoString &uri);
nsresult EnsureSubscribeDS();
nsresult EnsureRDFService();
nsresult DumpSubtree(SubscribeTreeNode *node);
};
#endif // nsSubscribableServer_h__

View File

@ -484,6 +484,7 @@ nsSubscribeDataSource::HasAssertion(nsIRDFResource *source,
if (!tv) return NS_OK;
if (property == kNC_Child.get()) {
nsCOMPtr<nsISubscribableServer> server;
nsXPIDLCString relativePath;
@ -493,7 +494,6 @@ nsSubscribeDataSource::HasAssertion(nsIRDFResource *source,
return NS_OK;
}
if (property == kNC_Child.get()) {
// not everything has children
rv = server->HasChildren((const char *)relativePath, hasAssertion);
NS_ENSURE_SUCCESS(rv,rv);
@ -536,13 +536,13 @@ nsSubscribeDataSource::HasArcOut(nsIRDFResource *source, nsIRDFResource *aArc, P
nsCOMPtr<nsISubscribableServer> server;
nsXPIDLCString relativePath;
if (aArc == kNC_Child.get()) {
rv = GetServerAndRelativePathFromResource(source, getter_AddRefs(server), getter_Copies(relativePath));
if (NS_FAILED(rv) || !server) {
*result = PR_FALSE;
return NS_OK;
}
if (aArc == kNC_Child.get()) {
PRBool hasChildren = PR_FALSE;
rv = server->HasChildren((const char *)relativePath, &hasChildren);
NS_ENSURE_SUCCESS(rv,rv);

View File

@ -277,9 +277,9 @@ nsresult NS_MsgCreatePathStringFromFolderURI(const char *folderURI, nsCString& p
// A file name has to be in native charset, convert from UTF-8.
nsCAutoString oldPath;
const nsString fileCharset(nsMsgI18NFileSystemCharset());
char *nativeString;
char *nativeString = nsnull;
nsresult rv = ConvertFromUnicode(fileCharset, nsAutoString(NS_ConvertUTF8toUCS2(folderURI)), &nativeString);
if (NS_SUCCEEDED(rv))
if (NS_SUCCEEDED(rv) && nativeString && nativeString[0])
oldPath.Assign(nativeString);
else
oldPath.Assign(folderURI);

View File

@ -2750,22 +2750,6 @@ nsImapIncomingServer::CommitSubscribeChanges()
return ReDiscoverAllFolders();
}
NS_IMETHODIMP
nsImapIncomingServer::DumpTree()
{
nsresult rv = EnsureInner();
NS_ENSURE_SUCCESS(rv,rv);
return mInner->DumpTree();
}
NS_IMETHODIMP
nsImapIncomingServer::SetDumpListener(nsISubscribeDumpListener *dumpListener)
{
nsresult rv = EnsureInner();
NS_ENSURE_SUCCESS(rv,rv);
return mInner->SetDumpListener(dumpListener);
}
NS_IMETHODIMP
nsImapIncomingServer::GetCanBeDefaultServer(PRBool *canBeDefaultServer)
{

View File

@ -70,7 +70,6 @@ NS_INTERFACE_MAP_BEGIN(nsNntpIncomingServer)
NS_INTERFACE_MAP_ENTRY(nsINntpIncomingServer)
NS_INTERFACE_MAP_ENTRY(nsIUrlListener)
NS_INTERFACE_MAP_ENTRY(nsISubscribableServer)
NS_INTERFACE_MAP_ENTRY(nsISubscribeDumpListener)
NS_INTERFACE_MAP_END_INHERITING(nsMsgIncomingServer)
nsNntpIncomingServer::nsNntpIncomingServer() : nsMsgLineBuffer(nsnull, PR_FALSE)
@ -702,27 +701,27 @@ nsNntpIncomingServer::OnStopRunningUrl(nsIURI *url, nsresult exitCode)
return NS_OK;
}
PRBool
checkIfSubscribedFunction(nsCString &aElement, void *aData)
{
if (nsCRT::strcmp((const char *)aData, (const char *)aElement) == 0) {
return PR_FALSE;
}
else {
return PR_TRUE;
}
}
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;
*containsGroup = !(mSubscribedNewsgroups.EnumerateForwards((nsCStringArrayEnumFunc)checkIfSubscribedFunction, (void *)name));
return NS_OK;
}
@ -751,47 +750,31 @@ nsNntpIncomingServer::SubscribeToNewsgroup(const char *name)
return NS_OK;
}
PRBool
writeGroupToHostInfoFile(nsCString &aElement, void *aData)
{
nsIOFileStream *stream;
stream = (nsIOFileStream *)aData;
NS_ASSERTION(stream, "no stream");
if (!stream) {
// stop, something is bad.
return PR_FALSE;
}
// XXX todo ",,1,0,0" is a temporary hack, fix it
*stream << aElement.get() << ",,1,0,0" << MSG_LINEBREAK;
return PR_TRUE;
}
nsresult
nsNntpIncomingServer::WriteHostInfoFile()
{
nsresult rv = NS_OK;
#ifdef DEBUG_NEWS
printf("WriteHostInfoFile()\n");
#endif
if (!mHostInfoHasChanged) {
#ifdef DEBUG_NEWS
printf("don't write out the hostinfo file\n");
#endif
return NS_OK;
}
#ifdef DEBUG_NEWS
else {
printf("write out the hostinfo file\n");
}
#endif
rv = EnsureInner();
NS_ENSURE_SUCCESS(rv,rv);
rv = mInner->SetDumpListener(this);
NS_ENSURE_SUCCESS(rv,rv);
rv = mInner->DumpTree();
NS_ENSURE_SUCCESS(rv,rv);
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::StartDumping()
{
nsresult rv;
#ifdef DEBUG_NEWS
printf("start dumping\n");
#endif
PRInt32 firstnewdate;
LL_L2I(firstnewdate, mFirstNewDate);
@ -826,39 +809,15 @@ nsNntpIncomingServer::StartDumping()
*mHostInfoStream << "" << MSG_LINEBREAK;
*mHostInfoStream << "begingroups" << MSG_LINEBREAK;
return NS_OK;
}
// XXX todo, sort groups first?
NS_IMETHODIMP
nsNntpIncomingServer::DumpItem(const char *name)
{
NS_ASSERTION(mHostInfoStream, "no stream!");
// todo ",,1,0,0" is a temporary hack, fix it
*mHostInfoStream << name << ",,1,0,0" << MSG_LINEBREAK;
return NS_OK;
}
mGroupsOnServer.EnumerateForwards((nsCStringArrayEnumFunc)writeGroupToHostInfoFile, (void *)mHostInfoStream);
NS_IMETHODIMP
nsNntpIncomingServer::DoneDumping()
{
nsresult rv;
#ifdef DEBUG_NEWS
printf("done dumping\n");
#endif
NS_ASSERTION(mHostInfoStream, "no stream!");
mHostInfoStream->close();
delete mHostInfoStream;
mHostInfoStream = nsnull;
mHostInfoHasChanged = PR_FALSE;
rv = EnsureInner();
NS_ENSURE_SUCCESS(rv,rv);
rv = mInner->SetDumpListener(nsnull);
NS_ENSURE_SUCCESS(rv,rv);
return NS_OK;
}
@ -916,9 +875,6 @@ nsNntpIncomingServer::LoadHostInfoFile()
rv = UpdateSubscribed();
if (NS_FAILED(rv)) return rv;
rv = StopPopulating(mMsgWindow);
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
@ -960,6 +916,7 @@ nsNntpIncomingServer::StartPopulating(nsIMsgWindow *aMsgWindow, PRBool aForceToS
rv = EnsureInner();
NS_ENSURE_SUCCESS(rv,rv);
rv = mInner->StartPopulating(aMsgWindow, aForceToServer);
NS_ENSURE_SUCCESS(rv,rv);
@ -969,11 +926,12 @@ nsNntpIncomingServer::StartPopulating(nsIMsgWindow *aMsgWindow, PRBool aForceToS
rv = SetShowFullName(PR_TRUE);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsINntpService> nntpService = do_GetService(NS_NNTPSERVICE_CONTRACTID, &rv);
nsCOMPtr<nsINntpService> nntpService = do_GetService(NS_NNTPSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv,rv);
mHostInfoLoaded = PR_FALSE;
mVersion = INVALID_VERSION;
mGroupsOnServer.Clear();
if (!aForceToServer) {
rv = LoadHostInfoFile();
@ -982,16 +940,20 @@ nsNntpIncomingServer::StartPopulating(nsIMsgWindow *aMsgWindow, PRBool aForceToS
// mHostInfoLoaded can be false if we failed to load anything
if (!mHostInfoLoaded || (mVersion != VALID_VERSION)) {
// set these to true, so when we call WriteHostInfoFile()
// we write it out to disk
// set these to true, so when we are done and we call WriteHostInfoFile()
// we'll write out to hostinfo.dat
mHostInfoHasChanged = PR_TRUE;
mVersion = VALID_VERSION;
// todo, make sure inner has been freed before we start?
mGroupsOnServer.Clear();
rv = nntpService->GetListOfGroupsOnServer(this, aMsgWindow);
if (NS_FAILED(rv)) return rv;
}
else {
rv = StopPopulating(aMsgWindow);
if (NS_FAILED(rv)) return rv;
}
return NS_OK;
}
@ -1111,7 +1073,13 @@ nsNntpIncomingServer::AddTo(const char *aName, PRBool addAsSubscribed, PRBool ch
{
nsresult rv = EnsureInner();
NS_ENSURE_SUCCESS(rv,rv);
return mInner->AddTo(aName,addAsSubscribed,changeIfExists);
rv = AddGroupOnServer(aName);
NS_ENSURE_SUCCESS(rv,rv);
rv = mInner->AddTo(aName,addAsSubscribed,changeIfExists);
NS_ENSURE_SUCCESS(rv,rv);
return rv;
}
NS_IMETHODIMP
@ -1214,9 +1182,11 @@ nsNntpIncomingServer::HandleLine(char* line, PRUint32 line_size)
if (commaPos) *commaPos = 0;
nsresult rv = AddTo(line, PR_FALSE, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to add the group");
// since we've seen one group, we can claim we've loaded the hostinfo file
mHostInfoLoaded = PR_TRUE;
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to add line");
if (NS_SUCCEEDED(rv)) {
// since we've seen one group, we can claim we've loaded the hostinfo file
mHostInfoLoaded = PR_TRUE;
}
}
else {
if (nsCRT::strncmp(line,"begingroups", 11) == 0) {
@ -1243,6 +1213,12 @@ nsNntpIncomingServer::HandleLine(char* line, PRUint32 line_size)
return 0;
}
nsresult
nsNntpIncomingServer::AddGroupOnServer(const char *name)
{
mGroupsOnServer.AppendCString(nsCAutoString(name));
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::AddNewsgroup(const char *name)
@ -1320,22 +1296,6 @@ nsNntpIncomingServer::CommitSubscribeChanges()
return WriteNewsrcFile();
}
NS_IMETHODIMP
nsNntpIncomingServer::DumpTree()
{
nsresult rv = EnsureInner();
NS_ENSURE_SUCCESS(rv,rv);
return mInner->DumpTree();
}
NS_IMETHODIMP
nsNntpIncomingServer::SetDumpListener(nsISubscribeDumpListener *dumpListener)
{
nsresult rv = EnsureInner();
NS_ENSURE_SUCCESS(rv,rv);
return mInner->SetDumpListener(dumpListener);
}
NS_IMETHODIMP
nsNntpIncomingServer::ForgetPassword()
{

View File

@ -49,7 +49,6 @@ class nsNntpIncomingServer : public nsMsgIncomingServer,
public nsINntpIncomingServer,
public nsIUrlListener,
public nsISubscribableServer,
public nsISubscribeDumpListener,
public nsMsgLineBuffer
{
@ -58,7 +57,6 @@ public:
NS_DECL_NSINNTPINCOMINGSERVER
NS_DECL_NSIURLLISTENER
NS_DECL_NSISUBSCRIBABLESERVER
NS_DECL_NSISUBSCRIBEDUMPLISTENER
nsNntpIncomingServer();
virtual ~nsNntpIncomingServer();
@ -88,11 +86,13 @@ protected:
private:
nsCStringArray mSubscribedNewsgroups;
nsCStringArray mGroupsOnServer;
PRBool mHasSeenBeginGroups;
nsresult WriteHostInfoFile();
nsresult LoadHostInfoFile();
nsresult AddGroupOnServer(const char *name);
PRBool mNewsrcHasChanged;
nsAdapterEnumerator *mGroupsEnumerator;
PRBool mHostInfoLoaded;