2011-11-14 15:57:52 +01:00
/*
* message . c , SJ
*/
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <time.h>
# include <sys/types.h>
# include <sys/mman.h>
# include <sys/socket.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
# include <syslog.h>
# include <piler.h>
# include <zlib.h>
int is_existing_message_id ( struct session_data * sdata , struct _state * state , struct __config * cfg ) {
int rc = 0 ;
char s [ SMALLBUFSIZE ] ;
MYSQL_STMT * stmt ;
MYSQL_BIND bind [ 1 ] ;
my_bool is_null [ 1 ] ;
unsigned long len = 0 ;
stmt = mysql_stmt_init ( & ( sdata - > mysql ) ) ;
if ( ! stmt ) {
if ( cfg - > verbosity > = _LOG_DEBUG ) syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_init() error " , sdata - > ttmpfile , SQL_METADATA_TABLE ) ;
goto ENDE ;
}
snprintf ( s , SMALLBUFSIZE - 1 , " SELECT message_id FROM %s WHERE message_id=? " , SQL_METADATA_TABLE ) ;
if ( mysql_stmt_prepare ( stmt , s , strlen ( s ) ) ) {
syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_prepare() error: %s " , sdata - > ttmpfile , SQL_METADATA_TABLE , mysql_stmt_error ( stmt ) ) ;
goto ENDE ;
}
memset ( bind , 0 , sizeof ( bind ) ) ;
bind [ 0 ] . buffer_type = MYSQL_TYPE_STRING ;
bind [ 0 ] . buffer = state - > message_id ;
bind [ 0 ] . is_null = 0 ;
len = strlen ( state - > message_id ) ; bind [ 0 ] . length = & len ;
if ( mysql_stmt_bind_param ( stmt , bind ) ) {
syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_bind_param() error: %s " , sdata - > ttmpfile , SQL_METADATA_TABLE , mysql_stmt_error ( stmt ) ) ;
goto ENDE ;
}
if ( mysql_stmt_execute ( stmt ) ) {
syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_execute() error: %s " , sdata - > ttmpfile , SQL_METADATA_TABLE , mysql_stmt_error ( stmt ) ) ;
goto ENDE ;
}
memset ( bind , 0 , sizeof ( bind ) ) ;
bind [ 0 ] . buffer_type = MYSQL_TYPE_STRING ;
bind [ 0 ] . buffer = & s [ 0 ] ;
bind [ 0 ] . buffer_length = sizeof ( s ) - 1 ;
bind [ 0 ] . is_null = & is_null [ 0 ] ;
bind [ 0 ] . length = & len ;
if ( mysql_stmt_bind_result ( stmt , bind ) ) {
syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_bind_result() error: %s " , sdata - > ttmpfile , SQL_METADATA_TABLE , mysql_stmt_error ( stmt ) ) ;
goto ENDE ;
}
if ( mysql_stmt_store_result ( stmt ) ) {
syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_store_result() error: %s " , sdata - > ttmpfile , SQL_METADATA_TABLE , mysql_stmt_error ( stmt ) ) ;
goto ENDE ;
}
if ( ! mysql_stmt_fetch ( stmt ) ) {
syslog ( LOG_PRIORITY , " %s: found message_id:*%s*(%ld) null=%d " , sdata - > ttmpfile , s , len , is_null [ 0 ] ) ;
if ( is_null [ 0 ] = = 0 ) rc = 1 ;
}
mysql_stmt_close ( stmt ) ;
ENDE :
return rc ;
}
int is_body_digest_already_stored ( struct session_data * sdata , struct _state * state , struct __config * cfg ) {
int rc = 0 ;
char s [ SMALLBUFSIZE ] ;
MYSQL_RES * res ;
MYSQL_ROW row ;
snprintf ( s , SMALLBUFSIZE - 1 , " SELECT `bodydigest` FROM `%s` WHERE `bodydigest`='%s' " , SQL_METADATA_TABLE , sdata - > bodydigest ) ;
if ( mysql_real_query ( & ( sdata - > mysql ) , s , strlen ( s ) ) = = 0 ) {
res = mysql_store_result ( & ( sdata - > mysql ) ) ;
if ( res ! = NULL ) {
row = mysql_fetch_row ( res ) ;
if ( row ) rc = 1 ;
mysql_free_result ( res ) ;
}
}
return rc ;
}
2011-12-03 23:05:00 +01:00
int store_index_data ( struct session_data * sdata , struct _state * state , uint64 id , struct __config * cfg ) {
2011-11-14 15:57:52 +01:00
int rc ;
2011-12-03 23:05:00 +01:00
char * subj , s [ SMALLBUFSIZE ] ;
MYSQL_STMT * stmt ;
2011-12-30 15:52:59 +01:00
MYSQL_BIND bind [ 5 ] ;
unsigned long len [ 5 ] ;
2011-11-14 15:57:52 +01:00
2011-11-28 14:21:14 +01:00
subj = state - > b_subject ;
if ( * subj = = ' ' ) subj + + ;
2011-11-14 15:57:52 +01:00
2011-12-03 23:05:00 +01:00
stmt = mysql_stmt_init ( & ( sdata - > mysql ) ) ;
if ( ! stmt ) {
if ( cfg - > verbosity > = _LOG_DEBUG ) syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_init() error " , sdata - > ttmpfile , SQL_SPHINX_TABLE ) ;
return ERR ;
}
2012-01-03 00:19:43 +01:00
snprintf ( s , sizeof ( s ) - 1 , " INSERT INTO %s (`id`, `from`, `to`, `subject`, `body`, `arrived`, `sent`, `size`, `direction`, `attachments`, `attachment_types`) values(%llu,?,?,?,?,%ld,%ld,%d,%d,%d,?) " , SQL_SPHINX_TABLE , id , sdata - > now , sdata - > sent , sdata - > tot_len , sdata - > direction , state - > n_attachments ) ;
2011-11-14 15:57:52 +01:00
2011-12-03 23:05:00 +01:00
if ( mysql_stmt_prepare ( stmt , s , strlen ( s ) ) ) {
syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_prepare() error: %s " , sdata - > ttmpfile , SQL_SPHINX_TABLE , mysql_stmt_error ( stmt ) ) ;
return ERR ;
}
2011-11-14 15:57:52 +01:00
2011-12-03 23:05:00 +01:00
2011-12-05 17:18:03 +01:00
fix_email_address_for_sphinx ( state - > b_from ) ;
fix_email_address_for_sphinx ( state - > b_to ) ;
2011-12-03 23:05:00 +01:00
memset ( bind , 0 , sizeof ( bind ) ) ;
bind [ 0 ] . buffer_type = MYSQL_TYPE_STRING ;
bind [ 0 ] . buffer = state - > b_from ;
bind [ 0 ] . is_null = 0 ;
len [ 0 ] = strlen ( state - > b_from ) ; bind [ 0 ] . length = & len [ 0 ] ;
bind [ 1 ] . buffer_type = MYSQL_TYPE_STRING ;
bind [ 1 ] . buffer = state - > b_to ;
bind [ 1 ] . is_null = 0 ;
len [ 1 ] = strlen ( state - > b_to ) ; bind [ 1 ] . length = & len [ 1 ] ;
bind [ 2 ] . buffer_type = MYSQL_TYPE_STRING ;
bind [ 2 ] . buffer = subj ;
bind [ 2 ] . is_null = 0 ;
len [ 2 ] = strlen ( subj ) ; bind [ 2 ] . length = & len [ 2 ] ;
bind [ 3 ] . buffer_type = MYSQL_TYPE_STRING ;
bind [ 3 ] . buffer = state - > b_body ;
bind [ 3 ] . is_null = 0 ;
len [ 3 ] = strlen ( state - > b_body ) ; bind [ 3 ] . length = & len [ 3 ] ;
2011-12-30 15:52:59 +01:00
bind [ 4 ] . buffer_type = MYSQL_TYPE_STRING ;
bind [ 4 ] . buffer = sdata - > attachments ;
bind [ 4 ] . is_null = 0 ;
2012-01-03 00:19:43 +01:00
len [ 4 ] = strlen ( sdata - > attachments ) ; bind [ 4 ] . length = & len [ 4 ] ;
2011-12-30 15:52:59 +01:00
2011-12-03 23:05:00 +01:00
if ( mysql_stmt_bind_param ( stmt , bind ) ) {
syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_bind_param() error: %s " , sdata - > ttmpfile , SQL_SPHINX_TABLE , mysql_stmt_error ( stmt ) ) ;
return ERR ;
}
rc = mysql_stmt_execute ( stmt ) ;
if ( rc ) {
syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_execute error: *%s* " , sdata - > ttmpfile , SQL_SPHINX_TABLE , mysql_error ( & ( sdata - > mysql ) ) ) ;
return ERR ;
}
return OK ;
}
int store_recipients ( struct session_data * sdata , char * to , uint64 id , struct __config * cfg ) {
int rc , ret = OK ;
2012-01-09 23:15:39 +01:00
char * p , * q , s [ SMALLBUFSIZE ] , puf [ SMALLBUFSIZE ] ;
2011-12-03 23:05:00 +01:00
MYSQL_STMT * stmt ;
2012-01-09 23:15:39 +01:00
MYSQL_BIND bind [ 2 ] ;
unsigned long len [ 2 ] ;
2011-12-03 23:05:00 +01:00
stmt = mysql_stmt_init ( & ( sdata - > mysql ) ) ;
if ( ! stmt ) {
if ( cfg - > verbosity > = _LOG_DEBUG ) syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_init() error " , sdata - > ttmpfile , SQL_RECIPIENT_TABLE ) ;
return ERR ;
}
2012-01-09 23:15:39 +01:00
snprintf ( s , sizeof ( s ) - 1 , " INSERT INTO %s (`id`,`to`,`todomain`) VALUES('%llu',?,?) " , SQL_RECIPIENT_TABLE , id ) ;
2011-12-03 23:05:00 +01:00
if ( mysql_stmt_prepare ( stmt , s , strlen ( s ) ) ) {
syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_prepare() error: %s " , sdata - > ttmpfile , SQL_RECIPIENT_TABLE , mysql_stmt_error ( stmt ) ) ;
return ERR ;
}
p = to ;
do {
p = split_str ( p , " " , puf , sizeof ( puf ) - 1 ) ;
2012-01-09 23:15:39 +01:00
q = strchr ( puf , ' @ ' ) ;
if ( q & & strlen ( q ) > 3 & & does_it_seem_like_an_email_address ( puf ) = = 1 ) {
q + + ;
2011-12-03 23:05:00 +01:00
memset ( bind , 0 , sizeof ( bind ) ) ;
bind [ 0 ] . buffer_type = MYSQL_TYPE_STRING ;
bind [ 0 ] . buffer = & puf [ 0 ] ;
bind [ 0 ] . is_null = 0 ;
len [ 0 ] = strlen ( puf ) ; bind [ 0 ] . length = & len [ 0 ] ;
2012-01-09 23:15:39 +01:00
bind [ 1 ] . buffer_type = MYSQL_TYPE_STRING ;
bind [ 1 ] . buffer = q ;
bind [ 1 ] . is_null = 0 ;
len [ 1 ] = strlen ( q ) ; bind [ 1 ] . length = & len [ 1 ] ;
2011-12-03 23:05:00 +01:00
if ( mysql_stmt_bind_param ( stmt , bind ) ) {
syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_bind_param() error: %s " , sdata - > ttmpfile , SQL_RECIPIENT_TABLE , mysql_stmt_error ( stmt ) ) ;
return ERR ;
}
rc = mysql_stmt_execute ( stmt ) ;
if ( rc ) {
syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_execute error: *%s* " , sdata - > ttmpfile , SQL_RECIPIENT_TABLE , mysql_error ( & ( sdata - > mysql ) ) ) ;
ret = ERR ;
}
2012-01-09 23:15:39 +01:00
} else {
syslog ( LOG_PRIORITY , " %s: invalid email address: %s " , sdata - > ttmpfile , puf ) ;
continue ;
2011-12-03 23:05:00 +01:00
}
} while ( p ) ;
return ret ;
2011-11-14 15:57:52 +01:00
}
2012-01-09 23:15:39 +01:00
int update_verification_code ( struct session_data * sdata , struct _state * state , uint64 id , struct __config * cfg ) {
char s [ SMALLBUFSIZE ] , vcode [ MAXBUFSIZE ] , digest [ 2 * DIGEST_LENGTH + 1 ] ;
MYSQL_RES * res ;
MYSQL_ROW row ;
snprintf ( vcode , sizeof ( vcode ) - 1 , " %llu+%s%s%ld%ld%d%d%d%d%s%s%s+ " , id , state - > b_from , state - > message_id , sdata - > now , sdata - > sent , sdata - > tot_len , sdata - > hdr_len , sdata - > direction , state - > n_attachments , sdata - > ttmpfile , sdata - > digest , sdata - > bodydigest ) ;
if ( id > 2 ) {
snprintf ( s , SMALLBUFSIZE - 1 , " SELECT `vcode` FROM `%s` WHERE `id`=%llu OR `id`=%llu ORDER BY `id` ASC " , SQL_METADATA_TABLE , id - 1 , id - 2 ) ;
if ( mysql_real_query ( & ( sdata - > mysql ) , s , strlen ( s ) ) = = 0 ) {
res = mysql_store_result ( & ( sdata - > mysql ) ) ;
if ( res ! = NULL ) {
while ( ( row = mysql_fetch_row ( res ) ) ) {
if ( row ) {
if ( ( char * ) row [ 0 ] ) strncat ( vcode , ( char * ) row [ 0 ] , sizeof ( vcode ) - 1 ) ;
}
}
mysql_free_result ( res ) ;
}
}
}
digest_string ( vcode , & digest [ 0 ] ) ;
if ( cfg - > verbosity > = _LOG_DEBUG ) syslog ( LOG_PRIORITY , " %s: verification data: %s, digest: %s " , sdata - > ttmpfile , vcode , digest ) ;
snprintf ( s , SMALLBUFSIZE - 1 , " UPDATE %s SET `vcode`='%s' WHERE id=%llu " , SQL_METADATA_TABLE , digest , id ) ;
return mysql_real_query ( & ( sdata - > mysql ) , s , strlen ( s ) ) ;
}
2011-11-14 15:57:52 +01:00
int store_meta_data ( struct session_data * sdata , struct _state * state , struct __config * cfg ) {
2011-12-03 23:05:00 +01:00
int rc , ret = ERR ;
2012-01-09 23:15:39 +01:00
char * subj , * p , s [ MAXBUFSIZE ] ;
2011-11-14 15:57:52 +01:00
MYSQL_STMT * stmt ;
MYSQL_BIND bind [ 4 ] ;
unsigned long len [ 4 ] ;
2011-12-03 23:05:00 +01:00
my_ulonglong id = 0 ;
2011-11-14 15:57:52 +01:00
stmt = mysql_stmt_init ( & ( sdata - > mysql ) ) ;
if ( ! stmt ) {
if ( cfg - > verbosity > = _LOG_DEBUG ) syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_init() error " , sdata - > ttmpfile , SQL_METADATA_TABLE ) ;
2011-12-03 23:05:00 +01:00
return ERR ;
2011-11-14 15:57:52 +01:00
}
2011-11-28 14:21:14 +01:00
subj = state - > b_subject ;
if ( * subj = = ' ' ) subj + + ;
2012-01-09 23:15:39 +01:00
snprintf ( s , MAXBUFSIZE - 1 , " INSERT INTO %s (`from`,`fromdomain`,`subject`,`arrived`,`sent`,`size`,`hlen`,`direction`,`attachments`,`piler_id`,`message_id`,`digest`,`bodydigest`) VALUES(?,?,?,%ld,%ld,%d,%d,%d,%d,'%s',?,'%s','%s') " , SQL_METADATA_TABLE , sdata - > now , sdata - > sent , sdata - > tot_len , sdata - > hdr_len , sdata - > direction , state - > n_attachments , sdata - > ttmpfile , sdata - > digest , sdata - > bodydigest ) ;
2011-11-14 15:57:52 +01:00
if ( cfg - > verbosity > = _LOG_DEBUG ) syslog ( LOG_PRIORITY , " %s: meta sql: *%s* " , sdata - > ttmpfile , s ) ;
if ( mysql_stmt_prepare ( stmt , s , strlen ( s ) ) ) {
syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_prepare() error: %s " , sdata - > ttmpfile , SQL_METADATA_TABLE , mysql_stmt_error ( stmt ) ) ;
2011-12-03 23:05:00 +01:00
return ERR ;
2011-11-14 15:57:52 +01:00
}
if ( strlen ( state - > b_to ) < 5 ) {
2012-01-09 23:15:39 +01:00
snprintf ( state - > b_to , SMALLBUFSIZE - 1 , " undisclosed-recipients@no.domain " ) ;
2011-11-14 15:57:52 +01:00
}
2011-12-03 23:05:00 +01:00
memset ( bind , 0 , sizeof ( bind ) ) ;
2011-11-14 15:57:52 +01:00
2011-12-03 23:05:00 +01:00
bind [ 0 ] . buffer_type = MYSQL_TYPE_STRING ;
bind [ 0 ] . buffer = state - > b_from ;
bind [ 0 ] . is_null = 0 ;
len [ 0 ] = strlen ( state - > b_from ) ; bind [ 0 ] . length = & len [ 0 ] ;
2011-11-14 15:57:52 +01:00
2012-01-09 23:15:39 +01:00
p = strchr ( state - > b_from , ' @ ' ) ;
if ( p & & strlen ( p ) > 3 ) {
p + + ;
bind [ 1 ] . buffer_type = MYSQL_TYPE_STRING ;
bind [ 1 ] . buffer = p ;
bind [ 1 ] . is_null = 0 ;
len [ 1 ] = strlen ( p ) ; bind [ 1 ] . length = & len [ 1 ] ;
}
2011-11-14 15:57:52 +01:00
2011-12-03 23:05:00 +01:00
bind [ 2 ] . buffer_type = MYSQL_TYPE_STRING ;
2012-01-09 23:15:39 +01:00
bind [ 2 ] . buffer = subj ;
2011-12-03 23:05:00 +01:00
bind [ 2 ] . is_null = 0 ;
2012-01-09 23:15:39 +01:00
len [ 2 ] = strlen ( subj ) ; bind [ 2 ] . length = & len [ 2 ] ;
bind [ 3 ] . buffer_type = MYSQL_TYPE_STRING ;
bind [ 3 ] . buffer = state - > message_id ;
bind [ 3 ] . is_null = 0 ;
len [ 3 ] = strlen ( state - > message_id ) ; bind [ 3 ] . length = & len [ 3 ] ;
2011-11-14 15:57:52 +01:00
2011-12-03 23:05:00 +01:00
if ( mysql_stmt_bind_param ( stmt , bind ) ) {
syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_bind_param() error: %s " , sdata - > ttmpfile , SQL_METADATA_TABLE , mysql_stmt_error ( stmt ) ) ;
return ERR ;
}
2011-11-14 15:57:52 +01:00
2011-12-03 23:05:00 +01:00
rc = mysql_stmt_execute ( stmt ) ;
2011-11-14 15:57:52 +01:00
2011-12-03 23:05:00 +01:00
if ( rc ) {
syslog ( LOG_PRIORITY , " %s: %s.mysql_stmt_execute() error: *%s* " , sdata - > ttmpfile , SQL_METADATA_TABLE , mysql_error ( & ( sdata - > mysql ) ) ) ;
ret = ERR_EXISTS ;
}
else {
id = mysql_stmt_insert_id ( stmt ) ;
2012-01-09 23:15:39 +01:00
2011-12-03 23:05:00 +01:00
rc = store_recipients ( sdata , state - > b_to , id , cfg ) ;
2011-11-14 15:57:52 +01:00
2011-12-03 23:05:00 +01:00
if ( cfg - > verbosity > = _LOG_DEBUG ) syslog ( LOG_PRIORITY , " %s: stored recipients, rc=%d " , sdata - > ttmpfile , rc ) ;
2011-11-14 15:57:52 +01:00
2011-12-03 23:05:00 +01:00
if ( rc = = OK ) {
2012-01-09 23:15:39 +01:00
rc = update_verification_code ( sdata , state , id , cfg ) ;
if ( cfg - > verbosity > = _LOG_DEBUG ) syslog ( LOG_PRIORITY , " %s: updated verification code, rc=%d " , sdata - > ttmpfile , rc ) ;
2011-12-03 23:05:00 +01:00
rc = store_index_data ( sdata , state , id , cfg ) ;
2011-11-14 15:57:52 +01:00
2011-12-03 23:05:00 +01:00
if ( cfg - > verbosity > = _LOG_DEBUG ) syslog ( LOG_PRIORITY , " %s: stored indexdata, rc=%d " , sdata - > ttmpfile , rc ) ;
2011-11-14 15:57:52 +01:00
2011-12-03 23:05:00 +01:00
if ( rc = = OK )
ret = OK ;
2011-11-14 15:57:52 +01:00
}
2011-12-03 23:05:00 +01:00
}
2011-11-14 15:57:52 +01:00
return ret ;
}
2012-01-07 00:00:36 +01:00
int process_message ( struct session_data * sdata , struct _state * state , struct __config * cfg ) {
2011-11-19 21:25:44 +01:00
int i , rc ;
2011-11-14 15:57:52 +01:00
/* discard if existing message_id */
if ( is_existing_message_id ( sdata , state , cfg ) = = 1 ) {
return ERR_EXISTS ;
}
/* check for existing body digest */
rc = is_body_digest_already_stored ( sdata , state , cfg ) ;
2011-11-19 21:25:44 +01:00
/*
* TODO : check if the bodydigest were stored , then we should
* only store the header and append a ' bodypointer '
*/
2011-11-23 12:24:21 +01:00
/* store base64 encoded file attachments */
2011-11-19 21:25:44 +01:00
2011-11-23 12:24:21 +01:00
if ( state - > n_attachments > 0 ) {
rc = store_attachments ( sdata , state , cfg ) ;
2011-11-19 21:25:44 +01:00
2011-11-23 12:24:21 +01:00
for ( i = 1 ; i < = state - > n_attachments ; i + + ) {
unlink ( state - > attachments [ i ] . internalname ) ;
}
if ( rc ) return ERR ;
2011-11-19 21:25:44 +01:00
}
rc = store_file ( sdata , sdata - > tmpframe , 0 , 0 , cfg ) ;
if ( rc = = 0 ) {
syslog ( LOG_PRIORITY , " %s: error storing message: %s " , sdata - > ttmpfile , sdata - > tmpframe ) ;
return ERR ;
}
2011-11-14 15:57:52 +01:00
rc = store_meta_data ( sdata , state , cfg ) ;
if ( cfg - > verbosity > = _LOG_DEBUG ) syslog ( LOG_PRIORITY , " %s: stored metadata, rc=%d " , sdata - > ttmpfile , rc ) ;
if ( rc = = ERR_EXISTS ) return ERR_EXISTS ;
return OK ;
}