linbpq/BBSHTMLConfig.c

3176 lines
87 KiB
C
Raw Permalink Normal View History

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"
#ifdef WIN32
//#include "C:\Program Files (x86)\GnuWin32\include\iconv.h"
#else
#include <iconv.h>
#endif
extern char NodeTail[];
extern char BBSName[10];
extern char LTFROMString[2048];
extern char LTTOString[2048];
extern char LTATString[2048];
//static UCHAR BPQDirectory[260];
extern ConnectionInfo Connections[];
2023-12-28 10:31:09 +00:00
2022-08-28 09:35:46 +01:00
extern int NumberofStreams;
extern time_t MaintClock; // Time to run housekeeping
extern int SMTPMsgs;
extern int ChatApplNum;
extern int MaxChatStreams;
extern char Position[81];
extern char PopupText[251];
extern int PopupMode;
2023-12-28 10:31:09 +00:00
extern int reportMailEvents;
2022-08-28 09:35:46 +01:00
#define MaxCMS 10 // Numbr of addresses we can keep - currently 4 are used.
struct UserInfo * BBSLIST[NBBBS + 1];
int MaxBBS = 0;
#define MAIL
#include "httpconnectioninfo.h"
struct TCPINFO * TCP;
VOID ProcessMailSignon(struct TCPINFO * TCP, char * MsgPtr, char * Appl, char * Reply, int * RLen);
static struct HTTPConnectionInfo * FindSession(char * Key);
VOID ProcessUserUpdate(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest);
VOID ProcessMsgFwdUpdate(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest);
VOID SendConfigPage(char * Reply, int * ReplyLen, char * Key);
VOID ProcessConfUpdate(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest);
VOID ProcessUIUpdate(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest);
VOID SendUserSelectPage(char * Reply, int * ReplyLen, char * Key);
VOID SendFWDSelectPage(char * Reply, int * ReplyLen, char * Key);
int EncryptPass(char * Pass, char * Encrypt);
VOID ProcessFWDUpdate(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest);
VOID SendStatusPage(char * Reply, int * ReplyLen, char * Key);
VOID SendUIPage(char * Reply, int * ReplyLen, char * Key);
VOID GetParam(char * input, char * key, char * value);
BOOL GetConfig(char * ConfigName);
VOID ProcessDisUser(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest);
int APIENTRY SessionControl(int stream, int command, int param);
int SendMessageDetails(struct MsgInfo * Msg, char * Reply, char * Key);
VOID ProcessMsgUpdate(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest);
VOID ProcessMsgAction(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest);
int APIENTRY GetNumberofPorts();
int APIENTRY GetPortNumber(int portslot);
UCHAR * APIENTRY GetPortDescription(int portslot, char * Desc);
struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot(int portslot);
VOID SendHouseKeeping(char * Reply, int * ReplyLen, char * Key);
VOID SendWelcomePage(char * Reply, int * ReplyLen, char * Key);
VOID SaveWelcome(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Key);
VOID GetMallocedParam(char * input, char * key, char ** value);
VOID SaveMessageText(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest);
VOID SaveHousekeeping(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Key);
VOID SaveWP(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Key);
int SendWPDetails(WPRec * WP, char * Reply, char * Key);
int SendUserDetails(struct HTTPConnectionInfo * Session, char * Reply, char * Key);
int SetupNodeMenu(char * Buff);
VOID SendFwdSelectPage(char * Reply, int * ReplyLen, char * Key);
VOID SendFwdDetails(struct UserInfo * User, char * Reply, int * ReplyLen, char * Key);
VOID SetMultiStringValue(char ** values, char * Multi);
VOID SendFwdMainPage(char * Reply, int * ReplyLen, char * Key);
VOID SaveFwdCommon(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest);
VOID SaveFwdDetails(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest);
char ** SeparateMultiString(char * MultiString, BOOL NoToUpper);
VOID TidyPrompts();
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 MulticastStatusHTML(char * Reply);
void ProcessWebMailMessage(struct HTTPConnectionInfo * Session, char * Key, BOOL LOCAL, char * Method, char * NodeURL, char * input, char * Reply, int * RLen, int InputLen);
int SendWebMailHeader(char * Reply, char * Key, struct HTTPConnectionInfo * Session);
struct UserInfo * FindBBS(char * Name);
void ReleaseWebMailStruct(WebMailInfo * WebMail);
VOID TidyWelcomeMsg(char ** pPrompt);
2024-11-05 21:03:15 +00:00
int MailAPIProcessHTTPMessage(struct HTTPConnectionInfo * Session, char * response, char * Method, char * URL, char * request, BOOL LOCAL, char * Param, char * Token);
2022-08-28 09:35:46 +01:00
char UNC[] = "";
char CHKD[] = "checked=checked ";
char sel[] = "selected";
char Sent[] = "#98FFA0";
char ToSend[] = "#FFFF00";
char NotThisOne[] = "#FFFFFF";
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 WebMailSignon[];
char MailSignon[] = "<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 the BBS</h3>"
"<form method=post action=/Mail/Signon?Mail>"
"<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>";
char MailPage[] = "<html><head><title>%s's BBS Web Server</title>"
"<style type=\"text/css\">"
"input.btn:active {background:black;color:white;} "
"submit.btn:active {background:black;color:white;} "
"</style>"
"</head>"
"<body background=\"/background.jpg\"><h3 align=center>BPQ32 BBS %s</h3><P>"
"<P align=center><table border=1 cellpadding=2 bgcolor=white><tr>"
"<td><a href=/Mail/Status?%s>Status</a></td>"
"<td><a href=/Mail/Conf?%s>Configuration</a></td>"
"<td><a href=/Mail/Users?%s>Users</a></td>"
"<td><a href=/Mail/Msgs?%s>Messages</a></td>"
"<td><a href=/Mail/FWD?%s>Forwarding</a></td>"
"<td><a href=/Mail/Wel?%s>Welcome Msgs & Prompts</a></td>"
"<td><a href=/Mail/HK?%s>Housekeeping</a></td>"
"<td><a href=/Mail/WP?%s>WP Update</a></td>"
2024-07-07 16:06:08 +01:00
"<td><a href=/Webmail>WebMail</a></td>"
2022-08-28 09:35:46 +01:00
"<td><a href=/>Node Menu</a></td>"
"</tr></table>";
char RefreshMainPage[] = "<html><head>"
"<meta http-equiv=refresh content=10>"
"<style type=\"text/css\">"
"input.btn:active {background:black;color:white;} "
"submit.btn:active {background:black;color:white;} "
"</style>"
"<title>%s's BBS Web Server</title></head>"
"<body background=\"/background.jpg\"><h3 align=center>BPQ32 BBS %s</h3><P>"
"<P align=center><table border=1 cellpadding=2 bgcolor=white><tr>"
"<td><a href=/Mail/Status?%s>Status</a></td>"
"<td><a href=/Mail/Conf?%s>Configuration</a></td>"
"<td><a href=/Mail/Users?%s>Users</a></td>"
"<td><a href=/Mail/Msgs?%s>Messages</a></td>"
"<td><a href=/Mail/FWD?%s>Forwarding</a></td>"
"<td><a href=/Mail/Wel?%s>Welcome Msgs & Prompts</a></td>"
"<td><a href=/Mail/HK?%s>Housekeeping</a></td>"
"<td><a href=/Mail/WP?%s>WP Update</a></td>"
2024-07-07 16:06:08 +01:00
"<td><a href=/Webmail>WebMail</a></td>"
2022-08-28 09:35:46 +01:00
"<td><a href=/>Node Menu</a></td>"
"</tr></table>";
char StatusPage [] =
"<form style=\"font-family: monospace; text-align: center\" method=post action=/Mail/DisSession?%s>"
"<br>User&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Callsign&nbsp;&nbsp; Stream Queue<br>"
"<select style=\"font-family: monospace;\" tabindex=1 size=10 name=call>";
char StreamEnd[] =
"</select><br><input name=Disconnect value=Disconnect type=submit class='btn'><br><br>";
char StatusTail[] =
"Msgs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <input readonly=readonly value=%d size=3><br>"
"Sysop Msgs <input readonly=readonly value=%d size=3><br>"
"Held Msgs&nbsp; <input readonly=readonly value=%d size=3><br>"
"SMTP Msgs&nbsp; <input readonly=readonly value=%d size=3><br></form>";
char UIHddr [] = "<form style=\"font-family: monospace;\" align=center method=post"
" action=/Mail/UI?%s> Mailfor Header <input size=40 value=\"%s\" name=MailFor><br>"
"&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;"
"&nbsp;&nbsp;&nbsp; (use \\r to insert newline in message)<br><br>"
"Enable Port&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;"
"&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; Path&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;"
"&nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Send: MailFor Headers Empty Mailfor<br><br>";
char UILine[] = "<input %sname=En%d type=checkbox> %s <input size=40 value=\"%s\" name=Path%d>"
" <input %sname=SndMF%d type=checkbox>"
"&nbsp;&nbsp;&nbsp;&nbsp;<input %sname=SndHDDR%d type=checkbox>"
"&nbsp; &nbsp; &nbsp; &nbsp; <input %sname=SndNull%d type=checkbox><br>";
char UITail[] = "<br><br><input name=Update value=Update type=submit class='btn'> "
"<input name=Cancel value=Cancel type=submit class='btn'><br></form>";
char FWDSelectHddr[] =
"<form style=\"font-family: monospace; text-align: center;\" method=post action=/Mail/FWDSel?%s>"
"Max Size to Send &nbsp;&nbsp; <input value=%d size=3 name=MaxTX><br>"
"Max Size to Receive <input value=%d size=3 name=MaxRX><br>"
"Warn if no route for P or T <input %sname=WarnNoRoute type=checkbox><br>"
"Use Local Time&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
"<input %sname=LocalTime type=checkbox><br><br>"
"Aliases &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; Select BBS<br>"
"<textarea rows=10 cols=20 name=Aliases>%s</textarea> &nbsp<select tabindex=1 size=10 name=call>";
char FWDSelectTail[] =
"</select><br>&nbsp;&nbsp; <input name=Save value=Save type=submit class='btn'>&nbsp;<input "
"name=Cancel value=Cancel type=submit class='btn'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
"&nbsp; <input name=Select value=Select type=submit class='btn'></form>";
char UserSelectHddr[] =
"<form style=\"font-family: monospace; text-align: center\" method=post action=/Mail/Users?%s>"
"Please Select User<br><br><select tabindex=1 size=10 name=call>";
char UserSelectLine[] = "<option value=%s>%s</option>";
char StatusLine[] = "<option value=%d>%s</option>";
char UserSelectTail[] = "</select><br><br>"
"<input size=6 value=\"\" name=NewCall>"
"<input type=submit class='btn' value=\"Add User\" name=Adduser><br>"
"<input type=submit class='btn' value=Select> "
"<input type=submit class='btn' value=Cancel name=Cancel><br></form>";
char UserUpdateHddr[] =
"<h3 align=center>Update User %s</h3>"
"<form style=\"font-family: monospace; text-align: center\" method=post action=/Mail/Users?%s>";
char UserUpdateLine[] = "<option value=%s>%s</option>";
//<option value="G8BPQ">G8BPQ</option>
//<input checked="checked" name=%s type="checkbox"><br>
char FWDUpdate[] =
"<h3 align=center>Update Forwarding for BBS %s</h3>"
"<form style=\"font-family: monospace; text-align: center\" method=post action=/Mail/FWD?%s"
" name=Test>&nbsp;&nbsp;&nbsp;&nbsp;"
"TO &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
"AT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
"TIMES&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Connect Script<br>"
"<textarea wrap=hard rows=10 cols=10 name=TO>%s</textarea>"
" <textarea wrap=hard rows=10 cols=10 name=AT>%s</textarea>"
" <textarea wrap=hard rows=10 cols=10 name=Times>%s</textarea>"
" <textarea wrap=hard rows=10 cols=20 name=FWD>%s</textarea><br>"
"<textarea wrap=hard rows=10 cols=30 name=HRB>%s</textarea>"
" <textarea wrap=hard rows=10 cols=30 name=HRP>%s</textarea><br><br>"
"Enable Forwarding&nbsp;<input %sname=EnF type=checkbox> Interval"
"<input value=%d size=3 name=Interval>(Secs) Request Reverse"
"<input %sname=EnR type=checkbox> Interval <input value=%d size=3 "
"name=RInterval>(Secs)<br>"
"Send new messages without waiting for poll timer<input %sname=NoWait type=checkbox><br>"
"BBS HA <input value=%s size=60 name=BBSHA> FBB Max Block <input "
"value=%d size=3 name=FBBBlock><br>"
"Send Personal Mail Only <input %sname=Personal type=checkbox>&nbsp;"
"Allow Binary&nbsp; <input %sname=Bin type=checkbox>&nbsp;&nbsp; Use B1 "
"Protocol <input %sname=B1 type=checkbox>&nbsp; Use B2 Protocol<input "
"%sname=B2 type=checkbox><br><br>"
"<input name=Submit value=Update type=submit class='btn'> <input name=Fwd value=\"Start Forwarding\" type=submit class='btn'> "
"<input name=Cancel value=Cancel type=submit class='btn'></form><br></body></html>";
static char MailDetailPage[] =
"<html><head><meta content=\"text/html; charset=ISO-8859-1\" http-equiv=\"content-type\">"
"<title>MsgEdit</title></head><body><h4>Message %d</h4>"
"<form style=\"font-family: monospace;\" method=post action=/Mail/Msg?%s name=Msgs>"
"From&nbsp; <input style=\"font-family: monospace;\" size=10 name=From value=%s> Sent&nbsp;&nbsp;&nbsp;"
"&nbsp; &nbsp; &nbsp; <input readonly=readonly size=12 name=Sent value=\"%s\">&nbsp;"
"Type &nbsp;&nbsp;&nbsp;&nbsp;<select tabindex=1 size=1 name=Type>"
"<option %s value=B>B</option>"
"<option %s value=P>P</option>"
"<option %s value=T>T</option>"
"</select><br>"
"To&nbsp; &nbsp; <input style=\"font-family: monospace;\" size=10 name=To value=%s>"
" Received&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input readonly=readonly size=12 name=RX value=\"%s\">&nbsp;"
"Status &nbsp;&nbsp;<select tabindex=1 size=1 name=Status>"
"<option %s value=N>N</option>"
"<option %s value=Y>Y</option>"
"<option %s value=F>F</option>"
"<option %s value=K>K</option>"
"<option %s value=H>H</option>"
"<option %s value=D>D</option>"
"<option %s value=$>$</option>"
"</select><br>"
"BID&nbsp;&nbsp; <input style=\"width:100px; font-family: monospace; \" name=BID value=\"%s\"> Last Changed <input readonly=readonly size=12 name=LastChange value=\"%s\">&nbsp;"
"Size&nbsp; <input readonly=readonly size=5 name=Size value=%d><br><br>"
"%s" // Email from Line
"&nbsp;VIA&nbsp; <input style=\"width:360px;\" name=VIA value=%s><br>"
"Title&nbsp; <input style=\"width:360px;\" name=Title value=\"%s\"> <br><br>"
"<span align = center><input onclick=editmsg(\"EditM?%s?%d\") value=\"Edit Text\" type=button class='btn'> "
"<input onclick=save(this.form) value=Save type=button class='btn'> "
"<td><a href=/Mail/SaveMessage?%s><button type=button class='btn'>Save Message</button></a></td>"
"<td><a href=/Mail/SaveAttachment?%s><button type=button class='btn' %s>Save Attachment</button></a></td>"
//"<input onclick=doit(\"SavetoFile\") value=\"Save to File\" type=button class='btn'> "
"<input onclick=doit(\"Print\") value=Print type=button class='btn'> "
"<input onclick=doit(\"Export\") value=Export type=button class='btn'></span><br><br>"
"Green = Sent, Yellow = Queued"
"<table style=\"text-align: left; width: 490px; font-family: monospace; align=center \" border=1 cellpadding=2 cellspacing=2>";
char MailDetailTail[] = "</table></form>";
char Welcome[] = "<form style=\"font-family: monospace; text-align: center;\""
"method=post action=/Mail/Welcome?%s>"
"Normal User Welcome<br>"
"<textarea cols=80 rows=3 name=NUWelcome>%s</textarea><br>"
"New User Welcome<br>"
"<textarea cols=80 rows=3 name=NewWelcome>%s</textarea><br>"
"Expert User Welcome<br>"
"<textarea cols=80 rows=3 name=ExWelcome>%s</textarea><br>"
"Normal User Prompt<br>"
"<textarea cols=80 rows=3 name=NUPrompt>%s</textarea><br>"
"New User Prompt<br>"
"<textarea cols=80 rows=3 name=NewPrompt>%s</textarea><br>"
"Expert User Prompt<br>"
"<textarea cols=80 rows=1 name=ExPrompt>%s</textarea><br>"
"Signoff<br>"
"<textarea cols=80 rows=1 name=Bye>%s</textarea><br><br>"
"$U:Callsign of the user&nbsp; $I:First name of the user $X:Messages for user $x:Unread messages<br>"
"$L:Number of the latest message $N:Number of active messages. $Z:Last message read by user<br><br>"
"<input name=Save value=Save type=submit class='btn'> <inputcname=Cancel value=Cancel type=submit class='btn'></form>";
static char MsgEditPage[] = "<html><head><meta content=\"text/html; charset=ISO-8859-1\" http-equiv=\"content-type\">"
"<title></title></head><body>"
"<form style=\"font-family: monospace; text-align: center;\"method=post action=EMSave?%s>"
"<textarea cols=90 rows=33 name=Msg>%s</textarea><br><br>"
"<input name=Save value=Save type=submit class='btn'><input name=Cancel value=Cancel type=submit class='btn'><br></form>";
static char WPDetail[] = "<form style=\"font-family: monospace;\" method=post action=/Mail/WP?%s>"
"<br><table style=\"text-align: left; width: 431px;\" border=0 cellpadding=2 cellspacing=2><tbody>"
"<tr><td>Call</td><td><input readonly=readonly size=10 value=\"%s\"></td></tr>"
"<tr><td>Name</td><td><input size=30 name=Name value=\"%s\"></td></tr>"
"<tr><td>Home BBS 1</td><td><input size=40 name=Home1 value=%s></td></tr>"
"<tr><td>Home BBS 2</td><td><input size=40 name=Home2 value=%s></td></tr>"
"<tr><td>QTH 1</td><td><input size=40 name=QTH1 value=\"%s\"></td></tr>"
"<tr><td>QTH 2</td><td><input size=40 name=QTH2 value=\"%s\"></td></tr>"
"<tr><td>ZIP 1<br></td><td><input size=10 name=ZIP1 value=\"%s\"></td></tr>"
"<tr><td>ZIP 2<br></td><td><input size=10 name=ZIP2 value=\"%s\"></td></tr>"
"<tr><td>Last Seen<br></td><td><input size=15 name=Seen value=\"%s\"></td></tr>"
"<tr><td>Last Modified<br></td><td><input size=15 name=Modif value=\"%s\"></td></tr>"
"<tr><td>Type<br></td><td><input size=4 name=Type value=%c></td></tr>"
"<tr><td>Changed<br></td><td><input size=4 name=Changed value=%d></td></tr>"
"<tr><td>Seen<br></td><td><input size=4 name=Seen value=%d></td></tr></tbody></table>"
"<br><input onclick=save(this.form) value=Save type=button class='btn'> "
"<input onclick=del(this.form) value=Delete type=button class='btn'> "
"<input name=Cancel value=Cancel type=submit class='btn'></form>";
static char LostSession[] = "<html><body>"
"<form style=\"font-family: monospace; text-align: center;\" method=post action=/Mail/Lost?%s>"
"Sorry, Session had been lost<br><br>&nbsp;&nbsp;&nbsp;&nbsp;"
"<input name=Submit value=Restart type=submit class='btn'> <input type=submit class='btn' value=Exit name=Cancel><br></form>";
char * MsgEditTemplate = NULL;
char * HousekeepingTemplate = NULL;
char * ConfigTemplate = NULL;
char * WPTemplate = NULL;
char * UserListTemplate = NULL;
char * UserDetailTemplate = NULL;
char * FwdTemplate = NULL;
char * FwdDetailTemplate = NULL;
char * WebMailTemplate = NULL;
char * WebMailMsgTemplate = NULL;
char * jsTemplate = NULL;
#ifdef LINBPQ
UCHAR * GetBPQDirectory();
#endif
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 SendHeader(char * Reply, char * Key)
{
return sprintf(Reply, MailPage, BBSName, BBSName, Key, Key, Key, Key, Key, Key, Key, Key);
}
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
{
2024-11-12 21:20:01 +00:00
Len = strlen(Title);
2023-10-10 22:07:04 +01:00
2024-11-12 21:20:01 +00:00
if (WebIsUTF8(Title, Len) == FALSE)
{
int code = TrytoGuessCode(Title, Len);
2022-08-28 09:35:46 +01:00
2024-11-12 21:20:01 +00:00
if (code == 437)
Len = Convert437toUTF8(Title, Len, UTF8Title);
else if (code == 1251)
Len = Convert1251toUTF8(Title, Len, UTF8Title);
else
Len = Convert1252toUTF8(Title, Len, UTF8Title);
2023-10-10 22:07:04 +01:00
2024-11-12 21:20:01 +00:00
UTF8Title[Len] = 0;
2022-08-28 09:35:46 +01:00
}
else
strcpy(UTF8Title, Title);
}
BOOL GotFirstMessage = 0;
2024-11-05 21:03:15 +00:00
void ProcessMailHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, char * URL, char * input, char * Reply, int * RLen, int InputLen, char * Token)
2022-08-28 09:35:46 +01:00
{
char * Context = 0, * NodeURL;
int ReplyLen;
BOOL LOCAL = FALSE;
char * Key;
char Appl = 'M';
if (URL[0] == 0 || Method == NULL)
return;
if (strstr(input, "Host: 127.0.0.1"))
LOCAL = TRUE;
2022-11-12 15:00:02 +00:00
if (Session->TNC == (void *)1) // Re-using an address as a flag
2022-08-28 09:35:46 +01:00
LOCAL = TRUE;
NodeURL = strtok_s(URL, "?", &Context);
Key = Session->Key;
if (_memicmp(URL, "/WebMail", 8) == 0)
{
// Pass All Webmail messages to Webmail
ProcessWebMailMessage(Session, Context, LOCAL, Method, NodeURL, input, Reply, RLen, InputLen);
return;
}
2024-11-05 21:03:15 +00:00
if (_memicmp(URL, "/Mail/API/v1/", 13) == 0)
{
*RLen = MailAPIProcessHTTPMessage(Session, Reply, Method, URL, input, LOCAL, Context, Token);
return;
}
2022-08-28 09:35:46 +01:00
// There is a problem if Mail is reloaded without reloading the node
if (GotFirstMessage == 0)
{
if (_stricmp(NodeURL, "/Mail/Header") == 0 || _stricmp(NodeURL, "/Mail/Lost") == 0)
{
*RLen = SendHeader(Reply, Session->Key);
}
else
{
*RLen = sprintf(Reply, "<html><script>window.location.href = '/Mail/Header?%s';</script>", Session->Key);
}
GotFirstMessage = 1;
return;
}
2023-12-28 10:31:09 +00:00
2022-08-28 09:35:46 +01:00
if (strcmp(Method, "POST") == 0)
{
if (_stricmp(NodeURL, "/Mail/Header") == 0)
{
*RLen = SendHeader(Reply, Session->Key);
return;
}
if (_stricmp(NodeURL, "/Mail/Config") == 0)
{
NodeURL[strlen(NodeURL)] = ' '; // Undo strtok
ProcessConfUpdate(Session, input, Reply, RLen, Key);
return ;
}
if (_stricmp(NodeURL, "/Mail/UI") == 0)
{
NodeURL[strlen(NodeURL)] = ' '; // Undo strtok
ProcessUIUpdate(Session, input, Reply, RLen, Key);
return ;
}
if (_stricmp(NodeURL, "/Mail/FwdCommon") == 0)
{
SaveFwdCommon(Session, input, Reply, RLen, Key);
return;
}
if (_stricmp(NodeURL, "/Mail/DisSession") == 0)
{
ProcessDisUser(Session, input, Reply, RLen, Key);
return ;
}
if (_stricmp(NodeURL, "/Mail/UserDetails") == 0)
{
char * param = strstr(input, "\r\n\r\n"); // End of headers
if (param)
{
Session->User = LookupCall(param+4);
if (Session->User)
{
* RLen = SendUserDetails(Session, Reply, Key);
return;
}
}
}
if (_stricmp(NodeURL, "/Mail/UserSave") == 0)
{
ProcessUserUpdate(Session, input, Reply, RLen, Key);
return ;
}
if (_stricmp(NodeURL, "/Mail/MsgDetails") == 0)
{
char * param = strstr(input, "\r\n\r\n"); // End of headers
if (param)
{
int Msgno = atoi(param + 4);
struct MsgInfo * Msg = FindMessageByNumber(Msgno);
Session->Msg = Msg; // Save current Message
* RLen = SendMessageDetails(Msg, Reply, Key);
return;
}
}
if (_stricmp(NodeURL, "/Mail/MsgSave") == 0)
{
ProcessMsgUpdate(Session, input, Reply, RLen, Key);
return ;
}
if (_stricmp(NodeURL, "/Mail/EMSave") == 0)
{
// Save Message Text
SaveMessageText(Session, input, Reply, RLen, Key);
return;
}
if (_stricmp(NodeURL, "/Mail/MsgAction") == 0)
{
ProcessMsgAction(Session, input, Reply, RLen, Key);
return;
}
if (_stricmp(NodeURL, "/Mail/MsgFwdUpdate") == 0)
{
ProcessMsgFwdUpdate(Session, input, Reply, RLen, Key);
return;
}
if (_stricmp(NodeURL, "/Mail/Welcome") == 0)
{
SaveWelcome(Session, input, Reply, RLen, Key);
return;
}
if (_stricmp(NodeURL, "/Mail/HK") == 0)
{
SaveHousekeeping(Session, input, Reply, RLen, Key);
return;
}
if (_stricmp(NodeURL, "/Mail/WPDetails") == 0)
{
char * param = strstr(input, "\r\n\r\n"); // End of headers
if (param)
{
WPRec * WP = LookupWP(param+4);
Session->WP = WP; // Save current Message
* RLen = SendWPDetails(WP, Reply, Key);
return;
}
}
if (_stricmp(NodeURL, "/Mail/WPSave") == 0)
{
SaveWP(Session, input, Reply, RLen, Key);
return;
}
if (_stricmp(NodeURL, "/Mail/MsgInfo.txt") == 0)
{
int n, len = 0;
char * FF = "", *FT = "", *FB = "", *FV = "";
char * param, * ptr1, *ptr2;
struct MsgInfo * Msg;
char UCto[80];
char UCfrom[80];
char UCvia[80];
char UCbid[80];
// Get filter string
param = strstr(input, "\r\n\r\n"); // End of headers
if (param)
{
ptr1 = param + 4;
ptr2 = strchr(ptr1, '|');
if (ptr2){*(ptr2++) = 0; FF = ptr1; ptr1 = ptr2;}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0; FT = ptr1;ptr1 = ptr2;}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0; FV = ptr1;ptr1 = ptr2;}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0; FB = ptr1;ptr1 = ptr2;}
}
if (FT[0])
_strupr(FT);
if (FF[0])
_strupr(FF);
if (FV[0])
_strupr(FV);
if (FB[0])
_strupr(FB);
for (n = NumberofMessages; n >= 1; n--)
{
Msg = MsgHddrPtr[n];
strcpy(UCto, Msg->to);
strcpy(UCfrom, Msg->from);
strcpy(UCvia, Msg->via);
strcpy(UCbid, Msg->bid);
_strupr(UCto);
_strupr(UCfrom);
_strupr(UCvia);
_strupr(UCbid);
if ((!FT[0] || strstr(UCto, FT)) &&
(!FF[0] || strstr(UCfrom, FF)) &&
(!FB[0] || strstr(UCbid, FB)) &&
(!FV[0] || strstr(UCvia, FV)))
{
len += sprintf(&Reply[len], "%d|", Msg->number);
}
}
*RLen = len;
return;
}
if (_stricmp(NodeURL, "/Mail/UserList.txt") == 0)
{
SendUserSelectPage(Reply, RLen, Key);
return;
}
if (_stricmp(NodeURL, "/Mail/FwdList.txt") == 0)
{
SendFwdSelectPage(Reply, RLen, Key);
return;
}
if (_stricmp(NodeURL, "/Mail/FwdDetails") == 0)
{
char * param;
param = strstr(input, "\r\n\r\n"); // End of headers
if (param)
{
Session->User = LookupCall(param+4);
if (Session->User)
{
SendFwdDetails(Session->User, Reply, RLen, Key);
return;
}
}
}
if (_stricmp(NodeURL, "/Mail/FWDSave") == 0)
{
SaveFwdDetails(Session, input, Reply, RLen, Key);
return ;
}
// End of POST section
}
if (strstr(NodeURL, "webscript.js"))
{
if (jsTemplate)
free(jsTemplate);
jsTemplate = GetTemplateFromFile(1, "webscript.js");
ReplyLen = sprintf(Reply, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n"
"Cache-Control: max-age=900\r\nContent-Type: text/javascript\r\n\r\n%s", (int)strlen(jsTemplate), jsTemplate);
*RLen = ReplyLen;
return;
}
if (_stricmp(NodeURL, "/Mail/Header") == 0)
{
*RLen = SendHeader(Reply, Session->Key);
return;
}
if (_stricmp(NodeURL, "/Mail/all.html") == 0)
{
*RLen = SendHeader(Reply, Session->Key);
return;
}
if (_stricmp(NodeURL, "/Mail/Status") == 0 ||
_stricmp(NodeURL, "/Mail/DisSession") == 0) // Sent as POST by refresh timer for some reason
{
SendStatusPage(Reply, RLen, Key);
return;
}
if (_stricmp(NodeURL, "/Mail/Conf") == 0)
{
if (ConfigTemplate)
free(ConfigTemplate);
ConfigTemplate = GetTemplateFromFile(7, "MainConfig.txt");
SendConfigPage(Reply, RLen, Key);
return;
}
if (_stricmp(NodeURL, "/Mail/FWD") == 0)
{
if (FwdTemplate)
free(FwdTemplate);
FwdTemplate = GetTemplateFromFile(4, "FwdPage.txt");
if (FwdDetailTemplate)
free(FwdDetailTemplate);
FwdDetailTemplate = GetTemplateFromFile(3, "FwdDetail.txt");
SendFwdMainPage(Reply, RLen, Key);
return;
}
if (_stricmp(NodeURL, "/Mail/Wel") == 0)
{
SendWelcomePage(Reply, RLen, Key);
return;
}
if (_stricmp(NodeURL, "/Mail/Users") == 0)
{
if (UserListTemplate)
free(UserListTemplate);
UserListTemplate = GetTemplateFromFile(4, "UserPage.txt");
if (UserDetailTemplate)
free(UserDetailTemplate);
UserDetailTemplate = GetTemplateFromFile(4, "UserDetail.txt");
*RLen = sprintf(Reply, UserListTemplate, Key, Key, BBSName,
Key, Key, Key, Key, Key, Key, Key, Key);
return;
}
if (_stricmp(NodeURL, "/Mail/SaveMessage") == 0)
{
struct MsgInfo * Msg = Session->Msg;
char * MailBuffer;
int Files = 0;
int BodyLen;
char * ptr;
int WriteLen=0;
char Hddr[1000];
char FullTo[100];
MailBuffer = ReadMessageFile(Msg->number);
BodyLen = Msg->length;
ptr = MailBuffer;
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);
sprintf(Hddr, "From: %s%s\r\nTo: %s\r\nType/Status: %c%c\r\nDate/Time: %s\r\nBid: %s\r\nTitle: %s\r\n\r\n",
Msg->from, Msg->emailfrom, FullTo, Msg->type, Msg->status, FormatDateAndTime((time_t)Msg->datecreated, FALSE), Msg->bid, Msg->title);
if (Msg->B2Flags & B2Msg)
{
// Remove B2 Headers (up to the File: Line)
char * bptr;
bptr = strstr(ptr, "Body:");
if (bptr)
{
BodyLen = atoi(bptr + 5);
bptr = strstr(bptr, "\r\n\r\n");
if (bptr)
ptr = bptr+4;
}
}
ptr[BodyLen] = 0;
sprintf(Reply, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Disposition: attachment; filename=\"SavedMsg%05d.txt\" \r\n\r\n",
(int)(strlen(Hddr) + strlen(ptr)), Msg->number);
strcat(Reply, Hddr);
strcat(Reply, ptr);
*RLen = (int)strlen(Reply);
free(MailBuffer);
return;
}
if (_stricmp(NodeURL, "/Mail/SaveAttachment") == 0)
{
struct MsgInfo * Msg = Session->Msg;
char * MailBuffer;
int Files = 0, i;
int BodyLen;
char * ptr;
int WriteLen=0;
char FileName[100][MAX_PATH] = {""};
int FileLen[100];
char Noatt[] = "Message has no attachments";
MailBuffer = ReadMessageFile(Msg->number);
BodyLen = Msg->length;
if ((Msg->B2Flags & Attachments) == 0)
{
sprintf(Reply, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s",
(int)strlen(Noatt), Noatt);
*RLen = (int)strlen(Reply);
free(MailBuffer);
return;
}
ptr = MailBuffer;
while(ptr && *ptr != 13)
{
char * ptr2 = strchr(ptr, 10); // Find CR
if (memcmp(ptr, "Body: ", 6) == 0)
{
BodyLen = atoi(&ptr[6]);
}
if (memcmp(ptr, "File: ", 6) == 0)
{
char * ptr1 = strchr(&ptr[6], ' '); // Find Space
FileLen[Files] = atoi(&ptr[6]);
memcpy(FileName[Files++], &ptr1[1], (ptr2-ptr1 - 2));
}
ptr = ptr2;
ptr++;
}
ptr += 4; // Over Blank Line and Separator
ptr += BodyLen; // to first file
if (Files == 0)
{
sprintf(Reply, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s",
(int)strlen(Noatt), Noatt);
*RLen = (int)strlen(Reply);
free(MailBuffer);
return;
}
*RLen = 0;
// For now only handle first
i = 0;
// for (i = 0; i < Files; i++)
{
int Len = sprintf(&Reply[*RLen], "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Disposition: attachment; filename=\"%s\" \r\n\r\n",
FileLen[i], FileName[i]);
memcpy(&Reply[Len + *RLen], ptr, FileLen[i]);
*RLen += (Len + FileLen[i]);
ptr += FileLen[i];
ptr +=2; // Over separator - I don't think there should be one
}
free(MailBuffer);
return;
}
if (_stricmp(NodeURL, "/Mail/Msgs") == 0)
{
struct UserInfo * USER = NULL;
int PageLen;
if (MsgEditTemplate)
free(MsgEditTemplate);
MsgEditTemplate = GetTemplateFromFile(2, "MsgPage.txt");
// Refresh BBS No to BBS list
MaxBBS = 0;
for (USER = BBSChain; USER; USER = USER->BBSNext)
{
int n = USER->BBSNumber;
BBSLIST[n] = USER;
if (n > MaxBBS)
MaxBBS = n;
}
PageLen = 334 + (MaxBBS / 8) * 24;
if (MsgEditTemplate)
{
int len =sprintf(Reply, MsgEditTemplate, PageLen, PageLen, PageLen - 97, Key, Key, Key, Key, Key,
BBSName, Key, Key, Key, Key, Key, Key, Key, Key);
*RLen = len;
return;
}
}
if (_stricmp(NodeURL, "/Mail/EditM") == 0)
{
// Edit Message
char * MsgBytes;
MsgBytes = ReadMessageFile(Session->Msg->number);
// See if Multipart
// if (Msg->B2Flags & Attachments)
// EnableWindow(GetDlgItem(hDlg, IDC_SAVEATTACHMENTS), TRUE);
if (MsgBytes)
{
*RLen = sprintf(Reply, MsgEditPage, Key, MsgBytes);
free (MsgBytes);
}
else
*RLen = sprintf(Reply, MsgEditPage, Key, "Message Not Found");
return;
}
if (_stricmp(NodeURL, "/Mail/HK") == 0)
{
if (HousekeepingTemplate)
free(HousekeepingTemplate);
HousekeepingTemplate = GetTemplateFromFile(2, "Housekeeping.txt");
SendHouseKeeping(Reply, RLen, Key);
return;
}
if (_stricmp(NodeURL, "/Mail/WP") == 0)
{
if (WPTemplate)
free(WPTemplate);
WPTemplate = GetTemplateFromFile(1, "WP.txt");
if (WPTemplate)
{
int len =sprintf(Reply, WPTemplate, Key, Key, Key, Key,
BBSName, Key, Key, Key, Key, Key, Key, Key, Key);
*RLen = len;
return;
}
return;
}
if (_stricmp(NodeURL, "/Mail/WPInfo.txt") == 0)
{
int i = 0, n, len = 0;
WPRec * WP[10000];
// Get array of addresses
for (n = 1; n <= NumberofWPrecs; n++)
{
WP[i++] = WPRecPtr[n];
if (i > 9999) break;
}
qsort((void *)WP, i, sizeof(void *), compare);
for (i=0; i < NumberofWPrecs; i++)
{
len += sprintf(&Reply[len], "%s|", WP[i]->callsign);
}
*RLen = len;
return;
}
ReplyLen = sprintf(Reply, MailSignon, BBSName, BBSName);
*RLen = ReplyLen;
}
int SendWPDetails(WPRec * WP, char * Reply, char * Key)
{
int len = 0;
char D1[80], D2[80];
if (WP)
{
strcpy(D1, FormatDateAndTime(WP->last_modif, FALSE));
strcpy(D2, FormatDateAndTime(WP->last_seen, FALSE));
len = sprintf(Reply, WPDetail, Key, WP->callsign, WP->name,
WP->first_homebbs, WP->secnd_homebbs,
WP->first_qth, WP->secnd_qth,
WP->first_zip, WP->secnd_zip, D1, D2,
WP->Type,
WP->changed,
WP->seen);
}
return(len);
}
VOID SaveWP(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Key)
{
WPRec * WP = Session->WP;
char * input, * ptr1, * ptr2;
int n;
input = strstr(MsgPtr, "\r\n\r\n"); // End of headers
if (input)
{
if (strstr(input, "Cancel=Cancel"))
{
*RLen = SendHeader(Reply, Session->Key);
return;
}
if (strcmp(input + 4, "Delete") == 0)
{
for (n = 1; n <= NumberofWPrecs; n++)
{
if (Session->WP == WPRecPtr[n])
break;
}
if (n <= NumberofWPrecs)
{
WP = Session->WP;
for (n = n; n < NumberofWPrecs; n++)
{
WPRecPtr[n] = WPRecPtr[n+1]; // move down all following entries
}
NumberofWPrecs--;
free(WP);
SaveWPDatabase();
Session->WP = WPRecPtr[1];
}
*RLen = SendWPDetails(Session->WP, Reply, Session->Key);
return;
}
}
if (input && WP)
{
ptr1 = input + 4;
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0;if (strlen(ptr1) > 12) ptr1[12] = 0;strcpy(WP->name, ptr1);ptr1 = ptr2;}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0;if (strlen(ptr1) > 40) ptr1[40] = 0;strcpy(WP->first_homebbs, ptr1);ptr1 = ptr2;}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0;if (strlen(ptr1) > 40) ptr1[40] = 0;strcpy(WP->secnd_homebbs, ptr1);ptr1 = ptr2;}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0;if (strlen(ptr1) > 30) ptr1[30] = 0;strcpy(WP->first_qth, ptr1);ptr1 = ptr2;}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0;if (strlen(ptr1) > 30) ptr1[30] = 0;strcpy(WP->secnd_qth, ptr1);ptr1 = ptr2;}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0;if (strlen(ptr1) > 8) ptr1[8] = 0;strcpy(WP->first_zip, ptr1);ptr1 = ptr2;}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0;if (strlen(ptr1) > 8) ptr1[8] = 0;strcpy(WP->secnd_zip, ptr1);ptr1 = ptr2;}
// GetParam(input, "BBSCall=", BBSName);
/*
GetDlgItemText(hDlg, IDC_WPNAME, WP->name, 13);
GetDlgItemText(hDlg, IDC_HOMEBBS1, WP->first_homebbs, 41);
GetDlgItemText(hDlg, IDC_HOMEBBS2, WP->first_homebbs, 41);
GetDlgItemText(hDlg, IDC_QTH1, WP->first_qth, 31);
GetDlgItemText(hDlg, IDC_QTH2, WP->secnd_qth, 31);
GetDlgItemText(hDlg, IDC_ZIP1, WP->first_zip, 31);
GetDlgItemText(hDlg, IDC_ZIP2, WP->secnd_zip, 31);
WP->seen = GetDlgItemInt(hDlg, IDC_SEEN, &OK1, FALSE);
*/
WP->last_modif = time(NULL);
WP->Type = 'U';
WP->changed = 1;
SaveWPDatabase();
*RLen = SendWPDetails(WP, Reply, Key);
}
}
int SendMessageDetails(struct MsgInfo * Msg, char * Reply, char * Key)
{
int BBSNo = 1, x, y, len = 0;
char D1[80], D2[80], D3[80];
struct UserInfo * USER;
int i = 0, n;
struct UserInfo * bbs[NBBBS+2] = {0};
if (Msg)
{
char EmailFromLine[256] = "";
strcpy(D1, FormatDateAndTime((time_t)Msg->datecreated, FALSE));
strcpy(D2, FormatDateAndTime((time_t)Msg->datereceived, FALSE));
strcpy(D3, FormatDateAndTime((time_t)Msg->datechanged, FALSE));
// if (Msg->emailfrom[0])
sprintf(EmailFromLine, "Email From <input style=\"width:320px;\" name=EFROM value=%s><br>", Msg->emailfrom);
len = sprintf(Reply, MailDetailPage, Msg->number, Key,
Msg->from, D1,
(Msg->type == 'B')?sel:"",
(Msg->type == 'P')?sel:"",
(Msg->type == 'T')?sel:"",
Msg->to, D2,
(Msg->status == 'N')?sel:"",
(Msg->status == 'Y')?sel:"",
(Msg->status == 'F')?sel:"",
(Msg->status == 'K')?sel:"",
(Msg->status == 'H')?sel:"",
(Msg->status == 'D')?sel:"",
(Msg->status == '$')?sel:"",
Msg->bid, D3, Msg->length, EmailFromLine, Msg->via, Msg->title,
Key, Msg->number, Key, Key,
(Msg->B2Flags & Attachments)?"":"disabled");
// Get a sorted list of BBS records
for (n = 1; n <= NumberofUsers; n++)
{
USER = UserRecPtr[n];
2022-12-09 11:05:49 +00:00
if ((USER->flags & F_BBS))
if (USER->BBSNumber)
bbs[i++] = USER;
2022-08-28 09:35:46 +01:00
}
qsort((void *)bbs, i, sizeof(void *), compare );
n = 0;
for (y = 0; y < NBBBS/8; y++)
{
len += sprintf(&Reply[len],"<tr>");
for (x= 0; x < 8; x++)
{
char * Colour = NotThisOne;
if (bbs[n])
{
if (memcmp(Msg->fbbs, zeros, NBMASK) != 0)
if (check_fwd_bit(Msg->fbbs, bbs[n]->BBSNumber))
Colour = ToSend;
if (memcmp(Msg->forw, zeros, NBMASK) != 0)
if (check_fwd_bit(Msg->forw, bbs[n]->BBSNumber))
Colour = Sent;
len += sprintf(&Reply[len],"<td style=\"background-color: %s;\"onclick=ck(\"%d\")>%s</td>",
Colour, bbs[n]->BBSNumber, bbs[n]->Call);
}
else
len += sprintf(&Reply[len], "<td>&nbsp;</td>");
n++;
}
len += sprintf(&Reply[len],"</tr>");
if (n > i)
break;
}
len += sprintf(&Reply[len], "%s", MailDetailTail);
}
return(len);
}
char ** GetMultiStringInput(char * input, char * key)
{
char MultiString[16384] = "";
GetParam(input, key, MultiString);
if (MultiString[0] == 0)
return NULL;
return SeparateMultiString(MultiString, TRUE);
}
char ** SeparateMultiString(char * MultiString, BOOL NoToUpper)
{
char * ptr1 = MultiString;
char * ptr2 = NULL;
char * DecodedString;
char ** Value;
int Count = 0;
char c;
char * ptr;
ptr2 = zalloc(strlen(MultiString) + 1);
DecodedString = ptr2;
// Input has crlf or lf - replace with |
while (*ptr1)
{
c = *(ptr1++);
if (c == 13)
continue;
if (c == 10)
{
*ptr2++ = '|';
}
else
*(ptr2++) = c;
}
// Convert to string array
Value = zalloc(sizeof(void *)); // always NULL entry on end even if no values
Value[0] = NULL;
ptr = DecodedString;
while (ptr && strlen(ptr))
{
ptr1 = strchr(ptr, '|');
if (ptr1)
*(ptr1++) = 0;
if (strlen(ptr))
{
Value = realloc(Value, (Count+2) * sizeof(void *));
if (_memicmp(ptr, "file ", 5) == 0 || NoToUpper)
Value[Count++] = _strdup(ptr);
else
Value[Count++] = _strupr(_strdup(ptr));
}
ptr = ptr1;
}
Value[Count] = NULL;
return Value;
}
VOID GetMallocedParam(char * input, char * key, char ** value)
{
char Param[32768] = "";
GetParam(input, key, Param);
if (Param[0])
{
free(*value);
*value = _strdup(Param);
}
}
VOID GetParam(char * input, char * key, char * value)
{
char * ptr = strstr(input, key);
char Param[32768];
char * ptr1, * ptr2;
char c;
if (ptr)
{
ptr2 = strchr(ptr, '&');
if (ptr2) *ptr2 = 0;
strcpy(Param, ptr + strlen(key));
if (ptr2) *ptr2 = '&'; // Restore string
// Undo any % transparency
ptr1 = Param;
ptr2 = Param;
c = *(ptr1++);
while (c)
{
if (c == '%')
{
int n;
int m = *(ptr1++) - '0';
if (m > 9) m = m - 7;
n = *(ptr1++) - '0';
if (n > 9) n = n - 7;
*(ptr2++) = m * 16 + n;
}
else if (c == '+')
*(ptr2++) = ' ';
else
*(ptr2++) = c;
c = *(ptr1++);
}
*(ptr2++) = 0;
strcpy(value, Param);
}
}
VOID GetCheckBox(char * input, char * key, int * value)
{
char * ptr = strstr(input, key);
if (ptr)
*value = 1;
else
*value = 0;
}
VOID * GetOverrideFromString(char * input)
{
char * ptr1;
char * MultiString = NULL;
char * ptr = input;
int Count = 0;
struct Override ** Value;
char * Val;
Value = zalloc(sizeof(void *)); // always NULL entry on end even if no values
Value[0] = NULL;
while (ptr && strlen(ptr))
{
ptr1 = strchr(ptr, 13);
if (ptr1)
{
*(ptr1) = 0;
ptr1 += 2;
}
Value = realloc(Value, (Count+2) * sizeof(void *));
Value[Count] = zalloc(sizeof(struct Override));
Val = strlop(ptr, ',');
if (Val == NULL)
break;
Value[Count]->Call = _strupr(_strdup(ptr));
Value[Count++]->Days = atoi(Val);
ptr = ptr1;
}
Value[Count] = NULL;
return Value;
}
VOID SaveHousekeeping(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Key)
{
int ReplyLen = 0;
char * input;
char Temp[80];
struct tm *tm;
time_t now;
input = strstr(MsgPtr, "\r\n\r\n"); // End of headers
if (input)
{
if (strstr(input, "RunNow="))
{
DoHouseKeeping(FALSE);
SendHouseKeeping(Reply, RLen, Key);
return;
}
if (strstr(input, "Cancel=Cancel"))
{
SendHouseKeeping(Reply, RLen, Key);
return;
}
GetParam(input, "MTTime=", Temp);
MaintTime = atoi(Temp);
GetParam(input, "MTInt=", Temp);
MaintInterval = atoi(Temp);
GetParam(input, "MAXMSG=", Temp);
MaxMsgno = atoi(Temp);
GetParam(input, "BIDLife=", Temp);
BidLifetime= atoi(Temp);
GetParam(input, "MaxAge=", Temp);
MaxAge = atoi(Temp);
GetParam(input, "LogLife=", Temp);
LogAge = atoi(Temp);
GetParam(input, "UserLife=", Temp);
UserLifetime= atoi(Temp);
GetCheckBox(input, "Deltobin=", &DeletetoRecycleBin);
GetCheckBox(input, "SendND=", &SendNonDeliveryMsgs);
GetCheckBox(input, "NoMail=", &SuppressMaintEmail);
GetCheckBox(input, "GenTraffic=", &GenerateTrafficReport);
GetCheckBox(input, "OvUnsent=", &OverrideUnsent);
GetParam(input, "PR=", Temp);
PR = atof(Temp);
GetParam(input, "PUR=", Temp);
PUR = atof(Temp);
GetParam(input, "PF=", Temp);
PF = atof(Temp);
GetParam(input, "PUF=", Temp);
PNF = atof(Temp);
GetParam(input, "BF=", Temp);
BF = atoi(Temp);
GetParam(input, "BUF=", Temp);
BNF = atoi(Temp);
GetParam(input, "NTSD=", Temp);
NTSD = atoi(Temp);
GetParam(input, "NTSF=", Temp);
NTSF = atoi(Temp);
GetParam(input, "NTSU=", Temp);
NTSU = atoi(Temp);
GetParam(input, "From=", LTFROMString);
LTFROM = GetOverrideFromString(LTFROMString);
GetParam(input, "To=", LTTOString);
LTTO = GetOverrideFromString(LTTOString);
GetParam(input, "At=", LTATString);
LTAT = GetOverrideFromString(LTATString);
SaveConfig(ConfigName);
GetConfig(ConfigName);
// Calulate time to run Housekeeping
now = time(NULL);
tm = gmtime(&now);
tm->tm_hour = MaintTime / 100;
tm->tm_min = MaintTime % 100;
tm->tm_sec = 0;
// MaintClock = _mkgmtime(tm);
MaintClock = mktime(tm) - (time_t)_MYTIMEZONE;
while (MaintClock < now)
MaintClock += MaintInterval * 3600;
Debugprintf("Maint Clock %d NOW %d Time to HouseKeeping %d", MaintClock, now, MaintClock - now);
}
SendHouseKeeping(Reply, RLen, Key);
return;
}
VOID SaveWelcome(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Key)
{
int ReplyLen = 0;
char * input;
input = strstr(MsgPtr, "\r\n\r\n"); // End of headers
if (input)
{
if (strstr(input, "Cancel=Cancel"))
{
*RLen = SendHeader(Reply, Session->Key);
return;
}
GetMallocedParam(input, "NUWelcome=", &WelcomeMsg);
GetMallocedParam(input, "NewWelcome=", &NewWelcomeMsg);
GetMallocedParam(input, "ExWelcome=", &ExpertWelcomeMsg);
TidyWelcomeMsg(&WelcomeMsg);
TidyWelcomeMsg(&NewWelcomeMsg);
TidyWelcomeMsg(&ExpertWelcomeMsg);
GetMallocedParam(input, "NUPrompt=", &Prompt);
GetMallocedParam(input, "NewPrompt=", &NewPrompt);
GetMallocedParam(input, "ExPrompt=", &ExpertPrompt);
TidyPrompts();
GetParam(input, "Bye=", &SignoffMsg[0]);
if (SignoffMsg[0])
{
if (SignoffMsg[strlen(SignoffMsg) - 1] == 10)
SignoffMsg[strlen(SignoffMsg) - 1] = 0;
if (SignoffMsg[strlen(SignoffMsg) - 1] != 13)
strcat(SignoffMsg, "\r");
}
if (SignoffMsg[0] == 13)
SignoffMsg[0] = 0;
}
SendWelcomePage(Reply, RLen, Key);
return;
}
VOID ProcessConfUpdate(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Key)
{
int ReplyLen = 0;
char * input;
struct UserInfo * USER = NULL;
char Temp[80];
input = strstr(MsgPtr, "\r\n\r\n"); // End of headers
if (input)
{
if (strstr(input, "Cancel=Cancel"))
{
*RLen = SendHeader(Reply, Session->Key);
return;
}
if (strstr(input, "ConfigUI=Config+UI"))
{
SendUIPage(Reply, RLen, Key);
return;
}
GetParam(input, "BBSCall=", BBSName);
_strupr(BBSName);
strlop(BBSName, '-');
GetParam(input, "SYSOPCall=", SYSOPCall);
_strupr(SYSOPCall);
strlop(SYSOPCall, '-');
GetParam(input, "HRoute=", HRoute);
_strupr(HRoute);
GetParam(input, "ApplNum=", Temp);
BBSApplNum = atoi(Temp);
GetParam(input, "Streams=", Temp);
MaxStreams = atoi(Temp);
GetCheckBox(input, "SysToSYSOP=", &SendSYStoSYSOPCall);
GetCheckBox(input, "BBSToSYSOP=", &SendBBStoSYSOPCall);
GetCheckBox(input, "RefuseBulls=", &RefuseBulls);
GetCheckBox(input, "EnUI=", &EnableUI);
GetParam(input, "UIInterval=", Temp);
MailForInterval = atoi(Temp);
GetCheckBox(input, "DontHold=", &DontHoldNewUsers);
GetCheckBox(input, "DefaultNoWinlink=", &DefaultNoWINLINK);
GetCheckBox(input, "DontNeedName=", &AllowAnon);
GetCheckBox(input, "DontNeedHomeBBS=", &DontNeedHomeBBS);
GetCheckBox(input, "DontCheckFromCall=", &DontCheckFromCall);
GetCheckBox(input, "UserCantKillT=", &UserCantKillT);
UserCantKillT = !UserCantKillT; // Reverse Logic
GetCheckBox(input, "FWDtoMe=", &ForwardToMe);
GetCheckBox(input, "OnlyKnown=", &OnlyKnown);
2023-12-28 10:31:09 +00:00
GetCheckBox(input, "Events=", &reportMailEvents);
2022-08-28 09:35:46 +01:00
GetParam(input, "POP3Port=", Temp);
POP3InPort = atoi(Temp);
GetParam(input, "SMTPPort=", Temp);
SMTPInPort = atoi(Temp);
GetParam(input, "NNTPPort=", Temp);
NNTPInPort = atoi(Temp);
GetCheckBox(input, "EnRemote=", &RemoteEmail);
GetCheckBox(input, "EnISP=", &ISP_Gateway_Enabled);
GetCheckBox(input, "SendAMPR=", &SendAMPRDirect);
GetParam(input, "AMPRDomain=", AMPRDomain);
GetParam(input, "ISPDomain=", MyDomain);
GetParam(input, "SMTPServer=", ISPSMTPName);
GetParam(input, "ISPEHLOName=", ISPEHLOName);
GetParam(input, "ISPSMTPPort=", Temp);
ISPSMTPPort = atoi(Temp);
GetParam(input, "POP3Server=", ISPPOP3Name);
GetParam(input, "ISPPOP3Port=", Temp);
ISPPOP3Port = atoi(Temp);
GetParam(input, "ISPAccount=", ISPAccountName);
GetParam(input, "ISPPassword=", ISPAccountPass);
EncryptedPassLen = EncryptPass(ISPAccountPass, EncryptedISPAccountPass);
GetParam(input, "PollInterval=", Temp);
ISPPOP3Interval = atoi(Temp);
GetCheckBox(input, "ISPAuth=", &SMTPAuthNeeded);
GetCheckBox(input, "EnWP=", &SendWP);
GetCheckBox(input, "RejWFBulls=", &FilterWPBulls);
if (strstr(input, "Type=TypeB"))
SendWPType = 0;
if (strstr(input, "Type=TypeP"))
SendWPType = 1;
SendWPAddrs = GetMultiStringInput(input, "WPTO=");
RejFrom = GetMultiStringInput(input, "Rfrom=");
RejTo = GetMultiStringInput(input, "Rto=");
RejAt = GetMultiStringInput(input, "Rat=");
RejBID = GetMultiStringInput(input, "RBID=");
HoldFrom = GetMultiStringInput(input, "Hfrom=");
HoldTo = GetMultiStringInput(input, "Hto=");
HoldAt = GetMultiStringInput(input, "Hat=");
HoldBID = GetMultiStringInput(input, "HBID=");
2023-10-10 22:07:04 +01:00
// Look for fbb style filters
input = strstr(input, "&Action=");
// delete old list
while(Filters && Filters->Next)
{
FBBFilter * next = Filters->Next;
free(Filters);
Filters = next;
}
free(Filters);
Filters = NULL;
while (input)
{
// extract and validate before saving
FBBFilter Filter;
FBBFilter * PFilter;
memset(&Filter, 0, sizeof(FBBFilter));
Filter.Action = toupper(input[8]);
input = strstr(input, "&Type=");
if (Filter.Action == 'H' || Filter.Action == 'R')
{
Filter.Type = toupper(input[6]);
input = strstr(input, "&From=");
memcpy(Filter.From, &input[6], 10);
input = strstr(input, "&TO=");
strlop(Filter.From, '&');
_strupr(Filter.From);
memcpy(Filter.TO, &input[4], 10);
input = strstr(input, "&AT=");
strlop(Filter.TO, '&');
_strupr(Filter.TO);
memcpy(Filter.AT, &input[4], 10);
input = strstr(input, "&BID=");
strlop(Filter.AT, '&');
_strupr(Filter.AT);
memcpy(Filter.BID, &input[5], 10);
input = strstr(input, "&MaxLen=");
strlop(Filter.BID, '&');
_strupr(Filter.BID);
Filter.MaxLen = atoi(&input[8]);
if (Filter.Type == '&') Filter.Type = '*';
if (Filter.From[0] == 0) strcpy(Filter.From, "*");
if (Filter.TO[0] == 0) strcpy(Filter.TO, "*");
if (Filter.AT[0] == 0) strcpy(Filter.AT, "*");
if (Filter.BID[0] == 0) strcpy(Filter.BID, "*");
// add to list
PFilter = zalloc(sizeof(FBBFilter));
memcpy(PFilter, &Filter, sizeof(FBBFilter));
if (Filters == 0)
Filters = PFilter;
else
{
FBBFilter * p = Filters;
while (p->Next)
p = p->Next;
p->Next = PFilter;
}
}
input = strstr(input, "&Action=");
}
2022-08-28 09:35:46 +01:00
SaveConfig(ConfigName);
GetConfig(ConfigName);
}
SendConfigPage(Reply, RLen, Key);
return;
}
VOID ProcessUIUpdate(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Key)
{
int ReplyLen = 0, i;
char * input;
struct UserInfo * USER = NULL;
input = strstr(MsgPtr, "\r\n\r\n"); // End of headers
if (input)
{
if (strstr(input, "Cancel=Cancel"))
{
*RLen = SendHeader(Reply, Session->Key);
return;
}
GetParam(input, "MailFor=", &MailForText[0]);
for (i = 1; i <= GetNumberofPorts(); i++)
{
char EnKey[10];
char DigiKey[10];
char MFKey[12];
char HDDRKey[12];
char NullKey[12];
char Temp[100];
sprintf(EnKey, "En%d=", i);
sprintf(DigiKey, "Path%d=", i);
sprintf(MFKey, "SndMF%d=", i);
sprintf(HDDRKey, "SndHDDR%d=", i);
sprintf(NullKey, "SndNull%d=", i);
GetCheckBox(input, EnKey, &UIEnabled[i]);
GetParam(input, DigiKey, Temp);
if (UIDigi[i])
free (UIDigi[i]);
UIDigi[i] = _strdup(Temp);
GetCheckBox(input, MFKey, &UIMF[i]);
GetCheckBox(input, HDDRKey, &UIHDDR[i]);
GetCheckBox(input, NullKey, &UINull[i]);
}
SaveConfig(ConfigName);
GetConfig(ConfigName);
}
SendUIPage(Reply, RLen, Key);
return;
}
VOID ProcessDisUser(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest)
{
char * input;
char * ptr;
input = strstr(MsgPtr, "\r\n\r\n"); // End of headers
if (input)
{
ptr = strstr(input, "call=");
if (ptr)
{
int Stream = atoi(ptr + 5);
Disconnect(Stream);
}
}
SendStatusPage(Reply, RLen, Rest);
}
VOID SaveFwdCommon(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest)
{
int ReplyLen = 0;
char * input;
struct UserInfo * USER = NULL;
char Temp[80];
int Mask = 0;
input = strstr(MsgPtr, "\r\n\r\n"); // End of headers
if (input)
{
int n;
GetParam(input, "MaxTX=", Temp);
MaxTXSize = atoi(Temp);
GetParam(input, "MaxRX=", Temp);
MaxRXSize = atoi(Temp);
GetParam(input, "MaxAge=", Temp);
MaxAge = atoi(Temp);
GetCheckBox(input, "WarnNoRoute=", &WarnNoRoute);
GetCheckBox(input, "LocalTime=", &Localtime);
GetCheckBox(input, "SendPtoMultiple=", &SendPtoMultiple);
2024-07-07 16:06:08 +01:00
GetCheckBox(input, "FourCharCont=", &FOURCHARCONT);
2022-08-28 09:35:46 +01:00
// Reinitialise Aliases
n = 0;
if (Aliases)
{
while(Aliases[n])
{
free(Aliases[n]->Dest);
free(Aliases[n]);
n++;
}
free(Aliases);
Aliases = NULL;
FreeList(AliasText);
}
AliasText = GetMultiStringInput(input, "Aliases=");
if (AliasText)
{
n = 0;
while (AliasText[n])
{
_strupr(AliasText[n]);
n++;
}
}
SetupFwdAliases();
}
SaveConfig(ConfigName);
GetConfig(ConfigName);
SendFwdMainPage(Reply, RLen, Session->Key);
}
char * GetNextParam(char ** next)
{
char * ptr1 = *next;
char * ptr2 = strchr(ptr1, '|');
if (ptr2)
{
*(ptr2++) = 0;
*next = ptr2;
}
return ptr1;
}
VOID SaveFwdDetails(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest)
{
int ReplyLen = 0;
char * input;
struct UserInfo * USER = Session->User;
struct BBSForwardingInfo * FWDInfo = USER->ForwardingInfo;
char * ptr1, *ptr2;
input = strstr(MsgPtr, "\r\n\r\n"); // End of headers
if (input)
{
if (strstr(input, "StartForward"))
{
StartForwarding(USER->BBSNumber, NULL);
SendFwdDetails(Session->User, Reply, RLen, Session->Key);
return;
}
if (strstr(input, "CopyForward"))
{
struct UserInfo * OldBBS;
// Get call to copy from
ptr2 = input + 4;
ptr1 = GetNextParam(&ptr2); // Call
_strupr(ptr2);
OldBBS = FindBBS(ptr2);
if (OldBBS == NULL)
{
*RLen = sprintf(Reply, "<h3 align=center>Copy From BBS %s not found</h3>", ptr2);
return;
}
// Set current info from OldBBS
//
// SetForwardingPage(hDlg, OldBBS); // moved to separate routine as also called from copy config
SendFwdDetails(OldBBS, Reply, RLen, Session->Key);
return;
}
// Fwd update
ptr2 = input + 4;
ptr1 = GetNextParam(&ptr2); // TO
FWDInfo->TOCalls = SeparateMultiString(ptr1, FALSE);
ptr1 = GetNextParam(&ptr2); // AT
FWDInfo->ATCalls = SeparateMultiString(ptr1, FALSE);
ptr1 = GetNextParam(&ptr2); // TIMES
FWDInfo->FWDTimes = SeparateMultiString(ptr1, FALSE);
ptr1 = GetNextParam(&ptr2); // FWD SCRIPT
FWDInfo->ConnectScript = SeparateMultiString(ptr1, TRUE);
ptr1 = GetNextParam(&ptr2); // HRB
FWDInfo->Haddresses = SeparateMultiString(ptr1, FALSE);
ptr1 = GetNextParam(&ptr2); // HRP
FWDInfo->HaddressesP = SeparateMultiString(ptr1, FALSE);
ptr1 = GetNextParam(&ptr2); // BBSHA
if (FWDInfo->BBSHA)
free(FWDInfo->BBSHA);
FWDInfo->BBSHA = _strdup(_strupr(ptr1));
ptr1 = GetNextParam(&ptr2); // EnF
if (strcmp(ptr1, "true") == 0) FWDInfo->Enabled = TRUE; else FWDInfo->Enabled = FALSE;
ptr1 = GetNextParam(&ptr2); // Interval
FWDInfo->FwdInterval = atoi(ptr1);
ptr1 = GetNextParam(&ptr2); // EnR
if (strcmp(ptr1, "true") == 0) FWDInfo->ReverseFlag = TRUE; else FWDInfo->ReverseFlag = FALSE;
ptr1 = GetNextParam(&ptr2); // RInterval
FWDInfo->RevFwdInterval = atoi(ptr1);
ptr1 = GetNextParam(&ptr2); // No Wait
if (strcmp(ptr1, "true") == 0) FWDInfo->SendNew = TRUE; else FWDInfo->SendNew = FALSE;
ptr1 = GetNextParam(&ptr2); // Blocked
if (strcmp(ptr1, "true") == 0) FWDInfo->AllowBlocked = TRUE; else FWDInfo->AllowBlocked = FALSE;
ptr1 = GetNextParam(&ptr2); // FBB Block
FWDInfo->MaxFBBBlockSize = atoi(ptr1);
ptr1 = GetNextParam(&ptr2); // Personals
if (strcmp(ptr1, "true") == 0) FWDInfo->PersonalOnly = TRUE; else FWDInfo->PersonalOnly = FALSE;
ptr1 = GetNextParam(&ptr2); // Binary
if (strcmp(ptr1, "true") == 0) FWDInfo->AllowCompressed = TRUE; else FWDInfo->AllowCompressed = FALSE;
ptr1 = GetNextParam(&ptr2); // B1
if (strcmp(ptr1, "true") == 0) FWDInfo->AllowB1 = TRUE; else FWDInfo->AllowB1 = FALSE;
ptr1 = GetNextParam(&ptr2); // B2
if (strcmp(ptr1, "true") == 0) FWDInfo->AllowB2 = TRUE; else FWDInfo->AllowB2 = FALSE;
ptr1 = GetNextParam(&ptr2); // CTRLZ
if (strcmp(ptr1, "true") == 0) FWDInfo->SendCTRLZ = TRUE; else FWDInfo->SendCTRLZ = FALSE;
ptr1 = GetNextParam(&ptr2); // Connect Timeout
FWDInfo->ConTimeout = atoi(ptr1);
SaveConfig(ConfigName);
GetConfig(ConfigName);
ReinitializeFWDStruct(Session->User);
SendFwdDetails(Session->User, Reply, RLen, Session->Key);
}
}
VOID ProcessUserUpdate(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest)
{
int ReplyLen = 0;
char * input;
struct UserInfo * USER = Session->User;
int SSID, Mask = 0;
char * ptr1, *ptr2;
int skipRMSExUser = 0;
input = strstr(MsgPtr, "\r\n\r\n"); // End of headers
if (input)
{
if (strstr(input, "Cancel"))
{
*RLen = SendHeader(Reply, Session->Key);
return;
}
if (strstr(input, "Delete"))
{
int n;
for (n = 1; n <= NumberofUsers; n++)
{
if (Session->User == UserRecPtr[n])
break;
}
if (n <= NumberofUsers)
{
USER = Session->User;
for (n = n; n < NumberofUsers; n++)
{
UserRecPtr[n] = UserRecPtr[n+1]; // move down all following entries
}
NumberofUsers--;
if (USER->flags & F_BBS) // was a BBS?
DeleteBBS(USER);
free(USER);
SaveUserDatabase();
Session->User = UserRecPtr[1];
SendUserSelectPage(Reply, RLen, Session->Key);
return;
}
}
if (strstr(input, "Add="))
{
char * Call;
Call = input + 8;
strlop(Call, '-');
if (strlen(Call) > 6)
Call[6] = 0;
_strupr(Call);
if (Call[0] == 0 || LookupCall(Call))
{
// Null or exists
SendUserSelectPage(Reply, RLen, Session->Key);
return;
}
USER = AllocateUserRecord(Call);
USER->Temp = zalloc(sizeof (struct TempUserInfo));
SendUserSelectPage(Reply, RLen, Session->Key);
return;
}
// User update
ptr2 = input + 4;
ptr1 = GetNextParam(&ptr2); // BBS
// If BBS Flag has changed, must set up or delete forwarding info
if (strcmp(ptr1, "true") == 0)
{
if ((USER->flags & F_BBS) == 0)
{
// New BBS
if(SetupNewBBS(USER))
{
USER->flags |= F_BBS;
USER->flags &= ~F_Temp_B2_BBS; // Clear RMS Express User
skipRMSExUser = 1; // Dont read old value
}
else
{
// Failed - too many bbs's defined
//sprintf(InfoBoxText, "Cannot set user to be a BBS - you already have 80 BBS's defined");
//DialogBox(hInst, MAKEINTRESOURCE(IDD_USERADDED_BOX), hWnd, InfoDialogProc);
USER->flags &= ~F_BBS;
//CheckDlgButton(hDlg, IDC_BBSFLAG, (user->flags & F_BBS));
}
}
}
else
{
if (USER->flags & F_BBS)
{
//was a BBS
USER->flags &= ~F_BBS;
DeleteBBS(USER);
}
}
ptr1 = GetNextParam(&ptr2); // Permit Email
if (strcmp(ptr1, "true") == 0) USER->flags |= F_EMAIL; else USER->flags &= ~F_EMAIL;
ptr1 = GetNextParam(&ptr2); // PMS
if (strcmp(ptr1, "true") == 0) USER->flags |= F_PMS; else USER->flags &= ~F_PMS;
ptr1 = GetNextParam(&ptr2); // RMS EX User
if (strcmp(ptr1, "true") == 0 && !skipRMSExUser) USER->flags |= F_Temp_B2_BBS; else USER->flags &= ~F_Temp_B2_BBS;
ptr1 = GetNextParam(&ptr2); // SYSOP
if (strcmp(ptr1, "true") == 0) USER->flags |= F_SYSOP; else USER->flags &= ~F_SYSOP;
ptr1 = GetNextParam(&ptr2); // PollRMS
if (strcmp(ptr1, "true") == 0) USER->flags |= F_POLLRMS; else USER->flags &= ~F_POLLRMS;
ptr1 = GetNextParam(&ptr2); // Expert
if (strcmp(ptr1, "true") == 0) USER->flags |= F_Expert; else USER->flags &= ~F_Expert;
ptr1 = GetNextParam(&ptr2); // SSID1
SSID = atoi(ptr1);
Mask |= (1 << SSID);
ptr1 = GetNextParam(&ptr2); // SSID2
SSID = atoi(ptr1);
Mask |= (1 << SSID);
ptr1 = GetNextParam(&ptr2); // SSID3
SSID = atoi(ptr1);
Mask |= (1 << SSID);
ptr1 = GetNextParam(&ptr2); // SSID4
SSID = atoi(ptr1);
Mask |= (1 << SSID);
Session->User->RMSSSIDBits = Mask;
ptr1 = GetNextParam(&ptr2); // Excluded
if (strcmp(ptr1, "true") == 0) USER->flags |= F_Excluded; else USER->flags &= ~F_Excluded;
ptr1 = GetNextParam(&ptr2); // Hold
if (strcmp(ptr1, "true") == 0) USER->flags |= F_HOLDMAIL; else USER->flags &= ~F_HOLDMAIL;
ptr1 = GetNextParam(&ptr2); // SYSOP gets LM
if (strcmp(ptr1, "true") == 0) USER->flags |= F_SYSOP_IN_LM; else USER->flags &= ~F_SYSOP_IN_LM;
ptr1 = GetNextParam(&ptr2); // Dont add winlink.org
if (strcmp(ptr1, "true") == 0) USER->flags |= F_NOWINLINK; else USER->flags &= ~F_NOWINLINK;
ptr1 = GetNextParam(&ptr2); // Allow Bulls
if (strcmp(ptr1, "true") == 0) USER->flags &= ~F_NOBULLS; else USER->flags |= F_NOBULLS; // Inverted flag
ptr1 = GetNextParam(&ptr2); // NTS Message Pickup Station
if (strcmp(ptr1, "true") == 0) USER->flags |= F_NTSMPS; else USER->flags &= ~F_NTSMPS;
ptr1 = GetNextParam(&ptr2); // APRS Mail For
if (strcmp(ptr1, "true") == 0) USER->flags |= F_RMSREDIRECT; else USER->flags &= ~F_RMSREDIRECT;
ptr1 = GetNextParam(&ptr2); // Redirect to RMS
if (strcmp(ptr1, "true") == 0) USER->flags |= F_APRSMFOR; else USER->flags &= ~F_APRSMFOR;
ptr1 = GetNextParam(&ptr2); // APRS SSID
SSID = atoi(ptr1);
SSID &= 15;
USER->flags &= 0x0fffffff;
USER->flags |= (SSID << 28);
ptr1 = GetNextParam(&ptr2); // Last Listed
USER->lastmsg = atoi(ptr1);
ptr1 = GetNextParam(&ptr2); // Name
strcpy(USER->Name, ptr1);
ptr1 = GetNextParam(&ptr2); // Pass
strcpy(USER->pass, ptr1);
ptr1 = GetNextParam(&ptr2); // CMS Pass
if (memcmp("****************", ptr1, strlen(ptr1) != 0))
{
strcpy(USER->CMSPass, ptr1);
}
ptr1 = GetNextParam(&ptr2); // QTH
strcpy(USER->Address, ptr1);
ptr1 = GetNextParam(&ptr2); // ZIP
strcpy(USER->ZIP, ptr1);
ptr1 = GetNextParam(&ptr2); // HomeBBS
strcpy(USER->HomeBBS, ptr1);
_strupr(USER->HomeBBS);
SaveUserDatabase();
UpdateWPWithUserInfo(USER);
*RLen = SendUserDetails(Session, Reply, Session->Key);
}
}
VOID ProcessMsgAction(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest)
{
int ReplyLen = 0;
char * input;
int BBSNumber = 0;
struct MsgInfo * Msg = Session->Msg;
char * ptr1;
input = strstr(MsgPtr, "\r\n\r\n"); // End of headers
if (input && Msg)
{
ptr1 = input + 4;
*RLen = SendMessageDetails(Msg, Reply, Session->Key);
}
}
VOID SaveMessageText(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest)
{
int ReplyLen = 0;
struct MsgInfo * Msg = Session->Msg;
char * ptr, * ptr1, * ptr2, *input;
char c;
int MsgLen, WriteLen;
char MsgFile[256];
FILE * hFile;
input = strstr(MsgPtr, "\r\n\r\n"); // End of headers
if (input)
{
if (strstr(input, "Cancel=Cancel"))
{
*RLen = sprintf(Reply, "%s", "<html><script>window.close();</script></html>");
return;
}
ptr = strstr(input, "&Save=");
if (ptr)
{
*ptr = 0;
// Undo any % transparency
ptr1 = ptr2 = input + 8;
c = *(ptr1++);
while (c)
{
if (c == '%')
{
int n;
int m = *(ptr1++) - '0';
if (m > 9) m = m - 7;
n = *(ptr1++) - '0';
if (n > 9) n = n - 7;
*(ptr2++) = m * 16 + n;
}
else if (c == '+')
*(ptr2++) = ' ';
else
*(ptr2++) = c;
c = *(ptr1++);
}
*(ptr2++) = 0;
MsgLen = (int)strlen(input + 8);
Msg->datechanged = time(NULL);
Msg->length = MsgLen;
sprintf_s(MsgFile, sizeof(MsgFile), "%s/m_%06d.mes", MailDir, Msg->number);
hFile = fopen(MsgFile, "wb");
if (hFile)
{
WriteLen = (int)fwrite(input + 8, 1, Msg->length, hFile);
fclose(hFile);
}
if (WriteLen != Msg->length)
{
char Mess[80];
sprintf_s(Mess, sizeof(Mess), "Failed to create Message File\r");
CriticalErrorHandler(Mess);
return;
}
SaveMessageDatabase();
*RLen = sprintf(Reply, "%s", "<html><script>alert(\"Message Saved\");window.close();</script></html>");
}
}
return;
}
VOID ProcessMsgUpdate(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest)
{
int ReplyLen = 0;
char * input;
int BBSNumber = 0;
struct MsgInfo * Msg = Session->Msg;
char * ptr1, * ptr2;
char OldStatus = Msg->status;
input = strstr(MsgPtr, "\r\n\r\n"); // End of headers
if (input && Msg)
{
ptr1 = input + 4;
ptr2 = strchr(ptr1, '|');
if (ptr2)
{
*(ptr2++) = 0;
strcpy(Msg->from, ptr1);
ptr1 = ptr2;
}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0;strcpy(Msg->to, ptr1);ptr1 = ptr2;}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0;strcpy(Msg->bid, ptr1);ptr1 = ptr2;}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0;strcpy(Msg->emailfrom, ptr1);ptr1 = ptr2;}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0;strcpy(Msg->via, ptr1);ptr1 = ptr2;}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0;strcpy(Msg->title, ptr1);ptr1 = ptr2;}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0;Msg->type = *ptr1;ptr1 = ptr2;}
ptr2 = strchr(ptr1, '|');if (ptr2){*(ptr2++) = 0;Msg->status = *ptr1;ptr1 = ptr2;}
if (Msg->status != OldStatus)
{
// Need to take action if killing message
if (Msg->status == 'K')
FlagAsKilled(Msg, FALSE); // Clear forwarding bits
}
Msg->datechanged = time(NULL);
SaveMessageDatabase();
}
*RLen = SendMessageDetails(Msg, Reply, Session->Key);
}
VOID ProcessMsgFwdUpdate(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Reply, int * RLen, char * Rest)
{
int ReplyLen = 0;
char * input;
int BBSNumber = 0;
struct UserInfo * User;
struct MsgInfo * Msg = Session->Msg;
BOOL toforward, forwarded;
input = strstr(MsgPtr, "\r\n\r\n"); // End of headers
if (input && Msg)
{
BBSNumber = atoi(input + 4);
User = BBSLIST[BBSNumber];
if (User == NULL)
return;
toforward = check_fwd_bit(Msg->fbbs, BBSNumber);
forwarded = check_fwd_bit(Msg->forw, BBSNumber);
if (forwarded)
{
// Changing to not this BBS
clear_fwd_bit(Msg->forw, BBSNumber);
}
else if (toforward)
{
// Change to Forwarded
clear_fwd_bit(Msg->fbbs, BBSNumber);
User->ForwardingInfo->MsgCount--;
set_fwd_bit(Msg->forw, BBSNumber);
}
else
{
// Change to to forward
set_fwd_bit(Msg->fbbs, BBSNumber);
User->ForwardingInfo->MsgCount++;
clear_fwd_bit(Msg->forw, BBSNumber);
if (FirstMessageIndextoForward > Msg->number)
FirstMessageIndextoForward = Msg->number;
}
*RLen = SendMessageDetails(Msg, Reply, Session->Key);
}
SaveMessageDatabase();
}
VOID SetMultiStringValue(char ** values, char * Multi)
{
char ** Calls;
char * ptr = &Multi[0];
*ptr = 0;
if (values)
{
Calls = values;
while(Calls[0])
{
strcpy(ptr, Calls[0]);
ptr += strlen(Calls[0]);
*(ptr++) = '\r';
*(ptr++) = '\n';
Calls++;
}
*(ptr) = 0;
}
}
VOID SendFwdDetails(struct UserInfo * User, char * Reply, int * ReplyLen, char * Key)
{
int Len;
struct BBSForwardingInfo * FWDInfo = User->ForwardingInfo;
char TO[2048] = "";
char AT[2048] = "";
char TIMES[2048] = "";
char FWD[100000] = "";
char HRB[2048] = "";
char HRP[2048] = "";
SetMultiStringValue(FWDInfo->TOCalls, TO);
SetMultiStringValue(FWDInfo->ATCalls, AT);
SetMultiStringValue(FWDInfo->FWDTimes, TIMES);
SetMultiStringValue(FWDInfo->ConnectScript, FWD);
SetMultiStringValue(FWDInfo->Haddresses, HRB);
SetMultiStringValue(FWDInfo->HaddressesP, HRP);
if (FwdDetailTemplate == NULL)
FwdDetailTemplate = GetTemplateFromFile(3, "FwdDetail.txt");
Len = sprintf(Reply, FwdDetailTemplate, User->Call,
CountMessagestoForward (User), Key,
TO, AT, TIMES , FWD, HRB, HRP,
(FWDInfo->BBSHA) ? FWDInfo->BBSHA : "",
(FWDInfo->Enabled) ? CHKD : UNC,
FWDInfo->FwdInterval,
(FWDInfo->ReverseFlag) ? CHKD : UNC,
FWDInfo->RevFwdInterval,
(FWDInfo->SendNew) ? CHKD : UNC,
(FWDInfo->AllowBlocked) ? CHKD : UNC,
FWDInfo->MaxFBBBlockSize,
(FWDInfo->PersonalOnly) ? CHKD : UNC,
(FWDInfo->AllowCompressed) ? CHKD : UNC,
(FWDInfo->AllowB1) ? CHKD : UNC,
(FWDInfo->AllowB2) ? CHKD : UNC,
(FWDInfo->SendCTRLZ) ? CHKD : UNC,
FWDInfo->ConTimeout);
*ReplyLen = Len;
}
VOID SendConfigPage(char * Reply, int * ReplyLen, char * Key)
{
2023-10-10 22:07:04 +01:00
int Len, i;
2022-08-28 09:35:46 +01:00
char HF[2048] = "";
char HT[2048] = "";
char HA[2048] = "";
char HB[2048] = "";
char RF[2048] = "";
char RT[2048] = "";
char RA[2048] = "";
char RB[2048] = "";
char WPTO[10000] = "";
2023-10-10 22:07:04 +01:00
char FBBFilters[100000] = "";
char * ptr = FBBFilters;
FBBFilter * Filter = Filters;
2022-08-28 09:35:46 +01:00
SetMultiStringValue(RejFrom, RF);
SetMultiStringValue(RejTo, RT);
SetMultiStringValue(RejAt, RA);
SetMultiStringValue(RejBID, RB);
SetMultiStringValue(HoldFrom, HF);
SetMultiStringValue(HoldTo, HT);
SetMultiStringValue(HoldAt, HA);
SetMultiStringValue(HoldBID, HB);
SetMultiStringValue(SendWPAddrs, WPTO);
2023-10-10 22:07:04 +01:00
// set up FB style fiters
2022-08-28 09:35:46 +01:00
2023-10-10 22:07:04 +01:00
ptr += sprintf(ptr,
"<table><tr><th>Action</th><th>Type</th><th>From</th><th>To</th><th>@BBS</th><th>Bid</th><th>Max Size</th></tr>");
while(Filter)
{
ptr += sprintf(ptr, "<tr>"
"<td><input type=text name=Action style=\"text-transform: uppercase\"maxlength=2 size=2 value=%c></td>"
"<td><input type=text name=Type style=\"text-transform: uppercase\"maxlength=2 size=2 value=%c></td>"
"<td><input type=text name=From style=\"text-transform: uppercase\" maxlength=7 size=7 value=%s></td>"
"<td><input type=text name=TO style=\"text-transform: uppercase\" maxlength=7 size=7 value=%s></td>"
"<td><input type=text name=AT style=\"text-transform: uppercase\" maxlength=7 size=7 value=%s></td>"
"<td><input type=text name=BID style=\"text-transform: uppercase\" maxlength=13 size=13 value=%s></td>"
"<td><input type=text name=MaxLen maxlength=6 size=6 value=%d></td></tr>",
Filter->Action, Filter->Type, Filter->From, Filter->TO, Filter->AT, Filter->BID, Filter->MaxLen);
Filter = Filter->Next;
}
// Add a few blank entries for input
for (i = 0; i < 5; i++)
{
ptr += sprintf(ptr, "<tr>"
"<td><input type=text name=Action style=\"text-transform: uppercase\"maxlength=2 size=2 value=%c></td>"
"<td><input type=text name=Type style=\"text-transform: uppercase\"maxlength=2 size=2 value=%c></td>"
"<td><input type=text name=From style=\"text-transform: uppercase\" maxlength=7 size=7 value=%s></td>"
"<td><input type=text name=TO style=\"text-transform: uppercase\" maxlength=7 size=7 value=%s></td>"
"<td><input type=text name=AT style=\"text-transform: uppercase\" maxlength=7 size=7 value=%s></td>"
"<td><input type=text name=BID style=\"text-transform: uppercase\" maxlength=13 size=13 value=%s></td>"
"<td><input type=text name=MaxLen maxlength=6 size=6 value=%d></td></tr>", ' ', ' ', "", "", "", "", 0);
}
ptr += sprintf(ptr, "</table>");
Debugprintf("%d", strlen(FBBFilters));
2022-08-28 09:35:46 +01:00
Len = sprintf(Reply, ConfigTemplate,
BBSName, Key, Key, Key, Key, Key, Key, Key, Key, Key,
BBSName, SYSOPCall, HRoute,
(SendBBStoSYSOPCall) ? CHKD : UNC,
BBSApplNum, MaxStreams,
(SendSYStoSYSOPCall) ? CHKD : UNC,
(RefuseBulls) ? CHKD : UNC,
(EnableUI) ? CHKD : UNC,
MailForInterval,
(DontHoldNewUsers) ? CHKD : UNC,
(DefaultNoWINLINK) ? CHKD : UNC,
(AllowAnon) ? CHKD : UNC,
(DontNeedHomeBBS) ? CHKD : UNC,
(DontCheckFromCall) ? CHKD : UNC,
(UserCantKillT) ? UNC : CHKD, // Reverse logic
(ForwardToMe) ? CHKD : UNC,
(OnlyKnown) ? CHKD : UNC,
2023-12-28 10:31:09 +00:00
(reportMailEvents) ? CHKD : UNC,
2022-08-28 09:35:46 +01:00
POP3InPort, SMTPInPort, NNTPInPort,
(RemoteEmail) ? CHKD : UNC,
AMPRDomain,
(SendAMPRDirect) ? CHKD : UNC,
(ISP_Gateway_Enabled) ? CHKD : UNC,
MyDomain, ISPSMTPName, ISPSMTPPort, ISPEHLOName, ISPPOP3Name, ISPPOP3Port,
ISPAccountName, ISPAccountPass, ISPPOP3Interval,
(SMTPAuthNeeded) ? CHKD : UNC,
(SendWP) ? CHKD : UNC,
(FilterWPBulls) ? CHKD : UNC,
(SendWPType == 0) ? CHKD : UNC,
(SendWPType == 1) ? CHKD : UNC,
WPTO,
2023-10-10 22:07:04 +01:00
RF, RT, RA, RB, HF, HT, HA, HB, FBBFilters);
2022-08-28 09:35:46 +01:00
*ReplyLen = Len;
}
VOID SendHouseKeeping(char * Reply, int * ReplyLen, char * Key)
{
char FromList[1000]= "", ToList[1000]= "", AtList[1000] = "";
char Line[80];
struct Override ** Call;
if (LTFROM)
{
Call = LTFROM;
while(Call[0])
{
sprintf(Line, "%s, %d\r\n", Call[0]->Call, Call[0]->Days);
strcat(FromList, Line);
Call++;
}
}
if (LTTO)
{
Call = LTTO;
while(Call[0])
{
sprintf(Line, "%s, %d\r\n", Call[0]->Call, Call[0]->Days);
strcat(ToList, Line);
Call++;
}
}
if (LTAT)
{
Call = LTAT;
while(Call[0])
{
sprintf(Line, "%s, %d\r\n", Call[0]->Call, Call[0]->Days);
strcat(AtList, Line);
Call++;
}
}
*ReplyLen = sprintf(Reply, HousekeepingTemplate,
BBSName, Key, Key, Key, Key, Key, Key, Key, Key, Key,
MaintTime, MaintInterval, MaxMsgno, BidLifetime, LogAge, UserLifetime,
(DeletetoRecycleBin) ? CHKD : UNC,
(SendNonDeliveryMsgs) ? CHKD : UNC,
(SuppressMaintEmail) ? CHKD : UNC,
(GenerateTrafficReport) ? CHKD : UNC,
PR, PUR, PF, PNF, BF, BNF, NTSD, NTSF, NTSU,
FromList, ToList, AtList,
(OverrideUnsent) ? CHKD : UNC);
return;
}
VOID SendWelcomePage(char * Reply, int * ReplyLen, char * Key)
{
int Len;
Len = SendHeader(Reply, Key);
Len += sprintf(&Reply[Len], Welcome, Key, WelcomeMsg, NewWelcomeMsg, ExpertWelcomeMsg,
Prompt, NewPrompt, ExpertPrompt, SignoffMsg);
*ReplyLen = Len;
}
VOID SendFwdMainPage(char * Reply, int * RLen, char * Key)
{
char ALIASES[16384];
SetMultiStringValue(AliasText, ALIASES);
*RLen = sprintf(Reply, FwdTemplate, Key, Key, BBSName,
Key, Key, Key, Key, Key, Key, Key, Key,
Key, MaxTXSize, MaxRXSize, MaxAge,
(WarnNoRoute) ? CHKD : UNC,
(Localtime) ? CHKD : UNC,
(SendPtoMultiple) ? CHKD : UNC,
2024-07-07 16:06:08 +01:00
(FOURCHARCONT) ? CHKD : UNC,
2022-08-28 09:35:46 +01:00
ALIASES);
}
char TenSpaces[] = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
VOID SendUIPage(char * Reply, int * ReplyLen, char * Key)
{
int Len, i;
Len = SendHeader(Reply, Key);
Len += sprintf(&Reply[Len], UIHddr, Key, MailForText);
for (i = 1; i <= GetNumberofPorts(); i++)
{
char PortNo[512];
char PortDesc[31];
int n;
// Only allow UI on ax.25 ports
struct _EXTPORTDATA * PORTVEC;
PORTVEC = (struct _EXTPORTDATA * )GetPortTableEntryFromSlot(i);
if (PORTVEC->PORTCONTROL.PORTTYPE == 16) // EXTERNAL
if (PORTVEC->PORTCONTROL.PROTOCOL == 10) // Pactor/WINMOR
if (PORTVEC->PORTCONTROL.UICAPABLE == 0)
continue;
GetPortDescription(i, PortDesc);
n = sprintf(PortNo, "Port&nbsp;%2d %s", GetPortNumber(i), PortDesc);
while (PortNo[--n] == ' ');
PortNo[n + 1] = 0;
while (n++ < 38)
strcat(PortNo, "&nbsp;");
Len += sprintf(&Reply[Len], UILine,
(UIEnabled[i])?CHKD:UNC, i,
PortNo,
(UIDigi[i])?UIDigi[i]:"", i,
(UIMF[i])?CHKD:UNC, i,
(UIHDDR[i])?CHKD:UNC, i,
(UINull[i])?CHKD:UNC, i);
}
Len += sprintf(&Reply[Len], UITail, Key);
*ReplyLen = Len;
}
VOID SendStatusPage(char * Reply, int * ReplyLen, char * Key)
{
int Len;
char msg[1024];
CIRCUIT * conn;
int i,n, SYSOPMsgs = 0, HeldMsgs = 0;
char Name[80];
SMTPMsgs = 0;
Len = sprintf(Reply, RefreshMainPage, BBSName, BBSName, Key, Key, Key, Key, Key, Key, Key, Key);
Len += sprintf(&Reply[Len], StatusPage, Key);
for (n = 0; n < NumberofStreams; n++)
{
conn=&Connections[n];
if (!conn->Active)
{
strcpy(msg,"Idle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n");
}
else
{
{
if (conn->UserPointer == 0)
strcpy(msg,"Logging in\r\n");
else
{
strcpy(Name, conn->UserPointer->Name);
Name[9] = 0;
i=sprintf_s(msg, sizeof(msg), "%s%s%s%s%2d&nbsp;%5d\r\n",
Name,
&TenSpaces[strlen(Name) * 6],
conn->UserPointer->Call,
&TenSpaces[strlen(conn->UserPointer->Call) * 6],
conn->BPQStream,
conn->OutputQueueLength - conn->OutputGetPointer);
}
}
}
Len += sprintf(&Reply[Len], StatusLine, conn->BPQStream, msg);
}
n = 0;
for (i=1; i <= NumberofMessages; i++)
{
if (MsgHddrPtr[i]->status == 'N')
{
if (_stricmp(MsgHddrPtr[i]->to, SYSOPCall) == 0 || _stricmp(MsgHddrPtr[i]->to, "SYSOP") == 0)
SYSOPMsgs++;
else
if (MsgHddrPtr[i]->to[0] == 0)
SMTPMsgs++;
}
else
{
if (MsgHddrPtr[i]->status == 'H')
HeldMsgs++;
}
}
Len += sprintf(&Reply[Len], StreamEnd,
NumberofMessages, SYSOPMsgs, HeldMsgs, SMTPMsgs);
// If there are any active multicast transfers, display them.
Len += MulticastStatusHTML(&Reply[Len]);
Len += sprintf(&Reply[Len], StatusTail,
NumberofMessages, SYSOPMsgs, HeldMsgs, SMTPMsgs);
*ReplyLen = Len;
}
VOID SendFwdSelectPage(char * Reply, int * ReplyLen, char * Key)
{
struct UserInfo * USER;
int i = 0;
int Len = 0;
for (USER = BBSChain; USER; USER = USER->BBSNext)
{
Len += sprintf(&Reply[Len], "%s|", USER->Call);
}
*ReplyLen = Len;
}
VOID SendUserSelectPage(char * Reply, int * ReplyLen, char * Key)
{
struct UserInfo * USER;
int i = 0, n;
int Len = 0;
struct UserInfo * users[10000];
// Get array of addresses
for (n = 1; n <= NumberofUsers; n++)
{
users[i++] = UserRecPtr[n];
if (i > 9999) break;
}
qsort((void *)users, i, sizeof(void *), compare );
for (n = 0; n < NumberofUsers; n++)
{
USER = users[n];
Len += sprintf(&Reply[Len], "%s|", USER->Call);
}
*ReplyLen = Len;
}
int SendUserDetails(struct HTTPConnectionInfo * Session, char * Reply, char * Key)
{
char SSID[16][16] = {""};
char ASSID[16];
int i, n, s, Len;
struct UserInfo * User = Session->User;
unsigned int flags = User->flags;
int RMSSSIDBits = Session->User->RMSSSIDBits;
char HiddenPass[20] = "";
int ConnectsIn;
int ConnectsOut;
int MsgsReceived;
int MsgsSent;
int MsgsRejectedIn;
int MsgsRejectedOut;
int BytesForwardedIn;
int BytesForwardedOut;
// char MsgsIn[80];
// char MsgsOut[80];
// char BytesIn[80];
// char BytesOut[80];
// char RejIn[80];
// char RejOut[80];
i = 0;
ConnectsIn = User->Total.ConnectsIn - User->Last.ConnectsIn;
ConnectsOut = User->Total.ConnectsOut - User->Last.ConnectsOut;
MsgsReceived = MsgsSent = MsgsRejectedIn = MsgsRejectedOut = BytesForwardedIn = BytesForwardedOut = 0;
for (n = 0; n < 4; n++)
{
MsgsReceived += User->Total.MsgsReceived[n] - User->Last.MsgsReceived[n];
MsgsSent += User->Total.MsgsSent[n] - User->Last.MsgsSent[n];
BytesForwardedIn += User->Total.BytesForwardedIn[n] - User->Last.BytesForwardedIn[n];
BytesForwardedOut += User->Total.BytesForwardedOut[n] - User->Last.BytesForwardedOut[n];
MsgsRejectedIn += User->Total.MsgsRejectedIn[n] - User->Last.MsgsRejectedIn[n];
MsgsRejectedOut += User->Total.MsgsRejectedOut[n] - User->Last.MsgsRejectedOut[n];
}
for (s = 0; s < 16; s++)
{
if (RMSSSIDBits & (1 << s))
{
if (s)
sprintf(&SSID[i++][0], "%d", s);
else
SSID[i++][0] = 0;
}
}
memset(HiddenPass, '*', strlen(User->CMSPass));
i = (flags >> 28);
sprintf(ASSID, "%d", i);
if (i == 0)
ASSID[0] = 0;
if (!UserDetailTemplate)
UserDetailTemplate = GetTemplateFromFile(4, "UserDetail.txt");
Len = sprintf(Reply, UserDetailTemplate, Key, User->Call,
(flags & F_BBS)?CHKD:UNC,
(flags & F_EMAIL)?CHKD:UNC,
(flags & F_PMS)?CHKD:UNC,
(flags & F_Temp_B2_BBS)?CHKD:UNC,
(flags & F_SYSOP)?CHKD:UNC,
(flags & F_POLLRMS)?CHKD:UNC,
(flags & F_Expert)?CHKD:UNC,
SSID[0], SSID[1], SSID[2], SSID[3],
(flags & F_Excluded)?CHKD:UNC,
(flags & F_HOLDMAIL)?CHKD:UNC,
(flags & F_SYSOP_IN_LM)?CHKD:UNC,
(flags & F_NOWINLINK)?CHKD:UNC,
(flags & F_NOBULLS)?UNC:CHKD, // Inverted flag
(flags & F_NTSMPS)?CHKD:UNC,
(flags & F_RMSREDIRECT)?CHKD:UNC,
(flags & F_APRSMFOR)?CHKD:UNC, ASSID,
ConnectsIn, MsgsReceived, MsgsRejectedIn,
ConnectsOut, MsgsSent, MsgsRejectedOut,
BytesForwardedIn, FormatDateAndTime((time_t)User->TimeLastConnected, FALSE),
BytesForwardedOut, User->lastmsg,
User->Name,
User->pass,
HiddenPass,
User->Address,
User->ZIP,
User->HomeBBS);
return Len;
}
#ifdef WIN32
2022-11-12 15:00:02 +00:00
int ProcessWebmailWebSock(char * MsgPtr, char * OutBuffer);
2022-08-28 09:35:46 +01:00
static char PipeFileName[] = "\\\\.\\pipe\\BPQMailWebPipe";
2024-11-05 21:03:15 +00:00
// Constants
2022-08-28 09:35:46 +01:00
static DWORD WINAPI InstanceThread(LPVOID lpvParam)
// This routine is a thread processing function to read from and reply to a client
// via the open pipe connection passed from the main loop. Note this allows
// the main loop to continue executing, potentially creating more threads of
// of this procedure to run concurrently, depending on the number of incoming
// client connections.
{
2022-11-12 15:00:02 +00:00
DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0;
BOOL fSuccess = FALSE;
HANDLE hPipe = NULL;
char Buffer[250000];
char OutBuffer[250000];
char * MsgPtr;
int InputLen = 0;
int OutputLen = 0;
2022-08-28 09:35:46 +01:00
struct HTTPConnectionInfo Session;
char URL[100001];
char * Context, * Method;
int n;
2024-11-05 21:03:15 +00:00
char token[16]= "";
2022-08-28 09:35:46 +01:00
char * ptr;
2022-11-12 15:00:02 +00:00
// The thread's parameter is a handle to a pipe object instance.
2022-08-28 09:35:46 +01:00
2022-11-12 15:00:02 +00:00
hPipe = (HANDLE) lpvParam;
2022-08-28 09:35:46 +01:00
2022-11-12 15:00:02 +00:00
// First block is the HTTPConnectionInfo record, rest is request
n = ReadFile(hPipe, &Session, sizeof (struct HTTPConnectionInfo), &n, NULL);
// Get the data
fSuccess = ReadFile(hPipe, Buffer, 250000, &InputLen, NULL);
2022-08-28 09:35:46 +01:00
if (!fSuccess || InputLen == 0)
{
if (GetLastError() == ERROR_BROKEN_PIPE)
Debugprintf("InstanceThread: client disconnected.", GetLastError());
else
Debugprintf("InstanceThread ReadFile failed, GLE=%d.", GetLastError());
2022-11-12 15:00:02 +00:00
return 1;
2022-08-28 09:35:46 +01:00
}
2022-11-12 15:00:02 +00:00
Buffer[InputLen] = 0;
2022-08-28 09:35:46 +01:00
2022-11-12 15:00:02 +00:00
MsgPtr = &Buffer[0];
if (memcmp(MsgPtr, "WMRefresh", 9) == 0)
{
OutputLen = ProcessWebmailWebSock(MsgPtr, OutBuffer);
}
else
{
2024-11-05 21:03:15 +00:00
// look for auth header
const char * auth_header = "Authorization: Bearer ";
char * token_begin = strstr(MsgPtr, auth_header);
int Flags = 0, n;
2022-08-28 09:35:46 +01:00
2024-11-05 21:03:15 +00:00
// Node Flags isn't currently used
2022-08-28 09:35:46 +01:00
2024-11-05 21:03:15 +00:00
char * Tok;
char * param;
2022-08-28 09:35:46 +01:00
2024-11-05 21:03:15 +00:00
if (token_begin)
{
// Using Auth Header
// Extract the token from the request (assuming it's present in the request headers)
2022-08-28 09:35:46 +01:00
2024-11-05 21:03:15 +00:00
token_begin += strlen(auth_header); // Move to the beginning of the token
strncpy(token, token_begin, 13);
token[13] = '\0'; // Null-terminate the token
}
2022-11-12 15:00:02 +00:00
}
2022-08-28 09:35:46 +01:00
2024-11-05 21:03:15 +00:00
strcpy(URL, MsgPtr);
ptr = strstr(URL, " HTTP");
if (ptr)
*ptr = 0;
Method = strtok_s(URL, " ", &Context);
ProcessMailHTTPMessage(&Session, Method, Context, MsgPtr, OutBuffer, &OutputLen, InputLen, token);
2022-11-12 15:00:02 +00:00
WriteFile(hPipe, &Session, sizeof (struct HTTPConnectionInfo), &n, NULL);
WriteFile(hPipe, OutBuffer, OutputLen, &cbWritten, NULL);
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
2022-08-28 09:35:46 +01:00
return 1;
}
static DWORD WINAPI PipeThreadProc(LPVOID lpvParam)
{
BOOL fConnected = FALSE;
DWORD dwThreadId = 0;
HANDLE hPipe = INVALID_HANDLE_VALUE, hThread = NULL;
// The main loop creates an instance of the named pipe and
// then waits for a client to connect to it. When the client
// connects, a thread is created to handle communications
// with that client, and this loop is free to wait for the
// next client connect request. It is an infinite loop.
for (;;)
{
hPipe = CreateNamedPipe(
PipeFileName, // pipe name
PIPE_ACCESS_DUPLEX, // read/write access
PIPE_TYPE_BYTE | // message type pipe
PIPE_WAIT, // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
4096, // output buffer size
4096, // input buffer size
0, // client time-out
NULL); // default security attribute
if (hPipe == INVALID_HANDLE_VALUE)
{
Debugprintf("CreateNamedPipe failed, GLE=%d.\n", GetLastError());
return -1;
}
// Wait for the client to connect; if it succeeds,
// the function returns a nonzero value. If the function
// returns zero, GetLastError returns ERROR_PIPE_CONNECTED.
fConnected = ConnectNamedPipe(hPipe, NULL) ?
TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
if (fConnected)
{
// Create a thread for this client.
hThread = CreateThread(
NULL, // no security attribute
0, // default stack size
InstanceThread, // thread proc
(LPVOID) hPipe, // thread parameter
0, // not suspended
&dwThreadId); // returns thread ID
if (hThread == NULL)
{
Debugprintf("CreateThread failed, GLE=%d.\n", GetLastError());
return -1;
}
else CloseHandle(hThread);
}
else
// The client could not connect, so close the pipe.
CloseHandle(hPipe);
}
return 0;
}
BOOL CreatePipeThread()
{
DWORD ThreadId;
CreateThread(NULL, 0, PipeThreadProc, 0, 0, &ThreadId);
return TRUE;
}
#endif
char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
char *dat[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
VOID FormatTime(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);
}