1
0
Fork 0
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:
B. Petersen 2018-03-02 15:12:52 +01:00
parent 236baa8011
commit 4a61a5b0f8
7 changed files with 1232 additions and 1264 deletions

View file

@ -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,

View file

@ -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">

View file

@ -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',

View file

@ -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);

File diff suppressed because it is too large Load diff

1119
src/mrmailbox_receive_imf.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -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;
}