summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Cloos <cloos@jhcloos.com>2010-10-19 12:51:48 -0400
committerJames Cloos <cloos@jhcloos.com>2010-10-19 12:58:58 -0400
commitf84cd95ec0cfa009363c0b2c6f36f0fb1fb9eea8 (patch)
tree906e5fe271998bf30224510ec6ffdca46fdaca85
parentcf3b344257d865174912ec685f7d92adfee16844 (diff)
parent6907dcb959f8d3b88ffbf614ba591f0c2bfa6f70 (diff)
Use dense, per mailbox UIDs.denseuid
Signed-off-by: James Cloos <cloos@jhcloos.com>
-rw-r--r--check_dbmail_misc.c4
-rw-r--r--db.c160
-rw-r--r--db.h38
-rw-r--r--dbmail-imapsession.c13
-rw-r--r--dbmail-mailbox.c4
-rw-r--r--dbmail-message.c32
-rw-r--r--dbmail-message.h3
-rw-r--r--dbmailtypes.h8
-rw-r--r--dbmodule.c3
-rw-r--r--dbmodule.h1
-rw-r--r--export.c2
-rw-r--r--imapcommands.c2
-rw-r--r--maintenance.c20
-rw-r--r--misc.c9
-rw-r--r--misc.h3
-rw-r--r--modules/dbmysql.c5
-rw-r--r--modules/dbpgsql.c21
-rw-r--r--modules/dbsqlite.c5
-rw-r--r--pipe.c19
-rw-r--r--pipe.h1
-rw-r--r--pop3.c6
-rw-r--r--sort.c11
22 files changed, 233 insertions, 137 deletions
diff --git a/check_dbmail_misc.c b/check_dbmail_misc.c
index 6d5f4b63..61400655 100644
--- a/check_dbmail_misc.c
+++ b/check_dbmail_misc.c
@@ -246,8 +246,8 @@ START_TEST(test_create_unique_id)
{
char *a = g_new0(char, 64);
char *b = g_new0(char, 64);
- create_unique_id(a,0);
- create_unique_id(b,0);
+ create_unique_id(a,0,0);
+ create_unique_id(b,0,0);
fail_unless(strlen(a)==32, "create_unique_id produced incorrect string length [%s]", a);
fail_unless(strlen(b)==32, "create_unique_id produced incorrect string length [%s]", b);
fail_unless(!MATCH(a,b),"create_unique_id shouldn't produce identical output");
diff --git a/db.c b/db.c
index 746ad3e8..5730e2df 100644
--- a/db.c
+++ b/db.c
@@ -325,7 +325,7 @@ int db_rollback_savepoint_transaction(const char* name)
return DM_SUCCESS;
}
-int db_get_physmessage_id(u64_t message_idnr, u64_t * physmessage_id)
+int db_get_physmessage_id(u64_t mailbox_idnr, u64_t message_idnr, u64_t * physmessage_id)
{
char query[DEF_QUERYSIZE];
memset(query,0,DEF_QUERYSIZE);
@@ -335,7 +335,7 @@ int db_get_physmessage_id(u64_t message_idnr, u64_t * physmessage_id)
snprintf(query, DEF_QUERYSIZE,
"SELECT physmessage_id FROM %smessages "
- "WHERE message_idnr = %" U64_T_FORMAT, DBPFX, message_idnr);
+ "WHERE mailbox_idnr = %" U64_T_FORMAT " AND message_idnr = %" U64_T_FORMAT, DBPFX, mailbox_idnr, message_idnr);
if (db_query(query) == -1) {
TRACE(TRACE_ERROR, "error getting physmessage_id");
@@ -1060,6 +1060,7 @@ int db_get_reply_body(u64_t user_idnr, char **reply_body)
return DM_SUCCESS;
}
+/* Cannot really have this w/ per-mailbox uids.... */
u64_t db_get_mailbox_from_message(u64_t message_idnr)
{
u64_t mailbox_idnr;
@@ -1087,7 +1088,7 @@ u64_t db_get_mailbox_from_message(u64_t message_idnr)
return mailbox_idnr;
}
-u64_t db_get_useridnr(u64_t message_idnr)
+u64_t db_get_useridnr(u64_t mailbox_idnr, u64_t message_idnr)
{
const char *query_result;
u64_t user_idnr;
@@ -1098,8 +1099,9 @@ u64_t db_get_useridnr(u64_t message_idnr)
snprintf(query, DEF_QUERYSIZE,
"SELECT %smailboxes.owner_idnr FROM %smailboxes, %smessages "
"WHERE %smailboxes.mailbox_idnr = %smessages.mailbox_idnr "
+ "AND %smessages.mailbox_idnr = %" U64_T_FORMAT " "
"AND %smessages.message_idnr = %" U64_T_FORMAT, DBPFX,DBPFX,DBPFX,
- DBPFX,DBPFX,DBPFX,message_idnr);
+ DBPFX,DBPFX,DBPFX,mailbox_idnr,DBPFX,message_idnr);
if (db_query(query) == -1) {
/* query failed */
TRACE(TRACE_ERROR, "query failed" );
@@ -1133,12 +1135,14 @@ int db_insert_physmessage_with_internal_date(timestring_t internal_date,
to_date_str = char2date_str(internal_date);
snprintf(query, DEF_QUERYSIZE,
"INSERT INTO %sphysmessage (messagesize, internal_date) "
- "VALUES (0, %s)", DBPFX,to_date_str);
+ "VALUES (0, %s) %s", DBPFX,to_date_str,
+ db_returning("id"));
g_free(to_date_str);
} else {
snprintf(query, DEF_QUERYSIZE,
"INSERT INTO %sphysmessage (messagesize, internal_date) "
- "VALUES (0, %s)", DBPFX,db_get_sql(SQL_CURRENT_TIMESTAMP));
+ "VALUES (0, %s) %s", DBPFX,db_get_sql(SQL_CURRENT_TIMESTAMP),
+ db_returning("id"));
}
if (db_query(query) == -1) {
@@ -1155,7 +1159,7 @@ int db_insert_physmessage(u64_t * physmessage_id)
return db_insert_physmessage_with_internal_date(NULL, physmessage_id);
}
-int db_message_set_unique_id(u64_t message_idnr, const char *unique_id)
+int db_message_set_unique_id(u64_t mailbox_idnr, u64_t message_idnr, const char *unique_id)
{
char query[DEF_QUERYSIZE];
memset(query,0,DEF_QUERYSIZE);
@@ -1164,11 +1168,11 @@ int db_message_set_unique_id(u64_t message_idnr, const char *unique_id)
snprintf(query, DEF_QUERYSIZE,
"UPDATE %smessages SET unique_id = '%s', status = %d "
- "WHERE message_idnr = %" U64_T_FORMAT, DBPFX, unique_id, MESSAGE_STATUS_NEW,
- message_idnr);
+ "WHERE mailbox_idnr = %" U64_T_FORMAT " AND message_idnr = %" U64_T_FORMAT, DBPFX,
+ unique_id, MESSAGE_STATUS_NEW, mailbox_idnr, message_idnr);
if (db_query(query) == DM_EQUERY) {
- TRACE(TRACE_ERROR, "setting unique id for message [%" U64_T_FORMAT "] failed",
- message_idnr);
+ TRACE(TRACE_ERROR, "setting unique id for mailbox [%" U64_T_FORMAT "] message [%" U64_T_FORMAT "] failed",
+ mailbox_idnr, message_idnr);
return DM_EQUERY;
}
return DM_SUCCESS;
@@ -1194,27 +1198,27 @@ int db_physmessage_set_sizes(u64_t physmessage_id, u64_t message_size,
return DM_SUCCESS;
}
-int db_update_message(u64_t message_idnr, const char *unique_id,
+int db_update_message(u64_t mailbox_idnr, u64_t message_idnr, const char *unique_id,
u64_t message_size, u64_t rfc_size)
{
assert(unique_id);
u64_t physmessage_id = 0;
- if (db_message_set_unique_id(message_idnr, unique_id))
+ if (db_message_set_unique_id(mailbox_idnr, message_idnr, unique_id))
return DM_EQUERY;
/* update the fields in the physmessage table */
- if (db_get_physmessage_id(message_idnr, &physmessage_id))
+ if (db_get_physmessage_id(mailbox_idnr, message_idnr, &physmessage_id))
return DM_EQUERY;
if (db_physmessage_set_sizes(physmessage_id, message_size, rfc_size))
return DM_EQUERY;
- if (user_quotum_inc(db_get_useridnr(message_idnr), message_size)) {
+ if (user_quotum_inc(db_get_useridnr(mailbox_idnr, message_idnr), message_size)) {
TRACE(TRACE_ERROR, "error calculating quotum "
"used for user [%" U64_T_FORMAT "]. Database might be "
"inconsistent. Run dbmail-util.",
- db_get_useridnr(message_idnr));
+ db_get_useridnr(mailbox_idnr, message_idnr));
return DM_EQUERY;
}
return DM_SUCCESS;
@@ -1255,8 +1259,8 @@ int db_insert_message_block_physmessage(const char *block,
/* escape & add data */
esclen = db_escape_binary(&escaped_query[startlen], block, block_size);
snprintf(&escaped_query[esclen + startlen],
- maxesclen - esclen - startlen, "', %" U64_T_FORMAT ", %" U64_T_FORMAT ")",
- block_size, physmessage_id);
+ maxesclen - esclen - startlen, "', %" U64_T_FORMAT ", %" U64_T_FORMAT ") %s",
+ block_size, physmessage_id, db_returning("messageblk_idnr"));
if (db_query(escaped_query) == DM_EQUERY) {
g_free(escaped_query);
@@ -1271,7 +1275,7 @@ int db_insert_message_block_physmessage(const char *block,
}
int db_insert_message_block(const char *block, u64_t block_size,
- u64_t message_idnr, u64_t *physmessage_id, u64_t * messageblk_idnr, unsigned is_header)
+ u64_t mailbox_idnr, u64_t message_idnr, u64_t *physmessage_id, u64_t * messageblk_idnr, unsigned is_header)
{
assert(messageblk_idnr != NULL);
*messageblk_idnr = 0;
@@ -1280,7 +1284,7 @@ int db_insert_message_block(const char *block, u64_t block_size,
return DM_EQUERY;
}
- if ((! *physmessage_id) && (db_get_physmessage_id(message_idnr, physmessage_id) == DM_EQUERY)) {
+ if ((! *physmessage_id) && (db_get_physmessage_id(mailbox_idnr, message_idnr, physmessage_id) == DM_EQUERY)) {
TRACE(TRACE_ERROR, "error getting physmessage_id");
return DM_EQUERY;
}
@@ -1600,7 +1604,7 @@ int db_icheck_physmessages(gboolean cleanup)
int db_icheck_messages(struct dm_list *lost_list)
{
- u64_t message_idnr;
+ static box_uid_t box_uid = { .mailbox = 0, .uid = 0 };
int i, n;
char query[DEF_QUERYSIZE];
memset(query,0,DEF_QUERYSIZE);
@@ -1609,7 +1613,7 @@ int db_icheck_messages(struct dm_list *lost_list)
dm_list_init(lost_list);
snprintf(query, DEF_QUERYSIZE,
- "SELECT msg.message_idnr FROM %smessages msg "
+ "SELECT msg.mailbox_idnr, msg.message_idnr FROM %smessages msg "
"LEFT JOIN %smailboxes mbx ON "
"msg.mailbox_idnr=mbx.mailbox_idnr "
"WHERE mbx.mailbox_idnr IS NULL",DBPFX,DBPFX);
@@ -1627,11 +1631,14 @@ int db_icheck_messages(struct dm_list *lost_list)
}
for (i = 0; i < n; i++) {
- if (!(message_idnr = db_get_result_u64(i, 0)))
+ if (!(box_uid.mailbox = db_get_result_u64(i, 0)))
continue;
- TRACE(TRACE_INFO, "found lost message id [%" U64_T_FORMAT "]", message_idnr);
- if (!dm_list_nodeadd(lost_list, &message_idnr, sizeof(u64_t))) {
+ if (!(box_uid.uid = db_get_result_u64(i, 1)))
+ continue;
+
+ TRACE(TRACE_INFO, "found lost message id [%" U64_T_FORMAT "/%" U64_T_FORMAT "]", box_uid.mailbox, box_uid.uid);
+ if (!dm_list_nodeadd(lost_list, &box_uid, sizeof(box_uid_t))) {
TRACE(TRACE_ERROR, "could not add message to list");
dm_list_free(&lost_list->start);
db_free_result();
@@ -1734,7 +1741,7 @@ int db_icheck_null_physmessages(struct dm_list *lost_list)
int db_icheck_null_messages(struct dm_list *lost_list)
{
- u64_t message_idnr;
+ static box_uid_t box_uid = { .mailbox = 0, .uid = 0 };
int i, n;
char query[DEF_QUERYSIZE];
memset(query,0,DEF_QUERYSIZE);
@@ -1743,7 +1750,7 @@ int db_icheck_null_messages(struct dm_list *lost_list)
dm_list_init(lost_list);
snprintf(query, DEF_QUERYSIZE,
- "SELECT msg.message_idnr FROM %smessages msg "
+ "SELECT msg.mailbox_idnr, msg.message_idnr FROM %smessages msg "
"LEFT JOIN %sphysmessage pm ON "
"msg.physmessage_id = pm.id WHERE pm.id is NULL",DBPFX,DBPFX);
@@ -1760,11 +1767,14 @@ int db_icheck_null_messages(struct dm_list *lost_list)
}
for (i = 0; i < n; i++) {
- if (!(message_idnr = db_get_result_u64(i, 0)))
+ if (!(box_uid.mailbox = db_get_result_u64(i, 0)))
+ continue;
+
+ if (!(box_uid.uid = db_get_result_u64(i, 1)))
continue;
- TRACE(TRACE_INFO, "found empty message id [%" U64_T_FORMAT "]", message_idnr);
- if (!dm_list_nodeadd(lost_list, &message_idnr, sizeof(u64_t))) {
+ TRACE(TRACE_INFO, "found empty mailbox id [ %" U64_T_FORMAT "] message id [%" U64_T_FORMAT "]", box_uid.mailbox, box_uid.uid);
+ if (!dm_list_nodeadd(lost_list, &box_uid, sizeof(box_uid_t))) {
TRACE(TRACE_ERROR, "could not add message to list");
dm_list_free(&lost_list->start);
db_free_result();
@@ -2046,13 +2056,13 @@ int db_icheck_envelope(GList **lost)
}
-int db_set_message_status(u64_t message_idnr, MessageStatus_t status)
+int db_set_message_status(u64_t mailbox_idnr, u64_t message_idnr, MessageStatus_t status)
{
char query[DEF_QUERYSIZE];
memset(query,0,DEF_QUERYSIZE);
- snprintf(query, DEF_QUERYSIZE, "UPDATE %smessages SET status = %d WHERE message_idnr = %" U64_T_FORMAT,
- DBPFX, status, message_idnr);
+ snprintf(query, DEF_QUERYSIZE, "UPDATE %smessages SET status = %d WHERE mailbox_idnr = %" U64_T_FORMAT " AND message_idnr = %" U64_T_FORMAT,
+ DBPFX, status, mailbox_idnr, message_idnr);
return db_query(query);
}
@@ -2092,7 +2102,7 @@ int db_delete_physmessage(u64_t physmessage_id)
return DM_EGENERAL;
}
-int db_delete_message(u64_t message_idnr)
+int db_delete_message(u64_t mailbox_idnr, u64_t message_idnr)
{
u64_t physmessage_id;
int rows;
@@ -2100,25 +2110,25 @@ int db_delete_message(u64_t message_idnr)
memset(query,0,DEF_QUERYSIZE);
- if (db_get_physmessage_id(message_idnr, &physmessage_id) == DM_EQUERY)
+ if (db_get_physmessage_id(mailbox_idnr, message_idnr, &physmessage_id) == DM_EQUERY)
return DM_EQUERY;
/* now delete the message from the message table */
snprintf(query, DEF_QUERYSIZE, "DELETE FROM %smessages "
- "WHERE message_idnr = %" U64_T_FORMAT,
- DBPFX, message_idnr);
+ "WHERE mailbox_idnr = %" U64_T_FORMAT " AND message_idnr = %" U64_T_FORMAT,
+ DBPFX, mailbox_idnr, message_idnr);
if (db_query(query) == DM_EQUERY) {
- TRACE(TRACE_ERROR,"error deleting message [%" U64_T_FORMAT "]", message_idnr);
+ TRACE(TRACE_ERROR,"error deleting mailbox [%" U64_T_FORMAT "] message [%" U64_T_FORMAT "]", mailbox_idnr, message_idnr);
return DM_EQUERY;
}
/* find other messages pointing to the same physmessage entry */
- snprintf(query, DEF_QUERYSIZE, "SELECT message_idnr FROM %smessages "
+ snprintf(query, DEF_QUERYSIZE, "SELECT mailbox_idnr, message_idnr FROM %smessages "
"WHERE physmessage_id = %" U64_T_FORMAT,DBPFX, physmessage_id);
if (db_query(query) == -1) {
- TRACE(TRACE_ERROR, "error finding physmessage for message [%" U64_T_FORMAT "]", message_idnr);
+ TRACE(TRACE_ERROR, "error finding physmessage for mailbox [%" U64_T_FORMAT "] message [%" U64_T_FORMAT "]", mailbox_idnr, message_idnr);
return DM_EQUERY;
}
@@ -2183,7 +2193,7 @@ static int mailbox_empty(u64_t mailbox_idnr)
db_free_result();
/* delete every message in the mailbox */
for (i = 0; i < n; i++) {
- if (db_delete_message(message_idnrs[i]) == -1) {
+ if (db_delete_message(mailbox_idnr, message_idnrs[i]) == -1) {
g_free(message_idnrs);
return DM_EQUERY;
}
@@ -2243,7 +2253,7 @@ int db_delete_mailbox(u64_t mailbox_idnr, int only_empty,
return DM_SUCCESS;
}
-int db_send_message_lines(void *fstream, u64_t message_idnr, long lines, int no_end_dot)
+int db_send_message_lines(void *fstream, u64_t mailbox_idnr, u64_t message_idnr, long lines, int no_end_dot)
{
struct DbmailMessage *msg;
@@ -2256,7 +2266,7 @@ int db_send_message_lines(void *fstream, u64_t message_idnr, long lines, int no_
TRACE(TRACE_DEBUG, "request for [%ld] lines", lines);
/* first find the physmessage_id */
- if (db_get_physmessage_id(message_idnr, &physmessage_id) != DM_SUCCESS)
+ if (db_get_physmessage_id(mailbox_idnr, message_idnr, &physmessage_id) != DM_SUCCESS)
return DM_EGENERAL;
TRACE(TRACE_DEBUG, "sending [%ld] lines from message [%" U64_T_FORMAT "]",
@@ -2320,6 +2330,8 @@ int db_createsession(u64_t user_idnr, PopSession_t * session_ptr)
g_return_val_if_fail(mailbox_idnr > 0, DM_EQUERY);
+ session_ptr->mailbox_idnr = mailbox_idnr;
+
/* query is < MESSAGE_STATUS_DELETE because we don't want deleted
* messages
*/
@@ -2420,14 +2432,19 @@ int db_update_pop(PopSession_t * session_ptr)
user_idnr =
db_get_useridnr(((struct message *)
tmpelement->data)->
+ mailbox,
+ ((struct message *)
+ tmpelement->data)->
realmessageid);
/* yes they need an update, do the query */
snprintf(query, DEF_QUERYSIZE,
"UPDATE %smessages set status=%d WHERE "
- "message_idnr=%" U64_T_FORMAT " AND status < %d",DBPFX,
+ "mailbox_idnr=%" U64_T_FORMAT " AND message_idnr=%" U64_T_FORMAT " AND status < %d",DBPFX,
((struct message *)
tmpelement->data)->virtual_messagestatus,
+ ((struct message *)
+ tmpelement->data)->mailbox,
((struct message *) tmpelement->data)->
realmessageid, MESSAGE_STATUS_DELETE);
@@ -2497,6 +2514,7 @@ int db_deleted_purge(u64_t * affected_rows)
char query[DEF_QUERYSIZE];
memset(query,0,DEF_QUERYSIZE);
+ u64_t *mailbox_idnrs;
u64_t *message_idnrs;
assert(affected_rows != NULL);
@@ -2504,12 +2522,12 @@ int db_deleted_purge(u64_t * affected_rows)
/* first we're deleting all the messageblks */
snprintf(query, DEF_QUERYSIZE,
- "SELECT message_idnr FROM %smessages WHERE status=%d",DBPFX,
+ "SELECT mailbox_idnr, message_idnr FROM %smessages WHERE status=%d",DBPFX,
MESSAGE_STATUS_PURGE);
TRACE(TRACE_DEBUG, "executing query [%s]", query);
if (db_query(query) == -1) {
- TRACE(TRACE_ERROR, "Cound not fetch message ID numbers");
+ TRACE(TRACE_ERROR, "Cound not fetch mailbox/message ID number tuples");
return DM_EQUERY;
}
@@ -2520,21 +2538,26 @@ int db_deleted_purge(u64_t * affected_rows)
return DM_SUCCESS;
}
+ mailbox_idnrs = g_new0(u64_t, *affected_rows);
message_idnrs = g_new0(u64_t, *affected_rows);
/* delete each message */
- for (i = 0; i < *affected_rows; i++)
- message_idnrs[i] = db_get_result_u64(i, 0);
-
+ for (i = 0; i < *affected_rows; i++) {
+ mailbox_idnrs[i] = db_get_result_u64(i, 0);
+ message_idnrs[i] = db_get_result_u64(i, 1);
+ }
+
db_free_result();
for (i = 0; i < *affected_rows; i++) {
- if (db_delete_message(message_idnrs[i]) == -1) {
- TRACE(TRACE_ERROR, "error deleting message");
+ if (db_delete_message(mailbox_idnrs[i], message_idnrs[i]) == -1) {
+ TRACE(TRACE_ERROR, "error deleting mailbox [%" U64_T_FORMAT "] message [%" U64_T_FORMAT "]",
+ mailbox_idnrs[i], message_idnrs[i]);
g_free(message_idnrs);
return DM_EQUERY;
}
}
g_free(message_idnrs);
+ g_free(mailbox_idnrs);
return DM_EGENERAL;
}
@@ -2593,8 +2616,8 @@ 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);
- db_delete_message(message->id);
+ result = db_copymsg(message->mailbox, message->id, mailbox_idnr, user_idnr, msg_idnr);
+ db_delete_message(mailbox_idnr, message->id);
dbmail_message_free(message);
switch (result) {
@@ -2615,7 +2638,7 @@ int db_imap_append_msg(const char *msgdata, u64_t datalen UNUSED,
TRACE(TRACE_MESSAGE, "message id=%" U64_T_FORMAT " is inserted", *msg_idnr);
- return db_set_message_status(*msg_idnr, MESSAGE_STATUS_SEEN);
+ return db_set_message_status(mailbox_idnr, *msg_idnr, MESSAGE_STATUS_SEEN);
}
int db_findmailbox(const char *fq_name, u64_t owner_idnr, u64_t * mailbox_idnr)
@@ -3404,8 +3427,9 @@ int db_createmailbox(const char * name, u64_t owner_idnr, u64_t * mailbox_idnr)
"INSERT INTO %smailboxes (name, owner_idnr,"
"seen_flag, answered_flag, deleted_flag, flagged_flag, "
"recent_flag, draft_flag, permission)"
- " VALUES ('%s', %" U64_T_FORMAT ", 1, 1, 1, 1, 1, 1, %d)",DBPFX,
- escaped_simple_name, owner_idnr, IMAPPERM_READWRITE);
+ " VALUES ('%s', %" U64_T_FORMAT ", 1, 1, 1, 1, 1, 1, %d) %s",DBPFX,
+ escaped_simple_name, owner_idnr, IMAPPERM_READWRITE,
+ db_returning("mailbox_idnr"));
g_free(escaped_simple_name);
@@ -3801,7 +3825,7 @@ int db_mailbox_has_message_id(u64_t mailbox_idnr, const char *messageid)
}
-static u64_t message_get_size(u64_t message_idnr)
+static u64_t message_get_size(u64_t mailbox_idnr, u64_t message_idnr)
{
u64_t size = 0;
char query[DEF_QUERYSIZE];
@@ -3811,7 +3835,7 @@ static u64_t message_get_size(u64_t message_idnr)
snprintf(query, DEF_QUERYSIZE,
"SELECT pm.messagesize FROM %sphysmessage pm, %smessages msg "
"WHERE pm.id = msg.physmessage_id "
- "AND message_idnr = %" U64_T_FORMAT,DBPFX,DBPFX, message_idnr);
+ "AND mailbox_idnr = %" U64_T_FORMAT " AND message_idnr = %" U64_T_FORMAT,DBPFX,DBPFX, mailbox_idnr, message_idnr);
if (db_query(query))
return size; /* err */
@@ -3823,8 +3847,8 @@ 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,
- u64_t * newmsg_idnr)
+int db_copymsg(u64_t mailbox_from, u64_t msg_idnr, u64_t mailbox_to,
+ u64_t user_idnr, u64_t * newmsg_idnr)
{
u64_t msgsize;
char unique_id[UID_SIZE];
@@ -3833,9 +3857,9 @@ int db_copymsg(u64_t msg_idnr, u64_t mailbox_to, u64_t user_idnr,
/* Get the size of the message to be copied. */
- if (! (msgsize = message_get_size(msg_idnr))) {
+ if (! (msgsize = message_get_size(mailbox_from, msg_idnr))) {
TRACE(TRACE_ERROR, "error getting message size for "
- "message [%" U64_T_FORMAT "]", msg_idnr);
+ "mailbox [%" U64_T_FORMAT "] message [%" U64_T_FORMAT "]", mailbox_from, msg_idnr);
return DM_EQUERY;
}
@@ -3850,7 +3874,7 @@ int db_copymsg(u64_t msg_idnr, u64_t mailbox_to, u64_t user_idnr,
return -2;
}
- create_unique_id(unique_id, msg_idnr);
+ create_unique_id(unique_id, mailbox_to, msg_idnr);
/* Copy the message table entry of the message. */
snprintf(query, DEF_QUERYSIZE,
@@ -3860,8 +3884,9 @@ int db_copymsg(u64_t msg_idnr, u64_t mailbox_to, u64_t user_idnr,
"SELECT %" U64_T_FORMAT ", "
"physmessage_id, seen_flag, answered_flag, deleted_flag, "
"flagged_flag, recent_flag, draft_flag, '%s', status "
- "FROM %smessages WHERE message_idnr = %" U64_T_FORMAT,DBPFX,
- mailbox_to, unique_id,DBPFX, msg_idnr);
+ "FROM %smessages WHERE mailbox_idnr = %" U64_T_FORMAT " AND message_idnr = %" U64_T_FORMAT " %s",
+ DBPFX, mailbox_to, unique_id, DBPFX, mailbox_from, msg_idnr,
+ db_returning("message_idnr"));
if (db_query(query) == -1) {
TRACE(TRACE_ERROR, "error copying message");
@@ -4914,9 +4939,10 @@ int db_user_create(const char *username, const char *password, const char *encty
snprintf(query, DEF_QUERYSIZE, "INSERT INTO %susers "
"(userid,user_idnr,passwd,client_idnr,maxmail_size,"
"encryption_type, last_login) VALUES "
- "('%s',%" U64_T_FORMAT ",'%s',%" U64_T_FORMAT ",%" U64_T_FORMAT ",'%s', %s)",
+ "('%s',%" U64_T_FORMAT ",'%s',%" U64_T_FORMAT ",%" U64_T_FORMAT ",'%s', %s) %s",
DBPFX,escaped_username,*user_idnr, escaped_password,clientid,
- maxmail, enctype ? enctype : "", db_get_sql(SQL_CURRENT_TIMESTAMP));
+ maxmail, enctype ? enctype : "", db_get_sql(SQL_CURRENT_TIMESTAMP),
+ db_returning("user_idnr"));
}
g_free(escaped_username);
g_free(escaped_password);
diff --git a/db.h b/db.h
index e30ad712..bef7d4a3 100644
--- a/db.h
+++ b/db.h
@@ -177,6 +177,14 @@ u64_t db_get_result_u64(unsigned row, unsigned field);
u64_t db_insert_result(const char *sequence_identifier);
/**
+ * \brief generate a RETURNING clause applicable to the
+ * current database backend.
+ * \param query SELECT-type clause of what to return
+ * \return string to append to INSERT or UPDATE query
+ */
+char *db_returning(char *query);
+
+/**
* \brief escape a string for use in query
* \param to string to copy escaped string to. Must be allocated by caller
* \param from original string
@@ -302,18 +310,19 @@ int db_rollback_savepoint_transaction(const char*);
/* shared implementattion from hereon */
/**
- * \brief get the physmessage_id from a message_idnr
+ * \brief get the physmessage_id from a mailbox_idnr, message_idnr tuple
+ * \param mailbox_idnr
* \param message_idnr
* \param physmessage_id will hold physmessage_id on return. Must hold a valid
* pointer on call.
* \return
* - -1 on error
* - 0 if a physmessage_id was found
- * - 1 if no message with this message_idnr found
+ * - 1 if no message with this mailbox_idnr, message_idnr tuple was found
* \attention function will fail and halt program if physmessage_id is
* NULL on call.
*/
-int db_get_physmessage_id(u64_t message_idnr, /*@out@*/ u64_t * physmessage_id);
+int db_get_physmessage_id(u64_t mailbox_idnr, u64_t message_idnr, /*@out@*/ u64_t * physmessage_id);
/**
* \brief return number of bytes used by user identified by userid
@@ -502,13 +511,14 @@ int db_get_reply_body(u64_t user_idnr, char **body);
/**
* \brief get user idnr of a message.
+ * \param mailbox_idnr idnr of message
* \param message_idnr idnr of message
* \return
* - -1 on failure
* - 0 if message is located in a shared mailbox.
* - user_idnr otherwise
*/
-u64_t db_get_useridnr(u64_t message_idnr);
+u64_t db_get_useridnr(u64_t mailbox_idnr, u64_t message_idnr);
/**
* \brief insert a new physmessage. This inserts only an new record in the
@@ -536,6 +546,7 @@ int db_insert_physmessage_with_internal_date(timestring_t internal_date,
/**
* \brief update unique_id, message_size and rfc_size of
* a message identified by message_idnr
+ * \param mailbox_idnr
* \param message_idnr
* \param unique_id unique id of message
* \param message_size size of message
@@ -544,17 +555,18 @@ int db_insert_physmessage_with_internal_date(timestring_t internal_date,
* - -1 on database error
* - 0 on success
*/
-int db_update_message(u64_t message_idnr, const char *unique_id,
+int db_update_message(u64_t mailbox_idnr, u64_t message_idnr, const char *unique_id,
u64_t message_size, u64_t rfc_size);
/**
* \brief set unique id of a message
+ * \param mailbox_idnr
* \param message_idnr
* \param unique_id unique id of message
* \return
* - -1 on database error
* - 0 on success
*/
-int db_message_set_unique_id(u64_t message_idnr, const char *unique_id);
+int db_message_set_unique_id(u64_t mailbox_idnr, u64_t message_idnr, const char *unique_id);
/**
* \brief set messagesize and rfcsize of a message
@@ -588,6 +600,7 @@ int db_insert_message_block_physmessage(const char *block,
* \brief insert a message block into the message block table
* \param block the message block (which is a string)
* \param block_size length of the block
+* \param mailbox_idnr mailbox of the message the block belongs to
* \param message_idnr id of the message the block belongs to
* \param messageblock_idnr will hold id of messageblock after call. Should
* be a valid pointer on call.
@@ -596,6 +609,7 @@ int db_insert_message_block_physmessage(const char *block,
* - 0 otherwise
*/
int db_insert_message_block(const char *block, u64_t block_size,
+ u64_t mailbox_idnr,
u64_t message_idnr, /*@out@*/ u64_t *physmessage_id,
/*@out@*/ u64_t * messageblock_idnr,
unsigned is_header);
@@ -751,11 +765,12 @@ int db_icheck_envelope(GList **lost);
int db_set_envelope(GList *lost);
/**
* \brief set status of a message
+ * \param mailbox_idnr
* \param message_idnr
* \param status new status of message
* \return result of db_query()
*/
-int db_set_message_status(u64_t message_idnr, MessageStatus_t status);
+int db_set_message_status(u64_t mailbox_idnr, u64_t message_idnr, MessageStatus_t status);
/**
* \brief delete a message block
@@ -774,12 +789,13 @@ int db_delete_physmessage(u64_t physmessage_id);
/**
* \brief delete a message
+ * \param mailbox_idnr
* \param message_idnr
* \return
* - -1 on error
* - 1 on success
*/
-int db_delete_message(u64_t message_idnr);
+int db_delete_message(u64_t mailbox_idnr, u64_t message_idnr);
/**
* \brief delete a mailbox.
@@ -799,6 +815,7 @@ int db_delete_mailbox(u64_t mailbox_idnr, int only_empty,
/**
* \brief write lines of message to fstream. Always write full headers.
* \param fstream the stream to write to
+ * \param mailbox_idnr mailbox of message to write
* \param message_idnr idrn of message to write
* \param lines number of lines to write. If <PRE>lines == -2</PRE>, then
* the whole message (excluding the header) is written.
@@ -810,7 +827,7 @@ int db_delete_mailbox(u64_t mailbox_idnr, int only_empty,
* - 0 on failure
* - 1 on success
*/
-int db_send_message_lines(void *fstream, u64_t message_idnr,
+int db_send_message_lines(void *fstream, u64_t mailbox_idnr, u64_t message_idnr,
long lines, int no_end_dot);
/**
* \brief create a new POP3 session. (was createsession() in dbmysql.c)
@@ -1093,6 +1110,7 @@ int db_removemsg(u64_t user_idnr, u64_t mailbox_idnr);
int db_movemsg(u64_t mailbox_to, u64_t mailbox_from);
/**
* \brief copy a message to a mailbox
+ * \param mailbox_from mailbox to copy from
* \param msg_idnr
* \param mailbox_to mailbox to copy to
* \param user_idnr user to copy the messages for.
@@ -1101,7 +1119,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 mailbox_from, u64_t msg_idnr, u64_t mailbox_to,
u64_t user_idnr, u64_t * newmsg_idnr);
/**
diff --git a/dbmail-imapsession.c b/dbmail-imapsession.c
index f444452f..aa25d057 100644
--- a/dbmail-imapsession.c
+++ b/dbmail-imapsession.c
@@ -362,7 +362,7 @@ static u64_t _imap_cache_update(struct ImapSession *self, message_filter_t filte
cached_msg.dmsg = NULL;
}
- cached_msg.dmsg = db_init_fetch(self->msg_idnr, DBMAIL_MESSAGE_FILTER_FULL);
+ cached_msg.dmsg = db_init_fetch(self->mailbox->id, self->msg_idnr, DBMAIL_MESSAGE_FILTER_FULL);
buf = dbmail_message_to_string(cached_msg.dmsg);
outcnt = _imap_cache_set_dump(buf,IMAP_CACHE_MEMDUMP);
@@ -2078,12 +2078,15 @@ int dbmail_imap_session_mailbox_close(struct ImapSession *self)
return 0;
}
-static int imap_session_update_recent(GList *recent)
+static int imap_session_update_recent(struct DbmailMailbox *mailbox, GList *recent)
{
GList *slices, *topslices;
char query[DEF_QUERYSIZE];
memset(query,0,DEF_QUERYSIZE);
+ if (mailbox == NULL)
+ return 0;
+
if (recent == NULL)
return 0;
@@ -2093,8 +2096,8 @@ static int imap_session_update_recent(GList *recent)
db_begin_transaction();
while (slices) {
snprintf(query, DEF_QUERYSIZE, "UPDATE %smessages SET recent_flag = 0 "
- "WHERE message_idnr IN (%s) AND recent_flag = 1",
- DBPFX, (gchar *)slices->data);
+ "WHERE mailbox_idnr = %" U64_T_FORMAT " AND message_idnr IN (%s) AND recent_flag = 1",
+ DBPFX, mailbox->id, (gchar *)slices->data);
if (db_query(query) == -1) {
db_rollback_transaction();
return (-1);
@@ -2111,7 +2114,7 @@ static int imap_session_update_recent(GList *recent)
int dbmail_imap_session_mailbox_update_recent(struct ImapSession *self)
{
- imap_session_update_recent(self->recent);
+ imap_session_update_recent(self->mailbox, self->recent);
g_list_destroy(self->recent);
self->recent = NULL;
diff --git a/dbmail-mailbox.c b/dbmail-mailbox.c
index 29911e0d..eaaaa198 100644
--- a/dbmail-mailbox.c
+++ b/dbmail-mailbox.c
@@ -326,10 +326,10 @@ int dbmail_mailbox_dump(struct DbmailMailbox *self, FILE *file)
g_string_printf(q,"SELECT is_header,messageblk,%s FROM %smessageblks b "
"JOIN %sphysmessage p ON b.physmessage_id = p.id "
"JOIN %smessages m ON m.physmessage_id = p.id "
- "WHERE message_idnr IN (%s) "
+ "WHERE mailbox_idnr = %" U64_T_FORMAT " AND message_idnr IN (%s) "
"ORDER BY messageblk_idnr ",
date2char,
- DBPFX, DBPFX, DBPFX,
+ DBPFX, DBPFX, DBPFX, self->id,
(char *)slice->data);
if (db_query(q->str) == -1) {
diff --git a/dbmail-message.c b/dbmail-message.c
index e56afc35..0465a90e 100644
--- a/dbmail-message.c
+++ b/dbmail-message.c
@@ -811,7 +811,7 @@ int dbmail_message_store(struct DbmailMessage *self)
break;
}
- create_unique_id(unique_id, user_idnr);
+ create_unique_id(unique_id, user_idnr, user_idnr);
/* create a message record */
if(_message_insert(self, user_idnr, DBMAIL_TEMPMBOX, unique_id) < 0)
return -1;
@@ -829,7 +829,7 @@ int dbmail_message_store(struct DbmailMessage *self)
hdrs = dbmail_message_hdrs_to_string(self);
hdrs_size = (u64_t)dbmail_message_get_hdrs_size(self, FALSE);
- if(db_insert_message_block(hdrs, hdrs_size, self->id, &physmessage_id, &messageblk_idnr,1) < 0) {
+ if(db_insert_message_block(hdrs, hdrs_size, self->mailbox, self->id, &physmessage_id, &messageblk_idnr,1) < 0) {
g_free(hdrs);
return -1;
}
@@ -838,14 +838,14 @@ int dbmail_message_store(struct DbmailMessage *self)
/* store body in several blocks (if needed */
body = dbmail_message_body_to_string(self);
body_size = (u64_t)dbmail_message_get_body_size(self, FALSE);
- if (store_message_in_blocks(body, body_size, self->id, physmessage_id) < 0) {
+ if (store_message_in_blocks(body, body_size, self->mailbox, self->id, physmessage_id) < 0) {
g_free(body);
return -1;
}
g_free(body);
rfcsize = (u64_t)dbmail_message_get_rfcsize(self);
- if (db_update_message(self->id, unique_id, (hdrs_size + body_size), rfcsize) < 0)
+ if (db_update_message(self->mailbox, self->id, unique_id, (hdrs_size + body_size), rfcsize) < 0)
return -1;
/* store message headers */
@@ -899,15 +899,16 @@ int _message_insert(struct DbmailMessage *self,
snprintf(query, DEF_QUERYSIZE, "INSERT INTO "
"%smessages(mailbox_idnr, physmessage_id, unique_id,"
"recent_flag, status) "
- "VALUES (%" U64_T_FORMAT ", %" U64_T_FORMAT ", '%s', 1, %d)",
+ "VALUES (%" U64_T_FORMAT ", %" U64_T_FORMAT ", '%s', 1, %d) %s",
DBPFX, mailboxid, physmessage_id, unique_id,
- MESSAGE_STATUS_INSERT);
+ MESSAGE_STATUS_INSERT, db_returning("message_idnr"));
if (db_query(query) == -1) {
TRACE(TRACE_ERROR, "query failed");
return -1;
}
+ self->mailbox = mailboxid;
self->id = db_insert_result("message_idnr");
return 1;
}
@@ -969,7 +970,7 @@ static int _header_get_id(const struct DbmailMessage *self, const char *header,
}
if (db_num_rows() < 1) {
db_free_result();
- g_string_printf(q, "INSERT INTO %sheadername (headername) VALUES ('%s')", DBPFX, safe_header);
+ g_string_printf(q, "INSERT INTO %sheadername (headername) VALUES ('%s') %s", DBPFX, safe_header, db_returning("id"));
if (db_query(q->str) == -1) {
g_string_free(q,TRUE);
g_free(safe_header);
@@ -1002,6 +1003,19 @@ static gboolean _header_cache(const char UNUSED *key, const char *header, gpoint
if (strchr(header, ' '))
return FALSE;
+ /* only cache the headers nnimap needs: */
+ /* subject from date message-id references in-reply-to xref to newsgroups */
+// if (strcasecmp(header, "to"))
+// if (strcasecmp(header, "date"))
+// if (strcasecmp(header, "from"))
+// if (strcasecmp(header, "subject"))
+// if (strcasecmp(header, "message-id"))
+// if (strcasecmp(header, "references"))
+// if (strcasecmp(header, "in-reply-to"))
+// if (strcasecmp(header, "newsgroups"))
+// if (strcasecmp(header, "xref"))
+// return FALSE;
+
if ((_header_get_id(self, header, &id) < 0))
return TRUE;
@@ -1392,13 +1406,13 @@ struct DbmailMessage * dbmail_message_construct(struct DbmailMessage *self,
/* old stuff moved here from dbmsgbuf.c */
-struct DbmailMessage * db_init_fetch(u64_t msg_idnr, int filter)
+struct DbmailMessage * db_init_fetch(u64_t mailbox_idnr, u64_t msg_idnr, int filter)
{
struct DbmailMessage *msg;
int result;
u64_t physid = 0;
- if ((result = db_get_physmessage_id(msg_idnr, &physid)) != DM_SUCCESS)
+ if ((result = db_get_physmessage_id(mailbox_idnr, msg_idnr, &physid)) != DM_SUCCESS)
return NULL;
msg = dbmail_message_new();
if (! (msg = dbmail_message_retrieve(msg, physid, filter)))
diff --git a/dbmail-message.h b/dbmail-message.h
index 979c105a..7240ad50 100644
--- a/dbmail-message.h
+++ b/dbmail-message.h
@@ -61,6 +61,7 @@ typedef enum DBMAIL_STREAM_TYPE {
} dbmail_stream_t;
struct DbmailMessage {
+ u64_t mailbox;
u64_t id;
u64_t physid;
time_t internal_date;
@@ -172,7 +173,7 @@ char * g_mime_object_get_body(const GMimeObject *object);
* - 1 on success
*/
-struct DbmailMessage * db_init_fetch(u64_t msg_idnr, int filter);
+struct DbmailMessage * db_init_fetch(u64_t mailbox_idnr, u64_t msg_idnr, int filter);
#define db_init_fetch_headers(x) db_init_fetch(x,DBMAIL_MESSAGE_FILTER_HEAD)
#define db_init_fetch_message(x) db_init_fetch(x,DBMAIL_MESSAGE_FILTER_FULL)
diff --git a/dbmailtypes.h b/dbmailtypes.h
index 3bfe912b..8af524ec 100644
--- a/dbmailtypes.h
+++ b/dbmailtypes.h
@@ -146,6 +146,7 @@ typedef struct {
/** all virtual_ definitions are session specific
* when a RSET occurs all will be set to the real values */
struct message {
+ u64_t mailbox; /**< mailbox idnr */
u64_t msize; /**< message size */
u64_t messageid; /**< messageid (from database) */
u64_t realmessageid;
@@ -191,8 +192,9 @@ typedef struct {
char *apop_stamp; /**< timestamp for APOP */
u64_t useridnr; /**< Used by timsieved */
+ u64_t mailbox_idnr;
- u64_t totalsize;/**< total size of messages */
+ u64_t totalsize; /**< total size of messages */
u64_t virtual_totalsize;
u64_t totalmessages; /**< number of messages */
u64_t virtual_totalmessages;
@@ -524,5 +526,9 @@ typedef enum {
IMAP_FLAG_RECENT
} imap_flag_t;
+typedef struct box_uid {
+ u64_t mailbox;
+ u64_t uid;
+} box_uid_t;
#endif
diff --git a/dbmodule.c b/dbmodule.c
index faff1909..aacf9ea6 100644
--- a/dbmodule.c
+++ b/dbmodule.c
@@ -85,6 +85,7 @@ int db_load_driver(void)
|| !g_module_symbol(module, "db_disconnect", (gpointer)&db->disconnect )
|| !g_module_symbol(module, "db_check_connection", (gpointer)&db->check_connection )
|| !g_module_symbol(module, "db_query", (gpointer)&db->query )
+ || !g_module_symbol(module, "db_returning", (gpointer)&db->returning )
|| !g_module_symbol(module, "db_insert_result", (gpointer)&db->insert_result )
|| !g_module_symbol(module, "db_num_rows", (gpointer)&db->num_rows )
|| !g_module_symbol(module, "db_num_fields", (gpointer)&db->num_fields )
@@ -153,6 +154,8 @@ int db_query(const char *the_query)
return result;
}
+char * db_returning(char *query)
+ { return db->returning(query); }
u64_t db_insert_result(const char *sequence_identifier)
{ return db->insert_result(sequence_identifier); }
unsigned db_num_rows(void)
diff --git a/dbmodule.h b/dbmodule.h
index e3f8aa12..847bbb98 100644
--- a/dbmodule.h
+++ b/dbmodule.h
@@ -16,6 +16,7 @@ typedef struct {
int (* disconnect)(void);
int (* check_connection)(void);
int (* query)(const char *the_query);
+ char * (* returning)(char *query);
u64_t (* insert_result)(const char *sequence_identifier);
unsigned (* num_rows)(void);
unsigned (* num_fields)(void);
diff --git a/export.c b/export.c
index cfb2fd30..e7cffe4c 100644
--- a/export.c
+++ b/export.c
@@ -141,7 +141,7 @@ static int mailbox_dump(u64_t mailbox_idnr, const char *dumpfile,
// Set deleted status on each message
// Following this, dbmail-util -p sets purge status
if (delete_after_dump & 2) {
- if (db_set_message_status(*(u64_t *)ids->data, MESSAGE_STATUS_DELETE)) {
+ if (db_set_message_status(mailbox_idnr, *(u64_t *)ids->data, MESSAGE_STATUS_DELETE)) {
qerrorf("Error setting status for message [%" U64_T_FORMAT "]\n", *(u64_t *)ids->data);
result = -1;
}
diff --git a/imapcommands.c b/imapcommands.c
index 26fecc64..1d3dcf36 100644
--- a/imapcommands.c
+++ b/imapcommands.c
@@ -1756,7 +1756,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(self->mailbox->id, *id, cmd->mailbox_id, ud->userid, &newid);
if (result == -1) {
dbmail_imap_session_printf(self, "* BYE internal dbase error\r\n");
db_rollback_transaction();
diff --git a/maintenance.c b/maintenance.c
index 6467905e..d2423b4a 100644
--- a/maintenance.c
+++ b/maintenance.c
@@ -461,12 +461,14 @@ int do_dangling_aliases(void)
return result;
}
+/* FIXME: lostlist needs to be of pairs of ints rather than of ints */
+/* figure out how to recover the individual pairs */
int do_null_messages(void)
{
time_t start, stop;
struct dm_list lostlist;
struct element *el;
- u64_t id;
+ u64_t mailbox, id;
if (no_to_all) {
qprintf("\nChecking DBMAIL for NULL messages...\n");
@@ -494,11 +496,12 @@ int do_null_messages(void)
if (lostlist.total_nodes > 0) {
el = lostlist.start;
while (el) {
- id = *((u64_t *) el->data);
- if (db_set_message_status(id, MESSAGE_STATUS_ERROR) < 0)
- qerrorf("Warning: could not set status on message [%" U64_T_FORMAT "]. Check log.\n", id);
+ mailbox = ((box_uid_t *) el->data)->mailbox;
+ id = ((box_uid_t *) el->data)->uid;
+ if (db_set_message_status(mailbox, id, MESSAGE_STATUS_ERROR) < 0)
+ qerrorf("Warning: could not set status on mailbox [%" U64_T_FORMAT "] message [%" U64_T_FORMAT "]. Check log.\n", mailbox, id);
else
- qverbosef("[%" U64_T_FORMAT "] set to MESSAGE_STATUS_ERROR)\n", id);
+ qverbosef("[%" U64_T_FORMAT "/%" U64_T_FORMAT "] set to MESSAGE_STATUS_ERROR)\n", mailbox, id);
el = el->nextnode;
}
@@ -551,7 +554,7 @@ int do_check_integrity(void)
struct element *el;
const char *action;
int count = 0;
- u64_t id;
+ u64_t mailbox, id;
if (yes_to_all)
action = "Repairing";
@@ -664,12 +667,13 @@ int do_check_integrity(void)
if (lostlist.total_nodes > 0) {
el = lostlist.start;
while (el) {
- id = *((u64_t *) el->data);
+ mailbox = ((box_uid_t *) el->data)->mailbox;
+ id = ((box_uid_t *) el->data)->uid;
if (no_to_all) {
qerrorf("%" U64_T_FORMAT " ", id);
} else if (yes_to_all) {
- if (db_delete_message(id) < 0)
+ if (db_delete_message(mailbox,id) < 0)
qerrorf
("Warning: could not delete message #%" U64_T_FORMAT ". Check log.\n",
id);
diff --git a/misc.c b/misc.c
index c696b973..0db89326 100644
--- a/misc.c
+++ b/misc.c
@@ -95,17 +95,18 @@ int drop_privileges(char *newuser, char *newgroup)
return 0;
}
-void create_unique_id(char *target, u64_t message_idnr)
+void create_unique_id(char *target, u64_t mailbox_idnr, u64_t message_idnr)
{
- char *a_message_idnr, *a_rand;
+ char *a_mailbox_idnr, *a_message_idnr, *a_rand;
char *md5_str;
+ a_mailbox_idnr = g_strdup_printf("%" U64_T_FORMAT,mailbox_idnr);
a_message_idnr = g_strdup_printf("%" U64_T_FORMAT,message_idnr);
a_rand = g_strdup_printf("%d",g_random_int());
if (message_idnr != 0)
- snprintf(target, UID_SIZE, "%s:%s",
- a_message_idnr, a_rand);
+ snprintf(target, UID_SIZE, "%s:%s:%s",
+ a_mailbox_idnr, a_message_idnr, a_rand);
else
snprintf(target, UID_SIZE, "%s", a_rand);
md5_str = dm_md5((unsigned char *)target);
diff --git a/misc.h b/misc.h
index 5993a6ff..51827d6a 100644
--- a/misc.h
+++ b/misc.h
@@ -40,9 +40,10 @@ int drop_privileges(char *newuser, char *newgroup);
/**
* \brief create a unique id for a message (used for pop, stored per message)
* \param target target string. Length should be UID_SIZE
+ * \param message_idnr mailbox_idnr of message
* \param message_idnr message_idnr of message
*/
-void create_unique_id(/*@out@*/ char *target, u64_t message_idnr);
+void create_unique_id(/*@out@*/ char *target, u64_t mailbox_idnr, u64_t message_idnr);
/**
* \brief create a timestring with the current time.
diff --git a/modules/dbmysql.c b/modules/dbmysql.c
index c86287d9..f8a7da4b 100644
--- a/modules/dbmysql.c
+++ b/modules/dbmysql.c
@@ -369,3 +369,8 @@ void db_set_result_set(void *the_result_set)
res = (MYSQL_RES *) the_result_set;
res_changed = 1;
}
+
+char *db_returning(char *query)
+{
+ return g_new0(char, 1);
+}
diff --git a/modules/dbpgsql.c b/modules/dbpgsql.c
index 26eec757..bfecbe11 100644
--- a/modules/dbpgsql.c
+++ b/modules/dbpgsql.c
@@ -243,23 +243,17 @@ const char *db_get_result(unsigned row, unsigned field)
return PQgetvalue(res, row, field);
}
+/* get the result of the RETURNING clause added
+ * by way of db_returning() */
u64_t db_insert_result(const char *sequence_identifier)
{
- char query[DEF_QUERYSIZE];
- memset(query,0,DEF_QUERYSIZE);
-
u64_t insert_result;
- /* postgres uses the currval call on a sequence to determine
- * the result value of an insert query */
- snprintf(query, DEF_QUERYSIZE,
- "SELECT currval('%s%s_seq')",_db_params.pfx, sequence_identifier);
-
- db_query(query);
if (db_num_rows() == 0) {
db_free_result();
return 0;
}
+
insert_result = strtoull(db_get_result(0, 0), NULL, 10);
db_free_result();
return insert_result;
@@ -365,3 +359,12 @@ void db_set_result_set(void *the_result_set)
{
res = (PGresult *) the_result_set;
}
+
+char *db_returning(char *query)
+{
+ unsigned bufferlen = 10 + strlen(query) + 1;
+ char *buffer = g_new0(char, bufferlen);
+ snprintf(buffer, bufferlen,
+ "RETURNING %s", query);
+ return buffer;
+}
diff --git a/modules/dbsqlite.c b/modules/dbsqlite.c
index 94d8d566..6bd31371 100644
--- a/modules/dbsqlite.c
+++ b/modules/dbsqlite.c
@@ -391,3 +391,8 @@ void db_set_result_set(void *the_result_set)
{
lastq = (struct qtmp *)the_result_set;
}
+
+char *db_returning(char *query)
+{
+ return g_new0(char, 1);
+}
diff --git a/pipe.c b/pipe.c
index 1482e4d0..66c7b01b 100644
--- a/pipe.c
+++ b/pipe.c
@@ -502,7 +502,7 @@ static int execute_auto_ran(struct DbmailMessage *message, u64_t useridnr)
int store_message_in_blocks(const char *message, u64_t message_size,
- u64_t msgidnr, u64_t physmsg_id)
+ u64_t mailbox, u64_t msgidnr, u64_t physmsg_id)
{
u64_t tmp_messageblk_idnr;
u64_t rest_size = message_size;
@@ -516,9 +516,9 @@ int store_message_in_blocks(const char *message, u64_t message_size,
rest_size : READ_BLOCK_SIZE);
rest_size = (rest_size < READ_BLOCK_SIZE ?
0 : rest_size - READ_BLOCK_SIZE);
- TRACE(TRACE_DEBUG, "inserting message: size [%llu] block[%d]", message_size, block_nr);
+ TRACE(TRACE_DEBUG, "inserting message: size [%" U64_T_FORMAT "] block[%d]", message_size, block_nr);
if (db_insert_message_block(&message[offset],
- block_size, msgidnr, &physmsg_id,
+ block_size, mailbox, msgidnr, &physmsg_id,
&tmp_messageblk_idnr,0) < 0) {
TRACE(TRACE_ERROR, "db_insert_message_block() failed");
return -1;
@@ -568,7 +568,7 @@ int insert_messages(struct DbmailMessage *message,
struct dm_list *dsnusers)
{
u64_t bodysize, rfcsize;
- u64_t tmpid;
+ u64_t tmpbox, tmpid;
struct element *element;
u64_t msgsize;
@@ -593,7 +593,9 @@ int insert_messages(struct DbmailMessage *message,
if (db_commit_transaction() < 0)
return -1;
- tmpid = message->id; // for later removal
+ /* for later removal */
+ tmpbox = message->mailbox;
+ tmpid = message->id;
bodysize = (u64_t)dbmail_message_get_body_size(message, FALSE);
rfcsize = (u64_t)dbmail_message_get_rfcsize(message);
@@ -702,7 +704,7 @@ int insert_messages(struct DbmailMessage *message,
/* Always delete the temporary message, even if the delivery failed.
* It is the MTA's job to requeue or bounce the message,
* and our job to keep a tidy database ;-) */
- if (db_delete_message(tmpid) < 0)
+ if (db_delete_message(tmpbox, tmpid) < 0)
TRACE(TRACE_ERROR, "failed to delete temporary message [%" U64_T_FORMAT "]", message->id);
TRACE(TRACE_DEBUG, "temporary message deleted from database. Done.");
@@ -755,7 +757,8 @@ int send_alert(u64_t user_idnr, char *subject, char *body)
// Pre-insert the message and get a new_message->id
dbmail_message_store(new_message);
- u64_t tmpid = new_message->id;
+ u64_t tmpbox = new_message->mailbox;
+ u64_t tmpid = new_message->id;
if (sort_deliver_to_mailbox(new_message, user_idnr,
"INBOX", BOX_BRUTEFORCE, msgflags) != DSN_CLASS_OK) {
@@ -763,7 +766,7 @@ int send_alert(u64_t user_idnr, char *subject, char *body)
}
g_free(to);
- db_delete_message(tmpid);
+ db_delete_message(tmpbox, tmpid);
dbmail_message_free(new_message);
return 0;
diff --git a/pipe.h b/pipe.h
index ef7806f7..5b074e8d 100644
--- a/pipe.h
+++ b/pipe.h
@@ -41,6 +41,7 @@ int insert_messages(struct DbmailMessage *message, struct dm_list *dsnusers);
*/
int store_message_in_blocks(const char* message,
u64_t message_size,
+ u64_t mailbox,
u64_t msgidnr,
u64_t physmsg_id);
diff --git a/pop3.c b/pop3.c
index 4f757cd4..88c435db 100644
--- a/pop3.c
+++ b/pop3.c
@@ -92,7 +92,7 @@ int pop3_handle_connection(clientinfo_t * ci)
/* create an unique timestamp + processid for APOP authentication */
session.apop_stamp = g_new0(char,APOP_STAMP_SIZE);
- create_unique_id(unique_id, 0);
+ create_unique_id(unique_id, 0, 0);
snprintf(session.apop_stamp, APOP_STAMP_SIZE, "<%s@%s>", unique_id, myhostname);
if (ci->tx) {
@@ -509,7 +509,7 @@ int pop3(clientinfo_t *ci, char *buffer, PopSession_t * session)
if (msg->messageid == strtoull(value, NULL, 10) && msg->virtual_messagestatus < MESSAGE_STATUS_DELETE) { /* message is not deleted */
msg->virtual_messagestatus = MESSAGE_STATUS_SEEN;
ci_write((FILE *) stream, "+OK %" U64_T_FORMAT " octets\r\n", msg->msize);
- return db_send_message_lines((void *) stream, msg->realmessageid, -2, 0);
+ return db_send_message_lines((void *) stream, session->mailbox_idnr, msg->realmessageid, -2, 0);
}
tmpelement = tmpelement->nextnode;
}
@@ -769,7 +769,7 @@ int pop3(clientinfo_t *ci, char *buffer, PopSession_t * session)
msg = (struct message *) tmpelement->data;
if (msg->messageid == top_messageid && msg->virtual_messagestatus < MESSAGE_STATUS_DELETE) { /* message is not deleted */
ci_write((FILE *) stream, "+OK %" U64_T_FORMAT " lines of message %" U64_T_FORMAT "\r\n", top_lines, top_messageid);
- return db_send_message_lines(stream, msg->realmessageid, top_lines, 0);
+ return db_send_message_lines(stream, session->mailbox_idnr, msg->realmessageid, top_lines, 0);
}
tmpelement = tmpelement->nextnode;
}
diff --git a/sort.c b/sort.c
index bf2bedee..ebe52e83 100644
--- a/sort.c
+++ b/sort.c
@@ -182,7 +182,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->mailbox, message->id, mboxidnr, useridnr, &newmsgidnr)) {
case -2:
TRACE(TRACE_DEBUG, "error copying message to user [%" U64_T_FORMAT "],"
"maxmail exceeded", useridnr);
@@ -192,14 +192,15 @@ dsn_class_t sort_deliver_to_mailbox(struct DbmailMessage *message,
useridnr);
return DSN_CLASS_TEMP;
default:
- TRACE(TRACE_MESSAGE, "message id=%" U64_T_FORMAT ", size=%zd is inserted",
- newmsgidnr, msgsize);
+ TRACE(TRACE_MESSAGE, "message id=%" U64_T_FORMAT ", size=%zd is inserted to mailbox id=%" U64_T_FORMAT "",
+ newmsgidnr, msgsize, mboxidnr);
if (msgflags) {
- TRACE(TRACE_MESSAGE, "message id=%" U64_T_FORMAT ", setting imap flags",
- newmsgidnr);
+ TRACE(TRACE_MESSAGE, "mbox id=%" U64_T_FORMAT ", message id=%" U64_T_FORMAT ", setting imap flags",
+ mboxidnr, newmsgidnr);
db_set_msgflag(newmsgidnr, mboxidnr, msgflags, IMAPFA_ADD);
}
message->id = newmsgidnr;
+ message->mailbox = mboxidnr;
return DSN_CLASS_OK;
}
}