/* Copyright 2001-2022 John Wiseman G8BPQ This file is part of LinBPQ/BPQ32. LinBPQ/BPQ32 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. LinBPQ/BPQ32 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses */ //#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #define _CRT_SECURE_NO_DEPRECATE #define DllImport #include "CHeaders.h" #include #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 #include "zlib.h" #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); 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 char * UIUIDigi[33]; extern char UIUIDEST[33][11]; // Dest for Beacons extern UCHAR FN[33][256]; // Filename extern int Interval[33]; // Beacon Interval (Mins) extern char Message[33][1000]; // Beacon Text extern int MinCounter[33]; // Interval Countdown extern BOOL SendFromFile[33]; extern HKEY REGTREE; extern BOOL APRSActive; extern UCHAR LogDirectory[]; extern struct RIGPORTINFO * PORTInfo[34]; extern int NumberofPorts; char * strlop(char * buf, char delim); 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); void ProcessMailHTTPMessage(struct HTTPConnectionInfo * Session, char * Method, char * URL, char * input, char * Reply, int * RLen, int InputLen); 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); 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[] = "%s's BPQ32 Web Server

" "" "" "
Node PagesAPRS Pages
"; char IndexNoAPRS[] = "" ""; //char APRSBit[] = "APRS Pages"; //char MailBit[] = "Mail Mgmt" // "WebMail"; //char ChatBit[] = "Chat Mgmt"; char Tail[] = ""; char RouteHddr[] = "

Routes

" ""; char RouteLine[] = ""; char xNodeHddr[] = "
" "
PortCallQualityNode CountFrame CountRetriesPercentMaxframeFrackLast HeardQueuedRem Qual
%s%d%s%c%d%d%d%d%d%%d%d%02d:%02d%d%d
" "
" "" "
" "

Nodes %s

"; char NodeHddr[] = "
" "" "" "
" "

Nodes %s

"; char NodeLine[] = ""; char StatsHddr[] = "

Node Stats

%s:%s
" ""; char PortStatsHddr[] = "

Stats for Port %d

"; char PortStatsLine[] = ""; char Beacons[] = "

Beacon Configuration for Port %d

You need to be signed in to save changes

%s %d
" "" "
" "" "" "" "" "" "
Send Interval (Minutes)
To
Path
Send From File
Text
" "" "

" ""; char LinkHddr[] = "

Links

" ""; char LinkLine[] = ""; char UserHddr[] = "

Sessions

Far CallOur CallPortax.25 stateLink Typeax.25 Version
%s%s%d%s%s%d
"; char UserLine[] = ""; char TermSignon[] = "BPQ32 Node %s Terminal Access" "

BPQ32 Node %s Terminal Access

" "

Please enter username and password to access the node

" "" "
%s%s%s
" "" "
User
Password
" "

" ""; char PassError[] = "

Sorry, User or Password is invalid - please try again

"; char BusyError[] = "

Sorry, No sessions available - please try later

"; char LostSession[] = "Sorry, Session had been lost - refresh page to sign in again"; char NoSessions[] = "Sorry, No Sessions available - refresh page to try again"; char TermPage[] = "" "BPQ32 Node %s" "" "" "

BPQ32 Node %s

" "
" "

" "" "" ""; char TermOutput[] = "" "" "" "" "" "" "" "
\""; // font-family:monospace;background-color:black;color:lawngreen;font-size:12px char TermOutputTail[] = "
"; /* char InputLine[] = "" "
" "" "
"; */ char InputLine[] = "" "
" "\" id=inp type=text text width=100%% name=input />" "
"; static char NodeSignon[] = "BPQ32 Node SYSOP Access" "

BPQ32 Node %s SYSOP Access

" "

This page sets Cookies. Don't continue if you object to this

" "

Please enter Callsign and Password to access the Node

" "
" "" "" "
User
Password
" "

"; static char MailSignon[] = "BPQ32 Mail Server Access" "

BPQ32 Mail Server %s Access

" "

Please enter Callsign and Password to access the BBS

" "
" "" "" "
User
Password
" "

"; static char ChatSignon[] = "BPQ32 Chat Server Access" "

BPQ32 Chat Server %s Access

" "

Please enter Callsign and Password to access the Chat Server

" "
" "" "" "
User
Password
" "

"; static char MailLostSession[] = "" "
" "Sorry, Session had been lost

    " "
"; static char ConfigEditPage[] = "" "Edit Config" "
" "

" "
"; 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
\r\n"); else Session->ScreenLines[Line] = _strdup("*** Disconnected
\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
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, "
\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, "", GetRValue(Colour), GetGValue(Colour), GetBValue(Colour)); memcpy(Formatted, ColString, 20); strcat(Formatted, ""); 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, "
\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;;) { strcat(_REPLYBUFFER, Session->ScreenLines[n]); 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\nContent-Length: %d\r\nContent-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
"); for (i = 20; i < 100; i++) Session->ScreenLines[i] = _strdup("
\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) { char _REPLYBUFFER[1024]; int ReplyLen; char Header[256]; int HeaderLen; int State; struct HTTPConnectionInfo * Session = FindSession(Key); int Stream; 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; struct TNCINFO * TNC = Session->TNC; struct TCPINFO * TCP = 0; if (TNC) TCP = TNC->TCPInfo; 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, "
\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\nContent-Length: %d\r\nContent-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\nContent-Length: %d\r\nContent-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\nContent-Length: %d\r\nContent-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\nContent-Length: %d\r\nContent-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, ""); 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\nContent-Length: 16\r\n\r\nPage 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"); 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; } if (_stricmp(ptr, "jpg") == 0 || _stricmp(ptr, "jpeg") == 0 || _stricmp(ptr, "png") == 0 || _stricmp(ptr, "gif") == 0 || _stricmp(ptr, "ico") == 0) strcpy(Type, "Content-Type: image\r\n"); HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-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\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen); sendandcheck(Session->sock, Header, HeaderLen); sendandcheck(Session->sock, _REPLYBUFFER, ReplyLen); return 1; } else return 0; } extern struct TNCINFO * TNCInfo[41]; int SetupNodeMenu(char * Buff, int LOCAL) { int Len = 0, i; struct TNCINFO * TNC; int top = 0, left = 0; char NodeMenuHeader[] = "%s's BPQ32 Web Server" "" "" "

BPQ32 Node %s

" "

" "" "" "" "" "" "" "%s%s%s%s%s%s"; char DriverBit[] = "" ""; char APRSBit[] = ""; char MailBit[] = "" ""; char ChatBit[] = ""; char SigninBit[] = ""; char NodeTail[] = "" "
RoutesNodesPortsLinksUsersStatsTerminalDriver WindowsStream StatusAPRS PagesMail MgmtWebMailChat MgmtSYSOP SigninEdit Config" "
"; Len = sprintf(Buff, NodeMenuHeader, Mycall); for (i=1; i<33; i++) { 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", ""); HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-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); if (BPQDirectory[0] == 0) { strcpy(inputname, "bpq32.cfg"); } else { strcpy(inputname,BPQDirectory); 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, "", Mess); HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-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; char * Context, * Method, * NodeURL, * Key; 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[] = "

Ports

" ""; char PortLine[] = ""; char PortLineWithBeacon[] = "" "\r\n"; char SessionPortLine[] = "" "\r\n"; char PortLineWithDriver[] = "" "\r\n"; char PortLineWithBeaconAndDriver[] = "" "" "\r\n"; char RigControlLine[] = "" "\r\n"; char Encoding[] = "Content-Encoding: deflate\r\n"; #ifdef WIN32 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: "); WebSock = strstr(MsgPtr, "Upgrade"); 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, ' '); // 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); if (Session == NULL) { 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; } // compress if allowed if (allowDeflate) Compressed = Compressit(Reply, ReplyLen, &ReplyLen); else Compressed = Reply; HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n%s\r\n", ReplyLen, Encoding); 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; ReplyLen = 0; if (Session == 0) Session = &Dummy; Session->TNC = (void *)LOCAL; // TNC only used for Web Terminal Sessions ProcessMailHTTPMessage(Session, Method, Context, MsgPtr, _REPLYBUFFER, &ReplyLen, MsgLen); 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; } HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", ReplyLen + (int)strlen(Tail)); HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-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; } 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\nContent-Length: %d\r\nContent-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 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\nContent-Length: 28\r\n\r\nMail 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; Session->TNC = LOCAL; // TNC is only used on Web Terminal Sessions so can reuse as LOCAL flag 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\nContent-Length: 28\r\n\r\nChat 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; if (port > 0 && port < 33) { 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; if (port > 0 && port < 33) { struct TNCINFO * TNC = TNCInfo[port]; if (TNC == 0) return 1; if (LOCAL == FALSE && COOKIE == FALSE) return 1; 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], "
Not authorized - please sign in"); HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-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\nContent-Length: %d\r\nContent-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; } GetParam(input, "Port", &Param[0]); Port = atoi(&Param[1]); PORT = GetPortTableEntryFromPortNum(Port); // Need slot not number if (PORT) Slot = PORT->PortSlot; GetParam(input, "Every", &Param[0]); Interval[Slot] = atoi(&Param[1]); //extern char * UIUIDigi[33]; //extern char UIUIDEST[33][11]; // Dest for Beacons //extern UCHAR FN[33][256]; // Filename //extern int [33]; // Beacon Interval (Mins) //extern char Message[33][1000]; // Beacon Text GetParam(input, "Dest", &Param[0]); _strupr(Param); strcpy(UIUIDEST[Slot], &Param[1]); GetParam(input, "Path", &Param[0]); _strupr(Param); if (UIUIDigi[Slot]) free(UIUIDigi[Slot]); UIUIDigi[Slot] = _strdup(&Param[1]); GetParam(input, "File", &Param[0]); strcpy(FN[Slot], &Param[1]); GetParam(input, "Text", &Param[0]); strcpy(Message[Slot], &Param[1]); 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\nContent-Length: %d\r\nContent-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\nContent-Length: %d\r\nContent-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); if (port > 0 && port < 33) { 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, "", "Ok"); HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-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\nContent-Length: %d\r\nContent-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\nContent-Length: %d\r\nContent-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); if (ReplyLen < 240000) ReplyLen += GetAISPageInfo(&_REPLYBUFFER[ReplyLen], ais, adsb); if (allowDeflate) Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen); else Compressed = _REPLYBUFFER; HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-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, "/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\nContent-Length: %d\r\nContent-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); if (port > 0 && port < 33) { 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); if (port > 0 && port < 33) { 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], "", "Version", VersionString); ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", "Uptime (Days Hours Mins)", UPTime); ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", "Semaphore: Get-Rel/Clashes", Semaphore.Gets - Semaphore.Rels, Semaphore.Clashes); ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", "Buffers: Max/Cur/Min/Out/Wait", MAXBUFFS, QCOUNT, MINBUFFCOUNT, NOBUFFCOUNT, BUFFERWAITS); ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", "Known Nodes/Max Nodes", NUMBEROFNODES, MAXDESTS); ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", "L4 Connects Sent/Rxed ", L4CONNECTSOUT, L4CONNECTSIN); ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", "L4 Frames TX/RX/Resent/Reseq", L4FRAMESTX, L4FRAMESRX, L4FRAMESRETRIED, OLDFRAMES); ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "", "L3 Frames Relayed", L3FRAMES); } else if (_stricmp(NodeURL, "/Node/RigControl.html") == 0) { char Test[] = "\r\n" "Rigcontrol\r\n" "\r\n" "\r\n" "\r\n" "
Waiting for data...
\r\n" "\r\n"; char NoRigCtl[] = "\r\n" "Rigcontrol\r\n" "\r\n" "\r\n" "
RigControl Not Configured...
\r\n" "\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[] = "" "" "Log Display" "" "
" "
" // "" "" "" "
"; 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], "
Not authorized - please sign in"); HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-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\nContent-Length: %d\r\nContent-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\nContent-Length: %d\r\nContent-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], "
Not authorized - please sign in"); HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-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 (BPQDirectory[0] == 0) { strcpy(inputname, "bpq32.cfg"); } else { strcpy(inputname,BPQDirectory); 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\nContent-Length: %d\r\nContent-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]; ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", PortsHddr); for (count = 1; count <= NUMBEROFPORTS; count++) { Port = GetPortTableEntryFromSlot(count); ExtPort = (struct _EXTPORTDATA *)Port; 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, Port->PORTDESCRIPTION, Port->PORTNUMBER, Port->PORTNUMBER, Port->TNC->WebWinX, Port->TNC->WebWinY, 200, 200); else ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortLineWithDriver, Port->PORTNUMBER, DLL, Port->PORTDESCRIPTION, Port->PORTNUMBER, Port->TNC->WebWinX, Port->TNC->WebWinY, 200, 200); continue; } if (Port->PORTTYPE == 16 && Port->PROTOCOL == 10 && Port->UICAPABLE == 0) // EXTERNAL, Pactor/WINMO ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], SessionPortLine, Port->PORTNUMBER, DLL, Port->PORTDESCRIPTION, Port->PORTNUMBER); else ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortLineWithBeacon, Port->PORTNUMBER, Port->PORTNUMBER, DLL, DLL, Port->PORTDESCRIPTION, Port->PORTNUMBER); } if (RigActive) ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], RigControlLine, 33, "Rig Control", "Rig Control", 600, 350, 200, 200); } 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], ""); } 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], "", 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], ""); } } } ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], ""); } 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], "

Call %s not found

", Context); goto SendResp; } memcpy(Alias, Dest->DEST_ALIAS, 6); strlop(Alias, ' '); ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "

Info for Node %s:%s

", Alias, Context); ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "

PortDriverIDBeaconsDriver Window
%d %s%s
%d %s%s Beacons
%d%s%s
%d%s%s Driver Window
%d%s%s BeaconsDriver Window
%d%s%s Rig Control
%s%s
%s%s
%s%d%d
%s%d%d%d%d%d
%s%d%d
%s%d%d
%s%d%d%d%d
%s%d
CallFramesRTTBPQ?Hops
%s:%s%d%d%c%.0d
"); ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "
FramesRTTBPQ?Hops
%d%d%c%.0d
", Dest->DEST_COUNT, Dest->DEST_RTT /16, (Dest->DEST_STATE & 0x40)? 'B':' ', (Dest->DEST_STATE & 63)); ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "

Neighbours

"); ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "" ""); 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], "", (Active == i)?'>':' ',NRRoute->ROUT_QUALITY, NRRoute->ROUT_OBSCOUNT, Neighbour->NEIGHBOUR_PORT, Normcall); } NRRoute++; } ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "
Qual Obs Port Call
%c %d%d%d%s
"); 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; countNEIGHBOUR_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; countLINKCALL[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\nContent-Length: %d\r\nContent-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; #ifdef WIN32 } #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, "" "Stream Status"); Len += sprintf(&Buff[Len], ""); Len += sprintf(&Buff[Len], ""); Len += sprintf(&Buff[Len], ""); Len += sprintf(&Buff[Len], ""); Len += sprintf(&Buff[Len], ""); Len += sprintf(&Buff[Len], ""); Len += sprintf(&Buff[Len], ""); 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], "" "", i, flag, RXCount(i), TXCount(i), MONCount(i), Mask, Flags, callsign, BPQHOSTVECTOR[i-1].PgmName); else Len += sprintf(&Buff[Len], "" "", i, flag, RXCount(i), TXCount(i), MONCount(i), AppNumber, Flags, callsign, BPQHOSTVECTOR[i-1].PgmName); if ((i & 1) == 0) Len += sprintf(&Buff[Len], ""); } Len += sprintf(&Buff[Len], "
    RX   TX   MON  App  Flg Callsign  Program    RX   TX   MON  App  Flg Callsign  Program
%d%s%d%d%d%x%x%s%s%d%s%d%d%d%d%x%s%s
"); 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\nContent-Length: %d\r\nContent-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\nContent-Length: %d\r\nContent-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\nContent-Length: %d\r\nContent-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; } 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; } #ifdef WIN32 #include #include #define SHA1_HASH_LEN 20 BOOL SHA1PasswordHash(char * lpszPassword, char * Hash) { HCRYPTPROV hCryptProv; // Handle to our context HCRYPTHASH hCryptHash; // Handle to our hash BYTE bHashValue[SHA1_HASH_LEN]; // This will hold our SHA-1 hash DWORD dwSize = SHA1_HASH_LEN; // Size of output BOOL bSuccess = FALSE; // We change this to TRUE if we complete the operations // Declare all the variables at the start of our code for C89 compatability if(CryptAcquireContext(&hCryptProv, NULL, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { // Initiate usage of the functions if(CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hCryptHash)) { // Create a SHA1 hash if(CryptHashData(hCryptHash, (PBYTE)lpszPassword, lstrlen(lpszPassword) * sizeof(TCHAR), 0)) { // Update the hash, (process our password) if(CryptGetHashParam(hCryptHash, HP_HASHVAL, bHashValue, &dwSize, 0)) { // Extract the hash memcpy(Hash, bHashValue, 20); bSuccess = TRUE; } } CryptDestroyHash(hCryptHash); } CryptReleaseContext(hCryptProv, 0); } return bSuccess; } #else #include BOOL SHA1PasswordHash(char * data, char * Hash) { SHA1(data, strlen(data), Hash); return 1; } #endif int BuildRigCtlPage(char * _REPLYBUFFER) { int ReplyLen; struct RIGPORTINFO * PORT; struct RIGINFO * RIG; int p, i; char Page[] = "\r\n" // "\r\n" "Rigcontrol\r\n" "" "

Rigcontrol

\r\n" "\r\n" "\r\n" "\r\n" "\r\n" "\r\n" "\r\n" "\r\n" ""; char RigLine[] = "\r\n" " \r\n" " \r\n" " \r\n" " \r\n" " \r\n" " \r\n" " \r\n"; char Tail[] = "
RadioFreqModeSTPorts
%s%s%s/1%c%c%s
\r\n" "\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() { int i, n; struct ConnectionInfo * sockptr; struct TNCINFO * TNC; struct TCPINFO * TCP; for (i = 0; i < 33; i++) { TNC = TNCInfo[i]; 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); } } } } } } } // 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; int InputLen; struct HTTPConnectionInfo Dummy = {0}; int ReplyLen = 0; #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 { InputLen -= Sent; 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; }