2022-08-28 09:35:46 +01:00
/*
2022-11-14 14:02:28 +00:00
Copyright 2001 - 2022 John Wiseman G8BPQ
2022-08-28 09:35:46 +01:00
This file is part of LinBPQ / BPQ32 .
LinBPQ / BPQ32 is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
LinBPQ / BPQ32 is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with LinBPQ / BPQ32 . If not , see http : //www.gnu.org/licenses
*/
//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
# define _CRT_SECURE_NO_DEPRECATE
# define DllImport
# include "CHeaders.h"
# include <stdlib.h>
# include "tncinfo.h"
# include "time.h"
# include "bpq32.h"
# include "telnetserver.h"
// This is needed to link with a lib built from source
# ifdef WIN32
# define ZEXPORT __stdcall
# endif
2024-12-16 17:54:16 +00:00
# include <zlib.h>
2022-08-28 09:35:46 +01:00
# define CKernel
# include "httpconnectioninfo.h"
extern int MAXBUFFS , QCOUNT , MINBUFFCOUNT , NOBUFFCOUNT , BUFFERWAITS , L3FRAMES ;
extern int NUMBEROFNODES , MAXDESTS , L4CONNECTSOUT , L4CONNECTSIN , L4FRAMESTX , L4FRAMESRX , L4FRAMESRETRIED , OLDFRAMES ;
extern int STATSTIME ;
extern TRANSPORTENTRY * L4TABLE ;
extern BPQVECSTRUC BPQHOSTVECTOR [ ] ;
extern BOOL APRSApplConnected ;
extern char VersionString [ ] ;
VOID FormatTime3 ( char * Time , time_t cTime ) ;
DllExport int APIENTRY Get_APPLMASK ( int Stream ) ;
VOID SaveUIConfig ( ) ;
int ProcessNodeSignon ( SOCKET sock , struct TCPINFO * TCP , char * MsgPtr , char * Appl , char * Reply , struct HTTPConnectionInfo * * Session , int LOCAL ) ;
VOID SetupUI ( int Port ) ;
VOID SendUIBeacon ( int Port ) ;
VOID GetParam ( char * input , char * key , char * value ) ;
VOID ARDOPAbort ( struct TNCINFO * TNC ) ;
VOID WriteMiniDump ( ) ;
BOOL KillTNC ( struct TNCINFO * TNC ) ;
BOOL RestartTNC ( struct TNCINFO * TNC ) ;
int GetAISPageInfo ( char * Buffer , int ais , int adsb ) ;
int GetAPRSPageInfo ( char * Buffer , double N , double S , double W , double E , int aprs , int ais , int adsb ) ;
unsigned char * Compressit ( unsigned char * In , int Len , int * OutLen ) ;
char * stristr ( char * ch1 , char * ch2 ) ;
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 ) ;
2023-12-28 10:31:09 +00:00
int APIProcessHTTPMessage ( char * response , char * Method , char * URL , char * request , BOOL LOCAL , BOOL COOKIE ) ;
2022-08-28 09:35:46 +01:00
extern struct ROUTE * NEIGHBOURS ;
extern int ROUTE_LEN ;
extern int MAXNEIGHBOURS ;
extern struct DEST_LIST * DESTS ; // NODE LIST
extern int DEST_LIST_LEN ;
extern int MAXDESTS ; // MAX NODES IN SYSTEM
extern struct _LINKTABLE * LINKS ;
extern int LINK_TABLE_LEN ;
extern int MAXLINKS ;
extern char * RigWebPage ;
extern COLORREF Colours [ 256 ] ;
extern BOOL IncludesMail ;
extern BOOL IncludesChat ;
extern BOOL APRSWeb ;
extern BOOL RigActive ;
extern HKEY REGTREE ;
extern BOOL APRSActive ;
extern UCHAR LogDirectory [ ] ;
extern struct RIGPORTINFO * PORTInfo [ 34 ] ;
extern int NumberofPorts ;
2023-10-10 22:07:04 +01:00
extern UCHAR ConfigDirectory [ 260 ] ;
2022-08-28 09:35:46 +01:00
VOID sendandcheck ( SOCKET sock , const char * Buffer , int Len ) ;
int CompareNode ( const void * a , const void * b ) ;
int CompareAlias ( const void * a , const void * b ) ;
2024-11-05 21:03:15 +00:00
void ProcessMailHTTPMessage ( struct HTTPConnectionInfo * Session , char * Method , char * URL , char * input , char * Reply , int * RLen , int InputLen , char * Token ) ;
2022-08-28 09:35:46 +01:00
void ProcessChatHTTPMessage ( struct HTTPConnectionInfo * Session , char * Method , char * URL , char * input , char * Reply , int * RLen ) ;
struct PORTCONTROL * APIENTRY GetPortTableEntryFromSlot ( int portslot ) ;
int SetupNodeMenu ( char * Buff , int SYSOP ) ;
int StatusProc ( char * Buff ) ;
int ProcessMailSignon ( struct TCPINFO * TCP , char * MsgPtr , char * Appl , char * Reply , struct HTTPConnectionInfo * * Session , BOOL WebMail , int LOCAL ) ;
2024-11-05 21:03:15 +00:00
int ProcessMailAPISignon ( struct TCPINFO * TCP , char * MsgPtr , char * Appl , char * Reply , struct HTTPConnectionInfo * * Session , BOOL WebMail , int LOCAL ) ;
2022-08-28 09:35:46 +01:00
int ProcessChatSignon ( struct TCPINFO * TCP , char * MsgPtr , char * Appl , char * Reply , struct HTTPConnectionInfo * * Session , int LOCAL ) ;
VOID APRSProcessHTTPMessage ( SOCKET sock , char * MsgPtr , BOOL LOCAL , BOOL COOKIE ) ;
static struct HTTPConnectionInfo * SessionList ; // active term mode sessions
char Mycall [ 10 ] ;
char MAILPipeFileName [ ] = " \\ \\ . \\ pipe \\ BPQMAILWebPipe " ;
char CHATPipeFileName [ ] = " \\ \\ . \\ pipe \\ BPQCHATWebPipe " ;
char Index [ ] = " <html><head><title>%s's BPQ32 Web Server</title></head><body><P align=center> "
" <table border=2 cellpadding=2 cellspacing=2 bgcolor=white> "
" <tr><td align=center><a href=/Node/NodeMenu.html>Node Pages</a></td> "
" <td align=center><a href=/aprs>APRS Pages</a></td></tr></table></body></html> " ;
char IndexNoAPRS [ ] = " <meta http-equiv= \" refresh \" content= \" 0;url=/Node/NodeIndex.html \" > "
" <html><head></head><body></body></html> " ;
//char APRSBit[] = "<td><a href=../aprs>APRS Pages</a></td>";
//char MailBit[] = "<td><a href=../Mail/Header>Mail Mgmt</a></td>"
// "<td><a href=/Webmail>WebMail</a></td>";
//char ChatBit[] = "<td><a href=../Chat/Header>Chat Mgmt</a></td>";
char Tail [ ] = " </body></html> " ;
char RouteHddr [ ] = " <h2 align=center>Routes</h2><table align=center border=2 style=font-family:monospace bgcolor=white> "
" <tr><th>Port</th><th>Call</th><th>Quality</th><th>Node Count</th><th>Frame Count</th><th>Retries</th><th>Percent</th><th>Maxframe</th><th>Frack</th><th>Last Heard</th><th>Queued</th><th>Rem Qual</th></tr> " ;
char RouteLine [ ] = " <tr><td>%s%d</td><td>%s%c</td><td>%d</td><td>%d</td><td>%d</td><td>%d</td><td>%d%</td><td>%d</td><td>%d</td><td>%02d:%02d</td><td>%d</td><td>%d</td></tr> " ;
char xNodeHddr [ ] = " <align=center><form align=center method=get action=/Node/Nodes.html> "
" <table align=center bgcolor=white> "
" <tr><td><input type=submit class='btn' name=a value= \" Nodes Sorted by Alias \" ></td><td> "
" <input type=submit class='btn' name=c value= \" Nodes Sorted by Call \" ></td><td> "
" <input type=submit class='btn' name=t value= \" Nodes with traffic \" ></td></tr></form></table> "
" <h2 align=center>Nodes %s</h2><table style=font-family:monospace align=center border=2 bgcolor=white><tr> " ;
char NodeHddr [ ] = " <center><form method=get action=/Node/Nodes.html> "
" <input type=submit class='btn' name=a value= \" Nodes Sorted by Alias \" > "
" <input type=submit class='btn' name=c value= \" Nodes Sorted by Call \" > "
" <input type=submit class='btn' name=t value= \" Nodes with traffic \" ></form></center> "
" <h2 align=center>Nodes %s</h2><table style=font-family:monospace align=center border=2 bgcolor=white><tr> " ;
char NodeLine [ ] = " <td><a href=NodeDetail?%s>%s:%s</td> " ;
char StatsHddr [ ] = " <h2 align=center>Node Stats</h2><table align=center cellpadding=2 bgcolor=white> "
" <col width=250 /><col width=80 /><col width=80 /><col width=80 /><col width=80 /><col width=80 /> " ;
char PortStatsHddr [ ] = " <h2 align=center>Stats for Port %d</h2><table align=center border=2 cellpadding=2 bgcolor=white> " ;
char PortStatsLine [ ] = " <tr><td> %s </td><td> %d </td></tr> " ;
char Beacons [ ] = " <h2 align=center>Beacon Configuration for Port %d</h2><h3 align=center>You need to be signed in to save changes</h3><table align=center border=2 cellpadding=2 bgcolor=white> "
" <form method=post action=BeaconAction> "
" <table align=center bgcolor=white> "
" <tr><td>Send Interval (Minutes)</td><td><input type=text name=Every tabindex=1 size=5 value=%d></td></tr> "
" <tr><td>To</td><td><input name=Dest style= \" text-transform:uppercase; \" tabindex=2 size=5 value=%s></td></tr> "
" <tr><td>Path</td><td><input type=text name=Path style= \" text-transform:uppercase; \" size=50 maxlength=50 value=%s></td></tr> "
" <tr><td>Send From File</td><td><input type=text name=File size=50 maxlength=50 value=%s></td></tr> "
" <tr><td>Text</td><td><textarea name= \" Text \" cols=40 rows=5>%s</textarea></td></tr> "
" </table> "
" <input type=hidden name=Port value=%d> "
" <p align=center><input type=submit class='btn' value=Save><input type=submit class='btn' value=Test name=Test> "
" </form> " ;
char LinkHddr [ ] = " <h2 align=center>Links</h2><table align=center border=2 bgcolor=white> "
" <tr><th>Far Call</th><th>Our Call</th><th>Port</th><th>ax.25 state</th><th>Link Type</th><th>ax.25 Version</th></tr> " ;
char LinkLine [ ] = " <tr><td>%s</td><td>%s</td><td>%d</td><td>%s</td><td>%s</td><td align=center >%d</td></tr> " ;
char UserHddr [ ] = " <h2 align=center>Sessions</h2><table align=center border=2 cellpadding=2 bgcolor=white> " ;
char UserLine [ ] = " <tr><td>%s</td><td>%s</td><td>%s</td></tr> " ;
char TermSignon [ ] = " <html><head><title>BPQ32 Node %s Terminal Access</title></head><body background= \" /background.jpg \" > "
" <h2 align=center>BPQ32 Node %s Terminal Access</h2> "
" <h3 align=center>Please enter username and password to access the node</h3> "
" <form method=post action=TermSignon> "
" <table align=center bgcolor=white> "
" <tr><td>User</td><td><input type=text name=user tabindex=1 size=20 maxlength=50 /></td></tr> "
" <tr><td>Password</td><td><input type=password name=password tabindex=2 size=20 maxlength=50 /></td></tr></table> "
" <p align=center><input type=submit class='btn' value=Submit><input type=submit class='btn' value=Cancel name=Cancel> "
" <input type=hidden name=Appl value= \" %s \" id=Pass></form> " ;
char PassError [ ] = " <p align=center>Sorry, User or Password is invalid - please try again</p> " ;
char BusyError [ ] = " <p align=center>Sorry, No sessions available - please try later</p> " ;
char LostSession [ ] = " <html><body>Sorry, Session had been lost - refresh page to sign in again " ;
char NoSessions [ ] = " <html><body>Sorry, No Sessions available - refresh page to try again " ;
char TermPage [ ] = " <!DOCTYPE html><html><meta http-equiv=Content-Type content='text/html; charset=UTF-8' /> "
" <head><title>BPQ32 Node %s</title></head> "
" <script>function resize(){ "
" var w=window,d=document,e=d.documentElement,g=d.getElementsByTagName('body')[0]; "
" x=w.innerWidth; "
" y=w.innerHeight; "
" var txt=document.getElementById('txt'); "
" txt.style.height = y - 150 + 'px';}</script> "
" <body onload='resize()' onresize='resize()'> "
" <h3 align=center>BPQ32 Node %s</h3> "
" <form method=post action=/Node/TermClose?%s> "
" <p align=center><input type=submit class='btn' value='Close and return to Node Page' /></form> "
" <iframe style='display:block;' id=txt frameborder=2 marginwidth=0 marginheight=0 src=OutputScreen.html?%s width=100%%></iframe> "
" <iframe style='display:block;' frameborder=0 marginwidth=0 marginheight=3 src=InputLine.html?%s width=100%% height=45px></iframe> "
" </body> " ;
char TermOutput [ ] = " <!DOCTYPE html><html><head> "
" <meta http-equiv=cache-control content=no-cache> "
" <meta http-equiv=pragma content=no-cache> "
" <meta http-equiv=expires content=0> "
" <meta http-equiv=refresh content=2> "
" <script type= \" text/javascript \" > \r \n "
" function ScrollOutput() \r \n "
" {window.scrollBy(0,document.body.scrollHeight)}</script> "
" </head><body id=Text> "
" <div style= \" font-family:monospace;%s> \" " ;
// font-family:monospace;background-color:black;color:lawngreen;font-size:12px
char TermOutputTail [ ] = " </div><script type= \" text/javascript \" > \r \n setTimeout(ScrollOutput, 1)</script></body></html> " ;
/*
char InputLine [ ] = " <html><head></head><body onload='resize()' onresize='resize()'> "
" <form name=inputform method=post action=/TermInput?%s> "
" <script>document.inputform.input.focus(); "
" function resize(){ "
" var w=window,d=document,e=d.documentElement,g=d.getElementsByTagName('body')[0]; "
" x=w.innerWidth;y=w.innerHeight; "
" var inp=document.getElementById('inp'); "
" inp.style.width = x + 'px';}</script> "
" <input id=inp type=text width=100%% name=input /></form> " ;
*/
char InputLine [ ] = " <!DOCTYPE html><html><head></head><body onload='resize()' onresize='resize()'> "
" <form name=inputform method=post action=/TermInput?%s> "
" <input style= \" font-family:monospace;%s> \" id=inp type=text text width=100%% name=input /> "
" <script>document.inputform.input.focus(); "
" function resize(){ "
" var w=window,d=document,e=d.documentElement,g=d.getElementsByTagName('body')[0]; "
" x=w.innerWidth;y=w.innerHeight; "
" var inp=document.getElementById('inp'); "
" inp.style.width=x-20+'px';}</script></form> " ;
static char NodeSignon [ ] = " <html><head><title>BPQ32 Node SYSOP Access</title></head><body background= \" /background.jpg \" > "
" <h3 align=center>BPQ32 Node %s SYSOP Access</h3> "
" <h3 align=center>This page sets Cookies. Don't continue if you object to this</h3> "
" <h3 align=center>Please enter Callsign and Password to access the Node</h3> "
" <form method=post action=/Node/Signon?Node> "
" <table align=center bgcolor=white> "
" <tr><td>User</td><td><input type=text name=user tabindex=1 size=20 maxlength=50 /></td></tr> "
" <tr><td>Password</td><td><input type=password name=password tabindex=2 size=20 maxlength=50 /></td></tr></table> "
" <p align=center><input type=submit class='btn' value=Submit /><input type=submit class='btn' value=Cancel name=Cancel /></form> " ;
static char MailSignon [ ] = " <html><head><title>BPQ32 Mail Server Access</title></head><body background= \" /background.jpg \" > "
" <h3 align=center>BPQ32 Mail Server %s Access</h3> "
" <h3 align=center>Please enter Callsign and Password to access the BBS</h3> "
" <form method=post action=/Mail/Signon?Mail> "
" <table align=center bgcolor=white> "
" <tr><td>User</td><td><input type=text name=user tabindex=1 size=20 maxlength=50 /></td></tr> "
" <tr><td>Password</td><td><input type=password name=password tabindex=2 size=20 maxlength=50 /></td></tr></table> "
" <p align=center><input type=submit class='btn' value=Submit /><input type=submit class='btn' value=Cancel name=Cancel /></form> " ;
static char ChatSignon [ ] = " <html><head><title>BPQ32 Chat Server Access</title></head><body background= \" /background.jpg \" > "
" <h3 align=center>BPQ32 Chat Server %s Access</h3> "
" <h3 align=center>Please enter Callsign and Password to access the Chat Server</h3> "
" <form method=post action=/Chat/Signon?Chat> "
" <table align=center bgcolor=white> "
" <tr><td>User</td><td><input type=text name=user tabindex=1 size=20 maxlength=50 /></td></tr> "
" <tr><td>Password</td><td><input type=password name=password tabindex=2 size=20 maxlength=50 /></td></tr></table> "
" <p align=center><input type=submit class='btn' value=Submit /><input type=submit class='btn' value=Cancel name=Cancel /></form> " ;
static char MailLostSession [ ] = " <html><body> "
" <form style= \" font-family: monospace; text-align: center; \" method=post action=/Mail/Lost?%s> "
" Sorry, Session had been lost<br><br> "
" <input name=Submit value=Restart type=submit class='btn'> <input type=submit class='btn' value=Exit name=Cancel><br></form> " ;
static char ConfigEditPage [ ] = " <html><head><meta content= \" text/html; charset=ISO-8859-1 \" http-equiv= \" content-type \" > "
" <title>Edit Config</title></head><body background=/background.jpg> "
" <form style= \" font-family: monospace; text-align: center; \" method=post action=CFGSave?%s> "
" <textarea cols=100 rows=25 name=Msg>%s</textarea><br><br> "
" <input name=Save value=Save type=submit class='btn'><input name=Cancel value=Cancel type=submit class='btn'><br></form> " ;
static char EXCEPTMSG [ 80 ] = " " ;
void UndoTransparency ( char * input )
{
char * ptr1 , * ptr2 ;
char c ;
int hex ;
if ( input = = NULL )
return ;
ptr1 = ptr2 = input ;
// Convert any %xx constructs
while ( 1 )
{
c = * ( ptr1 + + ) ;
if ( c = = 0 )
break ;
if ( c = = ' % ' )
{
c = * ( ptr1 + + ) ;
if ( isdigit ( c ) )
hex = ( c - ' 0 ' ) < < 4 ;
else
hex = ( tolower ( c ) - ' a ' + 10 ) < < 4 ;
c = * ( ptr1 + + ) ;
if ( isdigit ( c ) )
hex + = ( c - ' 0 ' ) ;
else
hex + = ( tolower ( c ) - ' a ' + 10 ) ;
* ( ptr2 + + ) = hex ;
}
else if ( c = = ' + ' )
* ( ptr2 + + ) = 32 ;
else
* ( ptr2 + + ) = c ;
}
* ptr2 = 0 ;
}
VOID PollSession ( struct HTTPConnectionInfo * Session )
{
int state , change ;
int count , len ;
char Msg [ 400 ] = " " ;
char Formatted [ 8192 ] ;
char * ptr1 , * ptr2 ;
char c ;
int Line ;
// Poll Node
SessionState ( Session - > Stream , & state , & change ) ;
if ( change = = 1 )
{
int Line = Session - > LastLine + + ;
free ( Session - > ScreenLines [ Line ] ) ;
if ( state = = 1 ) // Connected
Session - > ScreenLines [ Line ] = _strdup ( " *** Connected<br> \r \n " ) ;
else
Session - > ScreenLines [ Line ] = _strdup ( " *** Disconnected<br> \r \n " ) ;
if ( Line = = 99 )
Session - > LastLine = 0 ;
Session - > Changed = TRUE ;
}
if ( RXCount ( Session - > Stream ) > 0 )
{
int realLen = 0 ;
do
{
GetMsg ( Session - > Stream , & Msg [ 0 ] , & len , & count ) ;
// replace cr with <br> and space with
ptr1 = Msg ;
ptr2 = & Formatted [ 0 ] ;
if ( Session - > PartLine )
{
// Last line was incomplete - append to it
realLen = Session - > PartLine ;
Line = Session - > LastLine - 1 ;
if ( Line < 0 )
Line = 99 ;
strcpy ( Formatted , Session - > ScreenLines [ Line ] ) ;
ptr2 + = strlen ( Formatted ) ;
Session - > LastLine = Line ;
Session - > PartLine = FALSE ;
}
while ( len - - )
{
c = * ( ptr1 + + ) ;
realLen + + ;
if ( c = = 13 )
{
int LineLen ;
strcpy ( ptr2 , " <br> \r \n " ) ;
// Write to screen
Line = Session - > LastLine + + ;
free ( Session - > ScreenLines [ Line ] ) ;
LineLen = ( int ) strlen ( Formatted ) ;
// if line starts with a colour code, process it
if ( Formatted [ 0 ] = = 0x1b & & LineLen > 1 )
{
int ColourCode = Formatted [ 1 ] - 10 ;
COLORREF Colour = Colours [ ColourCode ] ;
char ColString [ 30 ] ;
memmove ( & Formatted [ 20 ] , & Formatted [ 2 ] , LineLen ) ;
sprintf ( ColString , " <font color=#%02X%02X%02X> " , GetRValue ( Colour ) , GetGValue ( Colour ) , GetBValue ( Colour ) ) ;
memcpy ( Formatted , ColString , 20 ) ;
strcat ( Formatted , " </font> " ) ;
LineLen = + 28 ;
}
Session - > ScreenLineLen [ Line ] = LineLen ;
Session - > ScreenLines [ Line ] = _strdup ( Formatted ) ;
if ( Line = = 99 )
Session - > LastLine = 0 ;
ptr2 = & Formatted [ 0 ] ;
realLen = 0 ;
}
else if ( c = = 32 )
{
memcpy ( ptr2 , " " , 6 ) ;
ptr2 + = 6 ;
// Make sure line isn't too long
// but beware of spaces expanded to - count chars in line
if ( ( realLen ) > 100 )
{
strcpy ( ptr2 , " <br> \r \n " ) ;
Line = Session - > LastLine + + ;
free ( Session - > ScreenLines [ Line ] ) ;
Session - > ScreenLines [ Line ] = _strdup ( Formatted ) ;
if ( Line = = 99 )
Session - > LastLine = 0 ;
ptr2 = & Formatted [ 0 ] ;
realLen = 0 ;
}
}
else if ( c = = ' > ' )
{
memcpy ( ptr2 , " > " , 4 ) ;
ptr2 + = 4 ;
}
else if ( c = = ' < ' )
{
memcpy ( ptr2 , " < " , 4 ) ;
ptr2 + = 4 ;
}
else
* ( ptr2 + + ) = c ;
}
* ptr2 = 0 ;
if ( ptr2 ! = & Formatted [ 0 ] )
{
// Incomplete line
// Save to screen
Line = Session - > LastLine + + ;
free ( Session - > ScreenLines [ Line ] ) ;
Session - > ScreenLines [ Line ] = _strdup ( Formatted ) ;
if ( Line = = 99 )
Session - > LastLine = 0 ;
Session - > PartLine = realLen ;
}
// strcat(Session->ScreenBuffer, Formatted);
Session - > Changed = TRUE ;
} while ( count > 0 ) ;
}
}
VOID HTTPTimer ( )
{
// Run every tick. Check for status change and data available
struct HTTPConnectionInfo * Session = SessionList ; // active term mode sessions
struct HTTPConnectionInfo * PreviousSession = NULL ;
// inf();
while ( Session )
{
Session - > KillTimer + + ;
if ( Session - > Key [ 0 ] ! = ' T ' )
{
PreviousSession = Session ;
Session = Session - > Next ;
continue ;
}
if ( Session - > KillTimer > 3000 ) // Around 5 mins
{
int i ;
int Stream = Session - > Stream ;
for ( i = 0 ; i < 100 ; i + + )
{
free ( Session - > ScreenLines [ i ] ) ;
}
SessionControl ( Stream , 2 , 0 ) ;
SessionState ( Stream , & i , & i ) ;
DeallocateStream ( Stream ) ;
if ( PreviousSession )
PreviousSession - > Next = Session - > Next ; // Remove from chain
else
SessionList = Session - > Next ;
free ( Session ) ;
break ;
}
PollSession ( Session ) ;
// if (Session->ResponseTimer == 0 && Session->Changed)
// Debugprintf("Data to send but no outstanding GET");
if ( Session - > ResponseTimer )
{
Session - > ResponseTimer - - ;
if ( Session - > ResponseTimer = = 0 | | Session - > Changed )
{
SOCKET sock = Session - > sock ;
char _REPLYBUFFER [ 100000 ] ;
int ReplyLen ;
char Header [ 256 ] ;
int HeaderLen ;
int Last = Session - > LastLine ;
int n ;
struct TNCINFO * TNC = Session - > TNC ;
struct TCPINFO * TCP = 0 ;
if ( TNC )
TCP = TNC - > TCPInfo ;
if ( TCP & & TCP - > WebTermCSS )
sprintf ( _REPLYBUFFER , TermOutput , TCP - > WebTermCSS ) ;
else
sprintf ( _REPLYBUFFER , TermOutput , " " ) ;
for ( n = Last ; ; )
{
2024-08-30 10:14:56 +01:00
if ( ( strlen ( Session - > ScreenLines [ n ] ) + strlen ( _REPLYBUFFER ) ) < 99999 )
strcat ( _REPLYBUFFER , Session - > ScreenLines [ n ] ) ;
2022-08-28 09:35:46 +01:00
if ( n = = 99 )
n = - 1 ;
if ( + + n = = Last )
break ;
}
ReplyLen = ( int ) strlen ( _REPLYBUFFER ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " %s " , TermOutputTail ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen ) ;
sendandcheck ( sock , Header , HeaderLen ) ;
sendandcheck ( sock , _REPLYBUFFER , ReplyLen ) ;
Session - > ResponseTimer = Session - > Changed = 0 ;
}
}
PreviousSession = Session ;
Session = Session - > Next ;
}
}
struct HTTPConnectionInfo * AllocateSession ( SOCKET sock , char Mode )
{
time_t KeyVal ;
struct HTTPConnectionInfo * Session = zalloc ( sizeof ( struct HTTPConnectionInfo ) ) ;
int i ;
if ( Session = = NULL )
return NULL ;
if ( Mode = = ' T ' )
{
// Terminal
for ( i = 0 ; i < 20 ; i + + )
Session - > ScreenLines [ i ] = _strdup ( " Scroll to end<br> " ) ;
for ( i = 20 ; i < 100 ; i + + )
Session - > ScreenLines [ i ] = _strdup ( " <br> \r \n " ) ;
Session - > Stream = FindFreeStream ( ) ;
if ( Session - > Stream = = 0 )
return NULL ;
SessionControl ( Session - > Stream , 1 , 0 ) ;
}
KeyVal = ( int ) sock * time ( NULL ) ;
sprintf ( Session - > Key , " %c%012X " , Mode , ( int ) KeyVal ) ;
if ( SessionList )
Session - > Next = SessionList ;
SessionList = Session ;
return Session ;
}
struct HTTPConnectionInfo * FindSession ( char * Key )
{
struct HTTPConnectionInfo * Session = SessionList ;
while ( Session )
{
if ( strcmp ( Session - > Key , Key ) = = 0 )
return Session ;
Session = Session - > Next ;
}
return NULL ;
}
void ProcessTermInput ( SOCKET sock , char * MsgPtr , int MsgLen , char * Key )
{
2024-08-30 10:14:56 +01:00
char _REPLYBUFFER [ 2048 ] ;
2022-08-28 09:35:46 +01:00
int ReplyLen ;
char Header [ 256 ] ;
int HeaderLen ;
int State ;
struct HTTPConnectionInfo * Session = FindSession ( Key ) ;
int Stream ;
2024-08-30 10:14:56 +01:00
int maxlen = 1000 ;
2022-08-28 09:35:46 +01:00
if ( Session = = NULL )
{
ReplyLen = sprintf ( _REPLYBUFFER , " %s " , LostSession ) ;
}
else
{
char * input = strstr ( MsgPtr , " \r \n \r \n " ) ; // End of headers
char * end = & MsgPtr [ MsgLen ] ;
int Line = Session - > LastLine + + ;
char * ptr1 , * ptr2 ;
char c ;
UCHAR hex ;
2024-08-30 10:14:56 +01:00
int msglen = end - input ;
2022-08-28 09:35:46 +01:00
struct TNCINFO * TNC = Session - > TNC ;
struct TCPINFO * TCP = 0 ;
if ( TNC )
TCP = TNC - > TCPInfo ;
2024-08-30 10:14:56 +01:00
if ( TCP & & TCP - > WebTermCSS )
maxlen - = strlen ( TCP - > WebTermCSS ) ;
if ( MsgLen > maxlen )
{
Session - > KillTimer = 99999 ; // close session
return ;
}
2022-08-28 09:35:46 +01:00
if ( TCP & & TCP - > WebTermCSS )
ReplyLen = sprintf ( _REPLYBUFFER , InputLine , Key , TCP - > WebTermCSS ) ;
else
ReplyLen = sprintf ( _REPLYBUFFER , InputLine , Key , " " ) ;
Stream = Session - > Stream ;
input + = 10 ;
ptr1 = ptr2 = input ;
// Convert any %xx constructs
while ( ptr1 ! = end )
{
c = * ( ptr1 + + ) ;
if ( c = = ' % ' )
{
c = * ( ptr1 + + ) ;
if ( isdigit ( c ) )
hex = ( c - ' 0 ' ) < < 4 ;
else
hex = ( tolower ( c ) - ' a ' + 10 ) < < 4 ;
c = * ( ptr1 + + ) ;
if ( isdigit ( c ) )
hex + = ( c - ' 0 ' ) ;
else
hex + = ( tolower ( c ) - ' a ' + 10 ) ;
* ( ptr2 + + ) = hex ;
}
else if ( c = = ' + ' )
* ( ptr2 + + ) = 32 ;
else
* ( ptr2 + + ) = c ;
}
end = ptr2 ;
* ptr2 = 0 ;
strcat ( input , " <br> \r \n " ) ;
free ( Session - > ScreenLines [ Line ] ) ;
Session - > ScreenLines [ Line ] = _strdup ( input ) ;
if ( Line = = 99 )
Session - > LastLine = 0 ;
* end + + = 13 ;
* end = 0 ;
SessionStateNoAck ( Stream , & State ) ;
if ( State = = 0 )
{
char AXCall [ 10 ] ;
SessionControl ( Stream , 1 , 0 ) ;
if ( BPQHOSTVECTOR [ Session - > Stream - 1 ] . HOSTSESSION = = NULL )
{
//No L4 sessions free
ReplyLen = sprintf ( _REPLYBUFFER , " %s " , NoSessions ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
return ;
}
ConvToAX25 ( Session - > HTTPCall , AXCall ) ;
ChangeSessionCallsign ( Stream , AXCall ) ;
if ( Session - > USER )
BPQHOSTVECTOR [ Session - > Stream - 1 ] . HOSTSESSION - > Secure_Session = Session - > USER - > Secure ;
else
Debugprintf ( " HTTP Term Session->USER is NULL " ) ;
}
SendMsg ( Stream , input , ( int ) ( end - input ) ) ;
Session - > Changed = TRUE ;
Session - > KillTimer = 0 ;
}
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
}
void ProcessTermClose ( SOCKET sock , char * MsgPtr , int MsgLen , char * Key , int LOCAL )
{
char _REPLYBUFFER [ 8192 ] ;
int ReplyLen = sprintf ( _REPLYBUFFER , InputLine , Key , " " ) ;
char Header [ 256 ] ;
int HeaderLen ;
struct HTTPConnectionInfo * Session = FindSession ( Key ) ;
if ( Session )
{
Session - > KillTimer = 99999 ;
}
ReplyLen = SetupNodeMenu ( _REPLYBUFFER , LOCAL ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n "
" \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
}
int ProcessTermSignon ( struct TNCINFO * TNC , SOCKET sock , char * MsgPtr , int MsgLen , int LOCAL )
{
char _REPLYBUFFER [ 8192 ] ;
int ReplyLen ;
char Header [ 256 ] ;
int HeaderLen ;
char * input = strstr ( MsgPtr , " \r \n \r \n " ) ; // End of headers
char * user , * password , * Context , * Appl ;
char NoApp [ ] = " " ;
struct TCPINFO * TCP = TNC - > TCPInfo ;
if ( input )
{
int i ;
struct UserRec * USER ;
UndoTransparency ( input ) ;
if ( strstr ( input , " Cancel=Cancel " ) )
{
ReplyLen = SetupNodeMenu ( _REPLYBUFFER , LOCAL ) ;
goto Sendit ;
}
user = strtok_s ( & input [ 9 ] , " & " , & Context ) ;
password = strtok_s ( NULL , " = " , & Context ) ;
password = strtok_s ( NULL , " & " , & Context ) ;
Appl = strtok_s ( NULL , " = " , & Context ) ;
Appl = strtok_s ( NULL , " & " , & Context ) ;
if ( Appl = = 0 )
Appl = NoApp ;
if ( password = = NULL )
{
ReplyLen = sprintf ( _REPLYBUFFER , TermSignon , Mycall , Mycall , Appl ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " %s " , PassError ) ;
goto Sendit ;
}
for ( i = 0 ; i < TCP - > NumberofUsers ; i + + )
{
USER = TCP - > UserRecPtr [ i ] ;
if ( ( strcmp ( password , USER - > Password ) = = 0 ) & &
( ( _stricmp ( user , USER - > UserName ) = = 0 ) | | ( _stricmp ( USER - > UserName , " ANON " ) = = 0 ) ) )
{
// ok
struct HTTPConnectionInfo * Session = AllocateSession ( sock , ' T ' ) ;
if ( Session )
{
char AXCall [ 10 ] ;
ReplyLen = sprintf ( _REPLYBUFFER , TermPage , Mycall , Mycall , Session - > Key , Session - > Key , Session - > Key ) ;
if ( _stricmp ( USER - > UserName , " ANON " ) = = 0 )
strcpy ( Session - > HTTPCall , _strupr ( user ) ) ;
else
strcpy ( Session - > HTTPCall , USER - > Callsign ) ;
ConvToAX25 ( Session - > HTTPCall , AXCall ) ;
ChangeSessionCallsign ( Session - > Stream , AXCall ) ;
BPQHOSTVECTOR [ Session - > Stream - 1 ] . HOSTSESSION - > Secure_Session = USER - > Secure ;
Session - > USER = USER ;
if ( USER - > Appl [ 0 ] )
SendMsg ( Session - > Stream , USER - > Appl , ( int ) strlen ( USER - > Appl ) ) ;
}
else
{
ReplyLen = SetupNodeMenu ( _REPLYBUFFER , LOCAL ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " %s " , BusyError ) ;
}
break ;
}
}
if ( i = = TCP - > NumberofUsers )
{
// Not found
ReplyLen = sprintf ( _REPLYBUFFER , TermSignon , Mycall , Mycall , Appl ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " %s " , PassError ) ;
}
}
Sendit :
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
return 1 ;
}
char * LookupKey ( char * Key )
{
if ( strcmp ( Key , " ##MY_CALLSIGN## " ) = = 0 )
{
char Mycall [ 10 ] ;
memcpy ( Mycall , & MYNODECALL , 10 ) ;
strlop ( Mycall , ' ' ) ;
return _strdup ( Mycall ) ;
}
return NULL ;
}
int ProcessSpecialPage ( char * Buffer , int FileSize )
{
// replaces ##xxx### constructs with the requested data
char * NewMessage = malloc ( 100000 ) ;
char * ptr1 = Buffer , * ptr2 , * ptr3 , * ptr4 , * NewPtr = NewMessage ;
int PrevLen ;
int BytesLeft = FileSize ;
int NewFileSize = FileSize ;
char * StripPtr = ptr1 ;
// strip comments blocks
while ( ptr4 = strstr ( ptr1 , " <!-- " ) )
{
ptr2 = strstr ( ptr4 , " --> " ) ;
if ( ptr2 )
{
PrevLen = ( int ) ( ptr4 - ptr1 ) ;
memcpy ( StripPtr , ptr1 , PrevLen ) ;
StripPtr + = PrevLen ;
ptr1 = ptr2 + 3 ;
BytesLeft = ( int ) ( FileSize - ( ptr1 - Buffer ) ) ;
}
}
memcpy ( StripPtr , ptr1 , BytesLeft ) ;
StripPtr + = BytesLeft ;
BytesLeft = ( int ) ( StripPtr - Buffer ) ;
FileSize = BytesLeft ;
NewFileSize = FileSize ;
ptr1 = Buffer ;
ptr1 [ FileSize ] = 0 ;
loop :
ptr2 = strstr ( ptr1 , " ## " ) ;
if ( ptr2 )
{
PrevLen = ( int ) ( ptr2 - ptr1 ) ; // Bytes before special text
ptr3 = strstr ( ptr2 + 2 , " ## " ) ;
if ( ptr3 )
{
char Key [ 80 ] = " " ;
int KeyLen ;
char * NewText ;
int NewTextLen ;
ptr3 + = 2 ;
KeyLen = ( int ) ( ptr3 - ptr2 ) ;
if ( KeyLen < 80 )
memcpy ( Key , ptr2 , KeyLen ) ;
NewText = LookupKey ( Key ) ;
if ( NewText )
{
NewTextLen = ( int ) strlen ( NewText ) ;
NewFileSize = NewFileSize + NewTextLen - KeyLen ;
// NewMessage = realloc(NewMessage, NewFileSize);
memcpy ( NewPtr , ptr1 , PrevLen ) ;
NewPtr + = PrevLen ;
memcpy ( NewPtr , NewText , NewTextLen ) ;
NewPtr + = NewTextLen ;
free ( NewText ) ;
NewText = NULL ;
}
else
{
// Key not found, so just leave
memcpy ( NewPtr , ptr1 , PrevLen + KeyLen ) ;
NewPtr + = ( PrevLen + KeyLen ) ;
}
ptr1 = ptr3 ; // Continue scan from here
BytesLeft = ( int ) ( Buffer + FileSize - ptr3 ) ;
}
else // Unmatched ##
{
memcpy ( NewPtr , ptr1 , PrevLen + 2 ) ;
NewPtr + = ( PrevLen + 2 ) ;
ptr1 = ptr2 + 2 ;
}
goto loop ;
}
// Copy Rest
memcpy ( NewPtr , ptr1 , BytesLeft ) ;
NewMessage [ NewFileSize ] = 0 ;
strcpy ( Buffer , NewMessage ) ;
free ( NewMessage ) ;
return NewFileSize ;
}
int SendMessageFile ( SOCKET sock , char * FN , BOOL OnlyifExists , int allowDeflate )
{
int FileSize = 0 , Sent , Loops = 0 ;
char * MsgBytes ;
char MsgFile [ 512 ] ;
FILE * hFile ;
int ReadLen ;
BOOL Special = FALSE ;
int Len ;
int HeaderLen ;
char Header [ 256 ] ;
char TimeString [ 64 ] ;
char FileTimeString [ 64 ] ;
struct stat STAT ;
char * ptr ;
char * Compressed = 0 ;
char Encoding [ ] = " Content-Encoding: deflate \r \n " ;
char Type [ 64 ] = " Content-Type: text/html \r \n " ;
# ifdef WIN32
struct _EXCEPTION_POINTERS exinfo ;
strcpy ( EXCEPTMSG , " SendMessageFile " ) ;
__try {
# endif
UndoTransparency ( FN ) ;
if ( strstr ( FN , " .. " ) )
{
FN [ 0 ] = ' / ' ;
FN [ 1 ] = 0 ;
}
if ( strlen ( FN ) > 256 )
{
FN [ 256 ] = 0 ;
Debugprintf ( " HTTP File Name too long %s " , FN ) ;
}
if ( strcmp ( FN , " / " ) = = 0 )
if ( APRSActive )
sprintf ( MsgFile , " %s/HTML/index.html " , BPQDirectory ) ;
else
sprintf ( MsgFile , " %s/HTML/indexnoaprs.html " , BPQDirectory ) ;
else
sprintf ( MsgFile , " %s/HTML%s " , BPQDirectory , FN ) ;
// First see if file exists so we can override standard ones in code
if ( stat ( MsgFile , & STAT ) = = 0 & & ( hFile = fopen ( MsgFile , " rb " ) ) )
{
FileSize = STAT . st_size ;
MsgBytes = zalloc ( FileSize + 1 ) ;
ReadLen = ( int ) fread ( MsgBytes , 1 , FileSize , hFile ) ;
fclose ( hFile ) ;
// ft.QuadPart -= 116444736000000000;
// ft.QuadPart /= 10000000;
// ctime = ft.LowPart;
FormatTime3 ( FileTimeString , STAT . st_ctime ) ;
}
else
{
// See if it is a hard coded file
MsgBytes = GetStandardPage ( & FN [ 1 ] , & FileSize ) ;
if ( MsgBytes )
{
if ( FileSize = = 0 )
FileSize = strlen ( MsgBytes ) ;
FormatTime3 ( FileTimeString , 0 ) ;
}
else
{
if ( OnlyifExists ) // Set if we dont want an error response if missing
return - 1 ;
Len = sprintf ( Header , " HTTP/1.1 404 Not Found \r \n Content-Length: 16 \r \n \r \n Page not found \r \n " ) ;
send ( sock , Header , Len , 0 ) ;
return 0 ;
}
}
// if HTML file, look for ##...## substitutions
if ( ( strcmp ( FN , " / " ) = = 0 | | strstr ( FN , " htm " ) | | strstr ( FN , " HTM " ) ) & & strstr ( MsgBytes , " ## " ) )
{
FileSize = ProcessSpecialPage ( MsgBytes , FileSize ) ;
FormatTime3 ( FileTimeString , time ( NULL ) ) ;
}
FormatTime3 ( TimeString , time ( NULL ) ) ;
ptr = FN ;
while ( strchr ( ptr , ' . ' ) )
{
ptr = strchr ( ptr , ' . ' ) ;
+ + ptr ;
}
if ( _stricmp ( ptr , " js " ) = = 0 )
strcpy ( Type , " Content-Type: text/javascript \r \n " ) ;
2024-11-05 21:03:15 +00:00
if ( _stricmp ( ptr , " css " ) = = 0 )
strcpy ( Type , " Content-Type: text/css \r \n " ) ;
2022-08-28 09:35:46 +01:00
if ( _stricmp ( ptr , " pdf " ) = = 0 )
strcpy ( Type , " Content-Type: application/pdf \r \n " ) ;
if ( allowDeflate )
{
Compressed = Compressit ( MsgBytes , FileSize , & FileSize ) ;
}
else
{
Encoding [ 0 ] = 0 ;
Compressed = MsgBytes ;
}
2024-11-05 21:03:15 +00:00
if ( _stricmp ( ptr , " jpg " ) = = 0 | | _stricmp ( ptr , " jpeg " ) = = 0 | | _stricmp ( ptr , " png " ) = = 0 | |
_stricmp ( ptr , " gif " ) = = 0 | | _stricmp ( ptr , " bmp " ) = = 0 | | _stricmp ( ptr , " ico " ) = = 0 )
2022-08-28 09:35:46 +01:00
strcpy ( Type , " Content-Type: image \r \n " ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n "
" Date: %s \r \n "
" Last-Modified: %s \r \n "
" %s%s "
" \r \n " , FileSize , TimeString , FileTimeString , Type , Encoding ) ;
send ( sock , Header , HeaderLen , 0 ) ;
Sent = send ( sock , Compressed , FileSize , 0 ) ;
while ( Sent ! = FileSize & & Loops + + < 3000 ) // 100 secs max
{
if ( Sent > 0 ) // something sent
{
// Debugprintf("%d out of %d sent", Sent, FileSize);
FileSize - = Sent ;
memmove ( Compressed , & Compressed [ Sent ] , FileSize ) ;
}
Sleep ( 30 ) ;
Sent = send ( sock , Compressed , FileSize , 0 ) ;
}
// Debugprintf("%d out of %d sent %d loops", Sent, FileSize, Loops);
free ( MsgBytes ) ;
if ( allowDeflate )
free ( Compressed ) ;
# ifdef WIN32
}
# include "StdExcept.c"
Debugprintf ( " Sending FIle %s " , FN ) ;
}
# endif
return 0 ;
}
VOID sendandcheck ( SOCKET sock , const char * Buffer , int Len )
{
int Loops = 0 ;
int Sent = send ( sock , Buffer , Len , 0 ) ;
char * Copy = NULL ;
while ( Sent ! = Len & & Loops + + < 300 ) // 10 secs max
{
// Debugprintf("%d out of %d sent %d Loops", Sent, Len, Loops);
if ( Copy = = NULL )
{
Copy = malloc ( Len ) ;
memcpy ( Copy , Buffer , Len ) ;
}
if ( Sent > 0 ) // something sent
{
Len - = Sent ;
memmove ( Copy , & Copy [ Sent ] , Len ) ;
}
Sleep ( 30 ) ;
Sent = send ( sock , Copy , Len , 0 ) ;
}
if ( Copy )
free ( Copy ) ;
return ;
}
int RefreshTermWindow ( struct TCPINFO * TCP , struct HTTPConnectionInfo * Session , char * _REPLYBUFFER )
{
char Msg [ 400 ] = " " ;
int HeaderLen , ReplyLen ;
char Header [ 256 ] ;
PollSession ( Session ) ; // See if anything received
if ( Session - > Changed )
{
int Last = Session - > LastLine ;
int n ;
if ( TCP & & TCP - > WebTermCSS )
sprintf ( _REPLYBUFFER , TermOutput , TCP - > WebTermCSS ) ;
else
sprintf ( _REPLYBUFFER , TermOutput , " " ) ;
for ( n = Last ; ; )
{
strcat ( _REPLYBUFFER , Session - > ScreenLines [ n ] ) ;
if ( n = = 99 )
n = - 1 ;
if ( + + n = = Last )
break ;
}
Session - > Changed = 0 ;
ReplyLen = ( int ) strlen ( _REPLYBUFFER ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " %s " , TermOutputTail ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen ) ;
sendandcheck ( Session - > sock , Header , HeaderLen ) ;
sendandcheck ( Session - > sock , _REPLYBUFFER , ReplyLen ) ;
return 1 ;
}
else
return 0 ;
2023-05-25 14:17:53 +01:00
}
2022-08-28 09:35:46 +01:00
int SetupNodeMenu ( char * Buff , int LOCAL )
{
int Len = 0 , i ;
struct TNCINFO * TNC ;
int top = 0 , left = 0 ;
char NodeMenuHeader [ ] = " <html id=body><head><title>%s's BPQ32 Web Server</title> "
" <style type= \" text/css \" > "
// The container <div> - needed to position the dropdown content
" .dropdown {position: relative; display: inline-block;} "
// Dropdown Content (Hidden by Default)
" .dropdown-content {display: none; position: absolute; left: -100px; background-color: #f1f1f1; "
" min-width: 120px; border: 1px solid; padding: 4px; z-index: 1;} "
// Links inside the dropdown
" .dropdown-content a {color: black; padding: 2px 2px; display: block;} "
// Change color of dropdown links on hover
" .dropdown-content a:hover {background-color: #ddd} "
// Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button)
" .show {display:block;} "
" input.btn:active {background:black;color:white;} "
" submit.btn:active {background:black;color:white;} "
" </style> "
" <script> \r \n "
// Close the dropdown menu if the user clicks outside of it
" window.onclick = function(event) {console.log(event.target.id); "
" if (event.target.id == 'body') { "
" var dropdowns = document.getElementsByClassName('dropdown-content'); "
" var i; \r \n "
" for (i = 0; i < dropdowns.length; i++) { "
" var openDropdown = dropdowns[i]; "
" if (openDropdown.classList.contains('show')) { "
" openDropdown.classList.remove('show'); "
" }}}} \r \n "
" function myShow() {document.getElementById('myDropdown').classList.add('show');} "
// "function myHide() {"
// " if (event.target.matches('.HTMLBodyElement'))"
// "{document.getElementById('myDropdown').classList.remove('show');}}"
" function dev_win(URL,w,h,top,left){ "
" var ww = \" width= \" + w; "
" var xx = \" ,height= \" + h; "
" var yy = \" ,top= \" + top; "
" var zz = \" ,left= \" + left; "
" var param = \" toolbar=no, location=no, directories=no, status=no, "
" menubar=no, scrollbars=no, resizable=no, titlebar=no, toobar=no, \" + ww + xx + yy + zz; "
" window.open(URL, \" _blank \" ,param); "
" } \r \n "
" function open_win(){ " ;
char NodeMenuLine [ ] = " dev_win( \" /Node/Port?%d \" ,%d,%d,%d,%d); " ;
char NodeMenuRest [ ] = " }</script></head> "
" <body id=body background= \" /background.jpg \" ><h1 align=center>BPQ32 Node %s</h1><P> "
" <P align=center><table border=1 cellpadding=2 bgcolor=white><tr> "
" <td><a href=/Node/Routes.html>Routes</a></td> "
" <td><a href=/Node/Nodes.html>Nodes</a></td> "
" <td><a href=/Node/Ports.html>Ports</a></td> "
" <td><a href=/Node/Links.html>Links</a></td> "
" <td><a href=/Node/Users.html>Users</a></td> "
" <td><a href=/Node/Stats.html>Stats</a></td> "
" <td><a href=/Node/Terminal.html>Terminal</a></td>%s%s%s%s%s%s " ;
char DriverBit [ ] = " <td><a href= \" javascript:open_win(); \" >Driver Windows</a></td> "
" <td><a href=javascript:dev_win( \" /Node/Streams \" ,820,700,200,200);>Stream Status</a></td> " ;
char APRSBit [ ] = " <td><a href=../aprs>APRS Pages</a></td> " ;
char MailBit [ ] = " <td><a href=../Mail/Header>Mail Mgmt</a></td> "
" <td><a href=/Webmail>WebMail</a></td> " ;
char ChatBit [ ] = " <td><a href=../Chat/Header>Chat Mgmt</a></td> " ;
char SigninBit [ ] = " <td><a href=/Node/Signon.html>SYSOP Signin</a></td> " ;
char NodeTail [ ] =
" <td><a href=/Node/EditCfg.html>Edit Config</a></td> "
" <td><div onmouseover=myShow() class='dropdown'> "
" <button class= \" dropbtn \" >View Logs</button> "
" <div id= \" myDropdown \" class= \" dropdown-content \" > "
" <form id = doDate form action='/node/ShowLog.html'><label> "
" Select Date: <input type='date' name='date' id=e> "
" <script> "
" document.getElementById('e').value = new Date().toISOString().substring(0, 10); "
" </script></label> "
" <input type=submit class='btn' name='BBS' value='BBS Log'></br> "
" <input type=submit class='btn' name='Debug' value='BBS Debug Log'></br> "
" <input type=submit class='btn' name='Telnet' value='Telnet Log'></br> "
" <input type=submit class='btn' name='CMS' value='CMS Log'></br> "
" <input type=submit class='btn' name='Chat' value='Chat Log'></br> "
" </form></div> "
" </div> "
" </td></tr></table> " ;
Len = sprintf ( Buff , NodeMenuHeader , Mycall ) ;
2023-06-21 08:21:04 +01:00
for ( i = 1 ; i < = MAXBPQPORTS ; i + + )
2022-08-28 09:35:46 +01:00
{
TNC = TNCInfo [ i ] ;
if ( TNC = = NULL )
continue ;
if ( TNC - > WebWindowProc )
{
Len + = sprintf ( & Buff [ Len ] , NodeMenuLine , i , TNC - > WebWinX , TNC - > WebWinY , top , left ) ;
top + = 22 ;
left + = 22 ;
}
}
Len + = sprintf ( & Buff [ Len ] , NodeMenuRest , Mycall ,
DriverBit ,
( APRSWeb ) ? APRSBit : " " ,
( IncludesMail ) ? MailBit : " " , ( IncludesChat ) ? ChatBit : " " , ( LOCAL ) ? " " : SigninBit , NodeTail ) ;
return Len ;
}
VOID SaveConfigFile ( SOCKET sock , char * MsgPtr , char * Rest , int LOCAL )
{
int ReplyLen = 0 ;
char * ptr , * ptr1 , * ptr2 , * input ;
char c ;
int MsgLen , WriteLen = 0 ;
char inputname [ 250 ] = " bpq32.cfg " ;
FILE * fp1 ;
char Header [ 256 ] ;
int HeaderLen ;
char Reply [ 4096 ] ;
char Mess [ 256 ] ;
char Backup1 [ MAX_PATH ] ;
char Backup2 [ MAX_PATH ] ;
struct stat STAT ;
input = strstr ( MsgPtr , " \r \n \r \n " ) ; // End of headers
if ( input )
{
if ( strstr ( input , " Cancel=Cancel " ) )
{
ReplyLen = SetupNodeMenu ( Reply , LOCAL ) ;
// ReplyLen = sprintf(Reply, "%s", "<html><script>window.close();</script></html>");
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , Reply , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
return ;
}
ptr = strstr ( input , " &Save= " ) ;
if ( ptr )
{
* ptr = 0 ;
// Undo any % transparency
ptr1 = ptr2 = input + 8 ;
c = * ( ptr1 + + ) ;
while ( c )
{
if ( c = = ' % ' )
{
int n ;
int m = * ( ptr1 + + ) - ' 0 ' ;
if ( m > 9 ) m = m - 7 ;
n = * ( ptr1 + + ) - ' 0 ' ;
if ( n > 9 ) n = n - 7 ;
c = m * 16 + n ;
}
else if ( c = = ' + ' )
c = ' ' ;
# ifndef WIN32
if ( c ! = 13 ) // Strip CR if Linux
# endif
* ( ptr2 + + ) = c ;
c = * ( ptr1 + + ) ;
}
* ( ptr2 + + ) = 0 ;
MsgLen = ( int ) strlen ( input + 8 ) ;
2023-10-10 22:07:04 +01:00
if ( ConfigDirectory [ 0 ] = = 0 )
2022-08-28 09:35:46 +01:00
{
strcpy ( inputname , " bpq32.cfg " ) ;
}
else
{
2023-10-10 22:07:04 +01:00
strcpy ( inputname , ConfigDirectory ) ;
2022-08-28 09:35:46 +01:00
strcat ( inputname , " / " ) ;
strcat ( inputname , " bpq32.cfg " ) ;
}
// Make a backup of the config
// Keep 4 Generations
strcpy ( Backup2 , inputname ) ;
strcat ( Backup2 , " .bak.3 " ) ;
strcpy ( Backup1 , inputname ) ;
strcat ( Backup1 , " .bak.2 " ) ;
DeleteFile ( Backup2 ) ; // Remove old .bak.3
MoveFile ( Backup1 , Backup2 ) ; // Move .bak.2 to .bak.3
strcpy ( Backup2 , inputname ) ;
strcat ( Backup2 , " .bak.1 " ) ;
MoveFile ( Backup2 , Backup1 ) ; // Move .bak.1 to .bak.2
strcpy ( Backup1 , inputname ) ;
strcat ( Backup1 , " .bak " ) ;
MoveFile ( Backup1 , Backup2 ) ; // Move .bak to .bak.1
CopyFile ( inputname , Backup1 , FALSE ) ; // Copy to .bak
// Get length to compare with new length
stat ( inputname , & STAT ) ;
fp1 = fopen ( inputname , " wb " ) ;
if ( fp1 )
{
WriteLen = ( int ) fwrite ( input + 8 , 1 , MsgLen , fp1 ) ;
fclose ( fp1 ) ;
}
if ( WriteLen ! = MsgLen )
sprintf_s ( Mess , sizeof ( Mess ) , " Failed to write Config File " ) ;
else
sprintf_s ( Mess , sizeof ( Mess ) , " Configuration Saved, Orig Length %d New Length %d " ,
STAT . st_size , MsgLen ) ;
}
ReplyLen = sprintf ( Reply , " <html><script>alert( \" %s \" );window.close();</script></html> " , Mess ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , Reply , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
}
return ;
}
// Compress using deflate. Caller must free output buffer after use
unsigned char * Compressit ( unsigned char * In , int Len , int * OutLen )
{
z_stream defstream ;
int maxSize ;
unsigned char * Out ;
defstream . zalloc = Z_NULL ;
defstream . zfree = Z_NULL ;
defstream . opaque = Z_NULL ;
defstream . avail_in = Len ; // size of input
defstream . next_in = ( Bytef * ) In ; // input char array
deflateInit ( & defstream , Z_BEST_COMPRESSION ) ;
maxSize = deflateBound ( & defstream , Len ) ;
Out = malloc ( maxSize ) ;
defstream . avail_out = maxSize ; // size of output
defstream . next_out = ( Bytef * ) Out ; // output char array
deflate ( & defstream , Z_FINISH ) ;
deflateEnd ( & defstream ) ;
* OutLen = defstream . total_out ;
return Out ;
}
int InnerProcessHTTPMessage ( struct ConnectionInfo * conn )
{
struct TCPINFO * TCP = conn - > TNC - > TCPInfo ;
SOCKET sock = conn - > socket ;
char * MsgPtr = conn - > InputBuffer ;
int MsgLen = conn - > InputLen ;
int InputLen = 0 ;
int OutputLen = 0 ;
int Bufferlen ;
struct HTTPConnectionInfo CI ;
struct HTTPConnectionInfo * sockptr = & CI ;
struct HTTPConnectionInfo * Session = NULL ;
char URL [ 100000 ] ;
char * ptr ;
char * encPtr = 0 ;
int allowDeflate = 0 ;
char * Compressed = 0 ;
char * HostPtr = 0 ;
2023-12-28 10:31:09 +00:00
char * Context , * Method , * NodeURL = 0 , * Key ;
2022-08-28 09:35:46 +01:00
char _REPLYBUFFER [ 250000 ] ;
char Reply [ 250000 ] ;
int ReplyLen = 0 ;
char Header [ 256 ] ;
int HeaderLen ;
char TimeString [ 64 ] ;
BOOL LOCAL = FALSE ;
BOOL COOKIE = FALSE ;
int Len ;
char * WebSock = 0 ;
char PortsHddr [ ] = " <h2 align=center>Ports</h2><table align=center border=2 bgcolor=white> "
2024-10-11 15:37:11 +01:00
" <tr><th>Port</th><th>Driver</th><th>ID</th><th>Beacons</th><th>Driver Window</th><th>Stats Graph</th></tr> " ;
2022-08-28 09:35:46 +01:00
2024-10-11 15:37:11 +01:00
// char PortLine[] = "<tr><td>%d</td><td><a href=PortStats?%d&%s> %s</a></td><td>%s</td></tr>";
2022-08-28 09:35:46 +01:00
char PortLineWithBeacon [ ] = " <tr><td>%d</td><td><a href=PortStats?%d&%s> %s</a></td><td>%s</td> "
2024-10-11 15:37:11 +01:00
" <td><a href=PortBeacons?%d> Beacons</a><td> </td></td><td>%s</td></tr> \r \n " ;
2022-08-28 09:35:46 +01:00
char SessionPortLine [ ] = " <tr><td>%d</td><td>%s</td><td>%s</td><td> </td> "
2024-10-11 15:37:11 +01:00
" <td> </td><td>%s</td></tr> \r \n " ;
2022-08-28 09:35:46 +01:00
char PortLineWithDriver [ ] = " <tr><td>%d</td><td>%s</td><td>%s</td><td> </td> "
2024-10-11 15:37:11 +01:00
" <td><a href= \" javascript:dev_win('/Node/Port?%d',%d,%d,%d,%d); \" >Driver Window</a></td><td>%s</td></tr> \r \n " ;
2022-08-28 09:35:46 +01:00
char PortLineWithBeaconAndDriver [ ] = " <tr><td>%d</td><td>%s</td><td>%s</td> "
" <td><a href=PortBeacons?%d> Beacons</a></td> "
2024-10-11 15:37:11 +01:00
" <td><a href= \" javascript:dev_win('/Node/Port?%d',%d,%d,%d,%d); \" >Driver Window</a></td><td>%s</td></tr> \r \n " ;
2022-08-28 09:35:46 +01:00
char RigControlLine [ ] = " <tr><td>%d</td><td>%s</td><td>%s</td><td> </td> "
" <td><a href= \" javascript:dev_win('/Node/RigControl.html',%d,%d,%d,%d); \" >Rig Control</a></td></tr> \r \n " ;
char Encoding [ ] = " Content-Encoding: deflate \r \n " ;
2023-12-28 10:31:09 +00:00
# ifdef WIN32xx
2022-08-28 09:35:46 +01:00
struct _EXCEPTION_POINTERS exinfo ;
strcpy ( EXCEPTMSG , " ProcessHTTPMessage " ) ;
__try {
# endif
Len = ( int ) strlen ( MsgPtr ) ;
if ( Len > 100000 )
return 0 ;
strcpy ( URL , MsgPtr ) ;
HostPtr = strstr ( MsgPtr , " Host: " ) ;
2023-07-29 07:23:11 +01:00
WebSock = strstr ( MsgPtr , " Upgrade: websocket " ) ;
2022-08-28 09:35:46 +01:00
if ( HostPtr )
{
uint32_t Host ;
char Hostname [ 32 ] = " " ;
struct LOCALNET * LocalNet = conn - > TNC - > TCPInfo - > LocalNets ;
HostPtr + = 6 ;
memcpy ( Hostname , HostPtr , 31 ) ;
strlop ( Hostname , ' : ' ) ;
Host = inet_addr ( Hostname ) ;
if ( strcmp ( Hostname , " 127.0.0.1 " ) = = 0 )
LOCAL = TRUE ;
else
{
if ( conn - > sin . sin_family ! = AF_INET6 )
{
while ( LocalNet )
{
uint32_t MaskedHost = conn - > sin . sin_addr . s_addr & LocalNet - > Mask ;
if ( MaskedHost = = LocalNet - > Network )
{
LOCAL = 1 ;
break ;
}
LocalNet = LocalNet - > Next ;
}
}
}
}
encPtr = stristr ( MsgPtr , " Accept-Encoding: " ) ;
if ( encPtr & & stristr ( encPtr , " deflate " ) )
allowDeflate = 1 ;
else
Encoding [ 0 ] = 0 ;
ptr = strstr ( MsgPtr , " BPQSessionCookie=N " ) ;
if ( ptr )
{
COOKIE = TRUE ;
Key = ptr + 17 ;
ptr = strchr ( Key , ' , ' ) ;
if ( ptr )
{
* ptr = 0 ;
Session = FindSession ( Key ) ;
* ptr = ' , ' ;
}
else
{
ptr = strchr ( Key , 13 ) ;
if ( ptr )
{
* ptr = 0 ;
Session = FindSession ( Key ) ;
* ptr = 13 ;
}
}
}
if ( WebSock )
{
// Websock connection request - Reply and remember state.
char KeyMsg [ 128 ] ;
char Webx [ ] = " 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 " ; // Fixed UID
char Hash [ 64 ] = " " ;
char * Hash64 ; // base 64 version
char * ptr ;
//Sec-WebSocket-Key: l622yZS3n+zI+hR6SVWkPw==
char ReplyMsg [ ] =
" HTTP/1.1 101 Switching Protocols \r \n "
" Upgrade: websocket \r \n "
" Connection: Upgrade \r \n "
" Sec-WebSocket-Accept: %s \r \n "
// "Sec-WebSocket-Protocol: chat\r\n"
" \r \n " ;
ptr = strstr ( MsgPtr , " Sec-WebSocket-Key: " ) ;
if ( ptr )
{
ptr + = 18 ;
while ( * ptr = = ' ' )
ptr + + ;
memcpy ( KeyMsg , ptr , 40 ) ;
strlop ( KeyMsg , 13 ) ;
strlop ( KeyMsg , ' ' ) ;
strcat ( KeyMsg , Webx ) ;
SHA1PasswordHash ( KeyMsg , Hash ) ;
Hash64 = byte_base64_encode ( Hash , 20 ) ;
conn - > WebSocks = 1 ;
strlop ( & URL [ 4 ] , ' ' ) ;
strcpy ( conn - > WebURL , & URL [ 4 ] ) ;
ReplyLen = sprintf ( Reply , ReplyMsg , Hash64 ) ;
free ( Hash64 ) ;
goto Returnit ;
}
}
ptr = strstr ( URL , " HTTP " ) ;
if ( ptr )
* ptr = 0 ;
Method = strtok_s ( URL , " " , & Context ) ;
memcpy ( Mycall , & MYNODECALL , 10 ) ;
strlop ( Mycall , ' ' ) ;
2023-12-28 10:31:09 +00:00
// Look for API messages
if ( _memicmp ( Context , " /api/ " , 5 ) = = 0 | | _stricmp ( Context , " /api " ) = = 0 )
{
char * Compressed ;
2024-11-05 21:03:15 +00:00
// if for mail api process signon here and rearrange url from
// api/v1/mail to mail/api/v1 so it goes to mail handler later
if ( _memicmp ( Context , " /api/v1/mail/ " , 13 ) = = 0 )
2023-12-28 10:31:09 +00:00
{
2024-11-05 21:03:15 +00:00
memcpy ( MsgPtr , " GET /mail/api/v1/ " , 17 ) ;
if ( memcmp ( & Context [ 13 ] , " login " , 5 ) = = 0 )
{
ReplyLen = ProcessMailAPISignon ( TCP , MsgPtr , " M " , Reply , & Session , FALSE , LOCAL ) ;
memcpy ( MsgPtr , " GET /mail/api/v1/ " , 17 ) ;
2023-12-28 10:31:09 +00:00
2024-11-05 21:03:15 +00:00
if ( ReplyLen ) // Error message
goto Returnit ;
}
2023-12-28 10:31:09 +00:00
2024-11-05 21:03:15 +00:00
memcpy ( Context , " /mail/api/v1/ " , 13 ) ;
goto doHeader ;
2023-12-28 10:31:09 +00:00
}
else
2024-11-05 21:03:15 +00:00
{
ReplyLen = APIProcessHTTPMessage ( _REPLYBUFFER , Method , Context , MsgPtr , LOCAL , COOKIE ) ;
if ( memcmp ( _REPLYBUFFER , " HTTP " , 4 ) = = 0 )
{
// Full Message - just send it
2023-12-28 10:31:09 +00:00
2024-11-05 21:03:15 +00:00
sendandcheck ( sock , _REPLYBUFFER , ReplyLen ) ;
2023-12-28 10:31:09 +00:00
2024-11-05 21:03:15 +00:00
return 0 ;
}
2023-12-28 10:31:09 +00:00
2024-11-05 21:03:15 +00:00
if ( allowDeflate )
Compressed = Compressit ( _REPLYBUFFER , ReplyLen , & ReplyLen ) ;
else
Compressed = _REPLYBUFFER ;
2023-12-28 10:31:09 +00:00
2024-11-05 21:03:15 +00:00
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 "
" Access-Control-Allow-Origin: * \r \n "
" %s \r \n " , ReplyLen , Encoding ) ;
sendandcheck ( sock , Header , HeaderLen ) ;
sendandcheck ( sock , Compressed , ReplyLen ) ;
2023-12-28 10:31:09 +00:00
2024-11-05 21:03:15 +00:00
if ( allowDeflate )
free ( Compressed ) ;
return 0 ;
}
}
2023-12-28 10:31:09 +00:00
2022-08-28 09:35:46 +01:00
// APRS process internally
if ( _memicmp ( Context , " /APRS/ " , 6 ) = = 0 | | _stricmp ( Context , " /APRS " ) = = 0 )
{
APRSProcessHTTPMessage ( sock , MsgPtr , LOCAL , COOKIE ) ;
return 0 ;
}
if ( _stricmp ( Context , " /Node/Signon?Node " ) = = 0 )
{
char * IContext ;
NodeURL = strtok_s ( Context , " ? " , & IContext ) ;
Key = strtok_s ( NULL , " ? " , & IContext ) ;
ProcessNodeSignon ( sock , TCP , MsgPtr , Key , Reply , & Session , LOCAL ) ;
return 0 ;
}
// If for Mail or Chat, check for a session, and send login screen if necessary
// Moved here to simplify operation with both internal and external clients
if ( _memicmp ( Context , " /Mail/ " , 6 ) = = 0 )
{
int RLen = 0 ;
char Appl ;
char * input ;
char * IContext ;
NodeURL = strtok_s ( Context , " ? " , & IContext ) ;
Key = strtok_s ( NULL , " ? " , & IContext ) ;
if ( _stricmp ( NodeURL , " /Mail/Signon " ) = = 0 )
{
ReplyLen = ProcessMailSignon ( TCP , MsgPtr , Key , Reply , & Session , FALSE , LOCAL ) ;
if ( ReplyLen )
{
goto Returnit ;
}
# ifdef LINBPQ
strcpy ( Context , " /Mail/Header " ) ;
# else
strcpy ( MsgPtr , " POST /Mail/Header " ) ;
# endif
goto doHeader ;
}
if ( _stricmp ( NodeURL , " /Mail/Lost " ) = = 0 )
{
input = strstr ( MsgPtr , " \r \n \r \n " ) ; // End of headers
if ( input & & strstr ( input , " Cancel=Exit " ) )
{
ReplyLen = SetupNodeMenu ( Reply , LOCAL ) ;
RLen = ReplyLen ;
goto Returnit ;
}
if ( Key )
Appl = Key [ 0 ] ;
Key = 0 ;
}
if ( Key = = 0 | | Key [ 0 ] = = 0 )
{
// No Session
// if not local send a signon screen, else create a user session
if ( LOCAL | | COOKIE )
{
Session = AllocateSession ( sock , ' M ' ) ;
if ( Session )
{
strcpy ( Context , " /Mail/Header " ) ;
goto doHeader ;
}
else
{
ReplyLen = SetupNodeMenu ( Reply , LOCAL ) ;
ReplyLen + = sprintf ( & Reply [ ReplyLen ] , " %s " , BusyError ) ;
}
RLen = ReplyLen ;
goto Returnit ;
}
ReplyLen = sprintf ( Reply , MailSignon , Mycall , Mycall ) ;
RLen = ReplyLen ;
goto Returnit ;
}
Session = FindSession ( Key ) ;
2023-12-28 10:31:09 +00:00
if ( Session = = NULL & & _memicmp ( Context , " /Mail/API/ " , 10 ) ! = 0 )
2022-08-28 09:35:46 +01:00
{
ReplyLen = sprintf ( Reply , MailLostSession , Key ) ;
RLen = ReplyLen ;
goto Returnit ;
}
}
if ( _memicmp ( Context , " /Chat/ " , 6 ) = = 0 )
{
int RLen = 0 ;
char Appl ;
char * input ;
char * IContext ;
HostPtr = strstr ( MsgPtr , " Host: " ) ;
if ( HostPtr )
{
uint32_t Host ;
char Hostname [ 32 ] = " " ;
struct LOCALNET * LocalNet = conn - > TNC - > TCPInfo - > LocalNets ;
HostPtr + = 6 ;
memcpy ( Hostname , HostPtr , 31 ) ;
strlop ( Hostname , ' : ' ) ;
Host = inet_addr ( Hostname ) ;
if ( strcmp ( Hostname , " 127.0.0.1 " ) = = 0 )
LOCAL = TRUE ;
else while ( LocalNet )
{
uint32_t MaskedHost = Host & LocalNet - > Mask ;
if ( MaskedHost = = LocalNet - > Network )
{
char * rest ;
LOCAL = 1 ;
rest = strchr ( HostPtr , 13 ) ;
if ( rest )
{
memmove ( HostPtr + 9 , rest , strlen ( rest ) + 1 ) ;
memcpy ( HostPtr , " 127.0.0.1 " , 9 ) ;
break ;
}
}
LocalNet = LocalNet - > Next ;
}
}
NodeURL = strtok_s ( Context , " ? " , & IContext ) ;
Key = strtok_s ( NULL , " ? " , & IContext ) ;
if ( _stricmp ( NodeURL , " /Chat/Signon " ) = = 0 )
{
ReplyLen = ProcessChatSignon ( TCP , MsgPtr , Key , Reply , & Session , LOCAL ) ;
if ( ReplyLen )
{
goto Returnit ;
}
# ifdef LINBPQ
strcpy ( Context , " /Chat/Header " ) ;
# else
strcpy ( MsgPtr , " POST /Chat/Header " ) ;
# endif
goto doHeader ;
}
if ( _stricmp ( NodeURL , " /Chat/Lost " ) = = 0 )
{
input = strstr ( MsgPtr , " \r \n \r \n " ) ; // End of headers
if ( input & & strstr ( input , " Cancel=Exit " ) )
{
ReplyLen = SetupNodeMenu ( Reply , LOCAL ) ;
RLen = ReplyLen ;
goto Returnit ;
}
if ( Key )
Appl = Key [ 0 ] ;
Key = 0 ;
}
if ( Key = = 0 | | Key [ 0 ] = = 0 )
{
// No Session
// if not local send a signon screen, else create a user session
if ( LOCAL | | COOKIE )
{
Session = AllocateSession ( sock , ' C ' ) ;
if ( Session )
{
strcpy ( Context , " /Chat/Header " ) ;
goto doHeader ;
}
else
{
ReplyLen = SetupNodeMenu ( Reply , LOCAL ) ;
ReplyLen + = sprintf ( & Reply [ ReplyLen ] , " %s " , BusyError ) ;
}
RLen = ReplyLen ;
goto Returnit ;
}
ReplyLen = sprintf ( Reply , ChatSignon , Mycall , Mycall ) ;
RLen = ReplyLen ;
goto Returnit ;
}
Session = FindSession ( Key ) ;
if ( Session = = NULL )
{
int Sent , Loops = 0 ;
ReplyLen = sprintf ( Reply , MailLostSession , Key ) ;
RLen = ReplyLen ;
Returnit :
if ( memcmp ( Reply , " HTTP " , 4 ) = = 0 )
{
// Full Header provided by appl - just send it
// Send may block
Sent = send ( sock , Reply , ReplyLen , 0 ) ;
while ( Sent ! = ReplyLen & & Loops + + < 3000 ) // 100 secs max
{
// Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops);
if ( Sent > 0 ) // something sent
{
InputLen - = Sent ;
memmove ( Reply , & Reply [ Sent ] , ReplyLen ) ;
}
Sleep ( 30 ) ;
Sent = send ( sock , Reply , ReplyLen , 0 ) ;
}
return 0 ;
}
2023-12-28 10:31:09 +00:00
if ( NodeURL & & _memicmp ( NodeURL , " /mail/api/ " , 10 ) ! = 0 )
{
// Add tail
2023-03-16 06:52:27 +00:00
2023-12-28 10:31:09 +00:00
strcpy ( & Reply [ ReplyLen ] , Tail ) ;
ReplyLen + = strlen ( Tail ) ;
}
2023-03-16 06:52:27 +00:00
2022-08-28 09:35:46 +01:00
// compress if allowed
if ( allowDeflate )
Compressed = Compressit ( Reply , ReplyLen , & ReplyLen ) ;
else
Compressed = Reply ;
2023-12-28 10:31:09 +00:00
if ( NodeURL & & _memicmp ( NodeURL , " /mail/api/ " , 10 ) = = 0 )
2024-11-05 21:03:15 +00:00
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 ) ;
2023-12-28 10:31:09 +00:00
else
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n %s \r \n " , ReplyLen , Encoding ) ;
2022-08-28 09:35:46 +01:00
sendandcheck ( sock , Header , HeaderLen ) ;
sendandcheck ( sock , Compressed , ReplyLen ) ;
if ( allowDeflate )
free ( Compressed ) ;
return 0 ;
}
}
doHeader :
# ifdef LINBPQ
if ( ( _memicmp ( Context , " /MAIL/ " , 6 ) = = 0 ) | | ( _memicmp ( Context , " /WebMail " , 8 ) = = 0 ) )
{
char _REPLYBUFFER [ 250000 ] ;
struct HTTPConnectionInfo Dummy = { 0 } ;
int Sent , Loops = 0 ;
2024-11-05 21:03:15 +00:00
char token [ 16 ] = " " ;
// look for auth header
const char * auth_header = " Authorization: Bearer " ;
char * token_begin = strstr ( MsgPtr , auth_header ) ;
int Flags = 0 , n ;
char * Tok ;
char * param ;
if ( token_begin )
{
// Using Auth Header
// Extract the token from the request (assuming it's present in the request headers)
token_begin + = strlen ( auth_header ) ; // Move to the beginning of the token
strncpy ( token , token_begin , 13 ) ;
token [ 13 ] = ' \0 ' ; // Null-terminate the token
}
2022-08-28 09:35:46 +01:00
ReplyLen = 0 ;
if ( Session = = 0 )
Session = & Dummy ;
2024-11-05 21:03:15 +00:00
if ( LOCAL )
Session - > TNC = ( void * ) 1 ; // TNC only used for Web Terminal Sessions
else
Session - > TNC = ( void * ) 0 ;
ProcessMailHTTPMessage ( Session , Method , Context , MsgPtr , _REPLYBUFFER , & ReplyLen , MsgLen , token ) ;
if ( Context & & _memicmp ( Context , " /mail/api/ " , 10 ) = = 0 )
{
if ( memcmp ( _REPLYBUFFER , " HTTP " , 4 ) = = 0 )
{
// Full Header provided by appl - just send it
// Send may block
Sent = send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
while ( Sent ! = ReplyLen & & Loops + + < 3000 ) // 100 secs max
{
// Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops);
if ( Sent > 0 ) // something sent
{
InputLen - = Sent ;
memmove ( _REPLYBUFFER , & _REPLYBUFFER [ Sent ] , ReplyLen ) ;
}
Sleep ( 30 ) ;
Sent = send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
}
return 0 ;
}
// compress if allowed
2022-08-28 09:35:46 +01:00
2024-11-05 21:03:15 +00:00
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 ;
}
2022-08-28 09:35:46 +01:00
if ( memcmp ( _REPLYBUFFER , " HTTP " , 4 ) = = 0 )
{
// Full Header provided by appl - just send it
// Send may block
Sent = send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
while ( Sent ! = ReplyLen & & Loops + + < 3000 ) // 100 secs max
{
// Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops);
if ( Sent > 0 ) // something sent
{
InputLen - = Sent ;
memmove ( _REPLYBUFFER , & _REPLYBUFFER [ Sent ] , ReplyLen ) ;
}
Sleep ( 30 ) ;
Sent = send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
}
return 0 ;
}
2024-11-05 21:03:15 +00:00
if ( Context & & _memicmp ( Context , " /mail/api/ " , 10 ) ! = 0 )
{
2023-03-16 06:52:27 +00:00
// Add tail
strcpy ( & _REPLYBUFFER [ ReplyLen ] , Tail ) ;
ReplyLen + = strlen ( Tail ) ;
2024-11-05 21:03:15 +00:00
}
2023-03-16 06:52:27 +00:00
// compress if allowed
if ( allowDeflate )
Compressed = Compressit ( _REPLYBUFFER , ReplyLen , & ReplyLen ) ;
else
Compressed = Reply ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n %s \r \n " , ReplyLen , Encoding ) ;
sendandcheck ( sock , Header , HeaderLen ) ;
sendandcheck ( sock , Compressed , ReplyLen ) ;
if ( allowDeflate )
free ( Compressed ) ;
return 0 ;
/*
2022-08-28 09:35:46 +01:00
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
// Send may block
Sent = send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
if ( Sent = = - 1 )
return 0 ;
while ( Sent ! = ReplyLen & & Loops + + < 3000 ) // 100 secs max
{
// Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops);
if ( Sent > 0 ) // something sent
{
InputLen - = Sent ;
memmove ( _REPLYBUFFER , & _REPLYBUFFER [ Sent ] , ReplyLen ) ;
}
Sleep ( 30 ) ;
Sent = send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
}
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
return 0 ;
2023-03-16 06:52:27 +00:00
*/
2022-08-28 09:35:46 +01:00
}
if ( _memicmp ( Context , " /CHAT/ " , 6 ) = = 0 )
{
char _REPLYBUFFER [ 100000 ] ;
ReplyLen = 0 ;
ProcessChatHTTPMessage ( Session , Method , Context , MsgPtr , _REPLYBUFFER , & ReplyLen ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
return 0 ;
}
/*
Sent = send ( sock , _REPLYBUFFER , InputLen , 0 ) ;
while ( Sent ! = InputLen & & Loops + + < 3000 ) // 100 secs max
{
// Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops);
if ( Sent > 0 ) // something sent
{
InputLen - = Sent ;
memmove ( _REPLYBUFFER , & _REPLYBUFFER [ Sent ] , InputLen ) ;
}
Sleep ( 30 ) ;
Sent = send ( sock , _REPLYBUFFER , InputLen , 0 ) ;
}
return 0 ;
}
*/
# else
// Pass to MailChat if active
2024-11-05 21:03:15 +00:00
NodeURL = Context ;
2022-08-28 09:35:46 +01:00
if ( ( _memicmp ( Context , " /MAIL/ " , 6 ) = = 0 ) | | ( _memicmp ( Context , " /WebMail " , 8 ) = = 0 ) )
{
// If for Mail, Pass to Mail Server via Named Pipe
HANDLE hPipe ;
hPipe = CreateFile ( MAILPipeFileName , GENERIC_READ | GENERIC_WRITE ,
0 , // exclusive access
NULL , // no security attrs
OPEN_EXISTING ,
FILE_ATTRIBUTE_NORMAL ,
NULL ) ;
if ( hPipe = = ( HANDLE ) - 1 )
{
InputLen = sprintf ( Reply , " HTTP/1.1 404 Not Found \r \n Content-Length: 28 \r \n \r \n Mail Data is not available \r \n " ) ;
send ( sock , Reply , InputLen , 0 ) ;
}
else
{
// int Sent;
int Loops = 0 ;
struct HTTPConnectionInfo Dummy = { 0 } ;
if ( Session = = 0 )
Session = & Dummy ;
2022-11-12 15:00:02 +00:00
Session - > TNC = LOCAL ; // TNC is only used on Web Terminal Sessions so can reuse as LOCAL flag
2022-08-28 09:35:46 +01:00
WriteFile ( hPipe , Session , sizeof ( struct HTTPConnectionInfo ) , & InputLen , NULL ) ;
WriteFile ( hPipe , MsgPtr , MsgLen , & InputLen , NULL ) ;
ReadFile ( hPipe , Session , sizeof ( struct HTTPConnectionInfo ) , & InputLen , NULL ) ;
ReadFile ( hPipe , Reply , 250000 , & ReplyLen , NULL ) ;
if ( ReplyLen < = 0 )
{
InputLen = GetLastError ( ) ;
}
CloseHandle ( hPipe ) ;
goto Returnit ;
}
return 0 ;
}
if ( _memicmp ( Context , " /CHAT/ " , 6 ) = = 0 )
{
HANDLE hPipe ;
hPipe = CreateFile ( CHATPipeFileName , GENERIC_READ | GENERIC_WRITE ,
0 , // exclusive access
NULL , // no security attrs
OPEN_EXISTING ,
FILE_ATTRIBUTE_NORMAL ,
NULL ) ;
if ( hPipe = = ( HANDLE ) - 1 )
{
InputLen = sprintf ( Reply , " HTTP/1.1 404 Not Found \r \n Content-Length: 28 \r \n \r \n Chat Data is not available \r \n " ) ;
send ( sock , Reply , InputLen , 0 ) ;
}
else
{
// int Sent;
int Loops = 0 ;
WriteFile ( hPipe , Session , sizeof ( struct HTTPConnectionInfo ) , & InputLen , NULL ) ;
WriteFile ( hPipe , MsgPtr , MsgLen , & InputLen , NULL ) ;
ReadFile ( hPipe , Session , sizeof ( struct HTTPConnectionInfo ) , & InputLen , NULL ) ;
ReadFile ( hPipe , Reply , 100000 , & ReplyLen , NULL ) ;
if ( ReplyLen < = 0 )
{
InputLen = GetLastError ( ) ;
}
CloseHandle ( hPipe ) ;
goto Returnit ;
}
return 0 ;
}
# endif
NodeURL = strtok_s ( NULL , " ? " , & Context ) ;
if ( NodeURL = = NULL )
return 0 ;
if ( strcmp ( Method , " POST " ) = = 0 )
{
if ( _stricmp ( NodeURL , " /Node/freqOffset " ) = = 0 )
{
char * input = strstr ( MsgPtr , " \r \n \r \n " ) ; // End of headers
int port = atoi ( Context ) ;
if ( input = = 0 )
return 1 ;
input + = 4 ;
2023-05-25 14:17:53 +01:00
if ( port > 0 & & port < = MaxBPQPortNo )
2022-08-28 09:35:46 +01:00
{
struct TNCINFO * TNC = TNCInfo [ port ] ;
char value [ 6 ] ;
if ( TNC = = 0 )
return 1 ;
TNC - > TXOffset = atoi ( input ) ;
# ifdef WIN32
sprintf ( value , " %d " , TNC - > TXOffset ) ;
MySetWindowText ( TNC - > xIDC_TXTUNEVAL , value ) ;
SendMessage ( TNC - > xIDC_TXTUNE , TBM_SETPOS , ( WPARAM ) TRUE , ( LPARAM ) TNC - > TXOffset ) ; // min. & max. positions
# endif
}
return 1 ;
}
if ( _stricmp ( NodeURL , " /Node/PortAction " ) = = 0 )
{
char * input = strstr ( MsgPtr , " \r \n \r \n " ) ; // End of headers
int port = atoi ( Context ) ;
if ( input = = 0 )
return 1 ;
input + = 4 ;
2023-05-25 14:17:53 +01:00
if ( port > 0 & & port < = MaxBPQPortNo )
2022-08-28 09:35:46 +01:00
{
struct TNCINFO * TNC = TNCInfo [ port ] ;
if ( TNC = = 0 )
return 1 ;
2023-01-25 10:12:51 +00:00
if ( LOCAL = = FALSE & & COOKIE = = FALSE )
return 1 ;
2022-08-28 09:35:46 +01:00
if ( strcmp ( input , " Abort " ) = = 0 )
{
if ( TNC - > ForcedCloseProc )
TNC - > ForcedCloseProc ( TNC , 0 ) ;
}
else if ( strcmp ( input , " Kill " ) = = 0 )
{
TNC - > DontRestart = TRUE ;
KillTNC ( TNC ) ;
}
else if ( strcmp ( input , " KillRestart " ) = = 0 )
{
TNC - > DontRestart = FALSE ;
KillTNC ( TNC ) ;
RestartTNC ( TNC ) ;
}
}
return 1 ;
}
if ( _stricmp ( NodeURL , " /TermInput " ) = = 0 )
{
ProcessTermInput ( sock , MsgPtr , MsgLen , Context ) ;
return 0 ;
}
if ( _stricmp ( NodeURL , " /Node/TermSignon " ) = = 0 )
{
ProcessTermSignon ( conn - > TNC , sock , MsgPtr , MsgLen , LOCAL ) ;
}
if ( _stricmp ( NodeURL , " /Node/Signon " ) = = 0 )
{
ProcessNodeSignon ( sock , TCP , MsgPtr , Key , Reply , & Session , LOCAL ) ;
return 0 ;
}
if ( _stricmp ( NodeURL , " /Node/TermClose " ) = = 0 )
{
ProcessTermClose ( sock , MsgPtr , MsgLen , Context , LOCAL ) ;
return 0 ;
}
if ( _stricmp ( NodeURL , " /Node/BeaconAction " ) = = 0 )
{
char Header [ 256 ] ;
int HeaderLen ;
char * input = strstr ( MsgPtr , " \r \n \r \n " ) ; // End of headers
int Port ;
char Param [ 100 ] ;
# ifndef LINBPQ
int retCode , disp ;
char Key [ 80 ] ;
HKEY hKey ;
# endif
struct PORTCONTROL * PORT ;
int Slot = 0 ;
if ( LOCAL = = FALSE & & COOKIE = = FALSE )
{
// Send Not Authorized
ReplyLen = SetupNodeMenu ( _REPLYBUFFER , LOCAL ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <br><B>Not authorized - please sign in</B> " ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
return 1 ;
}
if ( strstr ( input , " Cancel=Cancel " ) )
{
ReplyLen = SetupNodeMenu ( _REPLYBUFFER , LOCAL ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
return 1 ;
}
2024-03-26 00:52:55 +00:00
GetParam ( input , " Port= " , & Param [ 0 ] ) ;
Port = atoi ( & Param [ 0 ] ) ;
2022-08-28 09:35:46 +01:00
PORT = GetPortTableEntryFromPortNum ( Port ) ; // Need slot not number
if ( PORT )
Slot = PORT - > PortSlot ;
2024-03-26 00:52:55 +00:00
GetParam ( input , " Every= " , & Param [ 0 ] ) ;
Interval [ Slot ] = atoi ( & Param [ 0 ] ) ;
2022-08-28 09:35:46 +01:00
2024-03-26 00:52:55 +00:00
GetParam ( input , " Dest= " , & Param [ 0 ] ) ;
2022-08-28 09:35:46 +01:00
_strupr ( Param ) ;
2024-03-26 00:52:55 +00:00
strcpy ( UIUIDEST [ Slot ] , & Param [ 0 ] ) ;
2022-08-28 09:35:46 +01:00
2024-03-26 00:52:55 +00:00
GetParam ( input , " Path= " , & Param [ 0 ] ) ;
2022-08-28 09:35:46 +01:00
_strupr ( Param ) ;
if ( UIUIDigi [ Slot ] )
free ( UIUIDigi [ Slot ] ) ;
2024-03-26 00:52:55 +00:00
UIUIDigi [ Slot ] = _strdup ( & Param [ 0 ] ) ;
2022-08-28 09:35:46 +01:00
2024-03-26 00:52:55 +00:00
GetParam ( input , " File= " , & Param [ 0 ] ) ;
2024-04-06 02:10:08 +01:00
strcpy ( FN [ Slot ] , & Param [ 0 ] ) ;
2024-03-26 00:52:55 +00:00
GetParam ( input , " Text= " , & Param [ 0 ] ) ;
strcpy ( Message [ Slot ] , & Param [ 0 ] ) ;
2022-08-28 09:35:46 +01:00
MinCounter [ Slot ] = Interval [ Slot ] ;
SendFromFile [ Slot ] = 0 ;
if ( FN [ Slot ] [ 0 ] )
SendFromFile [ Slot ] = 1 ;
SetupUI ( Slot ) ;
# ifdef LINBPQ
SaveUIConfig ( ) ;
# else
SaveUIConfig ( ) ;
wsprintf ( Key , " SOFTWARE \\ G8BPQ \\ BPQ32 \\ UIUtil \\ UIPort%d " , Port ) ;
retCode = RegCreateKeyEx ( REGTREE ,
Key , 0 , 0 , 0 , KEY_ALL_ACCESS , NULL , & hKey , & disp ) ;
if ( retCode = = ERROR_SUCCESS )
{
retCode = RegSetValueEx ( hKey , " UIDEST " , 0 , REG_SZ , ( BYTE * ) & UIUIDEST [ Port ] [ 0 ] , strlen ( & UIUIDEST [ Port ] [ 0 ] ) ) ;
retCode = RegSetValueEx ( hKey , " FileName " , 0 , REG_SZ , ( BYTE * ) & FN [ Port ] [ 0 ] , strlen ( & FN [ Port ] [ 0 ] ) ) ;
retCode = RegSetValueEx ( hKey , " Message " , 0 , REG_SZ , ( BYTE * ) & Message [ Port ] [ 0 ] , strlen ( & Message [ Port ] [ 0 ] ) ) ;
retCode = RegSetValueEx ( hKey , " Interval " , 0 , REG_DWORD , ( BYTE * ) & Interval [ Port ] , 4 ) ;
retCode = RegSetValueEx ( hKey , " SendFromFile " , 0 , REG_DWORD , ( BYTE * ) & SendFromFile [ Port ] , 4 ) ;
retCode = RegSetValueEx ( hKey , " Digis " , 0 , REG_SZ , UIUIDigi [ Port ] , strlen ( UIUIDigi [ Port ] ) ) ;
RegCloseKey ( hKey ) ;
}
# endif
if ( strstr ( input , " Test=Test " ) )
SendUIBeacon ( Slot ) ;
ReplyLen = SetupNodeMenu ( _REPLYBUFFER , LOCAL ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , Beacons , Port ,
Interval [ Slot ] , & UIUIDEST [ Slot ] [ 0 ] , & UIUIDigi [ Slot ] [ 0 ] , & FN [ Slot ] [ 0 ] , & Message [ Slot ] [ 0 ] , Port ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
return 1 ;
}
if ( _stricmp ( NodeURL , " /Node/CfgSave " ) = = 0 )
{
// Save Config File
SaveConfigFile ( sock , MsgPtr , Key , LOCAL ) ;
return 0 ;
}
if ( _stricmp ( NodeURL , " /Node/LogAction " ) = = 0 )
{
ReplyLen = SetupNodeMenu ( _REPLYBUFFER , LOCAL ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
return 1 ;
}
if ( _stricmp ( NodeURL , " /Node/ARDOPAbort " ) = = 0 )
{
int port = atoi ( Context ) ;
2023-05-25 14:17:53 +01:00
if ( port > 0 & & port < = MaxBPQPortNo )
2022-08-28 09:35:46 +01:00
{
struct TNCINFO * TNC = TNCInfo [ port ] ;
if ( TNC & & TNC - > ForcedCloseProc )
TNC - > ForcedCloseProc ( TNC , 0 ) ;
if ( TNC & & TNC - > WebWindowProc )
ReplyLen = TNC - > WebWindowProc ( TNC , _REPLYBUFFER , LOCAL ) ;
ReplyLen = sprintf ( Reply , " <html><script>alert( \" %s \" );window.close();</script></html> " , " Ok " ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , Reply , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
// goto SendResp;
// HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + strlen(Tail));
// send(sock, Header, HeaderLen, 0);
// send(sock, _REPLYBUFFER, ReplyLen, 0);
// send(sock, Tail, strlen(Tail), 0);
return 1 ;
}
}
send ( sock , _REPLYBUFFER , InputLen , 0 ) ;
return 0 ;
}
if ( _stricmp ( NodeURL , " / " ) = = 0 | | _stricmp ( NodeURL , " /Index.html " ) = = 0 )
{
// Send if present, else use default
Bufferlen = SendMessageFile ( sock , NodeURL , TRUE , allowDeflate ) ; // return -1 if not found
if ( Bufferlen ! = - 1 )
return 0 ; // We've sent it
else
{
if ( APRSApplConnected )
ReplyLen = sprintf ( _REPLYBUFFER , Index , Mycall , Mycall ) ;
else
ReplyLen = sprintf ( _REPLYBUFFER , IndexNoAPRS , Mycall , Mycall ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
return 0 ;
}
}
else if ( _stricmp ( NodeURL , " /NodeMenu.html " ) = = 0 | | _stricmp ( NodeURL , " /Node/NodeMenu.html " ) = = 0 )
{
// Send if present, else use default
char Menu [ ] = " /NodeMenu.html " ;
Bufferlen = SendMessageFile ( sock , Menu , TRUE , allowDeflate ) ; // return -1 if not found
if ( Bufferlen ! = - 1 )
return 0 ; // We've sent it
}
else if ( _memicmp ( NodeURL , " /aisdata.txt " , 12 ) = = 0 )
{
char * Compressed ;
ReplyLen = GetAISPageInfo ( _REPLYBUFFER , 1 , 1 ) ;
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: Text \r \n %s \r \n " , ReplyLen , Encoding ) ;
sendandcheck ( sock , Header , HeaderLen ) ;
sendandcheck ( sock , Compressed , ReplyLen ) ;
if ( allowDeflate )
free ( Compressed ) ;
return 0 ;
}
else if ( _memicmp ( NodeURL , " /aprsdata.txt " , 13 ) = = 0 )
{
char * Compressed ;
char * ptr ;
double N , S , W , E ;
int aprs = 1 , ais = 1 , adsb = 1 ;
ptr = & NodeURL [ 14 ] ;
N = atof ( ptr ) ;
ptr = strlop ( ptr , ' | ' ) ;
S = atof ( ptr ) ;
ptr = strlop ( ptr , ' | ' ) ;
W = atof ( ptr ) ;
ptr = strlop ( ptr , ' | ' ) ;
E = atof ( ptr ) ;
ptr = strlop ( ptr , ' | ' ) ;
if ( ptr )
{
aprs = atoi ( ptr ) ;
ptr = strlop ( ptr , ' | ' ) ;
ais = atoi ( ptr ) ;
ptr = strlop ( ptr , ' | ' ) ;
adsb = atoi ( ptr ) ;
}
ReplyLen = GetAPRSPageInfo ( _REPLYBUFFER , N , S , W , E , aprs , ais , adsb ) ;
2022-12-31 10:44:53 +00:00
if ( ReplyLen < 240000 )
ReplyLen + = GetAISPageInfo ( & _REPLYBUFFER [ ReplyLen ] , ais , adsb ) ;
2022-08-28 09:35:46 +01:00
if ( allowDeflate )
Compressed = Compressit ( _REPLYBUFFER , ReplyLen , & ReplyLen ) ;
else
Compressed = _REPLYBUFFER ;
2023-03-02 09:33:47 +00:00
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Access-Control-Allow-Origin: * \r \n Content-Length: %d \r \n Content-Type: Text \r \n %s \r \n " , ReplyLen , Encoding ) ;
2022-08-28 09:35:46 +01:00
sendandcheck ( sock , Header , HeaderLen ) ;
sendandcheck ( sock , Compressed , ReplyLen ) ;
if ( allowDeflate )
free ( Compressed ) ;
return 0 ;
}
2024-10-11 15:37:11 +01:00
else if ( _memicmp ( NodeURL , " /portstats.txt " , 15 ) = = 0 )
{
char * Compressed ;
char * ptr ;
int port ;
struct PORTCONTROL * PORT ;
ptr = & NodeURL [ 15 ] ;
port = atoi ( ptr ) ;
PORT = GetPortTableEntryFromPortNum ( port ) ;
ReplyLen = 0 ;
if ( PORT & & PORT - > TX )
{
// We send the last 24 hours worth of data. Buffer is cyclic so oldest byte is at StatsPointer
int first = PORT - > StatsPointer ;
int firstlen = 1440 - first ;
memcpy ( & _REPLYBUFFER [ 0 ] , & PORT - > TX [ first ] , firstlen ) ;
memcpy ( & _REPLYBUFFER [ firstlen ] , PORT - > TX , first ) ;
memcpy ( & _REPLYBUFFER [ 1440 ] , & PORT - > BUSY [ first ] , firstlen ) ;
memcpy ( & _REPLYBUFFER [ 1440 + firstlen ] , PORT - > BUSY , first ) ;
ReplyLen = 2880 ;
}
if ( allowDeflate )
Compressed = Compressit ( _REPLYBUFFER , ReplyLen , & ReplyLen ) ;
else
Compressed = _REPLYBUFFER ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Access-Control-Allow-Origin: * \r \n Content-Length: %d \r \n Content-Type: Text \r \n %s \r \n " , ReplyLen , Encoding ) ;
sendandcheck ( sock , Header , HeaderLen ) ;
sendandcheck ( sock , Compressed , ReplyLen ) ;
if ( allowDeflate )
free ( Compressed ) ;
return 0 ;
}
2022-08-28 09:35:46 +01:00
else if ( _memicmp ( NodeURL , " /Icon " , 5 ) = = 0 & & _memicmp ( & NodeURL [ 10 ] , " .png " , 4 ) = = 0 )
{
// APRS internal Icon
char * Compressed ;
ReplyLen = GetAPRSIcon ( _REPLYBUFFER , NodeURL ) ;
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: Text \r \n %s \r \n " , ReplyLen , Encoding ) ;
sendandcheck ( sock , Header , HeaderLen ) ;
sendandcheck ( sock , Compressed , ReplyLen ) ;
if ( allowDeflate )
free ( Compressed ) ;
return 0 ;
}
else if ( _memicmp ( NodeURL , " /NODE/ " , 6 ) )
{
// Not Node, See if a local file
Bufferlen = SendMessageFile ( sock , NodeURL , FALSE , allowDeflate ) ; // Send error if not found
return 0 ;
}
// Node URL
{
ReplyLen = SetupNodeMenu ( _REPLYBUFFER , LOCAL ) ;
if ( _stricmp ( NodeURL , " /Node/webproc.css " ) = = 0 )
{
char WebprocCSS [ ] =
" .dropbtn {position: relative; border: 1px solid black;padding:1px;} \r \n "
" .dropdown {position: relative; display: inline-block;} \r \n "
" .dropdown-content {display: none; position: absolute;background-color: #ccc; "
" min-width: 160px; box-shadow: 0px 8px 16px 0px rgba(0,0,00.2); z-index: 1;} \r \n "
" .dropdown-content a {color: black; padding: 1px 1px;text-decoration:none;display:block;} "
" .dropdown-content a:hover {background-color: #dddfff;} \r \n "
" .dropdown:hover .dropdown-content {display: block;} \r \n "
" .dropdown:hover .dropbtn {background-color: #ddd;} \r \n "
" input.btn:active {background:black;color:white;} \r \n "
" submit.btn:active {background:black;color:white;} \r \n " ;
ReplyLen = sprintf ( _REPLYBUFFER , " %s " , WebprocCSS ) ;
}
else if ( _stricmp ( NodeURL , " /Node/Killandrestart " ) = = 0 )
{
int port = atoi ( Context ) ;
2023-05-25 14:17:53 +01:00
if ( port > 0 & & port < = MaxBPQPortNo )
2022-08-28 09:35:46 +01:00
{
struct TNCINFO * TNC = TNCInfo [ port ] ;
KillTNC ( TNC ) ;
TNC - > DontRestart = FALSE ;
RestartTNC ( TNC ) ;
if ( TNC & & TNC - > WebWindowProc )
ReplyLen = TNC - > WebWindowProc ( TNC , _REPLYBUFFER , LOCAL ) ;
}
}
else if ( _stricmp ( NodeURL , " /Node/Port " ) = = 0 | | _stricmp ( NodeURL , " /Node/ARDOPAbort " ) = = 0 )
{
int port = atoi ( Context ) ;
2023-05-25 14:17:53 +01:00
if ( port > 0 & & port < = MaxBPQPortNo )
2022-08-28 09:35:46 +01:00
{
struct TNCINFO * TNC = TNCInfo [ port ] ;
if ( TNC & & TNC - > WebWindowProc )
ReplyLen = TNC - > WebWindowProc ( TNC , _REPLYBUFFER , LOCAL ) ;
}
}
else if ( _stricmp ( NodeURL , " /Node/Streams " ) = = 0 )
{
ReplyLen = StatusProc ( _REPLYBUFFER ) ;
}
else if ( _stricmp ( NodeURL , " /Node/Stats.html " ) = = 0 )
{
struct tm * TM ;
char UPTime [ 50 ] ;
time_t szClock = STATSTIME * 60 ;
TM = gmtime ( & szClock ) ;
sprintf ( UPTime , " %.2d:%.2d:%.2d " , TM - > tm_yday , TM - > tm_hour , TM - > tm_min ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " %s " , StatsHddr ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <tr><td>%s</td><td align=right>%s</td></tr> " ,
" Version " , VersionString ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <tr><td>%s</td><td align=right>%s</td></tr> " ,
" Uptime (Days Hours Mins) " , UPTime ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <tr><td>%s</td><td align=right>%d</td><td align=right>%d</td></tr> " ,
" Semaphore: Get-Rel/Clashes " , Semaphore . Gets - Semaphore . Rels , Semaphore . Clashes ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <tr><td>%s</td><td align=right>%d</td><td align=right>%d</td><td align=right>%d</td><td align=right>%d</td align=right><td align=right>%d</td></tr> " ,
" Buffers: Max/Cur/Min/Out/Wait " , MAXBUFFS , QCOUNT , MINBUFFCOUNT , NOBUFFCOUNT , BUFFERWAITS ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <tr><td>%s</td><td align=right>%d</td><td align=right>%d</td></tr> " ,
" Known Nodes/Max Nodes " , NUMBEROFNODES , MAXDESTS ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <tr><td>%s</td><td align=right>%d</td><td align=right>%d</td></tr> " ,
" L4 Connects Sent/Rxed " , L4CONNECTSOUT , L4CONNECTSIN ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <tr><td>%s</td><td align=right>%d</td><td align=right>%d</td><td align=right>%d</td align=right><td align=right>%d</td></tr> " ,
" L4 Frames TX/RX/Resent/Reseq " , L4FRAMESTX , L4FRAMESRX , L4FRAMESRETRIED , OLDFRAMES ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <tr><td>%s</td><td align=right>%d</td></tr> " ,
" L3 Frames Relayed " , L3FRAMES ) ;
}
else if ( _stricmp ( NodeURL , " /Node/RigControl.html " ) = = 0 )
{
char Test [ ] =
" <html><meta http-equiv=expires content=0> \r \n "
" <head><title>Rigcontrol</title></head> \r \n "
" <script type = \" text/javascript \" > \r \n "
" var ws; "
" function WebSocketTest() "
" { "
" if ( \" WebSocket \" in window) "
" { "
" // Let us open a web socket. Get address from URL \r \n "
" var text = window.location.href; "
" var result = text.substring(7); "
" var myArray = result.split('/', 1); "
" ws = new WebSocket('ws://' + myArray[0] + '/RIGCTL'); \r \n "
" ws.onopen = function() { \r \n "
" // Web Socket is connected \r \n "
" const div = document.getElementById('div'); \r \n "
" div.innerHTML = 'Websock Connected' \r \n "
" }; \r \n "
" ws.onmessage = function (evt) "
" { "
" var received_msg = evt.data; \r \n "
" const div = document.getElementById('div'); \r \n "
" div.innerHTML = received_msg \r \n "
" }; "
" ws.onclose = function() "
" { "
" // websocket is closed. \r \n "
" const div = document.getElementById('div'); \r \n "
" div.innerHTML = 'Websock Connection Lost' \r \n "
" }; "
" } "
" else "
" { "
" // The browser doesn't support WebSocket \r \n "
" const div = document.getElementById('div'); \r \n "
2024-10-11 15:37:11 +01:00
" div.innerHTML = 'WebSocket not supported by your Browser - RigControl Page not availible' \r \n "
2022-08-28 09:35:46 +01:00
" } "
" } "
" function PTT(p) "
" { "
" ws.send(p); "
" } "
" </script> \r \n "
" </head> \r \n "
" <body height: 600px; onload=WebSocketTest()> \r \n "
" <div id = 'div'>Waiting for data...</div> \r \n "
" </body></html> \r \n " ;
char NoRigCtl [ ] =
" <html><meta http-equiv=expires content=0> \r \n "
" <head><title>Rigcontrol</title></head> \r \n "
" </head> \r \n "
" <body height: 600px> \r \n "
" <div id = 'div'>RigControl Not Configured...</div> \r \n "
" </body></html> \r \n " ;
if ( RigWebPage )
ReplyLen = sprintf ( _REPLYBUFFER , " %s " , Test ) ;
else
ReplyLen = sprintf ( _REPLYBUFFER , " %s " , NoRigCtl ) ;
}
else if ( _stricmp ( NodeURL , " /Node/ShowLog.html " ) = = 0 )
{
char ShowLogPage [ ] =
" <html><script> "
" function myResize() { "
" var h = document.getElementById('outer').clientHeight; "
" var offsets = document.getElementById('log').getBoundingClientRect(); "
" document.getElementById('log').style.height = h - offsets.top;} "
" </script> "
" <head><meta content= \" text/html; charset=ISO-8859-1 \" http-equiv= \" content-type \" > "
" <title>Log Display</title></head> "
" <body style= \" margin: 4; \" background=/background.jpg onload='myResize()' onresize='myResize()'> "
" <div id=outer style= \" width: 100%%; height: 100%%; \" > "
" <form id = form><input name=input value=Back type=submit class='btn'> "
// "<form id = doDate><input type=date value=Date name='date'><input type='submit'>"
" </form> "
" <textarea id=log style= \" box-sizing: border-box; overflow: auto; white-space: pre; width: 100%%; height: auto \" name=Msg>%s</textarea> "
" </div> " ;
char * _REPLYBUFFER ;
int ReplyLen ;
char Header [ 256 ] ;
int HeaderLen ;
char * CfgBytes ;
int CfgLen ;
char inputname [ 250 ] ;
FILE * fp1 ;
struct stat STAT ;
char DummyKey [ ] = " DummyKey " ;
time_t T ;
struct tm * tm ;
char Name [ 64 ] = " " ;
T = time ( NULL ) ;
tm = gmtime ( & T ) ;
if ( LOCAL = = FALSE & & COOKIE = = FALSE )
{
// Send Not Authorized
char _REPLYBUFFER [ 4096 ] ;
ReplyLen = SetupNodeMenu ( _REPLYBUFFER , LOCAL ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <br><B>Not authorized - please sign in</B> " ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
return 1 ;
}
if ( COOKIE = = FALSE )
Key = DummyKey ;
if ( memcmp ( Context , " date= " , 5 ) = = 0 )
{
memset ( tm , 0 , sizeof ( struct tm ) ) ;
tm - > tm_year = atoi ( & Context [ 5 ] ) - 1900 ;
tm - > tm_mon = atoi ( & Context [ 10 ] ) - 1 ;
tm - > tm_mday = atoi ( & Context [ 13 ] ) ;
}
if ( strcmp ( Context , " input=Back " ) = = 0 )
{
ReplyLen = SetupNodeMenu ( Reply , LOCAL ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , Reply , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
return 1 ;
}
if ( LogDirectory [ 0 ] = = 0 )
{
strcpy ( inputname , " logs/ " ) ;
}
else
{
strcpy ( inputname , LogDirectory ) ;
strcat ( inputname , " / " ) ;
strcat ( inputname , " /logs/ " ) ;
}
if ( strstr ( Context , " CMS " ) )
{
sprintf ( Name , " CMSAccess_%04d%02d%02d.log " ,
tm - > tm_year + 1900 , tm - > tm_mon + 1 , tm - > tm_mday ) ;
}
else if ( strstr ( Context , " Debug " ) )
{
sprintf ( Name , " log_%02d%02d%02d_DEBUG.txt " ,
tm - > tm_year - 100 , tm - > tm_mon + 1 , tm - > tm_mday ) ;
}
else if ( strstr ( Context , " BBS " ) )
{
sprintf ( Name , " log_%02d%02d%02d_BBS.txt " ,
tm - > tm_year - 100 , tm - > tm_mon + 1 , tm - > tm_mday ) ;
}
else if ( strstr ( Context , " Chat " ) )
{
sprintf ( Name , " log_%02d%02d%02d_CHAT.txt " ,
tm - > tm_year - 100 , tm - > tm_mon + 1 , tm - > tm_mday ) ;
}
else if ( strstr ( Context , " Telnet " ) )
{
sprintf ( Name , " Telnet_%02d%02d%02d.log " ,
tm - > tm_year - 100 , tm - > tm_mon + 1 , tm - > tm_mday ) ;
}
strcat ( inputname , Name ) ;
if ( stat ( inputname , & STAT ) = = - 1 )
{
CfgBytes = malloc ( 256 ) ;
sprintf ( CfgBytes , " Log %s not found " , inputname ) ;
CfgLen = strlen ( CfgBytes ) ;
}
else
{
fp1 = fopen ( inputname , " rb " ) ;
if ( fp1 = = 0 )
{
CfgBytes = malloc ( 256 ) ;
sprintf ( CfgBytes , " Log %s not found " , inputname ) ;
CfgLen = strlen ( CfgBytes ) ;
}
else
{
CfgLen = STAT . st_size ;
CfgBytes = malloc ( CfgLen + 1 ) ;
CfgLen = ( int ) fread ( CfgBytes , 1 , CfgLen , fp1 ) ;
CfgBytes [ CfgLen ] = 0 ;
}
}
_REPLYBUFFER = malloc ( CfgLen + 1000 ) ;
ReplyLen = sprintf ( _REPLYBUFFER , ShowLogPage , CfgBytes ) ;
free ( CfgBytes ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
sendandcheck ( sock , Header , HeaderLen ) ;
sendandcheck ( sock , _REPLYBUFFER , ReplyLen ) ;
sendandcheck ( sock , Tail , ( int ) strlen ( Tail ) ) ;
free ( _REPLYBUFFER ) ;
return 1 ;
}
else if ( _stricmp ( NodeURL , " /Node/EditCfg.html " ) = = 0 )
{
char * _REPLYBUFFER ;
int ReplyLen ;
char Header [ 256 ] ;
int HeaderLen ;
char * CfgBytes ;
int CfgLen ;
char inputname [ 250 ] = " bpq32.cfg " ;
FILE * fp1 ;
struct stat STAT ;
char DummyKey [ ] = " DummyKey " ;
if ( LOCAL = = FALSE & & COOKIE = = FALSE )
{
// Send Not Authorized
char _REPLYBUFFER [ 4096 ] ;
ReplyLen = SetupNodeMenu ( _REPLYBUFFER , LOCAL ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <br><B>Not authorized - please sign in</B> " ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , _REPLYBUFFER , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
return 1 ;
}
if ( COOKIE = = FALSE )
Key = DummyKey ;
2023-10-10 22:07:04 +01:00
if ( ConfigDirectory [ 0 ] = = 0 )
2022-08-28 09:35:46 +01:00
{
strcpy ( inputname , " bpq32.cfg " ) ;
}
else
{
2023-10-10 22:07:04 +01:00
strcpy ( inputname , ConfigDirectory ) ;
2022-08-28 09:35:46 +01:00
strcat ( inputname , " / " ) ;
strcat ( inputname , " bpq32.cfg " ) ;
}
if ( stat ( inputname , & STAT ) = = - 1 )
{
CfgBytes = _strdup ( " Config File not found " ) ;
}
else
{
fp1 = fopen ( inputname , " rb " ) ;
if ( fp1 = = 0 )
{
CfgBytes = _strdup ( " Config File not found " ) ;
}
else
{
CfgLen = STAT . st_size ;
CfgBytes = malloc ( CfgLen + 1 ) ;
CfgLen = ( int ) fread ( CfgBytes , 1 , CfgLen , fp1 ) ;
CfgBytes [ CfgLen ] = 0 ;
}
}
_REPLYBUFFER = malloc ( CfgLen + 1000 ) ;
ReplyLen = sprintf ( _REPLYBUFFER , ConfigEditPage , Key , CfgBytes ) ;
free ( CfgBytes ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ReplyLen + ( int ) strlen ( Tail ) ) ;
sendandcheck ( sock , Header , HeaderLen ) ;
sendandcheck ( sock , _REPLYBUFFER , ReplyLen ) ;
sendandcheck ( sock , Tail , ( int ) strlen ( Tail ) ) ;
free ( _REPLYBUFFER ) ;
return 1 ;
}
if ( _stricmp ( NodeURL , " /Node/PortBeacons " ) = = 0 )
{
char * PortChar = strtok_s ( NULL , " & " , & Context ) ;
int PortNo = atoi ( PortChar ) ;
struct PORTCONTROL * PORT ;
int PortSlot = 0 ;
PORT = GetPortTableEntryFromPortNum ( PortNo ) ; // Need slot not number
if ( PORT )
PortSlot = PORT - > PortSlot ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , Beacons , PortNo ,
Interval [ PortSlot ] , & UIUIDEST [ PortSlot ] [ 0 ] , & UIUIDigi [ PortSlot ] [ 0 ] , & FN [ PortSlot ] [ 0 ] , & Message [ PortSlot ] [ 0 ] , PortNo ) ;
}
if ( _stricmp ( NodeURL , " /Node/PortStats " ) = = 0 )
{
struct _EXTPORTDATA * Port ;
char * PortChar = strtok_s ( NULL , " & " , & Context ) ;
int PortNo = atoi ( PortChar ) ;
int Protocol ;
int PortType ;
// char PORTTYPE; // H/W TYPE
// 0 = ASYNC, 2 = PC120, 4 = DRSI
// 6 = TOSH, 8 = QUAD, 10 = RLC100
// 12 = RLC400 14 = INTERNAL 16 = EXTERNAL
# define KISS 0
# define NETROM 2
# define HDLC 6
# define L2 8
# define WINMOR 10
// char PROTOCOL; // PORT PROTOCOL
// 0 = KISS, 2 = NETROM, 4 = BPQKISS
//; 6 = HDLC, 8 = L2
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsHddr , PortNo ) ;
Port = ( struct _EXTPORTDATA * ) GetPortTableEntryFromPortNum ( PortNo ) ;
if ( Port = = NULL )
{
ReplyLen = sprintf ( _REPLYBUFFER , " Invalid Port " ) ;
goto SendResp ;
}
Protocol = Port - > PORTCONTROL . PROTOCOL ;
PortType = Port - > PORTCONTROL . PROTOCOL ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsLine , " L2 Frames Digied " , Port - > PORTCONTROL . L2DIGIED ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsLine , " L2 Frames Heard " , Port - > PORTCONTROL . L2FRAMES ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsLine , " L2 Frames Received " , Port - > PORTCONTROL . L2FRAMESFORUS ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsLine , " L2 Frames Sent " , Port - > PORTCONTROL . L2FRAMESSENT ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsLine , " L2 Timeouts " , Port - > PORTCONTROL . L2TIMEOUTS ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsLine , " REJ Frames Received " , Port - > PORTCONTROL . L2REJCOUNT ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsLine , " RX out of Seq " , Port - > PORTCONTROL . L2OUTOFSEQ ) ;
// ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortStatsLine, "L2 Resequenced", Port->PORTCONTROL.L2RESEQ);
if ( Protocol = = HDLC )
{
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsLine , " Underrun " , Port - > PORTCONTROL . L2URUNC ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsLine , " RX Overruns " , Port - > PORTCONTROL . L2ORUNC ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsLine , " RX CRC Errors " , Port - > PORTCONTROL . RXERRORS ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsLine , " Frames abandoned " , Port - > PORTCONTROL . L1DISCARD ) ;
}
else if ( ( Protocol = = KISS & & Port - > PORTCONTROL . KISSFLAGS ) | | Protocol = = NETROM )
{
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsLine , " Poll Timeout " , Port - > PORTCONTROL . L2URUNC ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsLine , " RX CRC Errors " , Port - > PORTCONTROL . RXERRORS ) ;
}
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsLine , " FRMRs Sent " , Port - > PORTCONTROL . L2FRMRTX ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortStatsLine , " FRMRs Received " , Port - > PORTCONTROL . L2FRMRRX ) ;
// DB 'Link Active % '
// DD AVSENDING
}
if ( _stricmp ( NodeURL , " /Node/Ports.html " ) = = 0 )
{
struct _EXTPORTDATA * ExtPort ;
struct PORTCONTROL * Port ;
int count ;
char DLL [ 20 ] ;
2024-10-11 15:37:11 +01:00
char StatsURL [ 64 ] ;
2022-08-28 09:35:46 +01:00
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " %s " , PortsHddr ) ;
for ( count = 1 ; count < = NUMBEROFPORTS ; count + + )
{
Port = GetPortTableEntryFromSlot ( count ) ;
ExtPort = ( struct _EXTPORTDATA * ) Port ;
2024-10-11 15:37:11 +01:00
// see if has a stats page
if ( Port - > AVACTIVE )
sprintf ( StatsURL , " <a href=/PortStats.html?%d> Stats Graph</a> " , Port - > PORTNUMBER ) ;
else
StatsURL [ 0 ] = 0 ;
2022-08-28 09:35:46 +01:00
if ( Port - > PORTTYPE = = 0x10 )
{
strcpy ( DLL , ExtPort - > PORT_DLL_NAME ) ;
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 - > TNC & & Port - > TNC - > WebWindowProc ) // Has a Window
{
if ( Port - > UICAPABLE )
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortLineWithBeaconAndDriver , Port - > PORTNUMBER , DLL ,
2024-10-11 15:37:11 +01:00
Port - > PORTDESCRIPTION , Port - > PORTNUMBER , Port - > PORTNUMBER , Port - > TNC - > WebWinX , Port - > TNC - > WebWinY , 200 , 200 , StatsURL ) ;
2022-08-28 09:35:46 +01:00
else
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortLineWithDriver , Port - > PORTNUMBER , DLL ,
2024-10-11 15:37:11 +01:00
Port - > PORTDESCRIPTION , Port - > PORTNUMBER , Port - > TNC - > WebWinX , Port - > TNC - > WebWinY , 200 , 200 , StatsURL ) ;
2022-08-28 09:35:46 +01:00
continue ;
}
if ( Port - > PORTTYPE = = 16 & & Port - > PROTOCOL = = 10 & & Port - > UICAPABLE = = 0 ) // EXTERNAL, Pactor/WINMO
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , SessionPortLine , Port - > PORTNUMBER , DLL ,
2024-10-11 15:37:11 +01:00
Port - > PORTDESCRIPTION , Port - > PORTNUMBER , StatsURL ) ;
2022-08-28 09:35:46 +01:00
else
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , PortLineWithBeacon , Port - > PORTNUMBER , Port - > PORTNUMBER ,
2024-10-11 15:37:11 +01:00
DLL , DLL , Port - > PORTDESCRIPTION , Port - > PORTNUMBER , StatsURL ) ;
2022-08-28 09:35:46 +01:00
}
if ( RigActive )
2023-05-25 14:17:53 +01:00
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , RigControlLine , 64 , " Rig Control " , " Rig Control " , 600 , 350 , 200 , 200 ) ;
2022-08-28 09:35:46 +01:00
}
if ( _stricmp ( NodeURL , " /Node/Nodes.html " ) = = 0 )
{
struct DEST_LIST * Dests = DESTS ;
int count , i ;
char Normcall [ 10 ] ;
char Alias [ 10 ] ;
int Width = 5 ;
int x = 0 , n = 0 ;
struct DEST_LIST * List [ 1000 ] ;
char Param = 0 ;
if ( Context )
{
_strupr ( Context ) ;
Param = Context [ 0 ] ;
}
for ( count = 0 ; count < MAXDESTS ; count + + )
{
if ( Dests - > DEST_CALL [ 0 ] ! = 0 )
{
if ( Param ! = ' T ' | | Dests - > DEST_COUNT )
List [ n + + ] = Dests ;
if ( n > 999 )
break ;
}
Dests + + ;
}
if ( n > 1 )
{
if ( Param = = ' C ' )
qsort ( List , n , sizeof ( void * ) , CompareNode ) ;
else
qsort ( List , n , sizeof ( void * ) , CompareAlias ) ;
}
Alias [ 6 ] = 0 ;
if ( Param = = ' T ' )
{
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , NodeHddr , " with traffic " ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <td>Call</td><td>Frames</td><td>RTT</td><td>BPQ?</td><td>Hops</td></tr><tr> " ) ;
}
else if ( Param = = ' C ' )
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , NodeHddr , " sorted by Call " ) ;
else
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , NodeHddr , " sorted by Alias " ) ;
for ( i = 0 ; i < n ; i + + )
{
int len = ConvFromAX25 ( List [ i ] - > DEST_CALL , Normcall ) ;
Normcall [ len ] = 0 ;
memcpy ( Alias , List [ i ] - > DEST_ALIAS , 6 ) ;
strlop ( Alias , ' ' ) ;
if ( Param = = ' T ' )
{
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <td>%s:%s</td><td align=center>%d</td><td align=center>%d</td><td align=center>%c</td><td align=center>%.0d</td></tr><tr> " ,
Normcall , Alias , List [ i ] - > DEST_COUNT , List [ i ] - > DEST_RTT / 16 ,
( List [ i ] - > DEST_STATE & 0x40 ) ? ' B ' : ' ' , ( List [ i ] - > DEST_STATE & 63 ) ) ;
}
else
{
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , NodeLine , Normcall , Alias , Normcall ) ;
if ( + + x = = Width )
{
x = 0 ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " </tr><tr> " ) ;
}
}
}
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " </tr> " ) ;
}
if ( _stricmp ( NodeURL , " /Node/NodeDetail " ) = = 0 )
{
UCHAR AXCall [ 8 ] ;
struct DEST_LIST * Dest = DESTS ;
struct NR_DEST_ROUTE_ENTRY * NRRoute ;
struct ROUTE * Neighbour ;
char Normcall [ 10 ] ;
int i , len , count , Active ;
char Alias [ 7 ] ;
Alias [ 6 ] = 0 ;
_strupr ( Context ) ;
ConvToAX25 ( Context , AXCall ) ;
for ( count = 0 ; count < MAXDESTS ; count + + )
{
if ( CompareCalls ( Dest - > DEST_CALL , AXCall ) )
{
break ;
}
Dest + + ;
}
if ( count = = MAXDESTS )
{
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <h3 align = center>Call %s not found</h3> " , Context ) ;
goto SendResp ;
}
memcpy ( Alias , Dest - > DEST_ALIAS , 6 ) ;
strlop ( Alias , ' ' ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] ,
" <h3 align=center>Info for Node %s:%s</h3><p style=font-family:monospace align=center> " , Alias , Context ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <table border=1 bgcolor=white><tr><td>Frames</td><td>RTT</td><td>BPQ?</td><td>Hops</td></tr> " ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <tr><td align=center>%d</td><td align=center>%d</td><td align=center>%c</td><td align=center>%.0d</td></tr></table> " ,
Dest - > DEST_COUNT , Dest - > DEST_RTT / 16 ,
( Dest - > DEST_STATE & 0x40 ) ? ' B ' : ' ' , ( Dest - > DEST_STATE & 63 ) ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <h3 align=center>Neighbours</h3> " ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] ,
" <table border=1 style=font-family:monospace align=center bgcolor=white> "
" <tr><td> </td><td> Qual </td><td> Obs </td><td> Port </td><td> Call </td></tr> " ) ;
NRRoute = & Dest - > NRROUTE [ 0 ] ;
Active = Dest - > DEST_ROUTE ;
for ( i = 1 ; i < 4 ; i + + )
{
Neighbour = NRRoute - > ROUT_NEIGHBOUR ;
if ( Neighbour )
{
len = ConvFromAX25 ( Neighbour - > NEIGHBOUR_CALL , Normcall ) ;
Normcall [ len ] = 0 ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " <tr><td>%c </td><td>%d</td><td>%d</td><td>%d</td><td>%s</td></tr> " ,
( Active = = i ) ? ' > ' : ' ' , NRRoute - > ROUT_QUALITY , NRRoute - > ROUT_OBSCOUNT , Neighbour - > NEIGHBOUR_PORT , Normcall ) ;
}
NRRoute + + ;
}
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " </table> " ) ;
goto SendResp ;
}
/*
MOV ESI , OFFSET32 NODEROUTEHDDR
MOV ECX , 11
REP MOVSB
LEA ESI , DEST_CALL [ EBX ]
CALL DECODENODENAME ; CONVERT TO ALIAS : CALL
REP MOVSB
CMP DEST_RTT [ EBX ] , 0
JE SHORT @ f ; TIMER NOT SET - DEST PROBABLY NOT USED
MOVSB ; ADD SPACE
CALL DORTT
@ @ :
MOV AL , CR
STOSB
MOV ECX , 3
MOV DH , DEST_ROUTE [ EBX ] ; CURRENT ACTIVE ROUTE
MOV DL , 1
push ebx
PUBLIC CMDN110
CMDN110 :
MOV ESI , ROUT1_NEIGHBOUR [ EBX ]
CMP ESI , 0
JE CMDN199
MOV AX , ' '
CMP DH , DL
JNE SHORT CMDN112 ; NOT CURRENT DEST
MOV AX , ' > '
CMDN112 :
STOSW
PUSH ECX
MOV AL , ROUT1_QUALITY [ EBX ]
CALL CONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS
mov AL , ' '
stosb
MOV AL , ROUT1_OBSCOUNT [ EBX ]
CALL CONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS
mov AL , ' '
stosb
MOV AL , NEIGHBOUR_PORT [ ESI ] ; GET PORT
CALL CONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS
mov AL , ' '
stosb
PUSH EDI
CALL CONVFROMAX25 ; CONVERT TO CALL
POP EDI
MOV ESI , OFFSET32 NORMCALL
REP MOVSB
MOV AL , CR
STOSB
ADD EBX , ROUTEVECLEN
INC DL ; ROUTE NUMBER
POP ECX
DEC ECX
JNZ CMDN110
PUBLIC CMDN199
CMDN199 :
POP EBX
; DISPLAY INP3 ROUTES
MOV ECX , 3
MOV DL , 4
PUBLIC CMDNINP3
CMDNINP3 :
MOV ESI , INPROUT1_NEIGHBOUR [ EBX ]
CMP ESI , 0
JE CMDNINPEND
MOV AX , ' '
CMP DH , DL
JNE SHORT @ F ; NOT CURRENT DEST
MOV AX , ' > '
@ @ :
STOSW
PUSH ECX
MOV AL , Hops1 [ EBX ]
CALL CONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS
mov AL , ' '
stosb
MOVZX EAX , SRTT1 [ EBX ]
MOV EDX , 0
MOV ECX , 100
DIV ECX
CALL CONV_5DIGITS
MOV AL , ' . '
STOSB
MOV EAX , EDX
CALL PRINTNUM
MOV AL , ' s '
STOSB
MOV AL , ' '
STOSB
MOV AL , NEIGHBOUR_PORT [ ESI ] ; GET PORT
CALL CONV_DIGITS ; CONVERT AL TO DECIMAL DIGITS
mov AL , ' '
stosb
PUSH EDI
CALL CONVFROMAX25 ; CONVERT TO CALL
POP EDI
MOV ESI , OFFSET32 NORMCALL
REP MOVSB
MOV AL , CR
STOSB
ADD EBX , INPROUTEVECLEN
INC DL ; ROUTE NUMBER
POP ECX
LOOP CMDNINP3
CMDNINPEND :
ret
*/
if ( _stricmp ( NodeURL , " /Node/Routes.html " ) = = 0 )
{
struct ROUTE * Routes = NEIGHBOURS ;
int MaxRoutes = MAXNEIGHBOURS ;
int count ;
char Normcall [ 10 ] ;
char locked ;
int NodeCount ;
int Percent = 0 ;
int Iframes , Retries ;
char Active [ 10 ] ;
int Queued ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " %s " , RouteHddr ) ;
for ( count = 0 ; count < MaxRoutes ; count + + )
{
if ( Routes - > NEIGHBOUR_CALL [ 0 ] ! = 0 )
{
int len = ConvFromAX25 ( Routes - > NEIGHBOUR_CALL , Normcall ) ;
Normcall [ len ] = 0 ;
if ( ( Routes - > NEIGHBOUR_FLAG & 1 ) = = 1 )
locked = ' ! ' ;
else
locked = ' ' ;
NodeCount = COUNTNODES ( Routes ) ;
if ( Routes - > NEIGHBOUR_LINK )
Queued = COUNT_AT_L2 ( Routes - > NEIGHBOUR_LINK ) ;
else
Queued = 0 ;
Iframes = Routes - > NBOUR_IFRAMES ;
Retries = Routes - > NBOUR_RETRIES ;
if ( Routes - > NEIGHBOUR_LINK & & Routes - > NEIGHBOUR_LINK - > L2STATE > = 5 )
strcpy ( Active , " > " ) ;
else
strcpy ( Active , " " ) ;
if ( Iframes )
Percent = ( Retries * 100 ) / Iframes ;
else
Percent = 0 ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , RouteLine , Active , Routes - > NEIGHBOUR_PORT , Normcall , locked ,
Routes - > NEIGHBOUR_QUAL , NodeCount , Iframes , Retries , Percent , Routes - > NBOUR_MAXFRAME , Routes - > NBOUR_FRACK ,
Routes - > NEIGHBOUR_TIME > > 8 , Routes - > NEIGHBOUR_TIME & 0xff , Queued , Routes - > OtherendsRouteQual ) ;
}
Routes + = 1 ;
}
}
if ( _stricmp ( NodeURL , " /Node/Links.html " ) = = 0 )
{
struct _LINKTABLE * Links = LINKS ;
int MaxLinks = MAXLINKS ;
int count ;
char Normcall1 [ 10 ] ;
char Normcall2 [ 10 ] ;
char State [ 12 ] = " " , Type [ 12 ] = " Uplink " ;
int axState ;
int cctType ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " %s " , LinkHddr ) ;
for ( count = 0 ; count < MaxLinks ; count + + )
{
if ( Links - > LINKCALL [ 0 ] ! = 0 )
{
int len = ConvFromAX25 ( Links - > LINKCALL , Normcall1 ) ;
Normcall1 [ len ] = 0 ;
len = ConvFromAX25 ( Links - > OURCALL , Normcall2 ) ;
Normcall2 [ len ] = 0 ;
axState = Links - > L2STATE ;
if ( axState = = 2 )
strcpy ( State , " Connecting " ) ;
else if ( axState = = 3 )
strcpy ( State , " FRMR " ) ;
else if ( axState = = 4 )
strcpy ( State , " Closing " ) ;
else if ( axState = = 5 )
strcpy ( State , " Active " ) ;
else if ( axState = = 6 )
strcpy ( State , " REJ Sent " ) ;
cctType = Links - > LINKTYPE ;
if ( cctType = = 1 )
strcpy ( Type , " Uplink " ) ;
else if ( cctType = = 2 )
strcpy ( Type , " Downlink " ) ;
else if ( cctType = = 3 )
strcpy ( Type , " Node-Node " ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , LinkLine , Normcall1 , Normcall2 , Links - > LINKPORT - > PORTNUMBER ,
State , Type , 2 - Links - > VER1FLAG ) ;
Links + = 1 ;
}
}
}
if ( _stricmp ( NodeURL , " /Node/Users.html " ) = = 0 )
{
TRANSPORTENTRY * L4 = L4TABLE ;
TRANSPORTENTRY * Partner ;
int MaxLinks = MAXLINKS ;
int count ;
char State [ 12 ] = " " , Type [ 12 ] = " Uplink " ;
char LHS [ 50 ] = " " , MID [ 10 ] = " " , RHS [ 50 ] = " " ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " %s " , UserHddr ) ;
for ( count = 0 ; count < MAXCIRCUITS ; count + + )
{
if ( L4 - > L4USER [ 0 ] )
{
RHS [ 0 ] = MID [ 0 ] = 0 ;
if ( ( L4 - > L4CIRCUITTYPE & UPLINK ) = = 0 ) //SHORT CMDS10A ; YES
{
// IF DOWNLINK, ONLY DISPLAY IF NO CROSSLINK
if ( L4 - > L4CROSSLINK = = 0 ) //jne CMDS60 ; WILL PROCESS FROM OTHER END
{
// ITS A DOWNLINK WITH NO PARTNER - MUST BE A CLOSING SESSION
// DISPLAY TO THE RIGHT FOR NOW
strcpy ( LHS , " (Closing) " ) ;
DISPLAYCIRCUIT ( L4 , RHS ) ;
goto CMDS50 ;
}
else
goto CMDS60 ; // WILL PROCESS FROM OTHER END
}
if ( L4 - > L4CROSSLINK = = 0 )
{
// Single Entry
DISPLAYCIRCUIT ( L4 , LHS ) ;
}
else
{
DISPLAYCIRCUIT ( L4 , LHS ) ;
Partner = L4 - > L4CROSSLINK ;
if ( Partner - > L4STATE = = 5 )
strcpy ( MID , " <--> " ) ;
else
strcpy ( MID , " <~~> " ) ;
DISPLAYCIRCUIT ( Partner , RHS ) ;
}
CMDS50 :
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , UserLine , LHS , MID , RHS ) ;
}
CMDS60 :
L4 + + ;
}
}
/*
PUBLIC CMDUXX_1
CMDUXX_1 :
push EBX
push ESI
PUSH ECX
push EDI
call _FINDDESTINATION
pop EDI
jz SHORT NODE_FOUND
push EDI ; NET / ROM not found
call CONVFROMAX25 ; CONVERT TO CALL
pop EDI
mov ESI , OFFSET32 NORMCALL
rep movsb
jmp SHORT END_CMDUXX
PUBLIC NODE_FOUND
NODE_FOUND :
lea ESI , DEST_CALL [ EBX ]
call DECODENODENAME
REP MOVSB
PUBLIC END_CMDUXX
END_CMDUXX :
POP ECX
pop ESI
pop EBX
ret
} } }
*/
else if ( _stricmp ( NodeURL , " /Node/Terminal.html " ) = = 0 )
{
if ( COOKIE & & Session )
{
// Already signed in as sysop
struct UserRec * USER = Session - > USER ;
struct HTTPConnectionInfo * NewSession = AllocateSession ( sock , ' T ' ) ;
if ( NewSession )
{
char AXCall [ 10 ] ;
ReplyLen = sprintf ( _REPLYBUFFER , TermPage , Mycall , Mycall , NewSession - > Key , NewSession - > Key , NewSession - > Key ) ;
strcpy ( NewSession - > HTTPCall , USER - > Callsign ) ;
ConvToAX25 ( NewSession - > HTTPCall , AXCall ) ;
ChangeSessionCallsign ( NewSession - > Stream , AXCall ) ;
BPQHOSTVECTOR [ NewSession - > Stream - 1 ] . HOSTSESSION - > Secure_Session = USER - > Secure ;
Session - > USER = USER ;
NewSession - > TNC = conn - > TNC ;
// if (Appl[0])
// {
// strcat(Appl, "\r");
// SendMsg(Session->Stream, Appl, strlen(Appl));
// }
}
else
{
ReplyLen = SetupNodeMenu ( _REPLYBUFFER , LOCAL ) ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " %s " , BusyError ) ;
}
}
else if ( LOCAL )
{
// connected to 127.0.0.1 so sign in using node call
struct HTTPConnectionInfo * NewSession = AllocateSession ( sock , ' T ' ) ;
if ( NewSession )
{
ReplyLen = sprintf ( _REPLYBUFFER , TermPage , Mycall , Mycall , NewSession - > Key , NewSession - > Key , NewSession - > Key ) ;
strcpy ( NewSession - > HTTPCall , MYNODECALL ) ;
ChangeSessionCallsign ( NewSession - > Stream , MYCALL ) ;
BPQHOSTVECTOR [ NewSession - > Stream - 1 ] . HOSTSESSION - > Secure_Session = TRUE ;
NewSession - > TNC = conn - > TNC ;
}
}
else
ReplyLen = sprintf ( _REPLYBUFFER , TermSignon , Mycall , Mycall , Context ) ;
}
else if ( _stricmp ( NodeURL , " /Node/Signon.html " ) = = 0 )
{
ReplyLen = sprintf ( _REPLYBUFFER , NodeSignon , Mycall , Mycall , Context ) ;
}
else if ( _stricmp ( NodeURL , " /Node/Drivers " ) = = 0 )
{
int Bufferlen = SendMessageFile ( sock , " /Drivers.htm " , TRUE , allowDeflate ) ; // return -1 if not found
if ( Bufferlen ! = - 1 )
return 0 ; // We've sent it
}
else if ( _stricmp ( NodeURL , " /Node/OutputScreen.html " ) = = 0 )
{
struct HTTPConnectionInfo * Session = FindSession ( Context ) ;
if ( Session = = NULL )
{
ReplyLen = sprintf ( _REPLYBUFFER , " %s " , LostSession ) ;
}
else
{
Session - > sock = sock ; // socket to reply on
ReplyLen = RefreshTermWindow ( TCP , Session , _REPLYBUFFER ) ;
if ( ReplyLen = = 0 ) // Nothing new
{
// Debugprintf("GET with no data avail - response held");
Session - > ResponseTimer = 1200 ; // Delay response for up to a minute
}
else
{
// Debugprintf("GET - outpur sent, timer was %d, set to zero", Session->ResponseTimer);
Session - > ResponseTimer = 0 ;
}
Session - > KillTimer = 0 ;
return 0 ; // Refresh has sent any available output
}
}
else if ( _stricmp ( NodeURL , " /Node/InputLine.html " ) = = 0 )
{
struct TNCINFO * TNC = conn - > TNC ;
struct TCPINFO * TCP = 0 ;
if ( TNC )
TCP = TNC - > TCPInfo ;
if ( TCP & & TCP - > WebTermCSS )
ReplyLen = sprintf ( _REPLYBUFFER , InputLine , Context , TCP - > WebTermCSS ) ;
else
ReplyLen = sprintf ( _REPLYBUFFER , InputLine , Context , " " ) ;
}
else if ( _stricmp ( NodeURL , " /Node/PTT " ) = = 0 )
{
struct TNCINFO * TNC = conn - > TNC ;
int x = atoi ( Context ) ;
}
SendResp :
FormatTime3 ( TimeString , time ( NULL ) ) ;
strcpy ( & _REPLYBUFFER [ ReplyLen ] , Tail ) ;
ReplyLen + = ( int ) strlen ( Tail ) ;
if ( allowDeflate )
{
Compressed = Compressit ( _REPLYBUFFER , ReplyLen , & ReplyLen ) ;
}
else
{
Encoding [ 0 ] = 0 ;
Compressed = _REPLYBUFFER ;
}
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n "
" Date: %s \r \n %s \r \n " , ReplyLen , TimeString , Encoding ) ;
sendandcheck ( sock , Header , HeaderLen ) ;
sendandcheck ( sock , Compressed , ReplyLen ) ;
if ( allowDeflate )
free ( Compressed ) ;
}
return 0 ;
2023-12-28 10:31:09 +00:00
# ifdef WIN32xx
2022-08-28 09:35:46 +01:00
}
# include "StdExcept.c"
}
return 0 ;
# endif
}
void ProcessHTTPMessage ( void * conn )
{
// conn is a malloc'ed copy to handle reused connections, so need to free it
InnerProcessHTTPMessage ( ( struct ConnectionInfo * ) conn ) ;
free ( conn ) ;
return ;
}
static char * month [ ] = { " Jan " , " Feb " , " Mar " , " Apr " , " May " , " Jun " , " Jul " , " Aug " , " Sep " , " Oct " , " Nov " , " Dec " } ;
static char * dat [ ] = { " Sun " , " Mon " , " Tue " , " Wed " , " Thu " , " Fri " , " Sat " } ;
VOID FormatTime3 ( char * Time , time_t cTime )
{
struct tm * TM ;
TM = gmtime ( & cTime ) ;
sprintf ( Time , " %s, %02d %s %3d %02d:%02d:%02d GMT " , dat [ TM - > tm_wday ] , TM - > tm_mday , month [ TM - > tm_mon ] ,
TM - > tm_year + 1900 , TM - > tm_hour , TM - > tm_min , TM - > tm_sec ) ;
}
// Sun, 06 Nov 1994 08:49:37 GMT
int StatusProc ( char * Buff )
{
int i ;
char callsign [ 12 ] = " " ;
char flag [ 3 ] ;
UINT Mask , MaskCopy ;
int Flags ;
int AppNumber ;
int OneBits ;
int Len = sprintf ( Buff , " <html><meta http-equiv=expires content=0><meta http-equiv=refresh content=15> "
" <head><title>Stream Status</title></head><body> " ) ;
Len + = sprintf ( & Buff [ Len ] , " <table style= \" text-align: left; font-family: monospace; align=center \" border=1 cellpadding=1 cellspacing=0> " ) ;
Len + = sprintf ( & Buff [ Len ] , " <tr><th> </th><th> RX </th><th> TX </th> " ) ;
Len + = sprintf ( & Buff [ Len ] , " <th> MON </th><th> App </th><th> Flg </th> " ) ;
Len + = sprintf ( & Buff [ Len ] , " <th>Callsign </th><th width=200px>Program</th> " ) ;
Len + = sprintf ( & Buff [ Len ] , " <th> </th><th> RX </th><th> TX </th> " ) ;
Len + = sprintf ( & Buff [ Len ] , " <th> MON </th><th> App </th><th> Flg </th> " ) ;
Len + = sprintf ( & Buff [ Len ] , " <th>Callsign </th><th width=200px>Program</th></tr><tr> " ) ;
for ( i = 1 ; i < 65 ; i + + )
{
callsign [ 0 ] = 0 ;
if ( GetAllocationState ( i ) )
strcpy ( flag , " * " ) ;
else
strcpy ( flag , " " ) ;
GetCallsign ( i , callsign ) ;
Mask = MaskCopy = Get_APPLMASK ( i ) ;
// if only one bit set, convert to number
AppNumber = 0 ;
OneBits = 0 ;
while ( MaskCopy )
{
if ( MaskCopy & 1 )
OneBits + + ;
AppNumber + + ;
MaskCopy = MaskCopy > > 1 ;
}
Flags = GetApplFlags ( i ) ;
if ( OneBits > 1 )
Len + = sprintf ( & Buff [ Len ] , " <td>%d%s</td><td>%d</td><td>%d</td><td>%d</td><td>%x</td> "
" <td>%x</td><td>%s</td><td>%s</td> " ,
i , flag , RXCount ( i ) , TXCount ( i ) , MONCount ( i ) , Mask , Flags , callsign , BPQHOSTVECTOR [ i - 1 ] . PgmName ) ;
else
Len + = sprintf ( & Buff [ Len ] , " <td>%d%s</td><td>%d</td><td>%d</td><td>%d</td><td>%d</td> "
" <td>%x</td><td>%s</td><td>%s</td> " ,
i , flag , RXCount ( i ) , TXCount ( i ) , MONCount ( i ) , AppNumber , Flags , callsign , BPQHOSTVECTOR [ i - 1 ] . PgmName ) ;
if ( ( i & 1 ) = = 0 )
Len + = sprintf ( & Buff [ Len ] , " </tr><tr> " ) ;
}
Len + = sprintf ( & Buff [ Len ] , " </tr></table> " ) ;
return Len ;
}
int ProcessNodeSignon ( SOCKET sock , struct TCPINFO * TCP , char * MsgPtr , char * Appl , char * Reply , struct HTTPConnectionInfo * * Session , int LOCAL )
{
int ReplyLen = 0 ;
char * input = strstr ( MsgPtr , " \r \n \r \n " ) ; // End of headers
char * user , * password , * Key ;
char Header [ 256 ] ;
int HeaderLen ;
struct HTTPConnectionInfo * Sess ;
if ( input )
{
int i ;
struct UserRec * USER ;
UndoTransparency ( input ) ;
if ( strstr ( input , " Cancel=Cancel " ) )
{
ReplyLen = SetupNodeMenu ( Reply , LOCAL ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n "
" \r \n " , ( int ) ( ReplyLen + strlen ( Tail ) ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , Reply , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
}
user = strtok_s ( & input [ 9 ] , " & " , & Key ) ;
password = strtok_s ( NULL , " = " , & Key ) ;
password = Key ;
for ( i = 0 ; i < TCP - > NumberofUsers ; i + + )
{
USER = TCP - > UserRecPtr [ i ] ;
if ( user & & _stricmp ( user , USER - > UserName ) = = 0 )
{
if ( strcmp ( password , USER - > Password ) = = 0 & & USER - > Secure )
{
// ok
Sess = * Session = AllocateSession ( sock , ' N ' ) ;
Sess - > USER = USER ;
ReplyLen = SetupNodeMenu ( Reply , LOCAL ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n "
" Set-Cookie: BPQSessionCookie=%s; Path = / \r \n \r \n " , ( int ) ( ReplyLen + strlen ( Tail ) ) , Sess - > Key ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , Reply , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
return ReplyLen ;
}
}
}
}
ReplyLen = sprintf ( Reply , NodeSignon , Mycall , Mycall ) ;
ReplyLen + = sprintf ( & Reply [ ReplyLen ] , " %s " , PassError ) ;
HeaderLen = sprintf ( Header , " HTTP/1.1 200 OK \r \n Content-Length: %d \r \n Content-Type: text/html \r \n \r \n " , ( int ) ( ReplyLen + strlen ( Tail ) ) ) ;
send ( sock , Header , HeaderLen , 0 ) ;
send ( sock , Reply , ReplyLen , 0 ) ;
send ( sock , Tail , ( int ) strlen ( Tail ) , 0 ) ;
return 0 ;
return ReplyLen ;
}
2024-11-05 21:03:15 +00:00
int ProcessMailAPISignon ( struct TCPINFO * TCP , char * MsgPtr , char * Appl , char * Reply , struct HTTPConnectionInfo * * Session , BOOL WebMail , int LOCAL )
{
int ReplyLen = 0 ;
char * input = strstr ( MsgPtr , " \r \n \r \n " ) ; // End of headers
char * user , * password , * Key ;
struct HTTPConnectionInfo * NewSession ;
int i ;
struct UserRec * USER ;
if ( strchr ( MsgPtr , ' ? ' ) )
{
// Check Password
user = strlop ( MsgPtr , ' ? ' ) ;
password = strlop ( user , ' & ' ) ;
strlop ( password , ' ' ) ;
for ( i = 0 ; i < TCP - > NumberofUsers ; i + + )
{
USER = TCP - > UserRecPtr [ i ] ;
if ( user & & _stricmp ( user , USER - > UserName ) = = 0 )
{
if ( ( strcmp ( password , USER - > Password ) = = 0 ) & & ( USER - > Secure | | WebMail ) )
{
// ok
NewSession = AllocateSession ( Appl [ 0 ] , ' M ' ) ;
* Session = NewSession ;
if ( NewSession )
{
ReplyLen = 0 ;
strcpy ( NewSession - > Callsign , USER - > Callsign ) ;
}
else
{
ReplyLen = SetupNodeMenu ( Reply , LOCAL ) ;
ReplyLen + = sprintf ( & Reply [ ReplyLen ] , " %s " , BusyError ) ;
}
return ReplyLen ;
}
}
}
// Pass failed attempt to BBS code so it can try a bbs user login
// Need to put url back together
if ( user & & user [ 0 ] & & password & & password [ 0 ] )
{
sprintf ( MsgPtr , " %s?%s&%s " , MsgPtr , user , password ) ;
}
}
NewSession = AllocateSession ( Appl [ 0 ] , ' M ' ) ;
* Session = NewSession ;
if ( NewSession )
ReplyLen = 0 ;
else
{
ReplyLen = SetupNodeMenu ( Reply , LOCAL ) ;
ReplyLen + = sprintf ( & Reply [ ReplyLen ] , " %s " , BusyError ) ;
}
return ReplyLen ;
}
2022-08-28 09:35:46 +01:00
int ProcessMailSignon ( struct TCPINFO * TCP , char * MsgPtr , char * Appl , char * Reply , struct HTTPConnectionInfo * * Session , BOOL WebMail , int LOCAL )
{
int ReplyLen = 0 ;
char * input = strstr ( MsgPtr , " \r \n \r \n " ) ; // End of headers
char * user , * password , * Key ;
struct HTTPConnectionInfo * NewSession ;
if ( input )
{
int i ;
struct UserRec * USER ;
UndoTransparency ( input ) ;
if ( strstr ( input , " Cancel=Cancel " ) )
{
ReplyLen = SetupNodeMenu ( Reply , LOCAL ) ;
return ReplyLen ;
}
user = strtok_s ( & input [ 9 ] , " & " , & Key ) ;
password = strtok_s ( NULL , " = " , & Key ) ;
password = Key ;
for ( i = 0 ; i < TCP - > NumberofUsers ; i + + )
{
USER = TCP - > UserRecPtr [ i ] ;
if ( user & & _stricmp ( user , USER - > UserName ) = = 0 )
{
if ( strcmp ( password , USER - > Password ) = = 0 & & ( USER - > Secure | | WebMail ) )
{
// ok
NewSession = AllocateSession ( Appl [ 0 ] , ' M ' ) ;
* Session = NewSession ;
if ( NewSession )
{
ReplyLen = 0 ;
strcpy ( NewSession - > Callsign , USER - > Callsign ) ;
}
else
{
ReplyLen = SetupNodeMenu ( Reply , LOCAL ) ;
ReplyLen + = sprintf ( & Reply [ ReplyLen ] , " %s " , BusyError ) ;
}
return ReplyLen ;
}
}
}
}
ReplyLen = sprintf ( Reply , MailSignon , Mycall , Mycall ) ;
ReplyLen + = sprintf ( & Reply [ ReplyLen ] , " %s " , PassError ) ;
return ReplyLen ;
}
int ProcessChatSignon ( struct TCPINFO * TCP , char * MsgPtr , char * Appl , char * Reply , struct HTTPConnectionInfo * * Session , int LOCAL )
{
int ReplyLen = 0 ;
char * input = strstr ( MsgPtr , " \r \n \r \n " ) ; // End of headers
char * user , * password , * Key ;
if ( input )
{
int i ;
struct UserRec * USER ;
UndoTransparency ( input ) ;
if ( strstr ( input , " Cancel=Cancel " ) )
{
ReplyLen = SetupNodeMenu ( Reply , LOCAL ) ;
return ReplyLen ;
}
user = strtok_s ( & input [ 9 ] , " & " , & Key ) ;
password = strtok_s ( NULL , " = " , & Key ) ;
password = Key ;
for ( i = 0 ; i < TCP - > NumberofUsers ; i + + )
{
USER = TCP - > UserRecPtr [ i ] ;
if ( user & & _stricmp ( user , USER - > UserName ) = = 0 )
{
if ( strcmp ( password , USER - > Password ) = = 0 & & USER - > Secure )
{
// ok
* Session = AllocateSession ( Appl [ 0 ] , ' C ' ) ;
if ( Session )
{
ReplyLen = 0 ;
}
else
{
ReplyLen = SetupNodeMenu ( Reply , LOCAL ) ;
ReplyLen + = sprintf ( & Reply [ ReplyLen ] , " %s " , BusyError ) ;
}
return ReplyLen ;
}
}
}
}
ReplyLen = sprintf ( Reply , ChatSignon , Mycall , Mycall ) ;
ReplyLen + = sprintf ( & Reply [ ReplyLen ] , " %s " , PassError ) ;
return ReplyLen ;
}
# define SHA1_HASH_LEN 20
2023-03-16 06:52:27 +00:00
/*
Copyright ( C ) 1998 , 2009
Paul E . Jones < paulej @ packetizer . com >
Freeware Public License ( FPL )
This software is licensed as " freeware. " Permission to distribute
this software in source and binary forms , including incorporation
into other products , is hereby granted without a fee . THIS SOFTWARE
IS PROVIDED ' AS IS ' AND WITHOUT ANY EXPRESSED OR IMPLIED WARRANTIES ,
INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE . THE AUTHOR SHALL NOT BE HELD
LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE , EITHER
DIRECTLY OR INDIRECTLY , INCLUDING , BUT NOT LIMITED TO , LOSS OF DATA
OR DATA BEING RENDERED INACCURATE .
*/
/* sha1.h
*
* Copyright ( C ) 1998 , 2009
* Paul E . Jones < paulej @ packetizer . com >
* All Rights Reserved
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* $ Id : sha1 . h 12 2009 - 06 - 22 19 : 34 : 25 Z paulej $
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Description :
* This class implements the Secure Hashing Standard as defined
* in FIPS PUB 180 - 1 published April 17 , 1995.
*
* Many of the variable names in the SHA1Context , especially the
* single character names , were used because those were the names
* used in the publication .
*
* Please read the file sha1 . c for more information .
*
*/
# ifndef _SHA1_H_
# define _SHA1_H_
/*
* This structure will hold context information for the hashing
* operation
*/
typedef struct SHA1Context
{
unsigned Message_Digest [ 5 ] ; /* Message Digest (output) */
unsigned Length_Low ; /* Message length in bits */
unsigned Length_High ; /* Message length in bits */
unsigned char Message_Block [ 64 ] ; /* 512-bit message blocks */
int Message_Block_Index ; /* Index into message block array */
int Computed ; /* Is the digest computed? */
int Corrupted ; /* Is the message digest corruped? */
} SHA1Context ;
/*
* Function Prototypes
*/
void SHA1Reset ( SHA1Context * ) ;
int SHA1Result ( SHA1Context * ) ;
void SHA1Input ( SHA1Context * , const unsigned char * , unsigned ) ;
# endif
2022-08-28 09:35:46 +01:00
BOOL SHA1PasswordHash ( char * lpszPassword , char * Hash )
{
2023-03-16 06:52:27 +00:00
SHA1Context sha ;
int i ;
2022-08-28 09:35:46 +01:00
2023-03-16 06:52:27 +00:00
SHA1Reset ( & sha ) ;
SHA1Input ( & sha , lpszPassword , strlen ( lpszPassword ) ) ;
SHA1Result ( & sha ) ;
2022-08-28 09:35:46 +01:00
2023-03-16 06:52:27 +00:00
// swap byte order if little endian
for ( i = 0 ; i < 5 ; i + + )
sha . Message_Digest [ i ] = htonl ( sha . Message_Digest [ i ] ) ;
2022-08-28 09:35:46 +01:00
2023-03-16 06:52:27 +00:00
memcpy ( Hash , & sha . Message_Digest [ 0 ] , 20 ) ;
return TRUE ;
2022-08-28 09:35:46 +01:00
}
int BuildRigCtlPage ( char * _REPLYBUFFER )
{
int ReplyLen ;
struct RIGPORTINFO * PORT ;
struct RIGINFO * RIG ;
int p , i ;
char Page [ ] =
" <html><meta http-equiv=expires content=0> \r \n "
// "<meta http-equiv=refresh content=5>\r\n"
" <head><title>Rigcontrol</title></head> \r \n "
" <style type=text/css>form{margin:0px; padding:0px; display:inline;}</style> "
" <body height: 580px;><h3>Rigcontrol</h3> \r \n "
" <table style= \" text-align: left; width: 580px; font-family: monospace; align=center \" border=1 cellpadding=2 cellspacing=2><tr> \r \n "
" <th width=90px>Radio</th> \r \n "
" <th width=90px>Freq</th> \r \n "
" <th width=90px>Mode</th> \r \n "
" <th>ST</th> \r \n "
" <th>Ports</th> \r \n "
" <th hidden width=10px>Action</th> \r \n "
" </tr> " ;
char RigLine [ ] =
" <tr> \r \n "
" <td>%s</td> \r \n "
" <td>%s</td> \r \n "
" <td>%s/1</td> \r \n "
" <td>%c%c</td> \r \n "
" <td>%s</td> \r \n "
" <td hidden width=10px><input onclick=PTT('R%d') type=submit class='btn' value='PTT'></td> \r \n "
" </tr> \r \n " ;
char Tail [ ] =
" </table> \r \n "
" </body></html> \r \n " ;
ReplyLen = sprintf ( _REPLYBUFFER , " %s " , Page ) ;
for ( p = 0 ; p < NumberofPorts ; p + + )
{
PORT = PORTInfo [ p ] ;
for ( i = 0 ; i < PORT - > ConfiguredRigs ; i + + )
{
RIG = & PORT - > Rigs [ i ] ;
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , RigLine , RIG - > WEB_Label , RIG - > WEB_FREQ , RIG - > WEB_MODE , RIG - > WEB_SCAN , RIG - > WEB_PTT , RIG - > WEB_PORTS , RIG - > Interlock ) ;
}
}
ReplyLen + = sprintf ( & _REPLYBUFFER [ ReplyLen ] , " %s " , Tail ) ;
return ReplyLen ;
}
void SendRigWebPage ( )
{
2022-10-03 15:55:07 +01:00
int i , n ;
2022-08-28 09:35:46 +01:00
struct ConnectionInfo * sockptr ;
struct TNCINFO * TNC ;
struct TCPINFO * TCP ;
2022-10-03 15:55:07 +01:00
for ( i = 0 ; i < 33 ; i + + )
2022-08-28 09:35:46 +01:00
{
2022-10-03 15:55:07 +01:00
TNC = TNCInfo [ i ] ;
2022-08-28 09:35:46 +01:00
if ( TNC & & TNC - > Hardware = = H_TELNET )
{
TCP = TNC - > TCPInfo ;
if ( TCP )
{
for ( n = 0 ; n < = TCP - > MaxSessions ; n + + )
{
sockptr = TNC - > Streams [ n ] . ConnectionInfo ;
if ( sockptr - > SocketActive )
{
if ( sockptr - > HTTPMode & & sockptr - > WebSocks & & strcmp ( sockptr - > WebURL , " RIGCTL " ) = = 0 )
{
char RigMsg [ 8192 ] ;
int RigMsgLen = strlen ( RigWebPage ) ;
char * ptr ;
RigMsg [ 0 ] = 0x81 ; // Fin, Data
RigMsg [ 1 ] = 126 ; // Unmasked, Extended Len
RigMsg [ 2 ] = RigMsgLen > > 8 ;
RigMsg [ 3 ] = RigMsgLen & 0xff ;
strcpy ( & RigMsg [ 4 ] , RigWebPage ) ;
// If secure session enable PTT button
if ( sockptr - > WebSecure )
{
while ( ptr = strstr ( RigMsg , " hidden " ) )
memcpy ( ptr , " " , 6 ) ;
}
send ( sockptr - > socket , RigMsg , RigMsgLen + 4 , 0 ) ;
}
}
}
}
}
}
}
2022-11-12 15:00:02 +00:00
// Webmail web socket code
int ProcessWebmailWebSock ( char * MsgPtr , char * OutBuffer ) ;
void ProcessWebmailWebSockThread ( void * conn )
{
// conn is a malloc'ed copy to handle reused connections, so need to free it
struct ConnectionInfo * sockptr = ( struct ConnectionInfo * ) conn ;
char * URL = sockptr - > WebURL ;
int Loops = 0 ;
int Sent ;
struct HTTPConnectionInfo Dummy = { 0 } ;
int ReplyLen = 0 ;
2023-03-16 06:52:27 +00:00
int InputLen = 0 ;
2022-11-12 15:00:02 +00:00
# ifdef LINBPQ
char _REPLYBUFFER [ 250000 ] ;
ReplyLen = ProcessWebmailWebSock ( URL , _REPLYBUFFER ) ;
// Send may block
Sent = send ( sockptr - > socket , _REPLYBUFFER , ReplyLen , 0 ) ;
while ( Sent ! = ReplyLen & & Loops + + < 3000 ) // 100 secs max
{
if ( Sent > 0 ) // something sent
{
2023-03-02 09:33:47 +00:00
ReplyLen - = Sent ;
2022-11-12 15:00:02 +00:00
memmove ( _REPLYBUFFER , & _REPLYBUFFER [ Sent ] , ReplyLen ) ;
}
Sleep ( 30 ) ;
Sent = send ( sockptr - > socket , _REPLYBUFFER , ReplyLen , 0 ) ;
}
# else
// Send URL to BPQMail via Pipe. Just need a dummy session, as URL contains session key
HANDLE hPipe ;
char Reply [ 250000 ] ;
hPipe = CreateFile ( MAILPipeFileName , GENERIC_READ | GENERIC_WRITE ,
0 , // exclusive access
NULL , // no security attrs
OPEN_EXISTING ,
FILE_ATTRIBUTE_NORMAL ,
NULL ) ;
if ( hPipe = = ( HANDLE ) - 1 )
{
free ( conn ) ;
return ;
}
WriteFile ( hPipe , & Dummy , sizeof ( struct HTTPConnectionInfo ) , & InputLen , NULL ) ;
WriteFile ( hPipe , URL , strlen ( URL ) , & InputLen , NULL ) ;
ReadFile ( hPipe , & Dummy , sizeof ( struct HTTPConnectionInfo ) , & InputLen , NULL ) ;
ReadFile ( hPipe , Reply , 250000 , & ReplyLen , NULL ) ;
if ( ReplyLen < = 0 )
{
InputLen = GetLastError ( ) ;
}
CloseHandle ( hPipe ) ;
// ?? do we need a thread to handle write which may block
Sent = send ( sockptr - > socket , Reply , ReplyLen , 0 ) ;
while ( Sent ! = ReplyLen & & Loops + + < 3000 ) // 100 secs max
{
// Debugprintf("%d out of %d sent %d Loops", Sent, InputLen, Loops);
if ( Sent > 0 ) // something sent
{
InputLen - = Sent ;
memmove ( Reply , & Reply [ Sent ] , ReplyLen ) ;
}
Sleep ( 30 ) ;
Sent = send ( sockptr - > socket , Reply , ReplyLen , 0 ) ;
}
# endif
free ( conn ) ;
return ;
}
2023-03-16 06:52:27 +00:00
/*
* sha1 . c
*
* Copyright ( C ) 1998 , 2009
* Paul E . Jones < paulej @ packetizer . com >
* All Rights Reserved
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* $ Id : sha1 . c 12 2009 - 06 - 22 19 : 34 : 25 Z paulej $
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Description :
* This file implements the Secure Hashing Standard as defined
* in FIPS PUB 180 - 1 published April 17 , 1995.
*
* The Secure Hashing Standard , which uses the Secure Hashing
* Algorithm ( SHA ) , produces a 160 - bit message digest for a
* given data stream . In theory , it is highly improbable that
* two messages will produce the same message digest . Therefore ,
* this algorithm can serve as a means of providing a " fingerprint "
* for a message .
*
* Portability Issues :
* SHA - 1 is defined in terms of 32 - bit " words " . This code was
* written with the expectation that the processor has at least
* a 32 - bit machine word size . If the machine word size is larger ,
* the code should still function properly . One caveat to that
* is that the input functions taking characters and character
* arrays assume that only 8 bits of information are stored in each
* character .
*
* Caveats :
* SHA - 1 is designed to work with messages less than 2 ^ 64 bits
* long . Although SHA - 1 allows a message digest to be generated for
* messages of any number of bits less than 2 ^ 64 , this
* implementation only works with messages with a length that is a
* multiple of the size of an 8 - bit character .
*
*/
/*
* Define the circular shift macro
*/
# define SHA1CircularShift(bits,word) \
( ( ( ( word ) < < ( bits ) ) & 0xFFFFFFFF ) | \
( ( word ) > > ( 32 - ( bits ) ) ) )
/* Function prototypes */
void SHA1ProcessMessageBlock ( SHA1Context * ) ;
void SHA1PadMessage ( SHA1Context * ) ;
/*
* SHA1Reset
*
* Description :
* This function will initialize the SHA1Context in preparation
* for computing a new message digest .
*
* Parameters :
* context : [ in / out ]
* The context to reset .
*
* Returns :
* Nothing .
*
* Comments :
*
*/
void SHA1Reset ( SHA1Context * context )
{
context - > Length_Low = 0 ;
context - > Length_High = 0 ;
context - > Message_Block_Index = 0 ;
context - > Message_Digest [ 0 ] = 0x67452301 ;
context - > Message_Digest [ 1 ] = 0xEFCDAB89 ;
context - > Message_Digest [ 2 ] = 0x98BADCFE ;
context - > Message_Digest [ 3 ] = 0x10325476 ;
context - > Message_Digest [ 4 ] = 0xC3D2E1F0 ;
context - > Computed = 0 ;
context - > Corrupted = 0 ;
}
/*
* SHA1Result
*
* Description :
* This function will return the 160 - bit message digest into the
* Message_Digest array within the SHA1Context provided
*
* Parameters :
* context : [ in / out ]
* The context to use to calculate the SHA - 1 hash .
*
* Returns :
* 1 if successful , 0 if it failed .
*
* Comments :
*
*/
int SHA1Result ( SHA1Context * context )
{
if ( context - > Corrupted )
{
return 0 ;
}
if ( ! context - > Computed )
{
SHA1PadMessage ( context ) ;
context - > Computed = 1 ;
}
return 1 ;
}
/*
* SHA1Input
*
* Description :
* This function accepts an array of octets as the next portion of
* the message .
*
* Parameters :
* context : [ in / out ]
* The SHA - 1 context to update
* message_array : [ in ]
* An array of characters representing the next portion of the
* message .
* length : [ in ]
* The length of the message in message_array
*
* Returns :
* Nothing .
*
* Comments :
*
*/
void SHA1Input ( SHA1Context * context ,
const unsigned char * message_array ,
unsigned length )
{
if ( ! length )
{
return ;
}
if ( context - > Computed | | context - > Corrupted )
{
context - > Corrupted = 1 ;
return ;
}
while ( length - - & & ! context - > Corrupted )
{
context - > Message_Block [ context - > Message_Block_Index + + ] =
( * message_array & 0xFF ) ;
context - > Length_Low + = 8 ;
/* Force it to 32 bits */
context - > Length_Low & = 0xFFFFFFFF ;
if ( context - > Length_Low = = 0 )
{
context - > Length_High + + ;
/* Force it to 32 bits */
context - > Length_High & = 0xFFFFFFFF ;
if ( context - > Length_High = = 0 )
{
/* Message is too long */
context - > Corrupted = 1 ;
}
}
if ( context - > Message_Block_Index = = 64 )
{
SHA1ProcessMessageBlock ( context ) ;
}
message_array + + ;
}
}
/*
* SHA1ProcessMessageBlock
*
* Description :
* This function will process the next 512 bits of the message
* stored in the Message_Block array .
*
* Parameters :
* None .
*
* Returns :
* Nothing .
*
* Comments :
* Many of the variable names in the SHAContext , especially the
* single character names , were used because those were the names
* used in the publication .
*
*
*/
void SHA1ProcessMessageBlock ( SHA1Context * context )
{
const unsigned K [ ] = /* Constants defined in SHA-1 */
{
0x5A827999 ,
0x6ED9EBA1 ,
0x8F1BBCDC ,
0xCA62C1D6
} ;
int t ; /* Loop counter */
unsigned temp ; /* Temporary word value */
unsigned W [ 80 ] ; /* Word sequence */
unsigned A , B , C , D , E ; /* Word buffers */
/*
* Initialize the first 16 words in the array W
*/
for ( t = 0 ; t < 16 ; t + + )
{
W [ t ] = ( ( unsigned ) context - > Message_Block [ t * 4 ] ) < < 24 ;
W [ t ] | = ( ( unsigned ) context - > Message_Block [ t * 4 + 1 ] ) < < 16 ;
W [ t ] | = ( ( unsigned ) context - > Message_Block [ t * 4 + 2 ] ) < < 8 ;
W [ t ] | = ( ( unsigned ) context - > Message_Block [ t * 4 + 3 ] ) ;
}
for ( t = 16 ; t < 80 ; t + + )
{
W [ t ] = SHA1CircularShift ( 1 , W [ t - 3 ] ^ W [ t - 8 ] ^ W [ t - 14 ] ^ W [ t - 16 ] ) ;
}
A = context - > Message_Digest [ 0 ] ;
B = context - > Message_Digest [ 1 ] ;
C = context - > Message_Digest [ 2 ] ;
D = context - > Message_Digest [ 3 ] ;
E = context - > Message_Digest [ 4 ] ;
for ( t = 0 ; t < 20 ; t + + )
{
temp = SHA1CircularShift ( 5 , A ) +
( ( B & C ) | ( ( ~ B ) & D ) ) + E + W [ t ] + K [ 0 ] ;
temp & = 0xFFFFFFFF ;
E = D ;
D = C ;
C = SHA1CircularShift ( 30 , B ) ;
B = A ;
A = temp ;
}
for ( t = 20 ; t < 40 ; t + + )
{
temp = SHA1CircularShift ( 5 , A ) + ( B ^ C ^ D ) + E + W [ t ] + K [ 1 ] ;
temp & = 0xFFFFFFFF ;
E = D ;
D = C ;
C = SHA1CircularShift ( 30 , B ) ;
B = A ;
A = temp ;
}
for ( t = 40 ; t < 60 ; t + + )
{
temp = SHA1CircularShift ( 5 , A ) +
( ( B & C ) | ( B & D ) | ( C & D ) ) + E + W [ t ] + K [ 2 ] ;
temp & = 0xFFFFFFFF ;
E = D ;
D = C ;
C = SHA1CircularShift ( 30 , B ) ;
B = A ;
A = temp ;
}
for ( t = 60 ; t < 80 ; t + + )
{
temp = SHA1CircularShift ( 5 , A ) + ( B ^ C ^ D ) + E + W [ t ] + K [ 3 ] ;
temp & = 0xFFFFFFFF ;
E = D ;
D = C ;
C = SHA1CircularShift ( 30 , B ) ;
B = A ;
A = temp ;
}
context - > Message_Digest [ 0 ] =
( context - > Message_Digest [ 0 ] + A ) & 0xFFFFFFFF ;
context - > Message_Digest [ 1 ] =
( context - > Message_Digest [ 1 ] + B ) & 0xFFFFFFFF ;
context - > Message_Digest [ 2 ] =
( context - > Message_Digest [ 2 ] + C ) & 0xFFFFFFFF ;
context - > Message_Digest [ 3 ] =
( context - > Message_Digest [ 3 ] + D ) & 0xFFFFFFFF ;
context - > Message_Digest [ 4 ] =
( context - > Message_Digest [ 4 ] + E ) & 0xFFFFFFFF ;
context - > Message_Block_Index = 0 ;
}
/*
* SHA1PadMessage
*
* Description :
* According to the standard , the message must be padded to an even
* 512 bits . The first padding bit must be a ' 1 ' . The last 64
* bits represent the length of the original message . All bits in
* between should be 0. This function will pad the message
* according to those rules by filling the Message_Block array
* accordingly . It will also call SHA1ProcessMessageBlock ( )
* appropriately . When it returns , it can be assumed that the
* message digest has been computed .
*
* Parameters :
* context : [ in / out ]
* The context to pad
*
* Returns :
* Nothing .
*
* Comments :
*
*/
void SHA1PadMessage ( SHA1Context * context )
{
/*
* Check to see if the current message block is too small to hold
* the initial padding bits and length . If so , we will pad the
* block , process it , and then continue padding into a second
* block .
*/
if ( context - > Message_Block_Index > 55 )
{
context - > Message_Block [ context - > Message_Block_Index + + ] = 0x80 ;
while ( context - > Message_Block_Index < 64 )
{
context - > Message_Block [ context - > Message_Block_Index + + ] = 0 ;
}
SHA1ProcessMessageBlock ( context ) ;
while ( context - > Message_Block_Index < 56 )
{
context - > Message_Block [ context - > Message_Block_Index + + ] = 0 ;
}
}
else
{
context - > Message_Block [ context - > Message_Block_Index + + ] = 0x80 ;
while ( context - > Message_Block_Index < 56 )
{
context - > Message_Block [ context - > Message_Block_Index + + ] = 0 ;
}
}
/*
* Store the message length as the last 8 octets
*/
context - > Message_Block [ 56 ] = ( context - > Length_High > > 24 ) & 0xFF ;
context - > Message_Block [ 57 ] = ( context - > Length_High > > 16 ) & 0xFF ;
context - > Message_Block [ 58 ] = ( context - > Length_High > > 8 ) & 0xFF ;
context - > Message_Block [ 59 ] = ( context - > Length_High ) & 0xFF ;
context - > Message_Block [ 60 ] = ( context - > Length_Low > > 24 ) & 0xFF ;
context - > Message_Block [ 61 ] = ( context - > Length_Low > > 16 ) & 0xFF ;
context - > Message_Block [ 62 ] = ( context - > Length_Low > > 8 ) & 0xFF ;
context - > Message_Block [ 63 ] = ( context - > Length_Low ) & 0xFF ;
SHA1ProcessMessageBlock ( context ) ;
}
2022-08-28 09:35:46 +01:00