Added recursive parsing
Signed-off-by: Tyrolyean <tyrolyean@tyrolyean.net>
This commit is contained in:
parent
8742db0b36
commit
8ca48344a8
5 changed files with 94 additions and 4 deletions
|
@ -23,7 +23,8 @@
|
|||
|
||||
#include "mail.h"
|
||||
|
||||
struct email_t* mail_from_text(char* message, size_t length);
|
||||
struct email_t* mail_from_text(char* message, size_t length,
|
||||
struct email_t* parent_mail);
|
||||
void redetect_body_head(struct email_t* mail);
|
||||
|
||||
void unravel_multipart_mail(struct email_t* mail);
|
||||
|
|
|
@ -41,6 +41,7 @@ struct email_t{
|
|||
char* boundary;
|
||||
size_t submes_cnt;
|
||||
struct email_t** submes;
|
||||
struct email_t* parent;
|
||||
};
|
||||
|
||||
int append_header(struct email_t* mail, const char* key, const char* value);
|
||||
|
|
|
@ -31,4 +31,7 @@ char* get_value_from_key(size_t* val_len, size_t key_offset,
|
|||
|
||||
char* get_multipart_boundary(char* content_type, size_t content_len,
|
||||
size_t* boundary_len);
|
||||
|
||||
const char* get_next_line(const char* message, size_t len);
|
||||
const char* get_prev_line(const char* message, size_t len_neg);
|
||||
#endif /* TOOLS_H */
|
||||
|
|
60
src/attach.c
60
src/attach.c
|
@ -28,7 +28,12 @@
|
|||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct email_t* mail_from_text(char* message, size_t length){
|
||||
/* Generates an email struct from the given eml text. If the content is
|
||||
* multipart, it will be slit up into several email_ts. This expansion is done
|
||||
* recursively. For the root message set parent_mail to NULL
|
||||
*/
|
||||
struct email_t* mail_from_text(char* message, size_t length,
|
||||
struct email_t* parent_mail){
|
||||
|
||||
struct email_t* mail = malloc(sizeof(struct email_t));;
|
||||
memset(mail, 0, sizeof(struct email_t));
|
||||
|
@ -39,6 +44,7 @@ struct email_t* mail_from_text(char* message, size_t length){
|
|||
mail->is_multipart = false;
|
||||
mail->boundary = NULL;
|
||||
mail->boundary_len = 0;
|
||||
mail->parent = parent_mail;
|
||||
|
||||
redetect_body_head(mail);
|
||||
char* cont_type = search_header_key(mail, "Content-Type");
|
||||
|
@ -157,6 +163,28 @@ void unravel_multipart_mail(struct email_t* mail){
|
|||
"submessages\n", mb_cnt, mb_cnt-1);
|
||||
}
|
||||
|
||||
for(ssize_t i = 0; i < ((ssize_t)mb_cnt)-1; i++){
|
||||
const char * begin_pointer = get_next_line(mail_boundarys[i],
|
||||
mail->message_length -
|
||||
(mail->message - mail_boundarys[i]));
|
||||
|
||||
if(begin_pointer == NULL){
|
||||
continue;
|
||||
}
|
||||
|
||||
const char* end_pointer = get_prev_line(mail_boundarys[i+1],
|
||||
(mail_boundarys[i+1] - begin_pointer));
|
||||
|
||||
if(end_pointer == NULL){
|
||||
continue;
|
||||
}
|
||||
struct email_t *submail = mail_from_text((char*)begin_pointer,
|
||||
end_pointer - begin_pointer, mail);
|
||||
mail->submes = realloc(mail->submes, ++mail->submes_cnt *
|
||||
(sizeof(struct email_t)));
|
||||
mail->submes[mail->submes_cnt - 1] = submail;
|
||||
}
|
||||
|
||||
free(mail_boundarys);
|
||||
free(boundary);
|
||||
return;
|
||||
|
@ -177,6 +205,27 @@ void free_submails(struct email_t* mail){
|
|||
|
||||
}
|
||||
|
||||
void print_mail_structure(struct email_t *email, unsigned int level){
|
||||
|
||||
for(unsigned int i = 0; i < level; i++){
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
if(email->is_multipart){
|
||||
printf("Multipart Message with %lu submessages:\n",
|
||||
email->submes_cnt);
|
||||
for(size_t i = 0; i < email->submes_cnt; i++){
|
||||
print_mail_structure(email->submes[i], level+1);
|
||||
}
|
||||
}else{
|
||||
printf("Final message with length %lu\n",
|
||||
email->message_length);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/* Message is required to be a null terminated string, length is the mail body.
|
||||
* One may leave something behind the body. len is without the '\0'
|
||||
* Attempts to replace files inside the email with links to it on a webserver
|
||||
|
@ -184,8 +233,13 @@ void free_submails(struct email_t* mail){
|
|||
char* attach_files(char* message, size_t len){
|
||||
|
||||
char* mess;
|
||||
struct email_t *email = mail_from_text(message,len);
|
||||
|
||||
struct email_t *email = mail_from_text(message,len, NULL);
|
||||
if(email == NULL){
|
||||
return NULL;
|
||||
}
|
||||
if(verbose){
|
||||
print_mail_structure(email, 0);
|
||||
}
|
||||
/* Check if mails are signed/encrypted, and abort if nescessary */
|
||||
if(abort_on_pgp && detect_pgp(email)){
|
||||
printf("PGP detected, aborting...");
|
||||
|
|
31
src/tools.c
31
src/tools.c
|
@ -150,3 +150,34 @@ char* get_multipart_boundary(char* content_type, size_t content_len,
|
|||
*boundary_len = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns a character pointer to the first character of the next line. */
|
||||
const char* get_next_line(const char* message, size_t len){
|
||||
for(size_t i = 0; i < len-1; i++){
|
||||
if(message[i] == '\n'){
|
||||
return &message[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns a character pointer to the last character of the last line which was
|
||||
* NOT part of a cr lf. The len_neg attribute specifies how far we can go to
|
||||
* the left.
|
||||
*/
|
||||
const char* get_prev_line(const char* message, size_t len_neg){
|
||||
for(size_t i = 0; i < len_neg-2; i++){
|
||||
if(message[-i] == '\n'){
|
||||
if(message[-(i+1)] == '\r'){
|
||||
return &message[i+2];
|
||||
|
||||
}else{
|
||||
return &message[i+2];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue