1 Unit PTMsg; 2 3 InterFace 4 5 Uses 6 DOS, 7 Types, GeneralP, 8 Log, MKMsgAbs, MKGlobT, 9 PTRegKey, TickType, TickCons, PTVar, PTProcs; 10 11 Procedure ProcessMail; 12 13 Procedure ConnectArea(Name: String; DReScan: Boolean; RSParams: String); 14 Procedure ReScan(Name, Params: String); 15 Procedure DisConnectArea(Name: String); 16 Procedure SendRsp(_Type: Word; Params: String); 17 Procedure SetActive(Act: Boolean); 18 Procedure SetPack(Pack: String); 19 Procedure AKAMatch(InAddr: TNetAddr; var OutAddr: TNetAddr); 20 21 Implementation 22 23 Procedure ProcessMail; 24 Var 25 MKAddr: AddrType; 26 A1: TNetAddr; 27 Pwd: String; 28 s1: String; 29 DoReScan: Boolean; 30 ReScanParams: String; 31 DoDelReq: Boolean; 32 Body: PString80List; 33 CurBody: PString80List; 34 35 Begin 36 DoReScan := False; 37 ReScanParams := ''; 38 DoDelReq := Cfg^.DelReq; 39 With NM^ do 40 Begin 41 LogSetCurLevel(LogHandle, 3); 42 LogWriteLn(LogHandle, 'Processing msg #'+IntToStr(GetMsgNum)); 43 44 MsgTxtStartUp; 45 SetRcvd(True); 46 ReWriteHdr; 47 48 GetOrig(MKAddr); 49 MKAddr2TNetAddr(MKAddr, A1); 50 LogSetCurLevel(LogHandle, 2); 51 LogWriteLn(LogHandle, 'From: '+GetFrom+' ('+Addr2Str(A1)+')'); 52 53 GetDest(MKAddr); 54 MKAddr2TNetAddr(MKAddr, A1); 55 LogSetCurLevel(LogHandle, 5); 56 LogWriteLn(LogHandle, 'To: '+GetTo+' ('+Addr2Str(A1)+')'); 57 58 GetOrig(MKAddr); 59 MKAddr2TNetAddr(MKAddr, A1); 60 Pwd := UpStr(GetSubj); 61 62 If ((A1.Zone = 0) and (A1.Net = 0) and (A1.Node = 0)) then 63 Begin 64 LogSetCurLevel(LogHandle, 2); 65 LogWriteLn(LogHandle, 'Unlisted sender: '+Addr2Str(A1)); 66 SendRsp(rs_Unlisted, ''); 67 Exit; 68 End; 69 CurUser := Cfg^.Users; 70 While (not CompAddr(CurUser^.Addr, A1)) and (CurUser^.Next <> Nil) do 71 CurUser := CurUser^.Next; 72 If (not CompAddr(CurUser^.Addr, A1)) then 73 Begin 74 LogSetCurLevel(LogHandle, 2); 75 LogWriteLn(LogHandle, 'Unlisted sender: '+Addr2Str(A1)); 76 SendRsp(rs_Unlisted, ''); 77 Exit; 78 End; 79 If (UpStr(CurUser^.Pwd) <> Pwd) then 80 Begin 81 LogSetCurLevel(LogHandle, 2); 82 LogWriteLn(LogHandle, 'Wrong password! User: "'+CurUser^.Pwd+'" Msg: "'+Pwd+'"'); 83 SendRsp(rs_WrongPwd, Pwd); 84 Exit; 85 End; 86 87 {read mail into stringlist} 88 New(Body); Body^.s := ''; Body^.Next := NIL; 89 CurBody := Body; 90 While not EOM do 91 Begin 92 New(CurBody^.Next); 93 CurBody := CurBody^.Next; 94 CurBody^.Next := NIL; 95 CurBody^.s := GetString; 96 End; 97 CurBody := Body; 98 99 While (CurBody^.Next <> NIL) do 100 Begin 101 CurBody := CurBody^.Next; 102 s1 := UpStr(CurBody^.s); 103 s1 := KillTrailingSpcs(KillLeadingSpcs(s1)); 104 If (s1[1] = #1) then Continue; 105 If (s1 = '') then Continue; 106 If (s1 = #10) then Continue; 107 If (s1[1] = '%') then 108 Begin 109 Delete(s1, 1, 1); 110 If Pos('RESCAN', s1) = 1 then 111 Begin 112 DoRescan := True; 113 If (Length(s1) > 7) then ReScanParams := Copy(s1, 8, Length(s1) - 8) 114 Else ReScanParams := ''; 115 End 116 Else If Pos('PAUSE', s1) = 1 then 117 Begin 118 If ((CurUser^.May and um_Pause) = 0) then 119 Begin 120 LogSetCurLevel(LogHandle, 2); 121 LogWriteLn(LogHandle, 'User isn''t allowed to pause'); 122 SendRsp(rs_NoPause, ''); 123 End 124 Else 125 Begin 126 SetActive(False); 127 LogSetCurLevel(LogHandle, 3); 128 LogWriteLn(LogHandle, 'paused.'); 129 SendRsp(rs_Pause, ''); 130 End; 131 End 132 Else If Pos('RESUME', s1) = 1 then 133 Begin 134 If ((CurUser^.May and um_Pause) = 0) then 135 Begin 136 LogSetCurLevel(LogHandle, 2); 137 LogWriteLn(LogHandle, 'User isn''t allowed to resume'); 138 SendRsp(rs_NoPause, ''); 139 End 140 Else 141 Begin 142 SetActive(True); 143 LogSetCurLevel(LogHandle, 3); 144 LogWriteLn(LogHandle, 'resumed.'); 145 SendRsp(rs_Resume, ''); 146 End; 147 End 148 Else If Pos('PACK', s1) = 1 then 149 Begin 150 If ((CurUser^.May and um_Compression) = 0) then 151 Begin 152 LogSetCurLevel(LogHandle, 2); 153 LogWriteLn(LogHandle, 'User isn''t allowed change compression'); 154 SendRsp(rs_NoComp, ''); 155 End 156 Else 157 Begin 158 Delete(s1, 1, 5); 159 SetPack(s1); 160 End; 161 End 162 Else If Pos('COMPRESSION', s1) = 1 then 163 Begin 164 If ((CurUser^.May and um_Compression) = 0) then 165 Begin 166 LogSetCurLevel(LogHandle, 2); 167 LogWriteLn(LogHandle, 'User isn''t allowed change compression'); 168 SendRsp(rs_NoComp, ''); 169 End 170 Else 171 Begin 172 Delete(s1, 1, 12); 173 SetPack(s1); 174 End; 175 End 176 Else If Pos('COMPRESS', s1) = 1 then 177 Begin 178 If ((CurUser^.May and um_Compression) = 0) then 179 Begin 180 LogSetCurLevel(LogHandle, 2); 181 LogWriteLn(LogHandle, 'User isn''t allowed change compression'); 182 SendRsp(rs_NoComp, ''); 183 End 184 Else 185 Begin 186 Delete(s1, 1, 9); 187 SetPack(s1); 188 End; 189 End 190 Else If (Pos('LIST', s1) = 1) then 191 Begin 192 SendRsp(rs_List, ''); 193 LogSetCurLevel(LogHandle, 3); 194 LogWriteLn(LogHandle, 'sent list of available areas'); 195 End 196 Else If (Pos('QUERY', s1) = 1) then 197 Begin 198 SendRsp(rs_Query, ''); 199 LogSetCurLevel(LogHandle, 3); 200 LogWriteLn(LogHandle, 'sent list of connected areas'); 201 End 202 Else If (Pos('UNLINKED', s1) = 1) then 203 Begin 204 SendRsp(rs_Unlinked, ''); 205 LogSetCurLevel(LogHandle, 3); 206 LogWriteLn(LogHandle, 'sent list of disconnected areas'); 207 End 208 Else If (Pos('HELP', s1) = 1) then 209 Begin 210 SendRsp(rs_Help, ''); 211 LogSetCurLevel(LogHandle, 3); 212 LogWriteLn(LogHandle, 'sent help.'); 213 End 214 Else If (Pos('QUIT', s1) = 1) then 215 Begin 216 Break; 217 End 218 Else If (Pos('NOTE', s1) = 1) then 219 Begin 220 Break; 221 LogSetCurLevel(LogHandle, 3); 222 LogWriteLn(LogHandle, '%NOTE'); 223 DoDelReq := False; 224 End 225 Else 226 Begin 227 LogSetCurLevel(LogHandle, 2); 228 LogWriteLn(LogHandle, 'Unknown command "'+s1+'"'); 229 SendRsp(rs_UnKnownCmd, s1); 230 SendRsp(rs_Help, ''); 231 End; 232 End 233 Else If (Copy(s1, 1, 3) = '---') then 234 Begin 235 Break; 236 End 237 Else If (s1[1] = '-') then 238 Begin 239 Delete(s1, 1, 1); 240 s1 := KillTrailingSpcs(KillLeadingSpcs(s1)); 241 If (s1[1] <> '-') then 242 Begin 243 If ((CurUser^.May and um_DisConnect) = 0) then 244 Begin 245 LogSetCurLevel(LogHandle, 2); 246 LogWriteLn(LogHandle, 'User isn''t allowed to disconnect areas'); 247 SendRsp(rs_NoDisConnect, ''); 248 End 249 Else 250 Begin 251 DisConnectArea(s1); 252 End; 253 End; 254 End 255 Else If (s1[1] = '=') then 256 Begin 257 Delete(s1, 1, 1); 258 s1 := KillTrailingSpcs(KillLeadingSpcs(s1)); 259 If ((CurUser^.May and um_Connect) = 0) then 260 Begin 261 LogSetCurLevel(LogHandle, 2); 262 LogWriteLn(LogHandle, 'User isn''t allowed to connect areas'); 263 SendRsp(rs_NoConnect, ''); 264 End 265 Else 266 Begin 267 ConnectArea(s1, True, ReScanParams); 268 End; 269 End 270 Else If (Pos('...', s1) <> 1) then 271 Begin 272 If (s1[1] = '+') then Delete(s1, 1, 1); 273 s1 := KillTrailingSpcs(KillLeadingSpcs(s1)); 274 If ((CurUser^.May and um_Connect) = 0) then 275 Begin 276 LogSetCurLevel(LogHandle, 2); 277 LogWriteLn(LogHandle, 'User isn''t allowed to connect areas'); 278 SendRsp(rs_NoConnect, ''); 279 End 280 Else 281 Begin 282 ConnectArea(s1, DoRescan, ReScanParams); 283 End; 284 End; 285 End; 286 287 CurBody := Body; 288 While (CurBody <> NIL) do 289 Begin 290 Body := CurBody^.Next; 291 Dispose(CurBody); 292 CurBody := Body; 293 End; 294 295 If Cfg^.DelReq then DeleteMsg; 296 End; 297 End; 298 299 Procedure ConnectArea(Name: String; DReScan: Boolean; RSParams: String); 300 Var 301 DoReScan: Boolean; 302 i: LongInt; 303 s: String; 304 ReScanParams: String; 305 A1: TNetAddr; 306 Found: Boolean; 307 DoAddArea: Boolean; 308 SecFault: Boolean; 309 310 Begin 311 DoReScan := DReScan; 312 ReScanParams := RSParams; 313 Found := False; 314 DoAddArea := False; 315 SecFault := False; 316 s := Name; 317 i := Pos(',R', s); 318 If (i > 0) then 319 Begin 320 DoReScan := True; 321 If (i < (Length(s) - 3)) then ReScanParams := Copy(s, i+3, Length(s) - i - 3); 322 s := Copy(s, 1, i - 1); 323 End; 324 CurArea := Cfg^.Areas; 325 While (CurArea^.Next <> Nil) do 326 Begin 327 While ((CurArea^.Next <> Nil) and (not Match(UpStr(CurArea^.Name), s))) do CurArea := CurArea^.Next; 328 If not (CurArea^.Group in CurUser^.Groups) then 329 Begin 330 If CurArea^.Next <> Nil then 331 Begin 332 CurArea := CurArea^.Next; 333 Continue; 334 End; 335 SecFault := True; 336 End 337 Else 338 Begin 339 If (CurArea^.Level > CurUser^.Level) then 340 Begin 341 If CurArea^.Next <> Nil then 342 Begin 343 CurArea := CurArea^.Next; 344 Continue; 345 End; 346 SecFault := True; 347 End 348 Else 349 Begin 350 If ((CurArea^.Flags and fa_RemoteChange) = 0) then 351 Begin 352 LogSetCurLevel(LogHandle, 2); 353 LogWriteLn(LogHandle, 'Area "'+CurArea^.Name+'" may not be linked remotely'); 354 SendRsp(rs_NoRemote, CurArea^.Name); 355 If CurArea^.Next <> Nil then 356 Begin 357 CurArea := CurArea^.Next; 358 Continue; 359 End; 360 SecFault := True; 361 End; 362 End; 363 End; 364 If (not Match(UpStr(CurArea^.Name), s)) or SecFault then 365 Begin 366 If not Found then 367 Begin 368 LogSetCurLevel(LogHandle, 2); 369 LogWriteLn(LogHandle, 'Area "'+s+'" not found'); 370 SendRsp(rs_UnKnownArea, s); 371 End; 372 End 373 Else 374 Begin 375 Found := True; 376 CurConnUser := CurArea^.Users; 377 DoAddArea := False; 378 If (CurConnUser <> NIL) then 379 Begin 380 While ((CurConnUser^.Next <> Nil) and (CurConnUser^.User <> CurUser)) do CurConnUser := CurConnUser^.Next; 381 If (CurConnUser^.User <> CurUser) then 382 Begin 383 New(CurConnUser^.Next); 384 CurConnUser^.Next^.Prev := CurConnUser; 385 CurConnUser := CurConnUser^.Next; 386 CurConnUser^.Next := Nil; 387 CurConnUser^.User := CurUser; 388 CurConnUser^.Receive := CurUser^.Receives; 389 CurConnUser^.Send := CurUser^.Sends; 390 DoAddArea := True; 391 End; 392 End 393 Else 394 Begin 395 New(CurArea^.Users); 396 CurConnUser := CurArea^.Users; 397 CurConnUser^.Prev := NIL; 398 CurConnUser^.Next := NIL; 399 CurConnUser^.User := CurUser; 400 CurConnUser^.Receive := CurUser^.Receives; 401 CurConnUser^.Send := CurUser^.Sends; 402 DoAddArea := True; 403 End; 404 If DoAddArea then 405 Begin 406 DoAddArea := False; 407 With Ini do 408 Begin 409 SetSection('USER'); 410 Repeat 411 While (UpStr(ReSecEnName) <> 'ADDR') do If not SetNextOpt then Break; 412 If (UpStr(ReSecEnName) <> 'ADDR') then Break; 413 Str2Addr(ReSecEnValue, A1); 414 If CompAddr(A1, CurUser^.Addr) then Break; 415 SetNextOpt; 416 Until CompAddr(A1, CurUser^.Addr); 417 If (not CompAddr(A1, CurUser^.Addr)) then 418 Begin 419 LogSetCurLevel(LogHandle, 1); 420 LogWriteLn(LogHandle, 'User "'+CurUser^.Name+'" ('+Addr2Str(CurUser^.Addr)+') not found in ConfigFile!'); 421 End 422 Else 423 Begin 424 LogSetCurLevel(LogHandle, 4); 425 LogWriteLn(LogHandle, 'Connected to '+CurArea^.Name); 426 SendRsp(rs_Connect, CurArea^.Name); 427 InsertSecEntry('Area', CurArea^.Name, ''); 428 End; 429 End; 430 End 431 Else 432 Begin 433 If (Pos('*', Name) = 0) and (Pos('?', Name) = 0) then 434 Begin 435 LogSetCurLevel(LogHandle, 4); 436 LogWriteLn(LogHandle, 'Already connected to '+s); 437 SendRsp(rs_AlreadyConn, s); 438 End; 439 End; 440 End; 441 If (CurArea^.Next <> Nil) then CurArea := CurArea^.Next; 442 End; 443 If DoReScan then ReScan(s, ReScanParams); 444 End; 445 446 Procedure DisConnectArea(Name: String); 447 Var 448 A1: TNetAddr; 449 s: String; 450 Found: Boolean; 451 SecFault: Boolean; 452 453 Begin 454 CurArea := Cfg^.Areas; 455 Found := False; 456 SecFault := False; 457 While (CurArea^.Next <> Nil) do 458 Begin 459 While ((CurArea^.Next <> Nil) and (not Match(UpStr(CurArea^.Name), Name))) do CurArea := CurArea^.Next; 460 If ((CurArea^.Flags and fa_RemoteChange) = 0) then 461 Begin 462 LogSetCurLevel(LogHandle, 2); 463 LogWriteLn(LogHandle, 'Area "'+CurArea^.Name+'" may not be unlinked remotely'); 464 SendRsp(rs_NoRemote, CurArea^.Name); 465 If CurArea^.Next <> Nil then 466 Begin 467 CurArea := CurArea^.Next; 468 Continue; 469 End; 470 SecFault := True; 471 End; 472 If ((CurArea^.Flags and fa_Mandatory) > 0) then 473 Begin 474 LogSetCurLevel(LogHandle, 2); 475 LogWriteLn(LogHandle, 'Area "'+CurArea^.Name+'" is mandatory'); 476 SendRsp(rs_Mandatory, CurArea^.Name); 477 If CurArea^.Next <> Nil then 478 Begin 479 CurArea := CurArea^.Next; 480 Continue; 481 End; 482 SecFault := True; 483 End; 484 If (not Match(UpStr(CurArea^.Name), Name)) or SecFault then 485 Begin 486 If (not Found) and (not SecFault) then 487 Begin 488 LogSetCurLevel(LogHandle, 2); 489 LogWriteLn(LogHandle, 'Area "'+Name+'" not found'); 490 SendRsp(rs_UnKnownArea, Name); 491 End; 492 End 493 Else 494 Begin 495 Found := True; 496 If (CurArea^.Users <> Nil) then 497 Begin 498 CurConnUser := CurArea^.Users; 499 While ((CurConnUser^.Next <> Nil) and (CurConnUser^.User <> CurUser)) do CurConnUser := CurConnUser^.Next; 500 If (CurConnUser^.User = CurUser) then 501 Begin 502 If (CurConnUser^.Next <> Nil) then 503 Begin 504 If (CurConnUser = CurArea^.Users) then 505 Begin 506 CurArea^.Users := CurConnUser^.Next; 507 End 508 Else 509 Begin 510 CurConnUser^.Prev^.Next := CurConnUser^.Next; 511 CurConnUser^.Next^.Prev := CurConnUser^.Prev; 512 End; 513 End 514 Else 515 Begin 516 If (CurConnUser = CurArea^.Users) then 517 Begin 518 CurArea^.Users := Nil; 519 End 520 Else 521 Begin 522 CurConnUser^.Prev^.Next := Nil; 523 End; 524 End; 525 Dispose(CurConnUser); 526 CurConnUser := NIL; 527 With Ini do 528 Begin 529 SetSection('USER'); 530 Repeat 531 While (UpStr(ReSecEnName) <> 'ADDR') do If not SetNextOpt then Break; 532 If (UpStr(ReSecEnName) <> 'ADDR') then Break; 533 Str2Addr(ReSecEnValue, A1); 534 If CompAddr(A1, CurUser^.Addr) then Break; 535 SetNextOpt; 536 Until CompAddr(A1, CurUser^.Addr); 537 If (not CompAddr(A1, CurUser^.Addr)) then 538 Begin 539 LogSetCurLevel(LogHandle, 1); 540 LogWriteLn(LogHandle, 'User "'+CurUser^.Name+'" ('+Addr2Str(CurUser^.Addr)+') not found in ConfigFile!'); 541 End 542 Else 543 Begin 544 Repeat 545 If not SetNextOpt then Break; 546 s := UpStr(ReSecEnValue); 547 If (Pos(',', s) <> 0) then s := Copy(s, 1, Pos(',', s) - 1); 548 Until ((UpStr(ReSecEnName) = 'AREA') and Match(s, UpStr(Name))); 549 If Match(s, UpStr(Name)) then 550 Begin 551 LogSetCurLevel(LogHandle, 4); 552 LogWriteLn(LogHandle, 'DisConnected from '+s); 553 SendRsp(rs_DisConnect, s); 554 DelCurEntry(False); 555 End; 556 End; 557 End; 558 End 559 Else 560 Begin 561 If (Pos('*', Name) = 0) and (Pos('?', Name) = 0) then 562 Begin 563 LogSetCurLevel(LogHandle, 4); 564 LogWriteLn(LogHandle, 'Not connected to '+Name); 565 SendRsp(rs_NotConn, Name); 566 End; 567 End; 568 End 569 Else 570 Begin 571 If (Pos('*', Name) = 0) and (Pos('?', Name) = 0) then 572 Begin 573 LogSetCurLevel(LogHandle, 4); 574 LogWriteLn(LogHandle, 'Not connected to '+Name); 575 SendRsp(rs_NotConn, Name); 576 End; 577 End; 578 End; 579 If (CurArea^.Next <> Nil) then CurArea := CurArea^.Next; 580 End; 581 End; 582 583 Procedure ReScan(Name, Params: String); 584 Begin 585 If ((CurUser^.May and um_Rescan) = 0) then 586 Begin 587 LogSetCurLevel(LogHandle, 2); 588 LogWriteLn(LogHandle, 'User isn''t allowed to rescan areas'); 589 SendRsp(rs_NoReScan, ''); 590 End 591 Else 592 Begin 593 LogSetCurLevel(LogHandle, 3); 594 LogWriteLn(LogHandle, 'Rescan not implemented.'); 595 SendRsp(rs_NotImplemented, 'Rescan'); 596 End; 597 End; 598 599 Procedure SendRsp(_Type: Word; Params: String); 600 Var 601 s: String; 602 DT: TimeTyp; 603 MKAddr: AddrType; 604 A1: TNetAddr; 605 606 Procedure SendList; 607 Var 608 CA: PArea; 609 CG: Byte; 610 CCG: Byte; 611 Found: Byte; 612 613 Begin 614 With NM2^ do 615 Begin 616 DoStringLn('List of areas available to you:'); 617 DoStringLn(''); 618 For CG := 1 to 255 do If (CG in CurUser^.Groups) then 619 Begin 620 Found := 0; 621 For CCG := 1 to Cfg^.NumGroups do If (Cfg^.Groups[CCG].Index = CG) then 622 Begin Found := CCG; Break; End; 623 If (Found > 0) then DoStringLn('Group '+Cfg^.Groups[Found].Name) 624 Else DoStringLn('Group <unknown>'); 625 CA := Cfg^.Areas; 626 If (CA^.Group = CG) and 627 (CA^.Level <= CurUser^.Level) then 628 DoStringLn(CA^.Name+Copy(Leer, 1, 30-Length(CA^.Name))+CA^.Desc); 629 Repeat 630 CA := CA^.Next; 631 If (CA^.Group = CG) and ((CA^.Flags and fa_Hidden) = 0) and 632 (CA^.Level <= CurUser^.Level) then 633 DoStringLn(CA^.Name+Copy(Leer, 1, 30-Length(CA^.Name))+CA^.Desc); 634 Until (CA^.Next = Nil); 635 DoStringLn(''); 636 End; 637 End; 638 End; 639 640 Procedure SendQuery; 641 Var 642 CA: PArea; 643 CG: Byte; 644 CCG: Byte; 645 Found: Byte; 646 WroteGroup: Boolean; 647 CheckConnnull648 Function CheckConn: Boolean; 649 Var 650 CCU: PConnectedUser; 651 652 Begin 653 CheckConn := False; 654 If (CA^.Users = NIL) then Exit; 655 CCU := CA^.Users; 656 If (CCU^.User = CurUser) then 657 Begin 658 CheckConn := True; 659 Exit; 660 End; 661 If (CCU^.Next = NIL) then Exit; 662 Repeat 663 CCU := CCU^.Next; 664 If (CCU^.User = CurUser) then 665 Begin 666 CheckConn := True; 667 Exit 668 End; 669 Until (CCU^.Next = NIL); 670 End; 671 672 Begin 673 With NM2^ do 674 Begin 675 DoStringLn('List of connected areas:'); 676 DoStringLn(''); 677 For CG := 1 to 255 do 678 Begin 679 WroteGroup := False; 680 CA := Cfg^.Areas; 681 If ((CA^.Group = CG) and CheckConn) then 682 Begin 683 If not WroteGroup then 684 Begin 685 WroteGroup := True; 686 Found := 0; 687 For CCG := 1 to Cfg^.NumGroups do If (Cfg^.Groups[CCG].Index = CG) then 688 Begin Found := CCG; Break; End; 689 If (Found > 0) then DoStringLn('Group '+Cfg^.Groups[Found].Name) 690 Else DoStringLn('Group <unknown>'); 691 End; 692 DoStringLn(CA^.Name+Copy(Leer, 1, 30-Length(CA^.Name))+CA^.Desc); 693 End; 694 Repeat 695 CA := CA^.Next; 696 If ((CA^.Group = CG) and CheckConn) then 697 Begin 698 If not WroteGroup then 699 Begin 700 WroteGroup := True; 701 Found := 0; 702 For CCG := 1 to Cfg^.NumGroups do If (Cfg^.Groups[CCG].Index = CG) then 703 Begin Found := CCG; Break; End; 704 If (Found > 0) then DoStringLn('Group '+Cfg^.Groups[Found].Name) 705 Else DoStringLn('Group <unknown>'); 706 End; 707 DoStringLn(CA^.Name+Copy(Leer, 1, 30-Length(CA^.Name))+CA^.Desc); 708 End; 709 Until (CA^.Next = Nil); 710 If WroteGroup then DoStringLn(''); 711 End; 712 End; 713 End; 714 715 Procedure SendUnlinked; 716 Var 717 CA: PArea; 718 CG: Byte; 719 CCG: Byte; 720 Found: Byte; 721 WroteGroup: Boolean; 722 CheckConnnull723 Function CheckConn: Boolean; 724 Var 725 CCU: PConnectedUser; 726 727 Begin 728 CheckConn := False; 729 If (CA^.Users = NIL) then Exit; 730 CCU := CA^.Users; 731 If (CCU^.User = CurUser) then 732 Begin 733 CheckConn := True; 734 Exit; 735 End; 736 If (CCU^.Next = NIL) then Exit; 737 Repeat 738 CCU := CCU^.Next; 739 If (CCU^.User = CurUser) then 740 Begin 741 CheckConn := True; 742 Exit 743 End; 744 Until (CCU^.Next = NIL); 745 End; 746 747 Begin 748 With NM2^ do 749 Begin 750 DoStringLn('List of disconnected areas:'); 751 DoStringLn(''); 752 For CG := 1 to 255 do If (CG in CurUser^.Groups) then 753 Begin 754 CA := Cfg^.Areas; 755 WroteGroup := False; 756 If (CA^.Group = CG) and (CA^.Level <= CurUser^.Level) and 757 (not CheckConn) then 758 Begin 759 If not WroteGroup then 760 Begin 761 WroteGroup := True; 762 Found := 0; 763 For CCG := 1 to Cfg^.NumGroups do If (Cfg^.Groups[CCG].Index = CG) then 764 Begin Found := CCG; Break; End; 765 If (Found > 0) then DoStringLn('Group '+Cfg^.Groups[Found].Name) 766 Else DoStringLn('Group <unknown>'); 767 End; 768 DoStringLn(CA^.Name+Copy(Leer, 1, 30-Length(CA^.Name))+CA^.Desc); 769 End; 770 771 Repeat 772 CA := CA^.Next; 773 If (CA^.Group = CG) and (CA^.Level <= CurUser^.Level) and 774 ((CA^.Flags and fa_Hidden) = 0) and (not CheckConn) then 775 Begin 776 If not WroteGroup then 777 Begin 778 WroteGroup := True; 779 Found := 0; 780 For CCG := 1 to Cfg^.NumGroups do If (Cfg^.Groups[CCG].Index = CG) then 781 Begin Found := CCG; Break; End; 782 If (Found > 0) then DoStringLn('Group '+Cfg^.Groups[Found].Name) 783 Else DoStringLn('Group <unknown>'); 784 End; 785 DoStringLn(CA^.Name+Copy(Leer, 1, 30-Length(CA^.Name))+CA^.Desc); 786 End; 787 Until (CA^.Next = Nil); 788 If WroteGroup then DoStringLn(''); 789 End; 790 End; 791 End; 792 793 Procedure UnListed; 794 Begin 795 NM2^.DoStringLn('You are not listed in the configuration. Did you use the right AKA?'); 796 End; 797 798 Procedure WrongPwd; 799 Begin 800 NM2^.DoStringLn('Wrong password:"'+Params+'"'); 801 End; 802 803 Procedure UnKnownCmd; 804 Begin 805 NM2^.DoStringLn('Unknown command: "'+Params+'"'); 806 End; 807 808 Procedure NoDisConnect; 809 Begin 810 NM2^.DoStringLn('You are not allowed to disconnect areas.'); 811 End; 812 813 Procedure NoConnect; 814 Begin 815 NM2^.DoStringLn('You are not allowed to connect areas.'); 816 End; 817 818 Procedure NoReScan; 819 Begin 820 NM2^.DoStringLn('You are not allowed to rescan areas.'); 821 End; 822 823 Procedure UnKnownArea; 824 Begin 825 NM2^.DoStringLn('Unknown area: "'+Params+'"'); 826 End; 827 828 Procedure AlreadyConn; 829 Begin 830 NM2^.DoStringLn('Area "'+Params+'" already connected.'); 831 End; 832 833 Procedure NotConn; 834 Begin 835 NM2^.DoStringLn('Area "'+Params+'" not connected.'); 836 End; 837 838 Procedure NoPause; 839 Begin 840 NM2^.DoStringLn('You are not allowed to pause.'); 841 End; 842 843 Procedure NoComp; 844 Begin 845 NM2^.DoStringLn('You are not allowed to change compression.'); 846 End; 847 848 Procedure UnKnownPacker; 849 Begin 850 NM2^.DoStringLn('Unknown packer: "'+Params+'"'); 851 End; 852 853 Procedure NotImplemented; 854 Begin 855 NM2^.DoStringLn(Params+' not implemented yet.'); 856 End; 857 858 Procedure Connect; 859 Begin 860 NM2^.DoStringLn(Params+' linked.'); 861 End; 862 863 Procedure DisConnect; 864 Begin 865 NM2^.DoStringLn(Params+' unlinked.'); 866 End; 867 868 Procedure Pause; 869 Begin 870 NM2^.DoStringLn('Paused.'); 871 End; 872 873 Procedure Resume; 874 Begin 875 NM2^.DoStringLn('Resumed.'); 876 End; 877 878 Procedure PackFiles; 879 Begin 880 NM2^.DoStringLn('PackFiles: '+Params); 881 End; 882 883 Procedure PackTICs; 884 Begin 885 NM2^.DoStringLn('PackTICs: '+Params); 886 End; 887 888 Procedure Packer; 889 Begin 890 NM2^.DoStringLn('Packer: '+Params); 891 End; 892 893 Procedure NoRemote; 894 Begin 895 NM2^.DoStringLn(Params+' may not be (un)linked remotely.'); 896 End; 897 898 Procedure Mandatory; 899 Begin 900 NM2^.DoStringLn(Params+' is mandatory.'); 901 End; 902 903 Procedure UnKnownResponse; 904 Begin 905 NM2^.DoStringLn('Unknown response (#'+Params+'). Please report to SysOp!'); 906 End; 907 908 Procedure Help; 909 Begin 910 With NM2^ do 911 Begin 912 DoStringLn('available commands:'); 913 DoStringLn(''); 914 DoStringLn('%HELP this help :)'); 915 DoStringLn('%LIST list of areas available to you'); 916 DoStringLn('%QUERY list of connected areas'); 917 DoStringLn('%UNLINKED list of disconnected areas'); 918 DoStringLn('%PACK \ on = pack all, off = pack none, files = pack files,'); 919 DoStringLn('%COMPRESS | tics = pack tics, Extension = set packer to use'); 920 DoStringLn('%COMPRESSION / examples: "%PACK ON", "%PACK ZIP"'); 921 DoStringLn('%PAUSE stop sending files (e.g. for holiday)'); 922 DoStringLn('%RESUME resume sending files (holiday over :) )'); 923 DoStringLn('%QUIT everything below (e.g. signature) is ignored'); 924 DoStringLn('%NOTE everything below is ignored, message will NOT be deleted'); 925 DoStringLn('<Area> connect area'); 926 DoStringLn('+<Area> connect area'); 927 DoStringLn('-<Area> disconnect area'); 928 End; 929 End; 930 931 Procedure ParamNeeded; 932 Begin 933 NM2^.DoStringLn(Params+': parameter needed'); 934 End; 935 936 937 Begin 938 With NM2^ do 939 Begin 940 StartNewMsg; 941 s := 'ProTick'; 942 SetFrom(s); 943 SetKillSent(Cfg^.DelRsp); 944 If (_Type <> rs_Unlisted) then 945 Begin 946 SetTo(CurUser^.Name); 947 TNetAddr2MKAddr(CurUser^.Addr, MKAddr); 948 SetDest(MKAddr); 949 If not CompAddr(CurUser^.OwnAddr, EmptyAddr) then A1 := CurUser^.OwnAddr 950 Else AKAMatch(CurUser^.Addr, A1); 951 End 952 Else 953 Begin 954 SetTo(NM^.GetFrom); 955 NM^.GetOrig(MKAddr); 956 SetDest(MKAddr); 957 MKAddr2TNetAddr(MKAddr, A1); 958 AKAMatch(A1, A1); 959 End; 960 TNetAddr2MKAddr(A1, MKAddr); 961 SetOrig(MKAddr); 962 SetLocal(True); 963 SetPriv(True); 964 SetSubj('FileFix response'); 965 Today(DT); 966 If (DT.Year > 100) then DT.Year := DT.Year mod 100; 967 Now(DT); 968 If (DT.Month > 9) then s := IntToStr(DT.Month) + '-' 969 Else s := '0' + IntToStr(DT.Month) + '-'; 970 If (DT.Day > 9) then s := s + IntToStr(DT.Day) + '-' 971 Else s := s + '0' + IntToStr(DT.Day) + '-'; 972 If (DT.Year > 9) then s := s + IntToStr(DT.Year) 973 Else s := s + '0' + IntToStr(DT.Year); 974 SetDate(s); 975 If (DT.Hour > 9) then s := IntToStr(DT.Hour) + ':' 976 Else s := '0' + IntToStr(DT.Hour) + ':'; 977 If (DT.Min > 9) then s := s + IntToStr(DT.Min) 978 Else s := s + '0' + IntToStr(DT.Min); 979 SetTime(s); 980 SetRefer(NM^.GetMsgNum); 981 DoKludgeLn(#01'MSGID: '+Addr2Str(A1)+' '+GetMsgID); 982 983 Case _Type of 984 rs_List: SendList; 985 rs_Unlisted: UnListed; 986 rs_WrongPwd: WrongPwd; 987 rs_UnKnownCmd: UnKnownCmd; 988 rs_NoDisConnect: NoDisConnect; 989 rs_NoConnect: NoConnect; 990 rs_NoReScan: NoReScan; 991 rs_UnKnownArea: UnKnownArea; 992 rs_AlreadyConn: AlreadyConn; 993 rs_NotConn: NotConn; 994 rs_NoPause: NoPause; 995 rs_NoComp: NoComp; 996 rs_UnKnownPacker: UnKnownPacker; 997 rs_NotImplemented: NotImplemented; 998 rs_Help: Help; 999 rs_ParamNeeded: ParamNeeded; 1000 rs_Connect: Connect; 1001 rs_DisConnect: DisConnect; 1002 rs_Pause: Pause; 1003 rs_Resume: Resume; 1004 rs_PackFiles: PackFiles; 1005 rs_PackTICs: PackTICs; 1006 rs_Packer: Packer; 1007 rs_NoRemote: NoRemote; 1008 rs_Mandatory: Mandatory; 1009 rs_Query: SendQuery; 1010 rs_Unlinked: SendUnlinked; 1011 Else UnKnownResponse; 1012 End; 1013 1014 DoStringLn(''); 1015 DoStringLn('--- ProTick'+Version); 1016 If (WriteMsg <> 0) then 1017 Begin 1018 LogSetCurLevel(LogHandle, 1); 1019 LogWriteLn(LogHandle, 'Couldn''t write response!'); 1020 Exit; 1021 End; 1022 NM^.InitMsgHdr; 1023 NM^.MsgTxtStartUp; 1024 NM^.SetSeeAlso(GetMsgNum); 1025 NM^.ReWriteHdr; 1026 End; 1027 End; 1028 1029 Procedure SetActive(Act: Boolean); 1030 Var 1031 s1: String; 1032 A1: TNetAddr; 1033 1034 Begin 1035 CurUser^.Active := Act; 1036 With Ini do 1037 Begin 1038 SetSection('USER'); 1039 Repeat 1040 While (UpStr(ReSecEnName) <> 'ADDR') do If not SetNextOpt then Break; 1041 If (UpStr(ReSecEnName) <> 'ADDR') then Break; 1042 Str2Addr(ReSecEnValue, A1); 1043 If CompAddr(A1, CurUser^.Addr) then Break; 1044 SetNextOpt; 1045 Until CompAddr(A1, CurUser^.Addr); 1046 If not CompAddr(A1, CurUser^.Addr) then 1047 Begin 1048 LogSetCurLevel(LogHandle, 1); 1049 LogWriteLn(LogHandle, 'User "'+CurUser^.Name+'" ('+Addr2Str(CurUser^.Addr)+') not found in ConfigFile!'); 1050 End 1051 Else 1052 Begin 1053 While ((UpStr(ReSecEnName) <> 'USER') and (UpStr(ReSecEnName) <> 'ACTIVE')) do If not SetNextOpt then Break; 1054 If (UpStr(ReSecEnName) = 'ACTIVE') then 1055 Begin 1056 If Act then WriteSecEntry('Active', 'Yes', '') 1057 Else WriteSecEntry('Active', 'No', ''); 1058 End 1059 Else If (UpStr(ReSecEnName) = 'USER') then 1060 Begin 1061 SetPrevOpt; 1062 If Act then InsertSecEntry('Active', 'Yes', '') 1063 Else InsertSecEntry('Active', 'No', ''); 1064 End 1065 Else 1066 Begin 1067 If Act then AddSecEntry('Active', 'Yes', '') 1068 Else AddSecEntry('Active', 'No', ''); 1069 End; 1070 If Act then 1071 Begin 1072 LogSetCurLevel(LogHandle, 2); 1073 LogWriteLn(LogHandle, 'Set User '+CurUser^.Name+' ('+Addr2Str(CurUser^.Addr)+') to ACTIVE'); 1074 End 1075 Else 1076 Begin 1077 LogSetCurLevel(LogHandle, 2); 1078 LogWriteLn(LogHandle, 'Set User '+CurUser^.Name+' ('+Addr2Str(CurUser^.Addr)+') to PASSIVE'); 1079 End; 1080 End; 1081 End; 1082 End; 1083 1084 Procedure SetPack(Pack: String); 1085 {PACK=ON/OFF/J/N/Y/YES/NO/JA/NEIN/0/1/ALL/FILES/TICS/NONE/<ArcExt>} 1086 Var 1087 s: String; 1088 A1: TNetAddr; 1089 i: LongInt; 1090 ChTICs, ChFiles, ChPacker: Boolean; 1091 Found: LongInt; 1092 1093 Begin 1094 ChTICs := False; 1095 ChFiles := False; 1096 ChPacker := False; 1097 While (Length(s) > 0) and (s[1] = ' ') do Delete(s, 1, 1); 1098 If (s = '') then 1099 Begin 1100 LogSetCurLevel(LogHandle, 3); 1101 LogWriteLn(LogHandle, 'set compression: parameter needed'); 1102 SendRsp(rs_ParamNeeded, 'set compression'); 1103 End; 1104 s := UpStr(Pack); 1105 If ((s = 'ON') or (s = 'Y') or (s = 'YES') or (s = '1') or (s = 'J') or 1106 (s = 'JA') or (s = 'ALL')) then 1107 Begin 1108 ChTICs := not CurUser^.PackTICs; 1109 ChFiles := not CurUser^.PackFiles; 1110 CurUser^.PackTICs := True; 1111 CurUser^.PackFiles := True; 1112 End 1113 Else If ((s = 'OFF') or (s = 'N') or (s = 'NO') or (s = '0') or (s = 'NEIN') or 1114 (s = 'NONE')) then 1115 Begin 1116 ChTICs := CurUser^.PackTICs; 1117 ChFiles := CurUser^.PackFiles; 1118 CurUser^.PackTICs := False; 1119 CurUser^.PackFiles := False; 1120 End 1121 Else If (s = 'FILES') then 1122 Begin 1123 ChTICs := not CurUser^.PackTICs; 1124 ChFiles := CurUser^.PackFiles; 1125 CurUser^.PackTICs := False; 1126 CurUser^.PackFiles := True; 1127 End 1128 Else If (s = 'TICS') then 1129 Begin 1130 ChTICs := CurUser^.PackTICs; 1131 ChFiles := not CurUser^.PackFiles; 1132 CurUser^.PackTICs := True; 1133 CurUser^.PackFiles := False; 1134 End 1135 Else 1136 Begin 1137 Found := 1; 1138 For i := 1 to Cfg^.NumPacker do If (s = Cfg^.Packer[i].Ext) then Begin Found := i; Break; End; 1139 If (s = Cfg^.Packer[Found].Ext) then 1140 Begin 1141 CurUser^.Packer := Cfg^.Packer[Found].Index; 1142 ChPacker := True; 1143 End 1144 Else 1145 Begin 1146 LogSetCurLevel(LogHandle, 3); 1147 LogWriteLn(LogHandle, 'Unknown Packer "'+s+'"'); 1148 SendRsp(rs_UnKnownPacker, s); 1149 End; 1150 End; 1151 With Ini do 1152 Begin 1153 If ChFiles then 1154 Begin 1155 SetSection('USER'); 1156 Repeat 1157 While (UpStr(ReSecEnName) <> 'ADDR') do If not SetNextOpt then Break; 1158 If (UpStr(ReSecEnName) <> 'ADDR') then Break; 1159 Str2Addr(ReSecEnValue, A1); 1160 If CompAddr(A1, CurUser^.Addr) then Break; 1161 SetNextOpt; 1162 Until CompAddr(A1, CurUser^.Addr); 1163 If not CompAddr(A1, CurUser^.Addr) then 1164 Begin 1165 LogSetCurLevel(LogHandle, 1); 1166 LogWriteLn(LogHandle, 'User "'+CurUser^.Name+'" ('+Addr2Str(CurUser^.Addr)+') not found in ConfigFile!'); 1167 End 1168 Else 1169 Begin 1170 While ((UpStr(ReSecEnName) <> 'USER') and (UpStr(ReSecEnName) <> 'PACKFILES')) do If not SetNextOpt then Break; 1171 If (UpStr(ReSecEnName) = 'PACKFILES') then 1172 Begin 1173 If CurUser^.PackFiles then WriteSecEntry('PackFiles', 'Yes', '') 1174 Else WriteSecEntry('PackFiles', 'No', ''); 1175 End 1176 Else If (UpStr(ReSecEnName) = 'USER') then 1177 Begin 1178 SetPrevOpt; 1179 If CurUser^.PackFiles then InsertSecEntry('PackFiles', 'Yes', '') 1180 Else InsertSecEntry('PackFiles', 'No', ''); 1181 End 1182 Else 1183 Begin 1184 If CurUser^.PackFiles then AddSecEntry('PackFiles', 'Yes', '') 1185 Else AddSecEntry('PackFiles', 'No', ''); 1186 End; 1187 If CurUser^.PackFiles then 1188 Begin 1189 LogSetCurLevel(LogHandle, 3); 1190 LogWriteLn(LogHandle, 'Set PackFiles for User '+CurUser^.Name+' ('+Addr2Str(CurUser^.Addr)+') to Yes'); 1191 SendRsp(rs_PackFiles, 'On'); 1192 End 1193 Else 1194 Begin 1195 LogSetCurLevel(LogHandle, 3); 1196 LogWriteLn(LogHandle, 'Set PackFiles for User '+CurUser^.Name+' ('+Addr2Str(CurUser^.Addr)+') to No'); 1197 SendRsp(rs_PackFiles, 'Off'); 1198 End; 1199 End; 1200 End; 1201 If ChTICs then 1202 Begin 1203 SetSection('USER'); 1204 Repeat 1205 While (UpStr(ReSecEnName) <> 'ADDR') do If not SetNextOpt then Break; 1206 If (UpStr(ReSecEnName) <> 'ADDR') then Break; 1207 Str2Addr(ReSecEnValue, A1); 1208 If CompAddr(A1, CurUser^.Addr) then Break; 1209 SetNextOpt; 1210 Until CompAddr(A1, CurUser^.Addr); 1211 If not CompAddr(A1, CurUser^.Addr) then 1212 Begin 1213 LogSetCurLevel(LogHandle, 1); 1214 LogWriteLn(LogHandle, 'User "'+CurUser^.Name+'" ('+Addr2Str(CurUser^.Addr)+') not found in ConfigFile!'); 1215 End 1216 Else 1217 Begin 1218 While ((UpStr(ReSecEnName) <> 'USER') and (UpStr(ReSecEnName) <> 'PACKTICS')) do If not SetNextOpt then Break; 1219 If (UpStr(ReSecEnName) = 'PACKTICS') then 1220 Begin 1221 If CurUser^.PackTICs then WriteSecEntry('PackTICs', 'Yes', '') 1222 Else WriteSecEntry('PackTICs', 'No', ''); 1223 End 1224 Else If (UpStr(ReSecEnName) = 'USER') then 1225 Begin 1226 SetPrevOpt; 1227 If CurUser^.PackTICs then InsertSecEntry('PackTICs', 'Yes', '') 1228 Else InsertSecEntry('PackTICs', 'No', ''); 1229 End 1230 Else 1231 Begin 1232 If CurUser^.PackTICs then AddSecEntry('PackTICs', 'Yes', '') 1233 Else AddSecEntry('PackTICs', 'No', ''); 1234 End; 1235 If CurUser^.PackTICs then 1236 Begin 1237 LogSetCurLevel(LogHandle, 3); 1238 LogWriteLn(LogHandle, 'Set PackTICs for User '+CurUser^.Name+' ('+Addr2Str(CurUser^.Addr)+') to Yes'); 1239 SendRsp(rs_PackTICs, 'On'); 1240 End 1241 Else 1242 Begin 1243 LogSetCurLevel(LogHandle, 3); 1244 LogWriteLn(LogHandle, 'Set PackTICs for User '+CurUser^.Name+' ('+Addr2Str(CurUser^.Addr)+') to No'); 1245 SendRsp(rs_PackTICs, 'Off'); 1246 End; 1247 End; 1248 End; 1249 If ChPacker then 1250 Begin 1251 SetSection('USER'); 1252 Repeat 1253 While (UpStr(ReSecEnName) <> 'ADDR') do If not SetNextOpt then Break; 1254 If (UpStr(ReSecEnName) <> 'ADDR') then Break; 1255 Str2Addr(ReSecEnValue, A1); 1256 If CompAddr(A1, CurUser^.Addr) then Break; 1257 SetNextOpt; 1258 Until CompAddr(A1, CurUser^.Addr); 1259 If not CompAddr(A1, CurUser^.Addr) then 1260 Begin 1261 LogSetCurLevel(LogHandle, 1); 1262 LogWriteLn(LogHandle, 'User "'+CurUser^.Name+'" ('+Addr2Str(CurUser^.Addr)+') not found in ConfigFile!'); 1263 End 1264 Else 1265 Begin 1266 While ((UpStr(ReSecEnName) <> 'USER') and (UpStr(ReSecEnName) <> 'PACKER')) do If not SetNextOpt then Break; 1267 If (UpStr(ReSecEnName) = 'PACKER') then 1268 Begin 1269 WriteSecEntry('Packer', IntToStr(CurUser^.Packer), '') 1270 End 1271 Else If (UpStr(ReSecEnName) = 'USER') then 1272 Begin 1273 SetPrevOpt; 1274 InsertSecEntry('Packer', IntToStr(CurUser^.Packer), '') 1275 End 1276 Else 1277 Begin 1278 AddSecEntry('Packer', IntToStr(CurUser^.Packer), '') 1279 End; 1280 Found := 1; 1281 For i := 1 to Cfg^.NumPacker do If (CurUser^.Packer = Cfg^.Packer[i].Index) then Begin Found := i; Break; End; 1282 LogSetCurLevel(LogHandle, 3); 1283 LogWriteLn(LogHandle, 'Set Packer for User '+CurUser^.Name+' ('+ 1284 Addr2Str(CurUser^.Addr)+') to '+IntToStr(CurUser^.Packer)+' ('+ 1285 Cfg^.Packer[Found].Ext+')'); 1286 SendRsp(rs_Packer, Cfg^.Packer[Found].Ext); 1287 End; 1288 End; 1289 End; 1290 End; 1291 1292 Procedure AKAMatch(InAddr: TNetAddr; var OutAddr: TNetAddr); 1293 Var 1294 i: Byte; 1295 Found: Boolean; 1296 1297 Begin 1298 Found := False; 1299 For i := 1 to Cfg^.NumAddrs do If (InAddr.Zone = Cfg^.Addrs[i].Zone) then 1300 Begin 1301 Found := True; 1302 OutAddr := Cfg^.Addrs[i]; 1303 Break; 1304 End; 1305 If not Found then OutAddr := Cfg^.Addrs[1]; 1306 End; 1307 1308 1309 End. 1310