Merge branch 'debian/latest' into ubuntu/jammy

This commit is contained in:
Dave Hibberd 2024-01-16 21:00:32 +00:00
commit 552b65aaf2
No known key found for this signature in database
GPG Key ID: 03A1FB7A1904771B
35 changed files with 2251 additions and 487 deletions

View File

@ -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 ";
@ -489,6 +492,13 @@ void ProcessMailHTTPMessage(struct HTTPConnectionInfo * Session, char * Method,
return;
}
if (_memicmp(URL, "/Mail/API/", 10) == 0)
{
*RLen = MailAPIProcessHTTPMessage(Reply, Method, URL, input, LOCAL, Context);
return;
}
if (strcmp(Method, "POST") == 0)
{
if (_stricmp(NodeURL, "/Mail/Header") == 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,

View File

@ -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,13 +10079,13 @@ 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)
@ -10120,6 +10101,8 @@ BOOL GetConfig(char * ConfigName)
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
}
}

View File

@ -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"

View File

@ -316,6 +316,10 @@
RelativePath="..\CommonSource\LzmaLib.c"
>
</File>
<File
RelativePath=".\mailapi.c"
>
</File>
<File
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="NOTTSDESKTOP"
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="NOTTSDESKTOP"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>

13
Bpq32.c
View File

@ -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)
@ -1203,6 +1203,11 @@ 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)
// Disable CTS check in WriteComBlock (26)
// Improvments to reporting to M0LTE Map (26)
// IPGateway fix from github user isavitsky (27)
#define CKernel
@ -2065,7 +2070,7 @@ VOID TimerProcX()
GetWindowRect(FrameWnd, &FRect);
SaveWindowPos(64); // Rigcontrol
SaveWindowPos(70); // Rigcontrol
for (i=0;i<NUMBEROFPORTS;i++)
{
@ -2181,7 +2186,7 @@ VOID TimerProcX()
if(TimerInst == GetCurrentProcessId())
{
RigReconfigFlag = FALSE;
CloseDriverWindow(40);
CloseDriverWindow(70);
Rig_Close();
Sleep(6000); // Allow any CATPTT, HAMLIB and FLRIG threads to close
RigActive = Rig_Init();
@ -6482,7 +6487,7 @@ VOID SaveBPQ32Windows()
PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER;
}
SaveWindowPos(40); // Rigcontrol
SaveWindowPos(70); // Rigcontrol
if (hIPResWnd)

View File

@ -438,6 +438,10 @@
RelativePath="..\CommonSource\MULTIPSK.c"
>
</File>
<File
RelativePath=".\nodeapi.c"
>
</File>
<File
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="NOTTSDESKTOP"
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="NOTTSDESKTOP"
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 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

View File

@ -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);

View File

@ -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;
@ -917,8 +917,7 @@ 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
@ -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 );
@ -3682,7 +3681,7 @@ VOID OpenReportingSockets()
{
// Enable Node Map Reports
ReportTimer = 600;
ReportTimer = 60;
ReportSocket = socket(AF_INET,SOCK_DGRAM,0);
@ -4877,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";
@ -4891,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);
@ -4986,12 +4989,76 @@ 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;
@ -5012,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);
@ -5058,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\": [");
@ -5232,7 +5313,7 @@ void SendDataToPktMap(char *Msg)
// TCP
Mode = Modenames[TNC->Hardware];
Mode = Modenames[TNC->Hardware - 1];
if (TNC->CONNECTED)
Active = 1;
@ -5258,12 +5339,25 @@ 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;
@ -5274,6 +5368,10 @@ void SendDataToPktMap(char *Msg)
// Neighbours
// G7TAJ //
b4Routesptr = ptr-3;
// G7TAJ //
ptr += sprintf(ptr, "\"neighbours\": [\r\n");
while (MaxRoutes--)
@ -5292,8 +5390,30 @@ void SendDataToPktMap(char *Msg)
Routes++;
}
// 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, "]}");
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 //
/*
{

View File

@ -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]);

View File

@ -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;
}
if (NodeURL && _memicmp(NodeURL, "/mail/api/", 10) != 0)
{
// Add tail
strcpy(&Reply[ReplyLen], Tail);
ReplyLen += strlen(Tail);
}
// compress if allowed
@ -2037,7 +2079,15 @@ Returnit:
else
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);
sendandcheck(sock, Header, HeaderLen);
sendandcheck(sock, Compressed, ReplyLen);
@ -3889,7 +3939,7 @@ SendResp:
}
return 0;
#ifdef WIN32
#ifdef WIN32xx
}
#include "StdExcept.c"
}

View File

@ -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);

View File

@ -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

View File

@ -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
{

View File

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

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
@ -1819,6 +1827,14 @@ static VOID SetupListenSet(struct TNCINFO * TNC)
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)

View File

@ -10,16 +10,16 @@
#endif
#define KVers 6,0,24,22
#define KVerstring "6.0.24.22\0"
#define KVers 6,0,24,27
#define KVerstring "6.0.24.27\0"
#ifdef CKernel
#define Vers KVers
#define Verstring KVerstring
#define Datestring "November 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"

View File

@ -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,17 +721,19 @@ VOID ProcessFormDir(char * FormSet, char * DirName, struct HtmlFormDir *** xxx,
{
if (entry->d_type == DT_DIR)
{
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
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[FormDir->FormCount++] = Form;
}
}
closedir(dir);
#endif
return;
@ -808,9 +811,9 @@ int GetHTMLFormSet(char * FormSet)
if (!(dir = opendir(name)))
{
Debugprintf("cant open forms dir %s %d %d", name, errno, dir);
return 0;
}
else
{
while ((entry = readdir(dir)) != NULL)
{
if (entry->d_type == DT_DIR)
@ -824,6 +827,7 @@ int GetHTMLFormSet(char * FormSet)
}
}
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,12 +2849,25 @@ 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)
{
return CheckFile(Dir, Dir->Dirs[l]->Forms[k]->FileName);
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(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, "</"); // end of value string
if (ptr3 == NULL)
goto quit;
@ -3236,6 +3260,14 @@ BOOL ParseXML(WebMailInfo * WebMail, char * XMLOrig)
XMLKeys++;
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
printf("%s\n", MsgFile);
if (stat(MsgFile, &STAT) != -1)
{
hFile = fopen(MsgFile, "rb");
@ -5365,6 +5399,8 @@ char * CheckFile(struct HtmlFormDir * Dir, char * FN)
MsgBytes[FileSize] = 0;
fclose(hFile);
printf("%d %s\n", strlen(MsgBytes), MsgBytes);
return MsgBytes;
}
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="NOTTSDESKTOP"
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="NOTTSDESKTOP"
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="NOTTSDESKTOP"
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="NOTTSDESKTOP"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>

18
debian/changelog vendored
View File

@ -1,3 +1,21 @@
linbpq (6.0.24.27-jammy1) jammy; urgency=medium
* Rebuild for jammy.
-- Dave Hibberd <d@vehibberd.com> Tue, 16 Jan 2024 20:59:52 +0000
linbpq (6.0.24.27-1) unstable; urgency=medium
* New Upstream Release
-- Dave Hibberd <d@vehibberd.com> Tue, 16 Jan 2024 20:51:43 +0000
linbpq (6.0.24.25-1) unstable; urgency=medium
* New Upstream Release
-- Dave Hibberd <d@vehibberd.com> Thu, 28 Dec 2023 10:44:47 +0000
linbpq (6.0.24.22-jammy2) jammy; urgency=medium
* Rebuild for jammy.

2
debian/preinst vendored
View File

@ -10,3 +10,5 @@ if [ -L $confile ]; then
cp $node $confile
mv $node $node.bak
fi
#DEBHELPER#

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 \
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:

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 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

View File

@ -478,7 +478,9 @@ char * MainConfigtxt()
" <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=\"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"
"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"
@ -515,7 +517,7 @@ char * MainConfigtxt()
"&nbsp;FBB reject.sys type filters (all fields must match, wildcards allowed)\r\n"
"<p></p>"
"<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'>"
"</div>"
"</form>\r\n"
@ -1428,7 +1430,7 @@ char * ChatConfigtxt()
"<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"
"<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"
"action=\"/Chat/ChatConfig?%s\">\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"
"&nbsp;&nbsp; <input value=\"%d\" size=\"3\" name=\"Streams\"><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 "
"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()
"<textarea cols=\"80\" rows=\"5\" name=\"welcome\">%s</textarea><br>\r\n"
"<br>\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=\"UpdateMap\" value=\"Update Map\" 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 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;

187
upnp.c.bak Normal file
View File

@ -0,0 +1,187 @@
// Includes code from MiniUPnPc, used subject to the following conditions:
/*
MiniUPnPc
Copyright (c) 2005-2020, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#define MINIUPNP_STATICLIB
#include <stdio.h>
#ifdef _WIN32
#include "upnpcommands.h"
#include "miniupnpc.h"
#include "upnperrors.h"
#include <winsock2.h>
#else
#include <miniupnpc/upnpcommands.h>
#include <miniupnpc/miniupnpc.h>
#include <miniupnpc/upnperrors.h>
#include <stdio.h>
#endif
int AddMap(char * controlURL, char * eport, char * iport, char * proto);
int DeleteMap(char * controlURL, char * eport, char * iport, char * proto);
void Consoleprintf(const char * format, ...);
struct UPNP
{
struct UPNP * Next;
char * Protocol;
char * LANport;
char * WANPort;
};
extern struct UPNP * UPNPConfig;
char * controlURL = 0;
char * servicetype = 0;
char iaddr[] = "IP";
char * inClient = NULL;
#ifdef LINBPQ
char desc[] = "LinBPQ ";
#else
char desc[] = "BPQ32 ";
#endif
char * remoteHost = NULL;
char * leaseDuration = NULL;
struct UPNPDev * devlist = 0;
char lanaddr[64] = "unset"; /* my ip address on the LAN */
struct UPNPUrls urls;
struct IGDdatas data;
int i;
const char * rootdescurl = 0;
const char * multicastif = 0;
const char * minissdpdpath = 0;
int localport = UPNP_LOCAL_PORT_ANY;
int retcode = 0;
int error = 0;
int ipv6 = 0;
int ignore = 0;
unsigned char ttl = 2;
int upnpInit()
{
struct UPNP * Config = UPNPConfig;
int i;
#ifdef WIN32
WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if(nResult != NO_ERROR)
{
fprintf(stderr, "WSAStartup() failed.\n");
return -1;
}
#endif
while (Config)
{
if (devlist == NULL)
{
devlist = upnpDiscover(2000, multicastif, minissdpdpath, localport, ipv6, ttl, &error);
if (devlist == NULL)
{
Consoleprintf("Failed to find a UPNP device");
return 0;
}
i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
}
AddMap(devlist->descURL, Config->LANport, Config->WANPort, Config->Protocol);
Config = Config->Next;
}
return 0;
}
int upnpClose()
{
struct UPNP * Config = UPNPConfig;
int i;
while (Config)
{
if (devlist == NULL)
{
devlist = upnpDiscover(2000, multicastif, minissdpdpath, localport, ipv6, ttl, &error);
if (devlist == NULL)
{
Consoleprintf("Failed to find a UPNP device");
return 0;
}
i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
}
DeleteMap(devlist->descURL, Config->LANport, Config->WANPort, Config->Protocol);
Config = Config->Next;
}
return 0;
}
int AddMap(char * controlURL, char * eport, char * iport, char * proto)
{
int r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
eport, iport, lanaddr, desc,
proto, remoteHost, leaseDuration);
if (r != UPNPCOMMAND_SUCCESS)
{
Consoleprintf("UPNP AddPortMapping(%s, %s, %s) failed with code %d (%s)", eport, iport, lanaddr, r, strupnperror(r));
return -2;
}
Consoleprintf("UPNP AddPortMapping(%s, %s, %s) Succeeded", eport, iport, lanaddr, r);
return 0;
}
int DeleteMap(char * controlURL, char * eport, char * iport, char * proto)
{
int r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, eport, proto, remoteHost);
if(r != UPNPCOMMAND_SUCCESS)
{
Consoleprintf("UPNP DeletePortMapping(%s, %s, %s) failed with code %d (%s)", eport, iport, lanaddr, r, strupnperror(r));
return -2;
}
Consoleprintf("UPNP DeletePortMapping(%s, %s, %s) Succeeded", eport, iport, lanaddr, r);
return 0;
}