diff options
-rw-r--r-- | check_dbmail_misc.c | 4 | ||||
-rw-r--r-- | db.c | 160 | ||||
-rw-r--r-- | db.h | 38 | ||||
-rw-r--r-- | dbmail-imapsession.c | 13 | ||||
-rw-r--r-- | dbmail-mailbox.c | 4 | ||||
-rw-r--r-- | dbmail-message.c | 32 | ||||
-rw-r--r-- | dbmail-message.h | 3 | ||||
-rw-r--r-- | dbmailtypes.h | 8 | ||||
-rw-r--r-- | dbmodule.c | 3 | ||||
-rw-r--r-- | dbmodule.h | 1 | ||||
-rw-r--r-- | export.c | 2 | ||||
-rw-r--r-- | imapcommands.c | 2 | ||||
-rw-r--r-- | maintenance.c | 20 | ||||
-rw-r--r-- | misc.c | 9 | ||||
-rw-r--r-- | misc.h | 3 | ||||
-rw-r--r-- | modules/dbmysql.c | 5 | ||||
-rw-r--r-- | modules/dbpgsql.c | 21 | ||||
-rw-r--r-- | modules/dbsqlite.c | 5 | ||||
-rw-r--r-- | pipe.c | 19 | ||||
-rw-r--r-- | pipe.h | 1 | ||||
-rw-r--r-- | pop3.c | 6 | ||||
-rw-r--r-- | sort.c | 11 |
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"); @@ -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); @@ -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 @@ -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) @@ -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); @@ -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); @@ -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); @@ -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); +} @@ -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; @@ -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); @@ -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; } @@ -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; } } |