gecko-dev/network/protocol/imap4/imaphier.cpp
1998-06-25 05:50:45 +00:00

204 lines
6.8 KiB
C++

/* -*- Mode: C++; tab-width: 4; 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) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "mkutils.h"
#include "imaphier.h"
#include "imap4pvt.h"
#include "imap.h"
ImapHierarchyMover::ImapHierarchyMover(
const char *destinationNodeName,
const char *sourceNodeName,
TNavigatorImapConnection &connection)
: fIMAPConnection(connection)
{
fDestinationNodeName = XP_STRDUP(destinationNodeName);
fSourceNodeName = XP_STRDUP(sourceNodeName);
fMailboxHierarchy = XP_ListNew();
}
ImapHierarchyMover::~ImapHierarchyMover()
{
// this is a leak, delete the structs
if (fMailboxHierarchy)
XP_ListDestroy(fMailboxHierarchy);
FREEIF(fDestinationNodeName);
FREEIF(fSourceNodeName);
}
void ImapHierarchyMover::AddToHierarchy(const char *nodeName)
{
int stringLength = XP_STRLEN(nodeName);
char *nodeTokens = new char [stringLength + 2]; // end the string in double null so AddToSubTree
XP_STRCPY(nodeTokens, nodeName); // will work
*(nodeTokens + stringLength) = 0;
*(nodeTokens + stringLength+1) = 0;
AddToSubTree(nodeTokens, nodeName, fMailboxHierarchy);
delete nodeTokens;
}
void ImapHierarchyMover::AddToSubTree(char *nodeTokens, const char *nodeName, XP_List *subTree)
{
char *positionOfNodeTokens = XP_STRSTR(nodeName, nodeTokens);
// make sure we find the last one
char *currentPositionOfNodeTokens = positionOfNodeTokens;
while (currentPositionOfNodeTokens && strlen(nodeTokens))
{
currentPositionOfNodeTokens = XP_STRSTR(currentPositionOfNodeTokens + 1, nodeTokens);
if (currentPositionOfNodeTokens)
positionOfNodeTokens = currentPositionOfNodeTokens;
}
char *placeHolderInTokenString = nil;
char *currentNodeToken = XP_STRTOK_R(nodeTokens, "/",&placeHolderInTokenString);
if (currentNodeToken)
{
// find the current node, if it exists
HierarchyNode *currentNode = NULL;
int numberOfNodes = XP_ListCount(subTree);
XP_Bool nodeFound = FALSE;
while (numberOfNodes && !nodeFound)
{
currentNode = (HierarchyNode *) XP_ListGetObjectNum(subTree, numberOfNodes--);
nodeFound = XP_STRCMP(currentNode->fNodeToken, currentNodeToken) == 0;
}
if (!nodeFound)
{
// create the node
currentNode = (HierarchyNode *) XP_ALLOC(sizeof(HierarchyNode));
if (currentNode)
{
currentNode->fPresentName = XP_STRDUP(nodeName);
// less the remaining tokens
*(currentNode->fPresentName + (positionOfNodeTokens-nodeName) + XP_STRLEN(currentNodeToken)) = 0;
currentNode->fNodeToken = XP_STRDUP(currentNodeToken);
currentNode->fSubFolders = XP_ListNew();
XP_ListAddObjectToEnd(subTree, currentNode);
}
}
// recurse!
char *subNodeTokens = nodeTokens + XP_STRLEN(currentNodeToken) + 1; // +1 see note in AddToHierarchy
AddToSubTree(subNodeTokens, nodeName, currentNode->fSubFolders);
}
}
// depth first, post process unsubscribe and delete everything including and below source node name
void ImapHierarchyMover::DestroyOldFolderTree(XP_List *subTree)
{
int numberOfNodesAtThisLevel = XP_ListCount(subTree);
for (int nodeIndex=numberOfNodesAtThisLevel; nodeIndex > 0; nodeIndex--)
{
HierarchyNode *currentNode = (HierarchyNode *) XP_ListGetObjectNum(subTree, nodeIndex);
DestroyOldFolderTree(currentNode->fSubFolders);
if (fIMAPConnection.GetServerStateParser().LastCommandSuccessful() &&
XP_STRSTR(currentNode->fPresentName, fSourceNodeName))
{
fIMAPConnection.Unsubscribe(currentNode->fPresentName);
if (fIMAPConnection.GetServerStateParser().LastCommandSuccessful())
fIMAPConnection.DeleteMailbox(currentNode->fPresentName);
}
}
}
// depth first, pre-process create, subscribe, and fill with messages
void ImapHierarchyMover::CreateNewFolderTree(const char *destinationNodeName, XP_List *subTree)
{
int numberOfNodesAtThisLevel = XP_ListCount(subTree);
for (int nodeIndex=1; nodeIndex <= numberOfNodesAtThisLevel; nodeIndex++)
{
HierarchyNode *currentNode = (HierarchyNode *) XP_ListGetObjectNum(subTree, nodeIndex);
if (!XP_STRSTR(fSourceNodeName, currentNode->fPresentName) ||
!XP_STRCMP(fSourceNodeName, currentNode->fPresentName)) // if we are not yet at the node name, don't rename
{
char *newNodeName = (char *) XP_ALLOC(XP_STRLEN(destinationNodeName) +
XP_STRLEN(currentNode->fNodeToken) + 2);
XP_STRCPY(newNodeName, destinationNodeName);
XP_STRCAT(newNodeName, "/");
XP_STRCAT(newNodeName, currentNode->fNodeToken);
fIMAPConnection.CreateMailbox(newNodeName);
if (fIMAPConnection.GetServerStateParser().LastCommandSuccessful())
{
fIMAPConnection.Subscribe(newNodeName);
if (fIMAPConnection.GetServerStateParser().LastCommandSuccessful())
{
// close the current folder if one is selected
if (fIMAPConnection.GetServerStateParser().GetIMAPstate() ==
TImapServerState::kFolderSelected)
fIMAPConnection.Close();
// select the old folder
fIMAPConnection.SelectMailbox(currentNode->fPresentName);
if (fIMAPConnection.GetServerStateParser().LastCommandSuccessful())
{
// copy its entire contents to the destination
int numOfMsgs = fIMAPConnection.GetServerStateParser().NumberOfMessages();
if (numOfMsgs)
{
char msgList[100]; // enough for trillions?
sprintf(msgList, "1:%d", numOfMsgs);
fIMAPConnection.Copy(msgList, newNodeName, FALSE); // not uids
}
if (fIMAPConnection.GetServerStateParser().LastCommandSuccessful())
fIMAPConnection.Close();
}
}
}
// recurse to my children
if (fIMAPConnection.GetServerStateParser().LastCommandSuccessful())
CreateNewFolderTree(newNodeName, currentNode->fSubFolders);
FREEIF( newNodeName);
}
else
CreateNewFolderTree(destinationNodeName, currentNode->fSubFolders);
}
}
int ImapHierarchyMover::DoMove()
{
int returnValue = 0;
CreateNewFolderTree(fDestinationNodeName, fMailboxHierarchy);
if (fIMAPConnection.GetServerStateParser().LastCommandSuccessful())
{
DestroyOldFolderTree(fMailboxHierarchy);
if (!fIMAPConnection.GetServerStateParser().LastCommandSuccessful())
returnValue = -1;
}
else
returnValue = -1;
return returnValue;
}