mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-13 10:25:01 +00:00
204 lines
6.8 KiB
C++
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;
|
|
}
|
|
|