diff --git a/BBSHTMLConfig.c b/BBSHTMLConfig.c index 01b05bd..16acac6 100644 --- a/BBSHTMLConfig.c +++ b/BBSHTMLConfig.c @@ -49,6 +49,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. @@ -1633,6 +1634,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 +2612,7 @@ VOID SendConfigPage(char * Reply, int * ReplyLen, char * Key) (UserCantKillT) ? UNC : CHKD, // Reverse logic (ForwardToMe) ? CHKD : UNC, (OnlyKnown) ? CHKD : UNC, + (reportMailEvents) ? CHKD : UNC, POP3InPort, SMTPInPort, NNTPInPort, (RemoteEmail) ? CHKD : UNC, AMPRDomain, diff --git a/BBSUtilities.c b/BBSUtilities.c index 1d3c1f2..48f927a 100644 --- a/BBSUtilities.c +++ b/BBSUtilities.c @@ -43,7 +43,7 @@ RECT ConsoleRect; BOOL OpenConsole; BOOL OpenMon; -int reportNewMesageEvents = 0; +int reportMailEvents = 0; FBBFilter * Filters = NULL; @@ -124,6 +124,8 @@ void decodeblock( unsigned char in[4], unsigned char out[3]); int encode_quoted_printable(char *s, char * out, int Len); int32_t Encode(char * in, char * out, int32_t inlen, BOOL B1Protocol, int Compress); int APIENTRY ChangeSessionCallsign(int Stream, unsigned char * AXCall); +void SendMessageReadEvent(char * user, struct MsgInfo * Msg); +void SendNewMessageEvent(char * call, struct MsgInfo * Msg); config_t cfg; config_setting_t * group; @@ -4904,6 +4906,7 @@ sendEOM: Msg->status = 'Y'; Msg->datechanged=time(NULL); SaveMessageDatabase(); + SendMessageReadEvent(user->Call, Msg); } } } @@ -6457,30 +6460,9 @@ nextline: // If Event Notifications enabled report a new message event - if (reportNewMesageEvents) - { - char msg[200]; - - //12345 B 2053 TEST@ALL F6FBB 920325 This is the subject - - struct tm *tm = gmtime((time_t *)&Msg->datecreated); - - sprintf_s(msg, sizeof(msg),"%-6d %c %6d %-13s %-6s %02d%02d%02d %s\r", - Msg->number, Msg->type, Msg->length, Msg->to, - Msg->from, tm->tm_year-100, tm->tm_mon+1, tm->tm_mday, Msg->title); - -#ifdef WIN32 - if (pRunEventProgram) - pRunEventProgram("MailNewMsg.exe", msg); -#else - { - char prog[256]; - sprintf(prog, "%s/%s", BPQDirectory, "MailNewMsg"); - RunEventProgram(prog, msg); - } -#endif - } + user = LookupCall(Msg->to); + SendNewMessageEvent(user->Call, Msg); if (EnableUI) #ifdef LINBPQ @@ -6493,8 +6475,6 @@ nextline: My__except_Routine("SendMsgUI"); #endif - user = LookupCall(Msg->to); - if (user && (user->flags & F_APRSMFOR)) { char APRS[128]; @@ -9576,6 +9556,7 @@ VOID SaveConfig(char * ConfigName) SaveIntValue(group, "EnableUI", EnableUI); SaveIntValue(group, "RefuseBulls", RefuseBulls); SaveIntValue(group, "OnlyKnown", OnlyKnown); + SaveIntValue(group, "reportMailEvents", reportMailEvents); SaveIntValue(group, "SendSYStoSYSOPCall", SendSYStoSYSOPCall); SaveIntValue(group, "SendBBStoSYSOPCall", SendBBStoSYSOPCall); SaveIntValue(group, "DontHoldNewUsers", DontHoldNewUsers); @@ -10098,28 +10079,30 @@ BOOL GetConfig(char * ConfigName) config_destroy(&cfg); return(EXIT_FAILURE); } - +/* #if LIBCONFIG_VER_MINOR > 5 config_set_option(&cfg, CONFIG_OPTION_AUTOCONVERT, 1); #else config_set_auto_convert (&cfg, 1); #endif - +*/ group = config_lookup (&cfg, "main"); if (group == NULL) return EXIT_FAILURE; - SMTPInPort = GetIntValue(group, "SMTPPort"); - POP3InPort = GetIntValue(group, "POP3Port"); - NNTPInPort = GetIntValue(group, "NNTPPort"); - RemoteEmail = GetIntValue(group, "RemoteEmail"); - MaxStreams = GetIntValue(group, "Streams"); - BBSApplNum = GetIntValue(group, "BBSApplNum"); - EnableUI = GetIntValue(group, "EnableUI"); - MailForInterval = GetIntValue(group, "MailForInterval"); - RefuseBulls = GetIntValue(group, "RefuseBulls"); - OnlyKnown = GetIntValue(group, "OnlyKnown"); + SMTPInPort = GetIntValue(group, "SMTPPort"); + POP3InPort = GetIntValue(group, "POP3Port"); + NNTPInPort = GetIntValue(group, "NNTPPort"); + RemoteEmail = GetIntValue(group, "RemoteEmail"); + MaxStreams = GetIntValue(group, "Streams"); + BBSApplNum = GetIntValue(group, "BBSApplNum"); + EnableUI = GetIntValue(group, "EnableUI"); + MailForInterval = GetIntValue(group, "MailForInterval"); + RefuseBulls = GetIntValue(group, "RefuseBulls"); + OnlyKnown = GetIntValue(group, "OnlyKnown"); + reportMailEvents = GetIntValue(group, "reportMailEvents"); + SendSYStoSYSOPCall = GetIntValue(group, "SendSYStoSYSOPCall"); SendBBStoSYSOPCall = GetIntValue(group, "SendBBStoSYSOPCall"); DontHoldNewUsers = GetIntValue(group, "DontHoldNewUsers"); @@ -15793,3 +15776,62 @@ VOID GetPGConfig() NUM_SERVERS = n; fclose(file); } + +void SendMessageReadEvent(char * call, struct MsgInfo * Msg) +{ + if (reportMailEvents) + { + char msg[512]; + + //12345 B 2053 TEST@ALL F6FBB 920325 This is the subject + + struct tm *tm = gmtime((time_t *)&Msg->datecreated); + + sprintf_s(msg, sizeof(msg),"%-6d %c %c %6d %-13s %-6s %02d%02d%02d %s\r", + Msg->number, Msg->type, Msg->status, Msg->length, Msg->to, + Msg->from, tm->tm_year-100, tm->tm_mon+1, tm->tm_mday, Msg->title); + +// sprintf(msg, "%s Read %d\r", user->Call, Msg->number); + +#ifdef WIN32 + if (pRunEventProgram) + pRunEventProgram("MailMsgRead.exe", msg); +#else + { + char prog[256]; + sprintf(prog, "%s/%s", BPQDirectory, "MailMsgRead"); + RunEventProgram(prog, msg); + } +#endif + } +} + +void SendNewMessageEvent(char * call, struct MsgInfo * Msg) +{ + if (reportMailEvents) + { + char msg[512]; + + //12345 B 2053 TEST@ALL F6FBB 920325 This is the subject + + struct tm *tm = gmtime((time_t *)&Msg->datecreated); + + sprintf_s(msg, sizeof(msg),"%-6d %c %c %6d %-13s %-6s %02d%02d%02d %s\r", + Msg->number, Msg->type, Msg->status, Msg->length, Msg->to, + Msg->from, tm->tm_year-100, tm->tm_mon+1, tm->tm_mday, Msg->title); + +#ifdef WIN32 + if (pRunEventProgram) + pRunEventProgram("MailNewMsg.exe", msg); +#else + { + char prog[256]; + sprintf(prog, "%s/%s", BPQDirectory, "MailNewMsg"); + RunEventProgram(prog, msg); + } +#endif + } +} + + + diff --git a/BPQMail.c b/BPQMail.c index bd37641..6b5273e 100644 --- a/BPQMail.c +++ b/BPQMail.c @@ -1123,6 +1123,7 @@ // 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) diff --git a/Bpq32.c b/Bpq32.c index f2c5451..e5868dd 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1203,6 +1203,9 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // Improve restart of WinRPR TNC on remote host (21) // Fix some Rigcontrol issues with empty timebands (22) // Fix 64 bit bug in processing INP3 Messages (22) +// First pass at api (24) +// Send OK in response to Rigcontrol CMD (24); + #define CKernel @@ -2065,7 +2068,7 @@ VOID TimerProcX() GetWindowRect(FrameWnd, &FRect); - SaveWindowPos(64); // Rigcontrol + SaveWindowPos(70); // Rigcontrol for (i=0;iPORTCONTROL.PORTPOINTER; } - SaveWindowPos(40); // Rigcontrol + SaveWindowPos(70); // Rigcontrol if (hIPResWnd) diff --git a/CBPQ32.vcproj b/CBPQ32.vcproj index c1c95a2..b26d36a 100644 --- a/CBPQ32.vcproj +++ b/CBPQ32.vcproj @@ -74,7 +74,7 @@ + + diff --git a/CHeaders.h b/CHeaders.h index 0d6886e..caf288b 100644 --- a/CHeaders.h +++ b/CHeaders.h @@ -406,7 +406,7 @@ extern BOOL CloseAllNeeded; extern int CloseOnError; extern char * PortConfig[70]; -extern struct TNCINFO * TNCInfo[70]; // Records are Malloc'd +extern struct TNCINFO * TNCInfo[71]; // Records are Malloc'd #define MaxBPQPortNo 63 // Port 64 reserved for BBS Mon #define MAXBPQPORTS 63 diff --git a/ChatHTMLConfig.c b/ChatHTMLConfig.c index b4d90b6..c4071cf 100644 --- a/ChatHTMLConfig.c +++ b/ChatHTMLConfig.c @@ -67,6 +67,7 @@ extern int MaxChatStreams; extern char Position[81]; extern char PopupText[251]; extern int PopupMode; +extern int reportChatEvents; #include "httpconnectioninfo.h" @@ -323,6 +324,8 @@ VOID SaveChatInfo(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Rep if (chatPaclen < 60) chatPaclen = 60; + GetCheckBox(input, "Events=", &reportChatEvents); + GetParam(input, "nodes=", Nodes); ptr1 = Nodes; @@ -508,7 +511,9 @@ scan: Len = sprintf(Reply, ChatConfigTemplate, OurNode, Key, Key, Key, - ChatApplNum, MaxChatStreams, Nodes, chatPaclen, Position, + ChatApplNum, MaxChatStreams, + (reportChatEvents) ? CHKD : UNC, + Nodes, chatPaclen, Position, (PopupMode) ? UNC : CHKD, (PopupMode) ? CHKD : UNC, Text, ptr2); diff --git a/CommonCode.c b/CommonCode.c index d28cefa..0ce16cb 100644 --- a/CommonCode.c +++ b/CommonCode.c @@ -49,7 +49,7 @@ extern struct CONFIGTABLE xxcfg; #endif -struct TNCINFO * TNCInfo[70]; // Records are Malloc'd +struct TNCINFO * TNCInfo[71]; // Records are Malloc'd extern int ReportTimer; diff --git a/FormatHTML.cpp b/FormatHTML.cpp index f27498c..88e306e 100644 --- a/FormatHTML.cpp +++ b/FormatHTML.cpp @@ -1,60 +1,60 @@ -// FormatHTML.cpp : Defines the entry point for the console application. -// -#include - -int main () { - FILE *fp, *fp2; - char str[256]; - char newstr[256]; - char * ptr, * inptr; - - /* opening file for reading */ - fp = fopen("D:/AtomProject/test.html" , "r"); - fp2 = fopen("D:/AtomProject/test.html.c" , "w"); - - if(fp == NULL) { - perror("Error opening file"); - return(-1); - } - - while(fgets (str, 256, fp) != NULL) - { - // Replace any " with \" and add " on front and \r\n" on end - - char c; - ptr = newstr; - inptr = str; - - c = *(inptr++); - - *(ptr++) = '"'; - - while (c && c != 10) - { - if (c == '"') - *(ptr++) = '\\'; - - *(ptr++) = c; - - c = *(inptr++); - } - - - *(ptr++) = '\\'; - *(ptr++) = 'r'; - *(ptr++) = '\\'; - *(ptr++) = 'n'; - *(ptr++) = '"'; - *(ptr++) = 10; - *(ptr++) = 0; - - puts(newstr); - fputs(newstr, fp2); - - } - - fclose(fp); - fclose(fp2); - - return(0); +// FormatHTML.cpp : Defines the entry point for the console application. +// +#include + +int main () { + FILE *fp, *fp2; + char str[256]; + char newstr[256]; + char * ptr, * inptr; + + /* opening file for reading */ + fp = fopen("D:/AtomProject/test.html" , "r"); + fp2 = fopen("D:/AtomProject/test.html.c" , "w"); + + if(fp == NULL) { + perror("Error opening file"); + return(-1); + } + + while(fgets (str, 256, fp) != NULL) + { + // Replace any " with \" and add " on front and \r\n" on end + + char c; + ptr = newstr; + inptr = str; + + c = *(inptr++); + + *(ptr++) = '"'; + + while (c && c != 10) + { + if (c == '"') + *(ptr++) = '\\'; + + *(ptr++) = c; + + c = *(inptr++); + } + + + *(ptr++) = '\\'; + *(ptr++) = 'r'; + *(ptr++) = '\\'; + *(ptr++) = 'n'; + *(ptr++) = '"'; + *(ptr++) = 10; + *(ptr++) = 0; + + puts(newstr); + fputs(newstr, fp2); + + } + + fclose(fp); + fclose(fp2); + + return(0); } \ No newline at end of file diff --git a/FormatHTML.vcproj b/FormatHTML.vcproj index 95563d4..1c3dce1 100644 --- a/FormatHTML.vcproj +++ b/FormatHTML.vcproj @@ -1,219 +1,219 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/HTTPcode.c b/HTTPcode.c index 30cf2bd..2bf6874 100644 --- a/HTTPcode.c +++ b/HTTPcode.c @@ -69,6 +69,7 @@ int GetAPRSIcon(unsigned char * _REPLYBUFFER, char * NodeURL); char * GetStandardPage(char * FN, int * Len); BOOL SHA1PasswordHash(char * String, char * Hash); char * byte_base64_encode(char *str, int len); +int APIProcessHTTPMessage(char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE); extern struct ROUTE * NEIGHBOURS; extern int ROUTE_LEN; @@ -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) @@ -3889,7 +3927,7 @@ SendResp: } return 0; -#ifdef WIN32 +#ifdef WIN32xx } #include "StdExcept.c" } diff --git a/HanksRT.c b/HanksRT.c index cfc6440..3a7d538 100644 --- a/HanksRT.c +++ b/HanksRT.c @@ -77,6 +77,8 @@ char PopupText[260] = ""; int PopupMode = 0; int chatPaclen = 236; +int reportChatEvents = 0; + char RtKnown[MAX_PATH] = "RTKnown.txt"; char RtUsr[MAX_PATH] = "STUsers.txt"; char RtUsrTemp[MAX_PATH] = "STUsers.tmp"; @@ -2079,6 +2081,18 @@ void text_tellu_Joined(USER * user) sprintf(buf, "%s%-6.6s : %s *** Joined Chat, Topic %s", Stamp, user->call, user->name, user->topic->name); + if (reportChatEvents) + { + +#ifdef WIN32 + if (pRunEventProgram) + pRunEventProgram("ChatNewUser.exe", user->call); +#else + sprintf(prog, "%s/%s", BPQDirectory, "ChatNewUser"); + RunEventProgram(prog, user->call); +#endif + } + // Send it to all connected users in the same topic. // Echo to originator if requested. @@ -2109,14 +2123,6 @@ void text_tellu_Joined(USER * user) nputc(circuit, 7); nputc(circuit, 13); - -#ifdef WIN32 - if (pRunEventProgram) - pRunEventProgram("ChatNewUser.exe", user->call); -#else - sprintf(prog, "%s/%s", BPQDirectory, "ChatNewUser"); - RunEventProgram(prog, user->call); -#endif } } // Tell one link circuit about a local user change of topic. @@ -4170,6 +4176,7 @@ BOOL GetChatConfig(char * ConfigName) ChatApplNum = GetIntValue(group, "ApplNum"); MaxChatStreams = GetIntValue(group, "MaxStreams"); + reportChatEvents = GetIntValue(group, "reportChatEvents"); chatPaclen = GetIntValue(group, "chatPaclen"); GetStringValue(group, "OtherChatNodes", OtherNodesList); GetStringValue(group, "ChatWelcomeMsg", ChatWelcomeMsg); @@ -4201,6 +4208,7 @@ VOID SaveChatConfigFile(char * ConfigName) SaveIntValue(group, "ApplNum", ChatApplNum); SaveIntValue(group, "MaxStreams", MaxChatStreams); + SaveIntValue(group, "reportChatEvents", reportChatEvents); SaveIntValue(group, "chatPaclen", chatPaclen); SaveStringValue(group, "OtherChatNodes", OtherNodesList); SaveStringValue(group, "ChatWelcomeMsg", ChatWelcomeMsg); diff --git a/MBLRoutines.c b/MBLRoutines.c index d116893..e7ae622 100644 --- a/MBLRoutines.c +++ b/MBLRoutines.c @@ -23,6 +23,9 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #include "bpqmail.h" +void SendMessageReadEvent(struct UserInfo * user, struct MsgInfo * Msg); + + VOID ProcessMBLLine(CIRCUIT * conn, struct UserInfo * user, UCHAR* Buffer, int len) { Buffer[len] = 0; @@ -86,6 +89,7 @@ VOID ProcessMBLLine(CIRCUIT * conn, struct UserInfo * user, UCHAR* Buffer, int l FBBputs(conn, ">\r"); Msg->status = 'Y'; // Mark as read SaveMessageDatabase(); + SendMessageReadEvent(user->Call, Msg); } else { diff --git a/RigControl.c b/RigControl.c index 0e56d6e..f5ef723 100644 --- a/RigControl.c +++ b/RigControl.c @@ -1142,7 +1142,6 @@ int Rig_CommandEx(struct RIGPORTINFO * PORT, struct RIGINFO * RIG, TRANSPORTENTR return FALSE; } - // Build a ScanEntry in the buffer FreqPtr = (struct ScanEntry *)buffptr->Data; @@ -1277,8 +1276,6 @@ int Rig_CommandEx(struct RIGPORTINFO * PORT, struct RIGINFO * RIG, TRANSPORTENTR } *(CmdPtr++) = 0xFD; - - *(CmdPtr) = 0; Len = (int)(CmdPtr - (char *)&buffptr[30]); @@ -1326,6 +1323,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 +2203,7 @@ DllExport BOOL APIENTRY Rig_Init() memset(&RIGTNC, 0, sizeof(struct TNCINFO)); - TNCInfo[40] = TNC; + TNCInfo[70] = TNC; // Get config info @@ -2229,7 +2229,7 @@ DllExport BOOL APIENTRY Rig_Init() #ifndef LINBPQ - TNC->Port = 40; + TNC->Port = 70; CreatePactorWindow(TNC, "RIGCONTROL", "RigControl", 10, PacWndProc, 550, NeedRig * 20 + 60, NULL); hDlg = TNC->hDlg; diff --git a/TelnetV6.c b/TelnetV6.c index ad4c70b..efec041 100644 --- a/TelnetV6.c +++ b/TelnetV6.c @@ -534,6 +534,9 @@ int ProcessLine(char * buf, int Port) else if (_stricmp(param,"HTTPPORT") == 0) TCP->HTTPPort = atoi(value); + else if (_stricmp(param,"APIPORT") == 0) + TCP->APIPort = atoi(value); + else if (_stricmp(param,"SYNCPORT") == 0) TCP->SyncPort = atoi(value); @@ -1646,6 +1649,9 @@ BOOL OpenSockets(struct TNCINFO * TNC) if (TCP->HTTPPort) TCP->HTTPsock = OpenSocket4(TNC, TCP->HTTPPort); + if (TCP->APIPort) + TCP->APIsock = OpenSocket4(TNC, TCP->APIPort); + if (TCP->SyncPort) TCP->Syncsock = OpenSocket4(TNC, TCP->SyncPort); @@ -1755,10 +1761,12 @@ BOOL OpenSockets6(struct TNCINFO * TNC) if (TCP->RelayPort) TCP->Relaysock6 = OpenSocket6(TNC, TCP->RelayPort); - if (TCP->HTTPPort) TCP->HTTPsock6 = OpenSocket6(TNC, TCP->HTTPPort); + if (TCP->APIPort) + TCP->APIsock6 = OpenSocket6(TNC, TCP->APIPort); + if (TCP->SyncPort) TCP->Syncsock6 = OpenSocket6(TNC, TCP->SyncPort); @@ -1818,6 +1826,14 @@ static VOID SetupListenSet(struct TNCINFO * TNC) if (sock > maxsock) maxsock = sock; } + + sock = TCP->APIsock; + if (sock) + { + FD_SET(sock, readfd); + if (sock > maxsock) + maxsock = sock; + } sock = TCP->Syncsock; if (sock) @@ -1886,6 +1902,14 @@ static VOID SetupListenSet(struct TNCINFO * TNC) maxsock = sock; } + sock = TCP->APIsock6; + if (sock) + { + FD_SET(sock, readfd); + if (sock > maxsock) + maxsock = sock; + } + sock = TCP->DRATSsock6; if (sock) @@ -3192,6 +3216,7 @@ int Socket_Accept(struct TNCINFO * TNC, SOCKET SocketId, int Port) TNC->Streams[n].FramesQueued = 0; sockptr->HTTPMode = FALSE; + sockptr->APIMode = FALSE; sockptr->SyncMode = FALSE; sockptr->DRATSMode = FALSE; sockptr->FBBMode = FALSE; @@ -3208,6 +3233,12 @@ int Socket_Accept(struct TNCINFO * TNC, SOCKET SocketId, int Port) if (SocketId == TCP->HTTPsock || SocketId == TCP->HTTPsock6) sockptr->HTTPMode = TRUE; + + if (SocketId == TCP->APIsock || SocketId == TCP->APIsock6) + { + sockptr->HTTPMode = TRUE; // API is a type of HTTP socket + sockptr->APIMode = TRUE; + } else if (SocketId == TCP->Syncsock || SocketId == TCP->Syncsock6) sockptr->SyncMode = TRUE; else if (SocketId == TCP->DRATSsock || SocketId == TCP->DRATSsock6) diff --git a/Versions.h b/Versions.h index 56bfe73..42ef59e 100644 --- a/Versions.h +++ b/Versions.h @@ -10,14 +10,14 @@ #endif -#define KVers 6,0,24,22 -#define KVerstring "6.0.24.22\0" +#define KVers 6,0,24,24 +#define KVerstring "6.0.24.24\0" #ifdef CKernel #define Vers KVers #define Verstring KVerstring -#define Datestring "November 2023" +#define Datestring "December 2023" #define VerComments "G8BPQ Packet Switch (C Version)" KVerstring #define VerCopyright "Copyright © 2001-2023 John Wiseman G8BPQ\0" #define VerDesc "BPQ32 Switch\0" diff --git a/WebMail.c b/WebMail.c index f626975..36b7adc 100644 --- a/WebMail.c +++ b/WebMail.c @@ -76,6 +76,8 @@ VOID SendTemplateSelectScreen(struct HTTPConnectionInfo * Session, char *URLPara BOOL isAMPRMsg(char * Addr); char * doXMLTransparency(char * string); Dll BOOL APIENTRY APISendAPRSMessage(char * Text, char * ToCall); +void SendMessageReadEvent(struct UserInfo * user, struct MsgInfo * Msg); +void SendNewMessageEvent(char * call, struct MsgInfo * Msg); extern char NodeTail[]; extern char BBSName[10]; @@ -1122,7 +1124,7 @@ int ViewWebMailMessage(struct HTTPConnectionInfo * Session, char * Reply, int Nu Msg->status = 'Y'; Msg->datechanged=time(NULL); SaveMessageDatabase(); - + SendMessageReadEvent(Session->Callsign, Msg); } } } @@ -1190,6 +1192,7 @@ int ViewWebMailMessage(struct HTTPConnectionInfo * Session, char * Reply, int Nu Msg->status = 'Y'; Msg->datechanged=time(NULL); SaveMessageDatabase(); + SendMessageReadEvent(Session->Callsign, Msg); } } } @@ -1303,6 +1306,7 @@ int ViewWebMailMessage(struct HTTPConnectionInfo * Session, char * Reply, int Nu Msg->status = 'Y'; Msg->datechanged=time(NULL); SaveMessageDatabase(); + SendMessageReadEvent(Session->Callsign, Msg); } } } @@ -2776,11 +2780,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]; diff --git a/debug/bpq32.pdb b/debug/bpq32.pdb new file mode 100644 index 0000000..88888aa Binary files /dev/null and b/debug/bpq32.pdb differ diff --git a/makefile b/makefile index 184cfbf..5ded262 100644 --- a/makefile +++ b/makefile @@ -13,7 +13,7 @@ OBJS = pngwtran.o pngrtran.o pngset.o pngrio.o pngwio.o pngtrans.o pngrutil.o pn MailCommands.o MailDataDefs.o LinBPQ.o MailRouting.o MailTCP.o MBLRoutines.o md5.o Moncode.o \ NNTPRoutines.o RigControl.o TelnetV6.o WINMOR.o TNCCode.o UZ7HODrv.o WPRoutines.o \ SCSTrackeMulti.o SCSPactor.o SCSTracker.o HanksRT.o UIRoutines.o AGWAPI.o AGWMoncode.o \ - DRATS.o FreeDATA.o base64.o Events.o + DRATS.o FreeDATA.o base64.o Events.o nodeapi.h # Configuration: diff --git a/makefile~ b/makefile~ new file mode 100644 index 0000000..184cfbf --- /dev/null +++ b/makefile~ @@ -0,0 +1,39 @@ +# LinBPQ Makefile + +# To exclude i2c support run make noi2c + +OBJS = pngwtran.o pngrtran.o pngset.o pngrio.o pngwio.o pngtrans.o pngrutil.o pngwutil.o\ + pngread.o pngwrite.o png.o pngerror.o pngget.o pngmem.o APRSIconData.o AISCommon.o\ + upnp.o APRSStdPages.o HSMODEM.o WinRPR.o KISSHF.o TNCEmulators.o bpqhdlc.o SerialPort.o\ + adif.o WebMail.o utf8Routines.o VARA.o LzFind.o Alloc.o LzmaDec.o LzmaEnc.o LzmaLib.o \ + Multicast.o ARDOP.o IPCode.o FLDigi.o linether.o CMSAuth.o APRSCode.o BPQtoAGW.o KAMPactor.o\ + AEAPactor.o HALDriver.o MULTIPSK.o BBSHTMLConfig.o ChatHTMLConfig.o BBSUtilities.o bpqaxip.o\ + BPQINP3.o BPQNRR.o cMain.o Cmd.o CommonCode.o HTMLCommonCode.o compatbits.o config.o datadefs.o \ + FBBRoutines.o HFCommon.o Housekeeping.o HTTPcode.o kiss.o L2Code.o L3Code.o L4Code.o lzhuf32.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 \ + SCSTrackeMulti.o SCSPactor.o SCSTracker.o HanksRT.o UIRoutines.o AGWAPI.o AGWMoncode.o \ + DRATS.o FreeDATA.o base64.o Events.o + +# Configuration: + +CC = gcc + +all: CFLAGS = -DLINBPQ -MMD -g -fcommon +all: linbpq + + +noi2c: CFLAGS = -DLINBPQ -MMD -DNOI2C -g -fcommon +noi2c: linbpq + + +linbpq: $(OBJS) + gcc $(OBJS) -Xlinker -Map=output.map -l:libminiupnpc.a -lrt -lm -lz -lpthread -lconfig -lpcap -o linbpq + sudo setcap "CAP_NET_ADMIN=ep CAP_NET_RAW=ep CAP_NET_BIND_SERVICE=ep" linbpq + +-include *.d + +clean : + rm *.d + rm linbpq $(OBJS) + diff --git a/nodeapi.c b/nodeapi.c new file mode 100644 index 0000000..75fa272 --- /dev/null +++ b/nodeapi.c @@ -0,0 +1,645 @@ +// basic JASON API to BPQ Node + +// Authentication is via Telnet USER records. + + +#define _CRT_SECURE_NO_DEPRECATE + +#include "CHeaders.h" +#include +#include "tncinfo.h" +#include "asmstrucs.h" +#include "kiss.h" + +// Constants +#define TOKEN_SIZE 32 // Length of the authentication token +#define TOKEN_EXPIRATION 7200 // Token expiration time in seconds (2 hours) + +// Token data structure +typedef struct Token { + char token[TOKEN_SIZE + 1]; + time_t expiration_time; + struct Token* next; +} Token; + + +// Function prototypes +void handle_request(SOCKET client_socket, char * request, char * response); +int verify_token(const char* token); +void remove_expired_tokens(); +char* fetch_data(const char* endpoint); +int request_token(char * response); +int send_http_response(char * response, const char* msg); +int create_json_response(char * response, char* access_token, int expires_in, char* scope); +void add_token_to_list(Token* token); + +Token* find_token(const char* token); +Token* generate_token(); + +int sendPortList(char * response, char * token,int Flags); +int sendNodeList(char * response, char * token,int Flags); +int sendUserList(char * response, char * token,int Flags); +int sendInfo(char * response, char * token, int Flags); + +DllExport struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot(int portslot); + +// Token list +Token* token_list = NULL; + +int xx() +{ + while (1) + { + // Remove expired tokens + remove_expired_tokens(); + + // Handle the client request + // handle_request(); + } + + return 0; +} + +int APIProcessHTTPMessage(char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE) +{ + const char * auth_header = "Authorization: Bearer "; + char * token_begin = strstr(request, auth_header); + char token[TOKEN_SIZE + 1]= ""; + char * param = strlop(URL, '?'); + int Flags = 0; + + if (param && strlen(param) == TOKEN_SIZE) + { + // assume auth token + + strcpy(token, param); + } + + remove_expired_tokens(); // Tidy up + + // Check if the request is for token generation + + if (strcmp(Method, "GET") != 0) + return send_http_response(response, "403 (Bad Method)"); + + if (_stricmp(URL, "/api/request_token") == 0) + return request_token(response); + + if (token[0] == 0) + { + // Extract the token from the request (assuming it's present in the request headers) + if (token_begin == NULL) + { + Debugprintf("Invalid request: No authentication token provided.\n"); + return send_http_response(response, "403 (Forbidden)"); + } + token_begin += strlen(auth_header); // Move to the beginning of the token + strncpy(token, token_begin, TOKEN_SIZE); + token[TOKEN_SIZE] = '\0'; // Null-terminate the token + } + + // Verify the token + if (!verify_token(token)) + { + Debugprintf("Invalid authentication token.\n"); + return send_http_response(response, "401 Unauthorized"); + } + + // Determine the requested API endpoint + + if (_stricmp(URL, "/api/getports") == 0) + return sendPortList(response, token, Flags); + else if (_stricmp(URL, "/api/getnodes") == 0) + return sendNodeList(response, token, Flags); + else if (_stricmp(URL, "/api/getusers") == 0) + return sendUserList(response, token, Flags); + else if (_stricmp(URL, "/api/getinfo") == 0) + return sendInfo(response, token, Flags); + + return send_http_response(response, "401 Invalid API Call"); + +} + +int request_token(char * response) +{ + Token * token = generate_token(); + int expires_in = 3600; + char scope[] = "create"; + + printf("Token generated: %s\n", token->token); + + sprintf(response, "{\"access_token\":\"%s\", \"expires_in\":%d, \"scope\":\"create\"}\r\n", + token->token, expires_in); + + return strlen(response); +} + +Token * generate_token() +{ + // Generate a random authentication token + int i; + + Token * token = malloc(sizeof(Token)); + for (i = 0; i < TOKEN_SIZE; i++) + { + token->token[i] = 'A' + rand() % 26; // Random uppercase alphabet character + } + token->token[TOKEN_SIZE] = '\0'; // Null-terminate the token + token->expiration_time = time(NULL) + TOKEN_EXPIRATION; // Set token expiration time + add_token_to_list(token); + return token; +} + +// Function to add the token to the token_list +void add_token_to_list(Token* token) +{ + if (token_list == NULL) + { + token_list = token; + token->next = NULL; + } + else + { + Token* current = token_list; + + while (current->next != NULL) + current = current->next; + + current->next = token; + token->next = NULL; + } +} + +int verify_token(const char* token) +{ + // Find the token in the token list + Token * existing_token = find_token(token); + + if (existing_token != NULL) + { + // Check if the token has expired + time_t current_time = time(NULL); + if (current_time > existing_token->expiration_time) + { + // Token has expired, remove it from the token list + remove_expired_tokens(); + return 0; + } + // Token is valid + return 1; + } + + // Token doesn't exist in the token list + return 0; +} + +void remove_expired_tokens() +{ + time_t current_time = time(NULL); + Token* current_token = token_list; + Token* prev_token = NULL; + Token* next_token; + + while (current_token != NULL) + { + if (current_time > current_token->expiration_time) + { + // Token has expired, remove it from the token list + if (prev_token == NULL) + { + token_list = current_token->next; + } else { + prev_token->next = current_token->next; + } + next_token = current_token->next; + free(current_token); + current_token = next_token; + } else { + prev_token = current_token; + current_token = current_token->next; + } + } +} + +Token * find_token(const char* token) +{ + Token* current_token = token_list; + while (current_token != NULL) + { + if (strcmp(current_token->token, token) == 0) + { + return current_token; + } + current_token = current_token->next; + } + return NULL; +} + +int send_http_response(char * response, const char* msg) +{ + return sprintf(response, "HTTP/1.1 %s\r\nContent-Length: 0\r\nConnection: close\r\n\r\n", msg); +} + +/* +{ +"access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3", +"expires_in":3600, +"scope":"create" +} +*/ + +/* +{"ports":[ +{"ID":"My Port", "Driver":"KISS", "Number":2, "State":"Active"), +{ ...}, +{...} +]} +*/ + +extern int MasterPort[MAXBPQPORTS+1]; // Pointer to first BPQ port for a specific MPSK or UZ7HO host + +int sendPortList(char * response, char * token, int Flags) +{ + char * Array = 0; + int ArrayLen = 0; + int ArrayPtr = 0; + + struct _EXTPORTDATA * ExtPort; + struct PORTCONTROL * Port; + struct PORTCONTROL * SAVEPORT; + int PortNo; + + int count; + char DLL[20]; + char Status[32]="Unknown"; + char ID[33]; + char * ptr; + + Array = (char *)malloc(2048); + ArrayLen = 2048; + + ArrayPtr += sprintf(&Array[ArrayPtr], "[\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; + } + + if ((ArrayPtr + 512) > ArrayLen) + { + ArrayLen += 2048; + Array = (char *)realloc(Array, ArrayLen); + } + ArrayPtr += sprintf(&Array[ArrayPtr], " {\"ID\":\"%s\", \"Driver\":\"%s\", \"Number\":%d,\"State\":\"%s\"},\r\n", + ID, DLL, Port->PORTNUMBER, Status); + } + + ArrayPtr -= 3; // remove trailing comma + + ArrayPtr += sprintf(&Array[ArrayPtr], "\r\n]\r\n"); + + sprintf(response, "%s", Array); + + return strlen(response); +} + +/* +{"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], "[\r\n"); + + Dests-=1; + + for (count = 0; count < MaxNodes; count++) + { + Dests+=1; + + if (Dests->DEST_CALL[0] == 0) + continue; + + len = ConvFromAX25(Dests->DEST_CALL, Normcall); + Normcall[len] = 0; + + memcpy(Alias, Dests->DEST_ALIAS, 6); + + Alias[6]=0; + + for (i=0;i<6;i++) + { + if (Alias[i] == ' ') + Alias[i] = 0; + } + + + ArrayPtr += sprintf(&response[ArrayPtr], " {\"Call\":\"%s\", \"Alias\":\"%s\", \"Routes\":[", Normcall, Alias); + + + // Add an array with up to 6 objects (3 NR + 3 INP3 Neighbours + + if (Dests->NRROUTE[0].ROUT_NEIGHBOUR != 0 && Dests->NRROUTE[0].ROUT_NEIGHBOUR->INP3Node == 0) + { + len = ConvFromAX25(Dests->NRROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL,Portcall); + Portcall[len] = 0; + + ArrayPtr += sprintf(&response[ArrayPtr], "{\"Call\":\"%s\", \"Port\":%d, \"Quality\":%d},", + Portcall, Dests->NRROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, Dests->NRROUTE[0].ROUT_QUALITY); + + + // if (Dests->NRROUTE[0].ROUT_OBSCOUNT > 127) + // { + // len=sprintf(&line[cursor],"! "); + // cursor+=len; + // } + + + if (Dests->NRROUTE[1].ROUT_NEIGHBOUR != 0 && Dests->NRROUTE[1].ROUT_NEIGHBOUR->INP3Node == 0) + { + len=ConvFromAX25(Dests->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL,Portcall); + Portcall[len]=0; + + + + ArrayPtr += sprintf(&response[ArrayPtr], " {\"Call\":\"%s\", \"Port\":%d, \"Quality\":%d},", + Portcall, Dests->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, Dests->NRROUTE[1].ROUT_QUALITY); + //if (Dests->NRROUTE[1].ROUT_OBSCOUNT > 127) + //{ + //len=sprintf(&line[cursor],"! "); + //cursor+=len; + //} + + } + + if (Dests->NRROUTE[2].ROUT_NEIGHBOUR != 0 && Dests->NRROUTE[2].ROUT_NEIGHBOUR->INP3Node == 0) + { + len=ConvFromAX25(Dests->NRROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL,Portcall); + Portcall[len]=0; + + + ArrayPtr += sprintf(&response[ArrayPtr], " {\"Call\":\"%s\", \"Port\":%d, \"Quality\":%d},", + Portcall, Dests->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_PORT, Dests->NRROUTE[1].ROUT_QUALITY); + + //if (Dests->NRROUTE[2].ROUT_OBSCOUNT > 127) + //{ + //len=sprintf(&line[cursor],"! "); + //cursor+=len; + + } + ArrayPtr -= 1; // remove comma + } + + ArrayPtr += sprintf(&response[ArrayPtr], "]},\r\n"); + } + + ArrayPtr -= 3; // remove comma + ArrayPtr += sprintf(&response[ArrayPtr], "\r\n]"); + + return ArrayPtr; +} + + +int sendUserList(char * response, char * token, int Flags) +{ + int ArrayPtr = 0; + int n = MAXCIRCUITS; + TRANSPORTENTRY * L4 = L4TABLE; + TRANSPORTENTRY * Partner; + int MaxLinks = MAXLINKS; + char State[12] = "", Type[12] = "Uplink"; + char LHS[50] = "", MID[10] = "", RHS[50] = ""; + char Line[100]; + char Normcall[10]; + int len; + + ArrayPtr += sprintf(&response[ArrayPtr], "{\"users\":[\r\n"); + + while (n--) + { + if (L4->L4USER[0]) + { + RHS[0] = MID[0] = 0; + + len = ConvFromAX25(L4->L4USER, Normcall); + Normcall[len] = 0; + + ArrayPtr += sprintf(&response[ArrayPtr], " {\"Call\", \"%s\"},\r\n", Normcall); + L4++; + } + } + + if (ArrayPtr == 12) //empty list + { + ArrayPtr -=2; + ArrayPtr += sprintf(&response[ArrayPtr], "]}\r\n"); + } + else + { + ArrayPtr -= 3; // remove trailing comma + ArrayPtr += sprintf(&response[ArrayPtr], "\r\n]}\r\n"); + } + return ArrayPtr; +} + +extern char MYALIASLOPPED[]; +extern char TextVerstring[]; +extern char LOCATOR[]; + +int sendInfo(char * response, char * token, int Flags) +{ + char call[10]; + + memcpy(call, MYNODECALL, 10); + strlop(call, ' '); + + sprintf(response, "{\"info\":{\"NodeCall\":\"%s\", \"Alias\":\"%s\", \"Locator\":\"%s\", \"Version\":\"%s\"}}\r\n", + call, MYALIASLOPPED, LOCATOR, TextVerstring); + + return strlen(response); +} diff --git a/telnetserver.h b/telnetserver.h index 77da27c..48f87d0 100644 --- a/telnetserver.h +++ b/telnetserver.h @@ -36,7 +36,8 @@ struct ConnectionInfo BOOL RelayMode; // Pure TCP for RMS Relay Emulation forwarding BOOL DRATSMode; // HTML Terminal Emulator BOOL SyncMode; // RMS Relay Sync - BOOL HTTPMode; // DRATS Reflector Emulator + BOOL HTTPMode; // HTTP Server + BOOL APIMode; // REST API Server BOOL TriMode; // Trimode emulation BOOL TriModeConnected; // Set when remote session is connected - now send data to DataSock SOCKET TriModeDataSock; // Data Socket diff --git a/templatedefs.c b/templatedefs.c index 72f1c8b..dbd7485 100644 --- a/templatedefs.c +++ b/templatedefs.c @@ -478,7 +478,9 @@ char * MainConfigtxt() " Dont Check From Call
\r\n" " Allow users to kill T messages
\r\n" " Forward Messages to BBS Call
\r\n" - " Don't allow unknown users

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

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

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

 Chat Server Params

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

\r\n" + "
The Nodes to link to box defines which other Chat Nodes should be connected to, or from which " "connections may be accepted. The format is ALIAS:CALL, eg BPQCHT:G8BPQ-4. If the node is not directly " "connectable (ie is not in your NODES table) you can add a connect script. This consists of a series of commands " @@ -1460,7 +1464,7 @@ char * ChatConfigtxt() "
\r\n" "
\r\n" "\r\n" - "
\r\n" + "
\r\n" " \r\n" " \r\n" " \r\n" diff --git a/tncinfo.h b/tncinfo.h index 2d6ad93..9b9cb54 100644 --- a/tncinfo.h +++ b/tncinfo.h @@ -110,6 +110,7 @@ struct TCPINFO int FBBPort[100]; int RelayPort; int HTTPPort; + int APIPort; int TriModePort; int SyncPort; int DRATSPort; @@ -159,6 +160,7 @@ struct TCPINFO SOCKET FBBsock[100]; SOCKET Relaysock; SOCKET HTTPsock; + SOCKET APIsock; SOCKET TriModeSock; SOCKET TriModeDataSock; SOCKET Syncsock; @@ -169,6 +171,7 @@ struct TCPINFO SOCKET FBBsock6[100]; SOCKET Relaysock6; SOCKET HTTPsock6; + SOCKET APIsock6; SOCKET Syncsock6; SOCKET DRATSsock6;