From 1fbded9d3afd766e861577ba08d0f86f952de64e Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Sat, 16 Dec 2023 14:40:33 +0000 Subject: [PATCH 1/7] Tested final release for new layout --- debian/changelog | 4 ++-- debian/conffiles | 1 - debian/install | 2 +- debian/linbpq.links | 1 - debian/linbpq.service | 2 +- debian/patches/makefile | 4 ++-- debian/postinst | 2 +- debian/preinst | 2 +- 8 files changed, 8 insertions(+), 10 deletions(-) delete mode 100644 debian/conffiles delete mode 100644 debian/linbpq.links diff --git a/debian/changelog b/debian/changelog index 019b549..c144a78 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,8 @@ -linbpq (6.0.24.22-2) UNRELEASED; urgency=medium +linbpq (6.0.24.22-2) unstable; urgency=medium * Moved config file home, caused chaos - -- Dave Hibberd Sat, 16 Dec 2023 13:30:06 +0000 + -- Dave Hibberd Sat, 16 Dec 2023 14:40:20 +0000 linbpq (6.0.24.22-1) unstable; urgency=medium diff --git a/debian/conffiles b/debian/conffiles deleted file mode 100644 index 9667d53..0000000 --- a/debian/conffiles +++ /dev/null @@ -1 +0,0 @@ -/opt/oarc/bpq/bpq32.cfg diff --git a/debian/install b/debian/install index fb787b0..3367546 100644 --- a/debian/install +++ b/debian/install @@ -1 +1 @@ -debian/templates/bpq32.cfg etc/bpq32.cfg +debian/templates/bpq32.cfg etc/ diff --git a/debian/linbpq.links b/debian/linbpq.links deleted file mode 100644 index 9f1a328..0000000 --- a/debian/linbpq.links +++ /dev/null @@ -1 +0,0 @@ -/opt/oarc/bpq/bpq32.cfg /etc/bpq32.cfg diff --git a/debian/linbpq.service b/debian/linbpq.service index 3b46a5d..598393c 100644 --- a/debian/linbpq.service +++ b/debian/linbpq.service @@ -2,7 +2,7 @@ After=network.target [Service] -ExecStart=/usr/sbin/linbpq -c /etc -d /opt/oarc/linbpq -l /opt/oarc/linbpq/logs +ExecStart=/usr/sbin/linbpq -c /etc -d /opt/oarc/bpq -l /opt/oarc/bpq WorkingDirectory=/opt/oarc/bpq Restart=always User=linbpq diff --git a/debian/patches/makefile b/debian/patches/makefile index 2132816..d2888a9 100644 --- a/debian/patches/makefile +++ b/debian/patches/makefile @@ -8,8 +8,8 @@ +# setcap "CAP_NET_ADMIN=ep CAP_NET_RAW=ep CAP_NET_BIND_SERVICE=ep" linbpq + +install: -+ install -b -m 755 -D -d debian/usr/sbin -+ install -b -m 755 -s -p linbpq debian/usr/sbin ++ install -b -m 755 -D -d debian/linbpq/usr/sbin ++ install -b -m 755 -s -p linbpq debian/linbpq/usr/sbin -include *.d diff --git a/debian/postinst b/debian/postinst index 4289690..70eac96 100644 --- a/debian/postinst +++ b/debian/postinst @@ -26,7 +26,7 @@ if [ "$1" = configure ]; then # which allows us to install our binaries without the setuid # bit. if command -v setcap > /dev/null; then - setcap "CAP_NET_ADMIN=ep CAP_NET_RAW=ep CAP_NET_BIND_SERVICE=ep" /opt/oarc/bpq/linbpq + setcap "CAP_NET_ADMIN=ep CAP_NET_RAW=ep CAP_NET_BIND_SERVICE=ep" /usr/sbin/linbpq else echo "Setcap failed on /usr/sbin/linbpq, Features may be limited" >&2 fi diff --git a/debian/preinst b/debian/preinst index 8ba52dd..4dae0eb 100644 --- a/debian/preinst +++ b/debian/preinst @@ -8,5 +8,5 @@ node="/opt/oarc/bpq/bpq32.cfg" if [ -L $confile ]; then rm $confile cp $node $confile - rm $node + mv $node $node.bak fi From 7a61c594e1bf9fd62e156d3d8db772fe7c4bfd03 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Thu, 28 Dec 2023 10:31:09 +0000 Subject: [PATCH 2/7] New upstream version 6.0.24.25 --- BBSHTMLConfig.c | 12 + BBSUtilities.c | 118 +- BPQMail.c | 5 +- BPQMail.vcproj | 4 + BPQMail.vcproj.DESKTOP-TGEL8RC.John.user | 65 + BPQWinAPP.vcproj.DESKTOP-TGEL8RC.John.user | 65 + BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 + Bpq32.c | 9 +- CBPQ32.vcproj | 4 + ...vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user | 65 + CBPQ32.vcproj.DESKTOP-TGEL8RC.John.user | 65 + ...cproj.LAPTOP-Q6S4RP5Q.johnw-notpi4-64.user | 65 + CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 + CHeaders.h | 2 +- ChatHTMLConfig.c | 7 +- CommonCode.c | 6 +- FormatHTML.cpp | 118 +- FormatHTML.vcproj | 438 +-- HTTPcode.c | 66 +- HanksRT.c | 24 +- MBLRoutines.c | 4 + MailNode.vcproj | 8 + MailNode.vcproj.DESKTOP-TGEL8RC.John.user | 65 + RigControl.c | 11 +- TelnetV6.c | 33 +- Versions.h | 6 +- WebMail.c | 92 +- ...vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user | 65 + WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user | 65 + ...orControl.vcproj.DESKTOP-TGEL8RC.John.user | 65 + ...rControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 + bbshtmlconfig.c~ | 3161 +++++++++++++++++ mailapi.c | 196 + makefile | 2 +- nodeapi.c | 633 ++++ telnetserver.h | 3 +- templatedefs.c | 12 +- tncinfo.h | 3 + 38 files changed, 5370 insertions(+), 387 deletions(-) create mode 100644 BPQMail.vcproj.DESKTOP-TGEL8RC.John.user create mode 100644 BPQWinAPP.vcproj.DESKTOP-TGEL8RC.John.user create mode 100644 BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user create mode 100644 CBPQ32.vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user create mode 100644 CBPQ32.vcproj.DESKTOP-TGEL8RC.John.user create mode 100644 CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw-notpi4-64.user create mode 100644 CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user create mode 100644 MailNode.vcproj.DESKTOP-TGEL8RC.John.user create mode 100644 WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user create mode 100644 WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user create mode 100644 WinmorControl.vcproj.DESKTOP-TGEL8RC.John.user create mode 100644 WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user create mode 100644 bbshtmlconfig.c~ create mode 100644 mailapi.c create mode 100644 nodeapi.c diff --git a/BBSHTMLConfig.c b/BBSHTMLConfig.c index 01b05bd..80f2bca 100644 --- a/BBSHTMLConfig.c +++ b/BBSHTMLConfig.c @@ -38,6 +38,7 @@ extern char LTATString[2048]; //static UCHAR BPQDirectory[260]; extern ConnectionInfo Connections[]; + extern int NumberofStreams; extern time_t MaintClock; // Time to run housekeeping @@ -49,6 +50,7 @@ extern int MaxChatStreams; extern char Position[81]; extern char PopupText[251]; extern int PopupMode; +extern int reportMailEvents; #define MaxCMS 10 // Numbr of addresses we can keep - currently 4 are used. @@ -114,6 +116,7 @@ int SendWebMailHeader(char * Reply, char * Key, struct HTTPConnectionInfo * Sess struct UserInfo * FindBBS(char * Name); void ReleaseWebMailStruct(WebMailInfo * WebMail); VOID TidyWelcomeMsg(char ** pPrompt); +int MailAPIProcessHTTPMessage(char * response, char * Method, char * URL, char * request, BOOL LOCAL, char * Param); char UNC[] = ""; char CHKD[] = "checked=checked "; @@ -488,6 +491,13 @@ void ProcessMailHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, GotFirstMessage = 1; return; } + + if (_memicmp(URL, "/Mail/API/", 10) == 0) + { + *RLen = MailAPIProcessHTTPMessage(Reply, Method, URL, input, LOCAL, Context); + return; + } + if (strcmp(Method, "POST") == 0) { @@ -1633,6 +1643,7 @@ VOID ProcessConfUpdate(struct HTTPConnectionInfo * Session, char * MsgPtr, char UserCantKillT = !UserCantKillT; // Reverse Logic GetCheckBox(input, "FWDtoMe=", &ForwardToMe); GetCheckBox(input, "OnlyKnown=", &OnlyKnown); + GetCheckBox(input, "Events=", &reportMailEvents); GetParam(input, "POP3Port=", Temp); POP3InPort = atoi(Temp); @@ -2610,6 +2621,7 @@ VOID SendConfigPage(char * Reply, int * ReplyLen, char * Key) (UserCantKillT) ? UNC : CHKD, // Reverse logic (ForwardToMe) ? CHKD : UNC, (OnlyKnown) ? CHKD : UNC, + (reportMailEvents) ? CHKD : UNC, POP3InPort, SMTPInPort, NNTPInPort, (RemoteEmail) ? CHKD : UNC, AMPRDomain, diff --git a/BBSUtilities.c b/BBSUtilities.c index 1d3c1f2..48f927a 100644 --- a/BBSUtilities.c +++ b/BBSUtilities.c @@ -43,7 +43,7 @@ RECT ConsoleRect; BOOL OpenConsole; BOOL OpenMon; -int reportNewMesageEvents = 0; +int reportMailEvents = 0; FBBFilter * Filters = NULL; @@ -124,6 +124,8 @@ void decodeblock( unsigned char in[4], unsigned char out[3]); int encode_quoted_printable(char *s, char * out, int Len); int32_t Encode(char * in, char * out, int32_t inlen, BOOL B1Protocol, int Compress); int APIENTRY ChangeSessionCallsign(int Stream, unsigned char * AXCall); +void SendMessageReadEvent(char * user, struct MsgInfo * Msg); +void SendNewMessageEvent(char * call, struct MsgInfo * Msg); config_t cfg; config_setting_t * group; @@ -4904,6 +4906,7 @@ sendEOM: Msg->status = 'Y'; Msg->datechanged=time(NULL); SaveMessageDatabase(); + SendMessageReadEvent(user->Call, Msg); } } } @@ -6457,30 +6460,9 @@ nextline: // If Event Notifications enabled report a new message event - if (reportNewMesageEvents) - { - char msg[200]; - - //12345 B 2053 TEST@ALL F6FBB 920325 This is the subject - - struct tm *tm = gmtime((time_t *)&Msg->datecreated); - - sprintf_s(msg, sizeof(msg),"%-6d %c %6d %-13s %-6s %02d%02d%02d %s\r", - Msg->number, Msg->type, Msg->length, Msg->to, - Msg->from, tm->tm_year-100, tm->tm_mon+1, tm->tm_mday, Msg->title); - -#ifdef WIN32 - if (pRunEventProgram) - pRunEventProgram("MailNewMsg.exe", msg); -#else - { - char prog[256]; - sprintf(prog, "%s/%s", BPQDirectory, "MailNewMsg"); - RunEventProgram(prog, msg); - } -#endif - } + user = LookupCall(Msg->to); + SendNewMessageEvent(user->Call, Msg); if (EnableUI) #ifdef LINBPQ @@ -6493,8 +6475,6 @@ nextline: My__except_Routine("SendMsgUI"); #endif - user = LookupCall(Msg->to); - if (user && (user->flags & F_APRSMFOR)) { char APRS[128]; @@ -9576,6 +9556,7 @@ VOID SaveConfig(char * ConfigName) SaveIntValue(group, "EnableUI", EnableUI); SaveIntValue(group, "RefuseBulls", RefuseBulls); SaveIntValue(group, "OnlyKnown", OnlyKnown); + SaveIntValue(group, "reportMailEvents", reportMailEvents); SaveIntValue(group, "SendSYStoSYSOPCall", SendSYStoSYSOPCall); SaveIntValue(group, "SendBBStoSYSOPCall", SendBBStoSYSOPCall); SaveIntValue(group, "DontHoldNewUsers", DontHoldNewUsers); @@ -10098,28 +10079,30 @@ BOOL GetConfig(char * ConfigName) config_destroy(&cfg); return(EXIT_FAILURE); } - +/* #if LIBCONFIG_VER_MINOR > 5 config_set_option(&cfg, CONFIG_OPTION_AUTOCONVERT, 1); #else config_set_auto_convert (&cfg, 1); #endif - +*/ group = config_lookup (&cfg, "main"); if (group == NULL) return EXIT_FAILURE; - SMTPInPort = GetIntValue(group, "SMTPPort"); - POP3InPort = GetIntValue(group, "POP3Port"); - NNTPInPort = GetIntValue(group, "NNTPPort"); - RemoteEmail = GetIntValue(group, "RemoteEmail"); - MaxStreams = GetIntValue(group, "Streams"); - BBSApplNum = GetIntValue(group, "BBSApplNum"); - EnableUI = GetIntValue(group, "EnableUI"); - MailForInterval = GetIntValue(group, "MailForInterval"); - RefuseBulls = GetIntValue(group, "RefuseBulls"); - OnlyKnown = GetIntValue(group, "OnlyKnown"); + SMTPInPort = GetIntValue(group, "SMTPPort"); + POP3InPort = GetIntValue(group, "POP3Port"); + NNTPInPort = GetIntValue(group, "NNTPPort"); + RemoteEmail = GetIntValue(group, "RemoteEmail"); + MaxStreams = GetIntValue(group, "Streams"); + BBSApplNum = GetIntValue(group, "BBSApplNum"); + EnableUI = GetIntValue(group, "EnableUI"); + MailForInterval = GetIntValue(group, "MailForInterval"); + RefuseBulls = GetIntValue(group, "RefuseBulls"); + OnlyKnown = GetIntValue(group, "OnlyKnown"); + reportMailEvents = GetIntValue(group, "reportMailEvents"); + SendSYStoSYSOPCall = GetIntValue(group, "SendSYStoSYSOPCall"); SendBBStoSYSOPCall = GetIntValue(group, "SendBBStoSYSOPCall"); DontHoldNewUsers = GetIntValue(group, "DontHoldNewUsers"); @@ -15793,3 +15776,62 @@ VOID GetPGConfig() NUM_SERVERS = n; fclose(file); } + +void SendMessageReadEvent(char * call, struct MsgInfo * Msg) +{ + if (reportMailEvents) + { + char msg[512]; + + //12345 B 2053 TEST@ALL F6FBB 920325 This is the subject + + struct tm *tm = gmtime((time_t *)&Msg->datecreated); + + sprintf_s(msg, sizeof(msg),"%-6d %c %c %6d %-13s %-6s %02d%02d%02d %s\r", + Msg->number, Msg->type, Msg->status, Msg->length, Msg->to, + Msg->from, tm->tm_year-100, tm->tm_mon+1, tm->tm_mday, Msg->title); + +// sprintf(msg, "%s Read %d\r", user->Call, Msg->number); + +#ifdef WIN32 + if (pRunEventProgram) + pRunEventProgram("MailMsgRead.exe", msg); +#else + { + char prog[256]; + sprintf(prog, "%s/%s", BPQDirectory, "MailMsgRead"); + RunEventProgram(prog, msg); + } +#endif + } +} + +void SendNewMessageEvent(char * call, struct MsgInfo * Msg) +{ + if (reportMailEvents) + { + char msg[512]; + + //12345 B 2053 TEST@ALL F6FBB 920325 This is the subject + + struct tm *tm = gmtime((time_t *)&Msg->datecreated); + + sprintf_s(msg, sizeof(msg),"%-6d %c %c %6d %-13s %-6s %02d%02d%02d %s\r", + Msg->number, Msg->type, Msg->status, Msg->length, Msg->to, + Msg->from, tm->tm_year-100, tm->tm_mon+1, tm->tm_mday, Msg->title); + +#ifdef WIN32 + if (pRunEventProgram) + pRunEventProgram("MailNewMsg.exe", msg); +#else + { + char prog[256]; + sprintf(prog, "%s/%s", BPQDirectory, "MailNewMsg"); + RunEventProgram(prog, msg); + } +#endif + } +} + + + diff --git a/BPQMail.c b/BPQMail.c index bd37641..a4015b1 100644 --- a/BPQMail.c +++ b/BPQMail.c @@ -1123,8 +1123,9 @@ // Add FBB reject.sys style filters (3) // Improve Webmail on 64 bit builds // Fix setting status '$' on Bulls sent via WebMail (22) - - +// Implement New Message and Message Read Events (23) +// Start adding json api (25) +// Fix reading nested directories when loading Standard Templates and other template bugs (25) #include "bpqmail.h" #include "winstdint.h" diff --git a/BPQMail.vcproj b/BPQMail.vcproj index 3c7ef20..81a5df9 100644 --- a/BPQMail.vcproj +++ b/BPQMail.vcproj @@ -316,6 +316,10 @@ RelativePath="..\CommonSource\LzmaLib.c" > + + diff --git a/BPQMail.vcproj.DESKTOP-TGEL8RC.John.user b/BPQMail.vcproj.DESKTOP-TGEL8RC.John.user new file mode 100644 index 0000000..40182c4 --- /dev/null +++ b/BPQMail.vcproj.DESKTOP-TGEL8RC.John.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/BPQWinAPP.vcproj.DESKTOP-TGEL8RC.John.user b/BPQWinAPP.vcproj.DESKTOP-TGEL8RC.John.user new file mode 100644 index 0000000..40182c4 --- /dev/null +++ b/BPQWinAPP.vcproj.DESKTOP-TGEL8RC.John.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user new file mode 100644 index 0000000..0cd9a72 --- /dev/null +++ b/BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/Bpq32.c b/Bpq32.c index f2c5451..e5868dd 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1203,6 +1203,9 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // Improve restart of WinRPR TNC on remote host (21) // Fix some Rigcontrol issues with empty timebands (22) // Fix 64 bit bug in processing INP3 Messages (22) +// First pass at api (24) +// Send OK in response to Rigcontrol CMD (24); + #define CKernel @@ -2065,7 +2068,7 @@ VOID TimerProcX() GetWindowRect(FrameWnd, &FRect); - SaveWindowPos(64); // Rigcontrol + SaveWindowPos(70); // Rigcontrol for (i=0;iPORTCONTROL.PORTPOINTER; } - SaveWindowPos(40); // Rigcontrol + SaveWindowPos(70); // Rigcontrol if (hIPResWnd) diff --git a/CBPQ32.vcproj b/CBPQ32.vcproj index c1c95a2..0648ae6 100644 --- a/CBPQ32.vcproj +++ b/CBPQ32.vcproj @@ -438,6 +438,10 @@ RelativePath="..\CommonSource\MULTIPSK.c" > + + diff --git a/CBPQ32.vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user b/CBPQ32.vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user new file mode 100644 index 0000000..40b9267 --- /dev/null +++ b/CBPQ32.vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/CBPQ32.vcproj.DESKTOP-TGEL8RC.John.user b/CBPQ32.vcproj.DESKTOP-TGEL8RC.John.user new file mode 100644 index 0000000..40b9267 --- /dev/null +++ b/CBPQ32.vcproj.DESKTOP-TGEL8RC.John.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw-notpi4-64.user b/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw-notpi4-64.user new file mode 100644 index 0000000..ddedde2 --- /dev/null +++ b/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw-notpi4-64.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user new file mode 100644 index 0000000..ddedde2 --- /dev/null +++ b/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/CHeaders.h b/CHeaders.h index 0d6886e..caf288b 100644 --- a/CHeaders.h +++ b/CHeaders.h @@ -406,7 +406,7 @@ extern BOOL CloseAllNeeded; extern int CloseOnError; extern char * PortConfig[70]; -extern struct TNCINFO * TNCInfo[70]; // Records are Malloc'd +extern struct TNCINFO * TNCInfo[71]; // Records are Malloc'd #define MaxBPQPortNo 63 // Port 64 reserved for BBS Mon #define MAXBPQPORTS 63 diff --git a/ChatHTMLConfig.c b/ChatHTMLConfig.c index b4d90b6..c4071cf 100644 --- a/ChatHTMLConfig.c +++ b/ChatHTMLConfig.c @@ -67,6 +67,7 @@ extern int MaxChatStreams; extern char Position[81]; extern char PopupText[251]; extern int PopupMode; +extern int reportChatEvents; #include "httpconnectioninfo.h" @@ -323,6 +324,8 @@ VOID SaveChatInfo(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Rep if (chatPaclen < 60) chatPaclen = 60; + GetCheckBox(input, "Events=", &reportChatEvents); + GetParam(input, "nodes=", Nodes); ptr1 = Nodes; @@ -508,7 +511,9 @@ scan: Len = sprintf(Reply, ChatConfigTemplate, OurNode, Key, Key, Key, - ChatApplNum, MaxChatStreams, Nodes, chatPaclen, Position, + ChatApplNum, MaxChatStreams, + (reportChatEvents) ? CHKD : UNC, + Nodes, chatPaclen, Position, (PopupMode) ? UNC : CHKD, (PopupMode) ? CHKD : UNC, Text, ptr2); diff --git a/CommonCode.c b/CommonCode.c index d28cefa..31e4ebc 100644 --- a/CommonCode.c +++ b/CommonCode.c @@ -49,7 +49,7 @@ extern struct CONFIGTABLE xxcfg; #endif -struct TNCINFO * TNCInfo[70]; // Records are Malloc'd +struct TNCINFO * TNCInfo[71]; // Records are Malloc'd extern int ReportTimer; @@ -3516,8 +3516,6 @@ int __sync_lock_test_and_set(int * ptr, int val) #endif // __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ #endif // MACBPQ - - void GetSemaphore(struct SEM * Semaphore, int ID) { // @@ -5232,7 +5230,7 @@ void SendDataToPktMap(char *Msg) // TCP - Mode = Modenames[TNC->Hardware]; + Mode = Modenames[TNC->Hardware - 1]; if (TNC->CONNECTED) Active = 1; diff --git a/FormatHTML.cpp b/FormatHTML.cpp index f27498c..88e306e 100644 --- a/FormatHTML.cpp +++ b/FormatHTML.cpp @@ -1,60 +1,60 @@ -// FormatHTML.cpp : Defines the entry point for the console application. -// -#include - -int main () { - FILE *fp, *fp2; - char str[256]; - char newstr[256]; - char * ptr, * inptr; - - /* opening file for reading */ - fp = fopen("D:/AtomProject/test.html" , "r"); - fp2 = fopen("D:/AtomProject/test.html.c" , "w"); - - if(fp == NULL) { - perror("Error opening file"); - return(-1); - } - - while(fgets (str, 256, fp) != NULL) - { - // Replace any " with \" and add " on front and \r\n" on end - - char c; - ptr = newstr; - inptr = str; - - c = *(inptr++); - - *(ptr++) = '"'; - - while (c && c != 10) - { - if (c == '"') - *(ptr++) = '\\'; - - *(ptr++) = c; - - c = *(inptr++); - } - - - *(ptr++) = '\\'; - *(ptr++) = 'r'; - *(ptr++) = '\\'; - *(ptr++) = 'n'; - *(ptr++) = '"'; - *(ptr++) = 10; - *(ptr++) = 0; - - puts(newstr); - fputs(newstr, fp2); - - } - - fclose(fp); - fclose(fp2); - - return(0); +// FormatHTML.cpp : Defines the entry point for the console application. +// +#include + +int main () { + FILE *fp, *fp2; + char str[256]; + char newstr[256]; + char * ptr, * inptr; + + /* opening file for reading */ + fp = fopen("D:/AtomProject/test.html" , "r"); + fp2 = fopen("D:/AtomProject/test.html.c" , "w"); + + if(fp == NULL) { + perror("Error opening file"); + return(-1); + } + + while(fgets (str, 256, fp) != NULL) + { + // Replace any " with \" and add " on front and \r\n" on end + + char c; + ptr = newstr; + inptr = str; + + c = *(inptr++); + + *(ptr++) = '"'; + + while (c && c != 10) + { + if (c == '"') + *(ptr++) = '\\'; + + *(ptr++) = c; + + c = *(inptr++); + } + + + *(ptr++) = '\\'; + *(ptr++) = 'r'; + *(ptr++) = '\\'; + *(ptr++) = 'n'; + *(ptr++) = '"'; + *(ptr++) = 10; + *(ptr++) = 0; + + puts(newstr); + fputs(newstr, fp2); + + } + + fclose(fp); + fclose(fp2); + + return(0); } \ No newline at end of file diff --git a/FormatHTML.vcproj b/FormatHTML.vcproj index 95563d4..1c3dce1 100644 --- a/FormatHTML.vcproj +++ b/FormatHTML.vcproj @@ -1,219 +1,219 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/HTTPcode.c b/HTTPcode.c index 30cf2bd..049fce3 100644 --- a/HTTPcode.c +++ b/HTTPcode.c @@ -69,6 +69,7 @@ int GetAPRSIcon(unsigned char * _REPLYBUFFER, char * NodeURL); char * GetStandardPage(char * FN, int * Len); BOOL SHA1PasswordHash(char * String, char * Hash); char * byte_base64_encode(char *str, int len); +int APIProcessHTTPMessage(char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE); extern struct ROUTE * NEIGHBOURS; extern int ROUTE_LEN; @@ -1593,7 +1594,7 @@ int InnerProcessHTTPMessage(struct ConnectionInfo * conn) char * Compressed = 0; char * HostPtr = 0; - char * Context, * Method, * NodeURL, * Key; + char * Context, * Method, * NodeURL = 0, * Key; char _REPLYBUFFER[250000]; char Reply[250000]; @@ -1631,7 +1632,7 @@ int InnerProcessHTTPMessage(struct ConnectionInfo * conn) char Encoding[] = "Content-Encoding: deflate\r\n"; -#ifdef WIN32 +#ifdef WIN32xx struct _EXCEPTION_POINTERS exinfo; strcpy(EXCEPTMSG, "ProcessHTTPMessage"); @@ -1772,6 +1773,43 @@ int InnerProcessHTTPMessage(struct ConnectionInfo * conn) strlop(Mycall, ' '); + // Look for API messages + + if (_memicmp(Context, "/api/", 5) == 0 || _stricmp(Context, "/api") == 0) + { + char * Compressed; + ReplyLen = APIProcessHTTPMessage(_REPLYBUFFER, Method, Context, MsgPtr, LOCAL, COOKIE); + + if (memcmp(_REPLYBUFFER, "HTTP", 4) == 0) + { + // Full Message - just send it + + sendandcheck(sock, _REPLYBUFFER, ReplyLen); + + return 0; + } + + if (allowDeflate) + Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); + else + Compressed = _REPLYBUFFER; + + HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\n" + "Content-Length: %d\r\n" + "Content-Type: application/json\r\n" + "Connection: close\r\n" + "%s\r\n", ReplyLen, Encoding); + + sendandcheck(sock, Header, HeaderLen); + sendandcheck(sock, Compressed, ReplyLen); + + if (allowDeflate) + free (Compressed); + + return 0; + } + + // APRS process internally if (_memicmp(Context, "/APRS/", 6) == 0 || _stricmp(Context, "/APRS") == 0) @@ -1874,7 +1912,8 @@ int InnerProcessHTTPMessage(struct ConnectionInfo * conn) Session = FindSession(Key); - if (Session == NULL) + + if (Session == NULL && _memicmp(Context, "/Mail/API/", 10) != 0) { ReplyLen = sprintf(Reply, MailLostSession, Key); RLen = ReplyLen; @@ -2025,10 +2064,13 @@ Returnit: return 0; } - // Add tail + if (NodeURL && _memicmp(NodeURL, "/mail/api/", 10) != 0) + { + // Add tail - strcpy(&Reply[ReplyLen], Tail); - ReplyLen += strlen(Tail); + strcpy(&Reply[ReplyLen], Tail); + ReplyLen += strlen(Tail); + } // compress if allowed @@ -2037,7 +2079,15 @@ Returnit: else Compressed = Reply; - HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n%s\r\n", ReplyLen, Encoding); + if (NodeURL && _memicmp(NodeURL, "/mail/api/", 10) == 0) + HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\n" + "Content-Length: %d\r\n" + "Content-Type: application/json\r\n" + "Connection: close\r\n" + "%s\r\n", ReplyLen, Encoding); + else + HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n%s\r\n", ReplyLen, Encoding); + sendandcheck(sock, Header, HeaderLen); sendandcheck(sock, Compressed, ReplyLen); @@ -3889,7 +3939,7 @@ SendResp: } return 0; -#ifdef WIN32 +#ifdef WIN32xx } #include "StdExcept.c" } diff --git a/HanksRT.c b/HanksRT.c index cfc6440..3a7d538 100644 --- a/HanksRT.c +++ b/HanksRT.c @@ -77,6 +77,8 @@ char PopupText[260] = ""; int PopupMode = 0; int chatPaclen = 236; +int reportChatEvents = 0; + char RtKnown[MAX_PATH] = "RTKnown.txt"; char RtUsr[MAX_PATH] = "STUsers.txt"; char RtUsrTemp[MAX_PATH] = "STUsers.tmp"; @@ -2079,6 +2081,18 @@ void text_tellu_Joined(USER * user) sprintf(buf, "%s%-6.6s : %s *** Joined Chat, Topic %s", Stamp, user->call, user->name, user->topic->name); + if (reportChatEvents) + { + +#ifdef WIN32 + if (pRunEventProgram) + pRunEventProgram("ChatNewUser.exe", user->call); +#else + sprintf(prog, "%s/%s", BPQDirectory, "ChatNewUser"); + RunEventProgram(prog, user->call); +#endif + } + // Send it to all connected users in the same topic. // Echo to originator if requested. @@ -2109,14 +2123,6 @@ void text_tellu_Joined(USER * user) nputc(circuit, 7); nputc(circuit, 13); - -#ifdef WIN32 - if (pRunEventProgram) - pRunEventProgram("ChatNewUser.exe", user->call); -#else - sprintf(prog, "%s/%s", BPQDirectory, "ChatNewUser"); - RunEventProgram(prog, user->call); -#endif } } // Tell one link circuit about a local user change of topic. @@ -4170,6 +4176,7 @@ BOOL GetChatConfig(char * ConfigName) ChatApplNum = GetIntValue(group, "ApplNum"); MaxChatStreams = GetIntValue(group, "MaxStreams"); + reportChatEvents = GetIntValue(group, "reportChatEvents"); chatPaclen = GetIntValue(group, "chatPaclen"); GetStringValue(group, "OtherChatNodes", OtherNodesList); GetStringValue(group, "ChatWelcomeMsg", ChatWelcomeMsg); @@ -4201,6 +4208,7 @@ VOID SaveChatConfigFile(char * ConfigName) SaveIntValue(group, "ApplNum", ChatApplNum); SaveIntValue(group, "MaxStreams", MaxChatStreams); + SaveIntValue(group, "reportChatEvents", reportChatEvents); SaveIntValue(group, "chatPaclen", chatPaclen); SaveStringValue(group, "OtherChatNodes", OtherNodesList); SaveStringValue(group, "ChatWelcomeMsg", ChatWelcomeMsg); diff --git a/MBLRoutines.c b/MBLRoutines.c index d116893..e7ae622 100644 --- a/MBLRoutines.c +++ b/MBLRoutines.c @@ -23,6 +23,9 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #include "bpqmail.h" +void SendMessageReadEvent(struct UserInfo * user, struct MsgInfo * Msg); + + VOID ProcessMBLLine(CIRCUIT * conn, struct UserInfo * user, UCHAR* Buffer, int len) { Buffer[len] = 0; @@ -86,6 +89,7 @@ VOID ProcessMBLLine(CIRCUIT * conn, struct UserInfo * user, UCHAR* Buffer, int l FBBputs(conn, ">\r"); Msg->status = 'Y'; // Mark as read SaveMessageDatabase(); + SendMessageReadEvent(user->Call, Msg); } else { diff --git a/MailNode.vcproj b/MailNode.vcproj index 4478265..a67f072 100644 --- a/MailNode.vcproj +++ b/MailNode.vcproj @@ -424,6 +424,10 @@ RelativePath="..\CommonSource\LzmaLib.c" > + + @@ -464,6 +468,10 @@ RelativePath="..\CommonSource\NNTPRoutines.c" > + + diff --git a/MailNode.vcproj.DESKTOP-TGEL8RC.John.user b/MailNode.vcproj.DESKTOP-TGEL8RC.John.user new file mode 100644 index 0000000..40182c4 --- /dev/null +++ b/MailNode.vcproj.DESKTOP-TGEL8RC.John.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/RigControl.c b/RigControl.c index 0e56d6e..b7e22d1 100644 --- a/RigControl.c +++ b/RigControl.c @@ -1142,7 +1142,6 @@ int Rig_CommandEx(struct RIGPORTINFO * PORT, struct RIGINFO * RIG, TRANSPORTENTR return FALSE; } - // Build a ScanEntry in the buffer FreqPtr = (struct ScanEntry *)buffptr->Data; @@ -1277,8 +1276,6 @@ int Rig_CommandEx(struct RIGPORTINFO * PORT, struct RIGINFO * RIG, TRANSPORTENTR } *(CmdPtr++) = 0xFD; - - *(CmdPtr) = 0; Len = (int)(CmdPtr - (char *)&buffptr[30]); @@ -1325,7 +1322,9 @@ int Rig_CommandEx(struct RIGPORTINFO * PORT, struct RIGINFO * RIG, TRANSPORTENTR FreqPtr[0].Cmd1Len = Len; // for ICOM C_Q_ADD(&RIG->BPQtoRADIO_Q, buffptr); - return TRUE; + + sprintf(Command, "Ok\r"); + return FALSE; } if (_memicmp(FreqString, "Chan", 4) == 0) @@ -2203,7 +2202,7 @@ DllExport BOOL APIENTRY Rig_Init() memset(&RIGTNC, 0, sizeof(struct TNCINFO)); - TNCInfo[40] = TNC; + TNCInfo[70] = TNC; // Get config info @@ -2229,7 +2228,7 @@ DllExport BOOL APIENTRY Rig_Init() #ifndef LINBPQ - TNC->Port = 40; + TNC->Port = 70; CreatePactorWindow(TNC, "RIGCONTROL", "RigControl", 10, PacWndProc, 550, NeedRig * 20 + 60, NULL); hDlg = TNC->hDlg; diff --git a/TelnetV6.c b/TelnetV6.c index ad4c70b..efec041 100644 --- a/TelnetV6.c +++ b/TelnetV6.c @@ -534,6 +534,9 @@ int ProcessLine(char * buf, int Port) else if (_stricmp(param,"HTTPPORT") == 0) TCP->HTTPPort = atoi(value); + else if (_stricmp(param,"APIPORT") == 0) + TCP->APIPort = atoi(value); + else if (_stricmp(param,"SYNCPORT") == 0) TCP->SyncPort = atoi(value); @@ -1646,6 +1649,9 @@ BOOL OpenSockets(struct TNCINFO * TNC) if (TCP->HTTPPort) TCP->HTTPsock = OpenSocket4(TNC, TCP->HTTPPort); + if (TCP->APIPort) + TCP->APIsock = OpenSocket4(TNC, TCP->APIPort); + if (TCP->SyncPort) TCP->Syncsock = OpenSocket4(TNC, TCP->SyncPort); @@ -1755,10 +1761,12 @@ BOOL OpenSockets6(struct TNCINFO * TNC) if (TCP->RelayPort) TCP->Relaysock6 = OpenSocket6(TNC, TCP->RelayPort); - if (TCP->HTTPPort) TCP->HTTPsock6 = OpenSocket6(TNC, TCP->HTTPPort); + if (TCP->APIPort) + TCP->APIsock6 = OpenSocket6(TNC, TCP->APIPort); + if (TCP->SyncPort) TCP->Syncsock6 = OpenSocket6(TNC, TCP->SyncPort); @@ -1818,6 +1826,14 @@ static VOID SetupListenSet(struct TNCINFO * TNC) if (sock > maxsock) maxsock = sock; } + + sock = TCP->APIsock; + if (sock) + { + FD_SET(sock, readfd); + if (sock > maxsock) + maxsock = sock; + } sock = TCP->Syncsock; if (sock) @@ -1886,6 +1902,14 @@ static VOID SetupListenSet(struct TNCINFO * TNC) maxsock = sock; } + sock = TCP->APIsock6; + if (sock) + { + FD_SET(sock, readfd); + if (sock > maxsock) + maxsock = sock; + } + sock = TCP->DRATSsock6; if (sock) @@ -3192,6 +3216,7 @@ int Socket_Accept(struct TNCINFO * TNC, SOCKET SocketId, int Port) TNC->Streams[n].FramesQueued = 0; sockptr->HTTPMode = FALSE; + sockptr->APIMode = FALSE; sockptr->SyncMode = FALSE; sockptr->DRATSMode = FALSE; sockptr->FBBMode = FALSE; @@ -3208,6 +3233,12 @@ int Socket_Accept(struct TNCINFO * TNC, SOCKET SocketId, int Port) if (SocketId == TCP->HTTPsock || SocketId == TCP->HTTPsock6) sockptr->HTTPMode = TRUE; + + if (SocketId == TCP->APIsock || SocketId == TCP->APIsock6) + { + sockptr->HTTPMode = TRUE; // API is a type of HTTP socket + sockptr->APIMode = TRUE; + } else if (SocketId == TCP->Syncsock || SocketId == TCP->Syncsock6) sockptr->SyncMode = TRUE; else if (SocketId == TCP->DRATSsock || SocketId == TCP->DRATSsock6) diff --git a/Versions.h b/Versions.h index 56bfe73..f880e42 100644 --- a/Versions.h +++ b/Versions.h @@ -10,14 +10,14 @@ #endif -#define KVers 6,0,24,22 -#define KVerstring "6.0.24.22\0" +#define KVers 6,0,24,25 +#define KVerstring "6.0.24.25\0" #ifdef CKernel #define Vers KVers #define Verstring KVerstring -#define Datestring "November 2023" +#define Datestring "December 2023" #define VerComments "G8BPQ Packet Switch (C Version)" KVerstring #define VerCopyright "Copyright © 2001-2023 John Wiseman G8BPQ\0" #define VerDesc "BPQ32 Switch\0" diff --git a/WebMail.c b/WebMail.c index f626975..157938b 100644 --- a/WebMail.c +++ b/WebMail.c @@ -76,6 +76,8 @@ VOID SendTemplateSelectScreen(struct HTTPConnectionInfo * Session, char *URLPara BOOL isAMPRMsg(char * Addr); char * doXMLTransparency(char * string); Dll BOOL APIENTRY APISendAPRSMessage(char * Text, char * ToCall); +void SendMessageReadEvent(char * Call, struct MsgInfo * Msg); +void SendNewMessageEvent(char * call, struct MsgInfo * Msg); extern char NodeTail[]; extern char BBSName[10]; @@ -719,26 +721,27 @@ VOID ProcessFormDir(char * FormSet, char * DirName, struct HtmlFormDir *** xxx, { if (entry->d_type == DT_DIR) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + char Dir[MAX_PATH]; + + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; - Debugprintf("Recurse %s/%s/%s", FormSet, DirName, entry->d_name); + // Recurse in subdir + + sprintf(Dir, "%s/%s", DirName, entry->d_name); + + ProcessFormDir(FormSet, Dir, &FormDir->Dirs, &FormDir->DirCount); continue; - } - // see if initial html -// if (stristr(entry->d_name, "initial.html")) - { - // Add to list + // Add to list - Form = zalloc(sizeof (struct HtmlForm)); + Form = zalloc(sizeof (struct HtmlForm)); - Form->FileName = _strdup(entry->d_name); + Form->FileName = _strdup(entry->d_name); - FormDir->Forms=realloc(FormDir->Forms, (FormDir->FormCount + 1) * sizeof(void *)); - FormDir->Forms[FormDir->FormCount++] = Form; - } + FormDir->Forms=realloc(FormDir->Forms, (FormDir->FormCount + 1) * sizeof(void *)); + FormDir->Forms[FormDir->FormCount++] = Form; } closedir(dir); #endif @@ -808,22 +811,23 @@ int GetHTMLFormSet(char * FormSet) if (!(dir = opendir(name))) { Debugprintf("cant open forms dir %s %d %d", name, errno, dir); - return 0; } - - while ((entry = readdir(dir)) != NULL) + else { - if (entry->d_type == DT_DIR) + while ((entry = readdir(dir)) != NULL) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; + if (entry->d_type == DT_DIR) + { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; - // Add to Directory List + // Add to Directory List - ProcessFormDir(FormSet, entry->d_name, &HtmlFormDirs, &FormDirCount); - } - } - closedir(dir); + ProcessFormDir(FormSet, entry->d_name, &HtmlFormDirs, &FormDirCount); + } + } + closedir(dir); + } #endif // List for testing @@ -1122,7 +1126,7 @@ int ViewWebMailMessage(struct HTTPConnectionInfo * Session, char * Reply, int Nu Msg->status = 'Y'; Msg->datechanged=time(NULL); SaveMessageDatabase(); - + SendMessageReadEvent(Session->Callsign, Msg); } } } @@ -1190,6 +1194,7 @@ int ViewWebMailMessage(struct HTTPConnectionInfo * Session, char * Reply, int Nu Msg->status = 'Y'; Msg->datechanged=time(NULL); SaveMessageDatabase(); + SendMessageReadEvent(Session->Callsign, Msg); } } } @@ -1303,6 +1308,7 @@ int ViewWebMailMessage(struct HTTPConnectionInfo * Session, char * Reply, int Nu Msg->status = 'Y'; Msg->datechanged=time(NULL); SaveMessageDatabase(); + SendMessageReadEvent(Session->Callsign, Msg); } } } @@ -2776,11 +2782,16 @@ VOID SaveNewMessage(struct HTTPConnectionInfo * Session, char * MsgPtr, char * R if (Msg->status != 'H' && Msg->type == 'B' && memcmp(Msg->fbbs, zeros, NBMASK) != 0) Msg->status = '$'; // Has forwarding + if (EnableUI) SendMsgUI(Msg); user = LookupCall(Msg->to); + // If Event Notifications enabled report a new message event + + SendNewMessageEvent(user->Call, Msg); + if (user && (user->flags & F_APRSMFOR)) { char APRS[128]; @@ -2838,13 +2849,26 @@ char * GetHTMLViewerTemplate(char * FN) { for (l = 0; l < Dir->DirCount; l++) { - for (k = 0; k < Dir->Dirs[l]->FormCount; k++) + struct HtmlFormDir * SDir = Dir->Dirs[l]; + + if (SDir->DirCount) { - if (strcmp(FN, Dir->Dirs[l]->Forms[k]->FileName) == 0) + struct HtmlFormDir * SSDir = SDir->Dirs[0]; + int x = 1; + } + + for (k = 0; k < SDir->FormCount; k++) + { + if (_stricmp(FN, SDir->Forms[k]->FileName) == 0) { - return CheckFile(Dir, Dir->Dirs[l]->Forms[k]->FileName); + return CheckFile(SDir, SDir->Forms[k]->FileName); } } + if (SDir->DirCount) + { + struct HtmlFormDir * SSDir = SDir->Dirs[0]; + int x = 1; + } } } } @@ -3224,7 +3248,7 @@ BOOL ParseXML(WebMailInfo * WebMail, char * XMLOrig) *ptr2++ = 0; - ptr3 = strchr(ptr2, '<'); // end of value string + ptr3 = strstr(ptr2, " + + + + + + + + + + diff --git a/WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user b/WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user new file mode 100644 index 0000000..40182c4 --- /dev/null +++ b/WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/WinmorControl.vcproj.DESKTOP-TGEL8RC.John.user b/WinmorControl.vcproj.DESKTOP-TGEL8RC.John.user new file mode 100644 index 0000000..40182c4 --- /dev/null +++ b/WinmorControl.vcproj.DESKTOP-TGEL8RC.John.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user new file mode 100644 index 0000000..0cd9a72 --- /dev/null +++ b/WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/bbshtmlconfig.c~ b/bbshtmlconfig.c~ new file mode 100644 index 0000000..33c1048 --- /dev/null +++ b/bbshtmlconfig.c~ @@ -0,0 +1,3161 @@ +/* +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 +#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[]; +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; +extern int reportMailEvents; + +#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); + +char UNC[] = ""; +char CHKD[] = "checked=checked "; +char sel[] = "selected"; + +char Sent[] = "#98FFA0"; +char ToSend[] = "#FFFF00"; +char NotThisOne[] = "#FFFFFF"; + +static char PassError[] = "

Sorry, User or Password is invalid - please try again

"; + +static char BusyError[] = "

Sorry, No sessions available - please try later

"; + +extern char WebMailSignon[]; + +char MailSignon[] = "BPQ32 Mail Server Access" + "

BPQ32 Mail Server %s Access

" + "

Please enter Callsign and Password to access the BBS

" + "
" + "" + "" + "
User
Password
" + "

"; + + +char MailPage[] = "%s's BBS Web Server" + "" + "" + "

BPQ32 BBS %s

" + "

" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "
StatusConfigurationUsersMessagesForwardingWelcome Msgs & PromptsHousekeepingWP UpdateNode Menu
"; + +char RefreshMainPage[] = "" + "" + "" + "%s's BBS Web Server" + "

BPQ32 BBS %s

" + "

" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "
StatusConfigurationUsersMessagesForwardingWelcome Msgs & PromptsHousekeepingWP UpdateNode Menu
"; + +char StatusPage [] = + +"

" +"
User     Callsign   Stream Queue
" +"


"; + +char StatusTail[] = +"Msgs      
" +"Sysop Msgs
" +"Held Msgs 
" +"SMTP Msgs 
"; + + +char UIHddr [] = "
Mailfor Header
" +"           " +"    (use \\r to insert newline in message)

" +"Enable Port           " +"             Path           " +"                   Send: MailFor Headers Empty Mailfor

"; + +char UILine[] = " %s " +" " +"    " +"       
"; + +char UITail[] = "

" +"
"; + +char FWDSelectHddr[] = + "
" + "Max Size to Send   
" + "Max Size to Receive
" + "Warn if no route for P or T
" + "Use Local Time              " + "

" + "Aliases                   Select BBS
" + "  
         " + " 
"; + +char UserSelectHddr[] = + "
" + "Please Select User



" + "" + "
" + " " + "
"; + +char UserUpdateHddr[] = + "

Update User %s

" + "
"; + +char UserUpdateLine[] = ""; + +// +//
+ + +char FWDUpdate[] = +"

Update Forwarding for BBS %s

" +"    " +"TO            " +"AT          " +"TIMES         Connect Script
" +"" +" " +" " +"
" +"" +"

" +"Enable Forwarding  Interval" +"(Secs) Request Reverse" +" Interval (Secs)
" +"Send new messages without waiting for poll timer
" +"BBS HA FBB Max Block
" +"Send Personal Mail Only  " +"Allow Binary     Use B1 " +"Protocol   Use B2 Protocol

" +" " +"

"; + +static char MailDetailPage[] = +"" +"MsgEdit

Message %d

" +"
" +"From  Sent   " +"       " +"Type     
" +"To    " +" Received      " +"Status   
" +"BID   Last Changed  " +"Size 

" +"%s" // Email from Line +" VIA 
" +"Title 

" +" " +" " +"" +"" +//" " +" " +"

" +"Green = Sent, Yellow = Queued" +""; + +char MailDetailTail[] = "
"; + +char Welcome[] = "
" +"Normal User Welcome
" +"
" +"New User Welcome
" +"
" +"Expert User Welcome
" +"
" +"Normal User Prompt
" +"
" +"New User Prompt
" +"
" +"Expert User Prompt
" +"
" +"Signoff
" +"

" +"$U:Callsign of the user  $I:First name of the user $X:Messages for user $x:Unread messages
" +"$L:Number of the latest message $N:Number of active messages. $Z:Last message read by user

" +" "; + +static char MsgEditPage[] = "" +"" +"
" +"

" +"
"; + +static char WPDetail[] = "
" +"
" + +"" +"" +"" +"" +"" +"" +"" +"" +"" +"" +"" +"" +"
Call
Name
Home BBS 1
Home BBS 2
QTH 1
QTH 2
ZIP 1
ZIP 2
Last Seen
Last Modified
Type
Changed
Seen
" +"
" +" " +"
"; + + +static char LostSession[] = "" +"
" +"Sorry, Session had been lost

    " +"
"; + + +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); +} + + +void ConvertTitletoUTF8(WebMailInfo * WebMail, char * Title, char * UTF8Title, int Len) +{ + if (WebIsUTF8(Title, (int)strlen(Title)) == FALSE) + { + // With Windows it is simple - convert using current codepage + // I think the only reliable way is to convert to unicode and back + + int origlen = (int)strlen(Title) + 1; +#ifdef WIN32 + WCHAR BufferW[128]; + int wlen; + int len = origlen; + + wlen = MultiByteToWideChar(CP_ACP, 0, Title, len, BufferW, origlen * 2); + len = WideCharToMultiByte(CP_UTF8, 0, BufferW, wlen, UTF8Title, origlen * 2, NULL, NULL); +#else + size_t left = Len - 1; + size_t len = origlen; + + iconv_t * icu = WebMail->iconv_toUTF8; + + if (WebMail->iconv_toUTF8 == NULL) + icu = WebMail->iconv_toUTF8 = iconv_open("UTF-8//IGNORE", "CP1252"); + + if (icu == (iconv_t)-1) + { + strcpy(UTF8Title, Title); + WebMail->iconv_toUTF8 = NULL; + return; + } + + char * orig = UTF8Title; + + iconv(icu, NULL, NULL, NULL, NULL); // Reset State Machine + iconv(icu, &Title, &len, (char ** __restrict__)&UTF8Title, &left); + +#endif + } + else + strcpy(UTF8Title, Title); +} + +BOOL GotFirstMessage = 0; + +void ProcessMailHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, char * URL, char * input, char * Reply, int * RLen, int InputLen) +{ + 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; + + if (Session->TNC == (void *)1) // Re-using an address as a flag + 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; + + } + + // 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, "", Session->Key); + } + + GotFirstMessage = 1; + return; + } + + if (_memicmp(URL, "/Mail/API/", 10) == 0) + { + *RLen = APIProcessHTTPMessage(Reply, Method, URL, input, LOCAL, 0); + return; + } + + + 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
", 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]; + + if ((USER->flags & F_BBS)) + if (USER->BBSNumber) + bbs[i++] = USER; + } + + qsort((void *)bbs, i, sizeof(void *), compare ); + + n = 0; + + for (y = 0; y < NBBBS/8; y++) + { + len += sprintf(&Reply[len],""); + 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],"%s", + Colour, bbs[n]->BBSNumber, bbs[n]->Call); + } + else + len += sprintf(&Reply[len], " "); + + n++; + } + len += sprintf(&Reply[len],""); + 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); + GetCheckBox(input, "Events=", &reportMailEvents); + + 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="); + + // 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="); + } + + 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); + + // 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, "

Copy From BBS %s not found

", 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", ""); + 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", ""); + + } + } + 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) +{ + int Len, i; + + 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] = ""; + + char FBBFilters[100000] = ""; + + + char * ptr = FBBFilters; + FBBFilter * Filter = Filters; + + 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); + + // set up FB style fiters + + ptr += sprintf(ptr, + ""); + + while(Filter) + { + ptr += sprintf(ptr, "" + "" + "" + "" + "" + "" + "" + "", + 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, "" + "" + "" + "" + "" + "" + "" + "", ' ', ' ', "", "", "", "", 0); + } + + ptr += sprintf(ptr, "
ActionTypeFromTo@BBSBidMax Size
"); + + Debugprintf("%d", strlen(FBBFilters)); + + 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, + (reportMailEvents) ? CHKD : UNC, + 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, + RF, RT, RA, RB, HF, HT, HA, HB, FBBFilters); + + *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, + 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 + +int ProcessWebmailWebSock(char * MsgPtr, char * OutBuffer); + +static char PipeFileName[] = "\\\\.\\pipe\\BPQMailWebPipe"; + +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. +{ + 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; + struct HTTPConnectionInfo Session; + char URL[100001]; + char * Context, * Method; + int n; + + char * ptr; + + // The thread's parameter is a handle to a pipe object instance. + + hPipe = (HANDLE) lpvParam; + + // 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); + + if (!fSuccess || InputLen == 0) + { + if (GetLastError() == ERROR_BROKEN_PIPE) + Debugprintf("InstanceThread: client disconnected.", GetLastError()); + else + Debugprintf("InstanceThread ReadFile failed, GLE=%d.", GetLastError()); + + return 1; + } + + Buffer[InputLen] = 0; + + MsgPtr = &Buffer[0]; + + if (memcmp(MsgPtr, "WMRefresh", 9) == 0) + { + OutputLen = ProcessWebmailWebSock(MsgPtr, OutBuffer); + } + else + { + strcpy(URL, MsgPtr); + + ptr = strstr(URL, " HTTP"); + + if (ptr) + *ptr = 0; + + Method = strtok_s(URL, " ", &Context); + + ProcessMailHTTPMessage(&Session, Method, Context, MsgPtr, OutBuffer, &OutputLen, InputLen); + } + + WriteFile(hPipe, &Session, sizeof (struct HTTPConnectionInfo), &n, NULL); + WriteFile(hPipe, OutBuffer, OutputLen, &cbWritten, NULL); + + FlushFileBuffers(hPipe); + DisconnectNamedPipe(hPipe); + CloseHandle(hPipe); + + 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); +} + + + + + + + diff --git a/mailapi.c b/mailapi.c new file mode 100644 index 0000000..b60ec77 --- /dev/null +++ b/mailapi.c @@ -0,0 +1,196 @@ +// basic JASON API to BPQ Node + +// Authentication is via Telnet USER records. + + +#define _CRT_SECURE_NO_DEPRECATE +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +//#include +#include "CHeaders.h" +#include +#include "bpqmail.h" + + +// Constants +#define TOKEN_SIZE 32 // Length of the authentication token +#define TOKEN_EXPIRATION 7200 // Token expiration time in seconds (2 hours) + +// Token data structure +typedef struct MailToken { + char token[TOKEN_SIZE + 1]; + time_t expiration_time; + struct UserInfo * User; + char Call[10]; + struct MailToken* next; +} MailToken; + +static MailToken * token_list = NULL; + +static int verify_token(const char* token); +static void remove_expired_tokens(); +static int request_token(char * response); +static void add_token_to_list(MailToken* token); +static MailToken * find_token(const char* token); + +static MailToken * generate_token() +{ + // Generate a random authentication token + int i; + + MailToken * token = malloc(sizeof(MailToken)); + + srand(time(NULL)); + + for (i = 0; i < TOKEN_SIZE; i++) + { + token->token[i] = 'A' + rand() % 26; // Random uppercase alphabet character + } + token->token[TOKEN_SIZE] = '\0'; // Null-terminate the token + token->expiration_time = time(NULL) + TOKEN_EXPIRATION; // Set token expiration time + add_token_to_list(token); + return token; +} + +// Function to add the token to the token_list +static void add_token_to_list(MailToken * token) +{ + if (token_list == NULL) + { + token_list = token; + token->next = NULL; + } + else + { + MailToken * current = token_list; + + while (current->next != NULL) + current = current->next; + + current->next = token; + token->next = NULL; + } +} + +static int verify_token(const char* token) +{ + // Find the token in the token list + MailToken * existing_token = find_token(token); + + if (existing_token != NULL) + { + // Check if the token has expired + time_t current_time = time(NULL); + if (current_time > existing_token->expiration_time) + { + // Token has expired, remove it from the token list + remove_expired_tokens(); + return 0; + } + // Token is valid + return 1; + } + + // Token doesn't exist in the token list + return 0; +} + +static void remove_expired_tokens() +{ + time_t current_time = time(NULL); + MailToken* current_token = token_list; + MailToken* prev_token = NULL; + MailToken* next_token; + + while (current_token != NULL) + { + if (current_time > current_token->expiration_time) + { + // Token has expired, remove it from the token list + if (prev_token == NULL) + { + token_list = current_token->next; + } else { + prev_token->next = current_token->next; + } + next_token = current_token->next; + free(current_token); + current_token = next_token; + } else { + prev_token = current_token; + current_token = current_token->next; + } + } +} + +static MailToken * find_token(const char* token) +{ + MailToken * current_token = token_list; + while (current_token != NULL) + { + if (strcmp(current_token->token, token) == 0) + { + return current_token; + } + current_token = current_token->next; + } + return NULL; +} + +static int send_http_response(char * response, const char* msg) +{ + return sprintf(response, "HTTP/1.1 %s\r\nContent-Length: 0\r\nConnection: close\r\n\r\n", msg); +} + + +int MailAPIProcessHTTPMessage(char * response, char * Method, char * URL, char * request, BOOL LOCAL, char *Params) +{ + char * pass = strlop(Params, '&'); + int Flags = 0; + MailToken * Token; + + + // Check if the request is for token generation + + if (strcmp(Method, "GET") != 0) + return send_http_response(response, "403 (Bad Method)"); + + if (_stricmp(URL, "/mail/api/login") == 0) + { + // user is in Params and Password in pass + + struct UserInfo * User; + char Msg[256]; + int n; + + User = LookupCall(Params); + + if (User) + { + // Check Password + + if (pass[0] == 0 || strcmp(User->pass, pass) != 0 || User->flags & F_Excluded) + return send_http_response(response, "403 (Login Failed)"); + + n=sprintf_s(Msg, sizeof(Msg), "API Connect from %s", _strupr(Params)); + WriteLogLine(NULL, '|',Msg, n, LOG_BBS); + + Token = generate_token(); + add_token_to_list(Token); + + Token->User = User; + + strcpy(Token->Call, Params); + + // Return Token + + sprintf(response, "{\"access_token\":\"%s\", \"expires_in\":%d, \"scope\":\"create\"}\r\n", + Token->token, TOKEN_EXPIRATION); + + return strlen(response); + + } + } + + return 0; +} diff --git a/makefile b/makefile index 184cfbf..0bd8491 100644 --- a/makefile +++ b/makefile @@ -13,7 +13,7 @@ OBJS = pngwtran.o pngrtran.o pngset.o pngrio.o pngwio.o pngtrans.o pngrutil.o pn MailCommands.o MailDataDefs.o LinBPQ.o MailRouting.o MailTCP.o MBLRoutines.o md5.o Moncode.o \ NNTPRoutines.o RigControl.o TelnetV6.o WINMOR.o TNCCode.o UZ7HODrv.o WPRoutines.o \ SCSTrackeMulti.o SCSPactor.o SCSTracker.o HanksRT.o UIRoutines.o AGWAPI.o AGWMoncode.o \ - DRATS.o FreeDATA.o base64.o Events.o + DRATS.o FreeDATA.o base64.o Events.o nodeapi.o mailapi.o # Configuration: diff --git a/nodeapi.c b/nodeapi.c new file mode 100644 index 0000000..8a5a814 --- /dev/null +++ b/nodeapi.c @@ -0,0 +1,633 @@ +// basic JASON API to BPQ Node + +// Authentication is via Telnet USER records. + + +#define _CRT_SECURE_NO_DEPRECATE + +#include "CHeaders.h" +#include +#include "tncinfo.h" +#include "asmstrucs.h" +#include "kiss.h" + +// Constants +#define TOKEN_SIZE 32 // Length of the authentication token +#define TOKEN_EXPIRATION 7200 // Token expiration time in seconds (2 hours) + +// Token data structure +typedef struct Token { + char token[TOKEN_SIZE + 1]; + time_t expiration_time; + struct Token* next; +} Token; + + +// Function prototypes +void handle_request(SOCKET client_socket, char * request, char * response); +int verify_token(const char* token); +void remove_expired_tokens(); +char* fetch_data(const char* endpoint); +int request_token(char * response); +int send_http_response(char * response, const char* msg); +int create_json_response(char * response, char* access_token, int expires_in, char* scope); +void add_token_to_list(Token* token); + +Token* find_token(const char* token); +Token* generate_token(); + +int sendPortList(char * response, char * token,int Flags); +int sendNodeList(char * response, char * token,int Flags); +int sendUserList(char * response, char * token,int Flags); +int sendInfo(char * response, char * token, int Flags); + +DllExport struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot(int portslot); + +// Token list +Token* token_list = NULL; + +int xx() +{ + while (1) + { + // Remove expired tokens + remove_expired_tokens(); + + // Handle the client request + // handle_request(); + } + return 0; +} + +int APIProcessHTTPMessage(char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE) +{ + const char * auth_header = "Authorization: Bearer "; + char * token_begin = strstr(request, auth_header); + char token[TOKEN_SIZE + 1]= ""; + char * param = strlop(URL, '?'); + int Flags = 0; + + if (param && strlen(param) == TOKEN_SIZE) + { + // assume auth token + + strcpy(token, param); + } + + remove_expired_tokens(); // Tidy up + + // Check if the request is for token generation + + if (strcmp(Method, "GET") != 0) + return send_http_response(response, "403 (Bad Method)"); + + if (_stricmp(URL, "/api/request_token") == 0) + return request_token(response); + + if (token[0] == 0) + { + // Extract the token from the request (assuming it's present in the request headers) + if (token_begin == NULL) + { + Debugprintf("Invalid request: No authentication token provided.\n"); + return send_http_response(response, "403 (Forbidden)"); + } + token_begin += strlen(auth_header); // Move to the beginning of the token + strncpy(token, token_begin, TOKEN_SIZE); + token[TOKEN_SIZE] = '\0'; // Null-terminate the token + } + + // Verify the token + if (!verify_token(token)) + { + Debugprintf("Invalid authentication token.\n"); + return send_http_response(response, "401 Unauthorized"); + } + + // Determine the requested API endpoint + + if (_stricmp(URL, "/api/getports") == 0) + return sendPortList(response, token, Flags); + else if (_stricmp(URL, "/api/getnodes") == 0) + return sendNodeList(response, token, Flags); + else if (_stricmp(URL, "/api/getusers") == 0) + return sendUserList(response, token, Flags); + else if (_stricmp(URL, "/api/getinfo") == 0) + return sendInfo(response, token, Flags); + + return send_http_response(response, "401 Invalid API Call"); + +} + +int request_token(char * response) +{ + Token * token = generate_token(); + int expires_in = 3600; + char scope[] = "create"; + + printf("Token generated: %s\n", token->token); + + sprintf(response, "{\"access_token\":\"%s\", \"expires_in\":%d, \"scope\":\"create\"}\r\n", + token->token, expires_in); + + return strlen(response); +} + +Token * generate_token() +{ + // Generate a random authentication token + int i; + + Token * token = malloc(sizeof(Token)); + for (i = 0; i < TOKEN_SIZE; i++) + { + token->token[i] = 'A' + rand() % 26; // Random uppercase alphabet character + } + token->token[TOKEN_SIZE] = '\0'; // Null-terminate the token + token->expiration_time = time(NULL) + TOKEN_EXPIRATION; // Set token expiration time + add_token_to_list(token); + return token; +} + +// Function to add the token to the token_list +void add_token_to_list(Token* token) +{ + if (token_list == NULL) + { + token_list = token; + token->next = NULL; + } + else + { + Token* current = token_list; + + while (current->next != NULL) + current = current->next; + + current->next = token; + token->next = NULL; + } +} + +int verify_token(const char* token) +{ + // Find the token in the token list + Token * existing_token = find_token(token); + + if (existing_token != NULL) + { + // Check if the token has expired + time_t current_time = time(NULL); + if (current_time > existing_token->expiration_time) + { + // Token has expired, remove it from the token list + remove_expired_tokens(); + return 0; + } + // Token is valid + return 1; + } + + // Token doesn't exist in the token list + return 0; +} + +void remove_expired_tokens() +{ + time_t current_time = time(NULL); + Token* current_token = token_list; + Token* prev_token = NULL; + Token* next_token; + + while (current_token != NULL) + { + if (current_time > current_token->expiration_time) + { + // Token has expired, remove it from the token list + if (prev_token == NULL) + { + token_list = current_token->next; + } else { + prev_token->next = current_token->next; + } + next_token = current_token->next; + free(current_token); + current_token = next_token; + } else { + prev_token = current_token; + current_token = current_token->next; + } + } +} + +Token * find_token(const char* token) +{ + Token* current_token = token_list; + while (current_token != NULL) + { + if (strcmp(current_token->token, token) == 0) + { + return current_token; + } + current_token = current_token->next; + } + return NULL; +} + +int send_http_response(char * response, const char* msg) +{ + return sprintf(response, "HTTP/1.1 %s\r\nContent-Length: 0\r\nConnection: close\r\n\r\n", msg); +} + +/* +{ +"access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3", +"expires_in":3600, +"scope":"create" +} +*/ + +/* +{"ports":[ +{"ID":"My Port", "Driver":"KISS", "Number":2, "State":"Active"), +{ ...}, +{...} +]} +*/ + +extern int MasterPort[MAXBPQPORTS+1]; // Pointer to first BPQ port for a specific MPSK or UZ7HO host + +int sendPortList(char * response, char * token, int Flags) +{ + char * Array = 0; + int ArrayLen = 0; + int ArrayPtr = 0; + + struct _EXTPORTDATA * ExtPort; + struct PORTCONTROL * Port; + struct PORTCONTROL * SAVEPORT; + int PortNo; + + int count; + char DLL[20]; + char Status[32]="Unknown"; + char ID[33]; + char * ptr; + + ArrayPtr += sprintf(&response[ArrayPtr], "{\"ports\":[\r\n"); + + for (count = 1; count <= NUMBEROFPORTS; count++) + { + Port = GetPortTableEntryFromSlot(count); + ExtPort = (struct _EXTPORTDATA *)Port; + PortNo = Port->PORTNUMBER; + + if (Port->PORTTYPE == 0x10) + { + strcpy(DLL, ExtPort->PORT_DLL_NAME); + strlop(DLL, '.'); + strlop(DLL, ' '); + } + else if (Port->PORTTYPE == 0) + strcpy(DLL, "ASYNC"); + + else if (Port->PORTTYPE == 22) + strcpy(DLL, "I2C"); + + else if (Port->PORTTYPE == 14) + strcpy(DLL, "INTERNAL"); + + else if (Port->PORTTYPE > 0 && Port->PORTTYPE < 14) + strcpy(DLL, "HDLC"); + + + if (Port->PortStopped) + { + strcpy(Status, "Stopped"); + + } + else + { + if (Port->PORTTYPE == 0) + { + struct KISSINFO * KISS = (struct KISSINFO *)Port; + NPASYINFO KPort; + + SAVEPORT = Port; + + if (KISS->FIRSTPORT && KISS->FIRSTPORT != KISS) + { + // Not first port on device + + Port = (struct PORTCONTROL *)KISS->FIRSTPORT; + KPort = KISSInfo[PortNo]; + } + + KPort = KISSInfo[PortNo]; + + if (KPort) + { + // KISS like - see if connected + + if (Port->PORTIPADDR.s_addr || Port->KISSSLAVE) + { + // KISS over UDP or TCP + + if (Port->KISSTCP) + { + if (KPort->Connected) + strcpy(Status, "Open "); + else + if (Port->KISSSLAVE) + strcpy(Status, "Listen"); + else + strcpy(Status, "Closed"); + } + else + strcpy(Status, "UDP"); + } + else + if (KPort->idComDev) // Serial port Open + strcpy(Status, "Open "); + else + strcpy(Status, "Closed"); + + + Port = SAVEPORT; + } + } + + if (Port->PORTTYPE == 14) // Loopback + strcpy(Status, "Open "); + + else if (Port->PORTTYPE == 16) // External + { + if (Port->PROTOCOL == 10) // 'HF' Port + { + struct TNCINFO * TNC = TNCInfo[PortNo]; + + if (TNC) + { + switch (TNC->Hardware) // Hardware Type + { + case H_SCS: + case H_KAM: + case H_AEA: + case H_HAL: + case H_TRK: + case H_SERIAL: + + // Serial + + if (TNC->hDevice) + strcpy(Status, "Open "); + else + strcpy(Status, "Closed"); + + break; + + case H_UZ7HO: + + if (TNCInfo[MasterPort[PortNo]]->CONNECTED) + strcpy(Status, "Open "); + else + strcpy(Status, "Closed"); + + break; + + case H_WINMOR: + case H_V4: + + case H_MPSK: + case H_FLDIGI: + case H_UIARQ: + case H_ARDOP: + case H_VARA: + case H_KISSHF: + case H_WINRPR: + case H_FREEDATA: + + // TCP + + if (TNC->CONNECTED) + { + if (TNC->Streams[0].Attached) + strcpy(Status, "In Use"); + else + strcpy(Status, "Open "); + } + else + strcpy(Status, "Closed"); + + break; + + case H_TELNET: + + strcpy(Status, "Open "); + } + } + } + else + { + // External but not HF - AXIP, BPQETHER VKISS, ?? + + struct _EXTPORTDATA * EXTPORT = (struct _EXTPORTDATA *)Port; + + strcpy(Status, "Open "); + } + } + } + + strlop(Status, ' '); + strcpy(ID, Port->PORTDESCRIPTION); + ptr = &ID[29]; + while (*(ptr) == ' ') + { + *(ptr--) = 0; + } + + ArrayPtr += sprintf(&response[ArrayPtr], " {\"ID\":\"%s\", \"Driver\":\"%s\", \"Number\":%d,\"State\":\"%s\"},\r\n", + ID, DLL, Port->PORTNUMBER, Status); + } + + ArrayPtr -= 3; // remove trailing comma + ArrayPtr += sprintf(&response[ArrayPtr], "\r\n]}\r\n"); + + return ArrayPtr; +} + +/* +{"Nodes":[ +{"Call":"xx", "Alias":"xx", "Nbour1 ":"xx", "Quality":192), +{ ...}, +{...} +]} +*/ + +extern int MaxNodes; +extern struct DEST_LIST * DESTS; // NODE LIST +extern int DEST_LIST_LEN; + + +int sendNodeList(char * response, char * token, int Flags) +{ + int ArrayPtr = 0; + + int count, len, i; + char Normcall[10], Portcall[10]; + char Alias[7]; + struct DEST_LIST * Dests = DESTS ; + // struct ROUTE * Routes; + + Dests = DESTS; + MaxNodes = MAXDESTS; + + ArrayPtr += sprintf(&response[ArrayPtr], "{\"nodes\":[\r\n"); + + Dests-=1; + + for (count = 0; count < MaxNodes; count++) + { + Dests+=1; + + if (Dests->DEST_CALL[0] == 0) + continue; + + len = ConvFromAX25(Dests->DEST_CALL, Normcall); + Normcall[len] = 0; + + memcpy(Alias, Dests->DEST_ALIAS, 6); + + Alias[6]=0; + + for (i=0;i<6;i++) + { + if (Alias[i] == ' ') + Alias[i] = 0; + } + + + ArrayPtr += sprintf(&response[ArrayPtr], " {\"Call\":\"%s\", \"Alias\":\"%s\", \"Routes\":[", Normcall, Alias); + + + // Add an array with up to 6 objects (3 NR + 3 INP3 Neighbours + + if (Dests->NRROUTE[0].ROUT_NEIGHBOUR != 0 && Dests->NRROUTE[0].ROUT_NEIGHBOUR->INP3Node == 0) + { + len = ConvFromAX25(Dests->NRROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL,Portcall); + Portcall[len] = 0; + + ArrayPtr += sprintf(&response[ArrayPtr], "{\"Call\":\"%s\", \"Port\":%d, \"Quality\":%d},", + Portcall, Dests->NRROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, Dests->NRROUTE[0].ROUT_QUALITY); + + + // if (Dests->NRROUTE[0].ROUT_OBSCOUNT > 127) + // { + // len=sprintf(&line[cursor],"! "); + // cursor+=len; + // } + + + if (Dests->NRROUTE[1].ROUT_NEIGHBOUR != 0 && Dests->NRROUTE[1].ROUT_NEIGHBOUR->INP3Node == 0) + { + len=ConvFromAX25(Dests->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL,Portcall); + Portcall[len]=0; + + + + ArrayPtr += sprintf(&response[ArrayPtr], " {\"Call\":\"%s\", \"Port\":%d, \"Quality\":%d},", + Portcall, Dests->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, Dests->NRROUTE[1].ROUT_QUALITY); + //if (Dests->NRROUTE[1].ROUT_OBSCOUNT > 127) + //{ + //len=sprintf(&line[cursor],"! "); + //cursor+=len; + //} + + } + + if (Dests->NRROUTE[2].ROUT_NEIGHBOUR != 0 && Dests->NRROUTE[2].ROUT_NEIGHBOUR->INP3Node == 0) + { + len=ConvFromAX25(Dests->NRROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL,Portcall); + Portcall[len]=0; + + + ArrayPtr += sprintf(&response[ArrayPtr], " {\"Call\":\"%s\", \"Port\":%d, \"Quality\":%d},", + Portcall, Dests->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, Dests->NRROUTE[1].ROUT_QUALITY); + + //if (Dests->NRROUTE[2].ROUT_OBSCOUNT > 127) + //{ + //len=sprintf(&line[cursor],"! "); + //cursor+=len; + + } + ArrayPtr -= 1; // remove comma + } + + ArrayPtr += sprintf(&response[ArrayPtr], "]},\r\n"); + } + + ArrayPtr -= 3; // remove comma + ArrayPtr += sprintf(&response[ArrayPtr], "\r\n]}"); + + return ArrayPtr; +} + + +int sendUserList(char * response, char * token, int Flags) +{ + int ArrayPtr = 0; + int n = MAXCIRCUITS; + TRANSPORTENTRY * L4 = L4TABLE; + TRANSPORTENTRY * Partner; + int MaxLinks = MAXLINKS; + char State[12] = "", Type[12] = "Uplink"; + char LHS[50] = "", MID[10] = "", RHS[50] = ""; + char Line[100]; + char Normcall[10]; + int len; + + ArrayPtr += sprintf(&response[ArrayPtr], "{\"users\":[\r\n"); + + while (n--) + { + if (L4->L4USER[0]) + { + RHS[0] = MID[0] = 0; + + len = ConvFromAX25(L4->L4USER, Normcall); + Normcall[len] = 0; + + ArrayPtr += sprintf(&response[ArrayPtr], " {\"Call\", \"%s\"},\r\n", Normcall); + L4++; + } + } + + if (ArrayPtr == 12) //empty list + { + ArrayPtr -=2; + ArrayPtr += sprintf(&response[ArrayPtr], "]}\r\n"); + } + else + { + ArrayPtr -= 3; // remove trailing comma + ArrayPtr += sprintf(&response[ArrayPtr], "\r\n]}\r\n"); + } + return ArrayPtr; +} + +extern char MYALIASLOPPED[]; +extern char TextVerstring[]; +extern char LOCATOR[]; + +int sendInfo(char * response, char * token, int Flags) +{ + char call[10]; + + memcpy(call, MYNODECALL, 10); + strlop(call, ' '); + + sprintf(response, "{\"info\":{\"NodeCall\":\"%s\", \"Alias\":\"%s\", \"Locator\":\"%s\", \"Version\":\"%s\"}}\r\n", + call, MYALIASLOPPED, LOCATOR, TextVerstring); + + return strlen(response); +} diff --git a/telnetserver.h b/telnetserver.h index 77da27c..48f87d0 100644 --- a/telnetserver.h +++ b/telnetserver.h @@ -36,7 +36,8 @@ struct ConnectionInfo BOOL RelayMode; // Pure TCP for RMS Relay Emulation forwarding BOOL DRATSMode; // HTML Terminal Emulator BOOL SyncMode; // RMS Relay Sync - BOOL HTTPMode; // DRATS Reflector Emulator + BOOL HTTPMode; // HTTP Server + BOOL APIMode; // REST API Server BOOL TriMode; // Trimode emulation BOOL TriModeConnected; // Set when remote session is connected - now send data to DataSock SOCKET TriModeDataSock; // Data Socket diff --git a/templatedefs.c b/templatedefs.c index 72f1c8b..dbd7485 100644 --- a/templatedefs.c +++ b/templatedefs.c @@ -478,7 +478,9 @@ char * MainConfigtxt() " Dont Check From Call
\r\n" " Allow users to kill T messages
\r\n" " Forward Messages to BBS Call
\r\n" - " Don't allow unknown users

\r\n" + " Don't allow unknown users
\r\n" + " Enable Event Reporting

\r\n" + " POP3 Port   \r\n" "SMTP Port NTPPort   Enable Remote Access
\r\n" " AMPR Address Send AMPR Mail to AMPR host\r\n" @@ -515,7 +517,7 @@ char * MainConfigtxt() " FBB reject.sys type filters (all fields must match, wildcards allowed)\r\n" "

" "
%s
" - "
" + "
" " " "
" "\r\n" @@ -1428,7 +1430,7 @@ char * ChatConfigtxt() "
Chat Configuration
\r\n" "
\r\n" + "style=\"align: center; border: 2px solid ; overflow: auto; text-align: center; position: relative; top: 10px; height: 650px; width: 700px; left: 96.5px;\">\r\n" "
\r\n" "

 Chat Server Params

\r\n" @@ -1437,6 +1439,8 @@ char * ChatConfigtxt() "Streams    \r\n" "  
\r\n" " 
\r\n" + " Enable Event Reporting

\r\n" + "
The Nodes to link to box defines which other Chat Nodes should be connected to, or from which " "connections may be accepted. The format is ALIAS:CALL, eg BPQCHT:G8BPQ-4. If the node is not directly " "connectable (ie is not in your NODES table) you can add a connect script. This consists of a series of commands " @@ -1460,7 +1464,7 @@ char * ChatConfigtxt() "
\r\n" "
\r\n" "\r\n" - "
\r\n" + "
\r\n" " \r\n" " \r\n" " \r\n" diff --git a/tncinfo.h b/tncinfo.h index 2d6ad93..9b9cb54 100644 --- a/tncinfo.h +++ b/tncinfo.h @@ -110,6 +110,7 @@ struct TCPINFO int FBBPort[100]; int RelayPort; int HTTPPort; + int APIPort; int TriModePort; int SyncPort; int DRATSPort; @@ -159,6 +160,7 @@ struct TCPINFO SOCKET FBBsock[100]; SOCKET Relaysock; SOCKET HTTPsock; + SOCKET APIsock; SOCKET TriModeSock; SOCKET TriModeDataSock; SOCKET Syncsock; @@ -169,6 +171,7 @@ struct TCPINFO SOCKET FBBsock6[100]; SOCKET Relaysock6; SOCKET HTTPsock6; + SOCKET APIsock6; SOCKET Syncsock6; SOCKET DRATSsock6; From 851dcb6fd8232cc0a265e1ba6ffa33f1f9c9b664 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Thu, 28 Dec 2023 10:33:19 +0000 Subject: [PATCH 3/7] first build of new upstream --- debian/changelog | 6 ++++++ debian/preinst | 2 ++ 2 files changed, 8 insertions(+) diff --git a/debian/changelog b/debian/changelog index c144a78..b31ed82 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +linbpq (6.0.24.25-1) UNRELEASED; urgency=medium + + * New Upstream Release + + -- Dave Hibberd Thu, 28 Dec 2023 10:31:54 +0000 + linbpq (6.0.24.22-2) unstable; urgency=medium * Moved config file home, caused chaos diff --git a/debian/preinst b/debian/preinst index 4dae0eb..c0e122c 100644 --- a/debian/preinst +++ b/debian/preinst @@ -10,3 +10,5 @@ if [ -L $confile ]; then cp $node $confile mv $node $node.bak fi + +#DEBHELPER# From 018d733deedddce26af296db8901ebe0ed1cd72a Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Thu, 28 Dec 2023 10:45:07 +0000 Subject: [PATCH 4/7] release --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index b31ed82..b02bc37 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,8 @@ -linbpq (6.0.24.25-1) UNRELEASED; urgency=medium +linbpq (6.0.24.25-1) unstable; urgency=medium * New Upstream Release - -- Dave Hibberd Thu, 28 Dec 2023 10:31:54 +0000 + -- Dave Hibberd Thu, 28 Dec 2023 10:44:47 +0000 linbpq (6.0.24.22-2) unstable; urgency=medium From 2634d16f4159b217417724b0cf2a834d5a816346 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Tue, 16 Jan 2024 20:42:28 +0000 Subject: [PATCH 5/7] New upstream version 6.0.24.27 --- ...=> BPQWinAPP.vcproj.NOTTSDESKTOP.John.user | 4 +- Bpq32.c | 8 +- ...vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user | 65 - ...cproj.LAPTOP-Q6S4RP5Q.johnw-notpi4-64.user | 65 - CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 - ...er => CBPQ32.vcproj.NOTTSDESKTOP.John.user | 4 +- CommonCode.c | 150 +- GetVersion.h | 5 +- IPCode.c | 44 + MailNode.vcproj.DESKTOP-TGEL8RC.John.user | 65 - NNTPRoutines.c | 240 +- Versions.h | 22 +- ...vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user | 65 - WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user | 65 - ...WinRPRHelper.vcproj.NOTTSDESKTOP.John.user | 4 +- ...orControl.vcproj.DESKTOP-TGEL8RC.John.user | 65 - ...rControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 - ...inmorControl.vcproj.NOTTSDESKTOP.John.user | 4 +- bbshtmlconfig.c~ | 3161 ----------------- 19 files changed, 370 insertions(+), 3796 deletions(-) rename BPQMail.vcproj.DESKTOP-TGEL8RC.John.user => BPQWinAPP.vcproj.NOTTSDESKTOP.John.user (90%) delete mode 100644 CBPQ32.vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user delete mode 100644 CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw-notpi4-64.user delete mode 100644 CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user rename CBPQ32.vcproj.DESKTOP-TGEL8RC.John.user => CBPQ32.vcproj.NOTTSDESKTOP.John.user (90%) delete mode 100644 MailNode.vcproj.DESKTOP-TGEL8RC.John.user delete mode 100644 WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user delete mode 100644 WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user rename BPQWinAPP.vcproj.DESKTOP-TGEL8RC.John.user => WinRPRHelper.vcproj.NOTTSDESKTOP.John.user (90%) delete mode 100644 WinmorControl.vcproj.DESKTOP-TGEL8RC.John.user delete mode 100644 WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user rename BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user => WinmorControl.vcproj.NOTTSDESKTOP.John.user (90%) delete mode 100644 bbshtmlconfig.c~ diff --git a/BPQMail.vcproj.DESKTOP-TGEL8RC.John.user b/BPQWinAPP.vcproj.NOTTSDESKTOP.John.user similarity index 90% rename from BPQMail.vcproj.DESKTOP-TGEL8RC.John.user rename to BPQWinAPP.vcproj.NOTTSDESKTOP.John.user index 40182c4..fa82c00 100644 --- a/BPQMail.vcproj.DESKTOP-TGEL8RC.John.user +++ b/BPQWinAPP.vcproj.NOTTSDESKTOP.John.user @@ -15,7 +15,7 @@ Attach="false" DebuggerType="3" Remote="1" - RemoteMachine="DESKTOP-TGEL8RC" + RemoteMachine="NOTTSDESKTOP" RemoteCommand="" HttpUrl="" PDBPath="" @@ -43,7 +43,7 @@ Attach="false" DebuggerType="3" Remote="1" - RemoteMachine="DESKTOP-TGEL8RC" + RemoteMachine="NOTTSDESKTOP" RemoteCommand="" HttpUrl="" PDBPath="" diff --git a/Bpq32.c b/Bpq32.c index e5868dd..bc76ca0 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1086,7 +1086,7 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // Add ? and * wildcards to NODES command (74) // Add Port RADIO config parameter (74) -// Version 6.0.24.1 August 2023 +// Version 6.0.24.1 August 2024 // Apply NODES command wildcard to alias as well a call (2) // Add STOPPORT/STARTPORT to VARA Driver (2) @@ -1204,8 +1204,10 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // Fix some Rigcontrol issues with empty timebands (22) // Fix 64 bit bug in processing INP3 Messages (22) // First pass at api (24) -// Send OK in response to Rigcontrol CMD (24); - +// Send OK in response to Rigcontrol CMD (24) +// Disable CTS check in WriteComBlock (26) +// Improvments to reporting to M0LTE Map (26) +// IPGateway fix from github user isavitsky (27) #define CKernel diff --git a/CBPQ32.vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user b/CBPQ32.vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user deleted file mode 100644 index 40b9267..0000000 --- a/CBPQ32.vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw-notpi4-64.user b/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw-notpi4-64.user deleted file mode 100644 index ddedde2..0000000 --- a/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw-notpi4-64.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user deleted file mode 100644 index ddedde2..0000000 --- a/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/CBPQ32.vcproj.DESKTOP-TGEL8RC.John.user b/CBPQ32.vcproj.NOTTSDESKTOP.John.user similarity index 90% rename from CBPQ32.vcproj.DESKTOP-TGEL8RC.John.user rename to CBPQ32.vcproj.NOTTSDESKTOP.John.user index 40b9267..f4ba73a 100644 --- a/CBPQ32.vcproj.DESKTOP-TGEL8RC.John.user +++ b/CBPQ32.vcproj.NOTTSDESKTOP.John.user @@ -15,7 +15,7 @@ Attach="false" DebuggerType="3" Remote="1" - RemoteMachine="DESKTOP-TGEL8RC" + RemoteMachine="NOTTSDESKTOP" RemoteCommand="" HttpUrl="" PDBPath="" @@ -43,7 +43,7 @@ Attach="false" DebuggerType="3" Remote="1" - RemoteMachine="DESKTOP-TGEL8RC" + RemoteMachine="NOTTSDESKTOP" RemoteCommand="" HttpUrl="" PDBPath="" diff --git a/CommonCode.c b/CommonCode.c index 31e4ebc..abcbee1 100644 --- a/CommonCode.c +++ b/CommonCode.c @@ -917,9 +917,8 @@ BOOL ProcessIncommingConnectEx(struct TNCINFO * TNC, char * Call, int Stream, BO PMSGWITHLEN buffptr; int Totallen = 0; UCHAR * ptr; - struct PORTCONTROL * PORT = TNC->PortRecord; + struct PORTCONTROL * PORT = (struct PORTCONTROL *)TNC->PortRecord; - // Stop Scanner if (Stream == 0 || TNC->Hardware == H_UZ7HO) @@ -2365,8 +2364,8 @@ BOOL WriteCOMBlock(HANDLE fd, char * Block, int BytesToWrite) Err = GetCommModemStatus(fd, &Mask); - if ((Mask & MS_CTS_ON) == 0) // trap com0com other end not open - return TRUE; +// if ((Mask & MS_CTS_ON) == 0) // trap com0com other end not open +// return TRUE; fWriteStat = WriteFile(fd, Block, BytesToWrite, &BytesWritten, NULL ); @@ -3516,6 +3515,8 @@ int __sync_lock_test_and_set(int * ptr, int val) #endif // __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ #endif // MACBPQ + + void GetSemaphore(struct SEM * Semaphore, int ID) { // @@ -3680,7 +3681,7 @@ VOID OpenReportingSockets() { // Enable Node Map Reports - ReportTimer = 600; + ReportTimer = 60; ReportSocket = socket(AF_INET,SOCK_DGRAM,0); @@ -4875,7 +4876,7 @@ static char HeaderTemplate[] = "POST %s HTTP/1.1\r\n" "Content-Type: application/json\r\n" "Host: %s:%d\r\n" "Content-Length: %d\r\n" - //r\nUser-Agent: BPQ32(G8BPQ)\r\n" + "User-Agent: %s%s\r\n" // "Expect: 100-continue\r\n" "\r\n"; @@ -4889,7 +4890,11 @@ VOID SendWebRequest(SOCKET sock, char * Host, char * Request, char * Params, int char * ptr, * ptr1; int Sent; - sprintf(Header, HeaderTemplate, Request, Host, 80, Len, Params); +#ifdef LINBPQ + sprintf(Header, HeaderTemplate, Request, Host, 80, Len, "linbpq/", VersionString, Params); +#else + sprintf(Header, HeaderTemplate, Request, Host, 80, Len, "bpq32/", VersionString, Params); +#endif Sent = send(sock, Header, (int)strlen(Header), 0); Sent = send(sock, Params, (int)strlen(Params), 0); @@ -4984,17 +4989,81 @@ VOID SendWebRequest(SOCKET sock, char * Host, char * Request, char * Params, int extern char MYALIASLOPPED[10]; extern int MasterPort[MAXBPQPORTS+1]; + +// G7TAJ // +/* + {"mheard": [ + { + "Callsign": "GB7CIP-7", + "Port": "VHF", + "Packets": 70369, + "LastHeard": "2024-12-29 20:26:32" + }, +*/ + +void BuildPortMH(char * MHJSON, struct PORTCONTROL * PORT) +{ + struct tm * TM; + static char MHTIME[50]; + time_t szClock; + MHSTRUC * MH = PORT->PORTMHEARD; + int count = MHENTRIES; + char Normcall[20]; + int len; + char * ptr; + char mhstr[400]; + + if (MH == NULL) + return; + + while (count--) + { + if (MH->MHCALL[0] == 0) + break; + + len = ConvFromAX25(MH->MHCALL, Normcall); + Normcall[len] = 0; + + ptr = &MH->MHCALL[6]; // End of Address bit + + if ((*ptr & 1) == 0) + { + // at least one digi - which we are not going to include + MH++; + continue; + } + + Normcall[len++] = 0; + + //format TIME + + szClock = MH->MHTIME; + TM = gmtime(&szClock); + sprintf(MHTIME, "%d-%d-%d %02d:%02d:%02d", + TM->tm_year+1900, TM->tm_mon + 1, TM->tm_mday, TM->tm_hour, TM->tm_min, TM->tm_sec); + + sprintf(mhstr, "{\"callSign\": \"%s\", \"port\": \"%d\", \"packets\": %d, \"lastHeard\": \"%s\" },\r\n" , + Normcall, PORT->PORTNUMBER, MH->MHCOUNT, MHTIME); + + strcat( MHJSON, mhstr ); + + MH++; + } +} + + void SendDataToPktMap(char *Msg) { SOCKET sock; char Return[256]; char Request[64]; char Params[50000]; + struct PORTCONTROL * PORT = PORTTABLE; struct PORTCONTROL * SAVEPORT; struct ROUTE * Routes = NEIGHBOURS; int MaxRoutes = MAXNEIGHBOURS; - + int PortNo; int Active; uint64_t Freq; @@ -5010,10 +5079,19 @@ void SendDataToPktMap(char *Msg) int Port = 0; char Normcall[10]; char Copy[20]; + char ID[33]; char * ptr = Params; - printf("Sending to new map\n"); +// G7TAJ // + char MHJSON[50000]; + char * mhptr; + char * b4Routesptr; + + MHJSON[0]=0; +// G7TAJ // + +// printf("Sending to new map\n"); sprintf(Request, "/api/NodeData/%s", MYNODECALL); @@ -5056,6 +5134,11 @@ void SendDataToPktMap(char *Msg) #endif ptr += sprintf(ptr, "\"source\": \"ReportedByNode\",\r\n"); +// G7TAJ // + sprintf(MHJSON, ",\"mheard\": ["); +// G7TAJ // + + //Ports ptr += sprintf(ptr, "\"ports\": ["); @@ -5256,14 +5339,27 @@ void SendDataToPktMap(char *Msg) if (Active) { + char * ptr2 = &ID[29]; + strcpy(ID, PORT->PORTDESCRIPTION); + while (*(ptr2) == ' ' && ptr2 != ID) + *(ptr2--) = 0; + ptr += sprintf(ptr, "{\"id\": \"%d\",\"linkType\": \"%s\"," "\"freq\": \"%lld\",\"mode\": \"%s\",\"modulation\": \"%s\"," "\"baud\": \"%d\",\"bitrate\": \"%d\",\"usage\": \"%s\",\"comment\": \"%s\"},\r\n", PortNo, Type, Freq, Mode, Modulation, - Baud, Bitrate, "Access", PORT->PORTDESCRIPTION); + Baud, Bitrate, "Access", ID); + +// G7TAJ // + // make MH list to be added later + BuildPortMH(MHJSON, PORT); + +// G7TAJ // + + } - + PORT = PORT->PORTPOINTER; } @@ -5272,6 +5368,10 @@ void SendDataToPktMap(char *Msg) // Neighbours +// G7TAJ // + b4Routesptr = ptr-3; +// G7TAJ // + ptr += sprintf(ptr, "\"neighbours\": [\r\n"); while (MaxRoutes--) @@ -5282,7 +5382,7 @@ void SendDataToPktMap(char *Msg) ConvFromAX25(Routes->NEIGHBOUR_CALL, Normcall); strlop(Normcall, ' '); - ptr += sprintf(ptr, + ptr += sprintf(ptr, "{\"node\": \"%s\", \"port\": \"%d\", \"quality\": \"%d\"},\r\n", Normcall, Routes->NEIGHBOUR_PORT, Routes->NEIGHBOUR_QUAL); } @@ -5290,8 +5390,30 @@ void SendDataToPktMap(char *Msg) Routes++; } - ptr -= 3; - ptr += sprintf(ptr, "]}"); +// G7TAJ // + + // if !strstr quality, then there are none, so remove neighbours portion + if ( strstr(Params, "quality") == NULL ) { + ptr = b4Routesptr; + } else { + ptr -= 3; + ptr += sprintf(ptr, "]"); + } + + if ( strlen(MHJSON) > 15 ) { + mhptr = MHJSON + strlen(MHJSON); + mhptr -= 3; + sprintf(mhptr, "]\r\n"); + ptr += sprintf(ptr, "\r\n%s", MHJSON); + + } + + ptr += sprintf(ptr, "}"); + + + +// G7TAJ // + /* { diff --git a/GetVersion.h b/GetVersion.h index c239ae1..d830bef 100644 --- a/GetVersion.h +++ b/GetVersion.h @@ -11,13 +11,14 @@ void GetVersionInfo(char * File) char isDebug[40]=""; #ifdef SPECIALVERSION + strcat(isDebug, " "); strcat(isDebug, SPECIALVERSION); #endif #ifdef _DEBUG - strcat(isDebug, "Debug Build "); + strcat(isDebug, " Debug Build"); #endif - sprintf(VersionString,"%d.%d.%d.%d %s", Ver[0], Ver[1], Ver[2], Ver[3], isDebug); + sprintf(VersionString,"%d.%d.%d.%d%s", Ver[0], Ver[1], Ver[2], Ver[3], isDebug); sprintf(TextVerstring,"V%d.%d.%d.%d", Ver[0], Ver[1], Ver[2], Ver[3]); diff --git a/IPCode.c b/IPCode.c index efc4d91..7958b73 100644 --- a/IPCode.c +++ b/IPCode.c @@ -4539,6 +4539,50 @@ void OpenTAP() return; } + // Fix from github user isavitsky + + /* + * After some research I found that on most of my + * systems, including Raspberry Pi IV, a slight delay + * is needed before considering the TAP device + * up and running. Otherwise the interface structures + * do not initialise properly and later in the code + * around the line 4700 when we initialise our ARP + * structure: + * + * memcpy(Arp->HWADDR, xbuffer.ifr_hwaddr.sa_data, 6); + * + * the MAC address is getting filled in with random + * value which makes the communication via our TAP + * device using the configured IPADDR virtually + * impossible. + * + */ + + Debugprintf("Waiting for the TAP to become UP and RUNNING"); + + for (int i=10; i>0; i--) + { + Sleep(10); + + if ((err = ioctl(sockfd, SIOCGIFFLAGS, &ifr)) < 0) + { + perror("SIOCGIFFLAGS"); + return; + } + + if((ifr.ifr_flags & IFF_UP) && (ifr.ifr_flags & IFF_RUNNING)) + { + Debugprintf("TAP is UP and RUNNING"); + break; + } + else if (i == 1) + { + Debugprintf("TAP is still not UP and RUNNING"); + return; + } + } + printf("TAP brought up\n"); // Set MTU to 256 diff --git a/MailNode.vcproj.DESKTOP-TGEL8RC.John.user b/MailNode.vcproj.DESKTOP-TGEL8RC.John.user deleted file mode 100644 index 40182c4..0000000 --- a/MailNode.vcproj.DESKTOP-TGEL8RC.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/NNTPRoutines.c b/NNTPRoutines.c index 2875a06..16b6478 100644 --- a/NNTPRoutines.c +++ b/NNTPRoutines.c @@ -41,6 +41,87 @@ char *day[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; VOID ReleaseNNTPSock(SOCKET sock); +int NNTPSendSock(SocketConn * sockptr, char * msg) +{ + int len = (int)strlen(msg); + char * newmsg = malloc(len+10); + + WriteLogLine(NULL, '>',msg, len, LOG_TCP); + + strcpy(newmsg, msg); + + strcat(newmsg, "\r\n"); + + len+=2; + + // Attempt to fix Thunderbird - Queue all and send at end + + if ((sockptr->SendSize + len) > sockptr->SendBufferSize) + { + sockptr->SendBufferSize += (10000 + len); + sockptr->SendBuffer = realloc(sockptr->SendBuffer, sockptr->SendBufferSize); + } + + memcpy(&sockptr->SendBuffer[sockptr->SendSize], newmsg, len); + sockptr->SendSize += len; + free (newmsg); + return len; +} + +void NNTPFlush(SocketConn * sockptr) +{ + int sent; + + sent = send(sockptr->socket, sockptr->SendBuffer, sockptr->SendSize, 0); + + if (sent < sockptr->SendSize) + { + int error, remains; + + // Not all could be sent - queue rest + + if (sent == SOCKET_ERROR) + { + error = WSAGetLastError(); + if (error == WSAEWOULDBLOCK) + sent=0; + + // What else?? + } + + remains = sockptr->SendSize - sent; + + sockptr->SendBufferSize += (10000 + remains); + sockptr->SendBuffer = malloc(sockptr->SendBufferSize); + + memmove(sockptr->SendBuffer, &sockptr->SendBuffer[sent], remains); + + sockptr->SendSize = remains; + sockptr->SendPtr = 0; + + return; + } + + free(sockptr->SendBuffer); + sockptr->SendBuffer = NULL; + sockptr->SendSize = 0; + sockptr->SendBufferSize = 0; + return; +} + +VOID __cdecl NNTPsockprintf(SocketConn * sockptr, const char * format, ...) +{ + // printf to a socket + + char buff[1000]; + va_list(arglist); + + va_start(arglist, format); + vsprintf(buff, format, arglist); + + NNTPSendSock(sockptr, buff); +} + struct NNTPRec * LookupNNTP(char * Group) { struct NNTPRec * ptr = FirstNNTPRec; @@ -304,7 +385,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (ptr2 == NULL) { - SendSock(sockptr, "500 Eh"); + NNTPSendSock(sockptr, "500 Eh"); return; } @@ -428,7 +509,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) sockptr->Flags &= ~GETTINGMESSAGE; - SendSock(sockptr, "240 OK"); + NNTPSendSock(sockptr, "240 OK"); return; } @@ -459,13 +540,13 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (Len > 22) Buffer[22]=0; strcpy(sockptr->CallSign, &Buffer[14]); sockptr->State = GettingPass; - sockprintf(sockptr, "381 More authentication information required"); + NNTPsockprintf(sockptr, "381 More authentication information required"); return; } if (sockptr->State == GettingUser) { - sockprintf(sockptr, "480 Authentication required"); + NNTPsockprintf(sockptr, "480 Authentication required"); return; } @@ -481,19 +562,19 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) { if (strcmp(user->pass, &Buffer[14]) == 0) { - sockprintf(sockptr, "281 Authentication accepted"); + NNTPsockprintf(sockptr, "281 Authentication accepted"); sockptr->State = Authenticated; sockptr->POP3User = user; return; } } - SendSock(sockptr, "482 Authentication rejected"); + NNTPSendSock(sockptr, "482 Authentication rejected"); sockptr->State = GettingUser; return; } - sockprintf(sockptr, "480 Authentication required"); + NNTPsockprintf(sockptr, "480 Authentication required"); return; } @@ -506,7 +587,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) { if (_stricmp(REC->NewsGroup, &Buffer[6]) == 0) { - sockprintf(sockptr, "211 %d %d %d %s", REC->Count, REC->FirstMsg, REC->LastMsg, REC->NewsGroup); + NNTPsockprintf(sockptr, "211 %d %d %d %s", REC->Count, REC->FirstMsg, REC->LastMsg, REC->NewsGroup); sockptr->NNTPNum = 0; sockptr->NNTPGroup = REC; return; @@ -514,7 +595,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) REC =REC->Next; } - sockprintf(sockptr, "411 no such news group"); + NNTPsockprintf(sockptr, "411 no such news group"); return; } @@ -528,7 +609,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (REC == NULL && Buffer[10] == 0) { - sockprintf(sockptr, "412 No Group Selected"); + NNTPsockprintf(sockptr, "412 No Group Selected"); return; } @@ -543,7 +624,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) { GotGroup: - sockprintf(sockptr, "211 Article Numbers Follows"); + NNTPsockprintf(sockptr, "211 Article Numbers Follows"); sockptr->NNTPNum = 0; sockptr->NNTPGroup = REC; @@ -557,22 +638,22 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) sprintf(FullGroup, "%s.%s", Msg->to, Msg->via ); if (_stricmp(FullGroup, REC->NewsGroup) == 0) { - sockprintf(sockptr, "%d", MsgNo); + NNTPsockprintf(sockptr, "%d", MsgNo); } } } - SendSock(sockptr,"."); + NNTPSendSock(sockptr,"."); return; } REC = REC->Next; } - sockprintf(sockptr, "411 no such news group"); + NNTPsockprintf(sockptr, "411 no such news group"); return; } if(_memicmp(Buffer, "MODE READER", 11) == 0) { - SendSock(sockptr, "200 Hello"); + NNTPSendSock(sockptr, "200 Hello"); return; } @@ -580,15 +661,15 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) { struct NNTPRec * REC = FirstNNTPRec; - SendSock(sockptr, "215 list of newsgroups follows"); + NNTPSendSock(sockptr, "215 list of newsgroups follows"); while (REC) { - sockprintf(sockptr, "%s %d %d y", REC->NewsGroup, REC->LastMsg, REC->FirstMsg); + NNTPsockprintf(sockptr, "%s %d %d y", REC->NewsGroup, REC->LastMsg, REC->FirstMsg); REC = REC->Next; } - SendSock(sockptr,"."); + NNTPSendSock(sockptr,"."); return; } @@ -615,16 +696,16 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) else Time = mktime(&rtime); - SendSock(sockptr, "231 list of new newsgroups follows"); + NNTPSendSock(sockptr, "231 list of new newsgroups follows"); while(REC) { if (REC->DateCreated > Time) - sockprintf(sockptr, "%s %d %d y", REC->NewsGroup, REC->LastMsg, REC->FirstMsg); + NNTPsockprintf(sockptr, "%s %d %d y", REC->NewsGroup, REC->LastMsg, REC->FirstMsg); REC = REC->Next; } - SendSock(sockptr,"."); + NNTPSendSock(sockptr,"."); return; } @@ -636,7 +717,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (REC == NULL) { - SendSock(sockptr,"412 no newsgroup has been selected"); + NNTPSendSock(sockptr,"412 no newsgroup has been selected"); return; } @@ -646,7 +727,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (MsgNo == 0) { - SendSock(sockptr,"420 no current article has been selected"); + NNTPSendSock(sockptr,"420 no current article has been selected"); return; } } @@ -659,20 +740,20 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (Msg) { - sockprintf(sockptr, "221 %d <%s>", MsgNo, Msg->bid); + NNTPsockprintf(sockptr, "221 %d <%s>", MsgNo, Msg->bid); - sockprintf(sockptr, "From: %s", Msg->from); - sockprintf(sockptr, "Date: %s", FormatNNTPDateAndTime((time_t)Msg->datecreated)); - sockprintf(sockptr, "Newsgroups: %s.s", Msg->to, Msg->via); - sockprintf(sockptr, "Subject: %s", Msg->title); - sockprintf(sockptr, "Message-ID: <%s>", Msg->bid); - sockprintf(sockptr, "Path: %s", BBSName); + NNTPsockprintf(sockptr, "From: %s", Msg->from); + NNTPsockprintf(sockptr, "Date: %s", FormatNNTPDateAndTime((time_t)Msg->datecreated)); + NNTPsockprintf(sockptr, "Newsgroups: %s.s", Msg->to, Msg->via); + NNTPsockprintf(sockptr, "Subject: %s", Msg->title); + NNTPsockprintf(sockptr, "Message-ID: <%s>", Msg->bid); + NNTPsockprintf(sockptr, "Path: %s", BBSName); - SendSock(sockptr,"."); + NNTPSendSock(sockptr,"."); return; } - SendSock(sockptr,"423 No such article in this newsgroup"); + NNTPSendSock(sockptr,"423 No such article in this newsgroup"); return; } @@ -686,7 +767,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (REC == NULL) { - SendSock(sockptr,"412 no newsgroup has been selected"); + NNTPSendSock(sockptr,"412 no newsgroup has been selected"); return; } @@ -696,7 +777,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (MsgNo == 0) { - SendSock(sockptr,"420 no current article has been selected"); + NNTPSendSock(sockptr,"420 no current article has been selected"); return; } } @@ -709,25 +790,25 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (Msg) { - sockprintf(sockptr, "220 %d <%s>", MsgNo, Msg->bid); + NNTPsockprintf(sockptr, "220 %d <%s>", MsgNo, Msg->bid); msgbytes = ReadMessageFile(Msg->number); Path = GetPathFromHeaders(msgbytes); - sockprintf(sockptr, "From: %s", Msg->from); - sockprintf(sockptr, "Date: %s", FormatNNTPDateAndTime((time_t)Msg->datecreated)); - sockprintf(sockptr, "Newsgroups: %s.%s", Msg->to, Msg->via); - sockprintf(sockptr, "Subject: %s", Msg->title); - sockprintf(sockptr, "Message-ID: <%s>", Msg->bid); - sockprintf(sockptr, "Path: %s", &Path[1]); + NNTPsockprintf(sockptr, "From: %s", Msg->from); + NNTPsockprintf(sockptr, "Date: %s", FormatNNTPDateAndTime((time_t)Msg->datecreated)); + NNTPsockprintf(sockptr, "Newsgroups: %s.%s", Msg->to, Msg->via); + NNTPsockprintf(sockptr, "Subject: %s", Msg->title); + NNTPsockprintf(sockptr, "Message-ID: <%s>", Msg->bid); + NNTPsockprintf(sockptr, "Path: %s", &Path[1]); - SendSock(sockptr,""); + NNTPSendSock(sockptr,""); - SendSock(sockptr,msgbytes); - SendSock(sockptr,""); + NNTPSendSock(sockptr,msgbytes); + NNTPSendSock(sockptr,""); - SendSock(sockptr,"."); + NNTPSendSock(sockptr,"."); free(msgbytes); free(Path); @@ -735,7 +816,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) return; } - SendSock(sockptr,"423 No such article in this newsgroup"); + NNTPSendSock(sockptr,"423 No such article in this newsgroup"); return; } @@ -749,7 +830,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (REC == NULL) { - SendSock(sockptr,"412 no newsgroup has been selected"); + NNTPSendSock(sockptr,"412 no newsgroup has been selected"); return; } @@ -759,7 +840,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (MsgNo == 0) { - SendSock(sockptr,"420 no current article has been selected"); + NNTPSendSock(sockptr,"420 no current article has been selected"); return; } } @@ -772,15 +853,15 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (Msg) { - sockprintf(sockptr, "222 %d <%s>", MsgNo, Msg->bid); + NNTPsockprintf(sockptr, "222 %d <%s>", MsgNo, Msg->bid); msgbytes = ReadMessageFile(Msg->number); Path = GetPathFromHeaders(msgbytes); - SendSock(sockptr,msgbytes); - SendSock(sockptr,""); + NNTPSendSock(sockptr,msgbytes); + NNTPSendSock(sockptr,""); - SendSock(sockptr,"."); + NNTPSendSock(sockptr,"."); free(msgbytes); free(Path); @@ -788,7 +869,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) return; } - SendSock(sockptr,"423 No such article in this newsgroup"); + NNTPSendSock(sockptr,"423 No such article in this newsgroup"); return; } @@ -801,7 +882,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (REC == NULL) { - SendSock(sockptr,"412 no newsgroup has been selected"); + NNTPSendSock(sockptr,"412 no newsgroup has been selected"); return; } @@ -821,7 +902,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (MsgStart == 0) { - SendSock(sockptr,"420 no current article has been selected"); + NNTPSendSock(sockptr,"420 no current article has been selected"); return; } } @@ -830,7 +911,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) sockptr->NNTPNum = MsgEnd; } - sockprintf(sockptr, "221 "); + NNTPsockprintf(sockptr, "221 "); for (MsgNo = MsgStart; MsgNo <= MsgEnd; MsgNo++) { @@ -843,20 +924,20 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (_stricmp(FullGroup, REC->NewsGroup) == 0) { if (_stricmp(Header, "subject") == 0) - sockprintf(sockptr, "%d Subject: %s", MsgNo, Msg->title); + NNTPsockprintf(sockptr, "%d Subject: %s", MsgNo, Msg->title); else if (_stricmp(Header, "from") == 0) - sockprintf(sockptr, "%d From: %s", MsgNo, Msg->from); + NNTPsockprintf(sockptr, "%d From: %s", MsgNo, Msg->from); else if (_stricmp(Header, "date") == 0) - sockprintf(sockptr, "%d Date: %s", MsgNo, FormatNNTPDateAndTime((time_t)Msg->datecreated)); + NNTPsockprintf(sockptr, "%d Date: %s", MsgNo, FormatNNTPDateAndTime((time_t)Msg->datecreated)); else if (_stricmp(Header, "message-id") == 0) - sockprintf(sockptr, "%d Message-ID: <%s>", MsgNo, Msg->bid); + NNTPsockprintf(sockptr, "%d Message-ID: <%s>", MsgNo, Msg->bid); else if (_stricmp(Header, "lines") == 0) - sockprintf(sockptr, "%d Lines: %d", MsgNo, Msg->length); + NNTPsockprintf(sockptr, "%d Lines: %d", MsgNo, Msg->length); } } } - SendSock(sockptr,"."); + NNTPSendSock(sockptr,"."); return; } @@ -869,7 +950,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (REC == NULL) { - SendSock(sockptr,"412 no newsgroup has been selected"); + NNTPSendSock(sockptr,"412 no newsgroup has been selected"); return; } @@ -887,7 +968,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (MsgStart == 0) { - SendSock(sockptr,"420 no current article has been selected"); + NNTPSendSock(sockptr,"420 no current article has been selected"); return; } } @@ -896,7 +977,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) sockptr->NNTPNum = MsgEnd; } - sockprintf(sockptr, "224 "); + NNTPsockprintf(sockptr, "224 "); for (MsgNo = MsgStart; MsgNo <= MsgEnd; MsgNo++) { @@ -909,14 +990,14 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (_stricmp(FullGroup, REC->NewsGroup) == 0) { // subject, author, date, message-id, references, byte count, and line count. - sockprintf(sockptr, "%d\t%s\t%s\t%s\t%s\t%s\t%d\t%d", + NNTPsockprintf(sockptr, "%d\t%s\t%s\t%s\t%s\t%s\t%d\t%d", MsgNo, Msg->title, Msg->from, FormatNNTPDateAndTime((time_t)Msg->datecreated), Msg->bid, "", Msg->length, Msg->length); } } } - SendSock(sockptr,"."); + NNTPSendSock(sockptr,"."); return; } @@ -932,7 +1013,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) { if (sockptr->State != Authenticated) { - sockprintf(sockptr, "480 Authentication required"); + NNTPsockprintf(sockptr, "480 Authentication required"); return; } @@ -942,7 +1023,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if (sockptr->MailBuffer == NULL) { CriticalErrorHandler("Failed to create POP3 Message Buffer"); - SendSock(sockptr, "QUIT"); + NNTPSendSock(sockptr, "QUIT"); sockptr->State = WaitingForQUITResponse; shutdown(sock, 0); @@ -951,7 +1032,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) sockptr->Flags |= GETTINGMESSAGE; - SendSock(sockptr, "340 OK"); + NNTPSendSock(sockptr, "340 OK"); return; } @@ -959,7 +1040,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) if(_memicmp(Buffer, "QUIT", 4) == 0) { - SendSock(sockptr, "205 OK"); + NNTPSendSock(sockptr, "205 OK"); Sleep(500); shutdown(sock, 0); return; @@ -967,7 +1048,7 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) /* if(memcmp(Buffer, "RSET\r\n", 6) == 0) { - SendSock(sockptr, "250 Ok"); + NNTPSendSock(sockptr, "250 Ok"); sockptr->State = 0; sockptr->Recipients; return; @@ -991,15 +1072,15 @@ VOID ProcessNNTPServerMessage(SocketConn * sockptr, char * Buffer, int Len) sprintf_s(Date, sizeof(Date), "111 %04d%02d%02d%02d%02d%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - SendSock(sockptr, Date); + NNTPSendSock(sockptr, Date); } else - SendSock(sockptr, "500 command not recognized"); + NNTPSendSock(sockptr, "500 command not recognized"); return; } - SendSock(sockptr, "500 command not recognized"); + NNTPSendSock(sockptr, "500 command not recognized"); return; } @@ -1068,6 +1149,9 @@ loop: } } + + NNTPFlush(sockptr); + return 0; } @@ -1110,9 +1194,11 @@ int NNTP_Accept(SOCKET SocketId) sockptr->socket = sock; sockptr->State = 0; - SendSock(sockptr, "200 BPQMail NNTP Server ready"); + NNTPSendSock(sockptr, "200 BPQMail NNTP Server ready"); Logprintf(LOG_TCP, NULL, '|', "Incoming NNTP Connect Socket = %d", sock); + NNTPFlush(sockptr); + return 0; } /* @@ -1144,7 +1230,7 @@ int NNTP_Data(int sock, int error, int eventcode) SendFromQueue(sockptr); else { - SendSock(sockptr, "200 BPQMail NNTP Server ready"); + NNTPSendSock(sockptr, "200 BPQMail NNTP Server ready"); // sockptr->State = GettingUser; } diff --git a/Versions.h b/Versions.h index f880e42..d86948c 100644 --- a/Versions.h +++ b/Versions.h @@ -10,16 +10,16 @@ #endif -#define KVers 6,0,24,25 -#define KVerstring "6.0.24.25\0" +#define KVers 6,0,24,27 +#define KVerstring "6.0.24.27\0" #ifdef CKernel #define Vers KVers #define Verstring KVerstring -#define Datestring "December 2023" +#define Datestring "January 2024" #define VerComments "G8BPQ Packet Switch (C Version)" KVerstring -#define VerCopyright "Copyright © 2001-2023 John Wiseman G8BPQ\0" +#define VerCopyright "Copyright © 2001-2024 John Wiseman G8BPQ\0" #define VerDesc "BPQ32 Switch\0" #define VerProduct "BPQ32" @@ -30,7 +30,7 @@ #define Vers 1,0,16,2 #define Verstring "1.0.16.2\0" #define VerComments "Internet Terminal for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2011-2023 John Wiseman G8BPQ\0" +#define VerCopyright "Copyright © 2011-2024 John Wiseman G8BPQ\0" #define VerDesc "Simple TCP Terminal Program for G8BPQ Switch\0" #define VerProduct "BPQTermTCP" @@ -41,7 +41,7 @@ #define Vers 2,2,5,2 #define Verstring "2.2.5.2\0" #define VerComments "Simple Terminal for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 1999-2023 John Wiseman G8BPQ\0" +#define VerCopyright "Copyright © 1999-2024 John Wiseman G8BPQ\0" #define VerDesc "Simple Terminal Program for G8BPQ Switch\0" #define VerProduct "BPQTerminal" @@ -52,7 +52,7 @@ #define Vers 2,2,0,3 #define Verstring "2.2.0.3\0" #define VerComments "MDI Terminal for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 1999-2023 John Wiseman G8BPQ\0" +#define VerCopyright "Copyright © 1999-2024 John Wiseman G8BPQ\0" #define VerDesc "MDI Terminal Program for G8BPQ Switch\0" #endif @@ -62,7 +62,7 @@ #define Vers KVers #define Verstring KVerstring #define VerComments "Mail server for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2009-2023 John Wiseman G8BPQ\0" +#define VerCopyright "Copyright © 2009-2024 John Wiseman G8BPQ\0" #define VerDesc "Mail server for G8BPQ's 32 Bit Switch\0" #define VerProduct "BPQMail" @@ -97,7 +97,7 @@ #define Vers 0,1,0,0 #define Verstring "0.1.0.0\0" #define VerComments "Password Generation Utility for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2011-2023 John Wiseman G8BPQ\0" +#define VerCopyright "Copyright © 2011-2024 John Wiseman G8BPQ\0" #define VerDesc "Password Generation Utility for G8BPQ Switch\0" #endif @@ -107,7 +107,7 @@ #define Vers KVers #define Verstring KVerstring #define VerComments "APRS Client for G8BPQ Switch\0" -#define VerCopyright "Copyright © 2012-2023 John Wiseman G8BPQ\0" +#define VerCopyright "Copyright © 2012-2024 John Wiseman G8BPQ\0" #define VerDesc "APRS Client for G8BPQ Switch\0" #define VerProduct "BPQAPRS" @@ -118,7 +118,7 @@ #define Vers KVers #define Verstring KVerstring #define VerComments "Chat server for G8BPQ Packet Switch\0" -#define VerCopyright "Copyright © 2009-2023 John Wiseman G8BPQ\0" +#define VerCopyright "Copyright © 2009-2024 John Wiseman G8BPQ\0" #define VerDesc "Chat server for G8BPQ's 32 Bit Switch\0" #define VerProduct "BPQChat" diff --git a/WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user b/WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user deleted file mode 100644 index 40182c4..0000000 --- a/WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John-notpi4-64.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user b/WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user deleted file mode 100644 index 40182c4..0000000 --- a/WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQWinAPP.vcproj.DESKTOP-TGEL8RC.John.user b/WinRPRHelper.vcproj.NOTTSDESKTOP.John.user similarity index 90% rename from BPQWinAPP.vcproj.DESKTOP-TGEL8RC.John.user rename to WinRPRHelper.vcproj.NOTTSDESKTOP.John.user index 40182c4..fa82c00 100644 --- a/BPQWinAPP.vcproj.DESKTOP-TGEL8RC.John.user +++ b/WinRPRHelper.vcproj.NOTTSDESKTOP.John.user @@ -15,7 +15,7 @@ Attach="false" DebuggerType="3" Remote="1" - RemoteMachine="DESKTOP-TGEL8RC" + RemoteMachine="NOTTSDESKTOP" RemoteCommand="" HttpUrl="" PDBPath="" @@ -43,7 +43,7 @@ Attach="false" DebuggerType="3" Remote="1" - RemoteMachine="DESKTOP-TGEL8RC" + RemoteMachine="NOTTSDESKTOP" RemoteCommand="" HttpUrl="" PDBPath="" diff --git a/WinmorControl.vcproj.DESKTOP-TGEL8RC.John.user b/WinmorControl.vcproj.DESKTOP-TGEL8RC.John.user deleted file mode 100644 index 40182c4..0000000 --- a/WinmorControl.vcproj.DESKTOP-TGEL8RC.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user deleted file mode 100644 index 0cd9a72..0000000 --- a/WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/WinmorControl.vcproj.NOTTSDESKTOP.John.user similarity index 90% rename from BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user rename to WinmorControl.vcproj.NOTTSDESKTOP.John.user index 0cd9a72..fa82c00 100644 --- a/BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user +++ b/WinmorControl.vcproj.NOTTSDESKTOP.John.user @@ -15,7 +15,7 @@ Attach="false" DebuggerType="3" Remote="1" - RemoteMachine="LAPTOP-Q6S4RP5Q" + RemoteMachine="NOTTSDESKTOP" RemoteCommand="" HttpUrl="" PDBPath="" @@ -43,7 +43,7 @@ Attach="false" DebuggerType="3" Remote="1" - RemoteMachine="LAPTOP-Q6S4RP5Q" + RemoteMachine="NOTTSDESKTOP" RemoteCommand="" HttpUrl="" PDBPath="" diff --git a/bbshtmlconfig.c~ b/bbshtmlconfig.c~ deleted file mode 100644 index 33c1048..0000000 --- a/bbshtmlconfig.c~ +++ /dev/null @@ -1,3161 +0,0 @@ -/* -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 -#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[]; -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; -extern int reportMailEvents; - -#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); - -char UNC[] = ""; -char CHKD[] = "checked=checked "; -char sel[] = "selected"; - -char Sent[] = "#98FFA0"; -char ToSend[] = "#FFFF00"; -char NotThisOne[] = "#FFFFFF"; - -static char PassError[] = "

Sorry, User or Password is invalid - please try again

"; - -static char BusyError[] = "

Sorry, No sessions available - please try later

"; - -extern char WebMailSignon[]; - -char MailSignon[] = "BPQ32 Mail Server Access" - "

BPQ32 Mail Server %s Access

" - "

Please enter Callsign and Password to access the BBS

" - "" - "" - "" - "
User
Password
" - "

"; - - -char MailPage[] = "%s's BBS Web Server" - "" - "" - "

BPQ32 BBS %s

" - "

" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "
StatusConfigurationUsersMessagesForwardingWelcome Msgs & PromptsHousekeepingWP UpdateNode Menu
"; - -char RefreshMainPage[] = "" - "" - "" - "%s's BBS Web Server" - "

BPQ32 BBS %s

" - "

" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "
StatusConfigurationUsersMessagesForwardingWelcome Msgs & PromptsHousekeepingWP UpdateNode Menu
"; - -char StatusPage [] = - -"

" -"
User     Callsign   Stream Queue
" -"


"; - -char StatusTail[] = -"Msgs      
" -"Sysop Msgs
" -"Held Msgs 
" -"SMTP Msgs 
"; - - -char UIHddr [] = "
Mailfor Header
" -"           " -"    (use \\r to insert newline in message)

" -"Enable Port           " -"             Path           " -"                   Send: MailFor Headers Empty Mailfor

"; - -char UILine[] = " %s " -" " -"    " -"       
"; - -char UITail[] = "

" -"
"; - -char FWDSelectHddr[] = - "
" - "Max Size to Send   
" - "Max Size to Receive
" - "Warn if no route for P or T
" - "Use Local Time              " - "

" - "Aliases                   Select BBS
" - "  
         " - " 
"; - -char UserSelectHddr[] = - "
" - "Please Select User



" - "" - "
" - " " - "
"; - -char UserUpdateHddr[] = - "

Update User %s

" - "
"; - -char UserUpdateLine[] = ""; - -// -//
- - -char FWDUpdate[] = -"

Update Forwarding for BBS %s

" -"    " -"TO            " -"AT          " -"TIMES         Connect Script
" -"" -" " -" " -"
" -"" -"

" -"Enable Forwarding  Interval" -"(Secs) Request Reverse" -" Interval (Secs)
" -"Send new messages without waiting for poll timer
" -"BBS HA FBB Max Block
" -"Send Personal Mail Only  " -"Allow Binary     Use B1 " -"Protocol   Use B2 Protocol

" -" " -"

"; - -static char MailDetailPage[] = -"" -"MsgEdit

Message %d

" -"
" -"From  Sent   " -"       " -"Type     
" -"To    " -" Received      " -"Status   
" -"BID   Last Changed  " -"Size 

" -"%s" // Email from Line -" VIA 
" -"Title 

" -" " -" " -"" -"" -//" " -" " -"

" -"Green = Sent, Yellow = Queued" -""; - -char MailDetailTail[] = "
"; - -char Welcome[] = "
" -"Normal User Welcome
" -"
" -"New User Welcome
" -"
" -"Expert User Welcome
" -"
" -"Normal User Prompt
" -"
" -"New User Prompt
" -"
" -"Expert User Prompt
" -"
" -"Signoff
" -"

" -"$U:Callsign of the user  $I:First name of the user $X:Messages for user $x:Unread messages
" -"$L:Number of the latest message $N:Number of active messages. $Z:Last message read by user

" -" "; - -static char MsgEditPage[] = "" -"" -"
" -"

" -"
"; - -static char WPDetail[] = "
" -"
" - -"" -"" -"" -"" -"" -"" -"" -"" -"" -"" -"" -"" -"
Call
Name
Home BBS 1
Home BBS 2
QTH 1
QTH 2
ZIP 1
ZIP 2
Last Seen
Last Modified
Type
Changed
Seen
" -"
" -" " -"
"; - - -static char LostSession[] = "" -"
" -"Sorry, Session had been lost

    " -"
"; - - -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); -} - - -void ConvertTitletoUTF8(WebMailInfo * WebMail, char * Title, char * UTF8Title, int Len) -{ - if (WebIsUTF8(Title, (int)strlen(Title)) == FALSE) - { - // With Windows it is simple - convert using current codepage - // I think the only reliable way is to convert to unicode and back - - int origlen = (int)strlen(Title) + 1; -#ifdef WIN32 - WCHAR BufferW[128]; - int wlen; - int len = origlen; - - wlen = MultiByteToWideChar(CP_ACP, 0, Title, len, BufferW, origlen * 2); - len = WideCharToMultiByte(CP_UTF8, 0, BufferW, wlen, UTF8Title, origlen * 2, NULL, NULL); -#else - size_t left = Len - 1; - size_t len = origlen; - - iconv_t * icu = WebMail->iconv_toUTF8; - - if (WebMail->iconv_toUTF8 == NULL) - icu = WebMail->iconv_toUTF8 = iconv_open("UTF-8//IGNORE", "CP1252"); - - if (icu == (iconv_t)-1) - { - strcpy(UTF8Title, Title); - WebMail->iconv_toUTF8 = NULL; - return; - } - - char * orig = UTF8Title; - - iconv(icu, NULL, NULL, NULL, NULL); // Reset State Machine - iconv(icu, &Title, &len, (char ** __restrict__)&UTF8Title, &left); - -#endif - } - else - strcpy(UTF8Title, Title); -} - -BOOL GotFirstMessage = 0; - -void ProcessMailHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, char * URL, char * input, char * Reply, int * RLen, int InputLen) -{ - 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; - - if (Session->TNC == (void *)1) // Re-using an address as a flag - 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; - - } - - // 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, "", Session->Key); - } - - GotFirstMessage = 1; - return; - } - - if (_memicmp(URL, "/Mail/API/", 10) == 0) - { - *RLen = APIProcessHTTPMessage(Reply, Method, URL, input, LOCAL, 0); - return; - } - - - 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
", 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]; - - if ((USER->flags & F_BBS)) - if (USER->BBSNumber) - bbs[i++] = USER; - } - - qsort((void *)bbs, i, sizeof(void *), compare ); - - n = 0; - - for (y = 0; y < NBBBS/8; y++) - { - len += sprintf(&Reply[len],""); - 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],"%s", - Colour, bbs[n]->BBSNumber, bbs[n]->Call); - } - else - len += sprintf(&Reply[len], " "); - - n++; - } - len += sprintf(&Reply[len],""); - 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); - GetCheckBox(input, "Events=", &reportMailEvents); - - 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="); - - // 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="); - } - - 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); - - // 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, "

Copy From BBS %s not found

", 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", ""); - 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", ""); - - } - } - 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) -{ - int Len, i; - - 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] = ""; - - char FBBFilters[100000] = ""; - - - char * ptr = FBBFilters; - FBBFilter * Filter = Filters; - - 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); - - // set up FB style fiters - - ptr += sprintf(ptr, - ""); - - while(Filter) - { - ptr += sprintf(ptr, "" - "" - "" - "" - "" - "" - "" - "", - 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, "" - "" - "" - "" - "" - "" - "" - "", ' ', ' ', "", "", "", "", 0); - } - - ptr += sprintf(ptr, "
ActionTypeFromTo@BBSBidMax Size
"); - - Debugprintf("%d", strlen(FBBFilters)); - - 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, - (reportMailEvents) ? CHKD : UNC, - 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, - RF, RT, RA, RB, HF, HT, HA, HB, FBBFilters); - - *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, - 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 - -int ProcessWebmailWebSock(char * MsgPtr, char * OutBuffer); - -static char PipeFileName[] = "\\\\.\\pipe\\BPQMailWebPipe"; - -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. -{ - 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; - struct HTTPConnectionInfo Session; - char URL[100001]; - char * Context, * Method; - int n; - - char * ptr; - - // The thread's parameter is a handle to a pipe object instance. - - hPipe = (HANDLE) lpvParam; - - // 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); - - if (!fSuccess || InputLen == 0) - { - if (GetLastError() == ERROR_BROKEN_PIPE) - Debugprintf("InstanceThread: client disconnected.", GetLastError()); - else - Debugprintf("InstanceThread ReadFile failed, GLE=%d.", GetLastError()); - - return 1; - } - - Buffer[InputLen] = 0; - - MsgPtr = &Buffer[0]; - - if (memcmp(MsgPtr, "WMRefresh", 9) == 0) - { - OutputLen = ProcessWebmailWebSock(MsgPtr, OutBuffer); - } - else - { - strcpy(URL, MsgPtr); - - ptr = strstr(URL, " HTTP"); - - if (ptr) - *ptr = 0; - - Method = strtok_s(URL, " ", &Context); - - ProcessMailHTTPMessage(&Session, Method, Context, MsgPtr, OutBuffer, &OutputLen, InputLen); - } - - WriteFile(hPipe, &Session, sizeof (struct HTTPConnectionInfo), &n, NULL); - WriteFile(hPipe, OutBuffer, OutputLen, &cbWritten, NULL); - - FlushFileBuffers(hPipe); - DisconnectNamedPipe(hPipe); - CloseHandle(hPipe); - - 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); -} - - - - - - - From eec767af842d90b0fc59489902a624a25355ad72 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Tue, 16 Jan 2024 20:44:01 +0000 Subject: [PATCH 6/7] First build of new revision --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index b02bc37..1f3055f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +linbpq (6.0.24.27-1) UNRELEASED; urgency=medium + + * New Upstream Release + + -- Dave Hibberd Tue, 16 Jan 2024 20:42:47 +0000 + linbpq (6.0.24.25-1) unstable; urgency=medium * New Upstream Release From 710cc6fde7454126b4b749cc121c4bd0860aeb7f Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Tue, 16 Jan 2024 20:52:57 +0000 Subject: [PATCH 7/7] Release --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 1f3055f..cabb37c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,8 @@ -linbpq (6.0.24.27-1) UNRELEASED; urgency=medium +linbpq (6.0.24.27-1) unstable; urgency=medium * New Upstream Release - -- Dave Hibberd Tue, 16 Jan 2024 20:42:47 +0000 + -- Dave Hibberd Tue, 16 Jan 2024 20:51:43 +0000 linbpq (6.0.24.25-1) unstable; urgency=medium