#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #define _CRT_SECURE_NO_DEPRECATE #include "compatbits.h" #ifndef LINBPQ #include "asmstrucs.h" #include "bpq32.h" #include "chatrc.h" #else #define WCHAR wchar_t #endif #ifdef LINBPQ #ifdef WIN32 //#include "C:\Program Files (X86)\GnuWin32\include\iconv.h" #else #include #endif #endif #define IDC_STATIC -1 #define IDS_APP_TITLE 103 #define IDR_MAINFRAME 128 #define IDD_CONFIG 102 #define IDD_ABOUTBOX 103 #define IDM_ABOUT 104 #define IDM_EXIT 105 #define IDM_CONSOLE 120 #define IDM_MONITOR 121 #define IDC_BPQMailChat 109 #define IDM_DISCONNECT 2000 #define IDM_LOGGING 2100 #define IDM_CONFIG 110 #define IDC_MYICON 2 #define IDC_BBSCall 1001 #define IDC_BaseDir 1002 #define IDC_BBSAppl 1003 #define IDC_BBSStreams 1004 #define IDC_POP3Port 1005 #define IDC_SMTPPort 1006 #define IDC_HRoute 1007 #define IDC_SYSOPCALL 1008 #define IDC_REMOTEEMAIL 1009 #define IDC_BBSSAVE 1100 #define IDC_ChatAppl 2001 #define IDC_ChatNodes 2002 #define SAVENODES 2100 #define BPQBASE 1024 #define BPQMTX 1040 #define BPQMCOM 1041 #define BPQCOPYMON 1042 #define BPQCOPYOUT 1043 #define BPQCLEARMON 1044 #define BPQCLEAROUT 1045 #define BPQBELLS 1046 #define BPQCHAT 1047 #define BPQHELP 1048 #define BPQStripLF 1049 #define BPQLogOutput 1050 #define BPQLogMonitor 1051 #define BPQSendDisconnected 1052 #define BPQFLASHONBELL 1053 #define MONBBS 1060 #define MONCHAT 1061 #define MONTCP 1062 #define IDC_NODES 501 #define IDC_USERS 502 #define IDC_LINKS 503 #define IDC_SYSOPMSGS 504 #define IDC_FWDINT 505 #define IDC_UTC 506 #define IDC_LOCAL 507 #define IDC_MSGS 508 #define IDC_HELD 509 #define IDD_USEREDIT 200 #define IDD_FORWARDING 201 #define IDD_MSGEDIT 202 #define IDD_USERADDED_BOX 5051 #define CHAT_CONFIG 9013 #define IDC_ChatNodes 2002 // Standard __except handler for try/except VOID CheckProgramErrors(); extern int ProgramErrors; struct _EXCEPTION_POINTERS; int Dump_Process_State(struct _EXCEPTION_POINTERS * exinfo, char * Msg); #define My__except_Routine(Message) \ __except(memcpy(&exinfo, GetExceptionInformation(), sizeof(struct _EXCEPTION_POINTERS)), EXCEPTION_EXECUTE_HANDLER)\ {\ Debugprintf("CHAT *** Program Error %x at %x in %s EAX %x EBX %x ECX %x EDX %x ESI %x EDI %x",\ exinfo.ExceptionRecord->ExceptionCode, exinfo.ExceptionRecord->ExceptionAddress, Message,\ exinfo.ContextRecord->Eax, exinfo.ContextRecord->Ebx, exinfo.ContextRecord->Ecx,\ exinfo.ContextRecord->Edx, exinfo.ContextRecord->Esi, exinfo.ContextRecord->Edi);\ CheckProgramErrors();\ } /* #define My__except_Routine(Message) \ __except(memcpy(&exinfox, GetExceptionInformation(), sizeof(struct _EXCEPTION_POINTERS)), EXCEPTION_EXECUTE_HANDLER)\ {\ Dump_Process_State(&exinfox, Message);\ CheckProgramErrors();\ } #define My__except_RoutineWithDisconnect(Message) \ __except(memcpy(&exinfo, GetExceptionInformation(), sizeof(struct _EXCEPTION_POINTERS)), EXCEPTION_EXECUTE_HANDLER)\ {\ Debugprintf("MAILCHAT *** Program Error %x at %x in %s EAX %x EBX %x ECX %x EDX %x ESI %x EDI %x",\ exinfo.ExceptionRecord->ExceptionCode, exinfo.ExceptionRecord->ExceptionAddress, Message,\ exinfo.ContextRecord->Eax, exinfo.ContextRecord->Ebx, exinfo.ContextRecord->Ecx,\ exinfo.ContextRecord->Edx, exinfo.ContextRecord->Esi, exinfo.ContextRecord->Edi);\ FreeSemaphore(&ChatSemaphore);\ if (conn->BPQStream < 0)\ CloseConsole(conn->BPQStream);\ else\ Disconnect(conn->BPQStream);\ } */ #define My_except_RoutineWithDiscBBS(Message) \ __except(memcpy(&exinfo, GetExceptionInformation(), sizeof(struct _EXCEPTION_POINTERS)), EXCEPTION_EXECUTE_HANDLER)\ {\ Debugprintf("CHAT *** Program Error %x at %x in %s EAX %x EBX %x ECX %x EDX %x ESI %x EDI %x",\ exinfo.ExceptionRecord->ExceptionCode, exinfo.ExceptionRecord->ExceptionAddress, Message,\ exinfo.ContextRecord->Eax, exinfo.ContextRecord->Ebx, exinfo.ContextRecord->Ecx,\ exinfo.ContextRecord->Edx, exinfo.ContextRecord->Esi, exinfo.ContextRecord->Edi);\ if (conn->BPQStream < 0)\ CloseConsole(conn->BPQStream);\ else\ Disconnect(conn->BPQStream);\ CheckProgramErrors();\ } #define MAXUSERNAMELEN 6 #define WSA_ACCEPT WM_USER + 1 #define WSA_CONNECT WM_USER + 2 #define WSA_DATA WM_USER + 3 #define NNTP_ACCEPT WM_USER + 4 #define NNTP_DATA WM_USER + 5 #ifdef _DEBUG VOID * _malloc_dbg_trace(int len, int type, char * file, int line); #define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__) #define calloc(c, s) _calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__) #define realloc(p, s) _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__) #define _recalloc(p, c, s) _recalloc_dbg(p, c, s, _NORMAL_BLOCK, __FILE__, __LINE__) #define _expand(p, s) _expand_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__) #define free(p) _free_dbg(p, _NORMAL_BLOCK) #define _strdup(s) _strdup_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__) #define zalloc(s) _zalloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__) #else #define zalloc(s) _zalloc(s) #endif VOID * _zalloc_dbg(int len, int type, char * file, int line); #define LOG_CHAT 1 #define LOG_DEBUGx 3 //Chat Duplicate suppression Code #define MAXDUPS 10 // Number to keep #define DUPSECONDS 5 // TIme to Keep struct DUPINFO { time_t DupTime; char DupUser[10]; char DupText[100]; }; struct UserRec { char * Callsign; char * UserName; char * Password; }; //#define ln_ibuf 128 #define deftopic "General" // Protocol version. #define FORMAT 1 // Ctrl/A #define FORMAT_O 0 // Offset in frame to format byte. #define TYPE_O 1 // Offset in frame to kind byte. #define DATA_O 2 // Offset in frame to data. // Protocol Frame Types. #define id_join 'J' // User joins RT. #define id_leave 'L' // User leaves RT. #define id_link 'N' // Node joins RT. #define id_unlink 'Q' // Node leaves RT. #define id_data 'D' // Data for all users. #define id_send 'S' // Data for one user. #define id_topic 'T' // User changes topic. #define id_user 'I' // User login information. #define id_keepalive 'K' // Node-Node Keepalive. #define id_poll 'P' //Link Validation Poll #define id_pollresp 'R' //Link Validation Poll Response #define o_all 1 // To all users. #define o_one 2 // To a specific user. #define o_topic 3 // To all users in a specific topic. // RT protocol version 1. // First two bytes are FORMAT and Frame Type. // These are followed by text fields delimited by blanks. // Note that "node", "to", "from", "user" are callsigns. // ^AD - Data for all users. // ^AI - User information. // ^AJ - User joins. // ^AL - User leaves. // ^AN - Node joins. // ^AQ - Node leaves. // ^AS - Data for one user. // ^AT - User changes topic. // Connect protocol: // 1. Connect to node. // 2. Send *RTL // 3. Receive OK. Will get disconnect if link is not allowed. // 4. Go to it. // Disconnect protocol: // 1. If there are users on this node, send an id_leave for each user, // to each node you are disconnecting from. // 2. Disconnect. // Other RT systems to link with. Flags can be p_linked, p_linkini. typedef struct link_t { struct link_t *next; char *alias; char *call; int flags; // See circuit flags. int delay; // Limit connects when failing char ** ConnectScript; // Main Connect Script int ScriptIndex; // Next line in script int Lines; // Lines in Script BOOL MoreLines; // Set until script is finsihed int scriptRunning; int RTLSent; time_t lastMsgSent; // So we can send poll if no traffic time_t lastMsgReceived; // So can send poll if idle too long time_t timePollSent; // Poll response timer time_t supportsPolls; // So we know other end supports polls int RTT; // Last Poll response time } LINK; typedef struct knownnode_t { struct knownnode_t *next; char *call; time_t LastHeard; } KNOWNNODE; // Topics. typedef struct topic_t { struct topic_t *next; char *name; int refcnt; } TOPIC; // Nodes. typedef struct node_t { struct node_t *next; char *alias; char *call; char * Version; int refcnt; time_t timeconnected; } CHATNODE; // Topics in use at each circuit. typedef struct ct_t { struct ct_t *next; TOPIC *topic; int refcnt; } CT; // Nodes reached on each circuit. typedef struct cn_t { struct cn_t *next; CHATNODE *node; int refcnt; } CN; // Circuits. // A circuit may be used by one local user, or one link. // If it is used by a link, there may be many users on that link. // Bits for circuit flags and link flags. #define p_nil 0x00 // Circuit is being shut down. #define p_user 0x01 // User connected. #define p_linked 0x02 // Active link with another RT. #define p_linkini 0x04 // Outgoing link setup with another RT. #define p_linkwait 0x08 // Incoming link setup - waiting for *RTL #define p_linkfailed 0x10 // Outward attempt failed // Users. Could be connected at any node. #define u_echo 0x0002 // User wants his text echoed to him. #define u_bells 0x0004 // User wants bell when other users join. #define u_colour 0x0008 // User wants BPQTerminal colour codes. #define u_keepalive 0x0010 // User wants Keepalive Messages. #define u_shownames 0x0020 // User wants name as well as call on each message. #define u_showtime 0x0040 // User wants time on each message. #define u_auto 0x0080 // Determine UTF-8 Mode automatically. #define u_noUTF8 0x0100 // Terminal is not using UTF-8. struct UserInfo{ char Call[10]; // Connected call without SSID char Name[18]; /* 18 1st Name */ }; typedef struct ChatConnectionInfo_S { struct ChatConnectionInfo_S *next; PROC *proc; UCHAR rtcflags; // p_linked or p_user. int s; // Socket. // char buf[ln_ibuf]; // Line of incoming text. union { struct user_t *user; // Associated user if local. LINK *link; // Associated link if link. } u; int refcnt; // If link, # of users on that link. CN *hnode; // Nodes heard from this link. CT *topic; // Out this circuit if from these topics. int Number; // Number of record - for Connections display BOOL Active; int BPQStream; int paclen; UCHAR Callsign[11]; // Station call including SSID BOOL GotHeader; char FBBReplyChars[80]; // Version from other end UCHAR InputBuffer[10000]; int InputLen; // Data we have already = Offset of end of an incomplete packet; struct UserInfo * UserPointer; int Retries; int LoginState; // 1 = user ok, 2 = password ok int Flags; // Data to the user is kept in a static buffer. This can be appended to, // and data sucked out under both terminal and system flow control. PACLEN is // enfored when sending to node. UCHAR * OutputQueue; // Messages to user int OutputQueueSize; // Total Malloc'ed size. int OutputQueueLength; // Put Pointer for next Message int OutputGetPointer; // Next byte to send. When Getpointer = Queue Length all is sent - free the buffer and start again. BOOL sysop; // Set if user is authenticated as a sysop BOOL Secure_Session; // Set if Local Terminal, or Telnet connect with SYSOP status BOOL NewUser; // Set if first time user has accessed BBS int Watchdog; // Hung Circuit Detect. int SessType; // BPQ32 sesstype bits #define Sess_L2LINK 1 #define Sess_SESSION 2 #define Sess_UPLINK 4 #define Sess_DOWNLINK 8 #define Sess_BPQHOST 0x20 #define Sess_PACTOR 0x40 HANDLE DebugHandle; // File Handle for session-based debugging } ChatConnectionInfo, ChatCIRCUIT; // Flags Equates #define GETTINGUSER 1 #define CHATMODE 4 #define CHATLINK 32 // Link to another Chat Node // BBSFlags Equates #pragma pack(1) struct TempUserInfo { int LastAuthCode; // Protect against playback attack }; typedef struct user_t { struct user_t *next; char *call; char *name; char *qth; CHATNODE *node; // Node user logged into. ChatCIRCUIT *circuit; // Circuit user is on, local or link. TOPIC *topic; // Topic user is in. int rtflags; time_t lastmsgtime; // Time of last input from user including keepalives time_t lastrealmsgtime;// Time of last input from user time_t lastsendtime; // Time of last output to user time_t timeconnected; int Colour; // For Console Display #ifndef WIN32 char Codepage[80]; // For Converting UTF8 to local char set for non-utf-8 terminals iconv_t iconv_toUTF8; // per-uswer converison handles iconv_t iconv_fromUTF8; #else int Codepage; #endif } USER; #pragma pack() #pragma pack(1) #pragma pack() #define MAXSTACK 20 //#define MAXLINE 10000 #define INPUTLEN 512 #define MAXLINES 1000 #define LINELEN 200 char RTFHeader[4000]; int RTFHddrLen; struct ConsoleInfo { struct ConsoleInfo * next; ChatCIRCUIT * Console; int BPQStream; WNDPROC wpOrigInputProc; HWND hConsole; HWND hwndInput; HWND hwndOutput; HMENU hMenu; // handle of menu RECT OutputRect; int Height, Width, LastY; int ClientHeight, ClientWidth; char kbbuf[INPUTLEN]; int kbptr; WCHAR * readbuff; // Malloc'ed int readbufflen; // Current Length char * KbdStack[MAXSTACK]; int StackIndex; unsigned int WrapLen; int WarnLen; int maxlinelen; int PartLinePtr; int PartLineIndex; // Listbox index of (last) incomplete line DWORD dwCharX; // average width of characters DWORD dwCharY; // height of characters DWORD dwClientX; // width of client area DWORD dwClientY; // height of client area DWORD dwLineLen; // line length int nCaretPosX; // horizontal position of caret int nCaretPosY; // vertical position of caret COLORREF FGColour; // Text Colour COLORREF BGColour; // Background Colour COLORREF DefaultColour; // Default Text Colour int CurrentLine; // Line we are writing to in circular buffer. int Index; BOOL SendHeader; BOOL Finished; WCHAR OutputScreen[MAXLINES][LINELEN]; int Colourvalue[MAXLINES]; int LineLen[MAXLINES]; int CurrentColour; int Thumb; int FirstTime; BOOL Scrolled; // Set if scrolled back int RTFHeight; // Height of RTF control in pixels }; struct HistoryRec { struct HistoryRec * next; time_t Time; char * Topic; char * Message; }; extern struct HistoryRec * History; extern int HistoryCount; extern USER *user_hd; static PROC *Rt_Control; static int rtrun = FALSE; //#define rtjoin "*** Joined" #define rtleave "*** Left" KNOWNNODE *knownnode_find(char *call); static void cn_dec(ChatCIRCUIT *circuit, CHATNODE *node); static CHATNODE *cn_inc(ChatCIRCUIT *circuit, char *call, char *alias, char * Version); CHATNODE *node_find(char *call); static CHATNODE *node_inc(char *call, char *alias, char * Version); static int cn_find(ChatCIRCUIT *circuit, CHATNODE *node); static void text_xmit(USER *user, USER *to, char *text); void text_tellu(USER *user, char *text, char *to, int who); void text_tellu_Joined(USER *user); static void topic_xmit(USER *user, ChatCIRCUIT *circuit); static void node_xmit(CHATNODE *node, char kind, ChatCIRCUIT *circuit); static void node_tell(CHATNODE *node, char kind); static void user_xmit(USER *user, char kind, ChatCIRCUIT *circuit); static void user_tell(USER *user, char kind); USER *user_find(char *call, char * node); static void user_leave(USER *user); static BOOL topic_chg(USER *user, char *s); static USER *user_join(ChatCIRCUIT *circuit, char *ucall, char *ncall, char *nalias, BOOL Local); void link_drop(ChatCIRCUIT *circuit); static void echo(ChatCIRCUIT *fc, CHATNODE *node, char * Buffer); void state_tell(ChatCIRCUIT *circuit, char * Version); int ct_find(ChatCIRCUIT *circuit, TOPIC *topic); int rtlink (char * Call); int rtloginl (ChatCIRCUIT *conn, char * call); void chkctl(ChatCIRCUIT *ckt_from, char * Buffer, int Len); int rtloginu (ChatCIRCUIT *circuit, BOOL Local); void logout(ChatCIRCUIT *circuit); void show_users(ChatCIRCUIT *circuit); #ifdef LINBPQ static VOID __cdecl nprintf(ChatCIRCUIT * conn, const char * format, ...); static VOID nputs(ChatCIRCUIT * conn, char * buf); #else VOID __cdecl nprintf(ChatCIRCUIT * conn, const char * format, ...); VOID nputs(ChatCIRCUIT * conn, char * buf); #endif BOOL matchi(char * p1, char * p2); char * strlop(char * buf, char delim); int rt_cmd(ChatCIRCUIT *circuit, char * Buffer); ChatCIRCUIT *circuit_new(ChatCIRCUIT *circuit, int flags); void makelinks(void); VOID * _zalloc(size_t len); VOID FreeChatMemory(); VOID ChatTimer(); char * lookupuser(char * call); VOID node_close(); VOID removelinks(); VOID SetupChat(); int rtlink (char * Call); VOID SendChatLinkStatus(); VOID ClearChatLinkStatus(); void rduser(USER *user); void upduser(USER *user); VOID Send_MON_Datagram(UCHAR * Msg, DWORD Len); #define Connect(stream) SessionControl(stream,1,0) #define Disconnect(stream) SessionControl(stream,2,0) #define ReturntoNode(stream) SessionControl(stream,3,0) #define ConnectUsingAppl(stream, appl) SessionControl(stream, 0, appl) BOOL Initialise(); #ifndef LINBPQ INT_PTR CALLBACK ConfigWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); #endif int DisplaySessions(); int DoStateChange(int Stream); int DoReceivedData(int Stream); int DoMonitorData(int Stream); int Connected(int Stream); int Disconnected(int Stream); //int DeleteConnection(con); //int Socket_Accept(int SocketId); //int Socket_Data(int SocketId,int error, int eventcode); int RefreshMainWindow(); int Terminate(); int WriteLog(char * msg); int ConnectState(int Stream); UCHAR * EncodeCall(UCHAR * Call); int ParseIniFile(char * fn); VOID SendWelcomeMsg(int Stream, ChatCIRCUIT * conn, struct UserInfo * user); VOID ProcessLine(ChatCIRCUIT * conn, struct UserInfo * user, char* Buffer, int len); VOID ProcessChatLine(ChatCIRCUIT * conn, struct UserInfo * user, char* Buffer, int len); VOID SendPrompt(ChatCIRCUIT * conn, struct UserInfo * user); int ChatQueueMsg(ChatCIRCUIT * conn, char * msg, int len); VOID SendUnbuffered(int stream, char * msg, int len); void ChatWriteLogLine(ChatCIRCUIT * conn, int Flag, char * Msg, int MsgLen, int Flags); void ChatFlush(ChatCIRCUIT * conn); VOID ChatClearQueue(ChatCIRCUIT * conn); void TrytoSend(); int CriticalErrorHandler(char * error); void chat_link_out (LINK *link); int ProcessConnecting(ChatCIRCUIT * circuit, char * Buffer, int Len); BOOL SaveConfig(); VOID SaveWindowConfig(); VOID __cdecl nodeprintf(ChatCIRCUIT * conn, const char * format, ...); // Console Routines BOOL CreateConsole(int Stream); int WritetoConsoleWindow(int Stream, UCHAR * Msg, int len); int ToggleParam(HMENU hMenu, HWND hWnd, BOOL * Param, int Item); void CopyRichTextToClipboard(HWND hWnd); void CopyToClipboard(HWND hWnd); VOID CloseConsole(int Stream); // Monitor Routines BOOL CreateMonitor(); int WritetoMonitorWindow(char * Msg, int len); BOOL CreateDebugWindow(); VOID WritetoDebugWindow(char * Msg, int len); VOID ClearDebugWindow(); int RemoveLF(char * Message, int len); // Utilities struct SEM; BOOL isdigits(char * string); void GetSemaphore(struct SEM * Semaphore, int ID); void FreeSemaphore(struct SEM * Semaphore); VOID __cdecl Debugprintf(const char * format, ...); VOID __cdecl Logprintf(int LogMode, ChatCIRCUIT * conn, int InOut, const char * format, ...); int DeleteLogFiles(); VOID ExpandAndSendMessage(ChatCIRCUIT * conn, char * Msg, int LOG); extern char Session[]; extern HBRUSH bgBrush; extern BOOL cfgMinToTray; extern ChatCIRCUIT * Console; extern ULONG ChatApplMask; extern char Verstring[]; extern char AbortedMsg[]; extern char InfoBoxText[]; // Text to display in Config Info Popup extern int LastVer[4]; // In case we need to do somthing the first time a version is run extern HWND MainWnd; extern char BaseDir[]; extern char BaseDirRaw[]; extern char MailDir[]; extern char WPDatabasePath[]; extern char RlineVer[50]; extern BOOL LogBBS; extern BOOL LogTCP; extern int LatestMsg; extern char ChatSYSOPCall[]; extern char ChatSID[]; extern char NewUserPrompt[]; extern int Ver[4]; extern struct SEM AllocSemaphore; extern struct SEM ConSemaphore; extern struct SEM MsgNoSemaphore; extern char hostname[]; extern char RtUsr[]; extern char RtUsrTemp[]; extern char RtKnown[]; extern int AXIPPort; extern BOOL NeedStatus; extern LINK *link_hd; extern ChatCIRCUIT *circuit_hd ; // This is a chain of RT circuits. There may be others extern char OurNode[]; extern char OurAlias[]; extern BOOL SMTPMsgCreated; extern HINSTANCE hInst; extern HWND hWnd; extern RECT MainRect; extern int ChatApplNum; extern int MaxStreams; extern UCHAR * OtherNodes; // Forward Menu Handle extern char zeros[]; // For forward bitmask tests extern char *month[]; extern HWND hDebug; extern RECT MonitorRect; extern RECT DebugRect; extern HWND hMonitor; //extern HWND hConsole; extern RECT ConsoleRect; extern BOOL DeletetoRecycleBin; extern BOOL SuppressMaintEmail; extern BOOL SaveRegDuringMaint; extern BOOL SendWP; extern BOOL OverrideUnsent; extern BOOL SendNonDeliveryMsgs; struct ConsoleInfo * ConsHeader[2]; extern BOOL LogCHAT;