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
*/
# define _CRT_SECURE_NO_DEPRECATE
# include "CHeaders.h"
# include "bpqmail.h"
# define MAIL
# include "httpconnectioninfo.h"
# ifdef WIN32
//#include "C:\Program Files (x86)\GnuWin32\include\iconv.h"
# else
# include <iconv.h>
# include <dirent.h>
# endif
static struct HTTPConnectionInfo * FindSession ( char * Key ) ;
int APIENTRY SessionControl ( int stream , int command , int param ) ;
int SetupNodeMenu ( char * Buff ) ;
VOID SetMultiStringValue ( char * * values , char * Multi ) ;
char * GetTemplateFromFile ( int Version , char * FN ) ;
VOID FormatTime ( char * Time , time_t cTime ) ;
struct MsgInfo * GetMsgFromNumber ( int msgno ) ;
BOOL CheckUserMsg ( struct MsgInfo * Msg , char * Call , BOOL SYSOP ) ;
BOOL OkToKillMessage ( BOOL SYSOP , char * Call , struct MsgInfo * Msg ) ;
int DisplayWebForm ( struct HTTPConnectionInfo * Session , struct MsgInfo * Msg , char * FileName , char * XML , char * Reply , char * RawMessage , int RawLen ) ;
struct HTTPConnectionInfo * AllocateWebMailSession ( ) ;
VOID SaveNewMessage ( struct HTTPConnectionInfo * Session , char * MsgPtr , char * Reply , int * RLen , char * Rest , int InputLen ) ;
2023-10-10 22:07:04 +01:00
void ConvertTitletoUTF8 ( WebMailInfo * WebMail , char * Title , char * UTF8Title , int Len ) ;
2022-08-28 09:35:46 +01:00
char * stristr ( char * ch1 , char * ch2 ) ;
char * ReadTemplate ( char * FormSet , char * DirName , char * FileName ) ;
VOID DoStandardTemplateSubsitutions ( struct HTTPConnectionInfo * Session , char * txtFile ) ;
BOOL CheckifPacket ( char * Via ) ;
int GetHTMLFormSet ( char * FormSet ) ;
void ProcessFormInput ( struct HTTPConnectionInfo * Session , char * input , char * Reply , int * RLen , int InputLen ) ;
char * WebFindPart ( char * * Msg , char * Boundary , int * PartLen , char * End ) ;
struct HTTPConnectionInfo * FindWMSession ( char * Key ) ;
int SendWebMailHeaderEx ( char * Reply , char * Key , struct HTTPConnectionInfo * Session , char * Alert ) ;
char * BuildFormMessage ( struct HTTPConnectionInfo * Session , struct MsgInfo * Msg , char * Keys [ 1000 ] , char * Values [ 1000 ] , int NumKeys ) ;
char * FindXMLVariable ( WebMailInfo * WebMail , char * Var ) ;
int ReplyToFormsMessage ( struct HTTPConnectionInfo * Session , struct MsgInfo * Msg , char * Reply , BOOL Reenter ) ;
BOOL ParsetxtTemplate ( struct HTTPConnectionInfo * Session , struct HtmlFormDir * Dir , char * FN , BOOL isReply ) ;
VOID UpdateFormAction ( char * Template , char * Key ) ;
BOOL APIENTRY GetAPRSLatLon ( double * PLat , double * PLon ) ;
BOOL APIENTRY GetAPRSLatLonString ( char * PLat , char * PLon ) ;
void FreeWebMailFields ( WebMailInfo * WebMail ) ;
VOID BuildXMLAttachment ( struct HTTPConnectionInfo * Session , char * Keys [ 1000 ] , char * Values [ 1000 ] , int NumKeys ) ;
VOID SaveTemplateMessage ( struct HTTPConnectionInfo * Session , char * MsgPtr , char * Reply , int * RLen , char * Rest ) ;
VOID DownloadAttachments ( struct HTTPConnectionInfo * Session , char * Reply , int * RLen , char * Rest ) ;
VOID getAttachmentList ( struct HTTPConnectionInfo * Session , char * Reply , int * RLen , char * Rest ) ;
char * BuildB2Header ( WebMailInfo * WebMail , struct MsgInfo * Msg , char * * ToCalls , int Calls ) ;
VOID FormatTime2 ( char * Time , time_t cTime ) ;
VOID ProcessSelectResponse ( struct HTTPConnectionInfo * Session , char * URLParams ) ;
VOID ProcessAskResponse ( struct HTTPConnectionInfo * Session , char * URLParams ) ;
char * CheckFile ( struct HtmlFormDir * Dir , char * FN ) ;
VOID GetPage ( struct HTTPConnectionInfo * Session , char * NodeURL ) ;
VOID SendTemplateSelectScreen ( struct HTTPConnectionInfo * Session , char * URLParams , int InputLen ) ;
BOOL isAMPRMsg ( char * Addr ) ;
char * doXMLTransparency ( char * string ) ;
Dll BOOL APIENTRY APISendAPRSMessage ( char * Text , char * ToCall ) ;
2023-12-28 10:31:09 +00:00
void SendMessageReadEvent ( char * Call , struct MsgInfo * Msg ) ;
void SendNewMessageEvent ( char * call , struct MsgInfo * Msg ) ;
2024-12-16 17:54:16 +00:00
void MQTTMessageEvent ( void * message ) ;
2022-08-28 09:35:46 +01:00
extern char NodeTail [ ] ;
extern char BBSName [ 10 ] ;
extern char LTFROMString [ 2048 ] ;
extern char LTTOString [ 2048 ] ;
extern char LTATString [ 2048 ] ;
UCHAR BPQDirectory [ 260 ] ;
int LineCount = 35 ; // Lines per page on message list
// Forms
struct HtmlFormDir * * HtmlFormDirs = NULL ;
int FormDirCount = 0 ;
struct HtmlForm
{
char * FileName ;
BOOL HasInitial ;
BOOL HasViewer ;
BOOL HasReply ;
BOOL HasReplyViewer ;
} ;
struct HtmlFormDir
{
char * FormSet ;
char * DirName ;
struct HtmlForm * * Forms ;
int FormCount ;
struct HtmlFormDir * * Dirs ; // Nested Directories
int DirCount ;
} ;
char FormDirList [ 4 ] [ MAX_PATH ] = { " Standard_Templates " , " Standard Templates " , " Local_Templates " } ;
static char PassError [ ] = " <p align=center>Sorry, User or Password is invalid - please try again</p> " ;
static char BusyError [ ] = " <p align=center>Sorry, No sessions available - please try later</p> " ;
extern char MailSignon [ ] ;
char WebMailSignon [ ] = " <html><head><title>BPQ32 Mail Server Access</title></head><body background='/background.jpg'> "
" <h3 align=center>BPQ32 Mail Server %s Access</h3> "
" <h3 align=center>Please enter Callsign and Password to access WebMail</h3> "
" <form method=post action=/WebMail/Signon> "
" <table align=center bgcolor=white> "
" <tr><td>User</td><td><input type=text name=user tabindex=1 size=20 maxlength=50 /></td></tr> "
" <tr><td>Password</td><td><input type=password name=password tabindex=2 size=20 maxlength=50 /></td></tr></table> "
" <p align=center><input type=submit class='btn' value=Submit /><input type=submit class='btn' value=Cancel name=Cancel /></form> " ;
static char MsgInputPage [ ] = " <html><head><meta content= \" text/html; charset=UTF-8 \" http-equiv= \" content-type \" > "
" <title></title><script src='/WebMail/webscript.js'></script> "
" <style type= \" text/css \" > "
" input.btn:active {background:black;color:white;} "
" submit.btn:active {background:black;color:white;} "
" </style> "
" </head> "
" <body background=/background.jpg onload='initialize(185)' onresize='initialize(185)'> "
" <h3 align=center>Webmail Interface - Message Input Form</h3> "
" <form align=center id=myform style= \" font-family: monospace; \" method=post action=/WebMail/EMSave \ ?%s enctype=multipart/form-data> "
" <div style='text-align: center;'><div style='display: inline-block;'><span style='display:block; text-align: left;'> "
" To <input size=60 id='To' name='To' value='%s'>%s<br> "
" Subject <input size=60 id='Subj' name='Subj' value= \" %s \" > "
// "<button onclick='document.getElementById('getFile').click()'>Attach Files</button>"
// "<input type='file' id='getFile' name='myFile[]' multiple style='display:none'><br>"
" <label for='myfile'>Attachments </label><input type='file' name='myFile[]' multiple> "
" <br>Type "
" <select tabindex=1 size=1 name=Type><option value=P>P</option> "
" <option value=B>B</option><option value=T>T</option></select> "
" BID <input name=BID><br><label for='myfile2'>Header </label> "
" <input type='file' name='myFile2[]' style='width: 220px'> "
" <label for='myfile3'> Footer </label><input type='file' name='myFile3[]'> "
" </span></div> "
" <textarea id='main' name=Msg style='overflow:auto;'>%s</textarea><br> "
" <input name=Send value=Send type=submit class='btn'> <input name=Cancel value=Cancel type=submit class='btn'></div></form> " ;
static char CheckFormMsgPage [ ] = " <html><head><meta content= \" text/html; charset=UTF-8 \" http-equiv= \" content-type \" > "
" <title></title><script src='/WebMail/webscript.js'></script></head> "
" <body background=/background.jpg onload='initialize(210)' onresize='initialize(210)'> "
" <h3 align=center>Webmail Forms Interface - Check Message</h3> "
" <form align=center id=myform style= \" font-family: monospace; \" method=post action=/WebMail/FormMsgSave \ ?%s> "
" <div style='text-align: center;'><div style='display: inline-block;'><span style='display:block; text-align: left;'> "
" To <input size=60 id='To' name='To' value='%s'><br> "
" CC <input size=60 id='CC' name='CC' value='%s'><br> "
" Subject <input size=60 id='Subj' name='Subj' value='%s'> "
//"<input type='file' name='myFile' multiple>"
" <br>Type "
" <select tabindex=1 size=1 name=Type><option value=P %s>P</option> "
" <option value=B %s>B</option><option value=T %s>T</option></select> "
" BID <input name=BID value='%s'><br><br> "
" </span></div> "
" <textarea id='main' name=Msg style='overflow:auto;'>%s</textarea><br> "
" <input name=Send value=Send type=submit class='btn'><input name=Cancel value=Cancel type=submit class='btn'></div></form> " ;
extern char * WebMailTemplate ;
extern char * WebMailMsgTemplate ;
extern char * jsTemplate ;
static char * dat [ ] = { " Sun " , " Mon " , " Tue " , " Wed " , " Thu " , " Fri " , " Sat " } ;
char * longday [ ] = { " Sunday " , " Monday " , " Tusday " , " Wednesday " , " Thusday " , " Friday " , " Saturday " } ;
static struct HTTPConnectionInfo * WebSessionList = NULL ; // active WebMail sessions
# ifdef LINBPQ
UCHAR * GetBPQDirectory ( ) ;
# endif
void UndoTransparency ( char * input ) ;
# ifndef LINBPQ
void UndoTransparency ( char * input )
{
char * ptr1 , * ptr2 ;
char c ;
int hex ;
if ( input = = NULL )
return ;
ptr1 = ptr2 = input ;
// Convert any %xx constructs
while ( 1 )
{
c = * ( ptr1 + + ) ;
if ( c = = 0 )
break ;
if ( c = = ' % ' )
{
c = * ( ptr1 + + ) ;
if ( isdigit ( c ) )
hex = ( c - ' 0 ' ) < < 4 ;
else
hex = ( tolower ( c ) - ' a ' + 10 ) < < 4 ;
c = * ( ptr1 + + ) ;
if ( isdigit ( c ) )
hex + = ( c - ' 0 ' ) ;
else
hex + = ( tolower ( c ) - ' a ' + 10 ) ;
* ( ptr2 + + ) = hex ;
}
else if ( c = = ' + ' )
* ( ptr2 + + ) = 32 ;
else
* ( ptr2 + + ) = c ;
}
* ptr2 = 0 ;
}
# endif
void ReleaseWebMailStruct ( WebMailInfo * WebMail )
{
// release any malloc'ed resources
if ( WebMail = = NULL )
return ;
FreeWebMailFields ( WebMail ) ;
free ( WebMail ) ;
return ;
}
VOID FreeWebMailMallocs ( )
{
// called when closing. Not really needed, but simplifies tracking down real memory leaks
struct HTTPConnectionInfo * Session , * SaveNext ;
int i ;
Session = WebSessionList ;
while ( Session )
{
SaveNext = Session - > Next ;
// Release amy malloc'ed resouces
ReleaseWebMailStruct ( Session - > WebMail ) ;
free ( Session ) ;
Session = SaveNext ;
}
for ( i = 0 ; i < FormDirCount ; i + + )
{
struct HtmlFormDir * Dir = HtmlFormDirs [ i ] ;
int j ;
for ( j = 0 ; j < Dir - > FormCount ; j + + )
{
free ( Dir - > Forms [ j ] - > FileName ) ;
free ( Dir - > Forms [ j ] ) ;
}
if ( Dir - > DirCount )
{
struct HtmlFormDir * SubDir ;
int k , l ;
for ( l = 0 ; l < Dir - > DirCount ; l + + )
{
SubDir = Dir - > Dirs [ l ] ;
for ( k = 0 ; k < Dir - > Dirs [ l ] - > FormCount ; k + + )
{
free ( SubDir - > Forms [ k ] - > FileName ) ;
free ( SubDir - > Forms [ k ] ) ;
}
free ( SubDir - > DirName ) ;
free ( SubDir - > Forms ) ;
free ( SubDir - > FormSet ) ;
free ( Dir - > Dirs [ l ] ) ;
}
}
free ( Dir - > DirName ) ;
free ( Dir - > Forms ) ;
free ( Dir - > FormSet ) ;
free ( Dir ) ;
}
free ( HtmlFormDirs ) ;
return ;
}
char * initMultipartUnpack ( char * * Input )
{
// Check if Multipart and return Boundary. Update Input to first part
// look through header for Content-Type line, and if multipart
// find boundary string.
char * ptr , * ptr2 ;
char Boundary [ 128 ] ;
BOOL Multipart = FALSE ;
ptr = * Input ;
while ( * ptr ! = 13 )
{
ptr2 = strchr ( ptr , 10 ) ; // Find CR
while ( ptr2 [ 1 ] = = ' ' | | ptr2 [ 1 ] = = 9 ) // Whitespace - continuation line
ptr2 = strchr ( & ptr2 [ 1 ] , 10 ) ; // Find CR
if ( _memicmp ( ptr , " Content-Type: " , 14 ) = = 0 )
{
char Line [ 256 ] = " " ;
char * ptr3 ;
size_t len = ptr2 - ptr - 14 ;
if ( len > 255 )
return NULL ;
memcpy ( Line , & ptr [ 14 ] , len ) ;
if ( _memicmp ( Line , " Multipart/ " , 10 ) = = 0 )
{
ptr3 = stristr ( Line , " boundary " ) ;
if ( ptr3 )
{
ptr3 + = 9 ;
if ( ( * ptr3 ) = = ' " ' )
ptr3 + + ;
strcpy ( Boundary , ptr3 ) ;
ptr3 = strchr ( Boundary , ' " ' ) ;
if ( ptr3 ) * ptr3 = 0 ;
ptr3 = strchr ( Boundary , 13 ) ; // CR
if ( ptr3 ) * ptr3 = 0 ;
break ;
}
else
return NULL ; // Can't do anything without a boundary ??
}
}
ptr = ptr2 ;
ptr + + ;
}
// Find First part - there is a boundary before it
ptr = strstr ( ptr2 , Boundary ) ;
// Next should be crlf then part
ptr = strstr ( ptr , " \r \n " ) ;
if ( ptr )
ptr + = 2 ; // Over CRLF
* Input = ptr ; // Return first part or NULL
return _strdup ( Boundary ) ;
}
BOOL unpackPart ( char * Boundary , char * * Input , char * * Name , char * * Value , int * ValLen , char * End )
{
// Format seems to be
/*
- - - - - - WebKitFormBoundaryABJaEbBWB5SuAHmq
Content - Disposition : form - data ; name = " Subj "
subj
- - - - - - WebKitFormBoundaryABJaEbBWB5SuAHmq
Content - Disposition : form - data ; name = " myFile[] " ; filename = " exiftool.txt "
Content - Type : text / plain
c : \ exiftool " -filename<filemodifydate " - d " %Y-%m-%d_%H-%M-%S-%%c.%%e " *
- - - - - - WebKitFormBoundaryABJaEbBWB5SuAHmq
ie Header is terminated by \ r \ n \ r \ n
Value is terminated by - - - - - - WebKitFormBoundary7XHZ1i7Jc8tOZJbw
*/
// Find End of part - ie -- Boundary + CRLF or --
char * ptr , * endptr , * saveptr ;
char * Msgptr ;
size_t BLen = strlen ( Boundary ) ;
size_t Partlen ;
saveptr = Msgptr = ptr = * Input ;
while ( ptr < End ) // Just in case we run off end
{
if ( * ptr = = ' - ' & & * ( ptr + 1 ) = = ' - ' )
{
if ( memcmp ( & ptr [ 2 ] , Boundary , BLen ) = = 0 )
{
// Found Boundary
Partlen = ptr - Msgptr ;
ptr + = ( BLen + 2 ) ; // End of Boundary
if ( * ptr = = ' - ' ) // Terminating Boundary
* Input = NULL ;
else
* Input = ptr + 2 ;
// Now unpack Part to Name and Value
ptr = strstr ( Msgptr , " name= " ) ;
if ( ptr )
{
size_t vallen ;
endptr = strstr ( ptr , " \r \n \r \n " ) ; // "/r/n/r/n
if ( endptr = = NULL )
return FALSE ; // Malformed
vallen = Partlen - ( endptr - saveptr ) - 6 ;
// name is surrounded by ""
* ( - - endptr ) = 0 ; // Termanate name
ptr + = 6 ; // to start of name string
* Name = ptr ;
endptr + = 5 ; // to Value
endptr [ vallen ] = 0 ; // terminate to simplify string handling
* Value = endptr ;
* ValLen = ( int ) vallen ;
return TRUE ;
}
}
}
ptr + + ;
}
return FALSE ;
}
int SaveInputValue ( WebMailInfo * WebMail , char * Name , char * Value , int ValLength )
{
if ( strcmp ( Name , " Cancel " ) = = 0 )
return FALSE ;
if ( strcmp ( Name , " To " ) = = 0 )
WebMail - > To = _strdup ( Value ) ;
else if ( strcmp ( Name , " CC " ) = = 0 )
WebMail - > CC = _strdup ( Value ) ;
else if ( strcmp ( Name , " Subj " ) = = 0 )
WebMail - > Subject = _strdup ( Value ) ;
else if ( strcmp ( Name , " Type " ) = = 0 )
WebMail - > Type = Value [ 0 ] ;
else if ( strcmp ( Name , " BID " ) = = 0 )
WebMail - > BID = _strdup ( Value ) ;
else if ( strcmp ( Name , " Msg " ) = = 0 )
WebMail - > Body = _strdup ( Value ) ;
else if ( _memicmp ( Name , " myFile[] " , 8 ) = = 0 )
{
// Get File Name from param string - myFile[]"; filename="exiftool.txt" \r\nContent-Type: text/plain
char * fn = strstr ( Name , " filename= " ) ;
char * endfn ;
if ( fn )
{
fn + = 10 ;
endfn = strchr ( fn , ' " ' ) ;
if ( endfn )
{
* endfn = 0 ;
if ( strlen ( fn ) )
{
WebMail - > FileName [ WebMail - > Files ] = _strdup ( fn ) ;
WebMail - > FileBody [ WebMail - > Files ] = malloc ( ValLength ) ;
memcpy ( WebMail - > FileBody [ WebMail - > Files ] , Value , ValLength ) ;
WebMail - > FileLen [ WebMail - > Files + + ] = ValLength ;
}
}
}
}
else if ( _memicmp ( Name , " myFile2[] " , 8 ) = = 0 )
{
// Get File Name from param string - myFile[]"; filename="exiftool.txt" \r\nContent-Type: text/plain
char * fn = strstr ( Name , " filename= " ) ;
char * endfn ;
if ( fn )
{
fn + = 10 ;
endfn = strchr ( fn , ' " ' ) ;
if ( endfn )
{
* endfn = 0 ;
if ( strlen ( fn ) )
{
WebMail - > Header = malloc ( ValLength + 1 ) ;
memcpy ( WebMail - > Header , Value , ValLength + 1 ) ;
WebMail - > HeaderLen = RemoveLF ( WebMail - > Header , ValLength ) ;
}
}
}
}
else if ( _memicmp ( Name , " myFile3[] " , 8 ) = = 0 )
{
// Get File Name from param string - myFile[]"; filename="exiftool.txt" \r\nContent-Type: text/plain
char * fn = strstr ( Name , " filename= " ) ;
char * endfn ;
if ( fn )
{
fn + = 10 ;
endfn = strchr ( fn , ' " ' ) ;
if ( endfn )
{
* endfn = 0 ;
if ( strlen ( fn ) )
{
WebMail - > Footer = malloc ( ValLength + 1 ) ;
memcpy ( WebMail - > Footer , Value , ValLength + 1 ) ;
WebMail - > FooterLen = RemoveLF ( WebMail - > Footer , ValLength ) ;
}
}
}
}
return TRUE ;
}
struct HTTPConnectionInfo * AllocateWebMailSession ( )
{
int KeyVal ;
struct HTTPConnectionInfo * Session , * SaveNext ;
time_t NOW = time ( NULL ) ;
// First see if any session records havent been used for a while
Session = WebSessionList ;
while ( Session )
{
if ( NOW - Session - > WebMailLastUsed > 1200 ) // 20 Mins
{
SaveNext = Session - > Next ;
// Release amy malloc'ed resouces
ReleaseWebMailStruct ( Session - > WebMail ) ;
memset ( Session , 0 , sizeof ( struct HTTPConnectionInfo ) ) ;
Session - > Next = SaveNext ;
goto UseThis ;
}
Session = Session - > Next ;
}
Session = zalloc ( sizeof ( struct HTTPConnectionInfo ) ) ;
if ( Session = = NULL )
return NULL ;
if ( WebSessionList )
Session - > Next = WebSessionList ;
WebSessionList = Session ;
UseThis :
Session - > WebMail = zalloc ( sizeof ( WebMailInfo ) ) ;
KeyVal = ( ( rand ( ) % 100 ) + 1 ) ;
KeyVal * = ( int ) time ( NULL ) ;
sprintf ( Session - > Key , " %c%08X " , ' W ' , KeyVal ) ;
return Session ;
}
struct HTTPConnectionInfo * FindWMSession ( char * Key )
{
struct HTTPConnectionInfo * Session = WebSessionList ;
while ( Session )
{
if ( strcmp ( Session - > Key , Key ) = = 0 )
{
Session - > WebMailLastUsed = time ( NULL ) ;
return Session ;
}
Session = Session - > Next ;
}
return NULL ;
}
// Build list of available forms
VOID ProcessFormDir ( char * FormSet , char * DirName , struct HtmlFormDir * * * xxx , int * DirCount )
{
struct HtmlFormDir * FormDir ;
struct HtmlFormDir * * FormDirs = * xxx ;
struct HtmlForm * Form ;
char Search [ MAX_PATH ] ;
int count = * DirCount ;
# ifdef WIN32
HANDLE hFind = INVALID_HANDLE_VALUE ;
WIN32_FIND_DATA ffd ;
# else
DIR * dir ;
struct dirent * entry ;
char name [ 256 ] ;
# endif
FormDir = zalloc ( sizeof ( struct HtmlFormDir ) ) ;
FormDir - > DirName = _strdup ( DirName ) ;
FormDir - > FormSet = _strdup ( FormSet ) ;
FormDirs = realloc ( FormDirs , ( count + 1 ) * sizeof ( void * ) ) ;
FormDirs [ count + + ] = FormDir ;
* DirCount = count ;
* xxx = FormDirs ;
// Scan Directory for .txt files
sprintf ( Search , " %s/%s/%s/* " , GetBPQDirectory ( ) , FormSet , DirName ) ;
// Find the first file in the directory.
# ifdef WIN32
hFind = FindFirstFile ( Search , & ffd ) ;
if ( INVALID_HANDLE_VALUE = = hFind )
return ;
do
{
if ( ffd . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
char Dir [ MAX_PATH ] ;
if ( strcmp ( ffd . cFileName , " . " ) = = 0 | | strcmp ( ffd . cFileName , " .. " ) = = 0 )
continue ;
// Recurse in subdir
sprintf ( Dir , " %s/%s " , DirName , ffd . cFileName ) ;
ProcessFormDir ( FormSet , Dir , & FormDir - > Dirs , & FormDir - > DirCount ) ;
continue ;
}
// Add to list
Form = zalloc ( sizeof ( struct HtmlForm ) ) ;
Form - > FileName = _strdup ( ffd . cFileName ) ;
FormDir - > Forms = realloc ( FormDir - > Forms , ( FormDir - > FormCount + 1 ) * sizeof ( void * ) ) ;
FormDir - > Forms [ FormDir - > FormCount + + ] = Form ;
}
while ( FindNextFile ( hFind , & ffd ) ! = 0 ) ;
FindClose ( hFind ) ;
# else
sprintf ( Search , " %s/%s/%s " , GetBPQDirectory ( ) , FormSet , DirName ) ;
if ( ! ( dir = opendir ( Search ) ) )
{
Debugprintf ( " %s %d %d " , " cant open forms dir " , errno , dir ) ;
return ;
}
while ( ( entry = readdir ( dir ) ) ! = NULL )
{
if ( entry - > d_type = = DT_DIR )
{
2023-12-28 10:31:09 +00:00
char Dir [ MAX_PATH ] ;
if ( strcmp ( entry - > d_name , " . " ) = = 0 | | strcmp ( entry - > d_name , " .. " ) = = 0 )
2022-08-28 09:35:46 +01:00
continue ;
2023-12-28 10:31:09 +00:00
// Recurse in subdir
sprintf ( Dir , " %s/%s " , DirName , entry - > d_name ) ;
2022-08-28 09:35:46 +01:00
2023-12-28 10:31:09 +00:00
ProcessFormDir ( FormSet , Dir , & FormDir - > Dirs , & FormDir - > DirCount ) ;
continue ;
2022-08-28 09:35:46 +01:00
}
2023-12-28 10:31:09 +00:00
// Add to list
2022-08-28 09:35:46 +01:00
2023-12-28 10:31:09 +00:00
Form = zalloc ( sizeof ( struct HtmlForm ) ) ;
2022-08-28 09:35:46 +01:00
2023-12-28 10:31:09 +00:00
Form - > FileName = _strdup ( entry - > d_name ) ;
2022-08-28 09:35:46 +01:00
2023-12-28 10:31:09 +00:00
FormDir - > Forms = realloc ( FormDir - > Forms , ( FormDir - > FormCount + 1 ) * sizeof ( void * ) ) ;
FormDir - > Forms [ FormDir - > FormCount + + ] = Form ;
2022-08-28 09:35:46 +01:00
}
closedir ( dir ) ;
# endif
return ;
}
int GetHTMLForms ( )
{
int n = 0 ;
while ( FormDirList [ n ] [ 0 ] )
GetHTMLFormSet ( FormDirList [ n + + ] ) ;
return 0 ;
}
int GetHTMLFormSet ( char * FormSet )
{
int i ;
# ifdef WIN32
WIN32_FIND_DATA ffd ;
char szDir [ MAX_PATH ] ;
HANDLE hFind = INVALID_HANDLE_VALUE ;
DWORD dwError = 0 ;
sprintf ( szDir , " %s/%s/* " , BPQDirectory , FormSet ) ;
// Find the first file in the directory.
hFind = FindFirstFile ( szDir , & ffd ) ;
if ( INVALID_HANDLE_VALUE = = hFind )
{
// Accept either
return 0 ;
}
// Scan all directories looking for file
do
{
if ( ffd . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
if ( strcmp ( ffd . cFileName , " . " ) = = 0 | | strcmp ( ffd . cFileName , " .. " ) = = 0 )
continue ;
// Add to Directory List
ProcessFormDir ( FormSet , ffd . cFileName , & HtmlFormDirs , & FormDirCount ) ;
}
}
while ( FindNextFile ( hFind , & ffd ) ! = 0 ) ;
FindClose ( hFind ) ;
# else
DIR * dir ;
struct dirent * entry ;
char name [ 256 ] ;
sprintf ( name , " %s/%s " , BPQDirectory , FormSet ) ;
if ( ! ( dir = opendir ( name ) ) )
{
Debugprintf ( " cant open forms dir %s %d %d " , name , errno , dir ) ;
}
2023-12-28 10:31:09 +00:00
else
2022-08-28 09:35:46 +01:00
{
2023-12-28 10:31:09 +00:00
while ( ( entry = readdir ( dir ) ) ! = NULL )
2022-08-28 09:35:46 +01:00
{
2023-12-28 10:31:09 +00:00
if ( entry - > d_type = = DT_DIR )
{
if ( strcmp ( entry - > d_name , " . " ) = = 0 | | strcmp ( entry - > d_name , " .. " ) = = 0 )
continue ;
2022-08-28 09:35:46 +01:00
2023-12-28 10:31:09 +00:00
// Add to Directory List
2022-08-28 09:35:46 +01:00
2023-12-28 10:31:09 +00:00
ProcessFormDir ( FormSet , entry - > d_name , & HtmlFormDirs , & FormDirCount ) ;
}
}
closedir ( dir ) ;
}
2022-08-28 09:35:46 +01:00
# endif
// List for testing
return 0 ;
Debugprintf ( " %d form dirs " , FormDirCount ) ;
for ( i = 0 ; i < FormDirCount ; i + + )
{
struct HtmlFormDir * Dir = HtmlFormDirs [ i ] ;
int j ;
Debugprintf ( " %3d %s " , Dir - > FormCount , Dir - > DirName ) ;
for ( j = 0 ; j < Dir - > FormCount ; j + + )
Debugprintf ( " %s " , Dir - > Forms [ j ] - > FileName ) ;
if ( Dir - > DirCount )
{
int k , l ;
for ( l = 0 ; l < Dir - > DirCount ; l + + )
{
Debugprintf ( " Subdir %3d %s " , Dir - > Dirs [ l ] - > DirCount , Dir - > Dirs [ l ] - > DirName ) ;
for ( k = 0 ; k < Dir - > Dirs [ l ] - > FormCount ; k + + )
Debugprintf ( " %s " , Dir - > Dirs [ l ] - > Forms [ k ] - > FileName ) ;
}
}
}
return 0 ;
}
static int compare ( const void * arg1 , const void * arg2 )
{
// Compare Calls. Fortunately call is at start of stuct
return _stricmp ( * ( char * * ) arg1 , * ( char * * ) arg2 ) ;
}
int SendWebMailHeader ( char * Reply , char * Key , struct HTTPConnectionInfo * Session )
{
return SendWebMailHeaderEx ( Reply , Key , Session , NULL ) ;
}
int SendWebMailHeaderEx ( char * Reply , char * Key , struct HTTPConnectionInfo * Session , char * Alert )
{
// Ex includes an alert string to be sent before message
struct UserInfo * User = Session - > User ;
char Messages [ 245000 ] ;
int m ;
struct MsgInfo * Msg ;
char * ptr = Messages ;
int n = NumberofMessages ; //LineCount;
char Via [ 64 ] ;
int Count = 0 ;
Messages [ 0 ] = 0 ;
if ( Alert & & Alert [ 0 ] )
ptr + = sprintf ( Messages , " <script>alert( \" %s \" );window.location.href = '/Webmail/WebMail?%s';</script> " , Alert , Key ) ;
ptr + = sprintf ( ptr , " %s " , " # Date XX Len To @ From Subject \r \n \r \n " ) ;
for ( m = LatestMsg ; m > = 1 ; m - - )
{
if ( ptr > & Messages [ 244000 ] )
break ; // protect buffer
Msg = GetMsgFromNumber ( m ) ;
if ( Msg = = 0 | | Msg - > type = = 0 | | Msg - > status = = 0 )
continue ; // Protect against corrupt messages
if ( Msg & & CheckUserMsg ( Msg , User - > Call , User - > flags & F_SYSOP ) )
{
2023-10-10 22:07:04 +01:00
char UTF8Title [ 4096 ] ;
2022-08-28 09:35:46 +01:00
char * EncodedTitle ;
// List if it is the right type and in the page range we want
if ( Session - > WebMailTypes [ 0 ] & & strchr ( Session - > WebMailTypes , Msg - > type ) = = 0 )
continue ;
// All Types or right Type. Check Mine Flag
if ( Session - > WebMailMine )
{
// Only list if to or from me
if ( strcmp ( User - > Call , Msg - > to ) ! = 0 & & strcmp ( User - > Call , Msg - > from ) ! = 0 )
continue ;
}
2024-02-23 21:36:36 +00:00
if ( Session - > WebMailMyTX )
{
// Only list if to or from me
if ( strcmp ( User - > Call , Msg - > from ) ! = 0 )
continue ;
}
if ( Session - > WebMailMyRX )
{
// Only list if to or from me
if ( strcmp ( User - > Call , Msg - > to ) ! = 0 )
continue ;
}
2022-08-28 09:35:46 +01:00
if ( Count + + < Session - > WebMailSkip )
continue ;
strcpy ( Via , Msg - > via ) ;
strlop ( Via , ' . ' ) ;
// make sure title is HTML safe (no < > etc) and UTF 8 encoded
EncodedTitle = doXMLTransparency ( Msg - > title ) ;
2023-10-10 22:07:04 +01:00
memset ( UTF8Title , 0 , 4096 ) ; // In case convert fails part way through
ConvertTitletoUTF8 ( Session - > WebMail , EncodedTitle , UTF8Title , 4095 ) ;
2022-08-28 09:35:46 +01:00
free ( EncodedTitle ) ;
ptr + = sprintf ( ptr , " <a href=/WebMail/WM?%s&%d>%6d</a> %s %c%c %5d %-8s%-8s%-8s%s \r \n " ,
Key , Msg - > number , Msg - > number ,
FormatDateAndTime ( ( time_t ) Msg - > datecreated , TRUE ) , Msg - > type ,
Msg - > status , Msg - > length , Msg - > to , Via ,
Msg - > from , UTF8Title ) ;
n - - ;
if ( n = = 0 )
break ;
}
}
if ( WebMailTemplate = = NULL )
WebMailTemplate = GetTemplateFromFile ( 6 , " WebMailPage.txt " ) ;
2024-02-23 21:36:36 +00:00
return sprintf ( Reply , WebMailTemplate , BBSName , User - > Call , Key , Key , Key , Key , Key , Key , Key , Key , Key , Key , Messages ) ;
2022-08-28 09:35:46 +01:00
}
int ViewWebMailMessage ( struct HTTPConnectionInfo * Session , char * Reply , int Number , BOOL DisplayHTML )
{
char * Key = Session - > Key ;
struct UserInfo * User = Session - > User ;
WebMailInfo * WebMail = Session - > WebMail ;
char * DisplayStyle ;
char Message [ 200000 ] = " " ;
struct MsgInfo * Msg ;
char * ptr = Message ;
char * MsgBytes , * Save ;
int msgLen ;
char FullTo [ 100 ] ;
2023-10-10 22:07:04 +01:00
char UTF8Title [ 4096 ] ;
2022-08-28 09:35:46 +01:00
int Index ;
char * crcrptr ;
char DownLoad [ 256 ] = " " ;
DisplayStyle = " textarea " ; // Prevents interpretation of html and xml
Msg = GetMsgFromNumber ( Number ) ;
if ( Msg = = NULL )
{
ptr + = sprintf ( ptr , " Message %d not found \r \n " , Number ) ;
return sprintf ( Reply , WebMailTemplate , BBSName , User - > Call , Key , Key , Key , Key , Key , Key , Key , Message ) ;
}
// New Display so free any old values
FreeWebMailFields ( WebMail ) ;
WebMail - > CurrentMessageIndex = Number ;
if ( ! CheckUserMsg ( Msg , User - > Call , User - > flags & F_SYSOP ) )
{
ptr + = sprintf ( ptr , " Message %d not for you \r " , Number ) ;
return sprintf ( Reply , WebMailTemplate , BBSName , User - > Call , Key , Key , Key , Key , Key , Key , Key , Message ) ;
}
if ( _stricmp ( Msg - > to , " RMS " ) = = 0 )
sprintf ( FullTo , " RMS:%s " , Msg - > via ) ;
else
if ( Msg - > to [ 0 ] = = 0 )
sprintf ( FullTo , " smtp:%s " , Msg - > via ) ;
else
strcpy ( FullTo , Msg - > to ) ;
// make sure title is UTF 8 encoded
2023-10-10 22:07:04 +01:00
memset ( UTF8Title , 0 , 4096 ) ; // In case convert fails part way through
ConvertTitletoUTF8 ( Session - > WebMail , Msg - > title , UTF8Title , 4095 ) ;
2022-08-28 09:35:46 +01:00
// if a B2 message diplay B2 Header instead of a locally generated one
if ( ( Msg - > B2Flags & B2Msg ) = = 0 )
{
ptr + = sprintf ( ptr , " From: %s%s \n To: %s \n Type/Status: %c%c \n Date/Time: %s \n Bid: %s \n Title: %s \n \n " ,
Msg - > from , Msg - > emailfrom , FullTo , Msg - > type , Msg - > status , FormatDateAndTime ( ( time_t ) Msg - > datecreated , FALSE ) , Msg - > bid , UTF8Title ) ;
}
MsgBytes = Save = ReadMessageFile ( Number ) ;
msgLen = Msg - > length ;
if ( Msg - > type = = ' P ' )
Index = PMSG ;
else if ( Msg - > type = = ' B ' )
Index = BMSG ;
else
Index = TMSG ;
if ( MsgBytes )
{
if ( Msg - > B2Flags & B2Msg )
{
char * ptr1 ;
// if message has attachments, display them if plain text
if ( Msg - > B2Flags & Attachments )
{
int BodyLen , NewLen ;
int i ;
char * ptr2 , * attptr ;
sprintf ( DownLoad , " <td><a href=/WebMail/DL?%s&%d>Save Attachments</a></td> " , Key , Msg - > number ) ;
WebMail - > Files = 0 ;
ptr1 = MsgBytes ;
// ptr += sprintf(ptr, "Message has Attachments\r\n\r\n");
while ( * ptr1 ! = 13 )
{
ptr2 = strchr ( ptr1 , 10 ) ; // Find CR
if ( memcmp ( ptr1 , " Body: " , 6 ) = = 0 )
{
BodyLen = atoi ( & ptr1 [ 6 ] ) ;
}
if ( memcmp ( ptr1 , " File: " , 6 ) = = 0 )
{
char * ptr3 = strchr ( & ptr1 [ 6 ] , ' ' ) ; // Find Space
* ( ptr2 - 1 ) = 0 ;
WebMail - > FileLen [ WebMail - > Files ] = atoi ( & ptr1 [ 6 ] ) ;
WebMail - > FileName [ WebMail - > Files + + ] = _strdup ( & ptr3 [ 1 ] ) ;
* ( ptr2 - 1 ) = ' ' ; // put space back
}
ptr1 = ptr2 ;
ptr1 + + ;
}
ptr1 + = 2 ; // Over Blank Line and Separator
// ptr1 is pointing to body. Save for possible reply
WebMail - > Body = malloc ( BodyLen + 2 ) ;
memcpy ( WebMail - > Body , ptr1 , BodyLen ) ;
WebMail - > Body [ BodyLen ] = 0 ;
* ( ptr1 + BodyLen ) = 0 ;
ptr + = sprintf ( ptr , " %s " , MsgBytes ) ; // B2 Header and Body
ptr1 + = BodyLen + 2 ; // to first file
// Save pointers to file
attptr = ptr1 ;
for ( i = 0 ; i < WebMail - > Files ; i + + )
{
WebMail - > FileBody [ i ] = malloc ( WebMail - > FileLen [ i ] ) ;
memcpy ( WebMail - > FileBody [ i ] , attptr , WebMail - > FileLen [ i ] ) ;
attptr + = ( WebMail - > FileLen [ i ] + 2 ) ;
}
// if first (only??) attachment is XML and filename
// starts "RMS_Express_Form" process as HTML Form
if ( DisplayHTML & & _memicmp ( ptr1 , " <?xml " , 4 ) = = 0 & &
_memicmp ( WebMail - > FileName [ 0 ] , " RMS_Express_Form_ " , 16 ) = = 0 )
{
int Len = DisplayWebForm ( Session , Msg , WebMail - > FileName [ 0 ] , ptr1 , Reply , MsgBytes , BodyLen + 32 ) ; // 32 for added "has attachments"
free ( MsgBytes ) ;
// Flag as read
if ( ( _stricmp ( Msg - > to , User - > Call ) = = 0 ) | | ( ( User - > flags & F_SYSOP ) & & ( _stricmp ( Msg - > to , " SYSOP " ) = = 0 ) ) )
{
if ( ( Msg - > status ! = ' K ' ) & & ( Msg - > status ! = ' H ' ) & & ( Msg - > status ! = ' F ' ) & & ( Msg - > status ! = ' D ' ) )
{
if ( Msg - > status ! = ' Y ' )
{
Msg - > status = ' Y ' ;
Msg - > datechanged = time ( NULL ) ;
2022-11-12 15:00:02 +00:00
SaveMessageDatabase ( ) ;
2023-12-28 10:31:09 +00:00
SendMessageReadEvent ( Session - > Callsign , Msg ) ;
2022-08-28 09:35:46 +01:00
}
}
}
return Len ;
}
for ( i = 0 ; i < WebMail - > Files ; i + + )
{
int n ;
char * p = ptr1 ;
char c ;
// Check if message is probably binary
int BinCount = 0 ;
NewLen = WebMail - > FileLen [ i ] ;
for ( n = 0 ; n < NewLen ; n + + )
{
c = * p ;
if ( c = = 0 | | ( c & 128 ) )
BinCount + + ;
p + + ;
}
if ( BinCount > NewLen / 10 )
{
// File is probably Binary
ptr + = sprintf ( ptr , " \r Attachment %s is a binary file \r " , WebMail - > FileName [ i ] ) ;
}
else
{
* ( ptr1 + NewLen ) = 0 ;
ptr + = sprintf ( ptr , " \r Attachment %s \r \r " , WebMail - > FileName [ i ] ) ;
RemoveLF ( ptr1 , NewLen + 1 ) ; // Removes LF after CR but not on its own
ptr + = sprintf ( ptr , " %s \r \r " , ptr1 ) ;
User - > Total . MsgsSent [ Index ] + + ;
User - > Total . BytesForwardedOut [ Index ] + = NewLen ;
}
ptr1 + = WebMail - > FileLen [ i ] ;
ptr1 + = 2 ; // Over separator
}
free ( Save ) ;
ptr + = sprintf ( ptr , " \r \r [End of Message #%d from %s] \r " , Number , Msg - > from ) ;
RemoveLF ( Message , ( int ) strlen ( Message ) + 1 ) ; // Removes LF after CR but not on its own
if ( ( _stricmp ( Msg - > to , User - > Call ) = = 0 ) | | ( ( User - > flags & F_SYSOP ) & & ( _stricmp ( Msg - > to , " SYSOP " ) = = 0 ) ) )
{
if ( ( Msg - > status ! = ' K ' ) & & ( Msg - > status ! = ' H ' ) & & ( Msg - > status ! = ' F ' ) & & ( Msg - > status ! = ' D ' ) )
{
if ( Msg - > status ! = ' Y ' )
{
Msg - > status = ' Y ' ;
Msg - > datechanged = time ( NULL ) ;
2022-11-12 15:00:02 +00:00
SaveMessageDatabase ( ) ;
2023-12-28 10:31:09 +00:00
SendMessageReadEvent ( Session - > Callsign , Msg ) ;
2022-08-28 09:35:46 +01:00
}
}
}
2023-10-31 22:42:23 +00:00
if ( DisplayHTML & & stristr ( Message , " </html> " ) )
DisplayStyle = " div " ; // Use div so HTML and XML are interpreted
2022-08-28 09:35:46 +01:00
return sprintf ( Reply , WebMailMsgTemplate , BBSName , User - > Call , Msg - > number , Msg - > number , Key , Msg - > number , Key , DownLoad , Key , Key , Key , DisplayStyle , Message , DisplayStyle ) ;
}
// Remove B2 Headers (up to the File: Line)
// ptr1 = strstr(MsgBytes, "Body:");
// if (ptr1)
// MsgBytes = ptr1;
}
// Body may have cr cr lf which causes double space
crcrptr = strstr ( MsgBytes , " \r \r \n " ) ;
while ( crcrptr )
{
* crcrptr = ' ' ;
crcrptr = strstr ( crcrptr , " \r \r \n " ) ;
}
// Remove lf chars
msgLen = RemoveLF ( MsgBytes , msgLen ) ;
User - > Total . MsgsSent [ Index ] + + ;
// User->Total.BytesForwardedOut[Index] += Length;
// if body not UTF-8, convert it
if ( WebIsUTF8 ( MsgBytes , msgLen ) = = FALSE )
{
2024-11-12 21:20:01 +00:00
int code = TrytoGuessCode ( MsgBytes , msgLen ) ;
2022-08-28 09:35:46 +01:00
2024-11-12 21:20:01 +00:00
UCHAR * UTF = malloc ( msgLen * 3 ) ;
2022-08-28 09:35:46 +01:00
2024-11-12 21:20:01 +00:00
if ( code = = 437 )
msgLen = Convert437toUTF8 ( MsgBytes , msgLen , UTF ) ;
else if ( code = = 1251 )
msgLen = Convert1251toUTF8 ( MsgBytes , msgLen , UTF ) ;
2023-10-10 22:07:04 +01:00
else
2024-11-12 21:20:01 +00:00
msgLen = Convert1252toUTF8 ( MsgBytes , msgLen , UTF ) ;
free ( MsgBytes ) ;
Save = MsgBytes = UTF ;
MsgBytes [ msgLen ] = 0 ;
2022-08-28 09:35:46 +01:00
}
// ptr += sprintf(ptr, "%s", MsgBytes);
memcpy ( ptr , MsgBytes , msgLen ) ;
ptr + = msgLen ;
ptr [ 0 ] = 0 ;
free ( Save ) ;
ptr + = sprintf ( ptr , " \r \r [End of Message #%d from %s] \r " , Number , Msg - > from ) ;
if ( ( _stricmp ( Msg - > to , User - > Call ) = = 0 ) | | ( ( User - > flags & F_SYSOP ) & & ( _stricmp ( Msg - > to , " SYSOP " ) = = 0 ) ) )
{
if ( ( Msg - > status ! = ' K ' ) & & ( Msg - > status ! = ' H ' ) & & ( Msg - > status ! = ' F ' ) & & ( Msg - > status ! = ' D ' ) )
{
if ( Msg - > status ! = ' Y ' )
{
Msg - > status = ' Y ' ;
Msg - > datechanged = time ( NULL ) ;
2022-11-12 15:00:02 +00:00
SaveMessageDatabase ( ) ;
2023-12-28 10:31:09 +00:00
SendMessageReadEvent ( Session - > Callsign , Msg ) ;
2022-08-28 09:35:46 +01:00
}
}
}
}
else
{
ptr + = sprintf ( ptr , " File for Message %d not found \r " , Number ) ;
}
2023-10-31 22:42:23 +00:00
if ( DisplayHTML & & stristr ( Message , " </html> " ) )
2022-08-28 09:35:46 +01:00
DisplayStyle = " div " ; // Use div so HTML and XML are interpreted
return sprintf ( Reply , WebMailMsgTemplate , BBSName , User - > Call , Msg - > number , Msg - > number , Key , Msg - > number , Key , DownLoad , Key , Key , Key , DisplayStyle , Message , DisplayStyle ) ;
}
int KillWebMailMessage ( char * Reply , char * Key , struct UserInfo * User , int Number )
{
struct MsgInfo * Msg ;
char Message [ 100 ] = " " ;
Msg = GetMsgFromNumber ( Number ) ;
if ( Msg = = NULL )
{
sprintf ( Message , " Message %d not found " , Number ) ;
goto returnit ;
}
if ( OkToKillMessage ( User - > flags & F_SYSOP , User - > Call , Msg ) )
{
FlagAsKilled ( Msg , TRUE ) ;
sprintf ( Message , " Message #%d Killed \r " , Number ) ;
goto returnit ;
}
sprintf ( Message , " Not your message \r " ) ;
returnit :
return sprintf ( Reply , WebMailMsgTemplate , BBSName , User - > Call , Msg - > number , Msg - > number , Key , Msg - > number , Key , " " , Key , Key , Key , " div " , Message , " div " ) ;
}
void freeKeys ( KeyValues * Keys )
{
while ( Keys - > Key )
{
free ( Keys - > Key ) ;
free ( Keys - > Value ) ;
Keys + + ;
}
}
void FreeWebMailFields ( WebMailInfo * WebMail )
{
// release any malloc'ed resources
int i ;
char * SaveReply ;
int * SaveRlen ;
if ( WebMail = = NULL )
return ;
if ( WebMail - > txtFile )
free ( WebMail - > txtFile ) ;
if ( WebMail - > txtFileName )
free ( WebMail - > txtFileName ) ;
if ( WebMail - > InputHTMLName )
free ( WebMail - > InputHTMLName ) ;
if ( WebMail - > DisplayHTMLName )
free ( WebMail - > DisplayHTMLName ) ;
if ( WebMail - > ReplyHTMLName )
free ( WebMail - > ReplyHTMLName ) ;
if ( WebMail - > To )
free ( WebMail - > To ) ;
if ( WebMail - > CC )
free ( WebMail - > CC ) ;
if ( WebMail - > Subject )
free ( WebMail - > Subject ) ;
if ( WebMail - > BID )
free ( WebMail - > BID ) ;
if ( WebMail - > Body )
free ( WebMail - > Body ) ;
if ( WebMail - > XML )
free ( WebMail - > XML ) ;
if ( WebMail - > XMLName )
free ( WebMail - > XMLName ) ;
if ( WebMail - > OrigTo )
free ( WebMail - > OrigTo ) ;
if ( WebMail - > OrigSubject )
free ( WebMail - > OrigSubject ) ;
if ( WebMail - > OrigBID )
free ( WebMail - > OrigBID ) ;
if ( WebMail - > OrigBody )
free ( WebMail - > OrigBody ) ;
freeKeys ( WebMail - > txtKeys ) ;
freeKeys ( WebMail - > XMLKeys ) ;
for ( i = 0 ; i < WebMail - > Files ; i + + )
{
free ( WebMail - > FileBody [ i ] ) ;
free ( WebMail - > FileName [ i ] ) ;
}
if ( WebMail - > Header )
free ( WebMail - > Header ) ;
if ( WebMail - > Footer )
free ( WebMail - > Footer ) ;
SaveReply = WebMail - > Reply ;
SaveRlen = WebMail - > RLen ;
2023-10-10 22:07:04 +01:00
# ifndef WIN32
if ( WebMail - > iconv_toUTF8 )
iconv_close ( WebMail - > iconv_toUTF8 ) ;
# endif
2022-08-28 09:35:46 +01:00
memset ( WebMail , 0 , sizeof ( WebMailInfo ) ) ;
WebMail - > Reply = SaveReply ;
WebMail - > RLen = SaveRlen ;
return ;
}
void ProcessWebMailMessage ( struct HTTPConnectionInfo * Session , char * Key , BOOL LOCAL , char * Method , char * NodeURL , char * input , char * Reply , int * RLen , int InputLen )
{
char * URLParams = strlop ( Key , ' & ' ) ;
int ReplyLen ;
char Appl = ' M ' ;
// Webmail doesn't use the normal Mail Key.
// webscript.js doesn't need a key
if ( _stricmp ( NodeURL , " /WebMail/webscript.js " ) = = 0 )
{
if ( jsTemplate )
free ( jsTemplate ) ;
jsTemplate = GetTemplateFromFile ( 2 , " webscript.js " ) ;
ReplyLen = sprintf ( Reply , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n "
" Cache-Control: max-age=60 \r \n Content-Type: text/javascript \r \n \r \n %s " , ( int ) strlen ( jsTemplate ) , jsTemplate ) ;
* RLen = ReplyLen ;
return ;
}
// Neither do js or file downloads
if ( _memicmp ( NodeURL , " /WebMail/WMFile/ " , 16 ) = = 0 )
{
int FileSize ;
char * MsgBytes ;
char MsgFile [ 512 ] ;
FILE * hFile ;
size_t ReadLen ;
char TimeString [ 64 ] ;
char FileTimeString [ 64 ] ;
struct stat STAT ;
char * FN = & NodeURL [ 16 ] ;
char * fileBit = FN ;
char * ext ;
UndoTransparency ( FN ) ;
ext = strchr ( FN , ' . ' ) ;
sprintf ( MsgFile , " %s/%s " , BPQDirectory , FN ) ;
while ( strchr ( fileBit , ' / ' ) )
fileBit = strlop ( fileBit , ' / ' ) ;
if ( stat ( MsgFile , & STAT ) = = - 1 )
{
* RLen = sprintf ( Reply , " HTTP/1.1 404 Not Found \r \n Content-Length: 16 \r \n \r \n Page not found \r \n " ) ;
return ;
}
hFile = fopen ( MsgFile , " rb " ) ;
if ( hFile = = 0 )
{
* RLen = sprintf ( Reply , " HTTP/1.1 404 Not Found \r \n Content-Length: 16 \r \n \r \n Page not found \r \n " ) ;
return ;
}
FileSize = STAT . st_size ;
MsgBytes = malloc ( FileSize + 1 ) ;
ReadLen = fread ( MsgBytes , 1 , FileSize , hFile ) ;
fclose ( hFile ) ;
FormatTime2 ( FileTimeString , STAT . st_ctime ) ;
FormatTime2 ( TimeString , time ( NULL ) ) ;
if ( _stricmp ( ext , " .htm " ) = = 0 | | _stricmp ( ext , " .html " ) = = 0 | | _stricmp ( ext , " .css " ) = = 0 | | _stricmp ( ext , " .js " ) = = 0 )
{
* RLen = sprintf ( Reply , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n "
" Content-Type: text/css \r \n "
" Date: %s \r \n "
" Last-Modified: %s \r \n "
" \r \n %s " , FileSize , TimeString , FileTimeString , MsgBytes ) ;
}
else
{
* RLen = sprintf ( Reply , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n "
" Content-Type: application/octet-stream \r \n "
" Content-Disposition: attachment; filename= \" %s \" \r \n "
" Date: %s \r \n "
" Last-Modified: %s \r \n "
" \r \n %s " , FileSize , fileBit , TimeString , FileTimeString , MsgBytes ) ;
}
free ( MsgBytes ) ;
return ;
}
Session = NULL ;
if ( Key & & Key [ 0 ] )
Session = FindWMSession ( Key ) ;
if ( Session = = NULL )
{
// Lost Session
if ( LOCAL )
{
Session = AllocateWebMailSession ( ) ;
Key = Session - > Key ;
if ( SYSOPCall [ 0 ] )
Session - > User = LookupCall ( SYSOPCall ) ;
else
Session - > User = LookupCall ( BBSName ) ;
if ( Session - > User )
{
strcpy ( NodeURL , " /WebMail/WebMail " ) ;
Session - > WebMailSkip = 0 ;
Session - > WebMailLastUsed = time ( NULL ) ;
}
}
else
{
// Send Login Page unless Signon request
if ( _stricmp ( NodeURL , " /WebMail/Signon " ) ! = 0 | | strcmp ( Method , " POST " ) ! = 0 )
{
ReplyLen = sprintf ( Reply , WebMailSignon , BBSName , BBSName ) ;
* RLen = ReplyLen ;
return ;
}
}
}
if ( strcmp ( Method , " POST " ) = = 0 )
{
if ( _stricmp ( NodeURL , " /WebMail/Signon " ) = = 0 )
{
char * msg = strstr ( input , " \r \n \r \n " ) ; // End of headers
char * user , * password , * Key ;
char Msg [ 128 ] ;
int n ;
if ( msg )
{
struct UserInfo * User ;
if ( strstr ( msg , " Cancel=Cancel " ) )
{
* RLen = sprintf ( Reply , " <html><script>window.location.href = '/';</script> " ) ;
return ;
}
// Webmail Gets Here with a dummy Session
Session = AllocateWebMailSession ( ) ;
Session - > WebMail - > Reply = Reply ;
Session - > WebMail - > RLen = RLen ;
Key = Session - > Key ;
user = strtok_s ( & msg [ 9 ] , " & " , & Key ) ;
password = strtok_s ( NULL , " = " , & Key ) ;
password = Key ;
Session - > User = User = LookupCall ( user ) ;
if ( User )
{
// Check Password
if ( password [ 0 ] & & strcmp ( User - > pass , password ) = = 0 )
{
// send Message Index
Session - > WebMailLastUsed = time ( NULL ) ;
Session - > WebMailSkip = 0 ;
2024-02-23 21:36:36 +00:00
Session - > WebMailMyTX = FALSE ;
Session - > WebMailMyRX = FALSE ;
2022-08-28 09:35:46 +01:00
Session - > WebMailMine = FALSE ;
if ( WebMailTemplate )
{
free ( WebMailTemplate ) ;
WebMailTemplate = NULL ;
}
if ( User - > flags & F_Excluded )
{
n = sprintf_s ( Msg , sizeof ( Msg ) , " Webmail Connect from %s Rejected by Exclude Flag " , _strupr ( user ) ) ;
WriteLogLine ( NULL , ' | ' , Msg , n , LOG_BBS ) ;
ReplyLen = sprintf ( Reply , WebMailSignon , BBSName , BBSName ) ;
* RLen = ReplyLen ;
return ;
}
* RLen = SendWebMailHeader ( Reply , Session - > Key , Session ) ;
n = sprintf_s ( Msg , sizeof ( Msg ) , " Webmail Connect from %s " , _strupr ( user ) ) ;
WriteLogLine ( NULL , ' | ' , Msg , n , LOG_BBS ) ;
return ;
}
}
// Bad User or Pass
ReplyLen = sprintf ( Reply , WebMailSignon , BBSName , BBSName ) ;
* RLen = ReplyLen ;
return ;
}
}
Session - > WebMail - > Reply = Reply ;
Session - > WebMail - > RLen = RLen ;
if ( _stricmp ( NodeURL , " /WebMail/EMSave " ) = = 0 )
{
// Save New Message
SaveNewMessage ( Session , input , Reply , RLen , Key , InputLen ) ;
return ;
}
if ( _stricmp ( NodeURL , " /WebMail/Submit " ) = = 0 )
{
// Get the POST data from the page and place in message
char * param = strstr ( input , " \r \n \r \n " ) ; // End of headers
WebMailInfo * WebMail = Session - > WebMail ;
if ( WebMail = = NULL )
return ; // Can't proceed if we have no info on form
ProcessFormInput ( Session , input , Reply , RLen , InputLen ) ;
return ;
}
if ( _stricmp ( NodeURL , " /WebMail/FormMsgSave " ) = = 0 )
{
// Save New Message
SaveTemplateMessage ( Session , input , Reply , RLen , Key ) ;
return ;
}
if ( _stricmp ( NodeURL , " /WebMail/GetTemplates " ) = = 0 )
{
SendTemplateSelectScreen ( Session , input , InputLen ) ;
return ;
}
// End of POST section
}
if ( _stricmp ( NodeURL , " /WebMail/WMLogout " ) = = 0 )
{
Session - > Key [ 0 ] = 0 ;
Session - > WebMailLastUsed = 0 ;
ReplyLen = sprintf ( Reply , WebMailSignon , BBSName , BBSName ) ;
* RLen = ReplyLen ;
return ;
}
if ( ( _stricmp ( NodeURL , " /WebMail/MailEntry " ) = = 0 ) | |
( _stricmp ( NodeURL , " /WebMail " ) = = 0 ) | |
( _stricmp ( NodeURL , " /WebMail/ " ) = = 0 ) )
{
// Entry from Menu if signed in, continue. If not and Localhost
// signin as sysop.
if ( Session - > User = = NULL )
{
// Not yet signed in
if ( LOCAL )
{
// Webmail Gets Here with a dummy Session
Session = AllocateWebMailSession ( ) ;
Session - > WebMail - > Reply = Reply ;
Session - > WebMail - > RLen = RLen ;
Key = Session - > Key ;
if ( SYSOPCall [ 0 ] )
Session - > User = LookupCall ( SYSOPCall ) ;
else
Session - > User = LookupCall ( BBSName ) ;
if ( Session - > User )
{
strcpy ( NodeURL , " /WebMail/WebMail " ) ;
Session - > WebMailSkip = 0 ;
Session - > WebMailLastUsed = time ( NULL ) ;
}
}
else
{
// Send Login Page
ReplyLen = sprintf ( Reply , WebMailSignon , BBSName , BBSName ) ;
* RLen = ReplyLen ;
return ;
}
}
}
Session - > WebMail - > Reply = Reply ;
Session - > WebMail - > RLen = RLen ;
if ( _stricmp ( NodeURL , " /WebMail/WebMail " ) = = 0 )
{
if ( WebMailTemplate )
{
free ( WebMailTemplate ) ;
WebMailTemplate = NULL ;
}
Session - > WebMailSkip = 0 ;
Session - > WebMailMine = FALSE ;
2024-02-23 21:36:36 +00:00
Session - > WebMailMyTX = FALSE ;
Session - > WebMailMyRX = FALSE ;
2022-08-28 09:35:46 +01:00
* RLen = SendWebMailHeader ( Reply , Session - > Key , Session ) ;
return ;
}
if ( _stricmp ( NodeURL , " /WebMail/WMAll " ) = = 0 )
{
Session - > WebMailSkip = 0 ;
Session - > WebMailTypes [ 0 ] = 0 ;
Session - > WebMailMine = FALSE ;
2024-02-23 21:36:36 +00:00
Session - > WebMailMyTX = FALSE ;
Session - > WebMailMyRX = FALSE ;
2022-08-28 09:35:46 +01:00
* RLen = SendWebMailHeader ( Reply , Session - > Key , Session ) ;
return ;
}
if ( _stricmp ( NodeURL , " /WebMail/WMB " ) = = 0 )
{
Session - > WebMailSkip = 0 ;
strcpy ( Session - > WebMailTypes , " B " ) ;
Session - > WebMailMine = FALSE ;
2024-02-23 21:36:36 +00:00
Session - > WebMailMyTX = FALSE ;
Session - > WebMailMyRX = FALSE ;
2022-08-28 09:35:46 +01:00
* RLen = SendWebMailHeader ( Reply , Session - > Key , Session ) ;
return ;
}
if ( _stricmp ( NodeURL , " /WebMail/WMP " ) = = 0 )
{
Session - > WebMailSkip = 0 ;
strcpy ( Session - > WebMailTypes , " P " ) ;
Session - > WebMailMine = FALSE ;
2024-02-23 21:36:36 +00:00
Session - > WebMailMyTX = FALSE ;
Session - > WebMailMyRX = FALSE ;
2022-08-28 09:35:46 +01:00
* RLen = SendWebMailHeader ( Reply , Session - > Key , Session ) ;
return ;
}
if ( _stricmp ( NodeURL , " /WebMail/WMT " ) = = 0 )
{
Session - > WebMailSkip = 0 ;
strcpy ( Session - > WebMailTypes , " T " ) ;
Session - > WebMailMine = FALSE ;
2024-02-23 21:36:36 +00:00
Session - > WebMailMyTX = FALSE ;
Session - > WebMailMyRX = FALSE ;
2022-08-28 09:35:46 +01:00
* RLen = SendWebMailHeader ( Reply , Session - > Key , Session ) ;
return ;
}
if ( _stricmp ( NodeURL , " /WebMail/WMMine " ) = = 0 )
{
Session - > WebMailSkip = 0 ;
Session - > WebMailTypes [ 0 ] = 0 ;
Session - > WebMailMine = TRUE ;
2024-02-23 21:36:36 +00:00
Session - > WebMailMyTX = FALSE ;
Session - > WebMailMyRX = FALSE ;
* RLen = SendWebMailHeader ( Reply , Session - > Key , Session ) ;
return ;
}
if ( _stricmp ( NodeURL , " /WebMail/WMtoMe " ) = = 0 )
{
Session - > WebMailSkip = 0 ;
Session - > WebMailTypes [ 0 ] = 0 ;
Session - > WebMailMine = FALSE ;
Session - > WebMailMyTX = FALSE ;
Session - > WebMailMyRX = TRUE ;
* RLen = SendWebMailHeader ( Reply , Session - > Key , Session ) ;
return ;
}
if ( _stricmp ( NodeURL , " /WebMail/WMfromMe " ) = = 0 )
{
Session - > WebMailSkip = 0 ;
Session - > WebMailTypes [ 0 ] = 0 ;
Session - > WebMailMine = TRUE ;
Session - > WebMailMyTX = TRUE ;
Session - > WebMailMyRX = FALSE ;
2022-08-28 09:35:46 +01:00
* RLen = SendWebMailHeader ( Reply , Session - > Key , Session ) ;
return ;
}
if ( _stricmp ( NodeURL , " /WebMail/WMSame " ) = = 0 )
{
* RLen = SendWebMailHeader ( Reply , Session - > Key , Session ) ;
return ;
}
2022-11-12 15:00:02 +00:00
if ( _stricmp ( NodeURL , " /WebMail/WMAuto " ) = = 0 )
{
// Auto Refresh Version of index page. Uses Web Sockets
char Page [ 4096 ] ;
char WebSockPage [ ] =
" <!-- Version 6 8/11/2018 --> \r \n "
" <!DOCTYPE html> \r \n "
" <html xmlns= \" http://www.w3.org/1999/xhtml \" xml:lang= \" en \" > \r \n "
" <head> \r \n "
" <meta http-equiv= \" content-type \" content= \" text/html; charset=UTF-8 \" /> \r \n "
" <style type= \" text/css \" > \r \n "
" pre {margin-left: 4px;white-space: pre} \r \n "
" #main{width:700px;position:absolute;left:0px;border:2px solid;background-color: #ffffff;} \r \n "
" </style> \r \n "
" <script src= \" /WebMail/webscript.js \" ></script> \r \n "
" <script type = \" text/javascript \" > \r \n "
" var ws; "
" function Init() "
" { "
" if ( \" WebSocket \" in window) "
" { "
" // open a web socket. Get address from URL \r \n "
" var text = window.location.href; "
" var result = text.substring(7); "
" var myArray = result.split('/', 1); "
" ws = new WebSocket('ws://' + myArray[0] + '/WMRefresh&%s'); \r \n "
" ws.onopen = function() { \r \n "
" // Web Socket is connected \r \n "
" const div = document.getElementById('main'); \r \n "
" div.innerHTML = 'Websock Connected' \r \n "
" ws.send('WMRefresh&%s'); "
" }; \r \n "
" ws.onmessage = function (evt) "
" { "
" var received_msg = evt.data; \r \n "
" const div = document.getElementById('main'); \r \n "
" div.innerHTML = received_msg \r \n "
" }; "
" ws.onclose = function() "
" { "
" // websocket is closed. \r \n "
" const div = document.getElementById('main'); \r \n "
" div.innerHTML = 'Websock Connection Lost'; \r \n "
" }; "
" initialize(120); "
" } "
" else "
" { "
" // The browser doesn't support WebSocket \r \n "
" const div = document.getElementById('main'); \r \n "
" div.innerHTML = 'WebSocket not supported by your Browser - AutoRefresh not availble' \r \n "
" } "
" } "
" </script> \r \n "
" <title>WebMail</title> \r \n "
" </head> \r \n "
" <body background=/background.jpg onload=Init() onresize=initialize(120)> \r \n "
" <h3 align=center> %s Webmail Interface - User %s - Message List</h3> \r \n "
" <table align=center border=1 cellpadding=2 bgcolor=white><tr> \r \n "
" \r \n "
" <td><a href=/WebMail/WMB?%s>Bulls</a></td> \r \n "
" <td><a href=/WebMail/WMP?%s>Personal</a></td> \r \n "
" <td><a href=/WebMail/WMT?%s>NTS</a></td> \r \n "
" <td><a href=/WebMail/WMALL?%s>All Types</a></td> \r \n "
" <td><a href=/WebMail/WMMine?%s>Mine</a></td> \r \n "
2024-02-23 21:36:36 +00:00
" <td><a href=/WebMail/WMfromMe?%s>My Sent</a></td> \r \n "
" <td><a href=/WebMail/WMtoMe?%s>My Rxed</a></td> \r \n "
2022-11-12 15:00:02 +00:00
" <td><a href=/WebMail/WMAuto?%s>Auto Refresh</a></td> \r \n "
" <td><a href= \" # \" onclick= \" newmsg('%s'); return false; \" >Send Message</a></td> \r \n "
" <td><a href=/WebMail/WMLogout?%s>Logout</a></td> \r \n "
" <td><a href=/>Node Menu</a></td></tr></table> \r \n "
" <br> \r \n "
" <div align=left id=main style=overflow:scroll;>Waiting for data...</div> \r \n "
" </body></html> \r \n " ;
2024-02-23 21:36:36 +00:00
sprintf ( Page , WebSockPage , Key , Key , BBSName , Session - > User - > Call , Key , Key , Key , Key , Key , Key , Key , Key , Key , Key ) ;
2022-11-12 15:00:02 +00:00
* RLen = sprintf ( Reply , " %s " , Page ) ;
return ;
}
2022-08-28 09:35:46 +01:00
if ( memcmp ( NodeURL , " /WebMail/QuoteOriginal/ " , 15 ) = = 0 )
{
// Reply to Message
int n , len ;
struct MsgInfo * Msg ;
char Message [ 100 ] = " " ;
char Title [ 100 ] ;
char * MsgBytes , * Save , * NewBytes ;
char * ptr ;
char * ptr1 , * ptr2 ;
char * EncodedTitle ;
n = Session - > WebMail - > CurrentMessageIndex ;
Msg = GetMsgFromNumber ( n ) ;
if ( Msg = = NULL )
{
sprintf ( Message , " Message %d not found " , n ) ;
* RLen = sprintf ( Reply , " %s " , Message ) ;
return ;
}
Session - > WebMail - > Msg = Msg ;
if ( stristr ( Msg - > title , " Re: " ) = = 0 )
sprintf ( Title , " Re:%s " , Msg - > title ) ;
else
sprintf ( Title , " %s " , Msg - > title ) ;
MsgBytes = Save = ReadMessageFile ( n ) ;
ptr = NewBytes = malloc ( ( Msg - > length * 2 ) + 256 ) ;
// Copy a line at a time with "> " in front of each
ptr + = sprintf ( ptr , " %s " , " \r \n \r \n \r \n \r \n \r \n Original Message \r \n \r \n > " ) ;
ptr1 = ptr2 = MsgBytes ;
len = ( int ) strlen ( MsgBytes ) ;
while ( len - - > 0 )
{
* ptr + + = * ptr1 ;
if ( * ( ptr1 ) = = ' \n ' )
{
* ptr + + = ' > ' ;
* ptr + + = ' ' ;
}
ptr1 + + ;
}
* ptr + + = 0 ;
EncodedTitle = doXMLTransparency ( Msg - > title ) ;
* RLen = sprintf ( Reply , MsgInputPage , Key , Msg - > from , " " , EncodedTitle , NewBytes ) ;
free ( EncodedTitle ) ;
free ( MsgBytes ) ;
free ( NewBytes ) ;
return ;
}
if ( memcmp ( NodeURL , " /WebMail/Reply/ " , 15 ) = = 0 )
{
// Reply to Message
int n = atoi ( & NodeURL [ 15 ] ) ;
struct MsgInfo * Msg ;
char Message [ 100 ] = " " ;
char Title [ 100 ] ;
char * EncodedTitle ;
// Quote Original
char Button [ ] =
" <script>function myfunc(){ "
" document.getElementById('myform').action = '/WebMail/QuoteOriginal' + '?%s'; "
" document.getElementById('myform').submit();}</script> "
" <input type=button class='btn' onclick='myfunc()' "
2024-12-16 17:54:16 +00:00
" value='Include Original Msg'> " ;
2022-08-28 09:35:46 +01:00
char Temp [ 1024 ] ;
char ReplyAddr [ 128 ] ;
Msg = GetMsgFromNumber ( n ) ;
if ( Msg = = NULL )
{
sprintf ( Message , " Message %d not found " , n ) ;
* RLen = sprintf ( Reply , " %s " , Message ) ;
return ;
}
Session - > WebMail - > Msg = Msg ;
// See if the message was displayed in an HTML form with a reply template
* RLen = ReplyToFormsMessage ( Session , Msg , Reply , FALSE ) ;
// If couldn't build reply form use normal text reply
if ( * RLen )
return ;
sprintf ( Temp , Button , Key ) ;
if ( stristr ( Msg - > title , " Re: " ) = = 0 )
sprintf ( Title , " Re:%s " , Msg - > title ) ;
else
sprintf ( Title , " %s " , Msg - > title ) ;
strcpy ( ReplyAddr , Msg - > from ) ;
strcat ( ReplyAddr , Msg - > emailfrom ) ;
EncodedTitle = doXMLTransparency ( Msg - > title ) ;
* RLen = sprintf ( Reply , MsgInputPage , Key , Msg - > from , Temp , EncodedTitle , " " ) ;
free ( EncodedTitle ) ;
return ;
}
if ( strcmp ( NodeURL , " /WebMail/WM " ) = = 0 )
{
// Read Message
int n = 0 ;
if ( URLParams )
n = atoi ( URLParams ) ;
if ( WebMailMsgTemplate )
free ( WebMailMsgTemplate ) ;
WebMailMsgTemplate = GetTemplateFromFile ( 5 , " WebMailMsg.txt " ) ;
* RLen = ViewWebMailMessage ( Session , Reply , n , TRUE ) ;
return ;
}
if ( strcmp ( NodeURL , " /WebMail/WMPrev " ) = = 0 )
{
// Read Previous Message
int m ;
struct MsgInfo * Msg ;
struct UserInfo * User = Session - > User ;
for ( m = Session - > WebMail - > CurrentMessageIndex - 1 ; m > = 1 ; m - - )
{
Msg = GetMsgFromNumber ( m ) ;
if ( Msg = = 0 | | Msg - > type = = 0 | | Msg - > status = = 0 )
continue ; // Protect against corrupt messages
if ( Msg & & CheckUserMsg ( Msg , User - > Call , User - > flags & F_SYSOP ) )
{
// Display if it is the right type and in the page range we want
if ( Session - > WebMailTypes [ 0 ] & & strchr ( Session - > WebMailTypes , Msg - > type ) = = 0 )
continue ;
// All Types or right Type. Check Mine Flag
if ( Session - > WebMailMine )
{
// Only list if to or from me
if ( strcmp ( User - > Call , Msg - > to ) ! = 0 & & strcmp ( User - > Call , Msg - > from ) ! = 0 )
continue ;
}
2024-02-23 21:36:36 +00:00
if ( Session - > WebMailMyTX )
{
// Only list if to or from me
if ( strcmp ( User - > Call , Msg - > from ) ! = 0 )
continue ;
}
if ( Session - > WebMailMyRX )
{
// Only list if to or from me
if ( strcmp ( User - > Call , Msg - > to ) ! = 0 )
continue ;
}
2022-08-28 09:35:46 +01:00
* RLen = ViewWebMailMessage ( Session , Reply , m , TRUE ) ;
2024-02-23 21:36:36 +00:00
return ;
2022-08-28 09:35:46 +01:00
}
}
// No More
* RLen = sprintf ( Reply , " <html><script>alert( \" No More Messages \" );window.location.href = '/Webmail/WebMail?%s';</script></html></script></html> " , Session - > Key ) ;
return ;
}
if ( strcmp ( NodeURL , " /WebMail/WMNext " ) = = 0 )
{
// Read Previous Message
int m ;
struct MsgInfo * Msg ;
struct UserInfo * User = Session - > User ;
for ( m = Session - > WebMail - > CurrentMessageIndex + 1 ; m < = LatestMsg ; m + + )
{
Msg = GetMsgFromNumber ( m ) ;
2024-02-23 21:36:36 +00:00
2022-08-28 09:35:46 +01:00
if ( Msg = = 0 | | Msg - > type = = 0 | | Msg - > status = = 0 )
continue ; // Protect against corrupt messages
2024-02-23 21:36:36 +00:00
2022-08-28 09:35:46 +01:00
if ( Msg & & CheckUserMsg ( Msg , User - > Call , User - > flags & F_SYSOP ) )
{
// Display if it is the right type and in the page range we want
if ( Session - > WebMailTypes [ 0 ] & & strchr ( Session - > WebMailTypes , Msg - > type ) = = 0 )
continue ;
// All Types or right Type. Check Mine Flag
if ( Session - > WebMailMine )
{
// Only list if to or from me
if ( strcmp ( User - > Call , Msg - > to ) ! = 0 & & strcmp ( User - > Call , Msg - > from ) ! = 0 )
continue ;
}
2024-02-23 21:36:36 +00:00
if ( Session - > WebMailMyTX )
{
// Only list if to or from me
if ( strcmp ( User - > Call , Msg - > from ) ! = 0 )
continue ;
}
if ( Session - > WebMailMyRX )
{
// Only list if to or from me
if ( strcmp ( User - > Call , Msg - > to ) ! = 0 )
continue ;
}
2022-08-28 09:35:46 +01:00
* RLen = ViewWebMailMessage ( Session , Reply , m , TRUE ) ;
2024-02-23 21:36:36 +00:00
return ;
2022-08-28 09:35:46 +01:00
}
}
// No More
* RLen = sprintf ( Reply , " <html><script>alert( \" No More Messages \" );window.location.href = '/Webmail/WebMail?%s';</script></html></script></html> " , Session - > Key ) ;
return ;
}
if ( strcmp ( NodeURL , " /WebMail/DisplayText " ) = = 0 )
{
// Read Message
int n = 0 ;
if ( URLParams )
n = atoi ( URLParams ) ;
if ( WebMailMsgTemplate )
free ( WebMailMsgTemplate ) ;
WebMailMsgTemplate = GetTemplateFromFile ( 5 , " WebMailMsg.txt " ) ;
* RLen = ViewWebMailMessage ( Session , Reply , n , FALSE ) ;
return ;
}
if ( memcmp ( NodeURL , " /WebMail/WMDel/ " , 15 ) = = 0 )
{
// Kill Message
int n = atoi ( & NodeURL [ 15 ] ) ;
* RLen = KillWebMailMessage ( Reply , Session - > Key , Session - > User , n ) ;
return ;
}
if ( _stricmp ( NodeURL , " /WebMail/NewMsg " ) = = 0 )
{
// Add HTML Template Button if we have any HTML Form
char Button [ ] =
" <script>function myfunc(){ "
" document.getElementById('myform').action = '/WebMail/GetTemplates' + '?%s'; "
" document.getElementById('myform').submit();}</script> "
" <input type=button class='btn' onclick='myfunc()' "
" value='Use Template'> " ;
char Temp [ 1024 ] ;
FreeWebMailFields ( Session - > WebMail ) ; // Tidy up for new message
sprintf ( Temp , Button , Key ) ;
if ( FormDirCount = = 0 )
* RLen = sprintf ( Reply , MsgInputPage , Key , " " , " " , " " , " " ) ;
else
* RLen = sprintf ( Reply , MsgInputPage , Key , " " , Temp , " " , " " ) ;
return ;
}
if ( _memicmp ( NodeURL , " /WebMail/GetPage/ " , 17 ) = = 0 )
{
// Read and Parse Template File
GetPage ( Session , NodeURL ) ;
return ;
}
if ( _memicmp ( NodeURL , " /WebMail/GetList/ " , 17 ) = = 0 )
{
// Send Select Template Popup
char * SubDir ;
int DirNo = 0 ;
int SubDirNo = 0 ;
char popup [ 10000 ] ;
char popuphddr [ ] =
" <html><body align=center background='/background.jpg'> "
" <script>function myFunction() {var x = document.getElementById( \" mySelect \" ).value; "
" var Key = \" %s \" ; "
" var param = \" toolbar=yes,location=yes,directories=yes,status=yes,menubar,=scrollbars=yes,resizable=yes,titlebar=yes,toobar=yes \" ; "
" window.open( \" /WebMail/GetPage/ \" + x + \" ? \" + Key, \" _self \" ,param); "
" }</script> "
" <p align=center> "
" Select Required Template from %s<br><br> "
" <select size=15 id= \" mySelect \" onclick= \" myFunction() \" > "
" <option value=-1>No Page Selected " ;
struct HtmlFormDir * Dir ;
int i ;
SubDir = strlop ( & NodeURL [ 17 ] , ' : ' ) ;
DirNo = atoi ( & NodeURL [ 17 ] ) ;
if ( DirNo = = - 1 )
{
// User has gone back, then selected "No Folder Selected"
// For now just stop crash
DirNo = 0 ;
}
if ( SubDir )
SubDirNo = atoi ( SubDir ) ;
Dir = HtmlFormDirs [ DirNo ] ;
if ( SubDir )
sprintf ( popup , popuphddr , Key , Dir - > Dirs [ SubDirNo ] - > DirName ) ;
else
sprintf ( popup , popuphddr , Key , Dir - > DirName ) ;
if ( SubDir )
{
for ( i = 0 ; i < Dir - > Dirs [ SubDirNo ] - > FormCount ; i + + )
{
char * Name = Dir - > Dirs [ SubDirNo ] - > Forms [ i ] - > FileName ;
// We only send if there is a .txt file
if ( _stricmp ( & Name [ strlen ( Name ) - 4 ] , " .txt " ) = = 0 )
sprintf ( popup , " %s <option value=%d:%d,%d>%s " , popup , DirNo , SubDirNo , i , Name ) ;
}
}
else
{
for ( i = 0 ; i < Dir - > FormCount ; i + + )
{
char * Name = Dir - > Forms [ i ] - > FileName ;
// We only send if there is a .txt file
if ( _stricmp ( & Name [ strlen ( Name ) - 4 ] , " .txt " ) = = 0 )
sprintf ( popup , " %s <option value=%d,%d>%s " , popup , DirNo , i , Name ) ;
}
}
sprintf ( popup , " %s</select></p> " , popup ) ;
* RLen = sprintf ( Reply , " %s " , popup ) ;
return ;
}
if ( _stricmp ( NodeURL , " /WebMail/DL " ) = = 0 )
{
getAttachmentList ( Session , Reply , RLen , URLParams ) ;
return ;
}
if ( _stricmp ( NodeURL , " /WebMail/GetDownLoad " ) = = 0 )
{
DownloadAttachments ( Session , Reply , RLen , URLParams ) ;
return ;
}
if ( _stricmp ( NodeURL , " /WebMail/DoSelect " ) = = 0 )
{
// User has selected item from Template <select> field
ProcessSelectResponse ( Session , URLParams ) ;
return ;
}
// Unrecognised message - reset session
* RLen = sprintf ( Reply , WebMailSignon , BBSName , BBSName ) ;
}
VOID SendTemplateSelectScreen ( struct HTTPConnectionInfo * Session , char * Params , int InputLen )
{
// Save any supplied message fields and Send HTML Template dropdown list
char popuphddr [ ] =
" <html><body align=center background='/background.jpg'> "
" <script> "
" function myFunction(val) {var x = document.getElementById(val).value; "
" var Key = \" %s \" ; "
" var param = \" toolbar=yes,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,titlebar=yes,toobar=yes \" ; "
" window.open( \" /WebMail/GetList/ \" + x + \" ? \" + Key, \" _self \" ,param); "
" } "
" </script> "
" <p align=center> "
" Select Required Template Folder from List<br><br> "
" <table border=1 cellpadding=2 bgcolor=white> "
" <tr> "
" <th>Standard Templates</th> "
" <th>Local Templates</th> "
" </tr> "
" <tr><td width=50%%><select size=15 id= \" Sel1 \" onclick= \" myFunction('Sel1') \" > " ;
char NewGroup [ ] =
" </select></td><td width=50%% align=center> "
" <select size=15 id=Sel2 onclick= \" myFunction('Sel2') \" > " ;
char popup [ 10000 ] ;
struct HtmlFormDir * Dir ;
char * LastGroup ;
char * Input = strstr ( Params , " \r \n \r \n " ) ; // To end of HTML header
int i ;
int MsgLen = 0 ;
char * Boundary ;
WebMailInfo * WebMail = Session - > WebMail ;
Input = Params ;
Boundary = initMultipartUnpack ( & Input ) ;
if ( Boundary = = NULL )
return ; // Can't work without one
// Input points to start of part. Normally preceeded by \r\n which is Boundary Terminator. If preceeded by -- we have used last part
while ( Input & & Input [ - 1 ] ! = ' - ' )
{
char * Name , * Value ;
int ValLen ;
if ( unpackPart ( Boundary , & Input , & Name , & Value , & ValLen , Params + InputLen ) = = FALSE )
{
// ReportCorrupt(WebMail);
free ( Boundary ) ;
return ;
}
SaveInputValue ( WebMail , Name , Value , ValLen ) ;
}
strlop ( WebMail - > BID , ' ' ) ;
if ( strlen ( WebMail - > BID ) > 12 )
WebMail - > BID [ 12 ] = 0 ;
UndoTransparency ( WebMail - > To ) ;
UndoTransparency ( WebMail - > CC ) ;
UndoTransparency ( WebMail - > BID ) ;
UndoTransparency ( WebMail - > Subject ) ;
UndoTransparency ( WebMail - > Body ) ;
// Save values from message when Template requested (npt sure if we need these!
WebMail - > OrigTo = _strdup ( WebMail - > To ) ;
WebMail - > OrigSubject = _strdup ( WebMail - > Subject ) ;
WebMail - > OrigType = WebMail - > Type ;
WebMail - > OrigBID = _strdup ( WebMail - > BID ) ;
WebMail - > OrigBody = _strdup ( WebMail - > Body ) ;
// Also to active fields in case not changed by form
sprintf ( popup , popuphddr , Session - > Key ) ;
LastGroup = HtmlFormDirs [ 0 ] - > FormSet ; // Save so we know when changes
for ( i = 0 ; i < FormDirCount ; i + + )
{
int n ;
Dir = HtmlFormDirs [ i ] ;
if ( strcmp ( LastGroup , Dir - > FormSet ) ! = 0 )
{
LastGroup = Dir - > FormSet ;
sprintf ( popup , " %s%s " , popup , NewGroup ) ;
}
sprintf ( popup , " %s <option value=%d>%s " , popup , i , Dir - > DirName ) ;
// Recurse any Subdirs
n = 0 ;
while ( n < Dir - > DirCount )
{
sprintf ( popup , " %s <option value=%d:%d>%s " , popup , i , n , Dir - > Dirs [ n ] - > DirName ) ;
n + + ;
}
}
sprintf ( popup , " %s</select></td></tr></table></p> " , popup ) ;
* WebMail - > RLen = sprintf ( WebMail - > Reply , " %s " , popup ) ;
free ( Boundary ) ;
return ;
}
static char WinlinkAddr [ ] = " WINLINK.ORG " ;
VOID SaveNewMessage ( struct HTTPConnectionInfo * Session , char * MsgPtr , char * Reply , int * RLen , char * Rest , int InputLen )
{
int i , ReplyLen = 0 ;
struct MsgInfo * Msg ;
FILE * hFile ;
int Template = 0 ;
char * via = NULL ;
BIDRec * BIDRec ;
char MsgFile [ MAX_PATH ] ;
size_t WriteLen = 0 ;
char * HDest ;
char * HDestCopy ;
char * HDestRest ;
char * Vptr = NULL ;
char * FileList = NULL ;
char Prompt [ 256 ] = " Message Saved " ;
char OrigTo [ 256 ] ;
WebMailInfo * WebMail = Session - > WebMail ;
struct UserInfo * user ;
CIRCUIT conn ;
// So we can have attachments input is now Content-Type: multipart/form-data;
char * Input ;
size_t MsgLen = 0 ;
char * Boundary ;
strcpy ( conn . Callsign , Session - > User - > Call ) ;
Input = MsgPtr ;
Boundary = initMultipartUnpack ( & Input ) ;
if ( Boundary = = NULL )
return ; // Can't work without one
// Input points to start of part. Normally preceeded by \r\n which is Boundary Terminator. If preceeded by -- we have used last part
while ( Input & & Input [ - 1 ] ! = ' - ' )
{
char * Name , * Value ;
int ValLen ;
if ( unpackPart ( Boundary , & Input , & Name , & Value , & ValLen , MsgPtr + InputLen ) = = FALSE )
{
// ReportCorrupt(WebMail);
free ( Boundary ) ;
return ;
}
if ( SaveInputValue ( WebMail , Name , Value , ValLen ) = = FALSE )
{
* RLen = sprintf ( Reply , " <html><script>window.location.href = '/Webmail/WebMail?%s';</script> " , Session - > Key ) ;
return ;
}
}
if ( WebMail - > txtFileName )
{
// Processing Form Input
SaveTemplateMessage ( Session , MsgPtr , Reply , RLen , Rest ) ;
// Prevent re-entry
free ( WebMail - > txtFileName ) ;
WebMail - > txtFileName = NULL ;
return ;
}
// If we aren't using a template then all the information is in the WebMail fields, as we haven't been here before.
strlop ( WebMail - > BID , ' ' ) ;
if ( strlen ( WebMail - > BID ) > 12 )
WebMail - > BID [ 12 ] = 0 ;
UndoTransparency ( WebMail - > BID ) ;
UndoTransparency ( WebMail - > To ) ;
UndoTransparency ( WebMail - > Subject ) ;
UndoTransparency ( WebMail - > Body ) ;
MsgLen = strlen ( WebMail - > Body ) ;
// We will need to mess about with To field. Create a copy so the original can go in B2 header if we use one
if ( WebMail - > To [ 0 ] = = 0 )
{
* RLen = sprintf ( Reply , " %s " , " <html><script>alert( \" To: Call missing! \" );window.history.back();</script></html> " ) ;
FreeWebMailFields ( WebMail ) ; // We will reprocess message and attachments so reinitialise
return ;
}
if ( strlen ( WebMail - > To ) > 255 )
{
* RLen = sprintf ( Reply , " %s " , " <html><script>alert( \" To: Call too long! \" );window.history.back();</script></html> " ) ;
FreeWebMailFields ( WebMail ) ; // We will reprocess message and attachments so reinitialise
return ;
}
HDest = _strdup ( WebMail - > To ) ;
if ( strlen ( WebMail - > BID ) )
{
if ( LookupBID ( WebMail - > BID ) )
{
// Duplicate bid
* RLen = sprintf ( Reply , " %s " , " <html><script>alert( \" Duplicate BID \" );window.history.back();</script></html> " ) ;
FreeWebMailFields ( WebMail ) ; // We will reprocess message and attachments so reinitialise
return ;
}
}
if ( WebMail - > Type = = ' B ' )
{
if ( RefuseBulls )
{
* RLen = sprintf ( Reply , " %s " , " <html><script>alert( \" This system doesn't allow sending Bulls \" );window.history.back();script></html> " ) ;
FreeWebMailFields ( WebMail ) ; // We will reprocess message and attachments so reinitialise
return ;
}
if ( Session - > User - > flags & F_NOBULLS )
{
* RLen = sprintf ( Reply , " %s " , " <html><script>alert( \" You are not allowed to send Bulls \" );window.history.back();</script></html> " ) ;
FreeWebMailFields ( WebMail ) ; // We will reprocess message and attachments so reinitialise
return ;
}
}
// ?? Can we just loop though the rest of the code to allow multiple dests ??
HDestCopy = HDest ;
while ( HDest & & HDest [ 0 ] )
{
HDestRest = strlop ( HDest , ' ; ' ) ;
Msg = AllocateMsgRecord ( ) ;
// Set number here so they remain in sequence
Msg - > number = + + LatestMsg ;
MsgnotoMsg [ Msg - > number ] = Msg ;
strcpy ( Msg - > from , Session - > User - > Call ) ;
if ( _memicmp ( HDest , " rms: " , 4 ) = = 0 | | _memicmp ( HDest , " rms/ " , 4 ) = = 0 )
{
Vptr = & HDest [ 4 ] ;
strcpy ( Msg - > to , " RMS " ) ;
}
else if ( _memicmp ( HDest , " smtp: " , 5 ) = = 0 )
{
if ( ISP_Gateway_Enabled )
{
Vptr = & HDest [ 5 ] ;
Msg - > to [ 0 ] = 0 ;
}
}
else if ( strchr ( HDest , ' @ ' ) )
{
strcpy ( OrigTo , HDest ) ;
Vptr = strlop ( HDest , ' @ ' ) ;
if ( Vptr )
{
// If looks like a valid email address, treat as such
if ( strlen ( HDest ) > 6 | | ! CheckifPacket ( Vptr ) )
{
// Assume Email address
Vptr = OrigTo ;
if ( FindRMS ( ) | | strchr ( Vptr , ' ! ' ) ) // have RMS or source route
strcpy ( Msg - > to , " RMS " ) ;
else if ( ISP_Gateway_Enabled )
Msg - > to [ 0 ] = 0 ;
else if ( isAMPRMsg ( OrigTo ) )
strcpy ( Msg - > to , " RMS " ) ; // Routing will redirect it
else
{
* RLen = sprintf ( Reply , " %s " , " <html><script>alert( \" This system doesn't allow Sending to Internet Email \" );window.close();</script></html> " ) ;
FreeWebMailFields ( WebMail ) ; // We will reprocess message and attachments so reinitialise
return ;
}
}
else
strcpy ( Msg - > to , _strupr ( HDest ) ) ;
}
}
else
{
// No @
if ( strlen ( HDest ) > 6 )
HDest [ 6 ] = 0 ;
strcpy ( Msg - > to , _strupr ( HDest ) ) ;
}
if ( SendBBStoSYSOPCall )
if ( _stricmp ( HDest , BBSName ) = = 0 )
strcpy ( Msg - > to , SYSOPCall ) ;
if ( Vptr )
{
if ( strlen ( Vptr ) > 40 )
Vptr [ 40 ] = 0 ;
strcpy ( Msg - > via , _strupr ( Vptr ) ) ;
}
else
{
// No via. If not local user try to add BBS
struct UserInfo * ToUser = LookupCall ( Msg - > to ) ;
if ( ToUser )
{
// Local User. If Home BBS is specified, use it
if ( ToUser - > flags & F_RMSREDIRECT )
{
// sent to Winlink
strcpy ( Msg - > via , WinlinkAddr ) ;
sprintf ( Prompt , " Redirecting to winlink.org \r " ) ;
}
else if ( ToUser - > HomeBBS [ 0 ] )
{
strcpy ( Msg - > via , ToUser - > HomeBBS ) ;
sprintf ( Prompt , " %s added from HomeBBS. Message Saved " , Msg - > via ) ;
}
}
else
{
// Not local user - Check WP
WPRecP WP = LookupWP ( Msg - > to ) ;
if ( WP )
{
strcpy ( Msg - > via , WP - > first_homebbs ) ;
sprintf ( Prompt , " %s added from WP " , Msg - > via ) ;
}
}
}
if ( strlen ( WebMail - > Subject ) > 60 )
WebMail - > Subject [ 60 ] = 0 ;
strcpy ( Msg - > title , WebMail - > Subject ) ;
Msg - > type = WebMail - > Type ;
if ( Session - > User - > flags & F_HOLDMAIL )
{
int Length = 0 ;
char * MailBuffer = malloc ( 100 ) ;
char Title [ 100 ] ;
Msg - > status = ' H ' ;
Length = sprintf ( MailBuffer , " Message %d Held \r \n " , Msg - > number ) ;
sprintf ( Title , " Message %d Held - %s " , Msg - > number , " User has Hold Messages flag set " ) ;
SendMessageToSYSOP ( Title , MailBuffer , Length ) ;
}
else
Msg - > status = ' N ' ;
if ( strlen ( WebMail - > BID ) = = 0 )
sprintf ( Msg - > bid , " %d_%s " , LatestMsg , BBSName ) ;
else
strcpy ( Msg - > bid , WebMail - > BID ) ;
Msg - > datereceived = Msg - > datechanged = Msg - > datecreated = time ( NULL ) ;
BIDRec = AllocateBIDRecord ( ) ;
strcpy ( BIDRec - > BID , Msg - > bid ) ;
BIDRec - > mode = Msg - > type ;
BIDRec - > u . msgno = LOWORD ( Msg - > number ) ;
BIDRec - > u . timestamp = LOWORD ( time ( NULL ) / 86400 ) ;
Msg - > length = ( int ) MsgLen + WebMail - > HeaderLen + WebMail - > FooterLen ;
sprintf_s ( MsgFile , sizeof ( MsgFile ) , " %s/m_%06d.mes " , MailDir , Msg - > number ) ;
// BuildFormMessage(Session, Msg);
if ( WebMail - > Files )
{
// Send as B2
char * B2Header = BuildB2Header ( WebMail , Msg , NULL , 0 ) ;
hFile = fopen ( MsgFile , " wb " ) ;
if ( hFile )
{
WriteLen = fwrite ( B2Header , 1 , strlen ( B2Header ) , hFile ) ;
WriteLen + = fwrite ( WebMail - > Header , 1 , WebMail - > HeaderLen , hFile ) ;
WriteLen + = fwrite ( WebMail - > Body , 1 , MsgLen , hFile ) ;
WriteLen + = fwrite ( WebMail - > Footer , 1 , WebMail - > FooterLen , hFile ) ;
WriteLen + = fwrite ( " \r \n " , 1 , 2 , hFile ) ;
for ( i = 0 ; i < WebMail - > Files ; i + + )
{
WriteLen + = fwrite ( WebMail - > FileBody [ i ] , 1 , WebMail - > FileLen [ i ] , hFile ) ;
WriteLen + = fwrite ( " \r \n " , 1 , 2 , hFile ) ;
}
fclose ( hFile ) ;
free ( B2Header ) ;
Msg - > length = ( int ) WriteLen ;
}
}
else
{
hFile = fopen ( MsgFile , " wb " ) ;
if ( hFile )
{
WriteLen + = fwrite ( WebMail - > Header , 1 , WebMail - > HeaderLen , hFile ) ;
WriteLen + = fwrite ( WebMail - > Body , 1 , MsgLen , hFile ) ;
WriteLen + = fwrite ( WebMail - > Footer , 1 , WebMail - > FooterLen , hFile ) ;
fclose ( hFile ) ;
}
}
MatchMessagetoBBSList ( Msg , & conn ) ;
BuildNNTPList ( Msg ) ; // Build NNTP Groups list
2023-12-08 12:26:52 +00:00
if ( Msg - > status ! = ' H ' & & Msg - > type = = ' B ' & & memcmp ( Msg - > fbbs , zeros , NBMASK ) ! = 0 )
Msg - > status = ' $ ' ; // Has forwarding
2023-12-28 10:31:09 +00:00
2022-08-28 09:35:46 +01:00
if ( EnableUI )
SendMsgUI ( Msg ) ;
user = LookupCall ( Msg - > to ) ;
2023-12-28 10:31:09 +00:00
// If Event Notifications enabled report a new message event
SendNewMessageEvent ( user - > Call , Msg ) ;
2024-12-16 17:54:16 +00:00
# ifndef NOMQTT
if ( MQTT )
MQTTMessageEvent ( Msg ) ;
# endif
2022-08-28 09:35:46 +01:00
if ( user & & ( user - > flags & F_APRSMFOR ) )
{
char APRS [ 128 ] ;
char Call [ 16 ] ;
int SSID = user - > flags > > 28 ;
if ( SSID )
sprintf ( Call , " %s-%d " , Msg - > to , SSID ) ;
else
strcpy ( Call , Msg - > to ) ;
sprintf ( APRS , " New BBS Message %s From %s " , Msg - > title , Msg - > from ) ;
APISendAPRSMessage ( APRS , Call ) ;
}
HDest = HDestRest ;
}
* RLen = SendWebMailHeaderEx ( Reply , Session - > Key , Session , Prompt ) ;
SaveMessageDatabase ( ) ;
SaveBIDDatabase ( ) ;
FreeWebMailFields ( WebMail ) ;
free ( HDestCopy ) ;
return ;
}
// RMS Express Forms Support
char * GetHTMLViewerTemplate ( char * FN )
{
int i , j , k , l ;
// Seach list of forms for base file (without .html)
for ( i = 0 ; i < FormDirCount ; i + + )
{
struct HtmlFormDir * Dir = HtmlFormDirs [ i ] ;
for ( j = 0 ; j < Dir - > FormCount ; j + + )
{
if ( strcmp ( FN , Dir - > Forms [ j ] - > FileName ) = = 0 )
{
return CheckFile ( Dir , FN ) ;
}
}
if ( Dir - > DirCount )
{
for ( l = 0 ; l < Dir - > DirCount ; l + + )
{
2023-12-28 10:31:09 +00:00
struct HtmlFormDir * SDir = Dir - > Dirs [ l ] ;
if ( SDir - > DirCount )
2022-08-28 09:35:46 +01:00
{
2023-12-28 10:31:09 +00:00
struct HtmlFormDir * SSDir = SDir - > Dirs [ 0 ] ;
int x = 1 ;
}
for ( k = 0 ; k < SDir - > FormCount ; k + + )
{
if ( _stricmp ( FN , SDir - > Forms [ k ] - > FileName ) = = 0 )
2022-08-28 09:35:46 +01:00
{
2023-12-28 10:31:09 +00:00
return CheckFile ( SDir , SDir - > Forms [ k ] - > FileName ) ;
2022-08-28 09:35:46 +01:00
}
}
2023-12-28 10:31:09 +00:00
if ( SDir - > DirCount )
{
struct HtmlFormDir * SSDir = SDir - > Dirs [ 0 ] ;
int x = 1 ;
}
2022-08-28 09:35:46 +01:00
}
}
}
return NULL ;
}
VOID GetReply ( struct HTTPConnectionInfo * Session , char * NodeURL )
{
}
VOID GetPage ( struct HTTPConnectionInfo * Session , char * NodeURL )
{
// Read the HTML Template file and do any needed substitutions
WebMailInfo * WebMail = Session - > WebMail ;
KeyValues * txtKey = WebMail - > txtKeys ;
int DirNo ;
char * ptr ;
int FileNo = 0 ;
char * SubDir ;
int SubDirNo ;
int i ;
struct HtmlFormDir * Dir ;
char * Template ;
char * inptr ;
char FormDir [ MAX_PATH ] = " " ;
char FN [ MAX_PATH ] = " " ;
char * InputName = NULL ; // HTML to input message
char * ReplyName = NULL ;
char * To = NULL ;
char * CC = NULL ;
char * BID = NULL ;
char Type = 0 ;
char * Subject = NULL ;
char * MsgBody = NULL ;
char * varptr ;
char * endptr ;
size_t varlen , vallen = 0 ;
char val [ 256 ] = " " ; // replacement text
char var [ 100 ] = " \" " ;
char * MsgBytes ;
char Submit [ 64 ] ;
if ( NodeURL = = NULL )
{
//rentry after processing <select> or <ask>
goto reEnter ;
}
DirNo = atoi ( & NodeURL [ 17 ] ) ;
ptr = strchr ( & NodeURL [ 17 ] , ' , ' ) ;
Dir = HtmlFormDirs [ DirNo ] ;
SubDir = strlop ( & NodeURL [ 17 ] , ' : ' ) ;
if ( SubDir )
{
SubDirNo = atoi ( SubDir ) ;
Dir = Dir - > Dirs [ SubDirNo ] ;
}
sprintf ( Submit , " /Webmail/Submit?%s " , Session - > Key ) ;
if ( ptr )
FileNo = atoi ( ptr + 1 ) ;
// First we read the .txt. then get name of input .html from it
if ( WebMail - > txtFile )
free ( WebMail - > txtFile ) ;
WebMail - > txtFile = NULL ;
if ( WebMail - > txtFileName )
free ( WebMail - > txtFileName ) ;
WebMail - > txtFileName = _strdup ( Dir - > Forms [ FileNo ] - > FileName ) ;
// Read the file here to simplify reentry if we do <select> or <ask> substitutions
// if Dir not specified search all for Filename
if ( Dir = = NULL )
{
for ( i = 0 ; i < FormDirCount ; i + + )
{
int n ;
Dir = HtmlFormDirs [ i ] ;
MsgBytes = CheckFile ( Dir , WebMail - > txtFileName ) ;
if ( MsgBytes )
goto gotFile ;
// Recurse any Subdirs
n = 0 ;
while ( n < Dir - > DirCount )
{
MsgBytes = CheckFile ( Dir - > Dirs [ n ] , FN ) ;
if ( MsgBytes )
{
Dir = Dir - > Dirs [ n ] ;
goto gotFile ;
}
n + + ;
}
}
return ;
}
else
MsgBytes = CheckFile ( Dir , WebMail - > txtFileName ) ;
gotFile :
WebMail - > Dir = Dir ;
if ( WebMail - > txtFile )
free ( WebMail - > txtFile ) ;
WebMail - > txtFile = MsgBytes ;
reEnter :
if ( ParsetxtTemplate ( Session , Dir , WebMail - > txtFileName , FALSE ) = = FALSE )
{
// Template has <select> or <ask> tags and value has been requested
return ;
}
if ( WebMail - > InputHTMLName = = NULL )
{
// This is a plain text template without HTML
if ( To = = NULL & & WebMail - > To & & WebMail - > To [ 0 ] )
To = WebMail - > To ;
else
To = " " ;
if ( CC = = NULL & & WebMail - > CC & & WebMail - > CC [ 0 ] )
CC = WebMail - > CC ;
else
CC = " " ;
if ( Subject = = NULL & & WebMail - > Subject & & WebMail - > Subject [ 0 ] )
Subject = WebMail - > Subject ;
else
Subject = " " ;
if ( BID = = NULL & & WebMail - > BID & & WebMail - > BID [ 0 ] )
BID = WebMail - > BID ;
else
BID = " " ;
if ( Type = = 0 & & WebMail - > Type )
Type = WebMail - > Type ;
else
Type = ' P ' ;
if ( MsgBody = = NULL )
MsgBody = " " ;
if ( MsgBody [ 0 ] = = 0 & & WebMail - > Body & & WebMail - > Body [ 0 ] )
MsgBody = WebMail - > Body ;
* WebMail - > RLen = sprintf ( WebMail - > Reply , CheckFormMsgPage , Session - > Key , To , CC , Subject ,
( Type = = ' P ' ) ? " Selected " : " " , ( Type = = ' B ' ) ? " Selected " : " " , ( Type = = ' T ' ) ? " Selected " : " " , BID , MsgBody ) ;
return ;
}
Template = CheckFile ( Dir , WebMail - > InputHTMLName ) ;
if ( Template = = NULL )
{
* WebMail - > RLen = sprintf ( WebMail - > Reply , " %s " , " HTML Template not found " ) ;
return ;
}
// I've going to update the template in situ, as I can't see a better way
// of making sure all occurances of variables in any order are substituted.
// The space allocated to Template is twice the size of the file
// to allow for insertions
// First find the Form Action string and replace with our URL. It should have
// action="http://{FormServer}:{FormPort}" but some forms have localhost:8001 instead
// Also remove the OnSubmit if it contains the standard popup about having to close browser
UpdateFormAction ( Template , Session - > Key ) ;
// Search for "{var }" strings in form and replace with
// corresponding variable
// we run through the Template once for each variable
while ( txtKey - > Key )
{
char Key [ 256 ] = " { " ;
strcpy ( & Key [ 1 ] , & txtKey - > Key [ 1 ] ) ;
ptr = strchr ( Key , ' > ' ) ;
if ( ptr )
* ptr = ' } ' ;
inptr = Template ;
varptr = stristr ( inptr , Key ) ;
while ( varptr )
{
// Move the remaining message up/down the buffer to make space for substitution
varlen = strlen ( Key ) ;
if ( txtKey - > Value )
vallen = strlen ( txtKey - > Value ) ;
else vallen = 0 ;
endptr = varptr + varlen ;
memmove ( varptr + vallen , endptr , strlen ( endptr ) + 1 ) ; // copy null on end
memcpy ( varptr , txtKey - > Value , vallen ) ;
inptr = endptr + 1 ;
varptr = stristr ( inptr , Key ) ;
}
txtKey + + ;
}
// Remove </body></html> from end as we add it on later
ptr = stristr ( Template , " </body></html> " ) ;
if ( ptr )
* ptr = 0 ;
* WebMail - > RLen = sprintf ( WebMail - > Reply , " %s " , Template ) ;
free ( Template ) ;
return ;
}
char * xxReadTemplate ( char * FormSet , char * DirName , char * FileName )
{
int FileSize ;
char * MsgBytes ;
char MsgFile [ 265 ] ;
size_t ReadLen ;
struct stat STAT ;
FILE * hFile ;
# ifndef WIN32
// Need to do case insensitive file search
DIR * dir ;
struct dirent * entry ;
char name [ 256 ] ;
sprintf ( name , " %s/%s/%s " , BPQDirectory , FormSet , DirName ) ;
if ( ! ( dir = opendir ( name ) ) )
{
Debugprintf ( " cant open forms dir %s %d %d " , name , errno , dir ) ;
return 0 ;
}
while ( ( entry = readdir ( dir ) ) ! = NULL )
{
if ( entry - > d_type = = DT_DIR )
continue ;
if ( stristr ( entry - > d_name , FileName ) )
{
sprintf ( MsgFile , " %s/%s/%s/%s " , GetBPQDirectory ( ) , FormSet , DirName , entry - > d_name ) ;
closedir ( dir ) ;
break ;
}
}
closedir ( dir ) ;
# else
sprintf ( MsgFile , " %s/%s/%s/%s " , GetBPQDirectory ( ) , FormSet , DirName , FileName ) ;
# endif
if ( stat ( MsgFile , & STAT ) ! = - 1 )
{
hFile = fopen ( MsgFile , " rb " ) ;
if ( hFile = = 0 )
{
MsgBytes = _strdup ( " File is missing " ) ;
return MsgBytes ;
}
FileSize = STAT . st_size ;
MsgBytes = malloc ( FileSize * 2 ) ; // Allow plenty of room for template substitution
ReadLen = fread ( MsgBytes , 1 , FileSize , hFile ) ;
MsgBytes [ FileSize ] = 0 ;
fclose ( hFile ) ;
return MsgBytes ;
}
return NULL ;
}
int ReturnRawMessage ( struct UserInfo * User , struct MsgInfo * Msg , char * Key , char * Reply , char * RawMessage , int len , char * ErrorString )
{
char * ErrorMsg = malloc ( len + 100 ) ;
char * ptr ;
char DownLoad [ 256 ] ;
sprintf ( DownLoad , " <td><a href=/WebMail/DL?%s&%d>Save Attachments</a></td> " , Key , Msg - > number ) ;
RawMessage [ strlen ( RawMessage ) ] = ' . ' ; // We null terminated file name
RawMessage [ strlen ( RawMessage ) ] = ' ' ; // We null terminated file name Len = XML - RawMessage;
RawMessage [ len ] = 0 ;
// Body seems to have cr cr lf which causes double space
ptr = strstr ( RawMessage , " \r \r " ) ;
while ( ptr )
{
* ptr = ' ' ;
ptr = strstr ( ptr , " \r \r " ) ;
}
sprintf ( ErrorMsg , ErrorString , RawMessage ) ;
len = sprintf ( Reply , WebMailMsgTemplate , BBSName , User - > Call , Msg - > number , Msg - > number , Key , Msg - > number , Key , DownLoad , Key , Key , Key , " textarea " , ErrorMsg , " textarea " ) ;
free ( ErrorMsg ) ;
return len ;
}
char * FindXMLVariable ( WebMailInfo * WebMail , char * Var )
{
KeyValues * XMLKey = & WebMail - > XMLKeys [ 0 ] ;
while ( XMLKey - > Key )
{
if ( _stricmp ( Var , XMLKey - > Key ) = = 0 )
{
return XMLKey - > Value ;
}
XMLKey + + ;
}
return NULL ;
}
BOOL ParseXML ( WebMailInfo * WebMail , char * XMLOrig )
{
char * XML = _strdup ( XMLOrig ) ; // Get copy so we can mess about with it
char * ptr1 , * ptr2 , * ptr3 ;
KeyValues * XMLKeys = & WebMail - > XMLKeys [ 0 ] ;
// Extract Fields (stuff between < and >. Ignore Whitespace between fields
ptr1 = strstr ( XML , " <xml_file_version> " ) ;
while ( ptr1 )
{
ptr2 = strchr ( + + ptr1 , ' > ' ) ;
if ( ptr2 = = NULL )
goto quit ;
* ptr2 + + = 0 ;
2023-12-28 10:31:09 +00:00
ptr3 = strstr ( ptr2 , " </ " ) ; // end of value string
2022-08-28 09:35:46 +01:00
if ( ptr3 = = NULL )
goto quit ;
* ptr3 + + = 0 ;
XMLKeys - > Key = _strdup ( ptr1 ) ;
XMLKeys - > Value = _strdup ( ptr2 ) ;
XMLKeys + + ;
ptr1 = strchr ( ptr3 , ' < ' ) ;
2023-12-28 10:31:09 +00:00
if ( _memicmp ( ptr1 , " </ " , 2 ) = = 0 )
{
// end of a parameter block. Find start of next block
ptr1 = strchr ( + + ptr1 , ' < ' ) ;
ptr1 = strchr ( + + ptr1 , ' < ' ) ; // Skip start of next block
}
2022-08-28 09:35:46 +01:00
}
quit :
free ( XML ) ;
return TRUE ;
}
/*
? xml version = " 1.0 " ? >
< RMS_Express_Form >
< form_parameters >
< xml_file_version > 1 , 0 < / xml_file_version >
< rms_express_version > 6.0 .16 .38 Debug Build < / rms_express_version >
< submission_datetime > 20181022105202 < / submission_datetime >
< senders_callsign > G8BPQ < / senders_callsign >
< grid_square > < / grid_square >
< display_form > Alaska_ARES_ICS213_Initial_Viewer . html < / display_form >
< reply_template > Alaska_ARES_ICS213_SendReply . txt < / reply_template >
< / form_parameters >
< variables >
< msgto > g8bpq < / msgto >
< msgcc > < / msgcc >
< msgsender > G8BPQ < / msgsender >
< msgsubject > < / msgsubject >
< msgbody > < / msgbody >
< msgp2p > false < / msgp2p >
< msgisreply > false < / msgisreply >
< msgisforward > false < / msgisforward >
< msgisacknowledgement > false < / msgisacknowledgement >
< SeqNum > G8BPQ - 1 < / SeqNum >
< Priority > Routine < / Priority >
< HX > < / HX >
< OrgStation > < / OrgStation >
< Check > < / Check >
< OrgLocation > Here < / OrgLocation >
< Time > 11 : 51 < / Time >
< Date > 2018 - 10 - 22 < / Date >
< Incident_Name > Test < / Incident_Name >
< To_Name > John < / To_Name >
< From_Name > John < / From_Name >
< Subjectline > Test < / Subjectline >
< DateTime > 2018 - 10 - 22 11 : 51 < / DateTime >
< Message > < / Message >
< Approved_Name > Me < / Approved_Name >
< Approved_PosTitle > Me < / Approved_PosTitle >
< Submit > Submit < / Submit >
< / variables >
< / RMS_Express_Form >
*/
char HTMLNotFoundMsg [ ] = " *** HTML Template for message not found - displaying raw content *** \r \n \r \n %s " ;
char VarNotFoundMsg [ ] = " *** Variable {%s} not found in message - displaying raw content *** \r \n \r \n %s " ;
char BadXMLMsg [ ] = " *** XML for Variable {%s} invalid - displaying raw content *** \r \n \r \n %s " ;
char BadTemplateMsg [ ] = " *** Template near \" %s \" invalid - displaying raw content *** \r \n \r \n %s " ;
int DisplayWebForm ( struct HTTPConnectionInfo * Session , struct MsgInfo * Msg , char * FileName , char * XML , char * Reply , char * RawMessage , int RawLen )
{
WebMailInfo * WebMail = Session - > WebMail ;
struct UserInfo * User = Session - > User ;
char * Key = Session - > Key ;
int Len = 0 ;
char * Form ;
char * SaveReply = Reply ;
char FN [ MAX_PATH ] = " " ;
char * formptr , * varptr , * xmlptr ;
char * ptr = NULL , * endptr , * xmlend ;
size_t varlen , xmllen ;
char var [ 100 ] = " < " ;
KeyValues * KeyValue ;
if ( ParseXML ( WebMail , XML ) )
ptr = FindXMLVariable ( WebMail , " display_form " ) ;
if ( ptr = = NULL ) // ?? No Display Form Specified??
{
// Not found - just display as normal message
return ReturnRawMessage ( User , Msg , Key , Reply , RawMessage , ( int ) ( XML - RawMessage ) , HTMLNotFoundMsg ) ;
}
strcpy ( FN , ptr ) ;
Form = GetHTMLViewerTemplate ( FN ) ;
if ( Form = = NULL )
{
// Not found - just display as normal message
return ReturnRawMessage ( User , Msg , Key , Reply , RawMessage , ( int ) ( XML - RawMessage ) , HTMLNotFoundMsg ) ;
}
formptr = Form ;
// Search for {var xxx} strings in form and replace with
// corresponding variable in xml
// Don't know why, but {MsgOriginalBody} is sent instead of {var MsgOriginalBody}
varptr = stristr ( Form , " {MsgOriginalBody} " ) ;
{
char * temp , * tempsave ;
char * xvar , * varsave , * ptr ;
if ( varptr )
{
varptr + + ;
endptr = strchr ( varptr , ' } ' ) ;
varlen = endptr - varptr ;
if ( endptr = = NULL | | varlen > 99 )
{
// corrupt template - display raw message
char Err [ 256 ] ;
varptr [ 20 ] = 0 ;
sprintf ( Err , BadTemplateMsg , varptr - 5 , " %s " ) ;
return ReturnRawMessage ( User , Msg , Key , SaveReply , RawMessage , ( int ) ( XML - RawMessage ) , Err ) ;
}
memcpy ( var + 1 , varptr , varlen ) ;
var [ + + varlen ] = ' > ' ;
var [ + + varlen ] = 0 ;
xmlptr = stristr ( XML , var ) ;
if ( xmlptr )
{
xmlptr + = varlen ;
xmlend = strstr ( xmlptr , " </ " ) ;
if ( xmlend = = NULL )
{
// Bad XML - return error message
char Err [ 256 ] ;
// remove <> from var as it confuses html
var [ strlen ( var ) - 1 ] = 0 ;
sprintf ( Err , BadXMLMsg , var + 1 , " %s " ) ;
return ReturnRawMessage ( User , Msg , Key , SaveReply , RawMessage , ( int ) ( XML - RawMessage ) , Err ) ;
}
xmllen = xmlend - xmlptr ;
}
else
{
// Variable not found - return error message
char Err [ 256 ] ;
// remove <> from var as it confuses html
var [ strlen ( var ) - 1 ] = 0 ;
sprintf ( Err , VarNotFoundMsg , var + 1 , " %s " ) ;
return ReturnRawMessage ( User , Msg , Key , SaveReply , RawMessage , ( int ) ( XML - RawMessage ) , Err ) ;
}
// Ok, we have the position of the variable and the substitution text.
// Copy message up to variable to Result, then copy value
// We create a copy so we can rescan later.
// We also need to replace CR or CRLF with <br>
xvar = varsave = malloc ( xmllen * 2 ) ;
ptr = xmlptr ;
while ( ptr < xmlend )
{
while ( * ptr = = ' \n ' )
ptr + + ;
if ( * ptr = = ' \r ' )
{
* ptr + + ;
strcpy ( xvar , " <br> " ) ;
xvar + = 4 ;
}
else
* ( xvar + + ) = * ( ptr + + ) ;
}
* xvar = 0 ;
temp = tempsave = malloc ( strlen ( Form ) + strlen ( XML ) ) ;
memcpy ( temp , formptr , varptr - formptr - 1 ) ; // omit "{"
temp + = ( varptr - formptr - 1 ) ;
strcpy ( temp , varsave ) ;
temp + = strlen ( varsave ) ;
free ( varsave ) ;
formptr = endptr + 1 ;
strcpy ( temp , formptr ) ;
strcpy ( Form , tempsave ) ;
free ( tempsave ) ;
}
}
formptr = Form ;
varptr = stristr ( Form , " {var " ) ;
while ( varptr )
{
varptr + = 5 ;
endptr = strchr ( varptr , ' } ' ) ;
varlen = endptr - varptr ;
if ( endptr = = NULL | | varlen > 99 )
{
// corrupt template - display raw message
char Err [ 256 ] ;
varptr [ 20 ] = 0 ;
sprintf ( Err , BadTemplateMsg , varptr - 5 , " %s " ) ;
return ReturnRawMessage ( User , Msg , Key , SaveReply , RawMessage , ( int ) ( XML - RawMessage ) , Err ) ;
}
memcpy ( var , varptr , varlen ) ;
var [ varlen ] = 0 ;
KeyValue = & WebMail - > XMLKeys [ 0 ] ;
while ( KeyValue - > Key )
{
if ( _stricmp ( var , KeyValue - > Key ) = = 0 )
{
xmllen = strlen ( KeyValue - > Value ) ;
// Ok, we have the position of the variable and the substitution text.
// Copy message up to variable to Result, then copy value
memcpy ( Reply , formptr , varptr - formptr - 5 ) ; // omit "{var "
Reply + = ( varptr - formptr - 5 ) ;
strcpy ( Reply , KeyValue - > Value ) ;
Reply + = xmllen ;
break ;
}
if ( KeyValue - > Key = = NULL )
{
// Not found in XML
char Err [ 256 ] ;
sprintf ( Err , VarNotFoundMsg , var , " %s " ) ;
return ReturnRawMessage ( User , Msg , Key , SaveReply , RawMessage , ( int ) ( XML - RawMessage ) , Err ) ;
}
KeyValue + + ;
}
formptr = endptr + 1 ;
varptr = stristr ( endptr , " {var " ) ;
}
// copy remaining
// Remove </body></html> as we add it later
ptr = strstr ( formptr , " </body> " ) ;
if ( ptr )
* ptr = 0 ;
strcpy ( Reply , formptr ) ;
// Add Webmail header between <Body> and form data
ptr = stristr ( SaveReply , " <body " ) ;
if ( ptr )
{
ptr = strchr ( ptr , ' > ' ) ;
if ( ptr )
{
char * temp = malloc ( strlen ( SaveReply ) + 1000 ) ;
size_t len = + + ptr - SaveReply ;
memcpy ( temp , SaveReply , len ) ;
sprintf ( & temp [ len ] ,
" <script>function Reply(Num, Key) "
" { "
" var param = \" toolbar=yes,location=yes,directories=yes,status=yes,menubar=yes,scrollbars=yes,resizable=yes,titlebar=yes,toobar=yes \" ; "
" window.open( \" /WebMail/Reply/ \" + Num + \" ? \" + Key, \" _self \" ,param); "
" }</script> "
" <h3 align=center> %s Webmail Interface - User %s - Message %d</h3> "
" <table align=center border=1 cellpadding=2 bgcolor=white><tr> "
" <td><a href= \" # \" onclick= \" Reply('%d' ,'%s'); return false; \" >Reply</a></td> "
" <td><a href=/WebMail/WMDel/%d?%s>Kill Message</a></td> "
" <td><a href=/WebMail/DisplayText?%s&%d>Display as Text</a></td> "
" <td><a href=/WebMail/WMNext?%s>Next</a></td> "
" <td><a href=/WebMail/WMPrev?%s>Previous</a></td> "
" <td><a href=/WebMail/WMSame?%s>Back to List</a></td> "
" </tr></table> " , BBSName , User - > Call , Msg - > number , Msg - > number , Key , Msg - > number , Key , Key , Msg - > number , Key , Key , Key ) ;
strcat ( temp , ptr ) ;
strcpy ( SaveReply , temp ) ;
free ( temp ) ;
}
}
if ( Form )
free ( Form ) ;
return ( int ) strlen ( SaveReply ) ;
}
char * BuildB2Header ( WebMailInfo * WebMail , struct MsgInfo * Msg , char * * ToCalls , int Calls )
{
// Create B2 Header
char * NewMsg = malloc ( 100000 ) ;
char * SaveMsg = NewMsg ;
char DateString [ 80 ] ;
struct tm * tm ;
int n ;
char Type [ 16 ] = " Private " ;
// Get Type
if ( Msg - > type = = ' B ' )
strcpy ( Type , " Bulletin " ) ;
else if ( Msg - > type = = ' T ' )
strcpy ( Type , " Traffic " ) ;
tm = gmtime ( ( time_t * ) & Msg - > datecreated ) ;
sprintf ( DateString , " %04d/%02d/%02d %02d:%02d " ,
tm - > tm_year + 1900 , tm - > tm_mon + 1 , tm - > tm_mday , tm - > tm_hour , tm - > tm_min ) ;
NewMsg + = sprintf ( NewMsg ,
" MID: %s \r \n "
" Date: %s \r \n "
" Type: %s \r \n "
" From: %s \r \n " ,
Msg - > bid , DateString , Type , Msg - > from ) ;
if ( ToCalls )
{
int i ;
for ( i = 0 ; i < Calls ; i + + )
NewMsg + = sprintf ( NewMsg , " To: %s \r \n " , ToCalls [ i ] ) ;
}
else
{
NewMsg + = sprintf ( NewMsg , " To: %s \r \n " ,
WebMail - > To ) ;
}
if ( WebMail - > CC & & WebMail - > CC [ 0 ] )
NewMsg + = sprintf ( NewMsg , " CC: %s \r \n " , WebMail - > CC ) ;
NewMsg + = sprintf ( NewMsg ,
" Subject: %s \r \n "
" Mbo: %s \r \n " ,
Msg - > title , BBSName ) ;
2023-03-16 06:52:27 +00:00
NewMsg + = sprintf ( NewMsg , " Body: %d \r \n " , ( int ) strlen ( WebMail - > Body ) + WebMail - > HeaderLen + WebMail - > FooterLen ) ;
2022-08-28 09:35:46 +01:00
Msg - > B2Flags = B2Msg ;
if ( WebMail - > XML )
{
Msg - > B2Flags | = Attachments ;
NewMsg + = sprintf ( NewMsg , " File: %d %s \r \n " ,
WebMail - > XMLLen , WebMail - > XMLName ) ;
}
for ( n = 0 ; n < WebMail - > Files ; n + + )
{
Msg - > B2Flags | = Attachments ;
NewMsg + = sprintf ( NewMsg , " File: %d %s \r \n " ,
WebMail - > FileLen [ n ] , WebMail - > FileName [ n ] ) ;
}
NewMsg + = sprintf ( NewMsg , " \r \n " ) ; // Blank Line to end header
return SaveMsg ;
}
VOID WriteOneRecipient ( struct MsgInfo * Msg , WebMailInfo * WebMail , int MsgLen , char * * ToCalls , int Calls , char * BID )
{
FILE * hFile ;
char * via = NULL ;
BIDRec * BIDRec ;
char MsgFile [ MAX_PATH ] ;
size_t WriteLen = 0 ;
char * B2Header ;
if ( strlen ( WebMail - > Subject ) > 60 )
WebMail - > Subject [ 60 ] = 0 ;
strcpy ( Msg - > title , WebMail - > Subject ) ;
if ( strlen ( BID ) = = 0 )
sprintf_s ( BID , 32 , " %d_%s " , LatestMsg , BBSName ) ;
strcpy ( Msg - > bid , BID ) ;
Msg - > datereceived = Msg - > datechanged = Msg - > datecreated = time ( NULL ) ;
BIDRec = AllocateBIDRecord ( ) ;
strcpy ( BIDRec - > BID , Msg - > bid ) ;
BIDRec - > mode = Msg - > type ;
BIDRec - > u . msgno = LOWORD ( Msg - > number ) ;
BIDRec - > u . timestamp = LOWORD ( time ( NULL ) / 86400 ) ;
Msg - > length = MsgLen ;
sprintf_s ( MsgFile , sizeof ( MsgFile ) , " %s/m_%06d.mes " , MailDir , Msg - > number ) ;
// We write a B2 Header, Body and XML attachment if present
B2Header = BuildB2Header ( WebMail , Msg , ToCalls , Calls ) ;
hFile = fopen ( MsgFile , " wb " ) ;
if ( hFile )
{
int i ;
WriteLen = fwrite ( B2Header , 1 , strlen ( B2Header ) , hFile ) ;
WriteLen + = fwrite ( WebMail - > Body , 1 , Msg - > length , hFile ) ;
WriteLen + = fwrite ( " \r \n " , 1 , 2 , hFile ) ;
if ( WebMail - > XML )
{
WriteLen + = fwrite ( WebMail - > XML , 1 , WebMail - > XMLLen , hFile ) ;
WriteLen + = fwrite ( " \r \n " , 1 , 2 , hFile ) ;
}
// Do any attachments
for ( i = 0 ; i < WebMail - > Files ; i + + )
{
WriteLen + = fwrite ( WebMail - > FileBody [ i ] , 1 , WebMail - > FileLen [ i ] , hFile ) ;
WriteLen + = fwrite ( " \r \n " , 1 , 2 , hFile ) ;
}
fclose ( hFile ) ;
}
free ( B2Header ) ;
Msg - > length = ( int ) WriteLen ;
MatchMessagetoBBSList ( Msg , 0 ) ;
2023-12-08 12:26:52 +00:00
if ( Msg - > status ! = ' H ' & & Msg - > type = = ' B ' & & memcmp ( Msg - > fbbs , zeros , NBMASK ) ! = 0 )
Msg - > status = ' $ ' ; // Has forwarding
2022-08-28 09:35:46 +01:00
BuildNNTPList ( Msg ) ; // Build NNTP Groups list
2024-12-16 17:54:16 +00:00
# ifndef NOMQTT
if ( MQTT )
MQTTMessageEvent ( Msg ) ;
# endif
2022-08-28 09:35:46 +01:00
}
VOID SaveTemplateMessage ( struct HTTPConnectionInfo * Session , char * MsgPtr , char * Reply , int * RLen , char * Rest )
{
int ReplyLen = 0 ;
struct MsgInfo * Msg ;
char * ptr , * input , * context ;
size_t MsgLen ;
char Type ;
char * via = NULL ;
char BID [ 32 ] ;
size_t WriteLen = 0 ;
char * Body = NULL ;
char * To = NULL ;
char * CC = NULL ;
char * HDest = NULL ;
char * Title = NULL ;
char * Vptr = NULL ;
char * Context ;
char Prompt [ 256 ] = " Message Saved " ;
char OrigTo [ 256 ] ;
WebMailInfo * WebMail = Session - > WebMail ;
BOOL SendMsg = FALSE ;
BOOL SendReply = FALSE ;
char * RMSTo [ 1000 ] = { NULL } ; // Winlink addressees
char * PKTT0 [ 1000 ] = { NULL } ; // Packet addressees
__int32 Recipients = 0 ;
__int32 RMSMsgs = 0 , BBSMsgs = 0 ;
input = strstr ( MsgPtr , " \r \n \r \n " ) ; // End of headers
if ( input = = NULL )
return ;
if ( strstr ( input , " Cancel=Cancel " ) )
{
* RLen = sprintf ( Reply , " <html><script>window.location.href = '/Webmail/WebMail?%s';</script> " , Session - > Key ) ;
return ;
}
if ( WebMail - > txtFileName = = NULL )
{
// No template, so user must have used back button
* RLen = sprintf ( Reply , " <html><script>alert( \" Template missing. Was back Button used? \" );window.location.href = '/Webmail/WebMail?%s';</script></html> " , Session - > Key ) ;
return ;
}
ptr = strtok_s ( input + 4 , " & " , & Context ) ;
while ( ptr )
{
char * val = strlop ( ptr , ' = ' ) ;
if ( strcmp ( ptr , " To " ) = = 0 )
HDest = To = val ;
else if ( strcmp ( ptr , " CC " ) = = 0 )
CC = val ;
else if ( strcmp ( ptr , " Subj " ) = = 0 )
Title = val ;
else if ( strcmp ( ptr , " Type " ) = = 0 )
Type = val [ 0 ] ;
else if ( strcmp ( ptr , " BID " ) = = 0 )
strcpy ( BID , val ) ;
else if ( strcmp ( ptr , " Msg " ) = = 0 )
Body = _strdup ( val ) ;
ptr = strtok_s ( NULL , " & " , & Context ) ;
}
strlop ( BID , ' ' ) ;
if ( strlen ( BID ) > 12 )
BID [ 12 ] = 0 ;
UndoTransparency ( To ) ;
UndoTransparency ( CC ) ;
UndoTransparency ( BID ) ;
UndoTransparency ( HDest ) ;
UndoTransparency ( Title ) ;
UndoTransparency ( Body ) ;
MsgLen = strlen ( Body ) ;
// The user could have changed any of the input fields.
if ( To & & To [ 0 ] )
{
free ( WebMail - > To ) ;
WebMail - > To = _strdup ( To ) ;
}
if ( CC & & CC [ 0 ] )
{
free ( WebMail - > CC ) ;
WebMail - > CC = _strdup ( CC ) ;
}
if ( Title & & Title [ 0 ] )
{
free ( WebMail - > Subject ) ;
WebMail - > Subject = _strdup ( Title ) ;
}
if ( Body & & Body [ 0 ] )
{
free ( WebMail - > Body ) ;
WebMail - > Body = _strdup ( Body ) ;
}
// We will put the supplied address in the B2 header
// We may need to change the HDest to make sure message
// is delivered to Internet or Packet as requested
if ( HDest = = NULL | | HDest [ 0 ] = = 0 )
{
* RLen = sprintf ( Reply , " %s " , " <html><script>alert( \" To: Call Missing \" );window.history.back();</script></html> " ) ;
return ;
}
// Multiple TO fields could be more than 255 bytes long
// if (strlen(HDest) > 255)
// {
// *RLen = sprintf(Reply, "%s", "<html><script>alert(\"To: Call too long!\");window.history.back();</script></html>");
// return;
// }
if ( strlen ( BID ) )
{
if ( LookupBID ( BID ) )
{
// Duplicate bid
* RLen = sprintf ( Reply , " %s " , " <html><script>alert( \" Duplicate BID \" );window.history.back();</script></html> " ) ;
return ;
}
}
if ( Type = = ' B ' )
{
if ( RefuseBulls )
{
* RLen = sprintf ( Reply , " %s " , " <html><script>alert( \" This system doesn't allow sending Bulls \" );window.history.back();script></html> " ) ;
return ;
}
if ( Session - > User - > flags & F_NOBULLS )
{
* RLen = sprintf ( Reply , " %s " , " <html><script>alert( \" You are not allowed to send Bulls \" );window.history.back();</script></html> " ) ;
return ;
}
}
// We should be able to handle multiple recipients, with all Winlink addresses sent in one message and
// multiple copies for packet addressess. For Winlink we should use multiple To@ lines in B2 Header
ptr = strtok_s ( HDest , " ; " , & context ) ;
while ( ptr & & ptr [ 0 ] )
{
int Winlink = 0 ;
int AMPR = 0 ;
char * dest = zalloc ( 256 ) ;
char * via = NULL ;
strcpy ( dest , ptr ) ;
// See if packet or Winlink
// If Type=Winlink specified send plain call as @winlink.org
if ( strchr ( dest , ' @ ' ) = = 0 & & WebMail - > Winlink )
strcat ( dest , " @winlink.org " ) ;
if ( _memicmp ( dest , " rms: " , 4 ) = = 0 | | _memicmp ( dest , " rms/ " , 4 ) = = 0 )
{
memcpy ( dest , & dest [ 4 ] , strlen ( dest ) ) ;
Winlink = 1 ;
RMSTo [ RMSMsgs + + ] = dest ;
ptr = strtok_s ( NULL , " ; " , & context ) ;
continue ;
}
else if ( _memicmp ( dest , " smtp: " , 5 ) = = 0 )
{
if ( ISP_Gateway_Enabled )
{
via = & dest [ 5 ] ;
dest [ 0 ] = 0 ;
}
}
else if ( strchr ( dest , ' @ ' ) )
{
strcpy ( OrigTo , dest ) ;
via = strlop ( dest , ' @ ' ) ;
if ( via )
{
// If looks like a valid email address, treat as such
if ( strlen ( via ) > 6 | | ! CheckifPacket ( via ) )
{
// Assume Email address. See if to send via RMS or SMTP
if ( isAMPRMsg ( OrigTo ) )
{
dest [ strlen ( dest ) ] = ' @ ' ; // Put back together
memmove ( & dest [ 1 ] , dest , strlen ( dest ) ) ;
dest [ 0 ] = 0 ;
via = & dest [ 1 ] ;
AMPR = 1 ;
}
else if ( FindRMS ( ) | | strchr ( via , ' ! ' ) ) // have RMS or source route
{
dest [ strlen ( dest ) ] = ' @ ' ; // Put back together
Winlink = 1 ;
RMSTo [ RMSMsgs + + ] = dest ;
ptr = strtok_s ( NULL , " ; " , & context ) ;
continue ;
}
else if ( ISP_Gateway_Enabled )
{
dest [ strlen ( dest ) ] = ' @ ' ; // Put back together
memmove ( dest , & dest [ 1 ] , strlen ( dest ) ) ;
dest [ 0 ] = 0 ;
}
else
{
* RLen = sprintf ( Reply , " %s " , " <html><script>alert( \" This system doesn't allow Sending to Internet Email \" );window.close();</script></html> " ) ;
return ;
}
}
}
}
else
{
// No @
if ( strlen ( dest ) > 6 )
dest [ 6 ] = 0 ;
}
// This isn't an RMS Message, so can queue now
Msg = AllocateMsgRecord ( ) ;
// Set number here so they remain in sequence
Msg - > number = + + LatestMsg ;
MsgnotoMsg [ Msg - > number ] = Msg ;
strcpy ( Msg - > title , WebMail - > Subject ) ;
Msg - > type = Type ;
Msg - > status = ' N ' ;
strcpy ( Msg - > from , Session - > User - > Call ) ;
strcpy ( Msg - > to , _strupr ( dest ) ) ;
if ( SendBBStoSYSOPCall )
if ( _stricmp ( dest , BBSName ) = = 0 )
strcpy ( Msg - > to , SYSOPCall ) ;
if ( via )
{
if ( strlen ( via ) > 40 )
via [ 40 ] = 0 ;
strcpy ( Msg - > via , _strupr ( via ) ) ;
}
else
{
// No via. If not local user try to add BBS
struct UserInfo * ToUser = LookupCall ( Msg - > to ) ;
if ( ToUser )
{
// Local User. If Home BBS is specified, use it
if ( ToUser - > flags & F_RMSREDIRECT )
{
// sent to Winlink
strcpy ( Msg - > via , WinlinkAddr ) ;
sprintf ( Prompt , " Redirecting to winlink.org \r " ) ;
}
else if ( ToUser - > HomeBBS [ 0 ] )
{
strcpy ( Msg - > via , ToUser - > HomeBBS ) ;
sprintf ( Prompt , " %s added from HomeBBS. Message Saved " , Msg - > via ) ;
}
}
else
{
// Not local user - Check WP
WPRecP WP = LookupWP ( Msg - > to ) ;
if ( WP )
{
strcpy ( Msg - > via , WP - > first_homebbs ) ;
sprintf ( Prompt , " %s added from WP " , Msg - > via ) ;
}
}
}
WriteOneRecipient ( Msg , WebMail , MsgLen , NULL , 0 , BID ) ;
ptr = strtok_s ( NULL , " ; " , & context ) ;
free ( dest ) ;
BID [ 0 ] = 0 ; // Can't use more than once
}
if ( RMSMsgs )
{
// Write one message to all Winlink addresses
int i ;
Msg = AllocateMsgRecord ( ) ;
// Set number here so they remain in sequence
Msg - > number = + + LatestMsg ;
MsgnotoMsg [ Msg - > number ] = Msg ;
strcpy ( Msg - > title , WebMail - > Subject ) ;
Msg - > type = Type ;
Msg - > status = ' N ' ;
strcpy ( Msg - > from , Session - > User - > Call ) ;
strcpy ( Msg - > to , " RMS " ) ;
WriteOneRecipient ( Msg , WebMail , MsgLen , RMSTo , RMSMsgs , BID ) ;
for ( i = 0 ; i < RMSMsgs ; i + + )
free ( RMSTo [ i ] ) ;
}
SaveMessageDatabase ( ) ;
SaveBIDDatabase ( ) ;
* RLen = SendWebMailHeaderEx ( Reply , Session - > Key , Session , Prompt ) ;
FreeWebMailFields ( WebMail ) ;
return ;
}
VOID DoStandardTemplateSubsitutions ( struct HTTPConnectionInfo * Session , char * txtFile )
{
WebMailInfo * WebMail = Session - > WebMail ;
struct UserInfo * User = Session - > User ;
KeyValues * txtKey = WebMail - > txtKeys ;
char * inptr , * varptr , * endptr ;
int varlen , vallen ;
while ( txtKey - > Key ! = NULL )
{
inptr = WebMail - > txtFile ;
varptr = stristr ( inptr , txtKey - > Key ) ;
while ( varptr )
{
// Move the remaining message up/down the buffer to make space for substitution
varlen = ( int ) strlen ( txtKey - > Key ) ;
if ( txtKey - > Value )
vallen = ( int ) strlen ( txtKey - > Value ) ;
else
vallen = 0 ;
endptr = varptr + varlen ;
memmove ( varptr + vallen , endptr , strlen ( endptr ) + 1 ) ; // copy null on end
memcpy ( varptr , txtKey - > Value , vallen ) ;
inptr = endptr + 1 ;
varptr = stristr ( inptr , txtKey - > Key ) ;
}
txtKey + + ;
}
}
VOID BuildMessageFromHTMLInput ( struct HTTPConnectionInfo * Session , char * Reply , int * RLen , char * Keys [ 1000 ] , char * Values [ 1000 ] , int NumKeys )
{
int ReplyLen = 0 ;
struct MsgInfo * Msg ;
int MsgLen ;
FILE * hFile ;
char Type = ' P ' ;
BIDRec * BIDRec ;
char * MailBuffer ;
char MsgFile [ MAX_PATH ] ;
int WriteLen = 0 ;
char Prompt [ 256 ] = " Message Saved " ;
char OrigTo [ 256 ] ;
WebMailInfo * WebMail = Session - > WebMail ;
char * HDest = _strdup ( WebMail - > To ) ;
char * Vptr = NULL ;
char BID [ 16 ] = " " ;
/// if (strlen(HDest) > 255)
/// {
// *RLen = sprintf(Reply, "%s", "<html><script>alert(\"To: Call too long!\");</script></html>");
// return;
// }
MsgLen = ( int ) strlen ( WebMail - > Body ) ;
Msg = AllocateMsgRecord ( ) ;
// Set number here so they remain in sequence
Msg - > number = + + LatestMsg ;
MsgnotoMsg [ Msg - > number ] = Msg ;
strcpy ( Msg - > from , Session - > User - > Call ) ;
if ( _memicmp ( HDest , " rms: " , 4 ) = = 0 | | _memicmp ( HDest , " rms/ " , 4 ) = = 0 )
{
Vptr = & HDest [ 4 ] ;
strcpy ( Msg - > to , " RMS " ) ;
}
else if ( _memicmp ( HDest , " smtp: " , 5 ) = = 0 )
{
if ( ISP_Gateway_Enabled )
{
Vptr = & HDest [ 5 ] ;
Msg - > to [ 0 ] = 0 ;
}
}
else if ( strchr ( HDest , ' @ ' ) )
{
strcpy ( OrigTo , HDest ) ;
Vptr = strlop ( HDest , ' @ ' ) ;
if ( Vptr )
{
// If looks like a valid email address, treat as such
if ( strlen ( HDest ) > 6 | | ! CheckifPacket ( Vptr ) )
{
// Assume Email address
Vptr = OrigTo ;
if ( FindRMS ( ) | | strchr ( Vptr , ' ! ' ) ) // have RMS or source route
strcpy ( Msg - > to , " RMS " ) ;
else if ( ISP_Gateway_Enabled )
Msg - > to [ 0 ] = 0 ;
else if ( isAMPRMsg ( OrigTo ) )
strcpy ( Msg - > to , " RMS " ) ; // Routing will redirect it
else
{
* RLen = sprintf ( Reply , " %s " , " <html><script>alert( \" This system doesn't allow Sending to Internet Email \" );window.close();</script></html> " ) ;
return ;
}
}
}
}
else
{
if ( strlen ( HDest ) > 6 )
HDest [ 6 ] = 0 ;
strcpy ( Msg - > to , _strupr ( HDest ) ) ;
}
if ( SendBBStoSYSOPCall )
if ( _stricmp ( HDest , BBSName ) = = 0 )
strcpy ( Msg - > to , SYSOPCall ) ;
if ( Vptr )
{
if ( strlen ( Vptr ) > 40 )
Vptr [ 40 ] = 0 ;
strcpy ( Msg - > via , _strupr ( Vptr ) ) ;
}
else
{
// No via. If not local user try to add BBS
struct UserInfo * ToUser = LookupCall ( Msg - > to ) ;
if ( ToUser )
{
// Local User. If Home BBS is specified, use it
if ( ToUser - > flags & F_RMSREDIRECT )
{
// sent to Winlink
strcpy ( Msg - > via , WinlinkAddr ) ;
sprintf ( Prompt , " Redirecting to winlink.org \r " ) ;
}
else if ( ToUser - > HomeBBS [ 0 ] )
{
strcpy ( Msg - > via , ToUser - > HomeBBS ) ;
sprintf ( Prompt , " %s added from HomeBBS " , Msg - > via ) ;
}
}
else
{
// Not local user - Check WP
WPRecP WP = LookupWP ( Msg - > to ) ;
if ( WP )
{
strcpy ( Msg - > via , WP - > first_homebbs ) ;
sprintf ( Prompt , " %s added from WP " , Msg - > via ) ;
}
}
}
if ( strlen ( WebMail - > Subject ) > 60 )
WebMail - > Subject [ 60 ] = 0 ;
strcpy ( Msg - > title , WebMail - > Subject ) ;
Msg - > type = Type ;
Msg - > status = ' N ' ;
if ( strlen ( BID ) = = 0 )
sprintf_s ( BID , sizeof ( BID ) , " %d_%s " , LatestMsg , BBSName ) ;
strcpy ( Msg - > bid , BID ) ;
Msg - > datereceived = Msg - > datechanged = Msg - > datecreated = time ( NULL ) ;
BIDRec = AllocateBIDRecord ( ) ;
strcpy ( BIDRec - > BID , Msg - > bid ) ;
BIDRec - > mode = Msg - > type ;
BIDRec - > u . msgno = LOWORD ( Msg - > number ) ;
BIDRec - > u . timestamp = LOWORD ( time ( NULL ) / 86400 ) ;
MailBuffer = malloc ( MsgLen + 2000 ) ; // Allow for a B2 Header if attachments
Msg - > length = MsgLen ;
BuildFormMessage ( Session , Msg , Keys , Values , NumKeys ) ;
sprintf_s ( MsgFile , sizeof ( MsgFile ) , " %s/m_%06d.mes " , MailDir , Msg - > number ) ;
hFile = fopen ( MsgFile , " wb " ) ;
if ( hFile )
{
WriteLen = ( int ) fwrite ( WebMail - > Body , 1 , Msg - > length , hFile ) ;
fclose ( hFile ) ;
}
free ( WebMail - > Body ) ;
free ( HDest ) ;
WebMail - > Body = NULL ;
MatchMessagetoBBSList ( Msg , 0 ) ;
2023-12-08 12:26:52 +00:00
if ( Msg - > status ! = ' H ' & & Msg - > type = = ' B ' & & memcmp ( Msg - > fbbs , zeros , NBMASK ) ! = 0 )
Msg - > status = ' $ ' ; // Has forwarding
2022-08-28 09:35:46 +01:00
BuildNNTPList ( Msg ) ; // Build NNTP Groups list
2024-12-16 17:54:16 +00:00
# ifndef NOMQTT
if ( MQTT )
MQTTMessageEvent ( Msg ) ;
# endif
2022-08-28 09:35:46 +01:00
SaveMessageDatabase ( ) ;
SaveBIDDatabase ( ) ;
* RLen = sprintf ( Reply , " <html><script>alert( \" %s \" );window.close();</script></html> " , Prompt ) ;
return ;
}
void ProcessFormInput ( struct HTTPConnectionInfo * Session , char * input , char * Reply , int * RLen , int InputLen )
{
// If there is no display html defined place data in a normal
// input window, else build the Message body and XML attachment and send
// I now think it is better to put data in a normal input window
// even if there is a display form so user can view it before submission
WebMailInfo * WebMail = Session - > WebMail ;
char * info = strstr ( input , " \r \n \r \n " ) ; // To end of HTML header
// look through header for Content-Type line, and if multipart
// find boundary string.
char * ptr , * saveptr , * ptr1 , * ptr2 , * inptr ;
char Boundary [ 1000 ] ;
BOOL Multipart = FALSE ;
int Partlen ;
char * * Body = & info ;
int i ;
char * Keys [ 1000 ] ;
char * Values [ 1000 ] ;
char * saveForfree [ 1000 ] ;
int NumKeys = 0 ;
char * varptr ;
char * endptr ;
int varlen , vallen = 0 ;
char * crcrptr ;
if ( WebMail - > txtFile = = NULL )
{
// No template, so user must have used back button
* RLen = sprintf ( Reply , " <html><script>alert( \" Template missing. Was back Button used? \" );window.location.href = '/Webmail/WebMail?%s';</script></html> " , Session - > Key ) ;
return ;
}
ptr = input ;
while ( * ptr ! = 13 )
{
ptr2 = strchr ( ptr , 10 ) ; // Find CR
while ( ptr2 [ 1 ] = = ' ' | | ptr2 [ 1 ] = = 9 ) // Whitespace - continuation line
{
ptr2 = strchr ( & ptr2 [ 1 ] , 10 ) ; // Find CR
}
// Content-Type: multipart/mixed;
// boundary="----=_NextPart_000_025B_01CAA004.84449180"
// 7.2.2 The Multipart/mixed (primary) subtype
// 7.2.3 The Multipart/alternative subtype
if ( _memicmp ( ptr , " Content-Type: " , 14 ) = = 0 )
{
char Line [ 1000 ] = " " ;
char lcLine [ 1000 ] = " " ;
char * ptr3 ;
memcpy ( Line , & ptr [ 14 ] , ptr2 - ptr - 14 ) ;
memcpy ( lcLine , & ptr [ 14 ] , ptr2 - ptr - 14 ) ;
_strlwr ( lcLine ) ;
if ( _memicmp ( Line , " Multipart/ " , 10 ) = = 0 )
{
Multipart = TRUE ;
ptr3 = strstr ( Line , " boundary " ) ;
if ( ptr3 )
{
ptr3 + = 9 ;
if ( ( * ptr3 ) = = ' " ' )
ptr3 + + ;
strcpy ( Boundary , ptr3 ) ;
ptr3 = strchr ( Boundary , ' " ' ) ;
if ( ptr3 ) * ptr3 = 0 ;
ptr3 = strchr ( Boundary , 13 ) ; // CR
if ( ptr3 ) * ptr3 = 0 ;
}
else
return ; // Can't do anything without a boundary ??
}
}
ptr = ptr2 ;
ptr + + ;
}
if ( info = = NULL )
return ; // Wot!
// Extract the Key/Value pairs from input data
saveptr = ptr = WebFindPart ( Body , Boundary , & Partlen , input + InputLen ) ;
if ( ptr = = NULL )
return ; // Couldn't find separator
// Now extract fields
while ( ptr )
{
char * endptr ;
char * val ;
// Debugprintf(ptr);
// Format seems to be
//Content-Disposition: form-data; name="FieldName"
// crlf crlf
// field value
// crlf crlf
// No, is actually
// ------WebKitFormBoundary7XHZ1i7Jc8tOZJbw
// Content-Disposition: form-data; name="State"
//
// UK
// ------WebKitFormBoundary7XHZ1i7Jc8tOZJbw
// ie Value is terminated by ------WebKitFormBoundary7XHZ1i7Jc8tOZJbw
// But FindPart has returned length, so can use that
// Be aware that Part and PartLen include the CRLF which is actually part of the Boundary string so should be removed.
ptr = strstr ( ptr , " name= " ) ;
if ( ptr )
{
endptr = strstr ( ptr , " \" \r \n \r \n " ) ; // "/r/n/r/n
if ( endptr )
{
* endptr = 0 ;
ptr + = 6 ; // to start of name string
val = endptr + 5 ;
// val was Null Terminated by FindPart so can just use it. This assumes all fields are text,
// which I think is safe enough here.
saveptr [ Partlen - 2 ] = 0 ;
// Now have key value pair
Keys [ NumKeys ] = ptr ;
Values [ NumKeys ] = val ;
saveForfree [ NumKeys + + ] = saveptr ; // so we can free() when finished with it
}
else
free ( saveptr ) ;
}
else
free ( saveptr ) ;
saveptr = ptr = WebFindPart ( Body , Boundary , & Partlen , input + InputLen ) ;
}
if ( info = = NULL )
return ; // Wot!
info + = 4 ;
// It looks like some standard variables can be used in <var subsitutions as well as fields from form. Put on end,
// so fields from form have priority
saveForfree [ NumKeys ] = 0 ; // flag end of malloced items
Keys [ NumKeys ] = " MsgTo " ;
Values [ NumKeys + + ] = " " ;
Keys [ NumKeys ] = " MsgCc " ;
Values [ NumKeys + + ] = " " ;
Keys [ NumKeys ] = " MsgSender " ;
Values [ NumKeys + + ] = Session - > User - > Call ;
Keys [ NumKeys ] = " MsgSubject " ;
Values [ NumKeys + + ] = " " ;
Keys [ NumKeys ] = " MsgBody " ;
// if (WebMail->OrigBody)
// txtKey++->Value = _strdup(WebMail->OrigBody);
// else
Values [ NumKeys + + ] = " " ;
Keys [ NumKeys ] = _strdup ( " MsgP2P " ) ;
Values [ NumKeys + + ] = _strdup ( " " ) ;
Keys [ NumKeys ] = _strdup ( " MsgIsReply " ) ;
if ( WebMail - > isReply )
Values [ NumKeys + + ] = " True " ;
else
Values [ NumKeys + + ] = " True " ;
Keys [ NumKeys ] = " MsgIsForward " ;
Values [ NumKeys + + ] = " False " ;
Keys [ NumKeys ] = " MsgIsAcknowledgement " ;
Values [ NumKeys + + ] = " False " ;
// Update Template with variables from the form
// I've going to update the template in situ, as I can't see a better way
// of making sure all occurances of variables in any order are substituted.
// The space allocated to Template is twice the size of the file
// to allow for insertions
inptr = WebMail - > txtFile ;
// Search for "<var>" strings in form and replace with
// corresponding variable
// we run through the Template once for each variable
i = 0 ;
while ( i < NumKeys )
{
char Key [ 256 ] ;
sprintf ( Key , " <var %s> " , Keys [ i ] ) ;
inptr = WebMail - > txtFile ;
varptr = stristr ( inptr , Key ) ;
while ( varptr )
{
// Move the remaining message up/down the buffer to make space for substitution
varlen = ( int ) strlen ( Key ) ;
vallen = ( int ) strlen ( Values [ i ] ) ;
endptr = varptr + varlen ;
memmove ( varptr + vallen , endptr , strlen ( endptr ) + 1 ) ; // copy null on end
memcpy ( varptr , Values [ i ] , vallen ) ;
inptr = endptr + 1 ;
varptr = stristr ( inptr , Key ) ;
}
i + + ;
}
// We need to look for To:, CC: and Subject lines, and remove any other
// Var: lines. Use everything following Msg: as the plain text body
// Find start of Message body
ptr = WebMail - > txtFile ;
ptr1 = strchr ( ptr , ' \r ' ) ;
while ( ptr1 )
{
if ( _memicmp ( ptr , " Msg: " , 4 ) = = 0 )
{
// Rest is message body. <var> substitutions have been done
if ( WebMail - > Body )
free ( WebMail - > Body ) ;
WebMail - > Body = _strdup ( ptr + 4 ) ; // Remove Msg:
break ;
}
// Can now terminate lines
* ptr1 + + = 0 ;
while ( * ptr1 = = ' \r ' | | * ptr1 = = ' \n ' )
* ptr1 + + = 0 ;
if ( _memicmp ( ptr , " To: " , 3 ) = = 0 )
{
if ( strlen ( ptr ) > 5 )
WebMail - > To = _strdup ( & ptr [ 3 ] ) ;
}
else if ( _memicmp ( ptr , " CC: " , 3 ) = = 0 )
{
if ( strlen ( ptr ) > 5 )
WebMail - > CC = _strdup ( & ptr [ 3 ] ) ;
}
else if ( _memicmp ( ptr , " Subj: " , 5 ) = = 0 )
{
if ( ptr [ 5 ] = = ' ' ) // May have space after :
ptr + + ;
if ( strlen ( ptr ) > 6 )
WebMail - > Subject = _strdup ( & ptr [ 5 ] ) ;
}
else if ( _memicmp ( ptr , " Subject: " , 8 ) = = 0 )
{
if ( ptr [ 8 ] = = ' ' )
ptr + + ;
if ( strlen ( ptr ) > 9 )
WebMail - > Subject = _strdup ( & ptr [ 8 ] ) ;
}
ptr = ptr1 ;
ptr1 = strchr ( ptr , ' \r ' ) ;
}
if ( WebMail - > Subject = = NULL )
WebMail - > Subject = _strdup ( " " ) ;
if ( WebMail - > To = = NULL )
WebMail - > To = _strdup ( " " ) ;
if ( WebMail - > CC = = NULL )
WebMail - > CC = _strdup ( " " ) ;
// Replace var in Subject
if ( _memicmp ( WebMail - > Subject , " <var " , 5 ) = = 0 )
{
WebMail - > Subject = realloc ( WebMail - > Subject , 512 ) ; // Plenty of space
i = 0 ;
while ( i < NumKeys )
{
char Key [ 256 ] ;
sprintf ( Key , " <var %s> " , Keys [ i ] ) ;
inptr = WebMail - > Subject ;
varptr = stristr ( inptr , Key ) ;
while ( varptr )
{
// Move the remaining message up/down the buffer to make space for substitution
varlen = ( int ) strlen ( Key ) ;
vallen = ( int ) strlen ( Values [ i ] ) ;
endptr = varptr + varlen ;
memmove ( varptr + vallen , endptr , strlen ( endptr ) + 1 ) ; // copy null on end
memcpy ( varptr , Values [ i ] , vallen ) ;
inptr = endptr + 1 ;
varptr = stristr ( inptr , Key ) ;
}
i + + ;
}
}
// Build XML Attachment if Display Form is defined
if ( WebMail - > DisplayHTMLName )
BuildXMLAttachment ( Session , Keys , Values , NumKeys ) ;
// if Reply, attach original message to Body;
if ( WebMail - > isReply & & WebMail - > OrigBody )
{
char * NewBody = malloc ( strlen ( WebMail - > Body ) + strlen ( WebMail - > OrigBody ) + 100 ) ;
sprintf ( NewBody , " %s \r \n %s " , WebMail - > Body , WebMail - > OrigBody ) ;
free ( WebMail - > Body ) ;
WebMail - > Body = NewBody ;
}
// Display Message for user to check and send
// fix any cr cr lf sequence
crcrptr = strstr ( WebMail - > Body , " \r \r " ) ;
while ( crcrptr )
{
* crcrptr = ' ' ;
crcrptr = strstr ( crcrptr , " \r \r " ) ;
}
if ( WebMail - > BID = = NULL )
WebMail - > BID = _strdup ( " " ) ;
* RLen = sprintf ( Reply , CheckFormMsgPage , Session - > Key , WebMail - > To , WebMail - > CC , WebMail - > Subject , " Selected " , " " , " " , WebMail - > BID , WebMail - > Body ) ;
// Free the part strings
i = 0 ;
while ( saveForfree [ i ] )
free ( saveForfree [ i + + ] ) ;
}
// XML Template Stuff
char XMLHeader [ ] =
" <?xml version= \" 1.0 \" ?> \r \n "
" <RMS_Express_Form> \r \n "
" <form_parameters> \r \n "
" <xml_file_version>%s</xml_file_version> \r \n "
" <rms_express_version>%s</rms_express_version> \r \n "
" <submission_datetime>%s</submission_datetime> \r \n "
" <senders_callsign>%s</senders_callsign> \r \n "
" <grid_square>%s</grid_square> \r \n "
" <display_form>%s</display_form> \r \n "
" <reply_template>%s</reply_template> \r \n "
" </form_parameters> \r \n "
" <variables> \r \n "
" <msgto>%s</msgto> \r \n "
" <msgcc>%s</msgcc> \r \n "
" <msgsender>%s</msgsender> \r \n "
" <msgsubject>%s</msgsubject> \r \n "
" <msgbody>%s</msgbody> \r \n "
" <msgp2p>%s</msgp2p> \r \n "
" <msgisreply>%s</msgisreply> \r \n "
" <msgisforward>%s</msgisforward> \r \n "
" <msgisacknowledgement>%s</msgisacknowledgement> \r \n " ;
char XMLLine [ ] = " <%s>%s</%s> \r \n " ;
char XMLTrailer [ ] = " </variables> \r \n </RMS_Express_Form> \r \n " ;
char * doXMLTransparency ( char * string )
{
// Make sure string doesn't contain forbidden XML chars (<>"'&)
char * newstring = malloc ( 5 * strlen ( string ) + 1 ) ; // If len is zero still need null terminator
char * in = string ;
char * out = newstring ;
char c ;
c = * ( in + + ) ;
while ( c )
{
switch ( c )
{
case ' < ' :
strcpy ( out , " < " ) ;
out + = 4 ;
break ;
case ' > ' :
strcpy ( out , " > " ) ;
out + = 4 ;
break ;
case ' " ' :
strcpy ( out , " " " ) ;
out + = 6 ;
break ;
case ' \' ' :
strcpy ( out , " ' " ) ;
out + = 6 ;
break ;
case ' & ' :
strcpy ( out , " & " ) ;
out + = 5 ;
break ;
default :
* ( out + + ) = c ;
}
c = * ( in + + ) ;
}
* ( out + + ) = 0 ;
return newstring ;
}
VOID BuildXMLAttachment ( struct HTTPConnectionInfo * Session , char * Keys [ 1000 ] , char * Values [ 1000 ] , int NumKeys )
{
// Create XML Attachment for form
WebMailInfo * WebMail = Session - > WebMail ;
char XMLName [ MAX_PATH ] ;
char * XMLPtr ;
char DateString [ 80 ] ;
struct tm * tm ;
time_t NOW = time ( NULL ) ;
int n ;
int TotalFileSize = 0 ;
tm = gmtime ( & NOW ) ;
sprintf ( DateString , " %04d%02d%02d%02d%02d%02d " ,
tm - > tm_year + 1900 , tm - > tm_mon + 1 , tm - > tm_mday , tm - > tm_hour , tm - > tm_min , tm - > tm_sec ) ;
strcpy ( XMLName , WebMail - > DisplayHTMLName ) ;
XMLName [ strlen ( XMLName ) - 5 ] = 0 ; // remove .html
WebMail - > XMLName = malloc ( MAX_PATH ) ;
WebMail - > XML = XMLPtr = malloc ( 100000 ) ;
WebMail - > XMLLen = 0 ;
sprintf ( WebMail - > XMLName , " RMS_Express_Form_%s.xml " , XMLName ) ;
XMLPtr + = sprintf ( XMLPtr , XMLHeader ,
" 1,0 " , VersionString ,
DateString ,
Session - > User - > Call ,
" " , //Grid
WebMail - > DisplayHTMLName ,
WebMail - > ReplyHTMLName ,
WebMail - > To ,
WebMail - > CC ,
Session - > User - > Call ,
WebMail - > OrigSubject ,
" " , // WebMail->OrigBody,
" False " , // P2P
WebMail - > isReply ? " True " : " False " ,
" False " , // Forward,
" False " ) ; // Ack
// create XML lines for Key/Value Pairs
for ( n = 0 ; n < NumKeys ; n + + )
{
if ( Values [ n ] = = NULL )
Values [ n ] = _strdup ( " " ) ;
XMLPtr + = sprintf ( XMLPtr , XMLLine , Keys [ n ] , Values [ n ] , Keys [ n ] ) ;
}
if ( WebMail - > isReply )
{
if ( WebMail - > OrigBody )
{
char * goodXML = doXMLTransparency ( WebMail - > OrigBody ) ;
XMLPtr + = sprintf ( XMLPtr , XMLLine , " MsgOriginalBody " , goodXML , " MsgOriginalBody " ) ;
}
else
XMLPtr + = sprintf ( XMLPtr , XMLLine , " MsgOriginalBody " , " " , " MsgOriginalBody " ) ;
}
XMLPtr + = sprintf ( XMLPtr , " %s " , XMLTrailer ) ;
WebMail - > XMLLen = ( int ) ( XMLPtr - WebMail - > XML ) ;
}
char * BuildFormMessage ( struct HTTPConnectionInfo * Session , struct MsgInfo * Msg , char * Keys [ 1000 ] , char * Values [ 1000 ] , int NumKeys )
{
// Create B2 message with template body and xml attachment
char * NewMsg = malloc ( 100000 ) ;
char * SaveMsg = NewMsg ;
char * XMLPtr ;
char DateString [ 80 ] ;
struct tm * tm ;
char * FileName [ 100 ] ;
int FileLen [ 100 ] ;
char * FileBody [ 100 ] ;
int n , Files = 0 ;
int TotalFileSize = 0 ;
char Type [ 16 ] = " Private " ;
WebMailInfo * WebMail = Session - > WebMail ;
// Create a B2 Message
tm = gmtime ( ( time_t * ) & Msg - > datecreated ) ;
sprintf ( DateString , " %04d%02d%02d%02d%02d%02d " ,
tm - > tm_year + 1900 , tm - > tm_mon + 1 , tm - > tm_mday , tm - > tm_hour , tm - > tm_min , tm - > tm_sec ) ;
if ( WebMail - > DisplayHTMLName )
{
char XMLName [ MAX_PATH ] ;
strcpy ( XMLName , WebMail - > DisplayHTMLName ) ;
XMLName [ strlen ( XMLName ) - 5 ] = 0 ; // remove .html
FileName [ 0 ] = malloc ( MAX_PATH ) ;
FileBody [ 0 ] = malloc ( 100000 ) ;
Files = 1 ;
FileLen [ 0 ] = 0 ;
sprintf ( FileName [ 0 ] , " RMS_Express_Form_%s.xml " , XMLName ) ;
XMLPtr = FileBody [ 0 ] ;
XMLPtr + = sprintf ( XMLPtr , XMLHeader ,
" 1,0 " , VersionString ,
DateString ,
Session - > User - > Call ,
" " , //Grid
WebMail - > DisplayHTMLName ,
WebMail - > ReplyHTMLName ,
WebMail - > OrigTo ,
" " , // CC
Session - > User - > Call ,
WebMail - > OrigSubject ,
WebMail - > OrigBody ,
" false " , // P2P,
" false " , //Reply
" false " , //Forward,
" false " ) ; // Ack
// create XML lines for Key/Value Pairs
for ( n = 0 ; n < NumKeys ; n + + )
{
if ( Values [ n ] = = NULL )
Values [ n ] = _strdup ( " " ) ;
XMLPtr + = sprintf ( XMLPtr , XMLLine , Keys [ n ] , Values [ n ] , Keys [ n ] ) ;
}
XMLPtr + = sprintf ( XMLPtr , " %s " , XMLTrailer ) ;
FileLen [ 0 ] = ( int ) ( XMLPtr - FileBody [ 0 ] ) ;
}
sprintf ( DateString , " %04d/%02d/%02d %02d:%02d " ,
tm - > tm_year + 1900 , tm - > tm_mon + 1 , tm - > tm_mday , tm - > tm_hour , tm - > tm_min ) ;
// Get Type
if ( Msg - > type = = ' B ' )
strcpy ( Type , " Bulletin " ) ;
else if ( Msg - > type = = ' T ' )
strcpy ( Type , " NTS " ) ;
// We put original To call in B2 Header
NewMsg + = sprintf ( NewMsg ,
" MID: %s \r \n Date: %s \r \n Type: %s \r \n From: %s \r \n To: %s \r \n Subject: %s \r \n Mbo: %s \r \n " ,
Msg - > bid , DateString , Type , Msg - > from , WebMail - > To , Msg - > title , BBSName ) ;
NewMsg + = sprintf ( NewMsg , " Body: %d \r \n " , ( int ) strlen ( WebMail - > Body ) ) ;
for ( n = 0 ; n < Files ; n + + )
{
char * p = FileName [ n ] , * q ;
// Remove any path
q = strchr ( p , ' \\ ' ) ;
while ( q )
{
if ( q )
* q + + = 0 ;
p = q ;
q = strchr ( p , ' \\ ' ) ;
}
NewMsg + = sprintf ( NewMsg , " File: %d %s \r \n " , FileLen [ n ] , p ) ;
}
NewMsg + = sprintf ( NewMsg , " \r \n " ) ;
strcpy ( NewMsg , WebMail - > Body ) ;
NewMsg + = strlen ( WebMail - > Body ) ;
NewMsg + = sprintf ( NewMsg , " \r \n " ) ;
for ( n = 0 ; n < Files ; n + + )
{
memcpy ( NewMsg , FileBody [ n ] , FileLen [ n ] ) ;
NewMsg + = FileLen [ n ] ;
free ( FileName [ n ] ) ;
free ( FileBody [ n ] ) ;
NewMsg + = sprintf ( NewMsg , " \r \n " ) ;
}
Msg - > length = ( int ) strlen ( SaveMsg ) ;
Msg - > B2Flags = B2Msg ;
if ( Files )
Msg - > B2Flags | = Attachments ;
if ( WebMail - > Body )
free ( WebMail - > Body ) ;
WebMail - > Body = SaveMsg ;
return NULL ;
}
VOID UpdateFormAction ( char * Template , char * Key )
{
char * inptr , * saveptr ;
char * varptr , * endptr ;
size_t varlen , vallen ;
char Submit [ 64 ] ;
sprintf ( Submit , " /Webmail/Submit?%s " , Key ) ;
// First find the Form Action string and replace with our URL. It should have
// action="http://{FormServer}:{FormPort}" but some forms have localhost:8001 instead
// Also remove the OnSubmit if it contains the standard popup about having to close browser
inptr = Template ;
saveptr = varptr = stristr ( inptr , " <Form " ) ;
if ( varptr = = NULL )
return ;
varptr = stristr ( inptr , " Action= " ) ;
if ( varptr )
{
char delim = ' ' ;
varptr + = 8 ; // to first char.
if ( * varptr = = ' \" ' | | * varptr = = ' \' ' )
delim = * varptr + + ;
endptr = strchr ( varptr , delim ) ;
// Move the remaining message up/down the buffer to make space for substitution
varlen = endptr - varptr ;
vallen = strlen ( Submit ) ;
endptr = varptr + varlen ;
memmove ( varptr + vallen , endptr , strlen ( endptr ) + 1 ) ; // copy null on end
memcpy ( varptr , Submit , vallen ) ;
}
varptr = saveptr ;
saveptr = varptr = stristr ( inptr , " onsubmit= " ) ;
if ( varptr )
{
char delim = ' ' ;
varptr + = 10 ; // to first char.
if ( * varptr = = ' \" ' | | * varptr = = ' \' ' )
delim = * varptr + + ;
endptr = strchr ( varptr , delim ) ;
// We want to remove onsubmit and delimiter
varptr = saveptr ;
endptr + + ;
// Move the remaining message up/down the buffer to make space for substitution
varlen = endptr - varptr ;
vallen = 0 ;
endptr = varptr + varlen ;
memmove ( varptr + vallen , endptr , strlen ( endptr ) + 1 ) ; // copy null on end
memcpy ( varptr , Submit , vallen ) ;
}
// Some forms seem to have file://C:/RMS%20Express/Standard%20Templates/ instead of {FormFolder}
varptr = saveptr ;
saveptr = varptr = stristr ( inptr , " file://C:/RMS " ) ;
if ( varptr )
{
// We need the last part of the name
char * start = varptr ;
char * endptr = strchr ( varptr , ' " ' ) ;
if ( endptr )
* ( endptr ) = 0 ; // Null terminate for strlop
while ( strchr ( varptr , ' / ' ) )
varptr = strlop ( varptr , ' / ' ) ;
* ( endptr ) = ' " ' ; // Put Back
// We want to remove onsubmit and delimiter
varlen = varptr - saveptr ;
endptr + + ;
// Move the remaining message up/down the buffer to make space for substitution
endptr = varptr + varlen ;
memmove ( saveptr + 12 , varptr , strlen ( varptr ) + varlen ) ; // copy null on end
memcpy ( saveptr , " {FormFolder} " , 12 ) ;
}
}
int ReplyToFormsMessage ( struct HTTPConnectionInfo * Session , struct MsgInfo * Msg , char * Reply , BOOL Reenter )
{
WebMailInfo * WebMail = Session - > WebMail ;
KeyValues * txtKey = WebMail - > XMLKeys ;
int Len , i ;
char * inptr , * ptr ;
char * varptr , * endptr ;
int varlen , vallen ;
struct HtmlFormDir * Dir ;
char * Template = FindXMLVariable ( WebMail , " reply_template " ) ;
if ( Template = = NULL | | Template [ 0 ] = = 0 )
return 0 ; // No Template
if ( Reenter )
goto reEnter ;
WebMail - > isReply = TRUE ;
if ( WebMail - > OrigBody )
free ( WebMail - > OrigBody ) ;
WebMail - > OrigBody = _strdup ( WebMail - > Body ) ;
// Add "Re: " to Subject
ptr = WebMail - > Subject ;
WebMail - > Subject = malloc ( strlen ( Msg - > title ) + 10 ) ;
sprintf ( WebMail - > Subject , " Re: %s " , Msg - > title ) ;
// Set To: from From:
WebMail - > To = malloc ( 80 ) ;
if ( Msg - > emailfrom [ 0 ] )
sprintf ( WebMail - > To , " %s%s " , Msg - > from , Msg - > emailfrom ) ;
else
sprintf ( WebMail - > To , " %s " , Msg - > from ) ;
if ( ptr )
free ( ptr ) ;
WebMail - > txtFileName = _strdup ( Template ) ;
// Read the .txt file
if ( WebMail - > txtFile )
free ( WebMail - > txtFile ) ;
for ( i = 0 ; i < FormDirCount ; i + + )
{
int n ;
Dir = HtmlFormDirs [ i ] ;
WebMail - > txtFile = CheckFile ( Dir , WebMail - > txtFileName ) ;
if ( WebMail - > txtFile )
goto gotFile ;
// Recurse any Subdirs
n = 0 ;
while ( n < Dir - > DirCount )
{
WebMail - > txtFile = CheckFile ( Dir - > Dirs [ n ] , WebMail - > txtFileName ) ;
if ( WebMail - > txtFile )
{
Dir = Dir - > Dirs [ n ] ;
goto gotFile ;
}
n + + ;
}
}
// Template Not Found
// Missing template
* WebMail - > RLen = sprintf ( WebMail - > Reply , " <html><script>alert( \" Reply Template %s missing. Display as Text then Reply \" );;window.history.back();</script></html> " , WebMail - > txtFileName ) ;
return * WebMail - > RLen ;
gotFile :
WebMail - > Dir = Dir ;
reEnter :
if ( ParsetxtTemplate ( Session , WebMail - > Dir , WebMail - > txtFileName , TRUE ) = = FALSE )
return * WebMail - > RLen ; // processing <select> or <ask>
if ( WebMail - > InputHTMLName = = NULL )
{
// This is a plain text template without HTML
/*
if ( To = = NULL )
To = " " ;
if ( To [ 0 ] = = 0 & & WebMail - > To & & WebMail - > To [ 0 ] )
To = WebMail - > To ;
if ( CC = = NULL )
CC = " " ;
if ( CC [ 0 ] = = 0 & & WebMail - > CC & & WebMail - > CC [ 0 ] )
CC = WebMail - > CC ;
if ( Subject = = NULL )
Subject = " " ;
if ( Subject [ 0 ] = = 0 & & WebMail - > Subject & & WebMail - > Subject [ 0 ] )
Subject = WebMail - > Subject ;
if ( MsgBody = = NULL )
MsgBody = " " ;
if ( MsgBody [ 0 ] = = 0 & & WebMail - > Body & & WebMail - > Body [ 0 ] )
MsgBody = WebMail - > Body ;
* WebMail - > RLen = sprintf ( WebMail - > Reply , CheckFormMsgPage , Session - > Key , To , CC , Subject , MsgBody ) ;
*/
return * WebMail - > RLen ;
}
Template = CheckFile ( WebMail - > Dir , WebMail - > InputHTMLName ) ;
if ( Template = = NULL )
{
// Missing HTML
* WebMail - > RLen = sprintf ( WebMail - > Reply , " <html><script>alert( \" Reply HTML %s missing. Display as Text then Reply \" );;window.history.back();</script></html> " , WebMail - > InputHTMLName ) ;
return * WebMail - > RLen ;
}
// I've going to update the template in situ, as I can't see a better way
// of making sure all occurances of variables in any order are substituted.
// The space allocated to Template is twice the size of the file
// to allow for insertions
UpdateFormAction ( Template , Session - > Key ) ; // Update "Submit" Action
// Search for "{var }" strings in form and replace with
// corresponding variable from XML
while ( txtKey - > Key )
{
char Key [ 256 ] = " {var " ;
strcpy ( & Key [ 5 ] , txtKey - > Key ) ;
strcat ( Key , " } " ) ;
inptr = Template ;
varptr = stristr ( inptr , Key ) ;
while ( varptr )
{
// Move the remaining message up/down the buffer to make space for substitution
varlen = ( int ) strlen ( Key ) ;
if ( txtKey - > Value )
vallen = ( int ) strlen ( txtKey - > Value ) ;
else vallen = 0 ;
endptr = varptr + varlen ;
memmove ( varptr + vallen , endptr , strlen ( endptr ) + 1 ) ; // copy null on end
memcpy ( varptr , txtKey - > Value , vallen ) ;
inptr = endptr + 1 ;
varptr = stristr ( inptr , Key ) ;
}
txtKey + + ;
}
// Remove </body></html> from end as we add it on later
ptr = stristr ( Template , " </body></html> " ) ;
if ( ptr )
* ptr = 0 ;
Len = sprintf ( Reply , " %s " , Template ) ;
free ( Template ) ;
return Len ;
}
char * CheckFile ( struct HtmlFormDir * Dir , char * FN )
{
struct stat STAT ;
FILE * hFile ;
char MsgFile [ MAX_PATH ] ;
char * MsgBytes ;
int ReadLen ;
int FileSize ;
# ifndef WIN32
// Need to do case insensitive file search
DIR * dir ;
struct dirent * entry ;
char name [ 256 ] ;
sprintf ( name , " %s/%s/%s " , BPQDirectory , Dir - > FormSet , Dir - > DirName ) ;
if ( ! ( dir = opendir ( name ) ) )
{
Debugprintf ( " cant open forms dir %s %s %d " , Dir - > DirName , name , errno ) ;
return 0 ;
}
while ( ( entry = readdir ( dir ) ) ! = NULL )
{
if ( entry - > d_type = = DT_DIR )
continue ;
if ( stricmp ( entry - > d_name , FN ) = = 0 )
{
sprintf ( MsgFile , " %s/%s/%s/%s " , GetBPQDirectory ( ) , Dir - > FormSet , Dir - > DirName , entry - > d_name ) ;
break ;
}
}
closedir ( dir ) ;
# else
sprintf ( MsgFile , " %s/%s/%s/%s " , GetBPQDirectory ( ) , Dir - > FormSet , Dir - > DirName , FN ) ;
# endif
2023-12-28 10:31:09 +00:00
printf ( " %s \n " , MsgFile ) ;
2022-08-28 09:35:46 +01:00
if ( stat ( MsgFile , & STAT ) ! = - 1 )
{
hFile = fopen ( MsgFile , " rb " ) ;
if ( hFile = = 0 )
{
MsgBytes = _strdup ( " File is missing " ) ;
return MsgBytes ;
}
FileSize = STAT . st_size ;
MsgBytes = malloc ( FileSize * 10 ) ; // Allow plenty of room for template substitution
ReadLen = ( int ) fread ( MsgBytes , 1 , FileSize , hFile ) ;
MsgBytes [ FileSize ] = 0 ;
fclose ( hFile ) ;
2023-12-28 10:31:09 +00:00
printf ( " %d %s \n " , strlen ( MsgBytes ) , MsgBytes ) ;
2022-08-28 09:35:46 +01:00
return MsgBytes ;
}
return NULL ;
}
BOOL DoSelectPrompt ( struct HTTPConnectionInfo * Session , char * Select )
{
// Send a Popup window to select value. Reply handling code will update template then reenter ParsetxtTemplate
char popuphddr [ ] =
" <html><body align=center background='/background.jpg'> "
" <script> "
" function myFunction() {var x = document.getElementById('Sel').value; "
" var Key = \" %s \" ; "
" var param = \" toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=no,titlebar=no,toobar=no \" ; "
" window.open( \" /WebMail/DoSelect \" + '?' + Key + '&' + x,'_self'); "
" } "
" </script> "
" <div align=center>%s<br><br> "
" <table border=1 cellpadding=2 bgcolor=white> "
" <tr><td><select size=%d id='Sel' size=10 onclick=myFunction()> " ;
char popup [ 10000 ] ;
int i , vars = 0 ;
char * ptr , * ptr1 ;
char * prompt ;
char * var [ 100 ] ;
WebMailInfo * WebMail = Session - > WebMail ;
char * SelCopy = _strdup ( Select + 8 ) ; // Skip "<select "
ptr = strchr ( SelCopy , ' > ' ) ;
if ( ptr )
* ptr = 0 ;
ptr = SelCopy ;
if ( * ptr = = ' " ' )
{
// String has " " round it
ptr + + ;
ptr1 = strchr ( ptr , ' " ' ) ;
if ( ptr1 = = NULL )
goto returnDuff ;
* ( ptr1 + + ) = 0 ;
prompt = ptr ;
}
else
{
// Normal comma terminated
ptr1 = strchr ( ptr , ' , ' ) ;
if ( ptr1 = = NULL )
goto returnDuff ;
* ( ptr1 + + ) = 0 ;
prompt = ptr ;
}
ptr = ptr1 ;
while ( ptr & & ptr [ 0 ] )
{
if ( * ptr = = ' " ' )
{
// String has " " round it
ptr + + ;
ptr1 = strchr ( ptr , ' " ' ) ;
if ( ptr1 = = NULL )
goto returnDuff ;
* ( ptr1 + + ) = 0 ;
while ( ptr1 & & * ptr1 = = ' , ' )
ptr1 + + ;
}
else
{
// Normal comma terminated
ptr1 = strchr ( ptr , ' , ' ) ;
if ( ptr1 )
* ( ptr1 + + ) = 0 ;
}
var [ vars + + ] = ptr ;
ptr = ptr1 ;
}
sprintf ( popup , popuphddr , Session - > Key , prompt , vars + 1 ) ;
for ( i = 0 ; i < vars ; i + + )
{
char * key = strlop ( var [ i ] , ' = ' ) ;
if ( key = = NULL )
key = var [ i ] ;
sprintf ( popup , " %s <option value='%s'>%s " , popup , key , var [ i ] ) ;
}
sprintf ( popup , " %s</select></td></tr></table><br><input onclick=window.history.back() value=Back type=button class='btn'></div> " , popup ) ;
* WebMail - > RLen = sprintf ( WebMail - > Reply , " %s " , popup ) ;
free ( SelCopy ) ;
return TRUE ;
returnDuff :
* WebMail - > RLen = sprintf ( WebMail - > Reply , " <html><script>alert( \" Template <select> Corrupt. \" );window.location.href = '/Webmail/WebMail?%s';</script></html> " , Session - > Key ) ;
free ( SelCopy ) ;
return TRUE ;
}
BOOL DoAskPrompt ( struct HTTPConnectionInfo * Session , char * Select )
{
return TRUE ;
}
VOID ProcessSelectResponse ( struct HTTPConnectionInfo * Session , char * URLParams )
{
// User has entered a response for a Template <Select>. Update Template and re-renter ParsetxtTemplate
WebMailInfo * WebMail = Session - > WebMail ;
char * valptr , * varptr , * endptr ;
size_t varlen , vallen ;
char * Select = WebMail - > txtFile ;
if ( Select = = 0 )
{
// Missing template
* WebMail - > RLen = sprintf ( WebMail - > Reply , " <html><script>alert( \" Template missing. Was back Button used? \" );window.location.href = '/Webmail/WebMail?%s';</script></html> " , Session - > Key ) ;
return ;
}
Select = stristr ( Select , " <Select " ) ;
if ( Select = = 0 )
{
* WebMail - > RLen = sprintf ( WebMail - > Reply , " <html><script>alert( \" Template Corrupt. \" );window.location.href = '/Webmail/WebMail?%s';</script></html> " , Session - > Key ) ;
return ;
}
varptr = Select ;
endptr = strchr ( Select , ' > ' ) ;
if ( endptr = = NULL )
{
* WebMail - > RLen = sprintf ( WebMail - > Reply , " <html><script>alert( \" Template Corrupt. \" );window.location.href = '/Webmail/WebMail?%s';</script></html> " , Session - > Key ) ;
return ;
}
* endptr = 0 ;
varlen = endptr - varptr ;
valptr = URLParams ;
// Move the remaining message up/down the buffer to make space for substitution
vallen = strlen ( valptr ) ;
endptr = varptr + varlen ;
memcpy ( varptr , valptr , vallen ) ;
memmove ( varptr + vallen , endptr + 1 , strlen ( endptr + 1 ) + 1 ) ; // copy null on end
if ( WebMail - > isReply )
* WebMail - > RLen = ReplyToFormsMessage ( Session , Session - > Msg , WebMail - > Reply , TRUE ) ;
else
GetPage ( Session , NULL ) ;
return ;
}
BOOL ParsetxtTemplate ( struct HTTPConnectionInfo * Session , struct HtmlFormDir * Dir , char * FN , BOOL isReply )
{
WebMailInfo * WebMail = Session - > WebMail ;
KeyValues * txtKey = WebMail - > txtKeys ;
char * MsgBytes ;
char * txtFile ;
char * ptr , * ptr1 ;
char * InputName = NULL ; // HTML to input message
char * ReplyName = NULL ;
char * To = NULL ;
char * Subject = NULL ;
char * MsgBody = NULL ;
char * Select = NULL ;
char * Ask = NULL ;
char Date [ 16 ] ;
char UDate [ 16 ] ;
char DateTime [ 32 ] ;
char UDateTime [ 32 ] ;
char Day [ 16 ] ;
char UDay [ 16 ] ;
char UDTG [ 32 ] ;
char Seq [ 16 ] ;
char FormDir [ MAX_PATH ] ;
double Lat ;
double Lon ;
char LatString [ 32 ] , LonString [ 32 ] , GPSString [ 32 ] ;
BOOL GPSOK ;
struct tm * tm ;
time_t NOW ;
// Template is now read before entering here
MsgBytes = WebMail - > txtFile ;
// if Template uses <Select> or <Ask> get the values
Select = stristr ( MsgBytes , " <Select " ) ;
Ask = stristr ( MsgBytes , " <Ask " ) ;
if ( Select & & Ask )
{
// use whichever came first
if ( Select < Ask )
{
DoSelectPrompt ( Session , Select ) ;
return FALSE ;
}
else
{
DoAskPrompt ( Session , Ask ) ;
return FALSE ;
}
}
if ( Select )
{
DoSelectPrompt ( Session , Select ) ;
return FALSE ;
}
if ( Ask )
{
DoAskPrompt ( Session , Ask ) ;
return FALSE ;
}
NOW = time ( NULL ) ;
tm = localtime ( & NOW ) ;
sprintf ( Date , " %04d-%02d-%02d " ,
tm - > tm_year + 1900 , tm - > tm_mon + 1 , tm - > tm_mday ) ;
sprintf ( DateTime , " %04d-%02d-%02d %02d:%02d:%02d " ,
tm - > tm_year + 1900 , tm - > tm_mon + 1 , tm - > tm_mday , tm - > tm_hour , tm - > tm_min , tm - > tm_sec ) ;
strcpy ( Day , longday [ tm - > tm_wday ] ) ;
tm = gmtime ( & NOW ) ;
sprintf ( UDate , " %04d-%02d-%02dZ " ,
tm - > tm_year + 1900 , tm - > tm_mon + 1 , tm - > tm_mday ) ;
sprintf ( UDateTime , " %04d-%02d-%02d %02d:%02d:%02dZ " ,
tm - > tm_year + 100 , tm - > tm_mon + 1 , tm - > tm_mday , tm - > tm_hour , tm - > tm_min , tm - > tm_sec ) ;
sprintf ( UDTG , " %02d%02d%02dZ %s %04d " ,
tm - > tm_mday , tm - > tm_hour , tm - > tm_min , month [ tm - > tm_mon ] , tm - > tm_year + 1900 ) ;
strcpy ( UDay , longday [ tm - > tm_wday ] ) ;
sprintf ( Seq , " %d " , Session - > User - > WebSeqNo ) ;
sprintf ( FormDir , " /WebMail/WMFile/%s/%s/ " , WebMail - > Dir - > FormSet , WebMail - > Dir - > DirName ) ;
// Keep SeqNo at front
txtKey - > Key = _strdup ( " <SeqNum> " ) ;
txtKey + + - > Value = _strdup ( Seq ) ;
txtKey - > Key = _strdup ( " <DateTime> " ) ;
txtKey + + - > Value = _strdup ( DateTime ) ;
txtKey - > Key = _strdup ( " <UDateTime> " ) ;
txtKey + + - > Value = _strdup ( UDateTime ) ;
txtKey - > Key = _strdup ( " <Date> " ) ;
txtKey + + - > Value = _strdup ( Date ) ;
txtKey - > Key = _strdup ( " <UDate> " ) ;
txtKey + + - > Value = _strdup ( UDate ) ;
txtKey - > Key = _strdup ( " <Time> " ) ;
txtKey + + - > Value = _strdup ( & DateTime [ 11 ] ) ;
txtKey - > Key = _strdup ( " <UTime> " ) ;
txtKey + + - > Value = _strdup ( & UDateTime [ 11 ] ) ;
txtKey - > Key = _strdup ( " <Day> " ) ;
txtKey + + - > Value = _strdup ( Day ) ;
txtKey - > Key = _strdup ( " <UDay> " ) ;
txtKey + + - > Value = _strdup ( UDay ) ;
txtKey - > Key = _strdup ( " <UDTG> " ) ;
txtKey + + - > Value = _strdup ( UDTG ) ;
// Try to get position from APRS
GPSOK = GetAPRSLatLon ( & Lat , & Lon ) ;
GPSOK = GetAPRSLatLonString ( & LatString [ 1 ] , & LonString [ 1 ] ) ;
memmove ( LatString , & LatString [ 1 ] , 2 ) ;
memmove ( LonString , & LonString [ 1 ] , 3 ) ;
LatString [ 2 ] = ' - ' ;
LonString [ 3 ] = ' - ' ;
sprintf ( GPSString , " %s %s " , LatString , LonString ) ;
txtKey - > Key = _strdup ( " <GPS> " ) ;
if ( GPSOK )
txtKey + + - > Value = _strdup ( GPSString ) ;
else
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <Position> " ) ;
txtKey + + - > Value = _strdup ( GPSString ) ;
txtKey - > Key = _strdup ( " <ProgramVersion> " ) ;
txtKey + + - > Value = _strdup ( VersionString ) ;
txtKey - > Key = _strdup ( " <Callsign> " ) ;
txtKey + + - > Value = _strdup ( Session - > User - > Call ) ;
txtKey - > Key = _strdup ( " <MsgTo> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgCc> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgSender> " ) ;
txtKey + + - > Value = _strdup ( Session - > User - > Call ) ;
txtKey - > Key = _strdup ( " <MsgSubject> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgBody> " ) ;
// if (WebMail->OrigBody)
// txtKey++->Value = _strdup(WebMail->OrigBody);
// else
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgP2P> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
if ( isReply )
{
txtKey - > Key = _strdup ( " <MsgIsReply> " ) ;
txtKey + + - > Value = _strdup ( " True " ) ;
txtKey - > Key = _strdup ( " <MsgIsForward> " ) ;
txtKey + + - > Value = _strdup ( " False " ) ;
txtKey - > Key = _strdup ( " <MsgIsAcknowledgement> " ) ;
txtKey + + - > Value = _strdup ( " False " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalSubject> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalSender> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalBody> " ) ;
txtKey + + - > Value = _strdup ( WebMail - > Body ) ;
txtKey - > Key = _strdup ( " <MsgOriginalID> " ) ;
txtKey + + - > Value = _strdup ( WebMail - > Msg - > bid ) ;
// Get Timestamp from Message
tm = gmtime ( ( time_t * ) & WebMail - > Msg - > datecreated ) ;
sprintf ( Date , " %02d-%02d-%02d " ,
tm - > tm_year - 100 , tm - > tm_mon + 1 , tm - > tm_mday ) ;
sprintf ( DateTime , " %02d-%02d-%02d %02d:%02d " ,
tm - > tm_year - 100 , tm - > tm_mon + 1 , tm - > tm_mday , tm - > tm_hour , tm - > tm_min ) ;
strcpy ( Day , longday [ tm - > tm_wday ] ) ;
tm = gmtime ( ( time_t * ) & WebMail - > Msg - > datecreated ) ;
sprintf ( UDate , " %02d-%02d-%02dZ " ,
tm - > tm_year - 100 , tm - > tm_mon + 1 , tm - > tm_mday ) ;
sprintf ( UDateTime , " %02d-%02d-%02d %02d:%02dZ " ,
tm - > tm_year - 100 , tm - > tm_mon + 1 , tm - > tm_mday , tm - > tm_hour , tm - > tm_min ) ;
sprintf ( UDTG , " %02d%02d%02dZ %s %04d " ,
tm - > tm_mday , tm - > tm_hour , tm - > tm_min , month [ tm - > tm_mon ] , tm - > tm_year + 1900 ) ;
txtKey - > Key = _strdup ( " <MsgOriginalDate> " ) ;
txtKey + + - > Value = _strdup ( UDate ) ;
txtKey - > Key = _strdup ( " <MsgOriginalUtcDate> " ) ;
txtKey + + - > Value = _strdup ( UDate ) ;
txtKey - > Key = _strdup ( " <MsgOriginalUtcTime> " ) ;
txtKey + + - > Value = _strdup ( & UDateTime [ 9 ] ) ;
txtKey - > Key = _strdup ( " <MsgOriginalLocalDate> " ) ;
txtKey + + - > Value = _strdup ( Date ) ;
txtKey - > Key = _strdup ( " <MsgOriginalLocalTime> " ) ;
txtKey + + - > Value = _strdup ( & UDateTime [ 9 ] ) ;
txtKey - > Key = _strdup ( " <MsgOriginalDTG> " ) ;
txtKey + + - > Value = _strdup ( UDTG ) ;
txtKey - > Key = _strdup ( " <MsgOriginalSize> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalAttachmentCount> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalXML> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
}
else
{
txtKey - > Key = _strdup ( " <MsgIsReply> " ) ;
txtKey + + - > Value = _strdup ( " False " ) ;
txtKey - > Key = _strdup ( " <MsgIsForward> " ) ;
txtKey + + - > Value = _strdup ( " False " ) ;
txtKey - > Key = _strdup ( " <MsgIsAcknowledgement> " ) ;
txtKey + + - > Value = _strdup ( " False " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalSubject> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalSender> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalBody> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalID> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalDate> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalUtcDate> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalUtcTime> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalLocalDate> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalLocalTime> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalDTG> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalSize> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalAttachmentCount> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
txtKey - > Key = _strdup ( " <MsgOriginalXML> " ) ;
txtKey + + - > Value = _strdup ( " " ) ;
}
txtKey - > Key = _strdup ( " <FormFolder> " ) ;
txtKey + + - > Value = _strdup ( FormDir ) ; //Form Folder
// Do standard Variable substitution on file
DoStandardTemplateSubsitutions ( Session , WebMail - > txtFile ) ;
txtFile = _strdup ( WebMail - > txtFile ) ; // We chop up and modify bits of txtFile, so need copy
// Scan template line by line extracting useful information
ptr = txtFile ;
ptr1 = strchr ( ptr , ' \r ' ) ;
while ( ptr1 )
{
if ( _memicmp ( ptr , " Msg: " , 4 ) = = 0 )
{
// Rest is message body. May need <var> substitutions
if ( WebMail - > Body )
free ( WebMail - > Body ) ;
WebMail - > Body = _strdup ( ptr + 4 ) ;
break ;
}
// Can now terminate lines
* ptr1 + + = 0 ;
while ( * ptr1 = = ' \r ' | | * ptr1 = = ' \n ' )
* ptr1 + + = 0 ;
if ( _memicmp ( ptr , " Form: " , 5 ) = = 0 )
{
InputName = & ptr [ 5 ] ;
while ( * InputName = = ' ' ) // Remove leading spaces
InputName + + ;
WebMail - > InputHTMLName = _strdup ( InputName ) ;
WebMail - > DisplayHTMLName = strlop ( WebMail - > InputHTMLName , ' , ' ) ;
if ( WebMail - > DisplayHTMLName )
{
while ( * WebMail - > DisplayHTMLName = = ' ' ) // Remove leading spaces
WebMail - > DisplayHTMLName + + ;
WebMail - > DisplayHTMLName = _strdup ( WebMail - > DisplayHTMLName ) ;
}
}
else if ( _memicmp ( ptr , " ReplyTemplate: " , 14 ) = = 0 )
{
char * end ;
ReplyName = & ptr [ 14 ] ;
while ( * ReplyName = = ' ' )
ReplyName + + ;
strlop ( ReplyName , ' \r ' ) ; // Terminate
// Filename may have embedded spaces, so have to scan from end, not use strlop
end = ReplyName + strlen ( ReplyName ) - 1 ;
while ( * end = = ' ' )
* end - - = 0 ;
WebMail - > ReplyHTMLName = _strdup ( ReplyName ) ;
}
else if ( _memicmp ( ptr , " To: " , 3 ) = = 0 )
{
if ( strlen ( ptr ) > 5 )
WebMail - > To = _strdup ( & ptr [ 3 ] ) ;
}
else if ( _memicmp ( ptr , " Subj: " , 5 ) = = 0 )
{
if ( ptr [ 5 ] = = ' ' ) // May have space after :
ptr + + ;
if ( strlen ( ptr ) > 6 )
WebMail - > Subject = _strdup ( & ptr [ 5 ] ) ;
}
else if ( _memicmp ( ptr , " Subject: " , 8 ) = = 0 )
{
if ( ptr [ 8 ] = = ' ' )
ptr + + ;
if ( strlen ( ptr ) > 9 )
WebMail - > Subject = _strdup ( & ptr [ 8 ] ) ;
}
else if ( _memicmp ( ptr , " Def: " , 4 ) = = 0 )
{
// Def: MsgOriginalBody=<var MsgOriginalBody>
char * val = strlop ( ptr , ' = ' ) ;
if ( val )
{
// Make Room for {} delimiters
memmove ( ptr , ptr + 1 , strlen ( ptr ) ) ;
ptr [ 3 ] = ' < ' ;
ptr [ strlen ( ptr ) ] = ' > ' ;
while ( val [ strlen ( val ) - 1 ] = = ' ' )
val [ strlen ( val ) - 1 ] = 0 ;
txtKey - > Key = _strdup ( & ptr [ 3 ] ) ;
txtKey + + - > Value = _strdup ( val ) ; //Form Folder
}
}
else if ( _memicmp ( ptr , " Type: " , 5 ) = = 0 )
{
if ( stristr ( ptr , " Winlink " ) )
WebMail - > Winlink = TRUE ;
else if ( stristr ( ptr , " P2P " ) )
WebMail - > P2P = TRUE ;
else if ( stristr ( ptr , " Packet " ) )
WebMail - > Packet = TRUE ;
}
else if ( _memicmp ( ptr , " SeqInc: " , 7 ) = = 0 )
{
int SeqInc = 1 ;
while ( ptr [ 7 ] = = ' ' )
ptr + + ;
if ( strlen ( & ptr [ 7 ] ) )
SeqInc = atoi ( & ptr [ 7 ] ) ;
Session - > User - > WebSeqNo + = SeqInc ;
sprintf ( WebMail - > txtKeys [ 0 ] . Value , " %d " , Session - > User - > WebSeqNo ) ;
}
else if ( _memicmp ( ptr , " SeqSet: " , 7 ) = = 0 )
{
int SeqSet = 0 ;
while ( ptr [ 7 ] = = ' ' )
ptr + + ;
if ( strlen ( & ptr [ 7 ] ) )
SeqSet = atoi ( & ptr [ 7 ] ) ;
Session - > User - > WebSeqNo = SeqSet ;
sprintf ( WebMail - > txtKeys [ 0 ] . Value , " %d " , Session - > User - > WebSeqNo ) ;
}
// Attach:file1, file2, ... - If present, specifies one or more files to attach to the message.
//Readonly: Yes | No - If Readonly is set to Yes, then the message is created by the form and it cannot be edited by the user.
ptr = ptr1 ;
ptr1 = strchr ( ptr , ' \r ' ) ;
}
if ( WebMail - > ReplyHTMLName = = NULL )
WebMail - > ReplyHTMLName = _strdup ( " " ) ;
free ( txtFile ) ;
return TRUE ;
}
VOID FormatTime2 ( char * Time , time_t cTime )
{
struct tm * TM ;
TM = gmtime ( & cTime ) ;
sprintf ( Time , " %s, %02d %s %3d %02d:%02d:%02d GMT " , dat [ TM - > tm_wday ] , TM - > tm_mday , month [ TM - > tm_mon ] ,
TM - > tm_year + 1900 , TM - > tm_hour , TM - > tm_min , TM - > tm_sec ) ;
}
VOID DownloadAttachments ( struct HTTPConnectionInfo * Session , char * Reply , int * RLen , char * Param )
{
WebMailInfo * WebMail = Session - > WebMail ;
char TimeString [ 64 ] ;
char FileTimeString [ 64 ] ;
int file = atoi ( Param ) ;
file - - ; // Sent at +1 in case no downloadable attachments
if ( file = = - 1 )
{
// User has gone back, then selected "No file Selected"
// Or no files
* RLen = sprintf ( Reply , " <html><script>window.history.back();</script></html> " ) ;
return ;
}
FormatTime2 ( FileTimeString , time ( NULL ) ) ;
FormatTime2 ( TimeString , time ( NULL ) ) ;
* RLen = sprintf ( Reply , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n "
" Content-Type: application/octet-stream \r \n "
" Content-Disposition: attachment; filename= \" %s \" \r \n "
" Date: %s \r \n "
" Last-Modified: %s \r \n "
" \r \n " , WebMail - > FileLen [ file ] , WebMail - > FileName [ file ] , TimeString , FileTimeString ) ;
memcpy ( & Reply [ * RLen ] , WebMail - > FileBody [ file ] , WebMail - > FileLen [ file ] ) ;
* RLen + = WebMail - > FileLen [ file ] ;
return ;
}
VOID getAttachmentList ( struct HTTPConnectionInfo * Session , char * Reply , int * RLen , char * Rest )
{
char popuphddr [ ] =
" <html><body align=center background='/background.jpg'> "
" <script> "
" function myFunction() {var x = document.getElementById('Sel').value; "
" var Key = \" %s \" ; "
" var param = \" toolbar=yes,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,titlebar=yes,toobar=yes \" ; "
" window.open( \" /WebMail/GetDownLoad \" + '?' + Key + '&' + x,'_self', param); "
" } "
" </script> "
" <div align=center>Note files over 100K long can't be downloaded<br><br> "
" <table border=1 cellpadding=2 bgcolor=white> "
" <tr><td><select size=%d id='Sel' size=10 onclick=myFunction()> " ;
char popup [ 10000 ] ;
int i ;
WebMailInfo * WebMail = Session - > WebMail ;
sprintf ( popup , popuphddr , Session - > Key , WebMail - > Files ) ;
for ( i = 0 ; i < WebMail - > Files ; i + + )
{
if ( WebMail - > FileLen [ i ] < 100000 )
sprintf ( popup , " %s <option value=%d>%s (Len %d) " , popup , i + 1 , WebMail - > FileName [ i ] , WebMail - > FileLen [ i ] ) ;
}
sprintf ( popup , " %s</select></td></tr></table><br><input onclick=window.history.back() value=Back type=button class='btn'></div> " , popup ) ;
* RLen = sprintf ( Reply , " %s " , popup ) ;
return ;
}
char * WebFindPart ( char * * Msg , char * Boundary , int * PartLen , char * End )
{
char * ptr = * Msg ;
char * Msgptr = * Msg ;
size_t BLen = strlen ( Boundary ) ;
char * Part ;
while ( ptr < End ) // Just in case we run off end
{
if ( * ptr = = ' - ' & & * ( ptr + 1 ) = = ' - ' )
{
if ( memcmp ( & ptr [ 2 ] , Boundary , BLen ) = = 0 )
{
// Found Boundary
size_t Partlen = ptr - Msgptr ;
Part = malloc ( Partlen + 1 ) ;
memcpy ( Part , Msgptr , Partlen ) ;
Part [ Partlen ] = 0 ;
* Msg = ptr + BLen + 4 ;
* PartLen = ( int ) Partlen ;
return Part ;
}
}
ptr + + ;
}
return NULL ;
}
2022-11-12 15:00:02 +00:00
int ProcessWebmailWebSock ( char * MsgPtr , char * OutBuffer )
{
int Len = 129 ;
char * Key = strlop ( MsgPtr , ' & ' ) ;
struct HTTPConnectionInfo * Session ;
struct UserInfo * User ;
int m ;
struct MsgInfo * Msg ;
2023-03-16 06:52:27 +00:00
char * ptr = & OutBuffer [ 10 ] ; // allow room for full payload length (64 bit)
2022-11-12 15:00:02 +00:00
int n = NumberofMessages ;
char Via [ 64 ] ;
int Count = 0 ;
if ( Key = = 0 )
return 0 ;
Session = FindWMSession ( Key ) ;
if ( Session = = NULL )
return 0 ;
User = Session - > User ;
// Outbuffer is 250000
// ptr += sprintf(ptr, "<div align=left id=\"main\" style=\"overflow:scroll;\">\r\n"
ptr + = sprintf ( ptr , " <pre align=left> " ) ;
ptr + = sprintf ( ptr , " %s " , " # Date XX Len To @ From Subject \r \n \r \n " ) ;
for ( m = LatestMsg ; m > = 1 ; m - - )
{
if ( ptr > & OutBuffer [ 244000 ] )
break ; // protect buffer
Msg = GetMsgFromNumber ( m ) ;
if ( Msg = = 0 | | Msg - > type = = 0 | | Msg - > status = = 0 )
continue ; // Protect against corrupt messages
if ( Msg & & CheckUserMsg ( Msg , User - > Call , User - > flags & F_SYSOP ) )
{
2023-10-10 22:07:04 +01:00
char UTF8Title [ 4096 ] ;
2022-11-12 15:00:02 +00:00
char * EncodedTitle ;
// List if it is the right type and in the page range we want
if ( Session - > WebMailTypes [ 0 ] & & strchr ( Session - > WebMailTypes , Msg - > type ) = = 0 )
continue ;
// All Types or right Type. Check Mine Flag
if ( Session - > WebMailMine )
{
// Only list if to or from me
if ( strcmp ( User - > Call , Msg - > to ) ! = 0 & & strcmp ( User - > Call , Msg - > from ) ! = 0 )
continue ;
}
2024-02-23 21:36:36 +00:00
if ( Session - > WebMailMyTX )
{
// Only list if to or from me
if ( strcmp ( User - > Call , Msg - > from ) ! = 0 )
continue ;
}
if ( Session - > WebMailMyRX )
{
// Only list if to or from me
if ( strcmp ( User - > Call , Msg - > to ) ! = 0 )
continue ;
}
2022-11-12 15:00:02 +00:00
if ( Count + + < Session - > WebMailSkip )
continue ;
strcpy ( Via , Msg - > via ) ;
strlop ( Via , ' . ' ) ;
// make sure title is HTML safe (no < > etc) and UTF 8 encoded
EncodedTitle = doXMLTransparency ( Msg - > title ) ;
2023-10-10 22:07:04 +01:00
memset ( UTF8Title , 0 , 4096 ) ; // In case convert fails part way through
ConvertTitletoUTF8 ( Session - > WebMail , EncodedTitle , UTF8Title , 4095 ) ;
2022-11-12 15:00:02 +00:00
free ( EncodedTitle ) ;
2023-10-10 22:07:04 +01:00
2022-11-12 15:00:02 +00:00
ptr + = sprintf ( ptr , " <a href=/WebMail/WM?%s&%d>%6d</a> %s %c%c %5d %-8s%-8s%-8s%s \r \n " ,
Key , Msg - > number , Msg - > number ,
FormatDateAndTime ( ( time_t ) Msg - > datecreated , TRUE ) , Msg - > type ,
Msg - > status , Msg - > length , Msg - > to , Via ,
Msg - > from , UTF8Title ) ;
n - - ;
if ( n = = 0 )
break ;
}
}
ptr + = sprintf ( ptr , " %s</pre> \r \n " , ptr ) ;
2023-03-16 06:52:27 +00:00
Len = ptr - & OutBuffer [ 10 ] ;
2022-11-12 15:00:02 +00:00
OutBuffer [ 0 ] = 0x81 ; // Fin, Data
if ( Len < 126 )
{
OutBuffer [ 1 ] = Len ;
2023-03-16 06:52:27 +00:00
memmove ( & OutBuffer [ 2 ] , & OutBuffer [ 10 ] , Len ) ;
2022-11-12 15:00:02 +00:00
return Len + 2 ;
}
2023-03-16 06:52:27 +00:00
else if ( Len < 65536 )
2022-11-12 15:00:02 +00:00
{
2023-03-16 06:52:27 +00:00
OutBuffer [ 1 ] = 126 ; // Unmasked, Extended Len 16
2022-11-12 15:00:02 +00:00
OutBuffer [ 2 ] = Len > > 8 ;
OutBuffer [ 3 ] = Len & 0xff ;
2023-03-16 06:52:27 +00:00
memmove ( & OutBuffer [ 4 ] , & OutBuffer [ 10 ] , Len ) ;
2022-11-12 15:00:02 +00:00
return Len + 4 ;
}
2023-03-16 06:52:27 +00:00
else
{
OutBuffer [ 1 ] = 127 ; // Unmasked, Extended Len 64 bits
// Len is 32 bits, so pad with zeros
OutBuffer [ 2 ] = 0 ;
OutBuffer [ 3 ] = 0 ;
OutBuffer [ 4 ] = 0 ;
OutBuffer [ 5 ] = 0 ;
OutBuffer [ 6 ] = ( Len > > 24 ) & 0xff ;
OutBuffer [ 7 ] = ( Len > > 16 ) & 0xff ;
OutBuffer [ 8 ] = ( Len > > 8 ) & 0xff ;
OutBuffer [ 9 ] = Len & 0xff ;
2022-11-12 15:00:02 +00:00
2023-03-16 06:52:27 +00:00
return Len + 10 ;
}
2022-11-12 15:00:02 +00:00
}
2022-08-28 09:35:46 +01:00