summaryrefslogtreecommitdiff
path: root/src/operator-copy.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/operator-copy.cc')
-rw-r--r--src/operator-copy.cc169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/operator-copy.cc b/src/operator-copy.cc
new file mode 100644
index 0000000..cbe8767
--- /dev/null
+++ b/src/operator-copy.cc
@@ -0,0 +1,169 @@
+/** --------------------------------------------------------------------
+ * @file operator-copy.cc
+ * @brief Implementation of the COPY command.
+ * @author Andreas Aardal Hanssen
+ * @date 2002-2005
+ * ----------------------------------------------------------------- **/
+#include <string>
+
+#include "depot.h"
+#include "iodevice.h"
+#include "iofactory.h"
+#include "maildir.h"
+#include "operators.h"
+#include "recursivedescent.h"
+#include "session.h"
+#include "convert.h"
+
+using namespace ::std;
+using namespace Binc;
+
+//----------------------------------------------------------------------
+CopyOperator::CopyOperator(void)
+{
+}
+
+//----------------------------------------------------------------------
+CopyOperator::~CopyOperator(void)
+{
+}
+
+//----------------------------------------------------------------------
+const string CopyOperator::getName(void) const
+{
+ return "COPY";
+}
+
+//----------------------------------------------------------------------
+int CopyOperator::getState(void) const
+{
+ return Session::SELECTED;
+}
+
+//------------------------------------------------------------------------
+Operator::ProcessResult CopyOperator::process(Depot &depot,
+ Request &command)
+{
+ Session &session = Session::getInstance();
+
+ // Get the current mailbox
+ Mailbox *srcMailbox = depot.getSelected();
+
+ // Get the destination mailbox
+ string dmailbox = command.getMailbox();
+ Mailbox *destMailbox = depot.get(toCanonMailbox(dmailbox));
+ if (destMailbox == 0) {
+ session.setResponseCode("TRYCREATE");
+ session.setLastError("invalid mailbox " + toImapString(dmailbox));
+ return NO;
+ }
+
+ unsigned int mode = Mailbox::SKIP_EXPUNGED;
+ mode |= command.getUidMode() ? Mailbox::UID_MODE : Mailbox::SQNR_MODE;
+
+ // Copy each message in the sequence set to the destination mailbox.
+ bool success = true;
+ Mailbox::iterator i = srcMailbox->begin(command.bset, mode);
+ for (; success && i != srcMailbox->end(); ++i) {
+ Message &source = *i;
+
+ if (srcMailbox->fastCopy(source, *destMailbox,
+ depot.mailboxToFilename(toCanonMailbox(dmailbox))))
+ continue;
+
+ // Have the destination mailbox create a message for us.
+ Message *dest
+ = destMailbox->createMessage(depot.mailboxToFilename(toCanonMailbox(dmailbox)),
+ source.getInternalDate());
+ if (!dest) {
+ session.setLastError(destMailbox->getLastError());
+ success = false;
+ break;
+ }
+
+ // Set the flags and internal date.
+ dest->setStdFlag(source.getStdFlags());
+ dest->setInternalDate(source.getInternalDate());
+
+ // Copy chunks from the source message over to the destination
+ // message.
+ string chunk;
+ do {
+ int readSize = source.readChunk(chunk);
+
+ if (readSize == 0) break;
+ else if (readSize == -1) {
+ bincWarning << "when reading from message "
+ << i.getSqnr() << "/" << source.getUID()
+ << " in \"" << srcMailbox->getName() << "\": "
+ << source.getLastError() << endl;
+ success = false;
+ } else if (!dest->appendChunk(chunk)) {
+ bincWarning << "when writing to \""
+ << dmailbox << "\": "
+ << dest->getLastError() << endl;
+ success = false;
+ }
+ } while (success);
+
+ dest->close();
+ }
+
+ if (!success && !destMailbox->rollBackNewMessages()) {
+ session.setLastError("Failed to rollback after unsuccessful copy: "
+ + destMailbox->getLastError());
+ return NO;
+ }
+
+ if (success)
+ if (!destMailbox->commitNewMessages(depot.mailboxToFilename(toCanonMailbox(dmailbox)))) {
+ session.setLastError("Failed to commit after successful copy: "
+ + destMailbox->getLastError());
+ return NO;
+ }
+
+ if (!success)
+ session.setLastError("The transaction was unrolled. Please "
+ "contant your system administrator for "
+ "more information.");
+
+ return success ? OK : NO;
+}
+
+//------------------------------------------------------------------------
+Operator::ParseResult CopyOperator::parse(Request &c_in) const
+{
+ Session &session = Session::getInstance();
+
+ Operator::ParseResult res;
+ if ((res = expectSPACE()) != ACCEPT) {
+ session.setLastError("Expected SPACE after COPY");
+ return res;
+ }
+
+ if ((res = expectSet(c_in.getSet())) != ACCEPT) {
+ session.setLastError("Expected sequence set after COPY SPACE");
+ return res;
+ }
+
+ if ((res = expectSPACE()) != ACCEPT) {
+ session.setLastError("Expected SPACE after COPY SPACE set");
+ return res;
+ }
+
+ string mailbox;
+ if ((res = expectMailbox(mailbox)) != ACCEPT) {
+ session.setLastError("Expected mailbox after COPY SPACE set SPACE");
+ return res;
+ }
+
+ if ((res = expectCRLF()) != ACCEPT) {
+ session.setLastError("Expected CRLF after COPY SPACE set SPACE mailbox");
+ return res;
+ }
+
+ c_in.setMailbox(mailbox);
+ c_in.setName("COPY");
+
+ return ACCEPT;
+}