Aleksander wrote:
> Michael Monnerie wrote:
>> There's been no discussion on this list about that. Anybody considered
>> it? I've read it just quickly, looks interesting. I'd like to have
>> some developer feedback on it.
>
> You're the first to show interest. I haven't seen any replies off list
> either.
>
> Don't hesitate to ask questions. I'm really interested for some
> technical feedback too -- bugs, improvements etc. It works, but surely
> it can be made better somehow.
>
> The patch probably won't apply on current svn. I will make a patch
> available for the next release, it will take some time though.
Attached file should apply to svn alright. I've generalized the code and
removed the kred prefixes. I've also finished the mysql schema, and
added the sqlite version.
--
________________________________________________________________
Paul Stevens paul at nfg.nl
NET FACILITIES GROUP GPG/PGP: 1024D/11F8CD31
The Netherlands________________________________http://www.nfg.nl
diff --git a/db.c b/db.c
index a692544..6843fc3 100644
--- a/db.c
+++ b/db.c
@@ -2428,7 +2428,7 @@ int db_imap_append_msg(const char *msgdata, u64_t datalen UNUSED,
}
dbmail_message_store(message);
- result = db_copymsg(message->id, mailbox_idnr, user_idnr, msg_idnr);
+ result = db_copymsg(message->id, 0, mailbox_idnr, user_idnr, msg_idnr);
db_delete_message(message->id);
dbmail_message_free(message);
@@ -3602,7 +3602,32 @@ static u64_t message_get_size(u64_t message_idnr)
return size;
}
-int db_copymsg(u64_t msg_idnr, u64_t mailbox_to, u64_t user_idnr,
+gboolean db_getmailbox_flag(u64_t mailbox_idnr, const char *flagname)
+{
+ gboolean flag = FALSE;
+
+ char query[DEF_QUERYSIZE];
+ memset(query,0,DEF_QUERYSIZE);
+
+ g_return_val_if_fail(mailbox_idnr, 0);
+
+ snprintf(query, DEF_QUERYSIZE, "SELECT %s FROM %smailboxes WHERE mailbox_idnr = %llu", flagname, DBPFX, mailbox_idnr);
+
+ if(db_query(query) == -1)
+ return flag;
+
+ if (db_num_rows() == 0) {
+ TRACE(TRACE_ERROR, "invalid mailbox id (%lld) specified or [%s] doesnt exist", mailbox_idnr, flagname);
+ db_free_result();
+ return flag;
+ }
+ flag = db_get_result_bool(0,0);
+ db_free_result();
+ return flag;
+}
+
+
+int db_copymsg(u64_t msg_idnr, u64_t mailbox_from, u64_t mailbox_to, u64_t user_idnr,
u64_t * newmsg_idnr)
{
u64_t msgsize;
@@ -3610,7 +3635,6 @@ int db_copymsg(u64_t msg_idnr, u64_t mailbox_to, u64_t user_idnr,
char query[DEF_QUERYSIZE];
memset(query,0,DEF_QUERYSIZE);
-
/* Get the size of the message to be copied. */
if (! (msgsize = message_get_size(msg_idnr))) {
TRACE(TRACE_ERROR, "error getting message size for "
@@ -3649,7 +3673,7 @@ int db_copymsg(u64_t msg_idnr, u64_t mailbox_to, u64_t user_idnr,
/* get the id of the inserted record */
*newmsg_idnr = db_insert_result("message_idnr");
-
+
/* update quotum */
if (user_quotum_inc(user_idnr, msgsize) == -1) {
TRACE(TRACE_ERROR, "error setting the new quotum "
@@ -3658,6 +3682,31 @@ int db_copymsg(u64_t msg_idnr, u64_t mailbox_to, u64_t user_idnr,
return DM_EQUERY;
}
+ if(! (mailbox_from && mailbox_to))
+ return DM_EGENERAL;
+
+ gboolean do_src = db_getmailbox_flag(mailbox_from, "cplog_flag");
+ gboolean do_dst = db_getmailbox_flag(mailbox_to, "cplog_flag");
+ gboolean to_trash = db_getmailbox_flag(mailbox_to, "trash_flag");
+
+ if( do_src && (! to_trash) ) {
+ snprintf(query, DEF_QUERYSIZE, "INSERT INTO %scplogs "
+ "(message_idnr, mailbox_idnr, direction) "
+ "VALUES ('%llu','%llu','0')",
+ DBPFX, *newmsg_idnr, mailbox_from);
+ if(db_query(query) == -1)
+ return DM_EQUERY;
+ }
+
+ if( do_dst ) {
+ snprintf(query,DEF_QUERYSIZE, "INSERT INTO %scplogs "
+ "(message_idnr, mailbox_idnr, direction) "
+ "VALUES ('%llu', '%llu', '1')",
+ DBPFX, *newmsg_idnr, mailbox_to);
+ if(db_query(query) == -1)
+ return DM_EQUERY;
+ }
+
return DM_EGENERAL;
}
diff --git a/db.h b/db.h
index 69b1920..f73df91 100644
--- a/db.h
+++ b/db.h
@@ -948,6 +948,12 @@ int db_getmailbox_count(mailbox_t *mb);
int db_getmailbox(mailbox_t * mb);
/**
+ * \brief get flag from mailbox by-name as boolean value
+ *
+ */
+gboolean db_getmailbox_flag(u64_t mailbox_idnr, const char *flagname);
+
+/**
* \brief find owner of a mailbox
* \param mboxid id of mailbox
* \param owner_id will hold owner of mailbox after return
@@ -1100,7 +1106,7 @@ int db_movemsg(u64_t mailbox_to, u64_t mailbox_from);
* - -1 on failure
* - 0 on success
*/
-int db_copymsg(u64_t msg_idnr, u64_t mailbox_to,
+int db_copymsg(u64_t msg_idnr, u64_t mailbox_from, u64_t mailbox_to,
u64_t user_idnr, u64_t * newmsg_idnr);
/**
* \brief get name of mailbox
diff --git a/dbmail-imapsession.h b/dbmail-imapsession.h
index 448a76a..49aaa7c 100644
--- a/dbmail-imapsession.h
+++ b/dbmail-imapsession.h
@@ -40,7 +40,8 @@ typedef struct {
} cmd_store_t;
typedef struct {
- u64_t mailbox_id;
+ u64_t src_box_id;
+ u64_t dst_box_id;
} cmd_copy_t;
typedef int (*IMAP_COMMAND_HANDLER) (struct ImapSession *);
diff --git a/imapcommands.c b/imapcommands.c
index 0f1d1ba..7046c38 100644
--- a/imapcommands.c
+++ b/imapcommands.c
@@ -1668,7 +1668,7 @@ static gboolean _do_copy(u64_t *id, gpointer UNUSED value, struct ImapSession *s
u64_t newid;
int result;
- result = db_copymsg(*id, cmd->mailbox_id, ud->userid, &newid);
+ result = db_copymsg(*id, cmd->src_box_id, cmd->dst_box_id, ud->userid, &newid);
if (result == -1) {
dbmail_imap_session_printf(self, "* BYE internal dbase error\r\n");
db_rollback_transaction();
@@ -1686,22 +1686,24 @@ static gboolean _do_copy(u64_t *id, gpointer UNUSED value, struct ImapSession *s
int _ic_copy(struct ImapSession *self)
{
imap_userdata_t *ud = (imap_userdata_t *) self->ci->userData;
- u64_t destmboxid;
int result;
- mailbox_t destmbox;
+ mailbox_t dst_box;
+ u64_t dst_box_id, src_box_id;
cmd_copy_t cmd;
- memset(&destmbox, 0, sizeof(destmbox));
+ memset(&dst_box, 0, sizeof(dst_box));
+
+ src_box_id = ud->mailbox.uid;
if (!check_state_and_args(self, "COPY", 2, 2, IMAPCS_SELECTED))
return 1; /* error, return */
/* check if destination mailbox exists */
- if (db_findmailbox(self->args[self->args_idx+1], ud->userid, &destmboxid) == -1) {
+ if (db_findmailbox(self->args[self->args_idx+1], ud->userid, &dst_box_id) == -1) {
dbmail_imap_session_printf(self, "* BYE internal dbase error\r\n");
return -1; /* fatal */
}
- if (destmboxid == 0) {
+ if (dst_box_id == 0) {
/* error: cannot select mailbox */
dbmail_imap_session_printf(self,
"%s NO [TRYCREATE] specified mailbox does not exist\r\n",
@@ -1720,8 +1722,8 @@ int _ic_copy(struct ImapSession *self)
return 1;
}
// check if user has right to COPY to destination mailbox
- destmbox.uid = destmboxid;
- result = acl_has_right(&destmbox, ud->userid, ACL_RIGHT_INSERT);
+ dst_box.uid = dst_box_id;
+ result = acl_has_right(&dst_box, ud->userid, ACL_RIGHT_INSERT);
if (result < 0) {
dbmail_imap_session_printf(self, "* BYE internal database error\r\n");
return -1; /* fatal */
@@ -1732,7 +1734,9 @@ int _ic_copy(struct ImapSession *self)
return 1;
}
- cmd.mailbox_id = destmboxid;
+ cmd.src_box_id = src_box_id;
+ cmd.dst_box_id = dst_box_id;
+
self->cmd = &cmd;
/* reopen the mailbox */
diff --git a/sort.c b/sort.c
index 62a820c..6257491 100644
--- a/sort.c
+++ b/sort.c
@@ -181,7 +181,7 @@ dsn_class_t sort_deliver_to_mailbox(struct DbmailMessage *message,
}
// Ok, we have the ACL right, time to deliver the message.
- switch (db_copymsg(message->id, mboxidnr, useridnr, &newmsgidnr)) {
+ switch (db_copymsg(message->id, 0, mboxidnr, useridnr, &newmsgidnr)) {
case -2:
TRACE(TRACE_DEBUG, "error copying message to user [%llu],"
"maxmail exceeded", useridnr);
diff --git a/sql/mysql/2_2_x-2_3_0.mysql b/sql/mysql/2_2_x-2_3_0.mysql
new file mode 100644
index 0000000..8c8e9e6
--- /dev/null
+++ b/sql/mysql/2_2_x-2_3_0.mysql
@@ -0,0 +1,19 @@
+
+DROP TABLE IF EXISTS dbmail_cplogs;
+CREATE TABLE `dbmail_cplogs` (
+ `id` bigint(21) NOT NULL auto_increment,
+ `message_idnr` bigint(21) NOT NULL,
+ `mailbox_idnr` bigint(21) NOT NULL,
+ `direction` tinyint(1) NOT NULL,
+ PRIMARY KEY (`id`)
+ FOREIGN KEY (message_idnr)
+ REFERENCES dbmail_messages(message_idnr)
+ ON UPDATE CASCADE ON DELETE CASCADE,
+ FOREIGN KEY (mailbox_idnr)
+ REFERENCES dbmail_mailboxes(mailbox_idnr)
+ ON UPDATE CASCADE ON DELETE CASCADE,
+) ENGINE=InnoDB;
+
+
+ALTER TABLE dbmail_messages ADD cplog_flag tinyint(1) NOT NULL default '0';
+ALTER TABLE dbmail_messages ADD trash_flag tinyint(1) NOT NULL default '0';
diff --git a/sql/sqlite/2_2_x-2_3_0.sqlite b/sql/sqlite/2_2_x-2_3_0.sqlite
new file mode 100644
index 0000000..b50d333
--- /dev/null
+++ b/sql/sqlite/2_2_x-2_3_0.sqlite
@@ -0,0 +1,81 @@
+
+-- support faster FETCH commands by caching BODYSTRUCTURE and ENVELOPE information
+
+CREATE TABLE dbmail_cplogs (
+ id INTEGER NOT NULL PRIMARY KEY,
+ message_idnr INTEGER NOT NULL,
+ mailbox_idnr INTEGER NOT NULL,
+ direction boolean default '0' NOT NULL
+);
+
+-- FOREIGN KEY (message_idnr)
+-- REFERENCES dbmail_messages(message_idnr)
+-- ON UPDATE CASCADE ON DELETE CASCADE,
+
+CREATE TRIGGER fk_insert_cplogs_message_idnr
+ BEFORE INSERT ON dbmail_cplogs
+ FOR EACH ROW BEGIN
+ SELECT CASE
+ WHEN (new.message_idnr IS NOT NULL)
+ AND ((SELECT message_idnr FROM dbmail_messages WHERE message_idnr = new.message_idnr) IS NULL)
+ THEN RAISE (ABORT, 'insert on table "dbmail_cplogs" violates foreign key constraint "fk_insert_cplogs_message_idnr"')
+ END;
+ END;
+CREATE TRIGGER fk_update1_cplogs_message_idnr
+ BEFORE UPDATE ON dbmail_cplogs
+ FOR EACH ROW BEGIN
+ SELECT CASE
+ WHEN (new.message_idnr IS NOT NULL)
+ AND ((SELECT message_idnr FROM dbmail_messages WHERE message_idnr = new.message_idnr) IS NULL)
+ THEN RAISE (ABORT, 'update on table "dbmail_cplogs" violates foreign key constraint "fk_update1_cplogs_message_idnr"')
+ END;
+ END;
+CREATE TRIGGER fk_update2_cplogs_message_idnr
+ AFTER UPDATE ON dbmail_messages
+ FOR EACH ROW BEGIN
+ UPDATE dbmail_cplogs SET message_idnr = new.message_idnr WHERE message_idnr = OLD.message_idnr;
+ END;
+CREATE TRIGGER fk_delete_cplogs_message_idnr
+ BEFORE DELETE ON dbmail_messages
+ FOR EACH ROW BEGIN
+ DELETE FROM dbmail_cplogs WHERE message_idnr = OLD.message_idnr;
+ END;
+
+-- FOREIGN KEY (mailbox_idnr)
+-- REFERENCES dbmail_mailboxes(mailbox_idnr)
+-- ON UPDATE CASCADE ON DELETE CASCADE,
+
+CREATE TRIGGER fk_insert_cplogs_mailbox_idnr
+ BEFORE INSERT ON dbmail_cplogs
+ FOR EACH ROW BEGIN
+ SELECT CASE
+ WHEN (new.mailbox_idnr IS NOT NULL)
+ AND ((SELECT mailbox_idnr FROM dbmail_mailboxes WHERE mailbox_idnr = new.mailbox_idnr) IS NULL)
+ THEN RAISE (ABORT, 'insert on table "dbmail_cplogs" violates foreign key constraint "fk_insert_cplogs_mailbox_idnr"')
+ END;
+ END;
+CREATE TRIGGER fk_update1_cplogs_mailbox_idnr
+ BEFORE UPDATE ON dbmail_cplogs
+ FOR EACH ROW BEGIN
+ SELECT CASE
+ WHEN (new.mailbox_idnr IS NOT NULL)
+ AND ((SELECT mailbox_idnr FROM dbmail_mailboxes WHERE mailbox_idnr = new.mailbox_idnr) IS NULL)
+ THEN RAISE (ABORT, 'update on table "dbmail_cplogs" violates foreign key constraint "fk_update1_cplogs_mailbox_idnr"')
+ END;
+ END;
+CREATE TRIGGER fk_update2_cplogs_mailbox_idnr
+ AFTER UPDATE ON dbmail_mailboxes
+ FOR EACH ROW BEGIN
+ UPDATE dbmail_cplogs SET mailbox_idnr = new.mailbox_idnr WHERE mailbox_idnr = OLD.mailbox_idnr;
+ END;
+CREATE TRIGGER fk_delete_cplogs_mailbox_idnr
+ BEFORE DELETE ON dbmail_mailboxes
+ FOR EACH ROW BEGIN
+ DELETE FROM dbmail_cplogs WHERE mailbox_idnr = OLD.mailbox_idnr;
+ END;
+
+
+
+ALTER TABLE dbmail_mailboxes ADD cplog_flag BOOLEAN DEFAULT '0' NOT NULL;
+ALTER TABLE dbmail_mailboxes ADD trash_flag BOOLEAN DEFAULT '0' NOT NULL;
+
_______________________________________________
DBmail mailing list
[email protected]
https://mailman.fastxs.nl/mailman/listinfo/dbmail