2022-08-28 09:35:46 +01:00
/*
Copyright 2001 - 2018 John Wiseman G8BPQ
This file is part of LinBPQ / BPQ32 .
LinBPQ / BPQ32 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 .
LinBPQ / BPQ32 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 LinBPQ / BPQ32 . If not , see http : //www.gnu.org/licenses
*/
// Mail and Chat Server for BPQ32 Packet Switch
//
// Housekeeping Module
# include "bpqmail.h"
char * APIENTRY GetBPQDirectory ( ) ;
int LogAge = 7 ;
BOOL DeletetoRecycleBin = FALSE ;
BOOL SuppressMaintEmail = FALSE ;
BOOL GenerateTrafficReport = TRUE ;
BOOL SaveRegDuringMaint = FALSE ;
BOOL OverrideUnsent = FALSE ;
BOOL SendNonDeliveryMsgs = TRUE ;
VOID UpdateWP ( ) ;
double PR = 30 ;
double PUR = 30 ;
double PF = 30 ;
double PNF = 30 ;
int BF = 30 ;
int BNF = 30 ;
//int AP;
//int AB;
int NTSD = 30 ;
int NTSF = 30 ;
int NTSU = 30 ;
char LTFROMString [ 2048 ] ;
char LTTOString [ 2048 ] ;
char LTATString [ 2048 ] ;
struct Override * * LTFROM ;
struct Override * * LTTO ;
struct Override * * LTAT ;
int DeleteLogFiles ( ) ;
VOID SendNonDeliveryMessage ( struct MsgInfo * OldMsg , BOOL Forwarded , int Age ) ;
int CreateWPMessage ( ) ;
int DeleteRedundantMessages ( ) ;
VOID CreateUserReport ( ) ;
UCHAR * APIENTRY GetLogDirectory ( ) ;
time_t LastHouseKeepingTime ;
time_t LastTrafficTime ;
void DeletetoRecycle ( char * FN )
{
# ifdef WIN32
SHFILEOPSTRUCT FileOp ;
FileOp . hwnd = NULL ;
FileOp . wFunc = FO_DELETE ;
FileOp . fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR | FOF_ALLOWUNDO ;
FileOp . pFrom = FN ;
FileOp . pTo = NULL ;
SHFileOperation ( & FileOp ) ;
# else
// On Linux move to Deleted under current directory
char newName [ 256 ] ;
char oldName [ 256 ] ;
strcpy ( oldName , FN ) ;
char * old = FN ;
mkdir ( " Deleted " , S_IRWXU | S_IRWXG | S_IRWXO ) ; // Make sure exists
while ( strchr ( old , ' / ' ) )
{
old = strlop ( old , ' / ' ) ;
}
sprintf ( newName , " Deleted/%s " , old ) ;
rename ( oldName , newName ) ;
# endif
}
VOID FreeOverride ( struct Override * * Hddr )
{
struct Override * * Save ;
if ( Hddr )
{
Save = Hddr ;
while ( Hddr [ 0 ] )
{
free ( Hddr [ 0 ] - > Call ) ;
free ( Hddr [ 0 ] ) ;
Hddr + + ;
}
free ( Save ) ;
}
}
VOID FreeOverrides ( )
{
FreeOverride ( LTFROM ) ;
FreeOverride ( LTTO ) ;
FreeOverride ( LTAT ) ;
}
VOID * GetOverrides ( config_setting_t * group , char * ValueName )
{
char * ptr1 ;
char * MultiString = NULL ;
char * ptr ;
int Count = 0 ;
struct Override * * Value ;
char * Val ;
config_setting_t * setting ;
Value = zalloc ( sizeof ( void * ) ) ; // always NULL entry on end even if no values
Value [ 0 ] = NULL ;
setting = config_setting_get_member ( group , ValueName ) ;
if ( setting )
{
ptr = ( char * ) config_setting_get_string ( setting ) ;
while ( ptr & & strlen ( ptr ) )
{
ptr1 = strchr ( ptr , ' | ' ) ;
if ( ptr1 )
* ( ptr1 + + ) = 0 ;
Value = realloc ( Value , ( Count + 2 ) * sizeof ( void * ) ) ;
Value [ Count ] = zalloc ( sizeof ( struct Override ) ) ;
Val = strlop ( ptr , ' , ' ) ;
if ( Val = = NULL )
break ;
Value [ Count ] - > Call = _strupr ( _strdup ( ptr ) ) ;
Value [ Count + + ] - > Days = atoi ( Val ) ;
ptr = ptr1 ;
}
}
Value [ Count ] = NULL ;
return Value ;
}
VOID * RegGetOverrides ( HKEY hKey , char * ValueName )
{
# ifdef LINBPQ
return NULL ;
# else
int retCode , Type , Vallen ;
char * MultiString ;
int ptr , len ;
int Count = 0 ;
struct Override * * Value ;
char * Val ;
Value = zalloc ( sizeof ( void * ) ) ; // always NULL entry on end even if no values
Value [ 0 ] = NULL ;
Vallen = 0 ;
retCode = RegQueryValueEx ( hKey , ValueName , 0 , ( ULONG * ) & Type , NULL , ( ULONG * ) & Vallen ) ;
if ( ( retCode ! = 0 ) | | ( Vallen = = 0 ) )
return FALSE ;
MultiString = malloc ( Vallen ) ;
retCode = RegQueryValueEx ( hKey , ValueName , 0 ,
( ULONG * ) & Type , ( UCHAR * ) MultiString , ( ULONG * ) & Vallen ) ;
ptr = 0 ;
while ( MultiString [ ptr ] )
{
len = strlen ( & MultiString [ ptr ] ) ;
Value = realloc ( Value , ( Count + 2 ) * sizeof ( void * ) ) ;
Value [ Count ] = zalloc ( sizeof ( struct Override ) ) ;
Val = strlop ( & MultiString [ ptr ] , ' , ' ) ;
if ( Val = = NULL )
break ;
Value [ Count ] - > Call = _strupr ( _strdup ( & MultiString [ ptr ] ) ) ;
Value [ Count + + ] - > Days = atoi ( Val ) ;
ptr + = ( len + 1 ) ;
}
Value [ Count ] = NULL ;
free ( MultiString ) ;
return Value ;
# endif
}
int Removed ;
int Killed ;
int BIDSRemoved ;
# ifndef LINBPQ
INT_PTR CALLBACK HKDialogProc ( HWND hDlg , UINT message , WPARAM wParam , LPARAM lParam )
{
int Command ;
switch ( message )
{
case WM_INITDIALOG :
SetDlgItemInt ( hDlg , IDC_REMOVED , Removed , FALSE ) ;
SetDlgItemInt ( hDlg , IDC_KILLED , Killed , FALSE ) ;
SetDlgItemInt ( hDlg , IDC_LIVE , NumberofMessages - Killed , FALSE ) ;
SetDlgItemInt ( hDlg , IDC_TOTAL , NumberofMessages , FALSE ) ;
SetDlgItemInt ( hDlg , IDC_BIDSREMOVED , BIDSRemoved , FALSE ) ;
SetDlgItemInt ( hDlg , IDC_BIDSLEFT , NumberofBIDs , FALSE ) ;
return ( INT_PTR ) TRUE ;
case WM_COMMAND :
Command = LOWORD ( wParam ) ;
switch ( Command )
{
case IDOK :
case IDCANCEL :
EndDialog ( hDlg , LOWORD ( wParam ) ) ;
return ( INT_PTR ) TRUE ;
}
break ;
}
return 0 ;
}
# endif
VOID DoHouseKeeping ( BOOL Manual )
{
time_t NOW ;
CreateUserReport ( ) ;
UpdateWP ( ) ;
DeleteLogFiles ( ) ;
RemoveKilledMessages ( ) ;
ExpireMessages ( ) ;
GetSemaphore ( & AllocSemaphore , 0 ) ;
ExpireBIDs ( ) ;
FreeSemaphore ( & AllocSemaphore ) ;
if ( LatestMsg > MaxMsgno )
{
GetSemaphore ( & MsgNoSemaphore , 0 ) ;
GetSemaphore ( & AllocSemaphore , 0 ) ;
Renumber_Messages ( ) ;
FreeSemaphore ( & AllocSemaphore ) ;
FreeSemaphore ( & MsgNoSemaphore ) ;
}
if ( ! SuppressMaintEmail )
MailHousekeepingResults ( ) ;
LastHouseKeepingTime = NOW = time ( NULL ) ;
SaveMessageDatabase ( ) ;
SaveConfig ( ConfigName ) ;
GetConfig ( ConfigName ) ;
GetBadWordFile ( ) ; // Reread Badwords
# ifndef LINBPQ
if ( Manual )
DialogBox ( hInst , MAKEINTRESOURCE ( IDD_MAINTRESULTS ) , hWnd , HKDialogProc ) ;
# endif
if ( SendWP )
CreateWPMessage ( ) ;
return ;
}
VOID ExpireMessages ( )
{
struct MsgInfo * Msg ;
int n ;
time_t PRLimit ;
time_t PURLimit ;
time_t PFLimit ;
time_t PNFLimit ;
time_t BFLimit ;
time_t BNFLimit ;
time_t BLimit ;
time_t NTSDLimit ;
time_t NTSULimit ;
time_t NTSFLimit ;
struct Override * * Calls ;
time_t now = time ( NULL ) ;
time_t Future = now + ( 7 * 86400 ) ;
Killed = 0 ;
2024-10-11 15:37:11 +01:00
PRLimit = now - ( time_t ) PR * 86400 ;
PURLimit = now - ( time_t ) PUR * 86400 ;
PFLimit = now - ( time_t ) PF * 86400 ;
PNFLimit = now - ( time_t ) PNF * 86400 ;
BFLimit = now - ( time_t ) BF * 86400 ;
BNFLimit = now - ( time_t ) BNF * 86400 ;
2022-08-28 09:35:46 +01:00
if ( NTSU = = 0 )
{
// Assume all unset
NTSD = 30 ;
NTSU = 30 ;
NTSF = 30 ;
}
NTSDLimit = now - NTSD * 86400 ;
NTSULimit = now - NTSU * 86400 ;
NTSFLimit = now - NTSF * 86400 ;
for ( n = 1 ; n < = NumberofMessages ; n + + )
{
Msg = MsgHddrPtr [ n ] ;
// If from the future, Kill it
if ( Msg - > datecreated > Future )
{
KillMsg ( Msg ) ;
continue ;
}
switch ( Msg - > type )
{
case ' P ' :
switch ( Msg - > status )
{
case ' N ' :
case ' H ' :
// Is it unforwarded or unread?
if ( memcmp ( Msg - > fbbs , zeros , NBMASK ) = = 0 )
{
if ( Msg - > datecreated < PURLimit )
{
if ( SendNonDeliveryMsgs )
2024-10-11 15:37:11 +01:00
SendNonDeliveryMessage ( Msg , TRUE , ( int ) PUR ) ;
2022-08-28 09:35:46 +01:00
KillMsg ( Msg ) ;
}
}
else
{
if ( Msg - > datecreated < PNFLimit )
{
if ( SendNonDeliveryMsgs )
2024-10-11 15:37:11 +01:00
SendNonDeliveryMessage ( Msg , FALSE , ( int ) PNF ) ;
2022-08-28 09:35:46 +01:00
KillMsg ( Msg ) ;
}
}
continue ;
case ' F ' :
if ( Msg - > datechanged < PFLimit ) KillMsg ( Msg ) ;
continue ;
case ' Y ' :
if ( Msg - > datechanged < PRLimit ) KillMsg ( Msg ) ;
continue ;
default :
continue ;
}
case ' T ' :
switch ( Msg - > status )
{
case ' F ' :
if ( Msg - > datechanged < NTSFLimit )
KillMsg ( Msg ) ;
continue ;
case ' D ' :
if ( Msg - > datechanged < NTSDLimit )
KillMsg ( Msg ) ;
continue ;
default :
if ( Msg - > datecreated < NTSULimit )
{
if ( SendNonDeliveryMsgs )
SendNonDeliveryMessage ( Msg , TRUE , NTSU ) ;
KillMsg ( Msg ) ;
}
continue ;
}
case ' B ' :
BLimit = BF ;
BNFLimit = now - BNF * 86400 ;
// Check FROM Overrides
if ( LTFROM )
{
Calls = LTFROM ;
while ( Calls [ 0 ] )
{
if ( strcmp ( Calls [ 0 ] - > Call , Msg - > from ) = = 0 )
{
BLimit = Calls [ 0 ] - > Days ;
goto gotit ;
}
Calls + + ;
}
}
// Check TO Overrides
if ( LTTO )
{
Calls = LTTO ;
while ( Calls [ 0 ] )
{
if ( strcmp ( Calls [ 0 ] - > Call , Msg - > to ) = = 0 )
{
BLimit = Calls [ 0 ] - > Days ;
goto gotit ;
}
Calls + + ;
}
}
// Check AT Overrides
if ( LTAT )
{
Calls = LTAT ;
while ( Calls [ 0 ] )
{
if ( strcmp ( Calls [ 0 ] - > Call , Msg - > via ) = = 0 )
{
BLimit = Calls [ 0 ] - > Days ;
goto gotit ;
}
Calls + + ;
}
}
gotit :
BFLimit = now - BLimit * 86400 ;
if ( OverrideUnsent )
if ( BLimit ! = BF ) // Have we an override?
BNFLimit = BFLimit ;
switch ( Msg - > status )
{
case ' $ ' :
case ' N ' :
case ' ' :
case ' H ' :
if ( Msg - > datecreated < BNFLimit )
KillMsg ( Msg ) ;
break ;
case ' F ' :
case ' Y ' :
if ( Msg - > datecreated < BFLimit )
KillMsg ( Msg ) ;
break ;
}
}
}
}
VOID KillMsg ( struct MsgInfo * Msg )
{
FlagAsKilled ( Msg , FALSE ) ;
Killed + + ;
}
BOOL RemoveKilledMessages ( )
{
struct MsgInfo * Msg ;
struct MsgInfo * * NewMsgHddrPtr ;
char MsgFile [ MAX_PATH ] ;
int i , n ;
Removed = 0 ;
GetSemaphore ( & MsgNoSemaphore , 0 ) ;
GetSemaphore ( & AllocSemaphore , 0 ) ;
FirstMessageIndextoForward = 0 ;
NewMsgHddrPtr = zalloc ( ( NumberofMessages + 1 ) * sizeof ( void * ) ) ;
NewMsgHddrPtr [ 0 ] = MsgHddrPtr [ 0 ] ; // Copy Control Record
i = 0 ;
for ( n = 1 ; n < = NumberofMessages ; n + + )
{
Msg = MsgHddrPtr [ n ] ;
if ( Msg - > status = = ' K ' )
{
sprintf_s ( MsgFile , sizeof ( MsgFile ) , " %s/m_%06d.mes%c " , MailDir , Msg - > number , 0 ) ;
if ( DeletetoRecycleBin )
DeletetoRecycle ( MsgFile ) ;
else
DeleteFile ( MsgFile ) ;
MsgnotoMsg [ Msg - > number ] = NULL ;
free ( Msg ) ;
Removed + + ;
}
else
{
NewMsgHddrPtr [ + + i ] = Msg ;
if ( memcmp ( Msg - > fbbs , zeros , NBMASK ) ! = 0 )
{
if ( FirstMessageIndextoForward = = 0 )
FirstMessageIndextoForward = i ;
}
}
}
NumberofMessages = i ;
NewMsgHddrPtr [ 0 ] - > number = i ;
if ( FirstMessageIndextoForward = = 0 )
FirstMessageIndextoForward = NumberofMessages ;
free ( MsgHddrPtr ) ;
MsgHddrPtr = NewMsgHddrPtr ;
FreeSemaphore ( & MsgNoSemaphore ) ;
FreeSemaphore ( & AllocSemaphore ) ;
return TRUE ;
}
# define MESSAGE_NUMBER_MAX 100000
VOID Renumber_Messages ( )
{
int * NewNumber = ( int * ) 0 ;
struct MsgInfo * Msg ;
struct UserInfo * user = NULL ;
char OldMsgFile [ MAX_PATH ] ;
char NewMsgFile [ MAX_PATH ] ;
int j , lastmsg , result ;
int i , n , s ;
s = sizeof ( int ) * MESSAGE_NUMBER_MAX ;
NewNumber = malloc ( s ) ;
if ( ! NewNumber ) return ;
DeleteRedundantMessages ( ) ; // Make sure there aren't any old mail files, or renumber may fail
memset ( NewNumber , 0 , s ) ;
for ( i = 0 ; i < 100000 ; i + + )
{
MsgnotoMsg [ i ] = NULL ;
}
i = 0 ; // New Message Number
for ( n = 1 ; n < = NumberofMessages ; n + + )
{
Msg = MsgHddrPtr [ n ] ;
NewNumber [ Msg - > number ] = + + i ; // Save so we can update users' last listed count
// New will always be >= old unless something has gone horribly wrong,
// so can rename in place without risk of losing a message
if ( Msg - > number < i )
{
# ifndef LINBPQ
MessageBox ( MainWnd , " Invalid message number detected, quitting " , " BPQMailChat " , MB_OK ) ;
# else
Debugprintf ( " Invalid message number detected, quitting " ) ;
# endif
SaveMessageDatabase ( ) ;
if ( NewNumber ) free ( NewNumber ) ;
return ;
}
if ( Msg - > number ! = i )
{
sprintf ( OldMsgFile , " %s/m_%06d.mes " , MailDir , Msg - > number ) ;
sprintf ( NewMsgFile , " %s/m_%06d.mes " , MailDir , i ) ;
result = rename ( OldMsgFile , NewMsgFile ) ;
if ( result )
{
char Errmsg [ 100 ] ;
sprintf ( Errmsg , " Could not rename message no %d to %d, quitting " , Msg - > number , i ) ;
# ifndef LINBPQ
MessageBox ( MainWnd , Errmsg , " BPQMailChat " , MB_OK ) ;
# else
Debugprintf ( Errmsg ) ;
# endif
SaveMessageDatabase ( ) ;
if ( NewNumber ) free ( NewNumber ) ;
return ;
}
Msg - > number = i ;
MsgnotoMsg [ i ] = Msg ;
}
}
for ( n = 0 ; n < = NumberofUsers ; n + + )
{
user = UserRecPtr [ n ] ;
lastmsg = user - > lastmsg ;
if ( lastmsg < = 0 )
user - > lastmsg = 0 ;
else
{
j = NewNumber [ lastmsg ] ;
if ( j = = 0 )
{
// Last listed has gone. Find next above
while ( + + lastmsg < 65536 )
{
if ( NewNumber [ lastmsg ] ! = 0 )
{
user - > lastmsg = NewNumber [ lastmsg ] ;
break ;
}
}
// Not found, so use latest
user - > lastmsg = i ;
break ;
}
user - > lastmsg = NewNumber [ lastmsg ] ;
}
}
MsgHddrPtr [ 0 ] - > length = LatestMsg = i ;
SaveMessageDatabase ( ) ;
SaveUserDatabase ( ) ;
if ( NewNumber ) free ( NewNumber ) ;
return ;
}
BOOL ExpireBIDs ( )
{
BIDRec * BID ;
BIDRec * * NewBIDRecPtr ;
unsigned short now = LOWORD ( time ( NULL ) / 86400 ) ;
int i , n ;
NewBIDRecPtr = zalloc ( ( NumberofBIDs + 1 ) * sizeof ( BIDRec ) ) ;
NewBIDRecPtr [ 0 ] = BIDRecPtr [ 0 ] ; // Copy Control Record
i = 0 ;
for ( n = 1 ; n < = NumberofBIDs ; n + + )
{
BID = BIDRecPtr [ n ] ;
// Debugprintf("%d %d", BID->u.timestamp, now - BID->u.timestamp);
if ( ( now - BID - > u . timestamp ) < BidLifetime )
NewBIDRecPtr [ + + i ] = BID ;
}
BIDSRemoved = NumberofBIDs - i ;
NumberofBIDs = i ;
NewBIDRecPtr [ 0 ] - > u . msgno = i ;
free ( BIDRecPtr ) ;
BIDRecPtr = NewBIDRecPtr ;
SaveBIDDatabase ( ) ;
return TRUE ;
}
VOID MailHousekeepingResults ( )
{
int Length = 0 ;
char * MailBuffer = malloc ( 10000 ) ;
Length + = sprintf ( & MailBuffer [ Length ] , " Killed Messages Removed %d \r \n " , Removed ) ;
Length + = sprintf ( & MailBuffer [ Length ] , " Messages Killed %d \r \n " , Killed ) ;
Length + = sprintf ( & MailBuffer [ Length ] , " Live Messages %d \r \n " , NumberofMessages - Killed ) ;
Length + = sprintf ( & MailBuffer [ Length ] , " Total Messages %d \r \n " , NumberofMessages ) ;
Length + = sprintf ( & MailBuffer [ Length ] , " BIDs Removed %d \r \n " , BIDSRemoved ) ;
Length + = sprintf ( & MailBuffer [ Length ] , " BIDs Left %d \r \n " , NumberofBIDs ) ;
SendMessageToSYSOP ( " Housekeeping Results " , MailBuffer , Length ) ;
}
# ifdef WIN32
extern UCHAR LogDirectory [ 260 ] ;
int DeleteLogFiles ( )
{
WIN32_FIND_DATA ffd ;
char szDir [ MAX_PATH ] ;
char File [ MAX_PATH ] ;
HANDLE hFind = INVALID_HANDLE_VALUE ;
DWORD dwError = 0 ;
LARGE_INTEGER ft ;
time_t now = time ( NULL ) ;
int Age ;
UCHAR * ptr ;
// Prepare string for use with FindFile functions. First, copy the
// string to a buffer, then append '\*' to the directory name.
ptr = GetLogDirectory ( ) ;
strcpy ( szDir , ptr ) ;
strcat ( szDir , " /logs/Log_*.txt " ) ;
// Find the first file in the directory.
hFind = FindFirstFile ( szDir , & ffd ) ;
if ( INVALID_HANDLE_VALUE = = hFind )
{
return dwError ;
}
// List all the files in the directory with some info about them.
do
{
if ( ffd . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
OutputDebugString ( ffd . cFileName ) ;
}
else
{
ft . HighPart = ffd . ftCreationTime . dwHighDateTime ;
ft . LowPart = ffd . ftCreationTime . dwLowDateTime ;
ft . QuadPart - = 116444736000000000 ;
ft . QuadPart / = 10000000 ;
Age = ( int ) ( ( now - ft . LowPart ) / 86400 ) ;
if ( Age > LogAge )
{
sprintf ( File , " %s/logs/%s%c " , GetLogDirectory ( ) , ffd . cFileName , 0 ) ;
if ( DeletetoRecycleBin )
DeletetoRecycle ( File ) ;
else
DeleteFile ( File ) ;
}
}
}
while ( FindNextFile ( hFind , & ffd ) ! = 0 ) ;
dwError = GetLastError ( ) ;
FindClose ( hFind ) ;
return dwError ;
}
# else
# include <dirent.h>
int Filter ( const struct dirent * dir )
{
return memcmp ( dir - > d_name , " log " , 3 ) = = 0 & & strstr ( dir - > d_name , " .txt " ) ;
}
int DeleteLogFiles ( )
{
struct dirent * * namelist ;
int n ;
struct stat STAT ;
time_t now = time ( NULL ) ;
int Age = 0 , res ;
char FN [ 256 ] ;
n = scandir ( " logs " , & namelist , Filter , alphasort ) ;
if ( n < 0 )
perror ( " scandir " ) ;
else
{
while ( n - - )
{
sprintf ( FN , " logs/%s " , namelist [ n ] - > d_name ) ;
if ( stat ( FN , & STAT ) = = 0 )
{
Age = ( now - STAT . st_mtime ) / 86400 ;
if ( Age > LogAge )
{
printf ( " Deleting %s \n " , FN ) ;
unlink ( FN ) ;
}
}
free ( namelist [ n ] ) ;
}
free ( namelist ) ;
}
return 0 ;
}
# endif
VOID SendNonDeliveryMessage ( struct MsgInfo * OldMsg , BOOL Unread , int Age )
{
struct MsgInfo * Msg ;
BIDRec * BIDRec ;
char MailBuffer [ 1000 ] ;
char MsgFile [ MAX_PATH ] ;
FILE * hFile ;
int WriteLen = 0 ;
char From [ 100 ] ;
char * Via ;
struct UserInfo * FromUser ;
// Try to create a from Address. ( ? check RMS)
strcpy ( From , OldMsg - > from ) ;
if ( strcmp ( From , " SYSTEM " ) = = 0 )
return ; // Don't send non-deliverys SYSTEM messages
// Dont send NDN for NDN
if ( strcmp ( OldMsg - > title , " Non-delivery Notification " ) = = 0 )
return ;
FromUser = LookupCall ( OldMsg - > from ) ;
if ( FromUser )
{
if ( FromUser - > HomeBBS [ 0 ] )
sprintf ( From , " %s@%s " , OldMsg - > from , FromUser - > HomeBBS ) ;
else
sprintf ( From , " %s@%s " , OldMsg - > from , BBSName ) ;
}
else
{
WPRecP WP = LookupWP ( OldMsg - > from ) ;
if ( WP )
sprintf ( From , " %s@%s " , OldMsg - > from , WP - > first_homebbs ) ;
}
Msg = AllocateMsgRecord ( ) ;
GetSemaphore ( & MsgNoSemaphore , 0 ) ;
Msg - > number = + + LatestMsg ;
MsgnotoMsg [ Msg - > number ] = Msg ;
FreeSemaphore ( & MsgNoSemaphore ) ;
strcpy ( Msg - > from , SYSOPCall ) ;
Via = strlop ( From , ' @ ' ) ;
strcpy ( Msg - > to , From ) ;
if ( Via )
strcpy ( Msg - > via , Via ) ;
if ( strcmp ( From , " RMS: " ) = = 0 )
{
strcpy ( Msg - > to , " RMS " ) ;
strcpy ( Msg - > via , OldMsg - > emailfrom ) ;
}
if ( strcmp ( From , " smtp: " ) = = 0 )
{
Msg - > to [ 0 ] = 0 ;
strcpy ( Msg - > via , OldMsg - > emailfrom ) ;
}
if ( Msg - > to [ 0 ] = = 0 )
return ;
strcpy ( Msg - > title , " Non-delivery Notification " ) ;
if ( Unread )
Msg - > length = sprintf ( MailBuffer , " Your Message ID %s Subject %s to %s has not been read for %d days. \r \n Message had been deleted. \r \n " , OldMsg - > bid , OldMsg - > title , OldMsg - > to , Age ) ;
else
Msg - > length = sprintf ( MailBuffer , " Your Message ID %s Subject %s to %s could not be delivered in %d days. \r \n Message had been deleted. \r \n " , OldMsg - > bid , OldMsg - > title , OldMsg - > to , Age ) ;
Msg - > type = ' P ' ;
Msg - > status = ' N ' ;
Msg - > datereceived = Msg - > datechanged = Msg - > datecreated = time ( NULL ) ;
sprintf_s ( Msg - > bid , sizeof ( Msg - > bid ) , " %d_%s " , LatestMsg , BBSName ) ;
BIDRec = AllocateBIDRecord ( ) ;
strcpy ( BIDRec - > BID , Msg - > bid ) ;
BIDRec - > mode = Msg - > type ;
BIDRec - > u . msgno = LOWORD ( Msg - > number ) ;
BIDRec - > u . timestamp = LOWORD ( time ( NULL ) / 86400 ) ;
sprintf_s ( MsgFile , sizeof ( MsgFile ) , " %s/m_%06d.mes " , MailDir , Msg - > number ) ;
hFile = fopen ( MsgFile , " wb " ) ;
if ( hFile )
{
fwrite ( MailBuffer , 1 , Msg - > length , hFile ) ;
fclose ( hFile ) ;
}
MatchMessagetoBBSList ( Msg , NULL ) ;
}
VOID CreateBBSTrafficReport ( )
{
struct UserInfo * User ;
int i , n ;
char Line [ 200 ] ;
int len ;
char File [ MAX_PATH ] ;
FILE * hFile ;
time_t NOW = time ( NULL ) ;
int ConnectsIn ;
int ConnectsOut ;
// int MsgsReceived;
// int MsgsSent;
// int MsgsRejectedIn;
// int MsgsRejectedOut;
// int BytesForwardedIn;
// int BytesForwardedOut;
int TotMsgsReceived [ 4 ] = { 0 , 0 , 0 , 0 } ;
int TotMsgsSent [ 4 ] = { 0 , 0 , 0 , 0 } ;
int TotBytesForwardedIn [ 4 ] = { 0 , 0 , 0 , 0 } ;
int TotBytesForwardedOut [ 4 ] = { 0 , 0 , 0 , 0 } ;
char MsgsIn [ 80 ] ;
char MsgsOut [ 80 ] ;
char BytesIn [ 80 ] ;
char BytesOut [ 80 ] ;
char RejIn [ 80 ] ;
char RejOut [ 80 ] ;
struct tm tm ;
struct tm last ;
memcpy ( & tm , gmtime ( & NOW ) , sizeof ( tm ) ) ;
memcpy ( & last , gmtime ( ( const time_t * ) & LastTrafficTime ) , sizeof ( tm ) ) ;
sprintf ( File , " %s/Traffic_%02d%02d%02d.txt " , BaseDir , tm . tm_year - 100 , tm . tm_mon + 1 , tm . tm_mday ) ;
hFile = fopen ( File , " wb " ) ;
if ( hFile = = NULL )
{
Debugprintf ( " Failed to create traffic.txt " ) ;
return ;
}
len = sprintf ( Line , " Traffic Report for %s From: %04d/%02d/%02d %02d:%02dz To: %04d/%02d/%02d %02d:%02dz \r \n " ,
BBSName , last . tm_year + 1900 , last . tm_mon + 1 , last . tm_mday , last . tm_hour , last . tm_min ,
tm . tm_year + 1900 , tm . tm_mon + 1 , tm . tm_mday , tm . tm_hour , tm . tm_min ) ;
fwrite ( Line , 1 , len , hFile ) ;
len = sprintf ( Line , " Call Connects Connects Messages Messages Bytes Bytes Rejected Rejected \r \n " ) ;
fwrite ( Line , 1 , len , hFile ) ;
len = sprintf ( Line , " In Out Rxed(P/B/T) Sent Rxed Sent In Out \r \n \r \n " ) ;
fwrite ( Line , 1 , len , hFile ) ;
for ( i = 1 ; i < = NumberofUsers ; i + + )
{
User = UserRecPtr [ i ] ;
ConnectsIn = User - > Total . ConnectsIn - User - > Last . ConnectsIn ;
ConnectsOut = User - > Total . ConnectsOut - User - > Last . ConnectsOut ;
/*
MsgsReceived = MsgsSent = MsgsRejectedIn = MsgsRejectedOut = BytesForwardedIn = BytesForwardedOut = 0 ;
for ( n = 0 ; n < 4 ; n + + )
{
MsgsReceived + = User - > Total . MsgsReceived [ n ] - User - > Last . MsgsReceived [ n ] ;
MsgsSent + = User - > Total . MsgsSent [ n ] - User - > Last . MsgsSent [ n ] ;
BytesForwardedIn + = User - > Total . BytesForwardedIn [ n ] - User - > Last . BytesForwardedIn [ n ] ;
BytesForwardedOut + = User - > Total . BytesForwardedOut [ n ] - User - > Last . BytesForwardedOut [ n ] ;
MsgsRejectedIn + = User - > Total . MsgsRejectedIn [ n ] - User - > Last . MsgsRejectedIn [ n ] ;
MsgsRejectedOut + = User - > Total . MsgsRejectedOut [ n ] - User - > Last . MsgsRejectedOut [ n ] ;
}
len = sprintf ( Line , " %s %-7s %5d %8d %10d %10d %10d %10d %10d %10d \r \n " ,
( User - > flags & F_BBS ) ? " (B) " : " " ,
User - > Call , ConnectsIn ,
ConnectsOut ,
MsgsReceived ,
MsgsSent ,
BytesForwardedIn ,
BytesForwardedOut ,
MsgsRejectedIn ,
MsgsRejectedOut ) ;
*/
for ( n = 0 ; n < 4 ; n + + )
{
TotMsgsReceived [ n ] + = User - > Total . MsgsReceived [ n ] - User - > Last . MsgsReceived [ n ] ;
TotMsgsSent [ n ] + = User - > Total . MsgsSent [ n ] - User - > Last . MsgsSent [ n ] ;
TotBytesForwardedIn [ n ] + = User - > Total . BytesForwardedIn [ n ] - User - > Last . BytesForwardedIn [ n ] ;
TotBytesForwardedOut [ n ] + = User - > Total . BytesForwardedOut [ n ] - User - > Last . BytesForwardedOut [ n ] ;
}
sprintf ( MsgsIn , " %d/%d/%d " , User - > Total . MsgsReceived [ 1 ] - User - > Last . MsgsReceived [ 1 ] ,
User - > Total . MsgsReceived [ 2 ] - User - > Last . MsgsReceived [ 2 ] ,
User - > Total . MsgsReceived [ 3 ] - User - > Last . MsgsReceived [ 3 ] ) ;
sprintf ( MsgsOut , " %d/%d/%d " , User - > Total . MsgsSent [ 1 ] - User - > Last . MsgsSent [ 1 ] ,
User - > Total . MsgsSent [ 2 ] - User - > Last . MsgsSent [ 2 ] ,
User - > Total . MsgsSent [ 3 ] - User - > Last . MsgsSent [ 3 ] ) ;
sprintf ( BytesIn , " %d/%d/%d " , User - > Total . BytesForwardedIn [ 1 ] - User - > Last . BytesForwardedIn [ 1 ] ,
User - > Total . BytesForwardedIn [ 2 ] - User - > Last . BytesForwardedIn [ 2 ] ,
User - > Total . BytesForwardedIn [ 3 ] - User - > Last . BytesForwardedIn [ 3 ] ) ;
sprintf ( BytesOut , " %d/%d/%d " , User - > Total . BytesForwardedOut [ 1 ] - User - > Last . BytesForwardedOut [ 1 ] ,
User - > Total . BytesForwardedOut [ 2 ] - User - > Last . BytesForwardedOut [ 2 ] ,
User - > Total . BytesForwardedOut [ 3 ] - User - > Last . BytesForwardedOut [ 3 ] ) ;
sprintf ( RejIn , " %d/%d/%d " , User - > Total . MsgsRejectedIn [ 1 ] - User - > Last . MsgsRejectedIn [ 1 ] ,
User - > Total . MsgsRejectedIn [ 2 ] - User - > Last . MsgsRejectedIn [ 2 ] ,
User - > Total . MsgsRejectedIn [ 3 ] - User - > Last . MsgsRejectedIn [ 3 ] ) ;
sprintf ( RejOut , " %d/%d/%d " , User - > Total . MsgsRejectedOut [ 1 ] - User - > Last . MsgsRejectedOut [ 1 ] ,
User - > Total . MsgsRejectedOut [ 2 ] - User - > Last . MsgsRejectedOut [ 2 ] ,
User - > Total . MsgsRejectedOut [ 3 ] - User - > Last . MsgsRejectedOut [ 3 ] ) ;
len = sprintf ( Line , " %s %-7s %5d %8d%16s%16s%16s%16s%16s%16s \r \n " ,
( User - > flags & F_BBS ) ? " (B) " : " " ,
User - > Call , ConnectsIn ,
ConnectsOut ,
MsgsIn ,
MsgsOut ,
BytesIn ,
BytesOut ,
RejIn ,
RejOut ) ;
fwrite ( Line , 1 , len , hFile ) ;
User - > Last . ConnectsIn = User - > Total . ConnectsIn ;
User - > Last . ConnectsOut = User - > Total . ConnectsOut ;
for ( n = 0 ; n < 4 ; n + + )
{
User - > Last . MsgsReceived [ n ] = User - > Total . MsgsReceived [ n ] ;
User - > Last . MsgsSent [ n ] = User - > Total . MsgsSent [ n ] ;
User - > Last . BytesForwardedIn [ n ] = User - > Total . BytesForwardedIn [ n ] ;
User - > Last . BytesForwardedOut [ n ] = User - > Total . BytesForwardedOut [ n ] ;
User - > Last . MsgsRejectedIn [ n ] = User - > Total . MsgsRejectedIn [ n ] ;
User - > Last . MsgsRejectedOut [ n ] = User - > Total . MsgsRejectedOut [ n ] ;
}
}
sprintf ( MsgsIn , " %d/%d/%d " , TotMsgsReceived [ 1 ] , TotMsgsReceived [ 2 ] , TotMsgsReceived [ 3 ] ) ;
sprintf ( MsgsOut , " %d/%d/%d " , TotMsgsSent [ 1 ] , TotMsgsSent [ 2 ] , TotMsgsSent [ 3 ] ) ;
sprintf ( BytesIn , " %d/%d/%d " , TotBytesForwardedIn [ 1 ] , TotBytesForwardedIn [ 2 ] , TotBytesForwardedIn [ 3 ] ) ;
sprintf ( BytesOut , " %d/%d/%d " , TotBytesForwardedOut [ 1 ] , TotBytesForwardedOut [ 2 ] , TotBytesForwardedOut [ 3 ] ) ;
len = sprintf ( Line , " \r \n Totals %s Messages In %s Messages Out %s "
" Bytes In %s Bytes Out \r \n " , MsgsIn , MsgsOut , BytesIn , BytesOut ) ;
fwrite ( Line , 1 , len , hFile ) ;
SaveConfig ( ConfigName ) ;
GetConfig ( ConfigName ) ;
SaveUserDatabase ( ) ;
fclose ( hFile ) ;
}