mirror of
https://github.com/deltachat/deltachat-core.git
synced 2025-10-06 03:50:08 +02:00
refactor: moving receiving IMF code to a separate file, moving commandline-code to the corresponding file
This commit is contained in:
parent
236baa8011
commit
4a61a5b0f8
7 changed files with 1232 additions and 1264 deletions
|
@ -32,6 +32,108 @@ your library */
|
|||
#include "../src/mrpgp.h"
|
||||
|
||||
|
||||
/*
|
||||
* Reset database tables. This function is called from Core cmdline.
|
||||
*
|
||||
* Argument is a bitmask, executing single or multiple actions in one call.
|
||||
*
|
||||
* e.g. bitmask 7 triggers actions definded with bits 1, 2 and 4.
|
||||
*/
|
||||
int mrmailbox_reset_tables(mrmailbox_t* ths, int bits)
|
||||
{
|
||||
if( ths == NULL || ths->m_magic != MR_MAILBOX_MAGIC ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mrmailbox_log_info(ths, 0, "Resetting tables (%i)...", bits);
|
||||
|
||||
mrsqlite3_lock(ths->m_sql);
|
||||
|
||||
if( bits & 1 ) {
|
||||
mrsqlite3_execute__(ths->m_sql, "DELETE FROM jobs;");
|
||||
mrmailbox_log_info(ths, 0, "(1) Jobs reset.");
|
||||
}
|
||||
|
||||
if( bits & 2 ) {
|
||||
mrsqlite3_execute__(ths->m_sql, "DELETE FROM acpeerstates;");
|
||||
mrmailbox_log_info(ths, 0, "(2) Peerstates reset.");
|
||||
}
|
||||
|
||||
if( bits & 4 ) {
|
||||
mrsqlite3_execute__(ths->m_sql, "DELETE FROM keypairs;");
|
||||
mrmailbox_log_info(ths, 0, "(4) Private keypairs reset.");
|
||||
}
|
||||
|
||||
if( bits & 8 ) {
|
||||
mrsqlite3_execute__(ths->m_sql, "DELETE FROM contacts WHERE id>" MR_STRINGIFY(MR_CONTACT_ID_LAST_SPECIAL) ";"); /* the other IDs are reserved - leave these rows to make sure, the IDs are not used by normal contacts*/
|
||||
mrsqlite3_execute__(ths->m_sql, "DELETE FROM chats WHERE id>" MR_STRINGIFY(MR_CHAT_ID_LAST_SPECIAL) ";");
|
||||
mrsqlite3_execute__(ths->m_sql, "DELETE FROM chats_contacts;");
|
||||
mrsqlite3_execute__(ths->m_sql, "DELETE FROM msgs WHERE id>" MR_STRINGIFY(MR_MSG_ID_LAST_SPECIAL) ";");
|
||||
mrsqlite3_execute__(ths->m_sql, "DELETE FROM config WHERE keyname LIKE 'imap.%' OR keyname LIKE 'configured%';");
|
||||
mrsqlite3_execute__(ths->m_sql, "DELETE FROM leftgrps;");
|
||||
mrmailbox_log_info(ths, 0, "(8) Rest but server config reset.");
|
||||
}
|
||||
|
||||
mrsqlite3_unlock(ths->m_sql);
|
||||
|
||||
ths->m_cb(ths, MR_EVENT_MSGS_CHANGED, 0, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Clean up the contacts table. This function is called from Core cmdline.
|
||||
*
|
||||
* All contacts not involved in a chat, not blocked and not being a deaddrop
|
||||
* are removed.
|
||||
*
|
||||
* Deleted contacts from the OS address book normally stay in the contacts
|
||||
* database. With this cleanup, they are also removed, as well as all
|
||||
* auto-added contacts, unless they are used in a chat or for blocking purpose.
|
||||
*/
|
||||
static int mrmailbox_cleanup_contacts(mrmailbox_t* ths)
|
||||
{
|
||||
if( ths == NULL || ths->m_magic != MR_MAILBOX_MAGIC ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mrmailbox_log_info(ths, 0, "Cleaning up contacts ...");
|
||||
|
||||
mrsqlite3_lock(ths->m_sql);
|
||||
|
||||
mrsqlite3_execute__(ths->m_sql, "DELETE FROM contacts WHERE id>" MR_STRINGIFY(MR_CONTACT_ID_LAST_SPECIAL) " AND blocked=0 AND NOT EXISTS (SELECT contact_id FROM chats_contacts where contacts.id = chats_contacts.contact_id) AND NOT EXISTS (select from_id from msgs WHERE msgs.from_id = contacts.id);");
|
||||
|
||||
mrsqlite3_unlock(ths->m_sql);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mrmailbox_poke_eml_file(mrmailbox_t* ths, const char* filename)
|
||||
{
|
||||
/* mainly for testing, may be called by mrmailbox_import_spec() */
|
||||
int success = 0;
|
||||
char* data = NULL;
|
||||
size_t data_bytes;
|
||||
|
||||
if( ths == NULL || ths->m_magic != MR_MAILBOX_MAGIC ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( mr_read_file(filename, (void**)&data, &data_bytes, ths) == 0 ) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
mrmailbox_receive_imf(ths, data, data_bytes, "import", 0, 0); /* this static function is the reason why this function is not moved to mrmailbox_imex.c */
|
||||
success = 1;
|
||||
|
||||
cleanup:
|
||||
free(data);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
static int poke_public_key(mrmailbox_t* mailbox, const char* addr, const char* public_key_file)
|
||||
{
|
||||
/* mainly for testing: if the partner does not support Autocrypt,
|
||||
|
|
|
@ -492,7 +492,7 @@
|
|||
<Unit filename="src/mrmailbox_log.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="src/mrmailbox_tools.c">
|
||||
<Unit filename="src/mrmailbox_receive_imf.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="src/mrmimefactory.c">
|
||||
|
|
|
@ -18,7 +18,7 @@ lib_src = [
|
|||
'mrmailbox_e2ee.c',
|
||||
'mrmailbox_imex.c',
|
||||
'mrmailbox_log.c',
|
||||
'mrmailbox_tools.c',
|
||||
'mrmailbox_receive_imf.c',
|
||||
'mrmimefactory.c',
|
||||
'mrmimeparser.c',
|
||||
'mrmsg.c',
|
||||
|
|
|
@ -77,20 +77,12 @@ struct _mrmailbox
|
|||
|
||||
};
|
||||
|
||||
|
||||
void mrmailbox_receive_imf (mrmailbox_t*, const char* imf_raw_not_terminated, size_t imf_raw_bytes, const char* server_folder, uint32_t server_uid, uint32_t flags);
|
||||
uint32_t mrmailbox_send_msg_object (mrmailbox_t*, uint32_t chat_id, mrmsg_t*);
|
||||
void mrmailbox_connect_to_imap (mrmailbox_t*, mrjob_t*);
|
||||
void mrmailbox_wake_lock (mrmailbox_t*);
|
||||
void mrmailbox_wake_unlock (mrmailbox_t*);
|
||||
int mrmailbox_poke_eml_file (mrmailbox_t*, const char* file);
|
||||
int mrmailbox_is_reply_to_known_message__ (mrmailbox_t*, mrmimeparser_t*);
|
||||
int mrmailbox_is_reply_to_messenger_message__ (mrmailbox_t*, mrmimeparser_t*);
|
||||
time_t mrmailbox_correct_bad_timestamp__ (mrmailbox_t* ths, uint32_t chat_id, uint32_t from_id, time_t desired_timestamp, int is_fresh_msg);
|
||||
void mrmailbox_add_or_lookup_contacts_by_mailbox_list__(mrmailbox_t* ths, struct mailimf_mailbox_list* mb_list, int origin, mrarray_t* ids, int* check_self);
|
||||
void mrmailbox_add_or_lookup_contacts_by_address_list__(mrmailbox_t* ths, struct mailimf_address_list* adr_list, int origin, mrarray_t* ids, int* check_self);
|
||||
int mrmailbox_get_archived_count__ (mrmailbox_t*);
|
||||
int mrmailbox_reset_tables (mrmailbox_t*, int bits); /* reset tables but leaves server configuration, 1=jobs, 2=e2ee, 8=rest but server config */
|
||||
int mrmailbox_cleanup_contacts (mrmailbox_t* ths); /* remove all contacts that are not used (e.g. in a chat, or blocked */
|
||||
size_t mrmailbox_get_real_contact_cnt__ (mrmailbox_t*);
|
||||
uint32_t mrmailbox_add_or_lookup_contact__ (mrmailbox_t*, const char* display_name /*can be NULL*/, const char* addr_spec, int origin, int* sth_modified);
|
||||
int mrmailbox_get_contact_origin__ (mrmailbox_t*, uint32_t id, int* ret_blocked);
|
||||
|
|
969
src/mrmailbox.c
969
src/mrmailbox.c
File diff suppressed because it is too large
Load diff
1119
src/mrmailbox_receive_imf.c
Normal file
1119
src/mrmailbox_receive_imf.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,292 +0,0 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Delta Chat Core
|
||||
* Copyright (C) 2017 Björn Petersen
|
||||
* Contact: r10s@b44t.com, http://b44t.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see http://www.gnu.org/licenses/ .
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#include "mrmailbox_internal.h"
|
||||
#include "mrmimeparser.h"
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Add contacts to database on receiving messages
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
static void add_or_lookup_contact_by_addr__(mrmailbox_t* ths, const char* display_name_enc, const char* addr_spec, int origin, mrarray_t* ids, int* check_self)
|
||||
{
|
||||
/* is addr_spec equal to SELF? */
|
||||
int dummy;
|
||||
if( check_self == NULL ) { check_self = &dummy; }
|
||||
|
||||
*check_self = 0;
|
||||
|
||||
char* self_addr = mrsqlite3_get_config__(ths->m_sql, "configured_addr", "");
|
||||
if( strcasecmp(self_addr, addr_spec)==0 ) {
|
||||
*check_self = 1;
|
||||
}
|
||||
free(self_addr);
|
||||
|
||||
if( *check_self ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* add addr_spec if missing, update otherwise */
|
||||
char* display_name_dec = NULL;
|
||||
if( display_name_enc ) {
|
||||
display_name_dec = mr_decode_header_string(display_name_enc);
|
||||
mr_normalize_name(display_name_dec);
|
||||
}
|
||||
|
||||
uint32_t row_id = mrmailbox_add_or_lookup_contact__(ths, display_name_dec /*can be NULL*/, addr_spec, origin, NULL);
|
||||
|
||||
free(display_name_dec);
|
||||
|
||||
if( row_id ) {
|
||||
if( !mrarray_search_id(ids, row_id, NULL) ) {
|
||||
mrarray_add_id(ids, row_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void mrmailbox_add_or_lookup_contacts_by_mailbox_list__(mrmailbox_t* ths, struct mailimf_mailbox_list* mb_list, int origin, mrarray_t* ids, int* check_self)
|
||||
{
|
||||
clistiter* cur;
|
||||
for( cur = clist_begin(mb_list->mb_list); cur!=NULL ; cur=clist_next(cur) ) {
|
||||
struct mailimf_mailbox* mb = (struct mailimf_mailbox*)clist_content(cur);
|
||||
if( mb ) {
|
||||
add_or_lookup_contact_by_addr__(ths, mb->mb_display_name, mb->mb_addr_spec, origin, ids, check_self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void mrmailbox_add_or_lookup_contacts_by_address_list__(mrmailbox_t* ths, struct mailimf_address_list* adr_list, int origin, mrarray_t* ids, int* check_self)
|
||||
{
|
||||
clistiter* cur;
|
||||
for( cur = clist_begin(adr_list->ad_list); cur!=NULL ; cur=clist_next(cur) ) {
|
||||
struct mailimf_address* adr = (struct mailimf_address*)clist_content(cur);
|
||||
if( adr ) {
|
||||
if( adr->ad_type == MAILIMF_ADDRESS_MAILBOX ) {
|
||||
struct mailimf_mailbox* mb = adr->ad_data.ad_mailbox; /* can be NULL */
|
||||
if( mb ) {
|
||||
add_or_lookup_contact_by_addr__(ths, mb->mb_display_name, mb->mb_addr_spec, origin, ids, check_self);
|
||||
}
|
||||
}
|
||||
else if( adr->ad_type == MAILIMF_ADDRESS_GROUP ) {
|
||||
struct mailimf_group* group = adr->ad_data.ad_group; /* can be NULL */
|
||||
if( group && group->grp_mb_list /*can be NULL*/ ) {
|
||||
mrmailbox_add_or_lookup_contacts_by_mailbox_list__(ths, group->grp_mb_list, origin, ids, check_self);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Check if a message is a reply to a known message (messenger or non-messenger)
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
static int is_known_rfc724_mid__(mrmailbox_t* mailbox, const char* rfc724_mid)
|
||||
{
|
||||
if( rfc724_mid ) {
|
||||
sqlite3_stmt* stmt = mrsqlite3_predefine__(mailbox->m_sql, SELECT_id_FROM_msgs_WHERE_cm,
|
||||
"SELECT m.id FROM msgs m "
|
||||
" LEFT JOIN chats c ON m.chat_id=c.id "
|
||||
" WHERE m.rfc724_mid=? "
|
||||
" AND m.chat_id>" MR_STRINGIFY(MR_CHAT_ID_LAST_SPECIAL)
|
||||
" AND c.blocked=0;");
|
||||
sqlite3_bind_text(stmt, 1, rfc724_mid, -1, SQLITE_STATIC);
|
||||
if( sqlite3_step(stmt) == SQLITE_ROW ) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int is_known_rfc724_mid_in_list__(mrmailbox_t* mailbox, const clist* mid_list)
|
||||
{
|
||||
if( mid_list ) {
|
||||
clistiter* cur;
|
||||
for( cur = clist_begin(mid_list); cur!=NULL ; cur=clist_next(cur) ) {
|
||||
if( is_known_rfc724_mid__(mailbox, clist_content(cur)) ) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int mrmailbox_is_reply_to_known_message__(mrmailbox_t* mailbox, mrmimeparser_t* mime_parser)
|
||||
{
|
||||
/* check if the message is a reply to a known message; the replies are identified by the Message-ID from
|
||||
`In-Reply-To`/`References:` (to support non-Delta-Clients) or from `Chat-Predecessor:` (Delta clients, see comment in mrchat.c) */
|
||||
|
||||
struct mailimf_optional_field* optional_field;
|
||||
if( (optional_field=mrmimeparser_lookup_optional_field2(mime_parser, "Chat-Predecessor", "X-MrPredecessor")) != NULL )
|
||||
{
|
||||
if( is_known_rfc724_mid__(mailbox, optional_field->fld_value) ) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct mailimf_field* field;
|
||||
if( (field=mrmimeparser_lookup_field(mime_parser, "In-Reply-To"))!=NULL
|
||||
&& field->fld_type == MAILIMF_FIELD_IN_REPLY_TO )
|
||||
{
|
||||
struct mailimf_in_reply_to* fld_in_reply_to = field->fld_data.fld_in_reply_to;
|
||||
if( fld_in_reply_to ) {
|
||||
if( is_known_rfc724_mid_in_list__(mailbox, field->fld_data.fld_in_reply_to->mid_list) ) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( (field=mrmimeparser_lookup_field(mime_parser, "References"))!=NULL
|
||||
&& field->fld_type == MAILIMF_FIELD_REFERENCES )
|
||||
{
|
||||
struct mailimf_references* fld_references = field->fld_data.fld_references;
|
||||
if( fld_references ) {
|
||||
if( is_known_rfc724_mid_in_list__(mailbox, field->fld_data.fld_references->mid_list) ) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Check if a message is a reply to any messenger message
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
static int is_msgrmsg_rfc724_mid__(mrmailbox_t* mailbox, const char* rfc724_mid)
|
||||
{
|
||||
if( rfc724_mid ) {
|
||||
sqlite3_stmt* stmt = mrsqlite3_predefine__(mailbox->m_sql, SELECT_id_FROM_msgs_WHERE_mcm,
|
||||
"SELECT id FROM msgs "
|
||||
" WHERE rfc724_mid=? "
|
||||
" AND msgrmsg!=0 "
|
||||
" AND chat_id>" MR_STRINGIFY(MR_CHAT_ID_LAST_SPECIAL) ";");
|
||||
sqlite3_bind_text(stmt, 1, rfc724_mid, -1, SQLITE_STATIC);
|
||||
if( sqlite3_step(stmt) == SQLITE_ROW ) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int is_msgrmsg_rfc724_mid_in_list__(mrmailbox_t* mailbox, const clist* mid_list)
|
||||
{
|
||||
if( mid_list ) {
|
||||
clistiter* cur;
|
||||
for( cur = clist_begin(mid_list); cur!=NULL ; cur=clist_next(cur) ) {
|
||||
if( is_msgrmsg_rfc724_mid__(mailbox, clist_content(cur)) ) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int mrmailbox_is_reply_to_messenger_message__(mrmailbox_t* mailbox, mrmimeparser_t* mime_parser)
|
||||
{
|
||||
/* function checks, if the message defined by mime_parser references a message send by us from Delta Chat.
|
||||
|
||||
This is similar to is_reply_to_known_message__() but
|
||||
- checks also if any of the referenced IDs are send by a messenger
|
||||
- it is okay, if the referenced messages are moved to trash here
|
||||
- no check for the Chat-* headers (function is only called if it is no messenger message itself) */
|
||||
|
||||
struct mailimf_field* field;
|
||||
if( (field=mrmimeparser_lookup_field(mime_parser, "In-Reply-To"))!=NULL
|
||||
&& field->fld_type==MAILIMF_FIELD_IN_REPLY_TO )
|
||||
{
|
||||
struct mailimf_in_reply_to* fld_in_reply_to = field->fld_data.fld_in_reply_to;
|
||||
if( fld_in_reply_to ) {
|
||||
if( is_msgrmsg_rfc724_mid_in_list__(mailbox, field->fld_data.fld_in_reply_to->mid_list) ) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( (field=mrmimeparser_lookup_field(mime_parser, "References"))!=NULL
|
||||
&& field->fld_type==MAILIMF_FIELD_REFERENCES )
|
||||
{
|
||||
struct mailimf_references* fld_references = field->fld_data.fld_references;
|
||||
if( fld_references ) {
|
||||
if( is_msgrmsg_rfc724_mid_in_list__(mailbox, field->fld_data.fld_references->mid_list) ) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Misc.
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
time_t mrmailbox_correct_bad_timestamp__(mrmailbox_t* ths, uint32_t chat_id, uint32_t from_id, time_t desired_timestamp, int is_fresh_msg)
|
||||
{
|
||||
/* used for correcting timestamps of _received_ messages.
|
||||
use the last message from another user (including SELF) as the MINIMUM
|
||||
(we do this check only for fresh messages, other messages may pop up whereever, this may happen eg. when restoring old messages or synchronizing different clients) */
|
||||
if( is_fresh_msg )
|
||||
{
|
||||
sqlite3_stmt* stmt = mrsqlite3_predefine__(ths->m_sql, SELECT_timestamp_FROM_msgs_WHERE_timestamp,
|
||||
"SELECT MAX(timestamp) FROM msgs WHERE chat_id=? and from_id!=? AND timestamp>=?");
|
||||
sqlite3_bind_int (stmt, 1, chat_id);
|
||||
sqlite3_bind_int (stmt, 2, from_id);
|
||||
sqlite3_bind_int64(stmt, 3, desired_timestamp);
|
||||
if( sqlite3_step(stmt)==SQLITE_ROW )
|
||||
{
|
||||
time_t last_msg_time = sqlite3_column_int64(stmt, 0);
|
||||
if( last_msg_time > 0 /* may happen as we do not check against sqlite3_column_type()!=SQLITE_NULL */ ) {
|
||||
if( desired_timestamp <= last_msg_time ) {
|
||||
desired_timestamp = last_msg_time+1; /* this may result in several incoming messages having the same
|
||||
one-second-after-the-last-other-message-timestamp. however, this is no big deal
|
||||
as we do not try to recrete the order of bad-date-messages and as we always order by ID as second criterion */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* use the (smeared) current time as the MAXIMUM */
|
||||
if( desired_timestamp >= mr_smeared_time__() )
|
||||
{
|
||||
desired_timestamp = mr_create_smeared_timestamp__();
|
||||
}
|
||||
|
||||
return desired_timestamp;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue