code: plan9front

Download patch

ref: 3c748ebc11c8a7e8513efcdd61a38a56c8ccfb5a
parent: d78dd0557c8f854322470a86815ea3e0b5f441a4
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Thu Aug 10 13:28:33 EDT 2023

upas: "move" ctl verb to move messages between imap folders (thanks Risto Salminen)

--- a/sys/man/4/upasfs
+++ b/sys/man/4/upasfs
@@ -206,7 +206,7 @@
 .I fs
 to open, close, rename, create or remove new mailboxes,
 and also to
-delete or flag groups of messages atomically.
+delete, flag, or move groups of messages atomically.
 The messages that can be written to this file are:
 .TP 2i
 .PD 0
@@ -260,6 +260,13 @@
 .TP
 .B "flag \fImboxname flags number ...\fP
 flag the given messages.
+.TP
+.B "move \fImboxname number ... target\fP
+Move the given messages from
+.IR mboxname
+to mailbox named
+.IR target.
+At the moment only supported with IMAP mailboxes.
 .PD
 .PP
 The
--- a/sys/src/cmd/upas/fs/dat.h
+++ b/sys/src/cmd/upas/fs/dat.h
@@ -172,6 +172,7 @@
 	ulong	waketime;
 	void	(*close)(Mailbox*);
 	void	(*decache)(Mailbox*, Message*);
+	char	*(*move)(Mailbox*, Message*, char*);
 	int	(*fetch)(Mailbox*, Message*, uvlong, ulong);
 	void	(*delete)(Mailbox*, Message*);
 	char	*(*ctl)(Mailbox*, int, char**);
@@ -215,6 +216,7 @@
 void		unnewmessage(Mailbox*, Message*, Message*);
 char*		delmessages(int, char**);
 char		*flagmessages(int, char**);
+char*		movemessages(int, char**);
 void		digestmessage(Mailbox*, Message*);
 
 int		wraptls(int, char*);
--- a/sys/src/cmd/upas/fs/fs.c
+++ b/sys/src/cmd/upas/fs/fs.c
@@ -1242,6 +1242,11 @@
 				return nil;
 			return flagmessages(argc - 1, argv + 1);
 		}
+		if(strcmp(argv[0], "move") == 0){
+			if(argc < 4)
+				return nil;
+			return movemessages(argc - 1, argv + 1);
+		}
 		if(strcmp(argv[0], "remove") == 0){
 			v0 = argv0;
 			flags = 0;
--- a/sys/src/cmd/upas/fs/imap.c
+++ b/sys/src/cmd/upas/fs/imap.c
@@ -1023,7 +1023,29 @@
 	}
 	m->inmbox = 0;
 }
+static char*
+imap4move(Mailbox *mb, Message *m, char *dest)
+{
+	char *r;
+	Imap *imap;
 
+	imap = mb->aux;
+	imap4cmd(imap, "uid copy %lud %s", (ulong)m->imapuid, dest);
+	r = imap4resp(imap);
+	if(!isokay(r))
+		return r;
+	imap4cmd(imap, "uid store %lud +flags (\\Deleted)", (ulong)m->imapuid);
+	r = imap4resp(imap);
+	if(!isokay(r))
+		return r;
+	imap4cmd(imap, "expunge");
+	r = imap4resp(imap);
+	if(!isokay(r))
+		return r;
+	m->inmbox = 0;
+	return 0;
+}
+
 static char*
 imap4sync(Mailbox *mb)
 {
@@ -1183,6 +1205,7 @@
 	mb->delete = imap4delete;
 	mb->rename = imap4rename;
 	mb->modflags = imap4modflags;
+	mb->move = imap4move;
 	mb->addfrom = 1;
 	return nil;
 }
--- a/sys/src/cmd/upas/fs/mbox.c
+++ b/sys/src/cmd/upas/fs/mbox.c
@@ -1137,6 +1137,37 @@
 	return rerr;
 }
 
+char*
+movemessages(int argc, char **argv)
+{
+	char *err, *dest, *rerr;
+	int i, needwrite;
+	Mailbox *mb;
+	Message *m;
+
+	rerr = 0;
+	for(mb = mbl; mb != nil; mb = mb->next)
+		if(strcmp(*argv, mb->name) == 0)
+			break;
+	if(mb == nil)
+		return "no such mailbox";
+	if(mb->move == nil)
+		return "move not supported";
+	dest = argv[argc - 1];
+	needwrite = 0;
+	for(i = 1; i < argc - 1; i++)
+		for(m = mb->root->part; m; m = m->next)
+			if(strcmp(m->name, argv[i]) == 0){
+				if(err = mb->move(mb, m, dest))
+					rerr = err;
+				else
+					needwrite = 1;
+			}
+	if(needwrite)
+		syncmbox(mb, 1);
+	return rerr;
+}
+
 void
 msgincref(Mailbox *mb, Message *m)
 {
--- a/sys/src/cmd/upas/fs/mdir.c
+++ b/sys/src/cmd/upas/fs/mdir.c
@@ -294,5 +294,6 @@
 	mb->idxread = idxr;
 	mb->idxwrite = idxw;
 	mb->ctl = mdirctl;
+	mb->move = nil;
 	return nil;
 }
--- a/sys/src/cmd/upas/fs/plan9.c
+++ b/sys/src/cmd/upas/fs/plan9.c
@@ -414,5 +414,6 @@
 	mb->remove = localremove;
 	mb->rename = localrename;
 	mb->decache = plan9decache;
+	mb->move = nil;
 	return nil;
 }
--- a/sys/src/cmd/upas/fs/pop3.c
+++ b/sys/src/cmd/upas/fs/pop3.c
@@ -624,6 +624,7 @@
 	mb->sync = pop3sync;
 	mb->close = pop3close;
 	mb->ctl = pop3ctl;
+	mb->move = nil;
 	mb->addfrom = 1;
 	return nil;
 }