diff --git a/include/mail.h b/include/mail.h index 9be8423..f7835b7 100644 --- a/include/mail.h +++ b/include/mail.h @@ -71,6 +71,8 @@ struct email_t{ int append_header(struct email_t* mail, const char* key, const char* value); int append_to_header(struct email_t* mail, const char* pair); +int remove_mail(struct email_t* mail); + struct email_t* get_root_mail(struct email_t* mail); void propagate_insert_delete(struct email_t* mail, char* change_p, diff --git a/include/tools.h b/include/tools.h index 42a7f01..fa7bbed 100644 --- a/include/tools.h +++ b/include/tools.h @@ -24,6 +24,8 @@ char* insert_string(char * destination, const char* source, size_t dest_orig_len, size_t offset); +void remove_string(char * string, size_t len, size_t offset, size_t remove); + char* search_header_key(const struct email_t* mail, const char* key); char* get_value_from_key(size_t* val_len, size_t key_offset, @@ -36,4 +38,7 @@ const char* get_next_line(const char* message, size_t len); const char* get_prev_line(const char* message, size_t len_neg); bool detect_base64(const struct email_t* mail); + +void propagate_size_change(struct email_t *mail, ssize_t change); + #endif /* TOOLS_H */ diff --git a/src/attach.c b/src/attach.c index ca9c6b0..b9ec3c4 100644 --- a/src/attach.c +++ b/src/attach.c @@ -358,9 +358,15 @@ int replace_base64_files(struct email_t* mail, const char* dirname){ } } - /* Replace the mail message with some html text TODO */ + /* Delete old attachment */ + if(mail->parent != NULL){ + if(remove_mail(mail) < 0){ + fprintf(stderr, "Failed to remove old attachment!!\n"); + return -1; + } + } return 0; } diff --git a/src/mail.c b/src/mail.c index df6e33f..4f3a02d 100644 --- a/src/mail.c +++ b/src/mail.c @@ -76,7 +76,7 @@ int append_to_header(struct email_t* mail, const char* pair){ if(new_root == NULL){ return -1; } - mail->message_length += strlen(buffer); + propagate_size_change(mail, strlen(buffer)); propagate_root_pointer(root, new_root, old_root); propagate_insert_delete(root, root->message+root_offset, @@ -89,6 +89,60 @@ int append_to_header(struct email_t* mail, const char* pair){ } +int remove_mail(struct email_t* mail){ + + if(mail == NULL || mail->parent == NULL || !mail->parent->is_multipart){ + return -1; + } + + struct email_t* parent = mail->parent; + bool found = false; + for(size_t i = 0; i < parent->submes_cnt; i++){ + + if(parent->submes[i] == mail){ + /* Remove ourselfs from the parent */ + found = true; + } + + if(found && (i+1 < parent->submes_cnt)){ + parent->submes[i] = parent->submes[i+1]; + } + + } + if(!found){ + return -1; + } + + parent->submes_cnt--; + + /* Find the boundary that should come after our content */ + char * after_boundary = + strstr(mail->message+mail->message_length, parent->boundary); + if(after_boundary == NULL){ + return -1; + } + const char * end = get_next_line(after_boundary, + parent->message_length-(after_boundary - parent->message)); + if(end == NULL){ + end = parent->message + parent->message_length; + } + + size_t remove_len = mail->message - end; + struct email_t *root = get_root_mail(mail); + if(root == NULL){ + return -1; + } + size_t remove_offset = mail->message - root->message; + remove_string(root->message, root->message_length, + remove_offset, remove_len); + + propagate_size_change(mail, -remove_len); + propagate_insert_delete(root, mail->message+remove_offset, -remove_len); + + return 0; + +} + struct email_t* get_root_mail(struct email_t* mail){ if(mail == NULL){ diff --git a/src/tools.c b/src/tools.c index 4e23663..069b983 100644 --- a/src/tools.c +++ b/src/tools.c @@ -49,6 +49,19 @@ char* insert_string(char * destination, const char* source, } +/* Takes a string string and removes from offset INCLUDING the character there + * the following remove bytes. Len is without the NULL-termination + */ +void remove_string(char * string, size_t len, size_t offset, size_t remove){ + + + memmove(string+offset, string+offset+remove, len - (offset+remove)); + string[len-remove] = 0; + + return; + +} + /* Searches the given header for the key provided and, if found, returns the * pointer to that key NOT the value */ @@ -186,3 +199,21 @@ const char* get_prev_line(const char* message, size_t len_neg){ return NULL; } + +/* Propagates a size change inside the body UP. This only alters the complete + * BODY length, the header len remains untouched. A positive change tells that + * something was added, a negative one that something was removed. Call this + * from the object you modified. + */ +void propagate_size_change(struct email_t *mail, ssize_t change){ + + if(mail == NULL){ + return; + } + mail->message_length += change; + if(mail->parent != NULL){ + propagate_size_change(mail->parent, change); + } + + return; +}