MainFormUnit.cpp 107 KB
Newer Older
1
2
3
4
5
6
7
8
/* Synchronet Control Panel (GUI Borland C++ Builder Project for Win32) */

/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
9
 * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html		*
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
 *																			*
 * This program 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 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

//---------------------------------------------------------------------------
#include <vcl.h>
rswindell's avatar
rswindell committed
38
#include <vcl/Registry.hpp>	/* TRegistry */
39
40
41
42
43
#pragma hdrstop
#include <winsock.h>		// IPPORT_TELNET, INADDR_ANY
#include <process.h> 		// _beginthread()
#include <io.h>
#include <stdio.h>
rswindell's avatar
rswindell committed
44
45
#include <sys/stat.h>
#include <sys/locking.h>
46
47
48
49
50
#include <fcntl.h>
#include <share.h>

#include "MainFormUnit.h"
#include "TelnetFormUnit.h"
51
#include "EventsFormUnit.h"
52
#include "ServicesFormUnit.h"
53
54
55
#include "FtpFormUnit.h"
#include "MailFormUnit.h"
#include "NodeFormUnit.h"
56

57
58
59
60
61
62
#include "StatsFormUnit.h"
#include "ClientFormUnit.h"
#include "CtrlPathDialogUnit.h"
#include "TelnetCfgDlgUnit.h"
#include "MailCfgDlgUnit.h"
#include "FtpCfgDlgUnit.h"
63
#include "ServicesCfgDlgUnit.h"
64
65
66
#include "AboutBoxFormUnit.h"
#include "CodeInputFormUnit.h"
#include "TextFileEditUnit.h"
67
#include "UserListFormUnit.h"
68
#include "PropertiesDlgUnit.h"
69
#include "ConfigWizardUnit.h"
70
#include "PreviewFormUnit.h"
71

72
#include "sbbs.h"           // unixtodstr()
73
#include "sbbs_ini.h"		// sbbs_read_ini()
74
75
76
77
#include "userdat.h"		// lastuser()

//---------------------------------------------------------------------------
#pragma package(smart_init)
rswindell's avatar
rswindell committed
78
#pragma link "trayicon"
79
#pragma link "Trayicon"
80
81
82
83
84
#pragma resource "*.dfm"
TMainForm *MainForm;

#define LOG_TIME_FMT "  m/d  hh:mm:ssa/p"

85
DWORD	MaxLogLen=20000;
86
int     threads=1;
87

88
static void thread_up(BOOL up, BOOL setuid)
89
{
90
91
	char str[128];
	static HANDLE mutex;
92

93
94
95
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
96
97
98
99
100
101
102
103
    if(up)
	    threads++;
    else if(threads>0)
    	threads--;
    sprintf(str,"Threads: %d",threads);
    AnsiString Str=AnsiString(str);
    if(MainForm->StatusBar->Panels->Items[0]->Text!=Str)
		MainForm->StatusBar->Panels->Items[0]->Text=Str;
104
    ReleaseMutex(mutex);
105
106
107
108
109
110
111
}

int sockets=0;

void socket_open(BOOL open)
{
	char 	str[128];
112
	static HANDLE mutex;
113

114
115
116
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
117
118
119
120
121
122
123
124
    if(open)
	    sockets++;
    else if(sockets>0)
    	sockets--;
    sprintf(str,"Sockets: %d",sockets);
    AnsiString Str=AnsiString(str);
    if(MainForm->StatusBar->Panels->Items[1]->Text!=Str)
		MainForm->StatusBar->Panels->Items[1]->Text=Str;
125
    ReleaseMutex(mutex);
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
}

int clients=0;
int total_clients=0;

static void client_add(BOOL add)
{
	char 	str[128];

    if(add) {
	    clients++;
        total_clients++;
    } else if(clients>0)
    	clients--;
    sprintf(str,"Clients: %d",clients);
    AnsiString Str=AnsiString(str);
    if(MainForm->StatusBar->Panels->Items[2]->Text!=Str)
		MainForm->StatusBar->Panels->Items[2]->Text=Str;

    sprintf(str,"Served: %d",total_clients);
    Str=AnsiString(str);
    if(MainForm->StatusBar->Panels->Items[3]->Text!=Str)
		MainForm->StatusBar->Panels->Items[3]->Text=Str;
}

151
static void client_on(BOOL on, int sock, client_t* client, BOOL update)
152
153
154
155
{
    char    str[128];
    int     i,j;
    time_t  t;
156
	static  HANDLE mutex;
157
158
    TListItem*  Item;

159
160
161
162
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
    WaitForSingleObject(ClientForm->ListMutex,INFINITE);
163
164
165
166
167
168
169
170
171

    /* Search for exising entry for this socket */
    for(i=0;i<ClientForm->ListView->Items->Count;i++) {
        if(ClientForm->ListView->Items->Item[i]->Caption.ToIntDef(0)==sock)
            break;
    }
    if(i>=ClientForm->ListView->Items->Count)
        i=-1;

172
173
174
175
176
    if(on) {
	    if(!update)
	        client_add(TRUE);
    } else { // Off
        client_add(FALSE);
177
178
        if(i>=0)
            ClientForm->ListView->Items->Delete(i);
179
180
        ReleaseMutex(mutex);
        ReleaseMutex(ClientForm->ListMutex);
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
        return;
    }
    if(client!=NULL && client->size==sizeof(client_t)) {
        if(i>=0) {
            Item=ClientForm->ListView->Items->Item[i];
        } else {
            Item=ClientForm->ListView->Items->Add();
            Item->Data=(void*)client->time;
            Item->Caption=sock;
        }
        Item->SubItems->Clear();
        Item->SubItems->Add(client->protocol);
        Item->SubItems->Add(client->user);
        Item->SubItems->Add(client->addr);
        Item->SubItems->Add(client->host);
        Item->SubItems->Add(client->port);
        t=time(NULL)-(time_t)Item->Data;
        sprintf(str,"%d:%02d",t/60,t%60);
        Item->SubItems->Add(str);
    }
201
202
    ReleaseMutex(mutex);
    ReleaseMutex(ClientForm->ListMutex);
203
204
205
206
}

static int bbs_lputs(char *str)
{
207
	static HANDLE mutex;
208

209
210
211
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
212

213
    while(MaxLogLen && TelnetForm->Log->Text.Length()>=MaxLogLen)
214
215
216
217
218
        TelnetForm->Log->Lines->Delete(0);

    AnsiString Line=Now().FormatString(LOG_TIME_FMT)+"  ";
    Line+=AnsiString(str).Trim();
	TelnetForm->Log->Lines->Add(Line);
219
    ReleaseMutex(mutex);
220
221
222
223
224
    return(Line.Length());
}

static void bbs_status(char *str)
{
225
	static HANDLE mutex;
226

227
228
229
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
230
231
232

	TelnetForm->Status->Caption=AnsiString(str);

233
    ReleaseMutex(mutex);
234
235
236
237
}

static void bbs_clients(int clients)
{
238
	static HANDLE mutex;
239
240
241
242
    static save_clients;

    save_clients=clients;

243
244
245
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
246
247
248
249
250
251

    TelnetForm->ProgressBar->Max
    	=(MainForm->bbs_startup.last_node
	    -MainForm->bbs_startup.first_node)+1;
	TelnetForm->ProgressBar->Position=clients;

252
    ReleaseMutex(mutex);
253
254
255
256
257
258
259
}

static void bbs_terminated(int code)
{
	Screen->Cursor=crDefault;
	MainForm->TelnetStart->Enabled=true;
	MainForm->TelnetStop->Enabled=false;
rswindell's avatar
rswindell committed
260
	MainForm->TelnetRecycle->Enabled=false;    
261
    Application->ProcessMessages();
262
263
264
265
266
267
}
static void bbs_started(void)
{
	Screen->Cursor=crDefault;
	MainForm->TelnetStart->Enabled=false;
    MainForm->TelnetStop->Enabled=true;
rswindell's avatar
rswindell committed
268
    MainForm->TelnetRecycle->Enabled=true;    
269
    Application->ProcessMessages();
270
271
272
273
274
}
static void bbs_start(void)
{
	Screen->Cursor=crAppStart;
    bbs_status("Starting");
275
276
    SAFECOPY(MainForm->bbs_startup.ctrl_dir
        ,MainForm->CtrlDirectory.c_str());
277
278
    SAFECOPY(MainForm->bbs_startup.temp_dir
        ,MainForm->TempDirectory.c_str());
279
280
    SAFECOPY(MainForm->bbs_startup.host_name
        ,MainForm->Hostname.c_str());
281
    MainForm->bbs_startup.sem_chk_freq=MainForm->SemFileCheckFrequency;
282
    MainForm->bbs_startup.js_max_bytes=MainForm->JS_MaxBytes;
283
	_beginthread((void(*)(void*))bbs_thread,0,&MainForm->bbs_startup);
284
    Application->ProcessMessages();
285
286
}

287
288
static int event_log(char *str)
{
289
	static HANDLE mutex;
290

291
292
293
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
294

295
    while(MaxLogLen && EventsForm->Log->Text.Length()>=MaxLogLen)
296
297
298
299
300
        EventsForm->Log->Lines->Delete(0);

    AnsiString Line=Now().FormatString(LOG_TIME_FMT)+"  ";
    Line+=AnsiString(str).Trim();
	EventsForm->Log->Lines->Add(Line);
301
    ReleaseMutex(mutex);
302
303
304
    return(Line.Length());
}

305
306
static int service_log(char *str)
{
307
	static HANDLE mutex;
308

309
310
311
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
312

313
    while(MaxLogLen && ServicesForm->Log->Text.Length()>=MaxLogLen)
314
315
316
317
318
        ServicesForm->Log->Lines->Delete(0);

    AnsiString Line=Now().FormatString(LOG_TIME_FMT)+"  ";
    Line+=AnsiString(str).Trim();
	ServicesForm->Log->Lines->Add(Line);
319
    ReleaseMutex(mutex);
320
321
322
    return(Line.Length());
}

rswindell's avatar
rswindell committed
323
324
static void services_status(char *str)
{
325
	static HANDLE mutex;
rswindell's avatar
rswindell committed
326

327
328
329
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
rswindell's avatar
rswindell committed
330
331
332

	ServicesForm->Status->Caption=AnsiString(str);

333
    ReleaseMutex(mutex);
rswindell's avatar
rswindell committed
334
335
336
337
338
339
340
}

static void services_terminated(int code)
{
	Screen->Cursor=crDefault;
	MainForm->ServicesStart->Enabled=true;
	MainForm->ServicesStop->Enabled=false;
341
    MainForm->ServicesRecycle->Enabled=false;
rswindell's avatar
rswindell committed
342
343
344
345
346
347
348
    Application->ProcessMessages();
}
static void services_started(void)
{
	Screen->Cursor=crDefault;
	MainForm->ServicesStart->Enabled=false;
    MainForm->ServicesStop->Enabled=true;
349
    MainForm->ServicesRecycle->Enabled=true;
rswindell's avatar
rswindell committed
350
351
352
    Application->ProcessMessages();
}

353
354
355
356
static void services_clients(int clients)
{
}

357
358
static int mail_lputs(char *str)
{
359
	static HANDLE mutex;
360
361
	static FILE* LogStream;

362
363
364
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
365
366
367
368
369

    if(str==NULL) {
        if(LogStream!=NULL)
            fclose(LogStream);
        LogStream=NULL;
370
        ReleaseMutex(mutex);
371
372
        return(0);
    }
373

374
    while(MaxLogLen && MailForm->Log->Text.Length()>=MaxLogLen)
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
        MailForm->Log->Lines->Delete(0);

    AnsiString Line=Now().FormatString(LOG_TIME_FMT)+"  ";
    Line+=AnsiString(str).Trim();
	MailForm->Log->Lines->Add(Line);

    if(MainForm->MailLogFile && MainForm->MailStop->Enabled) {
        AnsiString LogFileName
            =AnsiString(MainForm->cfg.data_dir)
            +"LOGS\\MS"
            +Now().FormatString("mmddyy")
            +".LOG";

        if(!FileExists(LogFileName)) {
            if(LogStream!=NULL) {
            	fclose(LogStream);
                LogStream=NULL;
            }
        }
        if(LogStream==NULL)
395
            LogStream=_fsopen(LogFileName.c_str(),"a",SH_DENYNONE);
396
397
398
399
400
401
402
403
404

        if(LogStream!=NULL) {
			Line=Now().FormatString("hh:mm:ss")+"  ";
		    Line+=AnsiString(str).Trim();
	        Line+="\n";
        	fwrite(AnsiString(Line).c_str(),1,Line.Length(),LogStream);
        }
	}

405
    ReleaseMutex(mutex);
406
407
408
409
410
    return(Line.Length());
}

static void mail_status(char *str)
{
411
	static HANDLE mutex;
412

413
414
415
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
416
417
418

	MailForm->Status->Caption=AnsiString(str);

419
    ReleaseMutex(mutex);
420
421
422
423
}

static void mail_clients(int clients)
{
424
	static HANDLE mutex;
425

426
427
428
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
429
430
431
432

    MailForm->ProgressBar->Max=MainForm->mail_startup.max_clients;
	MailForm->ProgressBar->Position=clients;

433
    ReleaseMutex(mutex);
434
435
436
437
438
439
440
}

static void mail_terminated(int code)
{
	Screen->Cursor=crDefault;
	MainForm->MailStart->Enabled=true;
	MainForm->MailStop->Enabled=false;
441
    MainForm->MailRecycle->Enabled=false;
442
    Application->ProcessMessages();
443
444
445
446
447
448
}
static void mail_started(void)
{
	Screen->Cursor=crDefault;
	MainForm->MailStart->Enabled=false;
    MainForm->MailStop->Enabled=true;
449
    MainForm->MailRecycle->Enabled=true;
450
    Application->ProcessMessages();
451
452
453
454
455
}
static void mail_start(void)
{
	Screen->Cursor=crAppStart;
    mail_status("Starting");
456
457
458
459
    SAFECOPY(MainForm->mail_startup.ctrl_dir
        ,MainForm->CtrlDirectory.c_str());
    SAFECOPY(MainForm->mail_startup.host_name
        ,MainForm->Hostname.c_str());
460
    MainForm->mail_startup.sem_chk_freq=MainForm->SemFileCheckFrequency;
461
	_beginthread((void(*)(void*))mail_server,0,&MainForm->mail_startup);
462
    Application->ProcessMessages();
463
464
465
466
}

static int ftp_lputs(char *str)
{
467
	static HANDLE mutex;
468
469
	static FILE* LogStream;

470
471
472
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
473
474
475
476
477

    if(str==NULL) {
        if(LogStream!=NULL)
            fclose(LogStream);
        LogStream=NULL;
478
        ReleaseMutex(mutex);
479
480
        return(0);
    }
481

482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
#if defined(_DEBUG)
    if(IsBadReadPtr(FtpForm,sizeof(void*))) {
        DebugBreak();
        return(0);
    }
    if(IsBadReadPtr(FtpForm->Log,sizeof(void*))) {
        DebugBreak();
        return(0);
    }
    if(IsBadReadPtr(FtpForm->Log->Lines,sizeof(void*))) {
        DebugBreak();
        return(0);
    }
#endif

497
    while(MaxLogLen && FtpForm->Log->Text.Length()>=MaxLogLen)
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
        FtpForm->Log->Lines->Delete(0);

    AnsiString Line=Now().FormatString(LOG_TIME_FMT)+"  ";
    Line+=AnsiString(str).Trim();
	FtpForm->Log->Lines->Add(Line);

    if(MainForm->FtpLogFile && MainForm->FtpStop->Enabled) {
        AnsiString LogFileName
            =AnsiString(MainForm->cfg.data_dir)
            +"LOGS\\FS"
            +Now().FormatString("mmddyy")
            +".LOG";

        if(!FileExists(LogFileName)) {
            FileClose(FileCreate(LogFileName));
            if(LogStream!=NULL) {
                fclose(LogStream);
                LogStream=NULL;
            }
        }
        if(LogStream==NULL)
519
            LogStream=_fsopen(LogFileName.c_str(),"a",SH_DENYNONE);
520
521
522
523
524
525
526
527
528

        if(LogStream!=NULL) {
            Line=Now().FormatString("hh:mm:ss")+"  ";
            Line+=AnsiString(str).Trim();
            Line+="\n";
        	fwrite(AnsiString(Line).c_str(),1,Line.Length(),LogStream);
        }
	}

529
    ReleaseMutex(mutex);
530
531
532
533
534
    return(Line.Length());
}

static void ftp_status(char *str)
{
535
	static HANDLE mutex;
536

537
538
539
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
540
541
542

	FtpForm->Status->Caption=AnsiString(str);

543
    ReleaseMutex(mutex);
544
545
546
547
}

static void ftp_clients(int clients)
{
548
	static HANDLE mutex;
549

550
551
552
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
553
554
555
556

    FtpForm->ProgressBar->Max=MainForm->ftp_startup.max_clients;
	FtpForm->ProgressBar->Position=clients;

557
    ReleaseMutex(mutex);
558
559
560
561
562
563
564
}

static void ftp_terminated(int code)
{
	Screen->Cursor=crDefault;
	MainForm->FtpStart->Enabled=true;
	MainForm->FtpStop->Enabled=false;
565
    MainForm->FtpRecycle->Enabled=false;
566
    Application->ProcessMessages();
567
568
569
570
571
572
}
static void ftp_started(void)
{
	Screen->Cursor=crDefault;
	MainForm->FtpStart->Enabled=false;
    MainForm->FtpStop->Enabled=true;
573
    MainForm->FtpRecycle->Enabled=true;
574
    Application->ProcessMessages();
575
576
577
578
579
}
static void ftp_start(void)
{
	Screen->Cursor=crAppStart;
    ftp_status("Starting");
580
581
    SAFECOPY(MainForm->ftp_startup.ctrl_dir
        ,MainForm->CtrlDirectory.c_str());
582
583
    SAFECOPY(MainForm->ftp_startup.temp_dir
        ,MainForm->TempDirectory.c_str());
584
585
    SAFECOPY(MainForm->ftp_startup.host_name
        ,MainForm->Hostname.c_str());
586
    MainForm->ftp_startup.sem_chk_freq=MainForm->SemFileCheckFrequency;
587
    MainForm->ftp_startup.js_max_bytes=MainForm->JS_MaxBytes;
588
	_beginthread((void(*)(void*))ftp_server,0,&MainForm->ftp_startup);
589
    Application->ProcessMessages();
590
591
592
593
594
595
596
}
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
        : TForm(Owner)
{
597
    /* Defaults */
598
    CtrlDirectory="c:\\sbbs\\ctrl\\";
599
    LoginCommand="telnet://localhost";
600
    ConfigCommand="%sscfg.exe %s -l25";
601
    JS_MaxBytes=JAVASCRIPT_MAX_BYTES;
602
    MinimizeToSysTray=false;
603
    UndockableForms=false;
604
    NodeDisplayInterval=1;  	/* seconds */
605
    ClientDisplayInterval=5;    /* seconds */
606
    SemFileCheckFrequency=5;	/* seconds */
607
    Initialized=false;
608
609
610
611

    char* p;
    if((p=getenv("SBBSCTRL"))!=NULL)
        CtrlDirectory=p;
rswindell's avatar
rswindell committed
612
    char ch=*lastchar(CtrlDirectory.c_str());
613
614
    if(ch!='\\' && ch!='/')
        CtrlDirectory+="\\";
615

616
617
618
619
    memset(&bbs_startup,0,sizeof(bbs_startup));
    bbs_startup.size=sizeof(bbs_startup);
    bbs_startup.first_node=1;
    bbs_startup.last_node=4;
620
	bbs_startup.options=BBS_OPT_XTRN_MINIMIZED|BBS_OPT_SYSOP_AVAILABLE;
621
	bbs_startup.telnet_port=IPPORT_TELNET;
622
623
624
    bbs_startup.telnet_interface=INADDR_ANY;
    bbs_startup.rlogin_port=513;
    bbs_startup.rlogin_interface=INADDR_ANY;
625
626
627
628
629
630
631
632
	bbs_startup.lputs=bbs_lputs;
    bbs_startup.status=bbs_status;
    bbs_startup.clients=bbs_clients;
    bbs_startup.started=bbs_started;
    bbs_startup.terminated=bbs_terminated;
    bbs_startup.thread_up=thread_up;
    bbs_startup.client_on=client_on;
    bbs_startup.socket_open=socket_open;
633
    bbs_startup.event_log=event_log;
634
635
636
637

    memset(&mail_startup,0,sizeof(mail_startup));
    mail_startup.size=sizeof(mail_startup);
    mail_startup.smtp_port=IPPORT_SMTP;
638
    mail_startup.relay_port=IPPORT_SMTP;
639
640
641
642
643
644
645
646
647
648
649
    mail_startup.pop3_port=110;
    mail_startup.interface_addr=INADDR_ANY;
	mail_startup.lputs=mail_lputs;
    mail_startup.status=mail_status;
    mail_startup.clients=mail_clients;
    mail_startup.started=mail_started;
    mail_startup.terminated=mail_terminated;
    mail_startup.options=MAIL_OPT_ALLOW_POP3;
    mail_startup.thread_up=thread_up;
    mail_startup.client_on=client_on;
    mail_startup.socket_open=socket_open;
650
651
    mail_startup.max_delivery_attempts=50;
    mail_startup.rescan_frequency=3600;  /* 60 minutes */
652
    mail_startup.lines_per_yield=10;
653
    mail_startup.max_clients=10;
654
    mail_startup.max_msg_size=10*1024*1024;
655
656
657
658
659
660
661
662
663
664
665
666
667

    memset(&ftp_startup,0,sizeof(ftp_startup));
    ftp_startup.size=sizeof(ftp_startup);
    ftp_startup.port=IPPORT_FTP;
    ftp_startup.interface_addr=INADDR_ANY;
	ftp_startup.lputs=ftp_lputs;
    ftp_startup.status=ftp_status;
    ftp_startup.clients=ftp_clients;
    ftp_startup.started=ftp_started;
    ftp_startup.terminated=ftp_terminated;
    ftp_startup.thread_up=thread_up;
    ftp_startup.client_on=client_on;
    ftp_startup.socket_open=socket_open;
668
669
	ftp_startup.options
        =FTP_OPT_INDEX_FILE|FTP_OPT_HTML_INDEX_FILE|FTP_OPT_ALLOW_QWK;
670
    ftp_startup.max_clients=10;
671
    strcpy(ftp_startup.index_file_name,"00index");
672
673
    strcpy(ftp_startup.html_index_file,"00index.html");
    strcpy(ftp_startup.html_index_script,"ftp-html.js");
674

rswindell's avatar
rswindell committed
675
676
677
    memset(&web_startup,0,sizeof(web_startup));
    web_startup.size=sizeof(web_startup);

678
679
680
681
    memset(&services_startup,0,sizeof(services_startup));
    services_startup.size=sizeof(services_startup);
    services_startup.interface_addr=INADDR_ANY;
    services_startup.lputs=service_log;
rswindell's avatar
rswindell committed
682
    services_startup.status=services_status;
683
    services_startup.clients=services_clients;
rswindell's avatar
rswindell committed
684
685
    services_startup.started=services_started;
    services_startup.terminated=services_terminated;
686
687
688
689
    services_startup.thread_up=thread_up;
    services_startup.client_on=client_on;
    services_startup.socket_open=socket_open;

690
691
692
693
    /* Default local "Spy Terminal" settings */
    SpyTerminalFont=new TFont;
    SpyTerminalFont->Name="Terminal";
    SpyTerminalFont->Size=9;
694
    SpyTerminalFont->Pitch=fpFixed;
695
    SpyTerminalWidth=434;
696
    SpyTerminalHeight=365;
697
    SpyTerminalKeyboardActive=true;
698
699

    Application->OnMinimize=FormMinimize;    
700
701
702
703
704
705
706
707
708
709
710
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FileExitMenuItemClick(TObject *Sender)
{
        Close();
}
void __fastcall TMainForm::FormCreate(TObject *Sender)
{
	Height=400;	// Just incase we mess it up in the IDE
    Width=700;

711
712
    // Verify SBBS.DLL version
    long bbs_ver = bbs_ver_num();
713
    if(bbs_ver < (0x31000 | 'M'-'A') || bbs_ver > (0x399<<8)) {
714
715
716
717
718
719
        char str[128];
        sprintf(str,"Incorrect SBBS.DLL Version (%lX)",bbs_ver);
    	Application->MessageBox(str,"ERROR",MB_OK|MB_ICONEXCLAMATION);
        Application->Terminate();
    }

720
721
722
723
724
725
    // Read Registry keys
	TRegistry* Registry=new TRegistry;
    if(!Registry->OpenKey(REG_KEY,true)) {
    	Application->MessageBox("Error opening registry key"
        	,REG_KEY,MB_OK|MB_ICONEXCLAMATION);
        Application->Terminate();
726
        return;
727
728
729
730
731
732
733
734
735
736
737
    }
   	if(Registry->ValueExists("MainFormTop"))
	   	Top=Registry->ReadInteger("MainFormTop");
   	if(Registry->ValueExists("MainFormLeft"))
	   	Left=Registry->ReadInteger("MainFormLeft");
   	if(Registry->ValueExists("MainFormHeight"))
	   	Height=Registry->ReadInteger("MainFormHeight");
   	if(Registry->ValueExists("MainFormWidth"))
	   	Width=Registry->ReadInteger("MainFormWidth");
    else
        WindowState=wsMaximized;    // Default to fullscreen
738
739
740
741
742
743
744
745
   	if(Registry->ValueExists("SpyTerminalWidth"))
	   	SpyTerminalWidth=Registry->ReadInteger("SpyTerminalWidth");
   	if(Registry->ValueExists("SpyTerminalHeight"))
	   	SpyTerminalHeight=Registry->ReadInteger("SpyTerminalHeight");
   	if(Registry->ValueExists("SpyTerminalFontName"))
	   	SpyTerminalFont->Name=Registry->ReadString("SpyTerminalFontName");
   	if(Registry->ValueExists("SpyTerminalFontSize"))
	   	SpyTerminalFont->Size=Registry->ReadInteger("SpyTerminalFontSize");
746
747
748
   	if(Registry->ValueExists("SpyTerminalKeyboardActive"))
	   	SpyTerminalKeyboardActive
            =Registry->ReadBool("SpyTerminalKeyboardActive");
749

750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
    Registry->CloseKey();
    delete Registry;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormShow(TObject *Sender)
{
	StartupTimer->Enabled=true;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ViewToolbarMenuItemClick(TObject *Sender)
{
	Toolbar->Visible=!ViewToolbarMenuItem->Checked;
    ViewToolbarMenuItem->Checked=Toolbar->Visible;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action)
{
768
    UpTimer->Enabled=false; /* Stop updating the status bar */
769

770
771
    if(TrayIcon->Visible)           /* minimized to tray? */
        TrayIcon->Visible=false;    /* restore to avoid crash */
772
        
773
    /* This is necessary to save form sizes/positions */
774
775
776
777
    if(Initialized) /* Don't overwrite registry settings with defaults */
        SaveSettings(Sender);

	StatusBar->Panels->Items[4]->Text="Closing...";
778
    time_t start=time(NULL);
rswindell's avatar
rswindell committed
779
780
	while(TelnetStop->Enabled || MailStop->Enabled || FtpStop->Enabled
    	|| ServicesStop->Enabled) {
781
782
783
        if(time(NULL)-start>30)
            break;
        Application->ProcessMessages();
784
        YIELD();
785
    }
rswindell's avatar
rswindell committed
786
787
788
789
    /* Extra time for callbacks to be called by child threads */
    start=time(NULL);
    while(time(NULL)<start+2) {
        Application->ProcessMessages();
790
        YIELD();
rswindell's avatar
rswindell committed
791
    }
792
}
rswindell's avatar
rswindell committed
793
//---------------------------------------------------------------------------
794
795
796

void __fastcall TMainForm::FormCloseQuery(TObject *Sender, bool &CanClose)
{
797
	CanClose=false;
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821

    if(TelnetStop->Enabled) {
     	if(TelnetForm->ProgressBar->Position
	        && Application->MessageBox("Shut down the Telnet Server?"
        	,"Telnet Server In Use", MB_OKCANCEL)!=IDOK)
            return;
        TelnetStopExecute(Sender);
	}

    if(MailStop->Enabled) {
    	if(MailForm->ProgressBar->Position
    		&& Application->MessageBox("Shut down the Mail Server?"
        	,"Mail Server In Use", MB_OKCANCEL)!=IDOK)
            return;
        MailStopExecute(Sender);
    }

    if(FtpStop->Enabled) {
    	if(FtpForm->ProgressBar->Position
    		&& Application->MessageBox("Shut down the FTP Server?"
	       	,"FTP Server In Use", MB_OKCANCEL)!=IDOK)
            return;
        FtpStopExecute(Sender);
    }
rswindell's avatar
rswindell committed
822
    ServicesStopExecute(Sender);
823
824

    CanClose=true;
825
826
827
828
829
830
831
832
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TelnetStartExecute(TObject *Sender)
{
	bbs_start();
}
//---------------------------------------------------------------------------
rswindell's avatar
rswindell committed
833
834
835
836
837
void __fastcall TMainForm::ServicesStartExecute(TObject *Sender)
{
	Screen->Cursor=crAppStart;
    services_status("Starting");

838
839
840
841
    SAFECOPY(MainForm->services_startup.ctrl_dir
        ,MainForm->CtrlDirectory.c_str());
    SAFECOPY(MainForm->services_startup.host_name
        ,MainForm->Hostname.c_str());
842
    MainForm->services_startup.sem_chk_freq=SemFileCheckFrequency;        
843
    MainForm->services_startup.js_max_bytes=MainForm->JS_MaxBytes;
rswindell's avatar
rswindell committed
844
845
846
847
848
849
850
851
852
853
854
855
856
	_beginthread((void(*)(void*))services_thread,0,&MainForm->services_startup);
    Application->ProcessMessages();
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ServicesStopExecute(TObject *Sender)
{
	Screen->Cursor=crAppStart;
    services_status("Terminating");
	services_terminate();
    Application->ProcessMessages();
}
//---------------------------------------------------------------------------
857
858
859
860
861
862

void __fastcall TMainForm::TelnetStopExecute(TObject *Sender)
{
	Screen->Cursor=crAppStart;
    bbs_status("Terminating");
	bbs_terminate();
863
    Application->ProcessMessages();
864
865
866
867
868
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::TelnetConfigureExecute(TObject *Sender)
{
869
870
871
872
    static inside;
    if(inside) return;
    inside=true;

873
874
875
	Application->CreateForm(__classid(TTelnetCfgDlg), &TelnetCfgDlg);
	TelnetCfgDlg->ShowModal();
    delete TelnetCfgDlg;
876
877
    
    inside=false;
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
}
//---------------------------------------------------------------------------


void __fastcall TMainForm::NodeListStartExecute(TObject *Sender)
{
	NodeForm->Timer->Enabled=true;
    NodeListStart->Enabled=false;
    NodeListStop->Enabled=true;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::NodeListStopExecute(TObject *Sender)
{
    NodeForm->Timer->Enabled=false;
    NodeListStart->Enabled=true;
    NodeListStop->Enabled=false;
}
//---------------------------------------------------------------------------


void __fastcall TMainForm::MailConfigureExecute(TObject *Sender)
{
901
902
903
904
    static inside;
    if(inside) return;
    inside=true;

905
906
907
	Application->CreateForm(__classid(TMailCfgDlg), &MailCfgDlg);
	MailCfgDlg->ShowModal();
    delete MailCfgDlg;
908
909

    inside=false;
910
911
912
913
914
915
916
917
918
919
920
921
922
923
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::MailStartExecute(TObject *Sender)
{
    mail_start();
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::MailStopExecute(TObject *Sender)
{
	Screen->Cursor=crAppStart;
    mail_status("Terminating");
	mail_terminate();
924
    Application->ProcessMessages();
925
926
927
928
929
930
931
932
933
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ViewTelnetExecute(TObject *Sender)
{
	TelnetForm->Visible=!TelnetForm->Visible;
    ViewTelnet->Checked=TelnetForm->Visible;
}
//---------------------------------------------------------------------------
934
935
936
937
938
939
void __fastcall TMainForm::ViewEventsExecute(TObject *Sender)
{
	EventsForm->Visible=!EventsForm->Visible;
    ViewEvents->Checked=EventsForm->Visible;
}
//---------------------------------------------------------------------------
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972

void __fastcall TMainForm::ViewNodesExecute(TObject *Sender)
{
	NodeForm->Visible=!NodeForm->Visible;
    ViewNodes->Checked=NodeForm->Visible;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ViewMailServerExecute(TObject *Sender)
{
	MailForm->Visible=!MailForm->Visible;
    ViewMailServer->Checked=MailForm->Visible;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::ViewFtpServerExecute(TObject *Sender)
{
	FtpForm->Visible=!FtpForm->Visible;
    ViewFtpServer->Checked=FtpForm->Visible;
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::FtpStartExecute(TObject *Sender)
{
	ftp_start();
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::FtpStopExecute(TObject *Sender)
{
	Screen->Cursor=crAppStart;
    ftp_status("Terminating");
	ftp_terminate();
973
    Application->ProcessMessages();
974
975
976
977
978
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::FtpConfigureExecute(TObject *Sender)
{
979
980
981
982
    static inside;
    if(inside) return;
    inside=true;

983
984
985
	Application->CreateForm(__classid(TFtpCfgDlg), &FtpCfgDlg);
	FtpCfgDlg->ShowModal();
    delete FtpCfgDlg;
986
987

    inside=false;
988
989
990
991
992
993
994
995
}
//---------------------------------------------------------------------------


void __fastcall TMainForm::BBSConfigureMenuItemClick(TObject *Sender)
{
	char str[256];

996
    sprintf(str,ConfigCommand.c_str()
997
998
999
1000
    	,cfg.exec_dir, cfg.ctrl_dir);
    STARTUPINFO startup_info={0};
    PROCESS_INFORMATION process_info;
    startup_info.cb=sizeof(startup_info);
For faster browsing, not all history is shown. View entire blame