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 Callsign 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 <input readonly=readonly value=%d size=3><br>"
|
|
|
|
"Sysop Msgs <input readonly=readonly value=%d size=3><br>"
|
|
|
|
"Held Msgs <input readonly=readonly value=%d size=3><br>"
|
|
|
|
"SMTP Msgs <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>"
|
|
|
|
" "
|
|
|
|
" (use \\r to insert newline in message)<br><br>"
|
|
|
|
"Enable Port "
|
|
|
|
" Path "
|
|
|
|
" 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>"
|
|
|
|
" <input %sname=SndHDDR%d type=checkbox>"
|
|
|
|
" <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 <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 "
|
|
|
|
"<input %sname=LocalTime type=checkbox><br><br>"
|
|
|
|
"Aliases Select BBS<br>"
|
|
|
|
"<textarea rows=10 cols=20 name=Aliases>%s</textarea>  <select tabindex=1 size=10 name=call>";
|
|
|
|
|
|
|
|
char FWDSelectTail[] =
|
|
|
|
"</select><br> <input name=Save value=Save type=submit class='btn'> <input "
|
|
|
|
"name=Cancel value=Cancel type=submit class='btn'> "
|
|
|
|
" <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> "
|
|
|
|
"TO "
|
|
|
|
"AT "
|
|
|
|
"TIMES 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 <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> "
|
|
|
|
"Allow Binary <input %sname=Bin type=checkbox> Use B1 "
|
|
|
|
"Protocol <input %sname=B1 type=checkbox> 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 <input style=\"font-family: monospace;\" size=10 name=From value=%s> Sent "
|
|
|
|
" <input readonly=readonly size=12 name=Sent value=\"%s\"> "
|
|
|
|
"Type <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 <input style=\"font-family: monospace;\" size=10 name=To value=%s>"
|
|
|
|
" Received <input readonly=readonly size=12 name=RX value=\"%s\"> "
|
|
|
|
"Status <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 <input style=\"width:100px; font-family: monospace; \" name=BID value=\"%s\"> Last Changed <input readonly=readonly size=12 name=LastChange value=\"%s\"> "
|
|
|
|
"Size <input readonly=readonly size=5 name=Size value=%d><br><br>"
|
|
|
|
"%s" // Email from Line
|
|
|
|
" VIA <input style=\"width:360px;\" name=VIA value=%s><br>"
|
|
|
|
"Title <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 $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> "
|
|
|
|
"<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> </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[] = " ";
|
|
|
|
|
|
|
|
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 %2d %s", GetPortNumber(i), PortDesc);
|
|
|
|
|
|
|
|
while (PortNo[--n] == ' ');
|
|
|
|
|
|
|
|
PortNo[n + 1] = 0;
|
|
|
|
|
|
|
|
while (n++ < 38)
|
|
|
|
strcat(PortNo, " ");
|
|
|
|
|
|
|
|
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 "
|
|
|
|
" "
|
|
|
|
" \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 %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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|