New upstream version 6.0.24.25

This commit is contained in:
Dave Hibberd 2023-12-28 10:31:09 +00:00
parent 2ccd083256
commit 7a61c594e1
38 changed files with 5370 additions and 387 deletions

View File

@ -38,6 +38,7 @@ extern char LTATString[2048];
//static UCHAR BPQDirectory[260]; //static UCHAR BPQDirectory[260];
extern ConnectionInfo Connections[]; extern ConnectionInfo Connections[];
extern int NumberofStreams; extern int NumberofStreams;
extern time_t MaintClock; // Time to run housekeeping extern time_t MaintClock; // Time to run housekeeping
@ -49,6 +50,7 @@ extern int MaxChatStreams;
extern char Position[81]; extern char Position[81];
extern char PopupText[251]; extern char PopupText[251];
extern int PopupMode; extern int PopupMode;
extern int reportMailEvents;
#define MaxCMS 10 // Numbr of addresses we can keep - currently 4 are used. #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); struct UserInfo * FindBBS(char * Name);
void ReleaseWebMailStruct(WebMailInfo * WebMail); void ReleaseWebMailStruct(WebMailInfo * WebMail);
VOID TidyWelcomeMsg(char ** pPrompt); VOID TidyWelcomeMsg(char ** pPrompt);
int MailAPIProcessHTTPMessage(char * response, char * Method, char * URL, char * request, BOOL LOCAL, char * Param);
char UNC[] = ""; char UNC[] = "";
char CHKD[] = "checked=checked "; char CHKD[] = "checked=checked ";
@ -489,6 +492,13 @@ void ProcessMailHTTPMessage(struct HTTPConnectionInfo * Session, char * Method,
return; return;
} }
if (_memicmp(URL, "/Mail/API/", 10) == 0)
{
*RLen = MailAPIProcessHTTPMessage(Reply, Method, URL, input, LOCAL, Context);
return;
}
if (strcmp(Method, "POST") == 0) if (strcmp(Method, "POST") == 0)
{ {
if (_stricmp(NodeURL, "/Mail/Header") == 0) if (_stricmp(NodeURL, "/Mail/Header") == 0)
@ -1633,6 +1643,7 @@ VOID ProcessConfUpdate(struct HTTPConnectionInfo * Session, char * MsgPtr, char
UserCantKillT = !UserCantKillT; // Reverse Logic UserCantKillT = !UserCantKillT; // Reverse Logic
GetCheckBox(input, "FWDtoMe=", &ForwardToMe); GetCheckBox(input, "FWDtoMe=", &ForwardToMe);
GetCheckBox(input, "OnlyKnown=", &OnlyKnown); GetCheckBox(input, "OnlyKnown=", &OnlyKnown);
GetCheckBox(input, "Events=", &reportMailEvents);
GetParam(input, "POP3Port=", Temp); GetParam(input, "POP3Port=", Temp);
POP3InPort = atoi(Temp); POP3InPort = atoi(Temp);
@ -2610,6 +2621,7 @@ VOID SendConfigPage(char * Reply, int * ReplyLen, char * Key)
(UserCantKillT) ? UNC : CHKD, // Reverse logic (UserCantKillT) ? UNC : CHKD, // Reverse logic
(ForwardToMe) ? CHKD : UNC, (ForwardToMe) ? CHKD : UNC,
(OnlyKnown) ? CHKD : UNC, (OnlyKnown) ? CHKD : UNC,
(reportMailEvents) ? CHKD : UNC,
POP3InPort, SMTPInPort, NNTPInPort, POP3InPort, SMTPInPort, NNTPInPort,
(RemoteEmail) ? CHKD : UNC, (RemoteEmail) ? CHKD : UNC,
AMPRDomain, AMPRDomain,

View File

@ -43,7 +43,7 @@ RECT ConsoleRect;
BOOL OpenConsole; BOOL OpenConsole;
BOOL OpenMon; BOOL OpenMon;
int reportNewMesageEvents = 0; int reportMailEvents = 0;
FBBFilter * Filters = NULL; 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); int encode_quoted_printable(char *s, char * out, int Len);
int32_t Encode(char * in, char * out, int32_t inlen, BOOL B1Protocol, int Compress); int32_t Encode(char * in, char * out, int32_t inlen, BOOL B1Protocol, int Compress);
int APIENTRY ChangeSessionCallsign(int Stream, unsigned char * AXCall); 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_t cfg;
config_setting_t * group; config_setting_t * group;
@ -4904,6 +4906,7 @@ sendEOM:
Msg->status = 'Y'; Msg->status = 'Y';
Msg->datechanged=time(NULL); Msg->datechanged=time(NULL);
SaveMessageDatabase(); SaveMessageDatabase();
SendMessageReadEvent(user->Call, Msg);
} }
} }
} }
@ -6457,30 +6460,9 @@ nextline:
// If Event Notifications enabled report a new message event // If Event Notifications enabled report a new message event
if (reportNewMesageEvents) user = LookupCall(Msg->to);
{
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
}
SendNewMessageEvent(user->Call, Msg);
if (EnableUI) if (EnableUI)
#ifdef LINBPQ #ifdef LINBPQ
@ -6493,8 +6475,6 @@ nextline:
My__except_Routine("SendMsgUI"); My__except_Routine("SendMsgUI");
#endif #endif
user = LookupCall(Msg->to);
if (user && (user->flags & F_APRSMFOR)) if (user && (user->flags & F_APRSMFOR))
{ {
char APRS[128]; char APRS[128];
@ -9576,6 +9556,7 @@ VOID SaveConfig(char * ConfigName)
SaveIntValue(group, "EnableUI", EnableUI); SaveIntValue(group, "EnableUI", EnableUI);
SaveIntValue(group, "RefuseBulls", RefuseBulls); SaveIntValue(group, "RefuseBulls", RefuseBulls);
SaveIntValue(group, "OnlyKnown", OnlyKnown); SaveIntValue(group, "OnlyKnown", OnlyKnown);
SaveIntValue(group, "reportMailEvents", reportMailEvents);
SaveIntValue(group, "SendSYStoSYSOPCall", SendSYStoSYSOPCall); SaveIntValue(group, "SendSYStoSYSOPCall", SendSYStoSYSOPCall);
SaveIntValue(group, "SendBBStoSYSOPCall", SendBBStoSYSOPCall); SaveIntValue(group, "SendBBStoSYSOPCall", SendBBStoSYSOPCall);
SaveIntValue(group, "DontHoldNewUsers", DontHoldNewUsers); SaveIntValue(group, "DontHoldNewUsers", DontHoldNewUsers);
@ -10098,13 +10079,13 @@ BOOL GetConfig(char * ConfigName)
config_destroy(&cfg); config_destroy(&cfg);
return(EXIT_FAILURE); return(EXIT_FAILURE);
} }
/*
#if LIBCONFIG_VER_MINOR > 5 #if LIBCONFIG_VER_MINOR > 5
config_set_option(&cfg, CONFIG_OPTION_AUTOCONVERT, 1); config_set_option(&cfg, CONFIG_OPTION_AUTOCONVERT, 1);
#else #else
config_set_auto_convert (&cfg, 1); config_set_auto_convert (&cfg, 1);
#endif #endif
*/
group = config_lookup (&cfg, "main"); group = config_lookup (&cfg, "main");
if (group == NULL) if (group == NULL)
@ -10120,6 +10101,8 @@ BOOL GetConfig(char * ConfigName)
MailForInterval = GetIntValue(group, "MailForInterval"); MailForInterval = GetIntValue(group, "MailForInterval");
RefuseBulls = GetIntValue(group, "RefuseBulls"); RefuseBulls = GetIntValue(group, "RefuseBulls");
OnlyKnown = GetIntValue(group, "OnlyKnown"); OnlyKnown = GetIntValue(group, "OnlyKnown");
reportMailEvents = GetIntValue(group, "reportMailEvents");
SendSYStoSYSOPCall = GetIntValue(group, "SendSYStoSYSOPCall"); SendSYStoSYSOPCall = GetIntValue(group, "SendSYStoSYSOPCall");
SendBBStoSYSOPCall = GetIntValue(group, "SendBBStoSYSOPCall"); SendBBStoSYSOPCall = GetIntValue(group, "SendBBStoSYSOPCall");
DontHoldNewUsers = GetIntValue(group, "DontHoldNewUsers"); DontHoldNewUsers = GetIntValue(group, "DontHoldNewUsers");
@ -15793,3 +15776,62 @@ VOID GetPGConfig()
NUM_SERVERS = n; NUM_SERVERS = n;
fclose(file); 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
}
}

View File

@ -1123,8 +1123,9 @@
// Add FBB reject.sys style filters (3) // Add FBB reject.sys style filters (3)
// Improve Webmail on 64 bit builds // Improve Webmail on 64 bit builds
// Fix setting status '$' on Bulls sent via WebMail (22) // 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 "bpqmail.h"
#include "winstdint.h" #include "winstdint.h"

View File

@ -316,6 +316,10 @@
RelativePath="..\CommonSource\LzmaLib.c" RelativePath="..\CommonSource\LzmaLib.c"
> >
</File> </File>
<File
RelativePath=".\mailapi.c"
>
</File>
<File <File
RelativePath="..\CommonSource\MailCommands.c" RelativePath="..\CommonSource\MailCommands.c"
> >

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioUserFile
ProjectType="Visual C++"
Version="8.00"
ShowAllFiles="false"
>
<Configurations>
<Configuration
Name="Debug|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioUserFile
ProjectType="Visual C++"
Version="8.00"
ShowAllFiles="false"
>
<Configurations>
<Configuration
Name="Debug|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioUserFile
ProjectType="Visual C++"
Version="8.00"
ShowAllFiles="false"
>
<Configurations>
<Configuration
Name="Debug|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="LAPTOP-Q6S4RP5Q"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="LAPTOP-Q6S4RP5Q"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>

View File

@ -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) // Improve restart of WinRPR TNC on remote host (21)
// Fix some Rigcontrol issues with empty timebands (22) // Fix some Rigcontrol issues with empty timebands (22)
// Fix 64 bit bug in processing INP3 Messages (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 #define CKernel
@ -2065,7 +2068,7 @@ VOID TimerProcX()
GetWindowRect(FrameWnd, &FRect); GetWindowRect(FrameWnd, &FRect);
SaveWindowPos(64); // Rigcontrol SaveWindowPos(70); // Rigcontrol
for (i=0;i<NUMBEROFPORTS;i++) for (i=0;i<NUMBEROFPORTS;i++)
{ {
@ -2181,7 +2184,7 @@ VOID TimerProcX()
if(TimerInst == GetCurrentProcessId()) if(TimerInst == GetCurrentProcessId())
{ {
RigReconfigFlag = FALSE; RigReconfigFlag = FALSE;
CloseDriverWindow(40); CloseDriverWindow(70);
Rig_Close(); Rig_Close();
Sleep(6000); // Allow any CATPTT, HAMLIB and FLRIG threads to close Sleep(6000); // Allow any CATPTT, HAMLIB and FLRIG threads to close
RigActive = Rig_Init(); RigActive = Rig_Init();
@ -6482,7 +6485,7 @@ VOID SaveBPQ32Windows()
PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER; PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER;
} }
SaveWindowPos(40); // Rigcontrol SaveWindowPos(70); // Rigcontrol
if (hIPResWnd) if (hIPResWnd)

View File

@ -438,6 +438,10 @@
RelativePath="..\CommonSource\MULTIPSK.c" RelativePath="..\CommonSource\MULTIPSK.c"
> >
</File> </File>
<File
RelativePath=".\nodeapi.c"
>
</File>
<File <File
RelativePath=".\png.c" RelativePath=".\png.c"
> >

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioUserFile
ProjectType="Visual C++"
Version="8.00"
ShowAllFiles="false"
>
<Configurations>
<Configuration
Name="Debug|Win32"
>
<DebugSettings
Command="C:\Devprogs\BPQ32\bpq32.exe"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
>
<DebugSettings
Command=""
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioUserFile
ProjectType="Visual C++"
Version="8.00"
ShowAllFiles="false"
>
<Configurations>
<Configuration
Name="Debug|Win32"
>
<DebugSettings
Command="C:\Devprogs\BPQ32\bpq32.exe"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
>
<DebugSettings
Command=""
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioUserFile
ProjectType="Visual C++"
Version="8.00"
ShowAllFiles="false"
>
<Configurations>
<Configuration
Name="Debug|Win32"
>
<DebugSettings
Command="C:\Devprogs\BPQ32\bpq32.exe"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="LAPTOP-Q6S4RP5Q"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
>
<DebugSettings
Command=""
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="LAPTOP-Q6S4RP5Q"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioUserFile
ProjectType="Visual C++"
Version="8.00"
ShowAllFiles="false"
>
<Configurations>
<Configuration
Name="Debug|Win32"
>
<DebugSettings
Command="C:\Devprogs\BPQ32\bpq32.exe"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="LAPTOP-Q6S4RP5Q"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
>
<DebugSettings
Command=""
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="LAPTOP-Q6S4RP5Q"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>

View File

@ -406,7 +406,7 @@ extern BOOL CloseAllNeeded;
extern int CloseOnError; extern int CloseOnError;
extern char * PortConfig[70]; 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 MaxBPQPortNo 63 // Port 64 reserved for BBS Mon
#define MAXBPQPORTS 63 #define MAXBPQPORTS 63

View File

@ -67,6 +67,7 @@ extern int MaxChatStreams;
extern char Position[81]; extern char Position[81];
extern char PopupText[251]; extern char PopupText[251];
extern int PopupMode; extern int PopupMode;
extern int reportChatEvents;
#include "httpconnectioninfo.h" #include "httpconnectioninfo.h"
@ -323,6 +324,8 @@ VOID SaveChatInfo(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Rep
if (chatPaclen < 60) if (chatPaclen < 60)
chatPaclen = 60; chatPaclen = 60;
GetCheckBox(input, "Events=", &reportChatEvents);
GetParam(input, "nodes=", Nodes); GetParam(input, "nodes=", Nodes);
ptr1 = Nodes; ptr1 = Nodes;
@ -508,7 +511,9 @@ scan:
Len = sprintf(Reply, ChatConfigTemplate, Len = sprintf(Reply, ChatConfigTemplate,
OurNode, Key, Key, Key, OurNode, Key, Key, Key,
ChatApplNum, MaxChatStreams, Nodes, chatPaclen, Position, ChatApplNum, MaxChatStreams,
(reportChatEvents) ? CHKD : UNC,
Nodes, chatPaclen, Position,
(PopupMode) ? UNC : CHKD, (PopupMode) ? UNC : CHKD,
(PopupMode) ? CHKD : UNC, Text, ptr2); (PopupMode) ? CHKD : UNC, Text, ptr2);

View File

@ -49,7 +49,7 @@ extern struct CONFIGTABLE xxcfg;
#endif #endif
struct TNCINFO * TNCInfo[70]; // Records are Malloc'd struct TNCINFO * TNCInfo[71]; // Records are Malloc'd
extern int ReportTimer; 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 // __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
#endif // MACBPQ #endif // MACBPQ
void GetSemaphore(struct SEM * Semaphore, int ID) void GetSemaphore(struct SEM * Semaphore, int ID)
{ {
// //
@ -5232,7 +5230,7 @@ void SendDataToPktMap(char *Msg)
// TCP // TCP
Mode = Modenames[TNC->Hardware]; Mode = Modenames[TNC->Hardware - 1];
if (TNC->CONNECTED) if (TNC->CONNECTED)
Active = 1; Active = 1;

View File

@ -69,6 +69,7 @@ int GetAPRSIcon(unsigned char * _REPLYBUFFER, char * NodeURL);
char * GetStandardPage(char * FN, int * Len); char * GetStandardPage(char * FN, int * Len);
BOOL SHA1PasswordHash(char * String, char * Hash); BOOL SHA1PasswordHash(char * String, char * Hash);
char * byte_base64_encode(char *str, int len); 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 struct ROUTE * NEIGHBOURS;
extern int ROUTE_LEN; extern int ROUTE_LEN;
@ -1593,7 +1594,7 @@ int InnerProcessHTTPMessage(struct ConnectionInfo * conn)
char * Compressed = 0; char * Compressed = 0;
char * HostPtr = 0; char * HostPtr = 0;
char * Context, * Method, * NodeURL, * Key; char * Context, * Method, * NodeURL = 0, * Key;
char _REPLYBUFFER[250000]; char _REPLYBUFFER[250000];
char Reply[250000]; char Reply[250000];
@ -1631,7 +1632,7 @@ int InnerProcessHTTPMessage(struct ConnectionInfo * conn)
char Encoding[] = "Content-Encoding: deflate\r\n"; char Encoding[] = "Content-Encoding: deflate\r\n";
#ifdef WIN32 #ifdef WIN32xx
struct _EXCEPTION_POINTERS exinfo; struct _EXCEPTION_POINTERS exinfo;
strcpy(EXCEPTMSG, "ProcessHTTPMessage"); strcpy(EXCEPTMSG, "ProcessHTTPMessage");
@ -1772,6 +1773,43 @@ int InnerProcessHTTPMessage(struct ConnectionInfo * conn)
strlop(Mycall, ' '); 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 // APRS process internally
if (_memicmp(Context, "/APRS/", 6) == 0 || _stricmp(Context, "/APRS") == 0) if (_memicmp(Context, "/APRS/", 6) == 0 || _stricmp(Context, "/APRS") == 0)
@ -1874,7 +1912,8 @@ int InnerProcessHTTPMessage(struct ConnectionInfo * conn)
Session = FindSession(Key); Session = FindSession(Key);
if (Session == NULL)
if (Session == NULL && _memicmp(Context, "/Mail/API/", 10) != 0)
{ {
ReplyLen = sprintf(Reply, MailLostSession, Key); ReplyLen = sprintf(Reply, MailLostSession, Key);
RLen = ReplyLen; RLen = ReplyLen;
@ -2025,10 +2064,13 @@ Returnit:
return 0; return 0;
} }
if (NodeURL && _memicmp(NodeURL, "/mail/api/", 10) != 0)
{
// Add tail // Add tail
strcpy(&Reply[ReplyLen], Tail); strcpy(&Reply[ReplyLen], Tail);
ReplyLen += strlen(Tail); ReplyLen += strlen(Tail);
}
// compress if allowed // compress if allowed
@ -2037,7 +2079,15 @@ Returnit:
else else
Compressed = Reply; Compressed = Reply;
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); 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, Header, HeaderLen);
sendandcheck(sock, Compressed, ReplyLen); sendandcheck(sock, Compressed, ReplyLen);
@ -3889,7 +3939,7 @@ SendResp:
} }
return 0; return 0;
#ifdef WIN32 #ifdef WIN32xx
} }
#include "StdExcept.c" #include "StdExcept.c"
} }

View File

@ -77,6 +77,8 @@ char PopupText[260] = "";
int PopupMode = 0; int PopupMode = 0;
int chatPaclen = 236; int chatPaclen = 236;
int reportChatEvents = 0;
char RtKnown[MAX_PATH] = "RTKnown.txt"; char RtKnown[MAX_PATH] = "RTKnown.txt";
char RtUsr[MAX_PATH] = "STUsers.txt"; char RtUsr[MAX_PATH] = "STUsers.txt";
char RtUsrTemp[MAX_PATH] = "STUsers.tmp"; 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); 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. // Send it to all connected users in the same topic.
// Echo to originator if requested. // Echo to originator if requested.
@ -2109,14 +2123,6 @@ void text_tellu_Joined(USER * user)
nputc(circuit, 7); nputc(circuit, 7);
nputc(circuit, 13); 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. // Tell one link circuit about a local user change of topic.
@ -4170,6 +4176,7 @@ BOOL GetChatConfig(char * ConfigName)
ChatApplNum = GetIntValue(group, "ApplNum"); ChatApplNum = GetIntValue(group, "ApplNum");
MaxChatStreams = GetIntValue(group, "MaxStreams"); MaxChatStreams = GetIntValue(group, "MaxStreams");
reportChatEvents = GetIntValue(group, "reportChatEvents");
chatPaclen = GetIntValue(group, "chatPaclen"); chatPaclen = GetIntValue(group, "chatPaclen");
GetStringValue(group, "OtherChatNodes", OtherNodesList); GetStringValue(group, "OtherChatNodes", OtherNodesList);
GetStringValue(group, "ChatWelcomeMsg", ChatWelcomeMsg); GetStringValue(group, "ChatWelcomeMsg", ChatWelcomeMsg);
@ -4201,6 +4208,7 @@ VOID SaveChatConfigFile(char * ConfigName)
SaveIntValue(group, "ApplNum", ChatApplNum); SaveIntValue(group, "ApplNum", ChatApplNum);
SaveIntValue(group, "MaxStreams", MaxChatStreams); SaveIntValue(group, "MaxStreams", MaxChatStreams);
SaveIntValue(group, "reportChatEvents", reportChatEvents);
SaveIntValue(group, "chatPaclen", chatPaclen); SaveIntValue(group, "chatPaclen", chatPaclen);
SaveStringValue(group, "OtherChatNodes", OtherNodesList); SaveStringValue(group, "OtherChatNodes", OtherNodesList);
SaveStringValue(group, "ChatWelcomeMsg", ChatWelcomeMsg); SaveStringValue(group, "ChatWelcomeMsg", ChatWelcomeMsg);

View File

@ -23,6 +23,9 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
#include "bpqmail.h" #include "bpqmail.h"
void SendMessageReadEvent(struct UserInfo * user, struct MsgInfo * Msg);
VOID ProcessMBLLine(CIRCUIT * conn, struct UserInfo * user, UCHAR* Buffer, int len) VOID ProcessMBLLine(CIRCUIT * conn, struct UserInfo * user, UCHAR* Buffer, int len)
{ {
Buffer[len] = 0; Buffer[len] = 0;
@ -86,6 +89,7 @@ VOID ProcessMBLLine(CIRCUIT * conn, struct UserInfo * user, UCHAR* Buffer, int l
FBBputs(conn, ">\r"); FBBputs(conn, ">\r");
Msg->status = 'Y'; // Mark as read Msg->status = 'Y'; // Mark as read
SaveMessageDatabase(); SaveMessageDatabase();
SendMessageReadEvent(user->Call, Msg);
} }
else else
{ {

View File

@ -424,6 +424,10 @@
RelativePath="..\CommonSource\LzmaLib.c" RelativePath="..\CommonSource\LzmaLib.c"
> >
</File> </File>
<File
RelativePath=".\mailapi.c"
>
</File>
<File <File
RelativePath="..\CommonSource\MailCommands.c" RelativePath="..\CommonSource\MailCommands.c"
> >
@ -464,6 +468,10 @@
RelativePath="..\CommonSource\NNTPRoutines.c" RelativePath="..\CommonSource\NNTPRoutines.c"
> >
</File> </File>
<File
RelativePath=".\nodeapi.c"
>
</File>
<File <File
RelativePath="..\CommonSource\pibits.c" RelativePath="..\CommonSource\pibits.c"
> >

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioUserFile
ProjectType="Visual C++"
Version="8.00"
ShowAllFiles="false"
>
<Configurations>
<Configuration
Name="Debug|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>

View File

@ -1142,7 +1142,6 @@ int Rig_CommandEx(struct RIGPORTINFO * PORT, struct RIGINFO * RIG, TRANSPORTENTR
return FALSE; return FALSE;
} }
// Build a ScanEntry in the buffer // Build a ScanEntry in the buffer
FreqPtr = (struct ScanEntry *)buffptr->Data; FreqPtr = (struct ScanEntry *)buffptr->Data;
@ -1277,8 +1276,6 @@ int Rig_CommandEx(struct RIGPORTINFO * PORT, struct RIGINFO * RIG, TRANSPORTENTR
} }
*(CmdPtr++) = 0xFD; *(CmdPtr++) = 0xFD;
*(CmdPtr) = 0; *(CmdPtr) = 0;
Len = (int)(CmdPtr - (char *)&buffptr[30]); 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 FreqPtr[0].Cmd1Len = Len; // for ICOM
C_Q_ADD(&RIG->BPQtoRADIO_Q, buffptr); C_Q_ADD(&RIG->BPQtoRADIO_Q, buffptr);
return TRUE;
sprintf(Command, "Ok\r");
return FALSE;
} }
if (_memicmp(FreqString, "Chan", 4) == 0) if (_memicmp(FreqString, "Chan", 4) == 0)
@ -2203,7 +2202,7 @@ DllExport BOOL APIENTRY Rig_Init()
memset(&RIGTNC, 0, sizeof(struct TNCINFO)); memset(&RIGTNC, 0, sizeof(struct TNCINFO));
TNCInfo[40] = TNC; TNCInfo[70] = TNC;
// Get config info // Get config info
@ -2229,7 +2228,7 @@ DllExport BOOL APIENTRY Rig_Init()
#ifndef LINBPQ #ifndef LINBPQ
TNC->Port = 40; TNC->Port = 70;
CreatePactorWindow(TNC, "RIGCONTROL", "RigControl", 10, PacWndProc, 550, NeedRig * 20 + 60, NULL); CreatePactorWindow(TNC, "RIGCONTROL", "RigControl", 10, PacWndProc, 550, NeedRig * 20 + 60, NULL);
hDlg = TNC->hDlg; hDlg = TNC->hDlg;

View File

@ -534,6 +534,9 @@ int ProcessLine(char * buf, int Port)
else if (_stricmp(param,"HTTPPORT") == 0) else if (_stricmp(param,"HTTPPORT") == 0)
TCP->HTTPPort = atoi(value); TCP->HTTPPort = atoi(value);
else if (_stricmp(param,"APIPORT") == 0)
TCP->APIPort = atoi(value);
else if (_stricmp(param,"SYNCPORT") == 0) else if (_stricmp(param,"SYNCPORT") == 0)
TCP->SyncPort = atoi(value); TCP->SyncPort = atoi(value);
@ -1646,6 +1649,9 @@ BOOL OpenSockets(struct TNCINFO * TNC)
if (TCP->HTTPPort) if (TCP->HTTPPort)
TCP->HTTPsock = OpenSocket4(TNC, TCP->HTTPPort); TCP->HTTPsock = OpenSocket4(TNC, TCP->HTTPPort);
if (TCP->APIPort)
TCP->APIsock = OpenSocket4(TNC, TCP->APIPort);
if (TCP->SyncPort) if (TCP->SyncPort)
TCP->Syncsock = OpenSocket4(TNC, TCP->SyncPort); TCP->Syncsock = OpenSocket4(TNC, TCP->SyncPort);
@ -1755,10 +1761,12 @@ BOOL OpenSockets6(struct TNCINFO * TNC)
if (TCP->RelayPort) if (TCP->RelayPort)
TCP->Relaysock6 = OpenSocket6(TNC, TCP->RelayPort); TCP->Relaysock6 = OpenSocket6(TNC, TCP->RelayPort);
if (TCP->HTTPPort) if (TCP->HTTPPort)
TCP->HTTPsock6 = OpenSocket6(TNC, TCP->HTTPPort); TCP->HTTPsock6 = OpenSocket6(TNC, TCP->HTTPPort);
if (TCP->APIPort)
TCP->APIsock6 = OpenSocket6(TNC, TCP->APIPort);
if (TCP->SyncPort) if (TCP->SyncPort)
TCP->Syncsock6 = OpenSocket6(TNC, TCP->SyncPort); TCP->Syncsock6 = OpenSocket6(TNC, TCP->SyncPort);
@ -1819,6 +1827,14 @@ static VOID SetupListenSet(struct TNCINFO * TNC)
maxsock = sock; maxsock = sock;
} }
sock = TCP->APIsock;
if (sock)
{
FD_SET(sock, readfd);
if (sock > maxsock)
maxsock = sock;
}
sock = TCP->Syncsock; sock = TCP->Syncsock;
if (sock) if (sock)
{ {
@ -1886,6 +1902,14 @@ static VOID SetupListenSet(struct TNCINFO * TNC)
maxsock = sock; maxsock = sock;
} }
sock = TCP->APIsock6;
if (sock)
{
FD_SET(sock, readfd);
if (sock > maxsock)
maxsock = sock;
}
sock = TCP->DRATSsock6; sock = TCP->DRATSsock6;
if (sock) if (sock)
@ -3192,6 +3216,7 @@ int Socket_Accept(struct TNCINFO * TNC, SOCKET SocketId, int Port)
TNC->Streams[n].FramesQueued = 0; TNC->Streams[n].FramesQueued = 0;
sockptr->HTTPMode = FALSE; sockptr->HTTPMode = FALSE;
sockptr->APIMode = FALSE;
sockptr->SyncMode = FALSE; sockptr->SyncMode = FALSE;
sockptr->DRATSMode = FALSE; sockptr->DRATSMode = FALSE;
sockptr->FBBMode = 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) if (SocketId == TCP->HTTPsock || SocketId == TCP->HTTPsock6)
sockptr->HTTPMode = TRUE; 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) else if (SocketId == TCP->Syncsock || SocketId == TCP->Syncsock6)
sockptr->SyncMode = TRUE; sockptr->SyncMode = TRUE;
else if (SocketId == TCP->DRATSsock || SocketId == TCP->DRATSsock6) else if (SocketId == TCP->DRATSsock || SocketId == TCP->DRATSsock6)

View File

@ -10,14 +10,14 @@
#endif #endif
#define KVers 6,0,24,22 #define KVers 6,0,24,25
#define KVerstring "6.0.24.22\0" #define KVerstring "6.0.24.25\0"
#ifdef CKernel #ifdef CKernel
#define Vers KVers #define Vers KVers
#define Verstring KVerstring #define Verstring KVerstring
#define Datestring "November 2023" #define Datestring "December 2023"
#define VerComments "G8BPQ Packet Switch (C Version)" KVerstring #define VerComments "G8BPQ Packet Switch (C Version)" KVerstring
#define VerCopyright "Copyright © 2001-2023 John Wiseman G8BPQ\0" #define VerCopyright "Copyright © 2001-2023 John Wiseman G8BPQ\0"
#define VerDesc "BPQ32 Switch\0" #define VerDesc "BPQ32 Switch\0"

View File

@ -76,6 +76,8 @@ VOID SendTemplateSelectScreen(struct HTTPConnectionInfo * Session, char *URLPara
BOOL isAMPRMsg(char * Addr); BOOL isAMPRMsg(char * Addr);
char * doXMLTransparency(char * string); char * doXMLTransparency(char * string);
Dll BOOL APIENTRY APISendAPRSMessage(char * Text, char * ToCall); 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 NodeTail[];
extern char BBSName[10]; extern char BBSName[10];
@ -719,17 +721,19 @@ VOID ProcessFormDir(char * FormSet, char * DirName, struct HtmlFormDir *** xxx,
{ {
if (entry->d_type == DT_DIR) if (entry->d_type == DT_DIR)
{ {
char Dir[MAX_PATH];
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue; 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; 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));
@ -739,7 +743,6 @@ VOID ProcessFormDir(char * FormSet, char * DirName, struct HtmlFormDir *** xxx,
FormDir->Forms=realloc(FormDir->Forms, (FormDir->FormCount + 1) * sizeof(void *)); FormDir->Forms=realloc(FormDir->Forms, (FormDir->FormCount + 1) * sizeof(void *));
FormDir->Forms[FormDir->FormCount++] = Form; FormDir->Forms[FormDir->FormCount++] = Form;
} }
}
closedir(dir); closedir(dir);
#endif #endif
return; return;
@ -808,9 +811,9 @@ int GetHTMLFormSet(char * FormSet)
if (!(dir = opendir(name))) if (!(dir = opendir(name)))
{ {
Debugprintf("cant open forms dir %s %d %d", name, errno, dir); Debugprintf("cant open forms dir %s %d %d", name, errno, dir);
return 0;
} }
else
{
while ((entry = readdir(dir)) != NULL) while ((entry = readdir(dir)) != NULL)
{ {
if (entry->d_type == DT_DIR) if (entry->d_type == DT_DIR)
@ -824,6 +827,7 @@ int GetHTMLFormSet(char * FormSet)
} }
} }
closedir(dir); closedir(dir);
}
#endif #endif
// List for testing // List for testing
@ -1122,7 +1126,7 @@ int ViewWebMailMessage(struct HTTPConnectionInfo * Session, char * Reply, int Nu
Msg->status = 'Y'; Msg->status = 'Y';
Msg->datechanged=time(NULL); Msg->datechanged=time(NULL);
SaveMessageDatabase(); SaveMessageDatabase();
SendMessageReadEvent(Session->Callsign, Msg);
} }
} }
} }
@ -1190,6 +1194,7 @@ int ViewWebMailMessage(struct HTTPConnectionInfo * Session, char * Reply, int Nu
Msg->status = 'Y'; Msg->status = 'Y';
Msg->datechanged=time(NULL); Msg->datechanged=time(NULL);
SaveMessageDatabase(); SaveMessageDatabase();
SendMessageReadEvent(Session->Callsign, Msg);
} }
} }
} }
@ -1303,6 +1308,7 @@ int ViewWebMailMessage(struct HTTPConnectionInfo * Session, char * Reply, int Nu
Msg->status = 'Y'; Msg->status = 'Y';
Msg->datechanged=time(NULL); Msg->datechanged=time(NULL);
SaveMessageDatabase(); 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) if (Msg->status != 'H' && Msg->type == 'B' && memcmp(Msg->fbbs, zeros, NBMASK) != 0)
Msg->status = '$'; // Has forwarding Msg->status = '$'; // Has forwarding
if (EnableUI) if (EnableUI)
SendMsgUI(Msg); SendMsgUI(Msg);
user = LookupCall(Msg->to); user = LookupCall(Msg->to);
// If Event Notifications enabled report a new message event
SendNewMessageEvent(user->Call, Msg);
if (user && (user->flags & F_APRSMFOR)) if (user && (user->flags & F_APRSMFOR))
{ {
char APRS[128]; char APRS[128];
@ -2838,12 +2849,25 @@ char * GetHTMLViewerTemplate(char * FN)
{ {
for (l = 0; l < Dir->DirCount; l++) 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;
return CheckFile(Dir, Dir->Dirs[l]->Forms[k]->FileName);
} }
for (k = 0; k < SDir->FormCount; k++)
{
if (_stricmp(FN, SDir->Forms[k]->FileName) == 0)
{
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; *ptr2++ = 0;
ptr3 = strchr(ptr2, '<'); // end of value string ptr3 = strstr(ptr2, "</"); // end of value string
if (ptr3 == NULL) if (ptr3 == NULL)
goto quit; goto quit;
@ -3236,6 +3260,14 @@ BOOL ParseXML(WebMailInfo * WebMail, char * XMLOrig)
XMLKeys++; XMLKeys++;
ptr1 = strchr(ptr3, '<'); ptr1 = strchr(ptr3, '<');
if (_memicmp(ptr1, "</", 2) == 0)
{
// end of a parameter block. Find start of next block
ptr1 = strchr(++ptr1, '<');
ptr1 = strchr(++ptr1, '<'); // Skip start of next block
}
} }
@ -5349,6 +5381,8 @@ char * CheckFile(struct HtmlFormDir * Dir, char * FN)
#endif #endif
printf("%s\n", MsgFile);
if (stat(MsgFile, &STAT) != -1) if (stat(MsgFile, &STAT) != -1)
{ {
hFile = fopen(MsgFile, "rb"); hFile = fopen(MsgFile, "rb");
@ -5365,6 +5399,8 @@ char * CheckFile(struct HtmlFormDir * Dir, char * FN)
MsgBytes[FileSize] = 0; MsgBytes[FileSize] = 0;
fclose(hFile); fclose(hFile);
printf("%d %s\n", strlen(MsgBytes), MsgBytes);
return MsgBytes; return MsgBytes;
} }
return NULL; return NULL;

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioUserFile
ProjectType="Visual C++"
Version="8.00"
ShowAllFiles="false"
>
<Configurations>
<Configuration
Name="Debug|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioUserFile
ProjectType="Visual C++"
Version="8.00"
ShowAllFiles="false"
>
<Configurations>
<Configuration
Name="Debug|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioUserFile
ProjectType="Visual C++"
Version="8.00"
ShowAllFiles="false"
>
<Configurations>
<Configuration
Name="Debug|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="DESKTOP-TGEL8RC"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioUserFile
ProjectType="Visual C++"
Version="8.00"
ShowAllFiles="false"
>
<Configurations>
<Configuration
Name="Debug|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="LAPTOP-Q6S4RP5Q"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
>
<DebugSettings
Command="$(TargetPath)"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="LAPTOP-Q6S4RP5Q"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>

3161
bbshtmlconfig.c~ Normal file

File diff suppressed because it is too large Load Diff

196
mailapi.c Normal file
View File

@ -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 <windows.h>
#include "CHeaders.h"
#include <stdlib.h>
#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;
}

View File

@ -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 \ 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 \ 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 \ 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: # Configuration:

633
nodeapi.c Normal file
View File

@ -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 <stdlib.h>
#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);
}

View File

@ -36,7 +36,8 @@ struct ConnectionInfo
BOOL RelayMode; // Pure TCP for RMS Relay Emulation forwarding BOOL RelayMode; // Pure TCP for RMS Relay Emulation forwarding
BOOL DRATSMode; // HTML Terminal Emulator BOOL DRATSMode; // HTML Terminal Emulator
BOOL SyncMode; // RMS Relay Sync BOOL SyncMode; // RMS Relay Sync
BOOL HTTPMode; // DRATS Reflector Emulator BOOL HTTPMode; // HTTP Server
BOOL APIMode; // REST API Server
BOOL TriMode; // Trimode emulation BOOL TriMode; // Trimode emulation
BOOL TriModeConnected; // Set when remote session is connected - now send data to DataSock BOOL TriModeConnected; // Set when remote session is connected - now send data to DataSock
SOCKET TriModeDataSock; // Data Socket SOCKET TriModeDataSock; // Data Socket

View File

@ -478,7 +478,9 @@ char * MainConfigtxt()
" <input %sname=\"DontCheckFromCall\" type=\"checkbox\"> Dont Check From Call<br>\r\n" " <input %sname=\"DontCheckFromCall\" type=\"checkbox\"> Dont Check From Call<br>\r\n"
" <input %sname=\"UserCantKillT\" type=\"checkbox\"> Allow users to kill T messages<br>\r\n" " <input %sname=\"UserCantKillT\" type=\"checkbox\"> Allow users to kill T messages<br>\r\n"
" <input %sname=\"FWDtoMe\" type=\"checkbox\"> Forward Messages to BBS Call<br>\r\n" " <input %sname=\"FWDtoMe\" type=\"checkbox\"> Forward Messages to BBS Call<br>\r\n"
" <input %sname=\"OnlyKnown\" type=\"checkbox\"> Don't allow unknown users<br><br>\r\n" " <input %sname=\"OnlyKnown\" type=\"checkbox\"> Don't allow unknown users<br>\r\n"
" <input %sname=\"Events\" type=\"checkbox\"> Enable Event Reporting<br><br>\r\n"
"&nbsp;POP3 Port&nbsp;&nbsp; <input value=\"%d\" size=\"3\" name=\"POP3Port\">\r\n" "&nbsp;POP3 Port&nbsp;&nbsp; <input value=\"%d\" size=\"3\" name=\"POP3Port\">\r\n"
"SMTP Port <input value=\"%d\" size=\"3\" name=\"SMTPPort\"> NTPPort <input value=\"%d\" size=\"3\" name=\"NNTPPort\">&nbsp;<input %sname=\"EnRemote\" type=\"checkbox\"> Enable Remote Access<br>\r\n" "SMTP Port <input value=\"%d\" size=\"3\" name=\"SMTPPort\"> NTPPort <input value=\"%d\" size=\"3\" name=\"NNTPPort\">&nbsp;<input %sname=\"EnRemote\" type=\"checkbox\"> Enable Remote Access<br>\r\n"
"&nbsp;AMPR Address <input value=\"%s\" name=\"AMPRDomain\"> <input %sname=\"SendAMPR\" type=\"checkbox\"> Send AMPR Mail to AMPR host\r\n" "&nbsp;AMPR Address <input value=\"%s\" name=\"AMPRDomain\"> <input %sname=\"SendAMPR\" type=\"checkbox\"> Send AMPR Mail to AMPR host\r\n"
@ -515,7 +517,7 @@ char * MainConfigtxt()
"&nbsp;FBB reject.sys type filters (all fields must match, wildcards allowed)\r\n" "&nbsp;FBB reject.sys type filters (all fields must match, wildcards allowed)\r\n"
"<p></p>" "<p></p>"
"<div style='position: absolute; left: 20px;height: 120px; overflow:auto;'>%s</div>" "<div style='position: absolute; left: 20px;height: 120px; overflow:auto;'>%s</div>"
"<div style='position: absolute; top: 1100px;left: 300px; overflow:auto;'>" "<div style='position: absolute; top: 1120px;left: 300px; overflow:auto;'>"
"<input class='btn' name=\"Save\" value=\"Save\" type=submit class='btn'> <input class='btn' name=\"Cancel\" value=\"Cancel\" type=submit class='btn'>" "<input class='btn' name=\"Save\" value=\"Save\" type=submit class='btn'> <input class='btn' name=\"Cancel\" value=\"Cancel\" type=submit class='btn'>"
"</div>" "</div>"
"</form>\r\n" "</form>\r\n"
@ -1428,7 +1430,7 @@ char * ChatConfigtxt()
"<div style=\"text-align: center;\"><font size=\"+1\"><span\r\n" "<div style=\"text-align: center;\"><font size=\"+1\"><span\r\n"
"style=\"font-family: monospace; font-weight: bold;\">Chat Configuration</span></font></div>\r\n" "style=\"font-family: monospace; font-weight: bold;\">Chat Configuration</span></font></div>\r\n"
"<div id=\"main\"\r\n" "<div id=\"main\"\r\n"
"style=\"align: center; border: 2px solid ; overflow: auto; text-align: center; position: relative; top: 10px; height: 600px; width: 700px; left: 96.5px;\">\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"
"<form border=\"1\" style=\"font-family: monospace;\" method=\"post\"\r\n" "<form border=\"1\" style=\"font-family: monospace;\" method=\"post\"\r\n"
"action=\"/Chat/ChatConfig?%s\">\r\n" "action=\"/Chat/ChatConfig?%s\">\r\n"
"<h3>&nbsp;Chat Server Params<span style=\"font-family: monospace;\"></span></h3>\r\n" "<h3>&nbsp;Chat Server Params<span style=\"font-family: monospace;\"></span></h3>\r\n"
@ -1437,6 +1439,8 @@ char * ChatConfigtxt()
"<span style=\"font-family: monospace;\"></span>Streams &nbsp; &nbsp;\r\n" "<span style=\"font-family: monospace;\"></span>Streams &nbsp; &nbsp;\r\n"
"&nbsp;&nbsp; <input value=\"%d\" size=\"3\" name=\"Streams\"><br>\r\n" "&nbsp;&nbsp; <input value=\"%d\" size=\"3\" name=\"Streams\"><br>\r\n"
"&nbsp; <br>\r\n" "&nbsp; <br>\r\n"
"<input %sname=\"Events\" type=\"checkbox\"> Enable Event Reporting<br><br>\r\n"
"<div style=\"text-align: left; width: 680px; margin: auto;\">The Nodes to link to box defines which other Chat Nodes should be connected to, or from which " "<div style=\"text-align: left; width: 680px; margin: auto;\">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 " "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 " "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()
"<textarea cols=\"80\" rows=\"5\" name=\"welcome\">%s</textarea><br>\r\n" "<textarea cols=\"80\" rows=\"5\" name=\"welcome\">%s</textarea><br>\r\n"
"<br>\r\n" "<br>\r\n"
"\r\n" "\r\n"
"<div style=\"position: absolute; left: 150px; top: 600px;\">\r\n" "<div style=\"position: absolute; left: 150px; top: 620px;\">\r\n"
"<input name=\"Save\" value=\"Save\" type=submit class='btn'> \r\n" "<input name=\"Save\" value=\"Save\" type=submit class='btn'> \r\n"
"<input name=\"UpdateMap\" value=\"Update Map\" type=submit class='btn'> \r\n" "<input name=\"UpdateMap\" value=\"Update Map\" type=submit class='btn'> \r\n"
"<input name=\"Restart\" value=\"Restart Links\" type=submit class='btn'> \r\n" "<input name=\"Restart\" value=\"Restart Links\" type=submit class='btn'> \r\n"

View File

@ -110,6 +110,7 @@ struct TCPINFO
int FBBPort[100]; int FBBPort[100];
int RelayPort; int RelayPort;
int HTTPPort; int HTTPPort;
int APIPort;
int TriModePort; int TriModePort;
int SyncPort; int SyncPort;
int DRATSPort; int DRATSPort;
@ -159,6 +160,7 @@ struct TCPINFO
SOCKET FBBsock[100]; SOCKET FBBsock[100];
SOCKET Relaysock; SOCKET Relaysock;
SOCKET HTTPsock; SOCKET HTTPsock;
SOCKET APIsock;
SOCKET TriModeSock; SOCKET TriModeSock;
SOCKET TriModeDataSock; SOCKET TriModeDataSock;
SOCKET Syncsock; SOCKET Syncsock;
@ -169,6 +171,7 @@ struct TCPINFO
SOCKET FBBsock6[100]; SOCKET FBBsock6[100];
SOCKET Relaysock6; SOCKET Relaysock6;
SOCKET HTTPsock6; SOCKET HTTPsock6;
SOCKET APIsock6;
SOCKET Syncsock6; SOCKET Syncsock6;
SOCKET DRATSsock6; SOCKET DRATSsock6;