From 5286f9b644401f98f94dd377328bb8bdf1f508de Mon Sep 17 00:00:00 2001 From: Yasunori Endo Date: Fri, 28 Jun 2019 22:42:50 +0900 Subject: [PATCH 01/16] unzipped --- ICS_zlog.zip | Bin 992850 -> 0 bytes ICS_zlog/Delphi/Internet/Cli7.dfm | Bin 0 -> 1876 bytes ICS_zlog/Delphi/Internet/Cli7.pas | 263 + ICS_zlog/Delphi/Internet/CliDemo1.dfm | Bin 0 -> 1496 bytes ICS_zlog/Delphi/Internet/CliDemo1.pas | 257 + ICS_zlog/Delphi/Internet/Client7.dpr | 12 + ICS_zlog/Delphi/Internet/ConCli1.dpr | 78 + ICS_zlog/Delphi/Internet/ConCli2.dpr | 164 + ICS_zlog/Delphi/Internet/ConFtp.dpr | 226 + ICS_zlog/Delphi/Internet/ConHttp.dpr | 171 + ICS_zlog/Delphi/Internet/ConSmtp.dpr | 291 + ICS_zlog/Delphi/Internet/ConSrv1.dpr | 354 + ICS_zlog/Delphi/Internet/ConSrv1C.pas | 181 + ICS_zlog/Delphi/Internet/ConSrv1S.pas | 145 + ICS_zlog/Delphi/Internet/Del40Sam.bpg | 175 + ICS_zlog/Delphi/Internet/Del50Sam.bpg | 184 + ICS_zlog/Delphi/Internet/Del60Sam.bpg | 184 + ICS_zlog/Delphi/Internet/Del70Sam.bpg | 184 + ICS_zlog/Delphi/Internet/DllTst1.dpr | 13 + ICS_zlog/Delphi/Internet/DllTst_1.dfm | Bin 0 -> 1106 bytes ICS_zlog/Delphi/Internet/DllTst_1.pas | 210 + ICS_zlog/Delphi/Internet/DnsLook1.dfm | Bin 0 -> 1427 bytes ICS_zlog/Delphi/Internet/DnsLook1.pas | 165 + ICS_zlog/Delphi/Internet/DynCli.dpr | 12 + ICS_zlog/Delphi/Internet/DynCli1.dfm | Bin 0 -> 1167 bytes ICS_zlog/Delphi/Internet/DynCli1.pas | 167 + ICS_zlog/Delphi/Internet/FTPTST2.dfm | Bin 0 -> 402 bytes ICS_zlog/Delphi/Internet/FtpServ1.dfm | Bin 0 -> 3022 bytes ICS_zlog/Delphi/Internet/FtpServ1.pas | 842 ++ ICS_zlog/Delphi/Internet/FtpThrd1.dfm | Bin 0 -> 619 bytes ICS_zlog/Delphi/Internet/FtpThrd1.pas | 168 + ICS_zlog/Delphi/Internet/Ftptst2.pas | 25 + ICS_zlog/Delphi/Internet/HLembke/NsLook1.dfm | Bin 0 -> 1599 bytes ICS_zlog/Delphi/Internet/HLembke/NsLook1.pas | 322 + ICS_zlog/Delphi/Internet/HLembke/NsLookup.dpr | 12 + ICS_zlog/Delphi/Internet/HLembke/ReadMe.txt | 9 + ICS_zlog/Delphi/Internet/HLembke/dnsquery.pas | 1050 +++ ICS_zlog/Delphi/Internet/HttpAsp1.dfm | Bin 0 -> 1139 bytes ICS_zlog/Delphi/Internet/HttpAsp1.pas | 164 + ICS_zlog/Delphi/Internet/HttpAsy1.dfm | Bin 0 -> 2148 bytes ICS_zlog/Delphi/Internet/HttpAsy1.pas | 492 + ICS_zlog/Delphi/Internet/HttpChk1.dfm | Bin 0 -> 1014 bytes ICS_zlog/Delphi/Internet/HttpChk1.pas | 147 + ICS_zlog/Delphi/Internet/HttpDmo1.dfm | Bin 0 -> 1253 bytes ICS_zlog/Delphi/Internet/HttpDmo1.pas | 139 + ICS_zlog/Delphi/Internet/HttpGet1.dfm | Bin 0 -> 1505 bytes ICS_zlog/Delphi/Internet/HttpGet1.pas | 208 + ICS_zlog/Delphi/Internet/HttpPg1.dfm | Bin 0 -> 2005 bytes ICS_zlog/Delphi/Internet/HttpPg1.pas | 246 + ICS_zlog/Delphi/Internet/HttpThr1.dfm | Bin 0 -> 2011 bytes ICS_zlog/Delphi/Internet/HttpThr1.pas | 269 + ICS_zlog/Delphi/Internet/HttpThr2.pas | 161 + ICS_zlog/Delphi/Internet/Httpdmo.dpr | 12 + ICS_zlog/Delphi/Internet/Ics.ico | Bin 0 -> 766 bytes ICS_zlog/Delphi/Internet/IcsDll1.dpr | 286 + ICS_zlog/Delphi/Internet/IcsIsap1.dfm | Bin 0 -> 199 bytes ICS_zlog/Delphi/Internet/IcsIsap1.pas | 184 + ICS_zlog/Delphi/Internet/IcsIsapi.dpr | 19 + ICS_zlog/Delphi/Internet/MailRcv.dpr | 14 + ICS_zlog/Delphi/Internet/MailRcv1.dfm | Bin 0 -> 4788 bytes ICS_zlog/Delphi/Internet/MailRcv1.pas | 667 ++ ICS_zlog/Delphi/Internet/MailRcv2.dfm | Bin 0 -> 335 bytes ICS_zlog/Delphi/Internet/MailRcv2.pas | 33 + ICS_zlog/Delphi/Internet/MailRob.dpr | 12 + ICS_zlog/Delphi/Internet/MailRob1.dfm | Bin 0 -> 3134 bytes ICS_zlog/Delphi/Internet/MailRob1.pas | 692 ++ ICS_zlog/Delphi/Internet/MailSnd.dpr | 12 + ICS_zlog/Delphi/Internet/MailSnd1.dfm | Bin 0 -> 5901 bytes ICS_zlog/Delphi/Internet/MailSnd1.pas | 588 ++ ICS_zlog/Delphi/Internet/MbxSub.dpr | 13 + ICS_zlog/Delphi/Internet/MbxSub1.dfm | Bin 0 -> 2214 bytes ICS_zlog/Delphi/Internet/MbxSub1.pas | 621 ++ ICS_zlog/Delphi/Internet/MimeDemo.dpr | 12 + ICS_zlog/Delphi/Internet/MimeDmo1.dfm | Bin 0 -> 1535 bytes ICS_zlog/Delphi/Internet/MimeDmo1.pas | 352 + ICS_zlog/Delphi/Internet/MimeTst.dpr | 12 + ICS_zlog/Delphi/Internet/MimeTst1.dfm | Bin 0 -> 2147 bytes ICS_zlog/Delphi/Internet/MimeTst1.pas | 232 + ICS_zlog/Delphi/Internet/NewsRdr1.dfm | Bin 0 -> 6955 bytes ICS_zlog/Delphi/Internet/NewsRdr1.pas | 732 ++ ICS_zlog/Delphi/Internet/NsLook1.dfm | Bin 0 -> 1506 bytes ICS_zlog/Delphi/Internet/NsLook1.pas | 273 + ICS_zlog/Delphi/Internet/NsLookup.dpr | 12 + ICS_zlog/Delphi/Internet/POP3MIM1.dfm | Bin 0 -> 1391 bytes ICS_zlog/Delphi/Internet/PingTst1.dfm | Bin 0 -> 930 bytes ICS_zlog/Delphi/Internet/PingTst1.pas | 154 + ICS_zlog/Delphi/Internet/Pop3Mim1.pas | 283 + ICS_zlog/Delphi/Internet/Pop3Mime.dpr | 12 + ICS_zlog/Delphi/Internet/PopTst1.dfm | Bin 0 -> 4105 bytes ICS_zlog/Delphi/Internet/PopTst1.pas | 558 ++ ICS_zlog/Delphi/Internet/Recv.dpr | 12 + ICS_zlog/Delphi/Internet/Recv1.dfm | Bin 0 -> 1702 bytes ICS_zlog/Delphi/Internet/Recv1.pas | 302 + ICS_zlog/Delphi/Internet/Sender.dpr | 12 + ICS_zlog/Delphi/Internet/Sender1.dfm | Bin 0 -> 2588 bytes ICS_zlog/Delphi/Internet/Sender1.pas | 628 ++ ICS_zlog/Delphi/Internet/Socks1.dfm | Bin 0 -> 2675 bytes ICS_zlog/Delphi/Internet/Socks1.pas | 344 + ICS_zlog/Delphi/Internet/SocksTst.dpr | 12 + ICS_zlog/Delphi/Internet/SrvDemo1.dfm | Bin 0 -> 1108 bytes ICS_zlog/Delphi/Internet/SrvDemo1.pas | 189 + ICS_zlog/Delphi/Internet/SrvDemo2.dfm | Bin 0 -> 1334 bytes ICS_zlog/Delphi/Internet/SrvDemo2.pas | 256 + ICS_zlog/Delphi/Internet/SrvTcp.dpr | 16 + ICS_zlog/Delphi/Internet/SrvTcp1.dfm | Bin 0 -> 613 bytes ICS_zlog/Delphi/Internet/SrvTcp1.pas | 194 + ICS_zlog/Delphi/Internet/SvcTcp.dpr | 14 + ICS_zlog/Delphi/Internet/SvcTcp1.dfm | Bin 0 -> 264 bytes ICS_zlog/Delphi/Internet/SvcTcp1.pas | 171 + ICS_zlog/Delphi/Internet/TcpCmd.pas | 366 + ICS_zlog/Delphi/Internet/TcpSrv.dpr | 12 + ICS_zlog/Delphi/Internet/TcpSrv1.dfm | Bin 0 -> 1215 bytes ICS_zlog/Delphi/Internet/TcpSrv1.pas | 350 + ICS_zlog/Delphi/Internet/ThrdSrv.dpr | 12 + ICS_zlog/Delphi/Internet/TnCli1.dfm | Bin 0 -> 2260 bytes ICS_zlog/Delphi/Internet/TnCli1.pas | 268 + ICS_zlog/Delphi/Internet/UdpLstn1.dfm | Bin 0 -> 1592 bytes ICS_zlog/Delphi/Internet/UdpLstn1.pas | 288 + ICS_zlog/Delphi/Internet/UdpSend1.dfm | Bin 0 -> 1338 bytes ICS_zlog/Delphi/Internet/UdpSend1.pas | 150 + ICS_zlog/Delphi/Internet/WebServ.dpr | 12 + ICS_zlog/Delphi/Internet/WebServ1.dfm | Bin 0 -> 2290 bytes ICS_zlog/Delphi/Internet/WebServ1.pas | 755 ++ ICS_zlog/Delphi/Internet/cli5.dfm | Bin 0 -> 1316 bytes ICS_zlog/Delphi/Internet/cli5.pas | 193 + ICS_zlog/Delphi/Internet/clidemo.dpr | 12 + ICS_zlog/Delphi/Internet/client5.dpr | 12 + ICS_zlog/Delphi/Internet/clients.DBF | Bin 0 -> 434 bytes ICS_zlog/Delphi/Internet/clients.MDX | Bin 0 -> 6144 bytes ICS_zlog/Delphi/Internet/dnslook.dpr | 12 + ICS_zlog/Delphi/Internet/finger.dpr | 12 + ICS_zlog/Delphi/Internet/finger1.dfm | Bin 0 -> 1001 bytes ICS_zlog/Delphi/Internet/finger1.pas | 216 + ICS_zlog/Delphi/Internet/ftpServ.dpr | 12 + ICS_zlog/Delphi/Internet/ftpcli.ico | Bin 0 -> 766 bytes ICS_zlog/Delphi/Internet/ftpthrd.dpr | 13 + ICS_zlog/Delphi/Internet/ftptst.dpr | 14 + ICS_zlog/Delphi/Internet/ftptst1.dfm | Bin 0 -> 16936 bytes ICS_zlog/Delphi/Internet/ftptst1.pas | 1203 +++ ICS_zlog/Delphi/Internet/httpChk.dpr | 12 + ICS_zlog/Delphi/Internet/httpasp.dpr | 12 + ICS_zlog/Delphi/Internet/httpasy.dpr | 12 + ICS_zlog/Delphi/Internet/httpget.dpr | 12 + ICS_zlog/Delphi/Internet/httppg.dpr | 12 + ICS_zlog/Delphi/Internet/httpthrd.dpr | 14 + ICS_zlog/Delphi/Internet/httptst.dpr | 12 + ICS_zlog/Delphi/Internet/httptst1.dfm | Bin 0 -> 2991 bytes ICS_zlog/Delphi/Internet/httptst1.pas | 541 ++ ICS_zlog/Delphi/Internet/md5test.dpr | 12 + ICS_zlog/Delphi/Internet/md5test1.dfm | Bin 0 -> 505 bytes ICS_zlog/Delphi/Internet/md5test1.pas | 81 + ICS_zlog/Delphi/Internet/mtsrv.dpr | 14 + ICS_zlog/Delphi/Internet/mtsrv.ico | Bin 0 -> 766 bytes ICS_zlog/Delphi/Internet/mtsrv.res | Bin 0 -> 876 bytes ICS_zlog/Delphi/Internet/mtsrv1.dfm | Bin 0 -> 1174 bytes ICS_zlog/Delphi/Internet/mtsrv1.pas | 273 + ICS_zlog/Delphi/Internet/mtsrv2.pas | 191 + ICS_zlog/Delphi/Internet/newsrdr.dpr | 12 + ICS_zlog/Delphi/Internet/pingtst.dpr | 13 + ICS_zlog/Delphi/Internet/poptst.dpr | 14 + ICS_zlog/Delphi/Internet/poptst2.dfm | Bin 0 -> 337 bytes ICS_zlog/Delphi/Internet/poptst2.pas | 33 + ICS_zlog/Delphi/Internet/server5.dpr | 12 + ICS_zlog/Delphi/Internet/srv5.dfm | Bin 0 -> 1294 bytes ICS_zlog/Delphi/Internet/srv5.pas | 142 + ICS_zlog/Delphi/Internet/srvdemo.dpr | 13 + ICS_zlog/Delphi/Internet/thrdsrv1.dfm | Bin 0 -> 1143 bytes ICS_zlog/Delphi/Internet/thrdsrv1.pas | 491 + ICS_zlog/Delphi/Internet/tnclient.dpr | 12 + ICS_zlog/Delphi/Internet/tnclient.ico | Bin 0 -> 766 bytes ICS_zlog/Delphi/Internet/tndemo.dpr | 12 + ICS_zlog/Delphi/Internet/tndemo1.dfm | Bin 0 -> 1582 bytes ICS_zlog/Delphi/Internet/tndemo1.pas | 207 + ICS_zlog/Delphi/Internet/tnsrv.dpr | 13 + ICS_zlog/Delphi/Internet/tnsrv.ico | Bin 0 -> 766 bytes ICS_zlog/Delphi/Internet/tnsrv1.dfm | Bin 0 -> 1407 bytes ICS_zlog/Delphi/Internet/tnsrv1.pas | 325 + ICS_zlog/Delphi/Internet/tnsrv2.dfm | Bin 0 -> 1399 bytes ICS_zlog/Delphi/Internet/tnsrv2.pas | 544 ++ ICS_zlog/Delphi/Internet/twschat.dpr | 12 + ICS_zlog/Delphi/Internet/twschat1.dfm | Bin 0 -> 2603 bytes ICS_zlog/Delphi/Internet/twschat1.pas | 332 + ICS_zlog/Delphi/Internet/udplstn.dpr | 12 + ICS_zlog/Delphi/Internet/udpsend.dpr | 12 + ICS_zlog/Delphi/Vc/DnsQuery.dcr | Bin 0 -> 411 bytes ICS_zlog/Delphi/Vc/FtpSrv.dcr | Bin 0 -> 412 bytes ICS_zlog/Delphi/Vc/Pop3Prot.dcr | Bin 0 -> 824 bytes ICS_zlog/Delphi/Vc/SmtpProt.dcr | Bin 0 -> 824 bytes ICS_zlog/Delphi/Vc/TNSCRIPT.DCR | Bin 0 -> 411 bytes ICS_zlog/Delphi/Vc/WINSOCK.PAS | 634 ++ ICS_zlog/Delphi/Vc/emulvt.dcr | Bin 0 -> 409 bytes ICS_zlog/Delphi/Vc/fingcli.dcr | Bin 0 -> 412 bytes ICS_zlog/Delphi/Vc/ftpcli.dcr | Bin 0 -> 1208 bytes ICS_zlog/Delphi/Vc/httpprot.dcr | Bin 0 -> 410 bytes ICS_zlog/Delphi/Vc/httpsrv.dcr | Bin 0 -> 413 bytes ICS_zlog/Delphi/Vc/mbxfile.dcr | Bin 0 -> 413 bytes ICS_zlog/Delphi/Vc/mimedec.dcr | Bin 0 -> 413 bytes ICS_zlog/Delphi/Vc/nntpcli.dcr | Bin 0 -> 410 bytes ICS_zlog/Delphi/Vc/tncnx.dcr | Bin 0 -> 408 bytes ICS_zlog/Delphi/Vc/tnemulvt.dcr | Bin 0 -> 411 bytes ICS_zlog/Delphi/Vc/wait.dcr | Bin 0 -> 1198 bytes ICS_zlog/Delphi/Vc/wsocket.dcr | Bin 0 -> 410 bytes ICS_zlog/Delphi/Vc/wsockets.dcr | Bin 0 -> 1209 bytes ICS_zlog/Delphi/Vc32/DnsQuery.dcr | Bin 0 -> 472 bytes ICS_zlog/Delphi/Vc32/DnsQuery.dcu | Bin 0 -> 22672 bytes ICS_zlog/Delphi/Vc32/DnsQuery.pas | 1046 +++ ICS_zlog/Delphi/Vc32/EmulVT.dcu | Bin 0 -> 101193 bytes ICS_zlog/Delphi/Vc32/EmulVT.pas | 4006 ++++++++ ICS_zlog/Delphi/Vc32/FingCli.dcu | Bin 0 -> 5930 bytes ICS_zlog/Delphi/Vc32/FingCli.pas | 230 + ICS_zlog/Delphi/Vc32/FtpCli.dcu | Bin 0 -> 78444 bytes ICS_zlog/Delphi/Vc32/FtpCli.pas | 3806 ++++++++ ICS_zlog/Delphi/Vc32/FtpSrvC.dcu | Bin 0 -> 16720 bytes ICS_zlog/Delphi/Vc32/FtpSrvC.pas | 579 ++ ICS_zlog/Delphi/Vc32/FtpSrvT.dcu | Bin 0 -> 2701 bytes ICS_zlog/Delphi/Vc32/FtpSrvT.pas | 178 + ICS_zlog/Delphi/Vc32/HttpSrv.dcr | Bin 0 -> 476 bytes ICS_zlog/Delphi/Vc32/HttpSrv.dcu | Bin 0 -> 34405 bytes ICS_zlog/Delphi/Vc32/HttpSrv.pas | 1347 +++ ICS_zlog/Delphi/Vc32/IcsBcb30.bpk | 186 + ICS_zlog/Delphi/Vc32/IcsBcb30.cpp | 50 + ICS_zlog/Delphi/Vc32/IcsBcb30.res | Bin 0 -> 1764 bytes ICS_zlog/Delphi/Vc32/IcsBcb50.bpk | 131 + ICS_zlog/Delphi/Vc32/IcsBcb50.cpp | 53 + ICS_zlog/Delphi/Vc32/IcsBcb50.res | Bin 0 -> 1784 bytes ICS_zlog/Delphi/Vc32/IcsBcb60.bpk | 220 + ICS_zlog/Delphi/Vc32/IcsBcb60.cpp | 19 + ICS_zlog/Delphi/Vc32/IcsBcb60.res | Bin 0 -> 1752 bytes ICS_zlog/Delphi/Vc32/IcsDel30.dpk | 79 + ICS_zlog/Delphi/Vc32/IcsDel40.dpk | 79 + ICS_zlog/Delphi/Vc32/IcsDel40.res | Bin 0 -> 1844 bytes ICS_zlog/Delphi/Vc32/IcsDel50.dpk | 79 + ICS_zlog/Delphi/Vc32/IcsDel50.res | Bin 0 -> 1900 bytes ICS_zlog/Delphi/Vc32/IcsDel60.cfg | 35 + ICS_zlog/Delphi/Vc32/IcsDel60.dcu | Bin 0 -> 4288 bytes ICS_zlog/Delphi/Vc32/IcsDel60.dof | 108 + ICS_zlog/Delphi/Vc32/IcsDel60.dpk | 81 + ICS_zlog/Delphi/Vc32/IcsDel60.res | Bin 0 -> 1856 bytes ICS_zlog/Delphi/Vc32/IcsDel70.dof | 152 + ICS_zlog/Delphi/Vc32/IcsDel70.dpk | 81 + ICS_zlog/Delphi/Vc32/IcsDel70.res | Bin 0 -> 1860 bytes ICS_zlog/Delphi/Vc32/Icsbcb40.bpk | 221 + ICS_zlog/Delphi/Vc32/Icsbcb40.cpp | 53 + ICS_zlog/Delphi/Vc32/Icsbcb40.res | Bin 0 -> 1764 bytes ICS_zlog/Delphi/Vc32/Icsdel30.res | Bin 0 -> 32 bytes ICS_zlog/Delphi/Vc32/MD5.dcu | Bin 0 -> 8371 bytes ICS_zlog/Delphi/Vc32/MD5.pas | 362 + ICS_zlog/Delphi/Vc32/MbxFile.dcr | Bin 0 -> 476 bytes ICS_zlog/Delphi/Vc32/MbxFile.dcu | Bin 0 -> 8578 bytes ICS_zlog/Delphi/Vc32/MbxFile.pas | 355 + ICS_zlog/Delphi/Vc32/NntpCli.dcu | Bin 0 -> 32946 bytes ICS_zlog/Delphi/Vc32/NntpCli.pas | 1414 +++ ICS_zlog/Delphi/Vc32/POP3CLI.DCR | Bin 0 -> 1740 bytes ICS_zlog/Delphi/Vc32/Ping.dcu | Bin 0 -> 11777 bytes ICS_zlog/Delphi/Vc32/Ping.pas | 603 ++ ICS_zlog/Delphi/Vc32/Pop3Prot.dcr | Bin 0 -> 920 bytes ICS_zlog/Delphi/Vc32/Pop3Prot.dcu | Bin 0 -> 40200 bytes ICS_zlog/Delphi/Vc32/Pop3Prot.pas | 1776 ++++ ICS_zlog/Delphi/Vc32/Pop3cli.pas | 904 ++ ICS_zlog/Delphi/Vc32/SmtpProt.dcr | Bin 0 -> 920 bytes ICS_zlog/Delphi/Vc32/SmtpProt.dcu | Bin 0 -> 56777 bytes ICS_zlog/Delphi/Vc32/SmtpProt.pas | 2427 +++++ ICS_zlog/Delphi/Vc32/TNCNX.HLP | Bin 0 -> 33193 bytes ICS_zlog/Delphi/Vc32/TnCnx.dcu | Bin 0 -> 13087 bytes ICS_zlog/Delphi/Vc32/TnCnx.pas | 714 ++ ICS_zlog/Delphi/Vc32/TnEmulVT.dcu | Bin 0 -> 24842 bytes ICS_zlog/Delphi/Vc32/TnEmulVT.pas | 825 ++ ICS_zlog/Delphi/Vc32/TnOptFrm.dcu | Bin 0 -> 17997 bytes ICS_zlog/Delphi/Vc32/TnOptFrm.dfm | Bin 0 -> 3207 bytes ICS_zlog/Delphi/Vc32/TnOptFrm.pas | 564 ++ ICS_zlog/Delphi/Vc32/TnScript.dcu | Bin 0 -> 12441 bytes ICS_zlog/Delphi/Vc32/TnScript.pas | 570 ++ ICS_zlog/Delphi/Vc32/UUEncode.pas | 142 + ICS_zlog/Delphi/Vc32/WSOCKET.GID | Bin 0 -> 8628 bytes ICS_zlog/Delphi/Vc32/WSOCKET.HLP | Bin 0 -> 91775 bytes ICS_zlog/Delphi/Vc32/WSockBuf.dcu | Bin 0 -> 2740 bytes ICS_zlog/Delphi/Vc32/WSockBuf.pas | 225 + ICS_zlog/Delphi/Vc32/WSocket.dcu | Bin 0 -> 88122 bytes ICS_zlog/Delphi/Vc32/WSocket.pas | 5674 +++++++++++ ICS_zlog/Delphi/Vc32/WSocketE.dcu | Bin 0 -> 3740 bytes ICS_zlog/Delphi/Vc32/WSocketE.pas | 172 + ICS_zlog/Delphi/Vc32/WSocketS.dcr | Bin 0 -> 484 bytes ICS_zlog/Delphi/Vc32/WSocketS.dcu | Bin 0 -> 14519 bytes ICS_zlog/Delphi/Vc32/WSocketS.pas | 456 + ICS_zlog/Delphi/Vc32/emulvt.dcr | Bin 0 -> 468 bytes ICS_zlog/Delphi/Vc32/fingcli.dcr | Bin 0 -> 476 bytes ICS_zlog/Delphi/Vc32/formpos.dcu | Bin 0 -> 2961 bytes ICS_zlog/Delphi/Vc32/formpos.pas | 167 + ICS_zlog/Delphi/Vc32/ftpcli.dcr | Bin 0 -> 1252 bytes ICS_zlog/Delphi/Vc32/ftpsrv.dcr | Bin 0 -> 476 bytes ICS_zlog/Delphi/Vc32/ftpsrv.dcu | Bin 0 -> 84340 bytes ICS_zlog/Delphi/Vc32/ftpsrv.pas | 3360 +++++++ ICS_zlog/Delphi/Vc32/httpprot.dcr | Bin 0 -> 472 bytes ICS_zlog/Delphi/Vc32/httpprot.dcu | Bin 0 -> 42230 bytes ICS_zlog/Delphi/Vc32/httpprot.pas | 2331 +++++ ICS_zlog/Delphi/Vc32/icmp.dcu | Bin 0 -> 10937 bytes ICS_zlog/Delphi/Vc32/icmp.pas | 449 + ICS_zlog/Delphi/Vc32/mimedec.dcr | Bin 0 -> 476 bytes ICS_zlog/Delphi/Vc32/mimedec.dcu | Bin 0 -> 27766 bytes ICS_zlog/Delphi/Vc32/mimedec.pas | 1576 ++++ ICS_zlog/Delphi/Vc32/nntpcli.dcr | Bin 0 -> 472 bytes ICS_zlog/Delphi/Vc32/ping.dcr | Bin 0 -> 464 bytes ICS_zlog/Delphi/Vc32/tncnx.dcr | Bin 0 -> 468 bytes ICS_zlog/Delphi/Vc32/tnemulvt.dcr | Bin 0 -> 472 bytes ICS_zlog/Delphi/Vc32/tnscript.dcr | Bin 0 -> 472 bytes ICS_zlog/Delphi/Vc32/wait.dcr | Bin 0 -> 1300 bytes ICS_zlog/Delphi/Vc32/wait.dcu | Bin 0 -> 11346 bytes ICS_zlog/Delphi/Vc32/wait.pas | 336 + ICS_zlog/Delphi/Vc32/wsocket.dcr | Bin 0 -> 1312 bytes ICS_zlog/Delphi/Vc32/wsocket.ico | Bin 0 -> 766 bytes VCL.zip | Bin 5440976 -> 0 bytes VCL/ADVGRID3/ADVGRID.DCR | Bin 0 -> 484 bytes VCL/ADVGRID3/ADVGRID.DCU | Bin 0 -> 110913 bytes VCL/ADVGRID3/ADVGRID3.GID | Bin 0 -> 8628 bytes VCL/ADVGRID3/ASGPKG.DCP | Bin 0 -> 70564 bytes VCL/ADVGRID3/ASGPKG.DCU | Bin 0 -> 2356 bytes VCL/ADVGRID3/ASGPKG.DPL | Bin 0 -> 155136 bytes VCL/ADVGRID3/ASGPKG.RES | Bin 0 -> 32 bytes VCL/ADVGRID3/Asgpkg.dpk | 41 + VCL/ADVGRID3/Asgpkg.~dp | 38 + VCL/ADVGRID3/EDITBTN.DCU | Bin 0 -> 14235 bytes VCL/ADVGRID3/INTELLI.RES | Bin 0 -> 6820 bytes VCL/ADVGRID3/MATCH.DCU | Bin 0 -> 2468 bytes VCL/ASTrayIcon.dcr | Bin 0 -> 476 bytes VCL/ASTrayIcon.pas | 158 + VCL/Audio.dcr | Bin 0 -> 908 bytes VCL/Audio.dcu | Bin 0 -> 9060 bytes VCL/CM2x/Baltic Solutions.url | 3 + VCL/CM2x/Delphi3/Bs_cm.dcp | Bin 0 -> 32505 bytes VCL/CM2x/Delphi3/Bs_cm.dcu | Bin 0 -> 1886 bytes VCL/CM2x/Delphi3/Bs_cm.dpk | 37 + VCL/CM2x/Delphi3/Bs_cm.dpl | Bin 0 -> 75264 bytes VCL/CM2x/Delphi3/Bs_cm.res | Bin 0 -> 32 bytes VCL/CM2x/Delphi3/Bs_cm.~dp | 39 + VCL/CM2x/Delphi3/Cmemo.dcr | Bin 0 -> 816 bytes VCL/CM2x/Delphi3/Cmemo.dcu | Bin 0 -> 13233 bytes VCL/CM2x/Delphi3/Cmemo.dfm | Bin 0 -> 3253 bytes VCL/CM2x/Delphi3/Colmemo.dcu | Bin 0 -> 37305 bytes VCL/CM2x/Delphi3/Colmemo.res | Bin 0 -> 424 bytes VCL/CM2x/Delphi4/Bs_cm.bpl | Bin 0 -> 81920 bytes VCL/CM2x/Delphi4/Bs_cm.dcu | Bin 0 -> 2286 bytes VCL/CM2x/Delphi4/Bs_cm.dpk | 37 + VCL/CM2x/Delphi4/Bs_cm.res | Bin 0 -> 876 bytes VCL/CM2x/Delphi4/Cmemo.dcr | Bin 0 -> 816 bytes VCL/CM2x/Delphi4/Cmemo.dcu | Bin 0 -> 14212 bytes VCL/CM2x/Delphi4/Cmemo.dfm | Bin 0 -> 3253 bytes VCL/CM2x/Delphi4/Colmemo.dcu | Bin 0 -> 38981 bytes VCL/CM2x/Delphi4/Colmemo.res | Bin 0 -> 424 bytes VCL/CM2x/Demo/Main.dcu | Bin 0 -> 4300 bytes VCL/CM2x/Demo/Main.dfm | Bin 0 -> 3031 bytes VCL/CM2x/Demo/Main.pas | 92 + VCL/CM2x/Demo/cm2_demo.dof | 80 + VCL/CM2x/Demo/cm2_demo.dpr | 21 + VCL/CM2x/Demo/cm2_demo.res | Bin 0 -> 876 bytes VCL/CM2x/Demo/cm2_demo.~dp | 21 + VCL/CM2x/Demo/cm_even.dcu | Bin 0 -> 6153 bytes VCL/CM2x/Demo/cm_even.dfm | Bin 0 -> 5213 bytes VCL/CM2x/Demo/cm_even.pas | 146 + VCL/CM2x/Demo/cm_even.~df | Bin 0 -> 4923 bytes VCL/CM2x/Demo/cm_even.~pa | 146 + VCL/CM2x/Demo/cm_html.dcu | Bin 0 -> 2948 bytes VCL/CM2x/Demo/cm_html.dfm | Bin 0 -> 1840 bytes VCL/CM2x/Demo/cm_html.pas | 48 + VCL/CM2x/Demo/cm_hyper.dcu | Bin 0 -> 2921 bytes VCL/CM2x/Demo/cm_hyper.dfm | Bin 0 -> 3109 bytes VCL/CM2x/Demo/cm_hyper.pas | 45 + VCL/CM2x/Demo/cm_pasc.dcu | Bin 0 -> 2962 bytes VCL/CM2x/Demo/cm_pasc.dfm | Bin 0 -> 3169 bytes VCL/CM2x/Demo/cm_pasc.pas | 48 + VCL/CM2x/Help/colormemo.GID | Bin 0 -> 10876 bytes VCL/CM2x/INSTALL.LOG | 63 + VCL/CM2x/install.txt | 6 + VCL/CM2x/licence.txt | 106 + VCL/CM2x/news.txt | 31 + VCL/CM2x/ordering.txt | 23 + VCL/CM2x/readme.txt | 27 + VCL/CONSOLE.PAS | 1891 ++++ VCL/ComDrv32.dcr | Bin 0 -> 484 bytes VCL/ComDrv32.dcu | Bin 0 -> 14029 bytes VCL/ComDrv32.pas | 870 ++ VCL/Console.dcu | Bin 0 -> 33569 bytes VCL/EnhWave.dcr | Bin 0 -> 3416 bytes VCL/EnhWave.dcu | Bin 0 -> 8532 bytes VCL/FngSingleInst.dcu | Bin 0 -> 4235 bytes VCL/FngSingleInst.pas | 154 + VCL/FngSingleInst.~pas | 154 + VCL/GrabBar.bmp | Bin 0 -> 406 bytes VCL/GrabBar.dcu | Bin 0 -> 13608 bytes VCL/GrabBar.pas | 659 ++ VCL/GrabBar.r16 | Bin 0 -> 410 bytes VCL/GrabBar.r32 | Bin 0 -> 472 bytes VCL/GrabBar.rc | 1 + VCL/HEMIBTN.DCR | Bin 0 -> 488 bytes VCL/HEMIBTN.DCU | Bin 0 -> 18700 bytes VCL/HID/DBT.dcu | Bin 0 -> 5292 bytes VCL/HID/DBT.pas | 596 ++ VCL/HID/DEMOS/CollectionDemo/Project1.dof | 83 + VCL/HID/DEMOS/CollectionDemo/Project1.dpr | 14 + VCL/HID/DEMOS/CollectionDemo/Project1.res | Bin 0 -> 876 bytes VCL/HID/DEMOS/CollectionDemo/Unit1.dcu | Bin 0 -> 4975 bytes VCL/HID/DEMOS/CollectionDemo/Unit1.dfm | Bin 0 -> 524 bytes VCL/HID/DEMOS/CollectionDemo/Unit1.pas | 67 + VCL/HID/DEMOS/HidClassDemo/HidClassDemo.dof | 91 + VCL/HID/DEMOS/HidClassDemo/HidClassDemo.dpr | 17 + VCL/HID/DEMOS/HidClassDemo/HidClassDemo.res | Bin 0 -> 964 bytes VCL/HID/DEMOS/HidClassDemo/Unit1.dcu | Bin 0 -> 5219 bytes VCL/HID/DEMOS/HidClassDemo/Unit1.dfm | Bin 0 -> 578 bytes VCL/HID/DEMOS/HidClassDemo/Unit1.pas | 85 + .../DEMOS/ReadWriteDemo/SimpleHIDWrite.dof | 83 + .../DEMOS/ReadWriteDemo/SimpleHIDWrite.dpr | 14 + .../DEMOS/ReadWriteDemo/SimpleHIDWrite.res | Bin 0 -> 876 bytes VCL/HID/DEMOS/ReadWriteDemo/Unit1.dcu | Bin 0 -> 9775 bytes VCL/HID/DEMOS/ReadWriteDemo/Unit1.dfm | Bin 0 -> 1855 bytes VCL/HID/DEMOS/ReadWriteDemo/Unit1.pas | 228 + VCL/HID/DEMOS/ReadWriteDemo/Unit2.dcu | Bin 0 -> 5128 bytes VCL/HID/DEMOS/ReadWriteDemo/Unit2.dfm | Bin 0 -> 1867 bytes VCL/HID/DEMOS/ReadWriteDemo/Unit2.pas | 73 + VCL/HID/DEMOS/ThreadDemo/GreyMouser.dof | 83 + VCL/HID/DEMOS/ThreadDemo/GreyMouser.dpr | 13 + VCL/HID/DEMOS/ThreadDemo/GreyMouser.res | Bin 0 -> 876 bytes VCL/HID/DEMOS/ThreadDemo/MouseReader.dcu | Bin 0 -> 6182 bytes VCL/HID/DEMOS/ThreadDemo/MouseReader.dfm | Bin 0 -> 815 bytes VCL/HID/DEMOS/ThreadDemo/MouseReader.pas | 123 + VCL/HID/Hid.dcu | Bin 0 -> 12233 bytes VCL/HID/Hid.pas | 2110 +++++ VCL/HID/HidController.GID | Bin 0 -> 23123 bytes VCL/HID/HidController.dcu | Bin 0 -> 2626 bytes VCL/HID/HidController.dof | 91 + VCL/HID/HidController.dpk | 37 + VCL/HID/HidController.res | Bin 0 -> 1536 bytes VCL/HID/HidControllerClass.dcr | Bin 0 -> 500 bytes VCL/HID/HidControllerClass.dcu | Bin 0 -> 32966 bytes VCL/HID/HidControllerClass.pas | 1380 +++ VCL/HID/HidControllerClass.~pas | 1357 +++ VCL/HID/HidToken.pas | 204 + VCL/HID/HidUsage.pas | 783 ++ VCL/HID/README.TXT | 80 + VCL/HID/SetupApi.dcu | Bin 0 -> 98681 bytes VCL/HID/SetupApi.pas | 4720 ++++++++++ VCL/HID/help/BMP/empty.bmp | Bin 0 -> 246 bytes VCL/HID/help/BMP/published.bmp | Bin 0 -> 246 bytes VCL/HID/help/BMP/readonly.bmp | Bin 0 -> 246 bytes VCL/HID/help/BMP/usb.bmp | Bin 0 -> 838 bytes VCL/HID/help/HidController.GID | Bin 0 -> 23123 bytes VCL/HID/help/HidController.hpj | 22 + VCL/HID/help/HidController.toc | 8 + VCL/HID/help/RTF/_#HID_Overview.RTF | 16 + VCL/HID/help/RTF/hidController.rtf | 1614 ++++ VCL/JLLabel.dcu | Bin 0 -> 10755 bytes VCL/JLLabel.pas | 300 + VCL/JLlabel.dcr | Bin 0 -> 1728 bytes VCL/JLlabel.dcr.res | Bin 0 -> 1728 bytes VCL/MJWCRT.PAS | 809 ++ VCL/Mjwcrt.dcu | Bin 0 -> 16850 bytes VCL/OEDIT.PAS | 134 + VCL/Oedit.dcu | Bin 0 -> 5078 bytes VCL/PathDialog.dcu | Bin 0 -> 5316 bytes VCL/PathDialog.pas | 250 + VCL/Rbutton.dcu | Bin 0 -> 6241 bytes VCL/SoftButt.pas | 257 + VCL/Splitbar.dcu | Bin 0 -> 5303 bytes VCL/Splitbar.pas | 238 + VCL/StrCGrid.dcr | Bin 0 -> 476 bytes VCL/StrCGrid.dcu | Bin 0 -> 14541 bytes VCL/StrCGrid.pas | 875 ++ VCL/Strcgrid.txt | 109 + VCL/Super32.dcr | Bin 0 -> 476 bytes VCL/Super32.dcu | Bin 0 -> 704 bytes VCL/Super32.res | Bin 0 -> 1360 bytes VCL/SuperCol.dcu | Bin 0 -> 19191 bytes VCL/SuperGrd.dcu | Bin 0 -> 22244 bytes VCL/SuperGrid.dcu | Bin 0 -> 2396 bytes VCL/SuperGrid.dpl | Bin 0 -> 128000 bytes VCL/THDTIM.PAS | 151 + VCL/TRAPEDIT.PAS | 44 + VCL/TToneGen.dcu | Bin 0 -> 2507 bytes VCL/TToneGen.dof | 83 + VCL/TToneGen.dpk | 33 + VCL/TToneGen.res | Bin 0 -> 1976 bytes VCL/TToneGen.~dpk | 33 + VCL/Thdtim.dcu | Bin 0 -> 3617 bytes VCL/Thumbs.db | Bin 0 -> 5632 bytes VCL/ToneGen.dcu | Bin 0 -> 22132 bytes VCL/ToneGen.pas | 1614 ++++ VCL/Trapedit.dcu | Bin 0 -> 3510 bytes VCL/Unit1.dcu | Bin 0 -> 3690 bytes VCL/VNTI files/AND_Gate_152_GFPUV.gb | 139 + VCL/VNTI files/ApE_pLacthiM2lacZ.gb | 246 + VCL/VNTI files/CLC_pBADHisA.gb | 127 + VCL/VNTI files/Hashimoto-Goto et al 2000.pdf | Bin 0 -> 254331 bytes .../Theophylline Aptamer for Riboswitch.gb | 488 + VCL/VNTI files/p+thiM#2lacZ.gb | 1440 +++ VCL/VNTI files/pBADHisA.gb | 1369 +++ VCL/VNTI files/pCIBT.gb | 1278 +++ VCL/VNTI files/pDelEStheogfpuv2.1.gb | 1485 +++ VCL/VNTI files/pE19T.gb | 1422 +++ VCL/VNTI files/pEGFP-N1.gb | 1315 +++ VCL/VNTI files/pINV-107bgfpuv.gb | 1475 +++ VCL/VNTI files/pK-A-CIT1.gb | 1529 +++ VCL/VNTI files/pK184.1.gb | 1389 +++ VCL/VNTI files/pK184.3.gb | 1317 +++ VCL/VNTI files/pK184.gb | 1446 +++ VCL/VNTI files/pLac+thiM#2tetA (JACS).gb | 981 ++ VCL/VNTI files/pLac+thiM#2tetA.gb | 1480 +++ VCL/VNTI files/pLacECR#48-LibAL1.gb | 1700 ++++ VCL/VNTI files/pLacECR#48-lacZ.gb | 1513 +++ VCL/VNTI files/pLacECR#48-tetA-GS-GFP.gb | 1651 ++++ VCL/VNTI files/pLacECR48-GFP.gb | 1559 ++++ VCL/VNTI files/pLacN99mtetA.gb | 1487 +++ VCL/VNTI files/pLacNH-H6.gb | 653 ++ VCL/VNTI files/pLacStrHNgfpuvX.gb | 880 ++ VCL/VNTI files/pLacT.gb | 1365 +++ VCL/VNTI files/pLacT1.gb | 1163 +++ VCL/VNTI files/pLacTheo28-N20+thiM2gfpuv.gb | 1613 ++++ VCL/VNTI files/pLacTheo28-N20+thiM2lacZ.gb | 1540 +++ VCL/VNTI files/pLacTheo28-N20-thiMtetA-N30.gb | 1613 ++++ VCL/VNTI files/pLacTheo28thiMtetA.gb | 1553 ++++ VCL/VNTI files/pLactenA#59tetA-GS-GFP.gb | 1648 ++++ .../pLactenAtetA-GS-GFP-lib2(Archit).gb | 1637 ++++ VCL/VNTI files/pLactenAtetA.gb | 1497 +++ VCL/VNTI files/pLactheo28bgl-lacZX.gb | 1121 +++ VCL/VNTI files/pLacthiM2gfpuv.gb | 1512 +++ VCL/VNTI files/pLacthiM2lacZ.gb | 1434 +++ VCL/VNTI files/pLacthiM2tetA-GS-GFP.gb | 1677 ++++ VCL/VNTI files/pLacthiM2tetA.gb | 1482 +++ VCL/VNTI files/pLacthiMN15#19gfpuv.gb | 1383 +++ .../pLacthiMgfpuv-sp1+thiM81lacZ.gb | 1668 ++++ VCL/VNTI files/pLacthiMgfpuv.gb | 1493 +++ VCL/VNTI files/pLacthiMlacZ-N30#2mutCCGG.gb | 1410 +++ VCL/VNTI files/pLacthiMlacZ-N30#2mutTCGA.gb | 1410 +++ VCL/VNTI files/pLacthiMlacZ-N30.gb | 1271 +++ VCL/VNTI files/pLacthiMlacZ.gb | 1533 +++ VCL/VNTI files/pLacthiMmcherry-N30#2.gb | 1429 +++ VCL/VNTI files/pLacthiMtetA(BamHI-).gb | 1470 +++ VCL/VNTI files/pLacthiMtetA.gb | 1486 +++ VCL/VNTI files/pNAND10tetA.gb | 1558 ++++ VCL/VNTI files/pNAND1tetA.gb | 1550 ++++ VCL/VNTI files/pNMS1-29 gfp-NheI.gb | 1745 ++++ VCL/VNTI files/pNMS1-29.gb | 1603 ++++ VCL/VNTI files/pPantACIT1.gb | 1169 +++ VCL/VNTI files/pRDV-1.4k-His6-mcherry.gb | 1446 +++ VCL/VNTI files/pRDV-His6-mcherry(SD-).gb | 1358 +++ VCL/VNTI files/pRDV-His6-mcherry.gb | 1355 +++ VCL/VNTI files/pRDV-His6-tolAk.gb | 1248 +++ VCL/VNTI files/pRDV-NanoTag15-mcherry(SD-).gb | 956 ++ VCL/VNTI files/pRDV-NanoTag15-mcherry.gb | 981 ++ .../pRDV-thiMN15#19-His6-mcherry.gb | 1326 +++ .../pRDV-thiMN15#19-NanoTag15-mcherry.gb | 1022 ++ .../pRDV-thiMN25SDN6-His6-mcherry.gb | 1265 +++ VCL/VNTI files/pRDV.gb | 943 ++ VCL/VNTI files/pTH18XXA.gb | 772 ++ VCL/VNTI files/pTH18cr (AB019609).gb | 1122 +++ VCL/VNTI files/pTH18kr.gb | 124 + VCL/VNTI files/pTenA gfpuv (1uM ON) #59.gb | 1539 +++ .../pTenA gfpuv (XhoI-) (1uM ON) #59.gb | 1546 +++ VCL/VNTI files/pWY1.gb | 1619 ++++ VCL/VNTI files/pWY2.gb | 1624 ++++ VCL/VNTI files/ptheogfpuv2.1.gb | 1483 +++ VCL/VNTI files/pthiCgfp#19.gb | 1417 +++ VCL/VNTI files/pthiCgfp#35.gb | 1393 +++ VCL/VNTI files/pthiCgfpuv (XhoI-).gb | 1298 +++ VCL/VNTI files/thiM riboswitch library.gb | 780 ++ VCL/WSockets/Examples/TCPClient.dpr | 13 + VCL/WSockets/Examples/TCPClientUnit.dcu | Bin 0 -> 6424 bytes VCL/WSockets/Examples/TCPClientUnit.dfm | Bin 0 -> 1465 bytes VCL/WSockets/Examples/TCPClientUnit.pas | 153 + VCL/WSockets/Examples/TCPServer.dpr | 13 + VCL/WSockets/Examples/TCPServerUnit.dfm | Bin 0 -> 1490 bytes VCL/WSockets/Examples/TCPServerUnit.pas | 184 + VCL/WSockets/Examples/UDPClient.dpr | 13 + VCL/WSockets/Examples/UDPClientUnit.dfm | Bin 0 -> 1383 bytes VCL/WSockets/Examples/UDPClientUnit.pas | 130 + VCL/WSockets/Examples/UDPServer.dpr | 13 + VCL/WSockets/Examples/UDPServerUnit.dfm | Bin 0 -> 989 bytes VCL/WSockets/Examples/UDPServerUnit.pas | 121 + VCL/WSockets/Examples/WSockets.dcu | Bin 0 -> 33560 bytes VCL/WSockets/FILE_ID.DIZ | 6 + VCL/WSockets/Readme.txt | 129 + VCL/WSockets/WSockets.dcr | Bin 0 -> 2584 bytes VCL/WSockets/WSockets.dcu | Bin 0 -> 27340 bytes VCL/WSockets/WSockets.doc | Bin 0 -> 26112 bytes VCL/WSockets/WSockets.pas | 1550 ++++ VCL/WTHREAD.DCR | Bin 0 -> 316 bytes VCL/WTHREAD.PAS | 531 ++ VCL/Wthread.dcu | Bin 0 -> 11994 bytes VCL/addedcomp.dcp | Bin 0 -> 308749 bytes VCL/addedcomp.dcu | Bin 0 -> 2779 bytes VCL/addedcomp.dpk | 55 + VCL/addedcomp.dpl | Bin 0 -> 350208 bytes VCL/addedcomp.res | Bin 0 -> 32 bytes VCL/addedcomp.~dp | 54 + VCL/aligrid21/AH_COMP.DPK | 35 + VCL/aligrid21/AH_DEF.INC | 93 + VCL/aligrid21/AH_TOOL.PAS | 1157 +++ VCL/aligrid21/AH_TOOL.dcu | Bin 0 -> 16416 bytes VCL/aligrid21/AH_TOOL.~PAS | 1156 +++ VCL/aligrid21/ALIGREDI.DFM | Bin 0 -> 4854 bytes VCL/aligrid21/ALIGREDI.PAS | 700 ++ VCL/aligrid21/ALIGREDI.dcu | Bin 0 -> 25836 bytes VCL/aligrid21/ALIGRID.D16 | Bin 0 -> 418 bytes VCL/aligrid21/ALIGRID.PAS | 6542 +++++++++++++ VCL/aligrid21/ALIGRIDR.PAS | 64 + VCL/aligrid21/ALIGRIDR.dcu | Bin 0 -> 2517 bytes VCL/aligrid21/D3/AH_COMP.DPK | 35 + VCL/aligrid21/D4/AH_COMP.DPK | 34 + VCL/aligrid21/D5/AH_COMP.DPK | 34 + VCL/aligrid21/ICONGRID.PAS | 279 + VCL/aligrid21/README.TXT | 30 + VCL/aligrid21/aligrid.dcu | Bin 0 -> 117687 bytes VCL/async32.dcr | Bin 0 -> 468 bytes VCL/async32.dcu | Bin 0 -> 17231 bytes VCL/async32.pas | 753 ++ VCL/async32.~pas | 753 ++ VCL/async32_x/Async32.doc | 399 + VCL/async32_x/CommInt.dcr | Bin 0 -> 464 bytes VCL/async32_x/CommInt.dcu | Bin 0 -> 22254 bytes VCL/async32_x/CommInt.pas | 858 ++ VCL/async32_x/CommObjs.dcu | Bin 0 -> 4044 bytes VCL/async32_x/CommObjs.pas | 143 + VCL/async32_x/CommReg.bpl | Bin 0 -> 29184 bytes VCL/async32_x/CommReg.dcp | Bin 0 -> 25485 bytes VCL/async32_x/CommReg.dcu | Bin 0 -> 1157 bytes VCL/async32_x/CommReg.dof | 83 + VCL/async32_x/CommReg.dpk | 37 + VCL/async32_x/CommReg.res | Bin 0 -> 876 bytes VCL/async32_x/CommReg.~dpk | 37 + VCL/async32_x/Demo.dpr | 13 + VCL/async32_x/Demo.res | Bin 0 -> 876 bytes VCL/async32_x/Readme.txt | 32 + VCL/async32_x/Whatsnew.txt | 108 + VCL/async32_x/formMain.dcu | Bin 0 -> 15801 bytes VCL/async32_x/formMain.dfm | Bin 0 -> 4437 bytes VCL/async32_x/formMain.pas | 315 + VCL/asynctim.zip | Bin 0 -> 22362 bytes VCL/audio.int | 87 + VCL/bpanel.dcu | Bin 0 -> 4220 bytes VCL/bpanel.pas | 151 + VCL/bpreg.dcu | Bin 0 -> 351 bytes VCL/bpreg.pas | 19 + VCL/cdd4/CPDReg.dcu | Bin 0 -> 572 bytes VCL/cdd4/CPDReg.pas | 25 + VCL/cdd4/CPDrv.dcu | Bin 0 -> 18738 bytes VCL/cdd4/CPDrv.pas | 1136 +++ VCL/cdd4/ComDrv32.bpl | Bin 0 -> 28160 bytes VCL/cdd4/ComDrv32.dcr | Bin 0 -> 484 bytes VCL/cdd4/ComDrv32.dcu | Bin 0 -> 1771 bytes VCL/cdd4/ComDrv32.dpk | 35 + VCL/cdd4/ComDrv32.res | Bin 0 -> 2036 bytes VCL/cdd4/Demos/TTY/AboutTTY.dcu | Bin 0 -> 4531 bytes VCL/cdd4/Demos/TTY/AboutTTY.dfm | Bin 0 -> 20493 bytes VCL/cdd4/Demos/TTY/AboutTTY.pas | 70 + VCL/cdd4/Demos/TTY/MnForm.dfm | Bin 0 -> 70274 bytes VCL/cdd4/Demos/TTY/MnForm.pas | 448 + VCL/cdd4/Demos/TTY/MnForm.~dfm | Bin 0 -> 39232 bytes VCL/cdd4/Demos/TTY/MnForm.~pas | 449 + VCL/cdd4/Demos/TTY/Res/About.bmp | Bin 0 -> 2374 bytes VCL/cdd4/Demos/TTY/Res/Connect.bmp | Bin 0 -> 2374 bytes VCL/cdd4/Demos/TTY/Res/Disconnect.bmp | Bin 0 -> 2374 bytes VCL/cdd4/Demos/TTY/Res/Quit.bmp | Bin 0 -> 2374 bytes VCL/cdd4/Demos/TTY/Res/Settings.bmp | Bin 0 -> 2374 bytes VCL/cdd4/Demos/TTY/Res/TTYDemo.bmp | Bin 0 -> 12602 bytes VCL/cdd4/Demos/TTY/SettingsDlg.dcu | Bin 0 -> 6882 bytes VCL/cdd4/Demos/TTY/SettingsDlg.dfm | Bin 0 -> 3518 bytes VCL/cdd4/Demos/TTY/SettingsDlg.pas | 119 + VCL/cdd4/Demos/TTY/TTY.dof | 81 + VCL/cdd4/Demos/TTY/TTY.dpr | 17 + VCL/cdd4/Demos/TTY/TTY.res | Bin 0 -> 876 bytes VCL/cdd4/Help/ComDrv32.GID | Bin 0 -> 19022 bytes VCL/cdd4/Help/ComDrv32.toc | 9 + VCL/cdd4/OpenMe.bpg | 23 + VCL/cologrid/Cologrid.dcu | Bin 0 -> 9876 bytes VCL/cologrid/Cologrid.pas | 264 + VCL/cologrid/Cologrid.~pa | 265 + VCL/cologrid/P2.DPR | 12 + VCL/cologrid/P2.OPT | 34 + VCL/cologrid/README.TXT | 8 + VCL/cologrid/U3.DFM | Bin 0 -> 4629 bytes VCL/cologrid/U3.PAS | 71 + VCL/comm32.zip | Bin 0 -> 17018 bytes VCL/consol.zip | Bin 0 -> 18043 bytes VCL/console1.zip | Bin 0 -> 26795 bytes VCL/console2.dcu | Bin 0 -> 33584 bytes VCL/console2.pas | 1891 ++++ VCL/console2.~pa | 1891 ++++ VCL/console2.~pas | 1891 ++++ VCL/d2_qa.zip | Bin 0 -> 11680 bytes VCL/date/CalPop97.dcu | Bin 0 -> 22504 bytes VCL/date/CalPop97.dfm | Bin 0 -> 379 bytes VCL/date/CalPop97.pas | 1268 +++ VCL/date/DATEED97.RC | 88 + VCL/date/DEd97_b.res | Bin 0 -> 1260 bytes VCL/date/DateDB97.dcu | Bin 0 -> 8494 bytes VCL/date/DateDB97.pas | 322 + VCL/date/DateEd97.dcu | Bin 0 -> 24526 bytes VCL/date/DateEd97.pas | 977 ++ VCL/date/DateEd97.res | Bin 0 -> 1116 bytes VCL/date/DateFT97.dcu | Bin 0 -> 17208 bytes VCL/date/DateFT97.pas | 627 ++ VCL/date/DatePk97.txt | 143 + VCL/date/DateRg97.dcr | Bin 0 -> 1372 bytes VCL/date/DateRg97.dcu | Bin 0 -> 857 bytes VCL/date/DateRg97.pas | 40 + VCL/graph/AABGRAPH.DCR | Bin 0 -> 906 bytes VCL/graph/AABGRAPH.DOC | Bin 0 -> 19968 bytes VCL/graph/AABGRAPH.PAS | 2458 +++++ VCL/graph/AABGRAPH.TXT | 210 + VCL/graph/Aabgraph.dcu | Bin 0 -> 52324 bytes VCL/graph/DEMO/TEST.DPR | 13 + VCL/graph/DEMO/TEST.RES | Bin 0 -> 794 bytes VCL/graph/DEMO/TEST1.DFM | Bin 0 -> 11783 bytes VCL/graph/DEMO/TEST1.PAS | 292 + VCL/graph/DEMO/TEST1.dcu | Bin 0 -> 10927 bytes VCL/hemi/HEMIBTN.DCR | Bin 0 -> 488 bytes VCL/hemi/HemiBtn.pas | 970 ++ VCL/hemi/Hemibtn.dcu | Bin 0 -> 27181 bytes VCL/hemi/Project1.dpr | 13 + VCL/hemi/Project2.dpr | 13 + VCL/hemi/Unit1.dcu | Bin 0 -> 4109 bytes VCL/hemi/Unit2.dfm | Bin 0 -> 311331 bytes VCL/hemi/Unit2.pas | 25 + VCL/hemi/pHemibtn.dcp | Bin 0 -> 16095 bytes VCL/hemi/pHemibtn.dcu | Bin 0 -> 1286 bytes VCL/hemi/pHemibtn.dpk | 35 + VCL/hemi/pHemibtn.dpl | Bin 0 -> 32256 bytes VCL/hemi/pHemibtn.res | Bin 0 -> 32 bytes VCL/hemi/pHemibtn.~dp | 35 + VCL/hemi/unit1.dfm | Bin 0 -> 351913 bytes VCL/hemi/unit1.pas | 65 + VCL/ics/Bcb1/DelBcb1.mak | 77 + VCL/ics/Bcb1/IcsBcb1.bat | 45 + VCL/ics/Bcb1/IcsBcb1.mak | 254 + VCL/ics/Cpp/Internet/Bcb1/CliDemo.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/CliDemo.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/Clidemo.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/Client5.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/Client5.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/Client5.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/Client7.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/Client7.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/Client7.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/ConCli1.cpp | 85 + VCL/ics/Cpp/Internet/Bcb1/ConCli1.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/ConCli2.cpp | 155 + VCL/ics/Cpp/Internet/Bcb1/ConCli2.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/Finger.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/Finger.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/Finger.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/FtpServ.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/FtpServ.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/FtpServ.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/HttpPg.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/HttpPg.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/HttpPg.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/MailSnd.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/MailSnd.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/MailSnd.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/MtSrv.cpp | 23 + VCL/ics/Cpp/Internet/Bcb1/MtSrv.mak | 59 + VCL/ics/Cpp/Internet/Bcb1/MtSrv.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/NewsRdr.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/NewsRdr.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/NewsRdr.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/PingTst.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/PingTst.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/PingTst.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/Recv.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/Recv.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/Recv.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/Sender.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/Sender.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/Sender.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/Server5.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/Server5.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/Server5.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/SocksTst.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/SocksTst.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/Sockstst.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/SrvDemo.cpp | 24 + VCL/ics/Cpp/Internet/Bcb1/SrvDemo.mak | 60 + VCL/ics/Cpp/Internet/Bcb1/Srvdemo.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/TWSChat.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/TWSChat.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/TcpSrv.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/TcpSrv.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/Tcpsrv.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/TnDemo.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/TnDemo.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/TnDemo.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/TnSrv.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/UdpLstn.cpp | 23 + VCL/ics/Cpp/Internet/Bcb1/UdpLstn.mak | 59 + VCL/ics/Cpp/Internet/Bcb1/clients.DBF | Bin 0 -> 434 bytes VCL/ics/Cpp/Internet/Bcb1/clients.MDX | Bin 0 -> 6144 bytes VCL/ics/Cpp/Internet/Bcb1/ftptst.cpp | 24 + VCL/ics/Cpp/Internet/Bcb1/ftptst.mak | 60 + VCL/ics/Cpp/Internet/Bcb1/ftptst.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/httptst.cpp | 22 + VCL/ics/Cpp/Internet/Bcb1/httptst.mak | 58 + VCL/ics/Cpp/Internet/Bcb1/httptst.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/poptst.cpp | 28 + VCL/ics/Cpp/Internet/Bcb1/poptst.mak | 57 + VCL/ics/Cpp/Internet/Bcb1/tnclient.cpp | 25 + VCL/ics/Cpp/Internet/Bcb1/tnclient.mak | 61 + VCL/ics/Cpp/Internet/Bcb1/tnclient.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/tnsrv.cpp | 24 + VCL/ics/Cpp/Internet/Bcb1/tnsrv.mak | 59 + VCL/ics/Cpp/Internet/Bcb1/twschat.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/udplstn.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb1/udpsend.cpp | 23 + VCL/ics/Cpp/Internet/Bcb1/udpsend.mak | 59 + VCL/ics/Cpp/Internet/Bcb1/udpsend.res | Bin 0 -> 876 bytes VCL/ics/Cpp/Internet/Bcb3/Bcb30Sam.bpg | 107 + VCL/ics/Cpp/Internet/Bcb3/CliDemo.bpr | 187 + VCL/ics/Cpp/Internet/Bcb3/CliDemo.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/Client5.bpr | 183 + VCL/ics/Cpp/Internet/Bcb3/Client5.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/Client7.bpr | 181 + VCL/ics/Cpp/Internet/Bcb3/Client7.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/ConCli1.bpr | 177 + VCL/ics/Cpp/Internet/Bcb3/ConCli1.cpp | 86 + VCL/ics/Cpp/Internet/Bcb3/ConCli2.bpr | 161 + VCL/ics/Cpp/Internet/Bcb3/ConCli2.cpp | 154 + VCL/ics/Cpp/Internet/Bcb3/Finger.bpr | 181 + VCL/ics/Cpp/Internet/Bcb3/Finger.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/FtpServ.bpr | 181 + VCL/ics/Cpp/Internet/Bcb3/FtpServ.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/HttpPg.bpr | 181 + VCL/ics/Cpp/Internet/Bcb3/HttpPg.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/MailRcv.bpr | 181 + VCL/ics/Cpp/Internet/Bcb3/MailRcv.cpp | 23 + VCL/ics/Cpp/Internet/Bcb3/MailSnd.bpr | 181 + VCL/ics/Cpp/Internet/Bcb3/MailSnd.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/MtSrv.bpr | 181 + VCL/ics/Cpp/Internet/Bcb3/MtSrv.cpp | 22 + VCL/ics/Cpp/Internet/Bcb3/NewsRdr.bpr | 181 + VCL/ics/Cpp/Internet/Bcb3/NewsRdr.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/NsLookup.bpr | 183 + VCL/ics/Cpp/Internet/Bcb3/NsLookup.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/PingTst.bpr | 181 + VCL/ics/Cpp/Internet/Bcb3/PingTst.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/Recv.bpr | 183 + VCL/ics/Cpp/Internet/Bcb3/Recv.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/Sender.bpr | 187 + VCL/ics/Cpp/Internet/Bcb3/Sender.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/Server5.bpr | 181 + VCL/ics/Cpp/Internet/Bcb3/Server5.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/SocksTst.bpr | 181 + VCL/ics/Cpp/Internet/Bcb3/SocksTst.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/SrvDemo.bpr | 187 + VCL/ics/Cpp/Internet/Bcb3/SrvDemo.cpp | 23 + VCL/ics/Cpp/Internet/Bcb3/TWSChat.bpr | 179 + VCL/ics/Cpp/Internet/Bcb3/TWSChat.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/TcpSrv.bpr | 188 + VCL/ics/Cpp/Internet/Bcb3/TcpSrv.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/TnClient.bpr | 181 + VCL/ics/Cpp/Internet/Bcb3/TnClient.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/TnDemo.bpr | 181 + VCL/ics/Cpp/Internet/Bcb3/TnDemo.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/UdpLstn.bpr | 179 + VCL/ics/Cpp/Internet/Bcb3/UdpLstn.cpp | 22 + VCL/ics/Cpp/Internet/Bcb3/UdpSend.bpr | 179 + VCL/ics/Cpp/Internet/Bcb3/UdpSend.cpp | 22 + VCL/ics/Cpp/Internet/Bcb3/clients.DBF | Bin 0 -> 434 bytes VCL/ics/Cpp/Internet/Bcb3/clients.MDX | Bin 0 -> 6144 bytes VCL/ics/Cpp/Internet/Bcb3/ftptst.bpr | 183 + VCL/ics/Cpp/Internet/Bcb3/ftptst.cpp | 23 + VCL/ics/Cpp/Internet/Bcb3/httptst.bpr | 187 + VCL/ics/Cpp/Internet/Bcb3/httptst.cpp | 21 + VCL/ics/Cpp/Internet/Bcb3/poptst.bpr | 183 + VCL/ics/Cpp/Internet/Bcb3/poptst.cpp | 27 + VCL/ics/Cpp/Internet/Bcb3/tnsrv.bpr | 178 + VCL/ics/Cpp/Internet/Bcb3/tnsrv.cpp | 23 + VCL/ics/Cpp/Internet/Bcb4/Bcb40Sam.bpg | 108 + VCL/ics/Cpp/Internet/Bcb4/Clidemo.bpr | 213 + VCL/ics/Cpp/Internet/Bcb4/Clidemo.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/Client5.bpr | 207 + VCL/ics/Cpp/Internet/Bcb4/Client5.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/Client7.bpr | 207 + VCL/ics/Cpp/Internet/Bcb4/Client7.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/Concli1.bpr | 205 + VCL/ics/Cpp/Internet/Bcb4/Concli1.cpp | 86 + VCL/ics/Cpp/Internet/Bcb4/Concli2.bpr | 186 + VCL/ics/Cpp/Internet/Bcb4/Concli2.cpp | 154 + VCL/ics/Cpp/Internet/Bcb4/Finger.bpr | 205 + VCL/ics/Cpp/Internet/Bcb4/Finger.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/FtpTst.bpr | 206 + VCL/ics/Cpp/Internet/Bcb4/FtpTst.cpp | 23 + VCL/ics/Cpp/Internet/Bcb4/Ftpserv.bpr | 205 + VCL/ics/Cpp/Internet/Bcb4/Ftpserv.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/HttpPg.bpr | 205 + VCL/ics/Cpp/Internet/Bcb4/HttpPg.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/HttpTst.bpr | 210 + VCL/ics/Cpp/Internet/Bcb4/HttpTst.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/MailRcv.bpr | 206 + VCL/ics/Cpp/Internet/Bcb4/MailRcv.cpp | 23 + VCL/ics/Cpp/Internet/Bcb4/MailSnd.bpr | 205 + VCL/ics/Cpp/Internet/Bcb4/MailSnd.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/MtSrv.bpr | 205 + VCL/ics/Cpp/Internet/Bcb4/MtSrv.cpp | 22 + VCL/ics/Cpp/Internet/Bcb4/NewsRdr.bpr | 205 + VCL/ics/Cpp/Internet/Bcb4/NewsRdr.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/NsLookup.bpr | 207 + VCL/ics/Cpp/Internet/Bcb4/NsLookup.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/PingTst.bpr | 205 + VCL/ics/Cpp/Internet/Bcb4/PingTst.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/PopTst.bpr | 206 + VCL/ics/Cpp/Internet/Bcb4/PopTst.cpp | 27 + VCL/ics/Cpp/Internet/Bcb4/Recv.bpr | 207 + VCL/ics/Cpp/Internet/Bcb4/Recv.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/Sender.bpr | 207 + VCL/ics/Cpp/Internet/Bcb4/Sender.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/Server5.bpr | 205 + VCL/ics/Cpp/Internet/Bcb4/Server5.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/SocksTst.bpr | 203 + VCL/ics/Cpp/Internet/Bcb4/SocksTst.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/SrvDemo.bpr | 207 + VCL/ics/Cpp/Internet/Bcb4/SrvDemo.cpp | 23 + VCL/ics/Cpp/Internet/Bcb4/TWSChat.bpr | 203 + VCL/ics/Cpp/Internet/Bcb4/TWSChat.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/TcpSrv.bpr | 208 + VCL/ics/Cpp/Internet/Bcb4/TcpSrv.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/TnClient.bpr | 205 + VCL/ics/Cpp/Internet/Bcb4/TnClient.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/TnDemo.bpr | 205 + VCL/ics/Cpp/Internet/Bcb4/TnDemo.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/TnSrv.bpr | 202 + VCL/ics/Cpp/Internet/Bcb4/TnSrv.cpp | 23 + VCL/ics/Cpp/Internet/Bcb4/UdpLstn.bpr | 203 + VCL/ics/Cpp/Internet/Bcb4/UdpLstn.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/UdpSend.bpr | 203 + VCL/ics/Cpp/Internet/Bcb4/UdpSend.cpp | 21 + VCL/ics/Cpp/Internet/Bcb4/clients.DBF | Bin 0 -> 434 bytes VCL/ics/Cpp/Internet/Bcb4/clients.MDX | Bin 0 -> 6144 bytes VCL/ics/Cpp/Internet/Bcb5/Bcb50Sam.bpg | 122 + VCL/ics/Cpp/Internet/Bcb5/Clidemo.bpr | 128 + VCL/ics/Cpp/Internet/Bcb5/Clidemo.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/Client5.bpr | 125 + VCL/ics/Cpp/Internet/Bcb5/Client5.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/Client7.bpr | 125 + VCL/ics/Cpp/Internet/Bcb5/Client7.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/Concli1.bpr | 123 + VCL/ics/Cpp/Internet/Bcb5/Concli1.cpp | 87 + VCL/ics/Cpp/Internet/Bcb5/Concli2.bpr | 102 + VCL/ics/Cpp/Internet/Bcb5/Concli2.cpp | 156 + VCL/ics/Cpp/Internet/Bcb5/DllTst1.bpr | 100 + VCL/ics/Cpp/Internet/Bcb5/DllTst1.cpp | 22 + VCL/ics/Cpp/Internet/Bcb5/Finger.bpr | 127 + VCL/ics/Cpp/Internet/Bcb5/Finger.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/FtpTst.bpr | 127 + VCL/ics/Cpp/Internet/Bcb5/FtpTst.cpp | 23 + VCL/ics/Cpp/Internet/Bcb5/Ftpserv.bpr | 127 + VCL/ics/Cpp/Internet/Bcb5/Ftpserv.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/HttpPg.bpr | 126 + VCL/ics/Cpp/Internet/Bcb5/HttpPg.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/HttpTst.bpr | 131 + VCL/ics/Cpp/Internet/Bcb5/HttpTst.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/IcsDll1.bpf | 6 + VCL/ics/Cpp/Internet/Bcb5/IcsDll1.bpr | 118 + VCL/ics/Cpp/Internet/Bcb5/IcsDll1.cpp | 273 + VCL/ics/Cpp/Internet/Bcb5/MailRcv.bpr | 124 + VCL/ics/Cpp/Internet/Bcb5/MailRcv.cpp | 23 + VCL/ics/Cpp/Internet/Bcb5/MailSnd.bpr | 129 + VCL/ics/Cpp/Internet/Bcb5/MailSnd.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/MtSrv.bpr | 124 + VCL/ics/Cpp/Internet/Bcb5/MtSrv.cpp | 22 + VCL/ics/Cpp/Internet/Bcb5/NewsRdr.bpr | 123 + VCL/ics/Cpp/Internet/Bcb5/NewsRdr.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/NsLookup.bpr | 127 + VCL/ics/Cpp/Internet/Bcb5/NsLookup.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/PingTst.bpr | 125 + VCL/ics/Cpp/Internet/Bcb5/PingTst.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/PopTst.cpp | 27 + VCL/ics/Cpp/Internet/Bcb5/Recv.bpr | 127 + VCL/ics/Cpp/Internet/Bcb5/Recv.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/Sender.bpr | 128 + VCL/ics/Cpp/Internet/Bcb5/Sender.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/Server5.bpr | 125 + VCL/ics/Cpp/Internet/Bcb5/Server5.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/SocksTst.bpr | 123 + VCL/ics/Cpp/Internet/Bcb5/SocksTst.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/SrvDemo.bpr | 127 + VCL/ics/Cpp/Internet/Bcb5/SrvDemo.cpp | 23 + VCL/ics/Cpp/Internet/Bcb5/TWSChat.bpr | 123 + VCL/ics/Cpp/Internet/Bcb5/TWSChat.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/TcpSrv.bpr | 119 + VCL/ics/Cpp/Internet/Bcb5/TcpSrv.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/TnClient.bpr | 125 + VCL/ics/Cpp/Internet/Bcb5/TnClient.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/TnDemo.bpr | 125 + VCL/ics/Cpp/Internet/Bcb5/TnDemo.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/TnSrv.bpr | 122 + VCL/ics/Cpp/Internet/Bcb5/TnSrv.cpp | 23 + VCL/ics/Cpp/Internet/Bcb5/UdpLstn.bpr | 123 + VCL/ics/Cpp/Internet/Bcb5/UdpLstn.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/UdpSend.bpr | 123 + VCL/ics/Cpp/Internet/Bcb5/UdpSend.cpp | 21 + VCL/ics/Cpp/Internet/Bcb5/WebServ.bpr | 119 + VCL/ics/Cpp/Internet/Bcb5/WebServ.cpp | 22 + VCL/ics/Cpp/Internet/Bcb5/clients.DBF | Bin 0 -> 434 bytes VCL/ics/Cpp/Internet/Bcb5/clients.MDX | Bin 0 -> 6144 bytes VCL/ics/Cpp/Internet/Bcb6/Bcb60Sam.bpg | 122 + VCL/ics/Cpp/Internet/Bcb6/Clidemo.bpr | 150 + VCL/ics/Cpp/Internet/Bcb6/Clidemo.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/Client5.bpr | 139 + VCL/ics/Cpp/Internet/Bcb6/Client5.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/Client7.bpr | 139 + VCL/ics/Cpp/Internet/Bcb6/Client7.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/ConCli1.bpr | 144 + VCL/ics/Cpp/Internet/Bcb6/ConCli2.bpr | 144 + VCL/ics/Cpp/Internet/Bcb6/ConCli2.cpp | 155 + VCL/ics/Cpp/Internet/Bcb6/Concli1.cpp | 87 + VCL/ics/Cpp/Internet/Bcb6/DllTst1.bpr | 114 + VCL/ics/Cpp/Internet/Bcb6/DllTst1.cpp | 22 + VCL/ics/Cpp/Internet/Bcb6/Finger.bpr | 141 + VCL/ics/Cpp/Internet/Bcb6/Finger.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/FtpServ.bpr | 146 + VCL/ics/Cpp/Internet/Bcb6/FtpTst.bpr | 142 + VCL/ics/Cpp/Internet/Bcb6/FtpTst.cpp | 23 + VCL/ics/Cpp/Internet/Bcb6/Ftpserv.cpp | 20 + VCL/ics/Cpp/Internet/Bcb6/HttpPg.bpr | 140 + VCL/ics/Cpp/Internet/Bcb6/HttpPg.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/HttpTst.bpr | 145 + VCL/ics/Cpp/Internet/Bcb6/HttpTst.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/IcsDll1.bpf | 6 + VCL/ics/Cpp/Internet/Bcb6/IcsDll1.bpr | 145 + VCL/ics/Cpp/Internet/Bcb6/IcsDll1.cpp | 273 + VCL/ics/Cpp/Internet/Bcb6/MailRcv.bpr | 139 + VCL/ics/Cpp/Internet/Bcb6/MailRcv.cpp | 23 + VCL/ics/Cpp/Internet/Bcb6/MailSnd.bpr | 143 + VCL/ics/Cpp/Internet/Bcb6/MailSnd.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/MtSrv.bpr | 139 + VCL/ics/Cpp/Internet/Bcb6/MtSrv.cpp | 22 + VCL/ics/Cpp/Internet/Bcb6/NewsRdr.bpr | 137 + VCL/ics/Cpp/Internet/Bcb6/NewsRdr.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/NsLookup.bpr | 141 + VCL/ics/Cpp/Internet/Bcb6/NsLookup.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/PingTst.bpr | 139 + VCL/ics/Cpp/Internet/Bcb6/PingTst.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/Recv.bpr | 141 + VCL/ics/Cpp/Internet/Bcb6/Recv.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/Sender.bpr | 142 + VCL/ics/Cpp/Internet/Bcb6/Sender.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/Server5.bpr | 139 + VCL/ics/Cpp/Internet/Bcb6/Server5.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/SocksTst.bpr | 137 + VCL/ics/Cpp/Internet/Bcb6/SocksTst.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/SrvDemo.bpr | 143 + VCL/ics/Cpp/Internet/Bcb6/SrvDemo.cpp | 23 + VCL/ics/Cpp/Internet/Bcb6/TWSChat.bpr | 139 + VCL/ics/Cpp/Internet/Bcb6/TWSChat.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/TcpSrv.bpr | 133 + VCL/ics/Cpp/Internet/Bcb6/TcpSrv.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/TnClient.bpr | 139 + VCL/ics/Cpp/Internet/Bcb6/TnClient.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/TnDemo.bpr | 139 + VCL/ics/Cpp/Internet/Bcb6/TnDemo.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/TnSrv.bpr | 139 + VCL/ics/Cpp/Internet/Bcb6/TnSrv.cpp | 23 + VCL/ics/Cpp/Internet/Bcb6/UdpLstn.bpr | 139 + VCL/ics/Cpp/Internet/Bcb6/UdpLstn.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/UdpSend.bpr | 139 + VCL/ics/Cpp/Internet/Bcb6/UdpSend.cpp | 21 + VCL/ics/Cpp/Internet/Bcb6/WebServ.bpr | 133 + VCL/ics/Cpp/Internet/Bcb6/WebServ.cpp | 22 + VCL/ics/Cpp/Internet/Bcb6/clients.DBF | Bin 0 -> 434 bytes VCL/ics/Cpp/Internet/Bcb6/clients.MDX | Bin 0 -> 6144 bytes VCL/ics/Cpp/Internet/Cli7.cpp | 195 + VCL/ics/Cpp/Internet/Cli7.dfm | Bin 0 -> 1855 bytes VCL/ics/Cpp/Internet/Cli7.h | 47 + VCL/ics/Cpp/Internet/CliDemo1.cpp | 176 + VCL/ics/Cpp/Internet/CliDemo1.dfm | Bin 0 -> 1627 bytes VCL/ics/Cpp/Internet/CliDemo1.h | 45 + VCL/ics/Cpp/Internet/DllTst1.cpp | 165 + VCL/ics/Cpp/Internet/DllTst1.dfm | 84 + VCL/ics/Cpp/Internet/DllTst1.h | 36 + VCL/ics/Cpp/Internet/FtpSrv1.cpp | 526 ++ VCL/ics/Cpp/Internet/FtpSrv1.dfm | Bin 0 -> 2871 bytes VCL/ics/Cpp/Internet/FtpSrv1.h | 122 + VCL/ics/Cpp/Internet/MailRcv1.cpp | 462 + VCL/ics/Cpp/Internet/MailRcv1.dfm | Bin 0 -> 4102 bytes VCL/ics/Cpp/Internet/MailRcv1.h | 105 + VCL/ics/Cpp/Internet/MailRcv2.cpp | 15 + VCL/ics/Cpp/Internet/MailRcv2.dfm | Bin 0 -> 370 bytes VCL/ics/Cpp/Internet/MailRcv2.h | 21 + VCL/ics/Cpp/Internet/MailSnd1.cpp | 277 + VCL/ics/Cpp/Internet/MailSnd1.dfm | Bin 0 -> 4633 bytes VCL/ics/Cpp/Internet/MailSnd1.h | 78 + VCL/ics/Cpp/Internet/NsLook1.cpp | 205 + VCL/ics/Cpp/Internet/NsLook1.dfm | Bin 0 -> 1457 bytes VCL/ics/Cpp/Internet/NsLook1.h | 42 + VCL/ics/Cpp/Internet/Poptst1.cpp | 241 + VCL/ics/Cpp/Internet/Recv1.cpp | 234 + VCL/ics/Cpp/Internet/Recv1.dfm | Bin 0 -> 1783 bytes VCL/ics/Cpp/Internet/Recv1.h | 55 + VCL/ics/Cpp/Internet/Sender1.cpp | 470 + VCL/ics/Cpp/Internet/Sender1.dfm | Bin 0 -> 2698 bytes VCL/ics/Cpp/Internet/Sender1.h | 81 + VCL/ics/Cpp/Internet/Socks1.cpp | 239 + VCL/ics/Cpp/Internet/Socks1.dfm | Bin 0 -> 2756 bytes VCL/ics/Cpp/Internet/Socks1.h | 61 + VCL/ics/Cpp/Internet/SrvDemo1.cpp | 152 + VCL/ics/Cpp/Internet/SrvDemo1.dfm | Bin 0 -> 1216 bytes VCL/ics/Cpp/Internet/SrvDemo1.h | 43 + VCL/ics/Cpp/Internet/SrvDemo2.cpp | 130 + VCL/ics/Cpp/Internet/SrvDemo2.dfm | Bin 0 -> 1290 bytes VCL/ics/Cpp/Internet/SrvDemo2.h | 41 + VCL/ics/Cpp/Internet/TcpSrv1.cpp | 225 + VCL/ics/Cpp/Internet/TcpSrv1.dfm | Bin 0 -> 1059 bytes VCL/ics/Cpp/Internet/TcpSrv1.h | 58 + VCL/ics/Cpp/Internet/WebServ1.cpp | 337 + VCL/ics/Cpp/Internet/WebServ1.dfm | 155 + VCL/ics/Cpp/Internet/WebServ1.h | 78 + VCL/ics/Cpp/Internet/cli5.cpp | 130 + VCL/ics/Cpp/Internet/cli5.dfm | Bin 0 -> 1354 bytes VCL/ics/Cpp/Internet/cli5.h | 35 + VCL/ics/Cpp/Internet/finger1.cpp | 159 + VCL/ics/Cpp/Internet/finger1.dfm | Bin 0 -> 1348 bytes VCL/ics/Cpp/Internet/finger1.h | 35 + VCL/ics/Cpp/Internet/formpos.cpp | 154 + VCL/ics/Cpp/Internet/formpos.h | 14 + VCL/ics/Cpp/Internet/ftptst1.cpp | 643 ++ VCL/ics/Cpp/Internet/ftptst1.dfm | Bin 0 -> 7958 bytes VCL/ics/Cpp/Internet/ftptst1.h | 144 + VCL/ics/Cpp/Internet/ftptst2.cpp | 14 + VCL/ics/Cpp/Internet/ftptst2.dfm | Bin 0 -> 462 bytes VCL/ics/Cpp/Internet/ftptst2.h | 21 + VCL/ics/Cpp/Internet/httppg1.cpp | 208 + VCL/ics/Cpp/Internet/httppg1.dfm | Bin 0 -> 1655 bytes VCL/ics/Cpp/Internet/httppg1.h | 42 + VCL/ics/Cpp/Internet/httptst1.cpp | 273 + VCL/ics/Cpp/Internet/httptst1.dfm | Bin 0 -> 2716 bytes VCL/ics/Cpp/Internet/httptst1.h | 57 + VCL/ics/Cpp/Internet/mtsrv1.cpp | 218 + VCL/ics/Cpp/Internet/mtsrv1.dfm | Bin 0 -> 1147 bytes VCL/ics/Cpp/Internet/mtsrv1.h | 34 + VCL/ics/Cpp/Internet/mtsrv2.cpp | 160 + VCL/ics/Cpp/Internet/mtsrv2.h | 23 + VCL/ics/Cpp/Internet/newsrdr1.cpp | 511 + VCL/ics/Cpp/Internet/newsrdr1.dfm | Bin 0 -> 6919 bytes VCL/ics/Cpp/Internet/newsrdr1.h | 109 + VCL/ics/Cpp/Internet/pingtst1.cpp | 110 + VCL/ics/Cpp/Internet/pingtst1.dfm | Bin 0 -> 946 bytes VCL/ics/Cpp/Internet/pingtst1.h | 33 + VCL/ics/Cpp/Internet/poptst1.dfm | Bin 0 -> 3373 bytes VCL/ics/Cpp/Internet/poptst1.h | 76 + VCL/ics/Cpp/Internet/srv5.cpp | 117 + VCL/ics/Cpp/Internet/srv5.dfm | Bin 0 -> 1294 bytes VCL/ics/Cpp/Internet/srv5.h | 29 + VCL/ics/Cpp/Internet/tncli1.cpp | 156 + VCL/ics/Cpp/Internet/tncli1.dfm | Bin 0 -> 2200 bytes VCL/ics/Cpp/Internet/tncli1.h | 56 + VCL/ics/Cpp/Internet/tndemo1.cpp | 159 + VCL/ics/Cpp/Internet/tndemo1.dfm | Bin 0 -> 1360 bytes VCL/ics/Cpp/Internet/tndemo1.h | 43 + VCL/ics/Cpp/Internet/tnsrv1.cpp | 211 + VCL/ics/Cpp/Internet/tnsrv1.dfm | Bin 0 -> 1106 bytes VCL/ics/Cpp/Internet/tnsrv1.h | 51 + VCL/ics/Cpp/Internet/tnsrv2.cpp | 237 + VCL/ics/Cpp/Internet/tnsrv2.dfm | Bin 0 -> 1179 bytes VCL/ics/Cpp/Internet/tnsrv2.h | 46 + VCL/ics/Cpp/Internet/twschat1.cpp | 269 + VCL/ics/Cpp/Internet/twschat1.dfm | Bin 0 -> 2815 bytes VCL/ics/Cpp/Internet/twschat1.h | 51 + VCL/ics/Cpp/Internet/udplstn1.cpp | 188 + VCL/ics/Cpp/Internet/udplstn1.dfm | Bin 0 -> 1594 bytes VCL/ics/Cpp/Internet/udplstn1.h | 44 + VCL/ics/Cpp/Internet/udpsend1.cpp | 117 + VCL/ics/Cpp/Internet/udpsend1.dfm | Bin 0 -> 983 bytes VCL/ics/Cpp/Internet/udpsend1.h | 32 + VCL/ics/Delphi/Internet/Cli7.dfm | Bin 0 -> 1876 bytes VCL/ics/Delphi/Internet/Cli7.pas | 263 + VCL/ics/Delphi/Internet/CliDemo1.dfm | Bin 0 -> 1496 bytes VCL/ics/Delphi/Internet/CliDemo1.pas | 257 + VCL/ics/Delphi/Internet/Client7.dpr | 12 + VCL/ics/Delphi/Internet/ConFtp.dpr | 226 + VCL/ics/Delphi/Internet/ConHttp.dpr | 171 + VCL/ics/Delphi/Internet/ConSmtp.dpr | 291 + VCL/ics/Delphi/Internet/ConSrv1.dpr | 354 + VCL/ics/Delphi/Internet/ConSrv1C.pas | 181 + VCL/ics/Delphi/Internet/ConSrv1S.pas | 145 + VCL/ics/Delphi/Internet/Del40Sam.bpg | 175 + VCL/ics/Delphi/Internet/Del50Sam.bpg | 184 + VCL/ics/Delphi/Internet/Del60Sam.bpg | 184 + VCL/ics/Delphi/Internet/Del70Sam.bpg | 184 + VCL/ics/Delphi/Internet/DllTst1.dpr | 13 + VCL/ics/Delphi/Internet/DllTst_1.dfm | Bin 0 -> 1106 bytes VCL/ics/Delphi/Internet/DllTst_1.pas | 210 + VCL/ics/Delphi/Internet/DnsLook1.dfm | Bin 0 -> 1427 bytes VCL/ics/Delphi/Internet/DnsLook1.pas | 165 + VCL/ics/Delphi/Internet/DynCli.dpr | 12 + VCL/ics/Delphi/Internet/DynCli1.dfm | Bin 0 -> 1167 bytes VCL/ics/Delphi/Internet/DynCli1.pas | 167 + VCL/ics/Delphi/Internet/FTPTST2.dfm | Bin 0 -> 402 bytes VCL/ics/Delphi/Internet/FtpServ1.dfm | Bin 0 -> 3022 bytes VCL/ics/Delphi/Internet/FtpServ1.pas | 842 ++ VCL/ics/Delphi/Internet/FtpThrd1.dfm | Bin 0 -> 619 bytes VCL/ics/Delphi/Internet/FtpThrd1.pas | 168 + VCL/ics/Delphi/Internet/Ftptst2.pas | 25 + VCL/ics/Delphi/Internet/HLembke/NsLook1.dfm | Bin 0 -> 1599 bytes VCL/ics/Delphi/Internet/HLembke/NsLook1.pas | 322 + VCL/ics/Delphi/Internet/HLembke/NsLookup.dpr | 12 + VCL/ics/Delphi/Internet/HLembke/ReadMe.txt | 9 + VCL/ics/Delphi/Internet/HLembke/dnsquery.pas | 1050 +++ VCL/ics/Delphi/Internet/HttpAsp1.dfm | Bin 0 -> 1139 bytes VCL/ics/Delphi/Internet/HttpAsp1.pas | 164 + VCL/ics/Delphi/Internet/HttpAsy1.dfm | Bin 0 -> 2148 bytes VCL/ics/Delphi/Internet/HttpAsy1.pas | 492 + VCL/ics/Delphi/Internet/HttpChk1.dfm | Bin 0 -> 1014 bytes VCL/ics/Delphi/Internet/HttpChk1.pas | 147 + VCL/ics/Delphi/Internet/HttpDmo1.dfm | Bin 0 -> 1253 bytes VCL/ics/Delphi/Internet/HttpDmo1.pas | 139 + VCL/ics/Delphi/Internet/HttpGet1.dfm | Bin 0 -> 1505 bytes VCL/ics/Delphi/Internet/HttpGet1.pas | 208 + VCL/ics/Delphi/Internet/HttpPg1.dfm | Bin 0 -> 2005 bytes VCL/ics/Delphi/Internet/HttpPg1.pas | 246 + VCL/ics/Delphi/Internet/HttpThr1.dfm | Bin 0 -> 2011 bytes VCL/ics/Delphi/Internet/HttpThr1.pas | 269 + VCL/ics/Delphi/Internet/HttpThr2.pas | 161 + VCL/ics/Delphi/Internet/Httpdmo.dpr | 12 + VCL/ics/Delphi/Internet/Ics.ico | Bin 0 -> 766 bytes VCL/ics/Delphi/Internet/IcsDll1.dpr | 286 + VCL/ics/Delphi/Internet/IcsIsap1.dfm | Bin 0 -> 199 bytes VCL/ics/Delphi/Internet/IcsIsap1.pas | 184 + VCL/ics/Delphi/Internet/IcsIsapi.dpr | 19 + VCL/ics/Delphi/Internet/MailRcv.dpr | 14 + VCL/ics/Delphi/Internet/MailRcv1.dfm | Bin 0 -> 4788 bytes VCL/ics/Delphi/Internet/MailRcv1.pas | 667 ++ VCL/ics/Delphi/Internet/MailRcv2.dfm | Bin 0 -> 335 bytes VCL/ics/Delphi/Internet/MailRcv2.pas | 33 + VCL/ics/Delphi/Internet/MailRob.dpr | 12 + VCL/ics/Delphi/Internet/MailRob1.dfm | Bin 0 -> 3134 bytes VCL/ics/Delphi/Internet/MailRob1.pas | 692 ++ VCL/ics/Delphi/Internet/MailSnd.dpr | 12 + VCL/ics/Delphi/Internet/MailSnd1.dfm | Bin 0 -> 5901 bytes VCL/ics/Delphi/Internet/MailSnd1.pas | 588 ++ VCL/ics/Delphi/Internet/MbxSub.dpr | 13 + VCL/ics/Delphi/Internet/MbxSub1.dfm | Bin 0 -> 2214 bytes VCL/ics/Delphi/Internet/MbxSub1.pas | 621 ++ VCL/ics/Delphi/Internet/MimeDemo.dpr | 12 + VCL/ics/Delphi/Internet/MimeDmo1.dfm | Bin 0 -> 1535 bytes VCL/ics/Delphi/Internet/MimeDmo1.pas | 352 + VCL/ics/Delphi/Internet/MimeTst.dpr | 12 + VCL/ics/Delphi/Internet/MimeTst1.dfm | Bin 0 -> 2147 bytes VCL/ics/Delphi/Internet/MimeTst1.pas | 232 + VCL/ics/Delphi/Internet/NewsRdr1.dfm | Bin 0 -> 6955 bytes VCL/ics/Delphi/Internet/NewsRdr1.pas | 732 ++ VCL/ics/Delphi/Internet/NsLook1.dfm | Bin 0 -> 1506 bytes VCL/ics/Delphi/Internet/NsLook1.pas | 273 + VCL/ics/Delphi/Internet/NsLookup.dpr | 12 + VCL/ics/Delphi/Internet/POP3MIM1.dfm | Bin 0 -> 1391 bytes VCL/ics/Delphi/Internet/PingTst1.dfm | Bin 0 -> 930 bytes VCL/ics/Delphi/Internet/PingTst1.pas | 154 + VCL/ics/Delphi/Internet/Pop3Mim1.pas | 283 + VCL/ics/Delphi/Internet/Pop3Mime.dpr | 12 + VCL/ics/Delphi/Internet/PopTst1.dfm | Bin 0 -> 4105 bytes VCL/ics/Delphi/Internet/PopTst1.pas | 558 ++ VCL/ics/Delphi/Internet/Recv.dpr | 12 + VCL/ics/Delphi/Internet/Recv1.dfm | Bin 0 -> 1702 bytes VCL/ics/Delphi/Internet/Recv1.pas | 302 + VCL/ics/Delphi/Internet/Sender.dpr | 12 + VCL/ics/Delphi/Internet/Sender1.dfm | Bin 0 -> 2588 bytes VCL/ics/Delphi/Internet/Sender1.pas | 628 ++ VCL/ics/Delphi/Internet/Socks1.dfm | Bin 0 -> 2675 bytes VCL/ics/Delphi/Internet/Socks1.pas | 344 + VCL/ics/Delphi/Internet/SocksTst.dpr | 12 + VCL/ics/Delphi/Internet/SrvDemo1.dfm | Bin 0 -> 1108 bytes VCL/ics/Delphi/Internet/SrvDemo1.pas | 189 + VCL/ics/Delphi/Internet/SrvDemo2.dfm | Bin 0 -> 1334 bytes VCL/ics/Delphi/Internet/SrvDemo2.pas | 256 + VCL/ics/Delphi/Internet/SrvTcp.dpr | 16 + VCL/ics/Delphi/Internet/SrvTcp1.dfm | Bin 0 -> 613 bytes VCL/ics/Delphi/Internet/SrvTcp1.pas | 194 + VCL/ics/Delphi/Internet/SvcTcp.dpr | 14 + VCL/ics/Delphi/Internet/SvcTcp1.dfm | Bin 0 -> 264 bytes VCL/ics/Delphi/Internet/SvcTcp1.pas | 171 + VCL/ics/Delphi/Internet/TcpCmd.pas | 366 + VCL/ics/Delphi/Internet/TcpSrv.dpr | 12 + VCL/ics/Delphi/Internet/TcpSrv1.dfm | Bin 0 -> 1215 bytes VCL/ics/Delphi/Internet/TcpSrv1.pas | 350 + VCL/ics/Delphi/Internet/ThrdSrv.dpr | 12 + VCL/ics/Delphi/Internet/ThrdSrv1.dfm | Bin 0 -> 1143 bytes VCL/ics/Delphi/Internet/ThrdSrv1.pas | 491 + VCL/ics/Delphi/Internet/TnCli1.dfm | Bin 0 -> 2260 bytes VCL/ics/Delphi/Internet/TnCli1.pas | 268 + VCL/ics/Delphi/Internet/UdpLstn1.dfm | Bin 0 -> 1592 bytes VCL/ics/Delphi/Internet/UdpLstn1.pas | 288 + VCL/ics/Delphi/Internet/UdpSend1.dfm | Bin 0 -> 1338 bytes VCL/ics/Delphi/Internet/UdpSend1.pas | 150 + VCL/ics/Delphi/Internet/WebServ.dpr | 12 + VCL/ics/Delphi/Internet/WebServ1.dfm | Bin 0 -> 2290 bytes VCL/ics/Delphi/Internet/WebServ1.pas | 755 ++ VCL/ics/Delphi/Internet/cli5.dfm | Bin 0 -> 1316 bytes VCL/ics/Delphi/Internet/cli5.pas | 193 + VCL/ics/Delphi/Internet/clidemo.dpr | 12 + VCL/ics/Delphi/Internet/client5.dpr | 12 + VCL/ics/Delphi/Internet/clients.DBF | Bin 0 -> 434 bytes VCL/ics/Delphi/Internet/clients.MDX | Bin 0 -> 6144 bytes VCL/ics/Delphi/Internet/concli1.dpr | 78 + VCL/ics/Delphi/Internet/concli2.dpr | 164 + VCL/ics/Delphi/Internet/dnslook.dpr | 12 + VCL/ics/Delphi/Internet/finger.dpr | 12 + VCL/ics/Delphi/Internet/finger1.dfm | Bin 0 -> 1001 bytes VCL/ics/Delphi/Internet/finger1.pas | 216 + VCL/ics/Delphi/Internet/ftpServ.dpr | 12 + VCL/ics/Delphi/Internet/ftpcli.ico | Bin 0 -> 766 bytes VCL/ics/Delphi/Internet/ftpthrd.dpr | 13 + VCL/ics/Delphi/Internet/ftptst.dpr | 14 + VCL/ics/Delphi/Internet/ftptst1.dfm | Bin 0 -> 16936 bytes VCL/ics/Delphi/Internet/ftptst1.pas | 1203 +++ VCL/ics/Delphi/Internet/httpChk.dpr | 12 + VCL/ics/Delphi/Internet/httpasp.dpr | 12 + VCL/ics/Delphi/Internet/httpasy.dpr | 12 + VCL/ics/Delphi/Internet/httpget.dpr | 12 + VCL/ics/Delphi/Internet/httppg.dpr | 12 + VCL/ics/Delphi/Internet/httpthrd.dpr | 14 + VCL/ics/Delphi/Internet/httptst.dpr | 12 + VCL/ics/Delphi/Internet/httptst1.dfm | Bin 0 -> 2991 bytes VCL/ics/Delphi/Internet/httptst1.pas | 541 ++ VCL/ics/Delphi/Internet/md5test.dpr | 12 + VCL/ics/Delphi/Internet/md5test1.dfm | Bin 0 -> 505 bytes VCL/ics/Delphi/Internet/md5test1.pas | 81 + VCL/ics/Delphi/Internet/mtsrv.dpr | 14 + VCL/ics/Delphi/Internet/mtsrv.ico | Bin 0 -> 766 bytes VCL/ics/Delphi/Internet/mtsrv.res | Bin 0 -> 876 bytes VCL/ics/Delphi/Internet/mtsrv1.dfm | Bin 0 -> 1174 bytes VCL/ics/Delphi/Internet/mtsrv1.pas | 273 + VCL/ics/Delphi/Internet/mtsrv2.pas | 191 + VCL/ics/Delphi/Internet/newsrdr.dpr | 12 + VCL/ics/Delphi/Internet/pingtst.dpr | 13 + VCL/ics/Delphi/Internet/poptst.dpr | 14 + VCL/ics/Delphi/Internet/poptst2.dfm | Bin 0 -> 337 bytes VCL/ics/Delphi/Internet/poptst2.pas | 33 + VCL/ics/Delphi/Internet/server5.dpr | 12 + VCL/ics/Delphi/Internet/srv5.dfm | Bin 0 -> 1294 bytes VCL/ics/Delphi/Internet/srv5.pas | 142 + VCL/ics/Delphi/Internet/srvdemo.dpr | 13 + VCL/ics/Delphi/Internet/tnclient.dpr | 12 + VCL/ics/Delphi/Internet/tnclient.ico | Bin 0 -> 766 bytes VCL/ics/Delphi/Internet/tndemo.dpr | 12 + VCL/ics/Delphi/Internet/tndemo1.dfm | Bin 0 -> 1582 bytes VCL/ics/Delphi/Internet/tndemo1.pas | 207 + VCL/ics/Delphi/Internet/tnsrv.dpr | 13 + VCL/ics/Delphi/Internet/tnsrv.ico | Bin 0 -> 766 bytes VCL/ics/Delphi/Internet/tnsrv1.dfm | Bin 0 -> 1407 bytes VCL/ics/Delphi/Internet/tnsrv1.pas | 325 + VCL/ics/Delphi/Internet/tnsrv2.dfm | Bin 0 -> 1399 bytes VCL/ics/Delphi/Internet/tnsrv2.pas | 544 ++ VCL/ics/Delphi/Internet/twschat.dpr | 12 + VCL/ics/Delphi/Internet/twschat1.dfm | Bin 0 -> 2603 bytes VCL/ics/Delphi/Internet/twschat1.pas | 332 + VCL/ics/Delphi/Internet/udplstn.dpr | 12 + VCL/ics/Delphi/Internet/udpsend.dpr | 12 + VCL/ics/Delphi/Vc/DnsQuery.dcr | Bin 0 -> 411 bytes VCL/ics/Delphi/Vc/FtpSrv.dcr | Bin 0 -> 412 bytes VCL/ics/Delphi/Vc/Pop3Prot.dcr | Bin 0 -> 824 bytes VCL/ics/Delphi/Vc/SmtpProt.dcr | Bin 0 -> 824 bytes VCL/ics/Delphi/Vc/TNSCRIPT.DCR | Bin 0 -> 411 bytes VCL/ics/Delphi/Vc/WINSOCK.PAS | 634 ++ VCL/ics/Delphi/Vc/emulvt.dcr | Bin 0 -> 409 bytes VCL/ics/Delphi/Vc/fingcli.dcr | Bin 0 -> 412 bytes VCL/ics/Delphi/Vc/ftpcli.dcr | Bin 0 -> 1208 bytes VCL/ics/Delphi/Vc/httpprot.dcr | Bin 0 -> 410 bytes VCL/ics/Delphi/Vc/httpsrv.dcr | Bin 0 -> 413 bytes VCL/ics/Delphi/Vc/mbxfile.dcr | Bin 0 -> 413 bytes VCL/ics/Delphi/Vc/mimedec.dcr | Bin 0 -> 413 bytes VCL/ics/Delphi/Vc/nntpcli.dcr | Bin 0 -> 410 bytes VCL/ics/Delphi/Vc/tncnx.dcr | Bin 0 -> 408 bytes VCL/ics/Delphi/Vc/tnemulvt.dcr | Bin 0 -> 411 bytes VCL/ics/Delphi/Vc/wait.dcr | Bin 0 -> 1198 bytes VCL/ics/Delphi/Vc/wsocket.dcr | Bin 0 -> 410 bytes VCL/ics/Delphi/Vc/wsockets.dcr | Bin 0 -> 1209 bytes VCL/ics/Delphi/Vc32/DnsQuery.dcr | Bin 0 -> 472 bytes VCL/ics/Delphi/Vc32/DnsQuery.dcu | Bin 0 -> 22672 bytes VCL/ics/Delphi/Vc32/DnsQuery.pas | 1046 +++ VCL/ics/Delphi/Vc32/FingCli.dcu | Bin 0 -> 5930 bytes VCL/ics/Delphi/Vc32/FingCli.pas | 230 + VCL/ics/Delphi/Vc32/FtpCli.dcu | Bin 0 -> 78444 bytes VCL/ics/Delphi/Vc32/FtpCli.pas | 3806 ++++++++ VCL/ics/Delphi/Vc32/FtpSrv.dcu | Bin 0 -> 84340 bytes VCL/ics/Delphi/Vc32/FtpSrv.pas | 3360 +++++++ VCL/ics/Delphi/Vc32/FtpSrvC.dcu | Bin 0 -> 16720 bytes VCL/ics/Delphi/Vc32/FtpSrvC.pas | 579 ++ VCL/ics/Delphi/Vc32/FtpSrvT.dcu | Bin 0 -> 2701 bytes VCL/ics/Delphi/Vc32/FtpSrvT.pas | 178 + VCL/ics/Delphi/Vc32/HttpProt.dcu | Bin 0 -> 42230 bytes VCL/ics/Delphi/Vc32/HttpProt.pas | 2331 +++++ VCL/ics/Delphi/Vc32/HttpSrv.dcr | Bin 0 -> 476 bytes VCL/ics/Delphi/Vc32/HttpSrv.dcu | Bin 0 -> 34405 bytes VCL/ics/Delphi/Vc32/HttpSrv.pas | 1347 +++ VCL/ics/Delphi/Vc32/IcsBcb30.bpk | 186 + VCL/ics/Delphi/Vc32/IcsBcb30.cpp | 50 + VCL/ics/Delphi/Vc32/IcsBcb30.res | Bin 0 -> 1764 bytes VCL/ics/Delphi/Vc32/IcsBcb50.bpk | 131 + VCL/ics/Delphi/Vc32/IcsBcb50.cpp | 53 + VCL/ics/Delphi/Vc32/IcsBcb50.res | Bin 0 -> 1784 bytes VCL/ics/Delphi/Vc32/IcsBcb60.bpk | 220 + VCL/ics/Delphi/Vc32/IcsBcb60.cpp | 19 + VCL/ics/Delphi/Vc32/IcsBcb60.res | Bin 0 -> 1752 bytes VCL/ics/Delphi/Vc32/IcsDel30.dpk | 79 + VCL/ics/Delphi/Vc32/IcsDel40.dpk | 79 + VCL/ics/Delphi/Vc32/IcsDel40.res | Bin 0 -> 1844 bytes VCL/ics/Delphi/Vc32/IcsDel50.dpk | 79 + VCL/ics/Delphi/Vc32/IcsDel50.res | Bin 0 -> 1900 bytes VCL/ics/Delphi/Vc32/IcsDel60.dcu | Bin 0 -> 4288 bytes VCL/ics/Delphi/Vc32/IcsDel60.dof | 108 + VCL/ics/Delphi/Vc32/IcsDel60.dpk | 81 + VCL/ics/Delphi/Vc32/IcsDel60.res | Bin 0 -> 1856 bytes VCL/ics/Delphi/Vc32/IcsDel70.dof | 152 + VCL/ics/Delphi/Vc32/IcsDel70.dpk | 81 + VCL/ics/Delphi/Vc32/IcsDel70.res | Bin 0 -> 1860 bytes VCL/ics/Delphi/Vc32/Icsbcb40.bpk | 221 + VCL/ics/Delphi/Vc32/Icsbcb40.cpp | 53 + VCL/ics/Delphi/Vc32/Icsbcb40.res | Bin 0 -> 1764 bytes VCL/ics/Delphi/Vc32/Icsdel30.res | Bin 0 -> 32 bytes VCL/ics/Delphi/Vc32/MD5.dcu | Bin 0 -> 8371 bytes VCL/ics/Delphi/Vc32/MD5.pas | 362 + VCL/ics/Delphi/Vc32/MbxFile.dcr | Bin 0 -> 476 bytes VCL/ics/Delphi/Vc32/MbxFile.dcu | Bin 0 -> 8578 bytes VCL/ics/Delphi/Vc32/MbxFile.pas | 355 + VCL/ics/Delphi/Vc32/NntpCli.dcu | Bin 0 -> 32946 bytes VCL/ics/Delphi/Vc32/NntpCli.pas | 1414 +++ VCL/ics/Delphi/Vc32/POP3CLI.DCR | Bin 0 -> 1740 bytes VCL/ics/Delphi/Vc32/Pop3Prot.dcr | Bin 0 -> 920 bytes VCL/ics/Delphi/Vc32/Pop3Prot.dcu | Bin 0 -> 40200 bytes VCL/ics/Delphi/Vc32/Pop3Prot.pas | 1776 ++++ VCL/ics/Delphi/Vc32/Pop3cli.pas | 904 ++ VCL/ics/Delphi/Vc32/SmtpProt.dcr | Bin 0 -> 920 bytes VCL/ics/Delphi/Vc32/SmtpProt.dcu | Bin 0 -> 56777 bytes VCL/ics/Delphi/Vc32/SmtpProt.pas | 2427 +++++ VCL/ics/Delphi/Vc32/TNCNX.HLP | Bin 0 -> 33193 bytes VCL/ics/Delphi/Vc32/TnCnx.dcu | Bin 0 -> 13085 bytes VCL/ics/Delphi/Vc32/TnCnx.pas | 714 ++ VCL/ics/Delphi/Vc32/TnEmulVT.dcu | Bin 0 -> 24842 bytes VCL/ics/Delphi/Vc32/TnEmulVT.pas | 825 ++ VCL/ics/Delphi/Vc32/TnOptFrm.dcu | Bin 0 -> 17997 bytes VCL/ics/Delphi/Vc32/TnOptFrm.dfm | Bin 0 -> 3207 bytes VCL/ics/Delphi/Vc32/TnOptFrm.pas | 564 ++ VCL/ics/Delphi/Vc32/UUEncode.pas | 142 + VCL/ics/Delphi/Vc32/WSOCKET.GID | Bin 0 -> 8628 bytes VCL/ics/Delphi/Vc32/WSOCKET.HLP | Bin 0 -> 91775 bytes VCL/ics/Delphi/Vc32/WSocket.dcu | Bin 0 -> 87665 bytes VCL/ics/Delphi/Vc32/WSocket.pas | 5674 +++++++++++ VCL/ics/Delphi/Vc32/WSocketE.pas | 172 + VCL/ics/Delphi/Vc32/WSocketS.dcr | Bin 0 -> 484 bytes VCL/ics/Delphi/Vc32/WSocketS.dcu | Bin 0 -> 14519 bytes VCL/ics/Delphi/Vc32/WSocketS.pas | 456 + VCL/ics/Delphi/Vc32/emulvt.dcr | Bin 0 -> 468 bytes VCL/ics/Delphi/Vc32/emulvt.dcu | Bin 0 -> 101193 bytes VCL/ics/Delphi/Vc32/emulvt.pas | 4006 ++++++++ VCL/ics/Delphi/Vc32/fingcli.dcr | Bin 0 -> 476 bytes VCL/ics/Delphi/Vc32/formpos.dcu | Bin 0 -> 2961 bytes VCL/ics/Delphi/Vc32/formpos.pas | 167 + VCL/ics/Delphi/Vc32/ftpcli.dcr | Bin 0 -> 1252 bytes VCL/ics/Delphi/Vc32/ftpsrv.dcr | Bin 0 -> 476 bytes VCL/ics/Delphi/Vc32/httpprot.dcr | Bin 0 -> 472 bytes VCL/ics/Delphi/Vc32/icmp.dcu | Bin 0 -> 10937 bytes VCL/ics/Delphi/Vc32/icmp.pas | 449 + VCL/ics/Delphi/Vc32/mimedec.dcr | Bin 0 -> 476 bytes VCL/ics/Delphi/Vc32/mimedec.dcu | Bin 0 -> 27766 bytes VCL/ics/Delphi/Vc32/mimedec.pas | 1576 ++++ VCL/ics/Delphi/Vc32/nntpcli.dcr | Bin 0 -> 472 bytes VCL/ics/Delphi/Vc32/ping.dcr | Bin 0 -> 464 bytes VCL/ics/Delphi/Vc32/ping.dcu | Bin 0 -> 11777 bytes VCL/ics/Delphi/Vc32/ping.pas | 603 ++ VCL/ics/Delphi/Vc32/tncnx.dcr | Bin 0 -> 468 bytes VCL/ics/Delphi/Vc32/tnemulvt.dcr | Bin 0 -> 472 bytes VCL/ics/Delphi/Vc32/tnscript.dcr | Bin 0 -> 472 bytes VCL/ics/Delphi/Vc32/tnscript.dcu | Bin 0 -> 12441 bytes VCL/ics/Delphi/Vc32/tnscript.pas | 570 ++ VCL/ics/Delphi/Vc32/wait.dcr | Bin 0 -> 1300 bytes VCL/ics/Delphi/Vc32/wait.dcu | Bin 0 -> 11346 bytes VCL/ics/Delphi/Vc32/wait.pas | 336 + VCL/ics/Delphi/Vc32/wsockbuf.dcu | Bin 0 -> 2740 bytes VCL/ics/Delphi/Vc32/wsockbuf.pas | 225 + VCL/ics/Delphi/Vc32/wsocket.dcr | Bin 0 -> 1312 bytes VCL/ics/Delphi/Vc32/wsocket.ico | Bin 0 -> 766 bytes VCL/ics/Delphi1/IcsDel1.bat | 129 + VCL/ics/Delphi1/dcc1.bat | 14 + VCL/ics/Delphi2/Dcc2.bat | 19 + VCL/ics/Delphi2/Icsdel2.bat | 142 + VCL/ics/Delphi3/Dcc3.bat | 19 + VCL/ics/Delphi3/Icsdel3.bat | 142 + VCL/ics/Ics.diz | 26 + VCL/ics/ics7spec.zip | Bin 0 -> 78572 bytes VCL/ics/ics_logo.gif | Bin 0 -> 9455 bytes VCL/ics/powered_by_ics.gif | Bin 0 -> 5779 bytes VCL/ics/readme.txt | 465 + VCL/ics/zipics.bat | 8 + VCL/ics/zipics7.lst | 100 + VCL/ics/zipicsb.lst | 437 + VCL/ics/zipicsd.lst | 299 + VCL/ini_mw/Ini.dcu | Bin 0 -> 7229 bytes VCL/ini_mw/Ini.pas | 251 + VCL/ini_mw/Ini.~pa | 251 + VCL/midicom3/CIRCBUF.PAS | 192 + VCL/midicom3/DELPHMCB.PAS | 140 + VCL/midicom3/MIDICOMP.DPK | 38 + VCL/midicom3/MIDICOMP.DPL | Bin 0 -> 31232 bytes VCL/midicom3/MIDICONS.PAS | 42 + VCL/midicom3/MIDIDEFS.PAS | 47 + VCL/midicom3/MIDIIN.DCR | Bin 0 -> 476 bytes VCL/midicom3/MIDIIN.PAS | 689 ++ VCL/midicom3/MIDIMON.DPR | 18 + VCL/midicom3/MIDIMON.RES | Bin 0 -> 876 bytes VCL/midicom3/MIDIMONP.DFM | Bin 0 -> 1619 bytes VCL/midicom3/MIDIMONP.PAS | 184 + VCL/midicom3/MIDIOUT.DCR | Bin 0 -> 476 bytes VCL/midicom3/MIDIOUT.PAS | 586 ++ VCL/midicom3/MIDITYPE.PAS | 79 + VCL/midicom3/MONPROCS.PAS | 148 + VCL/midicom3/MULTIMNP.DFM | Bin 0 -> 983 bytes VCL/midicom3/MULTIMNP.PAS | 142 + VCL/midicom3/MULTIMON.DPR | 25 + VCL/midicom3/MULTIMON.RES | Bin 0 -> 876 bytes VCL/midicom3/README.TXT | 198 + VCL/midicomp/circbuf.pas | 182 + VCL/midicomp/delphmcb.dfm | Bin 0 -> 182 bytes VCL/midicomp/delphmcb.pas | 131 + VCL/midicomp/delphmid.dpr | 9 + VCL/midicomp/delphmid.opt | 34 + VCL/midicomp/delphmid.res | Bin 0 -> 794 bytes VCL/midicomp/midiin.pas | 744 ++ VCL/midicomp/midiin.res | Bin 0 -> 413 bytes VCL/midicomp/midimon.dpr | 16 + VCL/midicomp/midimon.opt | 34 + VCL/midicomp/midimon.res | Bin 0 -> 794 bytes VCL/midicomp/midimonp.dfm | Bin 0 -> 1478 bytes VCL/midicomp/midimonp.pas | 180 + VCL/midicomp/midiout.pas | 486 + VCL/midicomp/monprocs.pas | 144 + VCL/midicomp/multimnp.dfm | Bin 0 -> 893 bytes VCL/midicomp/multimnp.pas | 144 + VCL/midicomp/multimon.dpr | 15 + VCL/midicomp/multimon.opt | 34 + VCL/midicomp/multimon.res | Bin 0 -> 794 bytes VCL/midicomp/readme.txt | 42 + VCL/mynewpack.dcp | Bin 0 -> 300865 bytes VCL/mynewpack.dcu | Bin 0 -> 3055 bytes VCL/mynewpack.dpk | 61 + VCL/mynewpack.dpl | Bin 0 -> 349696 bytes VCL/mynewpack.res | Bin 0 -> 32 bytes VCL/mynewpack.~dp | 60 + VCL/nfigrid/GridWizard.dcu | Bin 0 -> 19725 bytes VCL/nfigrid/GridWizard.dfm | Bin 0 -> 53252 bytes VCL/nfigrid/NFIGrid.dcu | Bin 0 -> 164301 bytes VCL/nfigrid/Sample.zip | Bin 0 -> 6857 bytes VCL/nfigrid/Sample/NFITest.dof | 45 + VCL/nfigrid/Sample/NFITest.dpr | 13 + VCL/nfigrid/Sample/NFITest.res | Bin 0 -> 876 bytes VCL/nfigrid/Sample/NFIunit1.dcu | Bin 0 -> 4856 bytes VCL/nfigrid/Sample/NFIunit1.dfm | Bin 0 -> 2121 bytes VCL/nfigrid/Sample/NFIunit1.pas | 113 + VCL/nfigrid/Sample/NFIunit1.~df | Bin 0 -> 2080 bytes VCL/nfigrid/Sample/NFIunit1.~pa | 105 + VCL/nfigrid/nfigrid.upl | 31 + VCL/nkprn/NkPrinters.dcu | Bin 0 -> 46005 bytes VCL/nkprn/NkPrinters.pas | 2113 +++++ VCL/nkprn/NkPrn.GID | Bin 0 -> 16016 bytes VCL/nkprn/demo/Demo.dpr | 17 + VCL/nkprn/demo/Demo.res | Bin 0 -> 876 bytes VCL/nkprn/demo/DemoForm1.dcu | Bin 0 -> 18605 bytes VCL/nkprn/demo/DemoForm1.dfm | Bin 0 -> 3809 bytes VCL/nkprn/demo/DemoForm1.pas | 547 ++ VCL/nkprn/demo/DemoForm2.dcu | Bin 0 -> 2736 bytes VCL/nkprn/demo/DemoForm2.dfm | Bin 0 -> 779 bytes VCL/nkprn/demo/DemoForm2.pas | 40 + VCL/nkprn/demo/DemoForm3.dcu | Bin 0 -> 3565 bytes VCL/nkprn/demo/DemoForm3.dfm | Bin 0 -> 1188 bytes VCL/nkprn/demo/DemoForm3.pas | 65 + VCL/nkprn/demo/Shun06.bmp | Bin 0 -> 29078 bytes VCL/nkprn/mypack.dcp | Bin 0 -> 56716 bytes VCL/nkprn/mypack.dcu | Bin 0 -> 1813 bytes VCL/nkprn/mypack.dpk | 37 + VCL/nkprn/mypack.dpl | Bin 0 -> 82432 bytes VCL/nkprn/mypack.res | Bin 0 -> 32 bytes VCL/nkprn/mypack.~dp | 38 + VCL/nkprn/readme.txt | 234 + VCL/rbutton.pas | 304 + VCL/sock/Base64/Test.dfm | Bin 0 -> 773 bytes VCL/sock/Base64/Test.pas | 42 + VCL/sock/Base64/Test64.dpr | 13 + VCL/sock/Base64/Test64.res | Bin 0 -> 876 bytes VCL/sock/PROXY/IP.DFM | Bin 0 -> 322 bytes VCL/sock/PROXY/IP.PAS | 25 + VCL/sock/PROXY/PROXY.RES | Bin 0 -> 876 bytes VCL/sock/PROXY/main.dfm | Bin 0 -> 2194 bytes VCL/sock/PROXY/main.pas | 160 + VCL/sock/PROXY/proxy.dpr | 16 + VCL/sock/README.TXT | 25 + VCL/sock/SOCK.DCR | Bin 0 -> 464 bytes VCL/sock/SOCK.HTM | 868 ++ VCL/sock/SOCK.JPG | Bin 0 -> 2304 bytes VCL/sock/SOCK.RES | Bin 0 -> 1804 bytes VCL/sock/SOCKTEST/Main.dcu | Bin 0 -> 6042 bytes VCL/sock/SOCKTEST/Main.dfm | Bin 0 -> 2685 bytes VCL/sock/SOCKTEST/Main.pas | 120 + VCL/sock/SOCKTEST/SOCKTEST.RES | Bin 0 -> 876 bytes VCL/sock/SOCKTEST/SockTest.dpr | 15 + VCL/sock/SRVTEST/SRVTEST.RES | Bin 0 -> 876 bytes VCL/sock/SRVTEST/Srvtest.dpr | 14 + VCL/sock/SRVTEST/srvr.dfm | Bin 0 -> 1718 bytes VCL/sock/SRVTEST/srvr.pas | 81 + VCL/sock/Sock.dcu | Bin 0 -> 26667 bytes VCL/sock/Sock.pas | 1319 +++ VCL/sock/UDPTest/UDPTester.dpr | 13 + VCL/sock/UDPTest/UDPTester.res | Bin 0 -> 876 bytes VCL/sock/UDPTest/Unit1.dfm | Bin 0 -> 904 bytes VCL/sock/UDPTest/Unit1.pas | 57 + VCL/supergrid/RZTBAR32.RES | Bin 0 -> 5240 bytes VCL/supergrid/RzCommon.dcu | Bin 0 -> 2609 bytes VCL/supergrid/RzTrkBar.dcu | Bin 0 -> 17661 bytes VCL/supergrid/SUPER.GID | Bin 0 -> 8628 bytes VCL/supergrid/SUPER.KWF | Bin 0 -> 8192 bytes VCL/supergrid/SUPER14.TXT | 180 + VCL/supergrid/SUPERBUG.TXT | 158 + VCL/supergrid/Super32.dcr | Bin 0 -> 476 bytes VCL/supergrid/Super32.dcu | Bin 0 -> 704 bytes VCL/supergrid/Super32.res | Bin 0 -> 1360 bytes VCL/supergrid/SuperCol.dcu | Bin 0 -> 19191 bytes VCL/supergrid/SuperDlg.dcu | Bin 0 -> 36956 bytes VCL/supergrid/SuperDlg.dfm | Bin 0 -> 18856 bytes VCL/supergrid/SuperGrd.dcu | Bin 0 -> 22244 bytes VCL/supergrid/SuperGrid.dcp | Bin 0 -> 89018 bytes VCL/supergrid/SuperGrid.dcu | Bin 0 -> 2396 bytes VCL/supergrid/SuperGrid.dpl | Bin 0 -> 128000 bytes VCL/supergrid/SuperGrid.res | Bin 0 -> 32 bytes VCL/supergrid/colorpik.dcu | Bin 0 -> 8974 bytes VCL/supertmr.zip | Bin 0 -> 7493 bytes VCL/telnet/CLI5.DFM | Bin 0 -> 1170 bytes VCL/telnet/CLI5.PAS | 191 + VCL/telnet/CLIDEMO.DPR | 12 + VCL/telnet/CLIDEMO1.DFM | Bin 0 -> 1424 bytes VCL/telnet/CLIDEMO1.PAS | 223 + VCL/telnet/CLIENT5.DPR | 12 + VCL/telnet/CLIENTS.DBF | Bin 0 -> 434 bytes VCL/telnet/CLIENTS.MDX | Bin 0 -> 6144 bytes VCL/telnet/CONCLI1.DPR | 66 + VCL/telnet/CONCLI2.DPR | 169 + VCL/telnet/DNSLOOK.DPR | 12 + VCL/telnet/DNSLOOK1.DFM | Bin 0 -> 790 bytes VCL/telnet/DNSLOOK1.PAS | 121 + VCL/telnet/EMULVT.DCR | Bin 0 -> 468 bytes VCL/telnet/EMULVT.PAS | 3168 +++++++ VCL/telnet/EmulVT.dcu | Bin 0 -> 45544 bytes VCL/telnet/FINGCLI.DCR | Bin 0 -> 476 bytes VCL/telnet/FINGCLI.PAS | 202 + VCL/telnet/FINGER.DPR | 12 + VCL/telnet/FINGER1.DFM | Bin 0 -> 1009 bytes VCL/telnet/FINGER1.PAS | 183 + VCL/telnet/FORMPOS.PAS | 159 + VCL/telnet/FPiette2.dcp | Bin 0 -> 21914 bytes VCL/telnet/FPiette2.dcu | Bin 0 -> 1660 bytes VCL/telnet/FPiette2.dpl | Bin 0 -> 38912 bytes VCL/telnet/FTPCLI.DCR | Bin 0 -> 1324 bytes VCL/telnet/FTPCLI.PAS | 1045 +++ VCL/telnet/FTPTST.DPR | 14 + VCL/telnet/FTPTST1.DFM | Bin 0 -> 4277 bytes VCL/telnet/FTPTST1.PAS | 386 + VCL/telnet/FTPTST2.DFM | Bin 0 -> 402 bytes VCL/telnet/FTPTST2.PAS | 25 + VCL/telnet/FormPos.dcu | Bin 0 -> 2102 bytes VCL/telnet/HTTPPG.DPR | 13 + VCL/telnet/HTTPPG1.DFM | Bin 0 -> 915 bytes VCL/telnet/HTTPPG1.PAS | 142 + VCL/telnet/HTTPPROT.DCR | Bin 0 -> 472 bytes VCL/telnet/HTTPPROT.PAS | 893 ++ VCL/telnet/HTTPTST.DPR | 12 + VCL/telnet/HTTPTST1.DFM | Bin 0 -> 1656 bytes VCL/telnet/HTTPTST1.PAS | 240 + VCL/telnet/ICMP.PAS | 435 + VCL/telnet/MD5.PAS | 351 + VCL/telnet/MTSRV.DPR | 14 + VCL/telnet/MTSRV.RES | Bin 0 -> 876 bytes VCL/telnet/MTSRV.dof | 80 + VCL/telnet/MTSRV.~DP | 14 + VCL/telnet/PING.DCR | Bin 0 -> 464 bytes VCL/telnet/PING.PAS | 501 + VCL/telnet/PINGTST.DPR | 13 + VCL/telnet/PINGTST1.DFM | Bin 0 -> 899 bytes VCL/telnet/PINGTST1.PAS | 143 + VCL/telnet/POP3CLI.DCR | Bin 0 -> 1740 bytes VCL/telnet/POP3CLI.PAS | 866 ++ VCL/telnet/POPTST.DPR | 14 + VCL/telnet/POPTST1.DFM | Bin 0 -> 3798 bytes VCL/telnet/POPTST1.PAS | 544 ++ VCL/telnet/POPTST2.DFM | Bin 0 -> 337 bytes VCL/telnet/POPTST2.PAS | 25 + VCL/telnet/SERVER5.DPR | 12 + VCL/telnet/SMTPCLI.DCR | Bin 0 -> 476 bytes VCL/telnet/SMTPCLI.PAS | 549 ++ VCL/telnet/SMTPTST.DPR | 12 + VCL/telnet/SMTPTST1.DFM | Bin 0 -> 1806 bytes VCL/telnet/SMTPTST1.PAS | 165 + VCL/telnet/SRV5.DFM | Bin 0 -> 635 bytes VCL/telnet/SRV5.PAS | 141 + VCL/telnet/SRVDEMO.DPR | 13 + VCL/telnet/SRVDEMO1.DFM | Bin 0 -> 889 bytes VCL/telnet/SRVDEMO1.PAS | 182 + VCL/telnet/SRVDEMO2.DFM | Bin 0 -> 1051 bytes VCL/telnet/SRVDEMO2.PAS | 268 + VCL/telnet/TNCLI1.DFM | Bin 0 -> 2006 bytes VCL/telnet/TNCLI1.PAS | 220 + VCL/telnet/TNCLIENT.DPR | 12 + VCL/telnet/TNCNX.DCR | Bin 0 -> 468 bytes VCL/telnet/TNCNX.GID | Bin 0 -> 8628 bytes VCL/telnet/TNDEMO.DPR | 12 + VCL/telnet/TNDEMO1.DFM | Bin 0 -> 1315 bytes VCL/telnet/TNDEMO1.PAS | 185 + VCL/telnet/TNEMULVT.DCR | Bin 0 -> 472 bytes VCL/telnet/TNEMULVT.PAS | 703 ++ VCL/telnet/TNOPTFRM.DFM | Bin 0 -> 2698 bytes VCL/telnet/TNOPTFRM.PAS | 461 + VCL/telnet/TNSRV.DPR | 13 + VCL/telnet/TNSRV1.DFM | Bin 0 -> 1096 bytes VCL/telnet/TNSRV1.PAS | 309 + VCL/telnet/TNSRV2.DFM | Bin 0 -> 992 bytes VCL/telnet/TNSRV2.PAS | 503 + VCL/telnet/TWSCHAT.DPR | 12 + VCL/telnet/TWSCHAT1.DFM | Bin 0 -> 2003 bytes VCL/telnet/TWSCHAT1.PAS | 327 + VCL/telnet/TnCnx.pas | 680 ++ VCL/telnet/TnCnx.~pa | 685 ++ VCL/telnet/TnOptFrm.dcu | Bin 0 -> 9334 bytes VCL/telnet/Tncnx.dcu | Bin 0 -> 12382 bytes VCL/telnet/UDPLSTN.DPR | 12 + VCL/telnet/UDPLSTN1.DFM | Bin 0 -> 1231 bytes VCL/telnet/UDPLSTN1.PAS | 281 + VCL/telnet/UDPSEND.DPR | 12 + VCL/telnet/UDPSEND1.DFM | Bin 0 -> 624 bytes VCL/telnet/UDPSEND1.PAS | 124 + VCL/telnet/WAIT.DCR | Bin 0 -> 1300 bytes VCL/telnet/WAIT.PAS | 335 + VCL/telnet/WSOCKBUF.PAS | 224 + VCL/telnet/WSOCKET.DCR | Bin 0 -> 1312 bytes VCL/telnet/WSOCKET.GID | Bin 0 -> 8628 bytes VCL/telnet/WSOCKET.PAS | 4799 ++++++++++ VCL/telnet/WSockBuf.dcu | Bin 0 -> 2448 bytes VCL/telnet/Wait.dcu | Bin 0 -> 8140 bytes VCL/telnet/Wsocket.dcu | Bin 0 -> 76572 bytes VCL/telnet/mtsrv1.dfm | Bin 0 -> 1014 bytes VCL/telnet/mtsrv1.pas | 291 + VCL/telnet/mtsrv1.~df | Bin 0 -> 882 bytes VCL/telnet/mtsrv1.~pa | 259 + VCL/telnet/mtsrv2.pas | 192 + VCL/telnet/mtsrv2.~pa | 192 + VCL/telnet/tncnx2.pas | 680 ++ VCL/telnet/winsock.dcp | Bin 0 -> 45491 bytes VCL/telnet/winsock.dcu | Bin 0 -> 1716 bytes VCL/telnet/winsock.dpk | 37 + VCL/telnet/winsock.dpl | Bin 0 -> 55296 bytes VCL/telnet/winsock.res | Bin 0 -> 32 bytes VCL/thdtim.zip | Bin 0 -> 933 bytes VCL/timer32.zip | Bin 0 -> 1884 bytes VCL/timer32/HIRESTIM.DCR | Bin 0 -> 476 bytes VCL/timer32/HIRESTIM.PAS | 154 + VCL/timer32/Hirestim.dcu | Bin 0 -> 4150 bytes VCL/tsrich/TRECODE.DCR | Bin 0 -> 476 bytes VCL/tsrich/TRECODE.PAS | 203 + VCL/tsrich/TRECODE.RES | Bin 0 -> 1320 bytes VCL/tsrich/TRECODE.TXT | 97 + VCL/tsrich/Trecode.dcu | Bin 0 -> 5260 bytes VCL/tvicres/DELPHI3/MAIN.DFM | Bin 0 -> 3406 bytes VCL/tvicres/DELPHI3/MAIN.PAS | 216 + VCL/tvicres/DELPHI3/Main.dcu | Bin 0 -> 8767 bytes VCL/tvicres/DELPHI3/TEST_RES.DPR | 14 + VCL/tvicres/DELPHI3/VIC_RES.DCU | Bin 0 -> 21537 bytes VCL/tvicres/DELPHI4/MAIN.DFM | Bin 0 -> 3406 bytes VCL/tvicres/DELPHI4/MAIN.PAS | 216 + VCL/tvicres/DELPHI4/TEST_RES.DPR | 14 + VCL/tvicres/DELPHI4/VIC_RES.DCU | Bin 0 -> 23189 bytes VCL/tvicres/FILE_ID.DIZ | 12 + VCL/tvicres/LICENSE.TXT | 70 + VCL/tvicres/ORDER.TXT | 25 + VCL/tvicres/README.TXT | 204 + VCL/tvicres/VENDOR.TXT | 62 + VCL/vsscm32/MISC.PAS | 112 + VCL/vsscm32/Misc.dcu | Bin 0 -> 1674 bytes VCL/vsscm32/Readme.txt | 78 + VCL/vsscm32/VSSComm32.dcr | Bin 0 -> 696 bytes VCL/vsscm32/VSSComm32.dcu | Bin 0 -> 21149 bytes VCL/vsscm32/VSSComm32.pas | 1599 ++++ VCL/vsscm32/vsscmdemo.dof | 48 + VCL/vsscm32/vsscmdemo.dpr | 13 + VCL/vsscm32/vsscmdemo.res | Bin 0 -> 876 bytes VCL/vsscm32/vsscomdemo.dcu | Bin 0 -> 3490 bytes VCL/vsscm32/vsscomdemo.dfm | Bin 0 -> 832 bytes VCL/vsscm32/vsscomdemo.pas | 66 + VCL/vsscm32/vsscomm32.res | Bin 0 -> 1316 bytes VCL/wsagraph/EXAMPLE.TXT | 42 + VCL/wsagraph/Wsagraph.dcu | Bin 0 -> 14235 bytes VCL/wsagraph/Wsagraph.pas | 387 + VCL/wsagraph/Wsagraph.~pa | 387 + VCL/z_timer/Z_TIMER.TXT | 70 + VCL/z_timer/Z_timer.dcr | Bin 0 -> 692 bytes VCL/z_timer/Z_timer.dcu | Bin 0 -> 3841 bytes VCL/z_timer/Z_timer.pas | 155 + omnirig.zip | Bin 107844 -> 0 bytes omnirig/Chartfx3.dcu | Bin 0 -> 41053 bytes omnirig/OmniRig_TLB.dcr | Bin 0 -> 9934 bytes omnirig/OmniRig_TLB.dcu | Bin 0 -> 28562 bytes omnirig/OmniRig_TLB.pas | 1437 +++ omnirig/VCF1.dcu | Bin 0 -> 96162 bytes omnirig/VCFI.dcu | Bin 0 -> 118314 bytes omnirig/VCSpell3.dcu | Bin 0 -> 37322 bytes zlogsource2.zip | Bin 349104 -> 0 bytes zlogsource2/BGK32Lib.pas | 2214 +++++ zlogsource2/BGK32Lib2.pas | 1759 ++++ zlogsource2/Project1.dpr | 14 + zlogsource2/TScratchSheet.dfm | Bin 0 -> 124 bytes zlogsource2/TScratchSheet.pas | 63 + zlogsource2/UACAGMulti.dfm | Bin 0 -> 4147 bytes zlogsource2/UACAGMulti.pas | 321 + zlogsource2/UACAGScore.dfm | Bin 0 -> 895 bytes zlogsource2/UACAGScore.pas | 154 + zlogsource2/UALLJAEditDialog.dfm | Bin 0 -> 477 bytes zlogsource2/UALLJAEditDialog.pas | 63 + zlogsource2/UALLJAMulti.dfm | Bin 0 -> 3603 bytes zlogsource2/UALLJAMulti.pas | 373 + zlogsource2/UALLJAScore.dfm | Bin 0 -> 1141 bytes zlogsource2/UALLJAScore.pas | 123 + zlogsource2/UALLJAScore1.dfm | Bin 0 -> 2384 bytes zlogsource2/UALLJAScore1.pas | 119 + zlogsource2/UAPSprintScore.dfm | Bin 0 -> 923 bytes zlogsource2/UAPSprintScore.pas | 74 + zlogsource2/UARRL10Multi.dfm | Bin 0 -> 816 bytes zlogsource2/UARRL10Multi.pas | 388 + zlogsource2/UARRL10Score.dfm | Bin 0 -> 592 bytes zlogsource2/UARRL10Score.pas | 95 + zlogsource2/UARRLDXMulti.dfm | Bin 0 -> 774 bytes zlogsource2/UARRLDXMulti.pas | 325 + zlogsource2/UARRLDXScore.dfm | Bin 0 -> 1013 bytes zlogsource2/UARRLDXScore.pas | 99 + zlogsource2/UARRLWMulti.dfm | Bin 0 -> 120 bytes zlogsource2/UARRLWMulti.pas | 161 + zlogsource2/UAbout.dfm | Bin 0 -> 2300 bytes zlogsource2/UAbout.pas | 58 + zlogsource2/UAgeDialog.dfm | Bin 0 -> 811 bytes zlogsource2/UAgeDialog.pas | 43 + zlogsource2/UAllAsianScore.dfm | Bin 0 -> 89 bytes zlogsource2/UAllAsianScore.pas | 66 + zlogsource2/UBGKMonitorThread.pas | 63 + zlogsource2/UBandScope2.dfm | 125 + zlogsource2/UBandScope2.pas | 499 + zlogsource2/UBasicMulti.dfm | Bin 0 -> 360 bytes zlogsource2/UBasicMulti.pas | 262 + zlogsource2/UBasicScore.dfm | Bin 0 -> 810 bytes zlogsource2/UBasicScore.pas | 294 + zlogsource2/UCWForm.dfm | Bin 0 -> 194 bytes zlogsource2/UCWForm.pas | 24 + zlogsource2/UCWKeyBoard.dfm | Bin 0 -> 800 bytes zlogsource2/UCWKeyBoard.pas | 131 + zlogsource2/UChat.dfm | Bin 0 -> 1400 bytes zlogsource2/UChat.pas | 167 + zlogsource2/UCheckCall%.dfm | Bin 0 -> 887 bytes zlogsource2/UCheckCall%.pas | 129 + zlogsource2/UCheckCall2.dfm | Bin 0 -> 114 bytes zlogsource2/UCheckCall2.pas | 90 + zlogsource2/UCheckCountry.dfm | Bin 0 -> 187 bytes zlogsource2/UCheckCountry.pas | 124 + zlogsource2/UCheckMulti.dfm | Bin 0 -> 114 bytes zlogsource2/UCheckMulti.pas | 63 + zlogsource2/UCheckWin.dfm | Bin 0 -> 904 bytes zlogsource2/UCheckWin.pas | 122 + zlogsource2/UCluster.dfm | Bin 0 -> 579 bytes zlogsource2/UCluster.pas | 55 + zlogsource2/UClusterCOMSet.dfm | Bin 0 -> 1306 bytes zlogsource2/UClusterCOMSet.pas | 62 + zlogsource2/UClusterTelnetSet.dfm | Bin 0 -> 1410 bytes zlogsource2/UClusterTelnetSet.pas | 64 + zlogsource2/UComm.dfm | Bin 0 -> 2655 bytes zlogsource2/UComm.pas | 663 ++ zlogsource2/UConsolePad.dfm | Bin 0 -> 802 bytes zlogsource2/UConsolePad.pas | 90 + zlogsource2/UELogJapanese.dfm | 509 + zlogsource2/UELogJapanese.pas | 332 + zlogsource2/UEditDialog.dfm | Bin 0 -> 3965 bytes zlogsource2/UEditDialog.pas | 905 ++ zlogsource2/UFDMulti.dfm | Bin 0 -> 713 bytes zlogsource2/UFDMulti.pas | 244 + zlogsource2/UFreqList.dfm | Bin 0 -> 249 bytes zlogsource2/UFreqList.pas | 137 + zlogsource2/UGeneralMulti.dfm | Bin 0 -> 123 bytes zlogsource2/UGeneralMulti.pas | 25 + zlogsource2/UGeneralMulti2.dfm | Bin 0 -> 103 bytes zlogsource2/UGeneralMulti2.pas | 730 ++ zlogsource2/UGeneralScore.dfm | Bin 0 -> 904 bytes zlogsource2/UGeneralScore.pas | 951 ++ zlogsource2/UIARUMulti.dfm | Bin 0 -> 508 bytes zlogsource2/UIARUMulti.pas | 551 ++ zlogsource2/UIARUScore.dfm | Bin 0 -> 576 bytes zlogsource2/UIARUScore.pas | 162 + zlogsource2/UIOTACategory.dfm | Bin 0 -> 922 bytes zlogsource2/UIOTACategory.pas | 50 + zlogsource2/UIOTAMulti.dfm | Bin 0 -> 1038 bytes zlogsource2/UIOTAMulti.pas | 414 + zlogsource2/UIntegerDialog.dfm | Bin 0 -> 790 bytes zlogsource2/UIntegerDialog.pas | 104 + zlogsource2/UJA0Multi.dfm | Bin 0 -> 664 bytes zlogsource2/UJA0Multi.pas | 168 + zlogsource2/UJA0Score.dfm | Bin 0 -> 804 bytes zlogsource2/UJA0Score.pas | 128 + zlogsource2/UJIDXMulti.dfm | Bin 0 -> 111 bytes zlogsource2/UJIDXMulti.pas | 123 + zlogsource2/UJIDXScore.dfm | Bin 0 -> 661 bytes zlogsource2/UJIDXScore.pas | 58 + zlogsource2/UJIDXScore2.dfm | Bin 0 -> 1057 bytes zlogsource2/UJIDXScore2.pas | 137 + zlogsource2/UJIDX_DX_Multi.dfm | Bin 0 -> 4541 bytes zlogsource2/UJIDX_DX_Multi.pas | 296 + zlogsource2/UJIDX_DX_Score.dfm | Bin 0 -> 1062 bytes zlogsource2/UJIDX_DX_Score.pas | 104 + zlogsource2/UKCJMulti.dfm | Bin 0 -> 2287 bytes zlogsource2/UKCJMulti.pas | 260 + zlogsource2/UKCJScore.dfm | Bin 0 -> 1133 bytes zlogsource2/UKCJScore.pas | 70 + zlogsource2/UKCJZone.dfm | Bin 0 -> 4617 bytes zlogsource2/UKCJZone.pas | 115 + zlogsource2/UMMTTY.pas | 145 + zlogsource2/UMenu.dfm | Bin 0 -> 5185 bytes zlogsource2/UMenu.pas | 972 ++ zlogsource2/UMinMaxFreqDlg.dfm | Bin 0 -> 896 bytes zlogsource2/UMinMaxFreqDlg.pas | 79 + zlogsource2/UMultipliers.pas | 1197 +++ zlogsource2/UNewIOTARef.dfm | Bin 0 -> 783 bytes zlogsource2/UNewIOTARef.pas | 50 + zlogsource2/UNewPrefix.dfm | Bin 0 -> 1022 bytes zlogsource2/UNewPrefix.pas | 73 + zlogsource2/UOptions.dfm | Bin 0 -> 23568 bytes zlogsource2/UOptions.pas | 2316 +++++ zlogsource2/UPartials.dfm | Bin 0 -> 1848 bytes zlogsource2/UPartials.pas | 492 + zlogsource2/UPediScore.dfm | Bin 0 -> 1969 bytes zlogsource2/UPediScore.pas | 122 + zlogsource2/UQTCForm.dfm | Bin 0 -> 1567 bytes zlogsource2/UQTCForm.pas | 278 + zlogsource2/UQTHDialog.dfm | Bin 0 -> 1817 bytes zlogsource2/UQTHDialog.pas | 63 + zlogsource2/UQuickRef.dfm | 35 + zlogsource2/UQuickRef.pas | 52 + zlogsource2/URateDialog.dfm | Bin 0 -> 2107 bytes zlogsource2/URateDialog.pas | 264 + zlogsource2/URenewThread.pas | 89 + zlogsource2/URigControl.dfm | Bin 0 -> 2533 bytes zlogsource2/URigControl.pas | 2902 ++++++ zlogsource2/UScratchSheet.dfm | Bin 0 -> 403 bytes zlogsource2/UScratchSheet.pas | 134 + zlogsource2/USixDownMulti.dfm | Bin 0 -> 709 bytes zlogsource2/USixDownMulti.pas | 43 + zlogsource2/USixDownScore.dfm | Bin 0 -> 1217 bytes zlogsource2/USixDownScore.pas | 153 + zlogsource2/USoundForm.Pas | 27 + zlogsource2/USoundForm.dfm | Bin 0 -> 394 bytes zlogsource2/USpotClass.pas | 335 + zlogsource2/USpotForm.dfm | Bin 0 -> 1069 bytes zlogsource2/USpotForm.pas | 81 + zlogsource2/USummaryInfo.dfm | Bin 0 -> 2138 bytes zlogsource2/USummaryInfo.pas | 103 + zlogsource2/USuperCheck.dfm | Bin 0 -> 1125 bytes zlogsource2/USuperCheck.pas | 255 + zlogsource2/UTTYConsole.dfm | Bin 0 -> 1779 bytes zlogsource2/UTTYConsole.pas | 366 + zlogsource2/UUTCDialog.dfm | Bin 0 -> 680 bytes zlogsource2/UUTCDialog.pas | 35 + zlogsource2/UVoiceForm.dfm | 30 + zlogsource2/UVoiceForm.pas | 67 + zlogsource2/UVoiceThread.pas | 140 + zlogsource2/UWAEMulti.dfm | Bin 0 -> 174 bytes zlogsource2/UWAEMulti.pas | 121 + zlogsource2/UWAEScore.dfm | Bin 0 -> 950 bytes zlogsource2/UWAEScore.pas | 126 + zlogsource2/UWPXMulti.dfm | Bin 0 -> 138 bytes zlogsource2/UWPXMulti.pas | 376 + zlogsource2/UWPXScore.dfm | Bin 0 -> 981 bytes zlogsource2/UWPXScore.pas | 124 + zlogsource2/UWWMulti.dfm | Bin 0 -> 2688 bytes zlogsource2/UWWMulti.pas | 749 ++ zlogsource2/UWWScore.dfm | Bin 0 -> 1049 bytes zlogsource2/UWWScore.pas | 144 + zlogsource2/UWWZone.dfm | Bin 0 -> 3121 bytes zlogsource2/UWWZone.pas | 96 + zlogsource2/UZLinkForm.dfm | Bin 0 -> 1931 bytes zlogsource2/UZLinkForm.pas | 1074 +++ zlogsource2/UZLinkFormOld.dfm | Bin 0 -> 1868 bytes zlogsource2/UZLinkFormOld.pas | 385 + zlogsource2/UZServerInquiry.dfm | Bin 0 -> 845 bytes zlogsource2/UZServerInquiry.pas | 68 + zlogsource2/UZlinkComSet.dfm | Bin 0 -> 296 bytes zlogsource2/UZlinkComSet.pas | 34 + zlogsource2/UZlinkTelnetSet.dfm | Bin 0 -> 165 bytes zlogsource2/UZlinkTelnetSet.pas | 34 + zlogsource2/Unit1.dfm | Bin 0 -> 775 bytes zlogsource2/Unit1.pas | 90 + zlogsource2/UzLogCW.pas | 373 + zlogsource2/UzLogVoice.pas | 91 + zlogsource2/Vic_Res.pas | 1318 +++ zlogsource2/WavePlayer.pas | 483 + zlogsource2/Zlog.dpr | 155 + zlogsource2/ccczlogconv.dfm | Bin 0 -> 484 bytes zlogsource2/ccczlogconv.pas | 147 + zlogsource2/main.dfm | Bin 0 -> 117392 bytes zlogsource2/main.pas | 8264 +++++++++++++++++ zlogsource2/menu.dfm | Bin 0 -> 1544 bytes zlogsource2/menu.pas | 39 + zlogsource2/testmain.dfm | Bin 0 -> 316 bytes zlogsource2/testmain.pas | 33 + zlogsource2/testscope.dpr | 17 + zlogsource2/ubandscope.dfm | Bin 0 -> 1727 bytes zlogsource2/ubandscope.pas | 688 ++ zlogsource2/upaddlethread.pas | 72 + zlogsource2/utelnetset.dfm | Bin 0 -> 890 bytes zlogsource2/utelnetset.pas | 28 + zlogsource2/zLogGlobal.pas | 1793 ++++ zlogsource2/zprintw.pas | Bin 0 -> 766 bytes 2013 files changed, 402201 insertions(+) delete mode 100644 ICS_zlog.zip create mode 100644 ICS_zlog/Delphi/Internet/Cli7.dfm create mode 100644 ICS_zlog/Delphi/Internet/Cli7.pas create mode 100644 ICS_zlog/Delphi/Internet/CliDemo1.dfm create mode 100644 ICS_zlog/Delphi/Internet/CliDemo1.pas create mode 100644 ICS_zlog/Delphi/Internet/Client7.dpr create mode 100644 ICS_zlog/Delphi/Internet/ConCli1.dpr create mode 100644 ICS_zlog/Delphi/Internet/ConCli2.dpr create mode 100644 ICS_zlog/Delphi/Internet/ConFtp.dpr create mode 100644 ICS_zlog/Delphi/Internet/ConHttp.dpr create mode 100644 ICS_zlog/Delphi/Internet/ConSmtp.dpr create mode 100644 ICS_zlog/Delphi/Internet/ConSrv1.dpr create mode 100644 ICS_zlog/Delphi/Internet/ConSrv1C.pas create mode 100644 ICS_zlog/Delphi/Internet/ConSrv1S.pas create mode 100644 ICS_zlog/Delphi/Internet/Del40Sam.bpg create mode 100644 ICS_zlog/Delphi/Internet/Del50Sam.bpg create mode 100644 ICS_zlog/Delphi/Internet/Del60Sam.bpg create mode 100644 ICS_zlog/Delphi/Internet/Del70Sam.bpg create mode 100644 ICS_zlog/Delphi/Internet/DllTst1.dpr create mode 100644 ICS_zlog/Delphi/Internet/DllTst_1.dfm create mode 100644 ICS_zlog/Delphi/Internet/DllTst_1.pas create mode 100644 ICS_zlog/Delphi/Internet/DnsLook1.dfm create mode 100644 ICS_zlog/Delphi/Internet/DnsLook1.pas create mode 100644 ICS_zlog/Delphi/Internet/DynCli.dpr create mode 100644 ICS_zlog/Delphi/Internet/DynCli1.dfm create mode 100644 ICS_zlog/Delphi/Internet/DynCli1.pas create mode 100644 ICS_zlog/Delphi/Internet/FTPTST2.dfm create mode 100644 ICS_zlog/Delphi/Internet/FtpServ1.dfm create mode 100644 ICS_zlog/Delphi/Internet/FtpServ1.pas create mode 100644 ICS_zlog/Delphi/Internet/FtpThrd1.dfm create mode 100644 ICS_zlog/Delphi/Internet/FtpThrd1.pas create mode 100644 ICS_zlog/Delphi/Internet/Ftptst2.pas create mode 100644 ICS_zlog/Delphi/Internet/HLembke/NsLook1.dfm create mode 100644 ICS_zlog/Delphi/Internet/HLembke/NsLook1.pas create mode 100644 ICS_zlog/Delphi/Internet/HLembke/NsLookup.dpr create mode 100644 ICS_zlog/Delphi/Internet/HLembke/ReadMe.txt create mode 100644 ICS_zlog/Delphi/Internet/HLembke/dnsquery.pas create mode 100644 ICS_zlog/Delphi/Internet/HttpAsp1.dfm create mode 100644 ICS_zlog/Delphi/Internet/HttpAsp1.pas create mode 100644 ICS_zlog/Delphi/Internet/HttpAsy1.dfm create mode 100644 ICS_zlog/Delphi/Internet/HttpAsy1.pas create mode 100644 ICS_zlog/Delphi/Internet/HttpChk1.dfm create mode 100644 ICS_zlog/Delphi/Internet/HttpChk1.pas create mode 100644 ICS_zlog/Delphi/Internet/HttpDmo1.dfm create mode 100644 ICS_zlog/Delphi/Internet/HttpDmo1.pas create mode 100644 ICS_zlog/Delphi/Internet/HttpGet1.dfm create mode 100644 ICS_zlog/Delphi/Internet/HttpGet1.pas create mode 100644 ICS_zlog/Delphi/Internet/HttpPg1.dfm create mode 100644 ICS_zlog/Delphi/Internet/HttpPg1.pas create mode 100644 ICS_zlog/Delphi/Internet/HttpThr1.dfm create mode 100644 ICS_zlog/Delphi/Internet/HttpThr1.pas create mode 100644 ICS_zlog/Delphi/Internet/HttpThr2.pas create mode 100644 ICS_zlog/Delphi/Internet/Httpdmo.dpr create mode 100644 ICS_zlog/Delphi/Internet/Ics.ico create mode 100644 ICS_zlog/Delphi/Internet/IcsDll1.dpr create mode 100644 ICS_zlog/Delphi/Internet/IcsIsap1.dfm create mode 100644 ICS_zlog/Delphi/Internet/IcsIsap1.pas create mode 100644 ICS_zlog/Delphi/Internet/IcsIsapi.dpr create mode 100644 ICS_zlog/Delphi/Internet/MailRcv.dpr create mode 100644 ICS_zlog/Delphi/Internet/MailRcv1.dfm create mode 100644 ICS_zlog/Delphi/Internet/MailRcv1.pas create mode 100644 ICS_zlog/Delphi/Internet/MailRcv2.dfm create mode 100644 ICS_zlog/Delphi/Internet/MailRcv2.pas create mode 100644 ICS_zlog/Delphi/Internet/MailRob.dpr create mode 100644 ICS_zlog/Delphi/Internet/MailRob1.dfm create mode 100644 ICS_zlog/Delphi/Internet/MailRob1.pas create mode 100644 ICS_zlog/Delphi/Internet/MailSnd.dpr create mode 100644 ICS_zlog/Delphi/Internet/MailSnd1.dfm create mode 100644 ICS_zlog/Delphi/Internet/MailSnd1.pas create mode 100644 ICS_zlog/Delphi/Internet/MbxSub.dpr create mode 100644 ICS_zlog/Delphi/Internet/MbxSub1.dfm create mode 100644 ICS_zlog/Delphi/Internet/MbxSub1.pas create mode 100644 ICS_zlog/Delphi/Internet/MimeDemo.dpr create mode 100644 ICS_zlog/Delphi/Internet/MimeDmo1.dfm create mode 100644 ICS_zlog/Delphi/Internet/MimeDmo1.pas create mode 100644 ICS_zlog/Delphi/Internet/MimeTst.dpr create mode 100644 ICS_zlog/Delphi/Internet/MimeTst1.dfm create mode 100644 ICS_zlog/Delphi/Internet/MimeTst1.pas create mode 100644 ICS_zlog/Delphi/Internet/NewsRdr1.dfm create mode 100644 ICS_zlog/Delphi/Internet/NewsRdr1.pas create mode 100644 ICS_zlog/Delphi/Internet/NsLook1.dfm create mode 100644 ICS_zlog/Delphi/Internet/NsLook1.pas create mode 100644 ICS_zlog/Delphi/Internet/NsLookup.dpr create mode 100644 ICS_zlog/Delphi/Internet/POP3MIM1.dfm create mode 100644 ICS_zlog/Delphi/Internet/PingTst1.dfm create mode 100644 ICS_zlog/Delphi/Internet/PingTst1.pas create mode 100644 ICS_zlog/Delphi/Internet/Pop3Mim1.pas create mode 100644 ICS_zlog/Delphi/Internet/Pop3Mime.dpr create mode 100644 ICS_zlog/Delphi/Internet/PopTst1.dfm create mode 100644 ICS_zlog/Delphi/Internet/PopTst1.pas create mode 100644 ICS_zlog/Delphi/Internet/Recv.dpr create mode 100644 ICS_zlog/Delphi/Internet/Recv1.dfm create mode 100644 ICS_zlog/Delphi/Internet/Recv1.pas create mode 100644 ICS_zlog/Delphi/Internet/Sender.dpr create mode 100644 ICS_zlog/Delphi/Internet/Sender1.dfm create mode 100644 ICS_zlog/Delphi/Internet/Sender1.pas create mode 100644 ICS_zlog/Delphi/Internet/Socks1.dfm create mode 100644 ICS_zlog/Delphi/Internet/Socks1.pas create mode 100644 ICS_zlog/Delphi/Internet/SocksTst.dpr create mode 100644 ICS_zlog/Delphi/Internet/SrvDemo1.dfm create mode 100644 ICS_zlog/Delphi/Internet/SrvDemo1.pas create mode 100644 ICS_zlog/Delphi/Internet/SrvDemo2.dfm create mode 100644 ICS_zlog/Delphi/Internet/SrvDemo2.pas create mode 100644 ICS_zlog/Delphi/Internet/SrvTcp.dpr create mode 100644 ICS_zlog/Delphi/Internet/SrvTcp1.dfm create mode 100644 ICS_zlog/Delphi/Internet/SrvTcp1.pas create mode 100644 ICS_zlog/Delphi/Internet/SvcTcp.dpr create mode 100644 ICS_zlog/Delphi/Internet/SvcTcp1.dfm create mode 100644 ICS_zlog/Delphi/Internet/SvcTcp1.pas create mode 100644 ICS_zlog/Delphi/Internet/TcpCmd.pas create mode 100644 ICS_zlog/Delphi/Internet/TcpSrv.dpr create mode 100644 ICS_zlog/Delphi/Internet/TcpSrv1.dfm create mode 100644 ICS_zlog/Delphi/Internet/TcpSrv1.pas create mode 100644 ICS_zlog/Delphi/Internet/ThrdSrv.dpr create mode 100644 ICS_zlog/Delphi/Internet/TnCli1.dfm create mode 100644 ICS_zlog/Delphi/Internet/TnCli1.pas create mode 100644 ICS_zlog/Delphi/Internet/UdpLstn1.dfm create mode 100644 ICS_zlog/Delphi/Internet/UdpLstn1.pas create mode 100644 ICS_zlog/Delphi/Internet/UdpSend1.dfm create mode 100644 ICS_zlog/Delphi/Internet/UdpSend1.pas create mode 100644 ICS_zlog/Delphi/Internet/WebServ.dpr create mode 100644 ICS_zlog/Delphi/Internet/WebServ1.dfm create mode 100644 ICS_zlog/Delphi/Internet/WebServ1.pas create mode 100644 ICS_zlog/Delphi/Internet/cli5.dfm create mode 100644 ICS_zlog/Delphi/Internet/cli5.pas create mode 100644 ICS_zlog/Delphi/Internet/clidemo.dpr create mode 100644 ICS_zlog/Delphi/Internet/client5.dpr create mode 100644 ICS_zlog/Delphi/Internet/clients.DBF create mode 100644 ICS_zlog/Delphi/Internet/clients.MDX create mode 100644 ICS_zlog/Delphi/Internet/dnslook.dpr create mode 100644 ICS_zlog/Delphi/Internet/finger.dpr create mode 100644 ICS_zlog/Delphi/Internet/finger1.dfm create mode 100644 ICS_zlog/Delphi/Internet/finger1.pas create mode 100644 ICS_zlog/Delphi/Internet/ftpServ.dpr create mode 100644 ICS_zlog/Delphi/Internet/ftpcli.ico create mode 100644 ICS_zlog/Delphi/Internet/ftpthrd.dpr create mode 100644 ICS_zlog/Delphi/Internet/ftptst.dpr create mode 100644 ICS_zlog/Delphi/Internet/ftptst1.dfm create mode 100644 ICS_zlog/Delphi/Internet/ftptst1.pas create mode 100644 ICS_zlog/Delphi/Internet/httpChk.dpr create mode 100644 ICS_zlog/Delphi/Internet/httpasp.dpr create mode 100644 ICS_zlog/Delphi/Internet/httpasy.dpr create mode 100644 ICS_zlog/Delphi/Internet/httpget.dpr create mode 100644 ICS_zlog/Delphi/Internet/httppg.dpr create mode 100644 ICS_zlog/Delphi/Internet/httpthrd.dpr create mode 100644 ICS_zlog/Delphi/Internet/httptst.dpr create mode 100644 ICS_zlog/Delphi/Internet/httptst1.dfm create mode 100644 ICS_zlog/Delphi/Internet/httptst1.pas create mode 100644 ICS_zlog/Delphi/Internet/md5test.dpr create mode 100644 ICS_zlog/Delphi/Internet/md5test1.dfm create mode 100644 ICS_zlog/Delphi/Internet/md5test1.pas create mode 100644 ICS_zlog/Delphi/Internet/mtsrv.dpr create mode 100644 ICS_zlog/Delphi/Internet/mtsrv.ico create mode 100644 ICS_zlog/Delphi/Internet/mtsrv.res create mode 100644 ICS_zlog/Delphi/Internet/mtsrv1.dfm create mode 100644 ICS_zlog/Delphi/Internet/mtsrv1.pas create mode 100644 ICS_zlog/Delphi/Internet/mtsrv2.pas create mode 100644 ICS_zlog/Delphi/Internet/newsrdr.dpr create mode 100644 ICS_zlog/Delphi/Internet/pingtst.dpr create mode 100644 ICS_zlog/Delphi/Internet/poptst.dpr create mode 100644 ICS_zlog/Delphi/Internet/poptst2.dfm create mode 100644 ICS_zlog/Delphi/Internet/poptst2.pas create mode 100644 ICS_zlog/Delphi/Internet/server5.dpr create mode 100644 ICS_zlog/Delphi/Internet/srv5.dfm create mode 100644 ICS_zlog/Delphi/Internet/srv5.pas create mode 100644 ICS_zlog/Delphi/Internet/srvdemo.dpr create mode 100644 ICS_zlog/Delphi/Internet/thrdsrv1.dfm create mode 100644 ICS_zlog/Delphi/Internet/thrdsrv1.pas create mode 100644 ICS_zlog/Delphi/Internet/tnclient.dpr create mode 100644 ICS_zlog/Delphi/Internet/tnclient.ico create mode 100644 ICS_zlog/Delphi/Internet/tndemo.dpr create mode 100644 ICS_zlog/Delphi/Internet/tndemo1.dfm create mode 100644 ICS_zlog/Delphi/Internet/tndemo1.pas create mode 100644 ICS_zlog/Delphi/Internet/tnsrv.dpr create mode 100644 ICS_zlog/Delphi/Internet/tnsrv.ico create mode 100644 ICS_zlog/Delphi/Internet/tnsrv1.dfm create mode 100644 ICS_zlog/Delphi/Internet/tnsrv1.pas create mode 100644 ICS_zlog/Delphi/Internet/tnsrv2.dfm create mode 100644 ICS_zlog/Delphi/Internet/tnsrv2.pas create mode 100644 ICS_zlog/Delphi/Internet/twschat.dpr create mode 100644 ICS_zlog/Delphi/Internet/twschat1.dfm create mode 100644 ICS_zlog/Delphi/Internet/twschat1.pas create mode 100644 ICS_zlog/Delphi/Internet/udplstn.dpr create mode 100644 ICS_zlog/Delphi/Internet/udpsend.dpr create mode 100644 ICS_zlog/Delphi/Vc/DnsQuery.dcr create mode 100644 ICS_zlog/Delphi/Vc/FtpSrv.dcr create mode 100644 ICS_zlog/Delphi/Vc/Pop3Prot.dcr create mode 100644 ICS_zlog/Delphi/Vc/SmtpProt.dcr create mode 100644 ICS_zlog/Delphi/Vc/TNSCRIPT.DCR create mode 100644 ICS_zlog/Delphi/Vc/WINSOCK.PAS create mode 100644 ICS_zlog/Delphi/Vc/emulvt.dcr create mode 100644 ICS_zlog/Delphi/Vc/fingcli.dcr create mode 100644 ICS_zlog/Delphi/Vc/ftpcli.dcr create mode 100644 ICS_zlog/Delphi/Vc/httpprot.dcr create mode 100644 ICS_zlog/Delphi/Vc/httpsrv.dcr create mode 100644 ICS_zlog/Delphi/Vc/mbxfile.dcr create mode 100644 ICS_zlog/Delphi/Vc/mimedec.dcr create mode 100644 ICS_zlog/Delphi/Vc/nntpcli.dcr create mode 100644 ICS_zlog/Delphi/Vc/tncnx.dcr create mode 100644 ICS_zlog/Delphi/Vc/tnemulvt.dcr create mode 100644 ICS_zlog/Delphi/Vc/wait.dcr create mode 100644 ICS_zlog/Delphi/Vc/wsocket.dcr create mode 100644 ICS_zlog/Delphi/Vc/wsockets.dcr create mode 100644 ICS_zlog/Delphi/Vc32/DnsQuery.dcr create mode 100644 ICS_zlog/Delphi/Vc32/DnsQuery.dcu create mode 100644 ICS_zlog/Delphi/Vc32/DnsQuery.pas create mode 100644 ICS_zlog/Delphi/Vc32/EmulVT.dcu create mode 100644 ICS_zlog/Delphi/Vc32/EmulVT.pas create mode 100644 ICS_zlog/Delphi/Vc32/FingCli.dcu create mode 100644 ICS_zlog/Delphi/Vc32/FingCli.pas create mode 100644 ICS_zlog/Delphi/Vc32/FtpCli.dcu create mode 100644 ICS_zlog/Delphi/Vc32/FtpCli.pas create mode 100644 ICS_zlog/Delphi/Vc32/FtpSrvC.dcu create mode 100644 ICS_zlog/Delphi/Vc32/FtpSrvC.pas create mode 100644 ICS_zlog/Delphi/Vc32/FtpSrvT.dcu create mode 100644 ICS_zlog/Delphi/Vc32/FtpSrvT.pas create mode 100644 ICS_zlog/Delphi/Vc32/HttpSrv.dcr create mode 100644 ICS_zlog/Delphi/Vc32/HttpSrv.dcu create mode 100644 ICS_zlog/Delphi/Vc32/HttpSrv.pas create mode 100644 ICS_zlog/Delphi/Vc32/IcsBcb30.bpk create mode 100644 ICS_zlog/Delphi/Vc32/IcsBcb30.cpp create mode 100644 ICS_zlog/Delphi/Vc32/IcsBcb30.res create mode 100644 ICS_zlog/Delphi/Vc32/IcsBcb50.bpk create mode 100644 ICS_zlog/Delphi/Vc32/IcsBcb50.cpp create mode 100644 ICS_zlog/Delphi/Vc32/IcsBcb50.res create mode 100644 ICS_zlog/Delphi/Vc32/IcsBcb60.bpk create mode 100644 ICS_zlog/Delphi/Vc32/IcsBcb60.cpp create mode 100644 ICS_zlog/Delphi/Vc32/IcsBcb60.res create mode 100644 ICS_zlog/Delphi/Vc32/IcsDel30.dpk create mode 100644 ICS_zlog/Delphi/Vc32/IcsDel40.dpk create mode 100644 ICS_zlog/Delphi/Vc32/IcsDel40.res create mode 100644 ICS_zlog/Delphi/Vc32/IcsDel50.dpk create mode 100644 ICS_zlog/Delphi/Vc32/IcsDel50.res create mode 100644 ICS_zlog/Delphi/Vc32/IcsDel60.cfg create mode 100644 ICS_zlog/Delphi/Vc32/IcsDel60.dcu create mode 100644 ICS_zlog/Delphi/Vc32/IcsDel60.dof create mode 100644 ICS_zlog/Delphi/Vc32/IcsDel60.dpk create mode 100644 ICS_zlog/Delphi/Vc32/IcsDel60.res create mode 100644 ICS_zlog/Delphi/Vc32/IcsDel70.dof create mode 100644 ICS_zlog/Delphi/Vc32/IcsDel70.dpk create mode 100644 ICS_zlog/Delphi/Vc32/IcsDel70.res create mode 100644 ICS_zlog/Delphi/Vc32/Icsbcb40.bpk create mode 100644 ICS_zlog/Delphi/Vc32/Icsbcb40.cpp create mode 100644 ICS_zlog/Delphi/Vc32/Icsbcb40.res create mode 100644 ICS_zlog/Delphi/Vc32/Icsdel30.res create mode 100644 ICS_zlog/Delphi/Vc32/MD5.dcu create mode 100644 ICS_zlog/Delphi/Vc32/MD5.pas create mode 100644 ICS_zlog/Delphi/Vc32/MbxFile.dcr create mode 100644 ICS_zlog/Delphi/Vc32/MbxFile.dcu create mode 100644 ICS_zlog/Delphi/Vc32/MbxFile.pas create mode 100644 ICS_zlog/Delphi/Vc32/NntpCli.dcu create mode 100644 ICS_zlog/Delphi/Vc32/NntpCli.pas create mode 100644 ICS_zlog/Delphi/Vc32/POP3CLI.DCR create mode 100644 ICS_zlog/Delphi/Vc32/Ping.dcu create mode 100644 ICS_zlog/Delphi/Vc32/Ping.pas create mode 100644 ICS_zlog/Delphi/Vc32/Pop3Prot.dcr create mode 100644 ICS_zlog/Delphi/Vc32/Pop3Prot.dcu create mode 100644 ICS_zlog/Delphi/Vc32/Pop3Prot.pas create mode 100644 ICS_zlog/Delphi/Vc32/Pop3cli.pas create mode 100644 ICS_zlog/Delphi/Vc32/SmtpProt.dcr create mode 100644 ICS_zlog/Delphi/Vc32/SmtpProt.dcu create mode 100644 ICS_zlog/Delphi/Vc32/SmtpProt.pas create mode 100644 ICS_zlog/Delphi/Vc32/TNCNX.HLP create mode 100644 ICS_zlog/Delphi/Vc32/TnCnx.dcu create mode 100644 ICS_zlog/Delphi/Vc32/TnCnx.pas create mode 100644 ICS_zlog/Delphi/Vc32/TnEmulVT.dcu create mode 100644 ICS_zlog/Delphi/Vc32/TnEmulVT.pas create mode 100644 ICS_zlog/Delphi/Vc32/TnOptFrm.dcu create mode 100644 ICS_zlog/Delphi/Vc32/TnOptFrm.dfm create mode 100644 ICS_zlog/Delphi/Vc32/TnOptFrm.pas create mode 100644 ICS_zlog/Delphi/Vc32/TnScript.dcu create mode 100644 ICS_zlog/Delphi/Vc32/TnScript.pas create mode 100644 ICS_zlog/Delphi/Vc32/UUEncode.pas create mode 100644 ICS_zlog/Delphi/Vc32/WSOCKET.GID create mode 100644 ICS_zlog/Delphi/Vc32/WSOCKET.HLP create mode 100644 ICS_zlog/Delphi/Vc32/WSockBuf.dcu create mode 100644 ICS_zlog/Delphi/Vc32/WSockBuf.pas create mode 100644 ICS_zlog/Delphi/Vc32/WSocket.dcu create mode 100644 ICS_zlog/Delphi/Vc32/WSocket.pas create mode 100644 ICS_zlog/Delphi/Vc32/WSocketE.dcu create mode 100644 ICS_zlog/Delphi/Vc32/WSocketE.pas create mode 100644 ICS_zlog/Delphi/Vc32/WSocketS.dcr create mode 100644 ICS_zlog/Delphi/Vc32/WSocketS.dcu create mode 100644 ICS_zlog/Delphi/Vc32/WSocketS.pas create mode 100644 ICS_zlog/Delphi/Vc32/emulvt.dcr create mode 100644 ICS_zlog/Delphi/Vc32/fingcli.dcr create mode 100644 ICS_zlog/Delphi/Vc32/formpos.dcu create mode 100644 ICS_zlog/Delphi/Vc32/formpos.pas create mode 100644 ICS_zlog/Delphi/Vc32/ftpcli.dcr create mode 100644 ICS_zlog/Delphi/Vc32/ftpsrv.dcr create mode 100644 ICS_zlog/Delphi/Vc32/ftpsrv.dcu create mode 100644 ICS_zlog/Delphi/Vc32/ftpsrv.pas create mode 100644 ICS_zlog/Delphi/Vc32/httpprot.dcr create mode 100644 ICS_zlog/Delphi/Vc32/httpprot.dcu create mode 100644 ICS_zlog/Delphi/Vc32/httpprot.pas create mode 100644 ICS_zlog/Delphi/Vc32/icmp.dcu create mode 100644 ICS_zlog/Delphi/Vc32/icmp.pas create mode 100644 ICS_zlog/Delphi/Vc32/mimedec.dcr create mode 100644 ICS_zlog/Delphi/Vc32/mimedec.dcu create mode 100644 ICS_zlog/Delphi/Vc32/mimedec.pas create mode 100644 ICS_zlog/Delphi/Vc32/nntpcli.dcr create mode 100644 ICS_zlog/Delphi/Vc32/ping.dcr create mode 100644 ICS_zlog/Delphi/Vc32/tncnx.dcr create mode 100644 ICS_zlog/Delphi/Vc32/tnemulvt.dcr create mode 100644 ICS_zlog/Delphi/Vc32/tnscript.dcr create mode 100644 ICS_zlog/Delphi/Vc32/wait.dcr create mode 100644 ICS_zlog/Delphi/Vc32/wait.dcu create mode 100644 ICS_zlog/Delphi/Vc32/wait.pas create mode 100644 ICS_zlog/Delphi/Vc32/wsocket.dcr create mode 100644 ICS_zlog/Delphi/Vc32/wsocket.ico delete mode 100644 VCL.zip create mode 100644 VCL/ADVGRID3/ADVGRID.DCR create mode 100644 VCL/ADVGRID3/ADVGRID.DCU create mode 100644 VCL/ADVGRID3/ADVGRID3.GID create mode 100644 VCL/ADVGRID3/ASGPKG.DCP create mode 100644 VCL/ADVGRID3/ASGPKG.DCU create mode 100644 VCL/ADVGRID3/ASGPKG.DPL create mode 100644 VCL/ADVGRID3/ASGPKG.RES create mode 100644 VCL/ADVGRID3/Asgpkg.dpk create mode 100644 VCL/ADVGRID3/Asgpkg.~dp create mode 100644 VCL/ADVGRID3/EDITBTN.DCU create mode 100644 VCL/ADVGRID3/INTELLI.RES create mode 100644 VCL/ADVGRID3/MATCH.DCU create mode 100644 VCL/ASTrayIcon.dcr create mode 100644 VCL/ASTrayIcon.pas create mode 100644 VCL/Audio.dcr create mode 100644 VCL/Audio.dcu create mode 100644 VCL/CM2x/Baltic Solutions.url create mode 100644 VCL/CM2x/Delphi3/Bs_cm.dcp create mode 100644 VCL/CM2x/Delphi3/Bs_cm.dcu create mode 100644 VCL/CM2x/Delphi3/Bs_cm.dpk create mode 100644 VCL/CM2x/Delphi3/Bs_cm.dpl create mode 100644 VCL/CM2x/Delphi3/Bs_cm.res create mode 100644 VCL/CM2x/Delphi3/Bs_cm.~dp create mode 100644 VCL/CM2x/Delphi3/Cmemo.dcr create mode 100644 VCL/CM2x/Delphi3/Cmemo.dcu create mode 100644 VCL/CM2x/Delphi3/Cmemo.dfm create mode 100644 VCL/CM2x/Delphi3/Colmemo.dcu create mode 100644 VCL/CM2x/Delphi3/Colmemo.res create mode 100644 VCL/CM2x/Delphi4/Bs_cm.bpl create mode 100644 VCL/CM2x/Delphi4/Bs_cm.dcu create mode 100644 VCL/CM2x/Delphi4/Bs_cm.dpk create mode 100644 VCL/CM2x/Delphi4/Bs_cm.res create mode 100644 VCL/CM2x/Delphi4/Cmemo.dcr create mode 100644 VCL/CM2x/Delphi4/Cmemo.dcu create mode 100644 VCL/CM2x/Delphi4/Cmemo.dfm create mode 100644 VCL/CM2x/Delphi4/Colmemo.dcu create mode 100644 VCL/CM2x/Delphi4/Colmemo.res create mode 100644 VCL/CM2x/Demo/Main.dcu create mode 100644 VCL/CM2x/Demo/Main.dfm create mode 100644 VCL/CM2x/Demo/Main.pas create mode 100644 VCL/CM2x/Demo/cm2_demo.dof create mode 100644 VCL/CM2x/Demo/cm2_demo.dpr create mode 100644 VCL/CM2x/Demo/cm2_demo.res create mode 100644 VCL/CM2x/Demo/cm2_demo.~dp create mode 100644 VCL/CM2x/Demo/cm_even.dcu create mode 100644 VCL/CM2x/Demo/cm_even.dfm create mode 100644 VCL/CM2x/Demo/cm_even.pas create mode 100644 VCL/CM2x/Demo/cm_even.~df create mode 100644 VCL/CM2x/Demo/cm_even.~pa create mode 100644 VCL/CM2x/Demo/cm_html.dcu create mode 100644 VCL/CM2x/Demo/cm_html.dfm create mode 100644 VCL/CM2x/Demo/cm_html.pas create mode 100644 VCL/CM2x/Demo/cm_hyper.dcu create mode 100644 VCL/CM2x/Demo/cm_hyper.dfm create mode 100644 VCL/CM2x/Demo/cm_hyper.pas create mode 100644 VCL/CM2x/Demo/cm_pasc.dcu create mode 100644 VCL/CM2x/Demo/cm_pasc.dfm create mode 100644 VCL/CM2x/Demo/cm_pasc.pas create mode 100644 VCL/CM2x/Help/colormemo.GID create mode 100644 VCL/CM2x/INSTALL.LOG create mode 100644 VCL/CM2x/install.txt create mode 100644 VCL/CM2x/licence.txt create mode 100644 VCL/CM2x/news.txt create mode 100644 VCL/CM2x/ordering.txt create mode 100644 VCL/CM2x/readme.txt create mode 100644 VCL/CONSOLE.PAS create mode 100644 VCL/ComDrv32.dcr create mode 100644 VCL/ComDrv32.dcu create mode 100644 VCL/ComDrv32.pas create mode 100644 VCL/Console.dcu create mode 100644 VCL/EnhWave.dcr create mode 100644 VCL/EnhWave.dcu create mode 100644 VCL/FngSingleInst.dcu create mode 100644 VCL/FngSingleInst.pas create mode 100644 VCL/FngSingleInst.~pas create mode 100644 VCL/GrabBar.bmp create mode 100644 VCL/GrabBar.dcu create mode 100644 VCL/GrabBar.pas create mode 100644 VCL/GrabBar.r16 create mode 100644 VCL/GrabBar.r32 create mode 100644 VCL/GrabBar.rc create mode 100644 VCL/HEMIBTN.DCR create mode 100644 VCL/HEMIBTN.DCU create mode 100644 VCL/HID/DBT.dcu create mode 100644 VCL/HID/DBT.pas create mode 100644 VCL/HID/DEMOS/CollectionDemo/Project1.dof create mode 100644 VCL/HID/DEMOS/CollectionDemo/Project1.dpr create mode 100644 VCL/HID/DEMOS/CollectionDemo/Project1.res create mode 100644 VCL/HID/DEMOS/CollectionDemo/Unit1.dcu create mode 100644 VCL/HID/DEMOS/CollectionDemo/Unit1.dfm create mode 100644 VCL/HID/DEMOS/CollectionDemo/Unit1.pas create mode 100644 VCL/HID/DEMOS/HidClassDemo/HidClassDemo.dof create mode 100644 VCL/HID/DEMOS/HidClassDemo/HidClassDemo.dpr create mode 100644 VCL/HID/DEMOS/HidClassDemo/HidClassDemo.res create mode 100644 VCL/HID/DEMOS/HidClassDemo/Unit1.dcu create mode 100644 VCL/HID/DEMOS/HidClassDemo/Unit1.dfm create mode 100644 VCL/HID/DEMOS/HidClassDemo/Unit1.pas create mode 100644 VCL/HID/DEMOS/ReadWriteDemo/SimpleHIDWrite.dof create mode 100644 VCL/HID/DEMOS/ReadWriteDemo/SimpleHIDWrite.dpr create mode 100644 VCL/HID/DEMOS/ReadWriteDemo/SimpleHIDWrite.res create mode 100644 VCL/HID/DEMOS/ReadWriteDemo/Unit1.dcu create mode 100644 VCL/HID/DEMOS/ReadWriteDemo/Unit1.dfm create mode 100644 VCL/HID/DEMOS/ReadWriteDemo/Unit1.pas create mode 100644 VCL/HID/DEMOS/ReadWriteDemo/Unit2.dcu create mode 100644 VCL/HID/DEMOS/ReadWriteDemo/Unit2.dfm create mode 100644 VCL/HID/DEMOS/ReadWriteDemo/Unit2.pas create mode 100644 VCL/HID/DEMOS/ThreadDemo/GreyMouser.dof create mode 100644 VCL/HID/DEMOS/ThreadDemo/GreyMouser.dpr create mode 100644 VCL/HID/DEMOS/ThreadDemo/GreyMouser.res create mode 100644 VCL/HID/DEMOS/ThreadDemo/MouseReader.dcu create mode 100644 VCL/HID/DEMOS/ThreadDemo/MouseReader.dfm create mode 100644 VCL/HID/DEMOS/ThreadDemo/MouseReader.pas create mode 100644 VCL/HID/Hid.dcu create mode 100644 VCL/HID/Hid.pas create mode 100644 VCL/HID/HidController.GID create mode 100644 VCL/HID/HidController.dcu create mode 100644 VCL/HID/HidController.dof create mode 100644 VCL/HID/HidController.dpk create mode 100644 VCL/HID/HidController.res create mode 100644 VCL/HID/HidControllerClass.dcr create mode 100644 VCL/HID/HidControllerClass.dcu create mode 100644 VCL/HID/HidControllerClass.pas create mode 100644 VCL/HID/HidControllerClass.~pas create mode 100644 VCL/HID/HidToken.pas create mode 100644 VCL/HID/HidUsage.pas create mode 100644 VCL/HID/README.TXT create mode 100644 VCL/HID/SetupApi.dcu create mode 100644 VCL/HID/SetupApi.pas create mode 100644 VCL/HID/help/BMP/empty.bmp create mode 100644 VCL/HID/help/BMP/published.bmp create mode 100644 VCL/HID/help/BMP/readonly.bmp create mode 100644 VCL/HID/help/BMP/usb.bmp create mode 100644 VCL/HID/help/HidController.GID create mode 100644 VCL/HID/help/HidController.hpj create mode 100644 VCL/HID/help/HidController.toc create mode 100644 VCL/HID/help/RTF/_#HID_Overview.RTF create mode 100644 VCL/HID/help/RTF/hidController.rtf create mode 100644 VCL/JLLabel.dcu create mode 100644 VCL/JLLabel.pas create mode 100644 VCL/JLlabel.dcr create mode 100644 VCL/JLlabel.dcr.res create mode 100644 VCL/MJWCRT.PAS create mode 100644 VCL/Mjwcrt.dcu create mode 100644 VCL/OEDIT.PAS create mode 100644 VCL/Oedit.dcu create mode 100644 VCL/PathDialog.dcu create mode 100644 VCL/PathDialog.pas create mode 100644 VCL/Rbutton.dcu create mode 100644 VCL/SoftButt.pas create mode 100644 VCL/Splitbar.dcu create mode 100644 VCL/Splitbar.pas create mode 100644 VCL/StrCGrid.dcr create mode 100644 VCL/StrCGrid.dcu create mode 100644 VCL/StrCGrid.pas create mode 100644 VCL/Strcgrid.txt create mode 100644 VCL/Super32.dcr create mode 100644 VCL/Super32.dcu create mode 100644 VCL/Super32.res create mode 100644 VCL/SuperCol.dcu create mode 100644 VCL/SuperGrd.dcu create mode 100644 VCL/SuperGrid.dcu create mode 100644 VCL/SuperGrid.dpl create mode 100644 VCL/THDTIM.PAS create mode 100644 VCL/TRAPEDIT.PAS create mode 100644 VCL/TToneGen.dcu create mode 100644 VCL/TToneGen.dof create mode 100644 VCL/TToneGen.dpk create mode 100644 VCL/TToneGen.res create mode 100644 VCL/TToneGen.~dpk create mode 100644 VCL/Thdtim.dcu create mode 100644 VCL/Thumbs.db create mode 100644 VCL/ToneGen.dcu create mode 100644 VCL/ToneGen.pas create mode 100644 VCL/Trapedit.dcu create mode 100644 VCL/Unit1.dcu create mode 100644 VCL/VNTI files/AND_Gate_152_GFPUV.gb create mode 100644 VCL/VNTI files/ApE_pLacthiM2lacZ.gb create mode 100644 VCL/VNTI files/CLC_pBADHisA.gb create mode 100644 VCL/VNTI files/Hashimoto-Goto et al 2000.pdf create mode 100644 VCL/VNTI files/Theophylline Aptamer for Riboswitch.gb create mode 100644 VCL/VNTI files/p+thiM#2lacZ.gb create mode 100644 VCL/VNTI files/pBADHisA.gb create mode 100644 VCL/VNTI files/pCIBT.gb create mode 100644 VCL/VNTI files/pDelEStheogfpuv2.1.gb create mode 100644 VCL/VNTI files/pE19T.gb create mode 100644 VCL/VNTI files/pEGFP-N1.gb create mode 100644 VCL/VNTI files/pINV-107bgfpuv.gb create mode 100644 VCL/VNTI files/pK-A-CIT1.gb create mode 100644 VCL/VNTI files/pK184.1.gb create mode 100644 VCL/VNTI files/pK184.3.gb create mode 100644 VCL/VNTI files/pK184.gb create mode 100644 VCL/VNTI files/pLac+thiM#2tetA (JACS).gb create mode 100644 VCL/VNTI files/pLac+thiM#2tetA.gb create mode 100644 VCL/VNTI files/pLacECR#48-LibAL1.gb create mode 100644 VCL/VNTI files/pLacECR#48-lacZ.gb create mode 100644 VCL/VNTI files/pLacECR#48-tetA-GS-GFP.gb create mode 100644 VCL/VNTI files/pLacECR48-GFP.gb create mode 100644 VCL/VNTI files/pLacN99mtetA.gb create mode 100644 VCL/VNTI files/pLacNH-H6.gb create mode 100644 VCL/VNTI files/pLacStrHNgfpuvX.gb create mode 100644 VCL/VNTI files/pLacT.gb create mode 100644 VCL/VNTI files/pLacT1.gb create mode 100644 VCL/VNTI files/pLacTheo28-N20+thiM2gfpuv.gb create mode 100644 VCL/VNTI files/pLacTheo28-N20+thiM2lacZ.gb create mode 100644 VCL/VNTI files/pLacTheo28-N20-thiMtetA-N30.gb create mode 100644 VCL/VNTI files/pLacTheo28thiMtetA.gb create mode 100644 VCL/VNTI files/pLactenA#59tetA-GS-GFP.gb create mode 100644 VCL/VNTI files/pLactenAtetA-GS-GFP-lib2(Archit).gb create mode 100644 VCL/VNTI files/pLactenAtetA.gb create mode 100644 VCL/VNTI files/pLactheo28bgl-lacZX.gb create mode 100644 VCL/VNTI files/pLacthiM2gfpuv.gb create mode 100644 VCL/VNTI files/pLacthiM2lacZ.gb create mode 100644 VCL/VNTI files/pLacthiM2tetA-GS-GFP.gb create mode 100644 VCL/VNTI files/pLacthiM2tetA.gb create mode 100644 VCL/VNTI files/pLacthiMN15#19gfpuv.gb create mode 100644 VCL/VNTI files/pLacthiMgfpuv-sp1+thiM81lacZ.gb create mode 100644 VCL/VNTI files/pLacthiMgfpuv.gb create mode 100644 VCL/VNTI files/pLacthiMlacZ-N30#2mutCCGG.gb create mode 100644 VCL/VNTI files/pLacthiMlacZ-N30#2mutTCGA.gb create mode 100644 VCL/VNTI files/pLacthiMlacZ-N30.gb create mode 100644 VCL/VNTI files/pLacthiMlacZ.gb create mode 100644 VCL/VNTI files/pLacthiMmcherry-N30#2.gb create mode 100644 VCL/VNTI files/pLacthiMtetA(BamHI-).gb create mode 100644 VCL/VNTI files/pLacthiMtetA.gb create mode 100644 VCL/VNTI files/pNAND10tetA.gb create mode 100644 VCL/VNTI files/pNAND1tetA.gb create mode 100644 VCL/VNTI files/pNMS1-29 gfp-NheI.gb create mode 100644 VCL/VNTI files/pNMS1-29.gb create mode 100644 VCL/VNTI files/pPantACIT1.gb create mode 100644 VCL/VNTI files/pRDV-1.4k-His6-mcherry.gb create mode 100644 VCL/VNTI files/pRDV-His6-mcherry(SD-).gb create mode 100644 VCL/VNTI files/pRDV-His6-mcherry.gb create mode 100644 VCL/VNTI files/pRDV-His6-tolAk.gb create mode 100644 VCL/VNTI files/pRDV-NanoTag15-mcherry(SD-).gb create mode 100644 VCL/VNTI files/pRDV-NanoTag15-mcherry.gb create mode 100644 VCL/VNTI files/pRDV-thiMN15#19-His6-mcherry.gb create mode 100644 VCL/VNTI files/pRDV-thiMN15#19-NanoTag15-mcherry.gb create mode 100644 VCL/VNTI files/pRDV-thiMN25SDN6-His6-mcherry.gb create mode 100644 VCL/VNTI files/pRDV.gb create mode 100644 VCL/VNTI files/pTH18XXA.gb create mode 100644 VCL/VNTI files/pTH18cr (AB019609).gb create mode 100644 VCL/VNTI files/pTH18kr.gb create mode 100644 VCL/VNTI files/pTenA gfpuv (1uM ON) #59.gb create mode 100644 VCL/VNTI files/pTenA gfpuv (XhoI-) (1uM ON) #59.gb create mode 100644 VCL/VNTI files/pWY1.gb create mode 100644 VCL/VNTI files/pWY2.gb create mode 100644 VCL/VNTI files/ptheogfpuv2.1.gb create mode 100644 VCL/VNTI files/pthiCgfp#19.gb create mode 100644 VCL/VNTI files/pthiCgfp#35.gb create mode 100644 VCL/VNTI files/pthiCgfpuv (XhoI-).gb create mode 100644 VCL/VNTI files/thiM riboswitch library.gb create mode 100644 VCL/WSockets/Examples/TCPClient.dpr create mode 100644 VCL/WSockets/Examples/TCPClientUnit.dcu create mode 100644 VCL/WSockets/Examples/TCPClientUnit.dfm create mode 100644 VCL/WSockets/Examples/TCPClientUnit.pas create mode 100644 VCL/WSockets/Examples/TCPServer.dpr create mode 100644 VCL/WSockets/Examples/TCPServerUnit.dfm create mode 100644 VCL/WSockets/Examples/TCPServerUnit.pas create mode 100644 VCL/WSockets/Examples/UDPClient.dpr create mode 100644 VCL/WSockets/Examples/UDPClientUnit.dfm create mode 100644 VCL/WSockets/Examples/UDPClientUnit.pas create mode 100644 VCL/WSockets/Examples/UDPServer.dpr create mode 100644 VCL/WSockets/Examples/UDPServerUnit.dfm create mode 100644 VCL/WSockets/Examples/UDPServerUnit.pas create mode 100644 VCL/WSockets/Examples/WSockets.dcu create mode 100644 VCL/WSockets/FILE_ID.DIZ create mode 100644 VCL/WSockets/Readme.txt create mode 100644 VCL/WSockets/WSockets.dcr create mode 100644 VCL/WSockets/WSockets.dcu create mode 100644 VCL/WSockets/WSockets.doc create mode 100644 VCL/WSockets/WSockets.pas create mode 100644 VCL/WTHREAD.DCR create mode 100644 VCL/WTHREAD.PAS create mode 100644 VCL/Wthread.dcu create mode 100644 VCL/addedcomp.dcp create mode 100644 VCL/addedcomp.dcu create mode 100644 VCL/addedcomp.dpk create mode 100644 VCL/addedcomp.dpl create mode 100644 VCL/addedcomp.res create mode 100644 VCL/addedcomp.~dp create mode 100644 VCL/aligrid21/AH_COMP.DPK create mode 100644 VCL/aligrid21/AH_DEF.INC create mode 100644 VCL/aligrid21/AH_TOOL.PAS create mode 100644 VCL/aligrid21/AH_TOOL.dcu create mode 100644 VCL/aligrid21/AH_TOOL.~PAS create mode 100644 VCL/aligrid21/ALIGREDI.DFM create mode 100644 VCL/aligrid21/ALIGREDI.PAS create mode 100644 VCL/aligrid21/ALIGREDI.dcu create mode 100644 VCL/aligrid21/ALIGRID.D16 create mode 100644 VCL/aligrid21/ALIGRID.PAS create mode 100644 VCL/aligrid21/ALIGRIDR.PAS create mode 100644 VCL/aligrid21/ALIGRIDR.dcu create mode 100644 VCL/aligrid21/D3/AH_COMP.DPK create mode 100644 VCL/aligrid21/D4/AH_COMP.DPK create mode 100644 VCL/aligrid21/D5/AH_COMP.DPK create mode 100644 VCL/aligrid21/ICONGRID.PAS create mode 100644 VCL/aligrid21/README.TXT create mode 100644 VCL/aligrid21/aligrid.dcu create mode 100644 VCL/async32.dcr create mode 100644 VCL/async32.dcu create mode 100644 VCL/async32.pas create mode 100644 VCL/async32.~pas create mode 100644 VCL/async32_x/Async32.doc create mode 100644 VCL/async32_x/CommInt.dcr create mode 100644 VCL/async32_x/CommInt.dcu create mode 100644 VCL/async32_x/CommInt.pas create mode 100644 VCL/async32_x/CommObjs.dcu create mode 100644 VCL/async32_x/CommObjs.pas create mode 100644 VCL/async32_x/CommReg.bpl create mode 100644 VCL/async32_x/CommReg.dcp create mode 100644 VCL/async32_x/CommReg.dcu create mode 100644 VCL/async32_x/CommReg.dof create mode 100644 VCL/async32_x/CommReg.dpk create mode 100644 VCL/async32_x/CommReg.res create mode 100644 VCL/async32_x/CommReg.~dpk create mode 100644 VCL/async32_x/Demo.dpr create mode 100644 VCL/async32_x/Demo.res create mode 100644 VCL/async32_x/Readme.txt create mode 100644 VCL/async32_x/Whatsnew.txt create mode 100644 VCL/async32_x/formMain.dcu create mode 100644 VCL/async32_x/formMain.dfm create mode 100644 VCL/async32_x/formMain.pas create mode 100644 VCL/asynctim.zip create mode 100644 VCL/audio.int create mode 100644 VCL/bpanel.dcu create mode 100644 VCL/bpanel.pas create mode 100644 VCL/bpreg.dcu create mode 100644 VCL/bpreg.pas create mode 100644 VCL/cdd4/CPDReg.dcu create mode 100644 VCL/cdd4/CPDReg.pas create mode 100644 VCL/cdd4/CPDrv.dcu create mode 100644 VCL/cdd4/CPDrv.pas create mode 100644 VCL/cdd4/ComDrv32.bpl create mode 100644 VCL/cdd4/ComDrv32.dcr create mode 100644 VCL/cdd4/ComDrv32.dcu create mode 100644 VCL/cdd4/ComDrv32.dpk create mode 100644 VCL/cdd4/ComDrv32.res create mode 100644 VCL/cdd4/Demos/TTY/AboutTTY.dcu create mode 100644 VCL/cdd4/Demos/TTY/AboutTTY.dfm create mode 100644 VCL/cdd4/Demos/TTY/AboutTTY.pas create mode 100644 VCL/cdd4/Demos/TTY/MnForm.dfm create mode 100644 VCL/cdd4/Demos/TTY/MnForm.pas create mode 100644 VCL/cdd4/Demos/TTY/MnForm.~dfm create mode 100644 VCL/cdd4/Demos/TTY/MnForm.~pas create mode 100644 VCL/cdd4/Demos/TTY/Res/About.bmp create mode 100644 VCL/cdd4/Demos/TTY/Res/Connect.bmp create mode 100644 VCL/cdd4/Demos/TTY/Res/Disconnect.bmp create mode 100644 VCL/cdd4/Demos/TTY/Res/Quit.bmp create mode 100644 VCL/cdd4/Demos/TTY/Res/Settings.bmp create mode 100644 VCL/cdd4/Demos/TTY/Res/TTYDemo.bmp create mode 100644 VCL/cdd4/Demos/TTY/SettingsDlg.dcu create mode 100644 VCL/cdd4/Demos/TTY/SettingsDlg.dfm create mode 100644 VCL/cdd4/Demos/TTY/SettingsDlg.pas create mode 100644 VCL/cdd4/Demos/TTY/TTY.dof create mode 100644 VCL/cdd4/Demos/TTY/TTY.dpr create mode 100644 VCL/cdd4/Demos/TTY/TTY.res create mode 100644 VCL/cdd4/Help/ComDrv32.GID create mode 100644 VCL/cdd4/Help/ComDrv32.toc create mode 100644 VCL/cdd4/OpenMe.bpg create mode 100644 VCL/cologrid/Cologrid.dcu create mode 100644 VCL/cologrid/Cologrid.pas create mode 100644 VCL/cologrid/Cologrid.~pa create mode 100644 VCL/cologrid/P2.DPR create mode 100644 VCL/cologrid/P2.OPT create mode 100644 VCL/cologrid/README.TXT create mode 100644 VCL/cologrid/U3.DFM create mode 100644 VCL/cologrid/U3.PAS create mode 100644 VCL/comm32.zip create mode 100644 VCL/consol.zip create mode 100644 VCL/console1.zip create mode 100644 VCL/console2.dcu create mode 100644 VCL/console2.pas create mode 100644 VCL/console2.~pa create mode 100644 VCL/console2.~pas create mode 100644 VCL/d2_qa.zip create mode 100644 VCL/date/CalPop97.dcu create mode 100644 VCL/date/CalPop97.dfm create mode 100644 VCL/date/CalPop97.pas create mode 100644 VCL/date/DATEED97.RC create mode 100644 VCL/date/DEd97_b.res create mode 100644 VCL/date/DateDB97.dcu create mode 100644 VCL/date/DateDB97.pas create mode 100644 VCL/date/DateEd97.dcu create mode 100644 VCL/date/DateEd97.pas create mode 100644 VCL/date/DateEd97.res create mode 100644 VCL/date/DateFT97.dcu create mode 100644 VCL/date/DateFT97.pas create mode 100644 VCL/date/DatePk97.txt create mode 100644 VCL/date/DateRg97.dcr create mode 100644 VCL/date/DateRg97.dcu create mode 100644 VCL/date/DateRg97.pas create mode 100644 VCL/graph/AABGRAPH.DCR create mode 100644 VCL/graph/AABGRAPH.DOC create mode 100644 VCL/graph/AABGRAPH.PAS create mode 100644 VCL/graph/AABGRAPH.TXT create mode 100644 VCL/graph/Aabgraph.dcu create mode 100644 VCL/graph/DEMO/TEST.DPR create mode 100644 VCL/graph/DEMO/TEST.RES create mode 100644 VCL/graph/DEMO/TEST1.DFM create mode 100644 VCL/graph/DEMO/TEST1.PAS create mode 100644 VCL/graph/DEMO/TEST1.dcu create mode 100644 VCL/hemi/HEMIBTN.DCR create mode 100644 VCL/hemi/HemiBtn.pas create mode 100644 VCL/hemi/Hemibtn.dcu create mode 100644 VCL/hemi/Project1.dpr create mode 100644 VCL/hemi/Project2.dpr create mode 100644 VCL/hemi/Unit1.dcu create mode 100644 VCL/hemi/Unit2.dfm create mode 100644 VCL/hemi/Unit2.pas create mode 100644 VCL/hemi/pHemibtn.dcp create mode 100644 VCL/hemi/pHemibtn.dcu create mode 100644 VCL/hemi/pHemibtn.dpk create mode 100644 VCL/hemi/pHemibtn.dpl create mode 100644 VCL/hemi/pHemibtn.res create mode 100644 VCL/hemi/pHemibtn.~dp create mode 100644 VCL/hemi/unit1.dfm create mode 100644 VCL/hemi/unit1.pas create mode 100644 VCL/ics/Bcb1/DelBcb1.mak create mode 100644 VCL/ics/Bcb1/IcsBcb1.bat create mode 100644 VCL/ics/Bcb1/IcsBcb1.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/CliDemo.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/CliDemo.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Clidemo.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Client5.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Client5.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Client5.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Client7.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Client7.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Client7.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/ConCli1.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/ConCli1.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/ConCli2.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/ConCli2.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Finger.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Finger.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Finger.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/FtpServ.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/FtpServ.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/FtpServ.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/HttpPg.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/HttpPg.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/HttpPg.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/MailSnd.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/MailSnd.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/MailSnd.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/MtSrv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/MtSrv.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/MtSrv.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/NewsRdr.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/NewsRdr.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/NewsRdr.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/PingTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/PingTst.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/PingTst.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Recv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Recv.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Recv.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Sender.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Sender.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Sender.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Server5.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Server5.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Server5.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/SocksTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/SocksTst.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Sockstst.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/SrvDemo.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/SrvDemo.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Srvdemo.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/TWSChat.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/TWSChat.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/TcpSrv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/TcpSrv.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/Tcpsrv.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/TnDemo.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/TnDemo.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/TnDemo.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/TnSrv.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/UdpLstn.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/UdpLstn.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/clients.DBF create mode 100644 VCL/ics/Cpp/Internet/Bcb1/clients.MDX create mode 100644 VCL/ics/Cpp/Internet/Bcb1/ftptst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/ftptst.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/ftptst.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/httptst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/httptst.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/httptst.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/poptst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/poptst.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/tnclient.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/tnclient.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/tnclient.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/tnsrv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/tnsrv.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/twschat.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/udplstn.res create mode 100644 VCL/ics/Cpp/Internet/Bcb1/udpsend.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb1/udpsend.mak create mode 100644 VCL/ics/Cpp/Internet/Bcb1/udpsend.res create mode 100644 VCL/ics/Cpp/Internet/Bcb3/Bcb30Sam.bpg create mode 100644 VCL/ics/Cpp/Internet/Bcb3/CliDemo.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/CliDemo.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/Client5.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/Client5.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/Client7.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/Client7.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/ConCli1.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/ConCli1.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/ConCli2.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/ConCli2.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/Finger.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/Finger.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/FtpServ.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/FtpServ.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/HttpPg.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/HttpPg.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/MailRcv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/MailRcv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/MailSnd.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/MailSnd.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/MtSrv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/MtSrv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/NewsRdr.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/NewsRdr.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/NsLookup.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/NsLookup.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/PingTst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/PingTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/Recv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/Recv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/Sender.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/Sender.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/Server5.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/Server5.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/SocksTst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/SocksTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/SrvDemo.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/SrvDemo.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/TWSChat.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/TWSChat.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/TcpSrv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/TcpSrv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/TnClient.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/TnClient.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/TnDemo.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/TnDemo.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/UdpLstn.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/UdpLstn.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/UdpSend.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/UdpSend.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/clients.DBF create mode 100644 VCL/ics/Cpp/Internet/Bcb3/clients.MDX create mode 100644 VCL/ics/Cpp/Internet/Bcb3/ftptst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/ftptst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/httptst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/httptst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/poptst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/poptst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb3/tnsrv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb3/tnsrv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Bcb40Sam.bpg create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Clidemo.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Clidemo.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Client5.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Client5.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Client7.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Client7.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Concli1.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Concli1.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Concli2.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Concli2.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Finger.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Finger.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/FtpTst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/FtpTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Ftpserv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Ftpserv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/HttpPg.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/HttpPg.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/HttpTst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/HttpTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/MailRcv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/MailRcv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/MailSnd.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/MailSnd.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/MtSrv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/MtSrv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/NewsRdr.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/NewsRdr.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/NsLookup.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/NsLookup.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/PingTst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/PingTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/PopTst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/PopTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Recv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Recv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Sender.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Sender.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Server5.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/Server5.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/SocksTst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/SocksTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/SrvDemo.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/SrvDemo.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/TWSChat.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/TWSChat.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/TcpSrv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/TcpSrv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/TnClient.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/TnClient.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/TnDemo.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/TnDemo.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/TnSrv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/TnSrv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/UdpLstn.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/UdpLstn.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/UdpSend.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb4/UdpSend.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb4/clients.DBF create mode 100644 VCL/ics/Cpp/Internet/Bcb4/clients.MDX create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Bcb50Sam.bpg create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Clidemo.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Clidemo.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Client5.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Client5.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Client7.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Client7.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Concli1.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Concli1.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Concli2.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Concli2.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/DllTst1.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/DllTst1.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Finger.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Finger.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/FtpTst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/FtpTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Ftpserv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Ftpserv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/HttpPg.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/HttpPg.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/HttpTst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/HttpTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/IcsDll1.bpf create mode 100644 VCL/ics/Cpp/Internet/Bcb5/IcsDll1.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/IcsDll1.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/MailRcv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/MailRcv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/MailSnd.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/MailSnd.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/MtSrv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/MtSrv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/NewsRdr.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/NewsRdr.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/NsLookup.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/NsLookup.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/PingTst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/PingTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/PopTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Recv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Recv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Sender.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Sender.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Server5.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/Server5.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/SocksTst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/SocksTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/SrvDemo.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/SrvDemo.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/TWSChat.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/TWSChat.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/TcpSrv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/TcpSrv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/TnClient.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/TnClient.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/TnDemo.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/TnDemo.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/TnSrv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/TnSrv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/UdpLstn.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/UdpLstn.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/UdpSend.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/UdpSend.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/WebServ.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb5/WebServ.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb5/clients.DBF create mode 100644 VCL/ics/Cpp/Internet/Bcb5/clients.MDX create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Bcb60Sam.bpg create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Clidemo.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Clidemo.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Client5.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Client5.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Client7.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Client7.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/ConCli1.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/ConCli2.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/ConCli2.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Concli1.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/DllTst1.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/DllTst1.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Finger.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Finger.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/FtpServ.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/FtpTst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/FtpTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Ftpserv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/HttpPg.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/HttpPg.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/HttpTst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/HttpTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/IcsDll1.bpf create mode 100644 VCL/ics/Cpp/Internet/Bcb6/IcsDll1.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/IcsDll1.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/MailRcv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/MailRcv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/MailSnd.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/MailSnd.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/MtSrv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/MtSrv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/NewsRdr.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/NewsRdr.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/NsLookup.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/NsLookup.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/PingTst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/PingTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Recv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Recv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Sender.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Sender.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Server5.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/Server5.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/SocksTst.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/SocksTst.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/SrvDemo.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/SrvDemo.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/TWSChat.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/TWSChat.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/TcpSrv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/TcpSrv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/TnClient.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/TnClient.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/TnDemo.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/TnDemo.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/TnSrv.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/TnSrv.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/UdpLstn.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/UdpLstn.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/UdpSend.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/UdpSend.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/WebServ.bpr create mode 100644 VCL/ics/Cpp/Internet/Bcb6/WebServ.cpp create mode 100644 VCL/ics/Cpp/Internet/Bcb6/clients.DBF create mode 100644 VCL/ics/Cpp/Internet/Bcb6/clients.MDX create mode 100644 VCL/ics/Cpp/Internet/Cli7.cpp create mode 100644 VCL/ics/Cpp/Internet/Cli7.dfm create mode 100644 VCL/ics/Cpp/Internet/Cli7.h create mode 100644 VCL/ics/Cpp/Internet/CliDemo1.cpp create mode 100644 VCL/ics/Cpp/Internet/CliDemo1.dfm create mode 100644 VCL/ics/Cpp/Internet/CliDemo1.h create mode 100644 VCL/ics/Cpp/Internet/DllTst1.cpp create mode 100644 VCL/ics/Cpp/Internet/DllTst1.dfm create mode 100644 VCL/ics/Cpp/Internet/DllTst1.h create mode 100644 VCL/ics/Cpp/Internet/FtpSrv1.cpp create mode 100644 VCL/ics/Cpp/Internet/FtpSrv1.dfm create mode 100644 VCL/ics/Cpp/Internet/FtpSrv1.h create mode 100644 VCL/ics/Cpp/Internet/MailRcv1.cpp create mode 100644 VCL/ics/Cpp/Internet/MailRcv1.dfm create mode 100644 VCL/ics/Cpp/Internet/MailRcv1.h create mode 100644 VCL/ics/Cpp/Internet/MailRcv2.cpp create mode 100644 VCL/ics/Cpp/Internet/MailRcv2.dfm create mode 100644 VCL/ics/Cpp/Internet/MailRcv2.h create mode 100644 VCL/ics/Cpp/Internet/MailSnd1.cpp create mode 100644 VCL/ics/Cpp/Internet/MailSnd1.dfm create mode 100644 VCL/ics/Cpp/Internet/MailSnd1.h create mode 100644 VCL/ics/Cpp/Internet/NsLook1.cpp create mode 100644 VCL/ics/Cpp/Internet/NsLook1.dfm create mode 100644 VCL/ics/Cpp/Internet/NsLook1.h create mode 100644 VCL/ics/Cpp/Internet/Poptst1.cpp create mode 100644 VCL/ics/Cpp/Internet/Recv1.cpp create mode 100644 VCL/ics/Cpp/Internet/Recv1.dfm create mode 100644 VCL/ics/Cpp/Internet/Recv1.h create mode 100644 VCL/ics/Cpp/Internet/Sender1.cpp create mode 100644 VCL/ics/Cpp/Internet/Sender1.dfm create mode 100644 VCL/ics/Cpp/Internet/Sender1.h create mode 100644 VCL/ics/Cpp/Internet/Socks1.cpp create mode 100644 VCL/ics/Cpp/Internet/Socks1.dfm create mode 100644 VCL/ics/Cpp/Internet/Socks1.h create mode 100644 VCL/ics/Cpp/Internet/SrvDemo1.cpp create mode 100644 VCL/ics/Cpp/Internet/SrvDemo1.dfm create mode 100644 VCL/ics/Cpp/Internet/SrvDemo1.h create mode 100644 VCL/ics/Cpp/Internet/SrvDemo2.cpp create mode 100644 VCL/ics/Cpp/Internet/SrvDemo2.dfm create mode 100644 VCL/ics/Cpp/Internet/SrvDemo2.h create mode 100644 VCL/ics/Cpp/Internet/TcpSrv1.cpp create mode 100644 VCL/ics/Cpp/Internet/TcpSrv1.dfm create mode 100644 VCL/ics/Cpp/Internet/TcpSrv1.h create mode 100644 VCL/ics/Cpp/Internet/WebServ1.cpp create mode 100644 VCL/ics/Cpp/Internet/WebServ1.dfm create mode 100644 VCL/ics/Cpp/Internet/WebServ1.h create mode 100644 VCL/ics/Cpp/Internet/cli5.cpp create mode 100644 VCL/ics/Cpp/Internet/cli5.dfm create mode 100644 VCL/ics/Cpp/Internet/cli5.h create mode 100644 VCL/ics/Cpp/Internet/finger1.cpp create mode 100644 VCL/ics/Cpp/Internet/finger1.dfm create mode 100644 VCL/ics/Cpp/Internet/finger1.h create mode 100644 VCL/ics/Cpp/Internet/formpos.cpp create mode 100644 VCL/ics/Cpp/Internet/formpos.h create mode 100644 VCL/ics/Cpp/Internet/ftptst1.cpp create mode 100644 VCL/ics/Cpp/Internet/ftptst1.dfm create mode 100644 VCL/ics/Cpp/Internet/ftptst1.h create mode 100644 VCL/ics/Cpp/Internet/ftptst2.cpp create mode 100644 VCL/ics/Cpp/Internet/ftptst2.dfm create mode 100644 VCL/ics/Cpp/Internet/ftptst2.h create mode 100644 VCL/ics/Cpp/Internet/httppg1.cpp create mode 100644 VCL/ics/Cpp/Internet/httppg1.dfm create mode 100644 VCL/ics/Cpp/Internet/httppg1.h create mode 100644 VCL/ics/Cpp/Internet/httptst1.cpp create mode 100644 VCL/ics/Cpp/Internet/httptst1.dfm create mode 100644 VCL/ics/Cpp/Internet/httptst1.h create mode 100644 VCL/ics/Cpp/Internet/mtsrv1.cpp create mode 100644 VCL/ics/Cpp/Internet/mtsrv1.dfm create mode 100644 VCL/ics/Cpp/Internet/mtsrv1.h create mode 100644 VCL/ics/Cpp/Internet/mtsrv2.cpp create mode 100644 VCL/ics/Cpp/Internet/mtsrv2.h create mode 100644 VCL/ics/Cpp/Internet/newsrdr1.cpp create mode 100644 VCL/ics/Cpp/Internet/newsrdr1.dfm create mode 100644 VCL/ics/Cpp/Internet/newsrdr1.h create mode 100644 VCL/ics/Cpp/Internet/pingtst1.cpp create mode 100644 VCL/ics/Cpp/Internet/pingtst1.dfm create mode 100644 VCL/ics/Cpp/Internet/pingtst1.h create mode 100644 VCL/ics/Cpp/Internet/poptst1.dfm create mode 100644 VCL/ics/Cpp/Internet/poptst1.h create mode 100644 VCL/ics/Cpp/Internet/srv5.cpp create mode 100644 VCL/ics/Cpp/Internet/srv5.dfm create mode 100644 VCL/ics/Cpp/Internet/srv5.h create mode 100644 VCL/ics/Cpp/Internet/tncli1.cpp create mode 100644 VCL/ics/Cpp/Internet/tncli1.dfm create mode 100644 VCL/ics/Cpp/Internet/tncli1.h create mode 100644 VCL/ics/Cpp/Internet/tndemo1.cpp create mode 100644 VCL/ics/Cpp/Internet/tndemo1.dfm create mode 100644 VCL/ics/Cpp/Internet/tndemo1.h create mode 100644 VCL/ics/Cpp/Internet/tnsrv1.cpp create mode 100644 VCL/ics/Cpp/Internet/tnsrv1.dfm create mode 100644 VCL/ics/Cpp/Internet/tnsrv1.h create mode 100644 VCL/ics/Cpp/Internet/tnsrv2.cpp create mode 100644 VCL/ics/Cpp/Internet/tnsrv2.dfm create mode 100644 VCL/ics/Cpp/Internet/tnsrv2.h create mode 100644 VCL/ics/Cpp/Internet/twschat1.cpp create mode 100644 VCL/ics/Cpp/Internet/twschat1.dfm create mode 100644 VCL/ics/Cpp/Internet/twschat1.h create mode 100644 VCL/ics/Cpp/Internet/udplstn1.cpp create mode 100644 VCL/ics/Cpp/Internet/udplstn1.dfm create mode 100644 VCL/ics/Cpp/Internet/udplstn1.h create mode 100644 VCL/ics/Cpp/Internet/udpsend1.cpp create mode 100644 VCL/ics/Cpp/Internet/udpsend1.dfm create mode 100644 VCL/ics/Cpp/Internet/udpsend1.h create mode 100644 VCL/ics/Delphi/Internet/Cli7.dfm create mode 100644 VCL/ics/Delphi/Internet/Cli7.pas create mode 100644 VCL/ics/Delphi/Internet/CliDemo1.dfm create mode 100644 VCL/ics/Delphi/Internet/CliDemo1.pas create mode 100644 VCL/ics/Delphi/Internet/Client7.dpr create mode 100644 VCL/ics/Delphi/Internet/ConFtp.dpr create mode 100644 VCL/ics/Delphi/Internet/ConHttp.dpr create mode 100644 VCL/ics/Delphi/Internet/ConSmtp.dpr create mode 100644 VCL/ics/Delphi/Internet/ConSrv1.dpr create mode 100644 VCL/ics/Delphi/Internet/ConSrv1C.pas create mode 100644 VCL/ics/Delphi/Internet/ConSrv1S.pas create mode 100644 VCL/ics/Delphi/Internet/Del40Sam.bpg create mode 100644 VCL/ics/Delphi/Internet/Del50Sam.bpg create mode 100644 VCL/ics/Delphi/Internet/Del60Sam.bpg create mode 100644 VCL/ics/Delphi/Internet/Del70Sam.bpg create mode 100644 VCL/ics/Delphi/Internet/DllTst1.dpr create mode 100644 VCL/ics/Delphi/Internet/DllTst_1.dfm create mode 100644 VCL/ics/Delphi/Internet/DllTst_1.pas create mode 100644 VCL/ics/Delphi/Internet/DnsLook1.dfm create mode 100644 VCL/ics/Delphi/Internet/DnsLook1.pas create mode 100644 VCL/ics/Delphi/Internet/DynCli.dpr create mode 100644 VCL/ics/Delphi/Internet/DynCli1.dfm create mode 100644 VCL/ics/Delphi/Internet/DynCli1.pas create mode 100644 VCL/ics/Delphi/Internet/FTPTST2.dfm create mode 100644 VCL/ics/Delphi/Internet/FtpServ1.dfm create mode 100644 VCL/ics/Delphi/Internet/FtpServ1.pas create mode 100644 VCL/ics/Delphi/Internet/FtpThrd1.dfm create mode 100644 VCL/ics/Delphi/Internet/FtpThrd1.pas create mode 100644 VCL/ics/Delphi/Internet/Ftptst2.pas create mode 100644 VCL/ics/Delphi/Internet/HLembke/NsLook1.dfm create mode 100644 VCL/ics/Delphi/Internet/HLembke/NsLook1.pas create mode 100644 VCL/ics/Delphi/Internet/HLembke/NsLookup.dpr create mode 100644 VCL/ics/Delphi/Internet/HLembke/ReadMe.txt create mode 100644 VCL/ics/Delphi/Internet/HLembke/dnsquery.pas create mode 100644 VCL/ics/Delphi/Internet/HttpAsp1.dfm create mode 100644 VCL/ics/Delphi/Internet/HttpAsp1.pas create mode 100644 VCL/ics/Delphi/Internet/HttpAsy1.dfm create mode 100644 VCL/ics/Delphi/Internet/HttpAsy1.pas create mode 100644 VCL/ics/Delphi/Internet/HttpChk1.dfm create mode 100644 VCL/ics/Delphi/Internet/HttpChk1.pas create mode 100644 VCL/ics/Delphi/Internet/HttpDmo1.dfm create mode 100644 VCL/ics/Delphi/Internet/HttpDmo1.pas create mode 100644 VCL/ics/Delphi/Internet/HttpGet1.dfm create mode 100644 VCL/ics/Delphi/Internet/HttpGet1.pas create mode 100644 VCL/ics/Delphi/Internet/HttpPg1.dfm create mode 100644 VCL/ics/Delphi/Internet/HttpPg1.pas create mode 100644 VCL/ics/Delphi/Internet/HttpThr1.dfm create mode 100644 VCL/ics/Delphi/Internet/HttpThr1.pas create mode 100644 VCL/ics/Delphi/Internet/HttpThr2.pas create mode 100644 VCL/ics/Delphi/Internet/Httpdmo.dpr create mode 100644 VCL/ics/Delphi/Internet/Ics.ico create mode 100644 VCL/ics/Delphi/Internet/IcsDll1.dpr create mode 100644 VCL/ics/Delphi/Internet/IcsIsap1.dfm create mode 100644 VCL/ics/Delphi/Internet/IcsIsap1.pas create mode 100644 VCL/ics/Delphi/Internet/IcsIsapi.dpr create mode 100644 VCL/ics/Delphi/Internet/MailRcv.dpr create mode 100644 VCL/ics/Delphi/Internet/MailRcv1.dfm create mode 100644 VCL/ics/Delphi/Internet/MailRcv1.pas create mode 100644 VCL/ics/Delphi/Internet/MailRcv2.dfm create mode 100644 VCL/ics/Delphi/Internet/MailRcv2.pas create mode 100644 VCL/ics/Delphi/Internet/MailRob.dpr create mode 100644 VCL/ics/Delphi/Internet/MailRob1.dfm create mode 100644 VCL/ics/Delphi/Internet/MailRob1.pas create mode 100644 VCL/ics/Delphi/Internet/MailSnd.dpr create mode 100644 VCL/ics/Delphi/Internet/MailSnd1.dfm create mode 100644 VCL/ics/Delphi/Internet/MailSnd1.pas create mode 100644 VCL/ics/Delphi/Internet/MbxSub.dpr create mode 100644 VCL/ics/Delphi/Internet/MbxSub1.dfm create mode 100644 VCL/ics/Delphi/Internet/MbxSub1.pas create mode 100644 VCL/ics/Delphi/Internet/MimeDemo.dpr create mode 100644 VCL/ics/Delphi/Internet/MimeDmo1.dfm create mode 100644 VCL/ics/Delphi/Internet/MimeDmo1.pas create mode 100644 VCL/ics/Delphi/Internet/MimeTst.dpr create mode 100644 VCL/ics/Delphi/Internet/MimeTst1.dfm create mode 100644 VCL/ics/Delphi/Internet/MimeTst1.pas create mode 100644 VCL/ics/Delphi/Internet/NewsRdr1.dfm create mode 100644 VCL/ics/Delphi/Internet/NewsRdr1.pas create mode 100644 VCL/ics/Delphi/Internet/NsLook1.dfm create mode 100644 VCL/ics/Delphi/Internet/NsLook1.pas create mode 100644 VCL/ics/Delphi/Internet/NsLookup.dpr create mode 100644 VCL/ics/Delphi/Internet/POP3MIM1.dfm create mode 100644 VCL/ics/Delphi/Internet/PingTst1.dfm create mode 100644 VCL/ics/Delphi/Internet/PingTst1.pas create mode 100644 VCL/ics/Delphi/Internet/Pop3Mim1.pas create mode 100644 VCL/ics/Delphi/Internet/Pop3Mime.dpr create mode 100644 VCL/ics/Delphi/Internet/PopTst1.dfm create mode 100644 VCL/ics/Delphi/Internet/PopTst1.pas create mode 100644 VCL/ics/Delphi/Internet/Recv.dpr create mode 100644 VCL/ics/Delphi/Internet/Recv1.dfm create mode 100644 VCL/ics/Delphi/Internet/Recv1.pas create mode 100644 VCL/ics/Delphi/Internet/Sender.dpr create mode 100644 VCL/ics/Delphi/Internet/Sender1.dfm create mode 100644 VCL/ics/Delphi/Internet/Sender1.pas create mode 100644 VCL/ics/Delphi/Internet/Socks1.dfm create mode 100644 VCL/ics/Delphi/Internet/Socks1.pas create mode 100644 VCL/ics/Delphi/Internet/SocksTst.dpr create mode 100644 VCL/ics/Delphi/Internet/SrvDemo1.dfm create mode 100644 VCL/ics/Delphi/Internet/SrvDemo1.pas create mode 100644 VCL/ics/Delphi/Internet/SrvDemo2.dfm create mode 100644 VCL/ics/Delphi/Internet/SrvDemo2.pas create mode 100644 VCL/ics/Delphi/Internet/SrvTcp.dpr create mode 100644 VCL/ics/Delphi/Internet/SrvTcp1.dfm create mode 100644 VCL/ics/Delphi/Internet/SrvTcp1.pas create mode 100644 VCL/ics/Delphi/Internet/SvcTcp.dpr create mode 100644 VCL/ics/Delphi/Internet/SvcTcp1.dfm create mode 100644 VCL/ics/Delphi/Internet/SvcTcp1.pas create mode 100644 VCL/ics/Delphi/Internet/TcpCmd.pas create mode 100644 VCL/ics/Delphi/Internet/TcpSrv.dpr create mode 100644 VCL/ics/Delphi/Internet/TcpSrv1.dfm create mode 100644 VCL/ics/Delphi/Internet/TcpSrv1.pas create mode 100644 VCL/ics/Delphi/Internet/ThrdSrv.dpr create mode 100644 VCL/ics/Delphi/Internet/ThrdSrv1.dfm create mode 100644 VCL/ics/Delphi/Internet/ThrdSrv1.pas create mode 100644 VCL/ics/Delphi/Internet/TnCli1.dfm create mode 100644 VCL/ics/Delphi/Internet/TnCli1.pas create mode 100644 VCL/ics/Delphi/Internet/UdpLstn1.dfm create mode 100644 VCL/ics/Delphi/Internet/UdpLstn1.pas create mode 100644 VCL/ics/Delphi/Internet/UdpSend1.dfm create mode 100644 VCL/ics/Delphi/Internet/UdpSend1.pas create mode 100644 VCL/ics/Delphi/Internet/WebServ.dpr create mode 100644 VCL/ics/Delphi/Internet/WebServ1.dfm create mode 100644 VCL/ics/Delphi/Internet/WebServ1.pas create mode 100644 VCL/ics/Delphi/Internet/cli5.dfm create mode 100644 VCL/ics/Delphi/Internet/cli5.pas create mode 100644 VCL/ics/Delphi/Internet/clidemo.dpr create mode 100644 VCL/ics/Delphi/Internet/client5.dpr create mode 100644 VCL/ics/Delphi/Internet/clients.DBF create mode 100644 VCL/ics/Delphi/Internet/clients.MDX create mode 100644 VCL/ics/Delphi/Internet/concli1.dpr create mode 100644 VCL/ics/Delphi/Internet/concli2.dpr create mode 100644 VCL/ics/Delphi/Internet/dnslook.dpr create mode 100644 VCL/ics/Delphi/Internet/finger.dpr create mode 100644 VCL/ics/Delphi/Internet/finger1.dfm create mode 100644 VCL/ics/Delphi/Internet/finger1.pas create mode 100644 VCL/ics/Delphi/Internet/ftpServ.dpr create mode 100644 VCL/ics/Delphi/Internet/ftpcli.ico create mode 100644 VCL/ics/Delphi/Internet/ftpthrd.dpr create mode 100644 VCL/ics/Delphi/Internet/ftptst.dpr create mode 100644 VCL/ics/Delphi/Internet/ftptst1.dfm create mode 100644 VCL/ics/Delphi/Internet/ftptst1.pas create mode 100644 VCL/ics/Delphi/Internet/httpChk.dpr create mode 100644 VCL/ics/Delphi/Internet/httpasp.dpr create mode 100644 VCL/ics/Delphi/Internet/httpasy.dpr create mode 100644 VCL/ics/Delphi/Internet/httpget.dpr create mode 100644 VCL/ics/Delphi/Internet/httppg.dpr create mode 100644 VCL/ics/Delphi/Internet/httpthrd.dpr create mode 100644 VCL/ics/Delphi/Internet/httptst.dpr create mode 100644 VCL/ics/Delphi/Internet/httptst1.dfm create mode 100644 VCL/ics/Delphi/Internet/httptst1.pas create mode 100644 VCL/ics/Delphi/Internet/md5test.dpr create mode 100644 VCL/ics/Delphi/Internet/md5test1.dfm create mode 100644 VCL/ics/Delphi/Internet/md5test1.pas create mode 100644 VCL/ics/Delphi/Internet/mtsrv.dpr create mode 100644 VCL/ics/Delphi/Internet/mtsrv.ico create mode 100644 VCL/ics/Delphi/Internet/mtsrv.res create mode 100644 VCL/ics/Delphi/Internet/mtsrv1.dfm create mode 100644 VCL/ics/Delphi/Internet/mtsrv1.pas create mode 100644 VCL/ics/Delphi/Internet/mtsrv2.pas create mode 100644 VCL/ics/Delphi/Internet/newsrdr.dpr create mode 100644 VCL/ics/Delphi/Internet/pingtst.dpr create mode 100644 VCL/ics/Delphi/Internet/poptst.dpr create mode 100644 VCL/ics/Delphi/Internet/poptst2.dfm create mode 100644 VCL/ics/Delphi/Internet/poptst2.pas create mode 100644 VCL/ics/Delphi/Internet/server5.dpr create mode 100644 VCL/ics/Delphi/Internet/srv5.dfm create mode 100644 VCL/ics/Delphi/Internet/srv5.pas create mode 100644 VCL/ics/Delphi/Internet/srvdemo.dpr create mode 100644 VCL/ics/Delphi/Internet/tnclient.dpr create mode 100644 VCL/ics/Delphi/Internet/tnclient.ico create mode 100644 VCL/ics/Delphi/Internet/tndemo.dpr create mode 100644 VCL/ics/Delphi/Internet/tndemo1.dfm create mode 100644 VCL/ics/Delphi/Internet/tndemo1.pas create mode 100644 VCL/ics/Delphi/Internet/tnsrv.dpr create mode 100644 VCL/ics/Delphi/Internet/tnsrv.ico create mode 100644 VCL/ics/Delphi/Internet/tnsrv1.dfm create mode 100644 VCL/ics/Delphi/Internet/tnsrv1.pas create mode 100644 VCL/ics/Delphi/Internet/tnsrv2.dfm create mode 100644 VCL/ics/Delphi/Internet/tnsrv2.pas create mode 100644 VCL/ics/Delphi/Internet/twschat.dpr create mode 100644 VCL/ics/Delphi/Internet/twschat1.dfm create mode 100644 VCL/ics/Delphi/Internet/twschat1.pas create mode 100644 VCL/ics/Delphi/Internet/udplstn.dpr create mode 100644 VCL/ics/Delphi/Internet/udpsend.dpr create mode 100644 VCL/ics/Delphi/Vc/DnsQuery.dcr create mode 100644 VCL/ics/Delphi/Vc/FtpSrv.dcr create mode 100644 VCL/ics/Delphi/Vc/Pop3Prot.dcr create mode 100644 VCL/ics/Delphi/Vc/SmtpProt.dcr create mode 100644 VCL/ics/Delphi/Vc/TNSCRIPT.DCR create mode 100644 VCL/ics/Delphi/Vc/WINSOCK.PAS create mode 100644 VCL/ics/Delphi/Vc/emulvt.dcr create mode 100644 VCL/ics/Delphi/Vc/fingcli.dcr create mode 100644 VCL/ics/Delphi/Vc/ftpcli.dcr create mode 100644 VCL/ics/Delphi/Vc/httpprot.dcr create mode 100644 VCL/ics/Delphi/Vc/httpsrv.dcr create mode 100644 VCL/ics/Delphi/Vc/mbxfile.dcr create mode 100644 VCL/ics/Delphi/Vc/mimedec.dcr create mode 100644 VCL/ics/Delphi/Vc/nntpcli.dcr create mode 100644 VCL/ics/Delphi/Vc/tncnx.dcr create mode 100644 VCL/ics/Delphi/Vc/tnemulvt.dcr create mode 100644 VCL/ics/Delphi/Vc/wait.dcr create mode 100644 VCL/ics/Delphi/Vc/wsocket.dcr create mode 100644 VCL/ics/Delphi/Vc/wsockets.dcr create mode 100644 VCL/ics/Delphi/Vc32/DnsQuery.dcr create mode 100644 VCL/ics/Delphi/Vc32/DnsQuery.dcu create mode 100644 VCL/ics/Delphi/Vc32/DnsQuery.pas create mode 100644 VCL/ics/Delphi/Vc32/FingCli.dcu create mode 100644 VCL/ics/Delphi/Vc32/FingCli.pas create mode 100644 VCL/ics/Delphi/Vc32/FtpCli.dcu create mode 100644 VCL/ics/Delphi/Vc32/FtpCli.pas create mode 100644 VCL/ics/Delphi/Vc32/FtpSrv.dcu create mode 100644 VCL/ics/Delphi/Vc32/FtpSrv.pas create mode 100644 VCL/ics/Delphi/Vc32/FtpSrvC.dcu create mode 100644 VCL/ics/Delphi/Vc32/FtpSrvC.pas create mode 100644 VCL/ics/Delphi/Vc32/FtpSrvT.dcu create mode 100644 VCL/ics/Delphi/Vc32/FtpSrvT.pas create mode 100644 VCL/ics/Delphi/Vc32/HttpProt.dcu create mode 100644 VCL/ics/Delphi/Vc32/HttpProt.pas create mode 100644 VCL/ics/Delphi/Vc32/HttpSrv.dcr create mode 100644 VCL/ics/Delphi/Vc32/HttpSrv.dcu create mode 100644 VCL/ics/Delphi/Vc32/HttpSrv.pas create mode 100644 VCL/ics/Delphi/Vc32/IcsBcb30.bpk create mode 100644 VCL/ics/Delphi/Vc32/IcsBcb30.cpp create mode 100644 VCL/ics/Delphi/Vc32/IcsBcb30.res create mode 100644 VCL/ics/Delphi/Vc32/IcsBcb50.bpk create mode 100644 VCL/ics/Delphi/Vc32/IcsBcb50.cpp create mode 100644 VCL/ics/Delphi/Vc32/IcsBcb50.res create mode 100644 VCL/ics/Delphi/Vc32/IcsBcb60.bpk create mode 100644 VCL/ics/Delphi/Vc32/IcsBcb60.cpp create mode 100644 VCL/ics/Delphi/Vc32/IcsBcb60.res create mode 100644 VCL/ics/Delphi/Vc32/IcsDel30.dpk create mode 100644 VCL/ics/Delphi/Vc32/IcsDel40.dpk create mode 100644 VCL/ics/Delphi/Vc32/IcsDel40.res create mode 100644 VCL/ics/Delphi/Vc32/IcsDel50.dpk create mode 100644 VCL/ics/Delphi/Vc32/IcsDel50.res create mode 100644 VCL/ics/Delphi/Vc32/IcsDel60.dcu create mode 100644 VCL/ics/Delphi/Vc32/IcsDel60.dof create mode 100644 VCL/ics/Delphi/Vc32/IcsDel60.dpk create mode 100644 VCL/ics/Delphi/Vc32/IcsDel60.res create mode 100644 VCL/ics/Delphi/Vc32/IcsDel70.dof create mode 100644 VCL/ics/Delphi/Vc32/IcsDel70.dpk create mode 100644 VCL/ics/Delphi/Vc32/IcsDel70.res create mode 100644 VCL/ics/Delphi/Vc32/Icsbcb40.bpk create mode 100644 VCL/ics/Delphi/Vc32/Icsbcb40.cpp create mode 100644 VCL/ics/Delphi/Vc32/Icsbcb40.res create mode 100644 VCL/ics/Delphi/Vc32/Icsdel30.res create mode 100644 VCL/ics/Delphi/Vc32/MD5.dcu create mode 100644 VCL/ics/Delphi/Vc32/MD5.pas create mode 100644 VCL/ics/Delphi/Vc32/MbxFile.dcr create mode 100644 VCL/ics/Delphi/Vc32/MbxFile.dcu create mode 100644 VCL/ics/Delphi/Vc32/MbxFile.pas create mode 100644 VCL/ics/Delphi/Vc32/NntpCli.dcu create mode 100644 VCL/ics/Delphi/Vc32/NntpCli.pas create mode 100644 VCL/ics/Delphi/Vc32/POP3CLI.DCR create mode 100644 VCL/ics/Delphi/Vc32/Pop3Prot.dcr create mode 100644 VCL/ics/Delphi/Vc32/Pop3Prot.dcu create mode 100644 VCL/ics/Delphi/Vc32/Pop3Prot.pas create mode 100644 VCL/ics/Delphi/Vc32/Pop3cli.pas create mode 100644 VCL/ics/Delphi/Vc32/SmtpProt.dcr create mode 100644 VCL/ics/Delphi/Vc32/SmtpProt.dcu create mode 100644 VCL/ics/Delphi/Vc32/SmtpProt.pas create mode 100644 VCL/ics/Delphi/Vc32/TNCNX.HLP create mode 100644 VCL/ics/Delphi/Vc32/TnCnx.dcu create mode 100644 VCL/ics/Delphi/Vc32/TnCnx.pas create mode 100644 VCL/ics/Delphi/Vc32/TnEmulVT.dcu create mode 100644 VCL/ics/Delphi/Vc32/TnEmulVT.pas create mode 100644 VCL/ics/Delphi/Vc32/TnOptFrm.dcu create mode 100644 VCL/ics/Delphi/Vc32/TnOptFrm.dfm create mode 100644 VCL/ics/Delphi/Vc32/TnOptFrm.pas create mode 100644 VCL/ics/Delphi/Vc32/UUEncode.pas create mode 100644 VCL/ics/Delphi/Vc32/WSOCKET.GID create mode 100644 VCL/ics/Delphi/Vc32/WSOCKET.HLP create mode 100644 VCL/ics/Delphi/Vc32/WSocket.dcu create mode 100644 VCL/ics/Delphi/Vc32/WSocket.pas create mode 100644 VCL/ics/Delphi/Vc32/WSocketE.pas create mode 100644 VCL/ics/Delphi/Vc32/WSocketS.dcr create mode 100644 VCL/ics/Delphi/Vc32/WSocketS.dcu create mode 100644 VCL/ics/Delphi/Vc32/WSocketS.pas create mode 100644 VCL/ics/Delphi/Vc32/emulvt.dcr create mode 100644 VCL/ics/Delphi/Vc32/emulvt.dcu create mode 100644 VCL/ics/Delphi/Vc32/emulvt.pas create mode 100644 VCL/ics/Delphi/Vc32/fingcli.dcr create mode 100644 VCL/ics/Delphi/Vc32/formpos.dcu create mode 100644 VCL/ics/Delphi/Vc32/formpos.pas create mode 100644 VCL/ics/Delphi/Vc32/ftpcli.dcr create mode 100644 VCL/ics/Delphi/Vc32/ftpsrv.dcr create mode 100644 VCL/ics/Delphi/Vc32/httpprot.dcr create mode 100644 VCL/ics/Delphi/Vc32/icmp.dcu create mode 100644 VCL/ics/Delphi/Vc32/icmp.pas create mode 100644 VCL/ics/Delphi/Vc32/mimedec.dcr create mode 100644 VCL/ics/Delphi/Vc32/mimedec.dcu create mode 100644 VCL/ics/Delphi/Vc32/mimedec.pas create mode 100644 VCL/ics/Delphi/Vc32/nntpcli.dcr create mode 100644 VCL/ics/Delphi/Vc32/ping.dcr create mode 100644 VCL/ics/Delphi/Vc32/ping.dcu create mode 100644 VCL/ics/Delphi/Vc32/ping.pas create mode 100644 VCL/ics/Delphi/Vc32/tncnx.dcr create mode 100644 VCL/ics/Delphi/Vc32/tnemulvt.dcr create mode 100644 VCL/ics/Delphi/Vc32/tnscript.dcr create mode 100644 VCL/ics/Delphi/Vc32/tnscript.dcu create mode 100644 VCL/ics/Delphi/Vc32/tnscript.pas create mode 100644 VCL/ics/Delphi/Vc32/wait.dcr create mode 100644 VCL/ics/Delphi/Vc32/wait.dcu create mode 100644 VCL/ics/Delphi/Vc32/wait.pas create mode 100644 VCL/ics/Delphi/Vc32/wsockbuf.dcu create mode 100644 VCL/ics/Delphi/Vc32/wsockbuf.pas create mode 100644 VCL/ics/Delphi/Vc32/wsocket.dcr create mode 100644 VCL/ics/Delphi/Vc32/wsocket.ico create mode 100644 VCL/ics/Delphi1/IcsDel1.bat create mode 100644 VCL/ics/Delphi1/dcc1.bat create mode 100644 VCL/ics/Delphi2/Dcc2.bat create mode 100644 VCL/ics/Delphi2/Icsdel2.bat create mode 100644 VCL/ics/Delphi3/Dcc3.bat create mode 100644 VCL/ics/Delphi3/Icsdel3.bat create mode 100644 VCL/ics/Ics.diz create mode 100644 VCL/ics/ics7spec.zip create mode 100644 VCL/ics/ics_logo.gif create mode 100644 VCL/ics/powered_by_ics.gif create mode 100644 VCL/ics/readme.txt create mode 100644 VCL/ics/zipics.bat create mode 100644 VCL/ics/zipics7.lst create mode 100644 VCL/ics/zipicsb.lst create mode 100644 VCL/ics/zipicsd.lst create mode 100644 VCL/ini_mw/Ini.dcu create mode 100644 VCL/ini_mw/Ini.pas create mode 100644 VCL/ini_mw/Ini.~pa create mode 100644 VCL/midicom3/CIRCBUF.PAS create mode 100644 VCL/midicom3/DELPHMCB.PAS create mode 100644 VCL/midicom3/MIDICOMP.DPK create mode 100644 VCL/midicom3/MIDICOMP.DPL create mode 100644 VCL/midicom3/MIDICONS.PAS create mode 100644 VCL/midicom3/MIDIDEFS.PAS create mode 100644 VCL/midicom3/MIDIIN.DCR create mode 100644 VCL/midicom3/MIDIIN.PAS create mode 100644 VCL/midicom3/MIDIMON.DPR create mode 100644 VCL/midicom3/MIDIMON.RES create mode 100644 VCL/midicom3/MIDIMONP.DFM create mode 100644 VCL/midicom3/MIDIMONP.PAS create mode 100644 VCL/midicom3/MIDIOUT.DCR create mode 100644 VCL/midicom3/MIDIOUT.PAS create mode 100644 VCL/midicom3/MIDITYPE.PAS create mode 100644 VCL/midicom3/MONPROCS.PAS create mode 100644 VCL/midicom3/MULTIMNP.DFM create mode 100644 VCL/midicom3/MULTIMNP.PAS create mode 100644 VCL/midicom3/MULTIMON.DPR create mode 100644 VCL/midicom3/MULTIMON.RES create mode 100644 VCL/midicom3/README.TXT create mode 100644 VCL/midicomp/circbuf.pas create mode 100644 VCL/midicomp/delphmcb.dfm create mode 100644 VCL/midicomp/delphmcb.pas create mode 100644 VCL/midicomp/delphmid.dpr create mode 100644 VCL/midicomp/delphmid.opt create mode 100644 VCL/midicomp/delphmid.res create mode 100644 VCL/midicomp/midiin.pas create mode 100644 VCL/midicomp/midiin.res create mode 100644 VCL/midicomp/midimon.dpr create mode 100644 VCL/midicomp/midimon.opt create mode 100644 VCL/midicomp/midimon.res create mode 100644 VCL/midicomp/midimonp.dfm create mode 100644 VCL/midicomp/midimonp.pas create mode 100644 VCL/midicomp/midiout.pas create mode 100644 VCL/midicomp/monprocs.pas create mode 100644 VCL/midicomp/multimnp.dfm create mode 100644 VCL/midicomp/multimnp.pas create mode 100644 VCL/midicomp/multimon.dpr create mode 100644 VCL/midicomp/multimon.opt create mode 100644 VCL/midicomp/multimon.res create mode 100644 VCL/midicomp/readme.txt create mode 100644 VCL/mynewpack.dcp create mode 100644 VCL/mynewpack.dcu create mode 100644 VCL/mynewpack.dpk create mode 100644 VCL/mynewpack.dpl create mode 100644 VCL/mynewpack.res create mode 100644 VCL/mynewpack.~dp create mode 100644 VCL/nfigrid/GridWizard.dcu create mode 100644 VCL/nfigrid/GridWizard.dfm create mode 100644 VCL/nfigrid/NFIGrid.dcu create mode 100644 VCL/nfigrid/Sample.zip create mode 100644 VCL/nfigrid/Sample/NFITest.dof create mode 100644 VCL/nfigrid/Sample/NFITest.dpr create mode 100644 VCL/nfigrid/Sample/NFITest.res create mode 100644 VCL/nfigrid/Sample/NFIunit1.dcu create mode 100644 VCL/nfigrid/Sample/NFIunit1.dfm create mode 100644 VCL/nfigrid/Sample/NFIunit1.pas create mode 100644 VCL/nfigrid/Sample/NFIunit1.~df create mode 100644 VCL/nfigrid/Sample/NFIunit1.~pa create mode 100644 VCL/nfigrid/nfigrid.upl create mode 100644 VCL/nkprn/NkPrinters.dcu create mode 100644 VCL/nkprn/NkPrinters.pas create mode 100644 VCL/nkprn/NkPrn.GID create mode 100644 VCL/nkprn/demo/Demo.dpr create mode 100644 VCL/nkprn/demo/Demo.res create mode 100644 VCL/nkprn/demo/DemoForm1.dcu create mode 100644 VCL/nkprn/demo/DemoForm1.dfm create mode 100644 VCL/nkprn/demo/DemoForm1.pas create mode 100644 VCL/nkprn/demo/DemoForm2.dcu create mode 100644 VCL/nkprn/demo/DemoForm2.dfm create mode 100644 VCL/nkprn/demo/DemoForm2.pas create mode 100644 VCL/nkprn/demo/DemoForm3.dcu create mode 100644 VCL/nkprn/demo/DemoForm3.dfm create mode 100644 VCL/nkprn/demo/DemoForm3.pas create mode 100644 VCL/nkprn/demo/Shun06.bmp create mode 100644 VCL/nkprn/mypack.dcp create mode 100644 VCL/nkprn/mypack.dcu create mode 100644 VCL/nkprn/mypack.dpk create mode 100644 VCL/nkprn/mypack.dpl create mode 100644 VCL/nkprn/mypack.res create mode 100644 VCL/nkprn/mypack.~dp create mode 100644 VCL/nkprn/readme.txt create mode 100644 VCL/rbutton.pas create mode 100644 VCL/sock/Base64/Test.dfm create mode 100644 VCL/sock/Base64/Test.pas create mode 100644 VCL/sock/Base64/Test64.dpr create mode 100644 VCL/sock/Base64/Test64.res create mode 100644 VCL/sock/PROXY/IP.DFM create mode 100644 VCL/sock/PROXY/IP.PAS create mode 100644 VCL/sock/PROXY/PROXY.RES create mode 100644 VCL/sock/PROXY/main.dfm create mode 100644 VCL/sock/PROXY/main.pas create mode 100644 VCL/sock/PROXY/proxy.dpr create mode 100644 VCL/sock/README.TXT create mode 100644 VCL/sock/SOCK.DCR create mode 100644 VCL/sock/SOCK.HTM create mode 100644 VCL/sock/SOCK.JPG create mode 100644 VCL/sock/SOCK.RES create mode 100644 VCL/sock/SOCKTEST/Main.dcu create mode 100644 VCL/sock/SOCKTEST/Main.dfm create mode 100644 VCL/sock/SOCKTEST/Main.pas create mode 100644 VCL/sock/SOCKTEST/SOCKTEST.RES create mode 100644 VCL/sock/SOCKTEST/SockTest.dpr create mode 100644 VCL/sock/SRVTEST/SRVTEST.RES create mode 100644 VCL/sock/SRVTEST/Srvtest.dpr create mode 100644 VCL/sock/SRVTEST/srvr.dfm create mode 100644 VCL/sock/SRVTEST/srvr.pas create mode 100644 VCL/sock/Sock.dcu create mode 100644 VCL/sock/Sock.pas create mode 100644 VCL/sock/UDPTest/UDPTester.dpr create mode 100644 VCL/sock/UDPTest/UDPTester.res create mode 100644 VCL/sock/UDPTest/Unit1.dfm create mode 100644 VCL/sock/UDPTest/Unit1.pas create mode 100644 VCL/supergrid/RZTBAR32.RES create mode 100644 VCL/supergrid/RzCommon.dcu create mode 100644 VCL/supergrid/RzTrkBar.dcu create mode 100644 VCL/supergrid/SUPER.GID create mode 100644 VCL/supergrid/SUPER.KWF create mode 100644 VCL/supergrid/SUPER14.TXT create mode 100644 VCL/supergrid/SUPERBUG.TXT create mode 100644 VCL/supergrid/Super32.dcr create mode 100644 VCL/supergrid/Super32.dcu create mode 100644 VCL/supergrid/Super32.res create mode 100644 VCL/supergrid/SuperCol.dcu create mode 100644 VCL/supergrid/SuperDlg.dcu create mode 100644 VCL/supergrid/SuperDlg.dfm create mode 100644 VCL/supergrid/SuperGrd.dcu create mode 100644 VCL/supergrid/SuperGrid.dcp create mode 100644 VCL/supergrid/SuperGrid.dcu create mode 100644 VCL/supergrid/SuperGrid.dpl create mode 100644 VCL/supergrid/SuperGrid.res create mode 100644 VCL/supergrid/colorpik.dcu create mode 100644 VCL/supertmr.zip create mode 100644 VCL/telnet/CLI5.DFM create mode 100644 VCL/telnet/CLI5.PAS create mode 100644 VCL/telnet/CLIDEMO.DPR create mode 100644 VCL/telnet/CLIDEMO1.DFM create mode 100644 VCL/telnet/CLIDEMO1.PAS create mode 100644 VCL/telnet/CLIENT5.DPR create mode 100644 VCL/telnet/CLIENTS.DBF create mode 100644 VCL/telnet/CLIENTS.MDX create mode 100644 VCL/telnet/CONCLI1.DPR create mode 100644 VCL/telnet/CONCLI2.DPR create mode 100644 VCL/telnet/DNSLOOK.DPR create mode 100644 VCL/telnet/DNSLOOK1.DFM create mode 100644 VCL/telnet/DNSLOOK1.PAS create mode 100644 VCL/telnet/EMULVT.DCR create mode 100644 VCL/telnet/EMULVT.PAS create mode 100644 VCL/telnet/EmulVT.dcu create mode 100644 VCL/telnet/FINGCLI.DCR create mode 100644 VCL/telnet/FINGCLI.PAS create mode 100644 VCL/telnet/FINGER.DPR create mode 100644 VCL/telnet/FINGER1.DFM create mode 100644 VCL/telnet/FINGER1.PAS create mode 100644 VCL/telnet/FORMPOS.PAS create mode 100644 VCL/telnet/FPiette2.dcp create mode 100644 VCL/telnet/FPiette2.dcu create mode 100644 VCL/telnet/FPiette2.dpl create mode 100644 VCL/telnet/FTPCLI.DCR create mode 100644 VCL/telnet/FTPCLI.PAS create mode 100644 VCL/telnet/FTPTST.DPR create mode 100644 VCL/telnet/FTPTST1.DFM create mode 100644 VCL/telnet/FTPTST1.PAS create mode 100644 VCL/telnet/FTPTST2.DFM create mode 100644 VCL/telnet/FTPTST2.PAS create mode 100644 VCL/telnet/FormPos.dcu create mode 100644 VCL/telnet/HTTPPG.DPR create mode 100644 VCL/telnet/HTTPPG1.DFM create mode 100644 VCL/telnet/HTTPPG1.PAS create mode 100644 VCL/telnet/HTTPPROT.DCR create mode 100644 VCL/telnet/HTTPPROT.PAS create mode 100644 VCL/telnet/HTTPTST.DPR create mode 100644 VCL/telnet/HTTPTST1.DFM create mode 100644 VCL/telnet/HTTPTST1.PAS create mode 100644 VCL/telnet/ICMP.PAS create mode 100644 VCL/telnet/MD5.PAS create mode 100644 VCL/telnet/MTSRV.DPR create mode 100644 VCL/telnet/MTSRV.RES create mode 100644 VCL/telnet/MTSRV.dof create mode 100644 VCL/telnet/MTSRV.~DP create mode 100644 VCL/telnet/PING.DCR create mode 100644 VCL/telnet/PING.PAS create mode 100644 VCL/telnet/PINGTST.DPR create mode 100644 VCL/telnet/PINGTST1.DFM create mode 100644 VCL/telnet/PINGTST1.PAS create mode 100644 VCL/telnet/POP3CLI.DCR create mode 100644 VCL/telnet/POP3CLI.PAS create mode 100644 VCL/telnet/POPTST.DPR create mode 100644 VCL/telnet/POPTST1.DFM create mode 100644 VCL/telnet/POPTST1.PAS create mode 100644 VCL/telnet/POPTST2.DFM create mode 100644 VCL/telnet/POPTST2.PAS create mode 100644 VCL/telnet/SERVER5.DPR create mode 100644 VCL/telnet/SMTPCLI.DCR create mode 100644 VCL/telnet/SMTPCLI.PAS create mode 100644 VCL/telnet/SMTPTST.DPR create mode 100644 VCL/telnet/SMTPTST1.DFM create mode 100644 VCL/telnet/SMTPTST1.PAS create mode 100644 VCL/telnet/SRV5.DFM create mode 100644 VCL/telnet/SRV5.PAS create mode 100644 VCL/telnet/SRVDEMO.DPR create mode 100644 VCL/telnet/SRVDEMO1.DFM create mode 100644 VCL/telnet/SRVDEMO1.PAS create mode 100644 VCL/telnet/SRVDEMO2.DFM create mode 100644 VCL/telnet/SRVDEMO2.PAS create mode 100644 VCL/telnet/TNCLI1.DFM create mode 100644 VCL/telnet/TNCLI1.PAS create mode 100644 VCL/telnet/TNCLIENT.DPR create mode 100644 VCL/telnet/TNCNX.DCR create mode 100644 VCL/telnet/TNCNX.GID create mode 100644 VCL/telnet/TNDEMO.DPR create mode 100644 VCL/telnet/TNDEMO1.DFM create mode 100644 VCL/telnet/TNDEMO1.PAS create mode 100644 VCL/telnet/TNEMULVT.DCR create mode 100644 VCL/telnet/TNEMULVT.PAS create mode 100644 VCL/telnet/TNOPTFRM.DFM create mode 100644 VCL/telnet/TNOPTFRM.PAS create mode 100644 VCL/telnet/TNSRV.DPR create mode 100644 VCL/telnet/TNSRV1.DFM create mode 100644 VCL/telnet/TNSRV1.PAS create mode 100644 VCL/telnet/TNSRV2.DFM create mode 100644 VCL/telnet/TNSRV2.PAS create mode 100644 VCL/telnet/TWSCHAT.DPR create mode 100644 VCL/telnet/TWSCHAT1.DFM create mode 100644 VCL/telnet/TWSCHAT1.PAS create mode 100644 VCL/telnet/TnCnx.pas create mode 100644 VCL/telnet/TnCnx.~pa create mode 100644 VCL/telnet/TnOptFrm.dcu create mode 100644 VCL/telnet/Tncnx.dcu create mode 100644 VCL/telnet/UDPLSTN.DPR create mode 100644 VCL/telnet/UDPLSTN1.DFM create mode 100644 VCL/telnet/UDPLSTN1.PAS create mode 100644 VCL/telnet/UDPSEND.DPR create mode 100644 VCL/telnet/UDPSEND1.DFM create mode 100644 VCL/telnet/UDPSEND1.PAS create mode 100644 VCL/telnet/WAIT.DCR create mode 100644 VCL/telnet/WAIT.PAS create mode 100644 VCL/telnet/WSOCKBUF.PAS create mode 100644 VCL/telnet/WSOCKET.DCR create mode 100644 VCL/telnet/WSOCKET.GID create mode 100644 VCL/telnet/WSOCKET.PAS create mode 100644 VCL/telnet/WSockBuf.dcu create mode 100644 VCL/telnet/Wait.dcu create mode 100644 VCL/telnet/Wsocket.dcu create mode 100644 VCL/telnet/mtsrv1.dfm create mode 100644 VCL/telnet/mtsrv1.pas create mode 100644 VCL/telnet/mtsrv1.~df create mode 100644 VCL/telnet/mtsrv1.~pa create mode 100644 VCL/telnet/mtsrv2.pas create mode 100644 VCL/telnet/mtsrv2.~pa create mode 100644 VCL/telnet/tncnx2.pas create mode 100644 VCL/telnet/winsock.dcp create mode 100644 VCL/telnet/winsock.dcu create mode 100644 VCL/telnet/winsock.dpk create mode 100644 VCL/telnet/winsock.dpl create mode 100644 VCL/telnet/winsock.res create mode 100644 VCL/thdtim.zip create mode 100644 VCL/timer32.zip create mode 100644 VCL/timer32/HIRESTIM.DCR create mode 100644 VCL/timer32/HIRESTIM.PAS create mode 100644 VCL/timer32/Hirestim.dcu create mode 100644 VCL/tsrich/TRECODE.DCR create mode 100644 VCL/tsrich/TRECODE.PAS create mode 100644 VCL/tsrich/TRECODE.RES create mode 100644 VCL/tsrich/TRECODE.TXT create mode 100644 VCL/tsrich/Trecode.dcu create mode 100644 VCL/tvicres/DELPHI3/MAIN.DFM create mode 100644 VCL/tvicres/DELPHI3/MAIN.PAS create mode 100644 VCL/tvicres/DELPHI3/Main.dcu create mode 100644 VCL/tvicres/DELPHI3/TEST_RES.DPR create mode 100644 VCL/tvicres/DELPHI3/VIC_RES.DCU create mode 100644 VCL/tvicres/DELPHI4/MAIN.DFM create mode 100644 VCL/tvicres/DELPHI4/MAIN.PAS create mode 100644 VCL/tvicres/DELPHI4/TEST_RES.DPR create mode 100644 VCL/tvicres/DELPHI4/VIC_RES.DCU create mode 100644 VCL/tvicres/FILE_ID.DIZ create mode 100644 VCL/tvicres/LICENSE.TXT create mode 100644 VCL/tvicres/ORDER.TXT create mode 100644 VCL/tvicres/README.TXT create mode 100644 VCL/tvicres/VENDOR.TXT create mode 100644 VCL/vsscm32/MISC.PAS create mode 100644 VCL/vsscm32/Misc.dcu create mode 100644 VCL/vsscm32/Readme.txt create mode 100644 VCL/vsscm32/VSSComm32.dcr create mode 100644 VCL/vsscm32/VSSComm32.dcu create mode 100644 VCL/vsscm32/VSSComm32.pas create mode 100644 VCL/vsscm32/vsscmdemo.dof create mode 100644 VCL/vsscm32/vsscmdemo.dpr create mode 100644 VCL/vsscm32/vsscmdemo.res create mode 100644 VCL/vsscm32/vsscomdemo.dcu create mode 100644 VCL/vsscm32/vsscomdemo.dfm create mode 100644 VCL/vsscm32/vsscomdemo.pas create mode 100644 VCL/vsscm32/vsscomm32.res create mode 100644 VCL/wsagraph/EXAMPLE.TXT create mode 100644 VCL/wsagraph/Wsagraph.dcu create mode 100644 VCL/wsagraph/Wsagraph.pas create mode 100644 VCL/wsagraph/Wsagraph.~pa create mode 100644 VCL/z_timer/Z_TIMER.TXT create mode 100644 VCL/z_timer/Z_timer.dcr create mode 100644 VCL/z_timer/Z_timer.dcu create mode 100644 VCL/z_timer/Z_timer.pas delete mode 100644 omnirig.zip create mode 100644 omnirig/Chartfx3.dcu create mode 100644 omnirig/OmniRig_TLB.dcr create mode 100644 omnirig/OmniRig_TLB.dcu create mode 100644 omnirig/OmniRig_TLB.pas create mode 100644 omnirig/VCF1.dcu create mode 100644 omnirig/VCFI.dcu create mode 100644 omnirig/VCSpell3.dcu delete mode 100644 zlogsource2.zip create mode 100644 zlogsource2/BGK32Lib.pas create mode 100644 zlogsource2/BGK32Lib2.pas create mode 100644 zlogsource2/Project1.dpr create mode 100644 zlogsource2/TScratchSheet.dfm create mode 100644 zlogsource2/TScratchSheet.pas create mode 100644 zlogsource2/UACAGMulti.dfm create mode 100644 zlogsource2/UACAGMulti.pas create mode 100644 zlogsource2/UACAGScore.dfm create mode 100644 zlogsource2/UACAGScore.pas create mode 100644 zlogsource2/UALLJAEditDialog.dfm create mode 100644 zlogsource2/UALLJAEditDialog.pas create mode 100644 zlogsource2/UALLJAMulti.dfm create mode 100644 zlogsource2/UALLJAMulti.pas create mode 100644 zlogsource2/UALLJAScore.dfm create mode 100644 zlogsource2/UALLJAScore.pas create mode 100644 zlogsource2/UALLJAScore1.dfm create mode 100644 zlogsource2/UALLJAScore1.pas create mode 100644 zlogsource2/UAPSprintScore.dfm create mode 100644 zlogsource2/UAPSprintScore.pas create mode 100644 zlogsource2/UARRL10Multi.dfm create mode 100644 zlogsource2/UARRL10Multi.pas create mode 100644 zlogsource2/UARRL10Score.dfm create mode 100644 zlogsource2/UARRL10Score.pas create mode 100644 zlogsource2/UARRLDXMulti.dfm create mode 100644 zlogsource2/UARRLDXMulti.pas create mode 100644 zlogsource2/UARRLDXScore.dfm create mode 100644 zlogsource2/UARRLDXScore.pas create mode 100644 zlogsource2/UARRLWMulti.dfm create mode 100644 zlogsource2/UARRLWMulti.pas create mode 100644 zlogsource2/UAbout.dfm create mode 100644 zlogsource2/UAbout.pas create mode 100644 zlogsource2/UAgeDialog.dfm create mode 100644 zlogsource2/UAgeDialog.pas create mode 100644 zlogsource2/UAllAsianScore.dfm create mode 100644 zlogsource2/UAllAsianScore.pas create mode 100644 zlogsource2/UBGKMonitorThread.pas create mode 100644 zlogsource2/UBandScope2.dfm create mode 100644 zlogsource2/UBandScope2.pas create mode 100644 zlogsource2/UBasicMulti.dfm create mode 100644 zlogsource2/UBasicMulti.pas create mode 100644 zlogsource2/UBasicScore.dfm create mode 100644 zlogsource2/UBasicScore.pas create mode 100644 zlogsource2/UCWForm.dfm create mode 100644 zlogsource2/UCWForm.pas create mode 100644 zlogsource2/UCWKeyBoard.dfm create mode 100644 zlogsource2/UCWKeyBoard.pas create mode 100644 zlogsource2/UChat.dfm create mode 100644 zlogsource2/UChat.pas create mode 100644 zlogsource2/UCheckCall%.dfm create mode 100644 zlogsource2/UCheckCall%.pas create mode 100644 zlogsource2/UCheckCall2.dfm create mode 100644 zlogsource2/UCheckCall2.pas create mode 100644 zlogsource2/UCheckCountry.dfm create mode 100644 zlogsource2/UCheckCountry.pas create mode 100644 zlogsource2/UCheckMulti.dfm create mode 100644 zlogsource2/UCheckMulti.pas create mode 100644 zlogsource2/UCheckWin.dfm create mode 100644 zlogsource2/UCheckWin.pas create mode 100644 zlogsource2/UCluster.dfm create mode 100644 zlogsource2/UCluster.pas create mode 100644 zlogsource2/UClusterCOMSet.dfm create mode 100644 zlogsource2/UClusterCOMSet.pas create mode 100644 zlogsource2/UClusterTelnetSet.dfm create mode 100644 zlogsource2/UClusterTelnetSet.pas create mode 100644 zlogsource2/UComm.dfm create mode 100644 zlogsource2/UComm.pas create mode 100644 zlogsource2/UConsolePad.dfm create mode 100644 zlogsource2/UConsolePad.pas create mode 100644 zlogsource2/UELogJapanese.dfm create mode 100644 zlogsource2/UELogJapanese.pas create mode 100644 zlogsource2/UEditDialog.dfm create mode 100644 zlogsource2/UEditDialog.pas create mode 100644 zlogsource2/UFDMulti.dfm create mode 100644 zlogsource2/UFDMulti.pas create mode 100644 zlogsource2/UFreqList.dfm create mode 100644 zlogsource2/UFreqList.pas create mode 100644 zlogsource2/UGeneralMulti.dfm create mode 100644 zlogsource2/UGeneralMulti.pas create mode 100644 zlogsource2/UGeneralMulti2.dfm create mode 100644 zlogsource2/UGeneralMulti2.pas create mode 100644 zlogsource2/UGeneralScore.dfm create mode 100644 zlogsource2/UGeneralScore.pas create mode 100644 zlogsource2/UIARUMulti.dfm create mode 100644 zlogsource2/UIARUMulti.pas create mode 100644 zlogsource2/UIARUScore.dfm create mode 100644 zlogsource2/UIARUScore.pas create mode 100644 zlogsource2/UIOTACategory.dfm create mode 100644 zlogsource2/UIOTACategory.pas create mode 100644 zlogsource2/UIOTAMulti.dfm create mode 100644 zlogsource2/UIOTAMulti.pas create mode 100644 zlogsource2/UIntegerDialog.dfm create mode 100644 zlogsource2/UIntegerDialog.pas create mode 100644 zlogsource2/UJA0Multi.dfm create mode 100644 zlogsource2/UJA0Multi.pas create mode 100644 zlogsource2/UJA0Score.dfm create mode 100644 zlogsource2/UJA0Score.pas create mode 100644 zlogsource2/UJIDXMulti.dfm create mode 100644 zlogsource2/UJIDXMulti.pas create mode 100644 zlogsource2/UJIDXScore.dfm create mode 100644 zlogsource2/UJIDXScore.pas create mode 100644 zlogsource2/UJIDXScore2.dfm create mode 100644 zlogsource2/UJIDXScore2.pas create mode 100644 zlogsource2/UJIDX_DX_Multi.dfm create mode 100644 zlogsource2/UJIDX_DX_Multi.pas create mode 100644 zlogsource2/UJIDX_DX_Score.dfm create mode 100644 zlogsource2/UJIDX_DX_Score.pas create mode 100644 zlogsource2/UKCJMulti.dfm create mode 100644 zlogsource2/UKCJMulti.pas create mode 100644 zlogsource2/UKCJScore.dfm create mode 100644 zlogsource2/UKCJScore.pas create mode 100644 zlogsource2/UKCJZone.dfm create mode 100644 zlogsource2/UKCJZone.pas create mode 100644 zlogsource2/UMMTTY.pas create mode 100644 zlogsource2/UMenu.dfm create mode 100644 zlogsource2/UMenu.pas create mode 100644 zlogsource2/UMinMaxFreqDlg.dfm create mode 100644 zlogsource2/UMinMaxFreqDlg.pas create mode 100644 zlogsource2/UMultipliers.pas create mode 100644 zlogsource2/UNewIOTARef.dfm create mode 100644 zlogsource2/UNewIOTARef.pas create mode 100644 zlogsource2/UNewPrefix.dfm create mode 100644 zlogsource2/UNewPrefix.pas create mode 100644 zlogsource2/UOptions.dfm create mode 100644 zlogsource2/UOptions.pas create mode 100644 zlogsource2/UPartials.dfm create mode 100644 zlogsource2/UPartials.pas create mode 100644 zlogsource2/UPediScore.dfm create mode 100644 zlogsource2/UPediScore.pas create mode 100644 zlogsource2/UQTCForm.dfm create mode 100644 zlogsource2/UQTCForm.pas create mode 100644 zlogsource2/UQTHDialog.dfm create mode 100644 zlogsource2/UQTHDialog.pas create mode 100644 zlogsource2/UQuickRef.dfm create mode 100644 zlogsource2/UQuickRef.pas create mode 100644 zlogsource2/URateDialog.dfm create mode 100644 zlogsource2/URateDialog.pas create mode 100644 zlogsource2/URenewThread.pas create mode 100644 zlogsource2/URigControl.dfm create mode 100644 zlogsource2/URigControl.pas create mode 100644 zlogsource2/UScratchSheet.dfm create mode 100644 zlogsource2/UScratchSheet.pas create mode 100644 zlogsource2/USixDownMulti.dfm create mode 100644 zlogsource2/USixDownMulti.pas create mode 100644 zlogsource2/USixDownScore.dfm create mode 100644 zlogsource2/USixDownScore.pas create mode 100644 zlogsource2/USoundForm.Pas create mode 100644 zlogsource2/USoundForm.dfm create mode 100644 zlogsource2/USpotClass.pas create mode 100644 zlogsource2/USpotForm.dfm create mode 100644 zlogsource2/USpotForm.pas create mode 100644 zlogsource2/USummaryInfo.dfm create mode 100644 zlogsource2/USummaryInfo.pas create mode 100644 zlogsource2/USuperCheck.dfm create mode 100644 zlogsource2/USuperCheck.pas create mode 100644 zlogsource2/UTTYConsole.dfm create mode 100644 zlogsource2/UTTYConsole.pas create mode 100644 zlogsource2/UUTCDialog.dfm create mode 100644 zlogsource2/UUTCDialog.pas create mode 100644 zlogsource2/UVoiceForm.dfm create mode 100644 zlogsource2/UVoiceForm.pas create mode 100644 zlogsource2/UVoiceThread.pas create mode 100644 zlogsource2/UWAEMulti.dfm create mode 100644 zlogsource2/UWAEMulti.pas create mode 100644 zlogsource2/UWAEScore.dfm create mode 100644 zlogsource2/UWAEScore.pas create mode 100644 zlogsource2/UWPXMulti.dfm create mode 100644 zlogsource2/UWPXMulti.pas create mode 100644 zlogsource2/UWPXScore.dfm create mode 100644 zlogsource2/UWPXScore.pas create mode 100644 zlogsource2/UWWMulti.dfm create mode 100644 zlogsource2/UWWMulti.pas create mode 100644 zlogsource2/UWWScore.dfm create mode 100644 zlogsource2/UWWScore.pas create mode 100644 zlogsource2/UWWZone.dfm create mode 100644 zlogsource2/UWWZone.pas create mode 100644 zlogsource2/UZLinkForm.dfm create mode 100644 zlogsource2/UZLinkForm.pas create mode 100644 zlogsource2/UZLinkFormOld.dfm create mode 100644 zlogsource2/UZLinkFormOld.pas create mode 100644 zlogsource2/UZServerInquiry.dfm create mode 100644 zlogsource2/UZServerInquiry.pas create mode 100644 zlogsource2/UZlinkComSet.dfm create mode 100644 zlogsource2/UZlinkComSet.pas create mode 100644 zlogsource2/UZlinkTelnetSet.dfm create mode 100644 zlogsource2/UZlinkTelnetSet.pas create mode 100644 zlogsource2/Unit1.dfm create mode 100644 zlogsource2/Unit1.pas create mode 100644 zlogsource2/UzLogCW.pas create mode 100644 zlogsource2/UzLogVoice.pas create mode 100644 zlogsource2/Vic_Res.pas create mode 100644 zlogsource2/WavePlayer.pas create mode 100644 zlogsource2/Zlog.dpr create mode 100644 zlogsource2/ccczlogconv.dfm create mode 100644 zlogsource2/ccczlogconv.pas create mode 100644 zlogsource2/main.dfm create mode 100644 zlogsource2/main.pas create mode 100644 zlogsource2/menu.dfm create mode 100644 zlogsource2/menu.pas create mode 100644 zlogsource2/testmain.dfm create mode 100644 zlogsource2/testmain.pas create mode 100644 zlogsource2/testscope.dpr create mode 100644 zlogsource2/ubandscope.dfm create mode 100644 zlogsource2/ubandscope.pas create mode 100644 zlogsource2/upaddlethread.pas create mode 100644 zlogsource2/utelnetset.dfm create mode 100644 zlogsource2/utelnetset.pas create mode 100644 zlogsource2/zLogGlobal.pas create mode 100644 zlogsource2/zprintw.pas diff --git a/ICS_zlog.zip b/ICS_zlog.zip deleted file mode 100644 index 23d0d740122186c71a9fbbe713d4aaf1468173dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 992850 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
sv2#o;f;o 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
#h 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�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

dK=;R{?ga}J%JbBeBV{?`>++%DQB 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≠ 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

RjxB3q4@Z6=~Rk5QwI+?GmNkO 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≪RY*6Htm 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 y{Y_lhSh8l=L7FLhSEF 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 diff --git a/ICS_zlog/Delphi/Internet/Cli7.dfm b/ICS_zlog/Delphi/Internet/Cli7.dfm new file mode 100644 index 0000000000000000000000000000000000000000..4454b106b4f77bf18c97f04ae8d76d964554af07 GIT binary patch literal 1876 zcmah~&2Aev5Tm;f((6gV+ylE@$C#4la%-HURNrcHzc8 z!Iv{utex8E1}GEeKfsLH#$0xKcQ_Tf`MzUaBfQFm`3cxQ+z8C5r7(yJ@3QAJ!V23> z$ZJ7oFhRo^qvG7pVZo8GpIuF7li!2*Pyc$djHYqFJk^+CLhdk4*)B%!#6TaELdF+Y zuWsQQS)+O6MUZkYLIuuBd?X$T8i1paq<(>*Kw*)h!nH%{6ULD(;l)~;j@;57wnWN3 zZCfFYa<;P_wWX}l0>49qFHmtqlic{LuOg~q838L^K#GW^zhCGi89GM>s8aNIog(8+ zZ$j{j+C4~Q5}g>{>(C4!Sps-3S@ieIGSweTnqf&}oK}f8Mopf(3s#6H;3|ZHDw9!T zfBqWlTr)0I4gu)J(-aFwktw58|6Hm&mHMwW!`WWgU6l!|0oF{znz~^#u5>sx*<(Z2 zy~b2nKPrH?%Ta+mks~j|1bLWyge9_k>Cplf@;RwmD0j!HEw_!OQ^s;24S*fL-U`9! z$Y+$IM3k$tNJAacPu2Z?t3!I;WY-y2s8+?$j|e9Z_Q?UGeDBFaD>n=r-!VSrfi8hTC;%+X+z+n zviCdtO_^A;?d-JbYzGoaAs?%*3O|oTf$55OtbHob2GRj?aTl@V0STx2ec`BJ=PX5z zE>nQlvMB-R09zeQX=)jxzIK`>Ide)&b#QM{Fu^QSBpWx7y+bBxT3GhQx&D+}s>`j; z#b~}I0>`-=c_~UAS1*0Yg>%%HH=8&PjE=iRTaFZ!bL_MAhEaLHP)~Y30M9~t1qGbE zg_yv5g6y;U8VB3bEkc~je+NBz)7I@^`=oU%pBPH*A8NwdvpyNl$d>0ZUL&>@#w#~M zG@TK+;`VUI)#6r8a7YF+Yb#WQG|V!)zvJ~%l}PT_c+gj6-~oCo=WyqjQ@xsOc4wvH?{0B$_O&9 + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Mar 07, 1999 V1.01 Adapted for Delphi 1 + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit Cli7; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, ExtCtrls, IniFiles, WSocket; + +const + EndOfLine = #13#10; + +type + TCli7Form = class(TForm) + Panel1: TPanel; + PortEdit: TEdit; + Label6: TLabel; + HostNameEdit: TEdit; + Label1: TLabel; + DisplayMemo: TMemo; + ConnectButton: TButton; + LineOnButton: TButton; + LineOffButton: TButton; + DisconnectButton: TButton; + ReadLineButton: TButton; + WSocket1: TWSocket; + procedure FormCreate(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure LineOnButtonClick(Sender: TObject); + procedure LineOffButtonClick(Sender: TObject); + procedure ConnectButtonClick(Sender: TObject); + procedure DisconnectButtonClick(Sender: TObject); + procedure ReadLineButtonClick(Sender: TObject); + procedure WSocket1SessionConnected(Sender: TObject; Error: Word); + procedure WSocket1SessionClosed(Sender: TObject; Error: Word); + procedure WSocket1DataAvailable(Sender: TObject; Error: Word); + private + FIniFileName : String; + FInitialized : Boolean; + procedure Display(Msg : String); + end; + +var + Cli7Form: TCli7Form; + +implementation + +{$R *.DFM} +const + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + SectionData = 'Data'; + KeyHostName = 'HostName'; + KeyPort = 'Port'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCli7Form.FormCreate(Sender: TObject); +begin + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCli7Form.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + IniFile := TIniFile.Create(FIniFileName); + HostNameEdit.Text := IniFile.ReadString(SectionData, KeyHostName, + 'localhost'); + PortEdit.Text := IniFile.ReadString(SectionData, KeyPort, + 'telnet'); + + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, (Screen.Width - Width) div 2); + + IniFile.Free; + DisplayMemo.Clear; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCli7Form.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteString(SectionData, KeyHostName, HostNameEdit.Text); + IniFile.WriteString(SectionData, KeyPort, PortEdit.Text); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCli7Form.Display(Msg : String); +begin + if DisplayMemo.Lines.Count > 200 then { Prevent TMemo overflow } + DisplayMemo.Clear; + DisplayMemo.Lines.Add(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCli7Form.LineOnButtonClick(Sender: TObject); +begin + WSocket1.LineMode := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCli7Form.LineOffButtonClick(Sender: TObject); +begin + WSocket1.LineMode := FALSE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCli7Form.ConnectButtonClick(Sender: TObject); +begin + WSocket1.Proto := 'tcp'; + WSocket1.Port := PortEdit.Text; + WSocket1.Addr := HostnameEdit.Text; + WSocket1.LineMode := TRUE; + WSocket1.LineEnd := EndOfLine; + WSocket1.Connect; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCli7Form.DisconnectButtonClick(Sender: TObject); +begin + WSocket1.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCli7Form.WSocket1SessionConnected(Sender: TObject; + Error: Word); +begin + if Error <> 0 then + Display('Connection failed, error #' + IntToStr(Error)) + else + Display('Session Connected.'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCli7Form.WSocket1SessionClosed(Sender: TObject; + Error: Word); +begin + Display('Session Closed.'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function RemoveEndOfLine(const Line : String) : String; +const + EOL : String = EndOfLine; { To make Delphi 1 happy } +begin + + if (Length(Line) >= Length(EndOfLine)) and + (StrLComp(@Line[1 + Length(Line) - Length(EndOfLine)], + @EOL[1], + Length(EndOfLine)) = 0) then + Result := Copy(Line, 1, Length(Line) - Length(EndOfLine)) + else + Result := Line; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCli7Form.WSocket1DataAvailable(Sender: TObject; + Error: Word); +var + Buf : array [0..127] of char; + Len : Integer; +begin + Len := TCustomLineWSocket(Sender).Receive(@Buf, Sizeof(Buf) - 1); + if Len <= 0 then + Exit; + Buf[Len] := #0; + if not WSocket1.LineMode then + { Normal mode, data is just a buffer with all caracters } + Display('DataAvailable (' + IntToStr(Len) +' bytes): ''' + + StrPas(@Buf) + '''') + else begin + { Line mode, buffer contains exactly one line, terminated by the } + { LineEnd string, unless our buffer is too small in which case } + { the line is truncated. We'll get the end of line on the next } + { call to Receive. } + Display('Line: ''' + RemoveEndOfLine(StrPas(@Buf)) + ''''); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCli7Form.ReadLineButtonClick(Sender: TObject); +var + Buffer : String; +begin + Display('Waiting for a line... (Timeout = 10Sec)'); + WSocket1.ReadLine(10000, Buffer); + Display('Received line: ''' + RemoveEndOfLine(Buffer) + ''''); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. diff --git a/ICS_zlog/Delphi/Internet/CliDemo1.dfm b/ICS_zlog/Delphi/Internet/CliDemo1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..c47b29ad6697afff403d5f2f40897925c04f2466 GIT binary patch literal 1496 zcmaJ>%Wl&^6dl`%$9580Q56ZXpew|xYLQqVu}RZJMC7H~QnyU)Nj&OgCh|=B*s)>H z-yqg(_yWFz4QrT(V<%7{OV*w7J?G55XMBH0AnA>U{Yf&IUW~!X{>;H;(@flSMAQXAbP4l_Z?`zC}d?&g5~AQ(nM! zN-qh^_-%skWXpW8IQLg*RuiRHbAAg0y`!T@ifhbN3PU#sc1oVYC<1!BtbTut9T(|%LKbawhsc+t= z+tT1~X>}N@+(cA$yQXmz%LrX57V|Dy0&R)gwk+;JX^7jY{AkR0A@vEiu&?Y1@*V8+ zf3d!@;szH$wXdHM8N`@nItkif0jmdO&d}Xd7o|9 z{>Rj?Od;hdqB$3e30U1^RxEd4_{fMbZRPFk zKd$ra9l;rVT2XFNH=o)Ax)ymtmYA=l`!>{+h_+PY7Py$Q>3j~O zTd`T{Nuu^Qcr`qf6=H;M)UWNlJ}|59TIQ-?k|I4+;i1qe6TZ7`f1ID@3V0utt>6!t CA<}aI literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/CliDemo1.pas b/ICS_zlog/Delphi/Internet/CliDemo1.pas new file mode 100644 index 00000000..3fe49dc5 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/CliDemo1.pas @@ -0,0 +1,257 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: Demonstration for Client program using TWSocket. +Creation: 8 december 1997 +Version: 1.04 +EMail: http://www.overbyte.be francois.piette@overbyte.be + http://www.rtfm.be/fpiette francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997-2001 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Dec 09, 1997 V1.01 Made it compatible with Delphi 1 +Jul 09, 1998 V1.02 Adapted for Delphi 4 +Dec 05, 1998 V1.03 Don't use TWait component +Dec 15, 2001 V1.04 Use LineMode + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit CliDemo1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, IniFiles, ExtCtrls, + { Don't forget to add your vc32 directory to Delphi library path } + WSocket; + +const + IniFileName = 'CliDemo.ini'; + +type + TClientForm = class(TForm) + CliSocket: TWSocket; + DisplayMemo: TMemo; + Panel1: TPanel; + Label1: TLabel; + Label2: TLabel; + SendEdit: TEdit; + SendButton: TButton; + DisconnectButton: TButton; + PortEdit: TEdit; + ServerEdit: TEdit; + procedure DisconnectButtonClick(Sender: TObject); + procedure SendButtonClick(Sender: TObject); + procedure CliSocketDataAvailable(Sender: TObject; Error: Word); + procedure CliSocketSessionConnected(Sender: TObject; Error: Word); + procedure CliSocketSessionClosed(Sender: TObject; Error: Word); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormShow(Sender: TObject); + procedure Timer1Timer(Sender: TObject); + private + Buffer : array [0..1023] of char; + ConnectError : Word; + Initialized : Boolean; + procedure Display(Msg : String); + procedure ProcessCommand(Cmd : String); + end; + +var + ClientForm: TClientForm; + +implementation + +{$R *.DFM} + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.DisconnectButtonClick(Sender: TObject); +begin + CliSocket.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.SendButtonClick(Sender: TObject); +begin + if CliSocket.State <> wsConnected then begin + CliSocket.Proto := 'tcp'; + CliSocket.Port := PortEdit.Text; + CliSocket.Addr := ServerEdit.Text; + CliSocket.LineMode := TRUE; + CliSocket.LineEnd := #13#10; + CliSocket.Connect; + { Connect is asynchronous (non-blocking). We will wait while the } + { session is connecting or application terminated. } + while CliSocket.State in [wsConnecting] do begin + Application.ProcessMessages; + if Application.Terminated then + Exit; + end; + end; + { Be sure we are connected before sending anything } + if CliSocket.State = wsConnected then + CliSocket.SendStr(SendEdit.Text + #13 + #10); + ActiveControl := SendEdit; + SendEdit.SelectAll; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.ProcessCommand(Cmd : String); +begin + { Here you should write your command interpreter. } + { For simplicity, we just display received command ! } + { First remove EndOfLine marker } + if (Length(Cmd) >= Length(CliSocket.LineEnd)) and + (Copy(Cmd, Length(Cmd) - Length(CliSocket.LineEnd) + 1, + Length(CliSocket.LineEnd)) = CliSocket.LineEnd) then + Cmd := Copy(Cmd, 1, Length(Cmd) - Length(CliSocket.LineEnd)); + { Then display in memo } + Display(Cmd); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.CliSocketDataAvailable(Sender: TObject; Error: Word); +var + Len : Integer; +begin + { We use line mode, we will receive a complete line } + Len := CliSocket.Receive(@Buffer, SizeOf(Buffer) - 1); + if Len <= 0 then + Exit; + + Buffer[Len] := #0; { Nul terminate } + ProcessCommand(StrPas(Buffer)); { Pass as string } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.CliSocketSessionConnected( + Sender : TObject; + Error : Word); +begin + ConnectError := Error; + if Error <> 0 then + Display('Can''t connect, error #' + IntToStr(Error)) + else + DisconnectButton.Enabled := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.CliSocketSessionClosed(Sender: TObject; Error: Word); +begin + DisconnectButton.Enabled := FALSE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(IniFileName); + IniFile.WriteInteger('Window', 'Top', Top); + IniFile.WriteInteger('Window', 'Left', Left); + IniFile.WriteInteger('Window', 'Width', Width); + IniFile.WriteInteger('Window', 'Height', Height); + IniFile.WriteString('Data', 'Server', ServerEdit.Text); + IniFile.WriteString('Data', 'Port', PortEdit.Text); + IniFile.WriteString('Data', 'Command', SendEdit.Text); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if Initialized then + Exit; + Initialized := TRUE; + IniFile := TIniFile.Create(IniFileName); + + Top := IniFile.ReadInteger('Window', 'Top', Top); + Left := IniFile.ReadInteger('Window', 'Left', Left); + Width := IniFile.ReadInteger('Window', 'Width', Width); + Height := IniFile.ReadInteger('Window', 'Height', Height); + + PortEdit.Text := IniFile.ReadString('Data', 'Port', 'telnet'); + ServerEdit.Text := IniFile.ReadString('Data', 'Server', 'localhost'); + SendEdit.Text := IniFile.ReadString('Data', 'Command', 'LASTNAME CAESAR'); + + IniFile.Free; + + DisplayMemo.Clear; + ActiveControl := SendEdit; + SendEdit.SelectAll; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Display a message in our display memo. Delete lines to be sure to not } +{ overflow the memo which may have a limited capacity. } +procedure TClientForm.Display(Msg : String); +var + I : Integer; +begin + DisplayMemo.Lines.BeginUpdate; + try + if DisplayMemo.Lines.Count > 200 then begin + for I := 1 to 50 do + DisplayMemo.Lines.Delete(0); + end; + DisplayMemo.Lines.Add(Msg); + finally + DisplayMemo.Lines.EndUpdate; +{$IFNDEF VER80} + SendMessage(DisplayMemo.Handle, EM_SCROLLCARET, 0, 0); +{$ENDIF} + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.Timer1Timer(Sender: TObject); +begin + if CliSocket.State = wsConnecting then + Exit; + + if CliSocket.State <> wsConnected then + SendButtonClick(nil) + else + DisconnectButtonClick(nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/Client7.dpr b/ICS_zlog/Delphi/Internet/Client7.dpr new file mode 100644 index 00000000..4ba287bd --- /dev/null +++ b/ICS_zlog/Delphi/Internet/Client7.dpr @@ -0,0 +1,12 @@ +program Client7; + +uses + Forms, + Cli7 in 'Cli7.pas' {Cli7Form}; + +{$R *.RES} + +begin + Application.CreateForm(TCli7Form, Cli7Form); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/ConCli1.dpr b/ICS_zlog/Delphi/Internet/ConCli1.dpr new file mode 100644 index 00000000..50693237 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/ConCli1.dpr @@ -0,0 +1,78 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: ConCli shows how to use TWSocket in a console mode application + (for Delphi 2, Delphi 3 or Delphi 4). +Creation: Nov 20, 1997 +Version: 1.01 +EMail: http://www.overbyte.be http://www.rtfm.be/fpiette + francois.piette@overbyte.be francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 1997-2002 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Dec 05, 1998 V1.01 Don't use TWait control anymore + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} + Bomb('Sorry, Delphi 1 does not support console mode programs'); +{$ENDIF} +{$APPTYPE CONSOLE} +program ConCli1; + +uses + Forms, WSocket; + +var + WSocket1 : TWSocket; + Buffer : String; +begin + WSocket1 := TWsocket.Create(nil); + WSocket1.Proto := 'tcp'; + WSocket1.Addr := 'localhost'; + WSocket1.Port := 'telnet'; + WSocket1.Connect; + { Connect is asynchronous (non-blocking). We will wait while the } + { session is connecting or application terminated. } + while WSocket1.State in [wsConnecting] do begin + Application.ProcessMessages; + if Application.Terminated then + break; + end; + if WSocket1.State = wsConnected then begin + WSocket1.ReadLine(15, Buffer); + Writeln('Server banner is: ' + Buffer); + WSocket1.Close; + end + else + Writeln('Connection failed'); + WSocket1.Destroy; + + Writeln('Hit enter...'); + Readln; +end. diff --git a/ICS_zlog/Delphi/Internet/ConCli2.dpr b/ICS_zlog/Delphi/Internet/ConCli2.dpr new file mode 100644 index 00000000..a837eea0 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/ConCli2.dpr @@ -0,0 +1,164 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: ConCli2 shows how to use TWSocket in a console mode application. + ConCli2 use a thread to make the socket run in the program + background while the foreground is busy with the user interface + (for simplicity here we just wait for the user to hit the + enter key). +Creation: Nov 20, 1997 +Version: 1.01 +EMail: http://www.overbyte.be http://www.rtfm.be/fpiette + francois.piette@overbyte.be francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 1997-2002 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Dec 05, 1998 V1.01 Don't use TWait object anymore. + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} + Bomb('Sorry, Delphi 1 does not support console mode programs'); +{$ENDIF} +{$APPTYPE CONSOLE} +program ConCli2; + +uses + Windows, Classes, WSocket; + +const + ServerHostName = 'localhost'; + ServerPort = 'telnet'; + +type + TWSocketThread = class(TThread) + protected + FWSocket : TWsocket; + FRcvBuf : array [0..1023] of char; + procedure Execute; override; + procedure FWSocketDataAvailable(Sender : TObject; Error : Word); + procedure FWSocketSessionConnected(Sender : TObject; Error : Word); + procedure FWSocketSessionClosed(Sender : TObject; Error : Word); + public + constructor Create; virtual; + end; + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TWSocketThread.Create; +begin + inherited Create(TRUE); + FreeOnTerminate := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TWSocketThread.Execute; +begin + // Let's the user know what we are doing + Writeln('Connecting to server ''', ServerHostName, + ''' on port ''', ServerPort, ''''); + + // Create the TWSocket we will use to communicate with the server + FWSocket := TWsocket.Create(nil); + + // Assign the event handler for the TWSocket events we care of + FWSocket.OnDataAvailable := FWSocketDataAvailable; + FWSocket.OnSessionClosed := FWSocketSessionClosed; + FWSocket.OnSessionConnected := FWSocketSessionConnected; + + // Connect to the server + FWSocket.Addr := ServerHostName; + FWSocket.Port := ServerPort; + FWSocket.Proto := 'tcp'; + FWSocket.Connect; + + // Let the TWSocket component makes his work + FWSocket.MessageLoop; + + // We are done, destroy the objects we created + FWSocket.Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called by the TWSocket when some data has been } +{ received by the lower level. } +procedure TWSocketThread.FWSocketDataAvailable(Sender : TObject; Error : Word); +var + Len : Integer; +begin + // Get the received data + Len := FWSocket.Receive(@FRcvBuf[0], SizeOf(FRcvBuf) - 1); + if Len <= 0 then + Exit; + + // Add a terminating nul byte to allow display using standard I/O + FRcvBuf[Len] := #0; + Write(FRcvBuf); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called by TWSocket when the connection is } +{ established with the remote host } +procedure TWSocketThread.FWSocketSessionConnected(Sender : TObject; Error : Word); +begin + Writeln('Connected'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called by TWSocket when the connection is broken } +procedure TWSocketThread.FWSocketSessionClosed(Sender : TObject; Error : Word); +begin + Writeln('Server has diconnected'); + FWSocket.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This is the main program. } +var + WSocketThread : TWSocketThread; +begin + Writeln('Hit enter to stop the program'); + Writeln; + // Create the socket working thread (suspended) + WSocketThread := TWSocketThread.Create; + + // Start the thread + WSocketThread.Resume; + + // The main thread continue here. Process user request here. + Readln; + + // We are done, quit the program + Writeln('Ok.'); +end. + diff --git a/ICS_zlog/Delphi/Internet/ConFtp.dpr b/ICS_zlog/Delphi/Internet/ConFtp.dpr new file mode 100644 index 00000000..b2135081 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/ConFtp.dpr @@ -0,0 +1,226 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +Author: François PIETTE +Object: This demo shows how to use TFtpCli component within a console + mode application. It connect to ftp.microsoft.com and download + readme.txt from /softlib directory. The local file is ConFtp.txt. +Creation: Dec 24, 2001 +Version: 1.00 +EMail: http://www.overbyte.be http://www.rtfm.be/fpiette + francois.piette@overbyte.be francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 2001 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +program ConFtp; + +{$IFDEF VER80} + Bomb('Sorry, Delphi 1 does not support console mode programs'); +{$ENDIF} +{$APPTYPE CONSOLE} +{$IFNDEF NOFORMS} + Bomb('Please add NOFORMS to your project defines'); +{$ENDIF} + +uses + Windows, Classes, SysUtils, Messages, FtpCli; + +const + ConFtpVersion = 100; + CopyRight = ' ConFtp (c) 2002 by Francois PIETTE. V1.00'; + +type + { We use TConApplication class (actually a component) to encapsulate all } + { the work to be done. This is easier because TFtpCli is event driven } + { and need methods (that is procedure of object) to handle events. } + TConApplication = class(TComponent) + protected + FFtpCli : TFtpClient; + FResult : Integer; + procedure FtpRequestDone(Sender : TObject; + RqType : TFtpRequest; + ErrorCode : Word); + procedure FtpDisplay(Sender : TObject; + var Msg : String); + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Execute; + end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TConApplication.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FFtpCli := TFtpClient.Create(Self); + FResult := 0; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor TConApplication.Destroy; +begin + if Assigned(FFtpCli) then begin + FFtpCli.Destroy; + FFtpCli := nil; + end; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TConApplication.Execute; +begin + { Prepare connection to Ftp server } + FFtpCli.HostName := 'ftp.microsoft.com'; + FFtpCli.Port := 'ftp'; + FFtpCli.HostDirName := '/softlib'; + FFtpCli.HostFileName := 'readme.txt'; + FFtpCli.LocalFileName := 'ConFtp.txt'; + FFtpCli.Binary := TRUE; + FFtpCli.UserName := 'anonymous'; + FFtpCli.Password := 'your.name@your.domain.com'; + FFtpCli.OnDisplay := FtpDisplay; + FFtpCli.OnRequestDone := FtpRequestDone; + + { Delete existing file } + DeleteFile(FFtpCli.LocalFileName); + + { Start FTP transfert by connecting to the server } + WriteLn('Connecting to ', FFtpCli.HostName, '/', FFtpCli.Port); + FFtpCli.OpenAsync; + + { We need a message loop in order for windows message processing to work. } + { There is a message loop built into each TWSocket, so we use the one in } + { TFtpCli control socket. } + { MessageLoop will exit only when WM_QUIT message is posted. We do that } + { form the OnRequestDone event handler when the component has finished. } + FFtpCli.ControlSocket.MessageLoop; + WriteLn('Going back to the OS'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TConApplication.FtpDisplay(Sender: TObject; var Msg: String); +begin + WriteLn(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TConApplication.FtpRequestDone( + Sender : TObject; + RqType : TFtpRequest; + ErrorCode : Word); +var + EndFlag : Boolean; +begin + EndFlag := FALSE; + + { Check status } + if ErrorCode <> 0 then begin + WriteLn('Failed, error #' + IntToStr(ErrorCode)); + FFtpCli.Abort; + EndFlag := TRUE; + end + else begin + case RqType of + ftpOpenAsync : + begin + FFtpCli.UserAsync; + end; + ftpUserAsync : + begin + FFtpCli.PassAsync; + end; + ftpPassAsync : + begin + FFtpCli.CwdAsync; + end; + ftpCwdAsync : + begin + FFtpCli.TypeSetAsync; + end; + ftpTypeSetAsync: + begin + FFtpCli.GetAsync; + end; + ftpGetAsync : + begin + FResult := FFtpCli.StatusCode; + FFtpCli.QuitAsync; + end; + ftpQuitAsync : + begin + EndFlag := TRUE; + end; + else + begin + WriteLn('Unknown FtpRequest ' + IntToStr(Ord(RqType))); + EndFlag := TRUE; + end; + end; + end; + + { If something wrong or end of job, then go back to the OS } + if EndFlag then begin + if FResult = 226 then + WriteLn('Transfert succesful. File is ', FFtpCli.LocalFileName) + else + WriteLn('Transfert failed !'); + { Prompt the user } + WriteLn('Hit ENTER key to return quit program...'); + ReadLn; + { Break message loop we called from the execute method } + PostMessage(FFtpCli.ControlSocket.Handle, WM_QUIT, 0, 0); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +var + ConApp : TConApplication; +begin + WriteLn(CopyRight); + WriteLn; + ConApp := TConApplication.Create(nil); + try + ConApp.Execute; + finally + ConApp.Destroy; + end; +end. + diff --git a/ICS_zlog/Delphi/Internet/ConHttp.dpr b/ICS_zlog/Delphi/Internet/ConHttp.dpr new file mode 100644 index 00000000..4d55b59e --- /dev/null +++ b/ICS_zlog/Delphi/Internet/ConHttp.dpr @@ -0,0 +1,171 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +Author: François PIETTE +Object: This demo shows how to use THttpCli component within a console + mode application. It Connect to www.borland.com and display + received (default) document on screen. +Creation: Apr 20, 2002 +Version: 1.00 +EMail: http://www.overbyte.be http://www.rtfm.be/fpiette + francois.piette@overbyte.be francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 2002 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +program ConHttp; + +{$IFDEF VER80} + Bomb('Sorry, Delphi 1 does not support console mode programs'); +{$ENDIF} +{$APPTYPE CONSOLE} +{$IFNDEF NOFORMS} + Bomb('Please add NOFORMS to your project defines'); +{$ENDIF} + +uses + Windows, SysUtils, Classes, Messages, HttpProt; + +const + ConHttpVersion = 100; + CopyRight = ' ConHttp (c) 2002 by Francois PIETTE. V1.00'; + +type + { We use TConApplication class (actually a component) to encapsulate all } + { the work to be done. This is easier because THttpCli is event driven } + { and need methods (that is procedure of object) to handle events. } + TConApplication = class(TComponent) + protected + FHttpCli : THttpCli; + procedure HttpRequestDone(Sender : TObject; + RqType : THttpRequest; + ErrorCode : Word); + procedure HttpDocData(Sender : TObject; + Buffer : Pointer; + Len : Integer); + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Execute; + end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TConApplication.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FHttpCli := THttpCli.Create(Self); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor TConApplication.Destroy; +begin + if Assigned(FHttpCli) then begin + FHttpCli.Destroy; + FHttpCli := nil; + end; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TConApplication.Execute; +var + Url : String; +begin + Url := 'http://www.borland.com'; + WriteLn('Querying ' + Url); + FHttpCli.URL := Url; + FHttpCli.OnRequestDone := HttpRequestDone; + FHttpCli.OnDocData := HttpDocData; + FHttpCli.GetASync; + { We need a message loop in order for windows message processing to work. } + { There is a message loop built into each TWSocket, so we use the one in } + { THttpCli control socket. } + { MessageLoop will exit only when WM_QUIT message is posted. We do that } + { form the OnRequestDone event handler when the component has finished. } + FHttpCli.CtrlSocket.MessageLoop; + WriteLn('Going back to the OS'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called each time THttpCli receive document data. } +procedure TConApplication.HttpDocData( + Sender : TObject; + Buffer : Pointer; + Len : Integer); +begin + while Len > 0 do begin { While we have bytes... } + Write(PChar(Buffer)^); { Write to standard output } + Buffer := PChar(Buffer) + 1; { Skip to next byte } + Len := Len - 1; { Count down the byte } + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when THttpCli has finihed his work. } +procedure TConApplication.HttpRequestDone( + Sender : TObject; + RqType : THttpRequest; + ErrorCode : Word); +begin + { Check status } + if ErrorCode <> 0 then + WriteLn('Failed, error #' + IntToStr(ErrorCode)) + else + WriteLn('Done.'); + { Prompt the user } + WriteLn('Hit ENTER key to return quit program...'); + ReadLn; + { Break message loop we called from the execute method } + PostMessage(FHttpCli.CtrlSocket.Handle, WM_QUIT, 0, 0); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +var + ConApp : TConApplication; +begin + WriteLn(CopyRight); + WriteLn; + ConApp := TConApplication.Create(nil); + try + ConApp.Execute; + finally + ConApp.Destroy; + end; +end. diff --git a/ICS_zlog/Delphi/Internet/ConSmtp.dpr b/ICS_zlog/Delphi/Internet/ConSmtp.dpr new file mode 100644 index 00000000..b91b7d20 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/ConSmtp.dpr @@ -0,0 +1,291 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +Author: François PIETTE +Object: This demo shows how to use TSmtpCli component within a console + mode application. It connect to your ISP server and mail a simple + message. See the "const" section below to change the SMTP setting + according to your situation. The mail message is also sent to + me (CCi). +Creation: Dec 24, 2001 +Version: 1.01 +EMail: http://www.overbyte.be http://www.rtfm.be/fpiette + francois.piette@overbyte.be francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 2001 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: +Nov 11, 2002 V1.01 Changed MsgLine argument of SmtpGetData from PChar to + pointer to reflect component change. + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +program ConSmtp; + +{$IFDEF VER80} + Bomb('Sorry, Delphi 1 does not support console mode programs'); +{$ENDIF} +{$APPTYPE CONSOLE} +{$IFNDEF NOFORMS} + Bomb('Please add NOFORMS to your project defines'); +{$ENDIF} + +uses + Windows, Classes, SysUtils, Messages, SmtpProt; + +const + ConSmtpVersion = 101; + CopyRight = ' ConSmtp (c) 2002 by Francois PIETTE. V1.01'; + +{ You *MUST* change the settings below so that your ISP mail server is } +{ addressed. If you don't change those settings, you'll use my ISP SMTP } +{ server which doesn't allow relaying. So you'll be rejected ! } +const + { This is your ISP SMPT server hostname } + YourSmtpServer = 'relay.skynet.be'; + { This is your sign on. Usually just your first and last names } + WhoYouAre = 'Firstname LastName'; + { And here your own email address } + YourEmailAddress = 'user.name@domain.name'; + { And finally the destination email address } + DestinationEmail = 'francois.piette@pophost.eunet.be'; + +type + { We use TConApplication class (actually a component) to encapsulate all } + { the work to be done. This is easier because TSmtpCli is event driven } + { and need methods (that is procedure of object) to handle events. } + TConApplication = class(TComponent) + protected + FSmtpCli : TSmtpCli; + FMessageBody : TStringList; + procedure SmtpRequestDone(Sender : TObject; + RqType : TSmtpRequest; + ErrorCode : Word); + procedure SmtpGetData(Sender : TObject; + LineNum : Integer; + MsgLine : Pointer; + MaxLen : Integer; + var More : Boolean); + procedure SmtpResponse(Sender : TObject; + Msg : String); + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Execute; + end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TConApplication.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FSmtpCli := TSmtpCli.Create(Self); + FMessageBody := TStringList.Create; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor TConApplication.Destroy; +begin + if Assigned(FSmtpCli) then begin + FSmtpCli.Destroy; + FSmtpCli := nil; + end; + if Assigned(FMessageBody) then begin + FMessageBody.Destroy; + FMessageBody := nil; + end; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TConApplication.Execute; +begin + { Prepare connection to SMTP server } + FSmtpCli.Host := YourSmtpServer; + FSmtpCli.Port := 'smtp'; + FSmtpCli.SignOn := WhoYouAre; + { Prepare message addressing (two recipients, one is CCi) } + FSmtpCli.FromName := YourEmailAddress; + FSmtpCli.RcptName.Clear; + FSmtpCli.RcptName.Add(DestinationEmail); + FSmtpCli.RcptName.Add('francois.piette@overbyte.be'); { This is CCi } + FSmtpCli.HdrSubject := 'ICS console mode SMTP demo is working'; + FSmtpCli.HdrTo := FSmtpCli.RcptName.Strings[0]; + FSmtpCli.HdrFrom := FSmtpCli.FromName; + + { Construct the message body } + FMessageBody.Clear; + FMessageBody.Add('Hello !'); + FMessageBody.Add(''); + FMessageBody.Add('This message has been sent by ConSmtp demo.'); + FMessageBody.Add(''); + FMessageBody.Add('--'); + FMessageBody.Add(FSmtpCli.SignOn); + FMessageBody.Add(FSmtpCli.FromName); + + { Prepare component event handlers } + FSmtpCli.OnRequestDone := SmtpRequestDone; + FSmtpCli.OnResponse := SmtpResponse; + FSmtpCli.OnGetData := SmtpGetData; + + WriteLn('> CONNECT ' + FSmtpCli.Host + '/' + FSmtpCli.Port); + FSmtpCli.Connect; + + { We need a message loop in order for windows message processing to work. } + { There is a message loop built into each TWSocket, so we use the one in } + { TSmtpCli control socket. } + { MessageLoop will exit only when WM_QUIT message is posted. We do that } + { form the OnRequestDone event handler when the component has finished. } + FSmtpCli.CtrlSocket.MessageLoop; + WriteLn('Going back to the OS'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called by TSmtpCli to get the next line of message } +{ body. It is called repeatedly to get all lines, until "More" argument } +{ is set to false. As we stored the message in a TStringList, we just have } +{ to read from it. Easy. We could also easily read from a file. } +procedure TConApplication.SmtpGetData( + Sender : TObject; + LineNum : Integer; { The line number, start from 0 } + MsgLine : Pointer; { Where to store each line (pointer to buffer) } + MaxLen : Integer; { SizeOf line buffer within smtp component } + var More : Boolean); { Return value to signal end of message body } +begin + if LineNum > FMessageBody.count then + More := FALSE + else + StrPLCopy(MsgLine, FMessageBody.Strings[LineNum - 1], MaxLen - 1); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called each time the smtp component receive an } +{ message from smtp server. } +procedure TConApplication.SmtpResponse(Sender: TObject; Msg: String); +begin + WriteLn('< ' + Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called each time smtp component has done a request } +{ We use it to start the next request because sending a smtp message } +{ require a few operations: connecting to server, sending helo message, } +{ sending originator, sending recipients, sending message body and finally } +{ disconnecting from server. There are of course optional request such as } +{ authentication. } +procedure TConApplication.SmtpRequestDone( + Sender : TObject; + RqType : TSmtpRequest; + ErrorCode : Word); +var + EndFlag : Boolean; +begin + EndFlag := FALSE; + case RqType of + smtpConnect: + begin + WriteLn('> HELO'); + if ErrorCode = 0 then + FSmtpCli.Helo; + end; + smtpHelo: + begin + WriteLn('> MAILFROM'); + if ErrorCode = 0 then + FSmtpCli.MailFrom; + end; + smtpMailFrom: + begin + WriteLn('> RCPTTO'); + if ErrorCode = 0 then + FSmtpCli.RcptTo; + end; + smtpRcptTo: + begin + WriteLn('> DATA'); + if ErrorCode = 0 then + FSmtpCli.Data; + end; + smtpData: + begin + WriteLn('> QUIT'); + if ErrorCode = 0 then + FSmtpCli.Quit; + end; + smtpQuit: + begin + WriteLn('Quit done'); + EndFlag := TRUE; + end; + else + begin + WriteLn('Unknown SmtpRequest ' + IntToStr(Ord(RqType))); + EndFlag := TRUE; + end; + end; + + { Check status } + if ErrorCode <> 0 then begin + WriteLn('Failed, error #' + IntToStr(ErrorCode)); + EndFlag := TRUE; + end; + + { If something wrong or end of job, then go back to the OS } + if EndFlag then begin + { Prompt the user } + WriteLn('Hit ENTER key to return quit program...'); + ReadLn; + { Break message loop we called from the execute method } + PostMessage(FSmtpCli.CtrlSocket.Handle, WM_QUIT, 0, 0); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +var + ConApp : TConApplication; +begin + WriteLn(CopyRight); + WriteLn; + ConApp := TConApplication.Create(nil); + try + ConApp.Execute; + finally + ConApp.Destroy; + end; +end. + diff --git a/ICS_zlog/Delphi/Internet/ConSrv1.dpr b/ICS_zlog/Delphi/Internet/ConSrv1.dpr new file mode 100644 index 00000000..4e4710ba --- /dev/null +++ b/ICS_zlog/Delphi/Internet/ConSrv1.dpr @@ -0,0 +1,354 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: Demo for a full blown multi-user server using TWSocket and + console mode. +EMail: francois.piette@pophost.eunet.be francois.piette@rtfm.be + http://www.rtfm.be/fpiette +Creation: Feb 17, 1999 +Version: 1.01 +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1996, 1997, 1998, 1999 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +History: +Sep 29, 1999 V1.01 Adapted for Delphi 5 + +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +program ConSrv1; +{$IFDEF VER80} + Bomb('Sorry but Delphi 1 doesn''t support console mode program'); +{$ENDIF} +{$APPTYPE CONSOLE} +{$IFNDEF NOFORMS} + Bomb('This demo must be compiled with symbol NOFORMS defined.' + + 'Go to Delphi/Menu/Project/Options and in "Directories/Conditionals"' + + 'tab, add NOFORMS to the "define" edit box.'); +{$ENDIF} + +uses + Windows, + SysUtils, + Messages, + Classes, + WSocket, + WinSock, + ConSrv1S in 'ConSrv1S.pas', + ConSrv1C in 'ConSrv1C.pas'; + +const + Version = 101; + +type + TKeyboardThread = class (TThread) + public + procedure Execute; override; + end; + +// Declare all standard functions and procedures +function InitAplication : Boolean; forward; +procedure RunAplication; forward; +procedure CleanupAplication; forward; +procedure CleanupData; forward; +function CtrlHandlerRoutine(CtrlType : DWORD) : DWORD; stdcall; forward; +function MyWindowProc(ahWnd : HWND; + auMsg : Integer; + awParam : WPARAM; + alParam : LPARAM): Integer; stdcall; forward; +function CreateEvent(var MsgRec : TMsg) : Integer; forward; +procedure ClientDisconnectedEvent(var MsgRec : TMsg); forward; + +// Declare some global variables +var + SrvObject : TServerObject; + Terminated : Boolean; + hWndMain : HWND; + KbdThread : TKeyboardThread; + MyWindowClass : TWndClass = (style : 0; + lpfnWndProc : @MyWindowProc; + cbClsExtra : 0; + cbWndExtra : 0; + hInstance : 0; + hIcon : 0; + hCursor : 0; + hbrBackground : 0; + lpszMenuName : nil; + lpszClassName : 'MyWindowClass'); + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Console mode applications do not receive keyboard messages as GUI apps. } +{ We use a thread to wait for keyboard activity and generate keyboard } +{ messages as in a GUI application. } +procedure TKeyboardThread.Execute; +var + hConsole : THandle; + Status : DWORD; + InputBuffer : TInputRecord; + KeyEvent : TKeyEventRecord; + Count : DWORD; +begin + hConsole := GetStdHandle(STD_INPUT_HANDLE); + while not Terminated do begin + Status := WaitForSingleObject(hConsole, 1000); + if Status = WAIT_OBJECT_0 then begin + if ReadConsoleInput(hConsole, InputBuffer, 1, Count) then begin + if InputBuffer.EventType = KEY_EVENT then begin +{$IFDEF VER90} { Delphi 2 } + KeyEvent := InputBuffer.KeyEvent; +{$ELSE} +{$IFDEF VER93} { Bcb 1 } + KeyEvent := InputBuffer.KeyEvent; +{$ELSE} +{$IFDEF VER100} { Delphi 3 } + KeyEvent := InputBuffer.KeyEvent; +{$ELSE} +{$IFDEF VER110} { Bcb 3 } + KeyEvent := InputBuffer.KeyEvent; +{$ELSE} +{$ENDIF} +{ Starting from Delphi 4 and Bcb4, they changed definition } + KeyEvent := InputBuffer.Event.KeyEvent; +{$ENDIF} +{$ENDIF} +{$ENDIF} + if KeyEvent.bKeyDown then begin + PostMessage(hWndMain, WM_KEYDOWN, + KeyEvent.wVirtualKeyCode, + KeyEvent.wRepeatCount + + (KeyEvent.wVirtualScanCode shl 16)); + end + else begin + PostMessage(hWndMain, WM_KEYUP, + KeyEvent.wVirtualKeyCode, + KeyEvent.wRepeatCount + + (KeyEvent.wVirtualScanCode shl 16)); + end; + end; + end; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This is a callback routine called by windows when some events occurs. } +{ We trap those events to close our application. } +function CtrlHandlerRoutine(CtrlType : DWORD) : DWORD; stdcall; +begin + case CtrlType of + CTRL_C_EVENT, // User hit CTRL-C + CTRL_BREAK_EVENT, // User hit CTRL-BREAK + CTRL_LOGOFF_EVENT, // User log off his session + CTRL_CLOSE_EVENT, // Close signal + CTRL_SHUTDOWN_EVENT : // Window shutdown signal + begin + Result := 1; + PostMessage(hWndMain, WM_QUIT, 0, 0); + end; + else + Result := 0; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure ClientDisconnectedEvent(var MsgRec : TMsg); +var + Client : TClientObject; +begin + Client := TClientObject(MsgRec.lParam); + if Assigned(SrvObject) and Assigned(Client) then + SrvObject.DisconnectedClient(Client); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function CreateEvent(var MsgRec : TMsg) : Integer; +begin + try + SetConsoleTitle(PChar('ConSrv V' + Format('%d.%2d', + [Version div 100,Version mod 100]))); + WriteLn('Hit CTRL-C to return to system.'); + SrvObject := TServerObject.Create; + SrvObject.CtrlWindow := MsgRec.hwnd; + KbdThread := TKeyboardThread.Create(FALSE); + Result := 0; // Success + except + on E:Exception do begin + WriteLn('CreateEvent failed.'); + WriteLn('Exception ' + E.ClassName + ': ' + E.Message); + Result := -1; // Failure + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure DisplayHelp; +begin + WriteLn('F1 Display this help text'); + WriteLn('F2 Display user list'); + WriteLn('CTRL-C Quit program'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure KeyDownEvent(MsgRec : TMsg); +var + Key : Integer; +begin + Key := MsgRec.wParam; + case Key of + VK_SHIFT, + VK_CONTROL, + VK_MENU: { Ignore }; + VK_F1: + DisplayHelp; + VK_F2: + SrvObject.DisplayClientList; + else + MessageBeep(MB_OK); + WriteLn('Unknown keyboard command. Type F1 to get help.'); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function MyWindowProc( + ahWnd : HWND; + auMsg : Integer; + awParam : WPARAM; + alParam : LPARAM): Integer; stdcall; +var + MsgRec : TMsg; +begin + Result := 0; // This means we handled the message + try + MsgRec.hwnd := ahWnd; + MsgRec.message := auMsg; + MsgRec.wParam := awParam; + MsgRec.lParam := alParam; + + case auMsg of + WM_CLIENT_DISCONNECTED: + ClientDisconnectedEvent(MsgRec); + WM_CREATE: + Result := CreateEvent(MsgRec); + WM_CLOSE: + begin + WriteLn('Closing'); + DestroyWindow(ahWnd); + end; + WM_DESTROY: + begin + WriteLn('Destroying'); + CleanupData; + end; + WM_KEYDOWN: KeyDownEvent(MsgRec); +{ WM_KEYUP: writeln('WM_KEYUP'); } +{ WM_CHAR: writeln('WM_CHAR'); } + else + Result := DefWindowProc(ahWnd, auMsg, awParam, alParam) + end; + except + on E:Exception do + WriteLn('Exception ' + E.ClassName + ': ' + E.Message); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function InitAplication : Boolean; +begin + Result := FALSE; + if Windows.RegisterClass(MyWindowClass) = 0 then + Exit; + hWndMain := CreateWindowEx(WS_EX_TOOLWINDOW, + MyWindowClass.lpszClassName, + '', { Window name } + WS_POPUP, { Window Style } + 0, 0, { X, Y } + 0, 0, { Width, Height } + 0, { hWndParent } + 0, { hMenu } + HInstance, { hInstance } + nil); { CreateParam } + if hWndMain = 0 then + Exit; + SetConsoleCtrlHandler(@CtrlHandlerRoutine, TRUE); + Result := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure CleanupData; +begin + if Assigned(SrvObject) then begin + SrvObject.Destroy; + SrvObject := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure CleanupAplication; +begin + CleanupData; + if hWndMain <> 0 then begin + DestroyWindow(hWndMain); + hWndMain := 0; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure RunAplication; +var + MsgRec : TMsg; +begin + { If GetMessage retrieves the WM_QUIT, the return value is FALSE and } + { the message loop is broken. } + while GetMessage(MsgRec, 0, 0, 0) do begin + TranslateMessage(MsgRec); + DispatchMessage(MsgRec) + end; + Terminated := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +begin + InitAplication; + try + RunAplication; + finally + CleanupAplication; + end; +end. diff --git a/ICS_zlog/Delphi/Internet/ConSrv1C.pas b/ICS_zlog/Delphi/Internet/ConSrv1C.pas new file mode 100644 index 00000000..fc7db4f0 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/ConSrv1C.pas @@ -0,0 +1,181 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: Client handling +Creation: Feb 17, 1999 +Version: 1.00 + +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit ConSrv1C; + +interface + +uses + Windows, SysUtils, Messages, Classes, WSocket, WinSock; + +const + WM_CLIENT_DISCONNECTED = WM_USER + 1; + CmdPrompt = #13#10 + '--> '; + +type + // TClientObject handle a single client communication + TClientObject = class (TObject) + protected + FCliWSocket : TWSocket; + FCtrlWindow : HWND; + FCommand : array [0..2047] of char; + FCmdLen : Integer; + FPeerName : String; + procedure DataAvailableHandler(Sender : TObject; Error : Word); + procedure SessionClosedHandler(Sender : TObject; Error : Word); + procedure CommandInterpreter; + procedure TELNET_Interpreter(CommandVerb : String; + CommandTail : String); + public + constructor Create; virtual; + destructor Destroy; override; + procedure StartClient(ASocket : TSocket); + property CtrlWindow : HWND read FCtrlWindow + write FCtrlWindow; + property PeerName : String read FPeerName; + end; + +implementation + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TClientObject.Create; +begin + inherited Create; + FCliWSocket := TWSocket.Create(nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor TClientObject.Destroy; +begin + if Assigned(FCliWSocket) then begin + FCliWSocket.Destroy; + FCliWSocket := nil; + end; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientObject.StartClient(ASocket : TSocket); +begin + FCliWSocket.LineMode := TRUE; + FCliWSocket.LineEnd := #13#10; + FCliWSocket.LineEcho := TRUE; + FCliWSocket.LineEdit := TRUE; + FCliWSocket.OnDataAvailable := DataAvailableHandler; + FCliWSocket.OnSessionClosed := SessionClosedHandler; + FCliWSocket.HSocket := ASocket; + FPeerName := FCliWSocket.GetPeerAddr; + FCliWSocket.SendStr('Welcome to ConSrv' + CmdPrompt); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientObject.SessionClosedHandler(Sender : TObject; Error : Word); +begin + PostMessage(FCtrlWindow, WM_CLIENT_DISCONNECTED, 0, LParam(Self)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +// This handler is called each time we received a complete line from +// connected client (remember we use line mode) +procedure TClientObject.DataAvailableHandler(Sender : TObject; Error : Word); +begin + // Get data from socket component. We should receive a complete line. + FCmdLen := FCliWSocket.Receive(@FCommand, SizeOf(FCommand) - 1); + if FCmdLen <= 0 then + Exit; // No data available + if FCliWSocket.State <> wsConnected then + Exit; // Ignore any data received while closing + + // Remove trailling CR/LF, if any (could be missing if our buffer + // was too small) + while (FCmdLen > 0) and (FCommand[FCmdLen - 1] in [#13, #10]) do + Dec(FCmdLen); + FCommand[FCmdLen] := #0; + + // Interpret received command + CommandInterpreter; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This is the command line interpreter. Should extend the code to support } +{ every command needed... } +procedure TClientObject.CommandInterpreter; +var + CommandVerb : String; + CommandTail : String; + I, J : Integer; +begin + { Skip leading spaces } + I := 0; + while (I < FCmdLen) and (FCommand[I] in [' ', #9]) do + Inc(I); + + { Find separator and separe CommandVerb and CommandTail } + J := I; + while TRUE do begin + if (J >= FCmdLen) then begin + SetLength(CommandVerb, FCmdLen - I); + Move(FCommand[I], CommandVerb[1], Length(CommandVerb)); + CommandTail := ''; + break; + end; + + if FCommand[J] in [' ', #9, '/'] then begin + SetLength(CommandVerb, J - I); + Move(FCommand[I], CommandVerb[1], Length(CommandVerb)); + SetLength(CommandTail, FCmdLen - J); + Move(FCommand[J], CommandTail[1], Length(CommandTail)); + break; + end; + Inc(J); + end; + CommandVerb := UpperCase(CommandVerb); + + // We could chack which port we are servicing and call appropriate + // interpeter (telnet, smtp, pop3, nntp or any line oriented protocol) + TELNET_Interpreter(CommandVerb, CommandTail); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Not a real TELNET command interpreter, just enough to see how it could } +{ be implemented. } +procedure TClientObject.TELNET_Interpreter( + CommandVerb : String; + CommandTail : String); +begin + if Length(CommandVerb) > 0 then begin + FCliWSocket.SendStr(#13#10 + 'Executing command ''' + + CommandVerb + '''...' + #13#10); + + if CommandVerb = 'EXIT' then begin + PostMessage(FCtrlWindow, WM_CLIENT_DISCONNECTED, 0, LParam(Self)); +// FCliWSocket.Close; + Exit; + end + else if CommandVerb = 'HELP' then + FCliWSocket.SendStr('List of commands:' + #13#10 + + ' Exit logoff from server' + #13#10 + + ' Help show this help screen' + #13#10) + else + FCliWSocket.SendStr('Unknown command, ignoring'); + end; + + FCliWSocket.SendStr(CmdPrompt); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. diff --git a/ICS_zlog/Delphi/Internet/ConSrv1S.pas b/ICS_zlog/Delphi/Internet/ConSrv1S.pas new file mode 100644 index 00000000..efe51cbf --- /dev/null +++ b/ICS_zlog/Delphi/Internet/ConSrv1S.pas @@ -0,0 +1,145 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: Server handling +Creation: Feb 17, 1999 +Version: 1.00 + +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit ConSrv1S; + +interface + +uses + Windows, SysUtils, Messages, Classes, WSocket, WinSock, ConSrv1C; + +type + // TServerObject handle all clients sessions + TServerObject = class (TObject) + protected + FSrvWSocket : TWSocket; + FCliList : TList; + FCtrlWindow : HWND; + procedure SessionAvailableHandler(Sender : TObject; Error : Word); + public + constructor Create; virtual; + destructor Destroy; override; + procedure StartServer; + procedure DisconnectedClient(Client : TClientObject); + procedure DisplayClientList; + property CtrlWindow : HWND read FCtrlWindow + write FCtrlWindow; + property SrvWSocket : TWSocket read FSrvWSocket; + end; + + +implementation + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TServerObject.Create; +begin + inherited Create; + FCliList := TList.Create; + FSrvWSocket := TWSocket.Create(nil); + StartServer; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor TServerObject.Destroy; +begin + if Assigned(FSrvWSocket) then begin + FSrvWSocket.Destroy; + FSrvWSocket := nil; + end; + if Assigned(FCliList) then begin + FCliList.Destroy; + FCliList := nil; + end; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerObject.StartServer; +begin + FSrvWSocket.Proto := 'tcp'; + FSrvWSocket.Port := 'telnet'; + FSrvWSocket.Addr := '0.0.0.0'; + FSrvWSocket.OnSessionAvailable := SessionAvailableHandler; + FSrvWSocket.Listen; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerObject.SessionAvailableHandler(Sender : TObject; Error : Word); +var + Client : TClientObject; + ASocket : TSocket; + SAddr : TSockAddrIn; + SAddrLen : integer; +begin + Write('Client connected: '); + + // Create a new object to handle client session + Client := TClientObject.Create; + + // Add to our client list + FCliList.Add(Client); + + // Accept the connection + ASocket := FSrvWSocket.Accept; + + // Determine who has connected before really starting the session + SAddrLen := SizeOf(SAddr); + WSocket_getpeername(ASocket, SAddr, SAddrLen); + WriteLn(WSocket_inet_ntoa(SAddr.sin_addr)); + WriteLn('There are: ', FCliList.Count, ' connected clients.'); + + // Startup the client connection (send banner) + Client.CtrlWindow := FCtrlWindow; + Client.StartClient(ASocket); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This procedure is called to disconnect a client and remove it from our } +{ client list. } +procedure TServerObject.DisconnectedClient(Client : TClientObject); +var + Index : Integer; +begin + + // Search client in our list + Index := FCliList.IndexOf(Client); + if Index < 0 then + Exit; // Not found already disconnected + + FCliList.Delete(Index); + WriteLn('Client ', Client.PeerName, ' disconnected'); + WriteLn('Remains: ', FCliList.Count, ' connected clients.'); + + // Then destroy client (this will abort the session if still active) + Client.Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerObject.DisplayClientList; +var + I : Integer; + Client : TClientObject; +begin + WriteLn('There are ', FCliList.Count, ' connected client.'); + for I := 1 to FCliList.Count do begin + Client := FCliList.Items[I - 1]; + WriteLn(I:3, ': ', Client.PeerName); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/Del40Sam.bpg b/ICS_zlog/Delphi/Internet/Del40Sam.bpg new file mode 100644 index 00000000..0b33090d --- /dev/null +++ b/ICS_zlog/Delphi/Internet/Del40Sam.bpg @@ -0,0 +1,175 @@ +#------------------------------------------------------------------------------ +VERSION = BWS.01 +#------------------------------------------------------------------------------ +!ifndef ROOT +ROOT = $(MAKEDIR)\.. +!endif +#------------------------------------------------------------------------------ +MAKE = $(ROOT)\bin\make.exe -$(MAKEFLAGS) -f$** +DCC = $(ROOT)\bin\dcc32.exe $** +BRCC = $(ROOT)\bin\brcc32.exe $** +#------------------------------------------------------------------------------ +PROJECTS = IcsDel40.bpl ThrdSrv.exe client5.exe Client7.exe concli1.exe \ + concli2.exe clidemo.exe ConFtp.exe ConHttp.exe ConSrv1.exe dnslook.exe \ + finger.exe ftpServ.exe ftpthrd.exe ftptst.exe httpasp.exe httpasy.exe \ + httpChk.exe Httpdmo.exe httpget.exe httppg.exe httpthrd.exe httptst.exe \ + MailRcv.exe MailSnd.exe md5test.exe MimeDemo.exe MimeTst.exe mtsrv.exe \ + MyYahoo.exe newsrdr.exe NsLookup.exe pingtst.exe Pop3Mime.exe Recv.exe \ + Sender.exe server5.exe srvdemo.exe SocksTst.exe DllTst1.exe TcpSrv.exe \ + tnclient.exe tndemo.exe tnsrv.exe twschat.exe udplstn.exe udpsend.exe \ + WebServ.exe IcsDll1.dll ConSmtp.exe +#------------------------------------------------------------------------------ +default: $(PROJECTS) +#------------------------------------------------------------------------------ + +ftptst.exe: ftptst.dpr + $(DCC) + +ftpServ.exe: ftpServ.dpr + $(DCC) + +IcsDel40.bpl: ..\VC32\IcsDel40.dpk + $(DCC) + +httptst.exe: httptst.dpr + $(DCC) + +httpthrd.exe: httpthrd.dpr + $(DCC) + +httpasp.exe: httpasp.dpr + $(DCC) + +httpasy.exe: httpasy.dpr + $(DCC) + +Httpdmo.exe: Httpdmo.dpr + $(DCC) + +httpget.exe: httpget.dpr + $(DCC) + +httppg.exe: httppg.dpr + $(DCC) + +md5test.exe: md5test.dpr + $(DCC) + +finger.exe: finger.dpr + $(DCC) + +client5.exe: client5.dpr + $(DCC) + +tnsrv.exe: tnsrv.dpr + $(DCC) + +concli1.exe: concli1.dpr + $(DCC) + +concli2.exe: concli2.dpr + $(DCC) + +dnslook.exe: dnslook.dpr + $(DCC) + +MimeDemo.exe: MimeDemo.dpr + $(DCC) + +MimeTst.exe: MimeTst.dpr + $(DCC) + +mtsrv.exe: mtsrv.dpr + $(DCC) + +newsrdr.exe: newsrdr.dpr + $(DCC) + +pingtst.exe: pingtst.dpr + $(DCC) + +Pop3Mime.exe: Pop3Mime.dpr + $(DCC) + +server5.exe: server5.dpr + $(DCC) + +tnclient.exe: tnclient.dpr + $(DCC) + +tndemo.exe: tndemo.dpr + $(DCC) + +twschat.exe: twschat.dpr + $(DCC) + +MailRcv.exe: MailRcv.dpr + $(DCC) + +MailSnd.exe: MailSnd.dpr + $(DCC) + +Sender.exe: Sender.dpr + $(DCC) + +Recv.exe: Recv.dpr + $(DCC) + +SocksTst.exe: SocksTst.dpr + $(DCC) + +Client7.exe: Client7.dpr + $(DCC) + +udpsend.exe: udpsend.dpr + $(DCC) + +udplstn.exe: udplstn.dpr + $(DCC) + +ftpthrd.exe: ftpthrd.dpr + $(DCC) + +srvdemo.exe: srvdemo.dpr + $(DCC) + +NsLookup.exe: NsLookup.dpr + $(DCC) + +ConSrv1.exe: ConSrv1.dpr + $(DCC) + +MyYahoo.exe: MyYahoo.dpr + $(DCC) + +TcpSrv.exe: TcpSrv.dpr + $(DCC) + +httpChk.exe: httpChk.dpr + $(DCC) + +WebServ.exe: WebServ.dpr + $(DCC) + +IcsDll1.dll: IcsDll1.dpr + $(DCC) + +DllTst1.exe: DllTst1.dpr + $(DCC) + +ThrdSrv.exe: ThrdSrv.dpr + $(DCC) + +clidemo.exe: clidemo.dpr + $(DCC) + +ConFtp.exe: ConFtp.dpr + $(DCC) + +ConHttp.exe: ConHttp.dpr + $(DCC) + +ConSmtp.exe: ConSmtp.dpr + $(DCC) + + diff --git a/ICS_zlog/Delphi/Internet/Del50Sam.bpg b/ICS_zlog/Delphi/Internet/Del50Sam.bpg new file mode 100644 index 00000000..f89c96d1 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/Del50Sam.bpg @@ -0,0 +1,184 @@ +#------------------------------------------------------------------------------ +VERSION = BWS.01 +#------------------------------------------------------------------------------ +!ifndef ROOT +ROOT = $(MAKEDIR)\.. +!endif +#------------------------------------------------------------------------------ +MAKE = $(ROOT)\bin\make.exe -$(MAKEFLAGS) -f$** +DCC = $(ROOT)\bin\dcc32.exe $** +BRCC = $(ROOT)\bin\brcc32.exe $** +#------------------------------------------------------------------------------ +PROJECTS = IcsDel50.bpl CliDemo.exe Client5.exe Client7.exe ConCli1.exe \ + ConCli2.exe ConSrv1.exe dnslook.exe Finger.exe FtpServ.exe FtpThrd.exe \ + FtpTst.exe Httpasp.exe Httpasy.exe HttpChk.exe HttpDmo.exe HttpGet.exe \ + HttpPg.exe HttpThrd.exe HttpTst.exe MailRcv.exe MailSnd.exe MD5Test.exe \ + MimeDemo.exe MimeTst.exe MtSrv.exe NewsRdr.exe NsLookup.exe PingTst.exe \ + Pop3Mime.exe Recv.exe Sender.exe Server5.exe SrvDemo.exe SocksTst.exe \ + TcpSrv.exe ThrdSrv.exe TnClient.exe TnDemo.exe TnSrv.exe TWSChat.exe UdpLstn.exe \ + UdpSend.exe DynCli.exe WebServ.exe DllTst1.exe IcsDll1.dll SrvTcp.exe \ + SvcTcp.exe IcsIsapi.dll ConHttp.exe ConSmtp.exe ConFtp.exe +#------------------------------------------------------------------------------ +default: $(PROJECTS) +#------------------------------------------------------------------------------ + +FtpTst.exe: FtpTst.dpr + $(DCC) + +FtpServ.exe: FtpServ.dpr + $(DCC) + +HttpTst.exe: HttpTst.dpr + $(DCC) + +HttpThrd.exe: HttpThrd.dpr + $(DCC) + +Httpasp.exe: Httpasp.dpr + $(DCC) + +Httpasy.exe: Httpasy.dpr + $(DCC) + +HttpDmo.exe: HttpDmo.dpr + $(DCC) + +HttpGet.exe: HttpGet.dpr + $(DCC) + +HttpPg.exe: HttpPg.dpr + $(DCC) + +MD5Test.exe: MD5Test.dpr + $(DCC) + +Finger.exe: Finger.dpr + $(DCC) + +CliDemo.exe: CliDemo.dpr + $(DCC) + +Client5.exe: Client5.dpr + $(DCC) + +TnSrv.exe: TnSrv.dpr + $(DCC) + +ConCli1.exe: ConCli1.dpr + $(DCC) + +ConCli2.exe: ConCli2.dpr + $(DCC) + +dnslook.exe: dnslook.dpr + $(DCC) + +MimeDemo.exe: MimeDemo.dpr + $(DCC) + +MimeTst.exe: MimeTst.dpr + $(DCC) + +MtSrv.exe: MtSrv.dpr + $(DCC) + +NewsRdr.exe: NewsRdr.dpr + $(DCC) + +PingTst.exe: PingTst.dpr + $(DCC) + +Pop3Mime.exe: Pop3Mime.dpr + $(DCC) + +Server5.exe: Server5.dpr + $(DCC) + +TnClient.exe: TnClient.dpr + $(DCC) + +TnDemo.exe: TnDemo.dpr + $(DCC) + +TWSChat.exe: TWSChat.dpr + $(DCC) + +MailRcv.exe: MailRcv.dpr + $(DCC) + +MailSnd.exe: MailSnd.dpr + $(DCC) + +Sender.exe: Sender.dpr + $(DCC) + +Recv.exe: Recv.dpr + $(DCC) + +SocksTst.exe: SocksTst.dpr + $(DCC) + +Client7.exe: Client7.dpr + $(DCC) + +UdpSend.exe: UdpSend.dpr + $(DCC) + +UdpLstn.exe: UdpLstn.dpr + $(DCC) + +FtpThrd.exe: FtpThrd.dpr + $(DCC) + +SrvDemo.exe: SrvDemo.dpr + $(DCC) + +NsLookup.exe: NsLookup.dpr + $(DCC) + +ConSrv1.exe: ConSrv1.dpr + $(DCC) + +TcpSrv.exe: TcpSrv.dpr + $(DCC) + +HttpChk.exe: HttpChk.dpr + $(DCC) + +IcsDel50.bpl: ..\VC32\IcsDel50.dpk + $(DCC) + +DynCli.exe: DynCli.dpr + $(DCC) + +WebServ.exe: WebServ.dpr + $(DCC) + +DllTst1.exe: DllTst1.dpr + $(DCC) + +IcsDll1.dll: IcsDll1.dpr + $(DCC) + +SrvTcp.exe: SrvTcp.dpr + $(DCC) + +SvcTcp.exe: SvcTcp.dpr + $(DCC) + +IcsIsapi.dll: IcsIsapi.dpr + $(DCC) + +ThrdSrv.exe: ThrdSrv.dpr + $(DCC) + +ConHttp.exe: ConHttp.dpr + $(DCC) + +ConSmtp.exe: ConSmtp.dpr + $(DCC) + +ConFtp.exe: ConFtp.dpr + $(DCC) + + diff --git a/ICS_zlog/Delphi/Internet/Del60Sam.bpg b/ICS_zlog/Delphi/Internet/Del60Sam.bpg new file mode 100644 index 00000000..085ad7ba --- /dev/null +++ b/ICS_zlog/Delphi/Internet/Del60Sam.bpg @@ -0,0 +1,184 @@ +#------------------------------------------------------------------------------ +VERSION = BWS.01 +#------------------------------------------------------------------------------ +!ifndef ROOT +ROOT = $(MAKEDIR)\.. +!endif +#------------------------------------------------------------------------------ +MAKE = $(ROOT)\bin\make.exe -$(MAKEFLAGS) -f$** +DCC = $(ROOT)\bin\dcc32.exe $** +BRCC = $(ROOT)\bin\brcc32.exe $** +#------------------------------------------------------------------------------ +PROJECTS = IcsDel60.bpl CliDemo.exe Client5.exe Client7.exe ConCli1.exe \ + ConCli2.exe ConSrv1.exe DllTst1.exe Dnslook.exe DynCli.exe Finger.exe \ + FtpServ.exe FtpThrd.exe FtpTst.exe HttpAsp.exe HttpAsy.exe HttpChk.exe \ + HttpDmo.exe HttpGet.exe HttpPg.exe HttpThrd.exe HttpTst.exe IcsDll1.dll \ + IcsIsapi.dll MailRcv.exe MailSnd.exe MD5Test.exe MimeDemo.exe MimeTst.exe \ + MtSrv.exe NewsRdr.exe NsLookup.exe PingTst.exe Pop3Mime.exe Recv.exe Sender.exe \ + Server5.exe SocksTst.exe SrvTcp.exe SrvDemo.exe SvcTcp.exe TcpSrv.exe \ + ThrdSrv.exe TnClient.exe TnDemo.exe TnSrv.exe TWSChat.exe UdpLstn.exe \ + UdpSend.exe WebServ.exe ConSmtp.exe ConHttp.exe ConFtp.exe +#------------------------------------------------------------------------------ +default: $(PROJECTS) +#------------------------------------------------------------------------------ + +FtpTst.exe: FtpTst.dpr + $(DCC) + +FtpServ.exe: FtpServ.dpr + $(DCC) + +HttpTst.exe: HttpTst.dpr + $(DCC) + +HttpThrd.exe: HttpThrd.dpr + $(DCC) + +HttpAsp.exe: HttpAsp.dpr + $(DCC) + +HttpAsy.exe: HttpAsy.dpr + $(DCC) + +HttpDmo.exe: HttpDmo.dpr + $(DCC) + +HttpGet.exe: HttpGet.dpr + $(DCC) + +HttpPg.exe: HttpPg.dpr + $(DCC) + +MD5Test.exe: MD5Test.dpr + $(DCC) + +Finger.exe: Finger.dpr + $(DCC) + +CliDemo.exe: CliDemo.dpr + $(DCC) + +Client5.exe: Client5.dpr + $(DCC) + +TnSrv.exe: TnSrv.dpr + $(DCC) + +ConCli1.exe: ConCli1.dpr + $(DCC) + +ConCli2.exe: ConCli2.dpr + $(DCC) + +Dnslook.exe: Dnslook.dpr + $(DCC) + +MimeDemo.exe: MimeDemo.dpr + $(DCC) + +MimeTst.exe: MimeTst.dpr + $(DCC) + +MtSrv.exe: MtSrv.dpr + $(DCC) + +NewsRdr.exe: NewsRdr.dpr + $(DCC) + +PingTst.exe: PingTst.dpr + $(DCC) + +Pop3Mime.exe: Pop3Mime.dpr + $(DCC) + +Server5.exe: Server5.dpr + $(DCC) + +TnClient.exe: TnClient.dpr + $(DCC) + +TnDemo.exe: TnDemo.dpr + $(DCC) + +TWSChat.exe: TWSChat.dpr + $(DCC) + +MailRcv.exe: MailRcv.dpr + $(DCC) + +MailSnd.exe: MailSnd.dpr + $(DCC) + +Sender.exe: Sender.dpr + $(DCC) + +Recv.exe: Recv.dpr + $(DCC) + +SocksTst.exe: SocksTst.dpr + $(DCC) + +Client7.exe: Client7.dpr + $(DCC) + +UdpSend.exe: UdpSend.dpr + $(DCC) + +UdpLstn.exe: UdpLstn.dpr + $(DCC) + +FtpThrd.exe: FtpThrd.dpr + $(DCC) + +SrvDemo.exe: SrvDemo.dpr + $(DCC) + +NsLookup.exe: NsLookup.dpr + $(DCC) + +ConSrv1.exe: ConSrv1.dpr + $(DCC) + +TcpSrv.exe: TcpSrv.dpr + $(DCC) + +HttpChk.exe: HttpChk.dpr + $(DCC) + +IcsDel60.bpl: ..\VC32\IcsDel60.dpk + $(DCC) + +DynCli.exe: DynCli.dpr + $(DCC) + +WebServ.exe: WebServ.dpr + $(DCC) + +DllTst1.exe: DllTst1.dpr + $(DCC) + +IcsDll1.dll: IcsDll1.dpr + $(DCC) + +SrvTcp.exe: SrvTcp.dpr + $(DCC) + +SvcTcp.exe: SvcTcp.dpr + $(DCC) + +IcsIsapi.dll: IcsIsapi.dpr + $(DCC) + +ThrdSrv.exe: ThrdSrv.dpr + $(DCC) + +ConSmtp.exe: ConSmtp.dpr + $(DCC) + +ConHttp.exe: ConHttp.dpr + $(DCC) + +ConFtp.exe: ConFtp.dpr + $(DCC) + + diff --git a/ICS_zlog/Delphi/Internet/Del70Sam.bpg b/ICS_zlog/Delphi/Internet/Del70Sam.bpg new file mode 100644 index 00000000..65a3876e --- /dev/null +++ b/ICS_zlog/Delphi/Internet/Del70Sam.bpg @@ -0,0 +1,184 @@ +#------------------------------------------------------------------------------ +VERSION = BWS.01 +#------------------------------------------------------------------------------ +!ifndef ROOT +ROOT = $(MAKEDIR)\.. +!endif +#------------------------------------------------------------------------------ +MAKE = $(ROOT)\bin\make.exe -$(MAKEFLAGS) -f$** +DCC = $(ROOT)\bin\dcc32.exe $** +BRCC = $(ROOT)\bin\brcc32.exe $** +#------------------------------------------------------------------------------ +PROJECTS = IcsDel70.bpl CliDemo.exe Client5.exe Client7.exe ConCli1.exe \ + ConCli2.exe ConFtp.exe ConSmtp.exe ConHttp.exe ConSrv1.exe DllTst1.exe \ + Dnslook.exe DynCli.exe Finger.exe FtpServ.exe FtpThrd.exe FtpTst.exe \ + HttpAsp.exe HttpAsy.exe HttpChk.exe HttpDmo.exe HttpGet.exe HttpPg.exe \ + HttpThrd.exe HttpTst.exe IcsDll1.dll IcsIsapi.dll MailRcv.exe MailSnd.exe \ + MD5Test.exe MimeDemo.exe MimeTst.exe MtSrv.exe NewsRdr.exe NsLookup.exe \ + PingTst.exe Pop3Mime.exe Recv.exe Sender.exe Server5.exe SocksTst.exe \ + SrvTcp.exe SrvDemo.exe SvcTcp.exe TcpSrv.exe ThrdSrv.exe TnClient.exe \ + TnDemo.exe TnSrv.exe TWSChat.exe UdpLstn.exe UdpSend.exe WebServ.exe +#------------------------------------------------------------------------------ +default: $(PROJECTS) +#------------------------------------------------------------------------------ + +FtpTst.exe: FtpTst.dpr + $(DCC) + +FtpServ.exe: FtpServ.dpr + $(DCC) + +HttpTst.exe: HttpTst.dpr + $(DCC) + +HttpThrd.exe: HttpThrd.dpr + $(DCC) + +HttpAsp.exe: HttpAsp.dpr + $(DCC) + +HttpAsy.exe: HttpAsy.dpr + $(DCC) + +HttpDmo.exe: HttpDmo.dpr + $(DCC) + +HttpGet.exe: HttpGet.dpr + $(DCC) + +HttpPg.exe: HttpPg.dpr + $(DCC) + +MD5Test.exe: MD5Test.dpr + $(DCC) + +Finger.exe: Finger.dpr + $(DCC) + +CliDemo.exe: CliDemo.dpr + $(DCC) + +Client5.exe: Client5.dpr + $(DCC) + +TnSrv.exe: TnSrv.dpr + $(DCC) + +ConCli1.exe: ConCli1.dpr + $(DCC) + +ConCli2.exe: ConCli2.dpr + $(DCC) + +Dnslook.exe: Dnslook.dpr + $(DCC) + +MimeDemo.exe: MimeDemo.dpr + $(DCC) + +MimeTst.exe: MimeTst.dpr + $(DCC) + +MtSrv.exe: MtSrv.dpr + $(DCC) + +NewsRdr.exe: NewsRdr.dpr + $(DCC) + +PingTst.exe: PingTst.dpr + $(DCC) + +Pop3Mime.exe: Pop3Mime.dpr + $(DCC) + +Server5.exe: Server5.dpr + $(DCC) + +TnClient.exe: TnClient.dpr + $(DCC) + +TnDemo.exe: TnDemo.dpr + $(DCC) + +TWSChat.exe: TWSChat.dpr + $(DCC) + +MailRcv.exe: MailRcv.dpr + $(DCC) + +MailSnd.exe: MailSnd.dpr + $(DCC) + +Sender.exe: Sender.dpr + $(DCC) + +Recv.exe: Recv.dpr + $(DCC) + +SocksTst.exe: SocksTst.dpr + $(DCC) + +Client7.exe: Client7.dpr + $(DCC) + +UdpSend.exe: UdpSend.dpr + $(DCC) + +UdpLstn.exe: UdpLstn.dpr + $(DCC) + +FtpThrd.exe: FtpThrd.dpr + $(DCC) + +SrvDemo.exe: SrvDemo.dpr + $(DCC) + +NsLookup.exe: NsLookup.dpr + $(DCC) + +ConSrv1.exe: ConSrv1.dpr + $(DCC) + +TcpSrv.exe: TcpSrv.dpr + $(DCC) + +HttpChk.exe: HttpChk.dpr + $(DCC) + +IcsDel70.bpl: ..\vc32\IcsDel70.dpk + $(DCC) + +DynCli.exe: DynCli.dpr + $(DCC) + +WebServ.exe: WebServ.dpr + $(DCC) + +DllTst1.exe: DllTst1.dpr + $(DCC) + +IcsDll1.dll: IcsDll1.dpr + $(DCC) + +SrvTcp.exe: SrvTcp.dpr + $(DCC) + +SvcTcp.exe: SvcTcp.dpr + $(DCC) + +IcsIsapi.dll: IcsIsapi.dpr + $(DCC) + +ThrdSrv.exe: ThrdSrv.dpr + $(DCC) + +ConSmtp.exe: ConSmtp.dpr + $(DCC) + +ConHttp.exe: ConHttp.dpr + $(DCC) + +ConFtp.exe: ConFtp.dpr + $(DCC) + + diff --git a/ICS_zlog/Delphi/Internet/DllTst1.dpr b/ICS_zlog/Delphi/Internet/DllTst1.dpr new file mode 100644 index 00000000..d450f7bb --- /dev/null +++ b/ICS_zlog/Delphi/Internet/DllTst1.dpr @@ -0,0 +1,13 @@ +program DllTst1; + +uses + Forms, + DllTst_1 in 'DllTst_1.pas' {DllTestForm}; + +{$R *.RES} + +begin + Application.Initialize; + Application.CreateForm(TDllTestForm, DllTestForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/DllTst_1.dfm b/ICS_zlog/Delphi/Internet/DllTst_1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..3814c3547ebd70ce661b39c88550781b6b1aa292 GIT binary patch literal 1106 zcmbW0L2uJA6vy49P0}_61mfQ74r>cX#DO+#wTW)67NZ@(OJ5gjj$Jvg>Lw&EdoZuP`?cm$wRS(%8s~h8sr$L+9Ra^g(fvjIh^>(;=?$v3?qN4YT)*n~x7%$` z<0|W2K!3I7fCzmqmvFtg>ZO=9A|;gen~4~qoU#PMsgl@>Ql@i2|M7S-9lo2<_tDYt zES}Jo{af~gi8wbTwWV;4?ed2ezu^hn8~~wgXSySALEUHHhDA`%SZ!5 znCm6zrazaFP&xRfU1wz&m{PgIH=U+d#?84L8=JJc@y)h6s}gT6<5X?^pr{p5XTh&Q zGF=;KBHcE + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +History: + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit DllTst_1; + +{$IFDEF VER80} +'Sorry, this is a demo program calling a 32 bit DLL.' +'Upgrade to latest Delphi version to use it.' +{$ENDIF} + +interface + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + IniFiles, StdCtrls, ExtCtrls, Buttons; + +type + TIcsDllDemo = function (HostName : PChar; + Port : PChar; + Buffer : PChar; + BufSize : PInteger): Integer; stdcall; + + TDllTestForm = class(TForm) + ToolsPanel: TPanel; + DisplayMemo: TMemo; + HostnameEdit: TEdit; + Label1: TLabel; + Label2: TLabel; + PortEdit: TEdit; + CallDllButton: TButton; + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure CallDllButtonClick(Sender: TObject); + procedure FormDestroy(Sender: TObject); + private + FIniFileName : String; + FInitialized : Boolean; + public + procedure Display(Msg : String); + property IniFileName : String read FIniFileName write FIniFileName; + end; + +var + DllTestForm : TDllTestForm; + DllHandle : THandle; + IcsDllDemo : TIcsDllDemo; + +implementation + +{$R *.DFM} + +const + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDllTestForm.FormCreate(Sender: TObject); +begin + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDllTestForm.FormDestroy(Sender: TObject); +begin + if DllHandle <> 0 then begin + FreeLibrary(DllHandle); + DllHandle := 0; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDllTestForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + + IniFile := TIniFile.Create(FIniFileName); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, + (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, + (Screen.Width - Width) div 2); + IniFile.Destroy; + DisplayMemo.Clear; + + DllHandle := LoadLibrary('IcsDLL1.dll'); + if DllHandle = 0 then begin + Application.MessageBox('ICSDLL1.DLL not found', 'Error', MB_OK); + Application.Terminate; + Exit; + end; + + IcsDllDemo := GetProcAddress(DllHandle, 'IcsDllDemo'); + if @IcsDllDemo = nil then begin + Application.MessageBox('IcsDllDemo not found (ICSDLL1.DLL)', + 'Error', MB_OK); + Application.Terminate; + Exit; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDllTestForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDllTestForm.Display(Msg : String); +begin + DisplayMemo.Lines.BeginUpdate; + try + if DisplayMemo.Lines.Count > 200 then begin + while DisplayMemo.Lines.Count > 200 do + DisplayMemo.Lines.Delete(0); + end; + DisplayMemo.Lines.Add(Msg); + finally + DisplayMemo.Lines.EndUpdate; + SendMessage(DisplayMemo.Handle, EM_SCROLLCARET, 0, 0); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDllTestForm.CallDllButtonClick(Sender: TObject); +var + Buffer : String; + BufSize : Integer; + Status : Integer; +begin + Display('Calling DLL...'); + BufSize := 100; + SetLength(Buffer, BufSize); + Status := IcsDllDemo(PChar(HostnameEdit.Text), + PChar(PortEdit.Text), + @Buffer[1], @BufSize); + SetLength(Buffer, BufSize); + if Status <> 0 then + Display('Error #' + IntToStr(Status)); + Display(Buffer); + Display('Done with DLL'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. diff --git a/ICS_zlog/Delphi/Internet/DnsLook1.dfm b/ICS_zlog/Delphi/Internet/DnsLook1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..ab250fa8b69a75a707db932c80993a420e13ac91 GIT binary patch literal 1427 zcmZuxL2uJA6n2s|Nz--=rb*-01KN$QLqbA`%hs;iw6qCJVB$uWxQ(^Mu56bM@dG$> z;|NFo4L^koXK?JKO`)okzUTP+zV|-A_>Tj^;UsW9@9K>|@~+3AzxSyDK>{xO4=eaixbXCfLzbB+i$k5<_3({9T7 z{N?fSa=GkLKFxc#@OU~$kaO4`WC&t@0nsew#t+a^`3*{VYJAh25y8ASAQ_=nJI-zp zPRKHZ_q-)vD471cDYHqGL$fmux@yd7YMZgdMXQ$A0m1G-%ppdU75jrudQ+PrGrz95Vj#efQLUHX!tPVk~6 zc=A6%wH<&)c%C3G35!7CFJu9G3U7P|6~TcWMz>yZC_30F+Avo@0IcwA!8yTgb-XH3 zNBT=1sa_K5?<&5>tB$NAg|dcl8Z9#3Tq|joa4|#io%OKJESGAkg9yhktE>82y$$_p zo2o*s#q_mUov;*ZgkzW!M|h1GFT%RrereYitrB|OaS?{B7jP;@muY4V37jCNB+Jes z$}ESmw~%raN7=d*W8K{THT(c6gZ2J5ob8uKy~Wwx65CbaHUG}4)x$0H|Jd7ci74*U z-{Nnjz0KbewH9rxL?3N1mU4D@6Oi~0a=ZLLu?q{wB!PCbh+LG5Aq7AKR*|0L#MC>E z+;kqN#8y!;(G8yxPE3Qx^QM$KO%iHa{hs`(C7)1kYW>bwOdJYR@u?;-vG)cfpA#%D z4Nu-QtOXu;cy-$h#VhNes&8YtJ<1j=4N(rsg6prE0mR8Di)PGfFIkaH#4QkIEm8Um zQV)C6spTwLl@{Y7)+@Xi5#a@M#o1@3_IzJvrwg8n%EYJ?m!NgPiY*hexvXa6r~2wr G0Ki`;g2Pz= literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/DnsLook1.pas b/ICS_zlog/Delphi/Internet/DnsLook1.pas new file mode 100644 index 00000000..fb0db92a --- /dev/null +++ b/ICS_zlog/Delphi/Internet/DnsLook1.pas @@ -0,0 +1,165 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: Demonstrate how to use TWSocket to asynchroneously resolve a + host name to an IP address. +Creation: October 29, 1997 +Version: 1.05 +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: +Oct 30, 1997 V1.01 Made the code compatible with Delphi 1. +Oct 31, 1997 V1.02 Added a cancel button +jan 31, 1998 V1.03 Added a scroll bar. Display addresses count +Aug 03, 1998 V1.04 Added reverse DNS lookup +Mar 13, 1999 V1.05 Added a button to get local ip list + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit DnsLook1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, WinSock, WSocket, StdCtrls; + +const + DNSLookVersion = 105; + +type + TDnsLookupForm = class(TForm) + WSocket1: TWSocket; + HostEdit: TEdit; + Label1: TLabel; + IPLabel: TLabel; + LookupButton: TButton; + CancelButton: TButton; + IPListMemo: TMemo; + ReverseLookupButton: TButton; + LocalIPButton: TButton; + procedure FormCreate(Sender: TObject); + procedure LookupButtonClick(Sender: TObject); + procedure WSocket1DnsLookupDone(Sender: TObject; Error: Word); + procedure CancelButtonClick(Sender: TObject); + procedure ReverseLookupButtonClick(Sender: TObject); + procedure LocalIPButtonClick(Sender: TObject); + end; + +var + DnsLookupForm: TDnsLookupForm; + +implementation + +{$R *.DFM} + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsLookupForm.FormCreate(Sender: TObject); +begin + IPLabel.Caption := ''; + LookupButton.Enabled := TRUE; + CancelButton.Enabled := FALSE; + HostEdit.Text := LocalHostName; + IPListMemo.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsLookupForm.LookupButtonClick(Sender: TObject); +begin + LookupButton.Enabled := FALSE; { Prevent recursive call } + ReverseLookupButton.Enabled := FALSE; + CancelButton.Enabled := TRUE; { Enable canceling } + HostEdit.SelectAll; { handy for the user } + ActiveControl := HostEdit; { he likes to have the cursor there } + IPLabel.Caption := 'Waiting for DNS...'; + IPListMemo.Clear; + WSocket1.DnsLookup(HostEdit.Text); { Start DnsLookup } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsLookupForm.ReverseLookupButtonClick(Sender: TObject); +begin + LookupButton.Enabled := FALSE; { Prevent recursive call } + ReverseLookupButton.Enabled := FALSE; + CancelButton.Enabled := TRUE; { Enable canceling } + HostEdit.SelectAll; { handy for the user } + ActiveControl := HostEdit; { he likes to have the cursor there } + IPLabel.Caption := 'Waiting for DNS...'; + IPListMemo.Clear; + WSocket1.ReverseDnsLookup(HostEdit.Text); { Start DnsLookup } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsLookupForm.WSocket1DnsLookupDone(Sender: TObject; + Error: Word); +begin + if Error = 0 then begin + IPLabel.Caption := WSocket1.DnsResult + + ' (' + IntToStr(WSocket1.DnsResultList.Count) + + ' addresses)'; + IPListMemo.Lines := WSocket1.DnsResultList; + end + else + IPLabel.Caption := 'NOT FOUND, ERROR #' + IntToStr(Error); + LookupButton.Enabled := TRUE; + ReverseLookupButton.Enabled := TRUE; + CancelButton.Enabled := FALSE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsLookupForm.CancelButtonClick(Sender: TObject); +begin + IPLabel.Caption := ''; + LookupButton.Enabled := TRUE; + CancelButton.Enabled := FALSE; + ActiveControl := HostEdit; + WSocket1.CancelDnsLookup; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsLookupForm.LocalIPButtonClick(Sender: TObject); +begin + IPListMemo.Lines := LocalIPList; + if LocalIPList.Count > 0 then + HostEdit.Text := LocalIPList.Strings[0]; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/DynCli.dpr b/ICS_zlog/Delphi/Internet/DynCli.dpr new file mode 100644 index 00000000..0264d090 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/DynCli.dpr @@ -0,0 +1,12 @@ +program DynCli; + +uses + Forms, + DynCli1 in 'DynCli1.pas' {DynCliForm}; + +{$R *.RES} + +begin + Application.CreateForm(TDynCliForm, DynCliForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/DynCli1.dfm b/ICS_zlog/Delphi/Internet/DynCli1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..c9945af3eefa5cb256e7e08149c5118f88a873ee GIT binary patch literal 1167 zcmbW0&5qMB6ouWSP13Z55ikojC~QV7P&LdOv}vnW^pA;A#R@#hZDWmVSB^)W@(4Tu zFTqQ&=W$qr^V6nfq*<`B;#lXq_Z(mUaS`r)n)>6>V0Jx0muFwA2;uqQvVnU$?lU?N za_yF%)iErU`4gE~Y|LM%wxE%U%?}l82y_)I)2-M(*(fTwb)>5Kf(dEYL)KM%KtgB^ z1Xpc8CNcqKKkfAgosVPu*&lYUgFbfi(@fJ0*@E&&Y%$!cMs|>wGJe;y-IT1sYE1$! zAUyE`kaU^r1GQt&Ku=~Y@+A-jGZ}$&T6202ESZBG@h~>NxGA_mwonaEU@aOwnrs-^ zrQexjBQtD3;dgZK`wi7PjIOxt5T?@tu1>8rJJVqF|GpZ&xRVs5H-+tqtJauuNZNst zl&_MC^%}=C@e;D$Fz_}~tRz|MeJr+#rx#BN>s7SlWKBcD*v<>HL_Ff*MIgdkP;Cn# zcTS{skjCn`K_~@dU428gl_XuEVh59(EJFi13n8P0BpU}I3(pA$W@YQUWyXs-jAqi?qTUB2MjYnv$*viXiqpVJ4e-YeylnZI@nmZv&T6p`(MJEa6~`GRu@RlYm!tXEijzi;ei8O=qZvU{*3cTCmGo(+4JKJD< + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +History: + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit DynCli1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, ExtCtrls, WSocket; + +type + TDynCliForm = class(TForm) + DisplayMemo: TMemo; + Panel1: TPanel; + Label1: TLabel; + HostnameEdit: TEdit; + PortEdit: TEdit; + Label2: TLabel; + ConnectButton: TButton; + DisconnectButton: TButton; + procedure ConnectButtonClick(Sender: TObject); + procedure DisconnectButtonClick(Sender: TObject); + private + FWSocket : TWSocket; + FRcvBuf : String; + procedure FWSocketSessionConnected(Sender: TObject; Error: Word); + procedure FWSocketSessionClosed(Sender: TObject; Error: Word); + procedure FWSocketDataAvailable(Sender: TObject; Error: Word); + public + { Déclarations publiques } + end; + +var + DynCliForm: TDynCliForm; + +implementation + +{$R *.DFM} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +procedure SetLength(var S: String; NewLength: Integer); +begin + S[0] := Chr(NewLength); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDynCliForm.ConnectButtonClick(Sender: TObject); +begin + if Assigned(FWSocket) then + FWSocket.Release; { This will close connection as needed } + { Create a new TWSocket and initialize all needed properties and events } + FWSocket := TWSocket.Create(Self); + FWSocket.Proto := 'tcp'; + FWSocket.Port := PortEdit.Text; + FWSocket.Addr := HostnameEdit.Text; + FWSocket.LineMode := TRUE; + FWSocket.LineEnd := #13#10; + FWSocket.OnSessionConnected := FWSocketSessionConnected; + FWSocket.OnSessionClosed := FWSocketSessionClosed; + FWSocket.OnDataAvailable := FWSocketDataAvailable; + try + FWSocket.Connect; + except + { Connect may fail because of invalid parameters and will trigger } + { an exception. } + on E:Exception do begin + DisplayMemo.Lines.Add('Unabled to connect: ' + + E.ClassName + ': ' + E.Message); + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDynCliForm.DisconnectButtonClick(Sender: TObject); +begin + if Assigned(FWSocket) then + FWSocket.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDynCliForm.FWSocketSessionConnected(Sender: TObject; Error: Word); +begin + if Error <> 0 then + DisplayMemo.Lines.Add('Can''t connect. Error #' + IntToStr(Error)) + else + DisplayMemo.Lines.Add('Session connected.'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDynCliForm.FWSocketSessionClosed(Sender: TObject; Error: Word); +begin + DisplayMemo.Lines.Add('Session closed.'); + { Destroy the socket. We can't use Destroy here because we are in } + { an event handler. We need to use Release which will delay destruction } + { until we are out of the event handler. } + FWSocket.Release; + FWSocket := nil; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDynCliForm.FWSocketDataAvailable(Sender: TObject; Error: Word); +begin + { Remember: we use line mode. We will always receive complete lines } + with Sender as TWSocket do + FRcvBuf := ReceiveStr; + { Remove trailing CR/LF, if any } + if (Length(FRcvBuf) > 1) and + (FRcvBuf[Length(FRcvBuf)] = #10) and + (FRcvBuf[Length(FRcvBuf) - 1] = #13) then + SetLength(FRcvBuf, Length(FRcvBuf) - 2); + { Display received line } + DisplayMemo.Lines.Add(FRcvBuf); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. diff --git a/ICS_zlog/Delphi/Internet/FTPTST2.dfm b/ICS_zlog/Delphi/Internet/FTPTST2.dfm new file mode 100644 index 0000000000000000000000000000000000000000..13389721b3f104d1e217be27d312c0b6eb0216bb GIT binary patch literal 402 zcmb8qK~94}6b9e{EZ`uGN8kjeS5PXEq%8y{Y1}!&Ynf!2X@)VS9?5%n7cbDnol?LB zOW$fgJT?*>97jTUpVWC{u`)hUvy_9xrb3U=E1LKcw+ zQ_Z%l)Rl!y`w7^-($=Tpg!G`96!tWSBPsMGpX-J4O)*fx296Ufjy2RHZjMu`y86qNu1n}^qDoLE>gE@6 C4uFmT literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/FtpServ1.dfm b/ICS_zlog/Delphi/Internet/FtpServ1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..17c59ffeecf14dd92ef0a15edc4b7b351d800728 GIT binary patch literal 3022 zcmd5;y>BB$6d&91j=hQPTuvMZNXV515=6;~1}bbPzC?;+nIPyqR6^M;wWU0Ii|Ueh1wxkuFtss>Wc8im!y2|d>pRjT-MUirCHea=EXt^8PWjwrjB z>dHh|&Fr)WBrAad321iijD$CpOI$M~Gi!|573I;Gs$&sM z%ip@j!o;=)s`^7ZleJ@UF3rTcu8fT5${#0=yGb4QJF0d$yAZfWc%L&W^ndN3&AwbH zMpgTiE(`8yoG?M7T~8|}E~1i?T8!K=QDBL2a?SMuB{}awys#5RJ*lTPpPX3_mJvdZ zKPG~5$KLnzhedY}3&)SoS|uF3k-?Mz<#{o^ zyo{f7w6yZ8HGX+7-{>;K9f^Z8lRUvCZd%_(tF;Nw2|1&DJI*ag1)(h=cJC(z_l{TY zZKTD#w$C719kmG!bAf6XkpAC+S~(7{Ir{azj!pxU1geggCZ7=g3B9z>`YXGyUVjzS zll6-KIpp8J2CDA&r!=_i$*V`6CQ1*PU^DhT4Oe6vvC1EDBUx3%cdL*+NJG}L+uP~> ztjvt9Zr0`9w8QUjbi+_NcyHHU8)K=oQ#sdjr$>aK%6a_c$zJ=o@3rCOVHz#GBihg! z!|U3!h$>TqW#kUYRh(r}8SRWo^uoYQh`6BEq6+%*L6HilD_5ZjTQ+WG=2(L1x?0Y0 zGf$WE=16oGdJ64{1<=Xyql}%W@0i|h+UWs{0ttr*G=4u5y~}H@#QTZtyLV+1Mow@x zBO=822wKKA*eRkVRlbas;l~+dk@EnQPmP}rm;yVcy2kHivUga3+gmUmX0kclBFC7( zHN+={&50H{kF2wmN23Vd;mKKPh(FBifMBfgVcUf2HFAF2ef)<-ZRQ;u;t%duWtp%c zkF&O6jR{#|XeKi~NP>Kp>9oX873P$I| z*A#7MW!mK&uv5TRCu6k<=PBen89m;z23kJNyk4{(gNCmbOs86^9lNw$0DQca@Ds>f zupD1X9%Z;r#}aZ9jXtMDg)EwLa-9h_JC@!~80j%~3gY)D?4HSm&TyQLC753R4+cMt A=Kufz literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/FtpServ1.pas b/ICS_zlog/Delphi/Internet/FtpServ1.pas new file mode 100644 index 00000000..0f081a27 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/FtpServ1.pas @@ -0,0 +1,842 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: This is a demo program showing how to use the TFtpServer + component to build a FTP server. + Waring: As this demo is writtent, full access is given to all + users to all files accessible by the computer running the demo. + In production program, you should add code to implement + security issues. +Creation: April 21, 1998 +Version: 1.06 +EMail: http://www.overbyte.be francois.piette@overbyte.be + http://www.rtfm.be/fpiette francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 1998-2001 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +History: +Apr 29, 1998 V0.90 Released for beta testing. +Apr 30, 1998 V0.91 Added an example of virtual file (see the code for + FtpServer1RetrSessionConnected. +May 01, 1998 V0.92 Adapted for Delphi 1.0 +May 03, 1998 V0.93 Adapted for Delphi 2.0 and C++Builder +May 04, 1998 V0.94 Added tools menu. +Jul 09, 1998 V1.00 Adapted for Delphi 4, removed beta status. +Jul 21, 1998 V1.01 Show how to refuse a client in OnClientConnected +Oct 25, 2000 V1.02 Added "List Clients" menu item and coding. +Jun 18, 2001 V1.03 Display version informations +Jul 30, 2001 V1.04 Add Trim function for Delphi 1 +Feb 26, 2002 V1.05 Add DisconectAll in main menu +Jun 07, 2002 V1.06 Added a processing thread (not for Delphi 1) for Get + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit FtpServ1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, IniFiles, FtpSrv, FtpSrvC, WSocket, StdCtrls, ExtCtrls, Menus, + Winsock; + +const + FtpServVersion = 106; + CopyRight : String = ' FtpServer (c) 1998-2002 F. Piette V1.06 '; + WM_APPSTARTUP = WM_USER + 1; + +type + TLogMsg = class(TComponent) + public + procedure Text(Prefix : Char; Msg : String); + end; + +{$IFNDEF VER80} { Not for Delphi 1, sorry } + TGetProcessingThread = class; { Forward declaration } + { We use our own client class to hold our thread } + TMyClient = class(TFtpCtrlSocket) + private + FWorkerThread : TGetProcessingThread; + end; + + TGetProcessingThread = class(TThread) + protected + Server : TFtpServer; + Client : TMyClient; + public + procedure Execute; override; + end; +{$ENDIF} + + TFtpServerForm = class(TForm) + FtpServer1: TFtpServer; + InfoMemo: TMemo; + Panel1: TPanel; + StartMinimizedCheckBox: TCheckBox; + MainMenu1: TMainMenu; + File1: TMenuItem; + MnuStartServer: TMenuItem; + MnuStopServer: TMenuItem; + MnuQuit: TMenuItem; + N1: TMenuItem; + About1: TMenuItem; + GreenImage: TImage; + ClientCountLabel: TLabel; + RedImage: TImage; + Tools1: TMenuItem; + Cleardisplay1: TMenuItem; + MnuListClients: TMenuItem; + N2: TMenuItem; + DisconnectAllMnu: TMenuItem; + procedure FormCreate(Sender: TObject); + procedure FtpServer1ClientConnect(Sender: TObject; + Client: TFtpCtrlSocket; Error: Word); + procedure FtpServer1ClientDisconnect(Sender: TObject; + Client: TFtpCtrlSocket; Error: Word); + procedure FtpServer1Start(Sender: TObject); + procedure FtpServer1Stop(Sender: TObject); + procedure FtpServer1ClientCommand(Sender: TObject; + Client: TFtpCtrlSocket; var Keyword, Params, Answer: TFtpString); + procedure FtpServer1StorSessionConnected(Sender: TObject; + Client: TFtpCtrlSocket; Data: TWSocket; Error: Word); + procedure FtpServer1StorSessionClosed(Sender: TObject; + Client: TFtpCtrlSocket; Data: TWSocket; Error: Word); + procedure FtpServer1RetrDataSent(Sender: TObject; + Client: TFtpCtrlSocket; Data: TWSocket; Error: Word); + procedure FtpServer1RetrSessionConnected(Sender: TObject; + Client: TFtpCtrlSocket; Data: TWSocket; Error: Word); + procedure FtpServer1RetrSessionClosed(Sender: TObject; + Client: TFtpCtrlSocket; Data: TWSocket; Error: Word); + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FtpServer1AnswerToClient(Sender: TObject; + Client: TFtpCtrlSocket; var Answer: TFtpString); + procedure FtpServer1Authenticate(Sender: TObject; + Client: TFtpCtrlSocket; UserName, Password: TFtpString; + var Authenticated: Boolean); + procedure FtpServer1ChangeDirectory(Sender: TObject; + Client: TFtpCtrlSocket; Directory: TFtpString; var Allowed: Boolean); + procedure MnuQuitClick(Sender: TObject); + procedure MnuStopServerClick(Sender: TObject); + procedure MnuStartServerClick(Sender: TObject); + procedure ImagesDblClick(Sender: TObject); + procedure FtpServer1BuildDirectory(Sender: TObject; + Client: TFtpCtrlSocket; var Directory: TFtpString; Detailed: Boolean); + procedure FtpServer1AlterDirectory(Sender: TObject; + Client: TFtpCtrlSocket; var Directory: TFtpString; Detailed: Boolean); + procedure Cleardisplay1Click(Sender: TObject); + procedure MnuListClientsClick(Sender: TObject); + procedure DisconnectAllMnuClick(Sender: TObject); + procedure FtpServer1GetProcessing(Sender: TObject; + Client: TFtpCtrlSocket; var DelayedSend : Boolean); + private + FInitialized : Boolean; + FIniFileName : String; + FPort : String; + FXTop : Integer; + FXLeft : Integer; + FXWidth : Integer; + FXHeight : Integer; + procedure WMAppStartup(var msg: TMessage); message WM_APPSTARTUP; + procedure LoadConfig; + procedure SaveConfig; + procedure StartServer; + procedure StopServer; + procedure UpdateClientCount; +{$IFNDEF VER80} + procedure WorkerThreadTerminated(Sender : TObject); +{$ENDIF} + end; + +var + FtpServerForm: TFtpServerForm; + Log : TLogMsg; + +implementation + +{$R *.DFM} + +const + MainTitle = 'FTP Server - http://www.overbyte.be'; + + { Ini file layout } + SectionData = 'Data'; + KeyPort = 'Port'; + + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + KeyMinim = 'RunMinimized'; + + STATUS_GREEN = 0; + STATUS_YELLOW = 1; + STATUS_RED = 2; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TLogMsg.Text(Prefix : Char; Msg : String); +begin +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +function TrimRight(Str : String) : String; +var + i : Integer; +begin + i := Length(Str); + while (i > 0) and (Str[i] in [' ', #9]) do + i := i - 1; + Result := Copy(Str, 1, i); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TrimLeft(Str : String) : String; +var + i : Integer; +begin + if Str[1] <> ' ' then + Result := Str + else begin + i := 1; + while (i <= Length(Str)) and (Str[i] = ' ') do + i := i + 1; + Result := Copy(Str, i, Length(Str) - i + 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function Trim(Str : String) : String; +begin + Result := TrimLeft(TrimRight(Str)); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; + Minim : Integer; +begin + if not FInitialized then begin + FInitialized := TRUE; + Caption := 'Starting ' + MainTitle; + Left := -Width; + + IniFile := TIniFile.Create(FIniFileName); + FXTop := IniFile.ReadInteger(SectionWindow, KeyTop, Top); + FXLeft := IniFile.ReadInteger(SectionWindow, KeyLeft, Left); + FXWidth := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + FXHeight := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Minim := IniFile.ReadInteger(SectionWindow, KeyMinim, 0); + + IniFile.Free; + + LoadConfig; + SaveConfig; { Create the inifile keys if they don't exists } + + { Be sure to always have the window visible } + { with a reasonable width and height } + if FXLeft < 0 then + FXLeft := 0; + if FXTop < 0 then + FXTop := 0; + if FXWidth < 310 then + FXWidth := 310; + if FXHeight <= 250 then + FXHeight := 250; + if (FXLeft + FXWidth) > Screen.Width then + FXLeft := Screen.Width - FXWidth; + if (FXTop + FXHeight) > Screen.Height then + FXTop := Screen.Height - FXHeight; + + StartMinimizedCheckBox.Checked := (Minim <> 0); + + { We use a custom message to initialize things once the form } + { is visible } + PostMessage(Handle, WM_APPSTARTUP, 0, 0); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.FormClose(Sender: TObject; + var Action: TCloseAction); +var + IniFile : TIniFile; + Minim : Integer; +begin + try + StopServer; + Minim := ord(StartMinimizedCheckBox.Checked); + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.WriteInteger(SectionWindow, KeyMinim, Minim); + IniFile.WriteString(SectionData, KeyPort, FPort); + IniFile.Free; + except + { Ignore any exception when we are closing } + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.LoadConfig; +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + FPort := IniFile.ReadString(SectionData, KeyPort, 'ftp'); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.SaveConfig; +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteString(SectionData, KeyPort, FPort); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This message handler is triggered by the FormShow event. We comes here } +{ only when the form is visible on screen. } +procedure TFtpServerForm.WMAppStartup(var msg: TMessage); +var + PrvWnd : HWND; + Buf : String; +begin + if StartMinimizedCheckBox.Checked then + Application.Minimize; + Top := FXTop; + Left := FXLeft; + Width := FXWidth; + Height := FXHeight; + + { Prevent the server from running twice } + Buf := ClassName + #0; + PrvWnd := FindWindow(@Buf[1], MainTitle); + if PrvWnd <> 0 then begin + Log.Text('E', 'Server already running. Shutdown.'); + Close; + Exit; + end; + Caption := MainTitle; + Update; { It's nice to have the form completely displayed } + + StartServer; + UpdateClientCount; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFNDEF VER80 } +{ To debug event driven programs, it is often handy to just use writeln to } +{ write debug messages to the console. To get a console, just ask the } +{ linker to build a console mode application. Then you'll get the default } +{ console. The function below will make it the size you like... } +procedure BigConsole(nCols, nLines : Integer); +var + sc : TCoord; + N : DWord; +begin + if not IsConsole then + Exit; + sc.x := nCols; + sc.y := nLines; + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), sc); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + BACKGROUND_BLUE or BACKGROUND_GREEN or + BACKGROUND_RED or BACKGROUND_INTENSITY); + sc.x := 0; + sc.y := 0; + FillConsoleOutputAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + BACKGROUND_BLUE or BACKGROUND_GREEN or + BACKGROUND_RED or BACKGROUND_INTENSITY, + nCols * nLines, sc, N); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.FormCreate(Sender: TObject); +begin + { Build Ini file name } + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; + { Create the Log object } + Log := TLogMsg.Create(Self); + +{$IFNDEF VER80} +{ BigConsole(80, 100); } +{$ENDIF} + InfoMemo.Clear; + GreenImage.Visible := FALSE; + RedImage.Visible := TRUE; + RedImage.Top := GreenImage.Top; + RedImage.Left := GreenImage.Left; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.StartServer; +var + wsi : TWSADATA; +begin + GreenImage.Visible := FALSE; + RedImage.Visible := TRUE; + Update; + + { Display version info for program and use components } + wsi := WinsockInfo; + InfoMemo.Lines.Add(Trim(CopyRight)); + InfoMemo.Lines.Add('Using:'); + InfoMemo.Lines.Add(' ' + WSocket.CopyRight); + InfoMemo.Lines.Add(' ' + FtpSrv.CopyRight); + InfoMemo.Lines.Add(' Winsock:'); + InfoMemo.Lines.Add(' Version ' + + Format('%d.%d', [WinsockInfo.wHighVersion shr 8, + WinsockInfo.wHighVersion and 15])); + InfoMemo.Lines.Add(' ' + StrPas(@wsi.szDescription)); + InfoMemo.Lines.Add(' ' + StrPas(@wsi.szSystemStatus)); +{$IFNDEF VER100} + { A bug in Delphi 3 makes lpVendorInfo invalid } + if wsi.lpVendorInfo <> nil then + InfoMemo.Lines.Add(' ' + StrPas(wsi.lpVendorInfo)); +{$ENDIF} +{$IFNDEF VER80} + { If not running 16 bits, we use our own client class } + FtpServer1.ClientClass := TMyClient; +{$ENDIF} + FtpServer1.Start; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.StopServer; +begin + FtpServer1.Stop; + FtpServer1.DisconnectAll; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.MnuQuitClick(Sender: TObject); +begin + Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.MnuStopServerClick(Sender: TObject); +begin + StopServer; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.MnuStartServerClick(Sender: TObject); +begin + StartServer; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.ImagesDblClick(Sender: TObject); +begin + if FtpServer1.Active then + StopServer + else + StartServer; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.UpdateClientCount; +begin + if FtpServer1.ClientCount = 0 then + ClientCountLabel.Caption := 'No user' + else + ClientCountLabel.Caption := IntToStr(FtpServer1.ClientCount) + ' users'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.FtpServer1ClientConnect(Sender: TObject; + Client: TFtpCtrlSocket; Error: Word); +begin + { The next test shows how to refuse a client } + if Client.GetPeerAddr = '193.121.12.25' then begin + Client.SendStr('421 Connection not allowed.' + #13#10); + Client.Close; + Exit; + end; + InfoMemo.Lines.Add('! ' + Client.GetPeerAddr + ' connected'); + UpdateClientCount; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.FtpServer1ClientDisconnect(Sender: TObject; + Client: TFtpCtrlSocket; Error: Word); +begin + InfoMemo.Lines.Add('! ' + Client.GetPeerAddr + ' disconnected'); + UpdateClientCount; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.FtpServer1Start(Sender: TObject); +begin + GreenImage.Visible := TRUE; + RedImage.Visible := FALSE; + InfoMemo.Lines.Add('! Server started'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.FtpServer1Stop(Sender: TObject); +begin + GreenImage.Visible := FALSE; + RedImage.Visible := TRUE; + InfoMemo.Lines.Add('! Server stopped'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.FtpServer1StorSessionConnected(Sender: TObject; + Client: TFtpCtrlSocket; Data: TWSocket; Error: Word); +begin + if Error <> 0 then + InfoMemo.Lines.Add('! ' + Client.GetPeerAddr + + ' Data session failed to open. Error #' + + IntToStr(Error)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.FtpServer1StorSessionClosed(Sender: TObject; + Client: TFtpCtrlSocket; Data: TWSocket; Error: Word); +begin + if Error <> 0 then + InfoMemo.Lines.Add('! ' + Client.GetPeerAddr + + ' Data session closed. Error #' + IntToStr(Error)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.FtpServer1RetrDataSent(Sender: TObject; + Client: TFtpCtrlSocket; Data: TWSocket; Error: Word); +begin + if Error <> 0 then + InfoMemo.Lines.Add('! ' + Client.GetPeerAddr + + ' Data sent. Error #' + IntToStr(Error)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when the data session for a get file has } +{ been opened. This is a good place build a file or a stream if the data } +{ requested is not already stored in a file on the file system. } +{ This feature is very powerfull and enable the FTP protocol to be used to } +{ retrieve any kind of data. It this sample, we just check for C:\VIRTUAL } +{ directory. If this directory is curent, then a TMemoryStream is created } +{ on the fly with some data. If another directory is selected, the FTP } +{ server works as any other: just send the requested file, if it exist ! } +{ This event handler is also a place where you can abort the file transfer. } +{ Simply trigger an exception and transfer will not take place. } +{ Note that if you just wants to prohibe access to some directory or file, } +{ the best place to code that is in the OnValidateGet or OnValidatePut } +{ event handlers. } +procedure TFtpServerForm.FtpServer1RetrSessionConnected(Sender: TObject; + Client : TFtpCtrlSocket; + Data : TWSocket; + Error : Word); +var + Buf : String; +begin + if Error <> 0 then + InfoMemo.Lines.Add('! ' + Client.GetPeerAddr + + ' Data session connected. Error #' + IntToStr(Error)) + else if Copy(UpperCase(Client.FilePath), 1, 19) = 'C:\VIRTUAL\FORBIDEN' then + raise Exception.Create('Access prohibed !') + else if Copy(UpperCase(Client.FilePath), 1, 11) = 'C:\VIRTUAL\' then begin + InfoMemo.Lines.Add('! VIRTUAL FILE'); + Client.UserData := 1; { Remember we created a stream } + if Assigned(Client.DataStream) then + Client.DataStream.Destroy; { Prevent memory leaks } + Client.DataStream := TMemoryStream.Create; + Buf := 'This is a file created on the fly by the FTP server' + #13#10 + + 'It could result of a query to a database or anything else.' + #13#10 + + 'The request was: ''' + Client.FilePath + '''' + #13#10; + Client.DataStream.Write(Buf[1], Length(Buf)); + Client.DataStream.Seek(0, 0); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.FtpServer1RetrSessionClosed(Sender: TObject; + Client: TFtpCtrlSocket; Data: TWSocket; Error: Word); +begin + if Error <> 0 then + InfoMemo.Lines.Add('! ' + Client.GetPeerAddr + + ' Data session closed. Error #' + IntToStr(Error)); + if Client.UserData = 1 then begin + { We created a stream for a virtual file or dir. Delete the TStream } + if Assigned(Client.DataStream) then begin + { There is no reason why we should not come here, but who knows ? } + Client.DataStream.Destroy; + Client.DataStream := nil; + end; + Client.UserData := 0; { Reset the flag } + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when the FTP component needs to build a } +{ directory listing. You can just return without doing anything then the } +{ component will build the directory for you, based on the actual disk } +{ content. But you can also build your own directory listing with anything } +{ you like in it. Just create a stream with the required content. The } +{ example below construct a virtual directory when the user is on the } +{ C:\VIRTUAL subdirectory (use elsewhere in this sample program). } +procedure TFtpServerForm.FtpServer1BuildDirectory( + Sender : TObject; + Client : TFtpCtrlSocket; + var Directory : TFtpString; + Detailed : Boolean); +var + Buf : String; +begin + if UpperCase(Client.Directory) <> 'C:\VIRTUAL\' then + Exit; + InfoMemo.Lines.Add('! VIRTUAL DIR'); + Client.UserData := 1; { Remember we created a stream } + if Assigned(Client.DataStream) then + Client.DataStream.Destroy; { Prevent memory leaks } + Client.DataStream := TMemoryStream.Create; + if Detailed then + { We need to format directory lines according to the Unix standard } + Buf := + '-rwxrwxrwx 1 ftp ftp 0 Apr 30 19:00 FORBIDEN' + #13#10 + + '-rwxrwxrwx 1 ftp ftp 0 Apr 30 19:00 TEST' + #13#10 + + 'drwxrwxrwx 1 ftp ftp 0 Apr 30 19:00 SOME DIR' + #13#10 + else + Buf := 'FORBIDEN' + #13#10 + + 'TEST' + #13#10; + Client.DataStream.Write(Buf[1], Length(Buf)); + Client.DataStream.Seek(0, 0); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called by the FTP component once it has built the } +{ directory listing. We can use this handler to alter the listing, adding } +{ or removing some info. This sample add the 'virtual' directory. } +procedure TFtpServerForm.FtpServer1AlterDirectory( + Sender : TObject; + Client : TFtpCtrlSocket; + var Directory : TFtpString; + Detailed : Boolean); +var + Buf : String; +begin + if UpperCase(Client.Directory) <> 'C:\' then + Exit; + { Add our 'virtual' directory to the list } + if Detailed then begin + { We need to format directory lines according to the Unix standard } + Buf := + 'drwxrwxrwx 1 ftp ftp 0 Apr 30 19:00 VIRTUAL' + #13#10; + Client.DataStream.Write(Buf[1], Length(Buf)); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.FtpServer1ClientCommand(Sender: TObject; + Client: TFtpCtrlSocket; var Keyword, Params, Answer: TFtpString); +begin + InfoMemo.Lines.Add('< ' + Client.GetPeerAddr + ' ' + + Keyword + ' ' + Params); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.FtpServer1AnswerToClient(Sender: TObject; + Client: TFtpCtrlSocket; var Answer: TFtpString); +begin + InfoMemo.Lines.Add('> ' + Client.GetPeerAddr + ' ' + Answer) +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.FtpServer1Authenticate(Sender: TObject; + Client: TFtpCtrlSocket; UserName, Password: TFtpString; + var Authenticated: Boolean); +begin + { You should place here the code needed to authenticate the user. } + { For example a text file with all permitted username/password. } + { If the user can't be authenticated, just set Authenticated to } + { false before returning. } + { It is also the right place to setup Client.HomeDir } + { If you need to store info about the client for later processing } + { you can use Client.UserData to store a pointer to an object or } + { a record with the needed info. } + InfoMemo.Lines.Add('! ' + Client.GetPeerAddr + + ' User ''' + UserName + ''' is authenticated'); + if Password = 'bad' then + Authenticated := FALSE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.FtpServer1ChangeDirectory(Sender: TObject; + Client: TFtpCtrlSocket; Directory: TFtpString; var Allowed: Boolean); +begin +{$IFDEF NEVER} + { It the right place to check if a user has access to a given directory } + { The example below disable C:\ access to non root user. } + if (UpperCase(Client.UserName) <> 'ROOT') and + (UpperCase(Client.Directory) = 'C:\') then + Allowed := FALSE; +{$ENDIF} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.Cleardisplay1Click(Sender: TObject); +begin + InfoMemo.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.MnuListClientsClick(Sender: TObject); +var + I : Integer; +begin + if FtpServer1.ClientCount <= 0 then begin + InfoMemo.Lines.Add('No client'); + Exit; + end; + + for I := 0 to FtpServer1.ClientCount - 1 do begin + InfoMemo.Lines.Add('Client ' + IntToStr(I + 1) + ': ' + + FtpServer1.Client[I].GetPeerAddr + '/' + + FtpServer1.Client[I].GetPeerPort); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.DisconnectAllMnuClick(Sender: TObject); +begin + FtpServer1.DisconnectAll; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} { Sorry, Delphi 1 doesn't support multi-threading } +procedure TFtpServerForm.FtpServer1GetProcessing( + Sender : TObject; + Client : TFtpCtrlSocket; + var DelayedSend : Boolean); +begin + { Nothing to do here... } +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFNDEF VER80} { 32 bits support multi-threading } +procedure TFtpServerForm.FtpServer1GetProcessing( + Sender : TObject; + Client : TFtpCtrlSocket; + var DelayedSend : Boolean); +var + MyServer : TFtpServer; + MyClient : TMyClient; +begin + MyServer := Sender as TFtpServer; + MyClient := Client as TMyClient; + { If client request a *.ZZZ file, then start a thread to do some } + { processing (here the thread just sleep 10 sec to show other clients } + { are not blocked. } + if UpperCase(ExtractFileExt(MyClient.FileName)) = '.ZZZ' then begin + MyClient.FWorkerThread := TGetProcessingThread.Create(TRUE); + MyClient.FWorkerThread.Server := MyServer; + MyClient.FWorkerThread.Client := MyClient; + MyClient.FWorkerThread.FreeOnTerminate := TRUE; + MyClient.FWorkerThread.OnTerminate := WorkerThreadTerminated; + MyClient.FWorkerThread.Resume; + { Ask server component to not start sending immediately } + { We will ask to start sending from WorkerThreadTerminated event } + DelayedSend := TRUE; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpServerForm.WorkerThreadTerminated(Sender : TObject); +var + MyThread : TGetProcessingThread; +begin + MyThread := Sender as TGetProcessingThread; + MyThread.Server.DoStartSendData(MyThread.Client); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TGetProcessingThread.Execute; +begin + Sleep(10000); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + + diff --git a/ICS_zlog/Delphi/Internet/FtpThrd1.dfm b/ICS_zlog/Delphi/Internet/FtpThrd1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..278ad6948d876747a0d50338354b029d85a0516f GIT binary patch literal 619 zcmaKo&r-rL5XM6aZE0cT>W!-x2OmLjIxvFm&^TNTbb*W^VZ!pqH}K#)=u3Lm(w2f3 zFUf8)-}l@7emufhfBX=zC3AOtm7E81~Do&5DQD|j1QW@|Bl6LCv1zO>4PfKl_#!OCxO7xz=0sZVFSJUr$ z);;kR*v(Pgj=9>jV=!W#>tlSA;FD$~4j?xXn1Pxt>5F$XDlD4BWka#Su0FWMeU}YQ zvzh5lF>+Xr+^^K`rC2D(<+3LQDD(yhtCOEU+Da5LNSI;WWqcZ%1WcL}v020wNIN_K zKu)=okQAFUYFwttd0p6n47UizsZV!9y$1uy*}Os=*4-j%<;Tbk=5@YC=NLV8^EK#W z5j?#vbFXERvl($hmF_irby^o@*$XK-Ud(rJfw8{wxc=c(kCHQ{Qev*oUIm4aUpJk+ Ay8r+H literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/FtpThrd1.pas b/ICS_zlog/Delphi/Internet/FtpThrd1.pas new file mode 100644 index 00000000..eafc23a4 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/FtpThrd1.pas @@ -0,0 +1,168 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE + Used code from Frank Neuhaus . +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Creation: December 22, 1998 +Version: 1.00 +Object: Demo for threaded TFtpCli use (not the best way to use the + component, but some like to use threads). +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +Updates: + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit FtpThrd1; + +interface + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + ExtCtrls, StdCtrls; + +type + TThrdFtpForm = class(TForm) + ListBox1: TListBox; + Panel1: TPanel; + StartButton: TButton; + SaveButton: TButton; + procedure StartButtonClick(Sender: TObject); + procedure SaveButtonClick(Sender: TObject); + end; + + TTransferThread = class(TThread) + private + FMsg : String; + public + constructor CreateThread; + procedure AddToListBox; + procedure Display(Msg: String); + procedure CliDisplay(Sender: TObject; var Msg: String); + procedure Execute ; override; + end; + +var + ThrdFtpForm: TThrdFtpForm; + +implementation +{$R *.DFM} + +uses + FtpCli; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TThrdFtpForm.StartButtonClick(Sender: TObject); +begin + TTransferThread.CreateThread; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TThrdFtpForm.SaveButtonClick(Sender: TObject); +begin + ListBox1.Items.SaveToFile('FtpThrd.Log'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TTransferThread.CreateThread; +begin + FreeOnTerminate := TRUE; + inherited Create(FALSE); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTransferThread.Execute; +var + FtpClient1 : TFtpClient; +begin + FtpClient1 := TFtpClient.Create(nil); + FtpClient1.OnDisplay := CliDisplay; + FtpClient1.OnProgress := nil; + FtpClient1.OnRequestDone := nil; + FtpClient1.OnSessionConnected := nil; + FtpClient1.OnSessionClosed := nil; + FtpClient1.OnStateChange := nil; + FtpClient1.Multithreaded := TRUE; + FtpClient1.Timeout := 60; // default is 15 + + FtpClient1.HostName := 'localhost'; + FtpClient1.Port := 'ftp'; + FtpClient1.UserName := 'fpiette'; + FtpClient1.Password := 'fp'; + FtpClient1.DisplayFileFlag := TRUE; + FtpClient1.LocalFileName := 'c:\temp\data1.txt'; + FtpClient1.HostDirName := 'c:\temp'; + FtpClient1.HostFileName := 'tofile.txt'; + + if not FtpClient1.Connect then begin + Display('Connect failed'); + FtpClient1.Abort; + Exit; + end; + if not FtpClient1.Put then begin + Display('Put failed'); + FtpClient1.Abort; + Exit; + end; + if not FtpClient1.Quit then begin + Display('Quit failed'); + FtpClient1.Abort; + Exit; + end; + Display('Finished ok.'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTransferThread.CliDisplay(Sender: TObject; var Msg: String); +begin + Display(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTransferThread.Display(Msg : String); +begin + FMsg := Msg; + Synchronize(AddToListBox); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTransferThread.AddToListBox; +begin + ThrdFtpForm.ListBox1.Items.Add(FMsg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/Ftptst2.pas b/ICS_zlog/Delphi/Internet/Ftptst2.pas new file mode 100644 index 00000000..2a390e63 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/Ftptst2.pas @@ -0,0 +1,25 @@ +unit FtpTst2; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls; + +type + TDirectoryForm = class(TForm) + DirListBox: TListBox; + private + { Déclarations privées } + public + { Déclarations publiques } + end; + +var + DirectoryForm: TDirectoryForm; + +implementation + +{$R *.DFM} + +end. diff --git a/ICS_zlog/Delphi/Internet/HLembke/NsLook1.dfm b/ICS_zlog/Delphi/Internet/HLembke/NsLook1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..2570bd4a54f284303bd15d24f789dc00babbe770 GIT binary patch literal 1599 zcmb_b%~IPi5LTSTb{s+&N`JULyc zLf-&hr?*_%$&^F7l46IS(q8IB(rQ<`-|E}d)Iom3t2LYZhplS!ppLedHcW*4R&}f3 zH=-J2XM=u~@!rDSO{RuVL^_p9`>dbdO=XY5j_9Ue80H=hPrD-h9a(PB7a^nOawF*B zH4pQ1%-3|dtjh@FR<2FTf>whzUZ^rEHr;N(BP^_9Wv5y?toiTVz0!fV<2%}_d=}c| zD5M=W^zntrD}#nKe&p0nqM3!dx8?;jlCa^4_V>hy;5=Gvl8(!9AaIj+Fwa>{>Jk=V z3*326i8iRz2@5d`86jn;l4V9wnTf9L2OkxW213a6TLHzyRP*-T`=W>U1qSqW zvjG7@=3!F6+)gJHR)t1#)lpt4*4A_sV>IhB#rm=CUcJ>X;H$1@9C1I%ENTDTdh9n()=*6sw$H3*u~7$w%D2xHWGLWi zEV~2;eAYu{rP8ov_3(@sb~T1wonxdEjF*q2C>&>(jQZWpN+1H~7nJWOjB;Jh@;isI z0b^-4QYZrwLYHdRleEphOKrToRA=N2BD%S`ffWQaRev;{N(l!1qzb0t>;pAiemE?G za{9zNmii)^=Cyr%{Y{2Y7;*g1u5#8B$2n#;!CXnK_xcLu ue0Wyx2AGd>v9O(KF)mEw&Feyw9^g*{9El2}*jh + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +History: +Feb 27, 1999 V1.01 Added PTR lookup (reverse DNS lookup) +Mar 07, 1999 V1.02 Adapted for Delphi 1 + +Aug 11, 2002 V1.99 Modified for new TDnsQuery-Oject + all changed lines have been commented with a //!!KAP!! + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit NsLook1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, IniFiles, WinSock, DnsQuery, StdCtrls, ExtCtrls, Buttons; + +type + TNsLookupForm = class(TForm) + DisplayMemo: TMemo; + Panel1: TPanel; + DnsEdit: TEdit; + NameEdit: TEdit; + MXLookupButton: TButton; + DnsQuery1: TDnsQuery; + ClearDisplayBitBtn: TBitBtn; + ALookupButton: TButton; + PTRLookupButton: TButton; + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure MXLookupButtonClick(Sender: TObject); + procedure DnsQuery1RequestDone(Sender: TObject; Error: Word); + procedure ClearDisplayBitBtnClick(Sender: TObject); + procedure ALookupButtonClick(Sender: TObject); + procedure PTRLookupButtonClick(Sender: TObject); + private + FIniFileName : String; + FInitialized : Boolean; + FRequestID : Integer; + procedure Display(Msg : String); + procedure DumpDnsResponse; + public + property IniFileName : String read FIniFileName write FIniFileName; + end; + +var + NsLookupForm: TNsLookupForm; + +implementation + +{$R *.DFM} + +const + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + SectionData = 'Data'; + KeyName = 'Name'; + KeyDns = 'Dns'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.FormCreate(Sender: TObject); +begin + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + + IniFile := TIniFile.Create(FIniFileName); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, + (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, + (Screen.Width - Width) div 2); + NameEdit.Text := IniFile.ReadString(SectionData, KeyName, 'inprise.com'); + DnsEdit.Text := IniFile.ReadString(SectionData, KeyDns, '193.121.171.135'); + DisplayMemo.Clear; + IniFile.Destroy; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.WriteString(SectionData, KeyName, NameEdit.Text); + IniFile.WriteString(SectionData, KeyDns, DnsEdit.Text); + IniFile.Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.Display(Msg : String); +begin + if DisplayMemo.Lines.Count > 200 then + DisplayMemo.Lines.Delete(0); + DisplayMemo.Lines.Add(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.DumpDnsResponse; +var + P : PChar; + I : Integer; + Len : Integer; + Buf : String; +begin + Display('Response dump (' + IntToStr(DnsQuery1.Response.len) + ' bytes):'); //!!KAP!! + P := DnsQuery1.ResponseBuf; + Len := DnsQuery1.Response.Len; //!!KAP!! + Buf := ''; + I := 0; + while I < Len do begin + if P^ in [' '..'~'] then + Buf := Buf + P^ + else + Buf := Buf + '<' + IntToStr(Ord(P^)) + '>'; + Inc(I); + Inc(P); + if (I mod 16) = 0 then begin + Display(' ' + Buf); + Buf := ''; + end; + end; + if Length(Buf) > 0 then + Display(' ' + Buf); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.DnsQuery1RequestDone(Sender: TObject; Error: Word); +var + I : Integer; + nIndex : Integer; +begin + if Error <> 0 then begin + Display('Error #' + IntToStr(Error)); + Exit; + end; + // !!KAP!! start of changes + //!!KAP!! added lots of '.'... + Display('ID : ' + IntToStr(DnsQuery1.Response.ID)); + Display('ResponseCode : ' + IntToStr(DnsQuery1.Response.rCode)); //!!KAP!! added ..r + Display('OpCode : ' + IntToStr(DnsQuery1.Response.OpCode)); + Display('Authoritative : ' + IntToStr(Ord(DnsQuery1.Response.AuthoritativeAnswer))); //!!KAP!! added ..Answer + Display('Truncation : ' + IntToStr(Ord(DnsQuery1.Response.Truncation))); + Display('RecursionAvailable : ' + IntToStr(Ord(DnsQuery1.Response.RecursionAvailable))); + Display('QDCount : ' + IntToStr(DnsQuery1.Response.QDCount)); + Display('ANCount : ' + IntToStr(DnsQuery1.Response.ANCount)); + Display('NSCount : ' + IntToStr(DnsQuery1.Response.NSCount)); + Display('ARCount : ' + IntToStr(DnsQuery1.Response.ARCount)); + Display('ResponseLen : ' + IntToStr(DnsQuery1.Response.Len)); + Display('QuestionName : ' + DnsQuery1.Question.QuestionName); //!!KAP!! added Question... + Display('QuestionType : ' + IntToStr(DnsQuery1.Question.QuestionType)); //!!KAP!! added Question... + Display('QuestionClass : ' + IntToStr(DnsQuery1.Question.QuestionClass)); //!!KAP!! added Question... + + + // !!KAP!! new style of access + // Attention: some records only exists, if the appropriated request has been done + // display the Name Server items + Display(''); + for i:=0 to DnsQuery1.ResponseCount[DnsQueryNS]-1 do begin + Display(' Nameserver: '+DnsQuery1.ResponseItem[DnsQueryNS,i].nsdname); + end; + Display(''); + // or the MX records + for i:=0 to DnsQuery1.ResponseCount[DnsQueryMX]-1 do begin + Display(' MailExchange: '+DnsQuery1.ResponseItem[DnsQueryMX,i].mx.exchange); + end; + Display(''); + + // !!KAP!! but possible to loop throu all items + for i:=0 to dnsquery1.ResponseCount[0]-1 do begin + Display('Item for: '+dnsquery1.ResponseItem[0,i].name); + case dnsquery1.ResponseItem[0,i].rrtype of + DnsQueryA : Display(' DnsQueryA: ' + dnsquery1.ResponseItem[0,i].ipnummer); + DnsQueryMD, + DnsQueryMB, + DnsQueryMF : Display(' Answer: ' + dnsquery1.ResponseItem[0,i].madname); + DnsQueryCNAME : Display(' Cname: ' + dnsquery1.ResponseItem[0,i].cname); + DnsQueryMG : Display(' MGMName: ' + dnsquery1.ResponseItem[0,i].mgmname); + DnsQueryMR : Display(' NewName: ' + dnsquery1.ResponseItem[0,i].newname); + DnsQueryPTR : Display(' PTRName: ' + dnsquery1.ResponseItem[0,i].ptrname); + DnsQueryAAAA : Display(' AAAA (ipv6): ' + dnsquery1.ResponseItem[0,i].ip6nummer); + DnsQueryMINFO : Display(' MInfo r: ' + dnsquery1.ResponseItem[0,i].minfo.rmailbx+ + ' MInfo re: ' + dnsquery1.ResponseItem[0,i].minfo.remailbx); + DnsQueryTXT : Display(' TXT: ' + dnsquery1.ResponseItem[0,i].txt); + DnsQueryHINFO : Display(' HInfo: CPU=' + inttostr(dnsquery1.ResponseItem[0,i].hinfo.cpu)+ + ' OS=' + inttostr(dnsquery1.ResponseItem[0,i].hinfo.os)); + DnsQueryNS : Display(' Nameserver: ' + dnsquery1.ResponseItem[0,i].nsdname); + DnsQueryMX : Display(' MailExchange: ' + dnsquery1.ResponseItem[0,i].mx.exchange+ + ' '+ + inttostr(dnsquery1.ResponseItem[0,i].mx.preference)); + end; + end; + Display(''); + // !!KAP!! end of changes + +(* !!KAP!! This type of access is not longer possible + for I := 0 to DnsQuery1.ResponseANCount - 1 do begin + Display('Answer #' + IntToStr(I + 1)); + Display(' AnswerName : ' + DnsQuery1.AnswerName[I]); + Display(' AnswerType : ' + IntToStr(DnsQuery1.AnswerType[I])); + Display(' AnswerClass : ' + IntToStr(DnsQuery1.AnswerClass[I])); + Display(' AnswerTTL : ' + IntToStr(DnsQuery1.AnswerTTL[I])); + nIndex := DnsQuery1.AnswerTag[I]; + if nIndex >= 0 then begin + case DnsQuery1.AnswerType[I] of + DnsQueryMX: + begin + Display(' MXPreference : ' + IntToStr(DnsQuery1.MXPreference[nIndex])); + Display(' MXExchange : ' + DnsQuery1.MXExchange[nIndex]); + end; + DnsQueryA: + begin + Display(' Address : ' + StrPas(inet_ntoa(DnsQuery1.Address[nIndex]))); + end; + DnsQueryPTR: + begin + Display(' Hostname : ' + DnsQuery1.Hostname[nIndex]); + end; + end; + end; + end; +*) + { Dump complete response } + DumpDnsResponse; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.ClearDisplayBitBtnClick(Sender: TObject); +begin + DisplayMemo.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.MXLookupButtonClick(Sender: TObject); +begin + DnsQuery1.Addr := DnsEdit.Text; + FRequestID := DnsQuery1.MXLookup(NameEdit.Text); + Display('Request ID : ' + IntToStr(FRequestID)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.ALookupButtonClick(Sender: TObject); +begin + DnsQuery1.Addr := DnsEdit.Text; + FRequestID := DnsQuery1.ALookup(NameEdit.Text); + Display('Request ID : ' + IntToStr(FRequestID)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.PTRLookupButtonClick(Sender: TObject); +begin + DnsQuery1.Addr := DnsEdit.Text; + FRequestID := DnsQuery1.PTRLookup(NameEdit.Text); + Display('Request ID : ' + IntToStr(FRequestID)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. diff --git a/ICS_zlog/Delphi/Internet/HLembke/NsLookup.dpr b/ICS_zlog/Delphi/Internet/HLembke/NsLookup.dpr new file mode 100644 index 00000000..914dbc80 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/HLembke/NsLookup.dpr @@ -0,0 +1,12 @@ +program NsLookup; + +uses + Forms, + NsLook1 in 'NsLook1.pas' {NsLookupForm}; + +{$R *.RES} + +begin + Application.CreateForm(TNsLookupForm, NsLookupForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/HLembke/ReadMe.txt b/ICS_zlog/Delphi/Internet/HLembke/ReadMe.txt new file mode 100644 index 00000000..254b0198 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/HLembke/ReadMe.txt @@ -0,0 +1,9 @@ +This HLembke directory contains a revised DnsLookup component +by Holger Lembke and corresponding NsLookup +project. + +This revised DnsLookup component will replace ICS original DnsQuery +component in the future. + +francois.piette@overbyte.be + diff --git a/ICS_zlog/Delphi/Internet/HLembke/dnsquery.pas b/ICS_zlog/Delphi/Internet/HLembke/dnsquery.pas new file mode 100644 index 00000000..d747bfc2 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/HLembke/dnsquery.pas @@ -0,0 +1,1050 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: Component to query DNS records. + Implement a subset of RFC 1035 (A and MX records). +Creation: January 29, 1999 +Version: 1.03 +EMail: http://www.overbyte.be francois.piette@overbyte.be + http://www.rtfm.be/fpiette francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 1999-2001 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +History: +Feb 14, 1999 V0.02 Indirectly call winsock functions using wsocket because + wsocket provide runtime dynamic link instead of loadtime link. + This allows a program to use DnsQuery if it discover that winsock + is installed and still run if winsock is not installed. +Feb 24, 1999 V1.00 Added code for reverse lookup (PTR record). +Mar 07, 1999 V1.01 Adapted for Delphi 1 +Aug 20, 1999 V1.02 Revise compile time option. Adapted for BCB4 +Jul 27, 2001 V1.03 Holger Lembke implemented a few new + queries or propreties (QueryAny, LongLatToDMS, Loc2Geo, Loc) + and related data types. +----------------------------- +Jul 27, 2002 V1.80 Holger Lembke has rewritten major parts + after error corrections, I suggest a jump to 2.01 + + changed almost everything. goal was + - to have a more comprehensive componente + - ease to implemente future DNS extentions/missing records + (future in meaning of this component. not really the dns system.) + + Users from 1.03 and before should be able to adapt code quickly. + - all the response... and question... things moved into a record, so + just add a point after response + - all array-properties are gone. + instead, you have to use a loop to run throu the desired types + + for i:=0 to dnsquery.ResponseCount[DnsQueryNS]-1 do + with dnsquery.ResponseItem[DnsQueryNS,i] do begin + writeln(nsdname); + end; + + Look up in TRRRecord, which record parts are defined for a + specific item. + + To add new records, follow this guidelines: + 1.) define the DNSQuery-Constant + 2.) Define the needed record + only one rule: no dynamic memory allocation + 3.) add it into the case structure in TRRRecord + 4.) add a 'decoder' into GetResponseItem + +Aug 30, 2002 V1.81 fixed a minor error in SubLOCgeo Holger Lembke + +----------------------------- + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit DnsQuery; + +{$B-} { Enable partial boolean evaluation } +{$T-} { Untyped pointers } +{$R-} { Disable range checking } +{$IFNDEF VER80} { Not for Delphi 1 } + {$H+} { Use long strings } + {$J+} { Allow typed constant to be modified } +{$ENDIF} +{$IFDEF VER110} { C++ Builder V3.0 } + {$ObjExportAll On} +{$ENDIF} +{$IFDEF VER125} { C++ Builder V4.0 } + {$ObjExportAll On} +{$ENDIF} + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + Winsock, WSocket; + +const + DnsQueryVersion = 102; + CopyRight : String = ' TDnsQuery (c) 1999-2000 F. Piette V1.02 '; + + { DNS Classes } + DnsClassIN = 1; { The internet } + DnsClassCS = 2; { The CSNET class (obsolete, used only for examples)} + DnsClassCH = 3; { The CHAOS class } + DnsClassHS = 4; { Hesiod name service } + DnsClassALL = 255; { Any class } + + { Type of query/response a DNS can handle } + DnsQueryA = 1; { A HostAddress } + DnsQueryNS = 2; { NS Authoritative name server } + DnsQueryMD = 3; { MD MailDestination, obsolete, use Mail Exchange } + DnsQueryMF = 4; { MF MailForwarder, obsolete, use Mail Exchange } + DnsQueryCNAME = 5; { CNAME CanonicalName } + DnsQuerySOA = 6; { SOA Start of a Zone of Authority } + DnsQueryMB = 7; { MB MailBox, experimental } + DnsQueryMG = 8; { MG MailGroup, experimental } + DnsQueryMR = 9; { MR MailRename, experimental } + DnsQueryNULL = 10; { NULL Experimental } + DnsQueryWKS = 11; { WKS Well Known Service Description } + DnsQueryPTR = 12; { PTR Domain Name Pointer } + DnsQueryHINFO = 13; { HINFO Host Information } + DnsQueryMINFO = 14; { MINFO Mailbox information } + DnsQueryMX = 15; { MX Mail Exchange } + DnsQueryTXT = 16; { TXT Text Strings } + { !!KAP!! } + DnsQueryRP = 17; // RFC 1183 + DnsQueryAFSDB = 18; // RFC 1183 + DnsQueryX25 = 19; // RFC 1183 + DnsQueryISDN = 20; // RFC 1183 + DnsQueryRT = 21; // RFC 1183 + DnsQueryNSAP = 22; // RFC 1706 + DnsQueryNSAPPTR = 23; + DnsQuerySIG = 24; { see RFC-2065 } + DnsQueryKEY = 25; { see RFC-2065 } + DnsQueryPX = 26; // rfc 1327? + DnsQueryGPOS = 27; { GPOS has the following format: + GPOS } + DnsQueryAAAA = 28; { see IP6 Address } + DnsQueryLOC = 29; (* see RFC-1876 http://rfc.net/rfc1876.html + LOC ( d1 [m1 [s1]] {"N"|"S"} d2 [m2 [s2]] + {"E"|"W"} alt["m"] [siz["m"] [hp["m"] + [vp["m"]]]] ) + *) + DnsQueryNXT = 30; { see RFC-2065 } + + DnsQuerySRV = 33; { see RFC-2052 } + DnsQueryNAPTR = 35; { see RFC-2168 } + DnsQueryKX = 36; + + { Some additional type only allowed in queries } + DnsQueryAXFR = 252; { Transfer for an entire zone } + DnsQueryMAILB = 253; { Mailbox related records (MB, MG or MR) } + DnsQueryMAILA = 254; { MailAgent, obsolete, use MX instead } + DnsQueryALL = 255; { Request ALL records } + + { Opcode field in query flags } + DnsOpCodeQUERY = 0; + DnsOpCodeIQUERY = 1; + DnsOpCodeSTATUS = 2; + +type + TDnsRequestDoneEvent = procedure (Sender : TObject; Error : WORD) of Object; + + TDnsRequestHeader = packed record + ID : WORD; + flags : word; + QDCount : WORD; + ANCount : WORD; + NSCount : WORD; + ARCount : WORD; + end; + PDnsRequestHeader = ^TDnsRequestHeader; + + // rfc 1035 p.10 + tname = string[255]; + ttxtstring = string[255]; + tadress = cardinal; //32bit + + // rfc 1035 p.26 + TDnsRequestAnswerHeader = record // + len : integer; + ID : WORD; + qr : boolean; + opcode : byte; + AuthoritativeAnswer : boolean; + Truncation : boolean; + RecursionDesired : boolean; + RecursionAvailable : boolean; + z : byte; + rcode : byte; + QDCount : WORD; + ANCount : WORD; + NSCount : WORD; + ARCount : WORD; + end; + + // rfc 1035 p.19 + TSoaRecord = record + mname : tname; + rname : tname; + serial : Cardinal; + refresh : Cardinal; + retry : Cardinal; + expire : Cardinal; + minimum : Cardinal; + end; + + // rfc 1876 + TLOCInfo = packed record { need to be 16 bytes } + version : byte; + size : byte; + horizpre : byte; + vertpre : byte; + latitude : longint; + longitude : longint; + altitude : longint; + end; + PLOCInfo = ^TLOCInfo; + + // RFC 1886 p.2 + TAAAA = array[0..3] of Cardinal; // 128 bit + + { Decoded TLOCInfo } + TLogGeo = record + version : byte; + longsize : integer; + latsize : integer; + horizpre : integer; + vertpre : integer; + { Latitude, degree, minutes, seconds, milliseconds } + lad, lam, las, lams : integer; + lahem : char; + { same for Longitude } + lod, lom, los, loms : integer; + lohem : char; + altitude : integer; + end; + + // Question Data rfc1035 p.28 + TQuestion = record + QuestionType : word; + QuestionClass : word; + QuestionName : tname; + end; + + // rfc 1035 p.14 + THinfo = packed record + cpu : word; + os : word; + end; + + // rfc 1035 p.16 + TMinfo = packed record + rmailbx : tname; + remailbx : tname; + end; + + // rfc 1035 p.17 + TMX = record + preference : word; + exchange : tname; + end; + + // rfc 1035 p.10 + TRRInternal = packed record + rrtype : word; // r due to token conflict + rrclass : word; // same + rrttl : cardinal; // same + rdlength : word; + end; + pRRInternal = ^TRRInternal; + + // Result-Record + TRRRecord = packed record + valid : boolean; + + // internal for caching + lastid : integer; + lastindex : integer; + + // RR record start rfc 1035 p.29 + name : tname; + rrtype : word; // r due to token conflict + rrclass : word; // same + rrttl : cardinal; // same + rdlength : word; + + case integer of // depending on rrtype, one of these structures is filled + // more or less following rfc 1035 p.15 + DnsQueryMD, + DnsQueryMB, + DnsQueryMF : (madname : tname); + DnsQueryCNAME : (cname : tname); + DnsQueryHINFO : (hinfo : thinfo); + DnsQueryMG : (mgmname : tname); + DnsQueryMINFO : (minfo : tminfo); + DnsQueryMR : (newname : tname); + DnsQueryNS : (nsdname : tname); + DnsQueryPTR : (ptrname : tname); + DnsQuerySOA : (soa : TSoaRecord); + DnsQueryTXT : (txt : ttxtstring); + DnsQueryMX : (mx : TMX); + DnsQueryA : (adress : tadress; + ipnummer : tname); // interpreted + DnsQueryAAAA : (aaaa : TAAAA; + ip6nummer : tname); // interpreted + DnsQueryLOC : (loc : TLOCInfo; + locdecode : TLogGeo); // interpreted + end; + + // for a quicker access + tdatacacheitem = record + rrtype : word; + rrpos : pchar; + end; + tdatacache = record + count : integer; + items : array of tdatacacheitem; + end; + + TDnsQuery = class(TComponent) + private + { Déclarations privées } + frrcache : TRRRecord; + fdatacache : tdatacache; + fDnsRequestAnswer : TDnsRequestAnswerHeader; + fquestion : TQuestion; + + function NewExtractName(var p : pchar):string; + function GetRepsonsecount(nid : integer):integer; + function GetResponseItem(nid : integer; nindex : integer):TRRRecord; + + protected + FWSocket : TWSocket; + FPort : String; + FAddr : String; + FIDCount : WORD; + FQueryBuf : array [0..511] of char; + FQueryLen : Integer; + + FResponseBuf : array [0..511*8] of char; // 4k genug? irgendwie wäre mir dynamisch ja lieber... + FResponseLen : Integer; + + FOnRequestDone : TDnsRequestDoneEvent; + + { !!KAP!! } + fQueryPending : boolean; + + procedure BuildRequestHeader(Dst : PDnsRequestHeader; + ID : WORD; + OPCode : BYTE; + Recursion : Boolean; + QDCount : WORD; + ANCount : WORD; + NSCount : WORD; + ARCount : WORD); virtual; + function BuildQuestionSection(Dst : PChar; + const QName : String; + QType : WORD; + QClass : WORD) : Integer; virtual; + procedure WSocketDataAvailable(Sender: TObject; Error: WORD); virtual; + procedure TriggerRequestDone(Error: WORD); virtual; + function GetResponseBuf : PChar; + procedure SendQuery; + + { !!KAP!! 2002-02-15} + procedure DNSSocketSessionClosed(Sender: TObject; Error: Word); + public + constructor Create(AOwner : TComponent); override; + destructor Destroy; override; + procedure Notification(AComponent: TComponent; operation: TOperation); override; + function MXLookup(Domain : String) : Integer; + function ALookup(Host : String) : Integer; + function PTRLookup(IP : String) : Integer; + { !!KAP!! } + function QueryAny(Host : String; QNumber : Integer) : Integer; + // Query this to see if dns-request is pending + property QueryPending : Boolean read fQueryPending; + + { !!KAP!! 2002-02-15} + procedure AbortPending; + + { !!KAP!! 2002-07-27} + property Response : TDnsRequestAnswerHeader read fDnsRequestAnswer; + property ResponseBuf : PChar read GetResponseBuf; + // 0 : all items, otherwise the queryitems + property ResponseCount[nid : integer]:integer read GetRepsonsecount; + property ResponseItem[nid : integer; nindex : integer]: TRRRecord read GetResponseItem; + + // simpler + property Question : TQuestion read fQuestion; + published + property Port : String read FPort write FPort; + property Addr : String read FAddr write FAddr; + property OnRequestDone : TDnsRequestDoneEvent read FOnRequestDone + write FOnRequestDone; + end; + + +function ReverseIP(const IP : String) : String; +function LongLatToDMS(longlat : longint; hemis : String) : String; { !!KAP!! } +function Loc2Geo(loc : TLOCInfo) : TLogGeo; { !!KAP!! } +function LocAltToAlt(Localt : LongInt) : LongInt; { !!KAP!! } +procedure Register; + +// should compile. +Const RRRecordsize = sizeof(TRRRecord); + +implementation + +type + PWORD = ^WORD; + PDWORD = ^DWORD; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function ReverseIP(const IP : String) : String; +var + I, J : Integer; +begin + Result := ''; + if Length(IP) = 0 then + Exit; + J := Length(IP); + I := J; + while I >= 0 do begin + if (I = 0) or (IP[I] = '.') then begin + Result := Result + '.' + Copy(IP, I + 1, J - I); + J := I - 1; + end; + Dec(I); + end; + if Result[1] = '.' then + Delete(Result, 1, 1); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure Register; +begin + RegisterComponents('FPiette', [TDnsQuery]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TDnsQuery.Create(AOwner : TComponent); +begin + inherited Create(AOwner); + FWSocket := TWSocket.Create(nil); + FPort := '53'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor TDnsQuery.Destroy; +begin + // erase cache + if (fdatacache.count>0) then begin + freemem(fdatacache.items,sizeof(fdatacache.items[0])*fdatacache.count); + fdatacache.count:=0 + end; + + if Assigned(FWSocket) then begin + FWSocket.Destroy; + FWSocket := nil; + end; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsQuery.Notification(AComponent: TComponent; operation: TOperation); +begin + inherited Notification(AComponent, operation); + if operation = opRemove then begin + if AComponent = FWSocket then + FWSocket := nil; + end; +end; + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.GetResponseBuf : PChar; +begin + Result := @FResponseBuf; +end; + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.MXLookup(Domain : String) : Integer; +begin + Inc(FIDCount); + BuildRequestHeader(PDnsRequestHeader(@FQueryBuf), FIDCount, DnsOpCodeQuery, TRUE, 1, 0, 0, 0); + FQueryLen := BuildQuestionSection(@FQueryBuf[SizeOf(TDnsRequestHeader)], Domain, DnsQueryMX, DnsClassIN); + FQueryLen := FQueryLen + SizeOf(TDnsRequestHeader); + Result := FIDCount; + SendQuery; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.ALookup(Host : String) : Integer; +begin + Inc(FIDCount); + BuildRequestHeader(PDnsRequestHeader(@FQueryBuf), FIDCount, DnsOpCodeQuery, TRUE, 1, 0, 0, 0); + FQueryLen := BuildQuestionSection(@FQueryBuf[SizeOf(TDnsRequestHeader)], Host, DnsQueryA, DnsClassIN); + FQueryLen := FQueryLen + SizeOf(TDnsRequestHeader); + Result := FIDCount; + SendQuery; +end; + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ !!KAP!! } +function TDnsQuery.QueryAny(Host : String; qnumber : integer) : Integer; +begin + Inc(FIDCount); + BuildRequestHeader(PDnsRequestHeader(@FQueryBuf), FIDCount, DnsOpCodeQuery, TRUE, 1, 0, 0, 0); + FQueryLen := BuildQuestionSection(@FQueryBuf[SizeOf(TDnsRequestHeader)], Host, qnumber, DnsClassIN); + FQueryLen := FQueryLen + SizeOf(TDnsRequestHeader); + Result := FIDCount; + SendQuery; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.PTRLookup(IP : String) : Integer; +begin + Inc(FIDCount); + BuildRequestHeader(PDnsRequestHeader(@FQueryBuf), FIDCount, DnsOpCodeQuery, TRUE, 1, 0, 0, 0); + FQueryLen := BuildQuestionSection(@FQueryBuf[SizeOf(TDnsRequestHeader)], + ReverseIP(IP) + '.in-addr.arpa', + DnsQueryPTR, DnsClassIN); + FQueryLen := FQueryLen + SizeOf(TDnsRequestHeader); + Result := FIDCount; + SendQuery; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsQuery.SendQuery; +begin +// !!KAP!! + fQueryPending:=true; + + // erase cache + if (fdatacache.count>0) then begin + freemem(fdatacache.items,sizeof(fdatacache.items[0])*fdatacache.count); + fdatacache.count:=0 + end; + + FResponseLen := -1; + FWSocket.OnDataAvailable := nil; + FWSocket.Abort; + FWSocket.OnDataAvailable := WSocketDataAvailable; + FWSocket.Proto := 'udp'; + FWSocket.Port := FPort; + FWSocket.Addr := FAddr; + FWSocket.Connect; + FWSocket.Send(@FQueryBuf, FQueryLen); + FWSocket.OnSessionClosed :=DNSSocketSessionClosed; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.BuildQuestionSection( + Dst : PChar; + const QName : String; + QType : WORD; + QClass : WORD) : Integer; +var + I : Integer; + p : PChar; + Ptr : PChar; +begin + Ptr := Dst; + if Ptr = nil then begin + Result := 0; + Exit; + end; + I := 1; + while I <= Length(QName) do begin + p := Ptr; + Inc(Ptr); + while (I <= Length(QName)) and (QName[I] <> '.') do begin + Ptr^ := QName[I]; + Inc(Ptr); + Inc(I); + end; + p^ := Chr(Ptr - p - 1); + Inc(I); + end; + Ptr^ := #0; + Inc(Ptr); + PWORD(Ptr)^ := htons(QType); + Inc(Ptr, 2); + PWORD(Ptr)^ := htons(QClass); + Inc(Ptr, 2); + Result := Ptr - Dst; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsQuery.BuildRequestHeader( + Dst : PDnsRequestHeader; + ID : WORD; + OPCode : BYTE; + Recursion : Boolean; + QDCount : WORD; + ANCount : WORD; + NSCount : WORD; + ARCount : WORD); +begin + if Dst = nil then + Exit; + Dst^.ID := htons(ID); + Dst^.Flags := htons((OpCode shl 11) + (Ord(Recursion) shl 8)); + Dst^.QDCount := htons(QDCount); + Dst^.ANCount := htons(ANCount); + Dst^.NSCount := htons(NSCount); + Dst^.ARCount := htons(ARCount); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsQuery.TriggerRequestDone(Error: WORD); +begin + if Assigned(FOnRequestDone) then + FOnRequestDone(Self, Error); + + //!!KAP!! + fQueryPending:=false; +end; + +{ !!KAP!! 2002-02-15} +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsQuery.AbortPending; +begin + fQueryPending:=false; +end; + +(************************************************************************************************) +(************************************************************************************************) +function TDnsQuery.NewExtractName(var p : pchar):string; +var N : Integer; + I : Integer; + pc : pchar; +begin + result:=''; + + if (P^=#0) then + Inc(P) + else + repeat + { Get name part length } + N:=Ord(P^); + if (N and $C0)=$C0 then begin + { Message compression } + N := ((N and $3F) shl 8) + Ord(P[1]); + pc:=fResponseBuf; + inc(pc,n); + result:=result+NewExtractName(pc); + // Weiter + Inc(P,2); + n:=0; + end else begin + Inc(P); + if (N<>0) then begin + { Copy name part } + i:=length(result); + setlength(result,i+n); + move(p^,result[i+1],n); + inc(p,n); + if (P^<>#0) then + result:=result+'.'; + end; + end; + until (n=0); +end; + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsQuery.WSocketDataAvailable(Sender: TObject; Error: WORD); +Var Flags : Integer; + Ans : PDnsRequestHeader; + i : integer; + REndPtr, + RDataPtr, + P : PChar; +begin + frrcache.lastid:=-1; + FResponseLen:=FWSocket.Receive(@FResponseBuf,SizeOf(FResponseBuf)); + + if (Error<>0) then begin + TriggerRequestDone(Error); + FResponseLen:=0; + exit; + end; + + { Check for minimum response length } + if FResponseLen< SizeOf(TDnsRequestHeader) then begin + TriggerRequestDone(10); + Exit; + end; + + Ans:=PDnsRequestHeader(@FResponseBuf); + + // --- + Flags:=WSocket_ntohs(Ans^.Flags); + { Check if we got a response } + if (Flags and $8000) = 0 then begin + TriggerRequestDone(11); + Exit; + end; + + { Decode response header } + fDnsRequestAnswer.len := FResponseLen; + fDnsRequestAnswer.ID := WSocket_ntohs(Ans^.ID); + fDnsRequestAnswer.qr := (Flags and $8000) = $8000; + fDnsRequestAnswer.opcode := (Flags shr 11) and $000F; + fDnsRequestAnswer.AuthoritativeAnswer := (Flags and $0400) = $0400; + fDnsRequestAnswer.Truncation := (Flags and $0200) = $0200; + fDnsRequestAnswer.RecursionDesired := (Flags and $0100) = $0100; + fDnsRequestAnswer.RecursionAvailable := (Flags and $0080) = $0080; + fDnsRequestAnswer.z := (Flags shr 4) and $0007; + fDnsRequestAnswer.rcode := (Flags and $000F); + fDnsRequestAnswer.QDCount := WSocket_ntohs(Ans^.QDCount); + fDnsRequestAnswer.ANCount := WSocket_ntohs(Ans^.ANCount); + fDnsRequestAnswer.NSCount := WSocket_ntohs(Ans^.NSCount); + fDnsRequestAnswer.ARCount := WSocket_ntohs(Ans^.ARCount); + + P:=@ResponseBuf[SizeOf(TDnsRequestHeader)]; + { Should never be greater than 1 because we sent only one question } + + fQuestion.QuestionName:=NewExtractName(p); + fQuestion.QuestionType:=WSocket_ntohs(PDWORD(p)^); inc(p,sizeof(word)); + fQuestion.QuestionClass:=WSocket_ntohs(PDWORD(p)^); inc(p,sizeof(word)); + + REndPtr:=FResponseBuf; + inc(rendptr,FResponseLen); + + // the following is not very smart due two loops.... + // get number or RRDatas + i:=0; + RDataPtr:=p; + while (integer(REndPtr)>integer(RDataPtr)) do begin + NewExtractName(RDataPtr); + i:=i+1; + inc(RDataPtr,sizeof(TRRInternal)+WSocket_ntohs(pRRInternal(rdataptr)^.rdlength)); + end; + fdatacache.count:=i; + getmem(fdatacache.items,sizeof(fdatacache.items[0])*fdatacache.count); + + // Fetch RRDatas + i:=0; + RDataPtr:=p; + while (integer(REndPtr)>integer(RDataPtr)) do begin + fdatacache.items[i].rrpos:=rdataptr; + NewExtractName(RDataPtr); + fdatacache.items[i].rrtype:=WSocket_ntohs(pRRInternal(rdataptr)^.rrtype); + i:=i+1; + inc(RDataPtr,sizeof(TRRInternal)+WSocket_ntohs(pRRInternal(rdataptr)^.rdlength)); + end; + + TriggerRequestDone(0); +end; + +{ !!KAP!! 2002-02-15} +procedure TDnsQuery.DNSSocketSessionClosed(Sender: TObject; Error: Word); +begin + // das geht garnicht, da dann wsocketdataavailable zu spät aufgerufen wird + //fQueryPending:=false; +end; + +(************************************************************************************************) +(************************************************************************************************) +// 0 : all items, otherwise the queryitems +function TDnsQuery.GetRepsonsecount(nid : integer):integer; +var i : integer; +begin + if (nid=0) then + result:=fdatacache.count + else begin + result:=0; + for i:=0 to fdatacache.count-1 do + if (fdatacache.items[i].rrtype=nid) then + inc(result); + end; +end; + +(************************************************************************************************) +(************************************************************************************************) +// 0 : all items, otherwise the queryitems +function TDnsQuery.GetResponseItem(nid : integer; nindex : integer):TRRRecord; + +var i, + index : integer; + pp : pchar; +begin + // nada + fillchar(result,sizeof(result),0); + result.valid:=false; + + // Cache hit + if (frrcache.lastid=nid) and (frrcache.lastindex=nindex) then begin + result:=frrcache; + exit; + end; + + // store for caching. + result.lastid:=nid; + result.lastindex:=nindex; + + // Search the entry + pp:=nil; + index:=-1; + for i:=0 to fdatacache.count-1 do + if (pp=nil) and ( (nid=0) or (fdatacache.items[i].rrtype=nid) ) then begin + if (nindex=0) then begin + index:=i; + pp:=fdatacache.items[i].rrpos; + end else + nindex:=nindex-1; + end; + + // not found. Better raise exception? + if (pp=nil) then exit; + + // headers + result.name:=NewExtractName(pp); + result.rrtype:=WSocket_ntohs(pRRInternal(pp)^.rrtype); + result.rrclass:=WSocket_ntohs(pRRInternal(pp)^.rrclass); + result.rrttl:=WSocket_ntohl(pRRInternal(pp)^.rrttl); + result.rdlength:=WSocket_ntohs(pRRInternal(pp)^.rdlength); + + // end + inc(pp,sizeof(TRRInternal)); + + // Build the record + case fdatacache.items[index].rrtype of + DnsQueryMD, + DnsQueryMB, + DnsQueryMF : result.madname:=NewExtractName(pp); + DnsQueryMG : result.mgmname:=NewExtractName(pp); + DnsQueryCNAME : result.cname:=NewExtractName(pp); + DnsQueryMR : result.newname:=NewExtractName(pp); + DnsQueryNS : result.nsdname:=NewExtractName(pp); + DnsQueryPTR : result.ptrname:=NewExtractName(pp); + DnsQueryTXT : result.txt:=NewExtractName(pp); + DnsQueryA : begin + result.adress:=PDWORD(pp)^; + result.ipnummer:=WSocket_inet_ntoa(tinaddr(result.adress)); + end; + DnsQueryMX : begin + result.mx.preference:=WSocket_ntohs(PDWORD(pp)^); + inc(pp,2); + result.mx.exchange:=NewExtractName(pp); + end; + DnsQueryHINFO : move(pp^,result.hinfo,sizeof(thinfo)); + DnsQueryMINFO : begin + result.minfo.rmailbx:=NewExtractName(pp); + result.minfo.remailbx:=NewExtractName(pp); + end; + DnsQueryAAAA : begin + move(pp^,result.aaaa,sizeof(TAAAA)); + result.ip6nummer:=format('%p:%p',[ pointer(result.aaaa[0]),pointer(result.aaaa[2]) ]); + end; + DnsQuerySOA : begin + result.soa.mname:=NewExtractName(pp); + result.soa.rname:=NewExtractName(pp); + result.soa.serial:=WSocket_ntohl(pcardinal(pp)^); inc(pp,sizeof(cardinal)); + result.soa.refresh:=WSocket_ntohl(pcardinal(pp)^); inc(pp,sizeof(cardinal)); + result.soa.retry:=WSocket_ntohl(pcardinal(pp)^); inc(pp,sizeof(cardinal)); + result.soa.expire:=WSocket_ntohl(pcardinal(pp)^); inc(pp,sizeof(cardinal)); + result.soa.minimum:=WSocket_ntohl(pcardinal(pp)^); inc(pp,sizeof(cardinal)); + end; + DnsQueryLOC : begin + move(pp^,result.loc,sizeof(TLOCInfo)); + result.locdecode:=Loc2Geo(result.loc); + end; + end; + + // merken + frrcache:=result; + + result.valid:=true; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ + <0><1><129><128><0><1><0><1><0><4><0><5><7>inp + rise<3>com<0><0><15><0><1><192><12><0> + <15><0><1><0><1>QV<0><10><0><10><5>drui + d<192><12><192><12><0><2><0><1><0><1>Qc<0><6><3> + ns1<192><12><192><12><0><2><0><1><0><1>Qc<0> + <20><3>NS1<10>SPRINTLINK + <3>NET<0><192><12><0><2><0><1><0><1>Qc<0> + <6><3>NS2<192>U<192><12><0><2><0><1><0><1>Q + c<0><6><3>NS3<192>U<192>+<0><1><0><1><0> + <1>QV<0><4><143><186><11>F<192>?<0><1><0><1><0> + <1>Qc<0><4><207>iS<30><192>Q<0><1><0><1><0> + <2><144>i<0><4><204>u<214><10><192>q<0><1><0><1><0> + <2><144>i<0><4><199><2><252><10><192><131><0><1><0><1><0> + <2><142><182><0><4><204>a<212><10> +} +{ + <0><3><129><128><0><1><0><1><0><2><0><3><4>rtf + m<2>be<0><0><15><0><1><192><12><0><15><0><1><0> + <1>.b<0><9><0><10><4>mail<192><12><192><12> + <0><2><0><1><0><1>.b<0><11><2>ns<3>dn + s<2>be<0><192><12><0><2><0><1><0><1>.b<0> + <5><2>ns<192><12><192>'<0><1><0><1><0><1>.b + <0><4><195><0>d<253><192>:<0><1><0><1><0><1>QY + <0><4><134>:J!<192>Q<0><1><0><1><0><1>.b + <0><4><195><0>d<253> +} +{ + <0><7><133><128><0><1><0><1><0><2><0><2><3>www + <4>rtfm<2>be<0><0><1><0><1><192><12><0> + <1><0><1><0><1>Q<128><0><4><195><0>d<253><4>rt + fm<2>be<0><0><2><0><1><0><1>Q<128><0><5> + <2>ns<192>-<192>-<0><2><0><1><0><1>Q<128><0> + <9><2>ns<3>dns<192>2<192>@<0><1><0><1> + <0><1>Q<128><0><4><195><0>d<253><192>Q<0><1><0><1> + <0><0><26><132><0><4><134>:J! +} +(* +<0><1><129><128><0><1><0><1><0><5><0><5><9>fu-berlin +<2>de<0><0> + +<29><0><1><192><12><0><29><0><1><0><0>, + +<0><16><0><21><22><19><139>Av<167><130><218>L<242> +<0><152><156>\<192><12><0><2><0><1><0><0><12><176> +<0>"<4>arbi<10>informatik<13>uni-oldenburg<2>de<0> +<192><12><0><2><0><1><0><0><12><176><0><12><5>deneb<3> +dfn<192>d<192><12><0><2><0><1><0><0><12><176><0><6><3> +ns3<192><12><192><12><0><2><0><1><0><0><12><176><0><6> +<3>ns2<192><12><192><12><0><2><0><1><0><0><12><176><0> +<6><3>ns1<192><12><192>F<0><1><0><1><0><0>t<169><0><4> +<134>j<1><7><192>t<0><1><0><1><0><0>9<209><0><4><192>L +<176><9><192><140><0><1><0><1><0><0>T<19><0><4><130> +<133><1>9<192><158><0><1><0><1><0><0><28><206><0><4> +<160>-<10><12><192><176><0><1><0><1><0><0>1<198><0> +<4><160>-<8><8> +*) + +{ !!KAP!! } +{raw translation of some perl-source LOC.pm from package Net::DNS::RR::LOC; + +fu-berlin.de LOC 52 27 19.591 N 13 17 40.978 E 15.00m 1000.00m 10000.00m 10.00m +} +const conv_sec = 1000.0; + conv_min = 60.0 * conv_sec; + conv_deg = 60.0 * conv_min; + zh31 = 1 shl 31; + +procedure SubLOCgeo(longlat : integer; + hemis : String; + var ldeg, lmin, lsec, lmsec : Extended; + var hemic : char); +var + Labs : Extended; +begin + LongLat := WSocket_ntohl(LongLat); + // !!KAP!! 2002-08-31 + if (LongLat<0) + then Labs := Abs(1.0 * LongLat - zh31) + else Labs := Abs(1.0 * LongLat + zh31); + //Labs := Abs(1.0 * LongLat - zh31); + Ldeg := Trunc(labs / conv_deg); + Labs := Labs - ldeg * conv_deg; + Lmin := Trunc(labs / conv_min); + Labs := Labs - lmin * conv_min; + Lsec := Trunc(labs / conv_sec); + Labs := Labs - lsec * conv_sec; + Lmsec := Labs; + Hemic := Copy(Hemis, 1 + ord(LongLat <= zh31), 1)[1]; { yeah. } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function LongLatToDMS(longlat : longint; hemis : string):string; +Var ldeg, lmin, lsec, lmsec : extended; + hemi : char; +begin + SubLOCgeo(longlat,hemis,ldeg,lmin,lsec,lmsec,hemi); + result := Format('%d %02d %02d.%02.2d', + [round(ldeg), round(lmin), round(lsec), + round(lmsec)]) + ' ' + hemi; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ in cm!! } +function LocAltToAlt(Localt : LongInt) : LongInt; +begin + Result := Round((WSocket_ntohl(localt) - 100000.0 * 100.0) / 100.0); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ !!KAP!! } +function Loc2Geo(loc : TLOCInfo):TLogGeo; + { dolle umwandlung } + procedure du(longlat : Integer; + hemis : String; + var ideg, imin, isec, imsec : Integer; + var hemic : Char); + var + ldeg, lmin, lsec, lmsec : extended; + begin + SubLOCgeo(longlat, hemis, ldeg, lmin, lsec, lmsec, hemic); + ideg := Round(ldeg); + imin := Round(lmin); + isec := Round(lsec); + imsec := Round(lmsec); + end; + +begin + Result.version := Loc.version; + Result.longsize := Round(Exp(Ln(10)*(loc.size and $f))); + Result.latsize := Round(Exp(Ln(10)*(loc.size shr 4))); + + Result.horizpre := Loc.horizpre; + Result.vertpre := Loc.vertpre; + + du(loc.latitude, 'NS', result.lad, result.lam, + result.las, result.lams, result.lahem); + du(loc.longitude, 'EW', result.lod, result.lom, + result.los, result.loms, result.lohem); + + Result.altitude := LocAltToAlt(loc.altitude); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. diff --git a/ICS_zlog/Delphi/Internet/HttpAsp1.dfm b/ICS_zlog/Delphi/Internet/HttpAsp1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..9a1bcf569f51312b9f9438fdfc6d51f75b646591 GIT binary patch literal 1139 zcmZuxO>fgc5Z%~~?W9dp4oKw|Bvh4(d=xGfx5P=5ilnjXMZF-w#@@sW>s@QTQ4++3 z|HFa5z>k6}ti5p)wOs5O+waYrc{~1F1#kqR2M0bJPH!imbMoN;0O$=nH8_$ofjE^z zF5;v8ONpn=PU6e?|ne`&WbWQ!QY`Iye=zL6AH$FCsC(-VU{$}( zF-HNtBP`@Ah}ZHkf1yPfzbkomgJNveCVs<5EN%E$kh#YDazpVUIG)nb6&Oi86(JTC zXUcSHtItHNa(12Xh{z8CY6_w)Gy z%3Vqp%ytlUDZxzE#)RRtA}v|_WT5H?f>YX4)3B{H?Qt175Y2ME1^~c<9%7hU z`So(Iw(+>MQlm?k5moN(cuI<9jAn`^ziw$xGmDKA?XYpSHQ1=#`|J42BvCDhOvWDm zwU(jroh`op7;k!n0X4xvNaS(Bb=}WW&EV}TFrO4NG@kCHgM-Wt>jAuAwN-_Obm!Y6 z`(L_}rYmp&*s!;hlC!FhS*XKYn|WHw#f`S@y(`*#c0Zo-S%$Iuc#f7-R(6^VTb(mX zf-iP`$C^J-hC2D`sm#f?N8K+gp5W_^$Az?vt4_JQP-n(Eo$#-OQq+Fa>NL&+9w$hW z8O1NHZV=!^T2~}S3*26i`KyKw*Uj~e$QUKXgU<$DDS?sNDU~_e#gqJ3@l*8%{sCpw BUSj|N literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/HttpAsp1.pas b/ICS_zlog/Delphi/Internet/HttpAsp1.pas new file mode 100644 index 00000000..5ea17bbb --- /dev/null +++ b/ICS_zlog/Delphi/Internet/HttpAsp1.pas @@ -0,0 +1,164 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +Author: François PIETTE +Creation: December 30, 1997 +Version: 1.00 +Description: Sample program to demonstrate some of the THttpCli features. + (POST a message to a CGI) + (requested by "Coen" ) +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit HttpAsp1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, WSocket, HttpProt, ExtCtrls; + +const + HttpPgVersion = 101; + +type + THttpTestForm = class(TForm) + DisplayMemo: TMemo; + Panel1: TPanel; + Label1: TLabel; + Label2: TLabel; + SupplierIDEdit: TEdit; + PinEdit: TEdit; + SendButton: TButton; + HttpCli1: THttpCli; + procedure FormCreate(Sender: TObject); + procedure SendButtonClick(Sender: TObject); + private + { Déclarations privées } + public + { Déclarations publiques } + end; + +var + HttpTestForm: THttpTestForm; + +implementation + +{$R *.DFM} + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +function TrimRight(Str : String) : String; +var + i : Integer; +begin + i := Length(Str); + while (i > 0) and (Str[i] = ' ') do + i := i - 1; + Result := Copy(Str, 1, i); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TrimLeft(Str : String) : String; +var + i : Integer; +begin + if Str[1] <> ' ' then + Result := Str + else begin + i := 1; + while (i <= Length(Str)) and (Str[i] = ' ') do + i := i + 1; + Result := Copy(Str, i, Length(Str) - i + 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function Trim(Str : String) : String; +begin + Result := TrimLeft(TrimRight(Str)); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.FormCreate(Sender: TObject); +begin + PinEdit.Text := ''; + SupplierIDEdit.Text := ''; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.SendButtonClick(Sender: TObject); +var + DataIn : TMemoryStream; + DataOut : TMemoryStream; + Buf : String; +begin + DisplayMemo.Clear; + DataIn := TMemoryStream.Create; + DataOut := TMemoryStream.Create; + try + Buf := 'suplno=' + Trim(SupplierIDEdit.Text) + + '&PIN=' + Trim(PinEdit.Text) + + '&LOGIN=Login'; + DataOut.Write(Buf[1], Length(Buf)); + DataOut.Seek(0, soFromBeginning); + + httpcli1.SendStream := DataOut; + httpcli1.RcvdStream := DataIn; + httpcli1.Proxy := 'intsrv02'; + httpcli1.ProxyPort := '80'; + HttpCli1.Cookie := 'ASPSESSIONID=OUYRWOSPOFGGPSSF'; + HttpCli1.URL := 'http://www.transmed.co.za/webserv/menu.asp'; + + SendButton.Enabled := FALSE; + try + httpcli1.Post; + finally + SendButton.Enabled := TRUE; + DataIn.Seek(0, 0); + DisplayMemo.Lines.LoadFromStream(DataIn); + end; + finally + DataOut.Free; + DataIn.Free; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/HttpAsy1.dfm b/ICS_zlog/Delphi/Internet/HttpAsy1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..152d221c0dae9deed08f46f8788a639a607dae53 GIT binary patch literal 2148 zcmai0$&%YP5QRvIq_)|z*hl7OyR6YTImDHlM2%`(r5ULtx?DLW5Y-Z4LjXfUBPpl+ zLjEM5;@`+ERjHhl<|cBs%7tt+_}*)DHvsda%)<#E4JDbwgVnbAbcl0 zU;DWcN0i0VCYC#5k?PA`9Mv5tfism^j)7_J5PXW8YdqivU zw3eBH3Nh`_sb_Zx@2QLG*zRbRp@p!15PnwvAmzTN-t5g~s2<2_ z!P6_PC6Gd{dXPIQk!3n~hFoLen%VkdJ8eUHrw#RIl?Q!jQH~@aRC~k(MCUUVGO>y( zMwyH>W?m>c@8ex#8d21j$}d90?PVpmAre{fm4@#(^+_mq`w1@F(B59udMlJLo?pvf z8RxY7-T8(6!jtQODmLfv(&%{}1j=~J)^r8k6+B*9)+an?mBq0c9wV>bv7Xf;mHLo+Shm#T0(oK%@q^lg%&k>5?-kjAkdl2Y=w{ GLH+}g{hQ7J literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/HttpAsy1.pas b/ICS_zlog/Delphi/Internet/HttpAsy1.pas new file mode 100644 index 00000000..52fbcfa3 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/HttpAsy1.pas @@ -0,0 +1,492 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Creation: January 31, 1998 +Version: 1.01 +Description: This program shows how to use the THttpCli component to execute + a list of request sequentialy or simultaneously. + Simultaneous request are possible without using threads because + the THttpCli component is fully event-driven and asynchronous. + Data is not stroed. See the HttpTst sample program for an + example of data store. We keep this sample as simple as possible. +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Feb 01, 1998 V1.01 Adedpted to be compatible with Delphi 1 + Save window position and size to ini file. + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit HttpAsy1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, ExtCtrls, HttpProt, IniFiles; + +type + THttpAsyForm = class(TForm) + URLListBox: TListBox; + Panel1: TPanel; + Label1: TLabel; + URLEdit: TEdit; + AddButton: TButton; + Panel2: TPanel; + ExecButton: TButton; + RemoveButton: TButton; + DisplayMemo: TMemo; + HttpCli1: THttpCli; + ReplaceButton: TButton; + ClearDisplayButton: TButton; + HeaderCheckBox: TCheckBox; + DataCheckBox: TCheckBox; + SimultCheckBox: TCheckBox; + AbortButton: TButton; + procedure AddButtonClick(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure RemoveButtonClick(Sender: TObject); + procedure ExecButtonClick(Sender: TObject); + procedure HttpCli1RequestDone(Sender: TObject; RqType: THttpRequest; + Error: Word); + procedure URLListBoxClick(Sender: TObject); + procedure ReplaceButtonClick(Sender: TObject); + procedure ClearDisplayButtonClick(Sender: TObject); + procedure HttpCli1HeaderData(Sender: TObject); + procedure HttpCli1DocData(Sender: TObject; Buffer: Pointer; + Len: Integer); + procedure AbortButtonClick(Sender: TObject); + private + { Déclarations privées } + FInitialized : Boolean; + FIniFileName : String; + FCurrentItem : Integer; + FHttpCliList : TList; { For simultaneous requests } + FFlagAbort : Boolean; + procedure StartNext; { For sequential requests } + procedure ExecSimultaneous; + procedure ExecSequential; + procedure HttpCliItemRequestDone(Sender: TObject; { For simult. requests } + RqType: THttpRequest; Error: Word); + end; + +var + HttpAsyForm: THttpAsyForm; + +implementation + +{$R *.DFM} + +const + SectionData = 'Data'; + KeyURL = 'URLEdit'; + KeyCount = 'Count'; + KeyList = 'List'; + KeySimult = 'Simultaneous'; + KeyHeader = 'DisplayHeader'; + KeyData = 'DisplayData'; + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +function TrimRight(Str : String) : String; +var + i : Integer; +begin + i := Length(Str); + while (i > 0) and (Str[i] = ' ') do + i := i - 1; + Result := Copy(Str, 1, i); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TrimLeft(Str : String) : String; +var + i : Integer; +begin + if Str[1] <> ' ' then + Result := Str + else begin + i := 1; + while (i <= Length(Str)) and (Str[i] = ' ') do + i := i + 1; + Result := Copy(Str, i, Length(Str) - i + 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function Trim(Str : String) : String; +begin + Result := TrimLeft(TrimRight(Str)); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpAsyForm.FormCreate(Sender: TObject); +begin + DisplayMemo.Clear; + FCurrentItem := -1; + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; + FHttpCliList := TList.Create; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpAsyForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; + Count : Integer; + I : Integer; + URL : String; +begin + if not FInitialized then begin + FInitialized := TRUE; + IniFile := TIniFile.Create(FIniFileName); + URLEdit.Text := IniFile.ReadString(SectionData, KeyURL, ''); + HeaderCheckBox.Checked := (IniFile.ReadInteger(SectionData, KeyHeader, 0) <> 0); + DataCheckBox.Checked := (IniFile.ReadInteger(SectionData, KeyData, 0) <> 0); + SimultCheckBox.Checked := (IniFile.ReadInteger(SectionData, KeySimult, 0) <> 0); + Count := IniFile.ReadInteger(SectionData, KeyCount, 0); + for I := 1 to Count do begin + URL := IniFile.ReadString(SectionData, KeyList + IntToStr(I), ''); + if URL <> '' then + URLListBox.Items.Add(URL); + end; + Top := IniFile.ReadInteger(SectionWindow, KeyTop, Top); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, Left); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + IniFile.Free; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpAsyForm.FormClose(Sender: TObject; + var Action: TCloseAction); +var + IniFile : TIniFile; + I : Integer; + Count : Integer; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteString(SectionData, KeyURL, URLEdit.Text); + IniFile.WriteInteger(SectionData, KeyHeader, Ord(HeaderCheckBox.Checked)); + IniFile.WriteInteger(SectionData, KeyData, Ord(DataCheckBox.Checked)); + IniFile.WriteInteger(SectionData, KeySimult, Ord(SimultCheckBox.Checked)); + Count := URLListBox.Items.Count; + IniFile.WriteInteger(SectionData, KeyCount, Count); + for I := 1 to Count do + IniFile.WriteString(SectionData, KeyList + IntToStr(I), + URLListBox.Items[I - 1]); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Add an URL to the URL list box } +procedure THttpAsyForm.AddButtonClick(Sender: TObject); +begin + if Trim(URLEdit.Text) <> '' then + URLListBox.Items.Add(URLEdit.Text); + ActiveControl := URLEdit; + URLEdit.SelectAll; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Remove the selected URL from hte URL listbox } +procedure THttpAsyForm.RemoveButtonClick(Sender: TObject); +var + Item : Integer; +begin + Item := URLListBox.ItemIndex; + if Item >= 0 then + URLListBox.Items.Delete(Item); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Execute button click handler. Start sequential or simultaneous execution } +procedure THttpAsyForm.ExecButtonClick(Sender: TObject); +begin + ExecButton.Enabled := FALSE; + FFLagAbort := FALSE; + if SimultCheckBox.Checked then + ExecSimultaneous + else + ExecSequential; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Start simultaneous execution by creating as much THttpCli components as } +{ there are URL in the list box. (We could alternatively limit the number } +{ of THttpCli components and use them sequentially. It would be a } +{ combination of the sequential and simultaneous implementations.) } +{ A TList is used to keep track of all the component created. This is only } +{ needed to abort each one if requested by the user. } +{ The Tag property is used to store the item number, just for display. } +procedure THttpAsyForm.ExecSimultaneous; +var + Count : Integer; + Item : Integer; + AHttpCli : THttpCli; +begin + { Check if the list if empty } + if FHttpCliList.Count > 0 then begin + MessageBeep(MB_OK); + Exit; + end; + + { Get the URL count } + Count := URLListBox.Items.Count; + if Count <= 0 then + Exit; { Nothing to do ! } + + { Create a new HTTP component for each URL, } + { add it to the list and start the request } + for Item := 1 to Count do begin + AHttpCli := THttpCli.Create(Self); + FHttpCliList.Add(AHttpCli); + AHttpCli.Tag := Item; + AHttpCli.URL := URLListBox.items[Item - 1]; + AHttpCli.OnRequestDone := HttpCliItemRequestDone; + AHttpCli.OnHeaderData := HttpCli1HeaderData; + AHttpCli.OnDocData := HttpCli1DocData; + DisplayMemo.Lines.Add('Start item ' + IntToStr(Item) + ': ' + + AHttpCli.Url); + AHttpCli.GetAsync; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This OnRequestDone handler is used for the simultaneous request model. } +{ It search the THttpCli component in the list and remove it. } +procedure THttpAsyForm.HttpCliItemRequestDone( + Sender : TObject; + RqType : THttpRequest; + Error : Word); +var + Item : Integer; + AHttpCli : THttpCli; + Count : Integer; +begin + AHttpCli := Sender as THttpCli; + Item := AHttpCli.Tag; + DisplayMemo.Lines.Add( + 'Finished Item ' + IntToStr(Item) + + ' StatusCode = ' + IntToStr(AHttpCli.StatusCode) + + ' ' + AHttpCli.URL + + ' Error = ' + IntToStr(Error)); + DisplayMemo.Lines.Add(''); + + { Remove the item form the list } + Count := FHttpCliList.Count; + for Item := 1 to Count do begin + if AHttpCli = FHttpCliList.Items[Item - 1] then begin + FHttpCliList.Delete(Item - 1); + break; + end; + end; + + { Free the item } + AHttpCli.Free; + + { Check if the list is empty. If yes, we have all requests finished. } + if FHttpCliList.Count <= 0 then begin + ExecButton.Enabled := TRUE; + DisplayMemo.Lines.Add('All Finished'); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpAsyForm.ExecSequential; +begin + if FCurrentItem >= 0 then begin + MessageBeep(MB_OK); + Exit; + end; + FCurrentItem := 0; + StartNext; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Start the next request (this could also be the first). } +procedure THttpAsyForm.StartNext; +begin + if FFlagAbort then begin + DisplayMemo.Lines.Add('Abort requested'); + FCurrentItem := -1; + ExecButton.Enabled := TRUE; + Exit; + end; + + Inc(FCurrentItem); + if FCurrentItem > URLListBox.Items.Count then begin + DisplayMemo.Lines.Add('All Finished'); + FCurrentItem := -1; + ExecButton.Enabled := TRUE; + Exit; + end; + HttpCli1.Url := URLListBox.Items[FCurrentItem - 1]; + HttpCli1.Tag := FCurrentItem; + DisplayMemo.Lines.Add('Start item ' + IntToStr(FCurrentItem) + ': ' + + HttpCli1.Url); + HttpCli1.GetASync; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This OnRequestDone event handler is called during the sequential model. } +{ Just start the next request. } +procedure THttpAsyForm.HttpCli1RequestDone(Sender: TObject; + RqType: THttpRequest; Error: Word); +begin + DisplayMemo.Lines.Add('Finished item ' + IntToStr(FCurrentItem) + + ' StatusCode = ' + IntToStr(HttpCli1.StatusCode) + + ' Error = ' + IntToStr(Error)); + DisplayMemo.Lines.Add(''); + StartNext; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpAsyForm.URLListBoxClick(Sender: TObject); +begin + UrlEdit.Text := UrlListBox.Items[URLListBox.ItemIndex]; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpAsyForm.ReplaceButtonClick(Sender: TObject); +var + Item : Integer; +begin + Item := URLListBox.ItemIndex; + if Item < 0 then + Exit; + URLListBox.Items.Delete(Item); + URLListBox.Items.Insert(Item, UrlEdit.Text); + URLListBox.ItemIndex := Item; + ActiveControl := URLEdit; + URLEdit.SelectAll; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpAsyForm.ClearDisplayButtonClick(Sender: TObject); +begin + DisplayMemo.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This OnHeaderData event handler is used in both sequential and } +{ simultaneous requests models. } +procedure THttpAsyForm.HttpCli1HeaderData(Sender: TObject); +var + AHttpCli : THttpCli; +begin + if not HeaderCheckBox.Checked then + Exit; + AHttpCli := Sender as THttpCli; + DisplayMemo.Lines.Add('Item ' + IntToStr(AHttpCli.Tag) + ': ' + + AHttpCli.LastResponse); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This OnDocData event handler is used in both sequential and } +{ simultaneous requests models. } +procedure THttpAsyForm.HttpCli1DocData(Sender: TObject; Buffer: Pointer; + Len: Integer); +var + AHttpCli : THttpCli; +begin + if not DataCheckBox.Checked then + Exit; + + AHttpCli := Sender as THttpCli; + { Display a message stating that data is available } + DisplayMemo.Lines.Add('Item ' + IntToStr(AHttpCli.Tag) + ' Data'); + + { We could display the data, but it use a huge space in the display } + { DisplayMemo.Lines.Add(StrPas(Buffer)); } + + { We could also store the data somewhere (with the help of OnDocBegin } + { and OnDocEnd events. Or using the RcvdStream property. } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Abort all the running request. } +{ In the simultaneous model, we use the list to abort all. } +{ We just need to call abort. We will get the OnRequestDone event with an } +{ error code stating that the request has been aborted. } +procedure THttpAsyForm.AbortButtonClick(Sender: TObject); +var + Count : Integer; + Item : Integer; + AHttpCli : THttpCli; +begin + FFLagAbort := TRUE; + if SimultCheckBox.Checked then begin + Count := FHttpCliList.Count; + for Item := 1 to Count do begin + AHttpCli := THttpCli(FHttpCliList.Items[Item - 1]); + AHttpCli.Abort; + end; + end + else + HttpCli1.Abort; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/HttpChk1.dfm b/ICS_zlog/Delphi/Internet/HttpChk1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..9eaa6a1fd3505ec8e3b9c338a5f03b8730b3ca0d GIT binary patch literal 1014 zcmZWo-Hy^g6duabmY=$)F;TDZ%5}3)HhMw!4hjS#EDi038xtMc1D)MrrcQ^z`c^)G z58)H|5_+ve3oOQ)nRCwc`@VeVoc<{x-x>6r4>yxxe>@qXX7y(tA>ZvcE#HYCxVsUw z&&9HGoSY0{F7rQfd7sDm*SW%!gfhy%%jp9ki%90poZ;YD63+C0a0Q1`E{tM8JCgNr z0F^#xvf)HnBp{8`Zm-|I8Ty}`L3`r${8ILsVk!Zh5*G5c4;xudA2KoRcQMVb@e*`v z7{omtH~cs)@~yh3|yc>>9b%9J4^sHOyGJA&5#1ji7B3Vtsn(om$^ zJEOQrDa>8RzoR|JGt@WxqWV2a|Z_zn5T|faHZwn$Ka|V=&x`bs~#yK&g@Nnyi4Rz1O*oG5JGFD+DiOL?W)Sm%9stdk?3NHjVF6U4>fDdCh%niiR^L)#?$>5N5yP+ LKBkj(5kh|fw{|?| literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/HttpChk1.pas b/ICS_zlog/Delphi/Internet/HttpChk1.pas new file mode 100644 index 00000000..ac495581 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/HttpChk1.pas @@ -0,0 +1,147 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Creation: September 4, 1999 +Version: 1.01 +Description: Use HTTP component to check for valid URL. + See IsAddressValid function below. Of course you can remove + display if all you need is a boolean status. +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998, 1999 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit HttpChk1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, HttpProt; + +type + TCheckUrlForm = class(TForm) + Label1: TLabel; + URLEdit: TEdit; + CheckButton: TButton; + ResultLabel: TLabel; + HttpCli1: THttpCli; + Memo1: TMemo; + procedure CheckButtonClick(Sender: TObject); + procedure HttpCli1RequestDone(Sender: TObject; RqType: THttpRequest; + Error: Word); + procedure HttpCli1HeaderData(Sender: TObject); + private + FDoneFlag : Boolean; + FDoneError : Word; + public + { Public declarations } + function IsAddressValid(URL : String) : Boolean; + end; + +var + CheckUrlForm: TCheckUrlForm; + +implementation + +{$R *.DFM} + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCheckUrlForm.CheckButtonClick(Sender: TObject); +begin + Memo1.Clear; + if IsAddressValid(UrlEdit.Text) then + ResultLabel.Caption := 'Valid' + else + ResultLabel.Caption := 'Invalid'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Check if an URL is valid. Use HTTP HEAD command to speed up thing. (It } +{ doesn't retrieve document, just webserver answer header). } +{ Syntax of an URL: protocol://[user[:password]@]server[:port]/path } +function TCheckUrlForm.IsAddressValid(URL : String) : Boolean; +var + Timeout : longInt; +begin + try + FDoneFlag := FALSE; + FDoneError := 0; + HttpCli1.URL := URL; + HttpCli1.HeadAsync; + Timeout := GetTickCount + 30000; { 30" timeout } + while not FDoneFlag do begin +{$IFNDEF VER80} + Sleep(0); +{$ENDIF} + Application.ProcessMessages; + if Timeout < Longint(GetTickCount) then begin + HttpCli1.Abort; + Result := FALSE; + Exit; + end; + end; + Result := (HttpCli1.StatusCode = 200); + { You can suppress next line if you don't want display } + Memo1.lines.Add('StatusCode = ' + IntToStr(HttpCli1.StatusCode)); + except + Result := FALSE; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCheckUrlForm.HttpCli1RequestDone(Sender: TObject; + RqType: THttpRequest; Error: Word); +begin + FDoneFlag := TRUE; + FDoneError := Error; + { You may suppress following two lines if you don't want any display } + if Error <> 0 then + Memo1.Lines.Add('Error #' + IntToStr(Error)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ You can remove this event handler if you don't want to see messages. } +procedure TCheckUrlForm.HttpCli1HeaderData(Sender: TObject); +begin + Memo1.Lines.Add(HttpCli1.LastResponse); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/HttpDmo1.dfm b/ICS_zlog/Delphi/Internet/HttpDmo1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..6cf4bba7a8a7bf894db9668c4043dfe8342e5d4e GIT binary patch literal 1253 zcmb_c&u`i=6gB~p0A=l^($*8ZOkGtHx~Xc_8>CPsL5aXsciT+zAl^(IIYvNlyYIL^ zYyZIhkexRt0ZKP%ryXMZCHcPhzW2kw$_RHccJZL!?hiVHVIMUPz84U}Zl|%2yHZA& z_hH66T+E(5H48nMNUfj8Jj#DT#e3?@Apb3=cY#g=nLp1N4v8e?p?;JAuWWmRVU#@9l3|B$EJfZUV?~~>YjQIsKgbfRy;$c}t8UX;xEuDa&{OQ2EU*lFyv82=jV-!@ zFINZ^aoeZTP)y05fsa$i=DMP1TUCcULJCQ4^wZ$6upW&q9#CG7rOK!U{@fN5FL^F5 z&Mmo=2pPCFmy(C(4bKj#zkHC}b*LR~qCMOy&A+rO znj2ZAROFw+YX1_JLkT$P_{uenBSu!qdAHilHGEs`{13D)w@H}t525_uO0T zTUb14;cAbD5L+WDXgG~?`fkvu>=L1ZNoK(;k37K{YpJm^^f+#D89e4ui8j+&SJ9iv ztg8JiOPrKytNa~k#My6m->EyJQ z9hddxn93Q6HZML!Fx{M^%s8=6j9cyyF937jQSmBYcol)mW2wI+QKX8j9P!Xz*3~6a ipQziYJ{Jr^kNeHP}4%93w%gm}(OPlJws^@RIjDvCj literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/HttpDmo1.pas b/ICS_zlog/Delphi/Internet/HttpDmo1.pas new file mode 100644 index 00000000..edb0c48c --- /dev/null +++ b/ICS_zlog/Delphi/Internet/HttpDmo1.pas @@ -0,0 +1,139 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +Author: François PIETTE +Creation: December 5, 1997 +Version: 1.02 +Description: Sample program to demonstrate some of the THttpCli features. +EMail: http://www.overbyte.be francois.piette@overbyte.be + http://www.rtfm.be/fpiette francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 1997-2001 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: +Jan 16, 1998 V1.01 Added a proxy edit box. +Aug 18, 2001 V1.02 Shay Horovitz corrected a small bug + in LoadMemoFromMemoryStream. + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit HttpDmo1; + +interface + +uses + WinProcs, WinTypes, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, HttpProt, ExtCtrls; + +type + THttpToMemoForm = class(TForm) + Panel1: TPanel; + Label1: TLabel; + URLEdit: TEdit; + GoButton: TButton; + HttpCli1: THttpCli; + DisplayMemo: TMemo; + Label2: TLabel; + ProxyEdit: TEdit; + procedure GoButtonClick(Sender: TObject); + procedure Panel1Resize(Sender: TObject); + private + { Déclarations privées } + public + { Déclarations publiques } + end; + +var + HttpToMemoForm: THttpToMemoForm; + +implementation + +{$R *.DFM} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure LoadMemoFromMemoryStream(Memo : TMemo; Stream : TMemoryStream); +var + p, q, r : PChar; +begin + p := Stream.Memory; + q := p + Stream.Size;// -1; fixed by Shay Horovitz + r := p; + while (p <> nil) and (p < q) do begin + while (p < q) and (p^ <> #13) and (p^ <> #10) do + Inc(p); + Memo.Lines.Add(Copy(StrPas(r), 1, p - r)); + if (p[0] = #13) and (p[1] = #10) then + Inc(p, 2) + else + Inc(p); + r := p; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpToMemoForm.GoButtonClick(Sender: TObject); +var + Data : TMemoryStream; +begin + DisplayMemo.Clear; + + GoButton.Enabled := FALSE; + Data := TMemoryStream.Create; + try + httpcli1.URL := URLEdit.Text; + httpcli1.Proxy := ProxyEdit.Text; + httpcli1.ProxyPort := '80'; + httpcli1.RcvdStream := Data; + httpcli1.Get; + LoadMemoFromMemoryStream(DisplayMemo, Data); + finally + Data.Free; + GoButton.Enabled := TRUE; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpToMemoForm.Panel1Resize(Sender: TObject); +begin + GoButton.Left := Panel1.Width - GoButton.Width - 8; + URLEdit.Width := Panel1.Width - URLEdit.Left - GoButton.Width - 16; + ProxyEdit.Width := URLEdit.Width; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/HttpGet1.dfm b/ICS_zlog/Delphi/Internet/HttpGet1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..ab30172c2fad892254f5f5db713eccd5721a9d95 GIT binary patch literal 1505 zcmb7EU2oGc6!nreN!ON5AkfBBd0-l2{TKsj;%%hsI&EF6HE6H6=}luu?I`us4hf0B zg7_i4BJn5q6Fh@sCuzG4BwmtxuXWDxJ+|-fRphiCr+0khw7M4^)L8$KN66{58YQRA zd3X%G#iDU>Apkl8;6`QYCMfm6+uy{R(uh@ zuGgp2X)WU3xHf>g7ZTtcR$Gknn#}?hnI$*4By`B84$OE_E+|^|B0k<^FPrqm(Ujp`oV4OT#rTkhV(17Z%ZmaPq4eUu~v%&5T8+oFPu=1 zN!t{~fu!*NPB8}{ly{DXgqy<0_`gVCDFS^ny?5F}%fW+gG=xY)x%lvm6qoXprKxQ; z;WydZ3ELNxwzR;eDYj+wGH2{q#;IE?vd4r}JGp~XU*t^DDQ77)F{9L!Yuo>7dPPw# zfe|vDH&>i9S`e>LMaso6-lG0FdA{0dy2s7z_U5((#B73xuL53}o12qQint%ldl{!4 zhzB46V6xK2u&_5JTE#x7>8-$eF&p84pp*K-!adbja?tCHCxOxq2*kM&=Z% + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit HttpGet1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, HttpProt, StdCtrls, IniFiles; + +type + THttpGetForm = class(TForm) + Label1: TLabel; + Label2: TLabel; + Label3: TLabel; + Label4: TLabel; + URLEdit: TEdit; + ProxyHostEdit: TEdit; + ProxyPortEdit: TEdit; + FileNameEdit: TEdit; + Label5: TLabel; + GetButton: TButton; + AbortButton: TButton; + InfoLabel: TLabel; + HttpCli1: THttpCli; + procedure GetButtonClick(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure HttpCli1DocData(Sender: TObject; Buffer: Pointer; + Len: Integer); + procedure HttpCli1HeaderData(Sender: TObject); + procedure AbortButtonClick(Sender: TObject); + private + { Déclarations privées } + FInitialized : Boolean; + FIniFileName : String; + public + { Déclarations publiques } + end; + +var + HttpGetForm: THttpGetForm; + +implementation + +{$R *.DFM} +const + SectionData = 'Data'; + KeyURL = 'URL'; + KeyProxyHost = 'ProxyHost'; + KeyProxyPort = 'ProxyPort'; + KeyFileName = 'FileName'; + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpGetForm.FormCreate(Sender: TObject); +begin + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; + InfoLabel.Caption := ''; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpGetForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + IniFile := TIniFile.Create(FIniFileName); + URLEdit.Text := IniFile.ReadString(SectionData, KeyURL, + 'http://www.rtfm.be/fpiette/images/overbyte.gif'); + ProxyHostEdit.Text := IniFile.ReadString(SectionData, KeyProxyHost, + ''); + ProxyPortEdit.Text := IniFile.ReadString(SectionData, KeyProxyPort, + '80'); + FileNameEdit.Text := IniFile.ReadString(SectionData, KeyFileName, + 'test.tmp'); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, Top); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, Left); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + IniFile.Free; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpGetForm.FormClose(Sender: TObject; + var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteString(SectionData, KeyURL, URLEdit.Text); + IniFile.WriteString(SectionData, KeyProxyHost, ProxyHostEdit.Text); + IniFile.WriteString(SectionData, KeyProxyPort, ProxyPortEdit.Text); + IniFile.WriteString(SectionData, KeyFileName, FileNameEdit.Text); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpGetForm.GetButtonClick(Sender: TObject); +begin + HttpCli1.URL := URLEdit.Text; + HttpCli1.Proxy := ProxyHostEdit.Text; + HttpCli1.ProxyPort := ProxyPortEdit.Text; + HttpCli1.RcvdStream := TFileStream.Create(FileNameEdit.Text, fmCreate); + GetButton.Enabled := FALSE; + AbortButton.Enabled := TRUE; + InfoLabel.Caption := 'Loading'; + try + try + HttpCli1.Get; + InfoLabel.Caption := 'Received ' + + IntToStr(HttpCli1.RcvdStream.Size) + ' bytes'; + except + on E: EHttpException do begin + InfoLabel.Caption := 'Failed : ' + + IntToStr(HttpCli1.StatusCode) + ' ' + + HttpCli1.ReasonPhrase;; + end + else + raise; + end; + finally + GetButton.Enabled := TRUE; + AbortButton.Enabled := FALSE; + HttpCli1.RcvdStream.Destroy; + HttpCli1.RcvdStream := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpGetForm.HttpCli1DocData(Sender: TObject; Buffer: Pointer; + Len: Integer); +begin + InfoLabel.Caption := IntToStr(HttpCli1.RcvdCount); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpGetForm.HttpCli1HeaderData(Sender: TObject); +begin + InfoLabel.Caption := InfoLabel.Caption + '.'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpGetForm.AbortButtonClick(Sender: TObject); +begin + HttpCli1.Abort; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/HttpPg1.dfm b/ICS_zlog/Delphi/Internet/HttpPg1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..19116fc05aebe9b06a46369ca13639348b2df2ac GIT binary patch literal 2005 zcma)7(QYF(6rE0*nMu;HXGqUIsFc69DNKKJfA2b^-@A0_k+VJTn5uvRVehfV7K-7u?H zcmZB}5}^n)i6RhWX7Q1_qtJ5NAz1^JA&5(sWbTjtH5*Va!PjuHFkzs#1YiZeM(RBi zd)F+=_{tB8ts-g`49ePVryfsW!CONjbBgbZ*l6Hd32sXX)JB3ooWn6;%Im}#kq8Sw zD?%wsEgq>%Z@^T7cn1OrkU3`(y7fLKbLIz_4k!Vp+E;{u>_$ouHkSw9Zhhy2P^V?8 z;98Ulno%M+rRP{k-;?s3t1PJgYy>f$UW*ijd*C=;9AXC4Gv6&VG=$sU_`$!?XGWL9J@}WFgoS@s!au$bua72}&^_?W zUGPx}{^CB^pMaEj4twygcH!~=)D8t--#OX}qm-y-agfVl5n6m`j*cw8_F?4&_akeB z-iRrE@}luK(dhN%5Z&=5T4AOnQXENODZ*%B8S0(=?*3;h4-1caJ5(xm4WrXOxwH3? z``(h%j0EBIBQ0_Q#Lex zuRT35jSoxXd|Uah?EBaHCMR!E26_ZkeKtB*%=Knr3IVrEJ!-YUT4mAQT$uWkqM$#7 z8D3J=cnJSPGxKy+|IwDLp;0N`Fjn5zyF5beS7+}GpKbNdi#ve0KosyhKvRm@TSR7v zaRv`^L9KMbhQU_aR)5Nc+ST?iJ6`W=yOGCxVnF_g;VFeQ*bb=rMup>@yrm3IU>-NU z3W^6x|Gu!Agqnfpo}JeFbI{}a@r3`Z=Qi%W?4F{h318&e@4C?EUO!17SKb*}=!w#s zli71*!*yppC2E25YU8II=2e{A#k1Zs{}mtLB!l45K)-&vR(zL3$ffc=!FjGdV=h*2 o-O&$bXQtnz&Qefd2~QzyPqY) + You can see what HttpPg does automatically using your browser + and surfing to http://www.unired.net.pe/mensatel.html HttpPg + does programmatically what you can do manually at this page using + your browser. +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Dec 28, 1997 Added a TMemo to display the POST's result. +Jan 16, 1998 Added a Proxy edit box. Added ini file stuff. + Better error handling. Added abort button. +Feb 10, 1999 Corrected Encode function (a test was done the wrong way). + Thanks to Howie Hamlin for finding that one. + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit HttpPg1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, WSocket, HttpProt, ExtCtrls, IniFiles; + +const + HttpPgVersion = 101; + +type + THttpTestForm = class(TForm) + DisplayMemo: TMemo; + Panel1: TPanel; + Label1: TLabel; + Label2: TLabel; + Label3: TLabel; + UserIDEdit: TEdit; + EMailEdit: TEdit; + MessageEdit: TEdit; + SendButton: TButton; + HttpCli1: THttpCli; + ProxyEdit: TEdit; + Label4: TLabel; + AbortButton: TButton; + procedure SendButtonClick(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure AbortButtonClick(Sender: TObject); + private + { Déclarations privées } + FIniFileName : String; + FInitialized : Boolean; + public + { Déclarations publiques } + end; + +var + HttpTestForm: THttpTestForm; + +implementation + +{$R *.DFM} +const + SectionData = 'Data'; + KeyUserID = 'UserID'; + KeyUserName = 'UserName'; + KeyEMail = 'EMail'; + KeyMessage = 'Message'; + KeyProxy = 'Proxy'; + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.FormCreate(Sender: TObject); +begin + DisplayMemo.Clear; + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Restore the form position and size, restore the datas for edit boxes. } +procedure THttpTestForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + IniFile := TIniFile.Create(FIniFileName); + UserIDEdit.Text := IniFile.ReadString(SectionData, KeyUserID, + '27313'); + EMailEdit.Text := IniFile.ReadString(SectionData, KeyEMail, + 'francois.piette@pophost.eunet.be'); + ProxyEdit.Text := IniFile.ReadString(SectionData, KeyProxy, + ''); + MessageEdit.Text := IniFile.ReadString(SectionData, KeyMessage, + 'Hello World ! (Message sent by HttpPg).'); + + Top := IniFile.ReadInteger(SectionWindow, KeyTop, Top); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, Left); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + + IniFile.Free; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Save the form position and size, save the datas for edit boxes. } +procedure THttpTestForm.FormClose(Sender: TObject; + var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteString(SectionData, KeyUserID, UserIDEdit.Text); + IniFile.WriteString(SectionData, KeyProxy, ProxyEdit.Text); + IniFile.WriteString(SectionData, KeyMessage, MessageEdit.Text); + IniFile.WriteString(SectionData, KeyEMail, EMailEdit.Text); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Encode the data to be sent to the CGI } +function Encode(const msg : String) : String; +var + I : Integer; +begin + Result := ''; + for I := 1 to Length(msg) do begin + if msg[I] = ' ' then + Result := Result + '+' + else if msg[I] in ['a'..'z', 'A'..'Z', '0'..'9'] then + Result := Result + msg[I] + else + Result := Result + '%' + IntToHex(ord(msg[I]), 2); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Do the job ! } +procedure THttpTestForm.SendButtonClick(Sender: TObject); +var + DataIn : TMemoryStream; + DataOut : TMemoryStream; + Buf : String; +begin + DisplayMemo.Clear; + DataIn := TMemoryStream.Create; { For the response } + DataOut := TMemoryStream.Create; { For the data to be sent } + try + { Build the data to be sent to the CGI. } + Buf := 'ID=' + Encode(UserIDEdit.Text) + + '&REMITE=' + Encode(EMailEdit.Text) + + '&MENSAJE=' + Encode(MessageEdit.Text); + { Write the data to the stream which will be used to send } + DataOut.Write(Buf[1], Length(Buf)); + { Position the stream at the beginning or nothing will be sent } + DataOut.Seek(0, soFromBeginning); + + { Setup the HTTP component to transmit } + httpcli1.SendStream := DataOut; + httpcli1.RcvdStream := DataIn; + httpcli1.Proxy := ProxyEdit.Text; + httpcli1.ProxyPort := '80'; + HttpCli1.URL := 'http://www.unired.net.pe/cgi-bin/a.out'; + + SendButton.Enabled := FALSE; + AbortButton.Enabled := TRUE; + try + try + httpcli1.Post; + { Data sent, copy the webserver response to the DisplayMemo } + DataIn.Seek(0, 0); + DisplayMemo.Lines.LoadFromStream(DataIn); + except + { An error occured ! } + DisplayMemo.Lines.Add('Failed : ' + HttpCli1.ReasonPhrase); + raise + end; + finally + SendButton.Enabled := TRUE; + AbortButton.Enabled := FALSE; + end; + finally + DataOut.Free; + DataIn.Free; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.AbortButtonClick(Sender: TObject); +begin + HttpCli1.Abort; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/HttpThr1.dfm b/ICS_zlog/Delphi/Internet/HttpThr1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..f9f885d4f301f48ac50826fa8c22767d36e7ee83 GIT binary patch literal 2011 zcmchYL2ueH6vs^hNeIw(lU8jz<*>t~NfcVxVW&a>fkq1=?z-ES5|>0x;>vLaJ?~3Q zyX^x^+P=b0`$9W!iS0r|q_y<03wd_<|7^ea{Ldd9z&?ay*q?M;o!)421Zq1!RRG|) zSKEetN-v>HknQv^3AWP1{1BZ}`9)5K_)`9sE1Y@`b>+UK^pQ7nsr)#nn)W62aHu>= z)-YfKLXH7ZL<=VNF;RZg;x9*2xflF#D~E)rC5L%QWSw zf9iz}o

tCH8`^DE%(7(XkyMrE+8$mK{chg@|{~^%lMMQ3-5~e8-IULeYpgh!oXP zX!nF@f?elQE0h%u4>6t5>>|D0{PJxkwG|hrH^{DBe9nXP~gx$ zL%za(>pWZUS+=A@o-FB=$dy!Crb^@aHfkUZ*q5O_lX5A{ySp*RHT2 z#S)nPEM}u(3CuwTvth9Wr;+7sRxH73W;vS`OJ#t1gVjlTnmCZOBf4)ld#B`+$#7X{ zp>1;Q4%5CA+UHqqVNCGi8h`@qIv!PHQu5^DLnhX^SpEub)K4^MpD}NdKtAyVW!H_J z^v&Mhd_J$9VdC4NQ=Q@@@bUB9IY|5@CkX46KMGdNE>Cjb!-hD?vf=F zUl9)x;~33T9$6WBA&RONC0;m-a?0%;0)1=~6w<_OHQkyL?ECH5w^b#I+L*el)8_zC zVf%_w9O@lBpgd$Jlr?_4ME0b&H_3apw8BCM8w0wcNzACd=|%i`Si(#{o&Z3DLocFj zyx5NGH6tjB#F#JkD}9x{|D8^KKv5vR3|qI;w>q7C(_=-}aqC@X{Hx3IyvtTf0Ki{c CvQ&!z literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/HttpThr1.pas b/ICS_zlog/Delphi/Internet/HttpThr1.pas new file mode 100644 index 00000000..025d7db9 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/HttpThr1.pas @@ -0,0 +1,269 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE (From a work done by Ed Hochman ) +Creation: Jan 13, 1998 +Version: 1.00 +Description: HttpThrd is a demo program showing how to use THttpCli component + in a multi-threaded program. +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit HttpThr1; + +interface + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + HttpProt, StdCtrls, IniFiles; + + +type + TThreadState = (tsInexistant, tsReady, tsInUse); + + THttpThreadForm = class(TForm) + URLEdit: TEdit; + ResultsMemo: TMemo; + DoItButton: TButton; + Label1: TLabel; + Label2: TLabel; + Label3: TLabel; + Label4: TLabel; + Label5: TLabel; + Label6: TLabel; + Thread0Label: TLabel; + Thread1Label: TLabel; + Thread2Label: TLabel; + Thread3Label: TLabel; + Thread4Label: TLabel; + Thread5Label: TLabel; + ProgressListBox: TListBox; + Label14: TLabel; + ProxyEdit: TEdit; + Label15: TLabel; + procedure DoItButtonClick(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + private + FInitialized : Boolean; + FIniFileName : String; + procedure CreateThread(Sender: TObject); + procedure SetThreadState(Which : Integer; State: TThreadState); + public + procedure ProcessResults(ThreadNumber: Integer; Success : Boolean); + end; + +const + SectionData = 'Data'; + KeyURL = 'URL'; + KeyProxy = 'Proxy'; + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + +var + HttpThreadForm: THttpThreadForm; + +implementation + +{$R *.DFM} + +uses + HttpThr2; // The thread class is defined there +const + MaxThreads = 6; // If you change this, change labels on the form +var + // The array with all our threads components + ThreadsObjects : array [0..MaxThreads - 1] of THTTPThread; + // The array with all thread states + ThreadsState : array [0..MaxThreads - 1] of TThreadState; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpThreadForm.FormCreate(Sender: TObject); +var + i: Integer; +begin + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; + for i := Low(ThreadsObjects) to High(ThreadsObjects) do + SetThreadState(i, tsInexistant); //Not created. + ResultsMemo.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpThreadForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + IniFile := TIniFile.Create(FIniFileName); + URLEdit.Text := IniFile.ReadString(SectionData, KeyURL, + 'http://www.rtfm.be/fpiette'); + ProxyEdit.Text := IniFile.ReadString(SectionData, KeyProxy, ''); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, Top); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, Left); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + + IniFile.Free; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpThreadForm.FormClose(Sender: TObject; + var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteString(SectionData, KeyURL, URLEdit.Text); + IniFile.WriteString(SectionData, KeyProxy, proxyEdit.Text); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpThreadForm.DoItButtonClick(Sender: TObject); +var + i: Integer; +begin + for i := Low(ThreadsObjects) to High(ThreadsObjects) do begin + if ThreadsState[i] = tsInexistant then //Thread has not been created yet + CreateThread(Self); + + if ThreadsState[i] = tsReady then begin //Thread is ready for use + with ThreadsObjects[i] do begin + FURL := UrlEdit.Text; + FProxy := ProxyEdit.Text; + SetThreadState(i, tsInUse); // In use + Resume; //get the page + Exit; //For now, only start one thread for each click of DoIt + end; + end; + end; + MessageBeep(MB_OK); + ShowMessage('No more threads available'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpThreadForm.CreateThread(Sender: TObject); +var + i: Integer; +begin + for i := Low(ThreadsObjects) to High(ThreadsObjects) do begin + if ThreadsObjects[i] = nil then begin + ThreadsObjects[i] := THTTPThread.Create(True); + ThreadsObjects[i].Setup(i); //Create the HTTP object + SetThreadState(i, tsReady); + Exit; //Found and activated an unused thread + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpThreadForm.SetThreadState(Which : Integer; State: TThreadState); +begin + ThreadsState[Which] := State; + case which of + 0: Thread0Label.Caption := IntToStr(Ord(State)); + 1: Thread1Label.Caption := IntToStr(Ord(State)); + 2: Thread2Label.Caption := IntToStr(Ord(State)); + 3: Thread3Label.Caption := IntToStr(Ord(State)); + 4: Thread4Label.Caption := IntToStr(Ord(State)); + 5: Thread5Label.Caption := IntToStr(Ord(State)); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure LoadMemoFromMemoryStream(Memo : TMemo; Stream : TMemoryStream); +var + p, q, r : PChar; +begin + p := Stream.Memory; + q := p + Stream.Size - 1; + r := p; + while (p <> nil) and (p < q) do begin + while (p < q) and (p^<> #13) do + Inc(p); + Memo.Lines.Add(Copy(StrPas(r), 1, p - r)); + if (p[0] = #13) and (p[1] = #10) then + Inc(p, 2) + else + Inc(p); + r := p; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +// To be called by each thread as it completes (using Synchronize !) +procedure THttpThreadForm.ProcessResults + (ThreadNumber: Integer; Success : Boolean); +var + Stream : TMemoryStream; +begin + ThreadsObjects[ThreadNumber].Suspend; + if Success then begin + ResultsMemo.Lines.Add('* * * * * * THREAD ' + + IntToStr(ThreadNumber) + ' * * * * * *'); + Stream := ThreadsObjects[ThreadNumber].FHttpCli.RcvdStream + as TMemoryStream; + LoadMemoFromMemoryStream(ResultsMemo, Stream); + ResultsMemo.Lines.Add(''); + end + else begin + // There was an error getting data. + ResultsMemo.Lines.Add('Nothing returned by thread: ' + + IntToStr(ThreadNumber)); + end; + ResultsMemo.Lines.Add('* * * * * * * * * * * * * * * * * * * *'); + SetThreadState(ThreadNumber, tsReady); + //Waiting for something to do (get next url here) +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/HttpThr2.pas b/ICS_zlog/Delphi/Internet/HttpThr2.pas new file mode 100644 index 00000000..ff2992fd --- /dev/null +++ b/ICS_zlog/Delphi/Internet/HttpThr2.pas @@ -0,0 +1,161 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE (From a work done by Ed Hochman ) +Creation: Jan 13, 1998 +Version: 1.00 +Description: HttpThrd is a demo program showing how to use THttpCli component + in a multi-threaded program. +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit HttpThr2; + +interface + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + HttpProt; + +type + THTTPThread = class(TThread) + private + FProgress : String; + procedure UpdateStatus; + procedure ShowProgress; + procedure Progress(Msg : String); + procedure DocBegin(Sender : TObject); + procedure DocData(Sender : TObject; Buffer : Pointer; Len : Integer); + procedure DocEnd(Sender : TObject); + published + procedure Setup(i: Integer); + procedure Execute; override; + public + FURL : String; + FProxy : String; + FThreadNumber : Integer; + FHttpCli : THTTPCli; + Success : Boolean; + end; + +implementation + +uses + HttpThr1; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THTTPThread.Setup(i: Integer); +begin + FThreadNumber := i; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THTTPThread.UpdateStatus; +begin + HttpThreadForm.ProcessResults(FThreadNumber, Success); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THTTPThread.ShowProgress; +begin + HttpThreadForm.ProgressListBox.Items.Add(FProgress); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THTTPThread.Progress(Msg : String); +begin + FProgress := Msg; + SynChronize(ShowProgress); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THTTPThread.Execute; +begin + FHttpCli := THTTPCli.Create(Nil); + FHttpCli.MultiThreaded := TRUE; + FHttpCli.RcvdStream := TMemoryStream.Create; + FHttpCli.OnDocBegin := DocBegin; + FHttpCli.OnDocEnd := DocEnd; + FHttpCli.OnDocData := DocData; + while not Terminated do begin + Progress(IntToStr(FThreadNumber) + ' Start get'); + with FHttpCli do begin + URL := FURL; + Proxy := FProxy; + (RcvdStream as TMemoryStream).Clear; + try + Get; // Get page from internet + Success := TRUE; + except + Success := FALSE; + end; + end; + + if not Terminated then + Synchronize(UpdateStatus); + end; + + if FHttpCli.RcvdStream <> nil then + FHttpCli.RcvdStream.Free; + + FHttpCli.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THTTPThread.DocBegin(Sender : TObject); +begin + Progress(IntToStr(FThreadNumber) + ' Doc begin'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THTTPThread.DocData(Sender : TObject; Buffer : Pointer; Len : Integer); +begin + Progress(IntToStr(FThreadNumber) + ' Doc data'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THTTPThread.DocEnd(Sender : TObject); +begin + Progress(IntToStr(FThreadNumber) + ' Doc end'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/Httpdmo.dpr b/ICS_zlog/Delphi/Internet/Httpdmo.dpr new file mode 100644 index 00000000..5d930194 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/Httpdmo.dpr @@ -0,0 +1,12 @@ +program HttpDmo; + +uses + Forms, + HttpDmo1 in 'HttpDmo1.pas' {HttpToMemoForm}; + +{$R *.RES} + +begin + Application.CreateForm(THttpToMemoForm, HttpToMemoForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/Ics.ico b/ICS_zlog/Delphi/Internet/Ics.ico new file mode 100644 index 0000000000000000000000000000000000000000..e5f5024bfa2fbb32444006376a0e5dcb6bc5114d GIT binary patch literal 766 zcmb`DF%H5o3`KttLpPY1J8}$;<{R`%Jq}~XZsFODX{k^oB;4A`&;N;kB6WPjaFxgN zB;6SAAR8(~a&P7%i zjnKW}pOywt}6_*zau$|4e4z7X@@rf&c&j literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/IcsDll1.dpr b/ICS_zlog/Delphi/Internet/IcsDll1.dpr new file mode 100644 index 00000000..f0e2901c --- /dev/null +++ b/ICS_zlog/Delphi/Internet/IcsDll1.dpr @@ -0,0 +1,286 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Creation: April 03, 2000 +Description: This is a demo showing how to use a TWSocket component in a DLL. + This demo must be used with ICS TcpSrv demo program as a server. + The DLL is a client which connect to the server and send "time" + command, then wait for the reply and return it in the buffer + passed to the DLL. + There is only one function exported from the DLL: IcsDllDemo. + It takes four arguments: a pointer to the hostname to connect to, + a pointer to the port, a pointer to a buffer and a pointer for + buffer size. On entry buffer size must be initialised with the + size of the actual buffer. On exit, it is filled with the + actual reply size. The function's return value is the error code + such as 10061 when the server is not running. +Version: 1.02 +EMail: http://www.overbyte.be http://www.rtfm.be/fpiette + francois.piette@overbyte.be francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 1996-2002 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +History: +Apr 29, 2000 V1.01 Use WSocketForceLoadWinsock. +Apr 27, 2002 V1.02 Use WSocketUnregisterClass + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +library IcsDll1; + +{$DEFINE NOFORMS} // This will avoid forms unit and reduce DLL size +// You should add NOFORMS in the project options to be sure to have all units +// compiled with this option. + +uses + Windows, Messages, SysUtils, Classes, WSocket; + +const + WSocketVersion = 102; + CopyRight : String = ' TWSocket (c) 2000-2002 Francois Piette V1.02 '; + +function IcsDllDemo(HostName : PChar; + Port : PChar; + Buffer : PChar; + BufSize : PInteger): Integer; stdcall; forward; +procedure StrToBuffer(Buffer : PChar; BufSize : PInteger; Msg : String); forward; + +exports + IcsDllDemo; + +type + // We use a workerthread to do the job. + // This will allows the DLL to be called by several processes simultaneously + TClientThread = class(TThread) + private + FClientSocket : TWSocket; + FBannerReceived : Boolean; + FErrorCode : PInteger; + FBuffer : PChar; + FBufSize : PInteger; + FHostName : PChar; + FPort : PChar; + procedure ClientWSocketDataAvailable(Sender: TObject; Error: Word); + procedure ClientWSocketSessionConnected(Sender: TObject; Error: Word); + procedure ClientWSocketSessionClosed(Sender: TObject; Error: Word); + protected + procedure Execute; override; + public + constructor Create; + destructor Destroy; override; + + property ClientWSocket : TWSocket read FClientSocket write FClientSocket; + property Buffer : PChar read FBuffer write FBuffer; + property BufSize : PInteger read FBufSize write FBufSize; + property ErrorCode : PInteger read FErrorCode write FErrorCode; + property HostName : PChar read FHostName write FHostName; + property Port : PChar read FPort write FPort; + end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Create a new thread in the blocked state. This allow the user to register } +{ the client thread before it actually start working. } +constructor TClientThread.Create; +begin + FreeOnTerminate := TRUE; + inherited Create(TRUE); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Destroy the thread. Destroy the ClientWSocket if needed. } +destructor TClientThread.Destroy; +begin + if Assigned(FClientSocket) then begin + FClientSocket.Destroy; + FClientSocket := nil; + end; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This is the main thread routine. There is not much to do because TWSocket } +{ is event driven. So everythong to do is done inside an event handler, } +{ mostly the OnDataAvailable event handler which is triggered each time } +{ something is received. } +procedure TClientThread.Execute; +begin + try + { Create the client TWSocket. It is important to create it inside the } + { Execute method because it *must* be created by the thread. } + { Otherwise the messages sent by winsock would be processed in the } + { main thread context, effectively disabling multi-threading. } + FClientSocket := TWSocket.Create(nil); + FClientSocket.OnDataAvailable := ClientWSocketDataAvailable; + FClientSocket.OnSessionConnected := ClientWSocketSessionConnected; + FClientSocket.OnSessionClosed := ClientWSocketSessionClosed; + FClientSocket.LineMode := TRUE; + FClientSocket.Addr := FHostName; + FClientSocket.Port := FPort; + FClientSocket.Proto := 'tcp'; + FClientSocket.Connect; + + { Message loop to handle TWSocket messages } + { The loop is exited when WM_QUIT message is received } + FClientSocket.MessageLoop; + except + on E:Exception do begin + FErrorCode^ := -3; + StrToBuffer(Buffer, BufSize, E.ClassName + ':' + E.Message); + end; + end; + + { Returning from the Execute function effectively terminate the thread } + ReturnValue := 0; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when the client connection is established. } +procedure TClientThread.ClientWSocketSessionConnected( + Sender: TObject; Error: Word); +begin + if Error <> 0 then begin + FErrorCode^ := Error; + StrToBuffer(Buffer, BufSize, 'Connect failed'); + PostMessage(FClientSocket.Handle, WM_QUIT, 0, 0); + Exit; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when the client connection is closed. } +procedure TClientThread.ClientWSocketSessionClosed( + Sender: TObject; Error: Word); +begin + PostMessage(FClientSocket.Handle, WM_QUIT, 0, 0); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when data has been received from server. } +{ Since this sample program use line mode, we comes here only when a } +{ complete line has been received. } +procedure TClientThread.ClientWSocketDataAvailable( + Sender: TObject; + Error: Word); +var + RcvBuffer : String; +begin + // Received the line + RcvBuffer := FClientSocket.ReceiveStr; + // Check if we already received the banner (message sent by server + // as soon as we are connected. + if not FBannerReceived then begin + // We are just receiving the banner. Flag as received + FBannerReceived := TRUE; + // Then send the command to the server + FClientSocket.SendStr('time' + #13 + #10); + end + else begin + // We already received then banner. So this must be the answer + // to our command. Copy to the buffer, without trailling CR/LF + // and without overflowing the given buffer + if Length(RcvBuffer) < BufSize^ then + BufSize^ := Length(RcvBuffer) - 2; // Remove CR/LF + if BufSize^ > 0 then + Move(RcvBuffer[1], Buffer^, BufSize^); + // Then just close the communication + FClientSocket.CloseDelayed; + FErrorCode^ := 0; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Copy a string to a buffer with overflow check. } +procedure StrToBuffer(Buffer : PChar; BufSize : PInteger; Msg : String); +begin + if Length(Msg) < BufSize^ then + BufSize^ := Length(Msg); + if BufSize^ > 0 then + Move(Msg[1], Buffer^, BufSize^); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function IcsDllDemo( + HostName : PChar; + Port : PChar; + Buffer : PChar; + BufSize : PInteger): integer; stdcall; +var + WorkerThread : TClientThread; +begin + try + Result := -1; + // Create a new thread. It is created in sleeping state + WorkerThread := TClientThread.Create; + // Then pass all parameters + WorkerThread.Buffer := Buffer; + WorkerThread.BufSize := BufSize; + WorkerThread.ErrorCode := @Result; + WorkerThread.HostName := HostName; + WorkerThread.Port := Port; + // Then let thread start his work + WorkerThread.Resume; + // And wait until it finishes + WaitForSingleObject(WorkerThread.Handle, INFINITE); + except + on E:Exception do begin + Result := -2; + StrToBuffer(Buffer, BufSize, E.ClassName + ': ' + E.Message); + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure DLLHandler(Reason: Integer); +begin + if Reason = DLL_PROCESS_DETACH then begin +// MessageBox(0, PChar('Reason = ' + IntToStr(Reason)), 'DLLHandler', MB_OK); + WSocketCancelForceLoadWinsock; + WSocketUnregisterClass; // 27/04/2002 + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +begin +// MessageBox(0, PChar('DLL Init ' + IntToStr(WSocketGCount)), 'DLL', MB_OK); + WSocketForceLoadWinsock; + DLLProc := @DLLHandler; +end. diff --git a/ICS_zlog/Delphi/Internet/IcsIsap1.dfm b/ICS_zlog/Delphi/Internet/IcsIsap1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..50bc95fdfd0b7a9172216de5f69d39854dfa48ac GIT binary patch literal 199 zcmey*#Sr4@9PAnF7~mQ1>g4P166)j1U?8xXfq@|;z|BA?#51|rvpBIJGdwlPH$SB` zCshzbgwH=G#knXou_V>MC?&OsgWWN?Br`v+n2(XgFEKZjO~9?B0H_@z>RFPS%i*5~ z;jk;fjWtA91X01jz~YmdR>J&>kvSy4fcXL=n@4J9dPWKJ69(4s%#@N0=68$?3;+gr BK$idj literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/IcsIsap1.pas b/ICS_zlog/Delphi/Internet/IcsIsap1.pas new file mode 100644 index 00000000..207d000d --- /dev/null +++ b/ICS_zlog/Delphi/Internet/IcsIsap1.pas @@ -0,0 +1,184 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: ISAPI dll showing how to use ICS component to build extension + to a webserver (note that ICS has a HTTP Server component which + could be used to build a web application without a webserver). + This ISAPI DLL is very basic. When invoked, it will open a FTP + connection to the localhost with user/password root/root and + retrieve the home directory list and return it as an answer + to the client browser. + To use this demo, you have to setup your webserver so that it is + able to execute this ISAPI dll and so that there is a FTP server + running on localhost and accepting user root with password root. + The ICS sample FTP server is OK as well as Microsoft FTP server + provided you configure it correctly. + FTP parameters are hardcoded in DoTheJob procedure. In a real + program, you probably would get them from the requesting URL. + This sample program has been tested with Delphi 5 and IIS5 running + on Windows 2000. Should work as well with other configurations... +Creation: July 22, 2000 +Version: 1.00 +EMail: http://users.swing.be/francois.piette francois.piette@swing.be + http://www.rtfm.be/fpiette francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + See http://www.rtfm.be/fpiette/supportuk.htm for subscription. +Legal issues: Copyright (C) 2000 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +History: + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit IcsIsap1; + +{$B-} { Enable partial boolean evaluation } +{$T-} { Untyped pointers } +{$X+} { Enable extended syntax } + +interface + +uses + Windows, Messages, SysUtils, Classes, HTTPApp, FtpCli; + +const + IcsIsapi1Version = 100; + CopyRight : String = ' IcsIsapi (c) 2000 F. Piette V1.00 '; + WM_START_MESSAGE = WM_USER + 1; + +type + TIcsIsapiWebModule = class(TWebModule) + procedure WebModule1FtpWebActionItemAction( + Sender : TObject; + Request : TWebRequest; + Response : TWebResponse; + var Handled : Boolean); + end; + +var + IcsIsapiWebModule: TIcsIsapiWebModule; + +implementation + +{$R *.DFM} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure DoTheJob(FtpCli1 : TFtpClient); +var + Buf : String; +begin + try + // Setup FTP parameters + FtpCli1.HostName := 'localhost'; + FtpCli1.Port := 'ftp'; + FtpCli1.UserName := 'root'; + FtpCli1.Password := 'root'; + FtpCli1.HostFileName := ''; + FtpCli1.HostDirName := ''; + try + FtpCli1.Directory; // This is a synchronous function ! + // Add some data to the directory list + Buf := #13#10 + 'Generated by IcsIsapi' + + #13#10 + 'Visit http://www.overbyte.be'; + FtpCli1.LocalStream.Write(Buf[1], Length(Buf)); + except + on E:Exception do begin + Buf := 'FTP Failed: ' + E.ClassName + ' ' + E.Message + #13#10; + FtpCli1.LocalStream.Position := 0; + FtpCli1.LocalStream.Write(Buf[1], Length(Buf)); + end; + end; + finally + // Posting WM_QUIT will make GetMessage return FALSE and message pump + // loop will terminate. + PostMessage(0, WM_QUIT, 0, 0); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TIcsIsapiWebModule.WebModule1FtpWebActionItemAction( + Sender : TObject; + Request : TWebRequest; + Response : TWebResponse; + var Handled : Boolean); +var + FtpCli1 : TFtpClient; + MsgRec : TMsg; +begin + // Dynamically create an ICS FTP client component. + // We can't use a static component because ISAPI are multithreaded + FtpCli1 := TFtpClient.Create(nil); + try + // We use a stream for data, it is much easier and faster than a file + FtpCli1.LocalStream := TMemoryStream.Create; + try + // This ISAPI is event driven (because ICS uses events) + // So we have to start processing using a custom message + // We pass the reference to FtpCli1 so that handler can do the job + // We can't use a global variable because ISAPI is multithreaded + Postmessage(0, WM_START_MESSAGE, 0, Integer(FtpCli1)); + + // ICS Components need a working message pump because they are event + // driven whithout message pump, nothing will happend at component + // level. A message pump is simply a loop calling Windows API + // GetMessage TranslateMessage and DisptachMessage + // If GetMessage retrieves the WM_QUIT, the return value is FALSE + // and the message loop is broken. } + while GetMessage(MsgRec, 0, 0, 0) do begin + // Our custom message is a thread message (hwnd is nul) + if (MsgRec.hwnd = 0) and (MsgRec.message = WM_START_MESSAGE) then + DoTheJob(TFtpClient(MsgRec.lParam)) + else begin + // Normal processing of any other message + TranslateMessage(MsgRec); + DispatchMessage(MsgRec) + end; + end; + // We comes here after everything is done with FTP + // DoTheJob has posted WM_QUIT message + // We used the stream as an answer for http request + FtpCli1.LocalStream.Position := 0; + // Our answer is just plain text data + Response.ContentType := 'text/plain'; + Response.ContentStream := FtpCli1.LocalStream; + // Send to client browser + Response.SendResponse; + finally + FtpCli1.LocalStream.Free; + end; + finally + FtpCli1.Destroy; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. diff --git a/ICS_zlog/Delphi/Internet/IcsIsapi.dpr b/ICS_zlog/Delphi/Internet/IcsIsapi.dpr new file mode 100644 index 00000000..749de447 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/IcsIsapi.dpr @@ -0,0 +1,19 @@ +library IcsIsapi; + +uses + WebBroker, + ISAPIApp, + IcsIsap1 in 'IcsIsap1.pas' {IcsIsapiWebModule: TWebModule}; + +{$R *.RES} + +exports + GetExtensionVersion, + HttpExtensionProc, + TerminateExtension; + +begin + Application.Initialize; + Application.CreateForm(TIcsIsapiWebModule, IcsIsapiWebModule); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/MailRcv.dpr b/ICS_zlog/Delphi/Internet/MailRcv.dpr new file mode 100644 index 00000000..5af0a5c1 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/MailRcv.dpr @@ -0,0 +1,14 @@ +program MailRcv; + +uses + Forms, + MailRcv1 in 'MailRcv1.pas' {POP3ExcercizerForm}, + MailRcv2 in 'MailRcv2.pas' {MessageForm}; + +{$R *.RES} + +begin + Application.CreateForm(TPOP3ExcercizerForm, POP3ExcercizerForm); + Application.CreateForm(TMessageForm, MessageForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/MailRcv1.dfm b/ICS_zlog/Delphi/Internet/MailRcv1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..1bb2a8ad73de40c72b6180cba834774cbe83c634 GIT binary patch literal 4788 zcmbW5O^@3|7{?tuv7Ptqw!2VXB=@qs2(7kV3I%Z>n@vci>?TcIwQvD%GMkus?O;#3 zyL^HkkvMQd;)ukBI~?HF-uMdK_yU|^-aIp&q-j-EY9}-P|9{Us^UQeM|4N!W=nwYW z4_fVE>&_SLVW&Sl()JoZY-(tvvv-9KUyMOK_P+&jCyLKDi6YaL?}1Zj{H7UhG&g?N z3itg9oEh7?*#-V|293*{)$-=hk3zGK)lQqs3#}-KVyid~4q({v#-P%PLb%(Sd2s@u zRX=QZn)iC{m#uDdIBL5kI!ZK^ad6)cC(*eJE?}7qP@ev8k^DOL&VX4x8aX2`Oq>yj z{ZpzR!OH-YwOT)zv|`{v(2pk|E>`+sD~J+scLCx{tA-~le%ok}JZm8jG(g(bfqwyl zWB}qj;drKhRl=dLAgWryJpyM@`Or`1fp>}9BvCre)1PUcYCKOrYWc1oLh~JW<|mGa z5Kc0S&K)=djyHz>BOhKm=RTZ~o>`Q@LNoBEp=EnPEAT-GUp#vj%6Q<7A3ig2tv^_#oz|*ozqj4Ms!2w!Y%S@7k z2+r(uuxPv930Vd`r)j1;@Inxn2m4+E zVqCzA!G6ZzZ5G1r3WI@{B5Xev6{aRB?IGoRt)-E%XoXVIQbfk;m1k@w`GH0QiC^_4a`m) zojI!fBRYMDOyA)8# zjPl11t<8)h=@Yo}-GvWjm|@ceTSF`CV39zTII1DJDWDQAQ+ZNdQdVm*SRybM$JB)v zqZHis1cik65pK}5QG(6V=JB)%OD&I&VUz1LbP{8ICEZip%=m|H#MJHc6>d6p%ZRxn z-emXDCR=iJSbVD-4dy6|#oD106rGKvYG|=NrZKL~Db|Pt*dnLGER)j`-P|JVzi54= ziMYNZ5qTPR?uHcW5I}kPjVCVs&m$6#!8chU}-XO2<(&mr3l(44ciG-HuOK0V#7xjXN;}JN3|3C-35= z&7Pi7t2TRqZT3BRv(K}kvW%<=H9tfW5o?9VTE_!)+Dbl3_xy>x1r3&v`Lj2B9!mse zOHhQDN@;RFJ7nqVuA^Xypll0@@KPzq=shGa?vv+I3OiV19fDJD5kToy{EFZSSA|#k z3@8Vf!H8?t$U>s*0aoRx4cU;v*h?8-&Ui(!b22TcRWIcnEhszHNp;nqgK$Nb)@^7k z5o_@(54bM8l-!h?Cn#bWV?Tc}h(>U(aZW>W%jBiZ?wukvxAA^8zSC&^8c%cl)oP(n zo)JVv#Xf@VaWL|ON9cAm1m2_{2A9(Mzee*X`=_@M8(&pb;Lj=WZ|&uPud@Y9%~P7` zMx15bCOI@X?CDFw-k>n%t!bL=4x;%!N^Ob#i#{q1*PH6-6B%6x&0-LZy#Rj#7kjwX zoJ?ZV+S?_6^0>&%Jle1O{5#6DPUk*=5ZLLp%hXTjc6vDK8vEYSwPHVHpX}C#fU~Yz zKRg0S;!VK;nEIi$EuN73(SIedpY3pBU0r$z^;Y>K_;j|mmY%`g<$g$B?SyqjJi(D1$pNXF^G;-r+lo2sLgu)onx}mz@-C`k5M#9zIqyXCAA)Zd WAc2QbcK%W~J)C>A%Kkugq5Ti|Y{LKm literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/MailRcv1.pas b/ICS_zlog/Delphi/Internet/MailRcv1.pas new file mode 100644 index 00000000..268d5d9b --- /dev/null +++ b/ICS_zlog/Delphi/Internet/MailRcv1.pas @@ -0,0 +1,667 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Object: Show how to use TPop3Cli (POP3 protocol, RFC-1225) +Creation: 03 october 1997 +Version: 1.03 +EMail: http://www.overbyte.be francois.piette@overbyte.be + http://www.rtfm.be/fpiette francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 1997-2002 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Nov 12, 1997 V1.01 Added a GetAll button to get all messages waiting in the + POP3 server, copying them to a file using the UIDL to build + the file name (sorry, wont work with D1 because of long file + name). The message is *NOT* deleted from the POP3 server. +Jan 10, 1998 V1.02 Added port selection +Jul 05, 2002 V1.03 Added header display in separate UI gadget + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit MailRcv1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, ExtCtrls, StdCtrls, IniFiles, Pop3Prot; + +const + MailRcvVersion = 103; + CopyRight : String = ' MailRcv demo (c) 1997-2002 F. Piette V1.03 '; + +type + TPOP3ExcercizerForm = class(TForm) + DisplayMemo: TMemo; + Panel1: TPanel; + InfoLabel: TLabel; + Label1: TLabel; + Label2: TLabel; + Label3: TLabel; + Label4: TLabel; + Label5: TLabel; + ConnectButton: TButton; + QuittButton: TButton; + UserButton: TButton; + HostEdit: TEdit; + UserNameEdit: TEdit; + PassWordEdit: TEdit; + PassButton: TButton; + MsgNumEdit: TEdit; + RetrButton: TButton; + StatButton: TButton; + ListAllButton: TButton; + ListButton: TButton; + DeleteButton: TButton; + NoopButton: TButton; + LastButton: TButton; + ResetButton: TButton; + TopButton: TButton; + MsgLinesEdit: TEdit; + RpopButton: TButton; + UidlButton: TButton; + ApopButton: TButton; + NextButton: TButton; + GetAllButton: TButton; + PortEdit: TEdit; + Label6: TLabel; + Pop3Client: TPop3Cli; + OpenButton: TButton; + AbortButton: TButton; + Label7: TLabel; + SubjectEdit: TEdit; + Label8: TLabel; + FromEdit: TEdit; + Label9: TLabel; + ToEdit: TEdit; + procedure ConnectButtonClick(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure QuittButtonClick(Sender: TObject); + procedure UserButtonClick(Sender: TObject); + procedure PassButtonClick(Sender: TObject); + procedure Pop3ClientMessageBegin(Sender: TObject); + procedure Pop3ClientMessageEnd(Sender: TObject); + procedure Pop3ClientMessageLine(Sender: TObject); + procedure RetrButtonClick(Sender: TObject); + procedure StatButtonClick(Sender: TObject); + procedure ListAllButtonClick(Sender: TObject); + procedure ListButtonClick(Sender: TObject); + procedure Pop3ClientListBegin(Sender: TObject); + procedure Pop3ClientListEnd(Sender: TObject); + procedure Pop3ClientListLine(Sender: TObject); + procedure DeleteButtonClick(Sender: TObject); + procedure NoopButtonClick(Sender: TObject); + procedure LastButtonClick(Sender: TObject); + procedure ResetButtonClick(Sender: TObject); + procedure TopButtonClick(Sender: TObject); + procedure RpopButtonClick(Sender: TObject); + procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); + procedure Pop3ClientDisplay(Sender: TObject; Msg: String); + procedure UidlButtonClick(Sender: TObject); + procedure Pop3ClientUidlBegin(Sender: TObject); + procedure Pop3ClientUidlEnd(Sender: TObject); + procedure Pop3ClientUidlLine(Sender: TObject); + procedure ApopButtonClick(Sender: TObject); + procedure NextButtonClick(Sender: TObject); + procedure GetAllButtonClick(Sender: TObject); + procedure Pop3ClientRequestDone(Sender: TObject; RqType: TPop3Request; + Error: Word); + procedure OpenButtonClick(Sender: TObject); + procedure AbortButtonClick(Sender: TObject); + procedure Pop3ClientHeaderEnd(Sender: TObject); + private + FFile : TextFile; + FFileName : String; + FFileOpened : Boolean; + FGetAllState : Integer; + FMsgPath : String; + procedure Exec(MethodPtr : TPop3NextProc; + MethodName : String); + procedure MessageBegin(Sender: TObject); + procedure MessageLine(Sender: TObject); + procedure GetAllMessageLine(Sender: TObject); + procedure GetAllRequestDone(Sender: TObject; + RqType: TPop3Request; Error: Word); + procedure NextMessageRequestDone(Sender: TObject; + RqType: TPop3Request; Error: Word); + public + { Déclarations publiques } + end; + +var + POP3ExcercizerForm: TPOP3ExcercizerForm; + +implementation + +{$R *.DFM} + +uses + MailRcv2; + +const + IniFileName = 'MAILRCV.INI'; + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Restore some data from the INI file } +procedure TPOP3ExcercizerForm.FormCreate(Sender: TObject); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(IniFileName); + HostEdit.Text := IniFile.ReadString('Data', 'Host', ''); + PortEdit.Text := IniFile.ReadString('Data', 'Port', ''); + UserNameEdit.Text := IniFile.ReadString('Data', 'UserName', ''); + PassWordEdit.Text := IniFile.ReadString('Data', 'Password', ''); + IniFile.Free; + InfoLabel.Caption := ''; + SubjectEdit.Text := ''; + FromEdit.Text := ''; + ToEdit.Text := ''; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Save data to INI file } +procedure TPOP3ExcercizerForm.FormCloseQuery(Sender: TObject; + var CanClose: Boolean); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(IniFileName); + IniFile.WriteString('Data', 'Host', HostEdit.Text); + IniFile.WriteString('Data', 'Port', PortEdit.Text); + IniFile.WriteString('Data', 'UserName', UserNameEdit.Text); + IniFile.WriteString('Data', 'Password', PassWordEdit.Text); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when the TPop3Client object wants to display } +{ some information such as connection progress or errors. } +procedure TPOP3ExcercizerForm.Pop3ClientDisplay(Sender: TObject; + Msg: String); +begin + DisplayMemo.Lines.Add(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ All the TPop3Client method are of the same type. To simplify this demo } +{ application, Exec transfert the parameters form the various EditBoxes } +{ to the Pop3Client instance and then call the appropriate method, showing } +{ the result in the InfoLabel.Caption. } +procedure TPOP3ExcercizerForm.Exec( + MethodPtr : TPop3NextProc; + MethodName : String); +begin + SubjectEdit.Text := ''; + FromEdit.Text := ''; + ToEdit.Text := ''; + + Pop3Client.Host := HostEdit.Text; + Pop3Client.Port := PortEdit.Text; + Pop3Client.UserName := UserNameEdit.Text; + Pop3Client.PassWord := PassWordEdit.Text; + Pop3Client.MsgNum := StrToInt(MsgNumEdit.Text); + Pop3Client.MsgLines := StrToInt(MsgLinesEdit.Text); + { We need to reassign event handlers because we may have changed them } + { doing GetAllMessages for example } + Pop3Client.OnRequestDone := Pop3ClientRequestDone; + Pop3Client.OnMessageBegin := Pop3ClientMessageBegin; + Pop3Client.OnMessageEnd := Pop3ClientMessageEnd; + Pop3Client.OnMessageLine := Pop3ClientMessageLine; + InfoLabel.Caption := MethodName + ' started'; + try + MethodPtr; + InfoLabel.Caption := MethodName + ' ok'; + except + on E:Exception do begin + InfoLabel.Caption := MethodName + ' failed (' + E.Message + ')'; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.ConnectButtonClick(Sender: TObject); +begin + Exec(Pop3Client.Connect, 'Connect'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.OpenButtonClick(Sender: TObject); +begin + Exec(Pop3Client.Open, 'Open'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.UserButtonClick(Sender: TObject); +begin + Exec(Pop3Client.User, 'User'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.PassButtonClick(Sender: TObject); +begin + Exec(Pop3Client.Pass, 'Pass'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.QuittButtonClick(Sender: TObject); +begin + Exec(Pop3Client.Quit, 'Quit'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.AbortButtonClick(Sender: TObject); +begin + Exec(Pop3Client.Abort, 'Abort'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.RetrButtonClick(Sender: TObject); +begin + Exec(Pop3Client.Retr, 'Retr'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.StatButtonClick(Sender: TObject); +begin + Exec(Pop3Client.Stat, 'Stat'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.ListAllButtonClick(Sender: TObject); +begin + MsgNumEdit.Text := '0'; + Exec(Pop3Client.List, 'List All'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.ListButtonClick(Sender: TObject); +begin + Exec(Pop3Client.List, 'List'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.DeleteButtonClick(Sender: TObject); +begin + Exec(Pop3Client.Dele, 'Delete'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.NoopButtonClick(Sender: TObject); +begin + Exec(Pop3Client.Noop, 'Noop'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.LastButtonClick(Sender: TObject); +begin + Exec(Pop3Client.Last, 'Last'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.ResetButtonClick(Sender: TObject); +begin + Exec(Pop3Client.RSet, 'Rset'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.TopButtonClick(Sender: TObject); +begin + Exec(Pop3Client.Top, 'Top'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.RpopButtonClick(Sender: TObject); +begin + Exec(Pop3Client.RPop, 'Rpop'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.UidlButtonClick(Sender: TObject); +begin + Exec(Pop3Client.Uidl, 'Uidl'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.ApopButtonClick(Sender: TObject); +begin + Exec(Pop3Client.APop, 'Apop'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when TPop3Client is about to receive a } +{ message. The MsgNum property gives the message number. } +{ This event handler could be used to open the file used to store the msg. } +{ The file handle could be stored in the TPop3Client.Tag property to be } +{ easily retrieved by the OnMessageLine and OnMessageEnd event handlers. } +procedure TPOP3ExcercizerForm.Pop3ClientMessageBegin(Sender: TObject); +begin + DisplayMemo.Lines.Add('*** Message ' + + IntToStr((Sender as TPop3Cli).MsgNum) + + ' begin ***'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when TPop3Client has detected the end of a } +{ message, even if there is an error or exception, this event gets called. } +{ This event handler could be used to close the file used to store the msg. } +procedure TPOP3ExcercizerForm.Pop3ClientMessageEnd(Sender: TObject); +begin + DisplayMemo.Lines.Add('*** Message ' + + IntToStr((Sender as TPop3Cli).MsgNum) + + ' end ***'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called for each message line that TPop3Client is } +{ receiveing. This could be used to write the message lines to a file. } +procedure TPOP3ExcercizerForm.Pop3ClientMessageLine(Sender: TObject); +begin + DisplayMemo.Lines.Add((Sender as TPop3Cli).LastResponse); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when TPop3Client is about to receive a } +{ list line. The MsgNum property gives the message number. } +procedure TPOP3ExcercizerForm.Pop3ClientListBegin(Sender: TObject); +begin + DisplayMemo.Lines.Add('*** List begin ***'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when TPop3Client has received the last list } +{ line. } +procedure TPOP3ExcercizerForm.Pop3ClientListEnd(Sender: TObject); +begin + DisplayMemo.Lines.Add('*** List End ***'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called for each list line received by TPop3Client. } +procedure TPOP3ExcercizerForm.Pop3ClientListLine(Sender: TObject); +var + Buffer : String; +begin + Buffer := 'MsgNum = ' + IntToStr((Sender as TPop3Cli).MsgNum) + ' ' + + 'MsgSize = ' + IntToStr((Sender as TPop3Cli).MsgSize) + ' ' + + 'Line = ''' + (Sender as TPop3Cli).LastResponse + ''''; + DisplayMemo.Lines.Add(Buffer); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.Pop3ClientUidlBegin(Sender: TObject); +begin + DisplayMemo.Lines.Add('*** Uidl begin ***'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.Pop3ClientUidlEnd(Sender: TObject); +begin + DisplayMemo.Lines.Add('*** Uidl end ***'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.Pop3ClientUidlLine(Sender: TObject); +var + Buffer : String; +begin + Buffer := 'MsgNum = ' + IntToStr((Sender as TPop3Cli).MsgNum) + ' ' + + 'MsgUidl = ' + (Sender as TPop3Cli).MsgUidl + ''''; + DisplayMemo.Lines.Add(Buffer); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.MessageBegin(Sender: TObject); +begin + MessageForm.Caption := 'Message ' + + IntToStr((Sender as TPop3Cli).MsgNum); + MessageForm.Show; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.MessageLine(Sender: TObject); +begin + MessageForm.DisplayMemo.Lines.Add((Sender as TPop3Cli).LastResponse); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.NextButtonClick(Sender: TObject); +begin + MessageForm.DisplayMemo.Clear; + MessageForm.Caption := 'Message'; + Pop3Client.OnMessageBegin := MessageBegin; + Pop3Client.OnMessageEnd := nil; + Pop3Client.OnMessageLine := MessageLine; + Pop3Client.OnRequestDone := NextMessageRequestDone; + Pop3Client.MsgNum := StrToInt(MsgNumEdit.Text); + Pop3Client.Retr; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.NextMessageRequestDone( + Sender: TObject; + RqType: TPop3Request; Error: Word); +begin + if Error <> 0 then + Exit; + + MsgNumEdit.Text := IntToStr(StrToInt(MsgNumEdit.Text) + 1); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.GetAllMessageLine(Sender: TObject); +begin + Writeln(FFile, (Sender as TPop3Cli).LastResponse); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ The procedure here after will start an event chain that will eventually } +{ download all messages for the POP3 server. We cannot simply loop because } +{ the POP3 compomnet is asynchronous: it will not wait for operation done } +{ before returning. We must "chain" operations one after the other using } +{ the OnRequestDone event handler. We use the variable FGetAllState to keep } +{ track of where we are. } +{ To get all messages, we must first call Stat to know how many messages } +{ are on the server, then for each message we call Uidl to get a unique } +{ identifier for each message to build a file name and know if we already } +{ have a message, then we retrieve the message, then we increment the } +{ message number and continue until the number of messages is reached. } +{ We should start a TTimer to handle timeout... } +procedure TPOP3ExcercizerForm.GetAllButtonClick(Sender: TObject); +var + IniFile : TIniFile; +begin + { Get path from INI file } + IniFile := TIniFile.Create(IniFileName); + FMsgPath := IniFile.ReadString('Data', 'MsgPath', + ExtractFilePath(Application.ExeName)); + IniFile.Free; + + { Be sure to have an ending backslash } + if (Length(FMsgPath) > 0) and (FMsgPath[Length(FMsgPath)] <> '\') then + FMsgPath := FMsgPath + '\'; + + FGetAllState := 0; + FFileOpened := FALSE; + Pop3Client.OnRequestDone := GetAllRequestDone; + Pop3Client.OnMessageBegin := nil; + Pop3Client.OnMessageEnd := nil; + Pop3Client.OnMessageLine := GetAllMessageLine; + Pop3Client.Stat; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when a request related to GetAll is done. } +{ We check for errors and our state variable FGetAllState which tells us } +{ where we are (stat, uidl or retr which are the 4 commands we use. } +{ Note that we also could use Dele to remove the messages from the server. } +procedure TPOP3ExcercizerForm.GetAllRequestDone( + Sender: TObject; + RqType: TPop3Request; Error: Word); +begin + if Error <> 0 then begin + if FFileOpened then begin + FFileOpened := FALSE; + CloseFile(FFile); + end; + DisplayMemo.Lines.Add('Error ' + Pop3Client.ErrorMessage); + Exit; + end; + + try + case FGetAllState of + 0: begin { Comes from the Stat command } + if Pop3Client.MsgCount < 1 then begin + DisplayMemo.Lines.Add('No message to download.'); + Exit; + end; + Pop3Client.MsgNum := 1; { Start with first message } + FGetAllState := 1; + Pop3Client.Uidl; + end; + 1: begin { Comes from the Uidl command } + FFileName := FMsgPath + 'Msg ' + Pop3Client.MsgUidl + '.txt'; + if FileExists(FFileName) then begin + DisplayMemo.Lines.Add('Message ' + IntToStr(Pop3Client.MsgNum) + ' already here'); + if Pop3Client.MsgNum >= Pop3Client.MsgCount then begin + DisplayMemo.Lines.Add('Finished'); + Exit; + end; + Pop3Client.MsgNum := Pop3Client.MsgNum + 1; + FGetAllState := 1; + Pop3Client.Uidl; + end + else begin + DisplayMemo.Lines.Add('Message ' + IntToStr(Pop3Client.MsgNum)); + AssignFile(FFile, FFileName); + Rewrite(FFile); + FFileOpened := TRUE; + FGetAllState := 2; + Pop3Client.Retr; + end; + end; + 2: begin { Comes from the Retr command } + FFileOpened := FALSE; + CloseFile(FFile); + if Pop3Client.MsgNum >= Pop3Client.MsgCount then begin + DisplayMemo.Lines.Add('Finished'); + Exit; + end; + Pop3Client.MsgNum := Pop3Client.MsgNum + 1; + FGetAllState := 1; + Pop3Client.Uidl; + end; + else + DisplayMemo.Lines.Add('Invalid state'); + Exit; + end; + except + on E:Exception do begin + if FFileOpened then begin + FFileOpened := FALSE; + CloseFile(FFile); + end; + DisplayMemo.Lines.Add('Error: ' + E.Message); + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.Pop3ClientRequestDone(Sender: TObject; + RqType: TPop3Request; Error: Word); +begin + DisplayMemo.Lines.Add('Request Done Rq=' + IntToStr(Integer(RqType)) + + ' Error=' + IntToStr(Error)); + + if RqType = pop3Stat then begin + InfoLabel.Caption := 'Stat ok, ' + + IntToStr(Pop3Client.MsgCount) + ' messages ' + + IntToStr(Pop3Client.MsgSize) + ' bytes' + end + else if RqType = pop3List then begin + InfoLabel.Caption := 'List ok, ' + + IntToStr(Pop3Client.MsgNum) + ' message ' + + IntToStr(Pop3Client.MsgSize) + ' bytes' + end + else if RqType = pop3Last then begin + InfoLabel.Caption := 'Last = ' + IntToStr(Pop3Client.MsgNum); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.Pop3ClientHeaderEnd(Sender: TObject); +begin + SubjectEdit.Text := Pop3Client.HeaderSubject; + FromEdit.Text := Pop3Client.HeaderFrom; + ToEdit.Text := Pop3Client.HeaderTo; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/MailRcv2.dfm b/ICS_zlog/Delphi/Internet/MailRcv2.dfm new file mode 100644 index 0000000000000000000000000000000000000000..db072fbf7ecbfd7517b70304c68444b2deb5368d GIT binary patch literal 335 zcmYk0!A^rf6h#LRs8A9=p$1h7CdHyNNw-en6($*G$h=8x7k->eKghMVKuq82 zzTBLf^BWPCuPI$VuCwi1P8N6f4k4__7E_i3BCjFSrj4)i%?1wEef5~`T=aLMvW@rc z1WzF9#(JMlnDWjFt%7ibqD(70Pqox0oR)GYRHZ){9Btee1L*$T_TLL{AxLsMqg>&P zf)R&-r}iWvCP^WVAh7`RtjflHk1j*wL_++tbgSbBft}>1OCD@VZ%anouYcRU<1eMC vRXE`?l>(GaHbMc;sWn2?=mghWB%-C!Qm(kcFhE>s+e{eWZ%qZpCFlDCo04dU literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/MailRcv2.pas b/ICS_zlog/Delphi/Internet/MailRcv2.pas new file mode 100644 index 00000000..6ec378a1 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/MailRcv2.pas @@ -0,0 +1,33 @@ +{ +EMail: francois.piette@pophost.eunet.be francois.piette@rtfm.be + http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + +} +unit MailRcv2; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls; + +type + TMessageForm = class(TForm) + DisplayMemo: TMemo; + private + { Déclarations privées } + public + { Déclarations publiques } + end; + +var + MessageForm: TMessageForm; + +implementation + +{$R *.DFM} + +end. diff --git a/ICS_zlog/Delphi/Internet/MailRob.dpr b/ICS_zlog/Delphi/Internet/MailRob.dpr new file mode 100644 index 00000000..905fdcc0 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/MailRob.dpr @@ -0,0 +1,12 @@ +program MailRob; + +uses + Forms, + MailRob1 in 'MailRob1.pas' {MailRobForm}; + +{$R *.RES} + +begin + Application.CreateForm(TMailRobForm, MailRobForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/MailRob1.dfm b/ICS_zlog/Delphi/Internet/MailRob1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..e69b65b2051ae10db46064c1f23dfedbe8c2698b GIT binary patch literal 3134 zcmcIm%Z}?b7*3NmNt-EiIU3H^i_r)q=Eg+~hy~M5%Z${VmL{Bo5DVPKZOuvTDskz| z?mPf&*dg&G?9PIBV986c20ONs^m33`u&Vnz-}hhr*?%{T(7(Cw4g0Nbf9M;R2k-0| zMmXqR?u9R47WIQv!bNZwm(-b)z zp3JkQ%S{P_3^^RhZQ0uHlVC{0fF+nr(~4aV$!H8-1jQ~7G+UH2Gqy78tYuaZRX9%% zj!;~`Cli{ja5ra%~m6SkI&QF8DFV%>z!{n3Lo$fyq1xRB;L z&bf|GIS}-4%D{xff#3SNh|$QV0gqog$D8!+n41mW=T3x~$GvuOjKo?d@k%yYC1L$i z$vs!^Fk$x39m06G*bITmGLFFlvKg3AY2h(|38w>$f^-Z?_F1|deUHXGO8!ysRV!!@ z?^_)JNd)-ZC6MoQ#6bcuiV~EjyyxJCh;$?sP5}fy=ABLHgn@hEp76{wjBs}TmK+8# z%OXVA)vJ0@kV;idxn0h;(I>Z~I4g(qq*MoOEVU?rKcJ9`T5q@LM74Woiv&>ih*v}e zTSR0QE!w1CZ&5F0J6oh2ms?b@TPoiYcrD+OeLLTy9)*#Z$&HLHASYa>{AE5H`Bd(o z3M>#{AfhfJs^o1F@k!*1MI>BWnF>s59z9(MYZc|DymEQLW2Qt}t9; zl)`vEj-nWCij4K!w#v{qsEnmm#?BPxs;mm08o7^k{YwfH_~8KD(Ugf`GN>eYUlLqq zvZ5RKbeo_mT9;#;KptKR_A>Bu<^5zEtUu53()Wi_T0kYk>*$|s;^u3p1 zKYz1t*H5R}5!2e{iYny7W)3m}t!uv<+WT=aqJ}&)IWT7uVdYHLwai27{M8O7B{!}H z=1iixIg^SBsJY%5lc{3TK+WW-&J<+VS%RS=dtC^3k)Wegp@h|Zjey_ceUj7ZEOl_N zcNI*jObJ_vW+Ol(D#@i~NbyhsnmhE;6A*bDq(#tfE*$#><+?=j)~`vVDQofBzty6u zYEi!&YYrRvBDYC2O*}c8Rsgl$$g+p;qsE^7{uVrDi z)BN30ycKG}DTfwL?ZW96r6V9plY(onx#VXY8OO(Q$0b~WYOPJ0HE05Q9P zQ+jrN{n009SNv7S?`guq#|3hl;;TUnF%frgoj*$He9rHG=dfT^Cf + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Aug 03, 1998 V1.10 Adapted with new TSmtpCli component + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit MailRob1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, IniFiles, MbxFile, StdCtrls, ExtCtrls, SmtpProt, DB, DBTables; + +const + RobotMailVersion = 110; + +type + TMailRobForm = class(TForm) + MbxHandler: TMbxHandler; + DisplayMemo: TMemo; + TopPanel: TPanel; + GetFromMbxButton: TButton; + EMailMemo: TMemo; + MiddlePanel: TPanel; + Label1: TLabel; + HostEdit: TEdit; + PortEdit: TEdit; + FromEdit: TEdit; + Label2: TLabel; + Subject: TLabel; + SubjectEdit: TEdit; + SignOnEdit: TEdit; + Label4: TLabel; + SmtpClient: TSyncSmtpCli; + MbxFileEdit: TEdit; + SendButton: TButton; + SaveToListButton: TButton; + LstFileEdit: TEdit; + LoadFromListButton: TButton; + InfoLabel: TLabel; + Label3: TLabel; + MsgFileEdit: TEdit; + MsgFileLoadButton: TButton; + SaveMsgFileButton: TButton; + OpenDialog1: TOpenDialog; + procedure GetFromMbxButtonClick(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure SendButtonClick(Sender: TObject); + procedure SmtpClientGetData(Sender: TObject; LineNum: Integer; + MsgLine: PChar; MaxLen: Integer; var More: Boolean); + procedure SaveToListButtonClick(Sender: TObject); + procedure LoadFromListButtonClick(Sender: TObject); + procedure SmtpClientCommand(Sender: TObject; Msg: String); + procedure SmtpClientResponse(Sender: TObject; Msg: String); + procedure MsgFileLoadButtonClick(Sender: TObject); + procedure SaveMsgFileButtonClick(Sender: TObject); + procedure MbxFileEditDblClick(Sender: TObject); + procedure MsgFileEditDblClick(Sender: TObject); + procedure LstFileEditDblClick(Sender: TObject); + private + FIniFileName : String; + FInitialized : Boolean; + FTxtFileName : String; + FMsgLines : TStrings; + FNames : TList; + FLogFileName : String; + FLog : TStream; + FRunning : Boolean; + procedure ProcessMsg; + function SearchHeader(Key : String) : Integer; + procedure ClearNames; + procedure CommitLog; + procedure CloseLog; + procedure Log(const Msg : String); + procedure LoadEMailMessage(FileName : String); + procedure SaveEMailMessage(FileName : String); + public + { Déclarations publiques } + end; + +var + MailRobForm: TMailRobForm; + +implementation + +{$R *.DFM} +const + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + SectionData = 'Data'; + KeyServer = 'MailServer'; + KeyPort = 'SmtpPort'; + KeyFrom = 'From'; + KeySignOn = 'SignOn'; + KeyMbxFile = 'MbxFile'; + KeyLstFile = 'LstFile'; + KeyMsgFile = 'MsgFile'; + + CrLf : array [0..1] of char = (#13, #10); + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.FormCreate(Sender: TObject); +begin + FMsgLines := TStringList.Create; + FNames := TList.Create; + FIniFileName := LowerCase(Application.ExeName); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; + FTxtFileName := LowerCase(Application.ExeName); + FTxtFileName := Copy(FTxtFileName, 1, Length(FTxtFileName) - 3) + 'txt'; + FLogFileName := LowerCase(Application.ExeName); + FLogFileName := Copy(FLogFileName, 1, Length(FLogFileName) - 3) + 'log'; + CommitLog; + Log('---- Start ----'); + InfoLabel.Caption := ''; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + DisplayMemo.Clear; + + IniFile := TIniFile.Create(FIniFileName); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, Top); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, Left); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + HostEdit.Text := IniFile.ReadString(SectionData, KeyServer, 'mail.server.provider'); + PortEdit.Text := IniFile.ReadString(SectionData, KeyPort, 'smtp'); + FromEdit.Text := IniFile.ReadString(SectionData, KeyFrom, 'your.email@your.provider'); + SignOnEdit.Text := IniFile.ReadString(SectionData, KeySignOn, 'Your full name'); + MbxFileEdit.Text := IniFile.ReadString(SectionData, KeyMbxFile, ''); + LstFileEdit.Text := IniFile.ReadString(SectionData, KeyLstFile, 'c:\temp\emails.txt'); + MsgFileEdit.Text := IniFile.ReadString(SectionData, KeyMsgFile, 'c:\temp\emailmsg.txt'); + IniFile.Free; + LoadEMailMessage(FTxtFileName); + end; + CloseLog; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + Log('Stop'); + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.WriteSTring(SectionData, KeyServer, HostEdit.Text); + IniFile.WriteSTring(SectionData, KeyPort, PortEdit.Text); + IniFile.WriteSTring(SectionData, KeyFrom, FromEdit.Text); + IniFile.WriteSTring(SectionData, KeySignOn, SignOnEdit.Text); + IniFile.WriteSTring(SectionData, KeyMbxFile, MbxFileEdit.Text); + IniFile.WriteSTring(SectionData, KeyLstFile, LstFileEdit.Text); + IniFile.WriteSTring(SectionData, KeyMsgFile, MsgFileEdit.Text); + IniFile.Free; + SaveEMailMessage(FTxtFileName); + MbxHandler.Active := FALSE; + FMsgLines.Destroy; + ClearNames; + FNames.Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.LoadEMailMessage(FileName : String); +begin + EMailMemo.Clear; + SubjectEdit.Text := ''; + try + EMailMemo.Lines.LoadFromFile(FileName); + if EMailMemo.Lines.Count > 0 then begin + SubjectEdit.Text := EMailMemo.Lines[0]; + EMailMemo.Lines.Delete(0); + end; + except + on E:Exception do Log('LoadEMailMessage failed: ' + E.Message); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.SaveEMailMessage(FileName : String); +begin + EMailMemo.Lines.Insert(0, SubjectEdit.Text); + EMailMemo.Lines.SaveToFile(FileName); + EMailMemo.Lines.Delete(0); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.CommitLog; +begin + if Assigned(FLog) then + FLog.Destroy; + try + FLog := TFileStream.Create(FLogFileName, fmOpenReadWrite or fmShareDenyNone); + except + on E:EFOpenError do begin + try + FLog := TFileStream.Create(FLogFileName, fmCreate); + FLog.Destroy; + FLog := TFileStream.Create(FLogFileName, fmOpenReadWrite or fmShareDenyNone); + except + DisplayMemo.Lines.Add('Can''t create log file ' + FLogFileName); + FLog := nil; + end; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.CloseLog; +begin + if Assigned(FLog) then begin + FLog.Destroy; + FLog := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.Log(const Msg : String); +var + Buf : String; +begin + if not Assigned(FLog) then begin + CommitLog; + if not Assigned(FLog) then + Exit; + end; + Buf := FormatDateTime('yyyy/mm/dd hh:nn:ss ', Now); + FLog.Seek(0, soFromEnd); + FLog.WriteBuffer(Buf[1], Length(Buf)); + FLog.WriteBuffer(Msg[1], Length(Msg)); + FLog.WriteBuffer(CrLf, 2); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.GetFromMbxButtonClick(Sender: TObject); +begin + if MbxFileEdit.Text = '' then begin + Application.MessageBox('Please enter the file name in the edit box !', + 'Warning', MB_OK); + Exit; + end; + + GetFromMbxButton.Enabled := FALSE; + try + MbxHandler.FileName := MbxFileEdit.Text; + MbxHandler.Active := TRUE; + ProcessMsg; + finally + GetFromMbxButton.Enabled := TRUE; + MbxHandler.Active := FALSE; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TMailRobForm.SearchHeader(Key : String) : Integer; +var + Line : String; + I, J : Integer; +begin + Key := UpperCase(Key); + Result := -1; + I := 0; + while I < FMsgLines.Count do begin + Line := FMsgLines.Strings[I]; + if Length(Line) = 0 then { End of header } + Break; + J := Pos(':', Line); + if (J > 0) and (UpperCase(Copy(Line, 1, J - 1)) = Key) then begin + Result := I; + Break; + end; + Inc(I); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.ClearNames; +begin + while FNames.Count > 0 do begin + FreeMem(FNames.Items[0], StrLen(PChar(FNames.Items[0])) + 1); + FNames.Delete(0); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function StringCompare(Item1, Item2: Pointer): Integer; +begin + Result := StrComp(PChar(Item1), PChar(Item2)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.ProcessMsg; +var + Line : String; + I : Integer; + EMail : String; + p : PChar; + MsgCount : Integer; + OkCount : Integer; +begin + DisplayMemo.Lines.Add('Clear list'); + ClearNames; + + DisplayMemo.Lines.Add('Reading EMail'); + MsgCount := 0; + OkCount := 0; + while not MbxHandler.Eof do begin + Inc(MsgCount); + FMsgLines.LoadFromStream(MbxHandler.MsgStream); + I := SearchHeader('SUBJECT'); + if I < 0 then + DisplayMemo.Lines.Add('Subject not found') + else begin + Line := FMsgLines.Strings[I]; + + if Copy(Line, 10, 9) = 'SUBSCRIBE' then begin + I := Length(Line); + while (I > 0) and (Line[I] <> ' ') do + Dec(I); + EMail := Copy(Line, I + 1, 255); + GetMem(p, Length(EMail) + 1); + Move(EMail[1], p^, Length(EMail)); + FNames.Add(p); + Inc(OkCount); + end; + end; + MbxHandler.Next; + InfoLabel.Caption := Format('%d/%d/%d', [MsgCount, OkCount, MbxHandler.MsgCount]); + Application.ProcessMessages; + end; + +{$IFNDEF VER80} { Delphi 1 does'nt support sorting TList items } + DisplayMemo.Lines.Add('Sort list'); + FNames.Sort(StringCompare); +{$ENDIF} + + DisplayMemo.Lines.Add('Remove duplicates'); + Line := ''; + p := @Line[1]; + I := 0; + while I < FNames.Count do begin + if StringCompare(p, FNames.Items[I]) = 0 then begin + FreeMem(FNames.Items[I], StrLen(PChar(FNames.Items[I])) + 1); + FNames.Delete(I); + end + else begin + p := FNames.Items[I]; + Inc(I); + end; + end; + + DisplayMemo.Lines.Add('Display list'); + for I := 0 to FNames.Count - 1 do + DisplayMemo.Lines.Add(StrPas(PChar(FNames.Items[I]))); + + DisplayMemo.Lines.Add('Total : ' + IntToStr(FNames.Count)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.SendButtonClick(Sender: TObject); +var + EMail : String; + I : Integer; + OkCount : Integer; + BadCount : Integer; + Success : Boolean; +begin + if FRunning then begin + FRunning := FALSE; + Exit; + end; + FRunning := TRUE; + DisplayMemo.Lines.Add('Sending EMails'); + if FNames.Count <= 0 then begin + Application.MessageBox('List is empty', 'Warning', MB_OK); + Exit; + end; + + OkCount := 0; + BadCount := 0; + try + SmtpClient.SignOn := SignOnEdit.Text; + SmtpClient.Host := HostEdit.Text; + SmtpClient.Port := PortEdit.Text; + Success := SmtpClient.OpenSync; + if not Success then + Exit; + I := 0; + while (not Application.Terminated) and (I < FNames.Count) do begin + if not FRunning then begin + Log('Canceled'); + CommitLog; + DisplayMemo.Lines.Add('Canceled'); + Exit; + end; + EMail := StrPas(PChar(FNames.Items[I])); + DisplayMemo.Lines.Add('Sending to ' + EMail); + Log('Sending to ' + EMail); + Success := FALSE; + try + SmtpClient.RcptName.Clear; + SmtpClient.RcptName.Add(EMail); + SmtpClient.HdrFrom := FromEdit.Text; + SmtpClient.HdrTo := EMail; + SmtpClient.HdrSubject := SubjectEdit.Text; + SmtpClient.FromName := FromEdit.Text; + SmtpClient.EmailFiles := nil; + Success := SmtpClient.MailSync; + except + on E:Exception do Log(E.Message); + end; + if Success then + Inc(OkCount) + else begin + Inc(BadCount); + Log('Can''t send to ' + EMail); + DisplayMemo.Lines.Add('Can''t send to ' + EMail); + { We failed, so disconnect before continuing } + try + SmtpClient.Quit; + except + on E:Exception do Log(E.Message); + end; + try + SmtpClient.Abort; + except + end; + SmtpClient.SignOn := SignOnEdit.Text; + SmtpClient.Host := HostEdit.Text; + SmtpClient.Port := PortEdit.Text; + Success := SmtpClient.OpenSync; + if not Success then + Exit; + end; + CommitLog; + Inc(I); + InfoLabel.Caption := Format('%d/%d/%d', [OkCount, BadCount, FNames.Count]); + end; + finally + try + SmtpClient.Quit; + except + on E:Exception do Log(E.Message); + end; + DisplayMemo.Lines.Add(IntToStr(OkCount) + ' emails sent succesfully'); + DisplayMemo.Lines.Add(IntToStr(BadCount) + ' failed'); + Log(IntToStr(OkCount) + ' emails sent succesfully'); + Log(IntToStr(BadCount) + ' failed'); + CloseLog; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.SmtpClientGetData(Sender: TObject; LineNum: Integer; + MsgLine: PChar; MaxLen: Integer; var More: Boolean); +var + Len : Integer; +begin + if LineNum > EMailMemo.Lines.count then + More := FALSE + else begin + Len := Length(EMailMemo.Lines[LineNum - 1]); + { Truncate the line if too long (should wrap to next line) } + if Len >= MaxLen then + StrPCopy(MsgLine, Copy(EMailMemo.Lines[LineNum - 1], 1, MaxLen - 1)) + else + StrPCopy(MsgLine, EMailMemo.Lines[LineNum - 1]); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.SaveToListButtonClick(Sender: TObject); +var + Stream : TStream; + I : Integer; +begin + DisplayMemo.Lines.Add('Saving to file'); + if FNames.Count <= 0 then begin + Application.MessageBox('List is empty', 'Warning', MB_OK); + Exit; + end; + + Stream := TFileStream.Create(LstFileEdit.Text, fmCreate); + try + for I := 0 to FNames.Count - 1 do begin + Stream.WriteBuffer(PChar(FNames.Items[I])^, StrLen(PChar(FNames.Items[I]))); + Stream.WriteBuffer(CrLf, 2); + end; + DisplayMemo.Lines.Add(IntToStr(FNames.Count) + ' EMails saved'); + finally + Stream.Destroy; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.LoadFromListButtonClick(Sender: TObject); +var + Stream : TMemoryStream; + I, J : Integer; + p, q : PChar; + Table : TTable; + Field : TField; +begin + DisplayMemo.Lines.Add('Loading from file'); + ClearNames; + if UpperCase(ExtractFileExt(LstFileEdit.Text)) = '.DBF' then begin + Table := TTable.Create(Self); + try + Table.DatabaseName := ExtractFilePath(LstFileEdit.Text); + Table.TableName := ExtractFileName(LstFileEdit.Text); + Table.Open; + Field := Table.FieldByName('EMail'); + while not Table.Eof do begin + GetMem(q, Length(Field.AsString) + 1); + StrPCopy(q, Field.AsString); + FNames.Add(q); + if DisplayMemo.Lines.Count > 200 then + DisplayMemo.Clear; + DisplayMemo.Lines.Add(StrPas(q)); + Table.Next; + end; + finally + Table.Destroy; + end; + end + else begin + Stream := TMemoryStream.Create; + Stream.LoadFromFile(LstFileEdit.Text); + p := Stream.Memory; + I := 0; + while I < Stream.Size do begin + J := I; + while (I < Stream.Size) and (p[i] <> #13) do + Inc(I); + if p[I] = #13 then + Dec(I); + GetMem(q, I - J + 2); + Move(p[J], q^, I - J + 1); + q[I - J + 1] := #0; + FNames.Add(q); + if DisplayMemo.Lines.Count > 200 then + DisplayMemo.Clear; + DisplayMemo.Lines.Add(StrPas(q)); + I := I + 3; + end; + Stream.Destroy; + end; + DisplayMemo.Lines.Add(IntToStr(FNames.Count) + ' EMails loaded'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.SmtpClientCommand(Sender: TObject; Msg: String); +begin + { Memo boxes are not unlimited...} + if DisplayMemo.Lines.Count > 200 then + DisplayMemo.Clear; + DisplayMemo.Lines.Add(' ' + Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.SmtpClientResponse(Sender: TObject; Msg: String); +begin + { Memo boxes are not unlimited...} + if DisplayMemo.Lines.Count > 200 then + DisplayMemo.Clear; + DisplayMemo.Lines.Add(' ' + Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.MsgFileLoadButtonClick(Sender: TObject); +begin + LoadEMailMessage(MsgFileEdit.Text); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.SaveMsgFileButtonClick(Sender: TObject); +begin + SaveEMailMessage(MsgFileEdit.Text); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.MbxFileEditDblClick(Sender: TObject); +begin + OpenDialog1.DefaultExt := '.mbx'; + OpenDialog1.Filter := 'Mail files (*.mbx)|*.MBX|All files (*.*)|*.*'; + OpenDialog1.Options := [ofFileMustExist]; + OpenDialog1.Title := 'MailRob - Open MBX file'; + OpenDialog1.InitialDir := ExtractFilePath(MbxFileEdit.Text); + if OpenDialog1.Execute then + MbxFileEdit.Text := OpenDialog1.FileName; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.MsgFileEditDblClick(Sender: TObject); +begin + OpenDialog1.DefaultExt := '.txt'; + OpenDialog1.Filter := 'Message files (*.txt)|*.TXT|All files (*.*)|*.*'; + OpenDialog1.Options := [ofFileMustExist]; + OpenDialog1.Title := 'MailRob - Open message file'; + OpenDialog1.InitialDir := ExtractFilePath(MsgFileEdit.Text); + if OpenDialog1.Execute then + MsgFileEdit.Text := OpenDialog1.FileName; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMailRobForm.LstFileEditDblClick(Sender: TObject); +begin + OpenDialog1.DefaultExt := '.txt'; + OpenDialog1.Filter := 'AMail list files (*.txt)|*.TXT|All files (*.*)|*.*'; + OpenDialog1.Options := [ofFileMustExist]; + OpenDialog1.Title := 'MailRob - Open email list file'; + OpenDialog1.InitialDir := ExtractFilePath(LstFileEdit.Text); + if OpenDialog1.Execute then + LstFileEdit.Text := OpenDialog1.FileName; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/MailSnd.dpr b/ICS_zlog/Delphi/Internet/MailSnd.dpr new file mode 100644 index 00000000..375b0e20 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/MailSnd.dpr @@ -0,0 +1,12 @@ +program MailSnd; + +uses + Forms, + MailSnd1 in 'MailSnd1.pas' {SmtpTestForm}; + +{$R *.RES} + +begin + Application.CreateForm(TSmtpTestForm, SmtpTestForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/MailSnd1.dfm b/ICS_zlog/Delphi/Internet/MailSnd1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..8b20435196e8af8dd0a56ecc9411caf035488a94 GIT binary patch literal 5901 zcma)ATXWmS6^1|(;9Zhs*-fXOSv#I4>Bx+n#EIkSLnK}*%}6FI!bu-8lY-z%L<8c$o14jpxnmL-`C}^3r=-C66vj|F$Y$g;PE&-M5_+ z9A3?M>7QF}*I)3E66cA~j)WHU49z%Sy!!CNo12>s{WFdycN}*nxYDH&jon%h9dk19 z1Kb=?!aLoWA2ZC|?OuOy^ybX_rh9U9G46YH^;OC=gXpV}OzDk>Z+Sz0P!R0@)a27^ ze~z8j`529T!q6DU;iZxv^ScN)toAUPc4O>wJdCF}uDL_fjVQw|h{tpJvkI@|3Kt~d zo&4<#$#_O@+^Tpbeziv7Esod-$EPHi*?+7HL>f!Ws(9ykPTg~MCH|N6*_LGQN5fvz zuxHieK{Z1(30!v20M@qq`Qo&QL;9*fgc@WciPWEFdTl$BL zVA}|{io&)>6H#}3J^2$3xU&0!w0oiLJ}rux<%zu7_b1Bq-<4^z@x7vac|_yuq0exzj&i?Y=>495hD zS0e8!zaJ{=KP&4-!z#y(e8%$9I&8|4fxj3APK)+;j;4V7(8#XvVd*#k;fmLvhP*0bSo}}~j-=hHwtHtbu&;{1lXE|ept{A- zWY7!*1(S%z=yZhq=`;rK<}1_6GE^2t+(}F)SVT_bv7j|r+JZ?MzsFEtpxVT)t?e2! z#;)Vh#A@kZDgxG-ecFST3niJ;m>r-gj>37!@f1z&fR}j~K>H*ckx)`#v~2^Wp|d%` zV=Ir0*08W`GK#4xun7&0vYa(#%-2O~4M}3%u(8hkyJ9^hrVpS?hy~H8PWop<6wvwH zC(}(Jxe8Loyg^hI^`?MlU4TB$2IvAL(fiP?t|RadbY(bpeXt3dEgdJuv}L*8@ipg^ z-0Mczk9G4@uTY4JKk@S;>TJY;r=&GAQd>{{0VeqZ1 zR4+k-9vpm|f^KywA>NT6dttN2qErH1)t)JkC zu7LTgb+nE#9J55gv86anFqVbFO#n6%fZHjC9J;m$E>SyHAYAA8UnB@6g)|PYRPjh4 zR*lw8U~VTc_l%eVlY`p42o~I1MWyL%d5=F_1{&iaTtJ^<2~J0;+yv!Lf^s*DBZslx z^SNK7vh;nSed;87EFnrB<$)b)3-USlgBjG{%P_(z*s{>Q3Dn&L>UIhz2effCfl87^ zs`q~BY`-O*C2C^tH`CBAl*-p?qu-fpw@qX9j-!pxCZHt zSdS#7s;ejNE{iXl;JTmS+D?tR5M$WHO;jt&ayW&o+b)S!+)E`y4IK#wyc`h1=rAHdfOByGxLx+R;HPq;;hJd zf!hvPFQ$tgy&-2IdJ?n*hMzDoTx!ONnhCMbRl7 zH*t2`sgg77@nYD1|Ekd0VAGdzTyYs`qfFu ztOFQyN)W)=BwHUQWbZBSLKAK#6pbU~H$X)NHBeqJ__A2XeRtZB7otmbQ_f z1nmT`zJ@Gad_94IRfoehFnPn_W+mPf21MDhP@S=-s){W3?iScxDrBx0;EpkO>LH`gUcP+s`LpK@ND2;W + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Oct 26, 1997 V1.00 Released +Jan 10, 1998 V1.01 Added a Port property +Feb 15, 1998 V1.02 Added file attachement support +Mar 06, 1998 V1.03 Check for DisplayMemo overflow (100 lines allowed) +Aug 03, 1998 V2.00 Revised for new asynchronous SMTP component version +Jul 26, 2001 V2.01 Added authentification +Sep 07, 2002 V2.02 Added Cc and Bcc fields. + Added AllInOne demo to show how to "chain" several operations + using OnRequest done, avoiding any wait loop. This is how event + driven operation has to be done. +Sep 15, 2002 V2.02 Corrected typo error in BuildRcptList where CcEdi was used + where ToEdit should. + Thanks to konstantinos.Kokkorogiannis@diala.greenpeace.org + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit MailSnd1; + +{$B-} { Enable partial boolean evaluation } +{$T-} { Untyped pointers } +{$X+} { Enable extended syntax } + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, SmtpProt, StdCtrls, ExtCtrls, IniFiles; + +const + SmtpTestVersion = 2.03; + CopyRight : String = ' MailSnd (c) 1997-2002 F. Piette V2.03 '; + +type + TSmtpTestForm = class(TForm) + MsgMemo: TMemo; + DisplayMemo: TMemo; + ToolsPanel: TPanel; + Label1: TLabel; + Label2: TLabel; + Label3: TLabel; + Subject: TLabel; + Label4: TLabel; + HostEdit: TEdit; + FromEdit: TEdit; + ToEdit: TEdit; + SubjectEdit: TEdit; + SignOnEdit: TEdit; + PortEdit: TEdit; + Label5: TLabel; + AttachPanel: TPanel; + Label6: TLabel; + FileAttachMemo: TMemo; + InfoPanel: TPanel; + Label7: TLabel; + ClearDisplayButton: TButton; + ConnectButton: TButton; + HeloButton: TButton; + MailFromButton: TButton; + RcptToButton: TButton; + DataButton: TButton; + AbortButton: TButton; + QuitButton: TButton; + MailButton: TButton; + OpenButton: TButton; + Label8: TLabel; + SmtpClient: TSmtpCli; + Label9: TLabel; + Label10: TLabel; + UsernameEdit: TEdit; + PasswordEdit: TEdit; + AuthComboBox: TComboBox; + Label11: TLabel; + EhloButton: TButton; + AuthButton: TButton; + Label12: TLabel; + CcEdit: TEdit; + Label13: TLabel; + BccEdit: TEdit; + AllInOneButton: TButton; + procedure FormCreate(Sender: TObject); + procedure ClearDisplayButtonClick(Sender: TObject); + procedure ConnectButtonClick(Sender: TObject); + procedure SmtpClientRequestDone(Sender: TObject; RqType: TSmtpRequest; + Error: Word); + procedure HeloButtonClick(Sender: TObject); + procedure MailFromButtonClick(Sender: TObject); + procedure RcptToButtonClick(Sender: TObject); + procedure DataButtonClick(Sender: TObject); + procedure AbortButtonClick(Sender: TObject); + procedure QuitButtonClick(Sender: TObject); + procedure MailButtonClick(Sender: TObject); + procedure OpenButtonClick(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure EhloButtonClick(Sender: TObject); + procedure AuthButtonClick(Sender: TObject); + procedure AllInOneButtonClick(Sender: TObject); + procedure SmtpClientDisplay(Sender: TObject; Msg: String); + procedure SmtpClientGetData(Sender: TObject; LineNum: Integer; + MsgLine: Pointer; MaxLen: Integer; var More: Boolean); + procedure SmtpClientHeaderLine(Sender: TObject; Msg: Pointer; + Size: Integer); + private + FIniFileName : String; + FInitialized : Boolean; + FAllInOneFlag : Boolean; + procedure Display(const Msg : String); + procedure BuildRcptList; + procedure ExceptionHandler(Sender: TObject; E: Exception); + end; + +var + SmtpTestForm: TSmtpTestForm; + +implementation + +{$R *.DFM} +const + SectionData = 'Data'; + KeyHost = 'HostName'; + KeyPort = 'Port'; + KeyFrom = 'From'; + KeyTo = 'To'; + KeyCc = 'Cc'; + KeyBcc = 'Bcc'; + KeySubject = 'Subject'; + KeySignOn = 'SignOn'; + KeyUser = 'UserName'; + KeyPass = 'Password'; + KeyAuth = 'Authentification'; + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Display a message in display memo box, making sure we don't overflow it. } +procedure TSmtpTestForm.Display(const Msg : String); +begin + DisplayMemo.Lines.BeginUpdate; + try + if DisplayMemo.Lines.Count > 200 then begin + { We preserve only 200 lines } + while DisplayMemo.Lines.Count > 200 do + DisplayMemo.Lines.Delete(0); + end; + DisplayMemo.Lines.Add(Msg); + finally + DisplayMemo.Lines.EndUpdate; + { Makes last line visible } + {$IFNDEF VER80} + SendMessage(DisplayMemo.Handle, EM_SCROLLCARET, 0, 0); + {$ENDIF} + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSmtpTestForm.FormCreate(Sender: TObject); +begin + Application.OnException := ExceptionHandler; + DisplayMemo.Clear; + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSmtpTestForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + IniFile := TIniFile.Create(FIniFileName); + HostEdit.Text := IniFile.ReadString(SectionData, KeyHost, + 'localhost'); + PortEdit.Text := IniFile.ReadString(SectionData, KeyPort, + 'smtp'); + FromEdit.Text := IniFile.ReadString(SectionData, KeyFrom, + 'first.last@company.com'); + ToEdit.Text := IniFile.ReadString(SectionData, KeyTo, + 'john.doe@acme;tartempion@brol.fr'); + CcEdit.Text := IniFile.ReadString(SectionData, KeyCc, + ''); + BccEdit.Text := IniFile.ReadString(SectionData, KeyBcc, + 'francois.piette@swing.be'); + SubjectEdit.Text := IniFile.ReadString(SectionData, KeySubject, + 'This is the message subject'); + SignOnEdit.Text := IniFile.ReadString(SectionData, KeySignOn, + 'your name'); + UsernameEdit.Text := IniFile.ReadString(SectionData, KeyUser, + 'account name'); + PasswordEdit.Text := IniFile.ReadString(SectionData, KeyPass, + 'account password'); + AuthComboBox.ItemIndex := IniFile.ReadInteger(SectionData, KeyAuth, + 0); + + Top := IniFile.ReadInteger(SectionWindow, KeyTop, (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, (Screen.Width - Width) div 2); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + + IniFile.Free; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSmtpTestForm.FormClose(Sender: TObject; + var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteString(SectionData, KeyHost, HostEdit.Text); + IniFile.WriteString(SectionData, KeyPort, PortEdit.Text); + IniFile.WriteString(SectionData, KeyFrom, FromEdit.Text); + IniFile.WriteString(SectionData, KeyTo, ToEdit.Text); + IniFile.WriteString(SectionData, KeyCc, CcEdit.Text); + IniFile.WriteString(SectionData, KeyBcc, BccEdit.Text); + IniFile.WriteString(SectionData, KeySubject, SubjectEdit.Text); + IniFile.WriteString(SectionData, KeySignOn, SignOnEdit.Text); + IniFile.WriteString(SectionData, KeyUser, UsernameEdit.Text); + IniFile.WriteString(SectionData, KeyPass, PasswordEdit.Text); + IniFile.WriteInteger(SectionData, KeyAuth, AuthComboBox.ItemIndex); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +function TrimRight(Str : String) : String; +var + i : Integer; +begin + i := Length(Str); + while (i > 0) and (Str[i] = ' ') do + i := i - 1; + Result := Copy(Str, 1, i); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TrimLeft(Str : String) : String; +var + i : Integer; +begin + if Str[1] <> ' ' then + Result := Str + else begin + i := 1; + while (i <= Length(Str)) and (Str[i] = ' ') do + i := i + 1; + Result := Copy(Str, i, Length(Str) - i + 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function Trim(Str : String) : String; +begin + Result := TrimLeft(TrimRight(Str)); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSmtpTestForm.BuildRcptList; +var + Buf : String; + I : Integer; +begin + SmtpClient.RcptName.Clear; + // Recipient list is the sum of To, Cc and Bcc fields + Buf := ''; + if Length(Trim(ToEdit.Text)) > 0 then + Buf := Trim(ToEdit.Text); + if Length(Trim(CcEdit.Text)) > 0 then + Buf := Buf + ';' + Trim(CcEdit.Text); + if Length(Trim(BccEdit.Text)) > 0 then + Buf := Buf + ';' + Trim(BccEdit.Text); + if (Length(Buf) > 0) and (Buf[1] = ';') then + Buf := Trim(Copy(Buf, 2, Length(Buf))); + while TRUE do begin + I := Pos(';', Buf); + if I <= 0 then begin + SmtpClient.RcptName.Add(Trim(Buf)); + break; + end + else begin + SmtpClient.RcptName.Add(Trim(Copy(Buf, 1, I - 1))); + Delete(Buf, 1, I); + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSmtpTestForm.SmtpClientDisplay(Sender: TObject; Msg: String); +begin + Display(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSmtpTestForm.SmtpClientGetData( + Sender : TObject; + LineNum : Integer; + MsgLine : Pointer; + MaxLen : Integer; + var More: Boolean); +var + Len : Integer; +begin + if LineNum > MsgMemo.Lines.count then + More := FALSE + else begin + Len := Length(MsgMemo.Lines[LineNum - 1]); + { Truncate the line if too long (should wrap to next line) } + if Len >= MaxLen then + StrPCopy(MsgLine, Copy(MsgMemo.Lines[LineNum - 1], 1, MaxLen - 1)) + else + StrPCopy(MsgLine, MsgMemo.Lines[LineNum - 1]); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSmtpTestForm.SmtpClientHeaderLine( + Sender : TObject; + Msg : Pointer; + Size : Integer); +begin + { This demonstrate how to add a line to the message header } + { Just detect one of the header lines and add text at the end of this } + { line. Use #13#10 to form a new line } + { Here we check for the From: header line and add a Comments: line } + if StrLIComp(Msg, 'From:', 5) = 0 then + StrCat(Msg, #13#10 + 'Comments: This is a test'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSmtpTestForm.ClearDisplayButtonClick(Sender: TObject); +begin + DisplayMemo.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSmtpTestForm.ExceptionHandler(Sender: TObject; E: Exception); +begin + Application.ShowException(E); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Connect to the mail server } +procedure TSmtpTestForm.ConnectButtonClick(Sender: TObject); +begin + FAllInOneFlag := FALSE; + SmtpClient.Host := HostEdit.Text; + SmtpClient.Port := PortEdit.Text; + SmtpClient.Connect; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Send HELO command with our local identification } +procedure TSmtpTestForm.HeloButtonClick(Sender: TObject); +begin + FAllInOneFlag := FALSE; + SmtpClient.SignOn := SignOnEdit.Text; + SmtpClient.Helo; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSmtpTestForm.EhloButtonClick(Sender: TObject); +begin + FAllInOneFlag := FALSE; + SmtpClient.SignOn := SignOnEdit.Text; + SmtpClient.EHlo; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSmtpTestForm.AuthButtonClick(Sender: TObject); +begin + FAllInOneFlag := FALSE; + SmtpClient.Username := UsernameEdit.Text; + SmtpClient.Password := PasswordEdit.Text; + SmtpClient.AuthType := TSmtpAuthType(AuthComboBox.ItemIndex); + SmtpClient.Auth; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Open is Connect and Helo methods combined } +procedure TSmtpTestForm.OpenButtonClick(Sender: TObject); +begin + FAllInOneFlag := FALSE; + SmtpClient.Host := HostEdit.Text; + SmtpClient.Port := PortEdit.Text; + SmtpClient.SignOn := SignOnEdit.Text; + SmtpClient.Open; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Send originator } +procedure TSmtpTestForm.MailFromButtonClick(Sender: TObject); +begin + FAllInOneFlag := FALSE; + SmtpClient.FromName := FromEdit.Text; + SmtpClient.MailFrom; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Send recipients } +procedure TSmtpTestForm.RcptToButtonClick(Sender: TObject); +begin + FAllInOneFlag := FALSE; + BuildRcptList; + SmtpClient.RcptTo; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Send text and attached files to mail server } +procedure TSmtpTestForm.DataButtonClick(Sender: TObject); +begin + FAllInOneFlag := FALSE; + BuildRcptList; + SmtpClient.HdrFrom := FromEdit.Text; + SmtpClient.HdrTo := ToEdit.Text; + SmtpClient.HdrCc := CcEdit.Text; + SmtpClient.HdrSubject := SubjectEdit.Text; + SmtpClient.EmailFiles := FileAttachMemo.Lines; + SmtpClient.Data; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ MailFrom, RcptTo and Data methods combined } +procedure TSmtpTestForm.MailButtonClick(Sender: TObject); +begin + FAllInOneFlag := FALSE; + BuildRcptList; + SmtpClient.HdrFrom := FromEdit.Text; + SmtpClient.HdrTo := ToEdit.Text; + SmtpClient.HdrTo := CcEdit.Text; + SmtpClient.HdrSubject := SubjectEdit.Text; + SmtpClient.SignOn := SignOnEdit.Text; + SmtpClient.FromName := FromEdit.Text; + SmtpClient.EmailFiles := FileAttachMemo.Lines; + SmtpClient.Host := HostEdit.Text; + SmtpClient.Port := PortEdit.Text; + SmtpClient.Mail; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSmtpTestForm.QuitButtonClick(Sender: TObject); +begin + FAllInOneFlag := FALSE; + SmtpClient.Quit; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSmtpTestForm.AbortButtonClick(Sender: TObject); +begin + FAllInOneFlag := FALSE; + SmtpClient.Abort; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSmtpTestForm.SmtpClientRequestDone( + Sender : TObject; + RqType : TSmtpRequest; + Error : Word); +begin + { For every operation, we display the status } + Display('RequestDone Rq=' + IntToStr(Ord(RqType)) + + ' Error='+ IntToStr(Error)); + { Check if the user has asked for "All-In-One" demo } + if not FAllInOneFlag then + Exit; { No, nothing more to do here } + { We are in "All-In-One" demo, start next operation } + { But first check if previous one was OK } + if Error <> 0 then begin + FAllInOneFlag := FALSE; { Terminate All-In-One demo } + Display('Error, stoped All-In-One demo'); + Exit; + end; + case RqType of + smtpConnect: SmtpClient.Helo; + smtpHelo: SmtpClient.MailFrom; + smtpMailFrom: SmtpClient.RcptTo; + smtpRcptTo: SmtpClient.Data; + smtpData: SmtpClient.Quit; + smtpQuit: Display('All-In-One done !'); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSmtpTestForm.AllInOneButtonClick(Sender: TObject); +begin + if SmtpClient.Connected then begin + MessageBeep(MB_OK); + Display('All-In-One demo start in non connected state.'); + Display('Please quit or abort the connection first.'); + Exit; + end; + + FAllInOneFlag := TRUE; + + { Initialize all SMTP component properties from our GUI } + SmtpClient.Host := HostEdit.Text; + SmtpClient.Port := PortEdit.Text; + SmtpClient.SignOn := SignOnEdit.Text; + SmtpClient.FromName := FromEdit.Text; + SmtpClient.HdrFrom := FromEdit.Text; + SmtpClient.HdrTo := ToEdit.Text; + SmtpClient.HdrCc := CcEdit.Text; + SmtpClient.HdrSubject := SubjectEdit.Text; + SmtpClient.EmailFiles := FileAttachMemo.Lines; + { Recipient list is computed from To, Cc and Bcc fields } + { We use a little function to do that. } + BuildRcptList; + { Start first operation to do to send an email } + { Next operations are started from OnRequestDone event } + SmtpClient.Connect +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/MbxSub.dpr b/ICS_zlog/Delphi/Internet/MbxSub.dpr new file mode 100644 index 00000000..dd36edbd --- /dev/null +++ b/ICS_zlog/Delphi/Internet/MbxSub.dpr @@ -0,0 +1,13 @@ +program MbxSub; + +uses + Forms, + MbxSub1 in 'MbxSub1.pas' {AppBaseForm}; + +{$R *.RES} + +begin + Application.Initialize; + Application.CreateForm(TAppBaseForm, AppBaseForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/MbxSub1.dfm b/ICS_zlog/Delphi/Internet/MbxSub1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..728658d4a9a49e2b90a68f39c0f20311c8bfd714 GIT binary patch literal 2214 zcmbVOy^h;P5MGiJNs+w201o1$k(&eD1a^@krASG+L#&f_6<1j9S-OWX z;Fn0BB8`F6evmvt8Uty9WPi9MrMuWcy5a2n?Kkty^6vm-qs1Z~rIYFWdIp}HzVQLb z7SktDHri}rSfMFp>#!sDo}riAIklXOZk*8SKgR`MIepu`KzO<0&bj3!aKkYz-L6|d zp@cGTkdv5~Q<$S@N=yD_vVyEa+&dXhrlaqkWj`brqw92%1^QI^L^*km%Ytq*wBw;V z(7EjQ1NC(U*T_AZrNb1K)i6a2ztsLIza=OH$8%C73_*_OtUzqw&C7()3VFhvt(E8t zm9p@Jr_d?cotNo~ZarVBq;#~vJ4C7lVwYvUvVRO@MRhGlz|9u0L?p;46*f{-SlK{A zWrG^2zpNT5`*D9n@Ury!kO%`mgD+HhHUM50-*8ULAkAT^MIGuh70TD4>~Bq^hYjTY zbLrBFrS6LJpS+VcRzifL%@W0oZY$Ky!#|eCJJ(KaCacMG){R%^0+9e`i4xIsMoH9> zpLRidd9T$Tme*;c14+1V8=h4Uxf ztXc;KnTZxje9T9Kr|Q6PGJ}{1+jK)P=VF44po@3j?zPx<3>V%3H@RVzn0r5G7s?5M zel|mE8jf+bA@EkpT?EXSyajEL`l2o*l6(8aiAGoH<^N|*n9v)B5gT5i?H*@>1!MwK z$uD1kAeu&EK~>MKs+jUs3otM@8Yq;S`#8Vtf#Q5^=H7V+4mnY0g>H+@4 zw9kGRj3I}qfH_CriS}(22QW?w%>Aj@by84aoj)~-bzJ+_Q2s&dYW3tAavR5X;*U+N zdfEjGuVI0yruu`FG9KTG@=!;s)9%!Mx6P*c%A`GOAn!@Pwg|hS|L6CHt@prQ0iSBi z$y%`MP6fYyw1U0@vn|1CO8Dabz-AYDqMhF`T!eKerQGGRBXgELL9ohfXRqHIn zoQOB{15e#a$K>vNciNtsNAI{*-ShHw!qv~8;13A1*^Au;EDM5I*oseGy + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +History: + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit MbxSub1; + +{$IFDEF VER80} + Bomb('Sorry, this program uses 32 bits features.'); +{$ENDIF} + +interface + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + IniFiles, StdCtrls, ExtCtrls, MbxFile, Db, DBTables, Bde, Grids, DBGrids, + DBCtrls, ComCtrls; + +const + WM_APPSTARTUP = WM_USER + 1; + +type + TAppBaseForm = class(TForm) + ToolsPanel: TPanel; + MbxHandler1: TMbxHandler; + ScanButton: TButton; + EMailTable: TTable; + PageControl1: TPageControl; + ScanTabSheet: TTabSheet; + DisplayMemo: TMemo; + EMailMemo: TMemo; + Splitter1: TSplitter; + ViewTabSheet: TTabSheet; + Panel1: TPanel; + EMailDBNavigator: TDBNavigator; + EMailDBGrid: TDBGrid; + EMailDataSource: TDataSource; + FindEdit: TEdit; + SortByDateRadioButton: TRadioButton; + SortByEmailRadioButton: TRadioButton; + OpenDialog1: TOpenDialog; + BrowseButton: TButton; + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure ScanButtonClick(Sender: TObject); + procedure PageControl1Change(Sender: TObject); + procedure FindEditChange(Sender: TObject); + procedure SortByDateRadioButtonClick(Sender: TObject); + procedure SortByEmailRadioButtonClick(Sender: TObject); + procedure BrowseButtonClick(Sender: TObject); + private + FIniFileName : String; + FInitialized : Boolean; + FDatabaseName : String; + FTableName : String; + function Extract(Item : String) : String; + procedure CreateDataTable; + procedure PackTable(aTable : TTable); + procedure WMAppStartup(var msg: TMessage); message WM_APPSTARTUP; + procedure SelectIndex; + public + procedure Display(Msg : String); + property IniFileName : String read FIniFileName write FIniFileName; + end; + +function RenameToNumberedFile(From : String) : String; +function GetToken(pDelim : PCHar; Src : PChar; var Dst : String): PChar; + +var + AppBaseForm: TAppBaseForm; + +implementation + +{$R *.DFM} + +const + SectionWindow = 'Window'; // Must be unique for each window + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + SectionData = 'Data'; + KeyMbxFile = 'MbxFile'; + KeySplitter = 'Splitter'; + TempFileName = 'MbxSub.tmp'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TAppBaseForm.FormCreate(Sender: TObject); +begin + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; + FDatabaseName := LowerCase(ExtractFilePath(Application.ExeName)); + FTableName := 'subscribe.dbf'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TAppBaseForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + + IniFile := TIniFile.Create(FIniFileName); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, + (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, + (Screen.Width - Width) div 2); + DisplayMemo.Width := IniFile.ReadInteger(SectionData, KeySplitter, Width div 2); + MbxHandler1.FileName := IniFile.ReadString(SectionData, KeyMbxFile, + 'c:\Windows\Application Data\Microsoft\Outlook Express\Mail\Dossier24.mbx'); + IniFile.WriteString(SectionData, KeyMbxFile, MbxHandler1.FileName); + IniFile.Destroy; + DisplayMemo.Clear; + EMailMemo.Clear; + FindEdit.Clear; + SortByEmailRadioButton.Checked := TRUE; + PageControl1.ActivePage := ScanTabSheet; + Caption := 'MbxSub - ' + ExtractFileName(MbxHandler1.FileName); + PostMessage(Handle, WM_APPSTARTUP, 0, 0); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TAppBaseForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.WriteInteger(SectionData, KeySplitter, DisplayMemo.Width); + IniFile.Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TAppBaseForm.WMAppStartup(var msg: TMessage); +var + I : Integer; +begin + Update; + EMailTable.DatabaseName := FDatabaseName; + EMailTable.TableName := FTableName; + try + EMailTable.Open; + except + on E:EDBEngineError do begin + if E.Errors[0].ErrorCode = DBIERR_NOSUCHTABLE then begin + Display('Missing datafile. Creating a new file.'); + CreateDataTable; + EMailTable.Open; + end + else if E.Errors[0].ErrorCode = DBIERR_NOSUCHINDEX then begin + Display('Missing index file. Creating new index file.'); + DeleteFile(FDatabaseName + TempFileName); + RenameFile(FDatabaseName + FTableName, FDatabaseName + TempFileName); + CreateDataTable; + DeleteFile(FDatabaseName + FTableName); + RenameFile(FDatabaseName + TempFileName, FDatabaseName + FTableName); + PackTable(EMailTable); + EMailTable.Open; + end + else if (E.Errors[0].Category = ERRCAT_DATACORRUPT) and + (E.ErrorCount > 1) and + (UpperCase(ExtractFileExt(E.Errors[1].Message)) = '.MDX') then begin + Display('Corrupt index file. Rebuilding index file.'); + DeleteFile(FDatabaseName + TempFileName); + RenameFile(FDatabaseName + FTableName, FDatabaseName + TempFileName); + CreateDataTable; + DeleteFile(FDatabaseName + FTableName); + RenameFile(FDatabaseName + TempFileName, FDatabaseName + FTableName); + PackTable(EMailTable); + EMailTable.Open; + end + else if E.Errors[0].ErrorCode = DBIERR_HEADERCORRUPT then begin + Display('Corrupt data file.'); + Display('Save corrupted file to: ''' + + RenameToNumberedFile(FDatabaseName + + FTableName) + + ''''); + Display('Creating new data file.'); + CreateDataTable; + EMailTable.Open; + end + else begin + Display(E.ClassName + ': ' + E.Message); + for I := 0 to E.ErrorCount - 1 do + Display(IntToStr(E.Errors[I].ErrorCode) + '/' + + IntToStr(E.Errors[I].Category) + + ': ' + E.Errors[I].Message); + end; + end; + end; + EMailTable.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TAppBaseForm.Display(Msg : String); +begin + DisplayMemo.Lines.BeginUpdate; + try + if DisplayMemo.Lines.Count > 200 then begin + while DisplayMemo.Lines.Count > 200 do + DisplayMemo.Lines.Delete(0); + end; + DisplayMemo.Lines.Add(Msg); + finally + DisplayMemo.Lines.EndUpdate; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +//Fri, 19 Mar 1999 18:50:07 +0100 +function ExtractDate(S : String) : TDateTime; +var + P : PChar; + Token : String; + Year, Month, Day : Word; +begin + P := PChar(S); + if P = nil then begin + Result := 0; + Exit; + end; + // Get day of week + P := GetToken(' ', P, Token); + Token := LowerCase(Copy(Trim(Token), 1, 3)); + if not ((Token = 'mon') or (Token = 'tue') or + (Token = 'wed') or (Token = 'thu') or + (Token = 'fri') or (Token = 'sat') or (Token = 'sun')) then + raise Exception.Create('Invalid day name: ' + S); + + // get day + P := GetToken(' ', P, Token); + Day := StrToInt(Trim(Token)); + + // get month + P := GetToken(' ', P, Token); + Token := LowerCase(Trim(Token)); + if Token = 'jan' then + Month := 1 + else if Token = 'feb' then + Month := 2 + else if Token = 'mar' then + Month := 3 + else if Token = 'apr' then + Month := 4 + else if Token = 'may' then + Month := 5 + else if Token = 'jun' then + Month := 6 + else if Token = 'jul' then + Month := 7 + else if Token = 'aug' then + Month := 8 + else if Token = 'sep' then + Month := 9 + else if Token = 'oct' then + Month := 10 + else if Token = 'nov' then + Month := 11 + else if Token = 'dec' then + Month := 12 + else + raise Exception.Create('Invalid month name: ' + S); + + // get year + GetToken(' ', P, Token); + Year := StrToInt(Trim(Token)); + + Result := EncodeDate(Year, Month, Day); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TAppBaseForm.ScanButtonClick(Sender: TObject); +var + Subject : String; + Token : String; + List : String; + EMail : String; + P : PChar; + MsgDate : String; + MsgCount : Integer; + NewCount : Integer; + FieldEMail : TField; + FieldSubDate : TField; +// FieldUnsDate : TField; +// FieldName : TField; +begin + Display('Scanning ' + MbxHandler1.FileName); + PageControl1.ActivePage := ScanTabSheet; + MsgCount := 0; + NewCount := 0; + EMailTable.Active := TRUE; + EMailTable.IndexName := 'EMAIL'; + FieldEMail := EMailTable.FieldByName('EMail'); + FieldSubDate := EMailTable.FieldByName('SubDate'); +// FieldName := EMailTable.FieldByName('Name'); +// FieldUnsDate := EMailTable.FieldByName('UnsDate'); + + MbxHandler1.Active := TRUE; + MbxHandler1.First; + while not MbxHandler1.Eof do begin + Inc(MsgCount); + Subject := Extract('Subject'); +// Display(Subject); + P := PChar(Subject); + P := GetToken(' ', P, Token); + Token := LowerCase(Trim(Token)); + if Token = 'subscribe' then begin + P := GetToken(' ', P, List); + List := LowerCase(Trim(List)); + if (List = 'twsocket') or + (List = 'twsocket-announce') or + (List = 'midware') then begin + GetToken(' ', P, EMail); + EMail := LowerCase(Trim(EMail)); +if Copy(Email, 1, 5) = 'napol' then + MessageBeep(MB_OK); + EMailTable.SetKey; + FieldEMail.AsString := EMail; + EMailTable.GotoNearest; + if FieldEMail.AsString <> EMail then begin + // Do not exists yet, will create + Inc(NewCount); + MsgDate := Extract('Date'); + Display(List + ' ' + EMail); + EMailMemo.Lines.Add(EMail + ';'); + EMailTable.Append; + FieldEMail.AsString := EMail; + FieldSubDate.AsString := FormatDateTime('YYYYMMDD', ExtractDate(MsgDate)); + EMailTable.Post; + end; + end; + end; + MbxHandler1.Next; + end; + MbxHandler1.Active := FALSE; + EMailTable.Active := FALSE; + Display('Done ' + IntToStr(MsgCount) + '/' + IntToStr(NewCount)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TAppBaseForm.Extract(Item : String) : String; +var + P, Q, R : PChar; +begin + Result := ''; + P := MbxHandler1.MsgStream.Memory; + Q := StrPos(P, PChar(#13#10 + Item + ': ')); + if Q <> nil then begin + R := StrPos(Q + 2, #13#10); + if R > Q then begin + SetLength(Result, R - Q - 2 - Length(Item) - 2); + if Length(Result) > 0 then + Move(Q[2 + Length(Item) + 2], Result[1], Length(Result)); + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TAppBaseForm.PackTable(aTable : TTable); +var + Status : Integer; +begin + aTable.Active := FALSE; + aTable.Exclusive := TRUE; + aTable.Active := TRUE; + + Status := DbiPackTable(aTable.DataBase.Handle, + aTable.Handle, + nil, nil, TRUE); + + if Status <> DBIERR_NONE then + DbiError(Status); + aTable.Active := FALSE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TAppBaseForm.CreateDataTable; +var + Table : TTable; +begin + Table := TTable.Create(nil); + try + Table.TableType := ttDBase; + Table.DatabaseName := FDatabaseName; + Table.TableName := FTableName; + with Table.FieldDefs do begin + Clear; + + Add('SubDate', ftString, 8, FALSE); + Add('UnsDate', ftString, 8, FALSE); + Add('EMail', ftString, 64, FALSE); + Add('Name', ftString, 64, FALSE); + end; + + // A bug in D3 prevent us from defining the indexes before calling + // CreateTable. We will just add the indexes after creation. + Table.CreateTable; + Table.AddIndex('EMail', 'EMAIL+SUBDATE', [ixExpression]); + Table.AddIndex('SubDate', 'SUBDATE', []); + + finally + Table.Free; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +// Replace any existing file extension, or add an extension is none exists. +// The extension is a 3 digits number, with leading zeros, build to make +// it unique. Numbering start at 001 and increment until an unused number +// is found. If 1000 is reached, then an exception will be triggered. +function RenameToNumberedFile(From : String) : String; +var + FPath : String; + FDir : String; + FName : String; + FExt : String; + FBaseName : String; + FileHandle : DWORD; + Count : Integer; +begin + FExt := ExtractFileExt(From); + FName := Copy(From, 1, Length(From) - Length(FExt)); + FName := ExtractFileName(FName); + FDir := ExtractFilePath(From); + if FDir[Length(FDir)] <> '\' then + FDir := FDir + '\'; + + Count := 1; + while TRUE do begin + FBaseName := FName + '.' + Format('%3.3d', [Count]); + FPath := FDir + FBaseName; + FileHandle := CreateFile(PChar(FPath), + GENERIC_READ or GENERIC_WRITE, + 0, // ShareMode + nil, // SecurityAttributes + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + 0); // TemplateFile + if FileHandle = INVALID_HANDLE_VALUE then begin + RenameFile(From, FPath); + Result := FPath; + Exit; + end; + // File exists, close it and continue + Windows.CloseHandle(FileHandle); + + // Be sure to not loop forever here ! + Inc(Count); + if Count >= 1000 then + raise Exception.Create('RenameToNumberedFile failed'); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function GetToken(pDelim : PChar; Src : PChar; var Dst : String): PChar; +var + FldSep : Char; + RecSep : Char; +begin + Dst := ''; + if Src = nil then begin + Result := nil; + Exit; + end; + + FldSep := pDelim[0]; + RecSep := pDelim[1]; + Result := Src; + + while (Result^ <> FldSep) and (Result^ <> RecSep) do begin + Dst := Dst + Result^; + Inc(Result); + end; + Inc(Result); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TAppBaseForm.PageControl1Change(Sender: TObject); +begin + if PageControl1.ActivePage = ViewTabSheet then begin + EMailTable.Active := TRUE; + SelectIndex; + end + else + EMailTable.Active := FALSE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TAppBaseForm.SelectIndex; +begin + if SortByEmailRadioButton.Checked then + EMailTable.IndexName := 'EMAIL' + else + EMailTable.IndexName := 'SUBDATE'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TAppBaseForm.FindEditChange(Sender: TObject); +var + FldName : String; +begin + if not EMailTable.Active then + Exit; + SelectIndex; + if SortByEmailRadioButton.Checked then + FldName := 'EMAIL' + else + FldName := 'SUBDATE'; + EMailTable.SetKey; + EMailTable.FieldByName(FldName).AsString := LowerCase(Trim(FindEdit.Text)); + EMailTable.GotoNearest; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TAppBaseForm.SortByDateRadioButtonClick(Sender: TObject); +begin + SelectIndex; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TAppBaseForm.SortByEmailRadioButtonClick(Sender: TObject); +begin + SelectIndex; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TAppBaseForm.BrowseButtonClick(Sender: TObject); +var + IniFile : TIniFile; +begin + OpenDialog1.DefaultExt := 'mbx'; + OpenDialog1.InitialDir := ExtractFilePath(MbxHandler1.FileName); + OpenDialog1.FileName := ExtractFileName(MbxHandler1.FileName); + OpenDialog1.Filter := 'Mailbox files (*.mbx)|*.mbx|All files (*.*)|*.*'; + if not OpenDialog1.Execute then + Exit; + MbxHandler1.Close; + MbxHandler1.FileName := OpenDialog1.FileName; + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteString(SectionData, KeyMbxFile, MbxHandler1.FileName); + IniFile.Free; + Caption := 'MbxSub - ' + ExtractFileName(MbxHandler1.FileName); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/MimeDemo.dpr b/ICS_zlog/Delphi/Internet/MimeDemo.dpr new file mode 100644 index 00000000..94a5d757 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/MimeDemo.dpr @@ -0,0 +1,12 @@ +program MimeDemo; + +uses + Forms, + MimeDmo1 in 'MIMEDMO1.PAS' {MimeDecodeForm}; + +{$R *.RES} + +begin + Application.CreateForm(TMimeDecodeForm, MimeDecodeForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/MimeDmo1.dfm b/ICS_zlog/Delphi/Internet/MimeDmo1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..9dd9765f4b802344eab17197fc9b1295b2cc2a55 GIT binary patch literal 1535 zcmb_c%WfJm6g2}g9vBEDX{x>!tRiI-CA(H#g#kn)$e_$rEL(?hz>2XWkE0|%)IV$0 zALzREV}JqDT{o6}?>YAzUqAlTKr*@<^}4+<>h}84^$47`e!2i8950%+yyQgMf;uVrK3|ES~d6 z=OUrtnSM^qA;IU=FF1|$%R94qYCDVE`y@UJ3 z${|&uwQ3Mjj6_lN*QV&FT~Y7Ykk(SpN~%>Tmn*4GjqrlIde}IrlkJl#{{Z<>`G_hu zX7YdE+#uu+f?(0U!jBvGwlO3OXQ#0ggw3*&XYGR87zt%VUwyw8PX(v6qh1m8vaG}9 zeBFYQKj9*s2z2iQ5ENc^uzuC&jff2}QqQ7;XN1Amg;XJ4U!t@nc(eo3;b4jBu@t`A zfvD(y#FTgSV%B=^3b?IYtB5wbZ(juKRI`ZH`fpx@s*G}}b?k17E?3c-MHt1ytui`T zwRx>_u$5M^!-!ons$lsAH(mWu!0luYHW^0u{XYmgsk&IKp?ws)xRtY?z(?~53;+Os E0S$`kq5uE@ literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/MimeDmo1.pas b/ICS_zlog/Delphi/Internet/MimeDmo1.pas new file mode 100644 index 00000000..52b766e8 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/MimeDmo1.pas @@ -0,0 +1,352 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Object: This program is a demo for TMimeDecode component. + TMimeDecode is a component whose job is to decode MIME encoded + EMail messages (file attach). You can use it for example to + decode messages received with a POP3 component. + MIME is described in RFC-1521. headers are described if RFC-822. +Creation: March 08, 1998 +Version: 1.05 +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +Updates: +Sep 13, 1998 V1.01 Added part and header end numbering +Feb 16/02/99 V1.02 In OnPartLine event handler, assemble line of text for + display. +May 04, 2002 V1.03 Adapted InLineDecodeLine event to new Len argument. + Added file store for UUEncoded files. +Nov 01, 2002 V1.04 Changed PChar arguments to Pointer to work around Delphi 7 + bug with PAnsiChar<->PChar (change has be done in component). + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit MimeDmo1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, ExtCtrls, IniFiles, MimeDec; + +type + TMimeDecodeForm = class(TForm) + Panel1: TPanel; + FileEdit: TEdit; + DecodeButton: TButton; + Memo1: TMemo; + MimeDecode1: TMimeDecode; + Label1: TLabel; + ClearButton: TButton; + procedure DecodeButtonClick(Sender: TObject); + procedure MimeDecode1PartBegin(Sender: TObject); + procedure MimeDecode1PartEnd(Sender: TObject); + procedure MimeDecode1PartHeaderLine(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure ClearButtonClick(Sender: TObject); + procedure MimeDecode1HeaderLine(Sender: TObject); + procedure MimeDecode1PartLine(Sender: TObject; Data: Pointer; + DataLen: Integer); + procedure MimeDecode1HeaderBegin(Sender: TObject); + procedure MimeDecode1HeaderEnd(Sender: TObject); + procedure MimeDecode1PartHeaderBegin(Sender: TObject); + procedure MimeDecode1PartHeaderEnd(Sender: TObject); + procedure MimeDecode1InlineDecodeBegin(Sender: TObject; + Filename: String); + procedure MimeDecode1InlineDecodeEnd(Sender: TObject; + Filename: String); + procedure MimeDecode1InlineDecodeLine(Sender: TObject; + Line: Pointer; Len : Integer); + private + FInitialized : Boolean; + FIniFileName : String; + FLineBuf : array [0..255] of char; + FCharCnt : Integer; + FFileStream : TFileStream; + FFileName : String; + procedure Display(Msg: String); + end; + +var + MimeDecodeForm: TMimeDecodeForm; + +implementation + +{$R *.DFM} +const + SectionData = 'Data'; + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + KeyFile = 'FileName'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.FormCreate(Sender: TObject); +begin + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; + Memo1.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + IniFile := TIniFile.Create(FIniFileName); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, Top); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, Left); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + FileEdit.Text := IniFile.ReadString(SectionData, KeyFile, ''); + IniFile.Free; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.WriteString(SectionData, KeyFile, FileEdit.Text); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.DecodeButtonClick(Sender: TObject); +begin + Memo1.Clear; + Update; + MimeDecode1.DecodeFile(FileEdit.Text); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.Display(Msg: String); +begin + { TMemo cannot hold too much data. Limit to 400 lines } + if Memo1.Lines.count > 400 then + Memo1.Clear; + Memo1.Lines.Add(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1PartBegin(Sender: TObject); +begin + Display('--------- PART ' + + IntToStr(MimeDecode1.PartNumber) + + ' BEGIN ----------'); + FCharCnt := 0; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1PartEnd(Sender: TObject); +begin + if FCharCnt > 0 then begin + Display(StrPas(FLineBuf)); + FCharCnt := 0; + end; + + Display('--------- PART ' + + IntToStr(MimeDecode1.PartNumber) + + ' END ----------'); + { Close file, if any } + if Assigned(FFileStream) then begin + FFileStream.Destroy; + FFileStream := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Decoded data arrives here. This routine suppose that we have text data } +{ organized in lines. } +procedure TMimeDecodeForm.MimeDecode1PartLine( + Sender : TObject; + Data : Pointer; + DataLen : Integer); +var + I : Integer; +begin + { Copy data to LineBuf until CR/LF } + I := 0; + while (I < DataLen) do begin + if PChar(Data)[I] = #13 then { Just ignre CR } + Inc(I) + else if PChar(Data)[I] = #10 then begin { LF is end of line } + FLineBuf[FCharCnt] := #0; + Display(StrPas(FLineBuf)); + FCharCnt := 0; + Inc(I); + end + else begin + FLineBuf[FCharCnt] := PChar(Data)[I]; + Inc(FCharCnt); + Inc(I); + end; + if FCharCnt >= (High(FLineBuf) - 1) then begin + { Buffer overflow, display data accumulated so far } + FLineBuf[High(FLineBuf) - 1] := #0; + Display(StrPas(FLineBuf)); + FCharCnt := 0; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1PartHeaderLine(Sender: TObject); +begin + Display('Part header: ' + StrPas(MimeDecode1.CurrentData)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.ClearButtonClick(Sender: TObject); +begin + Memo1.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1HeaderLine(Sender: TObject); +begin + Display('Msg header: ' + StrPas(MimeDecode1.CurrentData)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1HeaderBegin(Sender: TObject); +begin + Display('--------- HEADER BEGIN ----------'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1HeaderEnd(Sender: TObject); +begin + Display('--------- HEADER END ----------'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1PartHeaderBegin(Sender: TObject); +begin + Display('--------- PART ' + + IntToStr(MimeDecode1.PartNumber) + + ' HEADER BEGIN ----------'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1PartHeaderEnd(Sender: TObject); +begin + Display('--------- PART ' + + IntToStr(MimeDecode1.PartNumber) + + ' HEADER END ----------'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1InlineDecodeBegin( + Sender : TObject; + FileName : String); +begin + Display('--------- INLINE begin. Filename is ''' + FileName + ''''); + Display(''); + FFileName := FileNAme; + if Assigned(FFileStream) then + FFileStream.Destroy; { Close previous file, if any } + FFileStream := TFileStream.Create('MimeFile_' + FFileName, fmCreate); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1InlineDecodeEnd( + Sender : TObject; + Filename : String); +begin + Display('--------- INLINE end'); + { Close file, if any } + if Assigned(FFileStream) then begin + FFileStream.Destroy; + FFileStream := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1InlineDecodeLine( + Sender : TObject; + Line : Pointer; + Len : Integer); +var + LastLine : String; + DataLine : String; +begin + if (Line = nil) or (Len <= 0) then + Exit; + { If any file assigned, then write data to it } + if Assigned(FFileStream) then + FFileStream.Write(Line^, Len); + + SetLength(DataLine, Len); + Move(Line^, DataLine[1], Len); + if Memo1.Lines.Count < 1 then + Memo1.Lines.Add(DataLine) + else begin + LastLine := Memo1.Lines.Strings[Memo1.Lines.Count - 2]; + Memo1.Lines.Delete(Memo1.Lines.Count - 1); + Memo1.Lines.Delete(Memo1.Lines.Count - 1); + LastLine := LastLine + DataLine; + Memo1.Lines.Add(LastLine); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/MimeTst.dpr b/ICS_zlog/Delphi/Internet/MimeTst.dpr new file mode 100644 index 00000000..a4bb0b85 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/MimeTst.dpr @@ -0,0 +1,12 @@ +program MimeTst; + +uses + Forms, + MimeTst1 in 'MimeTst1.pas' {MimeTestForm}; + +{$R *.RES} + +begin + Application.CreateForm(TMimeTestForm, MimeTestForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/MimeTst1.dfm b/ICS_zlog/Delphi/Internet/MimeTst1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..da15472bf3955ca3fa54b4ca140c7dd3f58c87c8 GIT binary patch literal 2147 zcma)8-HsbI6n18knMpRYy9FU=uLcQKNNA&Np|EhZ*=$0Jk|x@5DRpywKIb_9v;Z7GANOHDg@eh>7@VJuA^_lY za2~@kSzw5T9Po0{u1@MBd@KF;YChyk@0Z3alFP#XqZSM?nHSRky%zS+QWDOBriLY& zq|xJ)mtixbSCS1-hT8+qWT#i4QeYXLT=xgvmm~ONZ`i#_`>;+ojAReblikL`JT#{RhPvx58BXB&Sd9TDs;z^m~vKdX7orY>#xv=AS zO5S2Brnr30vch}a($<`v7&PD*FL*c>bNy=s@PLVb?c)D!6TdgD4+)b&dyIuZbDYe0 zzHW3WnX|BgsM0JR5r#!4l_gfXr@@q)3GGxv_7>g-iIz(z4$&?>w}Unvz_MH#FA~e*{|YuVA8a+R)pfZ94{uAvGEPKiNwAdoQoLC+EITvh zpQR2U-zUC!7qRz$iI1F+`|MN4{_ws&D{lLi{n4h@WPuZGic8pI=>QPItCf_T9jBP( zV^w%|YNYXB+a~CYc-?zx?$fHJVaa0++{#rCRSTjddlSCD%W4)kTA9P$k0*MUTEND0 zQesucor?Ioh2_%PG%)|q!^%3{X;)3tyL6igV~KR{|86BDxm|DL@psGS%WC#{)?x4Q zMw@NPwFZRZWJH8isppzdTd(P*{Vw#^p`YCyKlfYE4infqTi3NxX)~@=ts0LGd)2S|gu3~gDc HzY^eIP2Py& literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/MimeTst1.pas b/ICS_zlog/Delphi/Internet/MimeTst1.pas new file mode 100644 index 00000000..d2aa7cea --- /dev/null +++ b/ICS_zlog/Delphi/Internet/MimeTst1.pas @@ -0,0 +1,232 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +Author: François PIETTE + Using code donated by Brad Choate +Object: Demo for MIME support (files attach) in sending files. + This demo use TSyncSmtpCli for simplicity. High performnace + programs should use the async SMTP component TSmtpCli. +Creation: February 14th, 1998 +Version: 1.13 +EMail: francois.piette@pophost.eunet.be francois.piette@rtfm.be + http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1998, 1999 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Sep 12, 1998 V1.10 Revised to use the new TSyncSmtpCli component. +Mar 06, 1999 V1.11 Replaced LastDelimiter by FindLastDelim for D2 compatibility + Added Trim functions for Delphi 1. Used GetText/SetText for + TStrings because of Delphi 1. +Aug 21, 1999 V1.12 Disposed memory got with GetText. +Nov 01, 2002 V1.13 Changed arguments in events handlers from PChar to Pointer + to reflect this change in the component. + Added a call to HeloSync before MailSync because some servers + really wants this before accepting email. + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit MimeTst1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, SmtpProt, StdCtrls, ExtCtrls; + +type + TMimeTestForm = class(TForm) + FSmtp: TSyncSmtpCli; + MsgMemo: TMemo; + DisplayMemo: TMemo; + Panel1: TPanel; + Label1: TLabel; + Label2: TLabel; + FromEdit: TEdit; + ToEdit: TEdit; + Label3: TLabel; + SubjectEdit: TEdit; + SendMailButton: TButton; + HostEdit: TEdit; + Label4: TLabel; + Panel2: TPanel; + FileListMemo: TMemo; + Label5: TLabel; + Label6: TLabel; + Panel3: TPanel; + Label7: TLabel; + procedure SendMailButtonClick(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure FSmtpDisplay(Sender: TObject; Msg: String); + procedure FSmtpGetData(Sender: TObject; LineNum: Integer; + MsgLine: Pointer; MaxLen: Integer; var More: Boolean); + end; + +var + MimeTestForm: TMimeTestForm; + +implementation + +{$R *.DFM} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeTestForm.FormCreate(Sender: TObject); +begin + FileListMemo.Clear; + FileListMemo.Lines.Add('c:\temp\test.txt'); + FileListMemo.Lines.Add('c:\temp\brol.txt'); + DisplayMemo.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function FindLastDelim(Delim : Char; const S : String) : Integer; +begin + Result := Length(S); + while (Result > 0) and (S[Result] <> Delim) do + Dec(Result); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +function TrimRight(Str : String) : String; +var + i : Integer; +begin + i := Length(Str); + while (i > 0) and (Str[i] = ' ') do + i := i - 1; + Result := Copy(Str, 1, i); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TrimLeft(Str : String) : String; +var + i : Integer; +begin + if Str[1] <> ' ' then + Result := Str + else begin + i := 1; + while (i <= Length(Str)) and (Str[i] = ' ') do + i := i + 1; + Result := Copy(Str, i, Length(Str) - i + 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function Trim(Str : String) : String; +begin + Result := TrimLeft(TrimRight(Str)); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ General-purpose routine that reformats the text portion } +{ of our message to a particular margin. } +procedure Reformat(stl: TStrings; iMargin: integer); +var + sOverage, sUnderage: string; + i, iBreak: integer; +begin + i := 0; + while i < stl.Count do begin + if Length(stl[i]) > iMargin then begin + iBreak := FindLastDelim(' ', Copy(stl[i], 1, iMargin)); + if iBreak > 0 then begin + sOverage := Trim(Copy(stl[i], iBreak, Length(stl[i]))); + sUnderage := Copy(stl[i], 1, iBreak - 1); + if Trim(sUnderage) <> '' then begin + stl[i] := sUnderage; + stl.Insert(i + 1, sOverage); + end; + end; + end; + Inc(i); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeTestForm.SendMailButtonClick(Sender: TObject); +var + TextPtr : PChar; +begin + TextPtr := FileListMemo.Lines.GetText; + FSmtp.EmailFiles.SetText(TextPtr); + StrDispose(TextPtr); + FSmtp.RcptName.Clear; + FSmtp.RcptName.Add(ToEdit.text); + FSmtp.HdrSubject := SubjectEdit.text; + FSmtp.FromName := FromEdit.Text; + FSmtp.HdrFrom := FromEdit.Text; + FSmtp.HdrTo := ToEdit.Text; + FSmtp.Host := HostEdit.Text; + FSmtp.Port := 'smtp'; + FSmtp.ConnectSync; + FSmtp.HeloSync; + FSmtp.MailSync; + FSmtp.QuitSync; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeTestForm.FSmtpDisplay(Sender: TObject; Msg: String); +begin + if DisplayMemo.Lines.count > 200 then + DisplayMemo.Clear; + DisplayMemo.Lines.Add(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeTestForm.FSmtpGetData(Sender: TObject; LineNum: Integer; + MsgLine: Pointer; MaxLen: Integer; var More: Boolean); +var + Len : Integer; +begin + if LineNum > MsgMemo.Lines.count then + More := FALSE + else begin + Len := Length(MsgMemo.Lines[LineNum - 1]); + { Truncate the line if too long (should wrap to next line) } + if Len >= MaxLen then + StrPCopy(MsgLine, Copy(MsgMemo.Lines[LineNum - 1], 1, MaxLen - 1)) + else + StrPCopy(MsgLine, MsgMemo.Lines[LineNum - 1]); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/NewsRdr1.dfm b/ICS_zlog/Delphi/Internet/NewsRdr1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..9e91f054a2ac182a47ec13b739ad34a930d81da0 GIT binary patch literal 6955 zcmb_h>u%e~6{dBiZk8``oXs}PG+4OFBGuZv-EPnpZDq-hjmnnS(r&W-(~iWk#fBOx zBxSAs6@7{V?E~}``Ud^cKYfe7K!N^i&s;b|QKZ2I8U!}YneUwMT;|No;eV^f@bYqa zb=tqaFb=mKeP|f)$6-ahbiJv`N8zE+BR4_*A4Y!Y&fr(^jco;!{4iHKBlhhi$j>&) z9XtzcmzJI|4Ehn81i|d5pM0`dEL!dz@kYylv__=ZaUItySH{k9Ku__Q)K6U+v^o>) z`6MVeyC3bIOD&;=yIId610QaW+vDBx7iMuG9>@Cd~4pHhs;T%D^6Pv@RWN9P*K&m}Mr{2D`lDo7xX9!hj=9i2Px#*m*0WPu}p zCXp}Kk(IU=w9w^z+KLJIu@F$_0-i|$Pu2w#UwiI+76X4Sz>hijodj>KgA1p&Lt@yU z2wMLiZF?jS^9=U{5JX7drmsbvvoHnCffgT$jG$ijL< zeP;ugfU!^USk2GN{(1^~bBer&272&@MN&EoOID1CB(WK)$-;k6@!t($B1hx?KZbg6kN?xM_+#aNU1nHmSs@=QEfu9J ziv`=tf_;TcjewYu7=bhkewY-2H4~!#50zwL|4^~t4PnXt9|SnK$Ny;yRpq}Acvz_; zcMfYI5{sqWn^a+`C{0=T?RS{)2+TEtSDjXd)64v1wVD z7DTue9UW;nYb^LV-%kj4+R|x-tDRjkVf7#$T^~JX@fYD|Y>y6+g_r&d750i!mW8xv zy|7E(1BFXm`3)F`|0@>A6iBl`?RTLC6!2^O8GX&ZEY)P;zNu1UXN6ombI;%ol;HTZ zGW&zj@e{zI8_%7lrg4FZ&O+5xRGXSjjA!j_A9@H;qVhbH=HK_cxMFdw@)7Ip-PvT( zLQwBSUkHt1dmFJb>)Z5}Wjntcy@VIyiC=FpgutI5mih}<4*19?GweZ!4z53N@!?Z+ zbuMzQSuB5~EZ>UQ7c+gES^hO}Kb@}B7*P@Pe=ydz7nSa{2vql0K2Ta8M#d8pyV?aK zqh1$TeXr62!)R@fmA0l9wpycD%PLl*l!o;p^&3&7o-N(E$1Bt`^mF#yV!fqbv8S;+ zong9cS?(0u^cQGhL-k_o%yQx4Ptg0h8xT0-Kw-l?@*_NcM*_c-aUw>l{hJ>phq@LrM$+FNI;Hk_AHvEqTvc{b@4GmciR6F zcG^wsfDnku|NA3Dtpkg}hCU7K04tvu8ay#RLjmK>8? zo5D6PtT~Flt*c2V)GF`9rocN;B}yBhzxtg%gnzF`1d~&dbkn* literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/NewsRdr1.pas b/ICS_zlog/Delphi/Internet/NewsRdr1.pas new file mode 100644 index 00000000..fe13113e --- /dev/null +++ b/ICS_zlog/Delphi/Internet/NewsRdr1.pas @@ -0,0 +1,732 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: This sample program show how to use TNntpCli to write a news + enabled application. +Creation: December 24, 1997 +Version: 0.94 +EMail: http://www.overbyte.be http://www.rtfm.be/fpiette + francois.piette@overbyte.be francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 1997-2002 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: +Dec 29, 1997 V0.91 Adapted to be compatible with Delphi 1 +Jan 04, 1998 V0.92 Added LIST OVERVIEW.FMT, XOVER and DATE +Jan 31, 1998 V0.93 Added the UserEditBox (used for Post command) + Added code to get UserName and EMail from IE settings +Aug 14, 1999 V0.94 Added support for XHDR and MODE READER. + Corrected a bug that let Connect and Abort button + disabled when DNS lookup failed. + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit NewsRdr1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, NntpCli, StdCtrls, ExtCtrls, IniFiles; + +type + TNNTPForm = class(TForm) + NntpCli1: TNntpCli; + Panel1: TPanel; + ServerEdit: TEdit; + ConnectButton: TButton; + Label1: TLabel; + DisplayMemo: TMemo; + AbortButton: TButton; + GroupButton: TButton; + GroupEdit: TEdit; + ArticleNumEdit: TEdit; + ArticleByNumberButton: TButton; + ArticleByIDButton: TButton; + NextButton: TButton; + LastButton: TButton; + HeadByNumberButton: TButton; + HeadByIDButton: TButton; + BodyByNumberButton: TButton; + BodyByIDButton: TButton; + StatByNumberButton: TButton; + StatByIDButton: TButton; + ListButton: TButton; + ArticleIDEdit: TEdit; + Label2: TLabel; + Label3: TLabel; + Label4: TLabel; + PostButton: TButton; + QuitButton: TButton; + FileEdit: TEdit; + Label5: TLabel; + NewGroupsButton: TButton; + NewNewsButton: TButton; + HelpButton: TButton; + XOverButton: TButton; + OverViewFmtButton: TButton; + DateButton: TButton; + UserEdit: TEdit; + Label6: TLabel; + Label7: TLabel; + UserNameEdit: TEdit; + Label8: TLabel; + PasswordEdit: TEdit; + AuthenticateButton: TButton; + ModeReaderButton: TButton; + XHdrButton: TButton; + procedure ConnectButtonClick(Sender: TObject); + procedure NntpCli1SessionConnected(Sender: TObject; Error: Word); + procedure NntpCli1SessionClosed(Sender: TObject; Error: Word); + procedure AbortButtonClick(Sender: TObject); + procedure GroupButtonClick(Sender: TObject); + procedure NntpCli1RequestDone(Sender: TObject; RqType: TNntpRequest; Error: Word); + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure ArticleByNumberButtonClick(Sender: TObject); + procedure NntpCli1DataAvailable(Sender: TObject; Error: Word); + procedure NntpCli1MessageLine(Sender: TObject); + procedure NntpCli1MessageBegin(Sender: TObject); + procedure NntpCli1MessageEnd(Sender: TObject); + procedure ArticleByIDButtonClick(Sender: TObject); + procedure NextButtonClick(Sender: TObject); + procedure LastButtonClick(Sender: TObject); + procedure HeadByIDButtonClick(Sender: TObject); + procedure HeadByNumberButtonClick(Sender: TObject); + procedure BodyByIDButtonClick(Sender: TObject); + procedure BodyByNumberButtonClick(Sender: TObject); + procedure StatByIDButtonClick(Sender: TObject); + procedure StatByNumberButtonClick(Sender: TObject); + procedure ListButtonClick(Sender: TObject); + procedure PostButtonClick(Sender: TObject); + procedure QuitButtonClick(Sender: TObject); + procedure NewGroupsButtonClick(Sender: TObject); + procedure NewNewsButtonClick(Sender: TObject); + procedure HelpButtonClick(Sender: TObject); + procedure XOverButtonClick(Sender: TObject); + procedure OverViewFmtButtonClick(Sender: TObject); + procedure DateButtonClick(Sender: TObject); + procedure AuthenticateButtonClick(Sender: TObject); + procedure ModeReaderButtonClick(Sender: TObject); + procedure XHdrButtonClick(Sender: TObject); + procedure NntpCli1XHdrBegin(Sender: TObject); + procedure NntpCli1XHdrEnd(Sender: TObject); + procedure NntpCli1XHdrLine(Sender: TObject); + private + FInitialized : Boolean; + FDataStream : TStream; + function GetStream : TStream; + procedure Display(Msg : String); + procedure LineToStream(Buf : String); + end; + +var + NNTPForm: TNNTPForm; + +implementation + +{$R *.DFM} + +{$IFNDEF VER80} +uses + Registry; +{$ENDIF} + + +const + IniFileName = 'NEWSRDR.INI'; + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +function TrimRight(Str : String) : String; +var + i : Integer; +begin + i := Length(Str); + while (i > 0) and (Str[i] = ' ') do + i := i - 1; + Result := Copy(Str, 1, i); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TrimLeft(Str : String) : String; +var + i : Integer; +begin + if Str[1] <> ' ' then + Result := Str + else begin + i := 1; + while (i <= Length(Str)) and (Str[i] = ' ') do + i := i + 1; + Result := Copy(Str, i, Length(Str) - i + 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function Trim(Str : String) : String; +begin + Result := TrimLeft(TrimRight(Str)); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; + EMail : String; + UserName : String; +{$IFNDEF VER80} + Reg : TRegistry; + Key : String; +{$ENDIF} +begin + if FInitialized then + Exit; + FInitialized := TRUE; + + EMail := 'your.name@yourcompany.domain'; + UserName := 'Your Name'; + +{$IFNDEF VER80} + { Get username and EMail from the Internet Explorer settings } + { Should add code for Netscape Navigator... } + Reg := TRegistry.Create; + Reg.RootKey := HKEY_CURRENT_USER; + Key := '\Software\Microsoft\Internet Mail and News\Mail'; + if Reg.OpenKey(Key, FALSE) then begin + EMail := Reg.ReadString('Sender EMail'); + UserName := Reg.ReadString('Sender Name'); + end; + Reg.CloseKey; + Reg.Free; +{$ENDIF} + + IniFile := TIniFile.Create(IniFileName); + Top := IniFile.ReadInteger('Window', 'Top', Top); + Left := IniFile.ReadInteger('Window', 'Left', Left); + Width := IniFile.ReadInteger('Window', 'Width', Width); + Height := IniFile.ReadInteger('Window', 'Height', Height); + ServerEdit.Text := IniFile.ReadString('Data', 'Server', ''); + ArticleNumEdit.Text := IniFile.ReadString('Data', 'ArticleNum', ''); + ArticleIDEdit.Text := IniFile.ReadString('Data', 'ArticleID', ''); + FileEdit.Text := IniFile.ReadString('Data', 'File', 'nntprdr.txt'); + UserNameEdit.Text := IniFile.ReadString('Data', 'UserName', ''); + PasswordEdit.Text := IniFile.ReadString('Data', 'Password', ''); + UserEdit.Text := IniFile.ReadString('Data', 'User', + '"' + UserName + '" <' + EMail + '>'); + GroupEdit.Text := IniFile.ReadString('Data', 'Group', + 'borland.public.delphi.thirdparty-tools'); + IniFile.Free; + DisplayMemo.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(IniFileName); + IniFile.WriteString('Data', 'Server', ServerEdit.Text); + IniFile.WriteString('Data', 'Group', GroupEdit.Text); + IniFile.WriteString('Data', 'ArticleNum', ArticleNumEdit.Text); + IniFile.WriteString('Data', 'ArticleID', ArticleIDEdit.Text); + IniFile.WriteString('Data', 'File', FileEdit.Text); + IniFile.WriteString('Data', 'User', UserEdit.Text); + IniFile.WriteString('Data', 'UserName', UserNameEdit.Text); + IniFile.WriteString('Data', 'Password', PasswordEdit.Text); + IniFile.WriteInteger('Window', 'Top', Top); + IniFile.WriteInteger('Window', 'Left', Left); + IniFile.WriteInteger('Window', 'Width', Width); + IniFile.WriteInteger('Window', 'Height', Height); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.Display(Msg : String); +begin + { Limit the memo to 100 lines } + while DisplayMemo.Lines.Count > 100 do + DisplayMemo.Lines.Delete(1); + DisplayMemo.Lines.Add(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.NntpCli1SessionConnected(Sender: TObject; Error: Word); +begin + AbortButton.Enabled := TRUE; + Display('Connected, StatusCode = ' + IntToStr(NntpCli1.StatusCode)); + if NntpCli1.PostingPermited then + Display('Posting permited') + else + Display('Posting not permited'); + Display(NntpCli1.LastResponse); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.NntpCli1SessionClosed(Sender: TObject; Error: Word); +begin + AbortButton.Enabled := FALSE; + ConnectButton.Enabled := TRUE; + Display('Connection closed'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called for each NNTP command when the command has } +{ been exected (correctly or not). } +procedure TNNTPForm.NntpCli1RequestDone( + Sender: TObject; + RqType: TNntpRequest; + Error: Word); +begin + Display('Request done. LastResponse = ' + + NntpCli1.LastResponse); + + if Error = 0 then + Display('No error') + else + Display('Error #' + IntToStr(Error)); + + case RqType of + nntpConnect: + begin + if Error <> 0 then begin + AbortButton.Enabled := FALSE; + ConnectButton.Enabled := TRUE; + Display('Connect failed'); + end; + end; + nntpGroup: + begin + Display('ArticleEstimated = ' + IntToStr(NntpCli1.ArticleEstimated)); + Display('ArticleFirst = ' + IntToStr(NntpCli1.ArticleFirst)); + Display('ArticleLast = ' + IntToStr(NntpCli1.ArticleLast)); + ArticleNumEdit.Text := IntToStr(NntpCli1.ArticleFirst); + end; + nntpPost, nntpQuit, nntpAbort, nntpHelp, nntpNewGroups, nntpNewNews, + nntpXOver, nntpListOverViewFmt, nntpAuthenticate, nntpModeReader, + nntpXHdr: + begin + { Nothing to do } + end; + nntpDate: + begin + Display('Server Date is ' + DateTimeToStr(NntpCli1.ServerDate)); + end; + nntpStatByNumber, nntpStatByID, + nntpHeadByNumber, nntpHeadByID, + nntpBodyByNumber, nntpBodyByID, + nntpArticleByNumber, nntpArticleByID, + nntpNext, nntpLast: + begin + Display('ArticleNumber = ' + + IntToStr(NntpCli1.ArticleNumber)); + Display('ArticleID = ' + + '<' + NntpCli1.ArticleID + '>'); + if Error = 0 then begin + ArticleNumEdit.Text := IntToStr(NntpCli1.ArticleNumber); + ArticleIDEdit.Text := NntpCli1.ArticleID; + end; + end; + else + Display('Unknown request type.'); + end; + + { If any stream where used, destroy it } + if Assigned(FDataStream) then begin + FDataStream.Free; + FDataStream := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called by TNntpCli when it has received data and } +{ don't know what to do with it. It should normally not occur ! } +procedure TNNTPForm.NntpCli1DataAvailable(Sender: TObject; Error: Word); +begin + Display('Data: ' + NntpCli1.LastResponse); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called by TNntpCli component just before the } +{ component will begin receiving a message. It's a good place to open a } +{ file or start a progress bar. } +procedure TNNTPForm.NntpCli1MessageBegin(Sender: TObject); +begin + Display('Message begin'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called by TNntpCli component for each line of an } +{ incomming message. Header line as well as body lines are comming here. } +{ It's a good place to write to a file or update screen or progress bar. } +{ It's also the place to intercept header lines. } +procedure TNNTPForm.NntpCli1MessageLine(Sender: TObject); +var + NewsGroupName : String; + LastArticle : Integer; + FirstArticle : Integer; + PostingFlag : Char; +begin + Display('Line: ' + NntpCli1.LastResponse); + ParseListLine(NntpCli1.LastResponse, + NewsGroupName, + LastArticle, + FirstArticle, + PostingFlag); + { It the place to do something with NewsGroupName, LastArticle, } + { FirstArticle and PostingFlag } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called by TNntpCli component when a message has } +{ been received completely. It's a good place to close a file, delete the } +{ progress bar and alert user. } +procedure TNNTPForm.NntpCli1MessageEnd(Sender: TObject); +begin + Display('Message End'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This function is called internally to create a TFileStream if any file } +{ name is specified in the FileEdit box. If the edit box is blank, nil is } +{ returned. The TFileStream will be supplyed to the comoponent for every } +{ command which can take a TStream to store data such as ArticleByNum. } +{ The stream is destroyed in the OnRequestDone event handler. } +function TNNTPForm.GetStream : TStream; +begin + { Delete the previous stream if not already done } + if Assigned(FDataStream) then begin + FDataStream.Free; + FDataStream := nil; + end; + + if Trim(FileEdit.Text) = '' then + FDataStream := nil + else begin + { Try to open the file stream. Trap errors. } + try + FDataStream := TFileStream.Create(Trim(FileEdit.Text), fmCreate); + except + on E:Exception do begin + { Display an error message in our TMemo } + Display(E.Message); + FDataStream := nil; + raise; { Show the exception box } + end; + end; + end; + Result := FDataStream; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.ConnectButtonClick(Sender: TObject); +begin + DisplayMemo.Clear; + ConnectButton.Enabled := FALSE; + NntpCli1.Host := ServerEdit.Text; + NntpCli1.Connect; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.AbortButtonClick(Sender: TObject); +begin + NntpCli1.Abort; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.QuitButtonClick(Sender: TObject); +begin + NntpCli1.Quit; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.GroupButtonClick(Sender: TObject); +begin + NntpCli1.Group(GroupEdit.Text); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.NextButtonClick(Sender: TObject); +begin + NntpCli1.Next; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.LastButtonClick(Sender: TObject); +begin + NntpCli1.Last; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.ArticleByIDButtonClick(Sender: TObject); +begin + NntpCli1.ArticleByID(ArticleIDEdit.Text, GetStream); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.ArticleByNumberButtonClick(Sender: TObject); +begin + NntpCli1.ArticleByNumber(StrToInt(ArticleNumEdit.Text), GetStream); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.HeadByIDButtonClick(Sender: TObject); +begin + NntpCli1.HeadByID(ArticleIDEdit.Text, GetStream); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.HeadByNumberButtonClick(Sender: TObject); +begin + NntpCli1.HeadByNumber(StrToInt(ArticleNumEdit.Text), GetStream); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.BodyByIDButtonClick(Sender: TObject); +begin + NntpCli1.BodyByID(ArticleIDEdit.Text, GetStream); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.BodyByNumberButtonClick(Sender: TObject); +begin + NntpCli1.BodyByNumber(StrToInt(ArticleNumEdit.Text), GetStream); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.StatByIDButtonClick(Sender: TObject); +begin + NntpCli1.StatByID(ArticleIDEdit.Text); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.StatByNumberButtonClick(Sender: TObject); +begin + NntpCli1.StatByNumber(StrToInt(ArticleNumEdit.Text)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.ListButtonClick(Sender: TObject); +begin + if Application.MessageBox('This could take a VERY long time, proceed ? ', + 'Warning', MB_YESNO) <> ID_YES then + Exit; + NntpCli1.List(GetStream); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.NewGroupsButtonClick(Sender: TObject); +begin + NntpCli1.NewGroups(Now - 10, FALSE, '', GetStream); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.NewNewsButtonClick(Sender: TObject); +begin + NntpCli1.NewNews(Now - 1, FALSE, GroupEdit.Text, '', GetStream); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.HelpButtonClick(Sender: TObject); +begin + NntpCli1.Help(GetStream); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNntpForm.LineToStream(Buf : String); +begin + Display('Line: ' + Buf); + Buf := Buf + #13#10; + FDataStream.WriteBuffer(Buf[1], Length(Buf)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Posting a message require to build the message, including his header. } +{ Here we use a TMemoryStream to create a message on the fly. Normally we } +{ should use a TFileStream to get the message from a file where it has } +{ been written by some user interface. } +procedure TNNTPForm.PostButtonClick(Sender: TObject); +begin + { Delete the stream if not already done } + if Assigned(FDataStream) then begin + FDataStream.Free; + FDataStream := nil; + end; + + { Create a new stream in memory } + FDataStream := TMemoryStream.Create; + + { Write the message header } + LineToStream('From: ' + UserEdit.Text); + LineToStream('Newsgroups: ' + GroupEdit.Text); + LineToStream('Subject: Internet Components Suite (ICS)'); + LineToStream('Organization: None'); + LineToStream('X-Newsreader: NNTP component ' + + '(http://www.overbyte.be)'); + + { End of header is a blank line } + LineToStream(''); + + { Write the message body } + LineToStream(''); + LineToStream('The Internet Component Suite is a set of native'); + LineToStream('components for Borland Delphi (all versions,'); + LineToStream('including 16 bits) and Borland C++ Builder. The'); + LineToStream('major TCP/IP protocols are supported for building'); + LineToStream('client/server, intranet or Internet applications.'); + LineToStream(''); + LineToStream('TCP, UDP, TELNET, FTP, SMTP, POP3, PING, FINGER, HTTP,'); + LineToStream('NNTP and more. Each component has samples writen'); + LineToStream('in Delphi and in C++ Builder. Several client/server'); + LineToStream('applications, including an event-driven and a'); + LineToStream('multi-threaded server, a complete FTP client and'); + LineToStream('TELNET client with ansi emulation are provided.'); + LineToStream('Full source code provided for everything.'); + LineToStream(''); + LineToStream('The Internet Component Suite is freeware, royalty'); + LineToStream('free and support is done using a mailing list.'); + LineToStream('Visit our website and download now from'); + LineToStream('http://www.overbyte.be'); + + { Set stream pointer to beginning of stream because TNntpCli will post } + { from the current position } + FDataStream.Seek(0, soFromBeginning ); + + { Ask the component to post the stream. The posting occurs in the } + { background ! We will receive the OnRequestDone event when done. } + { It's in this event handler that the stream must be destroyed } + NntpCli1.Post(FDataStream); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.XOverButtonClick(Sender: TObject); +begin + NntpCli1.XOver(ArticleNumEdit.Text, GetStream); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.OverViewFmtButtonClick(Sender: TObject); +begin + NntpCli1.ListOverViewFmt(GetStream); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.DateButtonClick(Sender: TObject); +begin + NntpCli1.Date; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.AuthenticateButtonClick(Sender: TObject); +begin + NntpCli1.UserName := UserNameEdit.Text; + NntpCli1.Password := PasswordEdit.Text; + NntpCli1.Authenticate; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.ModeReaderButtonClick(Sender: TObject); +begin + NntpCli1.ModeReader; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.XHdrButtonClick(Sender: TObject); +begin + NntpCli1.XHdr(GetStream, 'subject', ArticleNumEdit.Text); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.NntpCli1XHdrBegin(Sender: TObject); +begin + Display('XHdr begin'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.NntpCli1XHdrEnd(Sender: TObject); +begin + Display('Xhdr End'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNNTPForm.NntpCli1XHdrLine(Sender: TObject); +begin + Display('XHdr: ' + NntpCli1.LastResponse); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/NsLook1.dfm b/ICS_zlog/Delphi/Internet/NsLook1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..7cb9b3d9224e5fbac05c6dfff59a706a2d5730de GIT binary patch literal 1506 zcmb7D%Tn7g6jhwWb{s+&N+0a9V!C2rI{g5WG_*rr#qPkeZX$>WM@nS{lU;VKI{k%y zLjM5v{gUpoX(v+_>6PS1fYMHtNV+;#_gvkF7Z!5bcC*ttc-L)o4qIqv?OPrpr`y;m zIqjfH>DhSHplrCZe8@HN3D0ISS%;3Y`l9dVBmeZB1t zamB{$9J7j|vl^7}?HctdGgf;3kw^M8bnpc)N`>OkeiY^gKtsb6kdQ3#g2;CX z<((ED(qi2UM!q`{vW!_nB4lkZig-1N_!G+S`Q9lpOxLgZ9wz+%qb%0wn0b(oRaBl4V+Uk5S*Rx-2mCAgEG4Fdg?phxIYj5JI}sbqV%$ zx$Z7UgziQJF{*&_t`8xnG#SXvtG>sLItj$CSf0teR1}Lgi5fwBoZ6wBNU$E8p@_y5 z1-{E;{)H!_coI8=45vEgoRZbnv1%}NR89ItRV-#aNM4q7Xkjb1OCPJrHu8FB#-muN zNTIg9GwIUfRZiAxK6Y8uB~=M2w^jLVXtCSP*zIQOBb)emdY?u5vG)DRXs}&(xoiD` z^8JKaZHZNkbC}Ozu0=D0av&izm8)8WE*(>)oKEE(v4V)MudiVT0WIVoEfzw82|oeB z5=H}H2tEwU04^TbX96#yMN#QzS6}7*;?0c_meK6<6#!sAzX6~;E0+Zz_yCxLegVLx z$fP=3d^P{cb&ug9%ujTDr+k-Onv4P zpBstxR$rll1E1B~F=mrOEbQjGlyO~q`J&Vzhxp?d2fR)RHa3zQOQ>qUxq9C*twc literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/NsLook1.pas b/ICS_zlog/Delphi/Internet/NsLook1.pas new file mode 100644 index 00000000..abbca4f2 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/NsLook1.pas @@ -0,0 +1,273 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Program: NsLookup +Description: Demo for DnsQuery ICS component. +Author: François Piette +EMail: francois.piette@pophost.eunet.be francois.piette@rtfm.be + http://www.rtfm.be/fpiette +Creation: January 29, 1999 +Version: 1.02 +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1999 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +History: +Feb 27, 1999 V1.01 Added PTR lookup (reverse DNS lookup) +Mar 07, 1999 V1.02 Adapted for Delphi 1 + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit NsLook1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, IniFiles, WinSock, DnsQuery, StdCtrls, ExtCtrls, Buttons; + +type + TNsLookupForm = class(TForm) + DisplayMemo: TMemo; + Panel1: TPanel; + DnsEdit: TEdit; + NameEdit: TEdit; + MXLookupButton: TButton; + DnsQuery1: TDnsQuery; + ClearDisplayBitBtn: TBitBtn; + ALookupButton: TButton; + PTRLookupButton: TButton; + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure MXLookupButtonClick(Sender: TObject); + procedure DnsQuery1RequestDone(Sender: TObject; Error: Word); + procedure ClearDisplayBitBtnClick(Sender: TObject); + procedure ALookupButtonClick(Sender: TObject); + procedure PTRLookupButtonClick(Sender: TObject); + private + FIniFileName : String; + FInitialized : Boolean; + FRequestID : Integer; + procedure Display(Msg : String); + procedure DumpDnsResponse; + public + property IniFileName : String read FIniFileName write FIniFileName; + end; + +var + NsLookupForm: TNsLookupForm; + +implementation + +{$R *.DFM} + +const + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + SectionData = 'Data'; + KeyName = 'Name'; + KeyDns = 'Dns'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.FormCreate(Sender: TObject); +begin + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + + IniFile := TIniFile.Create(FIniFileName); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, + (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, + (Screen.Width - Width) div 2); + NameEdit.Text := IniFile.ReadString(SectionData, KeyName, 'inprise.com'); + DnsEdit.Text := IniFile.ReadString(SectionData, KeyDns, '193.121.171.135'); + DisplayMemo.Clear; + IniFile.Destroy; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.WriteString(SectionData, KeyName, NameEdit.Text); + IniFile.WriteString(SectionData, KeyDns, DnsEdit.Text); + IniFile.Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.Display(Msg : String); +begin + if DisplayMemo.Lines.Count > 200 then + DisplayMemo.Lines.Delete(0); + DisplayMemo.Lines.Add(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.DumpDnsResponse; +var + P : PChar; + I : Integer; + Len : Integer; + Buf : String; +begin + Display('Response dump (' + IntToStr(DnsQuery1.ResponseLen) + ' bytes):'); + P := DnsQuery1.ResponseBuf; + Len := DnsQuery1.ResponseLen; + Buf := ''; + I := 0; + while I < Len do begin + if P^ in [' '..'~'] then + Buf := Buf + P^ + else + Buf := Buf + '<' + IntToStr(Ord(P^)) + '>'; + Inc(I); + Inc(P); + if (I mod 16) = 0 then begin + Display(' ' + Buf); + Buf := ''; + end; + end; + if Length(Buf) > 0 then + Display(' ' + Buf); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.DnsQuery1RequestDone(Sender: TObject; Error: Word); +var + I : Integer; + nIndex : Integer; +begin + if Error <> 0 then begin + Display('Error #' + IntToStr(Error)); + Exit; + end; + Display('ID : ' + IntToStr(DnsQuery1.ResponseID)); + Display('ResponseCode : ' + IntToStr(DnsQuery1.ResponseCode)); + Display('OpCode : ' + IntToStr(DnsQuery1.ResponseOpCode)); + Display('Authoritative : ' + IntToStr(Ord(DnsQuery1.ResponseAuthoritative))); + Display('Truncation : ' + IntToStr(Ord(DnsQuery1.ResponseTruncation))); + Display('RecursionAvailable : ' + IntToStr(Ord(DnsQuery1.ResponseRecursionAvailable))); + Display('QDCount : ' + IntToStr(DnsQuery1.ResponseQDCount)); + Display('ANCount : ' + IntToStr(DnsQuery1.ResponseANCount)); + Display('NSCount : ' + IntToStr(DnsQuery1.ResponseNSCount)); + Display('ARCount : ' + IntToStr(DnsQuery1.ResponseARCount)); + Display('ResponseLen : ' + IntToStr(DnsQuery1.ResponseLen)); + Display('QuestionName : ' + DnsQuery1.QuestionName); + Display('QuestionType : ' + IntToStr(DnsQuery1.QuestionType)); + Display('QuestionClass : ' + IntToStr(DnsQuery1.QuestionClass)); + + for I := 0 to DnsQuery1.ResponseANCount - 1 do begin + Display('Answer #' + IntToStr(I + 1)); + Display(' AnswerName : ' + DnsQuery1.AnswerName[I]); + Display(' AnswerType : ' + IntToStr(DnsQuery1.AnswerType[I])); + Display(' AnswerClass : ' + IntToStr(DnsQuery1.AnswerClass[I])); + Display(' AnswerTTL : ' + IntToStr(DnsQuery1.AnswerTTL[I])); + nIndex := DnsQuery1.AnswerTag[I]; + if nIndex >= 0 then begin + case DnsQuery1.AnswerType[I] of + DnsQueryMX: + begin + Display(' MXPreference : ' + IntToStr(DnsQuery1.MXPreference[nIndex])); + Display(' MXExchange : ' + DnsQuery1.MXExchange[nIndex]); + end; + DnsQueryA: + begin + Display(' Address : ' + StrPas(inet_ntoa(DnsQuery1.Address[nIndex]))); + end; + DnsQueryPTR: + begin + Display(' Hostname : ' + DnsQuery1.Hostname[nIndex]); + end; + end; + end; + end; + { Dump complete response } + DumpDnsResponse; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.ClearDisplayBitBtnClick(Sender: TObject); +begin + DisplayMemo.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.MXLookupButtonClick(Sender: TObject); +begin + DnsQuery1.Addr := DnsEdit.Text; + FRequestID := DnsQuery1.MXLookup(NameEdit.Text); + Display('Request ID : ' + IntToStr(FRequestID)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.ALookupButtonClick(Sender: TObject); +begin + DnsQuery1.Addr := DnsEdit.Text; + FRequestID := DnsQuery1.ALookup(NameEdit.Text); + Display('Request ID : ' + IntToStr(FRequestID)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TNsLookupForm.PTRLookupButtonClick(Sender: TObject); +begin + DnsQuery1.Addr := DnsEdit.Text; + FRequestID := DnsQuery1.PTRLookup(NameEdit.Text); + Display('Request ID : ' + IntToStr(FRequestID)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. diff --git a/ICS_zlog/Delphi/Internet/NsLookup.dpr b/ICS_zlog/Delphi/Internet/NsLookup.dpr new file mode 100644 index 00000000..914dbc80 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/NsLookup.dpr @@ -0,0 +1,12 @@ +program NsLookup; + +uses + Forms, + NsLook1 in 'NsLook1.pas' {NsLookupForm}; + +{$R *.RES} + +begin + Application.CreateForm(TNsLookupForm, NsLookupForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/POP3MIM1.dfm b/ICS_zlog/Delphi/Internet/POP3MIM1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..59ba349e7df8e9fc60092df738ff55addcf3c574 GIT binary patch literal 1391 zcmb7D%Tn7g6jf|uId)P4EuFTjte9cLz^9FiK z^mF)uu3J6q*a>X9(Mac>bI-lf)!zW5s=NKxvSemV`Ac2v@P$?B=_Fl}A1;2y7hV(Ab6%^hb;H4A9F!juOYI=2mZq)%r zr;lZ)&QbFVC36Owh$@1gqN`YBSU5msxjxH5Y~QnSpDkLPR!0QQls0)bHd=;TBwG%OO`GP9y}vyI4n6smccjAC<@(+ znW|lVxXSNCjkgu+*4f7Q{flHB+O2c7|GO8dDx#{?KDOI>m1{Jx4CDBED~$$QHm+Uv Rx55gufA*u9y)!jS{{YX?xBvhE literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/PingTst1.dfm b/ICS_zlog/Delphi/Internet/PingTst1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..d784109eb8b6dc9d5bfac6057e8609bab1f1a2e3 GIT binary patch literal 930 zcmY+BO>Wab6vwA_;>nkrfCOTLlvULYZc~W}Sdlt0sYsfr9#nQPv0s}}Co{n_Aq^5Y z-~#Meas^JoEf5z#Vh6FEI?iVFKIZ>_?>FgtxMicY`bS0M&E(iQn3y%g+^Q6#@JEf5VjqBZ>*LgD_@7#Xp!taqv+D$aI zfL}5Z$|ZqYT}>M4bmLDs$zWke?T0Xv)h<(WPFHc9r$5|${*UbQzao3U z1SrSX(R!NNv+`QB9cpY@YAzK4@I1}mU7AitW2JY?85KTAE4U}d-(|& zSqxi@j~4EPVFXH9CY=NYpM3)3876E7a-q#{b(4^R@v`V~daVp(k3=t+$_x0g0Htvw samZDwcl|kE;r(29o!3XAE7U;Bo5j2<1>pNhf2Wo{@T25A-y($m12-BTJ^%m! literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/PingTst1.pas b/ICS_zlog/Delphi/Internet/PingTst1.pas new file mode 100644 index 00000000..c1da3261 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/PingTst1.pas @@ -0,0 +1,154 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: This demo show how to use the TPing object to ping any host. +Creation: November 30, 1997 +Version: 1.03 +EMail: francois.piette@overbyte.be http://www.overbyte.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 1997-2002 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + + +Updates: +Dec 13, 1997 V1.01 Use the new OnEchoRequest and OnEchoReply events. +Dec 26, 1998 V1.02 Changed event handler for new TPing version (1.10) +Nov 10, 2002 V1.03 Added Reply.Status in display when failed + Changed argument name from Error to Status in EchoReply + event (same change has in component). + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit PingTst1; + +interface + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + Ping, StdCtrls; + +type + TPingTstForm = class(TForm) + Ping1: TPing; + Label1: TLabel; + HostEdit: TEdit; + PingButton: TButton; + DisplayMemo: TMemo; + CancelButton: TButton; + procedure PingButtonClick(Sender: TObject); + procedure Ping1Display(Sender: TObject; Icmp: TObject; Msg: String); + procedure Ping1DnsLookupDone(Sender: TObject; Error: Word); + procedure CancelButtonClick(Sender: TObject); + procedure Ping1EchoRequest(Sender: TObject; Icmp: TObject); + procedure Ping1EchoReply(Sender: TObject; Icmp: TObject; Status: Integer); + end; + +var + PingTstForm: TPingTstForm; + +implementation + +{$R *.DFM} + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPingTstForm.PingButtonClick(Sender: TObject); +begin + DisplayMemo.Clear; + DisplayMemo.Lines.Add('Resolving host ''' + HostEdit.Text + ''''); + PingButton.Enabled := FALSE; + CancelButton.Enabled := TRUE; + Ping1.DnsLookup(HostEdit.Text); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPingTstForm.Ping1DnsLookupDone(Sender: TObject; Error: Word); +begin + CancelButton.Enabled := FALSE; + PingButton.Enabled := TRUE; + + if Error <> 0 then begin + DisplayMemo.Lines.Add('Unknown Host ''' + HostEdit.Text + ''''); + Exit; + end; + + DisplayMemo.Lines.Add('Host ''' + HostEdit.Text + ''' is ' + Ping1.DnsResult); + Ping1.Address := Ping1.DnsResult; + Ping1.Ping; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPingTstForm.Ping1Display(Sender: TObject; Icmp: TObject; Msg: String); +begin + DisplayMemo.Lines.Add(Msg); +end; + + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPingTstForm.CancelButtonClick(Sender: TObject); +begin + Ping1.CancelDnsLookup; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPingTstForm.Ping1EchoRequest(Sender: TObject; Icmp: TObject); +begin + DisplayMemo.Lines.Add('Sending ' + IntToStr(Ping1.Size) + ' bytes to ' + + Ping1.HostName + ' (' + Ping1.HostIP + ')'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPingTstForm.Ping1EchoReply( + Sender : TObject; + Icmp : TObject; + Status : Integer); +begin + if Status <> 0 then + { Success } + DisplayMemo.Lines.Add('Received ' + IntToStr(Ping1.Reply.DataSize) + + ' bytes from ' + Ping1.HostIP + + ' in ' + IntToStr(Ping1.Reply.RTT) + ' msecs') + else + { Failure } + DisplayMemo.Lines.Add('Cannot ping host (' + Ping1.HostIP + ') : ' + + Ping1.ErrorString + + '. Status = ' + IntToStr(Ping1.Reply.Status)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/Pop3Mim1.pas b/ICS_zlog/Delphi/Internet/Pop3Mim1.pas new file mode 100644 index 00000000..4bdec5c9 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/Pop3Mim1.pas @@ -0,0 +1,283 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Object: This program is a demo for TMimeDecode component. + TMimeDecode is a component whose job is to decode MIME encoded + EMail messages (file attach). You can use it for example to + decode messages received with a POP3 component. + MIME is described in RFC-1521. headers are described if RFC-822. +Creation: March 08, 1998 +Version: 1.01 +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +Updates: +Apr 22, 1998 V1.01 Added an option box to save the parts in files. The files + are writen in the current directory with a name like Part0.dat, + Part1.dat and so on. + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit Pop3Mim1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, ExtCtrls, IniFiles, MimeDec; + +type + TMimeDecodeForm = class(TForm) + Panel1: TPanel; + FileEdit: TEdit; + DecodeButton: TButton; + Memo1: TMemo; + MimeDecode1: TMimeDecode; + Label1: TLabel; + ClearButton: TButton; + SaveToFileCheckBox: TCheckBox; + procedure DecodeButtonClick(Sender: TObject); + procedure MimeDecode1PartBegin(Sender: TObject); + procedure MimeDecode1PartEnd(Sender: TObject); + procedure MimeDecode1PartHeaderLine(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure ClearButtonClick(Sender: TObject); + procedure MimeDecode1HeaderLine(Sender: TObject); + procedure MimeDecode1PartLine(Sender: TObject; Data: PChar; + DataLen: Integer); + procedure MimeDecode1HeaderBegin(Sender: TObject); + procedure MimeDecode1HeaderEnd(Sender: TObject); + procedure MimeDecode1PartHeaderBegin(Sender: TObject); + procedure MimeDecode1PartHeaderEnd(Sender: TObject); + private + FInitialized : Boolean; + FIniFileName : String; + FDstStream : TStream; + procedure Display(Msg: String); + end; + +var + MimeDecodeForm: TMimeDecodeForm; + +implementation + +{$R *.DFM} +const + SectionData = 'Data'; + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + KeyFile = 'FileName'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +function TrimRight(Str : String) : String; +var + i : Integer; +begin + i := Length(Str); + while (i > 0) and (Str[i] = ' ') do + i := i - 1; + Result := Copy(Str, 1, i); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TrimLeft(Str : String) : String; +var + i : Integer; +begin + if Str[1] <> ' ' then + Result := Str + else begin + i := 1; + while (i <= Length(Str)) and (Str[i] = ' ') do + i := i + 1; + Result := Copy(Str, i, Length(Str) - i + 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function Trim(Str : String) : String; +begin + Result := TrimLeft(TrimRight(Str)); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.FormCreate(Sender: TObject); +begin + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; + Memo1.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + IniFile := TIniFile.Create(FIniFileName); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, Top); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, Left); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + FileEdit.Text := IniFile.ReadString(SectionData, KeyFile, ''); + IniFile.Free; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.WriteString(SectionData, KeyFile, FileEdit.Text); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.DecodeButtonClick(Sender: TObject); +begin + Memo1.Clear; + MimeDecode1.DecodeFile(Trim(FileEdit.Text)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.Display(Msg: String); +begin + { TMemo cannot hold too much data. Limit to 200 lines } + if Memo1.Lines.count > 200 then + Memo1.Clear; + Memo1.Lines.Add(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1PartBegin(Sender: TObject); +begin + Display('--------- PART ' + + IntToStr(MimeDecode1.PartNumber) + + ' BEGIN ----------'); + if SaveToFileCheckBox.Checked then + FDstStream := TFileStream.Create('Part' + IntToStr(MimeDecode1.PartNumber) + '.dat', fmCreate ); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1PartEnd(Sender: TObject); +begin + Display('--------- PART END ----------'); + if FDstStream <> nil then begin + FDstStream.Destroy; + FDstStream := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1PartLine(Sender: TObject; Data: PChar; + DataLen: Integer); +begin + Display(StrPas(Data)); + if (FDstStream <> nil) and (DataLen > 0) then + FDstStream.WriteBuffer(Data^, DataLen); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1PartHeaderLine(Sender: TObject); +begin + Display('Part header: ' + StrPas(MimeDecode1.CurrentData)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.ClearButtonClick(Sender: TObject); +begin + Memo1.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1HeaderLine(Sender: TObject); +begin + Display('Msg header: ' + StrPas(MimeDecode1.CurrentData)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1HeaderBegin(Sender: TObject); +begin + Display('--------- HEADER BEGIN ----------'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1HeaderEnd(Sender: TObject); +begin + Display('--------- HEADER END ----------'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1PartHeaderBegin(Sender: TObject); +begin + Display('--------- PART ' + + IntToStr(MimeDecode1.PartNumber) + + ' HEADER BEGIN ----------'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMimeDecodeForm.MimeDecode1PartHeaderEnd(Sender: TObject); +begin + Display('--------- PART HEADER END ----------'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/Pop3Mime.dpr b/ICS_zlog/Delphi/Internet/Pop3Mime.dpr new file mode 100644 index 00000000..dcba48ff --- /dev/null +++ b/ICS_zlog/Delphi/Internet/Pop3Mime.dpr @@ -0,0 +1,12 @@ +program Pop3Mime; + +uses + Forms, + Pop3Mim1 in 'POP3MIM1.PAS' {MimeDecodeForm}; + +{$R *.RES} + +begin + Application.CreateForm(TMimeDecodeForm, MimeDecodeForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/PopTst1.dfm b/ICS_zlog/Delphi/Internet/PopTst1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..d5a15187794d0e49970e45c34efe12bf420bedf4 GIT binary patch literal 4105 zcma)9%W~sH6qP0G=~o_;0d``Of+;GMnJ}}USdch2c2yi3Td4##&?9$j)hLonYEKfr zV7B}LOO|}bY^Y+%C(ME^TcBU+mSm4J8&|tq=bYQ;-rFtx=P2H2I6CTFwL9Z>|A)@F zI~)&`!>zwt3SQ|R?y}`OA0~eAGfcX1aA@8BEb!yHbrF z3}$nr-B-*uSfC(|j21z=9Rb(daTq72?T05Q>H;6uyK#gL+H;Vk5SgvhPWSlY%=@w3 zJ04Fup2JotrtXKAK{SnTJ$Q#|bb;xq|Jd~3Ik5?)|BQj zoVF7P5F92`nAr7U)DGhmez%0lz1bw2mH#cgNS`$^2VS7##wfUhVLF0IKl115PYwx% z2hmV;Zvb!N+G&t3LU2#U)F_qt^ozoM8VR5NP^!HkLdNIbJV;%DCERo#-@0fHUErhO zb%5^O+W^h!%sft!ejEm~$h1J%4g(mW4|mVRj)%a1^Uc6X?hZ)xs@&2mIq$aG^iCt zF}x9oU}(_ar#aWuRnxGK%mf{Txc(#$p*aIDVQBZG>zIxhlS}GUy<_&PU+^kb8=^=h zKyVlo&qJ{&!4@ZYzJ`ESc@HP3MDUEY%I~xU)QsWTDuZ>A!h{rXiQuR}@EH%`U=6_t zr0H#(OiKh`GJ;<#g*`l3B`^l*?0k7sf|MEoNa2LMLqSzCewDvhlmW5%GHV^z)=1zf;&MCNQFF}BG z^24&N{l)gW;40r|Djy3K^~GUr5KlokhUqdys$%sc1e4bw)ZS@!KgBu-SH3MbvxN@@ ze`PGFC}euCfUNYZ~?H{f(;c6Npr4N)^dfQo$EdijMJxBE45x zv275t2*|}Ksnrr%I|as)oI@6KS{l#u2C*uENTDqu)RJ5!mHH_RA%b}wo}&#q1_Mc@ zZK1TC=PPMB=W)EqEAjJZgHn}1q|T1eX-TfK${8s7)?=l+Nrgb9%C1zATqTtnK6_y? zJrBz06eD#W37xGRTS>^qFAsUo_-;0IJ2_#cNKJ?|1rwLxryg!~dU>uidv->xYj&MC z`(eJ>7sXKDJb1lS#~31Gt&3P&WPxqF$ z*&)kq-=snyQsuE!kz8e!b9@iwlgl03prY>+jCl&L0lxZkudyFVJ;_?qtA7hi2blKu z!5o$a>R1`lavw~W8DOXrQ37n!RHE$Fzjxa5L!*}FR^T15S zpDy^;H|#L>K}bGLszlJJ;v5`_ms!K?j`|(X>sZ-UYN*$XDtXy5*(;an1vhZGL~6^* z+CWwKtEj5j!-#)PncGsIPc?_p0H!IJ!4o(OBJ;6)B0rD6^7!9QG&LWsJcMT(;t|q^ z=HALPWV$wt=pjzEcI6{t5(i7hL?st2pK{nD<=-iSIXP{GGP#(< + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: +Nov 12, 1997 V1.01 Added a GetAll button to get all messages waiting in the + POP3 server, copying them to a file using the UIDL to build + the file name (sorry, wont work with D1 because of long file + name). The message is *NOT* deleted from the POP3 server. +Jan 10, 1998 V1.02 Added port selection + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit PopTst1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, WSocket, pop3cli, StdCtrls, Wait, IniFiles, ExtCtrls; + +const + PopTstVersion = 102; + +type + TPOP3ExcercizerForm = class(TForm) + Pop3Client: TPop3Client; + DisplayMemo: TMemo; + Panel1: TPanel; + InfoLabel: TLabel; + Label1: TLabel; + Label2: TLabel; + Label3: TLabel; + Label4: TLabel; + Label5: TLabel; + ConnectButton: TButton; + Wait1: TWait; + DisconnectButton: TButton; + UserButton: TButton; + HostEdit: TEdit; + UserNameEdit: TEdit; + PassWordEdit: TEdit; + PassButton: TButton; + MsgNumEdit: TEdit; + RetrButton: TButton; + StatButton: TButton; + ListAllButton: TButton; + ListButton: TButton; + DeleteButton: TButton; + NoopButton: TButton; + LastButton: TButton; + ResetButton: TButton; + TopButton: TButton; + MsgLinesEdit: TEdit; + RpopButton: TButton; + UidlButton: TButton; + ApopButton: TButton; + NextButton: TButton; + GetAllButton: TButton; + PortEdit: TEdit; + Label6: TLabel; + procedure ConnectButtonClick(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure DisconnectButtonClick(Sender: TObject); + procedure UserButtonClick(Sender: TObject); + procedure PassButtonClick(Sender: TObject); + procedure Pop3ClientMessageBegin(Sender: TObject); + procedure Pop3ClientMessageEnd(Sender: TObject); + procedure Pop3ClientMessageLine(Sender: TObject); + procedure RetrButtonClick(Sender: TObject); + procedure StatButtonClick(Sender: TObject); + procedure ListAllButtonClick(Sender: TObject); + procedure ListButtonClick(Sender: TObject); + procedure Pop3ClientListBegin(Sender: TObject); + procedure Pop3ClientListEnd(Sender: TObject); + procedure Pop3ClientListLine(Sender: TObject); + procedure DeleteButtonClick(Sender: TObject); + procedure NoopButtonClick(Sender: TObject); + procedure LastButtonClick(Sender: TObject); + procedure ResetButtonClick(Sender: TObject); + procedure TopButtonClick(Sender: TObject); + procedure RpopButtonClick(Sender: TObject); + procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); + procedure Pop3ClientDisplay(Sender: TObject; Msg: String); + procedure UidlButtonClick(Sender: TObject); + procedure Pop3ClientUidlBegin(Sender: TObject); + procedure Pop3ClientUidlEnd(Sender: TObject); + procedure Pop3ClientUidlLine(Sender: TObject); + procedure ApopButtonClick(Sender: TObject); + procedure NextButtonClick(Sender: TObject); + procedure GetAllButtonClick(Sender: TObject); + private + FFile : TextFile; + FFileName : String; + function DoTheJob(MethodPtr : TPop3Method; MethodName : String) : Boolean; + procedure MessageBegin(Sender: TObject); + procedure MessageLine(Sender: TObject); + procedure GetAllMessageLine(Sender: TObject); + public + { Déclarations publiques } + end; + +var + POP3ExcercizerForm: TPOP3ExcercizerForm; + +implementation + +{$R *.DFM} + +uses + PopTst2; + +const + IniFileName = 'POPTST.INI'; + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Restore some data from the INI file } +procedure TPOP3ExcercizerForm.FormCreate(Sender: TObject); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(IniFileName); + HostEdit.Text := IniFile.ReadString('Data', 'Host', ''); + PortEdit.Text := IniFile.ReadString('Data', 'Port', ''); + UserNameEdit.Text := IniFile.ReadString('Data', 'UserName', ''); + PassWordEdit.Text := IniFile.ReadString('Data', 'Password', ''); + IniFile.Free; + InfoLabel.Caption := ''; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Save data to INI file } +procedure TPOP3ExcercizerForm.FormCloseQuery(Sender: TObject; + var CanClose: Boolean); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(IniFileName); + IniFile.WriteString('Data', 'Host', HostEdit.Text); + IniFile.WriteString('Data', 'Port', PortEdit.Text); + IniFile.WriteString('Data', 'UserName', UserNameEdit.Text); + IniFile.WriteString('Data', 'Password', PassWordEdit.Text); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when the TPop3Client object wants to display } +{ some information such as connection progress or errors. } +procedure TPOP3ExcercizerForm.Pop3ClientDisplay(Sender: TObject; + Msg: String); +begin + DisplayMemo.Lines.Add(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ All the TPop3Client method are of the same type. To simplify this demo } +{ application, DoTheJob transfert the parameters form the various EditBoxes } +{ to the Pop3Client instance and then call the appropriate method, showing } +{ the result in the InfoLabel.Caption. } +function TPOP3ExcercizerForm.DoTheJob( + MethodPtr : TPop3Method; + MethodName : String) : Boolean; +begin + Pop3Client.Host := HostEdit.Text; + Pop3Client.Port := PortEdit.Text; + Pop3Client.UserName := UserNameEdit.Text; + Pop3Client.PassWord := PassWordEdit.Text; + Pop3Client.MsgNum := StrToInt(MsgNumEdit.Text); + Pop3Client.MsgLines := StrToInt(MsgLinesEdit.Text); + InfoLabel.Caption := MethodName + ' started'; + Result := MethodPtr; + if Result then + InfoLabel.Caption := MethodName + ' ok' + else + InfoLabel.Caption := MethodName + ' failed'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.ConnectButtonClick(Sender: TObject); +begin + DoTheJob(Pop3Client.Connect, 'Connect'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.DisconnectButtonClick(Sender: TObject); +begin + DoTheJob(Pop3Client.Quit, 'Quit'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.UserButtonClick(Sender: TObject); +begin + DoTheJob(Pop3Client.User, 'User'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.PassButtonClick(Sender: TObject); +begin + DoTheJob(Pop3Client.Pass, 'Pass'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.RetrButtonClick(Sender: TObject); +begin + DoTheJob(Pop3Client.Retr, 'Retr'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.StatButtonClick(Sender: TObject); +begin + if DoTheJob(Pop3Client.Stat, 'Stat') then + InfoLabel.Caption := 'Stat ok, ' + + IntToStr(Pop3Client.MsgCount) + ' messages ' + + IntToStr(Pop3Client.MsgSize) + ' bytes' +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.ListAllButtonClick(Sender: TObject); +begin + MsgNumEdit.Text := '0'; + DoTheJob(Pop3Client.List, 'List All'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.ListButtonClick(Sender: TObject); +begin + DoTheJob(Pop3Client.List, 'List'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.DeleteButtonClick(Sender: TObject); +begin + DoTheJob(Pop3Client.Dele, 'Delete'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.NoopButtonClick(Sender: TObject); +begin + DoTheJob(Pop3Client.Noop, 'Noop'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.LastButtonClick(Sender: TObject); +begin + if DoTheJob(Pop3Client.Last, 'Last') then + InfoLabel.caption := 'Last = ' + IntToStr(Pop3Client.MsgNum); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.ResetButtonClick(Sender: TObject); +begin + DoTheJob(Pop3Client.Rset, 'Rset'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.TopButtonClick(Sender: TObject); +begin + DoTheJob(Pop3Client.Top, 'Top'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.RpopButtonClick(Sender: TObject); +begin + DoTheJob(Pop3Client.Rpop, 'Rpop'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.UidlButtonClick(Sender: TObject); +begin + DoTheJob(Pop3Client.Uidl, 'Uidl'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.ApopButtonClick(Sender: TObject); +begin + DoTheJob(Pop3Client.Apop, 'Apop'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when TPop3Client is about to receive a } +{ message. The MsgNum property gives the message number. } +{ This event handler could be used to open the file used to store the msg. } +{ The file handle could be stored in the TPop3Client.Tag property to be } +{ easily retrieved by the OnMessageLine and OnMessageEnd event handlers. } +procedure TPOP3ExcercizerForm.Pop3ClientMessageBegin(Sender: TObject); +begin + DisplayMemo.Lines.Add('*** Message ' + + IntToStr((Sender as TPop3Client).MsgNum) + + ' begin ***'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when TPop3Client has detected the end of a } +{ message, even if there is an error or exception, this event gets called. } +{ This event handler could be used to close the file used to store the msg. } +procedure TPOP3ExcercizerForm.Pop3ClientMessageEnd(Sender: TObject); +begin + DisplayMemo.Lines.Add('*** Message ' + + IntToStr((Sender as TPop3Client).MsgNum) + + ' end ***'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called for each message line that TPop3Client is } +{ receiveing. This could be used to write the message lines to a file. } +procedure TPOP3ExcercizerForm.Pop3ClientMessageLine(Sender: TObject); +begin + DisplayMemo.Lines.Add((Sender as TPop3Client).LastResponse); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when TPop3Client is about to receive a } +{ list line. The MsgNum property gives the message number. } +procedure TPOP3ExcercizerForm.Pop3ClientListBegin(Sender: TObject); +begin + DisplayMemo.Lines.Add('*** List begin ***'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when TPop3Client has received the last list } +{ line. } +procedure TPOP3ExcercizerForm.Pop3ClientListEnd(Sender: TObject); +begin + DisplayMemo.Lines.Add('*** List End ***'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called for each list line received by TPop3Client. } +procedure TPOP3ExcercizerForm.Pop3ClientListLine(Sender: TObject); +var + Buffer : String; +begin + Buffer := 'MsgNum = ' + IntToStr((Sender as TPop3Client).MsgNum) + ' ' + + 'MsgSize = ' + IntToStr((Sender as TPop3Client).MsgSize) + ' ' + + 'Line = ''' + (Sender as TPop3Client).LastResponse + ''''; + DisplayMemo.Lines.Add(Buffer); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.Pop3ClientUidlBegin(Sender: TObject); +begin + DisplayMemo.Lines.Add('*** Uidl begin ***'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.Pop3ClientUidlEnd(Sender: TObject); +begin + DisplayMemo.Lines.Add('*** Uidl end ***'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.Pop3ClientUidlLine(Sender: TObject); +var + Buffer : String; +begin + Buffer := 'MsgNum = ' + IntToStr((Sender as TPop3Client).MsgNum) + ' ' + + 'MsgUidl = ' + (Sender as TPop3Client).MsgUidl + ''''; + DisplayMemo.Lines.Add(Buffer); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.MessageBegin(Sender: TObject); +begin + MessageForm.Caption := 'Message ' + + IntToStr((Sender as TPop3Client).MsgNum); + MessageForm.Show; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.MessageLine(Sender: TObject); +begin + MessageForm.DisplayMemo.Lines.Add((Sender as TPop3Client).LastResponse); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.NextButtonClick(Sender: TObject); +var + OldBegin : TNotifyEvent; + OldEnd : TNotifyEvent; + OldLine : TNotifyEvent; +begin + OldBegin := Pop3Client.OnMessageBegin; + OldEnd := Pop3Client.OnMessageEnd; + OldLine := Pop3Client.OnMessageLine; + + Pop3Client.OnMessageBegin := MessageBegin; + Pop3Client.OnMessageEnd := nil; + Pop3Client.OnMessageLine := MessageLine; + + MessageForm.DisplayMemo.Clear; + MessageForm.Caption := 'Message'; + + DoTheJob(Pop3Client.Retr, 'Retr'); + + if (Length(Pop3Client.LastResponse) > 0) and + (Pop3Client.LastResponse[1] = '-') then + MessageForm.DisplayMemo.Lines.Add(Pop3Client.LastResponse) + else + MsgNumEdit.Text := IntToStr(StrToInt(MsgNumEdit.Text) + 1); + + MessageForm.DisplayMemo.SelStart := 0; + MessageForm.DisplayMemo.SelLength := 0; + + Pop3Client.OnMessageBegin := OldBegin; + Pop3Client.OnMessageEnd := OldEnd; + Pop3Client.OnMessageLine := OldLine; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.GetAllMessageLine(Sender: TObject); +begin + Writeln(FFile, (Sender as TPop3Client).LastResponse); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TPOP3ExcercizerForm.GetAllButtonClick(Sender: TObject); +var + MsgCnt : Integer; + MsgNum : Integer; + Uidl : String; + OldBegin : TNotifyEvent; + OldEnd : TNotifyEvent; + OldLine : TNotifyEvent; + IniFile : TIniFile; + Path : String; +begin + if not DoTheJob(Pop3Client.Stat, 'Stat') then + Exit; + + InfoLabel.Caption := 'Stat ok, ' + + IntToStr(Pop3Client.MsgCount) + ' messages ' + + IntToStr(Pop3Client.MsgSize) + ' bytes'; + if Pop3Client.MsgCount < 1 then + Exit; + + { Get path from INI file } + IniFile := TIniFile.Create(IniFileName); + Path := IniFile.ReadString('Data', 'MsgPath', + ExtractFilePath(Application.ExeName)); + IniFile.Free; + + { Be sure to have an ending backslash } + if (Length(Path) > 0) and (Path[Length(Path)] <> '\') then + Path := Path + '\'; + + OldBegin := Pop3Client.OnMessageBegin; + OldEnd := Pop3Client.OnMessageEnd; + OldLine := Pop3Client.OnMessageLine; + Pop3Client.OnMessageBegin := nil; + Pop3Client.OnMessageEnd := nil; + Pop3Client.OnMessageLine := GetAllMessageLine; + + try + MsgCnt := Pop3Client.MsgCount; + for MsgNum := 1 to MsgCnt do begin + Pop3Client.MsgNum := MsgNum; + if not Pop3Client.Uidl then + continue; + Uidl := Pop3Client.MsgUidl; + FFileName := Path + 'Msg ' + Uidl + '.txt'; + if FileExists(FFileName) then begin + DisplayMemo.Lines.Add('Message ' + IntToStr(MsgNum) + ' already here'); + continue; + end; + + DisplayMemo.Lines.Add('Message ' + IntToStr(Pop3Client.MsgNum)); + AssignFile(FFile, FFileName); + Rewrite(FFile); + try + Pop3Client.Retr; + finally + CloseFile(FFile); + end; + end; + DoTheJob(Pop3Client.Quit, 'Quit'); + finally + Pop3Client.OnMessageBegin := OldBegin; + Pop3Client.OnMessageEnd := OldEnd; + Pop3Client.OnMessageLine := OldLine; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/Recv.dpr b/ICS_zlog/Delphi/Internet/Recv.dpr new file mode 100644 index 00000000..1f6c0d41 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/Recv.dpr @@ -0,0 +1,12 @@ +program Recv; + +uses + Forms, + Recv1 in 'Recv1.pas' {RecvForm}; + +{$R *.RES} + +begin + Application.CreateForm(TRecvForm, RecvForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/Recv1.dfm b/ICS_zlog/Delphi/Internet/Recv1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..5b79e5e5120f12200cf68bf33be5f936284a1f97 GIT binary patch literal 1702 zcmZ`(%WmT~6s06vlwUz+G6Aym%4iqk#A#>IVm6KwqXq29h=gX-MHz{Th)|?K(Q)z} zGs`afAN`5`O4ltPlI0{V49L7B&pDUp^75Z9h;OcDzs$p%B{)0$;sX$`=4YMw1}Bem zE{dQYv=%s%-p27_zV^O#+P5T?x%Y?T|AfhXF1?-uXJ{=6XZ}QCFnPpc_;Hv^x&HC= zbi3V-h0Kca9X`$01WSoe2}|+Q=3$)6qC4kIj%S>50s9HPRZDyu<0siO3s%DYyJMnj zRA7IwjD`_nGmMbiNW=Zb;217QZyu?t!MPY`4ni3dE3>8w% znQ)onkTHiluK@4lRp&R2l6Kc0RXOT*z10b6cmisgv8U zz{9s-D|HS)JHASZ3^bP>*b{tXv}^ds8h*T&b4%Ocx4!@Ge4_2l5xd9mpr)}g05HDT zNXc1$n&`V>1FP}t3ysN6V|PA(6iFl`yu=yWP}yn39aB@1JivGRyfdn%8qEV!>nWvs zs@_*yocd^=-pY1I1~*i|M$z3V9=&9(G&}Ju$H~J5e>zwY<%Fn1TaOc4k5*NWA8OTi zyTihf#Wj*10DG(#h_U}+{ZO$^-?I7^){wRudk&Q#Uh))&`(^R|vIfQ{Z6JwHg zH!!&`NTGTQ00%&w>=jFWchEJPu9BPwcBC7zy%Jn<-;>F@v)~D$(=-)6JR6&zozh+A zJ7iJ4>8XV4evF1!A9-4=^?1A^{@xo=PI&b=j2t{`k!;?D2*DL)w-IRGu z3d}ds{oIK#OXn2bm$1Jrb#Sd-Kty}$0P2E=OjQwfw`Cn_x72)%2VLz*xxkO=U2{Gi gnP|F^xyp|uNWTW~xYS#&`O9hBG9PTqd + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +History: +Oct 28, 1998 V1.01 Added Linger and Banner checkboxes. +Dec 30, 1998 V1.02 Remove trailing CR/LF on data receive. +Mar 07, 1999 V1.03 Adapted for Delphi 1 + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit Recv1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, WSocket, StdCtrls, ExtCtrls, IniFiles; + +const + WM_DESTROY_SOCKET = WM_USER + 1; + +type + TRecvForm = class(TForm) + Panel1: TPanel; + DisplayMemo: TMemo; + Label1: TLabel; + PortEdit: TEdit; + ActionButton: TButton; + WSocket1: TWSocket; + CloseAllButton: TButton; + Label2: TLabel; + LingerCheckBox: TCheckBox; + BannerCheckBox: TCheckBox; + LineModeOnButton: TButton; + LineOffButton: TButton; + procedure ActionButtonClick(Sender: TObject); + procedure PortEditChange(Sender: TObject); + procedure WSocket1SessionAvailable(Sender: TObject; Error: Word); + procedure FormCreate(Sender: TObject); + procedure FormDestroy(Sender: TObject); + procedure CloseAllButtonClick(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure LineModeOnButtonClick(Sender: TObject); + procedure LineOffButtonClick(Sender: TObject); + private + FIniFileName : String; + FInitialized : Boolean; + FClients : TList; + procedure ClientDataAvailable(Sender : TObject; Error : Word); + procedure ClientSessionClosed(Sender: TObject; Error: Word); + procedure Display(Msg : String); + procedure WMDestroySocket(var msg: TMessage); message WM_DESTROY_SOCKET; + end; + +var + RecvForm: TRecvForm; + +implementation + +{$R *.DFM} + +const + SectionWindow = 'RecvForm'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + SectionData = 'Data'; + KeyPort = 'Port'; + KeyLinger = 'Linger'; + KeyBanner = 'SendBanner'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TRecvForm.FormCreate(Sender: TObject); +begin + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; + FClients := TList.Create; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TRecvForm.FormDestroy(Sender: TObject); +begin + if Assigned(FClients) then begin + FClients.Destroy; + FClients := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TRecvForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + IniFile := TIniFile.Create(FIniFileName); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, + (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, + (Screen.Width - Width) div 2); + PortEdit.Text := IniFile.ReadString(SectionData, KeyPort, 'telnet'); + LingerCheckBox.Checked := Boolean(IniFile.ReadInteger(SectionData, KeyLinger, 0)); + BannerCheckBox.Checked := Boolean(IniFile.ReadInteger(SectionData, KeyBanner, 1)); + Label2.Caption := ''; + IniFile.Destroy; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TRecvForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.WriteString(SectionData, KeyPort, PortEdit.text); + IniFile.WriteInteger(SectionData, KeyLinger, Ord(LingerCheckBox.Checked)); + IniFile.WriteInteger(SectionData, KeyBanner, Ord(BannerCheckBox.Checked)); + IniFile.Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TRecvForm.Display(Msg : String); +begin + if DisplayMemo.Lines.Count > 200 then { Prevent TMemo overflow } + DisplayMemo.Clear; + DisplayMemo.Lines.Add(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TRecvForm.ActionButtonClick(Sender: TObject); +begin + if ActionButton.Caption = '&Start' then begin + WSocket1.Addr := '0.0.0.0'; + WSocket1.Port := PortEdit.Text; + WSocket1.Proto := 'tcp'; + WSocket1.Listen; + ActionButton.Caption := '&Stop'; + Display('Listening for clients'); + end + else begin + WSocket1.Close; + ActionButton.Caption := '&Start'; + Display('Not listening for clients'); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TRecvForm.PortEditChange(Sender: TObject); +begin + WSocket1.Close; + ActionButton.Caption := '&Start'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TRecvForm.WSocket1SessionAvailable(Sender: TObject; Error: Word); +var + NewClient : TWSocket; +begin + Display('Client connected'); + Label2.Caption := ''; + NewClient := TWSocket.Create(nil); + FClients.Add(NewClient); + NewClient.LineMode := TRUE; + NewClient.OnDataAvailable := ClientDataAvailable; + NewClient.OnSessionClosed := ClientSessionClosed; + NewClient.HSocket := WSocket1.Accept; + if LingerCheckBox.Checked then + NewClient.LingerOnOff := wsLingerOn + else + NewClient.LingerOnOff := wsLingerOff; + NewClient.LingerTimeout := 300; + NewClient.SetLingerOption; + if BannerCheckBox.Checked then + NewClient.SendStr('Hello !' + #13#10); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TRecvForm.ClientDataAvailable(Sender : TObject; Error : Word); +var + Buf : array [0..127] of char; + Len : Integer; +begin + Len := TWSocket(Sender).Receive(@Buf, Sizeof(Buf) - 1); + if Len <= 0 then + Exit; + { Remove any trailing CR/LF} + while (Len > 0) and (Buf[Len - 1] in [#13, #10]) do + Dec(Len); + { Nul terminate the data } + Buf[Len] := #0; + Display('DataAvailable: ''' + StrPas(@Buf) + ''''); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TRecvForm.ClientSessionClosed(Sender: TObject; Error: Word); +var + Cli : TWSocket; + Itm : Integer; +begin + Cli := Sender as TWSocket; + Display('Client diconnected'); + + Itm := FClients.IndexOf(Cli); + if Itm >= 0 then + FClients.Delete(Itm); + { We can't destroy a TWSocket from a SessionClosed event handler. } + { So we post a message to delay destruction until we are out of the } + { message handler. } + PostMessage(Handle, WM_DESTROY_SOCKET, 0, LongInt(Cli)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TRecvForm.WMDestroySocket(var msg: TMessage); +begin + TWSocket(msg.LParam).Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TRecvForm.CloseAllButtonClick(Sender: TObject); +begin + Display('Disconnecting clients'); + while FClients.Count > 0 do + TWSocket(FClients.Items[0]).Close; + Display('All clients disconnected'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TRecvForm.LineModeOnButtonClick(Sender: TObject); +var + I : Integer; +begin + for I := 0 to FClients.Count - 1 do + TWSocket(FClients.Items[0]).LineMode := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TRecvForm.LineOffButtonClick(Sender: TObject); +var + I : Integer; +begin + for I := 0 to FClients.Count - 1 do + TWSocket(FClients.Items[0]).LineMode := FALSE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/Sender.dpr b/ICS_zlog/Delphi/Internet/Sender.dpr new file mode 100644 index 00000000..39db7cbc --- /dev/null +++ b/ICS_zlog/Delphi/Internet/Sender.dpr @@ -0,0 +1,12 @@ +program Sender; + +uses + Forms, + Sender1 in 'Sender1.pas' {SenderForm}; + +{$R *.RES} + +begin + Application.CreateForm(TSenderForm, SenderForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/Sender1.dfm b/ICS_zlog/Delphi/Internet/Sender1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..72bb582dfb2ca07b6cdbd3dc28c7ae9224574840 GIT binary patch literal 2588 zcmb7GO>g5w7@pXT$8nO~F5QYfAQ6dWwMbBR3+v*RE^ZstB-3eOYpnDwmVnkRk#$|r4@iD(G za2s@I`3)}E43}S#bng8Cr({@AhM|C$3$+ZzQHc@9P$0#bTDPX;2s2*NTPVVo3$qEP zB%af27|Jubili_jsSAQ+h6pYK^?j&P_f+PdP5h}%+#59qMSekG6BWXmFhOV2QrPDK z!7@Q-f<=8BmQecVb+monyT(1QTQ{$~!sQ0~V{QLyEyBY0?!tFwwB#G$Pjmtu75b?O z{q`2@5#neA`>76`HP&>$cNZMIz)NBN2KlK&(T03M_y}yO4X)<(B09wg# zj?>HM^rkZucdgxM*MHTVfpKkMIUlrC=Pxkfu*;Dg5MQqt&(CkGZf;4ooX{0>4hQPq z&C^TxpdM>jh$8@C@_fZPC7nSkhl$>39e-)ZjZxl5R>yu7E_f1iRB{)~cd_bxCYEUu z-F42x57#~Xpo-&ocZ`P)TK918C}+z8-O6gMTltHoerT-x#!|n5l^sLcldMh&tTKGG zC8|l(m3Qx3h9!X*(Hm9%NlWV)Y3P4QyC+C{lvrLTE_C9y#NDWPdxlmF*9-nwOR@z& zw36xtS0ER$1;5K#epX-?dbh^A5%T_E#i?qUdf1oiVO{;JK5IUaKo>Qt@_e|#c&7mO z#Gt#t<$7EErXwC0@B22E^7pJF5rSSfY_YIG`++;G{1+T#2(WOhb_69E&v9Bvd)hwd2mXSh0DMFECwk?~9gvZ5kKog2B!;lbaLqa)Ju^ zXcQeYCDZeB7+o{Fl_e7A77rp>1~$Q0;+3QEY)|b(H_nAAd5YvPh5JliazfXS^>lru Ko8zTupZ@?9r6Pj> literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/Sender1.pas b/ICS_zlog/Delphi/Internet/Sender1.pas new file mode 100644 index 00000000..6a46f6ee --- /dev/null +++ b/ICS_zlog/Delphi/Internet/Sender1.pas @@ -0,0 +1,628 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: Simple client program which just send data to a server and display + all incomming data. +EMail: francois.piette@pophost.eunet.be francois.piette@rtfm.be + http://www.rtfm.be/fpiette +Creation: Oct 01, 1998 +Version: 1.03 +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +History: +Oct 28, 1998 V1.02 Trapped Connect exceptions. + Added AutoStartButton and associated logic. + Added LingerCheckBox and associated logic. +Mar 07, 1999 V1.03 Adapted for Delphi 1 + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit Sender1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, ExtCtrls, StdCtrls, IniFiles, WSocket; + +const + WM_AUTO_START = WM_USER + 1; + WM_CLOSE_REQUEST = WM_USER + 2; + +type +{$IFDEF VER80} + LParam = LongInt; +{$ENDIF} + TSenderForm = class(TForm) + Panel1: TPanel; + Label1: TLabel; + ServerEdit: TEdit; + Label2: TLabel; + PortEdit: TEdit; + Label3: TLabel; + DataEdit: TEdit; + Label4: TLabel; + RepeatEdit: TEdit; + ContCheckBox: TCheckBox; + ActionButton: TButton; + DisplayMemo: TMemo; + Label5: TLabel; + LengthEdit: TEdit; + WSocket1: TWSocket; + DisplayDataCheckBox: TCheckBox; + UseDataSentCheckBox: TCheckBox; + PauseButton: TButton; + CountLabel: TLabel; + AutoStartButton: TButton; + LingerCheckBox: TCheckBox; + procedure FormCreate(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure ContCheckBoxClick(Sender: TObject); + procedure WSocket1DnsLookupDone(Sender: TObject; Error: Word); + procedure WSocket1SessionConnected(Sender: TObject; Error: Word); + procedure ActionButtonClick(Sender: TObject); + procedure FormDestroy(Sender: TObject); + procedure WSocket1DataAvailable(Sender: TObject; Error: Word); + procedure WSocket1SessionClosed(Sender: TObject; Error: Word); + procedure DisplayDataCheckBoxClick(Sender: TObject); + procedure UseDataSentCheckBoxClick(Sender: TObject); + procedure PauseButtonClick(Sender: TObject); + procedure AutoStartButtonClick(Sender: TObject); + private + FIniFileName : String; + FInitialized : Boolean; + FDataBuf : PChar; + FDataBufSize : Integer; + FCount : Integer; + FFinalCount : Integer; + FSending : Boolean; + FDisplayData : Boolean; + FUseDataSent : Boolean; + FFinished : Boolean; + FPaused : Boolean; + FAutoStart : Integer; + procedure Display(Msg : String); + procedure DoSend; + procedure WSocket1DataSent(Sender: TObject; Error: Word); + procedure WSocket1NoDataSent(Sender: TObject; Error: Word); + procedure WMAutoStart(var msg: TMessage); message WM_AUTO_START; + procedure WMCloseRequest(var msg: TMessage); message WM_CLOSE_REQUEST; + public + { Déclarations publiques } + end; + +var + SenderForm: TSenderForm; + +implementation + +{$R *.DFM} + +const + SectionWindow = 'RecvForm'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + SectionData = 'Data'; + KeyPort = 'Port'; + KeyServer = 'Server'; + KeyData = 'Data'; + KeyRepeat = 'RepeatCount'; + KeyContinuous = 'ContinuousSend'; + KeyLength = 'DataLength'; + KeyUseDataSent = 'UseDataSent'; + KeyDisplay = 'Display'; + KeyLinger = 'Linger'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.FormCreate(Sender: TObject); +begin + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + IniFile := TIniFile.Create(FIniFileName); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, + (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, + (Screen.Width - Width) div 2); + PortEdit.Text := IniFile.ReadString(SectionData, KeyPort, 'telnet'); + ServerEdit.Text := IniFile.ReadString(SectionData, KeyServer, 'localhost'); + DataEdit.Text := IniFile.ReadString(SectionData, KeyData, 'The quick brown fox jumps over the lazy dog'); + RepeatEdit.Text := IniFile.ReadString(SectionData, KeyRepeat, ''); + LengthEdit.Text := IniFile.ReadString(SectionData, KeyLength, '60'); + ContCheckBox.Checked := Boolean(IniFile.ReadInteger(SectionData, KeyContinuous, 0)); + LingerCheckBox.Checked := Boolean(IniFile.ReadInteger(SectionData, KeyLinger, 1)); + DisplayDataCheckBox.Checked := Boolean(IniFile.ReadInteger(SectionData, KeyDisplay, 0)); + UseDataSentCheckBox.Checked := Boolean(IniFile.ReadInteger(SectionData, KeyUseDataSent, 1)); + IniFile.Destroy; + RepeatEdit.Enabled := not ContCheckBox.Checked; + CountLabel.Caption := ''; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.WriteString(SectionData, KeyPort, PortEdit.text); + IniFile.WriteString(SectionData, KeyServer, ServerEdit.text); + IniFile.WriteString(SectionData, KeyData, DataEdit.text); + IniFile.WriteString(SectionData, KeyRepeat, RepeatEdit.text); + IniFile.WriteString(SectionData, KeyLength, LengthEdit.text); + IniFile.WriteInteger(SectionData, KeyContinuous, Ord(ContCheckBox.Checked)); + IniFile.WriteInteger(SectionData, KeyLinger, Ord(LingerCheckBox.Checked)); + IniFile.WriteInteger(SectionData, KeyUseDataSent, Ord(UseDataSentCheckBox.Checked)); + IniFile.WriteInteger(SectionData, KeyDisplay, Ord(DisplayDataCheckBox.Checked)); + IniFile.Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.FormDestroy(Sender: TObject); +begin + if FDataBuf <> nil then begin + Freemem(FDataBuf, FDataBufSize); + FDataBuf := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.ContCheckBoxClick(Sender: TObject); +begin + RepeatEdit.Enabled := not ContCheckBox.Checked; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.Display(Msg : String); +begin + if DisplayMemo.lines.Count > 200 then + DisplayMemo.Clear; + DisplayMemo.Lines.Add(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +function TrimRight(Str : String) : String; +var + i : Integer; +begin + i := Length(Str); + while (i > 0) and (Str[i] = ' ') do + i := i - 1; + Result := Copy(Str, 1, i); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TrimLeft(Str : String) : String; +var + i : Integer; +begin + if Str[1] <> ' ' then + Result := Str + else begin + i := 1; + while (i <= Length(Str)) and (Str[i] = ' ') do + i := i + 1; + Result := Copy(Str, i, Length(Str) - i + 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function Trim(Str : String) : String; +begin + Result := TrimLeft(TrimRight(Str)); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.ActionButtonClick(Sender: TObject); +var + Len : Integer; + N : Integer; + T : Integer; + Buf : String; +begin + { The ActionButton is used to start or stop data transmission } + if FSending then begin + { We are already sending, so user wants to stop } + { Display updated counter } + CountLabel.Caption := IntToStr(FCount); + + { Check if some data remains in TWSocket's internal buffer } + if (not WSocket1.AllSent) and + (Application.MessageBox('Data is still being sent' + #10 + + 'Close anyway ?', + 'Warning', MB_YESNO) <> IDYES) then + Exit; + + Display('Stop requested'); + if not WSocket1.AllSent then + Display('Not all data has been sent'); + + FAutoStart := 0; + { Close the socket. This will delete any data not already sent to } + { winsock. } + PostMessage(Handle, WM_CLOSE_REQUEST, 0, LParam(WSocket1)); + + Exit; + end; + + { The user wants to start data transmission } + CountLabel.Caption := ''; + PauseButton.Caption := '&Pause'; + PauseButton.Visible := TRUE; + ActionButton.Caption := '&Stop'; + FPaused := FALSE; + FSending := TRUE; + FFinished := FALSE; + FCount := 0; + + { Setup final count } + if ContCheckBox.Checked then + FFinalCount := 0 + else + FFinalCount := StrToInt(Trim(RepeatEdit.Text)); + + { Check which method use to send more data } + { Using OnDataSent event will prevent internal TWSocket buffer to be } + { enlarged without limit. } + FUseDataSent := UseDataSentCheckBox.Checked; + if FUseDataSent then + WSocket1.OnDataSent := WSocket1DataSent + else + WSocket1.OnDataSent := WSocket1NoDataSent; + + { Prepare data to be sent } + Buf := '0000 ' + DataEdit.Text; + Len := StrToInt(Trim(LengthEdit.Text)); + if Len <= 0 then + Len := Length(Buf); + if FDataBuf <> nil then + Freemem(FDataBuf, FDataBufSize); + FDataBufSize := Len + 3; + GetMem(FDataBuf, FDataBufSize); + if Len > 0 then begin + if Len < Length(Buf) then + Move(Buf[1], FDataBuf[0], Len) + else begin + T := 0; + while T < Len do begin + N := Length(Buf); + if (T + N) > Len then + N := Len - T; + if N > 0 then + Move(Buf[1], FDataBuf[T], N); + T := T + N; + end; + end; + end; + FDataBuf[Len] := #13; + FDataBuf[Len + 1] := #10; + FDataBuf[Len + 2] := #0; + + { Launch DNS lookup. When done, we'll try to connect. } + WSocket1.DnsLookup(Trim(ServerEdit.Text)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ We comes here when DNS lookup is finished, even in case of failure. } +procedure TSenderForm.WSocket1DnsLookupDone(Sender: TObject; Error: Word); +begin + { If any error occured, we just display info and prepare to restart. } + if Error <> 0 then begin + MessageBeep(MB_OK); + Display('DNS failure. Error #' + IntToStr(Error)); + ActionButton.Caption := '&Start'; + PauseButton.Visible := FALSE; + Exit; + end; + + { Now we know the IP address. Try to connect. } + WSocket1.Addr := WSocket1.DnsResult; + WSocket1.Port := Trim(PortEdit.Text); + WSocket1.Proto := 'tcp'; + try + WSocket1.Connect; + except + on E:Exception do begin + MessageBeep(MB_OK); + Display('Connect failed: ' + E.Message); + ActionButton.Caption := '&Start'; + PauseButton.Visible := FALSE; + FAutoStart := 0; + Exit; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.WSocket1SessionConnected(Sender: TObject; + Error: Word); +begin + if Error <> 0 then begin + MessageBeep(MB_OK); + Display('Can''t connect. Error #' + IntToStr(Error)); + ActionButton.Caption := '&Start'; + FAutoStart := 0; + Exit; + end; + Display('Connected'); + if LingerCheckBox.Checked then + WSocket1.LingerOnOff := wsLingerOn + else + WSocket1.LingerOnOff := wsLingerOff; + WSocket1.LingerTimeout := 300; + WSocket1.SetLingerOption; + DoSend; + if FUseDataSent then + Exit; + + { User requested to not use OnDataSent event. We will simply loop. } + { until all data has been sent. This will fill TWSocket internal buffer } + { very quickly while data is being sent in the background at network } + { speed. } + while (FFinalCount <= 0) or (FFinalCount > FCount) do begin + { We must break the loop if user temrinated the application, } + { or if connection is broke, or if user stopped. } + if (Application.Terminated) or + (WSocket1.State <> wsConnected) or + (not FSending) then + Exit; + { Otherwise, we can send data } + DoSend; + end; + CountLabel.Caption := IntToStr(FCount); + PauseButton.Visible := FALSE; + Display('All data is in TWSocket buffer and being sent in the background'); + FFinished := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.DoSend; +var + Buf : String; +begin + repeat + { Calling ProcessMessages let a chance to button and other events } + { to be handled. } + Application.ProcessMessages; + { We must stop if the user clicked the close button. } + if Application.Terminated then begin + Display('Application terminated'); + Exit; + end; + { We must stop if the user requested to stop send } + if not FSending then + Exit; + { We must stop if connection is broken } + if WSocket1.State <> wsConnected then + Exit; + {$IFNDEF VER80} + { We don't wants to use 100% CPU just looping. Sleep a little bit } + if FPaused then + Sleep(250); + {$ENDIF} + until FPaused = FALSE; + + { We need to check if we are still connected before sending } + if WSocket1.State <> wsConnected then + Exit; + + if (FFinalCount <= 0) or (FFinalCount > FCount) then begin + { Count the message sent } + Inc(FCount); + { Put the counter into the message, truvated to 4 digits } + Buf := IntToStr(FCount mod 10000) + ' '; + Move(Buf[1], FDataBuf[0], 4); + + { If required, display in memo box (slow down !) } + if FDisplayData then + Display('Sending ' + IntToStr(FCount)); + { Display the counter every 100 sends } + if (FCount mod 100) = 0 then + CountLabel.Caption := IntToStr(FCount); + + { Try to send data. Send may fail ! } + try + WSocket1.Send(FDataBuf, FDataBufSize - 1); + except + on E:Exception do begin + Display('Exception during TWSocket.Send: ' + E.Message); + FAutoStart := 0; + PostMessage(Handle, WM_CLOSE_REQUEST, 0, LParam(WSocket1)); + end; + end; + end + else begin + Display('Required data has been sent. Closing.'); + { We may have not read data send by server. But anyway, close the } + { session. } + PostMessage(Handle, WM_CLOSE_REQUEST, 0, LParam(WSocket1)); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.WSocket1DataSent(Sender: TObject; Error: Word); +begin + DoSend; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.WSocket1NoDataSent(Sender: TObject; Error: Word); +begin + if FFinished then begin + if not WSocket1.AllSent then + Display('Not all sent'); + Display('Required data has been sent. Closing.'); + PostMessage(Handle, WM_CLOSE_REQUEST, 0, LParam(WSocket1)); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.WSocket1DataAvailable(Sender: TObject; Error: Word); +var + Buf : PChar; + Cli : TWSocket; + Len : Integer; + Cnt : Integer; +begin + Cli := Sender as TWSocket; + Cnt := Cli.RcvdCount; + if Cnt <= 0 then + Exit; +{$IFDEF VER80} + { Delphi 1 has 255 character limit of strings (StrPas below) } + if Cnt > 254 then + Cnt := 254; +{$ENDIF} + GetMem(Buf, Cnt + 1); + try + Len := Cli.Receive(Buf, Cnt); + if Len > 0 then begin + Buf[Cnt] := #0; + Display('Received: ' + StrPas(Buf)); + end; + finally + FreeMem(Buf, Cnt + 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.WSocket1SessionClosed(Sender: TObject; Error: Word); +begin + if Error = 0 then + Display('Socket closed, no error') + else begin + Display('Socket closed, Error #' + IntToStr(Error)); + FAutoStart := 0; + end; + FSending := FALSE; + ActionButton.Caption := '&Start'; + PauseButton.Visible := FALSE; + FPaused := FALSE; + if FAutoStart > 0 then begin + Inc(FAutoStart); + AutoStartButton.Caption := IntToStr(FAutoStart); + PostMessage(Handle, WM_AUTO_START, 0, 0); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.DisplayDataCheckBoxClick(Sender: TObject); +begin + FDisplayData := DisplayDataCheckBox.Checked; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.UseDataSentCheckBoxClick(Sender: TObject); +begin + FUseDataSent := UseDataSentCheckBox.Checked; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.PauseButtonClick(Sender: TObject); +begin + CountLabel.Caption := IntToStr(FCount); + FPaused := not FPaused; + if FPaused then + PauseButton.Caption := '&Resume' + else + PauseButton.Caption := '&Pause'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.AutoStartButtonClick(Sender: TObject); +begin + if FAutoStart <> 0 then begin + FAutoStart := 0; + Exit; + end; + + FAutoStart := 1; + AutoStartButton.Caption := IntToStr(FAutoStart); + PostMessage(Handle, WM_AUTO_START, 0, 0); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.WMCloseRequest(var msg: TMessage); +var + WSocket : TWSocket; +begin + WSocket := TWSocket(msg.LParam); + WSocket.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSenderForm.WMAutoStart(var msg: TMessage); +begin + ActionButtonClick(Self); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. diff --git a/ICS_zlog/Delphi/Internet/Socks1.dfm b/ICS_zlog/Delphi/Internet/Socks1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..8a58485e2b2fe08efb1397b1d7873907fd776e4b GIT binary patch literal 2675 zcmbuB-EJc_6vv%OGoF04*+LQA^#WB~t-8=6R_q0Bwo!q!i8_NSu{XFgZe~=+j%=qN z5H-}0-n9To z#)HG{BxdQINU)Ft#;4uNXlsaXW&LkZPuQ&fy4JWZGMU$55T4^=lFRyE0QS*L7L0~1 z=O|F4SHJG|gpKC7DfHh7?F`+O*q)!S=Wp`LmEMCTv7jzK&P7xO{6ylW0JW9~bh-a7wAi8EeyXI&X0T3o*L@^1?@2h1EU`@l+X=os#)}sX0 z6lI8R6vg~HN>49Z(6N-@$|urYtk_P1_yo)Sb0#EJtDwa!VLrEFJ~Wum9Oif(({`9K z<8lS@g{_}w`%%4=Z`K(dTRdv@?=fG299c-aW`um|gdD9yTm^2>acmKPSRHR1VziFf zwmNmiQg6hRxh5C}%1g%$~-rGZW%yQeRTTtsmTWMbF z(*~_u7Q5>2xpouv(QMT?>c0B|o2U&-t$KUr3!~Ln=9=2C{)HP_?mD5$_T{?9_O-c5 zGhAjb698x?{T!!vr|i*2KAFqhTkJRa)i&hUPWzAkOTTEE&33A`S=g0GA41>Fg)DBL z7EQ6OY3hBEB7OXnWu*30-)-$a!H6&QTKzX0&?mH^*~0#Tb}D(zMb-C~aIWAx$rZ{9 zW<%I4kCrUU4epbC{U4Hqb~`#M)u=;zL(Jo~nCGV5{zuGXXqF0R%`$i!sxvH>Y}Nz- zM9H;Qhh^mczl!vUc%ingIVYmJKyKS$ZReAga D(i=@! literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/Socks1.pas b/ICS_zlog/Delphi/Internet/Socks1.pas new file mode 100644 index 00000000..7350bdb9 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/Socks1.pas @@ -0,0 +1,344 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: Show how to use TWSocket with SOCKS protocol to traverse + a firewall. +EMail: francois.piette@pophost.eunet.be francois.piette@rtfm.be + http://www.rtfm.be/fpiette +Creation: November 21, 1998 +Version: 1.00 +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +History: + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit Socks1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, IniFiles, WinSock, WSocket, StdCtrls, ExtCtrls; + +type + TSocksTestForm = class(TForm) + DisplayMemo: TMemo; + Panel1: TPanel; + ConnectButton: TButton; + DisconnectButton: TButton; + Label1: TLabel; + Label2: TLabel; + Label3: TLabel; + Label4: TLabel; + TargetHostEdit: TEdit; + TargetPortEdit: TEdit; + SocksServerEdit: TEdit; + SocksPortEdit: TEdit; + WSocket1: TWSocket; + Label5: TLabel; + SocksUsercodeEdit: TEdit; + SocksPasswordEdit: TEdit; + Label6: TLabel; + SocksAuthCheckBox: TCheckBox; + ClearButton: TButton; + Socks4RadioButton: TRadioButton; + Socks5RadioButton: TRadioButton; + procedure ConnectButtonClick(Sender: TObject); + procedure WSocket1SessionConnected(Sender: TObject; Error: Word); + procedure WSocket1DataAvailable(Sender: TObject; Error: Word); + procedure WSocket1SocksError(Sender: TObject; Error: Integer; + Msg: String); + procedure DisconnectButtonClick(Sender: TObject); + procedure WSocket1SessionClosed(Sender: TObject; Error: Word); + procedure FormCreate(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure WSocket1SocksAuthState(Sender: TObject; + AuthState: TSocksAuthState); + procedure WSocket1SocksConnected(Sender: TObject; Error: Word); + procedure DisplayMsg(Sender : TObject; var Msg : String); + procedure ClearButtonClick(Sender: TObject); + private + FIniFileName : String; + FInitialized : Boolean; + FRcvBuf : array [0..2047] of char; + FRcvCnt : Integer; + public + { Déclarations publiques } + end; + +var + SocksTestForm: TSocksTestForm; + +implementation + +{$R *.DFM} + +const + SectionWindow = 'Windows'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + SectionData = 'Data'; + KeyTargetHost = 'TargetHost'; + KeyTargetPort = 'TargetPort'; + KeySocksServer = 'SocksServer'; + KeySocksPort = 'SocksPort'; + KeySocksUsercode = 'SocksUsercode'; + KeySocksPassword = 'SocksPassword'; + KeySocksAuth = 'SocksAuthentification'; + KeySocks4 = 'Socks4'; + KeySocks5 = 'Socks5'; + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +function TrimRight(Str : String) : String; +var + i : Integer; +begin + i := Length(Str); + while (i > 0) and (Str[i] = ' ') do + i := i - 1; + Result := Copy(Str, 1, i); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TrimLeft(Str : String) : String; +var + i : Integer; +begin + if Str[1] <> ' ' then + Result := Str + else begin + i := 1; + while (i <= Length(Str)) and (Str[i] = ' ') do + i := i + 1; + Result := Copy(Str, i, Length(Str) - i + 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function Trim(Str : String) : String; +begin + Result := TrimLeft(TrimRight(Str)); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSocksTestForm.FormCreate(Sender: TObject); +begin + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSocksTestForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + DisplayMemo.Clear; + IniFile := TIniFile.Create(FIniFileName); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, + (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, + (Screen.Width - Width) div 2); + TargetHostEdit.Text := IniFile.ReadString(SectionData, KeyTargetHost, ''); + TargetPortEdit.Text := IniFile.ReadString(SectionData, KeyTargetPort, ''); + SocksServerEdit.Text := IniFile.ReadString(SectionData, KeySocksServer, ''); + SocksPortEdit.Text := IniFile.ReadString(SectionData, KeySocksPort, '1080'); + SocksUsercodeEdit.Text := IniFile.ReadString(SectionData, KeySocksUsercode, ''); + SocksPasswordEdit.Text := IniFile.ReadString(SectionData, KeySocksPassword, ''); + SocksAuthCheckBox.Checked := Boolean(IniFile.ReadInteger(SectionData, KeySocksAuth, 0)); + Socks4RadioButton.Checked := Boolean(IniFile.ReadInteger(SectionData, KeySocks4, 0)); + Socks5RadioButton.Checked := Boolean(IniFile.ReadInteger(SectionData, KeySocks5, 1)); + IniFile.Destroy; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSocksTestForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.WriteString(SectionData, KeyTargetHost, Trim(TargetHostEdit.Text)); + IniFile.WriteString(SectionData, KeyTargetPort, Trim(TargetPortEdit.Text)); + IniFile.WriteString(SectionData, KeySocksServer, Trim(SocksServerEdit.Text)); + IniFile.WriteString(SectionData, KeySocksPort, Trim(SocksPortEdit.Text)); + IniFile.WriteString(SectionData, KeySocksUsercode, Trim(SocksUsercodeEdit.Text)); + IniFile.WriteString(SectionData, KeySocksPassword, Trim(SocksPasswordEdit.Text)); + IniFile.WriteInteger(SectionData, KeySocksAuth, Ord(SocksAuthCheckBox.Checked)); + IniFile.WriteInteger(SectionData, KeySocks5, Ord(Socks5RadioButton.Checked)); + IniFile.WriteInteger(SectionData, KeySocks4, Ord(Socks4RadioButton.Checked)); + IniFile.Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSocksTestForm.DisplayMsg(Sender : TObject; var Msg : String); +begin + DisplayMemo.lines.Add(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSocksTestForm.ConnectButtonClick(Sender: TObject); +const + AuthMethod : array [Boolean] of TSocksAuthentication = + (socksNoAuthentication, socksAuthenticateUsercode); +begin + if Socks5RadioButton.Checked then + WSocket1.SocksLevel := '5' + else if Socks4RadioButton.Checked and SocksAuthCheckBox.Checked then + WSocket1.SocksLevel := '4A' + else + WSocket1.SocksLevel := '4'; + DisplayMemo.Lines.Add('Connecting using Socks' + WSocket1.SocksLevel); + + WSocket1.SocksServer := Trim(SocksServerEdit.Text); + WSocket1.SocksPort := Trim(SocksPortEdit.Text); + WSocket1.SocksUsercode := Trim(SocksUsercodeEdit.Text); + WSocket1.SocksPassword := Trim(SocksPasswordEdit.Text); + WSocket1.SocksAuthentication := AuthMethod[SocksAuthCheckBox.Checked]; + WSocket1.Proto := 'tcp'; + WSocket1.Addr := Trim(TargetHostEdit.Text); + WSocket1.Port := Trim(TargetPortEdit.Text); + WSocket1.OnDisplay := DisplayMsg; + WSocket1.Connect; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSocksTestForm.DisconnectButtonClick(Sender: TObject); +begin + WSocket1.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSocksTestForm.WSocket1SessionConnected(Sender: TObject; Error: Word); +begin + DisplayMemo.Lines.Add('Session connected to remote host.'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSocksTestForm.WSocket1SocksConnected(Sender: TObject; Error: Word); +begin + DisplayMemo.Lines.Add('Session connected to socks server.'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSocksTestForm.WSocket1SocksAuthState(Sender: TObject; + AuthState: TSocksAuthState); +begin + case AuthState of + socksAuthStart: + DisplayMemo.Lines.Add('Socks authentification start.'); + socksAuthSuccess: + DisplayMemo.Lines.Add('Socks authentification success.'); + socksAuthFailure: + DisplayMemo.Lines.Add('Socks authentification failure.'); + socksAuthNotRequired: + DisplayMemo.Lines.Add('Socks authentification not required.'); + else + DisplayMemo.Lines.Add('Unknown socks authentification state.') + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSocksTestForm.WSocket1SessionClosed(Sender: TObject; Error: Word); +begin + DisplayMemo.Lines.Add('Session Closed'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSocksTestForm.WSocket1DataAvailable(Sender: TObject; Error: Word); +var + Len : Integer; + I : Integer; + p : PChar; +begin + Len := TWSocket(Sender).Receive(@FRcvBuf[FRcvCnt], Sizeof(FRcvBuf) - FRcvCnt - 1); + if Len < 0 then + Exit; + FRcvCnt := FRcvCnt + Len; + FRcvBuf[FRcvCnt] := #0; + + while FRcvCnt > 0 do begin + p := StrScan(FRcvBuf, #10); + if p = nil then + Exit; + I := p - FRcvBuf; + + FRcvBuf[I] := #0; + if (I > 0) and (FRcvBuf[I - 1] = #13) then + FRcvBuf[I - 1] := #0; + + DisplayMemo.Lines.Add('Received: ''' + StrPas(FRcvBuf) + ''''); + Move(FRcvBuf[I + 1], FRcvBuf[0], FRcvCnt - I); + FRcvCnt := FRcvCnt - I - 1; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSocksTestForm.WSocket1SocksError(Sender : TObject; Error : Integer; Msg : String); +begin + DisplayMemo.Lines.Add('Socks error #' + IntToStr(Error) + ' ' + Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSocksTestForm.ClearButtonClick(Sender: TObject); +begin + DisplayMemo.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/SocksTst.dpr b/ICS_zlog/Delphi/Internet/SocksTst.dpr new file mode 100644 index 00000000..7a3077ea --- /dev/null +++ b/ICS_zlog/Delphi/Internet/SocksTst.dpr @@ -0,0 +1,12 @@ +program SocksTst; + +uses + Forms, + Socks1 in 'Socks1.pas' {SocksTestForm}; + +{$R *.RES} + +begin + Application.CreateForm(TSocksTestForm, SocksTestForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/SrvDemo1.dfm b/ICS_zlog/Delphi/Internet/SrvDemo1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..70b977f96f42ad0da19aeffa0428a41e2607abfb GIT binary patch literal 1108 zcmZ8gyKdVs6s2TalxzzP8U$#!Oa;0G?ojlBE{+qU25ifSgl6#&TDrD~(4;}qk526` zbnD0UH#)Z@pDW&q~8g%RBrl0F7f_bAHrPM zet5M^tZGxQaZd|f*1mbcXP}Ex*M1?~BP&e>4}uir24u4@xW4KMCM0g>?4I&MY%|#D zmitlh{NIs_#$*XWJW4N9!que_p!15K>aPr1D4x(AFf{==;Cbmk;Dq;>P=F0xE*%UK zo|a;ZL%U*8(7%wAe#^lEO75P|LUTrx+YU4+aSy&KFN4SWk_a5#l80`p{wq!Qt{9C zBlqLu#Oo6wHA0Q-wxBw+fdy3w9Y+rL5kHH3|^g!lH`McuV7 zO@TBg_PXH + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Dec 09, 1997 V1.01 Made it compatible with Delphi 1 +Dec 28, 1998 V1.02 Use line mode to make it simpler. + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit SrvDemo1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, IniFiles, WSocket, SrvDemo2, Db, DBTables, + ExtCtrls; + +const + IniFileName = 'SrvDemo.ini'; + +type + TSrvForm = class(TForm) + SrvSocket: TWSocket; + ClientListBox: TListBox; + DataTable: TTable; + Panel1: TPanel; + Label1: TLabel; + PortEdit: TEdit; + PortButton: TButton; + procedure FormShow(Sender: TObject); + procedure SrvSocketSessionAvailable(Sender: TObject; Error: Word); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure PortButtonClick(Sender: TObject); + private + Initialized : Boolean; + ClientNumber : Integer; + procedure WMUser(var msg: TMessage); message WM_USER; + procedure StartServer; + end; + +var + SrvForm: TSrvForm; + +implementation + +{$R *.DFM} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSrvForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; + Buffer : String; +begin + if not Initialized then begin + Initialized := TRUE; + IniFile := TIniFile.Create(IniFileName); + Top := IniFile.ReadInteger('Window', 'Top', Top); + Left := IniFile.ReadInteger('Window', 'Left', Left); + Width := IniFile.ReadInteger('Window', 'Width', Width); + Height := IniFile.ReadInteger('Window', 'Height', Height); + PortEdit.Text := IniFile.ReadString('Data', 'Port', 'telnet'); + IniFile.Free; + + DataTable.DataBaseName := ExtractFilePath(Application.ExeName); + try + DataTable.Open; + except + Buffer := 'Unable to open ' + DataTable.DataBaseName + + DataTable.TableName + #0; + Application.MessageBox(@Buffer[1], 'Error', MB_OK); + Application.Terminate; + Exit; + end; + StartServer; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSrvForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(IniFileName); + IniFile.WriteInteger('Window', 'Top', Top); + IniFile.WriteInteger('Window', 'Left', Left); + IniFile.WriteInteger('Window', 'Width', Width); + IniFile.WriteInteger('Window', 'Height', Height); + IniFile.WriteString('Data', 'Port', PortEdit.Text); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSrvForm.PortButtonClick(Sender: TObject); +begin + StartServer; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSrvForm.StartServer; +begin + SrvSocket.Close; + SrvSocket.Addr := '0.0.0.0'; + SrvSocket.Port := PortEdit.Text; + SrvSocket.Proto := 'tcp'; + SrvSocket.Listen; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSrvForm.SrvSocketSessionAvailable(Sender: TObject; Error: Word); +var + Form : TCliForm; +begin + Inc(ClientNumber); + Form := TCliForm.Create(self); + { Add the form address as an identifier in our client list } + ClientListBox.Items.Add(IntToStr(LongInt(Form))); + { We request line mode, to receive only complete line. } + { TWSocket does all the job for us... } + Form.CliSocket.LineMode := TRUE; + Form.CliSocket.LineEnd := #13#10; + { Now accept the new client connection } + Form.CliSocket.HSocket := SrvSocket.Accept; + Form.DataTable := DataTable; + Form.Caption := 'Client ' + IntToStr(ClientNumber); + { Showing the form is not mandatory. In a real server, this can be } + { annoying to have a form displayed for each client. In some situation, } + { it may be handy to have a user interface for each connected client. } + Form.Show; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TSrvForm.WMUser(var msg: TMessage); +var + Form : TCliForm; + I : Integer; +begin + Form := TCliForm(Msg.lParam); + Form.Release; + for I := 0 to ClientListBox.Items.Count - 1 do begin + if ClientListBox.Items[I] = IntToStr(LongInt(Form)) then begin + ClientListBox.Items.Delete(I); + break; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/SrvDemo2.dfm b/ICS_zlog/Delphi/Internet/SrvDemo2.dfm new file mode 100644 index 0000000000000000000000000000000000000000..7d0b7c5c1964cdc023449a4933a08853d0dbc600 GIT binary patch literal 1334 zcmZ`(L2uJA6n4@jPSTcDLPH#PKoh%E1&JG%E^V}lcBz)2aRV=L8*7eT#qPQZ@oV76 z@Kg8$95{jPv`vRVmD=ZLzwdqTd++sk0Mc-B5ye+iFzCH-07z%iz)M3)B3_kn^LsGC zbJ_Z8wNk!peFx4p$z{>{V!7v-EDG8B0bq!hl5pm_Dg-m>gq-pU`WZcwEJ7LXM4ZWf zSfEN^2@gl(X!w4TehkltSIIaH>RS`j$>=ptJ0Wm z%#wnyp{G6C>dweLrecPx3zil3r$F=CFzNy)o#K+WM?@?sdeF8J%LZC2`*b7KYAcof z*%?x@V9-OfR;oK842ymuE5a7Sa`&Ntm!ca}gbe_2(-~rzy5{@UUYgdoZA+Rwr%j$S zE+sD;C`*wZ=R|r5X1O+MsGeaQY#9Fno95a_O(ZzbwY$4O0APByQs^wuShZOX%X2d< z_6E*=w?o@aigTi4;HDvdlf^P!A=xcFY*3Y0+3nvVyxtSR{=WteqN*890$WKrK{uHC zT6<&FK%a~Romv9BzvbNBac%;d(tE1+8D|VmT*EPny7n8`u?p)LhrN zTM4}MI^o$ZmcH`TmZuAu@*I0LLsF`)0$>5CFUBl)?QUQmjkAJ#wWUYEnN?hJw<$6_1J8_XoJI;jgUmcJ47hD zp%^~f5q#uV?-DG8+DNl;`QE!n{!T`$5Jy5kx#W-C^>Dm24gH{I F@DJ%pptt}4 literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/SrvDemo2.pas b/ICS_zlog/Delphi/Internet/SrvDemo2.pas new file mode 100644 index 00000000..412fa87e --- /dev/null +++ b/ICS_zlog/Delphi/Internet/SrvDemo2.pas @@ -0,0 +1,256 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: Demonstration for Server program using TWSocket. +Creation: 8 december 1997 +Version: 1.03 +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Dec 28, 1998 V1.02 Use line mode. +Mar 07, 1999 V1.03 Adapted for Delphi 1 + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit SrvDemo2; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, WSocket, StdCtrls, Db, DBTables, ExtCtrls; + +type + TCliForm = class(TForm) + CliSocket: TWSocket; + DisplayMemo: TMemo; + Panel1: TPanel; + SendEdit: TEdit; + SendButton: TButton; + Panel2: TPanel; + LineLabel: TLabel; + DisconnectButton: TButton; + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure CliSocketDataAvailable(Sender: TObject; Error: Word); + procedure CliSocketSessionClosed(Sender: TObject; Error: Word); + procedure SendButtonClick(Sender: TObject); + procedure DisconnectButtonClick(Sender: TObject); + private + { Déclarations privées } + Initialized : Boolean; + Buffer : array [0..1023] of char; + procedure ProcessCommand(Cmd : String); + public + { Déclarations publiques } + DataTable : TTable; + end; + +var + CliForm: TCliForm; + +implementation + +{$R *.DFM} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +procedure SetLength(var S: string; NewLength: Integer); +begin + S[0] := chr(NewLength); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TrimRight(Str : String) : String; +var + i : Integer; +begin + i := Length(Str); + while (i > 0) and (Str[i] = ' ') do + i := i - 1; + Result := Copy(Str, 1, i); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TrimLeft(Str : String) : String; +var + i : Integer; +begin + if Str[1] <> ' ' then + Result := Str + else begin + i := 1; + while (i <= Length(Str)) and (Str[i] = ' ') do + i := i + 1; + Result := Copy(Str, i, Length(Str) - i + 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function Trim(Str : String) : String; +begin + Result := TrimLeft(TrimRight(Str)); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCliForm.FormShow(Sender: TObject); +begin + if not Initialized then begin + Initialized := TRUE; + DisplayMemo.Clear; + SendEdit.Text := 'Hello world !'; + ActiveControl := SendEdit; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCliForm.FormClose(Sender: TObject; var Action: TCloseAction); +begin + PostMessage(TForm(Owner).Handle, WM_USER, 0, LongInt(Self)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCliForm.ProcessCommand(Cmd : String); +var + CommandVerb : String; + CommandTail : String; + I, J : Integer; +begin + DisplayMemo.Lines.Add(Cmd); + + { Skip leading spaces } + I := 1; + while (I <= Length(Cmd)) and (Cmd[I] in [' ', #9]) do + Inc(I); + + { Find separator and separe CommandVerb and CommandTail } + J := I; + while TRUE do begin + if (J >= Length(Cmd)) then begin + CommandTail := ''; + CommandVerb := Cmd; + break; + end; + + if Cmd[J] in [' ', #9, '/'] then begin + CommandTail := Copy(Cmd, J, Length(Cmd) - J + 1); + CommandVerb := Copy(Cmd, I, J - I); + break; + end; + Inc(J); + end; + CommandVerb := UpperCase(CommandVerb); + CommandTail := Trim(CommandTail); + + if CommandVerb = 'LASTNAME' then begin + DataTable.IndexName := 'NOM'; + DataTable.SetKey; + DataTable.FieldByName('NOM').AsString := CommandTail; + end + else if CommandVerb = 'FIRSTNAME' then begin + DataTable.IndexName := 'PRENOM'; + DataTable.SetKey; + DataTable.FieldByName('PRENOM').AsString := CommandTail; + end + else begin + CliSocket.SendStr('Syntax error !' + #13 + #10); + Exit; + end; + + if DataTable.GotoKey then + CliSocket.SendStr( + '"' + DataTable.FieldByName('NOM').AsString + '", ' + + '"' + DataTable.FieldByName('PRENOM').AsString + '", ' + + '"' + DataTable.FieldByName('ADRESSE').AsString + '", ' + + '"' + DataTable.FieldByName('CP').AsString + '", ' + + '"' + DataTable.FieldByName('LOCALITE').AsString + '"' + + #13 + #10) + else + CliSocket.SendStr('Pas trouvé' + #13 + #10); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCliForm.CliSocketDataAvailable(Sender: TObject; Error: Word); +var + Len : Integer; +begin + { We use line mode. So when we call Receive, we always receive a } + { complete line, include end of line marker or nothing. } + Len := CliSocket.Receive(@Buffer[0], SizeOf(Buffer) - 1); + if Len <= 0 then + Exit; + + { Remove end of line marker } + while (Len > 0) and (Buffer[Len - 1] in [#13, #10]) do + Dec(Len); + + { Nul terminate the string } + Buffer[Len] := #0; + { Display command in label } + LineLabel.Caption := StrPas(Buffer); + { Process command } + ProcessCommand(StrPas(Buffer)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCliForm.CliSocketSessionClosed(Sender: TObject; Error: Word); +begin + Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCliForm.SendButtonClick(Sender: TObject); +begin + CliSocket.SendStr(SendEdit.Text + #13 + #10); + ActiveControl := SendEdit; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCliForm.DisconnectButtonClick(Sender: TObject); +begin + Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/SrvTcp.dpr b/ICS_zlog/Delphi/Internet/SrvTcp.dpr new file mode 100644 index 00000000..8b48ae65 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/SrvTcp.dpr @@ -0,0 +1,16 @@ +program SrvTcp; + +uses + Forms, + SrvTcp1 in 'SrvTcp1.pas' {GetGroupsForm}, + TcpCmd in 'TcpCmd.pas'; + +{$R *.RES} + +begin +{$IFNDEF VER80} + Application.Initialize; +{$ENDIF} + Application.CreateForm(TGetGroupsForm, GetGroupsForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/SrvTcp1.dfm b/ICS_zlog/Delphi/Internet/SrvTcp1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..02c4c2ea375b19bf8da48cd9d5e89f744520cc8b GIT binary patch literal 613 zcmb7ByHdhH6x}3}1Q5r@K81~ifzBB_Cki?vCPUVtb%6`nakHD*Tnzk+r9b4ySnDR@ z_~`7;eV%jAeeV!Dx}u{=e4nJlcrqq~!?8^WO@@O5IszPNwJyq`(s}P!w08?jbTZ4K zs&J02)|4+Wb6za>8u%(h=g9IRRv=f>J-dn0fX<5`1^om%I1Mty;=JFlsw&jD%)=S< zmjwqz=ySP%&H6FSFz*bN#4u7qX>WfnrlzDS3LES;g-;^;t=&X-EC;tYPJ@)mvS#AT z&-oO$0=lG^@C}GE0evIqnf>6!G7_o;&y4H5fxby;UG`R-1V|fWBYPIzYtK&A^1vqEhbEZPuVQi z3()2dq(#S&tL`N)3&FNE{<-Sp?<(h&>~{G~M1q6F|J&G&)LL`%sXM5Cn|RA5lwpdR Y%T;N)KV^|l!nC2Qzu|wMV3`{}00k$)+yDRo literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/SrvTcp1.pas b/ICS_zlog/Delphi/Internet/SrvTcp1.pas new file mode 100644 index 00000000..82062b8b --- /dev/null +++ b/ICS_zlog/Delphi/Internet/SrvTcp1.pas @@ -0,0 +1,194 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: This code is part of SvcTcp sample program. SvcTcp program + shows how to use TWSocket from within a Windows NT/2000 service. + This code has been tested with Delphi 5, Windows NT4 and 2000. + All TWSocket code has been encapsulated in TTcpDaemon object. + This is done so that you can see how the same code can be used + inside a service or inside a normal exe program (this sample). +Creation: July 15, 2000 +Version: 1.00 +EMail: http://users.swing.be/francois.piette francois.piette@swing.be + http://www.rtfm.be/fpiette francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + See http://www.rtfm.be/fpiette/supportuk.htm for subscription. +Legal issues: Copyright (C) 2000 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +History: + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit SrvTcp1; + +{$B-} { Enable partial boolean evaluation } +{$T-} { Untyped pointers } +{$X+} { Enable extended syntax } +{$IFNDEF VER80} { Not for Delphi 1 } + {$H+} { Use long strings } + {$J+} { Allow typed constant to be modified } +{$ENDIF} + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, IniFiles, StdCtrls, ExtCtrls, TcpCmd; + +const + SrvTcpVersion = 100; + CopyRight : String = ' SrvTcp (c) 2000 F. Piette V1.00 '; + WM_APPSTARTUP = WM_USER + 1; + +type + TGetGroupsForm = class(TForm) + ToolPanel: TPanel; + DisplayMemo: TMemo; + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure FormDestroy(Sender: TObject); + private + FIniFileName : String; + FInitialized : Boolean; + FTcpDaemon : TTcpDaemon; + procedure Display(Msg : String); + procedure WMAppStartup(var Msg: TMessage); message WM_APPSTARTUP; + public + property IniFileName : String read FIniFileName write FIniFileName; + end; + +var + GetGroupsForm: TGetGroupsForm; + +implementation + +{$R *.DFM} + +const + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + SectionData = 'Data'; + KeyLastServer = 'LastServer'; + KeyLastUser = 'LastUser'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TGetGroupsForm.FormCreate(Sender: TObject); +begin + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; + FTcpDaemon := TTcpDaemon.Create; + FTcpDaemon.Banner := 'ICS Tcp Server Ready'; + FTcpDaemon.OnDisplay := Display; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TGetGroupsForm.FormDestroy(Sender: TObject); +begin + if Assigned(FTcpDaemon) then begin + FTcpDaemon.Destroy; + FTcpDaemon := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TGetGroupsForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + + IniFile := TIniFile.Create(FIniFileName); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, + (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, + (Screen.Width - Width) div 2); + IniFile.Destroy; + DisplayMemo.Clear; + { Delay startup code until our UI is ready and visible } + PostMessage(Handle, WM_APPSTARTUP, 0, 0); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TGetGroupsForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TGetGroupsForm.Display(Msg : String); +var + I : Integer; +begin + DisplayMemo.Lines.BeginUpdate; + try + if DisplayMemo.Lines.Count > 200 then begin + for I := 1 to 50 do + DisplayMemo.Lines.Delete(0); + end; + DisplayMemo.Lines.Add(Msg); + finally + DisplayMemo.Lines.EndUpdate; + {$IFNDEF VER80} + SendMessage(DisplayMemo.Handle, EM_SCROLLCARET, 0, 0); + {$ENDIF} + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TGetGroupsForm.WMAppStartup(var Msg: TMessage); +begin + FTcpDaemon.Start; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. diff --git a/ICS_zlog/Delphi/Internet/SvcTcp.dpr b/ICS_zlog/Delphi/Internet/SvcTcp.dpr new file mode 100644 index 00000000..300c0042 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/SvcTcp.dpr @@ -0,0 +1,14 @@ +program SvcTcp; + +uses + SvcMgr, + SvcTcp1 in 'SvcTcp1.pas' {IcsTcpSvc: TService}, + TcpCmd in 'TcpCmd.pas'; + +{$R *.RES} + +begin + Application.Initialize; + Application.CreateForm(TIcsTcpSvc, IcsTcpSvc); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/SvcTcp1.dfm b/ICS_zlog/Delphi/Internet/SvcTcp1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..cd8be4fa8873fb3ce7c3d4a81d45ded8f3322ce5 GIT binary patch literal 264 zcmX|)T@HdU5QM8$3jSZf#3OJA)M%pCq>Vl|Wfc;HrmRMeyT2EHpQ^0wd1?98h} zTAH0FtDHyxDCO&E>C~R`U31F*6>4*r&Gw$ zW(6BmM#bG}oSQ@y8+8I_SPoChjY*a91S*TNFu>d#*D5`$q^z1_-gS6%=B literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/SvcTcp1.pas b/ICS_zlog/Delphi/Internet/SvcTcp1.pas new file mode 100644 index 00000000..61310992 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/SvcTcp1.pas @@ -0,0 +1,171 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: Shows how to use TWSocket from within a Windows NT/2000 service. + This code has been tested with Delphi 5, Windows NT4 and 2000. + All TWSocket code has been encapsulated in TTcpDaemon object. + This is done so that you can see how the same code can be used + inside a service or inside a normal exe program (see SrvTcp). + To install SvcTcp, you need Windows NT or Windows 2000. At + command prompt, enter: to uninstall it, just + enter the command . Once installed, you can + find SvcTcp service in the "services" applet. You can start and + stop it from that applet. You can also start and stop it from + the command line with the command . + To test for service operation, use command line telnet utility + and connect to port 2120, then enter the command help and hit + return key. If you wants to see what you type, turn telnet + local echo to on. +Creation: July 15, 2000 +Version: 1.00 +EMail: http://users.swing.be/francois.piette francois.piette@swing.be + http://www.rtfm.be/fpiette francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + See http://www.rtfm.be/fpiette/supportuk.htm for subscription. +Legal issues: Copyright (C) 2000 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +History: + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit SvcTcp1; + +{$B-} { Enable partial boolean evaluation } +{$T-} { Untyped pointers } +{$X+} { Enable extended syntax } +{$IFNDEF VER80} { Not for Delphi 1 } + {$H+} { Use long strings } + {$J+} { Allow typed constant to be modified } +{$ENDIF} + +interface + +uses + Windows, Messages, SysUtils, Classes, SvcMgr, TcpCmd; + +const + SvcTcpVersion = 100; + CopyRight : String = ' SvcTcp (c) 2000 F. Piette V1.00 '; + +type + TIcsTcpSvc = class(TService) + procedure ServiceExecute(Sender: TService); + procedure ServiceStop(Sender: TService; var Stopped: Boolean); + procedure ServiceCreate(Sender: TObject); + procedure ServiceDestroy(Sender: TObject); + procedure ServiceStart(Sender: TService; var Started: Boolean); + private + FTcpDaemon : TTcpDaemon; + procedure Display(Msg: String); + public + function GetServiceController: TServiceController; override; + end; + +var + IcsTcpSvc: TIcsTcpSvc; + +implementation + +{$R *.DFM} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure ServiceController(CtrlCode: DWord); stdcall; +begin + IcsTcpSvc.Controller(CtrlCode); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TIcsTcpSvc.GetServiceController: TServiceController; +begin + Result := ServiceController; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TIcsTcpSvc.ServiceStart(Sender: TService; var Started: Boolean); +begin + try + FTcpDaemon.Start; + Started := TRUE; + except + Started := FALSE; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TIcsTcpSvc.ServiceStop(Sender: TService; var Stopped: Boolean); +begin + FTcpDaemon.Stop; + Stopped := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TIcsTcpSvc.ServiceExecute(Sender: TService); +begin + while not Terminated do + ServiceThread.ProcessRequests(TRUE); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TIcsTcpSvc.Display(Msg : String); +begin + // A service has no access to the GUI. + // Simply ignore any display :-( + // We could log messages to the EventViewer +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TIcsTcpSvc.ServiceCreate(Sender: TObject); +begin + FTcpDaemon := TTcpDaemon.Create; + FTcpDaemon.Banner := DisplayName + ' Ready'; + FTcpDaemon.OnDisplay := Display; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TIcsTcpSvc.ServiceDestroy(Sender: TObject); +begin + if Assigned(FTcpDaemon) then begin + FTcpDaemon.Destroy; + FTcpDaemon := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. diff --git a/ICS_zlog/Delphi/Internet/TcpCmd.pas b/ICS_zlog/Delphi/Internet/TcpCmd.pas new file mode 100644 index 00000000..f0831ddc --- /dev/null +++ b/ICS_zlog/Delphi/Internet/TcpCmd.pas @@ -0,0 +1,366 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: This code is part of SvcTcp and SrvTcp sample programs. In those + samples, all TWSocket code has been encapsulated in TTcpDaemon + object. This is done so that you can see how the same code can + be used inside a service or inside a normal exe program. +Creation: July 15, 2000 +Version: 1.00 +EMail: http://users.swing.be/francois.piette francois.piette@swing.be + http://www.rtfm.be/fpiette francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + See http://www.rtfm.be/fpiette/supportuk.htm for subscription. +Legal issues: Copyright (C) 2000 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +History: + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit TcpCmd; + +{$B-} { Enable partial boolean evaluation } +{$T-} { Untyped pointers } +{$X+} { Enable extended syntax } +{$IFNDEF VER80} { Not for Delphi 1 } + {$H+} { Use long strings } + {$J+} { Allow typed constant to be modified } +{$ENDIF} + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, WSocket, WSocketS; + +const + TcpCmdVersion = 100; + CopyRight : String = ' TcpCmd (c) 2000 F. Piette V1.00 '; + +type + { This class is used as a client class for TWSocketServer. Each time a } + { client connect to the server, TWSocketServer will instanciate a new } + { TTcpSrvClient to handle the client. } + TTcpSrvClient = class(TWSocketClient) + public + RcvdLine : String; + Param : array [0..10] of String; + ParamCount : Integer; + ConnectTime : TDateTime; + end; + + TDisplayProc = procedure (Msg : String) of object; + + { This class encapsulate all the work for a basic TCP server. It include } + { a basic command interpreter. } + TTcpDaemon = class(TObject) + private + WSocketServer1 : TWSocketServer; + FPort : String; + FAddr : String; + FOnDisplay : TDisplayProc; + procedure Display(Msg : String); + procedure WSocketServer1BgException(Sender: TObject; E: Exception; + var CanClose: Boolean); + procedure WSocketServer1ClientConnect(Sender: TObject; + Client: TWSocketClient; + Error: Word); + procedure WSocketServer1ClientDisconnect(Sender: TObject; + Client: TWSocketClient; + Error: Word); + procedure ClientDataAvailable(Sender: TObject; Error: Word); + procedure ProcessData(Client: TTcpSrvClient); + procedure ClientBgException(Sender: TObject; E: Exception; + var CanClose: Boolean); + function GetBanner: String; + procedure SetBanner(const Value: String); + public + constructor Create; virtual; + destructor Destroy; override; + procedure Start; + procedure Stop; + property OnDisplay : TDisplayProc read FOnDisplay write FOnDisplay; + { Make Banner property available to the outside. We could make other } + { TWSocket properties available. } + property Banner : String read GetBanner write SetBanner; + property Port : String read FPort write FPort; + property Addr : String read FAddr write FAddr; + end; + +implementation + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TTcpDaemon.Create; +begin + inherited Create; + WSocketServer1 := TWSocketServer.Create(nil); + WSocketServer1.Banner := 'ICS Tcp Service Ready'; + FPort := '2120'; + FAddr := '0.0.0.0'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor TTcpDaemon.Destroy; +begin + if Assigned(WSocketServer1) then begin + WSocketServer1.Destroy; + WSocketServer1 := nil; + end; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpDaemon.WSocketServer1BgException(Sender: TObject; + E: Exception; var CanClose: Boolean); +begin + Display('Server exception occured: ' + E.ClassName + ': ' + E.Message); + CanClose := FALSE; { Hoping that server will still work ! } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event is called each time a new client connect. We can setup our } +{ client class to fit our needs (We use line mode and two events) } +procedure TTcpDaemon.WSocketServer1ClientConnect( + Sender : TObject; + Client : TWSocketClient; + Error : Word); +begin + with Client as TTcpSrvClient do begin + Display('Client connecting: ' + PeerAddr); + LineMode := TRUE; + LineEdit := TRUE; + OnDataAvailable := ClientDataAvailable; + OnBgException := ClientBgException; + ConnectTime := Now; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event is called each time a client disconnect. No many things to do } +{ here. Just display a message. } +procedure TTcpDaemon.WSocketServer1ClientDisconnect( + Sender : TObject; + Client : TWSocketClient; + Error : Word); +begin + with Client as TTcpSrvClient do begin + Display('Client disconnecting: ' + PeerAddr + ' ' + + 'Duration: ' + FormatDateTime('hh:nn:ss', + Now - ConnectTime)); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpDaemon.ClientDataAvailable( + Sender : TObject; + Error : Word); +begin + with Sender as TTcpSrvClient do begin + { We use line mode. We will receive complete lines } + RcvdLine := ReceiveStr; + { Remove trailing CR/LF } + while (Length(RcvdLine) > 0) and + (RcvdLine[Length(RcvdLine)] in [#13, #10]) do + RcvdLine := Copy(RcvdLine, 1, Length(RcvdLine) - 1); + Display('Received from ' + GetPeerAddr + ': ''' + RcvdLine + ''''); + ProcessData(Sender as TTcpSrvClient); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Split a command line into an array of words. Use spaces or tabs as } +{ command delimiter. Commands words have to be delimited by doubles quotes } +{ if they include spaces or tabs. } +function ParseCommandLine( + const CmdLine : String; + var ParamsArray : array of string) : Integer; +var + Index : Integer; + I, J : Integer; +begin + I := 1; + Index := Low(ParamsArray); + while (Index <= High(ParamsArray)) and + (I <= Length(CmdLine)) do begin + { Skip spaces and tabs } + while (I <= Length(CmdLine)) and (CmdLine[I] in [' ', #9]) do + Inc(I); + if I > Length(CmdLine) then + break; + { Check if quoted parameters (can have embeded spaces) } + if CmdLine[I] = '"' then begin + Inc(I); + ParamsArray[Index] := ''; + while I <= Length(CmdLine) do begin + if CmdLine[I] = '"' then begin + if (I >= Length(CmdLine)) or (CmdLine[I + 1] <> '"') then begin + Inc(I); + break; + end; + ParamsArray[Index] := ParamsArray[Index] + '"'; + Inc(I, 2); + end + else begin + ParamsArray[Index] := ParamsArray[Index] + CmdLine[I]; + Inc(I); + end; + end; + end + else begin + J := I; + while (I <= Length(CmdLine)) and (not (CmdLine[I] in [' ', #9])) do + Inc(I); + if J = I then + break; + ParamsArray[Index] := Copy(CmdLine, J, I - J); + end; + Inc(Index); + end; + Result := Index - Low(ParamsArray); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Process a command line received from any client. If process takes time, } +{ you should use a thread to do the work and return immediately. } +procedure TTcpDaemon.ProcessData(Client : TTcpSrvClient); +var + I : Integer; + AClient : TTcpSrvClient; +begin + { Parse command line. } + Client.ParamCount := ParseCommandLine(Client.RcvdLine, Client.Param); + if Client.ParamCount <= 0 then + Exit; + + { We could replace all those CompareText with a table lookup } + if CompareText(Client.Param[0], 'exit') = 0 then + { We can't call Client.Close here because we will immediately } + { reenter DataAvailable event handler with same line because } + { a line is removed from buffer AFTER it has been processed. } + { Using CloseDelayed will delay Close until we are out of } + { current event handler. } + Client.CloseDelayed + else if CompareText(Client.Param[0], 'time') = 0 then + { Send server date and time to client } + Client.SendStr(DateTimeToStr(Now) + #13#10) + else if CompareText(Client.Param[0], 'who') = 0 then begin + { Send client list to client } + Client.SendStr('There are ' + IntToStr(WSocketServer1.ClientCount) + + ' connected users:' + #13#10); + for I := WSocketServer1.ClientCount - 1 downto 0 do begin + AClient := TTcpSrvClient(WSocketServer1.Client[I]); + Client.SendStr(AClient.PeerAddr + ':' + AClient.GetPeerPort + ' ' + + DateTimeToStr(AClient.ConnectTime) + #13#10); + end; + end + else if CompareText(Client.Param[0], 'help') = 0 then begin + Client.SendStr('Commands are:' + #13#10 + + ' exit Close current session' + #13#10 + + ' time Display server time and date' + #13#10 + + ' who Display connected clients' + #13#10 + + ' help Show this help text' + #13#10); + end + else begin + if Client.State = wsConnected then + Client.SendStr('Unknown command: ''' + + Client.Param[0] + '''' + #13#10 + + 'Type help if you need help...' +#13#10); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when a client socket experience a background } +{ exception. It is likely to occurs when client aborted connection and data } +{ has not been sent yet. } +procedure TTcpDaemon.ClientBgException( + Sender : TObject; + E : Exception; + var CanClose : Boolean); +begin + Display('Client exception occured: ' + E.ClassName + ': ' + E.Message); + CanClose := TRUE; { Goodbye client ! } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpDaemon.Display(Msg: String); +begin + if Assigned(FOnDisplay) then + FOnDisplay(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpDaemon.Start; +begin + WSocketServer1.OnBgException := WSocketServer1BgException; + WSocketServer1.OnClientConnect := WSocketServer1ClientConnect; + WSocketServer1.OnClientDisconnect := WSocketServer1ClientDisconnect; + WSocketServer1.Proto := 'tcp'; + WSocketServer1.Port := FPort; + WSocketServer1.Addr := FAddr; + WSocketServer1.ClientClass := TTcpSrvClient; + WSocketServer1.Listen; + Display('Waiting for clients...'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpDaemon.Stop; +begin + WSocketServer1.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TTcpDaemon.GetBanner: String; +begin + Result := WSocketServer1.Banner; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpDaemon.SetBanner(const Value: String); +begin + WSocketServer1.Banner := Value; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. diff --git a/ICS_zlog/Delphi/Internet/TcpSrv.dpr b/ICS_zlog/Delphi/Internet/TcpSrv.dpr new file mode 100644 index 00000000..dee37a0b --- /dev/null +++ b/ICS_zlog/Delphi/Internet/TcpSrv.dpr @@ -0,0 +1,12 @@ +program TcpSrv; + +uses + Forms, + TcpSrv1 in 'TcpSrv1.pas' {TcpSrvForm}; + +{$R *.RES} + +begin + Application.CreateForm(TTcpSrvForm, TcpSrvForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/TcpSrv1.dfm b/ICS_zlog/Delphi/Internet/TcpSrv1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..d81da25673a38e1333a2cb0746910b07f152803c GIT binary patch literal 1215 zcmbVL&2AGh5cY1G{Y%moP=yc@%8^Q_YLO5ZF3C2bm6B}KHS|c$?j&pBwIkbUng>AQ z!i(@WJPc>BcT?I_oRBZy{Ceh_ncoq@IG&~#ABV}s7#;8b*g*(ShsQ09vqdVeheDRo z9o!kgOgG*;4J;OoZ%*@)=DKKncf2#8^FlWc96u%tO$GPvMKxo=g!IFV^)(-o4BA7% z^-)|9sX+UCr-Nbd!w7$h&w3Z>07td8ifL!;lJZ=vFx==?WvIV$e}$DaAtiX7aoSA@ zSKSmOoz?NFUNdN+-Gt?_1fn64ImpmYc+7+X--OGuf`L(09=?e*x(a&0I>yAxP# z5!)G24(ce?lJdE7y!#cSXiB81#7-!P(o71*`exX^r&M3);;vx_plI5iO}UJL(|ciUXc|ZYQdo23aA38s$_6&8ZYxcnzH`!jZ@b>*cxh z!jso;kB-edsg+Y9wdWjn#!IFtF3jk2$b+yFW1@7h`xl-sFdn&1cmYcVHd(MAi*g~j zX*8*JUbRps;r;pGCWA`hKih8Ro~b=#OI2W6f>>(zU6=yThm6dX-(D#zOw8U9)-qkr zK_)zz&HQMkZbi$!(ci|S$Wo|Aa1G3J-aM(K-clE)HkuK8kp6+PE)%h>_WFc#klv$9 zV3{bPt3|iI_jYZ;qQ6vY?`bNeT)#4A(JcvIce85OR5T_x_1Y;HJ+{YXSI}&4CQRN; f`!BXBcxd0d4T(4Y&;RAWG1iyxvO20Ob1Q!UpHqt; literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/TcpSrv1.pas b/ICS_zlog/Delphi/Internet/TcpSrv1.pas new file mode 100644 index 00000000..1066303d --- /dev/null +++ b/ICS_zlog/Delphi/Internet/TcpSrv1.pas @@ -0,0 +1,350 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François Piette +Creation: Aug 29, 1999 +Version: 1.04 +Description: Basic TCP server showing how to use TWSocketServer and + TWSocketClient components. +EMail: francois.piette@pophost.eunet.be francois.piette@rtfm.be + francois.piette@swing.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1999-2000 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. +History: +Sep 05, 1999 V1.01 Adapted for Delphi 1 +Oct 15, 2000 V1.02 Display remote and local socket binding when a client + connect. +Nov 11, 2000 V1.03 Implemented OnLineLimitExceeded event +Dec 15, 2001 V1.03 In command help changed #10#13 to the correct value #13#10. + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit TcpSrv1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, IniFiles, StdCtrls, ExtCtrls, WSocket, WSocketS; + +const + TcpSrvVersion = 104; + CopyRight = ' TcpSrv (c) 1999-2001 by François PIETTE. V1.04'; + WM_APPSTARTUP = WM_USER + 1; + +type + { TTcpSrvClient is the class which will be instanciated by server component } + { for each new client. N simultaneous clients means N TTcpSrvClient will be } + { instanciated. Each being used to handle only a single client. } + { We can add any data that has to be private for each client, such as } + { receive buffer or any other data needed for processing. } + TTcpSrvClient = class(TWSocketClient) + public + RcvdLine : String; + ConnectTime : TDateTime; + end; + + TTcpSrvForm = class(TForm) + ToolPanel: TPanel; + DisplayMemo: TMemo; + WSocketServer1: TWSocketServer; + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure WSocketServer1ClientConnect(Sender: TObject; + Client: TWSocketClient; Error: Word); + procedure WSocketServer1ClientDisconnect(Sender: TObject; + Client: TWSocketClient; Error: Word); + procedure WSocketServer1BgException(Sender: TObject; E: Exception; + var CanClose: Boolean); + private + FIniFileName : String; + FInitialized : Boolean; + procedure Display(Msg : String); + procedure WMAppStartup(var Msg: TMessage); message WM_APPSTARTUP; + procedure ClientDataAvailable(Sender: TObject; Error: Word); + procedure ProcessData(Client : TTcpSrvClient); + procedure ClientBgException(Sender : TObject; + E : Exception; + var CanClose : Boolean); + procedure ClientLineLimitExceeded(Sender : TObject; + Cnt : LongInt; + var ClearData : Boolean); + public + property IniFileName : String read FIniFileName write FIniFileName; + end; + +var + TcpSrvForm: TTcpSrvForm; + +implementation + +{$R *.DFM} + +const + SectionWindow = 'WindowTcpSrv'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpSrvForm.FormCreate(Sender: TObject); +begin + { Compute INI file name based on exe file name. Remove path to make it } + { go to windows directory. } + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpSrvForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + + { Fetch persistent parameters from INI file } + IniFile := TIniFile.Create(FIniFileName); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, + (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, + (Screen.Width - Width) div 2); + IniFile.Destroy; + DisplayMemo.Clear; + { Delay startup code until our UI is ready and visible } + PostMessage(Handle, WM_APPSTARTUP, 0, 0); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpSrvForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + { Save persistent data to INI file } + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Display a message in our display memo. Delete lines to be sure to not } +{ overflow the memo which may have a limited capacity. } +procedure TTcpSrvForm.Display(Msg : String); +var + I : Integer; +begin + DisplayMemo.Lines.BeginUpdate; + try + if DisplayMemo.Lines.Count > 200 then begin + for I := 1 to 50 do + DisplayMemo.Lines.Delete(0); + end; + DisplayMemo.Lines.Add(Msg); + finally + DisplayMemo.Lines.EndUpdate; + SendMessage(DisplayMemo.Handle, EM_SCROLLCARET, 0, 0); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This is our custom message handler. We posted a WM_APPSTARTUP message } +{ from FormShow event handler. Now UI is ready and visible. } +procedure TTcpSrvForm.WMAppStartup(var Msg: TMessage); +begin + Display(CopyRight); + Display(WSocket.Copyright); + Display(WSockets.CopyRight); + WSocketServer1.Proto := 'tcp'; { Use TCP protocol } + WSocketServer1.Port := 'telnet'; { Use telnet port } + WSocketServer1.Addr := '0.0.0.0'; { Use any interface } + WSocketServer1.ClientClass := TTcpSrvClient; { Use our component } + WSocketServer1.Listen; { Start litening } + Display('Waiting for clients...'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpSrvForm.WSocketServer1ClientConnect( + Sender : TObject; + Client : TWSocketClient; + Error : Word); +begin + with Client as TTcpSrvClient do begin + Display('Client connected.' + + ' Remote: ' + PeerAddr + '/' + PeerPort + + ' Local: ' + GetXAddr + '/' + GetXPort); + Display('There is now ' + + IntToStr(TWSocketServer(Sender).ClientCount) + + ' clients connected.'); + LineMode := TRUE; + LineEdit := TRUE; + LineLimit := 80; { Do not accept long lines } + OnDataAvailable := ClientDataAvailable; + OnLineLimitExceeded := ClientLineLimitExceeded; + OnBgException := ClientBgException; + ConnectTime := Now; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpSrvForm.WSocketServer1ClientDisconnect( + Sender : TObject; + Client : TWSocketClient; + Error : Word); +begin + with Client as TTcpSrvClient do begin + Display('Client disconnecting: ' + PeerAddr + ' ' + + 'Duration: ' + FormatDateTime('hh:nn:ss', + Now - ConnectTime)); + Display('There is now ' + + IntToStr(TWSocketServer(Sender).ClientCount - 1) + + ' clients connected.'); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpSrvForm.ClientLineLimitExceeded( + Sender : TObject; + Cnt : LongInt; + var ClearData : Boolean); +begin + with Sender as TTcpSrvClient do begin + Display('Line limit exceeded from ' + GetPeerAddr + '. Closing.'); + ClearData := TRUE; + Close; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpSrvForm.ClientDataAvailable( + Sender : TObject; + Error : Word); +begin + with Sender as TTcpSrvClient do begin + { We use line mode. We will receive complete lines } + RcvdLine := ReceiveStr; + { Remove trailing CR/LF } + while (Length(RcvdLine) > 0) and + (RcvdLine[Length(RcvdLine)] in [#13, #10]) do + RcvdLine := Copy(RcvdLine, 1, Length(RcvdLine) - 1); + Display('Received from ' + GetPeerAddr + ': ''' + RcvdLine + ''''); + ProcessData(Sender as TTcpSrvClient); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpSrvForm.ProcessData(Client : TTcpSrvClient); +var + I : Integer; + AClient : TTcpSrvClient; +begin + { We could replace all those CompareText with a table lookup } + if CompareText(Client.RcvdLine, 'help') = 0 then + Client.SendStr('Commands are:' + #13#10 + + ' exit' + #13#10 + + ' who' + #13#10 + + ' time' + #13#10 + + ' exception' + #13#10) + else if CompareText(Client.RcvdLine, 'exit') = 0 then + { We can't call Client.Close here because we will immediately } + { reenter DataAvailable event handler with same line because } + { a line is removed from buffer AFTER it has been processed. } + { Using CloseDelayed will delay Close until we are out of } + { current event handler. } + Client.CloseDelayed + else if CompareText(Client.RcvdLine, 'time') = 0 then + { Send server date and time to client } + Client.SendStr(DateTimeToStr(Now) + #13#10) + else if CompareText(Client.RcvdLine, 'who') = 0 then begin + { Send client list to client } + Client.SendStr('There are ' + IntToStr(WSocketServer1.ClientCount) + + ' connected users:' + #13#10); + for I := WSocketServer1.ClientCount - 1 downto 0 do begin + AClient := TTcpSrvClient(WSocketServer1.Client[I]); + Client.SendStr(AClient.PeerAddr + ':' + AClient.GetPeerPort + ' ' + + DateTimeToStr(AClient.ConnectTime) + #13#10); + end; + end + else if CompareText(Client.RcvdLine, 'exception') = 0 then + { This will trigger a background exception for client } + PostMessage(Client.Handle, WM_TRIGGER_EXCEPTION, 0, 0) + else + if Client.State = wsConnected then + Client.SendStr('Unknown command: ''' + Client.RcvdLine + '''' + #13#10); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when listening (server) socket experienced } +{ a background exception. Should normally never occurs. } +procedure TTcpSrvForm.WSocketServer1BgException( + Sender : TObject; + E : Exception; + var CanClose : Boolean); +begin + Display('Server exception occured: ' + E.ClassName + ': ' + E.Message); + CanClose := FALSE; { Hoping that server will still work ! } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when a client socket experience a background } +{ exception. It is likely to occurs when client aborted connection and data } +{ has not been sent yet. } +procedure TTcpSrvForm.ClientBgException( + Sender : TObject; + E : Exception; + var CanClose : Boolean); +begin + Display('Client exception occured: ' + E.ClassName + ': ' + E.Message); + CanClose := TRUE; { Goodbye client ! } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/ThrdSrv.dpr b/ICS_zlog/Delphi/Internet/ThrdSrv.dpr new file mode 100644 index 00000000..1b795032 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/ThrdSrv.dpr @@ -0,0 +1,12 @@ +program ThrdSrv; + +uses + Forms, + ThrdSrv1 in 'ThrdSrv1.pas' {TcpSrvForm}; + +{$R *.RES} + +begin + Application.CreateForm(TTcpSrvForm, TcpSrvForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/TnCli1.dfm b/ICS_zlog/Delphi/Internet/TnCli1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..48e4ee523011ec9fe9bdf99a2b1fbfdc4e540ccc GIT binary patch literal 2260 zcmb_d%W~T`6on{>1VyP<+&ELuG##xxUS;g8vb7j-dc)*I(D_h^_0tgXV1<@~D1mm_rgTBVPZlX1RFHV@A!FeVoNXPhoqr zlr2-dYPu|8sbvRApHmM9r0p@v-?$M@Gs3N-_XF?hW`urrhgWldfLiLS#I%FtHl`ta zK;)4-@`Gw>{B6tK1h0tM8T&mS)2!!{G+rpY&z}q!aO81tQ?uglg(G^29x@v~T+hT-9r<@=hvW$yUfnEGtg+G`0ivs`cA-*wVDKD{( z&oSR*l7YI$uV9D4yTc0G7yxX9=wP);J|bH$F6#&{4WJ0Aau>;`~MKaUt2cP6k25 zpeY!QJoVq5!^V#Z=5}k$D08Eftq81-*b+A8>>)Ew8@ZS>V+Q*;xK|NdEDMQ$;@M9m zNpg)$r6Dq>{fVdQ27Ql(Zn6j?VI(QqQ4YzsK3dNPCKrOsojpu&kLh`&@w-*jCNMQs?pcv z>ktR`*6~hBH_2lFG|?c8d0QJ)Y?KFv(o(SK^`v{9RF#c}cp1zctS$(JWA}?`;?EVU zt70Xtnnd?~oCSx&IG0bip=&-f4CkyuS_6vj5)#6Sexn@BNtLI@UCc(`Maw5N+`fn} z|JhqYdP8BGs$;Y4cvMx~>(wbd_Dnl{7tb6Oo)xgFnOQbF-YHr1vymH-;J(iuUzD$g zjwrSLsSc^1WvmtOqEuT;B75?|DXngmeP10E-aG4ebMotkWW3Cq((Pk^RRr|0OVv~a zUTznVJbF`FjR2NZUT-G~zPi&Mqtk=D#o`%C-|xGkqI9xdp`f%_RGie0wXow4+nJJ+ J?p2Ti{{n2v%ZC5} literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/TnCli1.pas b/ICS_zlog/Delphi/Internet/TnCli1.pas new file mode 100644 index 00000000..aa2aafac --- /dev/null +++ b/ICS_zlog/Delphi/Internet/TnCli1.pas @@ -0,0 +1,268 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Program: TNCLIENT.PAS +Object: Delphi application which is a basic telnet program demonstrating + WSocket, TnCnx, TnEmulVT, EmulVT components. +Author: François PIETTE +Creation: July 22, 1997 +Version: 2.05 +EMail: francois.piette@pophost.eunet.be francois.piette@rtfm.be + http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998, 1999 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Sep 05, 1997 Added display of windows socket version info. +Sep 23, 1997 Added local echo check box +Sep 24, 1997 V2.03 Added TnEmulVT1.RestoreOptions just before connecting + Added interactive support for telnet echo option. +Sep 25, 1997 V2.04 Port to C++Builder +Dec 10, 1998 V2.05 Added IniFile to save config + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit TnCli1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, IniFiles, EmulVT, TnEmulVT, WSocket, Winsock; + +type + TTelnetForm = class(TForm) + TnEmulVT1: TTnEmulVT; + ConnectButton: TButton; + Label1: TLabel; + HostNameEdit: TEdit; + Label2: TLabel; + PortEdit: TEdit; + DisconnectButton: TButton; + StatusLabel: TLabel; + SendButton: TButton; + OptionsButton: TButton; + LocalEchoCheckBox: TCheckBox; + RequestLocalEchoOnButton: TButton; + RequestLocalEchoOffButton: TButton; + procedure ConnectButtonClick(Sender: TObject); + procedure FormResize(Sender: TObject); + procedure DisconnectButtonClick(Sender: TObject); + procedure TnEmulVT1SessionConnected(Sender: TObject); + procedure TnEmulVT1SessionClosed(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure SendButtonClick(Sender: TObject); + procedure OptionsButtonClick(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure LocalEchoCheckBoxClick(Sender: TObject); + procedure TnEmulVT1LocalEcho(Sender: TObject); + procedure RequestLocalEchoOnButtonClick(Sender: TObject); + procedure RequestLocalEchoOffButtonClick(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + private + FIniFileName : String; + FInitialized : Boolean; + public + { Déclarations publiques } + end; + +var + TelnetForm: TTelnetForm; + +implementation + +{$R *.DFM} +const + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + SectionData = 'Data'; + KeyHostName = 'HostName'; + KeyPort = 'Port'; + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTelnetForm.FormCreate(Sender: TObject); +begin + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; + StatusLabel.Caption := 'Not connected'; + TnEmulVT1.RestoreOptions; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTelnetForm.FormShow(Sender: TObject); +var + WinsockData : TWSADATA; + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + IniFile := TIniFile.Create(FIniFileName); + HostNameEdit.Text := IniFile.ReadString(SectionData, KeyHostName, + 'localhost'); + PortEdit.Text := IniFile.ReadString(SectionData, KeyPort, + 'telnet'); + + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, (Screen.Width - Width) div 2); + + IniFile.Free; + TnEmulVT1.Clear; + { Set auto-wrap mode. Here is the place to do other settings. } + TnEmulVT1.WriteStr(#27'[?7h'); + WinsockData := WinsockInfo; + StatusLabel.Caption := StrPas(WinsockData.szDescription); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTelnetForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteString(SectionData, KeyHostName, HostNameEdit.Text); + IniFile.WriteString(SectionData, KeyPort, PortEdit.Text); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTelnetForm.ConnectButtonClick(Sender: TObject); +begin + StatusLabel.Caption := 'Connecting'; + Refresh; + ConnectButton.Enabled := FALSE; + try + TnEmulVT1.Disconnect; + TnEmulVT1.Port := PortEdit.Text; + TnEmulVT1.HostName := HostNameEdit.Text; + TnEmulVT1.RestoreOptions; + { This can take quite a long time when hostname is unknown and } + { if DNS feature is enabled (2 or 3 minutes !) } + TnEmulVT1.Connect; + except + ConnectButton.Enabled := TRUE; + raise; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTelnetForm.DisconnectButtonClick(Sender: TObject); +begin + TnEmulVT1.Disconnect; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTelnetForm.TnEmulVT1SessionConnected(Sender: TObject); +begin + DisconnectButton.Enabled := TRUE; + StatusLabel.Caption := 'Connected'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTelnetForm.TnEmulVT1SessionClosed(Sender: TObject); +begin + DisconnectButton.Enabled := FALSE; + ConnectButton.Enabled := TRUE; + StatusLabel.Caption := 'Not connected'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTelnetForm.FormResize(Sender: TObject); +begin + TnEmulVT1.Width := ClientWidth; + TnEmulVT1.Height := ClientHeight - TnEmulVT1.Top; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTelnetForm.SendButtonClick(Sender: TObject); +begin + TnEmulVT1.SendStr('Hello world !' + #13#10); + ActiveControl := TnEmulVT1; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTelnetForm.OptionsButtonClick(Sender: TObject); +begin + TnEmulVT1.HostName := HostNameEdit.Text; + TnEmulVT1.EditOptions; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTelnetForm.TnEmulVT1LocalEcho(Sender: TObject); +begin + if TnEmulVT1.GetLocalEcho then + StatusLabel.Caption := 'Remote will not echo' + else + StatusLabel.Caption := 'Remote will echo'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTelnetForm.LocalEchoCheckBoxClick(Sender: TObject); +begin + TnEmulVT1.LocalEcho := LocalEchoCheckBox.Checked; + ActiveControl := TnEmulVT1; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTelnetForm.RequestLocalEchoOnButtonClick(Sender: TObject); +begin + TnEmulVT1.RequestLocalEcho(TRUE); + ActiveControl := TnEmulVT1; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTelnetForm.RequestLocalEchoOffButtonClick(Sender: TObject); +begin + TnEmulVT1.RequestLocalEcho(FALSE); + ActiveControl := TnEmulVT1; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + + +end. + diff --git a/ICS_zlog/Delphi/Internet/UdpLstn1.dfm b/ICS_zlog/Delphi/Internet/UdpLstn1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..362aaa7d00813bcfd4d450ceb545a9acd0be3a13 GIT binary patch literal 1592 zcmah}+iuf95ZyS5FS+yv1@S~B1mXczDH2FXeMy}}jq22)-l{wx!PcI{R-N6*-t_Vh zd<>t&C-A~Ecz125Aw?(;nVFq)X6EdAem4*vb%&<|_iThZTQ7Bl@OaR%@Q6foz>=9+ z7&QkbT-&Z;wo0HwhrIS}wI?mcqvcBzMM!7;fq7F7-loW0)c= ztoAs%g*Y8UGNgW}eQk&~@&?*S#}2uKc&A4=>0Xm4CYLeDkdkRj%5>wT5)U*2p?J*_(B;C7|TcCH_EmQ~i!)JI#MHnCHFm-kc@;FM_u#1TS)e=j$!# znf}+1AY|a91?P-5Jx&s?Y^8}Qn=o^ZlY-+}sfqqdVvHV4$Rg&JiOHqBIt>}(?jrxn z*t$n6Bg={nkF)vxf}j3Zuk9vdrd^E3Z<={UGAzIMYZNN|zr>*kYy+#Z0?P zPOT;$j$Q&0QcMjc*c#VfuFpeURmF7=YG%5Ggiaw7MqYs6QxSwLY=_`q9kJW(F1=Id zMMU-gx*{biY918*ZnT?L6GQ1XJ7tmLV3OVzSF6X6ULcdT?BK>VLpjh@>EDB zS32!c_KqSPW?LYDz_g@mla!kqr8%5q>}VD13>GN}Ds#(bvpJ(cxhpqX+C-Z!UHR0F z$N6+C(Jae@G|iTvTr5GEwG!P~W-&^^=MWfAbGjn2IA{&xMH=F025iB#L(2mi3}P}( zjn+*noYQPwk+_*jIfcZf?qp&#ZqmYSE2F@phPay4foq8M%DYF>>n?bhjT-qxY;R*X T6)C4|HLRY?Pxagn5kh|ea-j0g literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/UdpLstn1.pas b/ICS_zlog/Delphi/Internet/UdpLstn1.pas new file mode 100644 index 00000000..59fc2228 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/UdpLstn1.pas @@ -0,0 +1,288 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Copyright: You can use this software freely, at your own risks +Creation: April 4, 1997 +Version: 2.03 +Object: Demo program to show how to use TWSocket object to listen + UDP messages from the network. Use UDPSend or any other + program to send UDP messages. +EMail: francois.piette@overbyte.be http://www.overbyte.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 1997, 2002 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Jul 23, 1997 Adapted for Delphi 1, 2 and 3 +Sep 06, 1997 Version 2.01 +Sep 27, 1997 Updated for TWSocket changes + Replace loopback address by real localhost IP addr +Dec 12, 1998 V2.02 Added icomming IP and port number display +Mar 07, 1999 V2.03 Corrected compatibility bug with Delphi 1 + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit UdpLstn1; + +{$J+} + +interface + +uses + WinTypes, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + FormPos, StdCtrls, WinSock, WSocket, IniFiles; + +type + TMainForm = class(TForm) + WSocket: TWSocket; + StartButton: TButton; + DataAvailableLabel: TLabel; + InfoLabel: TLabel; + StopButton: TButton; + PortEdit: TEdit; + Label1: TLabel; + Label2: TLabel; + ServerEdit: TEdit; + AnyServerCheckBox: TCheckBox; + procedure StartButtonClick(Sender: TObject); + procedure WSocketDataAvailable(Sender: TObject; Error: Word); + procedure WSocketSessionConnected(Sender: TObject; Error: Word); + procedure StopButtonClick(Sender: TObject); + procedure WSocketSessionClosed(Sender: TObject; Error: Word); + procedure FormShow(Sender: TObject); + procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); + procedure AnyServerCheckBoxClick(Sender: TObject); + procedure ServerEditChange(Sender: TObject); + private + { Déclarations privées } + FIniFileName : String; + FSectionName : String; + FKeyName : String; + FServerAddr : TInAddr; + public + { Déclarations publiques } + end; + +var + MainForm: TMainForm; + +implementation + +{$R *.DFM} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFNDEF WIN32} +function TrimRight(Str : String) : String; +var + i : Integer; +begin + i := Length(Str); + while (i > 0) and (Str[i] = ' ') do + i := i - 1; + Result := Copy(Str, 1, i); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFNDEF WIN32} +function TrimLeft(Str : String) : String; +var + i : Integer; +begin + if Str[1] <> ' ' then { Petite optimisation: pas d'espace } + Result := Str + else begin + i := 1; + while (i <= Length(Str)) and (Str[i] = ' ') do + i := i + 1; + Result := Copy(Str, i, Length(Str) - i + 1); + end; +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFNDEF WIN32} +function Trim(Str : String) : String; +begin + Result := TrimLeft(TrimRight(Str)); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMainForm.StartButtonClick(Sender: TObject); +begin + FServerAddr := WSocketResolveHost(ServerEdit.Text); + if FServerAddr.S_addr = htonl(INADDR_LOOPBACK) then begin + { Replace loopback address by real localhost IP addr } + FServerAddr := WSocketResolveHost(LocalHostName); + end; + WSocket.Proto := 'udp'; + WSocket.Addr := '0.0.0.0'; + WSocket.Port := PortEdit.Text; + WSocket.Listen; + PortEdit.Enabled := FALSE; + ServerEdit.Enabled := FALSE; + AnyServerCheckBox.Enabled := FALSE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function atoi(value : string) : Integer; +var + i : Integer; +begin + Result := 0; + i := 1; + while (i <= Length(Value)) and (Value[i] = ' ') do + i := i + 1; + while (i <= Length(Value)) and (Value[i] in ['0'..'9']) do begin + Result := Result * 10 + ord(Value[i]) - ord('0'); + i := i + 1; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMainForm.WSocketDataAvailable(Sender: TObject; Error: Word); +var + Buffer : array [0..1023] of char; + Len : Integer; + Src : TSockAddrIn; + SrcLen : Integer; +begin + SrcLen := SizeOf(Src); + Len := WSocket.ReceiveFrom(@Buffer, SizeOf(Buffer), Src, SrcLen); + if Len >= 0 then begin + if (FServerAddr.S_addr = INADDR_ANY) or + (FServerAddr.S_addr = Src.Sin_addr.S_addr) then begin + Buffer[Len] := #0; + DataAvailableLabel.Caption := IntToStr(atoi(DataAvailableLabel.caption) + 1) + + ' ' + StrPas(inet_ntoa(Src.sin_addr)) + + ':' + IntToStr(ntohs(Src.sin_port)) + + '--> ' + StrPas(Buffer); + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMainForm.WSocketSessionConnected(Sender: TObject; + Error: Word); +begin + StartButton.Enabled := FALSE; + StopButton.Enabled := TRUE; + InfoLabel.Caption := 'Connected'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMainForm.StopButtonClick(Sender: TObject); +begin + StartButton.Enabled := TRUE; + StopButton.Enabled := FALSE; + PortEdit.Enabled := TRUE; + ServerEdit.Enabled := TRUE; + AnyServerCheckBox.Enabled := TRUE; + WSocket.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMainForm.WSocketSessionClosed(Sender: TObject; Error: Word); +begin + StartButton.Enabled := TRUE; + StopButton.Enabled := FALSE; + PortEdit.Enabled := TRUE; + ServerEdit.Enabled := TRUE; + AnyServerCheckBox.Enabled := TRUE; + InfoLabel.Caption := 'Disconnected'; + DataAvailableLabel.Caption := ''; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMainForm.FormShow(Sender: TObject); +const + FirstTime : Boolean = TRUE; +var + IniFile : TIniFile; +begin + if FirstTime then begin + FirstTime := FALSE; + FIniFileName := 'UdpLstn'; + FSectionName := 'Windows'; + FKeyName := 'MainForm'; + LoadFormPos(Self, FIniFilename, FSectionName, FKeyName); + DataAvailableLabel.Caption := ''; + InfoLabel.Caption := 'Click on Start button'; + StartButton.Enabled := TRUE; + StopButton.Enabled := FALSE; + IniFile := TIniFile.Create(FIniFileName); + PortEdit.Text := IniFile.ReadString('data', 'port', '600'); + ServerEdit.Text := IniFile.ReadString('data', 'server', '0.0.0.0'); + IniFile.Free; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMainForm.FormCloseQuery(Sender: TObject; + var CanClose: Boolean); +var + IniFile : TIniFile; +begin + SaveFormPos(Self, FIniFilename, FSectionName, FKeyName); + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteString('data', 'port', PortEdit.Text); + IniFile.WriteString('data', 'server', ServerEdit.Text); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMainForm.AnyServerCheckBoxClick(Sender: TObject); +begin + if AnyServerCheckBox.Checked then + ServerEdit.Text := '0.0.0.0'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMainForm.ServerEditChange(Sender: TObject); +begin + AnyServerCheckBox.Checked := (Trim(ServerEdit.Text) = '0.0.0.0'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/UdpSend1.dfm b/ICS_zlog/Delphi/Internet/UdpSend1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..5c7d050d63df3ff1264cff950eabde1785b0a9af GIT binary patch literal 1338 zcmai!&2G~`5XU!m(C#MV%@unXRQ$?G0t0$x;aI0 zgcv`n`ZS}t?M7LblK@4y5m3U9{RHI<_TszB}fX^n$ettZO#*|_ZOwN@uC2={|41U8lkK;R0tb(=bTeglj>_z zbG~a%v*5fcIrrBERUgP0`vi~CJmand(T$SI0JhXBjc)C|4OJZgP=&oX<@G*h3{9}K zb^A@#ev!@m3d(ec8*F7qifH{FTk;&)%m%hpu%|`oNB>|MnzfEAL7viPi)J<}|HYXa zw;k;W6%s@y*xuiw>O%lr=qEV3?b795hpc4I(%+iouxR65*~T5Wlcf_f#e~})M{>)~ z=i+LNSL@N-9jzG0(^iyFab?wQ+32{l9?!uad5al2@Ong}Td`rquM?&O_i2nBS6X2@ z6=MUS0&MB_NNgEiO+C~T869nj(K^*(PC2zq9?e{(K_`xL%Wfa5k3N!(Ta~ug7ndl7 ziCDQ9$BwI9U%UmJ-L-i(gD^BI?j@cxEKyF=r_&iFLW+TUldw8y1lgP=Fr8vL=f+D{ zUcn$k6J|FSOga~0M^RQ6rB84^AcOJPt}R&UdfF)CK}|}*Li}FrYvtL#@;Y;#h?Hrh WmeD?B@{tR=eXNK0Nw1Lu0Qd!b&ZEcx literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/UdpSend1.pas b/ICS_zlog/Delphi/Internet/UdpSend1.pas new file mode 100644 index 00000000..a1a62203 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/UdpSend1.pas @@ -0,0 +1,150 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Copyright: You can use this software freely, at your own risks +Creation: April 4, 1997 +Version: 2.02 +Object: Demo program to show how to use TWSocket object to broadcast + UDP messages on the network. Use UDPLstn to listen to those + UDP messages, or other UDP messages. +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Sep 06, 1997 Version 2.01 +Dec 12, 1998 V2.02 Added LocalPort editbox + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit UdpSend1; + +{$J+} + +interface + +uses + WinTypes, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + FormPos, StdCtrls, WSocket, IniFiles; + +type + TMainForm = class(TForm) + WSocket: TWSocket; + SendButton: TButton; + MessageEdit: TEdit; + PortEdit: TEdit; + Label1: TLabel; + Label2: TLabel; + LocalPortEdit: TEdit; + AnyPortCheckBox: TCheckBox; + procedure FormShow(Sender: TObject); + procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); + procedure SendButtonClick(Sender: TObject); + procedure AnyPortCheckBoxClick(Sender: TObject); + procedure LocalPortEditChange(Sender: TObject); + private + FIniFileName : String; + FSectionName : String; + FKeyName : String; + end; + +var + MainForm: TMainForm; + +implementation + +{$R *.DFM} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMainForm.FormShow(Sender: TObject); +const + FirstTime : Boolean = TRUE; +var + IniFile : TIniFile; +begin + if FirstTime then begin + FirstTime := FALSE; + FIniFileName := 'UdpSend'; + FSectionName := 'Windows'; + FKeyName := 'MainForm'; + LoadFormPos(Self, FIniFilename, FSectionName, FKeyName); + IniFile := TIniFile.Create(FIniFileName); + PortEdit.Text := IniFile.ReadString('data', 'Port', '600'); + LocalPortEdit.Text := IniFile.ReadString('data', 'LocalPort', '0'); + MessageEdit.Text := IniFile.ReadString('data', 'Message', ''); + IniFile.Free; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMainForm.FormCloseQuery(Sender: TObject; + var CanClose: Boolean); +var + IniFile : TIniFile; +begin + SaveFormPos(Self, FIniFilename, FSectionName, FKeyName); + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteString('data', 'Port', PortEdit.Text); + IniFile.WriteString('data', 'LocalPort', LocalPortEdit.Text); + IniFile.WriteString('data', 'Message', MessageEdit.Text); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMainForm.SendButtonClick(Sender: TObject); +begin + WSocket.Proto := 'udp'; + WSocket.Addr := '255.255.255.255'; + WSocket.Port := PortEdit.Text; + WSocket.LocalPort := LocalPortEdit.Text; + WSocket.Connect; + WSocket.SendStr(MessageEdit.Text); + WSocket.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMainForm.AnyPortCheckBoxClick(Sender: TObject); +begin + if AnyPortCheckBox.Checked then + LocalPortEdit.Text := '0'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMainForm.LocalPortEditChange(Sender: TObject); +begin + AnyPortCheckBox.Checked := (LocalPortEdit.Text = '0'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/WebServ.dpr b/ICS_zlog/Delphi/Internet/WebServ.dpr new file mode 100644 index 00000000..d939950d --- /dev/null +++ b/ICS_zlog/Delphi/Internet/WebServ.dpr @@ -0,0 +1,12 @@ +program WebServ; + +uses + Forms, + WebServ1 in 'WebServ1.pas' {WebServForm}; + +{$R *.RES} + +begin + Application.CreateForm(TWebServForm, WebServForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/WebServ1.dfm b/ICS_zlog/Delphi/Internet/WebServ1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..2512f9b5e217eacec941e8de0fb3b06eb6af73b3 GIT binary patch literal 2290 zcmb_d-EQMV6rMPVo!Cv=T_`^S2_vDsL1f!SyJER(oP@5FZlc;tZjk82K1r-jW}@+Q z)4m3mh=<|<_5$$?a1G-b|D_3t3lu3jo;lxlzBy;+oWE=oOb0!GaP|Fge07OVkKeTr z3MRwTgJ23XANboL<143PH%2fQ^|M+%VC(v-)||$XSk`|w%nOJYOHqGOvpl>OF{9>} zuRPz)pupWeteE?iyA)#m?bD~5&8ExV0-xOr=+2<&F~Ydj4oOeYAr9eS$f)RgOUx4x z)=_^jJbyC^e)KNRulzw^>s^I82+1_25!(cCCmgk*wHSZ4)z@ph0<&}JyFR9gD-RXV zHQpEZ1RQiYCXvSh3mEeVc-tCNkFW$R3Fj+iw&arXuq0BhDcc-Vf5|phD_u&h&LqAA zl1zZVqT$lGwo^r!mJTw538p~ofHCQlnkttDN>gc|ER#RwnKWKD&q=(XRudEH&6Iw*Q_qUOdzMmrLno*JmVzCR0OnQ2zx;>PC{Rh?EF{Zo zR?uad+kv-)@TSM^PWo}OCiwmWuxuFlsxHWHI%=LLoEPL#QINw7?P_=#-9)I2@&1&@ z0!C~xj0x-wk-xP)As#8PE0{~z!ktToGKy84@#B3Vvct+paVZ7VgMq!DBf|Uc+Xqfp|eiN3IbXC9V#)0;OsE-A + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +History: +May 21, 2000 V1.01 Worked around a bug with Delphi 3 and lpVendorInfo +Oct 07, 2001 V1.02 Added Logfile feature + Added display if time and IP Addr for GET command. + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit WebServ1; +{$I+} + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, IniFiles, StdCtrls, ExtCtrls, WinSock, WSocket, WSocketS, HttpSrv; + +const + CopyRight : String = 'WebServ (c) 1999-2001 F. Piette V1.02 '; + +type + { This component is used for client connection instead of default one. } + { This enables to add any data we need to handle our application. } + { As this data is located in client component, each connected client has } + { his own private data. } + TMyHttpConnection = class(THttpConnection) + protected + FPostedDataBuffer : PChar; { Will hold dynamically allocated buffer } + FPostedDataSize : Integer; { Databuffer size } + FDataLen : Integer; { Keep track of received byte count. } + public + destructor Destroy; override; + end; + + { This is the main form for our application. Any data here is global for } + { all clients. Put provate data in TMyHttpConnection class (see above). } + TWebServForm = class(TForm) + ToolsPanel: TPanel; + DisplayMemo: TMemo; + HttpServer1: THttpServer; + Label1: TLabel; + DocDirEdit: TEdit; + Label2: TLabel; + DefaultDocEdit: TEdit; + StartButton: TButton; + StopButton: TButton; + Label3: TLabel; + PortEdit: TEdit; + ClientCountLabel: TLabel; + Label5: TLabel; + ClearButton: TButton; + DisplayHeaderCheckBox: TCheckBox; + WriteLogFileCheckBox: TCheckBox; + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure HttpServer1GetDocument(Sender, Client: TObject; + var Flags: THttpGetFlag); + procedure StartButtonClick(Sender: TObject); + procedure StopButtonClick(Sender: TObject); + procedure HttpServer1ClientConnect(Sender: TObject; + Client: TObject; Error: Word); + procedure HttpServer1ClientDisconnect(Sender: TObject; + Client: TObject; Error: Word); + procedure HttpServer1ServerStarted(Sender: TObject); + procedure HttpServer1ServerStopped(Sender: TObject); + procedure HttpServer1HeadDocument(Sender, Client: TObject; + var Flags: THttpGetFlag); + procedure HttpServer1PostedData(Sender: TObject; + Client: TObject; Error: Word); + procedure HttpServer1PostDocument(Sender, Client: TObject; + var Flags: THttpGetFlag); + procedure ClearButtonClick(Sender: TObject); + procedure WriteLogFileCheckBoxClick(Sender: TObject); + private + FIniFileName : String; + FInitialized : Boolean; + FCountRequests : Integer; + FLogFile : TextFile; + FLogFileName : String; + FLogFileOpened : Boolean; + procedure CreateVirtualDocument_time_htm(Sender : TObject; + Client : TObject; + var Flags : THttpGetFlag); + procedure DisplayHeader(Client : TMyHttpConnection); + procedure ProcessPostedData_CgiFrm1(Client : TMyHttpConnection); + procedure CloseLogFile; + procedure OpenLogFile; + public + procedure Display(Msg : String); + property IniFileName : String read FIniFileName write FIniFileName; + end; + +var + WebServForm: TWebServForm; + +implementation + +{$R *.DFM} + +const + { IniFile layout for persistent data } + SectionWindow = 'WindowMain'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + SectionData = 'Data'; + KeyDocDir = 'DocDir'; + KeyDefaultDoc = 'DefaultDoc'; + KeyPort = 'Port'; + KeyDisplayHeader = 'DisplayHeader'; + KeyLogToFile = 'LogToFile'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +function TrimRight(Str : String) : String; +var + i : Integer; +begin + i := Length(Str); + while (i > 0) and (Str[i] = ' ') do + i := i - 1; + Result := Copy(Str, 1, i); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TrimLeft(Str : String) : String; +var + i : Integer; +begin + if Str[1] <> ' ' then + Result := Str + else begin + i := 1; + while (i <= Length(Str)) and (Str[i] = ' ') do + i := i + 1; + Result := Copy(Str, i, Length(Str) - i + 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function Trim(Str : String) : String; +begin + Result := TrimLeft(TrimRight(Str)); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TWebServForm.FormCreate(Sender: TObject); +begin + { Create IniFileName based on EXE file name; } + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; + FLogFileName := Application.ExeName; + FLogFileName := Copy(FLogFileName, 1, Length(FLogFileName) - 3) + '.log' +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TWebServForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; + wsi : TWSADATA; +begin + if not FInitialized then begin + FInitialized := TRUE; + + { Restore persistent data from INI file } + IniFile := TIniFile.Create(FIniFileName); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, + (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, + (Screen.Width - Width) div 2); + DocDirEdit.Text := IniFile.ReadString(SectionData, KeyDocDir, + 'c:\WwwRoot'); + DefaultDocEdit.Text := IniFile.ReadString(SectionData, KeyDefaultDoc, + 'index.html'); + PortEdit.Text := IniFile.ReadString(SectionData, KeyPort, + '80'); + DisplayHeaderCheckBox.Checked := + Boolean(IniFile.ReadInteger(SectionData, KeyDisplayHeader, 0)); + WriteLogFileCheckBox.Checked := + Boolean(IniFile.ReadInteger(SectionData, KeyLogToFile, 0)); + IniFile.Destroy; + { Start log file } + if WriteLogFileCheckBox.Checked then begin + OpenLogFile; + WriteLogFileCheckBox.Checked := FLogFileOpened; + end; + { Initialize client count caption } + ClientCountLabel.Caption := '0'; + { Display version info for program and used components } + wsi := WinsockInfo; + DisplayMemo.Clear; + Display(CopyRight); + Display('Using:'); + Display(' ' + WSocket.CopyRight); + Display(' ' + WSocketS.CopyRight); + Display(' ' + HttpSrv.CopyRight); + Display(' Winsock:'); + Display(' Version ' + + Format('%d.%d', [WinsockInfo.wHighVersion shr 8, + WinsockInfo.wHighVersion and 15])); + Display(' ' + StrPas(@wsi.szDescription)); + Display(' ' + StrPas(@wsi.szSystemStatus)); +{$IFNDEF VER100} + { A bug in Delphi 3 makes lpVendorInfo invalid } + if wsi.lpVendorInfo <> nil then + Display(' ' + StrPas(wsi.lpVendorInfo)); +{$ENDIF} + { Automatically start server } + StartButtonClick(Self); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TWebServForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + { Save persistent data to INI file } + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.WriteString(SectionData, KeyDocDir, HttpServer1.DocDir); + IniFile.WriteString(SectionData, KeyDefaultDoc, HttpServer1.DefaultDoc); + IniFile.WriteString(SectionData, KeyPort, HttpServer1.Port); + IniFile.WriteInteger(SectionData, KeyDisplayHeader, + ord(DisplayHeaderCheckBox.Checked)); + IniFile.WriteInteger(SectionData, KeyLogToFile, + ord(WriteLogFileCheckBox.Checked)); + IniFile.Destroy; + CloseLogFile; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Display a message in display memo box, making sure we don't overflow it. } +procedure TWebServForm.Display(Msg : String); +begin + DisplayMemo.Lines.BeginUpdate; + try + { We preserve only 200 lines } + while DisplayMemo.Lines.Count > 200 do + DisplayMemo.Lines.Delete(0); + DisplayMemo.Lines.Add(Msg); + finally + DisplayMemo.Lines.EndUpdate; + { Makes last line visible } + {$IFNDEF VER80} + SendMessage(DisplayMemo.Handle, EM_SCROLLCARET, 0, 0); + {$ENDIF} + end; + if FLogFileOpened then begin + try + WriteLn(FLogFile, Msg); + except + on E:Exception do begin + DisplayMemo.Lines.Add('*** Exception' + + E.CLassName + ': ' + E.Message + + ' writing to log file ***'); + end; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when user clicks on start button. It is also } +{ called from FormShow event handler, at program startup. It starts server. } +{ We need to pass default document, document directory and client class } +{ to HTTP server component. Client class is very usefull because it } +{ instruct server component to instanciate our own client class instead of } +{ defualt client class. Using our own client class will enables you to add } +{ any data we need to handle our application. This data is private for each } +{ client. } +{ When server is started, we will get OnServerStarted event triggered. } +procedure TWebServForm.StartButtonClick(Sender: TObject); +begin + HttpServer1.DocDir := Trim(DocDirEdit.Text); + HttpServer1.DefaultDoc := Trim(DefaultDocEdit.Text); + HttpServer1.Port := Trim(PortEdit.Text); + HttpServer1.ClientClass := TMyHttpConnection; + HttpServer1.Start; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is triggered when user clicks on stop button. We just } +{ stop the server. We will get OnServerStopped event triggered. } +procedure TWebServForm.StopButtonClick(Sender: TObject); +begin + HttpServer1.Stop; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is triggered when user clicks on clear buttoN; We just } +{ clear the memo used for displaying activity. } +procedure TWebServForm.ClearButtonClick(Sender: TObject); +begin + DisplayMemo.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is triggered when HTTP server is started, that is when } +{ server socket has started listening. } +procedure TWebServForm.HttpServer1ServerStarted(Sender: TObject); +begin + DocDirEdit.Enabled := FALSE; + DefaultDocEdit.Enabled := FALSE; + PortEdit.Enabled := FALSE; + StartButton.Enabled := FALSE; + StopButton.Enabled := TRUE; + Display('Server is waiting for connections'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is triggered when server has been stopped, that is } +{ when server socket stop listening. } +procedure TWebServForm.HttpServer1ServerStopped(Sender: TObject); +begin + DocDirEdit.Enabled := TRUE; + DefaultDocEdit.Enabled := TRUE; + PortEdit.Enabled := TRUE; + StartButton.Enabled := TRUE; + StopButton.Enabled := FALSE; + Display('Server stopped'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is triggered when a new client has connected. } +procedure TWebServForm.HttpServer1ClientConnect( + Sender : TObject; { HTTP server component } + Client : TObject; { Client connecting } + Error : Word); { Error in connection } +begin + ClientCountLabel.Caption := IntToStr(HttpServer1.ClientCount); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is triggered when a client is disconnecting, just } +{ before client component is closed. } +procedure TWebServForm.HttpServer1ClientDisconnect( + Sender : TObject; { HTTP server component } + Client : TObject; { Client connecting } + Error : Word); { Error in disconnection } +begin + ClientCountLabel.Caption := IntToStr(HttpServer1.ClientCount - 1); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is triggered when HTTP server component receive a HEAD } +{ command from any client. } +{ We just count the request, display a message and let HTTP server } +{ component handle everything. } +{ We should trap every URI we handle internally... } +procedure TWebServForm.HttpServer1HeadDocument( + Sender : TObject; { HTTP server component } + Client : TObject; { Client connection issuing command } + var Flags : THttpGetFlag); { Tells what HTTP server has to do next } +begin + Inc(FCountRequests); + Display(IntToStr(FCountRequests) + + ': HEAD ' + TMyHttpConnection(Client).Path); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is triggered when HTTP server component receive a GET } +{ command from any client. } +{ We count the request, display a message and trap '/time.htm' path for } +{ special handling. } +{ There is no document time.htm on disk, we will create it on the fly. With } +{ a classic webserver we would have used a CGI or ISAPI/NSAPI to achieve } +{ the same goal. It is much easier here since we can use Delphi code } +{ directly to generate whatever we wants. Here for the demo we generate a } +{ page with server data and time displayed. } +procedure TWebServForm.HttpServer1GetDocument( + Sender : TObject; { HTTP server component } + Client : TObject; { Client connection issuing command } + var Flags : THttpGetFlag); { Tells what HTTP server has to do next } +begin + { Count request and display a message } + Inc(FCountRequests); + Display('[' + FormatDateTime('HH:NN:SS', Now) + ' ' + + TWSocket(Client).GetPeerAddr + '] ' + IntToStr(FCountRequests) + + ': GET ' + TMyHttpConnection(Client).Path); + DisplayHeader(TMyHttpConnection(Client)); + + { Trap '/time.htm' path to dynamically generate an answer. } + if CompareText(THttpConnection(Client).Path, '/time.htm') = 0 then + CreateVirtualDocument_time_htm(Sender, Client, Flags); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This procedure is use to generate /time.htm document } +procedure TWebServForm.CreateVirtualDocument_time_htm( + Sender : TObject; { HTTP server component } + Client : TObject; { Client connection issuing command } + var Flags : THttpGetFlag); { Tells what HTTP server has to do next } +var + Body : String; + Header : String; + Stream : TMemoryStream; +begin + { Let HTTP server component know we will send data to client } + Flags := hgWillSendMySelf; + { Create a stream to hold data sent to client that is the answer } + { made of a HTTP header and a body made of HTML code. } + Stream := TMemoryStream.Create; + Body := '' + + '' + + 'ICS WebServer Demo' + + '' + #13#10 + + '' + + '

Time at server side:

' + #13#10 + + '

' + DateTimeToStr(Now) +'

' + #13#10 + + '' + + '' + #13#10; + Header := TMyHttpConnection(Client).Version + ' 200 OK' + #13#10 + + 'Content-Type: text/html' + #13#10 + + 'Content-Length: ' + + IntToStr(Length(Body)) + #13#10 + + #13#10; + Stream.Write(Header[1], Length(Header)); + Stream.Write(Body[1], Length(Body)); + { We need to seek to start of stream ! } + Stream.Seek(0, 0); + { We ask server component to send the stream for us. } + TMyHttpConnection(Client).DocStream := Stream; + TMyHttpConnection(Client).SendStream; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is triggered when HTTP server component receive a POST } +{ command from any client. } +{ We count the request, display a message and trap posted data. } +{ To check for posted data, you may construct the following HTML document: } +{ } +{ } +{ Test Form 1 } +{ } +{ } +{

Enter your first and last name

} +{
} +{ } +{ } +{ } +{ } +{ } +{ } +{ } +{ } +{ } +{
First name
Last name
} +{

} +{
} +{ } +{ } +procedure TWebServForm.HttpServer1PostDocument( + Sender : TObject; { HTTP server component } + Client : TObject; { Client connection issuing command } + var Flags : THttpGetFlag); { Tells what HTTP server has to do next } +var + Remote : TMyHttpConnection; +begin + { It's easyer to do the cast one time. Could use with clause... } + Remote := TMyHttpConnection(Client); + + { Count request and display a message } + Inc(FCountRequests); + Display(IntToStr(FCountRequests) + ': POST ' + Remote.Path); + DisplayHeader(Remote); + + { Check for request past. We only accept data for '/cgi-bin/cgifrm1.exe' } + if CompareText(Remote.Path, '/cgi-bin/cgifrm1.exe') = 0 then begin + { Tell HTTP server that we will accept posted data } + { OnPostedData event will be triggered when data comes in } + Flags := hgAcceptData; + { We wants to receive any data type. So we turn line mode off on } + { client connection. } + Remote.LineMode := FALSE; + { We need a buffer to hold posted data. We allocate as much as the } + { size of posted data plus one byte for terminating nul char. } + { We should check for ContentLength = 0 and handle that case... } +{$IFDEF VER80} + if Remote.FPostedDataSize = 0 then begin + Remote.FPostedDataSize := Remote.RequestContentLength + 1; + GetMem(Remote.FPostedDataBuffer, Remote.FPostedDataSize); + end + else begin + ReallocMem(Remote.FPostedDataBuffer, Remote.FPostedDataSize, Remote.RequestContentLength + 1); + Remote.FPostedDataSize := Remote.RequestContentLength + 1; + end; +{$ELSE} + ReallocMem(Remote.FPostedDataBuffer, Remote.RequestContentLength + 1); +{$ENDIF} + { Clear received length } + Remote.FDataLen := 0; + end + else + Flags := hg404; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is triggered for each data packet posted by client } +{ when we told HTTP server component that we will accept posted data. } +{ We have to receive ALL data which is sent by remote client, even if there } +{ is more than what ContentLength tells us ! } +{ If ContentLength = 0, then we should receive data until connection is } +{ closed... } +procedure TWebServForm.HttpServer1PostedData( + Sender : TObject; { HTTP server component } + Client : TObject; { Client posting data } + Error : Word); { Error in data receiving } +var + Len : Integer; + Remains : Integer; + Junk : array [0..255] of char; + Remote : TMyHttpConnection; +begin + { It's easyer to do the cast one time. Could use with clause... } + Remote := TMyHttpConnection(Client); + + { How much data do we have to receive ? } + Remains := Remote.RequestContentLength - Remote.FDataLen; + if Remains <= 0 then begin + { We got all our data. Junk anything else ! } + Len := Remote.Receive(@Junk, SizeOf(Junk) - 1); + if Len >= 0 then + Junk[Len] := #0; + Exit; + end; + { Receive as much data as we need to receive. But warning: we may } + { receive much less data. Data will be split into several packets we } + { have to assemble in our buffer. } + Len := Remote.Receive(Remote.FPostedDataBuffer + Remote.FDataLen, Remains); + { Sometimes, winsock doesn't wants to givve any data... } + if Len <= 0 then + Exit; + + { Add received length to our count } + Inc(Remote.FDataLen, Len); + { Add a nul terminating byte (handy to handle data as a string) } + Remote.FPostedDataBuffer[Remote.FDataLen] := #0; + { Display receive data so far } + Display('Data: ''' + StrPas(Remote.FPostedDataBuffer) + ''''); + + { When we received the whole thing, we can process it } + if Remote.FDataLen = Remote.RequestContentLength then begin + if CompareText(Remote.Path, '/cgi-bin/cgifrm1.exe') = 0 then + ProcessPostedData_CgiFrm1(Remote) + else + Remote.Answer404; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This will process posted data for CgiFrm1.exe } +procedure TWebServForm.ProcessPostedData_CgiFrm1(Client : TMyHttpConnection); +var + Stream : TStream; + FileName : String; + Body : String; + Header : String; + FirstName : String; + LastName : String; + HostName : String; + Buf : String; +begin + { Extract fields from posted data. } + ExtractURLEncodedValue(Client.FPostedDataBuffer, 'FirstName', FirstName); + ExtractURLEncodedValue(Client.FPostedDataBuffer, 'LastName', LastName); + { Get client IP address. We could to ReverseDnsLookup to get hostname } + HostName := Client.PeerAddr; + { Build the record to write to data file } + Buf := FormatDateTime('YYYYMMDD HHNNSS ', Now) + + FirstName + '.' + LastName + '@' + HostName + #13#10; + + { Save data to a text file } + FileName := ExtractFilePath(Application.ExeName) + 'CgiFrm1.txt'; + if FileExists(FileName) then + Stream := TFileStream.Create(FileName, fmOpenWrite) + else + Stream := TFileStream.Create(FileName, fmCreate); + Stream.Seek(0, soFromEnd); + Stream.Write(Buf[1], Length(Buf)); + Stream.Destroy; + + { Now create output stream to send back to remote client } + Stream := TMemoryStream.Create; + Body := '' + + '' + + 'ICS WebServer Demo' + + '' + #13#10 + + '' + + '

Your data has been recorded:

' + #13#10 + + '

' + FirstName + '.' + LastName + '@' + HostName +'

' + + '' + + '' + #13#10; + Header := Client.Version + ' 200 OK' + #13#10 + + 'Content-Type: text/html' + #13#10 + + 'Content-Length: ' + + IntToStr(Length(Body)) + #13#10 + + #13#10; + Stream.Write(Header[1], Length(Header)); + Stream.Write(Body[1], Length(Body)); + Stream.Seek(0, 0); + { Ask HTTP server component to send data stream for us } + Client.DocStream := Stream; + Client.SendStream; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TWebServForm.DisplayHeader(Client : TMyHttpConnection); +var + I : Integer; +begin + if not DisplayHeaderCheckBox.Checked then + Exit; + for I := 0 to Client.RequestHeader.Count - 1 do + Display('HDR' + IntToStr(I + 1) + ') ' + + Client.RequestHeader.Strings[I]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ We need to override parent class destructor because we have allocated } +{ memory for our data buffer. } +destructor TMyHttpConnection.Destroy; +begin + if Assigned(FPostedDataBuffer) then begin + FreeMem(FPostedDataBuffer, FPostedDataSize); + FPostedDataBuffer := nil; + FPostedDataSize := 0; + end; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TWebServForm.OpenLogFile; +begin + if FLogFileOpened then + Exit; + try + AssignFile(FLogFile, FLogFileName); + if FileExists(FLogFileName) then + Append(FLogFile) + else + Rewrite(FLogFile); + WriteLn(FLogFile, '[' + FormatDateTime('HH:NN:SS YYYY/MM/DD', Now) + + ' Log file opened.]'); + FLogFileOpened := TRUE; + except + FLogFileOpened := FALSE; + Display('*** Unable to open log file ***'); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TWebServForm.CloseLogFile; +begin + if not FLogFileOpened then + Exit; + FLogFileOpened := FALSE; + WriteLn(FLogFile, '[' + FormatDateTime('HH:NN:SS YYYY/MM/DD', Now) + + ' Log file Closed.]'); + CloseFile(FLogFile); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TWebServForm.WriteLogFileCheckBoxClick(Sender: TObject); +begin + if WriteLogFileCheckBox.Checked then + OpenLogFile + else + CloseLogFile; + WriteLogFileCheckBox.Checked := FLogFileOpened; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/cli5.dfm b/ICS_zlog/Delphi/Internet/cli5.dfm new file mode 100644 index 0000000000000000000000000000000000000000..28939d5eb635113525cad33debf5e113b776ba5a GIT binary patch literal 1316 zcmaJ>O;6iE5Z&0spD`d1mAIvsoGO$aDskWvoLEG4;t0FqSQdMNS8R48djs_6^oLaH z|LM8sc5Nqi0;Te0W_ISid9yqIW1-0P$D?WF1=kbQKRjq76wSQ89l4YM6CTeNR%7n@ zFc<1Cq(*$H{%EytNFq}8eM`Fna-RzIJJMae6ofNvtE%mC$}`=J>7`&Ej-lgmCeGXx zXE_M{U^wyyU;OB+do{QYN0C*XmNlK2-Vm1XrwE>fT^>|a%5Ssurg#CGGYPvPW_dS+ zjLfV0P<*3cqy2y;ZU$IDkR_0r&Wt<*&1aB}S)3}jRsp<*bdVPL_ztK!W^-OzrC{Z} z(5o1gT;;=Bt>V;Tn*vm046(qkFuH4ukN?1^3lP$y%astEIWA`mVo`ZjGe+6W`5Nf+ z2I#bI#^|l9^dZdgiVD++@LefiL3+UCb;b|+(GGMOYj_WbB#&QH-@ZYuxtPUrY;_BE zuL00U4Bt^mjHZiL-Ni|hS806Fh%ugRX;*)iFHiZ8c)K^Ab#anpkmn7dQWH8Gz!yaO z*MJkBFxa9~s!`v*J!-30ly#}BYsl1^?06S+O=(0oA&(zGm@-gVM!`Jc2^eN!`D8)F z9zrdo7w(89n&Mbx(kM>3QCSHQMthcV!8KLHOVj5urUNNm)B9)TSA}Lg6I!e9OypA_ zQ7V@qk+*T^^2L%fx#K~(u(^#60#>}i!6PQLxHA1+-QZ4K=7n;+a?4%Hb4a%GcH&1( zUiFq_>S+zRN!=WEJi5x$h%A7wgmPhqz!Hz*`&{ol<%Khq{~}CnIgxwF0v62Yy7iQA tT&FTN^~fqFoBQwxRBL@YF1^7@q*5@6aq)}NPx2yV%6G%tTV^1H{sLp-qWu5> literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/cli5.pas b/ICS_zlog/Delphi/Internet/cli5.pas new file mode 100644 index 00000000..b2bef581 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/cli5.pas @@ -0,0 +1,193 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Object: Simple client application demonstrating TWSocket object in action. +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Creation: September 21, 1996 +Version: 2.06 +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1996, 1997, 1998, 1999 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Sep 06, 1997 Beautified +Nov 09, 1997 Added a button to display the list of IP addresses for the + local computer (you can have two IP addresses if you are connected + to a LAN and to your ISP). +Nov 11, 1997 V2.03 Added a ReadLine button to show how to read a single line + synchronously. +Nov 18, 1997 V2.04 Show how to use ReceiveStr +Dec 05, 1998 V2.05 Don't use TWait component anymore +Aug 20, 1999 V2.06 Introduced FError to disply connection errors correctly. + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit Cli5; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, + Forms, Dialogs, Winsock, WSocket, StdCtrls; + +const + Client5Version = 206; + +type + TClientForm = class(TForm) + ConnectButton: TButton; + CliSocket: TWSocket; + InfoLabel: TLabel; + DisconnectButton: TButton; + DataLabel: TLabel; + IPButton: TButton; + ReadLineButton: TButton; + procedure ConnectButtonClick(Sender: TObject); + procedure DisconnectButtonClick(Sender: TObject); + procedure CliSocketDataAvailable(Sender: TObject; Error: Word); + procedure CliSocketSessionConnected(Sender: TObject; Error: Word); + procedure CliSocketSessionClosed(Sender: TObject; Error: Word); + procedure IPButtonClick(Sender: TObject); + procedure ReadLineButtonClick(Sender: TObject); + public + FError : Word; + end; + +var + ClientForm: TClientForm; + +implementation + +{$R *.DFM} + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* This event handler gets called when we connected the server *} +procedure TClientForm.CliSocketSessionConnected(Sender: TObject; Error: Word); +begin + FError := Error; { Remember error code for SessionClosed event } + if Error <> 0 then + InfoLabel.Caption := 'Connection failed, error #' + IntToStr(Error) + else + InfoLabel.Caption := 'Connected'; + DisconnectButton.Enabled := TRUE; + ConnectButton.Enabled := FALSE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* This event handler gets called when the server's connection is broken *} +{* Either by us or by the server. *} +procedure TClientForm.CliSocketSessionClosed(Sender: TObject; Error: Word); +begin + DataLabel.Caption := ''; + if FError = 0 then begin + { FError = 0 means we connected succesfully } + if Error <> 0 then + InfoLabel.Caption := 'Disconnected. Error #' + IntToStr(Error) + else + InfoLabel.Caption := 'Disconnected'; + end; + DisconnectButton.Enabled := FALSE; + ConnectButton.Enabled := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* The user has clicked on the connect button... *} +procedure TClientForm.ConnectButtonClick(Sender: TObject); +begin + CliSocket.Addr := 'localhost'; { Server host name } + CliSocket.Proto := 'tcp'; { Protocol we wants to use } + CliSocket.Port := 'telnet'; { The port we wants to connect } + CliSocket.Connect; { Let's connect ! } + { Connect is just a request, it returns immediately. We eventually gets } + { gets connected later. At that time we will receive the event } + { SessionConnected. If you need a timeout, you have to start a TTimer. } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* The user has clicked the disconnect button... *} +procedure TClientForm.DisconnectButtonClick(Sender: TObject); +begin + CliSocket.Close; { This will close the connection } + { When the connection will be effectively closed, we will receive the } + { SessionClosed even. } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.CliSocketDataAvailable(Sender: TObject; Error: Word); +begin + DataLabel.Caption := CliSocket.ReceiveStr; +end; + +{$IFDEF NEVER} +{ The same procedure using Receive: a little bit more complicated but } +{ more efficient because data is less copied from here to there. } +procedure TClientForm.CliSocketDataAvailable(Sender: TObject; Error: Word); +var + Buffer : String[200]; + Count : Integer; +begin + Count := CliSocket.Receive(@Buffer[1], High(Buffer)); + Buffer[0] := chr(Count); + DataLabel.Caption := Buffer; +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.IPButtonClick(Sender: TObject); +var + IPList : TStrings; + I : Integer; +begin + IPList := WSocket.LocalIPList; + InfoLabel.Caption := ''; + for I := 0 to IPList.Count - 1 do + InfoLabel.Caption := InfoLabel.Caption + ' ' + IPList.Strings[I]; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.ReadLineButtonClick(Sender: TObject); +var + Buf : String; +begin + ReadLineButton.Enabled := FALSE; + try + CliSocket.ReadLine(30, Buf); + DataLabel.Caption := 'Line: ''' + Buf + ''''; + finally + ReadLineButton.Enabled := TRUE; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/clidemo.dpr b/ICS_zlog/Delphi/Internet/clidemo.dpr new file mode 100644 index 00000000..88529f53 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/clidemo.dpr @@ -0,0 +1,12 @@ +program CliDemo; + +uses + Forms, + CliDemo1 in 'CliDemo1.pas' {ClientForm}; + +{$R *.RES} + +begin + Application.CreateForm(TClientForm, ClientForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/client5.dpr b/ICS_zlog/Delphi/Internet/client5.dpr new file mode 100644 index 00000000..dc4bab20 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/client5.dpr @@ -0,0 +1,12 @@ +program client5; + +uses + Forms, + Cli5 in 'Cli5.pas' {ClientForm}; + +{$R *.RES} + +begin + Application.CreateForm(TClientForm, ClientForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/clients.DBF b/ICS_zlog/Delphi/Internet/clients.DBF new file mode 100644 index 0000000000000000000000000000000000000000..4f1066e9ced6068d9d95f8c76e2ca1bb27900bc7 GIT binary patch literal 434 zcmZuqF%H5o40M43A$R~x-e6#8B|Z?PE(%JM;-u{Sg75J&l9pC#8xOY6cfMP{_uCZ! zeBl%Nw6Yz5vGs72aXAjCpIO5+NRqrLnVh4j?)b~}A7nEgI({?4e$iG6t$Z{{`NIJl zMcxxGt72iKRc^s>OIQ->voe+CT6pzr>59c%c+2x#E4ru55v3p}c>WXcqt&zw4TN}+ U>7&`!sldNk5pts<;f;9u0g(eV)&Kwi literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/clients.MDX b/ICS_zlog/Delphi/Internet/clients.MDX new file mode 100644 index 0000000000000000000000000000000000000000..c30a465230720732fb3364b69a8bb550868a4645 GIT binary patch literal 6144 zcmeH~K?;K~5Je}clp-$NcGVoASCA0FVpY^0p!dH-XBL5I3T|9z_yZw{e~_6+^sD|B zH`_L@n()({{70_P);bIJewKlrCRUsIbEE0Vrt!2dU4At7M`-v7nl d>#^!=-%OFivnF}3PwQflvspuc00^9qzz?u%9Pt1E literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/dnslook.dpr b/ICS_zlog/Delphi/Internet/dnslook.dpr new file mode 100644 index 00000000..c7d8897c --- /dev/null +++ b/ICS_zlog/Delphi/Internet/dnslook.dpr @@ -0,0 +1,12 @@ +program DnsLook; + +uses + Forms, + DnsLook1 in 'DnsLook1.pas' {DnsLookupForm}; + +{$R *.RES} + +begin + Application.CreateForm(TDnsLookupForm, DnsLookupForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/finger.dpr b/ICS_zlog/Delphi/Internet/finger.dpr new file mode 100644 index 00000000..6b93e8b1 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/finger.dpr @@ -0,0 +1,12 @@ +program Finger; + +uses + Forms, + Finger1 in 'Finger1.pas' {FingerDemoForm}; + +{$R *.RES} + +begin + Application.CreateForm(TFingerDemoForm, FingerDemoForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/finger1.dfm b/ICS_zlog/Delphi/Internet/finger1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..f01e27d6d01f0ae56b0bbeabde9f742a9e9e99fb GIT binary patch literal 1001 zcmZ{j(Qeu>6oySGF$qx0rfJf&3ofQgy%=q8cQr`JS`8XTGWBvb$$?liHgZfUdy&1? z9$*i!7ufZd#Ej5NyNQl{eE!e=&&eMfh2HhehvC#6j(yLcj?u-*k19gp#JgyR9_0&= zE-Zy7Bbbobir7GLk3`V)1Xn#LAu2ga z7B$U?-BKQlO$ZOFQ6%&wjNewVx*GL2F8(hzyoky(+eE^nDKwk4GG4AY~v}3eTEgWYrYq&IBF|y6$!W%7~5TQjTZ-%N4XbfW1WJ0 zzobi%5`=I#SSuxXqma|Fo|o_1lz)mJ_lo;zF;9yk?82O^nX*b$1^YbnEBcC04s?s1 z64`VJkANLAfBlbX>a*6KjZgIs9&$2c5Z6n%v4?jK2|GHncRx$Ew)MDY(dDyjkRVO7 zpTH5EL!= + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: +Apr 11, 1999 V1.01 Added command line option +Aug 18, 2001 V1.02 Changed website url + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit Finger1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, ExtCtrls, FingCli, WinSock, WSocket; + +const + FingerVersion = 102; + CopyRight : String = ' Finger (c) 1997-2001 F. Piette V1.02 '; + WM_APPSTARTUP = WM_USER + 1; + +type + TFingerDemoForm = class(TForm) + FingerCli1: TFingerCli; + DisplayMemo: TMemo; + Panel1: TPanel; + QueryEdit: TEdit; + QueryButton: TButton; + CancelButton: TButton; + procedure QueryButtonClick(Sender: TObject); + procedure FingerCli1DataAvailable(Sender: TObject; Error: Word); + procedure FingerCli1QueryDone(Sender: TObject; Error: Word); + procedure FingerCli1SessionConnected(Sender: TObject; Error: Word); + procedure CancelButtonClick(Sender: TObject); + procedure FormShow(Sender: TObject); + private + procedure WMAppStartup(var msg: TMessage); message WM_APPSTARTUP; + end; + +var + FingerDemoForm: TFingerDemoForm; + +const +{$IFDEF VER80} + BufferSize = 255; { Delphi 1 is limited to 255 bytes } +{$ELSE} + BufferSize = 2048; +{$ENDIF} + +implementation + +{$R *.DFM} + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFingerDemoForm.FormShow(Sender: TObject); +begin + { We use a custom message to initialize things once the form } + { is visible } + PostMessage(Handle, WM_APPSTARTUP, 0, 0); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFingerDemoForm.WMAppStartup(var msg: TMessage); +begin + Update; { Let the window be visible completely } + if ParamCount > 0 then begin + QueryEdit.Text := ParamStr(1); + QueryButtonClick(Self); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* Display a message in the memo field, breaking with CR *} +procedure MemoAddLines(Memo : TMemo; Msg : String); +const + CR = #13; + LF = #10; +var + Start, Stop : Integer; +begin + if Memo.Lines.Count = 0 then + Memo.Lines.Add(''); + + Start := 1; + Stop := Pos(CR, Msg); + if Stop = 0 then + Stop := Length(Msg) + 1; + while Start <= Length(Msg) do begin + Memo.Lines.Strings[Memo.Lines.Count - 1] := + Memo.Lines.Strings[Memo.Lines.Count - 1] + + Copy(Msg, Start, Stop - Start); + if Msg[Stop] = CR then begin + Memo.Lines.Add(''); + SendMessage(Memo.Handle, WM_KEYDOWN, VK_UP, 1); + end; + Start := Stop + 1; + if Start > Length(Msg) then + Break; + while Msg[Start] in [CR, LF] do + Start := Start + 1; + Stop := Start; + while (Msg[Stop] <> CR) and (Stop <= Length(Msg)) do + Stop := Stop + 1; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFingerDemoForm.QueryButtonClick(Sender: TObject); +begin + DisplayMemo.Clear; + QueryButton.Enabled := FALSE; + CancelButton.Enabled := TRUE; + FingerCli1.Query := QueryEdit.Text; + FingerCli1.StartQuery; + MemoAddLines(DisplayMemo, 'Query started.' + #13); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFingerDemoForm.FingerCli1SessionConnected(Sender: TObject; Error: Word); +begin + if Error = 0 then + MemoAddLines(DisplayMemo, 'Connected to host.' + #13); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFingerDemoForm.FingerCli1DataAvailable(Sender: TObject; Error: Word); +var + Buffer : array [0..BufferSize - 1] of char; + Len : Integer; +begin + while TRUE do begin + Len := FingerCli1.Receive(@Buffer, SizeOf(Buffer) - 1); + if Len <= 0 then + break; + Buffer[Len] := #0; + MemoAddLines(DisplayMemo, StrPas(Buffer)); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFingerDemoForm.FingerCli1QueryDone(Sender: TObject; Error: Word); +begin + if Error <> 0 then begin + if Error = WSAECONNREFUSED then + MemoAddLines(DisplayMemo, 'No finger service available.' + #13) + else if Error = WSAETIMEDOUT then + MemoAddLines(DisplayMemo, 'Host unreachable.' + #13) + else + MemoAddLines(DisplayMemo, 'Error #' + IntToStr(Error) + #13); + end; + MemoAddLines(DisplayMemo, 'Done.' + #13); + + QueryButton.Enabled := TRUE; + CancelButton.Enabled := FALSE; + { If we started from command line, then close application } + if ParamCount > 0 then + Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFingerDemoForm.CancelButtonClick(Sender: TObject); +begin + FingerCli1.Abort; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/ftpServ.dpr b/ICS_zlog/Delphi/Internet/ftpServ.dpr new file mode 100644 index 00000000..3825f854 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/ftpServ.dpr @@ -0,0 +1,12 @@ +program FtpServ; + +uses + Forms, + FtpServ1 in 'FtpServ1.pas' {FtpServerForm}; + +{$R *.RES} + +begin + Application.CreateForm(TFtpServerForm, FtpServerForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/ftpcli.ico b/ICS_zlog/Delphi/Internet/ftpcli.ico new file mode 100644 index 0000000000000000000000000000000000000000..f0257c8019abdebce697ed701933cf699f41fb98 GIT binary patch literal 766 zcmcgqI~Ia45FC8IX916AWliZZJX(&Fekrzh4?$_g6>xS53TUg7>}QfN%LagoqwCIa zJPyEx@k;AxH(G@wJ;A;2NB}2Nngcyks4AmxOffM{p3yjb$z5YB=$4vk*_Pf!`n&0T z_|DLqc?kTP8|$y@EpXundowC@W_2#ay#_~_01d!cz{ku2YDSuNM|rUP(F P{KecT`WK{9Z(!{w#w~Qc literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/ftpthrd.dpr b/ICS_zlog/Delphi/Internet/ftpthrd.dpr new file mode 100644 index 00000000..f896099d --- /dev/null +++ b/ICS_zlog/Delphi/Internet/ftpthrd.dpr @@ -0,0 +1,13 @@ +program ftpthrd; + +uses + Forms, + FtpThrd1 in 'FtpThrd1.pas' {ThrdFtpForm}; + +{$R *.RES} + +begin + Application.Initialize; + Application.CreateForm(TThrdFtpForm, ThrdFtpForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/ftptst.dpr b/ICS_zlog/Delphi/Internet/ftptst.dpr new file mode 100644 index 00000000..d61df502 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/ftptst.dpr @@ -0,0 +1,14 @@ +program Ftptst; + +uses + Forms, + FtpTst1 in 'FtpTst1.pas' {FtpReceiveForm}, + Ftptst2 in 'Ftptst2.pas' {DirectoryForm}; + +{$R *.RES} + +begin + Application.CreateForm(TFtpReceiveForm, FtpReceiveForm); + Application.CreateForm(TDirectoryForm, DirectoryForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/ftptst1.dfm b/ICS_zlog/Delphi/Internet/ftptst1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..29219a64e92fd7fe8d636d6dfcda0dc6f428ad14 GIT binary patch literal 16936 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 + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: +Sep 13, 97 Added directory functions. Added button to show how to makes + several transferts in one session +Sep 27, 97 Change identifiers names to be more standard with other sources +Jan 10, 98 Saved edit boxes content to an IniFile, added FileSize, Quote + and RestartGet commands +Jan 25, 1998 Completely rewritten for new component version (Asynchronous) +Feb 02, 1998 V2.17 Added a checkbox to run the synchronous or asynchronous + version of the component methods. +Feb 15, 1998 V2.18 Removed useless wait unit from the use clause. + Added display of winsock information at startup. +Feb 22, 1998 V2.19 Added Append and AppendFile commands +Aug 21, 1998 V2.20 Added a comment in OnProgress event handler to warn user + about CPU usage. +Dec 22, 1998 V2.21 Replaced DisplayFlag by DysplayFileFlag. +Oct 19, 1999 V2.22 Correctly display Winsock version +Nov 24, 1999 V2.23 Added Restart Put and NoAutoResumeAt. +Jan 28, 2000 V2.24 Added code to OnProgress event handler to update screen + only once per second. This solve problem on fast LAN. +Jul 21, 2000 V2.25 Added two button to show TSream usage instead of files. + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit FtpTst1; + +interface + +uses + SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, + Forms, Dialogs, FtpCli, StdCtrls, IniFiles, ExtCtrls, WinSock, WSocket; + +const + FTPTstVersion = 225; + +type + TSyncCmd = function : Boolean of object; + TAsyncCmd = procedure of object; + + TFtpReceiveForm = class(TForm) + DisplayMemo: TMemo; + FtpClient1: TFtpClient; + Panel1: TPanel; + ExitButton: TButton; + OpenAsyncButton: TButton; + QuitAsyncButton: TButton; + CwdAsyncButton: TButton; + UserAsyncButton: TButton; + PassAsyncButton: TButton; + ConnectAsyncButton: TButton; + GetAsyncButton: TButton; + ReceiveAsyncButton: TButton; + AbortAsyncButton: TButton; + DirAsyncButton: TButton; + DirectoryAsyncButton: TButton; + LsAsyncButton: TButton; + ListAsyncButton: TButton; + SystAsyncButton: TButton; + SystemAsyncButton: TButton; + FileSizeAsyncButton: TButton; + SizeAsyncButton: TButton; + MkdAsyncButton: TButton; + MkdirAsyncButton: TButton; + RmdAsyncButton: TButton; + RmdirAsyncButton: TButton; + RenAsyncButton: TButton; + RenameAsyncButton: TButton; + DeleAsyncButton: TButton; + DeleteAsyncButton: TButton; + PwdAsyncButton: TButton; + QuoteAsyncButton: TButton; + DoQuoteAsyncButton: TButton; + PutAsyncButton: TButton; + TransmitAsyncButton: TButton; + TypeSetAsyncButton: TButton; + RestGetAsyncButton: TButton; + RestartGetAsyncButton: TButton; + CDupAsyncButton: TButton; + Panel2: TPanel; + Label1: TLabel; + Label3: TLabel; + Label4: TLabel; + Label5: TLabel; + Label2: TLabel; + Label6: TLabel; + HostNameEdit: TEdit; + HostFileEdit: TEdit; + UserNameEdit: TEdit; + PassWordEdit: TEdit; + cbDisplay: TCheckBox; + LocalFileEdit: TEdit; + cbBinary: TCheckBox; + HostDirEdit: TEdit; + PortEdit: TEdit; + InfoLabel: TLabel; + StateLabel: TLabel; + ClearButton: TButton; + SyncCheckBox: TCheckBox; + AppendFileAsyncButton: TButton; + AppendAsyncButton: TButton; + PassiveCheckBox: TCheckBox; + Button1: TButton; + RestPutAsyncButton: TButton; + RestartPutAsyncButton: TButton; + ResumeAtEdit: TEdit; + Label7: TLabel; + NoAutoResumeAtCheckBox: TCheckBox; + TransmitUsingStreamButton: TButton; + ReceiveUsingStreamButton: TButton; + StressPutButton: TButton; + AbortXferAsyncButton: TButton; + procedure ExitButtonClick(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure DisplayHandler(Sender: TObject; var Msg : String); + procedure FtpClient1Progress(Sender: TObject; Count: Longint; + var Abort: Boolean); + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure OpenAsyncButtonClick(Sender: TObject); + procedure FtpClient1RequestDone(Sender: TObject; RqType: TFtpRequest; + Error: Word); + procedure FtpClient1SessionConnected(Sender: TObject; Error: Word); + procedure FtpClient1SessionClosed(Sender: TObject; Error: Word); + procedure QuitAsyncButtonClick(Sender: TObject); + procedure CwdAsyncButtonClick(Sender: TObject); + procedure UserAsyncButtonClick(Sender: TObject); + procedure PassAsyncButtonClick(Sender: TObject); + procedure ConnectAsyncButtonClick(Sender: TObject); + procedure FtpClient1StateChange(Sender: TObject); + procedure GetAsyncButtonClick(Sender: TObject); + procedure ReceiveAsyncButtonClick(Sender: TObject); + procedure AbortAsyncButtonClick(Sender: TObject); + procedure DirAsyncButtonClick(Sender: TObject); + procedure DirectoryAsyncButtonClick(Sender: TObject); + procedure LsAsyncButtonClick(Sender: TObject); + procedure ListAsyncButtonClick(Sender: TObject); + procedure SystAsyncButtonClick(Sender: TObject); + procedure SystemAsyncButtonClick(Sender: TObject); + procedure FileSizeAsyncButtonClick(Sender: TObject); + procedure SizeAsyncButtonClick(Sender: TObject); + procedure MkdAsyncButtonClick(Sender: TObject); + procedure MkdirAsyncButtonClick(Sender: TObject); + procedure RmdAsyncButtonClick(Sender: TObject); + procedure RmdirAsyncButtonClick(Sender: TObject); + procedure RenAsyncButtonClick(Sender: TObject); + procedure RenameAsyncButtonClick(Sender: TObject); + procedure DeleAsyncButtonClick(Sender: TObject); + procedure DeleteAsyncButtonClick(Sender: TObject); + procedure PwdAsyncButtonClick(Sender: TObject); + procedure QuoteAsyncButtonClick(Sender: TObject); + procedure DoQuoteAsyncButtonClick(Sender: TObject); + procedure PutAsyncButtonClick(Sender: TObject); + procedure TransmitAsyncButtonClick(Sender: TObject); + procedure TypeSetAsyncButtonClick(Sender: TObject); + procedure RestGetAsyncButtonClick(Sender: TObject); + procedure RestartGetAsyncButtonClick(Sender: TObject); + procedure CDupAsyncButtonClick(Sender: TObject); + procedure ClearButtonClick(Sender: TObject); + procedure AppendAsyncButtonClick(Sender: TObject); + procedure AppendFileAsyncButtonClick(Sender: TObject); + procedure Button1Click(Sender: TObject); + procedure RestPutAsyncButtonClick(Sender: TObject); + procedure RestartPutAsyncButtonClick(Sender: TObject); + procedure TransmitUsingStreamButtonClick(Sender: TObject); + procedure ReceiveUsingStreamButtonClick(Sender: TObject); + procedure StressPutButtonClick(Sender: TObject); + procedure AbortXferAsyncButtonClick(Sender: TObject); + private + FIniFileName : String; + FInitialized : Boolean; + FLastProgress : DWORD; + FProgressCount : LongInt; + FRunning : Boolean; + procedure DisplayFile(FileName : String); + procedure ExecuteCmd(SyncCmd : TSyncCmd; ASyncCmd : TAsyncCmd); + function SendFile : Boolean; + procedure Display(Msg: String); + end; + +const + TEMP_FILE_NAME = 'FTPDIR.TXT'; + +var + FtpReceiveForm: TFtpReceiveForm; + +implementation + +uses + FtpTst2; + +{$R *.DFM} +const + SectionData = 'Data'; + KeyHostName = 'HostName'; + KeyUserName = 'UserName'; + KeyPassWord = 'PassWord'; + KeyHostDir = 'HostDir'; + KeyPort = 'Port'; + KeyHostFile = 'HostFile'; + KeyLocalFile = 'LocalFile'; + KeyResumeAt = 'ResumeAt'; + SectionWindow = 'Window'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFNDEF VER80 } +{ To debug event driven programs, it is often handy to just use writeln to } +{ write debug messages to the console. To get a console, just ask the } +{ linker to build a console mode application. Then you'll get the default } +{ console. The function below will make it the size you like... } +procedure BigConsole(nCols, nLines : Integer); +var + sc : TCoord; + N : DWord; +begin + if not IsConsole then + Exit; + sc.x := nCols; + sc.y := nLines; + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), sc); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + BACKGROUND_BLUE or BACKGROUND_GREEN or + BACKGROUND_RED or BACKGROUND_INTENSITY); + sc.x := 0; + sc.y := 0; + FillConsoleOutputAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + BACKGROUND_BLUE or BACKGROUND_GREEN or + BACKGROUND_RED or BACKGROUND_INTENSITY, + nCols * nLines, sc, N); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.FormCreate(Sender: TObject); +begin +{$IFNDEF VER80} + BigConsole(80, 100); +{$ENDIF} + DisplayMemo.Clear; + InfoLabel.Caption := ''; + StateLabel.Caption := ''; + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; + Data : TWSAData; +begin + if not FInitialized then begin + FInitialized := TRUE; + IniFile := TIniFile.Create(FIniFileName); + HostNameEdit.Text := IniFile.ReadString(SectionData, KeyHostName, + 'ftp.simtel.net'); + PortEdit.Text := IniFile.ReadString(SectionData, KeyPort, + 'ftp'); + UserNameEdit.Text := IniFile.ReadString(SectionData, KeyUserName, + 'anonymous'); + PassWordEdit.Text := IniFile.ReadString(SectionData, KeyPassWord, + 'your.name@your.company.com'); + HostDirEdit.Text := IniFile.ReadString(SectionData, KeyHostDir, + '/pub/simtelnet'); + HostFileEdit.Text := IniFile.ReadString(SectionData, KeyHostFile, + 'index.html'); + LocalFileEdit.Text := IniFile.ReadString(SectionData, KeyLocalFile, + 'c:\temp\index.htm'); + ResumeAtEdit.Text := IniFile.ReadString(SectionData, KeyResumeAt, + '0'); + + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, (Screen.Width - Width) div 2); + + IniFile.Free; + + { Display winsock info } + Data := WinsockInfo; + Display('Winsock version ' + + IntToStr(LOBYTE(Data.wHighVersion)) + '.' + + IntToStr(HIBYTE(Data.wHighVersion))); + Display(StrPas(Data.szDescription)); + Display(StrPas(Data.szSystemStatus)); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.FormClose(Sender: TObject; + var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteString(SectionData, KeyHostName, HostNameEdit.Text); + IniFile.WriteString(SectionData, KeyPort, PortEdit.Text); + IniFile.WriteString(SectionData, KeyUserName, UserNameEdit.Text); + IniFile.WriteString(SectionData, KeyPassWord, PassWordEdit.Text); + IniFile.WriteString(SectionData, KeyHostDir, HostDirEdit.Text); + IniFile.WriteString(SectionData, KeyHostFile, HostFileEdit.Text); + IniFile.WriteString(SectionData, KeyLocalFile, LocalFileEdit.Text); + IniFile.WriteString(SectionData, KeyResumeAt, ResumeAtEdit.Text); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +function DeleteFile(const FileName: string): Boolean; +var + F : File of char; +begin + Result := TRUE; + try + AssignFile(F, FileName); + Erase(F); + except + Result := FALSE; + end; +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.Display(Msg : String); +var + I : Integer; +begin + DisplayMemo.Lines.BeginUpdate; + try + if DisplayMemo.Lines.Count > 200 then begin + for I := 1 to 50 do + DisplayMemo.Lines.Delete(0); + end; + DisplayMemo.Lines.Add(Msg); + finally + DisplayMemo.Lines.EndUpdate; + {$IFNDEF VER80} + SendMessage(DisplayMemo.Handle, EM_SCROLLCARET, 0, 0); + {$ENDIF} + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.DisplayHandler(Sender : TObject; var Msg : String); +begin + Display(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.ExitButtonClick(Sender: TObject); +begin + Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.FtpClient1Progress(Sender: TObject; + Count: Longint; var Abort: Boolean); +begin + FProgressCount := Count; + { Be sure to update screen only once every second } + if FLastProgress < GetTickCount then begin + FLastProgress := GetTickCount + 1000; + InfoLabel.Caption := IntToStr(FProgressCount); + InfoLabel.Repaint; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.DisplayFile(FileName : String); +begin + try + DirectoryForm.DirListBox.Items.LoadFromFile(FileName); + except + DirectoryForm.DirListBox.Clear; + end; + DirectoryForm.ShowModal; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.FtpClient1RequestDone(Sender: TObject; + RqType: TFtpRequest; Error: Word); +begin + Display('Request ' + IntToStr(Ord(RqType)) + ' Done.'); + Display('StatusCode = ' + IntToStr(FtpClient1.StatusCode)); + Display('LastResponse was : ''' + FtpClient1.LastResponse + ''''); + if Error = 0 then + Display('No error') + else + Display('Error = ' + IntToStr(Error) + + ' (' + FtpClient1.ErrorMessage + ')'); + + { Display last progress value } + InfoLabel.Caption := IntToStr(FProgressCount); + + if Error = 0 then begin + case RqType of + ftpDirAsync, ftpDirectoryAsync, + ftpLsAsync, ftpListAsync : DisplayFile(TEMP_FILE_NAME); + ftpSizeAsync : Display( + 'File size is ' + + IntToStr(FtpClient1.SizeResult) + + ' bytes' ); + ftpPwdAsync, ftpMkdAsync, + ftpCDupAsync, ftpCwdAsync : Display( + 'Directory is "' + + FtpClient1.DirResult + '"'); + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.FtpClient1SessionConnected(Sender: TObject; + Error: Word); +begin + Display('Session Connected, error = ' + IntToStr(Error)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.FtpClient1SessionClosed(Sender: TObject; + Error: Word); +begin + Display('Session Closed, error = ' + IntToStr(Error)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.FtpClient1StateChange(Sender: TObject); +begin + StateLabel.Caption := IntToStr(Ord(FtpClient1.State)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.ExecuteCmd(SyncCmd : TSyncCmd; ASyncCmd : TAsyncCmd); +begin + Display('Executing Requested Command'); + { Initialize progress stuff } + FLastProgress := 0; + FProgressCount := 0; + + if SyncCheckBox.Checked then begin + if SyncCmd then + Display('Command Success') + else + Display('Command Failure'); + end + else + ASyncCmd; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.OpenAsyncButtonClick(Sender: TObject); +begin + DisplayMemo.Clear; + Display('Connect Async'); + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Open, FtpClient1.OpenAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.QuitAsyncButtonClick(Sender: TObject); +begin + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Quit, FtpClient1.QuitAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.CwdAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Cwd, FtpClient1.CwdAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.UserAsyncButtonClick(Sender: TObject); +begin + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.User, FtpClient1.UserAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.PassAsyncButtonClick(Sender: TObject); +begin + FtpClient1.Password := PasswordEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Pass, FtpClient1.PassAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.ConnectAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.Password := PasswordEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Connect, FtpClient1.ConnectAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.GetAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.Passive := PassiveCheckBox.Checked; + ExecuteCmd(FtpClient1.Get, FtpClient1.GetAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.ReceiveAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.Binary := cbBinary.Checked; + FtpClient1.Passive := PassiveCheckBox.Checked; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Receive, FtpClient1.ReceiveAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.AbortAsyncButtonClick(Sender: TObject); +begin + ExecuteCmd(FtpClient1.Abort, FtpClient1.AbortAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.DirAsyncButtonClick(Sender: TObject); +begin + DeleteFile(TEMP_FILE_NAME); + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := TEMP_FILE_NAME; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.Passive := PassiveCheckBox.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Dir, FtpClient1.DirAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.DirectoryAsyncButtonClick(Sender: TObject); +begin + DeleteFile(TEMP_FILE_NAME); + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := TEMP_FILE_NAME; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.Passive := PassiveCheckBox.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Directory, FtpClient1.DirectoryAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.LsAsyncButtonClick(Sender: TObject); +begin + DeleteFile(TEMP_FILE_NAME); + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := TEMP_FILE_NAME; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.Passive := PassiveCheckBox.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Ls, FtpClient1.LsAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.ListAsyncButtonClick(Sender: TObject); +begin + DeleteFile(TEMP_FILE_NAME); + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := TEMP_FILE_NAME; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.Passive := PassiveCheckBox.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.List, FtpClient1.ListAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.SystAsyncButtonClick(Sender: TObject); +begin + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Syst, FtpClient1.SystAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.SystemAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.System, FtpClient1.SystemAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.FileSizeAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.FileSize, FtpClient1.FileSizeAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.SizeAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Size, FtpClient1.SizeAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.MkdAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Mkd, FtpClient1.MkdAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.MkdirAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.MkDir, FtpClient1.MkdirAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.RmdAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Rmd, FtpClient1.RmdAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.RmdirAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.RmDir, FtpClient1.RmDirAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.RenAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Ren, FtpClient1.RenAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.RenameAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Rename, FtpClient1.RenameAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.DeleAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Dele, FtpClient1.DeleAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.DeleteAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Delete, FtpClient1.DeleteAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.PwdAsyncButtonClick(Sender: TObject); +begin + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Pwd, FtpClient1.PwdAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.QuoteAsyncButtonClick(Sender: TObject); +begin + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Quote, FtpClient1.QuoteAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.DoQuoteAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.DoQuote, FtpClient1.DoQuoteAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.PutAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.Binary := cbBinary.Checked; + FtpClient1.Passive := PassiveCheckBox.Checked; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Put, FtpClient1.PutAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.TransmitAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.Binary := cbBinary.Checked; + FtpClient1.Passive := PassiveCheckBox.Checked; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Transmit, FtpClient1.TransmitAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.TypeSetAsyncButtonClick(Sender: TObject); +begin + FtpClient1.Binary := cbBinary.Checked; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.TypeSet, FtpClient1.TypeSetAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.RestGetAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.Options := []; + if NoAutoResumeAtCheckBox.Checked then + FtpClient1.Options := FtpClient1.Options + [ftpNoAutoResumeAt]; + FtpClient1.ResumeAt := StrToInt(ResumeAtEdit.Text); + ExecuteCmd(FtpClient1.RestGet, FtpClient1.RestGetAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.RestartGetAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.Binary := cbBinary.Checked; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.Options := []; + if NoAutoResumeAtCheckBox.Checked then + FtpClient1.Options := FtpClient1.Options + [ftpNoAutoResumeAt]; + FtpClient1.OnDisplay := DisplayHandler; + FtpClient1.ResumeAt := StrToInt(ResumeAtEdit.Text); + ExecuteCmd(FtpClient1.RestartGet, FtpClient1.RestartGetAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.CDupAsyncButtonClick(Sender: TObject); +begin + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.CDup, FtpClient1.CDupAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.ClearButtonClick(Sender: TObject); +begin + DisplayMemo.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.AppendAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.Binary := cbBinary.Checked; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Append, FtpClient1.AppendAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.AppendFileAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.Binary := cbBinary.Checked; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.AppendFile, FtpClient1.AppendFileAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +procedure TFtpReceiveForm.Button1Click(Sender: TObject); +var + Count : Integer; +begin + SyncCheckBox.Checked := TRUE; + if not FtpClient1.Connected then begin + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.Password := PasswordEdit.Text; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Connect, FtpClient1.ConnectAsync); + if Copy(FtpClient1.LastResponse, 1, 3) <> '230' then + Exit; + end; + Count := 0; + repeat + DisplayMemo.Clear; + Inc(Count); + Display('Count=' + IntToStr(Count)); + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.Binary := cbBinary.Checked; + FtpClient1.Passive := PassiveCheckBox.Checked; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.Put, FtpClient1.PutAsync); + until Copy(FtpClient1.LastResponse, 1, 3) <> '226'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.RestPutAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.Passive := PassiveCheckBox.Checked; + FtpClient1.ResumeAt := StrToInt(ResumeAtEdit.Text); + ExecuteCmd(FtpClient1.RestPut, FtpClient1.RestPutAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.RestartPutAsyncButtonClick(Sender: TObject); +begin + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.Binary := cbBinary.Checked; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.Passive := PassiveCheckBox.Checked; + FtpClient1.OnDisplay := DisplayHandler; + FtpClient1.ResumeAt := StrToInt(ResumeAtEdit.Text); + ExecuteCmd(FtpClient1.RestartPut, FtpClient1.RestartPutAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.TransmitUsingStreamButtonClick(Sender: TObject); +var + MyStream : TStream; +begin + MyStream := TFileStream.Create(LocalFileEdit.Text, fmOpenRead); + try + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalStream := MyStream; + FtpClient1.Binary := cbBinary.Checked; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + if ResumeAtEdit.Text > '' then + FtpClient1.ResumeAt := StrToInt(ResumeAtEdit.Text); + FtpClient1.Transmit; + finally + FtpClient1.LocalStream := nil; + MyStream.Destroy; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.ReceiveUsingStreamButtonClick(Sender: TObject); +var + MyStream : TStream; +begin + MyStream := TFileStream.Create(LocalFileEdit.Text, fmCreate); + try + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.PassWord := PassWordEdit.Text; + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.LocalStream := MyStream; + FtpClient1.Binary := cbBinary.Checked; + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + if ResumeAtEdit.Text > '' then + FtpClient1.ResumeAt := StrToInt(ResumeAtEdit.Text); + FtpClient1.Receive; + finally + FtpClient1.LocalStream := nil; + MyStream.Destroy; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function GetFileSize(const FileName: string): LongInt; +var + SearchRec: TSearchRec; +begin + if FindFirst(ExpandFileName(FileName), faAnyFile, SearchRec) = 0 then begin + Result := SearchRec.Size; + SysUtils.FindClose(SearchRec); + end + else + Result := -1; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpReceiveForm.SendFile : Boolean; +var + LocalSize : LongInt; +begin + try + FtpClient1.Abort; { Whatever occured, abort ! } + FtpClient1.LocalFileName := LocalFileEdit.Text; + FtpClient1.HostDirName := HostDirEdit.Text; + FtpClient1.HostFileName := HostFileEdit.Text; + FtpClient1.HostName := HostNameEdit.Text; + FtpClient1.Port := PortEdit.Text; + FtpClient1.UserName := UserNameEdit.Text; + FtpClient1.Password := PassWordEdit.Text; + FtpClient1.Passive := PassiveCheckBox.Checked; + FtpClient1.Binary := cbBinary.Checked; + FtpClient1.Timeout := 30; + FtpClient1.ShareMode := ftpShareDenyNone; + if not FtpClient1.Connect then + raise Exception.Create('FtpClient1.Connect failed: ' + FtpClient1.ErrorMessage); + if FtpClient1.HostDirName <> '' then begin + if not FtpClient1.Cwd then + raise Exception.Create('FtpClient1.Cwd failed: ' + FtpClient1.ErrorMessage); + end; + if not FtpClient1.TypeSet then + raise Exception.Create('FtpClient1.TypeSet failed: ' + FtpClient1.ErrorMessage); + if not FtpClient1.Put then + raise Exception.Create('FtpClient1.Put failed: ' + FtpClient1.ErrorMessage); + if FtpClient1.StatusCode <> 226 then + raise Exception.Create('FtpClient1.Put failed: ' + FtpClient1.LastResponse); + if not FtpClient1.Size then + raise Exception.Create('FtpClient1.Size failed: ' + FtpClient1.ErrorMessage); + LocalSize := GetFileSize(FtpClient1.LocalFileName); + Result := (FtpClient1.SizeResult = LocalSize); + if not Result then + Display('Incorrect file size on server (S=' + + IntToStr(FtpClient1.SizeResult) + ' L=' + + IntToStr(LocalSize) + ')'); + if not FtpClient1.Quit then + raise Exception.Create('FtpClient1.Quit failed: ' + FtpClient1.ErrorMessage); + except + on E:Exception do begin + Display('Exception ' + E.ClassName + ': ' + E.Message); + Result := FALSE; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.StressPutButtonClick(Sender: TObject); +var + Count : Integer; +begin + if FRunning then begin + FRunning := FALSE; + Display('Stress Put interrupted.'); + StressPutButton.Caption := 'Stress Put'; + Exit; + end; + FRunning := TRUE; + try + Display('Stress Put started.'); + StressPutButton.Caption := 'STOP'; + Count := 0; + while FRunning and (not Application.Terminated) do begin + Inc(Count); + Display('STRESS COUNT = ' + IntToStr(Count)); + if not SendFile then + break; + Application.ProcessMessages; + end; + finally + FRunning := FALSE; + Display('Stress Put finished.'); + StressPutButton.Caption := 'Stress Put'; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpReceiveForm.AbortXferAsyncButtonClick(Sender: TObject); +begin + FtpClient1.DisplayFileFlag := cbDisplay.Checked; + FtpClient1.OnDisplay := DisplayHandler; + ExecuteCmd(FtpClient1.AbortXfer, FtpClient1.AbortXferAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/httpChk.dpr b/ICS_zlog/Delphi/Internet/httpChk.dpr new file mode 100644 index 00000000..4fb14696 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/httpChk.dpr @@ -0,0 +1,12 @@ +program httpChk; + +uses + Forms, + HttpChk1 in 'HttpChk1.pas' {CheckUrlForm}; + +{$R *.RES} + +begin + Application.CreateForm(TCheckUrlForm, CheckUrlForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/httpasp.dpr b/ICS_zlog/Delphi/Internet/httpasp.dpr new file mode 100644 index 00000000..887cb644 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/httpasp.dpr @@ -0,0 +1,12 @@ +program HttpAsp; + +uses + Forms, + HttpAsp1 in 'HttpAsp1.pas' {HttpTestForm}; + +{$R *.RES} + +begin + Application.CreateForm(THttpTestForm, HttpTestForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/httpasy.dpr b/ICS_zlog/Delphi/Internet/httpasy.dpr new file mode 100644 index 00000000..f3c55b6b --- /dev/null +++ b/ICS_zlog/Delphi/Internet/httpasy.dpr @@ -0,0 +1,12 @@ +program HttpAsy; + +uses + Forms, + HttpAsy1 in 'HttpAsy1.pas' {HttpAsyForm}; + +{$R *.RES} + +begin + Application.CreateForm(THttpAsyForm, HttpAsyForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/httpget.dpr b/ICS_zlog/Delphi/Internet/httpget.dpr new file mode 100644 index 00000000..2b9f79b9 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/httpget.dpr @@ -0,0 +1,12 @@ +program HttpGet; + +uses + Forms, + HttpGet1 in 'HttpGet1.pas' {HttpGetForm}; + +{$R *.RES} + +begin + Application.CreateForm(THttpGetForm, HttpGetForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/httppg.dpr b/ICS_zlog/Delphi/Internet/httppg.dpr new file mode 100644 index 00000000..53ee81b1 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/httppg.dpr @@ -0,0 +1,12 @@ +program HttpPg; + +uses + Forms, + HttpPg1 in 'HttpPg1.pas' {HttpTestForm}; + +{$R *.RES} + +begin + Application.CreateForm(THttpTestForm, HttpTestForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/httpthrd.dpr b/ICS_zlog/Delphi/Internet/httpthrd.dpr new file mode 100644 index 00000000..fbcef1b6 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/httpthrd.dpr @@ -0,0 +1,14 @@ +program HttpThrd; + +uses + Forms, + HttpThr1 in 'HttpThr1.pas' {HttpThreadForm}, + HttpThr2 in 'HttpThr2.pas'; + +{$R *.RES} + +begin + Application.Initialize; + Application.CreateForm(THttpThreadForm, HttpThreadForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/httptst.dpr b/ICS_zlog/Delphi/Internet/httptst.dpr new file mode 100644 index 00000000..b30d5856 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/httptst.dpr @@ -0,0 +1,12 @@ +program HttpTst; + +uses + Forms, + httptst1 in 'httptst1.pas' {HttpTestForm}; + +{$R *.RES} + +begin + Application.CreateForm(THttpTestForm, HttpTestForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/httptst1.dfm b/ICS_zlog/Delphi/Internet/httptst1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..cb4da75360ad5c9c9078ea61974387b7e81c4b49 GIT binary patch literal 2991 zcmc&$OK&4Z5FWo~#;?Rmv;lE4AVtfH#L2$2S}r(FjFFt!if6S#s|eaNWxL6^dv>P1 zPFDN?egFq9+&S@6_$^#GaDwXTdD-y-2P6{7?uWmxs=uo0>OU)*)w8UjbvClPgUfU6 zsPSV})2w0lsBZOy@GJ;Km;3Wtc2exaL==9?6)f)MY3U_(#H>JbdJpJyCJMjij1KVx zTs9)M%i{x1nUwTYF*C6VP{7C0EDr9 zde&{f=v!ZRdhN^6nN?A{A*N=#FDY~Q(t;aN4L6hv`QOXo?1Iceub+>aBf^5_2z)wG z_>s7Ep{i{ST&Lp$5isx_@XN-4bzB~RfpC8w4)p;W&G^zV<%%5Dhx7*AU~fK8070o2nsJQ``Rk>q4G;XKZ~Fr+=Z5gKEJtL13$`w zKaRlf-31p`6vKU02xi1^9GkzF#Gts35aSdkWZ{Z(8tGz~ zaMZpwwi3>ci*rpYS!WIv1_n=lE8Xsgv5xE%{?HOb#U5osZ+Si!+~zJ8*{ekW{;TI6 z34$f}ovY8UaE?WXOQ^(E%Ohg8H6%VTA(L9-O*0;4Jk*LZz4g7#wHv!x4-=)w1F`Px zvq+S$5?|BP=N0!Vc$HFyEuk#@tl}JVwl{DVvYatm)8f!ohUnvl*frlByVAbIq+XYj zm~E$IQP5&D_0A0J>!**imVQ&t58rLc+>c4Lq0J%CWi#R4TnzsZ>ZhO5q1>rKSAWowVBF3!j4Dyny9OAFcN(gWzx^ ze9ERlPS1L*Rn#@p#jb8vMz+sg_XLGA^dLClVwP%=lW8aqSv%$SVvbkS+KCIL+?^x; z5+B(lF3N_W|LxQ(ZvXpZ=QYg?-&*LtDc?)@eJs1SzLU9ieKDEiYpLAlHgVgIyp-^!=vVXo6oTUP)zzy^tNq- zC-i4@PNvYB(#fYyHM}{v8B;MQUcB(F2h(`$smX)Z1LJ~sh&=;yyMqx%Th^@y@@CXO zB%X)O3=MJCx;emi-@ybQQ3ng(1!i*xoccNTLu$?N35GMXHej;8!Iu}Bu@h^Nu9fk9 z#^-aw9Ai7)jTR~chFNn0Q_74+yce(Fg9?Xd2;0hR;k+(iTCW%QK0W0OjNN!Qv)C9g zskuA^zDd~>jJ^0*tLtc_!}&FZ)QFl_M%=y*`tSyyZn-DB;jFz7Gt??l$G8{BpIq?O PWmW7A+4b=r#=pM+ + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: +Jan 16, 1998 V1.00 Adapted for reviced HTTP component. +Apr 13, 1998 V1.01 Call HttpCli1DocEnd when to request failed, to close the + document file in the case it is already opened. +Jul 09, 1998 V1.02 Adapted for Delphi 4 +Sep 15, 1998 V1.03 Added some code to check for file creation errors (those + errors mostly comes from document names not suitable as file + names). + Added code to save form size and position and to resize it + correctly. +Sep 25, 1999 V1.04 Added display proxy setting +Aug 18, 2001 V1.05 Checked for document name before trying to display. + Wrapped document file access to a try/finally. + Checked ContentType to change document name extension according + to some content type. + Added display of copyright notice and version informations. + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit HttpTst1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, HttpProt, WinSock, WSocket, StdCtrls, ExtCtrls, IniFiles; + +const + HttpTstVersion = 105; + CopyRight : String = 'HttpTst (c) 1999-2002 F. Piette V1.05 '; + +type + THttpTestForm = class(TForm) + Panel1: TPanel; + GetButton: TButton; + HttpCli1: THttpCli; + URLEdit: TEdit; + DisplayMemo: TMemo; + Label1: TLabel; + Label2: TLabel; + ProxyHostEdit: TEdit; + ProxyPortEdit: TEdit; + PostButton: TButton; + Check64Button: TButton; + DataEdit: TEdit; + Label3: TLabel; + DateTimeEdit: TEdit; + DocumentMemo: TMemo; + Label4: TLabel; + HeadButton: TButton; + AbortButton: TButton; + Label5: TLabel; + Label6: TLabel; + ParseButton: TButton; + procedure GetButtonClick(Sender: TObject); + procedure HttpCli1Command(Sender: TObject; var s: String); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormShow(Sender: TObject); + procedure HttpCli1DocBegin(Sender: TObject); + procedure HttpCli1DocEnd(Sender: TObject); + procedure PostButtonClick(Sender: TObject); + procedure Check64ButtonClick(Sender: TObject); + procedure HeadButtonClick(Sender: TObject); + procedure HttpCli1RequestDone(Sender: TObject; RqType: THttpRequest; + Error: Word); + procedure AbortButtonClick(Sender: TObject); + procedure Panel1Resize(Sender: TObject); + procedure ParseButtonClick(Sender: TObject); + procedure HttpCli1HeaderData(Sender: TObject); + procedure HttpCli1Cookie(Sender: TObject; const Data: String; + var Accept: Boolean); + procedure HttpCli1LocationChange(Sender: TObject); + private + { Déclarations privées } + Initialized : Boolean; + DocFileName : String; + procedure SetButtonState(State : Boolean); + procedure Display(const Msg : String); + public + { Déclarations publiques } + end; + +var + HttpTestForm: THttpTestForm; + +implementation + +{$R *.DFM} + +const + IniFileName = 'httptest'; + SectionWindow = 'WindowMain'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + SectionData = 'Data'; + KeyUrl = 'URL'; + KeyProxyHost = 'ProxyHost'; + KeyProxyPort = 'ProxyPort'; + KeyData = 'Data'; + KeyDateTime = 'DateTime'; + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; + wsi : TWSADATA; +begin + if not Initialized then begin + Initialized := TRUE; + IniFile := TIniFile.Create(IniFileName); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, + (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, + (Screen.Width - Width) div 2); + URLEdit.Text := IniFile.ReadString(SectionData, KeyURL, ''); + ProxyHostEdit.Text := IniFile.ReadString(SectionData, KeyProxyHost, ''); + ProxyPortEdit.Text := IniFile.ReadString(SectionData, KeyProxyPort, '80'); + DataEdit.Text := IniFile.ReadString(SectionData, KeyData, ''); + DateTimeEdit.Text := IniFile.ReadString(SectionData, KeyDateTime, ''); + IniFile.Free; + { Display version info for program and used components } + wsi := WinsockInfo; + DisplayMemo.Clear; + Display(CopyRight); + Display('Using:'); + Display(' ' + WSocket.CopyRight); + Display(' ' + HttpProt.CopyRight); + Display(' Winsock:'); + Display(' Version ' + + Format('%d.%d', [WinsockInfo.wHighVersion shr 8, + WinsockInfo.wHighVersion and 15])); + Display(' ' + StrPas(@wsi.szDescription)); + Display(' ' + StrPas(@wsi.szSystemStatus)); +{$IFNDEF VER100} + { A bug in Delphi 3 makes lpVendorInfo invalid } + if wsi.lpVendorInfo <> nil then + Display(' ' + StrPas(wsi.lpVendorInfo)); +{$ENDIF} + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.FormClose(Sender: TObject; + var Action: TCloseAction); +var + IniFile : TIniFile; +begin + IniFile := TIniFile.Create(IniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.WriteString(SectionData, KeyURL, URLEdit.Text); + IniFile.WriteString(SectionData, KeyProxyHost, ProxyHostEdit.Text); + IniFile.WriteString(SectionData, KeyProxyPort, ProxyPortEdit.Text); + IniFile.WriteString(SectionData, KeyData, DataEdit.Text); + IniFile.WriteString(SectionData, KeyDateTime, DateTimeEdit.Text); + IniFile.Free; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Display a message in display memo box, making sure we don't overflow it. } +procedure THttpTestForm.Display(const Msg : String); +begin + DisplayMemo.Lines.BeginUpdate; + try + if DisplayMemo.Lines.Count > 200 then begin + { We preserve only 200 lines } + while DisplayMemo.Lines.Count > 200 do + DisplayMemo.Lines.Delete(0); + end; + DisplayMemo.Lines.Add(Msg); + finally + DisplayMemo.Lines.EndUpdate; + { Makes last line visible } + {$IFNDEF VER80} + SendMessage(DisplayMemo.Handle, EM_SCROLLCARET, 0, 0); + {$ENDIF} + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.HeadButtonClick(Sender: TObject); +var + I : Integer; +begin + DisplayMemo.Clear; + DocumentMemo.Clear; + SetButtonState(FALSE); + + try + httpcli1.URL := URLEdit.Text; + httpcli1.Proxy := ProxyHostEdit.Text; + httpcli1.ProxyPort := ProxyPortEdit.Text; + httpcli1.RcvdStream := nil; + if DateTimeEdit.Text <> '' then + httpcli1.ModifiedSince := StrToDateTime(DateTimeEdit.Text) + else + httpcli1.ModifiedSince := 0; + + if httpcli1.Proxy <> '' then + Display('Using proxy ''' + httpcli1.Proxy + ':' + + httpcli1.ProxyPort + '''') + else + Display('Not using proxy'); + + try + httpcli1.Head; + except + Display('HEAD Failed !'); + Display('StatusCode = ' + IntToStr(httpcli1.StatusCode)); + Display('ReasonPhrase = ' + httpcli1.ReasonPhrase); + Exit; + end; + + Display('StatusCode = ' + IntToStr(httpcli1.StatusCode)); + + for I := 0 to httpcli1.RcvdHeader.Count - 1 do + Display('hdr>' + httpcli1.RcvdHeader.Strings[I]); + finally + SetButtonState(TRUE); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.GetButtonClick(Sender: TObject); +var + I : Integer; + DataIn : TStream; +begin + DisplayMemo.Clear; + DocumentMemo.Clear; + SetButtonState(FALSE); + + try + httpcli1.URL := URLEdit.Text; + httpcli1.Proxy := ProxyHostEdit.Text; + httpcli1.ProxyPort := ProxyPortEdit.Text; + httpcli1.AcceptLanguage := 'en, fr'; + httpcli1.RcvdStream := nil; + if DateTimeEdit.Text <> '' then + httpcli1.ModifiedSince := StrToDateTime(DateTimeEdit.Text) + else + httpcli1.ModifiedSince := 0; + + if httpcli1.Proxy <> '' then + Display('Using proxy ''' + httpcli1.Proxy + ':' + + httpcli1.ProxyPort + '''') + else + Display('Not using proxy'); + + try + httpcli1.Get; + except + Display('GET Failed !'); + Display('StatusCode = ' + IntToStr(httpcli1.StatusCode)); + Display('ReasonPhrase = ' + httpcli1.ReasonPhrase); + HttpCli1DocEnd(nil); { This will close the file } + Exit; + end; + + Display('StatusCode = ' + IntToStr(httpcli1.StatusCode)); + + for I := 0 to httpcli1.RcvdHeader.Count - 1 do + Display('hdr>' + httpcli1.RcvdHeader.Strings[I]); + + if Length(DocFileName) = 0 then begin + DocumentMemo.Lines.Add('*** NO DOCUMENT FILE NAME ***'); + end + else begin + DataIn := TFileStream.Create(DocFileName, fmOpenRead); + try + if Copy(httpcli1.ContentType, 1, 5) = 'text/' then + DocumentMemo.Lines.LoadFromStream(DataIn) + else begin + DocumentMemo.Lines.Add('Content type is ' + + httpcli1.ContentType); + DocumentMemo.Lines.Add('Document stored in ''' + + DocFileName + + ''' Size=' + IntToStr(DataIn.Size)); + end; + finally + DataIn.Free; + end; + end; + finally + SetButtonState(TRUE); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.PostButtonClick(Sender: TObject); +var + DataOut : TMemoryStream; + DataIn : TFileStream; + Buf : String; + I : Integer; +begin + DisplayMemo.Clear; + DocumentMemo.Clear; + SetButtonState(FALSE); + + try + DataOut := TMemoryStream.Create; + Buf := DataEdit.Text; + if Length(Buf) > 0 then { Check if some data to post } + DataOut.Write(Buf[1], Length(Buf)); + DataOut.Seek(0, soFromBeginning); + + httpcli1.SendStream := DataOut; + httpcli1.Proxy := ProxyHostEdit.Text; + httpcli1.ProxyPort := ProxyPortEdit.Text; + httpcli1.RcvdStream := nil; + httpcli1.URL := URLEdit.Text; + + if httpcli1.Proxy <> '' then + Display('Using proxy ''' + httpcli1.Proxy + ':' + + httpcli1.ProxyPort + '''') + else + Display('Not using proxy'); + + try + httpcli1.Post; + except + DataOut.Free; + Display('POST Failed !'); + Display('StatusCode = ' + IntToStr(httpcli1.StatusCode)); + Display('ReasonPhrase = ' + httpcli1.ReasonPhrase); + Exit; + end; + DataOut.Free; + + Display('StatusCode = ' + IntToStr(httpcli1.StatusCode)); + + for I := 0 to httpcli1.RcvdHeader.Count - 1 do + Display('hdr>' + httpcli1.RcvdHeader.Strings[I]); + + DataIn := TFileStream.Create(httpcli1.DocName, fmOpenRead); + try + DocumentMemo.Lines.LoadFromStream(DataIn); + finally + DataIn.Free; + end; + finally + SetButtonState(TRUE); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ WARNING: With DELPHI1, change "s: String" to "s: OpenString" } +procedure THttpTestForm.HttpCli1Command(Sender: TObject; var s: String); +begin + Display('cmd> ' + s); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.HttpCli1DocBegin(Sender: TObject); +begin + Display(HttpCli1.ContentType + ' => ' + httpcli1.DocName); + Display('Document = ' + httpcli1.DocName); + + DocFileName := httpcli1.DocName; + + if httpcli1.ContentType = 'image/gif' then + ReplaceExt(DocFileName, 'gif') + else if httpcli1.ContentType = 'image/jpeg' then + ReplaceExt(DocFileName, 'jpg') + else if httpcli1.ContentType = 'image/bmp' then + ReplaceExt(DocFileName, 'bmp'); + + if DocFileName = '' then + DocFileName := 'HttpTst.htm'; + try + httpcli1.RcvdStream := TFileStream.Create(DocFileName, fmCreate); + except + on E:Exception do begin + Display('Error opening file: ' + E.Message); + DocFileName := 'HttpTst.htm'; + Display('Using default file name: ' + DocFileName); + httpcli1.RcvdStream := TFileStream.Create(DocFileName, fmCreate); + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.HttpCli1DocEnd(Sender: TObject); +begin + if httpcli1.RcvdStream <> nil then begin + httpcli1.RcvdStream.Free; + httpcli1.RcvdStream := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.Check64ButtonClick(Sender: TObject); +const + Inp : String = 'Aladdin:open sesame'; + Res : String = 'QWxhZGRpbjpvcGVuIHNlc2FtZQ=='; +begin + if EncodeLine(encBase64, @Inp[1], Length(Inp)) <> Res then + Display('Base64 encoding do not work !') + else + Display('Base64 encoding works OK !'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.SetButtonState(State : Boolean); +begin + GetButton.Enabled := State; + PostButton.Enabled := State; + HeadButton.Enabled := State; + AbortButton.Enabled := not State; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.HttpCli1RequestDone(Sender: TObject; + RqType: THttpRequest; Error: Word); +begin + SetButtonState(TRUE); + if Error <> 0 then + Display('RequestDone Error = ' + IntToStr(Error)) + else + Display('RequestDone, no error'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.AbortButtonClick(Sender: TObject); +begin + HttpCli1.Abort; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.Panel1Resize(Sender: TObject); +begin + GetButton.Left := Panel1.Width - GetButton.Width - 8; + PostButton.Left := GetButton.Left; + HeadButton.Left := GetButton.Left; + AbortButton.Left := GetButton.Left; + URLEdit.Width := GetButton.Left - URLEdit.Left - 8; + DataEdit.Width := URLEdit.Width; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.ParseButtonClick(Sender: TObject); +var + Proto, User, Pass, Host, Port, Path : String; +begin + ParseURL(URLEdit.Text, Proto, User, Pass, Host, Port, Path); + Display('URL = ''' + URLEdit.Text + ''''); + Display('Proto = ''' + Proto + ''''); + Display('Host = ''' + Host + ''''); + Display('Path = ''' + Path + ''''); + Display('Port = ''' + Port + ''''); + Display('User = ''' + User + ''''); + Display('Pass = ''' + Pass + ''''); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.HttpCli1HeaderData(Sender: TObject); +begin +{ Display('Header: "' + HttpCli1.LastResponse + '"'); } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.HttpCli1Cookie(Sender: TObject; const Data: String; + var Accept: Boolean); +begin + Display('Cookie: "' + Data + '"'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpTestForm.HttpCli1LocationChange(Sender: TObject); +begin + Display('Location changed to "' + HttpCli1.Location + '"'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/md5test.dpr b/ICS_zlog/Delphi/Internet/md5test.dpr new file mode 100644 index 00000000..33970051 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/md5test.dpr @@ -0,0 +1,12 @@ +program md5test; + +uses + Forms, + md5test1 in 'md5test1.pas' {MD5TestForm}; + +{$R *.RES} + +begin + Application.CreateForm(TMD5TestForm, MD5TestForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/md5test1.dfm b/ICS_zlog/Delphi/Internet/md5test1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..992de182b46a74be692dc2d1983ff25a160db7eb GIT binary patch literal 505 zcmZ9I%}#?r6orSOh5lh06Bq8-nCQZ`8x!MFTB1oSO_`+I(sC&ifgx}k>cXe+9bEWY zK7(uJuhqD_cV^C+@0{-rVYBfKo7l{>7Be#He@cX~xjE{U=a8Z)lCWF6sprNNJd{5q znTc3_mzqoNqA$mi@&J76qx?ox!-V`$Q2obJ$B2B%9eh$%k9YtLD6QmZaYz`+mLXt(%bkFK$mE9zK0;4 zL-H7He7fosMzw`T6gG9%5S-*(3rKeXmTQ@aUKWAqs>(yHIu6y2Y5u7QX|jpSu{Czk zDTc~MFKzmDEmwzH=vj+7Yb$Xfp`=kjDMuk8D!bnyim07~RnuRy+nVY1z;u3OIyFQX e?-2B&X_s&Fu7CfLR4Xz9zIj#)^vbu~2_Zir1DZMj literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/md5test1.pas b/ICS_zlog/Delphi/Internet/md5test1.pas new file mode 100644 index 00000000..4eacb22a --- /dev/null +++ b/ICS_zlog/Delphi/Internet/md5test1.pas @@ -0,0 +1,81 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE. Based on work given by Louis S. Berman from + BrainTree Ltd, lsb@braintree.com +Description: MD5 is an implmentation for the MD5 Message-Digest Algorithm + as described in RFC-1321 +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Creation: October 1997 +Version: 1.01 +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Sep 12, 1998 V1.01 Beautified source + +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit MD5Test1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, MD5, StdCtrls; + +type + TMD5TestForm = class(TForm) + DataEdit: TEdit; + MD5Button: TButton; + MD5ResultLabel: TLabel; + procedure MD5ButtonClick(Sender: TObject); + private + { Déclarations privées } + public + { Déclarations publiques } + end; + +var + MD5TestForm: TMD5TestForm; + +implementation + +{$R *.DFM} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TMD5TestForm.MD5ButtonClick(Sender: TObject); +var + Buffer : String; +begin + Buffer := DataEdit.Text + #0; + MD5ResultLabel.Caption := GetMD5(@Buffer[1], Length(Buffer) - 1); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. diff --git a/ICS_zlog/Delphi/Internet/mtsrv.dpr b/ICS_zlog/Delphi/Internet/mtsrv.dpr new file mode 100644 index 00000000..e0900c4b --- /dev/null +++ b/ICS_zlog/Delphi/Internet/mtsrv.dpr @@ -0,0 +1,14 @@ +program mtsrv; + +uses + Forms, + mtsrv1 in 'mtsrv1.pas' {ServerForm}, + mtsrv2 in 'mtsrv2.pas'; + +{$R *.RES} + +begin + Application.Initialize; + Application.CreateForm(TServerForm, ServerForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/mtsrv.ico b/ICS_zlog/Delphi/Internet/mtsrv.ico new file mode 100644 index 0000000000000000000000000000000000000000..c6ead6c6561ed02ea0e8adb7c0bec87a1b19b57e GIT binary patch literal 766 zcmchVF>-`33`IYg%%p(Hq)JVhW8`Q)61`lwUmb!n6;~inVs}}R-ANZ2ee?aTZyO_Z zv~he>#MhJbPX9rUU*0GenwpV@ngb1|H9d=O|fID8#)dfm+0-<`I5wEzGB literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/mtsrv.res b/ICS_zlog/Delphi/Internet/mtsrv.res new file mode 100644 index 0000000000000000000000000000000000000000..59352340383d72535eb83d22516adbcf5a0c95f8 GIT binary patch literal 876 zcmcgrF>b>!3_LXjTEIr&p%3ubu}?_RsYBW?=}F$HL3{WJkDdGl^+?6B-6rT(0zB$` zBt_X40QB@ys&l!que({_F( zlp2V2E*}U0i0p_b{ZL)GOJt*8j!NwJAxe{k-Wd zuoGo~qZ_C;LM{Wj!7n~FvY$p7rV7(feytwceh@7ES>MR8=_j;HfA(X-l0S1!D}znU z>P($(WzNsfX71;?=zdCmYq)7^XI#v`-$MCP+7%-mfrrRnjQ(%Ny==cQa_=YZ`a&;d dk0W03jt}}9J{f0Q-wV490e#>3t*~1Z@C{4WiO~Q6 literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/mtsrv1.dfm b/ICS_zlog/Delphi/Internet/mtsrv1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..661680b4f31c4fdb79db4b4f1dc63d830368f145 GIT binary patch literal 1174 zcmah}y>i+>5I!W(AILEAcqS<_<0_NNLz6BI$Y|_|urRvBWqg(v>&C|&qdOV9OqW;4 zTcph!|9;xlUkBl6GXFA}`{8_whJ$Zygz(HCc5wvRBV@kFmQEwK z16U}nuVb;&tj-NhRI2w|#s$#(ROv>`^vFt4!HvC`jwhJNOgm;{#eEV(≶sc`3;x zD6@Y)@kgHn{MEY{&7%o+YHJnKi`fn3iCANJQr*f>m(u>&6}lozFx+W$8WAo}i$3Y1 zj*rwcgDyG>S>k0t6ogpd*-_7y*z~g{73*ST{egNgx>%2i$KsiiB z0+wA$0bNp6+&~MNC7kfY&|If-n#8HFYAGpLY>$#8GtA*x^|ogsQ-+~{aZsIECX_IA z6|d|-#DpEV)~d?CHFT#rQxvDgjwX=Ub_G2mm36ceFIN}`TFah8E}=|i4Lq@230{1b zusS!{MX!qG1u2W$8$A-r$Q=Xo?ZKq~n|nUXWs2z%M6R@tb_6`}8M&8cZ!Jr3Rh$7~ z-GYaE$U+`27N)b7Tj?N{c3GOv;~vc_K@fD{-i + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: +Nov 18, 1997 V1.01 Corrected isxdigit (By Paul Taylor ) +Apr 26, 1998 V1.02 MultiThreaded property correctly setup to TRUE. + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit MtSrv1; + +interface + +{$IFDEF VER80} + 'This sample program use threads and hence is not compatible with Delphi 1'; +{$ENDIF} +{$J+} + +uses + Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + WSocket, MtSrv2, StdCtrls; + +type + TServerForm = class(TForm) + ServerWSocket: TWSocket; + DisconnectButton: TButton; + QuitButton: TButton; + ClientListBox: TListBox; + DisconnectAllButton: TButton; + procedure ServerWSocketSessionAvailable(Sender: TObject; Error: Word); + procedure FormShow(Sender: TObject); + procedure DisconnectButtonClick(Sender: TObject); + procedure QuitButtonClick(Sender: TObject); + procedure DisconnectAllButtonClick(Sender: TObject); + procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); + private + procedure ClientThreadTerminate(Sender: TObject); + procedure DisconnectAll; + end; + +var + ServerForm: TServerForm; + +implementation + +{$R *.DFM} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Check if a character is a valid hex digit } +function isxdigit(Ch : char) : Boolean; +begin + Result := (ch in ['0'..'9']) or (ch in ['a'..'f']) or (ch in ['A'..'F']); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Convert an hexdigit to an integer } +function xdigit(Ch : char) : Integer; +begin + if ch in ['0'..'9'] then + Result := ord(Ch) - ord('0') + else + Result := (ord(Ch) and 15) + 9; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Convert the ascii representation of a hex number to an integer } +function htoi(value : PChar) : Integer; +var + i : Integer; +begin + Result := 0; + i := 0; + while (Value[i] <> #0) and (Value[i] = ' ') do + i := i + 1; + while (Value[i] <> #0) and (isxDigit(Value[i])) do begin + Result := Result * 16 + xdigit(Value[i]); + i := i + 1; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event is generated when a client is connecting } +procedure TServerForm.ServerWSocketSessionAvailable(Sender: TObject; + Error: Word); +var + ClientThread : TClientThread; +begin + { Create a new thread to handle client request } + ClientThread := TClientThread.Create(ServerWSocket.Accept); + + { Assign the thread's OnTerminate event } + ClientThread.OnTerminate := ClientThreadTerminate; + + { Add the thread to the listbox which is our client list } + ClientListBox.Items.Add(IntToHex(Integer(ClientThread), 8)); + + { Then start the client thread work } + { because it was created in the blocked state } + ClientThread.Resume; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerForm.FormShow(Sender: TObject); +const + FirstTime : Boolean = TRUE; +begin + if FirstTime then begin + FirstTime := FALSE; + ServerWSocket.Proto := 'tcp'; { We use a TCP connection } + ServerWSocket.Port := 'telnet'; { We wants to use telnet } + ServerWSocket.Addr := '0.0.0.0'; { We accept any client } + ServerWSocket.Listen; { Start server accepting } + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event is generated when the user clicks on the 'Disconnect' button } +{ when he wants to disconnect the selected client in the listbox. } +procedure TServerForm.DisconnectButtonClick(Sender: TObject); +var + ClientThread : TClientThread; + Buf : String; +begin + { No selected item, nothing to do } + if ClientListBox.ItemIndex < 0 then + Exit; + + { Extract the ClientThread pointer from the list box } + Buf := ClientListBox.Items[ClientListBox.ItemIndex]; + ClientThread := TClientThread(htoi(PChar(Buf))); + + { Call ClientThread.Release which will stop the thread } + { In consequence, the OnTerminate event will be generated } + ClientThread.Release; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when one of the client thread terminate } +{ We will find this thread in our listbox, remove it and destroy the } +{ TWSocket object use by the corresponding client. } +procedure TServerForm.ClientThreadTerminate(Sender: TObject); +var + ClientThread : TClientThread; + Buf : String; + Index : Integer; +begin + { A thread has been terminated, remove it from our list and destroy } + { the ClientWSocket we passed to the thread. } + for Index := 0 to ClientListBox.Items.Count - 1 do begin + Buf := ClientListBox.Items[Index]; + ClientThread := TClientThread(htoi(PChar(Buf))); + if ClientThread = TClientThread(Sender) then begin + { Remove the client from our listbox } + ClientListBox.Items.Delete(Index); + Break; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This procedure scan the listbox and halt every ClientThread } +procedure TServerForm.DisconnectAll; +var + ClientThread : TClientThread; + Buf : String; +begin + while ClientListBox.Items.Count > 0 do begin + Buf := ClientListBox.Items[0]; + ClientThread := TClientThread(htoi(PChar(Buf))); + ClientThread.Release; + Application.ProcessMessages; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerForm.QuitButtonClick(Sender: TObject); +begin + Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerForm.DisconnectAllButtonClick(Sender: TObject); +begin + DisconnectAll; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); +begin + DisconnectAll; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/mtsrv2.pas b/ICS_zlog/Delphi/Internet/mtsrv2.pas new file mode 100644 index 00000000..2fc3ab4b --- /dev/null +++ b/ICS_zlog/Delphi/Internet/mtsrv2.pas @@ -0,0 +1,191 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: This little application shows how to use the TWSocket in a + multithreaded application. It is a very basic telnet werver. + Each time a client connect to the server, he receive an "hello" + message. Then every character sent is echoed back to the client. + There are two units is this application: one for the main + server code, and one for the client thread. + Each time a client connect to the server, a new TWSocket is + created and a new thread is launched to handle the client + work. When the client disconnect, the TWSocket and the thread + are destroyed. + To see this demo working on your computer, start the demo then + start several copies of the TELNET client program (the one which + comes with Windows 95 is perfect). Then using each telnet, connect + to 127.0.0.1. You'll see a new connection in the list box. You + must receive the "hello" message and see each character as you + type them. You can use the Disconnect button from the application + or from the telnet client to see what happends (the connection + should be closed). +Creation: September 21, 1997 +Version: 1.02 +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit MtSrv2; + +interface + +uses + Windows, Messages, Classes, WinSock, WSocket; + +type + TClientThread = class(TThread) + private + FClientSocket : TWSocket; + FClientHSocket : TSocket; + procedure ServerWSocketDataAvailable(Sender: TObject; Error: Word); + procedure ServerWSocketSessionClosed(Sender: TObject; Error: Word); + protected + procedure Execute; override; + public + constructor Create(ClientHSocket : TSocket); + destructor Destroy; override; + procedure Release; + + property ClientWSocket : TWSocket read FClientSocket write FClientSocket; + end; + +implementation + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Create a new thread in the blocked state. This allow the user to register } +{ the client thread before it actually start working. } +constructor TClientThread.Create(ClientHSocket : TSocket); +begin + FClientHSocket := ClientHSocket; + FreeOnTerminate := TRUE; + inherited Create(TRUE); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Destroy the thread. Destroy the ClientWSocket if needed. } +destructor TClientThread.Destroy; +begin + if Assigned(FClientSocket) then begin + FClientSocket.Destroy; + FClientSocket := nil; + end; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This method will be called by the main server thread to terminated a } +{ client thread. } +procedure TClientThread.Release; +begin + PostMessage(FClientSocket.Handle, WM_QUIT, 0, 0); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This is the main thread routine. There is not much to do because TWSocket } +{ is event driven. So everythong to do is done inside an event handler, } +{ mostly the OnDataAvailable event handler which is triggered each time } +{ the client send something to the server. } +procedure TClientThread.Execute; +begin + { Create the client TWSocket. It is important to create it inside the } + { Execute method because it *must* be created by the thread. Otherwise } + { the messages sent by winsock would be processed in the main thread } + { context, effectively disabling multi-threading. } + FClientSocket := TWSocket.Create(nil); + FClientSocket.HSocket := FClientHSocket; + FClientSocket.OnDataAvailable := ServerWSocketDataAvailable; + FClientSocket.OnSessionClosed := ServerWSocketSessionClosed; + + { Send the welcome message } + FClientSocket.SendStr('Hello !' + #10 + #13 + '> '); + + { Message loop to handle TWSocket messages } + { The loop is exited when WM_QUIT message is received } + FClientSocket.MessageLoop; + + { Returning from the Execute function effectively terminate the thread } + ReturnValue := 0; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when the client connection is closed. } +procedure TClientThread.ServerWSocketSessionClosed( + Sender: TObject; Error: Word); +begin + PostMessage(FClientSocket.Handle, WM_QUIT, 0, 0); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when the client has sent some data to the } +{ server. It is here that we must place the client requests execution } +{ probably by assembling data in lines, parsing those lines for commands } +{ and executing the commands. Here for simplicity, we just echo back the } +{ data sent by the user, without doing anything serious. } +{ To demonstrate that blocking a thread do not block the others, when a '*' } +{ is received, we go to Sleep for a few seconds, effectively blocking the } +{ the client. But as we are multi-threaded, this do not block any other } +{ client. } +{ Do not forget to call the Synchronize method if you need to update the } +{ user interface. Only the main thread can do it (VCL is not thread safe). } +procedure TClientThread.ServerWSocketDataAvailable( + Sender: TObject; + Error: Word); +var + Buffer : array [0..4095] of char; + Count : Integer; +begin + { Receive as much data as possible } + Count := FClientSocket.Receive(@Buffer, SizeOf(Buffer)); + + { If data received, then process it } + if Count > 0 then begin + if Buffer[0] = '*' then begin + { If the first character is '*' then go to sleep a while } + FClientSocket.SendStr('Sleeping for 15 sec...' + #10 + #13); + Sleep(15000); + FClientSocket.SendStr('Wake up !' + #10 + #13); + end + else + { Just echo data back to client } + FClientSocket.Send(@Buffer, Count); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/newsrdr.dpr b/ICS_zlog/Delphi/Internet/newsrdr.dpr new file mode 100644 index 00000000..90a3d24f --- /dev/null +++ b/ICS_zlog/Delphi/Internet/newsrdr.dpr @@ -0,0 +1,12 @@ +program NewsRdr; + +uses + Forms, + NewsRdr1 in 'NewsRdr1.pas' {NNTPForm}; + +{$R *.RES} + +begin + Application.CreateForm(TNNTPForm, NNTPForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/pingtst.dpr b/ICS_zlog/Delphi/Internet/pingtst.dpr new file mode 100644 index 00000000..fe956a09 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/pingtst.dpr @@ -0,0 +1,13 @@ +program PingTst; + +uses + Forms, + PingTst1 in 'PingTst1.pas' {PingTstForm}; + +{$R *.RES} + +begin + Application.Initialize; + Application.CreateForm(TPingTstForm, PingTstForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/poptst.dpr b/ICS_zlog/Delphi/Internet/poptst.dpr new file mode 100644 index 00000000..c3199e73 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/poptst.dpr @@ -0,0 +1,14 @@ +program PopTst; + +uses + Forms, + PopTst1 in 'PopTst1.pas' {POP3ExcercizerForm}, + PopTst2 in 'PopTst2.pas' {MessageForm}; + +{$R *.RES} + +begin + Application.CreateForm(TPOP3ExcercizerForm, POP3ExcercizerForm); + Application.CreateForm(TMessageForm, MessageForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/poptst2.dfm b/ICS_zlog/Delphi/Internet/poptst2.dfm new file mode 100644 index 0000000000000000000000000000000000000000..b2ece7d5c7489839f72518923dbbc5f3db61b1df GIT binary patch literal 337 zcmYk0K~BRk5Jl~nBqeDij?fcS-Lq;#14s>xu%&KslWAhfu_N0O?SjLxmg$dIg`9%Ik zRIVW(ICub2H;%mFFy);SS_R=5i!!a;G}Tg@a9qlbP?dgVuy^rLoIvmUdib7r3qg|8 z3FXR8C>XIj@zfn8#3(7m9;7Y6JgTzsUZQ^JJdq&(sNL%LPS{TJL!Sp<5B0jp=yhR%Pkbq(r76c+}JR%cA;G}Vtl(c6&Md4?-$+d BX^#K^ literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/poptst2.pas b/ICS_zlog/Delphi/Internet/poptst2.pas new file mode 100644 index 00000000..ac6c5990 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/poptst2.pas @@ -0,0 +1,33 @@ +{ +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + +} +unit PopTst2; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls; + +type + TMessageForm = class(TForm) + DisplayMemo: TMemo; + private + { Déclarations privées } + public + { Déclarations publiques } + end; + +var + MessageForm: TMessageForm; + +implementation + +{$R *.DFM} + +end. diff --git a/ICS_zlog/Delphi/Internet/server5.dpr b/ICS_zlog/Delphi/Internet/server5.dpr new file mode 100644 index 00000000..bcc9eba2 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/server5.dpr @@ -0,0 +1,12 @@ +program server5; + +uses + Forms, + Srv5 in 'Srv5.pas' {ServerForm}; + +{$R *.RES} + +begin + Application.CreateForm(TServerForm, ServerForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/srv5.dfm b/ICS_zlog/Delphi/Internet/srv5.dfm new file mode 100644 index 0000000000000000000000000000000000000000..155ad5940f8cdc5f8083fa2c38854add31524f70 GIT binary patch literal 1294 zcmdT@O>fgc5ZySf*LLDIDk@TMJs}RL$_0r7m(;b@3a5_Zg&tw+oz$ytcB9=*Qm!2M zDf~l(IDtRXr0@$szPy>)`FQijzXC+^c={opCfRh1hJ&Ab2$4xL?2#Pw3Us3MJlMg# z6lS*j19gd7biZ}>Z#c7M_iM+!1b$cA?iYk3y0BbH_es`%q=eGgFT}Z(2`!+XC~424 zl4=7MA6~@C=zU5)Mwg>$9+RMrHaY!5+;GX%n!tnYHG#I3^WAT(YdQxv9OtJwmFBdX zl+W7y+3;8hbUf8if=70K!Z_U&*3$J_U8BO^*<{B&D|? z{3|(A4Qe*vT-FP4yq3T7YD3=%x9oQb2w`%*v{uQ%1viC~5(?Wop4NJ~srBx$*2%V3 z@5L?=U%-qmh4pbP>8$|fd4%3J)EtB}83|t8rCh>T zG4T8vrF_n9bpsuQYcrP2b;6)|6c?rPTEw{Z_9jYO*R>!d*!_uCR=HhUEc{dzRE!wY zE*_pWU+Ze#cZT7(8lRK0(u7sx`;8eFIvsxsO9OQ&ZxE^ZLP?M|YtGB` z&{3r%7*pNaXhpfGw}DT#y#5aL6R|WU;d4++>%8@IkSr1O&fxyq)W&sn4^;Fj)_0&Y znayT6Ser*PY{6qb3hM2d6jmVI&g*B5HCo!T8ju&X{sHi@sh?b{Ki#e7gZ6%&DpE=G bzbkUMRU{J10K?C>q&9N2{(n)6HwdBM9%-T^ literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/srv5.pas b/ICS_zlog/Delphi/Internet/srv5.pas new file mode 100644 index 00000000..53080d83 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/srv5.pas @@ -0,0 +1,142 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Object: Demo program to show how to use TWSocket object is a very + simple server program. This server just wait for a client to + connect, then send 'Hello'. When the user click on the + disconnect button, the client is disconnected. +Creation: September 19, 1996 +Version: 2.02 +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1996, 1997, 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Mar 19, 1997 Use enhanced TWSocket object +Sep 06, 1997 Beautified +Aug 20, 1999 V2.02 Changed comment to correctly talk about interface use. + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit Srv5; + +{$J+} + +interface + +uses + SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, + Controls, Forms, Dialogs, WSocket, Winsock, StdCtrls; + +type + TServerForm = class(TForm) + SrvSocket: TWSocket; + InfoLabel: TLabel; + CliSocket: TWSocket; + DisconnectButton: TButton; + procedure SrvSocketSessionAvailable(Sender: TObject; Error: Word); + procedure FormShow(Sender: TObject); + procedure DisconnectButtonClick(Sender: TObject); + procedure CliSocketSessionClosed(Sender: TObject; Error: Word); + end; + +var + ServerForm: TServerForm; + +implementation + +{$R *.DFM} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerForm.FormShow(Sender: TObject); +const + FirstTime : Boolean = TRUE; +begin + if FirstTime then begin + FirstTime := FALSE; { Do it only once ! } + SrvSocket.Addr := '0.0.0.0'; { Use any interface } + SrvSocket.Listen; { Start listening for client } + InfoLabel.Caption := 'Waiting for client'; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* This event handler is called once a client has connected the server. *} +procedure TServerForm.SrvSocketSessionAvailable(Sender: TObject; Error: Word); +var + NewHSocket : TSocket; + PeerName : TSockAddrIn; + Peer : String; +begin + { We need to accept the client connection } + NewHSocket := SrvSocket.Accept; + + { And then associate this connection with our client socket } + CliSocket.Dup(NewHSocket); + + { Wants to know who is connected to display on screen } + CliSocket.GetPeerName(PeerName, Sizeof(PeerName)); + + { User likes to see internet address in dot notation } + Peer := IntToStr(ord(PeerName.sin_addr.S_un_b.s_b1)) + '.' + + IntToStr(ord(PeerName.sin_addr.S_un_b.s_b2)) + '.' + + IntToStr(ord(PeerName.sin_addr.S_un_b.s_b3)) + '.' + + IntToStr(ord(PeerName.sin_addr.S_un_b.s_b4)); + InfoLabel.Caption := 'Remote ' + Peer + ' connected'; + + { Send a welcome message to the client } + CliSocket.SendStr('Hello' + #13 + #10); + + { Enable the server user to disconect the client } + DisconnectButton.Enabled := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* This event handler is called once the user clicks on Ddisconnect *} +procedure TServerForm.DisconnectButtonClick(Sender: TObject); +begin + CliSocket.ShutDown(2); { Shut the communication down } + CliSocket.Close; { Close the communication } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* This event handler is called once the client connection is broken. *} +{* Either by the client or the server. *} +procedure TServerForm.CliSocketSessionClosed(Sender: TObject; Error: Word); +begin + DisconnectButton.Enabled := FALSE; + InfoLabel.Caption := 'Waiting for client';{ Inform the user } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/srvdemo.dpr b/ICS_zlog/Delphi/Internet/srvdemo.dpr new file mode 100644 index 00000000..3406c31f --- /dev/null +++ b/ICS_zlog/Delphi/Internet/srvdemo.dpr @@ -0,0 +1,13 @@ +program SrvDemo; + +uses + Forms, + SrvDemo1 in 'SrvDemo1.pas' {SrvForm}, + SrvDemo2 in 'SrvDemo2.pas' {CliForm}; + +{$R *.RES} + +begin + Application.CreateForm(TSrvForm, SrvForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/thrdsrv1.dfm b/ICS_zlog/Delphi/Internet/thrdsrv1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..d0f9040c670e7de848f2bc8ab73d0d0cea88fcb8 GIT binary patch literal 1143 zcmZuw%We}f6!lD+dF0gsst_QdEI~q5S+HZ1OcS+I(up#LEU7zlld5eLKcmC zcrb#wuKjXqSS)LQocfGrI+dBM}%y=s&jZFgxS4^IdO7GfcoMOG>ol}fp2E7XsjQ11JBkI@D9>x7wx z0F!IGor@5v<1rMXc}CTekxhvoQoVmnRr`&$TmfMbqri20L^-IFL`%vS%JCj@p+=HQ z!C2o&?|Vx1h0gDfcM$5}St8Q!ppBF_AUk`}$DpJhiwuIWL?c>IZ7ky;zYGUF^W1jB zHVx8T1Qp7t4(byrwD4*=U4|o(64uKy>G`K8_N!78A+_h6w#O@`sj&}`46-1!VMLS; zI(P75iSfvF!YQm2lvKe{B#Ncr=K8TUplYIa%=?SMIt82XU+rJzL8&!lE0tqffLLkw zbC>|nhKwwf-?~+0aA`b1Skv5b0W#+CeC{`H)h;acHu>GWk=O{RMsNenb3VPWQE#Pl zvl~rG`8xb#RkmD;{j}F7oP+e9&48t%fUXwZ>hZOz3Ksp9+ITM$A?4J!r{x?tcZ;PF~=IZUdezMorDg(c> JZ{f;V{6CO{b*caW literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/thrdsrv1.pas b/ICS_zlog/Delphi/Internet/thrdsrv1.pas new file mode 100644 index 00000000..3c666efe --- /dev/null +++ b/ICS_zlog/Delphi/Internet/thrdsrv1.pas @@ -0,0 +1,491 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François Piette +Creation: Sep 02, 2001 +Version: 1.01 +Description: Basic TCP server showing how to use TWSocketServer and + TWSocketClient components with threads. + This demo is mostly the same as TcpSrv demo but use a thread to + run client code. This is needed if client operation is lengthy + and blocking (such as a long database query) but otherwise will + consume more CPU cycles in task switching and makes thing much + more complexe because multithreading requires synchronization. +History: +Feb 24, 2002 V1.01 Wilfried Mestdagh added ThreadDetach + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit ThrdSrv1; + +interface + +{$IFDEF VER80} + 'This sample program use threads and hence is not compatible with Delphi 1'; +{$ENDIF} + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, IniFiles, StdCtrls, ExtCtrls, WSocket, WSocketS; + +const + ThrdSrvVersion = 101; + CopyRight = ' ThrdSrv (c) 2001-2002 by François PIETTE. V1.01'; + WM_APPSTARTUP = WM_USER + 1; + +type + TDisplayProc = procedure (const Msg : String) of object; + + { TClientThread is our worker thread class. Each time a client connect, a } + { new TClientThread is instanciated and client socket attached to it so } + { events are processed in the thread's context. } + { Remember that multithreading requires synchronization, specially when } + { updating GUI or accessing shared data. } + { TClientThread uses OnDisplay event to display data on the application } + { main form. Synchronization is automatically done. } + TClientThread = class(TThread) + private + FWSocket : TWSocket; { Reference to client socket } + FMsg : String; { Message to be displayed } + FOnDisplay : TDisplayProc; { Event variable } + FThreadAttached : Boolean; { TRUE once socket attached } + procedure DisplayMsg; { Synchronized procedure } + public + procedure Execute; override; { Main method } + procedure Display(const Msg : String); { Takes care of synchroniz. } + published + property WSocket : TWSocket read FWSocket + write FWSocket; + property ThreadAttached : Boolean read FThreadAttached + write FThreadAttached; + property OnDisplay : TDisplayProc read FOnDisplay + write FOnDisplay; + end; + + { TThrdSrvClient is the class which will be instanciated by server } + { component for each new client. N simultaneous clients means N } + { TThrdSrvClient will be instanciated. Each being used to handle only a } + { single client. } + { We can add any data that has to be private for each client, such as } + { receive buffer or any other data needed for processing. } + TThrdSrvClient = class(TWSocketClient) + public + ClientThread : TClientThread; + RcvdLine : String; + ConnectTime : TDateTime; + end; + + { Application main from } + TTcpSrvForm = class(TForm) + ToolPanel: TPanel; + DisplayMemo: TMemo; + WSocketServer1: TWSocketServer; + procedure FormShow(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure WSocketServer1ClientConnect(Sender: TObject; + Client: TWSocketClient; Error: Word); + procedure WSocketServer1ClientDisconnect(Sender: TObject; + Client: TWSocketClient; Error: Word); + procedure WSocketServer1BgException(Sender: TObject; E: Exception; + var CanClose: Boolean); + procedure WSocketServer1ClientCreate(Sender: TObject; + Client: TWSocketClient); + private + FIniFileName : String; + FInitialized : Boolean; + procedure Display(const Msg : String); + procedure WMAppStartup(var Msg: TMessage); message WM_APPSTARTUP; + procedure ClientDataAvailable(Sender: TObject; Error: Word); + procedure ProcessData(Client : TThrdSrvClient); + procedure ClientBgException(Sender : TObject; + E : Exception; + var CanClose : Boolean); + procedure ClientLineLimitExceeded(Sender : TObject; + Cnt : LongInt; + var ClearData : Boolean); +{$IFDEF VER140} + { Delphi 6 changed the rules about synchronization... } + procedure WakeMainThread(Sender: TObject); +{$ENDIF} + public + property IniFileName : String read FIniFileName write FIniFileName; + end; + +var + TcpSrvForm: TTcpSrvForm; + +implementation + +{$R *.DFM} + +const + SectionWindow = 'WindowTcpSrv'; + KeyTop = 'Top'; + KeyLeft = 'Left'; + KeyWidth = 'Width'; + KeyHeight = 'Height'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpSrvForm.FormCreate(Sender: TObject); +begin + { Compute INI file name based on exe file name. Remove path to make it } + { go to windows directory. } + FIniFileName := LowerCase(ExtractFileName(Application.ExeName)); + FIniFileName := Copy(FIniFileName, 1, Length(FIniFileName) - 3) + 'ini'; + +{$IFDEF VER140} + { With Delphi 6, we need to waken mainthread ourself ! } + Classes.WakeMainThread := Self.WakeMainThread; +{$ENDIF} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpSrvForm.FormShow(Sender: TObject); +var + IniFile : TIniFile; +begin + if not FInitialized then begin + FInitialized := TRUE; + + { Fetch persistent parameters from INI file } + IniFile := TIniFile.Create(FIniFileName); + Width := IniFile.ReadInteger(SectionWindow, KeyWidth, Width); + Height := IniFile.ReadInteger(SectionWindow, KeyHeight, Height); + Top := IniFile.ReadInteger(SectionWindow, KeyTop, + (Screen.Height - Height) div 2); + Left := IniFile.ReadInteger(SectionWindow, KeyLeft, + (Screen.Width - Width) div 2); + IniFile.Destroy; + DisplayMemo.Clear; + { Delay startup code until our UI is ready and visible } + PostMessage(Handle, WM_APPSTARTUP, 0, 0); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTcpSrvForm.FormClose(Sender: TObject; var Action: TCloseAction); +var + IniFile : TIniFile; +begin + { Save persistent data to INI file } + IniFile := TIniFile.Create(FIniFileName); + IniFile.WriteInteger(SectionWindow, KeyTop, Top); + IniFile.WriteInteger(SectionWindow, KeyLeft, Left); + IniFile.WriteInteger(SectionWindow, KeyWidth, Width); + IniFile.WriteInteger(SectionWindow, KeyHeight, Height); + IniFile.Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Display a message in our display memo. Delete lines to be sure to not } +{ overflow the memo which may have a limited capacity. } +procedure TTcpSrvForm.Display(const Msg : String); +var + I : Integer; +begin + DisplayMemo.Lines.BeginUpdate; + try + if DisplayMemo.Lines.Count > 200 then begin + for I := 1 to 50 do + DisplayMemo.Lines.Delete(0); + end; + DisplayMemo.Lines.Add(Msg); + finally + DisplayMemo.Lines.EndUpdate; + {$IFNDEF VER80} + { Scroll to makes caret visible } + SendMessage(DisplayMemo.Handle, EM_SCROLLCARET, 0, 0); + {$ENDIF} + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This is our custom message handler. We posted a WM_APPSTARTUP message } +{ from FormShow event handler. Now UI is ready and visible. } +procedure TTcpSrvForm.WMAppStartup(var Msg: TMessage); +begin + Display(Trim(CopyRight)); { This demo version } + Display(Trim(wsocket.Copyright)); { TWSocket version } + Display(Trim(wsockets.CopyRight)); { TWSocketServer version } + Display(''); + Display('MainThreadID : $' + IntToHex(GetCurrentThreadID, 8)); + WSocketServer1.Proto := 'tcp'; { Use TCP protocol } + WSocketServer1.Port := 'telnet'; { Use telnet port } + WSocketServer1.Addr := '0.0.0.0'; { Use any interface } + WSocketServer1.ClientClass := TThrdSrvClient; { Use our component } + WSocketServer1.Listen; { Start litening } + Display('Waiting for clients on port ''' + WSocketServer1.Port + '''...'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER140} +{ Delphi 6 requires a little help in order for TThread.Synchronize to work. } +{ We just post a do-nothing message to the form which will waken up the } +{ maine thread and execute waiting synchronized procedures. } +procedure TTcpSrvForm.WakeMainThread(Sender: TObject); +begin + PostMessage(Handle, WM_NULL, 0, 0); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Called in main thread context. } +procedure TTcpSrvForm.WSocketServer1ClientCreate( + Sender : TObject; + Client : TWSocketClient); +begin + with Client as TThrdSrvClient do begin + Client.ThreadDetach; + Client.MultiThreaded := TRUE; + ClientThread := TClientThread.Create(TRUE); + ClientThread.FreeOnTerminate := TRUE; + ClientThread.WSocket := Client; + ClientThread.OnDisplay := Display; + ClientThread.Suspended := FALSE; + { Wait until thread is started and has attached client socket to } + { his own context. } + while not ClientThread.ThreadAttached do + Sleep(0); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event is called each time a new client is connecting. } +{ Called in main thread context. } +procedure TTcpSrvForm.WSocketServer1ClientConnect( + Sender : TObject; + Client : TWSocketClient; + Error : Word); +begin + with Client as TThrdSrvClient do begin + Display('Client connected.' + + ' Remote: ' + PeerAddr + '/' + PeerPort + + ' Local: ' + GetXAddr + '/' + GetXPort + + ' ThreadID : $' + IntToHex(ClientThread.ThreadID, 8)); + LineMode := TRUE; + LineEdit := TRUE; + LineLimit := 80; { Do not accept long lines } + OnDataAvailable := ClientDataAvailable; + OnLineLimitExceeded := ClientLineLimitExceeded; + OnBgException := ClientBgException; + ConnectTime := Now; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called each time a client disconnect. } +{ This procedure is called in main thread context. } +procedure TTcpSrvForm.WSocketServer1ClientDisconnect( + Sender : TObject; + Client : TWSocketClient; + Error : Word); +begin + with Client as TThrdSrvClient do begin + Display('Client disconnecting: ' + PeerAddr + ' ' + + 'Duration: ' + FormatDateTime('hh:nn:ss', + Now - ConnectTime) + + ' ThreadID : $' + IntToHex(GetCurrentThreadID, 8)); + + { Clear WSocket reference in worker thread } + { ClientThread.WSocket := nil; } + { Break message pump within worker thread } + PostThreadMessage(ClientThread.ThreadID, WM_QUIT, 0, 0); + { Allow up to 10 second for thread termination } + WaitForSingleObject(ClientThread.Handle, 10000); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This procedure is called in client thread context. So be aware about GUI } +{ update: you must use synchronize like ClientThread.Display does. } +procedure TTcpSrvForm.ClientLineLimitExceeded( + Sender : TObject; + Cnt : LongInt; + var ClearData : Boolean); +begin + with Sender as TThrdSrvClient do begin + ClientThread.Display('Line limit exceeded from ' + GetPeerAddr + '. Closing.'); + ClearData := TRUE; + Close; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Each time a client has datavailable triggers this event handler. } +{ We receive data (line mode) and execute "commands". } +{ This procedure is called in client thread context. So be aware about GUI } +{ update: you must use synchronize like ClientThread.Display does. } +procedure TTcpSrvForm.ClientDataAvailable( + Sender : TObject; + Error : Word); +begin + with Sender as TThrdSrvClient do begin + { We use line mode. We will receive complete lines } + RcvdLine := ReceiveStr; + { Remove trailing CR/LF } + while (Length(RcvdLine) > 0) and + (RcvdLine[Length(RcvdLine)] in [#13, #10]) do + RcvdLine := Copy(RcvdLine, 1, Length(RcvdLine) - 1); + ClientThread.Display('Received from ' + GetPeerAddr + ': ''' + + RcvdLine + ''' ' + + 'ThreadID: $' + IntToHex(GetCurrentThreadID, 8)); + ProcessData(Sender as TThrdSrvClient); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This procedure is called in client thread context. So be aware about GUI } +{ update: you must use synchronize. } +procedure TTcpSrvForm.ProcessData(Client : TThrdSrvClient); +var + I : Integer; + AClient : TThrdSrvClient; +begin + { We could replace all those CompareText with a table lookup } + if CompareText(Client.RcvdLine, 'help') = 0 then + Client.SendStr('Commands are:' + #10#13 + + ' exit' + #10#13 + + ' who' + #10#13 + + ' sleep' + #10#13 + + ' time' + #10#13 + + ' exception' + #10#13) + else if CompareText(Client.RcvdLine, 'exit') = 0 then + { We can't call Client.Close here because we will immediately } + { reenter DataAvailable event handler with same line because } + { a line is removed from buffer AFTER it has been processed. } + { Using CloseDelayed will delay Close until we are out of } + { current event handler. } + Client.CloseDelayed + else if CompareText(Client.RcvdLine, 'time') = 0 then + { Send server date and time to client } + Client.SendStr(DateTimeToStr(Now) + #13#10) + else if CompareText(Client.RcvdLine, 'who') = 0 then begin + { Send client list to client } + Client.SendStr('There are ' + IntToStr(WSocketServer1.ClientCount) + + ' connected users:' + #13#10); + for I := WSocketServer1.ClientCount - 1 downto 0 do begin + AClient := TThrdSrvClient(WSocketServer1.Client[I]); + Client.SendStr(AClient.PeerAddr + ':' + AClient.GetPeerPort + ' ' + + DateTimeToStr(AClient.ConnectTime) + #13#10); + end; + end + else if CompareText(Client.RcvdLine, 'Sleep') = 0 then begin + Client.SendStr('Now sleeping for 15"...' + #13#10); + Sleep(15000); + Client.SendStr('Wakeup !' + #13#10); + end + else if CompareText(Client.RcvdLine, 'exception') = 0 then + { This will trigger a background exception for client } + PostMessage(Client.Handle, WM_TRIGGER_EXCEPTION, 0, 0) + else + if Client.State = wsConnected then + Client.SendStr('Unknown command: ''' + Client.RcvdLine + '''' + #13#10); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when listening (server) socket experienced } +{ a background exception. Should normally never occurs. } +{ This procedure is called in main thread context. } +procedure TTcpSrvForm.WSocketServer1BgException( + Sender : TObject; + E : Exception; + var CanClose : Boolean); +begin + Display('Server exception occured: ' + E.ClassName + ': ' + E.Message); + CanClose := FALSE; { Hoping that server will still work ! } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is called when a client socket experience a background } +{ exception. It is likely to occurs when client aborted connection and data } +{ has not been sent yet. } +{ Warning: This procedure is executed in worker thread context. } +procedure TTcpSrvForm.ClientBgException( + Sender : TObject; + E : Exception; + var CanClose : Boolean); +begin + with Sender as TThrdSrvClient do begin + ClientThread.Display('Client exception occured: ' + + E.ClassName + ': ' + E.Message); + end; + CanClose := TRUE; { Goodbye client ! } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* *} +{* TClientThread *} +{* *} +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This is our client worker thread main procedure. It is thread's code. } +{ We have to attach client socket to this thread's context and then } +{ process messages so that TWSocket events works. } +procedure TClientThread.Execute; +begin + if not Assigned(WSocket) then + Exit; + + { Attach client socket to this thread } + WSocket.ThreadAttach; + { Signal main thread that we've attached socket to this thread } + ThreadAttached := TRUE; + { Now let main thread continue starting the connection. } + { This little avoid race condition. } + Sleep(0); + { Then process messages until WM_QUIT message is posted. } + { TWSocket is event-driven. So even when used within a thread, we } + { have to have a "message pump". Any message pump will do and there } + { is one built in TWSocket, so use it ! } + WSocket.MessageLoop; + { Be sure to have main thread waiting for termination before terminating} + Sleep(0); + { Detach the hidden window from within the thread } + WSocket.ThreadDetach; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This procedure is called from client thread and must display a message } +{ on the GUI (main application form). As we are in a thread, we can't } +{ simply call something that act on the GUI, we MUST use synchronize to ask } +{ main thread to update the GUI. } +procedure TClientThread.Display(const Msg: String); +begin + { Synchronized procedure have no parameter, we must use a variable } + FMsg := Msg; + { Then synchronize the procedure (which will use FMsg) } + Synchronize(DisplayMsg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Never call this procedure directly, always call Synchronize(DisplayMsg) } +procedure TClientThread.DisplayMsg; +begin + if Assigned(FOnDisplay) then + FOnDisplay(FMsg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/tnclient.dpr b/ICS_zlog/Delphi/Internet/tnclient.dpr new file mode 100644 index 00000000..301be2d9 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/tnclient.dpr @@ -0,0 +1,12 @@ +program TnClient; + +uses + Forms, + TnCli1 in 'TnCli1.pas' {TelnetForm}; + +{$R *.RES} + +begin + Application.CreateForm(TTelnetForm, TelnetForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/tnclient.ico b/ICS_zlog/Delphi/Internet/tnclient.ico new file mode 100644 index 0000000000000000000000000000000000000000..00e85d677991dddd5a58b7c1219533920cadd15e GIT binary patch literal 766 zcmb_au};G<5PhLYsU@T^u@W}MN?kf2;FGdBOn6H+vifVt#*&Zd$jDZh%)7JW2B{Jf z;*xjg=jS_}F98ZZb$to3_cP#%@s_BGN20(vJ>aOFHb;?)b1~3!iE$hmMF{#L1X&S$ zWJ}yh>ytG}Jy>g7pz9Z$Tef$lgoc&W+Q@Ag&#gZbZ`NASy(DfcIeuU{&9}C?n5OCN ze|Xn*Kk6x$hRRr9xwd=cPOc$WWIv))i8gchCvJvizK75CS$|#7OM%9KHeWHqeOx literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/tndemo.dpr b/ICS_zlog/Delphi/Internet/tndemo.dpr new file mode 100644 index 00000000..b136dca2 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/tndemo.dpr @@ -0,0 +1,12 @@ +program tndemo; + +uses + Forms, + TnDemo1 in 'TnDemo1.pas' {TnDemoForm}; + +{$R *.RES} + +begin + Application.CreateForm(TTnDemoForm, TnDemoForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/tndemo1.dfm b/ICS_zlog/Delphi/Internet/tndemo1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..cd7dfa719215143244902db52c129c07db9009b4 GIT binary patch literal 1582 zcmaJ>%W~5&6jki_k))xWb_&CSAq(ihg0uxz%&0MbrEN zd<9E>gAIQKYmgO;0@BGsKzjmCz$s6?T12~o4M+rQ1I|P{n36OD;jQ=jgU;I_{umr|PQpH}>r;hU zi|G4=#e9z8QZ&?ou5bORskdWt4sP=(Y=wkntq{`WRO3UjpwK{fMl=pmAOc2d3~8-7 zPA-9FV@MBKG_^j}b7Di;L=HZZPBeN+Hlt*buaym!a>06SO!!`y@C!K|nw&AuCp4f5 zFyZwXnNW!R<}hK9wL_66>@2Ie%cQ6tMk%MXD-H16EbDSH^)Z>K7A;g8u{W^j@j3H0 zms&A`Le^~*#u0U$i0vtl+pvxvIl4VFHKx+p)6KbW2 z{5%j=LlaqdO&qLdk%npx$eYmcLw3qbxIM0{;JY{RYf@9h8G}ebT=I;0y4=QWg=Xs} zO*ID;a96cpywDOJ8434p!S;wCNT#75C&JJ5WrPyS%3>m=270`49^4?60d*pWb4gt<7@ + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Oct 23, 2002 V1.01 Changed Buffer arg in OnDataAvailable to untyped var instead + of PChar. More portable. + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit TnDemo1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, TnCnx, WSocket, ExtCtrls; + +type + TTnDemoForm = class(TForm) + DisplayMemo: TMemo; + Panel1: TPanel; + TnCnx: TTnCnx; + HostLabel: TLabel; + HostEdit: TEdit; + ConnectButton: TButton; + InfoLabel: TLabel; + DisconnectButton: TButton; + PortLabel: TLabel; + PortEdit: TEdit; + Label1: TLabel; + DataEdit: TEdit; + SendButton: TButton; + procedure ConnectButtonClick(Sender: TObject); + procedure TnCnxDataAvailable(Sender: TTnCnx; Buffer : Pointer; + Len: Integer); + procedure TnCnxSessionConnected(Sender: TTnCnx; Error: Word); + procedure DisplayMemoKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); + procedure DisplayMemoKeyPress(Sender: TObject; var Key: Char); + procedure TnCnxSessionClosed(Sender: TTnCnx; Error: Word); + procedure DisconnectButtonClick(Sender: TObject); + procedure SendButtonClick(Sender: TObject); + end; + +var + TnDemoForm: TTnDemoForm; + +implementation + +{$R *.DFM} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* Display a message in the memo field, breaking with CR *} +procedure MemoAddLines(Memo : TMemo; Msg : String); +const + CR = #13; + LF = #10; +var + Start, Stop : Integer; +begin + if Memo.Lines.Count = 0 then + Memo.Lines.Add(''); + + Start := 1; + Stop := Pos(CR, Msg); + if Stop = 0 then + Stop := Length(Msg) + 1; + while Start <= Length(Msg) do begin + Memo.Lines.Strings[Memo.Lines.Count - 1] := + Memo.Lines.Strings[Memo.Lines.Count - 1] + + Copy(Msg, Start, Stop - Start); + if Msg[Stop] = CR then begin + Memo.Lines.Add(''); + SendMessage(Memo.Handle, WM_KEYDOWN, VK_UP, 1); + end; + Start := Stop + 1; + if Start > Length(Msg) then + Break; + if Msg[Start] = LF then + Start := Start + 1; + Stop := Start; + while (Msg[Stop] <> CR) and (Stop <= Length(Msg)) do + Stop := Stop + 1; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTnDemoForm.ConnectButtonClick(Sender: TObject); +begin + TnCnx.Host := HostEdit.Text; + TnCnx.Port := PortEdit.Text; + TnCnx.TermType := 'VT100'; + TnCnx.LocalEcho := FALSE; + TnCnx.Connect; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTnDemoForm.DisconnectButtonClick(Sender: TObject); +begin + TnCnx.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTnDemoForm.TnCnxSessionConnected(Sender: TTnCnx; Error: Word); +begin + if Error <> 0 then begin + DisplayMemo.Lines.Add('Unable to connect. Error #' + IntToStr(Error)); + Exit; + end; + + DisplayMemo.Clear; + InfoLabel.Caption := 'Connected'; + DisplayMemo.Enabled := TRUE; + ConnectButton.Enabled := FALSE; + DisconnectButton.Enabled := TRUE; + ActiveControl := DisplayMemo; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTnDemoForm.TnCnxSessionClosed(Sender: TTnCnx; Error: Word); +begin + InfoLabel.Caption := 'Disconnected'; + DisplayMemo.Enabled := FALSE; + ConnectButton.Enabled := TRUE; + DisconnectButton.Enabled := FALSE; + ActiveControl := ConnectButton; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTnDemoForm.TnCnxDataAvailable( + Sender: TTnCnx; Buffer : Pointer; Len: Integer); +begin + MemoAddLines(DisplayMemo, StrPas(Buffer)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTnDemoForm.DisplayMemoKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); +begin + Key := 0; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTnDemoForm.DisplayMemoKeyPress(Sender: TObject; var Key: Char); +begin + TnCnx.Send(@Key, 1); + if Key = #13 then begin + { Send a LF after CR key } + Key := #10; + TnCnx.Send(@Key, 1); + end; + Key := #0; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTnDemoForm.SendButtonClick(Sender: TObject); +begin + if TnCnx.State = wsConnected then + TnCnx.SendStr(DataEdit.Text + #13#10) + else + DisplayMemo.Lines.Add('*** NOT CONNECTED ***'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/tnsrv.dpr b/ICS_zlog/Delphi/Internet/tnsrv.dpr new file mode 100644 index 00000000..21811a59 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/tnsrv.dpr @@ -0,0 +1,13 @@ +program Tnsrv; + +uses + Forms, + TnSrv1 in 'TnSrv1.pas' {ServerForm}, + TnSrv2 in 'TnSrv2.pas' {ClientForm}; + +{$R *.RES} + +begin + Application.CreateForm(TServerForm, ServerForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/tnsrv.ico b/ICS_zlog/Delphi/Internet/tnsrv.ico new file mode 100644 index 0000000000000000000000000000000000000000..d6951f9adea9cc30d727bcec30fa239948755e6a GIT binary patch literal 766 zcmcgqyKciU3_J$`I@mBWb@tfL$fxO(w9^Ck=p#IK(l5Aol9eb$3S=rJk~%(4^aB{U zmgNG;_X+r<|DrC`D|Nt`mcra?2>>@jsE(FLxI4WPd)e4`ov2(2$xNvee}*Y}N#88p zxVZf&UJG8=)=SKDk6C`l>bJFWsDq{IFB~0aRV6&~VpN*VrT>mg@K57FN_;T-Nkwik zrO~F*tj93nobzTe=h2w9nXqAtBk`kO1bzQ+9Cb&>7s=W4%>_3;%~s~)lomDdA-JanR`hAWe!xmnwj2kA0psp?_ubuhcltj;WieTNm@KCG;sTwee+CGZ^Xb{BEI@8R zPK9ify*Qk~jUIePgHo&psTW+)S~r95{qPOYWupf_dN?C1O$84hLkZX#*}k*pX7X8X}U4K*pw#Q zofhT1gTMw_ww-K@3sCeg=!~6wJg0ZS)EwknUN!z7iLG~AX^O&fMy`Ryb0M{p9FKnL zX#5v-H2N>MEc$6r;?PDQ6qFaxilO_n6Y$*t{B7XiSS%ks-cbpWJ6pWplIp9#KbD^84B-f5GA0dRx^R?E3C-2r&cVf2ze|xU< zPrK6J?Mi`|RzpKmn27VCqA&7*|B^$Gh#;VT!l z&*b-+(g%3kR6#kZO<9&-D|7?-<*=)tc1fP^K?g%S*)Y_=IGEAwC`!#X^Ceik2SoXI zhlpP*y9?ZB81`j9eT=!SJu0sXQGEm*7jn}{k)8B~s3D52G^4HQ2_X+*t4??w`p1cL znpBO5I>{0+9M`oB@!6^SxqaI;7tE#5A{^*y70*OP*nw+jvi*kM+3|(BCR#S;-fF0$ z*r^#&I(pKJZ&zhG^SyWhYXuf6N;A=}1P88j_svivbdvJ|lrm?UF`=Nw&-xY*?BDc$ z;|-yVTr + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Sep 18, 1996 Added resize event and about box +Mar 19, 1997 V1.10 Use enhanced TWSocket object +Jul 22, 1997 V1.20 Adapted to Delphi 3 +Sep 27, 1997 Adapted for TWSocket converted to support C++Builder +Oct 03, 1997 V1.22 Added a $DEFINE POP3 to simulate a POP3 server + Added an editbox to select the server port +Oct 09, 1997 Added a $DEFINE SMTP to simulate a SMTP server +Oct 11, 1997 V1.23 Added PortNum to client to tell him what he has to serve +Jul 30, 1998 V1.24 Added some code to the dummy SMTP server +Aug 20, 1999 V1.25 Added some comments, added Restartserver procedure. +Sep 26, 2000 V1.26 Replaced TEdit by TMemo for data to be sent to allow + multi-line sending (see TnSrv2 source). + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit TnSrv1; + +{$J+} + +interface + +uses + SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, + Forms, Dialogs, WSocket, WinSock, StdCtrls, TnSrv2; + +const + TnSrvVersion = 126; + +type + { TClient class is used to handle client connections. A TClient is } + { instanciated for each client which connect. } + { TnSrv keep track of all connected clients using Clients variable in } + { TServerForm (see below). } + { TClient class will dynamically create a TClientForm from his } + { constructor. Since TClientForm include a TWSocket, a new TWSocket } + { is also created dynamically and automaticcaly when the form is } + { created. } + TClient = class(TObject) + Form : TClientForm; + Peer : String; + constructor Create(AOwner : TComponent); + destructor Destroy; override; + end; + + TServerForm = class(TForm) + Memo: TMemo; + QuitButton: TButton; + AboutButton: TButton; + SrvSocket: TWSocket; + PortLabel: TLabel; + PortEdit: TEdit; + ChangePortButton: TButton; + procedure FormCreate(Sender: TObject); + procedure Display(Msg : String); + procedure QuitButtonClick(Sender: TObject); + procedure FormActivate(Sender: TObject); + procedure AboutButtonClick(Sender: TObject); + procedure FormResize(Sender: TObject); + procedure SrvSocketSessionAvailable(Sender: TObject; Error: Word); + procedure SrvSocketSessionClosed(Sender: TObject; Error: Word); + procedure ChangePortButtonClick(Sender: TObject); + protected + procedure WMDisconnect(var msg: TMessage); message WM_DISCONNECT; + procedure RestartServer; + public + Clients : TList; { List of all TClient object (one per connection) } + end; + +var + ServerForm: TServerForm; + +implementation + +{$R *.DFM} +{DEFINE Debug} { Add or remove dollar sign before Debug to } + { generate code for debug message output } + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure DebugString(Msg : String); +const + Cnt : Integer = 0; +{$IFDEF Debug} +var + Buf : String[20]; +{$ENDIF} +begin +{$IFDEF Debug} + Cnt := Cnt + 1; + Buf := IntToHex(Cnt, 4) + ' ' + #0; + OutputDebugString(@Buf[1]); +{$IFDEF WIN32} + OutputDebugString(PChar(Msg)); +{$ELSE} + if Length(Msg) < High(Msg) then + Msg[Length(Msg) + 1] := #0; + + OutputDebugString(@Msg[1]); +{$ENDIF} +{$ENDIF} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TClient.Create(AOwner : TComponent); +begin + Application.CreateForm(TClientForm, Form); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor TClient.Destroy; +begin + Form.Release; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerForm.FormCreate(Sender: TObject); +begin + Memo.Clear; + Clients := TList.Create; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerForm.FormActivate(Sender: TObject); +const + FirstTime : Boolean = TRUE; +begin + if FirstTime then begin + FirstTime := FALSE; + RestartServer; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerForm.RestartServer; +begin + with SrvSocket do begin + Close; + Addr := '0.0.0.0'; { Use any interface for listening } + Proto := 'tcp'; + Port := PortEdit.Text; + Listen; + end; + Memo.Clear; + Display(PortEdit.Text + ' Server Ready' + #13 + #10); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerForm.Display(Msg : String); +var + Start, Stop : Integer; +begin + if Memo.Lines.Count = 0 then + Memo.Lines.Add(''); + + Start := 1; + Stop := Pos(#13, Msg); + if Stop = 0 then + Stop := Length(Msg) + 1; + while Start <= Length(Msg) do begin + Memo.Lines.Strings[Memo.Lines.Count - 1] := Memo.Lines.Strings[Memo.Lines.Count - 1] + Copy(Msg, Start, Stop - Start); + if Msg[Stop] = #13 then begin + Memo.Lines.Add(''); + SendMessage(Memo.Handle, WM_KEYDOWN, VK_UP, 1); + end; + Start := Stop + 1; + if Start > Length(Msg) then + Break; + if Msg[Start] = #10 then + Start := Start + 1; + Stop := Start; + while (Stop <= Length(Msg)) and (Msg[Stop] <> #13) do + Stop := Stop + 1; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerForm.SrvSocketSessionAvailable(Sender: TObject; Error : word); +var + NewHSocket : TSocket; + PeerName : TSockAddrIn; + Client : TClient; +begin + NewHSocket := SrvSocket.Accept; + Client := TClient.Create(Self); + Client.Form.Reference := Client; + Client.Form.PortNum := SrvSocket.PortNum; + Client.Form.AcceptForm := Self; + Client.Form.Socket.Dup(NewHSocket); + Client.Form.Socket.GetPeerName(PeerName, Sizeof(PeerName)); + Client.Peer := StrPas(inet_ntoa(PeerName.Sin_addr)); + Display('Remote ' + Client.Peer + ' connected' + #13 + #10); + Client.Form.Caption := Client.Peer; + Client.Form.Show; + Clients.Add(Client); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerForm.WMDisconnect(var msg: TMessage); +var + Client : TClient; + Why : String; +begin + case msg.wParam of + DISCONNECT_SELF : Why := 'has been disconnected'; + DISCONNECT_REMOTE : Why := 'has closed the connection'; + else Why := 'disconnected'; + end; + + Client := TCLient(msg.lParam); + Display('Remote ' + Client.Peer + ' ' + Why + #13 + #10); + Client.Form.Socket.Shutdown(2); + Client.Form.Socket.Close; + Client.Form.Visible := FALSE; + Client.Form.Release; + Clients.Remove(Client); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerForm.SrvSocketSessionClosed(Sender: TObject; Error : word); +begin + Display(#13 + #10 + '*** Remote has closed ***' + #13 + #10); + if SrvSocket.State = wsOpened then + SrvSocket.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerForm.QuitButtonClick(Sender: TObject); +begin + SrvSocket.Close; + Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerForm.AboutButtonClick(Sender: TObject); +var + Buf : String; +begin + Buf := 'TnSRV V' + + IntToStr(TnSrvVersion div 100) + '.' + + IntToStr(TnSrvVersion mod 100) + ' ' + +{$IFDEF WIN32} + '32 bit' + +{$ELSE} + '16 bit' + +{$ENDIF} + ' Created march 19, 1997' + #10 + #10 + + 'Free Software, Copyright François Piette' + #10 + #10 + + 'francois.piette@pophost.eunet.be http://www.rtfm.be/fpiette' + #0; + Application.MessageBox(@Buf[1], 'About TnSrv', MB_OK); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Adjust the position for each control in the form as the user resize it *} +procedure TServerForm.FormResize(Sender: TObject); +begin + Memo.Height := ClientHeight - QuitButton.Height - 20; + QuitButton.Left := ClientWidth - QuitButton.Width - 10; + AboutButton.Left := QuitButton.Left - AboutButton.Width - 10; + QuitButton.Top := ClientHeight - QuitButton.Height - 10; + AboutButton.Top := QuitButton.Top; + ChangePortButton.Top := QuitButton.Top; + PortEdit.Top := QuitButton.Top; + PortLabel.Top := QuitButton.Top + 4; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TServerForm.ChangePortButtonClick(Sender: TObject); +begin + RestartServer; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/tnsrv2.dfm b/ICS_zlog/Delphi/Internet/tnsrv2.dfm new file mode 100644 index 0000000000000000000000000000000000000000..5bd553a87053f5efe8aa4bdf97d9a0f8239ff216 GIT binary patch literal 1399 zcmZux&2G~`5MJAj*LG4G331@a1#zl^1UD|Jlc*JG9mR$U2?@6LG+wdZjdnNv;f)YS zcm!UD6Au7uuM@X`EZH-&GxN=UGvnV8%HsLS^emet%TqKOUi1*k7PC=5ix~y3XF^s{ zC+^MRQhN)>%f#CIiF)U>(53gy@sEM7O6@&ya7@;k3hv*D>cxTyiNl;7X+9%43}%As z!?+|;fyM`u>1_OFo_&aq$IEn@MfS9b8RYDo@&ozOEhcbDHcT5+!r5(*aO;Up23c7-O!x$pmf{v0 zTv@e>@m+$VpTYWC*-v;{ifbIyjI9 z^XYEs{JNv_JL-)YU2z-`W}C1-rySH_swL$s<@ik!6fA)h^-aPk&81-M$S{k2rH+Iy zgN$4>6u1Z>KU)wE%x~V$n|4}s&tTbZ?%>^Jhi(#SQFW;tgtMcKv2koaZLXlX$qSpx zecjH5`*=4NTlX#%!iIiE^G|rtrfM{_Lx@t~g*~zbzrP3a?q87J(>esVT@E`eXNPsr zCH)I-IH4*RoI|effOn&zbltW;1P^cGTR;d?q?hjU?Y#zi50JUVP1Yg!1YeP^_PY8H=X zrCH4aieMOvYAv|=)g;Y-L-o;t**wF=_=-?QE*Rj4wz_*pbGR}K h + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +Updates: +Sep 18, 1996 Accept CR/LF or LF only as line terminator + Implement Help and Exit commands as demo +Mar 19, 1997 Use enhanced TWSocket object +Oct 03, 1997 V1.22 Added a $DEFINE POP3 to simulate a POP3 server +Oct 09, 1997 Added a $DEFINE SMTP to simulate a SMTP server +Oct 11, 1997 Added PortNum to specify which port we serve + Added pseudo POP3 and SMTP interpreters (nothing really happens + except transmission of pseudo correct answers. I use this + feature to debug SMTP and POP3 components). +Jul 30, 1998 V1.24 Added some code to the dummy SMTP server +Sep 26, 2000 V1.26 Replaced TEdit by TMemo for data to be sent to allow + multi-line sending. + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit TnSrv2; + + +interface + +uses + SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, + Forms, Dialogs, StdCtrls, WSocket, Winsock, ExtCtrls; + +const + SMTP_PORT = 25; + POP3_PORT = 110; + + { The message WM_DISCONNECT is used by the client form to tell the server } + { form that the client has disconnected or should be disconnected. } + WM_DISCONNECT = WM_USER + 2; + DISCONNECT_SELF = 1; { Client form ask to disconnect } + DISCONNECT_REMOTE = 2; { Client user (remote) has disconnected } + +type + { A new TClientForm will be instanciated for each new client connection. } + { Instanciation is done from TClient constructor. } + TClientForm = class(TForm) + Memo: TMemo; + Socket: TWSocket; + Panel1: TPanel; + Button1: TButton; + SendButton: TButton; + DisconnectButton: TButton; + DataMemo: TMemo; + procedure FormCreate(Sender: TObject); + procedure Display(Msg : String); + procedure FormDestroy(Sender: TObject); + procedure DisconnectButtonClick(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure SendButtonClick(Sender: TObject); + procedure FormResize(Sender: TObject); + procedure SocketDataAvailable(Sender: TObject; Error: Word); + procedure SocketSessionClosed(Sender: TObject; Error: Word); + procedure Button1Click(Sender: TObject); + private + FCommand : String; + FRcvdCR : Boolean; + FDataFlag : Boolean; + procedure ProcessChar(Ch : Char); + procedure CommandInterpreter; + procedure SMTP_Interpreter(CommandVerb : String; CommandTail : String); + procedure POP3_Interpreter(CommandVerb : String; CommandTail : String); + procedure TELNET_Interpreter(CommandVerb : String; CommandTail : String); + public + AcceptForm : TForm; + Reference : Pointer; + PortNum : Integer; + end; + +var + ClientForm: TClientForm; + +implementation + +{$R *.DFM} + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFNDEF WIN32} +procedure SetLength(var Str : String; Len : Integer); +begin + Str[0] := chr(Len); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TrimRight(Str : String) : String; +var + i : Integer; +begin + i := Length(Str); + while (i > 0) and (Str[i] = ' ') do + i := i - 1; + Result := Copy(Str, 1, i); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TrimLeft(Str : String) : String; +var + i : Integer; +begin + if Str[1] <> ' ' then + Result := Str + else begin + i := 1; + while (i <= Length(Str)) and (Str[i] = ' ') do + i := i + 1; + Result := Copy(Str, i, Length(Str) - i + 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function Trim(Str : String) : String; +begin + Result := TrimLeft(TrimRight(Str)); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function atoi(value : string) : Integer; +var + i : Integer; +begin + Result := 0; + i := 1; + while (i <= Length(Value)) and (Value[i] = ' ') do + i := i + 1; + while (i <= Length(Value)) and (Value[i] >= '0') and (Value[i] <= '9')do begin + Result := Result * 10 + ord(Value[i]) - ord('0'); + i := i + 1; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.FormCreate(Sender: TObject); +begin + Memo.Clear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This procedure display text in a memo control. } +{ I should add code to remove lines when there are too much of them... } +procedure TClientForm.Display(Msg : String); +var + Start, Stop : Integer; + SelStart : Integer; +begin + if Memo.Lines.Count = 0 then + Memo.Lines.Add('') + else if Memo.Lines.Count > 200 then + Memo.Clear; + + Start := 1; + Stop := Pos(#13, Msg); + if Stop = 0 then + Stop := Length(Msg) + 1; + while Start <= Length(Msg) do begin + Memo.Lines.Strings[Memo.Lines.Count - 1] := Memo.Lines.Strings[Memo.Lines.Count - 1] + Copy(Msg, Start, Stop - Start); + if (Stop <= Length(Msg)) and (Msg[Stop] = #13) then begin + SelStart := Memo.SelStart; + Memo.Lines.Add(''); + Memo.SelStart := SelStart + 2; + end; + Start := Stop + 1; + if Start > Length(Msg) then + Break; + if Msg[Start] = #10 then + Start := Start + 1; + Stop := Start; + while (Stop <= Length(Msg)) and (Msg[Stop] <> #13) do + Stop := Stop + 1; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Not a real SMTP command interpreter, just enough for me to test my SMTP } +{ component. } +procedure TClientForm.SMTP_Interpreter( + CommandVerb : String; + CommandTail : String); +var + Response : String; +begin + if FDataFlag then begin + { We should add storage here of course... } + { SMTP data ends with a line having being a single dot } + if FCommand = '.' then begin + Response := '250 Data received ok'; + Socket.SendStr(Response + #13 + #10); + FDataFlag := FALSE; + end; + end + else begin + FDataFlag := FALSE; + if CommandVerb = 'MAIL' then + Response := '250 Ok' + else if CommandVerb = 'RCPT' then + Response := '250 Ok' + else if CommandVerb = 'DATA' then begin + Response := '354 Send data now'; + FDataFlag := TRUE; + end + else if CommandVerb = 'HELO' then + Response := '250 Ok' + else if CommandVerb = 'QUIT' then + Response := '221 Goodbye' + else + Response := '500 syntax error'; + + Socket.SendStr(Response + #13 + #10); + if CommandVerb = 'QUIT' then + Socket.Close; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Not a real POP3 command interpreter, just enough for me to test my POP3 } +{ component. } +procedure TClientForm.POP3_Interpreter( + CommandVerb : String; + CommandTail : String); +var + Response : String; +begin + if CommandVerb = 'USER' then + Response := '+OK' + else if CommandVerb = 'PASS' then + Response := '+OK' + else if CommandVerb = 'RETR' then begin + Socket.SendStr('+OK' + #13 + #10); + Socket.SendStr('This is the message body.' + #13 + #10); + Socket.SendStr('This is the last message line.' + #13 + #10); + Response := '.' + end + else if CommandVerb = 'LIST' then begin + if Trim(CommandTail) = '' then begin + Socket.SendStr('+OK 2 messages (320 octets)' + #13 + #10); + Socket.SendStr('1 120' + #13 + #10); + Socket.SendStr('2 200' + #13 + #10); + Response := '.' + end + else + Response := '+OK ' + CommandTail + ' 200' + end + else if CommandVerb = 'STAT' then + Response := '+OK 10 12345' + else if CommandVerb = 'QUIT' then + Response := '+OK' + else if CommandVerb = 'TOP' then begin + if atoi(CommandTail) <= 0 then + Response := '-ERR Message doesn''t exists' + else begin + Socket.SendStr('+OK' + #13 + #10); + Socket.SendStr('This is the message body.' + #13 + #10); + Socket.SendStr('This is the last message line.' + #13 + #10); + Response := '.' + end; + end + else if CommandVerb = 'RPOP' then + Response := '+OK' + else if CommandVerb = 'APOP' then + Response := '+OK' + else if CommandVerb = 'DELE' then + Response := '+OK' + else if CommandVerb = 'LAST' then + Response := '+OK 1' + else if CommandVerb = 'NOOP' then + Response := '+OK' + else if CommandVerb = 'UIDL' then + Response := '+OK ' + Trim(CommandTail) + ' Msg' + Trim(CommandTail) + else if CommandVerb = 'RSET' then + Response := '+OK' + else + Response := '-ERR'; + + Socket.SendStr(Response + #13 + #10); + if CommandVerb = 'QUIT' then + Socket.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Not a real TELNET command interpreter, just enough to see how it could } +{ be implemented. } +procedure TClientForm.TELNET_Interpreter( + CommandVerb : String; + CommandTail : String); +begin + Socket.SendStr(#13 + #10 + 'Executing command ''' + CommandVerb + '''...' + + #13 + #10); + + if CommandVerb = 'EXIT' then + DisconnectButtonClick(Self) + else if CommandVerb = 'HELP' then + Socket.SendStr('List of commands:' + #13 + #10 + + ' Exit logoff from server' + #13 + #10 + + ' Help show this help screen' + #13 + #10) + else + Socket.SendStr('Unknown command, ignoring'); + + Socket.SendStr(#13 + #10 + '--> '); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This is the command line interpreter. Should extend the code to support } +{ every command needed... } +procedure TClientForm.CommandInterpreter; +var + CommandVerb : String; + CommandTail : String; + I, J : Integer; +begin + CommandVerb := FCommand; + + { Skip leading spaces } + I := 1; + while (I <= Length(CommandVerb)) and (CommandVerb[I] in [' ', #9]) do + Inc(I); + + { Find separator and separe CommandVerb and CommandTail } + J := I; + while TRUE do begin + if (J >= Length(CommandVerb)) then begin + CommandTail := ''; + break; + end; + + if CommandVerb[J] in [' ', #9, '/'] then begin + CommandTail := Copy(CommandVerb, J, Length(CommandVerb) - J + 1); + CommandVerb := Copy(CommandVerb, I, J - I); + break; + end; + Inc(J); + end; + CommandVerb := UpperCase(CommandVerb); + + if PortNum = SMTP_PORT then + SMTP_Interpreter(CommandVerb, CommandTail) + else if PortNum = POP3_PORT then + POP3_Interpreter(CommandVerb, CommandTail) + else + TELNET_Interpreter(CommandVerb, CommandTail); + + FCommand := ''; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* Process each charcter received to do minimal line editing } +procedure TClientForm.ProcessChar(Ch : Char); +begin + if Ch = #8 then begin + if Length(FCommand) > 0 then begin + SetLength(FCommand, Length(FCommand) - 1); + Socket.SendStr(#8 + ' ' + #8); + end + else + Socket.SendStr(#7); + Exit; + end + else if (Ch = #10) and FRcvdCR then begin + { Ignore LF just after CR (CR/LF is normal end of line) } + FRcvdCR := FALSE; + Exit; + end + else if Ch = #13 then begin + FRcvdCR := TRUE; + CommandInterpreter; + Exit; + end + else if Ch = #10 then begin + CommandInterpreter; + Exit; + end; + + { Ordinary character, put in buffer in some place left } +{$IFNDEF WIN32} + if Length(FCommand) = High(FCommand) then + Ch := #7 + else +{$ENDIF} + FCommand := FCommand + Ch; + + if (PortNum <> POP3_PORT) and (PortNum <> SMTP_PORT) then begin + { Echo to client } + Socket.Send(@Ch, 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* Event handler for datavailable. Called each time some data is received *} +procedure TClientForm.SocketDataAvailable(Sender: TObject; Error : word); +var + Len : Integer; + Buffer : String[255]; + Socket : TWSocket; + I : Integer; +begin + Socket := Sender as TWSocket; + Len := Socket.Receive(@Buffer[1], High(Buffer)); + if Len = 0 then begin + { Remote has closed } + Display(#13 + #10 + '**** Remote has closed ****' + #13 + #10); + end + else if Len < 0 then begin + { An error has occured } + if Socket.LastError <> WSAEWOULDBLOCK then + Display(#13 + #10 + '**** ERROR: ' + IntToStr(Socket.LastError) + + ' ****' + #13 + #10); + end + else begin + Buffer[0] := chr(Len); + Display(Buffer); + for I := 1 to Len do + ProcessChar(Buffer[I]); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* Event handler called when the remote has closed the connection *} +procedure TClientForm.SocketSessionClosed(Sender: TObject; Error : word); +begin + Display(#13 + #10 + '**** Remote has closed ****' + #13 + #10); + PostMessage(AcceptForm.Handle, WM_DISCONNECT, + DISCONNECT_REMOTE, + LongInt(Reference)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.FormDestroy(Sender: TObject); +begin + Socket.Shutdown(2); + Socket.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.DisconnectButtonClick(Sender: TObject); +begin + { Post a message to server form asking to disconnect the client } + PostMessage(AcceptForm.Handle, WM_DISCONNECT, + DISCONNECT_SELF, + LongInt(Reference)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.FormShow(Sender: TObject); +var + Buf : String; +begin + DataMemo.Text := ''; + ActiveControl := DataMemo; + + if PortNum = POP3_PORT then + Buf := '+OK POP3 server ready <1896.697170952@dbc.mtview.ca.us>' + #13 + #10 + else if PortNum = SMTP_PORT then begin + Buf := '220-SMTP Simulator ready' + #13 + #10; + Socket.Send(@Buf[1], Length(Buf)); + Buf := '220 ESMTP spoken here' + #13 + #10; + end + else + Buf := 'Hello from TnSrv !' + #13 + #10 + '--> '; + + Socket.Send(@Buf[1], Length(Buf)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.SendButtonClick(Sender: TObject); +var + Buf : String; +begin + Buf := DataMemo.Text + #13 + #10; + Socket.Send(@Buf[1], Length(Buf)); + DataMemo.Text := ''; + ActiveControl := DataMemo; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Adjust the position for each control in the form as the user resize it *} +procedure TClientForm.FormResize(Sender: TObject); +begin +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TClientForm.Button1Click(Sender: TObject); +begin + Socket.SendStr('Hello !'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/twschat.dpr b/ICS_zlog/Delphi/Internet/twschat.dpr new file mode 100644 index 00000000..fb4b6088 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/twschat.dpr @@ -0,0 +1,12 @@ +program twschat; + +uses + Forms, + TWSChat1 in 'TWSChat1.pas' {TWSChatForm}; + +{$R *.RES} + +begin + Application.CreateForm(TTWSChatForm, TWSChatForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/twschat1.dfm b/ICS_zlog/Delphi/Internet/twschat1.dfm new file mode 100644 index 0000000000000000000000000000000000000000..73dd6f9254182fbcf5700a05b304633722909bad GIT binary patch literal 2603 zcmd5-PjA~c9HpdKk|i7UQWzb2nGZvN9p<Bat&squ>(Np zFK2^tJ%N15^3;`Qs`1eZZMg9VFhZ6YA3^U5$2>89*UYyFZxe3JG;0Afju|z-t*%YJ zpCp`TKb@ZL_xowiH|g{moo+IWI7iNsQ9fNT!g6a6ktMZ_%sUzADfWzKq?@^5v@`ggrK!CPweAQ45eLwN1wG0Jry zP*(6-pp^d=iY+Urk5u9GZ>qZK!$a9jk=HHC0qBM2G3Jh%%ApElRsz@+z+DY6ZV?~J zT+BXU5hMvKH~?1oX2&_B!v&)hMO@8PGe4@tYQ!H8h=-8ulj>T-p;;bX5FFiD#~sLW zt>GJ;;UcMBQ6kZb)+YP;bpdUBqR8mz0gYXi@n5nhn%N?bdZd*$# z_n);+HQ(2PeAUXmy4#Q&2l8k4aUY})ILk5=e~JF3w>7B?sR`sO&4=^_ReA2+z#p#7>lrmQ+CnNAqj#~v1?^&7J;e{KYK=s5$ zfdmGk{QujQyI{K#w9~%;PvW zt=Y8vsU@G~+|*{nweV0JCOLw!c#)$8OEX4Ah+b*>g$s^_vkI*U*PY)&OytY8o;N}M zcW_VA1hMRp2KcJ%b!J)qU1P*x3*V zt7$A$oQ7i+X#fq_;U3Mm#-^T51Jg(mUtv))P-iB%R NsCxS-E0zHO{sob3K#~9e literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Internet/twschat1.pas b/ICS_zlog/Delphi/Internet/twschat1.pas new file mode 100644 index 00000000..e9818d3a --- /dev/null +++ b/ICS_zlog/Delphi/Internet/twschat1.pas @@ -0,0 +1,332 @@ +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: TWSChat shows how to use TWSocket to build a chat program +Creation: November 26, 1997 +Version: 1.03 +EMail: francois.piette@pophost.eunet.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Jan 04, 1998 V1.01 Corrected a bug in the CliWSocketDataAvailable which did'nt + append data to the receive buffer. +Jan 10, 1998 V1.02 Corrected yet another bug in CliWSocketDataAvailable which + did'nt take into account that variable I is zero based. +Mar 15, 1998 V1.03 Yet another bug in OnDataAvailable event. + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit TWSChat1; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, ExtCtrls, WinSock, WSocket; + +const + TWSChatVersion = 103; + ChatPort = '2200'; { Any port would do the job... } + +type + TTWSChatForm = class(TForm) + Panel1: TPanel; + Panel2: TPanel; + DisplayMemo: TMemo; + SrvWSocket: TWSocket; + ServerEdit: TEdit; + Label1: TLabel; + ConnectButton: TButton; + CliWSocket: TWSocket; + DisconnectButton: TButton; + MessageEdit: TEdit; + SendButton: TButton; + TmpWSocket: TWSocket; + RunningRadioButton: TRadioButton; + StoppedRadioButton: TRadioButton; + procedure FormShow(Sender: TObject); + procedure ConnectButtonClick(Sender: TObject); + procedure CliWSocketDnsLookupDone(Sender: TObject; Error: Word); + procedure CliWSocketSessionConnected(Sender: TObject; Error: Word); + procedure DisconnectButtonClick(Sender: TObject); + procedure SrvWSocketSessionAvailable(Sender: TObject; Error: Word); + procedure CliWSocketSessionClosed(Sender: TObject; Error: Word); + procedure CliWSocketDataAvailable(Sender: TObject; Error: Word); + procedure SendButtonClick(Sender: TObject); + procedure StoppedRadioButtonClick(Sender: TObject); + procedure RunningRadioButtonClick(Sender: TObject); + private + { Déclarations privées } + Initialized : Boolean; + RcvBuf : array [0..1023] of char; + RcvLen : integer; + procedure StartServer; + public + { Déclarations publiques } + end; + +var + TWSChatForm: TTWSChatForm; + +implementation + +{$R *.DFM} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTWSChatForm.StartServer; +begin + { Try to be a server } + SrvWSocket.Port := ChatPort; + SrvWSocket.Proto := 'tcp'; + SrvWSocket.Addr := '0.0.0.0'; + try + SrvWSocket.Listen; + RunningRadioButton.Checked := TRUE; + StoppedRadioButton.Checked := FALSE; + except + on E:ESocketException do begin + { The socket is probably already in use } + RunningRadioButton.Checked := FALSE; + StoppedRadioButton.Checked := TRUE; + if Copy(E.Message, 1, 11) = 'Error 10048' then + DisplayMemo.Lines.Add('TWSChat already running as server') + else + raise; + end + else + raise; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTWSChatForm.FormShow(Sender: TObject); +begin + if not Initialized then begin + Initialized := TRUE; + StartServer; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ The user has clicked on the 'connect' button. We will not connect here, } +{ but start the DNSLookup. We will receive a event when it is complete. } +{ The connection will be made at that later time. } +procedure TTWSChatForm.ConnectButtonClick(Sender: TObject); +begin + ConnectButton.Enabled := FALSE; + DisconnectButton.Enabled := TRUE; + CliWSocket.DnsLookup(ServerEdit.Text); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is triggered when the DNS lookup process is finished } +{ successfully or not. If DNS lookud failed, display a message. } +{ If DNS lookup successfull, ask TWSocket to connect the server. } +procedure TTWSChatForm.CliWSocketDnsLookupDone(Sender: TObject; Error: Word); +begin + if Error <> 0 then begin + { DNS Lookup has failed } + DisplayMemo.Lines.Add('Server name unknown'); + ConnectButton.Enabled := TRUE; + DisconnectButton.Enabled := FALSE; + Exit; + end; + + { DNS lookup successfull. Try to see if we are the server and we are } + { trying to connect to ourself. Check loopback address, should also } + { check the local IP address (returned by LocalIPList)... } + if (SrvWSocket.State = wsListening) and + (CliWSocket.DnsResult = '127.0.0.1') then begin + DisplayMemo.Lines.Add('Your are trying to connect to yourself !'); + ConnectButton.Enabled := TRUE; + DisconnectButton.Enabled := FALSE; + Exit; + end; + + { Transfert the IP address from DNSLookup to the TWSocket for connection } + { We could use the hostname for the Addr property, TWSocket will do the } + { DNS lookup for us, but it will block, maybe for a long time if DNS if } + { down. } + CliWSocket.Addr := CliWSocket.DnsResult; + CliWSocket.Port := ChatPort; + CliWSocket.Proto := 'tcp'; + + { The connect method is asynchronous. You get the control back quickly } + { The OnSessionConnected event will be eventually generated when the } + { connection is established. } + CliWSocket.Connect; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is triggered when the connection is established with } +{ the server. Enable the send button and the message edit box. } +procedure TTWSChatForm.CliWSocketSessionConnected(Sender: TObject; Error: Word); +begin + if Error = WSAECONNREFUSED then + DisplayMemo.Lines.Add('No server available') + else if Error <> 0 then + DisplayMemo.Lines.Add('Can''t connect, error #' + IntToStr(Error)) + else begin + DisplayMemo.Lines.Add('Connected'); + SendButton.Enabled := TRUE; + MessageEdit.Enabled := TRUE; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event is triggered when the client connection is closed, either } +{ by the client himself or by the local user pushing the disconnect button } +procedure TTWSChatForm.CliWSocketSessionClosed(Sender: TObject; Error: Word); +begin + DisconnectButton.Enabled := FALSE; + ConnectButton.Enabled := TRUE; + if SendButton.Enabled then begin + SendButton.Enabled := FALSE; + MessageEdit.Enabled := FALSE; + DisplayMemo.Lines.Add('Disconnected'); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event is triggered when data has been received from the client. } +{ A little bit of work here because the data can comes fragmented or in big } +{ chunks with several client lines. So we assemble the data received in a } +{ buffer and check the buffer for complete lines (there can be no complete } +{ line, exactly one complete line, several complete lines and may be an } +{ incomplete line at the end. } +procedure TTWSChatForm.CliWSocketDataAvailable(Sender: TObject; Error: Word); +var + Len : Integer; + I : Integer; +begin + { Receive the data that has arrived, put it after the data already here } + Len := CliWSocket.Receive(@RcvBuf[RcvLen], SizeOf(RcvBuf) - RcvLen - 1); + if Len <= 0 then + Exit; + { Update our conter } + RcvLen := RcvLen + Len; + { Place a null byte at the end of the buffer } + RcvBuf[RcvLen] := #0; + + { Scan the buffer to process each complete line } + while TRUE do begin + { find the terminating line feed } + I := StrScan(@RcvBuf, #10) - RcvBuf; + if I < 0 then + break; { not found, incomplete line, break loop } + { Replace the line feed by a nul char, truncating the line } + RcvBuf[I] := #0; + { Display the truncated line } + DisplayMemo.Lines.Add('Remote> ' + StrPas(RcvBuf)); + { Restore the line feed } + RcvBuf[I] := #10; + { Was it the last line in the buffer ? } + if I >= (RcvLen - 1) then begin + RcvLen := 0; + break; + end; + { Not the last line, move the next one in front of buffer } + Move(RcvBuf[I + 1], RcvBuf, RcvLen - I); + RcvLen := RcvLen - I - 1; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event is triggered when we - as a server - have received a client } +{ connection request. We must accept the connection. Two cases: we are } +{ already busy with another client, or this is the first client connecting. } +procedure TTWSChatForm.SrvWSocketSessionAvailable(Sender: TObject; Error: Word); +begin + if CliWSocket.State = wsConnected then begin + { We are already busy with a client. Use the TmpWSocket to send a } + { busy message to the second client. Display a message to notify } + { the user that someone is trying to contact him. } + TmpWSocket.HSocket := SrvWSocket.Accept; + DisplayMemo.Lines.Add('System> ' + TmpWSocket.GetPeerAddr + + ' is trying to call you'); + TmpWSocket.SendStr('Busy ! Try later...' + #13#10); + TmpWSocket.Close; + Exit; + end; + + { This is our first client trying to connect, we accept } + CliWSocket.HSocket := SrvWSocket.Accept; + ConnectButton.Enabled := FALSE; + DisconnectButton.Enabled := TRUE; + SendButton.Enabled := TRUE; + MessageEdit.Enabled := TRUE; + DisplayMemo.Lines.Add('Connected with ' + CliWSocket.GetPeerAddr); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ The user clicked on the disconnect button. } +procedure TTWSChatForm.DisconnectButtonClick(Sender: TObject); +begin + CliWSocket.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ The user has clicked on the send button. Just send the data in the edit } +{ box and a CRLF pair to make a complete line. } +procedure TTWSChatForm.SendButtonClick(Sender: TObject); +begin + CliWSocket.SendStr(MessageEdit.Text + #13#10); + DisplayMemo.Lines.Add(' Local> ' + MessageEdit.Text); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTWSChatForm.StoppedRadioButtonClick(Sender: TObject); +begin + SrvWSocket.Close; + RunningRadioButton.Checked := FALSE; + StoppedRadioButton.Checked := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TTWSChatForm.RunningRadioButtonClick(Sender: TObject); +begin + if SrvWSocket.State <> wsListening then + StartServer; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Internet/udplstn.dpr b/ICS_zlog/Delphi/Internet/udplstn.dpr new file mode 100644 index 00000000..455e3c7c --- /dev/null +++ b/ICS_zlog/Delphi/Internet/udplstn.dpr @@ -0,0 +1,12 @@ +program UdpLstn; + +uses + Forms, + UdpLstn1 in 'UdpLstn1.pas' {MainAutoForm}; + +{$R *.RES} + +begin + Application.CreateForm(TMainForm, MainForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Internet/udpsend.dpr b/ICS_zlog/Delphi/Internet/udpsend.dpr new file mode 100644 index 00000000..547266b2 --- /dev/null +++ b/ICS_zlog/Delphi/Internet/udpsend.dpr @@ -0,0 +1,12 @@ +program UdpSend; + +uses + Forms, + UdpSend1 in 'UdpSend1.pas' {MainAutoForm}; + +{$R *.RES} + +begin + Application.CreateForm(TMainForm, MainForm); + Application.Run; +end. diff --git a/ICS_zlog/Delphi/Vc/DnsQuery.dcr b/ICS_zlog/Delphi/Vc/DnsQuery.dcr new file mode 100644 index 0000000000000000000000000000000000000000..56425e70c90c53918697e9380404aeab938ed37d GIT binary patch literal 411 zcma)#I}QUO3`A$6NVHp~Ou1zak+hNWEA|%dXeo0nZboMC%38VrhUf8Mw*%hS`|I(! zJy%@j?*uFWPFqYkl7KVy{hA{w01ry>hc^+mR=z5%(_aBdK^NQlOlU%AAdqvrbc#|+(H#$U2DJv$R)nO(x2%K<<_%^p1ozaG tltj%zdhpp`QK7umM$wj0E0224eM9`m2`?I^e<(iwZw|7Vup0F%c>oXbYf z`|W<}E@vIvcOxAn?WWsk3zPQfztMh+ULw`^;{!r93)J&%0aGA1oP#%{*S$Zq3_?#KD|oBci%DQcR4%L&By) OCmlY|yZLvlZJQtO2^@X^ literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc/SmtpProt.dcr b/ICS_zlog/Delphi/Vc/SmtpProt.dcr new file mode 100644 index 0000000000000000000000000000000000000000..14fc34ac2e3b9b846a22824be83b83b0f38fcbe3 GIT binary patch literal 824 zcmd6kF%H5o3`KttlGl!mjEvl&6A~aKx^N3`UNds6+{}DC5oKklR41`t>?pFneTVsZ zn;+Blg7f$ufD?d2KLhq8;K=;1jo(WFxKTxrG80|c zl$I5Cz(O+HVeEM^F%{$+vM!u|DxmAP?=hLzecJMLC@ah3~jE8IW*d`{mn?+)ha8x!&K8 zSHd!H6L14?*?q#91YD_)Hpim?yeP#JBN4S$W-GLQ(V7vR$0P>*V=~l@vnW(l#5`vP z6)>xqyO#CKy@wOl + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +Updates: +Sep 21, 1997 Added $IFDEF to warn Delphi 2 or 3 user that something is wrong + if they use this file. +Dec 13, 1997 Changed winsocket form 'WINSOCK.DLL' to 'WINSOCK' because Win 3.x + like thos have it without extension (don't ask me why !) + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit Winsock; + +interface + +{$IFNDEF VER80} + 'This file is for use with Delphi 1 only. Use the Borland provided file' + 'with any other Delphi Version. If you use this file with Delphi 2 or 3' + 'this is probably because your library path is wrong or you have not' + 'restored the directory structure when unzipping the file (you must use' + 'pkunzip option -d to restore the files).' +{$ENDIF} + + +uses WinTypes, WinProcs; + +const + winsocket = 'WINSOCK'; + { If your application can't find winsock.dll on startup, please try to } + { change the preceding line to "winsocket = 'winsock.dll';" } + { Also, try upper or lower case letters. Win 3.x is very capricious ! } + + { Misc constants } + FD_SETSIZE = 64; + + { + Commands for ioctlsocket(), taken from the BSD file fcntl.h. + + Ioctl's have the command encoded in the lower word, + and the size of any in or out parameters in the upper + word. The high 2 bits of the upper word are used + to encode the in/out status of the parameter; for now + we restrict parameters to at most 128 bytes. + 0x20000000 distinguishes new & old ioctl's + } + IOCPARM_MASK = $7f; { parameters must be < 128 bytes } + IOC_VOID = $20000000; { no parameters } + IOC_OUT = $40000000; { copy out parameters } + IOC_IN = $80000000; { copy in parameters } + IOC_INOUT = (IOC_IN + IOC_OUT); + + FIONREAD = $4004667F; { get # bytes to read } + FIONBIO = $8004667E; { set/clear non-blocking i/o } + FIOASYNC = $8004667D; { set/clear async i/o } + + { Socket I/O Controls } + SIOCSHIWAT = $80047300; { set high watermark } + SIOCGHIWAT = $40047301; { set low watermark } + SIOCSLOWAT = $80047302; { set low watermark } + SIOCGLOWAT = $40047303; { get low watermark } + SIOCATMARK = $40047307; { at oob mark? } + + INADDR_ANY = $00000000; + INADDR_LOOPBACK = $7f000001; + INADDR_BROADCAST = $ffffffff; + INADDR_NONE = $ffffffff; + + WSADESCRIPTION_LEN = 256; + WSASYS_STATUS_LEN = 128; + + { Protocols } + IPPROTO_IP = 0; { dummy for IP } + IPPROTO_ICMP = 1; { control message protocol } + IPPROTO_GGP = 2; { gateway^2 (deprecated) } + IPPROTO_TCP = 6; { tcp } + IPPROTO_PUP = 12; { pup } + IPPROTO_UDP = 17; { user datagram protocol } + IPPROTO_IDP = 22; { xns idp } + IPPROTO_ND = 77; { UNOFFICIAL net disk proto } + IPPROTO_RAW = 255; { raw IP packet } + IPPROTO_MAX = 256; + + { Port/socket numbers: network standard functions } + IPPORT_ANY = 0; + IPPORT_ECHO = 7; + IPPORT_DISCARD = 9; + IPPORT_SYSTAT = 11; + IPPORT_DAYTIME = 13; + IPPORT_NETSTAT = 15; + IPPORT_FTP = 21; + IPPORT_TELNET = 23; + IPPORT_SMTP = 25; + IPPORT_TIMESERVER = 37; + IPPORT_NAMESERVER = 42; + IPPORT_WHOIS = 43; + IPPORT_MTP = 57; + + { Port/socket numbers: host specific functions } + IPPORT_TFTP = 69; + IPPORT_RJE = 77; + IPPORT_FINGER = 79; + IPPORT_TTYLINK = 87; + IPPORT_SUPDUP = 95; + + { UNIX TCP sockets } + IPPORT_EXECSERVER = 512; + IPPORT_LOGINSERVER = 513; + IPPORT_CMDSERVER = 514; + IPPORT_EFSSERVER = 520; + + { UNIX UDP sockets } + IPPORT_BIFFUDP = 512; + IPPORT_WHOSERVER = 513; + IPPORT_ROUTESERVER = 520; + + { Ports < IPPORT_RESERVED are reserved for privileged processes (e.g. root) } + IPPORT_RESERVED = 1024; + + { Link numbers } + IMPLINK_IP = 155; + IMPLINK_LOWEXPER = 156; + IMPLINK_HIGHEXPER = 158; + + INVALID_SOCKET = $ffff; + SOCKET_ERROR = (-1); + + { Types } + SOCK_STREAM = 1; { stream socket } + SOCK_DGRAM = 2; { datagram socket } + SOCK_RAW = 3; { raw-protocol interface } + SOCK_RDM = 4; { reliably-delivered message } + SOCK_SEQPACKET = 5; { sequenced packet stream } + + { Option flags per-socket } + SO_DEBUG = $0001; { turn on debugging info recording } + SO_ACCEPTCONN = $0002; { socket has had listen() } + SO_REUSEADDR = $0004; { allow local address reuse } + SO_KEEPALIVE = $0008; { keep connections alive } + SO_DONTROUTE = $0010; { just use interface addresses } + SO_BROADCAST = $0020; { permit sending of broadcast msgs } + SO_USELOOPBACK = $0040; { bypass hardware when possible } + SO_LINGER = $0080; { linger on close if data present } + SO_OOBINLINE = $0100; { leave received OOB data in line } + SO_DONTLINGER = (not SO_LINGER); + + { Additional options } + SO_SNDBUF = $1001; { send buffer size } + SO_RCVBUF = $1002; { receive buffer size } + SO_SNDLOWAT = $1003; { send low-water mark } + SO_RCVLOWAT = $1004; { receive low-water mark } + SO_SNDTIMEO = $1005; { send timeout } + SO_RCVTIMEO = $1006; { receive timeout } + SO_ERROR = $1007; { get error status and clear } + SO_TYPE = $1008; { get socket type } + + + { TCP options } + TCP_NODELAY = $0001; + + { Address families } + AF_UNSPEC = 0; { unspecified } + AF_UNIX = 1; { local to host (pipes, portals) } + AF_INET = 2; { internetwork: UDP, TCP, etc. } + AF_IMPLINK = 3; { arpanet imp addresses } + AF_PUP = 4; { pup protocols: e.g. BSP } + AF_CHAOS = 5; { mit CHAOS protocols } + AF_NS = 6; { XEROX NS protocols } + AF_ISO = 7; { ISO protocols } + AF_OSI = AF_ISO; { OSI is ISO } + AF_ECMA = 8; { european computer manufacturers } + AF_DATAKIT = 9; { datakit protocols } + AF_CCITT = 10; { CCITT protocols, X.25 etc } + AF_SNA = 11; { IBM SNA } + AF_DECnet = 12; { DECnet } + AF_DLI = 13; { Direct data link interface } + AF_LAT = 14; { LAT } + AF_HYLINK = 15; { NSC Hyperchannel } + AF_APPLETALK = 16; { AppleTalk } + AF_NETBIOS = 17; { NetBios-style addresses } + AF_MAX = 18; + + { Protocol families, same as address families for now } + PF_UNSPEC = AF_UNSPEC; + PF_UNIX = AF_UNIX; + PF_INET = AF_INET; + PF_IMPLINK = AF_IMPLINK; + PF_PUP = AF_PUP; + PF_CHAOS = AF_CHAOS; + PF_NS = AF_NS; + PF_ISO = AF_ISO; + PF_OSI = AF_OSI; + PF_ECMA = AF_ECMA; + PF_DATAKIT = AF_DATAKIT; + PF_CCITT = AF_CCITT; + PF_SNA = AF_SNA; + PF_DECnet = AF_DECnet; + PF_DLI = AF_DLI; + PF_LAT = AF_LAT; + PF_HYLINK = AF_HYLINK; + PF_APPLETALK = AF_APPLETALK; + PF_MAX = AF_MAX; + + { Level number for (get/set)sockopt() to apply to socket itself } + SOL_SOCKET = -1; { options for socket level } + + { Maximum queue length specifiable by listen } + SOMAXCONN = 5; + + MSG_OOB = 1; { process out-of-band data } + MSG_PEEK = 2; { peek at incoming message } + MSG_DONTROUTE = 4; { send without using routing tables } + + MSG_MAXIOVLEN = 16; + + { Define constant based on rfc883, used by gethostbyxxxx() calls } + MAXGETHOSTSTRUCT = 1024; + + { Define flags to be used with the WSAAsyncSelect() call } + FD_READ = 1; + FD_WRITE = 2; + FD_OOB = 4; + FD_ACCEPT = 8; + FD_CONNECT = 16; + FD_CLOSE = 32; + + { All Windows Sockets error constants are biased by WSABASEERR fromthe normal } + WSABASEERR = 10000; + + { Windows Sockets definitions of regular Microsoft C error constants } + WSAEINTR = (WSABASEERR+4); + WSAEBADF = (WSABASEERR+9); + WSAEACCES = (WSABASEERR+13); + WSAEFAULT = (WSABASEERR+14); + WSAEINVAL = (WSABASEERR+22); + WSAEMFILE = (WSABASEERR+24); + + { Windows Sockets definitions of regular Berkeley error constants } + WSAEWOULDBLOCK = (WSABASEERR+35); + WSAEINPROGRESS = (WSABASEERR+36); + WSAEALREADY = (WSABASEERR+37); + WSAENOTSOCK = (WSABASEERR+38); + WSAEDESTADDRREQ = (WSABASEERR+39); + WSAEMSGSIZE = (WSABASEERR+40); + WSAEPROTOTYPE = (WSABASEERR+41); + WSAENOPROTOOPT = (WSABASEERR+42); + WSAEPROTONOSUPPORT = (WSABASEERR+43); + WSAESOCKTNOSUPPORT = (WSABASEERR+44); + WSAEOPNOTSUPP = (WSABASEERR+45); + WSAEPFNOSUPPORT = (WSABASEERR+46); + WSAEAFNOSUPPORT = (WSABASEERR+47); + WSAEADDRINUSE = (WSABASEERR+48); + WSAEADDRNOTAVAIL = (WSABASEERR+49); + WSAENETDOWN = (WSABASEERR+50); + WSAENETUNREACH = (WSABASEERR+51); + WSAENETRESET = (WSABASEERR+52); + WSAECONNABORTED = (WSABASEERR+53); + WSAECONNRESET = (WSABASEERR+54); + WSAENOBUFS = (WSABASEERR+55); + WSAEISCONN = (WSABASEERR+56); + WSAENOTCONN = (WSABASEERR+57); + WSAESHUTDOWN = (WSABASEERR+58); + WSAETOOMANYREFS = (WSABASEERR+59); + WSAETIMEDOUT = (WSABASEERR+60); + WSAECONNREFUSED = (WSABASEERR+61); + WSAELOOP = (WSABASEERR+62); + WSAENAMETOOLONG = (WSABASEERR+63); + WSAEHOSTDOWN = (WSABASEERR+64); + WSAEHOSTUNREACH = (WSABASEERR+65); + WSAENOTEMPTY = (WSABASEERR+66); + WSAEPROCLIM = (WSABASEERR+67); + WSAEUSERS = (WSABASEERR+68); + WSAEDQUOT = (WSABASEERR+69); + WSAESTALE = (WSABASEERR+70); + WSAEREMOTE = (WSABASEERR+71); + + { Extended Windows Sockets error constant definitions } + WSASYSNOTREADY = (WSABASEERR+91); + WSAVERNOTSUPPORTED = (WSABASEERR+92); + WSANOTINITIALISED = (WSABASEERR+93); + + { Authoritative Answer: Host not found } + WSAHOST_NOT_FOUND = (WSABASEERR+1001); + HOST_NOT_FOUND = WSAHOST_NOT_FOUND; + +{ Non-Authoritative: Host not found, or SERVERFAIL } + WSATRY_AGAIN = (WSABASEERR+1002); + TRY_AGAIN = WSATRY_AGAIN; + +{ Non recoverable errors, FORMERR, REFUSED, NOTIMP } + WSANO_RECOVERY = (WSABASEERR+1003); + NO_RECOVERY = WSANO_RECOVERY; + +{ Valid name, no data record of requested type } + WSANO_DATA = (WSABASEERR+1004); + NO_DATA = WSANO_DATA; + +{ no address, look for MX record } + WSANO_ADDRESS = WSANO_DATA; + NO_ADDRESS = WSANO_ADDRESS; + +{ Windows Sockets errors redefined as regular Berkeley error constants } + EWOULDBLOCK = WSAEWOULDBLOCK; + EINPROGRESS = WSAEINPROGRESS; + EALREADY = WSAEALREADY; + ENOTSOCK = WSAENOTSOCK; + EDESTADDRREQ = WSAEDESTADDRREQ; + EMSGSIZE = WSAEMSGSIZE; + EPROTOTYPE = WSAEPROTOTYPE; + ENOPROTOOPT = WSAENOPROTOOPT; + EPROTONOSUPPORT = WSAEPROTONOSUPPORT; + ESOCKTNOSUPPORT = WSAESOCKTNOSUPPORT; + EOPNOTSUPP = WSAEOPNOTSUPP; + EPFNOSUPPORT = WSAEPFNOSUPPORT; + EAFNOSUPPORT = WSAEAFNOSUPPORT; + EADDRINUSE = WSAEADDRINUSE; + EADDRNOTAVAIL = WSAEADDRNOTAVAIL; + ENETDOWN = WSAENETDOWN; + ENETUNREACH = WSAENETUNREACH; + ENETRESET = WSAENETRESET; + ECONNABORTED = WSAECONNABORTED; + ECONNRESET = WSAECONNRESET; + ENOBUFS = WSAENOBUFS; + EISCONN = WSAEISCONN; + ENOTCONN = WSAENOTCONN; + ESHUTDOWN = WSAESHUTDOWN; + ETOOMANYREFS = WSAETOOMANYREFS; + ETIMEDOUT = WSAETIMEDOUT; + ECONNREFUSED = WSAECONNREFUSED; + ELOOP = WSAELOOP; + ENAMETOOLONG = WSAENAMETOOLONG; + EHOSTDOWN = WSAEHOSTDOWN; + EHOSTUNREACH = WSAEHOSTUNREACH; + ENOTEMPTY = WSAENOTEMPTY; + EPROCLIM = WSAEPROCLIM; + EUSERS = WSAEUSERS; + EDQUOT = WSAEDQUOT; + ESTALE = WSAESTALE; + EREMOTE = WSAEREMOTE; + +type + { Basic system type definitions, taken from the BSD file sys/types.h. } + u_char = byte; + u_short = word; + u_int = word; + u_long = longint; + short = word; + + { low level handle wich refer to sockets } + TSocket = u_int; + + { Select uses arrays of SOCKETs. } + TFDSet = packed record + fd_count : u_short; + fd_array : array [0..(FD_SETSIZE - 1)] of TSocket; + end; + PFDSet = ^TFDSet; + + { Structure used in select() call, taken from the BSD file sys/time.h. } + TTimeVal = packed record + tv_sec : longint; + tv_usec : longint; + end; + PTimeVal = ^TTimeVal; + + { Structures returned by network data base library, taken from the + BSD file netdb.h. All addresses are supplied in host order, and + returned in network order (suitable for use in system calls). } + + HostEnt = record + h_name : PChar; { official name of host } + h_aliases : ^PChar; { alias list } + h_addrtype : short; { host address type } + h_length : short; { length of address } + h_addr_list : ^PChar; { list of addresses } + end; + PHostEnt = ^HostEnt; + + NetEnt = record + n_name : PChar; { official name of net } + n_aliases : ^PChar; { alias list } + n_addrtype : short; { net address type } + n_net : u_long; { network # } + end; + PNetEnt = ^NetEnt; + + ServEnt = record + s_name : PChar; { official service name } + s_aliases : ^PChar; { alias list } + s_port : integer; { port # } + s_proto : PChar; { protocol to use } + end; + PServEnt = ^ServEnt; + + Protoent = record + p_name : PChar; { official protocol name } + p_aliases : ^PChar; { alias list } + p_proto : integer; { protocol # } + end; + Pprotoent = ^protoent; + + { Internet address (old style... should be updated) } + SunB = packed record + s_b1, s_b2, s_b3, s_b4: u_char; + end; + + SunW = packed record + s_w1, s_w2: u_short; + end; + + TInAddr = packed record + case integer of + 0: (S_un_b: SunB); + 1: (S_un_w: SunW); + 2: (S_addr: u_long); + end; + PInAddr = ^TInAddr; + + { Socket address, internet style. } + TSockAddrIn = packed record + case integer of + 0: (sin_family : u_short; + sin_port : u_short; + sin_addr : TInAddr; + sin_zero : array[0..7] of char); + 1: (sa_family: u_short; + sa_data: array [0..13] of char); + end; + PSockAddrIn = ^TSockAddrIn; + TSockAddr = TSockAddrIn; + + PWSADATA = ^TWSADATA; + TWSADATA = packed record + wVersion : word; + wHighVersion : word; + szDescription : array [0..WSADESCRIPTION_LEN] of char; + szSystemStatus : array [0..WSASYS_STATUS_LEN] of char; + iMaxSockets : u_short; + iMaxUdpDg : u_short; + lpVendorInfo : PChar; + end; + + { Structure used by kernel to pass protocol information in raw sockets. } + TSockProto = packed record + sp_family : u_short; + sp_protocol : u_short; + end; + + { Structure used for manipulating linger option. } + TLinger = packed record + l_onoff : u_short; + l_linger : u_short; + end; + +{ Socket function prototypes } + +function accept(s: TSocket; var addr: TSockAddr; var addrlen: Integer): TSocket; +function bind(s: TSocket; var addr: TSockAddr; namelen: Integer): Integer; +function closesocket(s: TSocket): Integer; +function connect(s: TSocket; var name: TSockAddr; namelen: Integer): Integer; +function ioctlsocket(s: TSocket; cmd: Longint; var arg: u_long): Integer; +function getpeername(s: TSocket; var name: TSockAddr; var namelen: Integer): Integer; +function getsockname(s: TSocket; var name: TSockAddr; var namelen: Integer): Integer; +function getsockopt(s: TSocket; level, optname: Integer; optval: PChar; var optlen: Integer): Integer; +function htonl(hostlong: u_long): u_long; +function htons(hostshort: u_short): u_short; +function inet_addr(cp: PChar): u_long; +function inet_ntoa(inaddr: TInAddr): PChar; +function listen(s: TSocket; backlog: Integer): Integer; +function ntohl(netlong: u_long): u_long; +function ntohs(netshort: u_short): u_short; +function recv(s: TSocket; var Buf; len, flags: Integer): Integer; +function recvfrom(s: TSocket; var Buf; len, flags: Integer; + var from: TSockAddr; var fromlen: Integer): Integer; +function select(nfds: Integer; readfds, writefds, exceptfds: PFDSet; + timeout: PTimeVal): Longint; +function send(s: TSocket; var Buf; len, flags: Integer): Integer; +function sendto(s: TSocket; var Buf; len, flags: Integer; var addrto: TSockAddr; + tolen: Integer): Integer; +function setsockopt(s: TSocket; level, optname: Integer; optval: PChar; + optlen: Integer): Integer; +function shutdown(s: TSocket; how: Integer): Integer; +function socket(af, struct, protocol: Integer): TSocket; +function gethostbyaddr(addr: Pointer; len, struct: Integer): PHostEnt; +function gethostbyname(name: PChar): PHostEnt; +function gethostname(name: PChar; len: Integer): Integer; +function getservbyport(port: Integer; proto: PChar): PServEnt; +function getservbyname(name, proto: PChar): PServEnt; +function getprotobynumber(proto: Integer): PProtoEnt; +function getprotobyname(name: PChar): PProtoEnt; +function WSAStartup(wVersionRequired: word; var WSData: TWSAData): Integer; +function WSACleanup: Integer; +procedure WSASetLastError(iError: Integer); +function WSAGetLastError: Integer; +function WSAIsBlocking: BOOL; +function WSAUnhookBlockingHook: Integer; +function WSASetBlockingHook(lpBlockFunc: TFarProc): TFarProc; +function WSACancelBlockingCall: Integer; +function WSAAsyncGetServByName(HWindow: HWND; wMsg: u_int; + name, proto, buf: PChar; buflen: Integer): THandle; +function WSAAsyncGetServByPort( HWindow: HWND; wMsg, port: u_int; + proto, buf: PChar; buflen: Integer): THandle; +function WSAAsyncGetProtoByName(HWindow: HWND; wMsg: u_int; + name, buf: PChar; buflen: Integer): THandle; +function WSAAsyncGetProtoByNumber(HWindow: HWND; wMsg: u_int; number: Integer; + buf: PChar; buflen: Integer): THandle; +function WSAAsyncGetHostByName(HWindow: HWND; wMsg: u_int; + name, buf: PChar; buflen: Integer): THandle; +function WSAAsyncGetHostByAddr(HWindow: HWND; wMsg: u_int; addr: PChar; + len, struct: Integer; buf: PChar; buflen: Integer): THandle; +function WSACancelAsyncRequest(hAsyncTaskHandle: THandle): Integer; +function WSAAsyncSelect(s: TSocket; HWindow: HWND; wMsg: u_int; lEvent: Longint): Integer; +function WSARecvEx(s: TSocket; var buf; len: Integer; var flags: Integer): Integer; +function WSAMakeSyncReply(Buflen, Error: Word): Longint; +function WSAMakeSelectReply(Event, Error: Word): Longint; +function WSAGetAsyncBuflen(Param: Longint): Word; +function WSAGetAsyncError(Param: Longint): Word; +function WSAGetSelectEvent(Param: Longint): Word; +function WSAGetSelectError(Param: Longint): Word; + + +implementation + +function WSAMakeSyncReply; +begin + WSAMakeSyncReply:= MakeLong(Buflen, Error); +end; + +function WSAMakeSelectReply; +begin + WSAMakeSelectReply:= MakeLong(Event, Error); +end; + +function WSAGetAsyncBuflen; +begin + WSAGetAsyncBuflen:= LOWORD(Param); +end; + +function WSAGetAsyncError; +begin + WSAGetAsyncError:= HIWORD(Param); +end; + +function WSAGetSelectEvent; +begin + WSAGetSelectEvent:= LOWORD(Param); +end; + +function WSAGetSelectError; +begin + WSAGetSelectError:= HIWORD(Param); +end; + +function accept; external winsocket name 'accept'; +function bind; external winsocket name 'bind'; +function closesocket; external winsocket name 'closesocket'; +function connect; external winsocket name 'connect'; +function getpeername; external winsocket name 'getpeername'; +function getsockname; external winsocket name 'getsockname'; +function getsockopt; external winsocket name 'getsockopt'; +function htonl; external winsocket name 'htonl'; +function htons; external winsocket name 'htons'; +function inet_addr; external winsocket name 'inet_addr'; +function inet_ntoa; external winsocket name 'inet_ntoa'; +function ioctlsocket; external winsocket name 'ioctlsocket'; +function listen; external winsocket name 'listen'; +function ntohl; external winsocket name 'ntohl'; +function ntohs; external winsocket name 'ntohs'; +function recv; external winsocket name 'recv'; +function recvfrom; external winsocket name 'recvfrom'; +function select; external winsocket name 'select'; +function send; external winsocket name 'send'; +function sendto; external winsocket name 'sendto'; +function setsockopt; external winsocket name 'setsockopt'; +function shutdown; external winsocket name 'shutdown'; +function socket; external winsocket name 'socket'; + +function gethostbyaddr; external winsocket name 'gethostbyaddr'; +function gethostbyname; external winsocket name 'gethostbyname'; +function getprotobyname; external winsocket name 'getprotobyname'; +function getprotobynumber; external winsocket name 'getprotobynumber'; +function getservbyname; external winsocket name 'getservbyname'; +function getservbyport; external winsocket name 'getservbyport'; +function gethostname; external winsocket name 'gethostname'; + +function WSAAsyncSelect; external winsocket name 'WSAAsyncSelect'; +function WSARecvEx; external winsocket name 'WSARecvEx'; +function WSAAsyncGetHostByAddr; external winsocket name 'WSAAsyncGetHostByAddr'; +function WSAAsyncGetHostByName; external winsocket name 'WSAAsyncGetHostByName'; +function WSAAsyncGetProtoByNumber; external winsocket name 'WSAAsyncGetProtoByNumber'; +function WSAAsyncGetprotoByName; external winsocket name 'WSAAsyncGetprotoByName'; +function WSAAsyncGetServByPort; external winsocket name 'WSAAsyncGetServByPort'; +function WSAAsyncGetServByName; external winsocket name 'WSAAsyncGetServByName'; +function WSACancelAsyncRequest; external winsocket name 'WSACancelAsyncRequest'; +function WSASetBlockingHook; external winsocket name 'WSASetBlockingHook'; +function WSAUnhookBlockingHook; external winsocket name 'WSAUnhookBlockingHook'; +function WSAGetLastError; external winsocket name 'WSAGetLastError'; +procedure WSASetLastError; external winsocket name 'WSASetLastError'; +function WSACancelBlockingCall; external winsocket name 'WSACancelBlockingCall'; +function WSAIsBlocking; external winsocket name 'WSAIsBlocking'; +function WSAStartup; external winsocket name 'WSAStartup'; +function WSACleanup; external winsocket name 'WSACleanup'; + +end. + diff --git a/ICS_zlog/Delphi/Vc/emulvt.dcr b/ICS_zlog/Delphi/Vc/emulvt.dcr new file mode 100644 index 0000000000000000000000000000000000000000..b6f27127c1ed53fb0e34488586a6f287969dfeb7 GIT binary patch literal 409 zcmcJKF%pCz3`L)gy_S}imR`cn?bP#7dMu8_4e$q6hhn#K3<-Jp3Ctwctn+7E_LZqS zDj0$O8x@TR2I-}Bci}*eb2;f2;=Nb4ModnOMhYF1tbWBp`Zu)p`9CJL^Gv}K?D5t7 T$r7!fW(v-A(1x@nKUwhv{GJY} literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc/fingcli.dcr b/ICS_zlog/Delphi/Vc/fingcli.dcr new file mode 100644 index 0000000000000000000000000000000000000000..8844962c7849cf4c31e82a398fe1a4620a01a2b8 GIT binary patch literal 412 zcmcJHJr2S!3`Sp3C9fSBJ2LhT2v8-&P;n4%Su=91+$?+!sLBQE_~+UF;(FqJUtf>g zc73ia(`SGSaQ?@@D1uq@-lo0DASdTvQ5I54QH@1yPOU)-y%;H_!wl-}zXX!Tit2kAr7`=tdfKvF}0DfQJ!60cGk3>v7u@3A(J{Z-C} zXgt=1iZ`WG)k&4lP*hjNXxQu{n4oKHG|mgpjdg9<_{XIl!XnCIv7|m?Uvl8-rkIJo zMYf3@@g%c6R}R$VXExNNVcr*QtVyE(Z%NdH5zgNY8hBSth?>ZfLKSj)Ie*B=wB4!G z^54GSP3Hr_SNgD*{O0}gIX=7Su57&Y;VTZ)^L?^!nZAgydoYN?x2&6h^`)r@(loR4T#>aDB zUh{(6v<|=(z`6N=Q4F}K|7lY%5+ER@Eh&m3=dA35Qh`#O$@RRYz$1o01S2cVC^#ou vGXxSeKuz%~Fw;==w(CnrF6}hFqpco(a_Df?c<$1AyXn8V|I@L%^{;pX&BBp= literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc/mbxfile.dcr b/ICS_zlog/Delphi/Vc/mbxfile.dcr new file mode 100644 index 0000000000000000000000000000000000000000..98b63deb996c2fb62fa1d4015e7b13e1bf706fdb GIT binary patch literal 413 zcmaKnF%H5o3`KuYC9fSB89Q xcDK;B7$yxu)YKp}f3~_M=Tb(l6LXX@f%e6T%T(r{T&y^2mMqykv-#iOjVC-6fbjqT literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc/mimedec.dcr b/ICS_zlog/Delphi/Vc/mimedec.dcr new file mode 100644 index 0000000000000000000000000000000000000000..27cfe51ee9026285bcccdb21d3361bb9ed8fa642 GIT binary patch literal 413 zcmZ{fI}XAy5JV>k$!$tXN=oiPQcy%`IEcHnE;*KOX5KE5afH0y&v-l<+vTL!@?7R= zeyr21`}iKDo21KLgU%r73g5<9H%TIu(s$5-$~iObpm?ejLlny>+SZH6k*pBJEwFsh uY-ef25zA%&{7>KbH2%Fep!Tby8}Ar#<$DVQ)K literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc/nntpcli.dcr b/ICS_zlog/Delphi/Vc/nntpcli.dcr new file mode 100644 index 0000000000000000000000000000000000000000..5e5113b06ab1c0804376306df3ab1495abc2b13b GIT binary patch literal 410 zcma)1F%H5o47?&FuN@gXGV%u|Bvdi
O=Z^qMwTd(2-J0TuG60W>%wAM=4?qnj|ikr4m@ literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc/tncnx.dcr b/ICS_zlog/Delphi/Vc/tncnx.dcr new file mode 100644 index 0000000000000000000000000000000000000000..897c60e70058d75437c23e161ce00447ffce1fe4 GIT binary patch literal 408 zcmb7;I}U>|5JVpc$t@*iN=ojK-W5fT;m)ng9LqN|v&JBbM1t{tX2;`C=~-9*_8*q< z+rbP>EjtD=cuBuvJck4dQrerUC^=_!+bA_C#h6mdB$apzf#{-B$i0&gL@iA;`3FBe d)Z@*pR-rp@;JDtb&$%9MurD^iWjMrteFJqtiLL+u literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc/tnemulvt.dcr b/ICS_zlog/Delphi/Vc/tnemulvt.dcr new file mode 100644 index 0000000000000000000000000000000000000000..6a5efeb665695cc007a6607701e0511e183e9269 GIT binary patch literal 411 zcmb7B z9*q&e0?%3D>YT_dsLU=ba8~23a&5v12tBj+zZN898gOJoSC5vJe0cgkTFfA)2P)DjQJ;Vid&5M^qwzNa{2Bn7}Pc z4m;Dw7M1CHxGg0#auT_X0p^?JfJU$E3pcSqMtp_nSd)8UHSx^fk+Z8wp#C)l)`L6D zzb@p2i)uovf1{k1)*|al6BoT*Ij_vM!rC2@$hbIz%_+J13 literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc/wsocket.dcr b/ICS_zlog/Delphi/Vc/wsocket.dcr new file mode 100644 index 0000000000000000000000000000000000000000..a536b4e9c0e04af6fbbe6e7166ae391319b3a3e7 GIT binary patch literal 410 zcma)0yAHxI5OWby){cyfjQj&)Vqlb-=k#9dH70SiHlY3^=mhqW@kZKtqf*F_I$Z%&doEhEl}nJSs8xZJ5{wSG7rq z#zT$vFbAf{Lu}(u@6)1Zr**6MmnW)hW_W9|J|SlAUS39h&^}cCg?3-z{3N*$9U9)$ HSFQ2~d})&^ literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc/wsockets.dcr b/ICS_zlog/Delphi/Vc/wsockets.dcr new file mode 100644 index 0000000000000000000000000000000000000000..ee027a856f8add21b96401bfdb0d04c563df854e GIT binary patch literal 1209 zcmd5+yH3ME5F95+P6a6_=;D%+KL`>^MS+w=@Ehs&T;)34rHuSH{*;uI=|X`xX7}uH zMiELu!8qRA*~i^_*G?E<`LcL=c$_U4v-$IEj=OP{0k;5d+B?GqHK3q9#rQ}(z#qJi z3nf)FO~X|k!F~uqHQv0`L?P#3#U$i0vQl`FZCN|BxV)^T-Z=Wb__{2QIz!6N&II|^ zh5D;V#SCJ@Ov_I6Ef1i*VifnRYj@Ddc$REfdDvSG;#Q1~2)p4hus zUBeI|<4oQLaV7Y+`iVT2%%Y=5pEd*vXPn(*BiJu? zOAV^Hk#P-Bx2#}X1C$=QYbV?JZ5HNlyQ;HEagwjYLBvGNuPSmAkz+(|;=gh}Vy`~q z6w>xfRRuqWUPHQmN3Xhj0ZNk{%$)>8cVB)2>knZ14ovpI)sFEEF!cJ`{S7kiHEg)= jj{EbB3D27H%r(yr;S$UEm&6zU8j6fpQH)L3Pa(q>5N&wP literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/DnsQuery.dcr b/ICS_zlog/Delphi/Vc32/DnsQuery.dcr new file mode 100644 index 0000000000000000000000000000000000000000..04b26c73a8cacdaf07b29219e1388defb37bd571 GIT binary patch literal 472 zcma)$I}QRd3`A!UQYa|4q}-B{LqLnfuizH$(x&8CxmlQrLqsGBtT=wL$94cN5? X$BGt5BI4ix>y#MFC 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 AT>t<8 literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/DnsQuery.pas b/ICS_zlog/Delphi/Vc32/DnsQuery.pas new file mode 100644 index 00000000..8afdd967 --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/DnsQuery.pas @@ -0,0 +1,1046 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: Component to query DNS records. + Implement a subset of RFC 1035 (A and MX records). +Creation: January 29, 1999 +Version: 1.03 +EMail: http://www.overbyte.be http://www.rtfm.be/fpiette + francois.piette@overbyte.be francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 1999-2002 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +History: +Feb 14, 1999 V0.02 Indirectly call winsock functions using wsocket because + wsocket provide runtime dynamic link instead of loadtime link. + This allows a program to use DnsQuery if it discover that winsock + is installed and still run if winsock is not installed. +Feb 24, 1999 V1.00 Added code for reverse lookup (PTR record). +Mar 07, 1999 V1.01 Adapted for Delphi 1 +Aug 20, 1999 V1.02 Revise compile time option. Adapted for BCB4 +Jul 27, 2001 V1.03 Holger Lembke implemented a few new + queries or propreties (QueryAny, LongLatToDMS, Loc2Geo, Loc) + and related data types. + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit DnsQuery; + +{$B-} { Enable partial boolean evaluation } +{$T-} { Untyped pointers } +{$R-} { Disable range checking } +{$IFNDEF VER80} { Not for Delphi 1 } + {$H+} { Use long strings } + {$J+} { Allow typed constant to be modified } +{$ENDIF} +{$IFDEF VER110} { C++ Builder V3.0 } + {$ObjExportAll On} +{$ENDIF} +{$IFDEF VER125} { C++ Builder V4.0 } + {$ObjExportAll On} +{$ENDIF} + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, + Winsock, WSocket; + +const + DnsQueryVersion = 102; + CopyRight : String = ' TDnsQuery (c) 1999-2000 F. Piette V1.02 '; + + { Maximum answers (responses) count } + MAX_ANCOUNT = 50; + { Maximum number of MX records taken into account in responses } + MAX_MX_RECORDS = 50; + MAX_A_RECORDS = 50; + MAX_PTR_RECORDS = 10; + + { DNS Classes } + DnsClassIN = 1; { The internet } + DnsClassCS = 2; { The CSNET class (obsolete, used only for examples)} + DnsClassCH = 3; { The CHAOS class } + DnsClassHS = 4; { Hesiod name service } + DnsClassALL = 255; { Any class } + + { Type of query/response a DNS can handle } + DnsQueryA = 1; { A HostAddress } + DnsQueryNS = 2; { NS Authoritative name server } + DnsQueryMD = 3; { MD MailDestination, obsolete, use Mail Exchange } + DnsQueryMF = 4; { MF MailForwarder, obsolete, use Mail Exchange } + DnsQueryCNAME = 5; { CNAME CanonicalName } + DnsQuerySOA = 6; { SOA Start of a Zone of Authority } + DnsQueryMB = 7; { MB MailBox, experimental } + DnsQueryMG = 8; { MG MailGroup, experimental } + DnsQueryMR = 9; { MR MailRename, experimental } + DnsQueryNULL = 10; { NULL Experimental } + DnsQueryWKS = 11; { WKS Well Known Service Description } + DnsQueryPTR = 12; { PTR Domain Name Pointer } + DnsQueryHINFO = 13; { HINFO Host Information } + DnsQueryMINFO = 14; { MINFO Mailbox information } + DnsQueryMX = 15; { MX Mail Exchange } + DnsQueryTXT = 16; { TXT Text Strings } + { !!KAP!! } + DnsQueryRP = 17; + DnsQueryAFSDB = 18; + DnsQueryX25 = 19; + DnsQueryISDN = 20; + DnsQueryRT = 21; + DnsQueryNSAP = 22; + DnsQueryNSAPPTR = 23; + DnsQuerySIG = 24; { see RFC-2065 } + DnsQueryKEY = 25; { see RFC-2065 } + DnsQueryPX = 26; + DnsQueryGPOS = 27; { GPOS has the following format: + GPOS } + DnsQueryAAAA = 28; { see IP6 Address } + DnsQueryLOC = 29; (* see RFC-1876 http://rfc.net/rfc1876.html + LOC ( d1 [m1 [s1]] {"N"|"S"} d2 [m2 [s2]] + {"E"|"W"} alt["m"] [siz["m"] [hp["m"] + [vp["m"]]]] ) + *) + DnsQueryNXT = 30; { see RFC-2065 } + + DnsQuerySRV = 33; { see RFC-2052 } + DnsQueryNAPTR = 35; { see RFC-2168 } + DnsQueryKX = 36; + + { Some additional type only allowed in queries } + DnsQueryAXFR = 252; { Transfer for an entire zone } + DnsQueryMAILB = 253; { Mailbox related records (MB, MG or MR) } + DnsQueryMAILA = 254; { MailAgent, obsolete, use MX instead } + DnsQueryALL = 255; { Request ALL records } + + { Opcode field in query flags } + DnsOpCodeQUERY = 0; + DnsOpCodeIQUERY = 1; + DnsOpCodeSTATUS = 2; + +type + TDnsAnswerNameArray = packed array [0..MAX_ANCOUNT - 1] of String; + TDnsAnswerTypeArray = packed array [0..MAX_ANCOUNT - 1] of Integer; + TDnsAnswerClassArray = packed array [0..MAX_ANCOUNT - 1] of Integer; + TDnsAnswerTTLArray = packed array [0..MAX_ANCOUNT - 1] of LongInt; + TDnsAnswerTagArray = packed array [0..MAX_ANCOUNT - 1] of Integer; + TDnsMXPreferenceArray = packed array [0..MAX_MX_RECORDS - 1] of Integer; + TDnsMXExchangeArray = packed array [0..MAX_MX_RECORDS - 1] of String; + TDnsAddressArray = packed array [0..MAX_A_RECORDS - 1] of TInAddr; + TDnsHostnameArray = packed array [0..MAX_PTR_RECORDS - 1] of String; + + TDnsRequestDoneEvent = procedure (Sender : TObject; Error : WORD) of Object; + TDnsRequestHeader = packed record + ID : WORD; + Flags : WORD; + QDCount : WORD; + ANCount : WORD; + NSCount : WORD; + ARCount : WORD; + end; + PDnsRequestHeader = ^TDnsRequestHeader; + + TLOCInfo = packed record { need to be 16 bytes } + version : byte; + size : byte; + horizpre : byte; + vertpre : byte; + latitude : longint; + longitude : longint; + altitude : longint; + end; + PLOCInfo = ^TLOCInfo; + + { Decoded TLOCInfo } + TLogGeo = record + version : byte; + longsize : integer; + latsize : integer; + horizpre : integer; + vertpre : integer; + { Latitude, degree, minutes, seconds, milliseconds } + lad, lam, las, lams : integer; + lahem : char; + { same for Longitude } + lod, lom, los, loms : integer; + lohem : char; + altitude : integer; + end; + + TDnsQuery = class(TComponent) + private + { Déclarations privées } + protected + FWSocket : TWSocket; + FPort : String; + FAddr : String; + FIDCount : WORD; + FQueryBuf : array [0..511] of char; + FQueryLen : Integer; + FResponseBuf : array [0..511] of char; + FResponseLen : Integer; + FResponseID : Integer; + FResponseCode : Integer; + FResponseOpCode : Integer; + FResponseAuthoritative : Boolean; + FResponseTruncation : Boolean; + FResponseRecursionAvailable : Boolean; + FResponseQDCount : Integer; + FResponseANCount : Integer; + FResponseNSCount : Integer; + FResponseARCount : Integer; + FQuestionType : Integer; + FQuestionClass : Integer; + FQuestionName : String; + FAnswerNameArray : TDnsAnswerNameArray; + FAnswerTypeArray : TDnsAnswerTypeArray; + FAnswerClassArray : TDnsAnswerClassArray; + FAnswerTTLArray : TDnsAnswerTTLArray; + FAnswerTagArray : TDnsAnswerTagArray; + FMXRecordCount : Integer; + FMXPreferenceArray : TDnsMXPreferenceArray; { For MX request } + FMXExchangeArray : TDnsMXExchangeArray; { For MX request } + FARecordCount : Integer; + FAddressArray : TDnsAddressArray; { For A request } + FPTRRecordCount : Integer; + FHostnameArray : TDnsHostnameArray; { For PTR request } + FOnRequestDone : TDnsRequestDoneEvent; + + { !!KAP!! } + fLOCInfo : TLOCInfo; + + function GetMXPreference(nIndex : Integer) : Integer; + function GetMXExchange(nIndex : Integer) : String; + function GetAnswerName(nIndex : Integer) : String; + function GetAnswerType(nIndex : Integer) : Integer; + function GetAnswerClass(nIndex : Integer) : Integer; + function GetAnswerTTL(nIndex : Integer) : LongInt; + function GetAnswerTag(nIndex : Integer) : Integer; + function GetAddress(nIndex : Integer) : TInAddr; + function GetHostname(nIndex : Integer) : String; + procedure BuildRequestHeader(Dst : PDnsRequestHeader; + ID : WORD; + OPCode : BYTE; + Recursion : Boolean; + QDCount : WORD; + ANCount : WORD; + NSCount : WORD; + ARCount : WORD); virtual; + function BuildQuestionSection(Dst : PChar; + const QName : String; + QType : WORD; + QClass : WORD) : Integer; virtual; + procedure WSocketDataAvailable(Sender: TObject; Error: WORD); virtual; + procedure TriggerRequestDone(Error: WORD); virtual; + function GetResponseBuf : PChar; + procedure SendQuery; + function ExtractName(Base : PChar; + From : PChar; + var Name : String) : PChar; + function DecodeQuestion(Base : PChar; + From : PChar; + var Name : String; + var QType : Integer; + var QClass : Integer) : PChar; + function DecodeAnswer(Base : PChar; + From : PChar; + var Name : String; + var QType : Integer; + var QClass : Integer; + var TTL : LongInt; + var RDataPtr : Pointer; + var RDataLen : Integer) : PChar; + function DecodeMXData(Base : PChar; + From : PChar; + var Preference : Integer; + var Exchange : String) : PChar; + function DecodeAData(Base : PChar; + From : PChar; + var Address : TInAddr) : PChar; + function DecodePTRData(Base : PChar; + From : PChar; + var Hostname : String) : PChar; + public + constructor Create(AOwner : TComponent); override; + destructor Destroy; override; + procedure Notification(AComponent: TComponent; operation: TOperation); override; + function MXLookup(Domain : String) : Integer; + function ALookup(Host : String) : Integer; + function PTRLookup(IP : String) : Integer; + { !!KAP!! } + function QueryAny(Host : String; QNumber : Integer) : Integer; + + property ResponseID : Integer read FResponseID; + property ResponseCode : Integer read FResponseCode; + property ResponseOpCode : Integer read FResponseOpCode; + property ResponseAuthoritative : Boolean read FResponseAuthoritative; + property ResponseTruncation : Boolean read FResponseTruncation; + property ResponseRecursionAvailable : Boolean read FResponseRecursionAvailable; + property ResponseQDCount : Integer read FResponseQDCount; + property ResponseANCount : Integer read FResponseANCount; + property ResponseNSCount : Integer read FResponseNSCount; + property ResponseARCount : Integer read FResponseARCount; + property ResponseBuf : PChar read GetResponseBuf; + property ResponseLen : Integer read FResponseLen; + property QuestionType : Integer read FQuestionType; + property QuestionClass : Integer read FQuestionClass; + property QuestionName : String read FQuestionName; + property AnswerName[nIndex : Integer] : String read GetAnswerName; + property AnswerType[nIndex : Integer] : Integer read GetAnswerType; + property AnswerClass[nIndex : Integer] : Integer read GetAnswerClass; + property AnswerTTL[nIndex : Integer] : LongInt read GetAnswerTTL; + property AnswerTag[nIndex : Integer] : Integer read GetAnswerTag; + property MXPreference[nIndex : Integer] : Integer read GetMXPreference; + property MXExchange[nIndex : Integer] : String read GetMXExchange; + property Address[nIndex : Integer] : TInAddr read GetAddress; + property Hostname[nIndex : Integer] : String read GetHostname; + + { !!KAP!! } + property Loc : TLOCInfo read fLOCInfo; + published + property Port : String read FPort write FPort; + property Addr : String read FAddr write FAddr; + property OnRequestDone : TDnsRequestDoneEvent read FOnRequestDone + write FOnRequestDone; + end; + + +function ReverseIP(const IP : String) : String; +function LongLatToDMS(longlat : longint; hemis : String) : String; { !!KAP!! } +function Loc2Geo(loc : TLOCInfo) : TLogGeo; { !!KAP!! } +procedure Register; + +implementation + +type + PWORD = ^WORD; + PDWORD = ^DWORD; + + + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function ReverseIP(const IP : String) : String; +var + I, J : Integer; +begin + Result := ''; + if Length(IP) = 0 then + Exit; + J := Length(IP); + I := J; + while I >= 0 do begin + if (I = 0) or (IP[I] = '.') then begin + Result := Result + '.' + Copy(IP, I + 1, J - I); + J := I - 1; + end; + Dec(I); + end; + if Result[1] = '.' then + Delete(Result, 1, 1); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure Register; +begin + RegisterComponents('FPiette', [TDnsQuery]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TDnsQuery.Create(AOwner : TComponent); +begin + inherited Create(AOwner); + FWSocket := TWSocket.Create(nil); + FPort := '53'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor TDnsQuery.Destroy; +begin + if Assigned(FWSocket) then begin + FWSocket.Destroy; + FWSocket := nil; + end; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsQuery.Notification(AComponent: TComponent; operation: TOperation); +begin + inherited Notification(AComponent, operation); + if operation = opRemove then begin + if AComponent = FWSocket then + FWSocket := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.GetMXPreference(nIndex : Integer) : Integer; +begin + { Silently ignore index out of bounds error } + if (nIndex < Low(FMXPreferenceArray)) or + (nIndex > High(FMXPreferenceArray)) then + Result := 0 + else + Result := FMXPreferenceArray[nIndex]; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.GetMXExchange(nIndex : Integer) : String; +begin + { Silently ignore index out of bounds error } + if (nIndex < Low(FMXExchangeArray)) or + (nIndex > High(FMXExchangeArray)) then + Result := '' + else + Result := FMXExchangeArray[nIndex]; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.GetAnswerName(nIndex : Integer) : String; +begin + { Silently ignore index out of bounds error } + if (nIndex < Low(FAnswerNameArray)) or + (nIndex > High(FAnswerNameArray)) then + Result := '' + else + Result := FAnswerNameArray[nIndex]; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.GetAnswerType(nIndex : Integer) : Integer; +begin + { Silently ignore index out of bounds error } + if (nIndex < Low(FAnswerTypeArray)) or + (nIndex > High(FAnswerTypeArray)) then + Result := 0 + else + Result := FAnswerTypeArray[nIndex]; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.GetAnswerClass(nIndex : Integer) : Integer; +begin + { Silently ignore index out of bounds error } + if (nIndex < Low(FAnswerClassArray)) or + (nIndex > High(FAnswerClassArray)) then + Result := 0 + else + Result := FAnswerClassArray[nIndex]; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.GetAnswerTTL(nIndex : Integer) : LongInt; +begin + { Silently ignore index out of bounds error } + if (nIndex < Low(FAnswerTTLArray)) or + (nIndex > High(FAnswerTTLArray)) then + Result := 0 + else + Result := FAnswerTTLArray[nIndex]; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.GetAnswerTag(nIndex : Integer) : Integer; +begin + { Silently ignore index out of bounds error } + if (nIndex < Low(FAnswerTagArray)) or + (nIndex > High(FAnswerTagArray)) then + Result := 0 + else + Result := FAnswerTagArray[nIndex]; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.GetAddress(nIndex : Integer) : TInAddr; +begin + { Silently ignore index out of bounds error } + if (nIndex < Low(FAddressArray)) or + (nIndex > High(FAddressArray)) then + Result.S_addr := 0 + else + Result := FAddressArray[nIndex]; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.GetHostname(nIndex : Integer) : String; +begin + { Silently ignore index out of bounds error } + if (nIndex < Low(FHostnameArray)) or + (nIndex > High(FHostnameArray)) then + Result := '' + else + Result := FHostnameArray[nIndex]; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.GetResponseBuf : PChar; +begin + Result := @FResponseBuf; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.MXLookup(Domain : String) : Integer; +begin + Inc(FIDCount); + BuildRequestHeader(PDnsRequestHeader(@FQueryBuf), FIDCount, DnsOpCodeQuery, TRUE, 1, 0, 0, 0); + FQueryLen := BuildQuestionSection(@FQueryBuf[SizeOf(TDnsRequestHeader)], Domain, DnsQueryMX, DnsClassIN); + FQueryLen := FQueryLen + SizeOf(TDnsRequestHeader); + Result := FIDCount; + SendQuery; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.ALookup(Host : String) : Integer; +begin + Inc(FIDCount); + BuildRequestHeader(PDnsRequestHeader(@FQueryBuf), FIDCount, DnsOpCodeQuery, TRUE, 1, 0, 0, 0); + FQueryLen := BuildQuestionSection(@FQueryBuf[SizeOf(TDnsRequestHeader)], Host, DnsQueryA, DnsClassIN); + FQueryLen := FQueryLen + SizeOf(TDnsRequestHeader); + Result := FIDCount; + SendQuery; +end; + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ !!KAP!! } +function TDnsQuery.QueryAny(Host : String; QNumber : integer) : Integer; +begin + Inc(FIDCount); + BuildRequestHeader(PDnsRequestHeader(@FQueryBuf), FIDCount, DnsOpCodeQuery, TRUE, 1, 0, 0, 0); + FQueryLen := BuildQuestionSection(@FQueryBuf[SizeOf(TDnsRequestHeader)], Host, QNumber, DnsClassIN); + FQueryLen := FQueryLen + SizeOf(TDnsRequestHeader); + Result := FIDCount; + SendQuery; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.PTRLookup(IP : String) : Integer; +begin + Inc(FIDCount); + BuildRequestHeader(PDnsRequestHeader(@FQueryBuf), FIDCount, DnsOpCodeQuery, TRUE, 1, 0, 0, 0); + FQueryLen := BuildQuestionSection(@FQueryBuf[SizeOf(TDnsRequestHeader)], + ReverseIP(IP) + '.in-addr.arpa', + DnsQueryPTR, DnsClassIN); + FQueryLen := FQueryLen + SizeOf(TDnsRequestHeader); + Result := FIDCount; + SendQuery; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsQuery.SendQuery; +begin + FResponseLen := -1; + FWSocket.OnDataAvailable := nil; + FWSocket.Abort; + FWSocket.OnDataAvailable := WSocketDataAvailable; + FWSocket.Proto := 'udp'; + FWSocket.Port := FPort; + FWSocket.Addr := FAddr; + FWSocket.Connect; + FWSocket.Send(@FQueryBuf, FQueryLen); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.BuildQuestionSection( + Dst : PChar; + const QName : String; + QType : WORD; + QClass : WORD) : Integer; +var + I : Integer; + p : PChar; + Ptr : PChar; +begin + Ptr := Dst; + if Ptr = nil then begin + Result := 0; + Exit; + end; + I := 1; + while I <= Length(QName) do begin + p := Ptr; + Inc(Ptr); + while (I <= Length(QName)) and (QName[I] <> '.') do begin + Ptr^ := QName[I]; + Inc(Ptr); + Inc(I); + end; + p^ := Chr(Ptr - p - 1); + Inc(I); + end; + Ptr^ := #0; + Inc(Ptr); + PWORD(Ptr)^ := htons(QType); + Inc(Ptr, 2); + PWORD(Ptr)^ := htons(QClass); + Inc(Ptr, 2); + Result := Ptr - Dst; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsQuery.BuildRequestHeader( + Dst : PDnsRequestHeader; + ID : WORD; + OPCode : BYTE; + Recursion : Boolean; + QDCount : WORD; + ANCount : WORD; + NSCount : WORD; + ARCount : WORD); +begin + if Dst = nil then + Exit; + Dst^.ID := htons(ID); + Dst^.Flags := htons((OpCode shl 11) + (Ord(Recursion) shl 8)); + Dst^.QDCount := htons(QDCount); + Dst^.ANCount := htons(ANCount); + Dst^.NSCount := htons(NSCount); + Dst^.ARCount := htons(ARCount); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsQuery.TriggerRequestDone(Error: WORD); +begin + if Assigned(FOnRequestDone) then + FOnRequestDone(Self, Error); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TDnsQuery.WSocketDataAvailable(Sender: TObject; Error: WORD); +var + Len : Integer; + Ans : PDnsRequestHeader; + Flags : Integer; + P : PChar; + RDataPtr : Pointer; + RDataLen : Integer; + I : Integer; +begin + Ans := PDnsRequestHeader(@FResponseBuf); + Len := FWSocket.Receive(Ans, SizeOf(FResponseBuf)); + if Error <> 0 then begin + TriggerRequestDone(Error); + Exit; + end; + { Check for minimum response length } + if Len < SizeOf(TDnsRequestHeader) then + Exit; + Flags := WSocket_ntohs(Ans^.Flags); + { Check if we got a response } + if (Flags and $8000) = 0 then + Exit; + FResponseLen := Len; + { Decode response header } + FResponseID := WSocket_ntohs(Ans^.ID); + FResponseCode := Flags and $000F; + FResponseOpCode := (Flags shr 11) and $000F; + FResponseAuthoritative := (Flags and $0400) = $0400; + FResponseTruncation := (Flags and $0200) = $0200; + FResponseRecursionAvailable := (Flags and $0080) = $0080; + FResponseQDCount := WSocket_ntohs(Ans^.QDCount); + FResponseANCount := WSocket_ntohs(Ans^.ANCount); + FResponseNSCount := WSocket_ntohs(Ans^.NSCount); + FResponseARCount := WSocket_ntohs(Ans^.ARCount); + + P := @ResponseBuf[SizeOf(TDnsRequestHeader)]; + if FResponseQDCount = 0 then begin + { I don't think we could receive 0 questions } + FQuestionName := ''; + FQuestionType := 0; + FQuestionClass := 0; + end + else begin + { Should never be greater than 1 because we sent only one question } + P := DecodeQuestion(@FResponseBuf, P, + FQuestionName, FQuestionType, FQuestionClass); + end; + if FResponseANCount = 0 then begin + RDataPtr := nil; + RDataLen := 0; + FMXRecordCount := 0; + FARecordCount := 0; + FPTRRecordCount := 0; + end + else begin + FMXRecordCount := 0; + FARecordCount := 0; + FPTRRecordCount := 0; + for I := 0 to FResponseANCount - 1 do begin + P := DecodeAnswer(@FResponseBuf, P, + FAnswerNameArray[I], FAnswerTypeArray[I], + FAnswerClassArray[I], FAnswerTTLArray[I], + RDataPtr, RDataLen); + FAnswerTagArray[I] := -1; + case FAnswerTypeArray[I] of + DnsQueryMX: + begin + if FMXRecordCount <= High(FMXPreferenceArray) then begin + FAnswerTagArray[I] := FMXRecordCount; + DecodeMXData(@FResponseBuf, RDataPtr, + FMXPreferenceArray[FMXRecordCount], + FMXExchangeArray[FMXRecordCount]); + Inc(FMXRecordCount); + end; + end; + DnsQueryA: + begin + if FARecordCount <= High(FAddressArray) then begin + FAnswerTagArray[I] := FARecordCount; + DecodeAData(@FResponseBuf, RDataPtr, + FAddressArray[FARecordCount]); + Inc(FARecordCount); + end; + end; + DnsQueryPTR: + begin + if FPTRRecordCount <= High(FHostnameArray) then begin + FAnswerTagArray[I] := FPTRRecordCount; + DecodePTRData(@FResponseBuf, RDataPtr, + FHostnameArray[FPTRRecordCount]); + Inc(FPTRRecordCount); + end; + end; + { !!KAP!! } + DnsQueryLOC: + begin + { for security reasons, if recompiled with future versions of delphi } + if (RDataLen = 16) and (rdatalen = sizeof(fLOCInfo)) then + Move(rdataptr^, fLOCInfo, 16) + else + FillChar(fLOCInfo, SizeOf(fLOCInfo), 0); + end; + end; + end; + end; + TriggerRequestDone(0); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.ExtractName( + Base : PChar; + From : PChar; + var Name : String) : PChar; +var + N : Integer; + I : Integer; + P : PChar; + NameEnd : String; +begin + P := From; + if P^ = #0 then begin + Name := ''; + Inc(P); + end + else begin + Name := ''; + while TRUE do begin + { Get name part length } + N := Ord(P^); + if (N and $C0) = $C0 then begin + { Message compression } + N := ((N and $3F) shl 8) + Ord(P[1]); + if Length(Name) = 0 then + Self.ExtractName(Base, Base + N, Name) + else begin + Self.ExtractName(Base, Base + N, NameEnd); + Name := Name + NameEnd; + end; + Inc(P, 2); + break; + end; + Inc(P); + if N = 0 then + break; + { Copy name part } + for I := 1 to N do begin + Name := Name + P^; + Inc(P); + end; + if P^ <> #0 then + Name := Name + '.'; + end; + end; + Result := P; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.DecodeQuestion( + Base : PChar; + From : PChar; + var Name : String; + var QType : Integer; + var QClass : Integer) : PChar; +var + P : PChar; +begin + P := ExtractName(Base, From, Name); + QType := WSocket_ntohs(PWORD(P)^); + Inc(P, 2); + QClass := WSocket_ntohs(PWORD(P)^); + Inc(P, 2); + Result := P; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.DecodeAnswer( + Base : PChar; + From : PChar; + var Name : String; + var QType : Integer; + var QClass : Integer; + var TTL : LongInt; + var RDataPtr : Pointer; + var RDataLen : Integer) : PChar; +var + P : PChar; +begin + P := ExtractName(Base, From, Name); + QType := WSocket_ntohs(PWORD(P)^); + Inc(P, 2); + QClass := WSocket_ntohs(PWORD(P)^); + Inc(P, 2); + TTL := WSocket_ntohl(PDWORD(P)^); + Inc(P, 4); + RDataLen := WSocket_ntohs(PWORD(P)^); + Inc(P, 2); + RDataPtr := P; + Result := P + RDataLen; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.DecodeMXData( + Base : PChar; + From : PChar; + var Preference : Integer; + var Exchange : String) : PChar; +begin + Result := From; + Preference := WSocket_ntohs(PWORD(Result)^); + Inc(Result, 2); + Result := ExtractName(Base, Result, Exchange); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.DecodePTRData( + Base : PChar; + From : PChar; + var Hostname : String) : PChar; +begin + Result := ExtractName(Base, From, Hostname); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TDnsQuery.DecodeAData( + Base : PChar; + From : PChar; + var Address : TInAddr) : PChar; +begin + Result := From; + Address.S_addr := PDWORD(Result)^; + Inc(Result, 4); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ + <0><1><129><128><0><1><0><1><0><4><0><5><7>inp + rise<3>com<0><0><15><0><1><192><12><0> + <15><0><1><0><1>QV<0><10><0><10><5>drui + d<192><12><192><12><0><2><0><1><0><1>Qc<0><6><3> + ns1<192><12><192><12><0><2><0><1><0><1>Qc<0> + <20><3>NS1<10>SPRINTLINK + <3>NET<0><192><12><0><2><0><1><0><1>Qc<0> + <6><3>NS2<192>U<192><12><0><2><0><1><0><1>Q + c<0><6><3>NS3<192>U<192>+<0><1><0><1><0> + <1>QV<0><4><143><186><11>F<192>?<0><1><0><1><0> + <1>Qc<0><4><207>iS<30><192>Q<0><1><0><1><0> + <2><144>i<0><4><204>u<214><10><192>q<0><1><0><1><0> + <2><144>i<0><4><199><2><252><10><192><131><0><1><0><1><0> + <2><142><182><0><4><204>a<212><10> +} +{ + <0><3><129><128><0><1><0><1><0><2><0><3><4>rtf + m<2>be<0><0><15><0><1><192><12><0><15><0><1><0> + <1>.b<0><9><0><10><4>mail<192><12><192><12> + <0><2><0><1><0><1>.b<0><11><2>ns<3>dn + s<2>be<0><192><12><0><2><0><1><0><1>.b<0> + <5><2>ns<192><12><192>'<0><1><0><1><0><1>.b + <0><4><195><0>d<253><192>:<0><1><0><1><0><1>QY + <0><4><134>:J!<192>Q<0><1><0><1><0><1>.b + <0><4><195><0>d<253> +} +{ + <0><7><133><128><0><1><0><1><0><2><0><2><3>www + <4>rtfm<2>be<0><0><1><0><1><192><12><0> + <1><0><1><0><1>Q<128><0><4><195><0>d<253><4>rt + fm<2>be<0><0><2><0><1><0><1>Q<128><0><5> + <2>ns<192>-<192>-<0><2><0><1><0><1>Q<128><0> + <9><2>ns<3>dns<192>2<192>@<0><1><0><1> + <0><1>Q<128><0><4><195><0>d<253><192>Q<0><1><0><1> + <0><0><26><132><0><4><134>:J! +} +(* +<0><1><129><128><0><1><0><1><0><5><0><5><9>fu-berlin +<2>de<0><0> + +<29><0><1><192><12><0><29><0><1><0><0>, + +<0><16><0><21><22><19><139>Av<167><130><218>L<242> +<0><152><156>\<192><12><0><2><0><1><0><0><12><176> +<0>"<4>arbi<10>informatik<13>uni-oldenburg<2>de<0> +<192><12><0><2><0><1><0><0><12><176><0><12><5>deneb<3> +dfn<192>d<192><12><0><2><0><1><0><0><12><176><0><6><3> +ns3<192><12><192><12><0><2><0><1><0><0><12><176><0><6> +<3>ns2<192><12><192><12><0><2><0><1><0><0><12><176><0> +<6><3>ns1<192><12><192>F<0><1><0><1><0><0>t<169><0><4> +<134>j<1><7><192>t<0><1><0><1><0><0>9<209><0><4><192>L +<176><9><192><140><0><1><0><1><0><0>T<19><0><4><130> +<133><1>9<192><158><0><1><0><1><0><0><28><206><0><4> +<160>-<10><12><192><176><0><1><0><1><0><0>1<198><0> +<4><160>-<8><8> +*) + +{ !!KAP!! } +{raw translation of some perl-source LOC.pm from package Net::DNS::RR::LOC; + +fu-berlin.de LOC 52 27 19.591 N 13 17 40.978 E 15.00m 1000.00m 10000.00m 10.00m +} +const conv_sec = 1000.0; + conv_min = 60.0 * conv_sec; + conv_deg = 60.0 * conv_min; + zh31 = 1 shl 31; + +procedure SubLOCgeo(longlat : longint; + hemis : String; + var ldeg, lmin, lsec, lmsec : Extended; + var hemic : char); +var + Labs : Extended; +begin + LongLat := WSocket_ntohl(LongLat); + Labs := Abs(1.0 * LongLat - zh31); + Ldeg := Trunc(labs / conv_deg); + Labs := Labs - ldeg * conv_deg; + Lmin := Trunc(labs / conv_min); + Labs := Labs - lmin * conv_min; + Lsec := Trunc(labs / conv_sec); + Labs := Labs - lsec * conv_sec; + Lmsec := Labs; + Hemic := Copy(Hemis, 1 + ord(LongLat <= zh31), 1)[1]; { yeah. } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function LongLatToDMS(longlat : longint; hemis : string):string; +Var ldeg, lmin, lsec, lmsec : extended; + hemi : char; +begin + SubLOCgeo(longlat,hemis,ldeg,lmin,lsec,lmsec,hemi); + result := Format('%d %02d %02d.%03d', + [round(ldeg), round(lmin), round(lsec), + round(lmsec)]) + ' ' + hemi; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ in cm!! } +function LocAltToAlt(Localt : LongInt) : LongInt; +begin + Result := Round((WSocket_ntohl(localt) - 100000.0 * 100.0) / 100.0); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ !!KAP!! } +function Loc2Geo(loc : TLOCInfo):TLogGeo; + { dolle umwandlung } + procedure du(longlat : Integer; + hemis : String; + var ideg, imin, isec, imsec : Integer; + var hemic : Char); + var + ldeg, lmin, lsec, lmsec : extended; + begin + SubLOCgeo(longlat, hemis, ldeg, lmin, lsec, lmsec, hemic); + ideg := Round(ldeg); + imin := Round(lmin); + isec := Round(lsec); + imsec := Round(lmsec); + end; + +begin + Result.version := Loc.version; + Result.longsize := Round(Exp(Ln(10)*(loc.size and $f))); + Result.latsize := Round(Exp(Ln(10)*(loc.size shr 4))); + + Result.horizpre := Loc.horizpre; + Result.vertpre := Loc.vertpre; + + du(loc.latitude, 'NS', result.lad, result.lam, + result.las, result.lams, result.lahem); + du(loc.longitude, 'EW', result.lod, result.lom, + result.los, result.loms, result.lohem); + + Result.altitude := LocAltToAlt(loc.altitude); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. diff --git a/ICS_zlog/Delphi/Vc32/EmulVT.dcu b/ICS_zlog/Delphi/Vc32/EmulVT.dcu new file mode 100644 index 0000000000000000000000000000000000000000..a12781a8b0bd3129820b0b313410a92e10cd8dbe GIT binary patch literal 101193 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 Z4IS|q`5dv$iskx@qJVPp> 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 literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/EmulVT.pas b/ICS_zlog/Delphi/Vc32/EmulVT.pas new file mode 100644 index 00000000..a0cf732c --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/EmulVT.pas @@ -0,0 +1,4006 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Program: EMULVT.PAS +Description: Delphi component which does Ansi terminal emulation + Not every escape sequence is implemented, but a large subset. +Author: François PIETTE +Creation: May, 1996 +Version: 2.19 +EMail: http://www.overbyte.be francois.piette@overbyte.be + http://www.rtfm.be/fpiette francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 1997-2001 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: +Jul 22, 1997 Some optimization + Adapted to Delphi 3 +Sep 05, 1997 Version 2.01 +Dec 16, 1997 V2.02 Corrected a bug int the paint routine which caused GDI + resource leak when color was used. +Feb 24, 1998 V2.03 Added AddFKey function +Jul 15, 1998 V2.04 Adapted to Delphi 4 (moved DoKeyBuffer to protected section) +Dec 04, 1998 V2.05 Added 'single char paint' and 'char zoom' features. +Dec 09, 1998 V2.10 Added graphic char drawing using graphic primitives + Added (with permission) scroll back code developed by Steve + Endicott +Dec 21, 1998 V2.11 Corrected some screen update problems related to scrollback. + Added fixes from Steve Endicott. + Beautified code. +Mar 14, 1999 V2.12 Added OnKeyDown event. + Corrected a missing band at right of screen when painting. +Aug 15, 1999 V2.13 Moved KeyPress procedure to public section for BCB4 compat. +Aug 20, 1999 V2.14 Added compile time options. Revised for BCB4. +Nov 12, 1999 V2.15 Corrected display attribute error in delete line. + Checked for range in SetLines/GetLine +Aug 09, 2000 V2.16 Wilfried Mestdagh" and + Steve Endicott corrected a + bug related to scroll back buffer. See WM + SE 09/08/00 + tags in code. +Jul 28, 2001 V2.17 Made FCharPos and FLinePos member variables instead of + global to avoid conflict when sevaral components are used + simultaneously. Suggested by Jeroen Cranendonk + +Jan 03, 2002 V2.19 Don't adjust scroll bar if not visible + Make properties with TopMargin, LeftMargin, RightMargin, + BottomMargin. +Jan 10, 2002 V2.19 Fixed SetLineHeight to fill FLinePos up to last item. + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit EmulVT; + +{$B-} { Enable partial boolean evaluation } +{$T-} { Untyped pointers } +{$X+} { Enable extended syntax } +{$IFNDEF VER80} { Not for Delphi 1 } + {$H+} { Use long strings } + {$J+} { Allow typed constant to be modified } +{$ENDIF} +{$IFDEF VER110} { C++ Builder V3.0 } + {$ObjExportAll On} +{$ENDIF} +{$IFDEF VER125} { C++ Builder V4.0 } + {$ObjExportAll On} +{$ENDIF} + +interface + +{$DEFINE SINGLE_CHAR_PAINT} +{$DEFINE CHAR_ZOOM} + +uses + SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, + Forms, Dialogs, StdCtrls, ClipBrd; + +const + EmulVTVersion = 219; + CopyRight : String = ' TEmulVT (c) 1996-2002 F. Piette V2.19 '; + MAX_ROW = 50; + MAX_COL = 160; + NumPaletteEntries = 16; + +type + TBackColors = (vtsBlack, vtsRed, vtsGreen, vtsYellow, + vtsBlue, vtsMagenta, vtsCyan, vtsWhite); + + TScreenOption = (vtoBackColor, vtoCopyBackOnClear); + TScreenOptions = set of TScreenOption; + TXlatTable = array [0..255] of char; + PXlatTable = ^TXlatTable; + TFuncKeyValue = String[50]; + PFuncKeyValue = ^TFuncKeyValue; + TFuncKey = record + ScanCode : Char; + Shift : TShiftState; + Ext : Boolean; + Value : TFuncKeyValue; + end; + TFuncKeysTable = array [0..63] of TFuncKey; + PFuncKeysTable = ^TFuncKeysTable; + TKeyBufferEvent = procedure (Sender : TObject; Buffer : PChar; Len : Integer) of object; + TKeyDownEvent = procedure (Sender : TObject; + var VirtKey : Integer; + var Shift : TShiftState; + var ShiftLock : Boolean; + var ScanCode : Char; + var Ext : Boolean) of object; + + +type + { TLine is an object used to hold one line of text on screen } + TLine = class(TObject) + public + Txt : array [0..MAX_COL] of Char; + Att : array [0..MAX_COL] of Byte; + constructor Create; + procedure Clear(Attr : Byte); + end; + TLineArray = array [0..16382] of TLine; + PLineArray = ^TLineArray; + + { TScreen is an object to hold an entire screen of line and handle } + { Ansi escape sequences to update this virtual screen } + TScreen = class(TObject) + public + FLines : PLineArray; + FRow : Integer; + FCol : Integer; + FRowSaved : Integer; + FColSaved : Integer; + FScrollRowTop : Integer; + FScrollRowBottom : Integer; + FAttribute : Byte; + FForceHighBit : Boolean; + FReverseVideo : Boolean; + FUnderLine : Boolean; + FRowCount : Integer; + FColCount : Integer; + FBackRowCount : Integer; + FBackEndRow : Integer; + FBackColor : TBackColors; + FOptions : TScreenOptions; + FEscBuffer : String[80]; + FEscFlag : Boolean; + Focused : Boolean; + FAutoLF : Boolean; + FAutoCR : Boolean; + FAutoWrap : Boolean; + FCursorOff : Boolean; + FCKeyMode : Boolean; + FNoXlat : Boolean; + FNoXlatInitial : Boolean; + FCntLiteral : Integer; + FCarbonMode : Boolean; + FXlatInputTable : PXlatTable; + FXlatOutputTable : PXlatTable; + FCharSetG0 : Char; + FCharSetG1 : Char; + FCharSetG2 : Char; + FCharSetG3 : Char; + FAllInvalid : Boolean; + FInvRect : TRect; + FOnCursorVisible : TNotifyEvent; + constructor Create; + destructor Destroy; override; + procedure AdjustFLines(NewCount : Integer); + procedure CopyScreenToBack; + procedure SetRowCount(NewCount : Integer); + procedure SetBackRowCount(NewCount : Integer); + procedure InvRect(nRow, nCol : Integer); + procedure InvClear; + procedure SetLines(I : Integer; Value : TLine); + function GetLines(I : Integer) : TLine; + procedure WriteChar(Ch : Char); + procedure WriteStr(Str : String); + function ReadStr : String; + procedure GotoXY(X, Y : Integer); + procedure WriteLiteralChar(Ch : Char); + procedure ProcessEscape(EscCmd : Char); + procedure SetAttr(Att : Char); + procedure CursorRight; + procedure CursorLeft; + procedure CursorDown; + procedure CursorUp; + procedure CarriageReturn; + procedure ScrollUp; + procedure ScrollDown; + procedure ClearScreen; + procedure BackSpace; + procedure Eol; + procedure Eop; + procedure ProcessESC_D; { Index } + procedure ProcessESC_M; { Reverse index } + procedure ProcessESC_E; { Next line } + procedure ProcessCSI_u; { Restore Cursor } + procedure ProcessCSI_I; { Select IBM char set } + procedure ProcessCSI_J; { Clear the screen } + procedure ProcessCSI_K; { Erase to End of Line } + procedure ProcessCSI_L; { Insert Line } + procedure ProcessCSI_M; { Delete Line } + procedure ProcessCSI_m_lc; { Select Attributes } + procedure ProcessCSI_n_lc; { Cursor position report } + procedure ProcessCSI_at; { Insert character } + procedure ProcessCSI_r_lc; { Scrolling margins } + procedure ProcessCSI_s_lc; { Save cursor location } + procedure ProcessCSI_u_lc; { Restore cursor location } + procedure ProcessCSI_7; { Save cursor location } + procedure ProcessCSI_8; { Restore cursor location } + procedure ProcessCSI_H; { Set Cursor Position } + procedure ProcessCSI_h_lc; { Terminal mode set } + procedure ProcessCSI_l_lc; { Terminal mode reset } + procedure ProcessCSI_A; { Cursor Up } + procedure ProcessCSI_B; { Cursor Down } + procedure ProcessCSI_C; { Cursor Right } + procedure ProcessCSI_D; { Cursor Left } + procedure ProcessCSI_P; { Delete Character } + procedure ProcessCSI_S; { Scroll up } + procedure ProcessCSI_T; { Scroll down } + procedure process_charset_G0(EscCmd : Char);{ G0 character set } + procedure process_charset_G1(EscCmd : Char);{ G1 character set } + procedure process_charset_G2(EscCmd : Char);{ G2 character set } + procedure process_charset_G3(EscCmd : Char);{ G3 character set } + procedure UnimplementedEscape(EscCmd : Char); + procedure InvalidEscape(EscCmd : Char); + function GetEscapeParam(From : Integer; var Value : Integer) : Integer; + property OnCursorVisible : TNotifyEvent read FonCursorVisible + write FOnCursorVisible; + property Lines[I : Integer] : TLine read GetLines write SetLines; + end; + + { TCustomEmulVT is an visual component wich does the actual display } + { of a TScreen object wich is the virtual screen } + { No property is published. See TEmulVT class } + TCustomEmulVT = class(TCustomControl) + private + FCharPos : array [0..MAX_COL + 1] of integer; + FLinePos : array [0..MAX_ROW + 1] of integer; + FFileHandle : TextFile; + FCursorVisible : Boolean; + FCaretShown : Boolean; + FCaretCreated : Boolean; + FLineHeight : Integer; + FLineZoom : Single; + FCharWidth : Integer; + FCharZoom : Single; + FGraphicDraw : Boolean; + FInternalLeading : Integer; + FBorderStyle : TBorderStyle; + FBorderWidth : Integer; + FAutoRepaint : Boolean; + FFont : TFont; + FVScrollBar : TScrollBar; + FTopLine : Integer; + FLocalEcho : Boolean; + FOnKeyBuffer : TKeyBufferEvent; + FOnKeyDown : TKeyDownEvent; + FFKeys : Integer; + FMonoChrome : Boolean; + FLog : Boolean; + FAppOnMessage : TMessageEvent; + FFlagCirconflexe : Boolean; + FFlagTrema : Boolean; + FSelectRect : TRect; + FTopMargin : Integer; + FLeftMargin : Integer; + FRightMargin : Integer; + FBottomMargin : Integer; + FPal : HPalette; + FPaletteEntries : array[0..NumPaletteEntries - 1] of TPaletteEntry; + FMarginColor : Integer; + procedure WMPaint(var Message: TWMPaint); message WM_PAINT; + procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS; + procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS; + procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN; + procedure WMPaletteChanged(var Message : TMessage); message WM_PALETTECHANGED; + procedure VScrollBarScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer); + procedure SetCaret; + procedure AdjustScrollBar; + function ProcessFKeys(ScanCode: Char; Shift: TShiftState; Ext: Boolean) : Boolean; + function FindFKeys(ScanCode: Char; Shift: TShiftState; + Ext: Boolean) : PFuncKeyValue; + procedure CursorVisibleEvent(Sender : TObject); + procedure SetFont(Value : TFont); + procedure SetAutoLF(Value : Boolean); + procedure SetAutoCR(Value : Boolean); + procedure SetXlat(Value : Boolean); + procedure SetLog(Value : Boolean); + procedure SetRows(Value : Integer); + procedure SetCols(Value : Integer); + procedure SetBackRows(Value : Integer); + procedure SetTopLine(Value : Integer); + procedure SetBackColor(Value : TBackColors); + procedure SetOptions(Value : TScreenOptions); + procedure SetLineHeight(Value : Integer); + function GetAutoLF : Boolean; + function GetAutoCR : Boolean; + function GetXlat : Boolean; + function GetRows : Integer; + function GetCols : Integer; + function GetBackRows : Integer; + function GetBackColor : TBackColors; + function GetOptions : TScreenOptions; + procedure SetMarginColor(const Value: Integer); + procedure SetLeftMargin(const Value: Integer); + procedure SetBottomMargin(const Value: Integer); + procedure SetRightMargin(const Value: Integer); + procedure SetTopMargin(const Value: Integer); + protected + FScreen : TScreen; + procedure AppMessageHandler(var Msg: TMsg; var Handled: Boolean); + procedure DoKeyBuffer(Buffer : PChar; Len : Integer); virtual; + procedure PaintGraphicChar(DC : HDC; + X, Y : Integer; + rc : PRect; + ch : Char); + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure ShowCursor; + procedure SetCursor(Row, Col : Integer); + procedure WriteChar(Ch : Char); + procedure WriteStr(Str : String); + procedure WriteBuffer(Buffer : Pointer; Len : Integer); + function ReadStr : String; + procedure CopyHostScreen; + procedure Clear; + procedure UpdateScreen; + function SnapPixelToRow(Y : Integer) : Integer; + function SnapPixelToCol(X : Integer) : Integer; + function PixelToRow(Y : Integer) : Integer; + function PixelToCol(X : Integer) : Integer; + procedure MouseToCell(X, Y: Integer; var ACol, ARow: Longint); + procedure SetLineZoom(newValue : Single); + procedure SetCharWidth(newValue : Integer); + procedure SetCharZoom(newValue : Single); + procedure KeyPress(var Key: Char); override; + property LineZoom : Single read FLineZoom write SetLineZoom; + property CharWidth : Integer read FCharWidth write SetCharWidth; + property CharZoom : Single read FCharZoom write SetCharZoom; + property GraphicDraw : Boolean read FGraphicDraw write FGraphicDraw; + property TopLine : Integer read FTopLine write SetTopLine; + property VScrollBar : TScrollBar read FVScrollBar; + property TopMargin : Integer read FTopMargin write SetTopMargin; + property LeftMargin : Integer read FLeftMargin write SetLeftMargin; + property RightMargin : Integer read FRightMargin write SetRightMargin; + property BottomMargin : Integer read FBottomMargin write SetBottomMargin; + property MarginColor : Integer read FMarginColor write SetMarginColor; + private + procedure PaintOneLine(DC: HDC; Y, Y1 : Integer; const Line : TLine; + nColFrom : Integer; nColTo : Integer; Blank : Boolean); + procedure SetupFont; + property Text : String read ReadStr write WriteStr; + property OnMouseMove; + property OnMouseDown; + property OnMouseUp; + property OnClick; + property OnKeyPress; + property OnKeyBuffer : TKeyBufferEvent read FOnKeyBuffer write FOnKeyBuffer; + property OnKeyDown : TKeyDownEvent read FOnKeyDown write FOnKeyDown; + property Ctl3D; + property Align; + property TabStop; + property TabOrder; + property BorderStyle: TBorderStyle read FBorderStyle write FBorderStyle; + property AutoRepaint : Boolean read FAutoRepaint write FAutoRepaint; + property Font : TFont read FFont write SetFont; + property LocalEcho : Boolean read FLocalEcho write FLocalEcho; + property AutoLF : Boolean read GetAutoLF write SetAutoLF; + property AutoCR : Boolean read GetAutoCR write SetAutoCR; + property Xlat : Boolean read GetXlat write SetXlat; + property MonoChrome : Boolean read FMonoChrome write FMonoChrome; + property Log : Boolean read FLog write SetLog; + property Rows : Integer read GetRows write SetRows; + property Cols : Integer read GetCols write SetCols; + property LineHeight : Integer read FLineHeight write SetLineHeight; + property FKeys : Integer read FFKeys write FFKeys; + property SelectRect : TRect read FSelectRect write FSelectRect; + property BackRows : Integer read GetBackRows write SetBackRows; + property BackColor : TBackColors read GetBackColor write SetBackColor; + property Options : TScreenOptions read GetOptions write SetOptions; + end; + + { Same as TCustomEmulVT, but with published properties } + TEmulVT = class(TCustomEmulVT) + public + property Screen : TScreen read FScreen; + property SelectRect; + property Text; + published + property OnMouseMove; + property OnMouseDown; + property OnMouseUp; + property OnClick; + property OnKeyPress; + property OnKeyDown; + property OnKeyBuffer; + property Ctl3D; + property Align; + property BorderStyle; + property AutoRepaint; + property Font; + property LocalEcho; + property AutoLF; + property AutoCR; + property Xlat; + property MonoChrome; + property Log; + property Rows; + property Cols; + property BackRows; + property BackColor; + property Options; + property LineHeight; + property CharWidth; + property TabStop; + property TabOrder; + property FKeys; + property TopMargin; + property LeftMargin; + property RightMargin; + property BottomMargin; + property MarginColor; + end; + +const + F_BLACK = $00; + F_BLUE = $01; + F_GREEN = $02; + F_CYAN = $03; + F_RED = $04; + F_MAGENTA = $05; + F_BROWN = $06; + F_WHITE = $07; + + B_BLACK = $00; + B_BLUE = $01; + B_GREEN = $02; + B_CYAN = $03; + B_RED = $04; + B_MAGENTA = $05; + B_BROWN = $06; + B_WHITE = $07; + + F_INTENSE = $08; + B_BLINK = $80; + + { Function keys (SCO Console) } + FKeys1 : TFuncKeysTable = ( + (ScanCode: #$48; Shift: []; Ext: TRUE ; Value: #$1B + '[A'), { UP } + (ScanCode: #$50; Shift: []; Ext: TRUE ; Value: #$1B + '[B'), { DOWN } + (ScanCode: #$4D; Shift: []; Ext: TRUE ; Value: #$1B + '[C'), { RIGHT } + (ScanCode: #$4B; Shift: []; Ext: TRUE ; Value: #$1B + '[D'), { LEFT } + (ScanCode: #$49; Shift: []; Ext: TRUE ; Value: #$1B + '[I'), { PREV } + (ScanCode: #$51; Shift: []; Ext: TRUE ; Value: #$1B + '[G'), { NEXT } + (ScanCode: #$47; Shift: []; Ext: TRUE ; Value: #$1B + '[H'), { HOME } + (ScanCode: #$4F; Shift: []; Ext: TRUE ; Value: #$1B + '[F'), { END } + (ScanCode: #$52; Shift: []; Ext: TRUE ; Value: #$1B + '[L'), { INS } + (ScanCode: #$0F; Shift: []; Ext: FALSE; Value: #$1B + '[Z'), { RTAB } + (ScanCode: #$53; Shift: []; Ext: TRUE ; Value: #$7F ), { DEL } + (ScanCode: #$3B; Shift: []; Ext: FALSE; Value: #$1B + '[M'), { F1 } + (ScanCode: #$3C; Shift: []; Ext: FALSE; Value: #$1B + '[N'), + (ScanCode: #$3D; Shift: []; Ext: FALSE; Value: #$1B + '[O'), + (ScanCode: #$3E; Shift: []; Ext: FALSE; Value: #$1B + '[P'), + (ScanCode: #$3F; Shift: []; Ext: FALSE; Value: #$1B + '[Q'), + (ScanCode: #$40; Shift: []; Ext: FALSE; Value: #$1B + '[R'), + (ScanCode: #$41; Shift: []; Ext: FALSE; Value: #$1B + '[S'), + (ScanCode: #$42; Shift: []; Ext: FALSE; Value: #$1B + '[T'), + (ScanCode: #$43; Shift: []; Ext: FALSE; Value: #$1B + '[U'), + (ScanCode: #$44; Shift: []; Ext: FALSE; Value: #$1B + '[V'), { F10 } + (ScanCode: #$85; Shift: []; Ext: FALSE; Value: #$1B + '[W'), { F11 } + (ScanCode: #$86; Shift: []; Ext: FALSE; Value: #$1B + '[X'), { F12 } + (ScanCode: #$3B; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[V'),{ SF1 should be 'Y' } + (ScanCode: #$3C; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[Z'), + (ScanCode: #$3D; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[a'), + (ScanCode: #$3E; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[b'), + (ScanCode: #$3F; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[c'), + (ScanCode: #$40; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[d'), + (ScanCode: #$41; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[e'), + (ScanCode: #$42; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[f'), + (ScanCode: #$43; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[g'), + (ScanCode: #$44; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[h'), + (ScanCode: #$85; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[i'), + (ScanCode: #$86; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[j'),{ SF10 } + (ScanCode: #$3B; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[k'), { CF1 } + (ScanCode: #$3C; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[l'), + (ScanCode: #$3D; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[m'), + (ScanCode: #$3E; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[n'), + (ScanCode: #$3F; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[o'), + (ScanCode: #$40; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[p'), + (ScanCode: #$41; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[q'), + (ScanCode: #$42; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[r'), + (ScanCode: #$43; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[s'), + (ScanCode: #$44; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[t'), + (ScanCode: #$85; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[u'), + (ScanCode: #$86; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[v'), { CF12 } + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ) + ); + +{ Alternate function keys (ordinary VT keys) } + FKeys2 : TFuncKeysTable = ( + (ScanCode: #$48; Shift: []; Ext: TRUE ; Value: #$1B + '[A'), { UP } + (ScanCode: #$50; Shift: []; Ext: TRUE ; Value: #$1B + '[B'), { DOWN } + (ScanCode: #$4D; Shift: []; Ext: TRUE ; Value: #$1B + '[C'), { RIGHT } + (ScanCode: #$4B; Shift: []; Ext: TRUE ; Value: #$1B + '[D'), { LEFT } + (ScanCode: #$49; Shift: []; Ext: TRUE ; Value: #$1B + '[5~'), { PREV } + (ScanCode: #$51; Shift: []; Ext: TRUE ; Value: #$1B + '[6~'), { NEXT } + (ScanCode: #$52; Shift: []; Ext: TRUE ; Value: #$1B + '[2~'), { INSERT } + (ScanCode: #$53; Shift: []; Ext: TRUE ; Value: #$7F ), { DELETE } + (ScanCode: #$3B; Shift: []; Ext: FALSE; Value: #$1B + 'OP'), { F1->PF1 } + (ScanCode: #$3C; Shift: []; Ext: FALSE; Value: #$1B + 'OQ'), { F2->PF2 } + (ScanCode: #$3D; Shift: []; Ext: FALSE; Value: #$1B + 'OR'), { F3->PF3 } + (ScanCode: #$3E; Shift: []; Ext: FALSE; Value: #$1B + 'OS'), { F4->PF4 } + (ScanCode: #$57; Shift: []; Ext: FALSE; Value: #$1B + '[28~'), { F11->Aide } + (ScanCode: #$58; Shift: []; Ext: FALSE; Value: #$1B + '[29~'), { F12->Exécuter } + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ) + ); + +{ A-Series Telnet function keys (ordinary VT100 keys + specials) } + FKeys3 : TFuncKeysTable = ( + (ScanCode: #$48; Shift: []; Ext: TRUE ; Value: #$1B + '[A'), { UP } + (ScanCode: #$50; Shift: []; Ext: TRUE ; Value: #$1B + '[B'), { DOWN } + (ScanCode: #$4D; Shift: []; Ext: TRUE ; Value: #$1B + '[C'), { RIGHT } + (ScanCode: #$4B; Shift: []; Ext: TRUE ; Value: #$1B + '[D'), { LEFT } + (ScanCode: #$49; Shift: []; Ext: TRUE ; Value: #$1B + '-'), { PREV } + (ScanCode: #$51; Shift: []; Ext: TRUE ; Value: #$1B + '+'), { NEXT } + (ScanCode: #$47; Shift: []; Ext: TRUE ; Value: #$1B + 'H'), { HOME } + (ScanCode: #$47; Shift: [ssCtrl]; Ext: TRUE ; Value: #$1B + 'C'),{ HOME } + (ScanCode: #$4F; Shift: []; Ext: TRUE ; Value: #$1B + 'R'), { END } + (ScanCode: #$52; Shift: []; Ext: TRUE ; Value: #$1B + 'I'), { INSERT } + (ScanCode: #$53; Shift: []; Ext: TRUE ; Value: #$7F ), { DELETE } + (ScanCode: #$3B; Shift: []; Ext: FALSE; Value: #$1B + 'OP'), { F1->PF1 } + (ScanCode: #$3C; Shift: []; Ext: FALSE; Value: #$1B + 'OQ'), { F2->PF2 } + (ScanCode: #$3D; Shift: []; Ext: FALSE; Value: #$1B + 'OR'), { F3->PF3 } + (ScanCode: #$3E; Shift: []; Ext: FALSE; Value: #$1B + 'OS'), { F4->PF4 } + (ScanCode: #$43; Shift: []; Ext: FALSE; Value: #$1B + 'OP'), { F9 } + (ScanCode: #$44; Shift: []; Ext: FALSE; Value: ''), { F10 } + (ScanCode: #$57; Shift: []; Ext: FALSE; Value: #$1B + 'OQ'), { F11 } + (ScanCode: #$58; Shift: []; Ext: FALSE; Value: #$1B + 'OS'), { F12 } + (ScanCode: #$0F; Shift: []; Ext: FALSE; Value: #$1B + 'Z'), { RTAB } + (ScanCode: #$40; Shift: []; Ext: FALSE; Value: #$1B + 'K'), { F6 } + (ScanCode: #$53; Shift: [ssCtrl]; Ext: TRUE ; Value: #$1B + 'D'), { CDEL } + (ScanCode: #$52; Shift: [ssCtrl]; Ext: TRUE ; Value: #$1B + 'L'), { CINS } + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ), + (ScanCode: #$00; Shift: []; Ext: FALSE; Value: '' ) + ); + + { Ethernet to screen } + ibm_iso8859_1_G0 : TXlatTable = ( + #$00, #$01, #$02, #$03, #$04, #$05, #$06, #$07, { 00 - 07 } + #$08, #$09, #$0A, #$0B, #$0C, #$0D, #$0E, #$0F, { 08 - 0F } + #$10, #$11, #$12, #$13, #$14, #$15, #$16, #$17, { 10 - 17 } + #$18, #$19, #$1A, #$1B, #$1C, #$1D, #$1E, #$1F, { 18 - 1F } + #$20, #$21, #$22, #$23, #$24, #$25, #$26, #$27, { 20 - 27 } + #$28, #$29, #$2A, #$2B, #$2C, #$2D, #$2E, #$2F, { 28 - 2F } + #$30, #$31, #$32, #$33, #$34, #$35, #$36, #$37, { 30 - 37 } + #$38, #$39, #$3A, #$3B, #$3C, #$3D, #$3E, #$3F, { 38 - 3F } + #$40, #$41, #$42, #$43, #$44, #$45, #$46, #$47, { 40 - 47 } + #$48, #$49, #$4A, #$4B, #$4C, #$4D, #$4E, #$4F, { 48 - 4F } + #$50, #$51, #$52, #$53, #$54, #$55, #$56, #$57, { 50 - 57 } + #$58, #$59, #$5A, #$5B, #$5C, #$5D, #$5E, #$5F, { 58 - 5F } + #$60, #$61, #$62, #$63, #$64, #$65, #$66, #$67, { 60 - 67 } + #$68, #$69, #$6A, #$6B, #$6C, #$6D, #$6E, #$6F, { 68 - 6F } + #$70, #$71, #$72, #$73, #$74, #$75, #$76, #$77, { 70 - 77 } + #$78, #$79, #$7A, #$7B, #$7C, #$7D, #$7E, #$7F, { 78 - 7F } + #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20, { 80 - 87 } + #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20, { 88 - 8F } + #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20, { 90 - 97 } + #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20, { 98 - 9F } + #$B1, #$AD, #$9B, #$9C, #$0F, #$9D, #$B3, #$15, { A0 - A7 } + #$20, #$43, #$A6, #$AE, #$AA, #$C4, #$52, #$C4, { A8 - AF } + #$F8, #$F1, #$FD, #$20, #$27, #$E6, #$14, #$FA, { B0 - B7 } + #$2C, #$20, #$A7, #$AF, #$AC, #$AB, #$20, #$A8, { B8 - BF } + #$41, #$41, #$41, #$41, #$8E, #$8F, #$92, #$80, { C0 - C7 } + #$45, #$45, #$45, #$45, #$45, #$49, #$49, #$49, { C8 - CF } + #$44, #$A5, #$4F, #$4F, #$4F, #$4F, #$4F, #$78, { D0 - D7 } + #$ED, #$55, #$55, #$55, #$55, #$59, #$70, #$E1, { D8 - DF } + #$85, #$A0, #$83, #$61, #$84, #$86, #$91, #$87, { E0 - E7 } + #$8A, #$82, #$88, #$89, #$8D, #$A1, #$8C, #$49, { E8 - EF } + #$64, #$A4, #$95, #$A2, #$93, #$6F, #$94, #$F6, { F0 - F7 } + #$ED, #$97, #$A3, #$96, #$9A, #$79, #$70, #$98); { F8 - FF } + +{ Ethernet to screen } + ibm_iso8859_1_G1 : TXlatTable = ( + #$00, #$01, #$02, #$03, #$04, #$05, #$06, #$07, { 00 - 07 } + #$08, #$09, #$0A, #$0B, #$0C, #$0D, #$0E, #$0F, { 08 - 0F } + #$10, #$11, #$12, #$13, #$14, #$15, #$16, #$17, { 10 - 17 } + #$18, #$19, #$1A, #$1B, #$1C, #$1D, #$1E, #$1F, { 18 - 1F } + #$20, #$21, #$22, #$23, #$24, #$25, #$26, #$27, { 20 - 27 } + #$28, #$29, #$2A, #$2B, #$2C, #$2D, #$2E, #$2F, { 28 - 2F } + #$30, #$31, #$32, #$33, #$34, #$35, #$36, #$37, { 30 - 37 } + #$38, #$39, #$3A, #$3B, #$3C, #$3D, #$3E, #$3F, { 38 - 3F } + #$40, #$41, #$42, #$43, #$44, #$45, #$46, #$47, { 40 - 47 } + #$48, #$49, #$4A, #$4B, #$4C, #$4D, #$4E, #$4F, { 48 - 4F } + #$50, #$51, #$52, #$53, #$54, #$55, #$56, #$57, { 50 - 57 } + #$58, #$59, #$5A, #$5B, #$5C, #$5D, #$5E, #$5F, { 58 - 5F } + #$60, #$61, #$62, #$63, #$64, #$65, #$66, #$67, { 60 - 67 } + #$68, #$69, #$D9, #$BF, #$DA, #$C0, #$C5, #$6F, { 68 - 6F } + #$70, #$C4, #$72, #$73, #$C3, #$B4, #$C1, #$C2, { 70 - 77 } + #$B3, #$79, #$7A, #$7B, #$7C, #$7D, #$7E, #$7F, { 78 - 7F } + #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20, { 80 - 87 } + #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20, { 88 - 8F } + #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20, { 90 - 97 } + #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20, { 98 - 9F } + #$B1, #$AD, #$9B, #$9C, #$0F, #$9D, #$B3, #$15, { A0 - A7 } + #$20, #$43, #$A6, #$AE, #$AA, #$C4, #$52, #$C4, { A8 - AF } + #$F8, #$F1, #$FD, #$20, #$27, #$E6, #$14, #$FA, { B0 - B7 } + #$2C, #$20, #$A7, #$AF, #$AC, #$AB, #$20, #$A8, { B8 - BF } + #$41, #$41, #$41, #$41, #$8E, #$8F, #$92, #$80, { C0 - C7 } + #$45, #$45, #$45, #$45, #$45, #$49, #$49, #$49, { C8 - CF } + #$44, #$A5, #$4F, #$4F, #$4F, #$4F, #$4F, #$78, { D0 - D7 } + #$ED, #$55, #$55, #$55, #$55, #$59, #$70, #$E1, { D8 - DF } + #$85, #$A0, #$83, #$61, #$84, #$86, #$91, #$87, { E0 - E7 } + #$8A, #$82, #$88, #$89, #$8D, #$A1, #$8C, #$49, { E8 - EF } + #$64, #$A4, #$95, #$A2, #$93, #$6F, #$94, #$F6, { F0 - F7 } + #$ED, #$97, #$A3, #$96, #$9A, #$79, #$70, #$98); { F8 - FF } + +{ Keyboard to Ethernet } + Output : TXlatTable = ( + #$00, #$01, #$02, #$03, #$04, #$05, #$06, #$07, { 00 - 07 } + #$08, #$09, #$0A, #$0B, #$0C, #$0D, #$0E, #$0F, { 08 - 0F } + #$10, #$11, #$12, #$13, #$14, #$15, #$16, #$17, { 10 - 17 } + #$18, #$19, #$1A, #$1B, #$1C, #$1D, #$1E, #$1F, { 18 - 1F } + #$20, #$21, #$22, #$23, #$24, #$25, #$26, #$27, { 20 - 27 } + #$28, #$29, #$2A, #$2B, #$2C, #$2D, #$2E, #$2F, { 28 - 2F } + #$30, #$31, #$32, #$33, #$34, #$35, #$36, #$37, { 30 - 37 } + #$38, #$39, #$3A, #$3B, #$3C, #$3D, #$3E, #$3F, { 38 - 3F } + #$40, #$41, #$42, #$43, #$44, #$45, #$46, #$47, { 40 - 47 } + #$48, #$49, #$4A, #$4B, #$4C, #$4D, #$4E, #$4F, { 48 - 4F } + #$50, #$51, #$52, #$53, #$54, #$55, #$56, #$57, { 50 - 57 } + #$58, #$59, #$5A, #$5B, #$5C, #$5D, #$5E, #$5F, { 58 - 5F } + #$60, #$61, #$62, #$63, #$64, #$65, #$66, #$67, { 60 - 67 } + #$68, #$69, #$6A, #$6B, #$6C, #$6D, #$6E, #$6F, { 68 - 6F } + #$70, #$71, #$72, #$73, #$74, #$75, #$76, #$77, { 70 - 77 } + #$78, #$79, #$7A, #$7B, #$7C, #$7D, #$7E, #$7F, { 78 - 7F } + #$C7, #$FC, #$E9, #$E2, #$E4, #$E0, #$E5, #$E7, { 80 - 87 } + #$EA, #$EB, #$E8, #$EF, #$EE, #$EC, #$C4, #$C5, { 88 - 8F } + #$C9, #$E6, #$C6, #$F4, #$F6, #$F2, #$FB, #$F9, { 90 - 97 } + #$FF, #$F6, #$FC, #$A2, #$A3, #$A5, #$DE, #$20, { 98 - 9F } + #$E1, #$ED, #$F3, #$FA, #$F1, #$D1, #$AA, #$BA, { A0 - A7 } + #$BF, #$20, #$AC, #$BD, #$BC, #$A1, #$AB, #$BB, { A8 - AF } + #$A0, #$A0, #$A0, #$A6, #$A6, #$A6, #$A6, #$AD, { B0 - B7 } + #$2B, #$A6, #$A6, #$2B, #$2B, #$2B, #$2B, #$2B, { B8 - BF } + #$2B, #$AD, #$AD, #$AD, #$A6, #$AD, #$2B, #$A6, { C0 - C7 } + #$2B, #$2B, #$AD, #$AD, #$A6, #$AD, #$2B, #$AD, { C8 - CF } + #$AD, #$AD, #$AD, #$2B, #$2B, #$2B, #$2B, #$2B, { D0 - D7 } + #$2B, #$2B, #$2B, #$A0, #$A0, #$A0, #$A0, #$A0, { D8 - DF } + #$20, #$20, #$20, #$AD, #$20, #$20, #$B5, #$20, { E0 - E7 } + #$20, #$20, #$20, #$20, #$20, #$F8, #$20, #$20, { E8 - EF } + #$A0, #$B1, #$20, #$20, #$20, #$20, #$F7, #$20, { F0 - F7 } + #$B0, #$B0, #$B0, #$20, #$20, #$B2, #$A0, #$20); { F8 - FF } + +procedure Register; +procedure FKeysToFile(var FKeys : TFuncKeysTable; FName : String); +procedure FileToFKeys(var FKeys : TFuncKeysTable; FName : String); +function AddFKey(var FKeys : TFuncKeysTable; + ScanCode : Char; + Shift : TShiftState; + Ext : Boolean; + Value : TFuncKeyValue) : Boolean; + + + +implementation +{$DEFINE Debug} { Add or remove minus sign before dollar sign to } + { generate code for debug message output } + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure Register; +begin + RegisterComponents('FPiette', [TEmulVT]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function ShiftStateToString(var State : TShiftState) : String; +begin + Result := ''; + if ssShift in State then + Result := Result + 'ssShift '; + if ssAlt in State then + Result := Result + 'ssAlt '; + if ssCtrl in State then + Result := Result + 'ssCtrl '; + if ssLeft in State then + Result := Result + 'ssLeft '; + if ssRight in State then + Result := Result + 'ssRight '; + if ssMiddle in State then + Result := Result + 'ssMiddle '; + if ssDouble in State then + Result := Result + 'ssDouble '; + if Result = '' then + Result := 'ssNormal'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function StringToShiftState(var S : String) : TShiftState; +begin + Result := []; + if Pos('ssShift', S) <> 0 then + Result := Result + [ssShift]; + if Pos('ssAlt', S) <> 0 then + Result := Result + [ssAlt]; + if Pos('ssCtrl', S) <> 0 then + Result := Result + [ssCtrl]; + if Pos('ssLeft', S) <> 0 then + Result := Result + [ssLeft]; + if Pos('ssRight', S) <> 0 then + Result := Result + [ssRight]; + if Pos('ssMiddle', S) <> 0 then + Result := Result + [ssMiddle]; + if Pos('ssDouble', S) <> 0 then + Result := Result + [ssDouble]; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function xdigit(Ch : char) : integer; +begin + if ch in ['0'..'9'] then + Result := Ord(ch) - ord('0') + else if ch in ['A'..'Z'] then + Result := Ord(ch) - Ord('A') + 10 + else if ch in ['a'..'z'] then + Result := Ord(ch) - Ord('a') + 10 + else + Result := 0; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function xdigit2(S : PChar) : integer; +begin + Result := 16 * xdigit(S[0]) + xdigit(S[1]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function FuncKeyValueToString(var S : TFuncKeyValue) : String; +var + I : Integer; +begin + Result := ''; + for I := 1 to Length(S) do begin + if (Ord(S[I]) < 32) or (Ord(S[I]) >= 127) or + (S[I] = '''') or (S[I] = '\') then + Result := Result + '\x' + IntToHex(Ord(S[I]), 2) + else + Result := Result + S[I]; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function StringToFuncKeyValue(var S : String) : TFuncKeyValue; +var + I : Integer; +begin + Result := ''; + I := 1; + while I <= Length(S) do begin + if (S[I] = '\') and + ((I + 3) <= Length(S)) and + (S[I + 1] = 'x') then begin + Result := Result + chr(xdigit2(@S[I + 2])); + I := I + 3; + end + else + Result := Result + S[I]; + Inc(I); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function AddFKey(var FKeys : TFuncKeysTable; + ScanCode : Char; + Shift : TShiftState; + Ext : Boolean; + Value : TFuncKeyValue) : Boolean; +var + I : Integer; +begin + { Search for existing key definition to replace it } + for I := Low(FKeys) to High(FKeys) do begin + if (FKeys[I].ScanCode = ScanCode) and + (FKeys[I].Shift = Shift) and + (FKeys[I].Ext = Ext) then begin + FKeys[I].Value := Value; + Result := TRUE; { Success} + Exit; + end; + end; + + { Key not existing, add in an empty space } + for I := Low(FKeys) to High(FKeys) do begin + if FKeys[I].ScanCode = #0 then begin + FKeys[I].ScanCode := ScanCode; + FKeys[I].Shift := Shift; + FKeys[I].Ext := Ext; + FKeys[I].Value := Value; + Result := TRUE; { Success} + Exit; + end; + end; + + { Failure, no more space available } + Result := FALSE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure FKeysToFile(var FKeys : TFuncKeysTable; FName : String); +var + I : Integer; + F : TextFile; +begin + AssignFile(F, FName); + Rewrite(F); + for I := Low(FKeys) to High(FKeys) do begin + with FKeys[I] do begin + if ScanCode <> chr(0) then + WriteLn(F, IntToHex(Ord(ScanCode), 2), ', ', + ShiftStateToString(Shift), ', ', + Ext, ', ''', + FuncKeyValueToString(Value), ''''); + end; + end; + CloseFile(F); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function GetToken(var S : String; var I : Integer; Delim : Char) : String; +begin + Result := ''; + while (I <= Length(S)) and (S[I] = ' ') do + Inc(I); + while (I <= Length(S)) and (S[I] <> Delim) do begin + Result := Result + S[I]; + Inc(I); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure FileToFKeys(var FKeys : TFuncKeysTable; FName : String); +var + I, J : Integer; + F : TextFile; + S, T : String; + sc : Integer; +begin + AssignFile(F, FName); + {$I-} + Reset(F); + if IOResult <> 0 then begin + { File do not exist, create default one } + FKeysToFile(FKeys, FName); + Exit; + end; + + for I := Low(FKeys) to High(FKeys) do begin + with FKeys[I] do begin + ScanCode := chr(0); + Shift := []; + Ext := FALSE; + Value := ''; + if not Eof(F) then begin + { 71, ssNormal, TRUE, '\x1B[H' } + ReadLn(F, S); + J := 1; + T := GetToken(S, J, ','); + if (Length(T) > 0) and (T[1] <> ';') then begin + sc := xdigit2(@T[1]); + if sc <> 0 then begin + ScanCode := chr(sc); + Inc(J); + T := GetToken(S, J, ','); + Shift := StringToShiftState(T); + Inc(J); + T := GetToken(S, J, ','); + Ext := UpperCase(T) = 'TRUE'; + Inc(J); + T := GetToken(S, J, ''''); + Inc(J); + T := GetToken(S, J, ''''); + Value := StringToFuncKeyValue(T); + end; + end; + end; + end; + end; + CloseFile(F); +{$I+} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure DebugString(Msg : String); +const + Cnt : Integer = 0; +var + Buf : String[20]; +begin +{$IFDEF Debug} + Cnt := Cnt + 1; + Buf := IntToHex(Cnt, 4) + ' ' + #0; + OutputDebugString(@Buf[1]); + +{$IFNDEF WIN32} + if Length(Msg) < High(Msg) then + Msg[Length(Msg) + 1] := #0; +{$ENDIF} + + OutputDebugString(@Msg[1]); +{$ENDIF} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFNDEF WIN32} +procedure SetLength(var S: string; NewLength: Integer); +begin + S[0] := chr(NewLength); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TLine.Create; +begin + inherited Create; + FillChar(Txt, SizeOf(Txt), ' '); + FillChar(Att, SizeOf(Att), Chr(F_WHITE)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TLine.Clear(Attr : Byte); +begin + FillChar(Txt, SizeOF(Txt), ' '); + FillChar(Att, SizeOf(Att), Attr); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TScreen.Create; +begin + inherited Create; + FRowCount := 0; + FBackRowCount := 0; + FBackEndRow := 0; + FBackColor := vtsWhite; + FOptions := [vtoBackColor]; + SetRowCount(25); + FColCount := 80; + FRowSaved := -1; + FColSaved := -1; + FScrollRowTop := 0; + {FScrollRowBottom := FRowCount - 1; // WM + SE 09/08/00 } + FAttribute := F_WHITE; + InvClear; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor TScreen.Destroy; +var + nRow : Integer; +begin + for nRow := 0 to FRowCount + FBackRowCount - 1 do + FLines^[nRow].Free; + FreeMem (FLines, (FRowCount + FBackRowCount) * SizeOf(TObject)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.AdjustFLines(NewCount : Integer); +var + NewLines : PLineArray; + CurrCount : Integer; + nRow : Integer; +begin + CurrCount := FRowCount + FBackRowCount; + if (NewCount <> CurrCount) and (NewCount > 0) then begin + GetMem(NewLines, NewCount * SizeOf(TObject)); + if NewCount > CurrCount then begin + if CurrCount <> 0 then + Move(FLines^, NewLines^, CurrCount * SizeOf(TObject)); + for nRow := CurrCount to NewCount - 1 do + NewLines^[nRow] := TLine.Create; + if CurrCount <> 0 then + FreeMem(FLines, CurrCount * SizeOf(TObject)); + end + else begin + Move (FLines^, NewLines^, NewCount * SizeOf(TObject)); + for nRow := NewCount to CurrCount - 1 do + FLines^[nRow].Free; + FreeMem(FLines, CurrCount * SizeOf(TObject)); + end; + FLines := NewLines; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.SetRowCount(NewCount : Integer); +begin + if NewCount <> FRowCount then begin + AdjustFLines(NewCount + FBackRowCount); + FRowCount := NewCount; + FScrollRowBottom := FRowCount - 1; { WM + SE 09/08/00 } + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.SetBackRowCount(NewCount : Integer); +begin + if NewCount <> FBackRowCount then begin + AdjustFLines(FRowCount + NewCount); + FBackRowCount := NewCount; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.CopyScreenToBack; +{ Copies the current host screen into the scrollback buffer. } +var + Temp : TLine; + Row : Integer; + Pass : Integer; + nCol : Integer; +begin + if FBackRowCount >= FRowCount then begin + Dec (FBackEndRow, FRowCount); + if (0 - FBackEndRow) >= FBackRowCount then + FBackEndRow := 1 - FBackRowCount; + { We have to make FRowCount lines available at the head of the + scrollback buffer. These will come from the end of the scrollback + buffer. We'll make FRowCount passes through the scrollback buffer + moving the available lines up to the top and the existing lines + down a page at a time. + Net result is that we only move each line once. } + For Pass := 0 To FRowCount - 1 Do begin + Row := FBackEndRow + Pass; + Temp := Lines[Row]; + Inc (Row, FRowCount); + While Row < 0 Do begin + Lines[Row - FRowCount] := Lines[Row]; + Inc (Row, FRowCount); + end; + Lines[Row - FRowCount] := Temp; + end; + + { Now, copy the host screen lines to the ones we made available. } + For Row := 0 To FRowCount - 1 Do begin + Move (Lines[Row].Txt, Lines[Row - FRowCount].Txt, FColCount); + Move (Lines[Row].Att, Lines[Row - FRowCount].Att, FColCount); + if vtoBackColor in FOptions then begin + with Lines[Row - FRowCount] do begin + for nCol := 0 to FColCount - 1 do begin + Att[nCol] := Att[nCol] And $8F Or (Ord (FBackColor) shl 4); + end; + end; + end; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ScrollUp; +var + Temp : TLine; + Row : Integer; + nCol : Integer; +begin + if FBackRowCount > 0 then begin + if (0 - FBackEndRow) < (FBackRowCount - 1) then + Dec (FBackEndRow); + Temp := Lines[FBackEndRow]; + For Row := FBackEndRow + 1 To -1 Do begin + Lines[Row - 1] := Lines[Row]; + end; + Lines[-1] := Lines[FScrollRowTop]; + if vtoBackColor in FOptions then begin + with Lines[-1] do begin + for nCol := 0 to FColCount - 1 do begin + Att[nCol] := Att[nCol] And $8F Or (Ord (FBackColor) shl 4); + end; + end; + end; + + end + else + Temp := Lines[FScrollRowTop]; + + for Row := FScrollRowTop + 1 to FScrollRowBottom do + Lines[Row - 1] := Lines[Row]; + Lines[FScrollRowBottom] := Temp; + Temp.Clear(F_WHITE {FAttribute}); + FAllInvalid := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ScrollDown; +var + Temp : TLine; + Row : Integer; +begin + Temp := Lines[FScrollRowBottom]; + for Row := FScrollRowBottom DownTo FScrollRowTop + 1 do + Lines[Row] := Lines[Row - 1]; + Lines[FScrollRowTop] := Temp; + Temp.Clear(F_WHITE {FAttribute}); + FAllInvalid := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.CursorDown; +begin + Inc(FRow); + if FRow > FScrollRowBottom then begin + FRow := FScrollRowBottom; + ScrollUp; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.CursorUp; +begin + Dec(FRow); + if FRow < 0 then begin + Inc(FRow); + ScrollDown; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.CursorRight; +begin + Inc(FCol); + if FCol >= FColCount then begin + FCol := 0; + CursorDown; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.CursorLeft; +begin + Dec(FCol); + if FCol < 0 then begin + FCol := FColCount - 1; + CursorUp; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.CarriageReturn; +begin + FCol := 0; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TScreen.GetEscapeParam(From : Integer; var Value : Integer) : Integer; +begin + while (From <= Length(FEscBuffer)) and (FEscBuffer[From] = ' ') do + From := From + 1; + + Value := 0; + while (From <= Length(FEscBuffer)) and (FEscBuffer[From] in ['0'..'9']) do begin + Value := Value * 10 + Ord(FEscBuffer[From]) - Ord('0'); + From := From + 1; + end; + + Result := From; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.UnimplementedEscape(EscCmd : Char); +{var + Buf : String;} +begin + DebugString('Unimplemented Escape Sequence: ' + FEscBuffer + EscCmd + #13 + #10); +{ Buf := FEscBuffer + EscCmd + #0; + MessageBox(0, @Buf[1], 'Unimplemented Escape Sequence', MB_OK); } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.InvalidEscape(EscCmd : Char); +{var + Buf : String;} +begin + DebugString('Invalid Escape Sequence: ' + FEscBuffer + EscCmd + #13 + #10); +{ Buf := FEscBuffer + EscCmd + #0; + MessageBox(0, @Buf[1], 'Invalid Escape Sequence', MB_OK); } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessESC_D; { Index } +begin + UnimplementedEscape('D'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Move cursor Up, scroll down if necessary } +procedure TScreen.ProcessESC_M; { Reverse index } +begin + Dec(FRow); + if FRow < FScrollRowTop then begin + FRow := FScrollRowTop; + ScrollDown; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessESC_E; { Next line } +begin + UnimplementedEscape('E'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_u; { Restore Cursor } +begin + UnimplementedEscape('u'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ IBM character set operation (not part of the ANSI standard) } +{ [0I => Set IBM character set } +{ [1;nnnI => Literal mode for nnn next characters } +{ [2;onoffI => Switch carbon mode on (1) or off (0) } +{ [3;ch;cl;sh;slI => Receive carbon mode keyboard code } +{ [4I => Select ANSI character set } +procedure TScreen.ProcessCSI_I; +var + From, mode, nnn : Integer; + ch, cl, sh, sl : Integer; +begin + From := GetEscapeParam(2, Mode); + + case Mode of + 0: begin { Select IBM character set } + FNoXlat := TRUE; + end; + 1: begin { Set literal mode for next N characters } + if FEscBuffer[From] = ';' then + GetEscapeParam(From + 1, FCntLiteral) + else + FCntLiteral := 1; + end; + 2: begin { Switch carbon mode on or off } + if FEscBuffer[From] = ';' then + GetEscapeParam(From + 1, nnn) + else + nnn := 0; + FCarbonMode := (nnn <> 0); + end; + 3: begin { Receive carbon mode key code } + ch := 0; cl := 0; sh := 0; sl := 0; + if FEscBuffer[From] = ';' then begin + From := GetEscapeParam(From + 1, cl); + if FEscBuffer[From] = ';' then begin + From := GetEscapeParam(From + 1, ch); + if FEscBuffer[From] = ';' then begin + From := GetEscapeParam(From + 1, sl); + if FEscBuffer[From] = ';' then begin + GetEscapeParam(From + 1, sh); + end; + end; + end; + end; + DebugString('Special key ' + + IntToHex(ch, 2) + IntToHex(cl, 2) + ' ' + + IntToHex(sh, 2) + IntToHex(sl, 2)); + end; + 4: begin { Select ANSI character set } + FNoXlat := FALSE; + end; + else + UnimplementedEscape('I'); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.BackSpace; +begin + if FCol > 0 then + Dec(FCol); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ClearScreen; +var + Row : Integer; +begin + for Row := 0 to FRowCount - 1 do + Lines[Row].Clear(FAttribute); + FRow := 0; + FCol := 0; + FAllInvalid := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.InvClear; +begin + with FInvRect do begin + Top := 9999; + Left := 9999; + Right := -1; + Bottom := -1; + end; + FAllInvalid := FALSE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.InvRect(nRow, nCol : Integer); +begin + if not FAllInvalid then begin + if FInvRect.Top > nRow then + FInvRect.Top := nRow; + if FInvRect.Bottom < nRow then + FInvRect.Bottom := nRow; + if FInvRect.Left > nCol then + FInvRect.Left := nCol; + if FInvRect.Right < nCol then + FInvRect.Right := nCol; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ The FLines array is inverted with the last host line at position 0 and + the first host line as position FRowCount - 1. } +procedure Tscreen.SetLines(I : Integer; Value : TLine); +begin + if I >= FRowCount then + FLines^[0] := Value + else + FLines^[FRowCount - 1 - I] := Value; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TScreen.GetLines(I : Integer) : TLine; +begin + if I >= FRowCount then + Result := FLines^[0] + else + Result := FLines^[FRowCount - 1 - I]; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.Eol; +begin + with Lines[FRow] do begin + FillChar(Txt[FCol], FColCount - FCol, ' '); + FillChar(Att[FCol], (FColCount - FCol) * SizeOf(Att[FCol]), FAttribute); + end; + InvRect(Frow, FCol); + InvRect(Frow, FColCount); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.Eop; +var + NRow : Integer; +begin + Eol; + for NRow := FRow + 1 to FRowCount - 1 do + Lines[NRow].Clear(FAttribute); + if FRow = 0 then + FAllInvalid := TRUE + else begin + InvRect(FRow, 0); + InvRect(FRowCount, FColCount); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_J; { Clear the screen } +var + Mode : Integer; + Row : Integer; +begin + GetEscapeParam(2, Mode); + case Mode of + 0: begin { Cursor to end of screen } + FAttribute := F_WHITE; + Eop; + end; + 1: begin { Start of screen to cursor } + for Row := 0 to FRow do + Lines[Row].Clear(FAttribute); + InvRect(0, 0); + InvRect(FRow, FColCount); + end; + 2: begin { Entire screen } + if vtoCopyBackOnClear in FOptions then CopyScreenToBack; + ClearScreen; + end; + else + InvalidEscape('J'); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_K; { Erase to End of Line } +begin + Eol; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_L; { Insert Line } +var + nLine : Integer; + nRow : Integer; + Temp : TLine; +begin + FCol := 0; + GetEscapeParam(2, nLine); + if nLine = 0 then + nLine := 1; + + if (FRow + nLine) > FScrollRowBottom then begin + for nRow := FRow to FScrollRowBottom do + Lines[nRow].Clear(FAttribute); + Exit; + end; + + for nRow := FScrollRowBottom downto FRow + nLine do begin + Temp := Lines[nRow]; + Lines[nRow] := Lines[nRow - nLine]; + Lines[nRow - nLine] := Temp; + end; + + for nRow := FRow to FRow + nLine - 1 do + Lines[nRow].Clear(FAttribute); + + FAllInvalid := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_M; { Delete Line } +var + nLine : Integer; + nRow : Integer; + Temp : TLine; +begin + FAllInvalid := TRUE; + FCol := 0; + GetEscapeParam(2, nLine); + if nLine = 0 then + nLine := 1; + + if (FRow + nLine) > FScrollRowBottom then begin + for nRow := FRow to FScrollRowBottom do + Lines[nRow].Clear(FAttribute); + Exit; + end; + + for nRow := FRow to FRow + nLine - 1 do + Lines[nRow].Clear(F_WHITE {FAttribute}); { 12/11/99 } + for nRow := FRow to FScrollRowBottom - nLine do begin + Temp := Lines[nRow]; + Lines[nRow] := Lines[nRow + nLine]; + Lines[nRow + nLine] := Temp; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_m_lc; { Select Attributes } +var + From, n : Integer; +begin + if FEscBuffer[1] <> '[' then + Exit; + + if Length(FEscBuffer) < 2 then begin + FAttribute := F_WHITE; + FReverseVideo := FALSE; + Exit; + end; + + From := 2; + while From <= Length(FEscBuffer) do begin + if FEscBuffer[From] in [' ', '[', ';'] then + Inc(From) + else begin + From := GetEscapeParam(From, n); + case n of + 0: begin { All attributes off } + FAttribute := F_WHITE; + FReverseVideo := FALSE; + FUnderLine := FALSE; + end; + 1: begin { High intensity } + FAttribute := FAttribute or F_INTENSE; + end; + 4: begin { Underline } + FUnderLine := TRUE; + end; + 5: begin { Blinking } + FAttribute := FAttribute or B_BLINK; + end; + 7: begin { Reverse video } + FReverseVideo := TRUE; + end; + 8: begin { Secret } + FAttribute := 0; + end; + 10: begin { Don't force high bit } + FForceHighBit := FALSE; + end; + 12: begin { Force high bit on } + FForceHighBit := TRUE; + end; + 22: begin { Normal intensity } + FAttribute := FAttribute and (not F_INTENSE); + end; + 27: begin { Normal characters } + FAttribute := F_WHITE; + FReverseVideo := FALSE; + end; + 30, 31, 32, 33, 34, 35, 36, 37: + begin { Foreground color } + FAttribute := (n mod 10) or (FAttribute and $F8); + end; + 40, 41, 42, 43, 44, 45, 46, 47: + begin { Background color } + FAttribute := ((n mod 10) shl 4) or (FAttribute and $8F); + end; + else + InvalidEscape('m'); + end; + end; + end; + if FReverseVideo then begin + FAttribute := ((FAttribute and 7) shl 4) or + ((FAttribute shr 4) and 7) or + (FAttribute and $88); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_n_lc; { Cursor position report } +begin + UnimplementedEscape('n'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_at; { Insert character } +var + nChar : Integer; + nCnt : Integer; + nCol : Integer; + Line : TLine; +begin + GetEscapeParam(2, nChar); + if nChar = 0 then + nChar := 1; + + nCnt := FColCount - FCol - nChar; + if nCnt <= 0 then begin + Eol; + Exit; + end; + + Line := Lines[FRow]; + for nCol := FColCount - 1 downto FCol + nChar do begin + Line.Txt[nCol] := Line.Txt[nCol - nChar]; + Line.Att[nCol] := Line.Att[nCol - nChar]; + InvRect(Frow, nCol); + end; + + for nCol := FCol to FCol + nChar - 1 do begin + Line.Txt[nCol] := ' '; + Line.Att[nCol] := FAttribute; + InvRect(Frow, nCol); + end; + +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_r_lc; { Scrolling margins } +var + From, Top, Bottom : Integer; +begin + From := GetEscapeParam(2, Top); + if Top = 0 then begin { Default = full screen } + FScrollRowTop := 0; + FScrollRowBottom := FRowCount - 1; + end + else begin + while (From <= Length(FEscBuffer)) and (FEscBuffer[From] = ' ') do + From := From + 1; + if FEscBuffer[From] = ';' then + GetEscapeParam(From + 1, Bottom) + else + Bottom := 1; + + FScrollRowTop := Top - 1; + FScrollRowBottom := Bottom - 1; + + if (FScrollRowBottom <= FScrollRowTop) or + (FScrollRowTop < 0) or + (FScrollRowBottom >= FRowCount) then begin + FScrollRowTop := 0; + FScrollRowBottom := FRowCount - 1; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_s_lc; { Save cursor location } +begin + ProcessCSI_7; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_u_lc; { Restore cursor location } +begin + ProcessCSI_8; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_7; { Save cursor location } +begin + FRowSaved := FRow; + FColSaved := FCol; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_8; { Restore cursor location } +begin + if FRowSaved = -1 then + GotoXY(0, 0) + else + GotoXY(FColSaved, FRowSaved); + FRowSaved := -1; + FColSaved := -1; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_H; { Set Cursor Position } +var + From, Row, Col : Integer; +begin + From := GetEscapeParam(2, Row); + while (From <= Length(FEscBuffer)) and (FEscBuffer[From] = ' ') do + From := From + 1; + if FEscBuffer[From] = ';' then + GetEscapeParam(From + 1, Col) + else + Col := 1; + + GotoXY(Col - 1, Row - 1); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_h_lc; { Terminal mode set } +var + Priv : Boolean; + Mode : Integer; +begin + if FEscBuffer[1] <> '[' then begin + UnimplementedEscape('h'); + Exit; + end; + + Priv := (FEscBuffer[2] = '?'); + if not Priv then begin + UnimplementedEscape('h'); + Exit; + end; + + GetEscapeParam(3, Mode); + case Mode of + 1 : { ANSI cursor keys } + FCKeyMode := TRUE; + 4 : { Smooth scroll OFF } + { Ignore }; + 7: { Auto-wrap OFF } + FAutoWrap := TRUE; + 25: { Cursor visible } + begin + FCursorOff := FALSE; + if Assigned(FOnCursorVisible) then + FOnCursorVisible(Self); + end; + else + UnimplementedEscape('h'); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_l_lc; { Terminal mode reset } +var + Priv : Boolean; + Mode : Integer; +begin + if FEscBuffer[1] <> '[' then begin + UnimplementedEscape('l'); + Exit; + end; + + Priv := (FEscBuffer[2] = '?'); + if not Priv then begin + UnimplementedEscape('l'); + Exit; + end; + + GetEscapeParam(3, Mode); + case Mode of + 1 : { ANSI cursor keys } + FCKeyMode := FALSE; + 4 : { Smooth scroll OFF } + { Ignore }; + 7: { Auto-wrap OFF } + FAutoWrap := FALSE; + 25: { Cursor invisible } + begin + FCursorOff := TRUE; + if Assigned(FOnCursorVisible) then + FOnCursorVisible(Self); + end; + else + UnimplementedEscape('l'); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_A; { Cursor Up } +var + Row : Integer; +begin + GetEscapeParam(2, Row); + if Row <= 0 then + Row := 1; + FRow := FRow - Row; + if FRow < 0 then + FRow := 0; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_B; { Cursor Down } +var + Row : Integer; +begin + GetEscapeParam(2, Row); + if Row <= 0 then + Row := 1; + FRow := FRow + Row; + if FRow >= FRowCount then + FRow := FRowCount - 1; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_C; { Cursor Right } +var + Col : Integer; +begin + GetEscapeParam(2, Col); + if Col <= 0 then + Col := 1; + FCol := FCol + Col; + if FCol >= FColCount then begin + if FAutoWrap then begin + FCol := FCol - FColCount; + Inc(FRow); + if FRow >= FRowCount then + FRow := FRowCount - 1; + end + else + FCol := FColCount - 1; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_D; { Cursor Left } +var + Col : Integer; +begin + GetEscapeParam(2, Col); + if Col <= 0 then + Col := 1; + FCol := FCol - Col; + if FCol < 0 then + FCol := 0; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_P; { Delete Character } +var + Count : Integer; + nCol : Integer; +begin + GetEscapeParam(2, Count); + if Count <= 0 then + Count := 1; + with Lines[FRow] do begin + for nCol := Fcol to FColCount - Count - 1 do begin + Txt[nCol] := Txt[nCol + Count]; + Att[nCol] := Att[nCol + Count]; + end; + for nCol := FcolCount - Count - 1 to FColCount - 1 do begin + Txt[nCol] := ' '; + Att[nCol] := F_WHITE; + end; + end; + InvRect(Frow, FCol); + InvRect(Frow, FColCount); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_S; { Scroll up } +begin + ScrollUp; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessCSI_T; { Scroll down } +begin + UnimplementedEscape('T'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.process_charset_G0(EscCmd : Char); { G0 character set } +begin + case EscCmd of + '0': begin + FCharSetG0 := EscCmd; + FXlatInputTable := @ibm_iso8859_1_G1; + FXlatOutputTable := @ibm_iso8859_1_G1; + FNoXlat := FNoXlatInitial; +{ FNoXlat := FALSE;} + end; + 'B': begin + FCharSetG0 := EscCmd; + FXlatInputTable := @ibm_iso8859_1_G0; + FXlatOutputTable := @ibm_iso8859_1_G0; + FNoXlat := FNoXlatInitial; + end; + else + InvalidEscape(EscCmd); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.process_charset_G1(EscCmd : Char); { G1 character set } +begin + FCharSetG1 := EscCmd; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.process_charset_G2(EscCmd : Char); { G2 character set } +begin + FCharSetG2 := EscCmd; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.process_charset_G3(EscCmd : Char); { G2 character set } +begin + FCharSetG3 := EscCmd; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.ProcessEscape(EscCmd : Char); +begin + if Length(FEscBuffer) = 0 then begin + case EscCmd of + 'D': ProcessESC_D; { Index } + 'M': ProcessESC_M; { Reverse index } + 'E': ProcessESC_E; { Next line } + 'H': ; { Tabulation set } + '7': ProcessCSI_7; { Save cursor } + '8': ProcessCSI_8; { Restore Cursor } + '=': ; { VT52 } { Enter Alternate keypad } + '>': ; { VT52 } { Exit Alternate keypad } + '<': ; { VT52 } { Enter ANSI mode } + else + InvalidEscape(EscCmd); + WriteLiteralChar(EscCmd); + end; + + Exit; + end; + + case FEscBuffer[1] of + ' ': begin + case EscCmd of + 'F': ; + else + InvalidEscape(EscCmd); + end; + end; + '[': begin + case EscCmd of + 'I': ProcessCSI_I; { Select IBM char set } + { Extension F. Piette !! } + 'J': ProcessCSI_J; { Clear the screen } + 'K': ProcessCSI_K; { Erase to End of Line } + 'L': ProcessCSI_L; { Insert Line } + 'M': ProcessCSI_M; { Delete Line } + 'm': ProcessCSI_m_lc; { Select Attributes } + 'n': ProcessCSI_n_lc; { Cursor position report } + '@': ProcessCSI_at; { Insert character } + 'r': ProcessCSI_r_lc; { Set Top and Bottom marg } + 's': ProcessCSI_s_lc; { Save cursor location } + 'u': ProcessCSI_u_lc; { Restore cursor location } + 'H': ProcessCSI_H; { Set Cursor Position } + 'f': ProcessCSI_H; { Set Cursor Position } + 'g': ; { Tabulation Clear } + 'h': ProcessCSI_h_lc; { Terminal mode set } + 'l': ProcessCSI_l_lc; { Terminal mode reset } + 'A': ProcessCSI_A; { Cursor Up } + 'B': ProcessCSI_B; { Cursor Down } + 'C': ProcessCSI_C; { Cursor Right } + 'D': ProcessCSI_D; { Cursor Left } + 'P': ProcessCSI_P; { Delete Character } + 'S': ProcessCSI_S; { Scroll up } + 'T': ProcessCSI_T; { Scroll down } + '>': ; { } + else + InvalidEscape(EscCmd); + end; + end; + '(': process_charset_G0(EscCmd); { G0 character set } + ')': process_charset_G1(EscCmd); { G1 character set } + '*': process_charset_G2(EscCmd); { G2 character set } + '+': process_charset_G3(EscCmd); { G3 character set } + else + InvalidEscape(EscCmd); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.WriteLiteralChar(Ch : Char); +var + Line : TLine; +begin + if FCol >= FColCount then begin + if FAutoWrap then begin + FCol := 0; + Inc(FRow); + if FRow >= FRowCount then begin + Dec(FRow); + ScrollUp; + end; + end; + end; + + if FForceHighBit then + Ch := Chr(ord(ch) or $80); + + Line := Lines[FRow]; + Line.Txt[FCol] := Ch; + Line.Att[FCol] := FAttribute; + InvRect(Frow, FCol); + + if FCol < High(Line.Txt) then + Inc(FCol); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.SetAttr(Att : Char); +begin + { Not implemented } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Write a single character at current cursor location. } +{ Update cursor position. } +procedure TScreen.WriteChar(Ch : Char); +var + bProcess : Boolean; +begin + if FCntLiteral > 0 then begin + if (FCntLiteral and 1) <> 0 then + WriteLiteralChar(Ch) + else + SetAttr(Ch); + Dec(FCntLiteral); + Exit; + end; + + if FNoXlat then + Ch := FXlatInputTable^[ord(Ch)]; + + if FEscFLag then begin + bProcess := FALSE; + if (Length(FEscBuffer) = 0) and + (Ch in ['D', 'M', 'E', 'H', '7', '8', '=', '>', '<']) then + bProcess := TRUE + else if (Length(FEscBuffer) = 1) and + (FEscBuffer[1] in ['(', ')', '*', '+']) then + bProcess := TRUE + else if (Ch in ['0'..'9', ';', '?', ' ']) or + ((Length(FEscBuffer) = 0) and + (ch in ['[', '(', ')', '*', '+'])) then begin + FEscBuffer := FEscBuffer + Ch; + if Length(FEscBuffer) >= High(FEscBuffer) then begin + MessageBeep(MB_ICONASTERISK); + FEscBuffer := ''; + FEscFlag := FALSE; + end; + end + else + bProcess := TRUE; + + if bProcess then begin + ProcessEscape(Ch); + FEscBuffer := ''; + FEscFlag := FALSE; + end; + + Exit; + end; + + case Ch of + #0: ; + #7: MessageBeep(MB_ICONASTERISK); + #8: BackSpace; + #9: begin + repeat + Inc(FCol); + until (FCol Mod 8) = 0; + end; + #10: begin + CursorDown; + if FAutoCR then + CarriageReturn; + end; + #13: begin + CarriageReturn; + if FAutoLF then + CursorDown; + end; + #14: begin + FXlatInputTable := @ibm_iso8859_1_G1; + FXlatOutputTable := @ibm_iso8859_1_G1; + end; + #15: begin + FXlatInputTable := @ibm_iso8859_1_G0; + FXlatOutputTable := @ibm_iso8859_1_G0; + end; + #27: begin + FEscBuffer := ''; + FEscFlag := TRUE; + end; + else + WriteLiteralChar(Ch); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Write characters at current cursor location. Update cursor position. } +procedure TScreen.WriteStr(Str : String); +var + I : Integer; +begin + for I := 1 to Length(Str) do + WriteChar(Str[I]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Read characters from the cursor to end of line } +function TScreen.ReadStr : String; +var + Line : TLine; + Len : Integer; +begin + Line := Lines[FRow]; + Len := FColCount - FCol; + if Len <= 0 then + Result := '' + else begin + SetLength(Result, Len); + Move(Line.Txt[FCol], Result[1], Len); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TScreen.GotoXY(X, Y : Integer); +begin + if X < 0 then + FCol := 0 + else if X >= FColCount then + FCol := FColCount - 1 + else + FCol := X; + + if Y < 0 then + FRow := 0 + else if Y >= FRowCount then + FRow := FRowCount - 1 + else + FRow := Y; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetCaret; +begin +{$IFDEF CHAR_ZOOM} + SetCaretPos(FCharPos[FScreen.FCol] + FLeftMargin + 2, + FLinePos[FScreen.FRow - FTopLine] + FTopMargin + 3); +{$ELSE} + SetCaretPos(FScreen.FCol * FCharWidth + FLeftMargin, + (FScreen.FRow - FTopLine) * FLineHeight + FTopMargin); +{$ENDIF} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Adjusts the scrollbar properties to match the number of host and scrollback + lines that we can scroll through. } +procedure TCustomEmulVT.AdjustScrollBar; +var + VisibleLines : Integer; +begin + if not FVScrollBar.Visible then + Exit; + FVScrollBar.Min := FScreen.FBackEndRow; +{$IFDEF CHAR_ZOOM} + VisibleLines := Trunc((Height - FTopMargin - FBottomMargin) / (LineHeight * FLineZoom)); +{$ELSE} + VisibleLines := (Height - FTopMargin - FBottomMargin) Div LineHeight; +{$ENDIF} + if VisibleLines > FScreen.FRowCount then + VisibleLines := FScreen.FRowCount; + FVScrollBar.Max := FScreen.FRowCount - VisibleLines; + FVScrollBar.Position := FTopLine; + FVScrollBar.SmallChange := 1; + FVScrollBar.LargeChange := VisibleLines; + FVScrollBar.Enabled := FVScrollBar.Max > FVScrollBar.Min; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.Clear; +begin + FScreen.ClearScreen; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetCursor(Row, Col : Integer); +begin + FScreen.GotoXY(Col - 1, Row - 1); +{ SetCaret; } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.WriteChar(Ch : Char); +begin + if FCaretCreated and FCaretShown then begin + HideCaret(Handle); + FCaretShown := FALSE; + end; + + if FLog then + Write(FFileHandle, Ch); + FScreen.WriteChar(ch); + if FAutoRepaint then + UpdateScreen; +{ SetCaret; } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.WriteStr(Str : String); +var + I : Integer; +begin + if FCaretCreated and FCaretShown then begin + HideCaret(Handle); + FCaretShown := FALSE; + end; + + for I := 1 to Length(Str) do begin + if FLog then + Write(FFileHandle, Str[I]); + FScreen.WriteChar(Str[I]); + end; + if FAutoRepaint then + UpdateScreen; +{ SetCaret; } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.WriteBuffer(Buffer : Pointer; Len : Integer); +var + I : Integer; +begin + if FCaretCreated and FCaretShown then begin + HideCaret(Handle); + FCaretShown := FALSE; + end; + + for I := 0 to Len - 1 do begin + if FLog then + Write(FFileHandle, PChar(Buffer)[I]); + FScreen.WriteChar(PChar(Buffer)[I]); + end; + if FAutoRepaint then + UpdateScreen; +{ SetCaret; } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomEmulVT.ReadStr : String; +begin + Result := FScreen.ReadStr; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.CopyHostScreen; +begin + FScreen.CopyScreenToBack; + AdjustScrollBar; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TCustomEmulVT.Create(AOwner: TComponent); +type + TMyLogPalette = record + palVersion: Word; + palNumEntries: Word; + palPalEntry: array[0..NumPaletteEntries - 1] of TPaletteEntry; + end; + TPLogPalette = ^TLogPalette; +var + plgpl : ^TMyLogPalette; + I : Integer; +begin + inherited Create(AOwner); + ControlStyle := ControlStyle + [csOpaque]; + + New(plgpl); + plgpl^.palNumEntries := High(plgpl^.palPalEntry) + 1; + plgpl^.palVersion := $300; + + FTopMargin := 4; + FLeftMargin := 6; + FRightMargin := 6; + FBottomMargin := 4; + + FPaletteEntries[0].peRed := 0; { Black } + FPaletteEntries[0].peGreen := 0; + FPaletteEntries[0].peBlue := 0; + FPaletteEntries[1].peRed := 168; { Red } + FPaletteEntries[1].peGreen := 0; + FPaletteEntries[1].peBlue := 0; + FPaletteEntries[2].peRed := 0; { Green } + FPaletteEntries[2].peGreen := 168; + FPaletteEntries[2].peBlue := 0; + FPaletteEntries[3].peRed := 168; { Yellow } + FPaletteEntries[3].peGreen := 168; + FPaletteEntries[3].peBlue := 0; + FPaletteEntries[4].peRed := 0; { Dark Blue } + FPaletteEntries[4].peGreen := 0; + FPaletteEntries[4].peBlue := 168; + FPaletteEntries[5].peRed := 168; { Magenta } + FPaletteEntries[5].peGreen := 0; + FPaletteEntries[5].peBlue := 168; + FPaletteEntries[6].peRed := 0; { Cyan } + FPaletteEntries[6].peGreen := 112; + FPaletteEntries[6].peBlue := 216; + FPaletteEntries[7].peRed := 200; { White } + FPaletteEntries[7].peGreen := 200; + FPaletteEntries[7].peBlue := 200; + FPaletteEntries[8].peRed := 84; { Grey } + FPaletteEntries[8].peGreen := 84; + FPaletteEntries[8].peBlue := 84; + FPaletteEntries[9].peRed := 255; { Red Highlight } + FPaletteEntries[9].peGreen := 84; + FPaletteEntries[9].peBlue := 212; + FPaletteEntries[10].peRed := 84; { Green Highlight } + FPaletteEntries[10].peGreen := 255; + FPaletteEntries[10].peBlue := 84; + FPaletteEntries[11].peRed := 255; { Yellow Highlight } + FPaletteEntries[11].peGreen := 255; + FPaletteEntries[11].peBlue := 84; + FPaletteEntries[12].peRed := 84; { Blue Highlight } + FPaletteEntries[12].peGreen := 84; + FPaletteEntries[12].peBlue := 255; + FPaletteEntries[13].peRed := 255; { Magenta Highlight } + FPaletteEntries[13].peGreen := 84; + FPaletteEntries[13].peBlue := 255; + FPaletteEntries[14].peRed := 84; { Cyan highlight } + FPaletteEntries[14].peGreen := 255; + FPaletteEntries[14].peBlue := 255; + FPaletteEntries[15].peRed := 255; { White Highlight } + FPaletteEntries[15].peGreen := 255; + FPaletteEntries[15].peBlue := 255; + + for I := 0 to High(plgpl^.palPalEntry) do begin + plgpl^.PalPalEntry[I].peRed := FPaletteEntries[I].peRed; + plgpl^.PalPalEntry[I].peGreen := FPaletteEntries[I].peGreen; + plgpl^.PalPalEntry[I].peBlue := FPaletteEntries[I].peBlue; + plgpl^.PalPalEntry[I].peFlags := PC_NOCOLLAPSE; + end; + + FPal := CreatePalette(TPLogPalette(plgpl)^); + Dispose(plgpl); + + FScreen := TScreen.Create; + FVScrollBar := TScrollBar.Create(Self); + FFont := TFont.Create; + FFont.Name := 'Terminal'; + FFont.Size := 12; + FFont.Style := []; + FCharZoom := 1.0; + FLineZoom := 1.0; + SetupFont; + + FScreen.FXlatInputTable := @ibm_iso8859_1_G0; + FScreen.FXlatOutputTable := @ibm_iso8859_1_G0; + FScreen.OnCursorVisible := CursorVisibleEvent; + + FCursorVisible := TRUE; + Width := 250; + Height := 100; + FBorderStyle := bsSingle; + FBorderWidth := 1; + FAutoRepaint := TRUE; + FFkeys := 1; + FGraphicDraw := FALSE; + + with FVScrollBar do begin + Parent := Self; + Kind := sbVertical; + Width := 16; + Visible := TRUE; + Align := alRight; + OnScroll := VScrollBarScroll; + end; + AdjustScrollBar; + + with FScreen do begin + GotoXY(0, 0); + WriteStr('EmulVT'); + GotoXY(0, 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetRows(Value : Integer); +begin + with FScreen do begin + if FRowCount <> Value then begin + SetRowCount(Value); + AdjustScrollBar; + ClearScreen; + Repaint; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomEmulVT.GetRows : Integer; +begin + Result := FScreen.FRowCount; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetCols(Value : Integer); +begin + with FScreen do begin + if FColCount <> Value then begin + FColCount := Value; + ClearScreen; + Repaint; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomEmulVT.GetCols : Integer; +begin + Result := FScreen.FColCount; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.CursorVisibleEvent(Sender : TObject); +begin + if FScreen.FCursorOff then begin + if FCaretShown then begin + HideCaret(Handle); + FCaretShown := FALSE; + end; + end + else begin + if FScreen.Focused and not FCaretShown then begin + ShowCaret(Handle); + FCaretShown := TRUE; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetAutoLF(Value : Boolean); +begin + FScreen.FAutoLF := Value; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetAutoCR(Value : Boolean); +begin + FScreen.FAutoCR := Value; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetLog(Value : Boolean); +begin + if FLog = Value then + Exit; + + FLog := Value; + + if FLog then begin +{$I-} + AssignFile(FFileHandle, 'EMULVT.LOG'); + Append(FFileHandle); + if IOResult <> 0 then + Rewrite(FFileHandle); + Write(FFileHandle, ''); +{$I+} + end + else begin + Write(FFileHandle, ''); + CloseFile(FFileHandle); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetXlat(Value : Boolean); +begin + FScreen.FNoXlat := not Value; + FScreen.FNoXlatInitial := not Value; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomEmulVT.GetXlat : Boolean; +begin + Result := not FScreen.FNoXlatInitial; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomEmulVT.GetAutoLF : Boolean; +begin + Result := FScreen.FAutoLF; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomEmulVT.GetAutoCR : Boolean; +begin + Result := FScreen.FAutoCR; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor TCustomEmulVT.Destroy; +begin + if FLog then + Log := FALSE; + + FFont.Free; + FVScrollBar.Free; + FScreen.Free; + DeleteObject(FPal); + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetBackRows(Value : Integer); +begin + with FScreen do begin + if FBackRowCount <> Value then begin + SetBackRowCount(Value); + AdjustScrollBar; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetTopLine(Value : Integer); +begin + if Value < FVScrollBar.Min then + Value := FVScrollBar.Min; + if Value > FVScrollBar.Max then + Value := FVScrollBar.Max; + FTopLine := Value; + FVScrollBar.Position := FTopLine; + Repaint; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomEmulVT.GetBackRows : Integer; +begin + Result := FScreen.FBackRowCount; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetBackColor(Value : TBackColors); +begin + FScreen.FBackColor := Value; + Invalidate; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomEmulVT.GetBackColor : TBackColors; +begin + Result := FScreen.FBackColor; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetMarginColor(const Value: Integer); +begin + FMarginColor := Value; + Invalidate; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetLeftMargin(const Value: Integer); +begin + FLeftMargin := Value; + Invalidate; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetBottomMargin(const Value: Integer); +begin + FBottomMargin := Value; + Invalidate; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetRightMargin(const Value: Integer); +begin + FRightMargin := Value; + Invalidate; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetTopMargin(const Value: Integer); +begin + FTopMargin := Value; + Invalidate; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetOptions(Value : TScreenOptions); +begin + FScreen.FOptions := Value; + Invalidate; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomEmulVT.GetOptions : TScreenOptions; +begin + Result := FScreen.FOptions; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetupFont; +var + DC : HDC; + Metrics : TTextMetric; + hObject : THandle; +begin + DC := GetDC(0); + hObject := SelectObject(DC, FFont.Handle); + GetTextMetrics(DC, Metrics); + SelectObject(DC, hOBject); + ReleaseDC(0, DC); + + SetCharWidth(Metrics.tmMaxCharWidth); + SetLineHeight(Metrics.tmHeight); + FInternalLeading := Metrics.tmInternalLeading; + Invalidate; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetCharWidth(newValue : Integer); +var + nCol : Integer; +begin + FCharWidth := newValue; + for nCol := Low(FCharPos) to High(FCharPos) do + FCharPos[nCol] := Trunc(FCharWidth * nCol * FCharZoom); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetCharZoom(newValue : Single); +begin + FCharZoom := newValue; + SetCharWidth(FCharWidth); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetLineHeight(Value : Integer); +var + nRow : Integer; +begin + FLineHeight := Value; + for nRow := 0 to High(FLinePos) do { Jan 10, 2002 } + FLinePos[nRow] := Trunc(FLineHeight * nRow * FLineZoom); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetLineZoom(newValue : Single); +begin + FLineZoom := newValue; + SetLineHeight(FLineHeight); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.SetFont(Value : TFont); +begin + FFont.Assign(Value); +{$IFNDEF SINGLE_CHAR_PAINT} + FFont.Pitch := fpFixed; +{$ENDIF} + SetupFont; + SetCaret; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.WMLButtonDown(var Message: TWMLButtonDown); +begin + inherited; + SetFocus; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.VScrollBarScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer); +begin + FTopLine := ScrollPos; + Repaint; + SetFocus; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.DoKeyBuffer(Buffer : PChar; Len : Integer); +var + J : Integer; + ch : Char; +begin + if Assigned(FOnKeyBuffer) then + FOnKeyBuffer(Self, Buffer, Len) + else begin + for J := 0 to Len - 1 do begin + ch := Buffer[J]; + KeyPress(ch); + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomEmulVT.FindFKeys(ScanCode: Char; Shift: TShiftState; + Ext: Boolean) : PFuncKeyValue; +var + I : Integer; + pFKeys : PFuncKeysTable; +begin + Result := nil; + case FKeys of + 0 : pFKeys := @FKeys1; + 1 : pFKeys := @FKeys2; + 2 : pFKeys := @FKeys3; + else + pFKeys := @FKeys2; + end; + + for I := Low(pFKeys^) to High(pFKeys^) do begin + if (pFKeys^[I].ScanCode <> #0) and (pFKeys^[I].ScanCode = ScanCode) and + (pFKeys^[I].Shift = Shift) and + (pFKeys^[I].Ext = Ext) then begin + Result := @pFKeys^[I].Value; + Break; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomEmulVT.ProcessFKeys(ScanCode: Char; Shift: TShiftState; + Ext: Boolean) : Boolean; +var + I : Integer; + pFKeys : PFuncKeysTable; +begin + Result := FALSE; + case FKeys of + 0 : pFKeys := @FKeys1; + 1 : pFKeys := @FKeys2; + 2 : pFKeys := @FKeys3; + else + pFKeys := @FKeys2; + end; + + for I := Low(pFKeys^) to High(pFKeys^) do begin + if (pFKeys^[I].ScanCode <> #0) and (pFKeys^[I].ScanCode = ScanCode) and + (pFKeys^[I].Shift = Shift) and + (pFKeys^[I].Ext = Ext) then begin + Result := TRUE; + DoKeyBuffer(@pFKeys^[I].Value[1], Length(pFKeys^[I].Value)); + Break; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.AppMessageHandler(var Msg: TMsg; var Handled: Boolean); +const + v1 : String = 'aeiou'; + v2 : String = 'âêîôû'; + v3 : String = 'äëïöü'; + SpyFlag : Boolean = FALSE; +var + Shift : TShiftState; + ShiftLock : Boolean; + VirtKey : Integer; + Key : Char; + I : Integer; + ScanCode : Char; + Ext : Boolean; + SpyBuffer : String; + FnBuffer : String; + pFV : PFuncKeyValue; +begin + if (Msg.hWnd = Handle) and (Msg.Message = WM_KEYDOWN) then begin + VirtKey := Msg.wParam; + Key := chr(Msg.wParam and $FF); +{ DebugString('AppMessageHandler KEYDOWN ' + IntToHex(Msg.wParam, 4) + #13 + #10); } + Shift := KeyDataToShiftState(Msg.lParam); + ShiftLock := ((GetKeyState(VK_CAPITAL) and 1) > 0); + ScanCode := Chr(LOBYTE(HIWORD(Msg.lParam))); + Ext := ((Msg.lParam and $1000000) <> 0); + + if Assigned(FOnKeyDown) then begin + FOnKeyDown(Self, VirtKey, Shift, ShiftLock, ScanCode, Ext); + if VirtKey = 0 then begin + Handled := TRUE; + Exit; + end; + end; + + if (Msg.wParam <> VK_SHIFT) and + (Msg.wParam <> VK_CONTROL) and + (Msg.wParam <> VK_MENU) then begin + if (ScanCode = '7') and + (Shift = [ssAlt, ssCtrl]) and (Ext = FALSE) then begin + { This is CTRL-ALT-* (on num pad) } + SpyFlag := TRUE; + Handled := TRUE; + Exit; + end; + + if SpyFlag then begin + SpyFlag := FALSE; + pFV := FindFKeys(ScanCode, Shift, Ext); + SpyBuffer := IntToHex(Ord(ScanCode), 2) + ', ' + + ShiftStateToString(Shift) + ', '; + + if Ext then + SpyBuffer := SpyBuffer + 'TRUE' + else + SpyBuffer := SpyBuffer + 'FALSE'; + + if pFV <> nil then + SpyBuffer := SpyBuffer + ', ''' + + FuncKeyValueToString(pFV^) + ''''; + + SpyBuffer := SpyBuffer + #0; + ClipBoard.SetTextBuf(@SpyBuffer[1]); + + FnBuffer := 'Key definition from tnchrk' + + IntToStr(FKeys) + '.cfg' + #0; + Application.MessageBox(@SpyBuffer[1], @FnBuffer[1], MB_OK); + Handled := TRUE; + Exit; + end; + + if ProcessFKeys(ScanCode, Shift, Ext) then begin + Handled := TRUE; + Exit; + end; + end; + + case Msg.wParam of + VK_SHIFT, VK_CONTROL, VK_MENU: ; + + VK_NEXT, VK_PRIOR, VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_HOME, VK_END: + begin + if ProcessFKeys(ScanCode, Shift, TRUE) then begin + Handled := TRUE; + Exit; + end; + end; + VK_TAB, VK_RETURN, VK_ESCAPE, VK_BACK: + begin + Handled := TRUE; + end; + + $DD: + begin + if not (ssAlt in Shift) then begin + Key := #0; + Handled := TRUE; + if (ssShift in Shift) then + FFlagTrema := TRUE + else + FFlagCirconflexe := TRUE; + end; + end; + + ord('A')..ord('Z') : + begin + if (ssCtrl in Shift) then + Key := chr(Word(Key) and $1F) + else if not ShiftLock and not (ssShift in Shift) then + Key := chr(Word(Key) or $20); + if (FFlagCirconflexe) then begin + for I := Length(v1) downto 1 do begin + if Key = v1[I] then begin + Key := v2[I]; + Break; + end; + end; + FFlagCirconflexe := FALSE; + end; + if (FFlagTrema) then begin + for I := Length(v1) downto 1 do begin + if Key = v1[I] then begin + Key := v3[I]; + Break; + end; + end; + FFlagTrema := FALSE; + end; + Handled := TRUE; + end; + end; + +{ DebugString('Char = ' + IntToHex(Integer(Key), 2) + #13 + #10); } + if Handled and (Key <> #0) then + KeyPress(Key); + end; + + if not Handled and Assigned(FAppOnMessage) then + FAppOnMessage(Msg, Handled); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.KeyPress(var Key: Char); +begin + if not FScreen.FNoXlat then + Key := FScreen.FXlatOutputTable^[ord(Key)]; + + inherited KeyPress(Key); + if FLocalEcho then begin + WriteChar(Key); + if not FAutoRepaint then + UpdateScreen; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.WMSetFocus(var Message: TWMSetFocus); +begin +{ inherited; } + FScreen.Focused := TRUE; +{ SetupFont; } + + if not FCursorVisible then + Exit; + + CreateCaret(Handle, 0, 2, FLineHeight); + FCaretCreated := TRUE; + SetCaret; + if not FScreen.FCursorOff then begin + ShowCaret(Handle); + FCaretShown := TRUE; + end; + + FAppOnMessage := Application.OnMessage; + Application.OnMessage := AppMessageHandler; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.WMKillFocus(var Message: TWMKillFocus); +begin +{ inherited; } + FScreen.Focused := FALSE; + + if not FCursorVisible then + Exit; + + if FCaretShown then begin + HideCaret(Handle); + FCaretShown := FALSE; + end; + + if FCaretCreated then begin + DestroyCaret; + FCaretCreated := FALSE; + end; + + Application.OnMessage := FAppOnMessage; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.MouseToCell(X, Y: Integer; var ACol, ARow: Longint); +begin +{$IFDEF CHAR_ZOOM} + aRow := FScreen.FRowCount - 1; + while (Y - FTopMargin) <= FLinePos[aRow] do + Dec(aRow); +{$ELSE} + aRow := (Y - FTopMargin) div FLineHeight; +{$ENDIF} + if aRow < 0 then + aRow := 0 + else if aRow >= FScreen.FRowCount then + aRow := FScreen.FRowCount - 1; + +{$IFDEF CHAR_ZOOM} + aCol := FScreen.FColCount - 1; + while (X - FLeftMargin) <= FCharPos[aCol] do + Dec(aCol); +{$ELSE} + aCol := (X - FLeftMargin) div FCharWidth; +{$ENDIF} + if aCol < 0 then + aCol := 0 + else if aCol >= FScreen.FColCount then + aCol := FScreen.FColCount - 1; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.ShowCursor; +begin + SetCaret; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.WMPaletteChanged(var Message : TMessage); +{var + HandleDC : HDC;} +begin +{ if Message.wParam <> Handle then begin + HandleDC := GetDC(Handle); + SelectPalette(HandleDC, FPal, FALSE); + if RealizePalette(HandleDC) <> 0 then begin + InvalidateRect(Handle, nil, TRUE); + MessageBeep(0); + end; + ReleaseDC(Handle, HandleDC); + end; +} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.UpdateScreen; +var + rc : TRect; +begin + if FScreen.FAllInvalid then + InvalidateRect(Handle, nil, FALSE) + else begin +{$Q-} + with FScreen.FInvRect do begin +{$IFDEF CHAR_ZOOM} + if Left = 9999 then begin + rc.Top := 0; + rc.Bottom := 0; + rc.Left := 0; + rc.Right := 0; + end + else begin + rc.Top := FTopMargin + FLinePos[Top - FTopLine] + FInternalLeading; + rc.Bottom := FTopMargin + FLinePos[Bottom + 1 - FTopLine] + FInternalLeading; + rc.Left := FLeftMargin + FCharPos[Left]; + rc.Right := FLeftMargin + FCharPos[Right + 1]; + end; +{$ELSE} + rc.Top := FTopMargin + FLineHeight * (Top - FTopLine) + FInternalLeading; + rc.Bottom := FTopMargin + FLineHeight * (Bottom + 1 - FTopLine) + FInternalLeading; + rc.Left := FLeftMargin + FCharWidth * Left; + rc.Right := FLeftMargin + FCharWidth * (Right + 1); +{$ENDIF} + end; + InvalidateRect(Handle, @rc, FALSE); +{$Q+} + end; + + { Invalidate the region where the caret is. I should'nt do that, but } + { if I do'nt, the caret remains where it is ! Bug ? } +{$IFDEF CHAR_ZOOM} + rc.Top := FLinePos[FScreen.FRow - FTopLine] + FTopMargin; + rc.Bottom := FLinePos[FScreen.FRow - FTopLine + 1] + FTopMargin; + rc.Left := FLeftMargin + FCharPos[FScreen.FCol]; + rc.Right := FLeftMargin + FCharPos[FScreen.FCol + 1]; +{$ELSE} + rc.Top := FTopMargin + FLineHeight * (FScreen.FRow - FTopLine); + rc.Bottom := rc.Top + FLineHeight; + rc.Left := FLeftMargin + FCharWidth * FScreen.FCol; + rc.Right := rc.Left + FCharWidth; +{$ENDIF} + InvalidateRect(Handle, @rc, FALSE); + + FScreen.InvClear; + + if FCaretCreated then begin + ShowCaret(Handle); + FCaretShown := TRUE; + end; + SetCaret; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomEmulVT.SnapPixelToRow(Y : Integer) : Integer; +var + nRow : Integer; +begin + nRow := PixelToRow(Y); +{$IFDEF CHAR_ZOOM} + Result := FTopMargin + FLinePos[nRow]; +{$ELSE} + Result := FTopMargin + nRow * FLineHeight; +{$ENDIF} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomEmulVT.SnapPixelToCol(X : Integer) : Integer; +var + nCol : Integer; +begin + nCol := PixelToCol(X); +{$IFDEF CHAR_ZOOM} + Result := FLeftMargin + FCharPos[nCol]; +{$ELSE} + Result := FLeftMargin + nCol * FCharWidth; +{$ENDIF} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomEmulVT.PixelToRow(Y : Integer) : Integer; +var + nRow : Integer; +begin +{$IFDEF CHAR_ZOOM} + nRow := FScreen.FRowCount - 1; + while (nRow > 0) and ((Y - FTopMargin) < FLinePos[nRow]) do + Dec(nRow); +{$ELSE} + nRow := (Y - FTopMargin) div FLineHeight; +{$ENDIF} + if nRow < 0 then + nRow := 0; + Result := nRow; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomEmulVT.PixelToCol(X : Integer) : Integer; +var + nCol : Integer; +begin +{$IFDEF CHAR_ZOOM} + nCol := FScreen.FColCount - 1; + while (X - FLeftMargin) < FCharPos[nCol] do + Dec(nCol); +{$ELSE} + nCol := (X - FLeftMargin) div FCharWidth; +{$ENDIF} + if nCol < 0 then + nCol := 0; + Result := nCol; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This procedure will paint graphic char from the OEM charset (lines, } +{ corners, T and other like) using GDI functions. This will result in } +{ autosized characters, necessary for example to draw a frame when zoom } +{ affect character and line spacing. } +procedure TCustomEmulVT.PaintGraphicChar( + DC : HDC; + X, Y : Integer; + rc : PRect; + ch : Char); +const + OneSpace : Char = ' '; +var + X1, X2, X3 : Integer; + Y1, Y2, Y3 : Integer; + Co : TColor; +begin + ExtTextOut(DC, + X, Y, + ETO_OPAQUE or ETO_CLIPPED, rc, + @OneSpace, 1, nil); + X1 := X; + X3 := rc^.Right; + X2 := (X1 + X3) div 2; + Y1 := rc^.Top; + Y3 := rc^.Bottom; + Y2 := (Y1 + Y3) div 2; + case Ch of + #$C4: begin { Horizontal single line } + Canvas.MoveTo(X1, Y2); + Canvas.LineTo(X3, Y2); + end; + #$B3: begin { Vertical single line } + Canvas.MoveTo(X2, Y1); + Canvas.LineTo(X2, Y3); + end; + #$DA: begin { Upper Left Single Corner } + Canvas.MoveTo(X3, Y2); + Canvas.LineTo(X2, Y2); + Canvas.LineTo(X2, Y3); + end; + #$C0: begin { Bottom Left Single Corner } + Canvas.MoveTo(X2, Y1); + Canvas.LineTo(X2, Y2); + Canvas.LineTo(X3, Y2); + end; + #$C1: begin { Reverse T } + Canvas.MoveTo(X2, Y1); + Canvas.LineTo(X2, Y2); + Canvas.MoveTo(X1, Y2); + Canvas.LineTo(X3, Y2); + end; + #$C2: begin { T } + Canvas.MoveTo(X2, Y3); + Canvas.LineTo(X2, Y2); + Canvas.MoveTo(X1, Y2); + Canvas.LineTo(X3, Y2); + end; + #$C3: begin { Left T } + Canvas.MoveTo(X2, Y1); + Canvas.LineTo(X2, Y3); + Canvas.MoveTo(X2, Y2); + Canvas.LineTo(X3, Y2); + end; + #$B4: begin { Right T } + Canvas.MoveTo(X2, Y1); + Canvas.LineTo(X2, Y3); + Canvas.MoveTo(X2, Y2); + Canvas.LineTo(X1 - 1, Y2); + end; + #$BF: begin { Top Right Single Corner } + Canvas.MoveTo(X1, Y2); + Canvas.LineTo(X2, Y2); + Canvas.LineTo(X2, Y3); + end; + #$D9: begin { Bottom Right Single Corner } + Canvas.MoveTo(X1, Y2); + Canvas.LineTo(X2, Y2); + Canvas.LineTo(X2, Y1 - 1); + end; + #$D6: begin { Upper Left Single/Double Corner } + Canvas.MoveTo(X3, Y2); + Canvas.LineTo(X2 - 1, Y2); + Canvas.LineTo(X2 - 1, Y3); + Canvas.MoveTo(X2 + 1, Y2); + Canvas.LineTo(X2 + 1, Y3); + end; + #$D3: begin { Bottom Left Single/Double Corner } + Canvas.MoveTo(X2 - 1, Y1); + Canvas.LineTo(X2 - 1, Y2); + Canvas.LineTo(X3, Y2); + Canvas.MoveTo(X2 + 1, Y1); + Canvas.LineTo(X2 + 1, Y2); + end; + #$B7: begin { Top Right Single/Double Corner } + Canvas.MoveTo(X1, Y2); + Canvas.LineTo(X2 + 1, Y2); + Canvas.LineTo(X2 + 1, Y3); + Canvas.MoveTo(X2 - 1, Y2); + Canvas.LineTo(X2 - 1, Y3); + end; + #$BD: begin { Bottom Right Single/Double Corner } + Canvas.MoveTo(X2 + 1, Y1); + Canvas.LineTo(X2 + 1, Y2); + Canvas.LineTo(X1 - 1, Y2); + Canvas.MoveTo(X2 - 1, Y1); + Canvas.LineTo(X2 - 1, Y2); + end; + #$D5: begin { Upper Left Double/Single Corner } + Canvas.MoveTo(X3, Y2 - 1); + Canvas.LineTo(X2, Y2 - 1); + Canvas.LineTo(X2, Y3); + Canvas.MoveTo(X3, Y2 + 1); + Canvas.LineTo(X2, Y2 + 1); + end; + #$D4: begin { Bottom Left Double/Single Corner } + Canvas.MoveTo(X2, Y1); + Canvas.LineTo(X2, Y2 + 1); + Canvas.LineTo(X3, Y2 + 1); + Canvas.MoveTo(X2, Y2 - 1); + Canvas.LineTo(X3, Y2 - 1); + end; + #$B8: begin { Top Right Double/Single Corner } + Canvas.MoveTo(X1, Y2 - 1); + Canvas.LineTo(X2, Y2 - 1); + Canvas.LineTo(X2, Y3); + Canvas.MoveTo(X1, Y2 + 1); + Canvas.LineTo(X2, Y2 + 1); + end; + #$BE: begin { Bottom Right Double/Single Corner } + Canvas.MoveTo(X2, Y1); + Canvas.LineTo(X2, Y2 + 1); + Canvas.LineTo(X1 - 1, Y2 + 1); + Canvas.MoveTo(X1, Y2 - 1); + Canvas.LineTo(X2, Y2 - 1); + end; + #$CD: begin { Horizontal Double line } + Canvas.MoveTo(X1, Y2 + 1); + Canvas.LineTo(X3, Y2 + 1); + Canvas.MoveTo(X1, Y2 - 1); + Canvas.LineTo(X3, Y2 - 1); + end; + #$BA: begin { Vertical Double line } + Canvas.MoveTo(X2 + 1, Y1); + Canvas.LineTo(X2 + 1, Y3); + Canvas.MoveTo(X2 - 1, Y1); + Canvas.LineTo(X2 - 1, Y3); + end; + #$D1: begin { T Top Horizontal Double line } + Canvas.MoveTo(X1, Y2 + 1); + Canvas.LineTo(X3, Y2 + 1); + Canvas.MoveTo(X1, Y2 - 1); + Canvas.LineTo(X3, Y2 - 1); + Canvas.MoveTo(X2, Y2 + 1); + Canvas.LineTo(X2, Y3); + end; + #$CF: begin { T Bottom Horizontal Double line } + Canvas.MoveTo(X1, Y2 + 1); + Canvas.LineTo(X3, Y2 + 1); + Canvas.MoveTo(X1, Y2 - 1); + Canvas.LineTo(X3, Y2 - 1); + Canvas.MoveTo(X2, Y2 - 1); + Canvas.LineTo(X2, Y1); + end; + #$C6: begin { T Left Horizontal Double line } + Canvas.MoveTo(X2, Y2 + 1); + Canvas.LineTo(X3, Y2 + 1); + Canvas.MoveTo(X2, Y2 - 1); + Canvas.LineTo(X3, Y2 - 1); + Canvas.MoveTo(X2, Y1); + Canvas.LineTo(X2, Y3); + end; + #$B5: begin { T Right Horizontal Double line } + Canvas.MoveTo(X1, Y2 + 1); + Canvas.LineTo(X2, Y2 + 1); + Canvas.MoveTo(X1, Y2 - 1); + Canvas.LineTo(X2, Y2 - 1); + Canvas.MoveTo(X2, Y1); + Canvas.LineTo(X2, Y3); + end; + #$C9: begin { Upper Left Double Corner } + Canvas.MoveTo(X3, Y2 - 1); + Canvas.LineTo(X2 - 1, Y2 - 1); + Canvas.LineTo(X2 - 1, Y3); + Canvas.MoveTo(X3, Y2 + 1); + Canvas.LineTo(X2 + 1, Y2 + 1); + Canvas.LineTo(X2 + 1, Y3); + end; + #$C8: begin { Bottom Left Double Corner } + Canvas.MoveTo(X2 - 1, Y1); + Canvas.LineTo(X2 - 1, Y2 + 1); + Canvas.LineTo(X3, Y2 + 1); + Canvas.MoveTo(X2 + 1, Y1); + Canvas.LineTo(X2 + 1, Y2 - 1); + Canvas.LineTo(X3, Y2 - 1); + end; + #$BB: begin { Top Right Double Corner } + Canvas.MoveTo(X1, Y2 - 1); + Canvas.LineTo(X2 + 1, Y2 - 1); + Canvas.LineTo(X2 + 1, Y3); + Canvas.MoveTo(X1, Y2 + 1); + Canvas.LineTo(X2 - 1, Y2 + 1); + Canvas.LineTo(X2 - 1, Y3); + end; + #$BC: begin { Bottom Right Double Corner } + Canvas.MoveTo(X2 - 1, Y1); + Canvas.LineTo(X2 - 1, Y2 - 1); + Canvas.LineTo(X1 - 1, Y2 - 1); + Canvas.MoveTo(X2 + 1, Y1); + Canvas.LineTo(X2 + 1, Y2 + 1); + Canvas.LineTo(X1 - 1, Y2 + 1); + end; + #$CC: begin { Double left T } + Canvas.MoveTo(X2 - 1, Y1); + Canvas.LineTo(X2 - 1, Y3); + Canvas.MoveTo(X2 + 1, Y1); + Canvas.LineTo(X2 + 1, Y2 - 1); + Canvas.LineTo(X3, Y2 - 1); + Canvas.MoveTo(X3, Y2 + 1); + Canvas.LineTo(X2 + 1, Y2 + 1); + Canvas.LineTo(X2 + 1, Y3); + end; + #$B9: begin { Double Right T } + Canvas.MoveTo(X2 + 1, Y1); + Canvas.LineTo(X2 + 1, Y3); + Canvas.MoveTo(X2 - 1, Y1); + Canvas.LineTo(X2 - 1, Y2 - 1); + Canvas.LineTo(X1 - 1, Y2 - 1); + Canvas.MoveTo(X1, Y2 + 1); + Canvas.LineTo(X2 - 1, Y2 + 1); + Canvas.LineTo(X2 - 1, Y3); + end; + #$C7: begin { Double T Single Left } + Canvas.MoveTo(X2 + 1, Y1); + Canvas.LineTo(X2 + 1, Y3); + Canvas.MoveTo(X2 - 1, Y1); + Canvas.LineTo(X2 - 1, Y3); + Canvas.MoveTo(X2 + 1, Y2); + Canvas.LineTo(X3, Y2); + end; + #$B6: begin { Double T Single Right } + Canvas.MoveTo(X2 + 1, Y1); + Canvas.LineTo(X2 + 1, Y3); + Canvas.MoveTo(X2 - 1, Y1); + Canvas.LineTo(X2 - 1, Y3); + Canvas.MoveTo(X2 - 1, Y2); + Canvas.LineTo(X1 - 1, Y2); + end; + #$D2: begin { Single T Double Top } + Canvas.MoveTo(X1, Y2); + Canvas.LineTo(X3, Y2); + Canvas.MoveTo(X2 - 1, Y2); + Canvas.LineTo(X2 - 1, Y3); + Canvas.MoveTo(X2 + 1, Y2); + Canvas.LineTo(X2 + 1, Y3); + end; + #$D0: begin { Single T Double Bottom } + Canvas.MoveTo(X1, Y2); + Canvas.LineTo(X3, Y2); + Canvas.MoveTo(X2 - 1, Y2); + Canvas.LineTo(X2 - 1, Y1); + Canvas.MoveTo(X2 + 1, Y2); + Canvas.LineTo(X2 + 1, Y1); + end; + #$DB: begin { Full Block } + Canvas.Rectangle(X1, Y1, X3, Y3); + end; + #$DC: begin { Half Bottom Block } + Canvas.Rectangle(X1, Y2, X3, Y3); + end; + #$DD: begin { Half Left Block } + Canvas.Rectangle(X1, Y1, X2, Y3); + end; + #$DE: begin { Half Right Block } + Canvas.Rectangle(X2, Y1, X3, Y3); + end; + #$DF: begin { Half Top Block } + Canvas.Rectangle(X1, Y1, X2, Y2); + end; + #$C5: begin { Single Cross } + Canvas.MoveTo(X1, Y2); + Canvas.LineTo(X3, Y2); + Canvas.MoveTo(X2, Y1); + Canvas.LineTo(X2, Y3); + end; + #$CE: begin { Double Cross } + Canvas.MoveTo(X1, Y2 - 1); + Canvas.LineTo(X2 - 1, Y2 - 1); + Canvas.LineTo(X2 - 1, Y1); + Canvas.MoveTo(X1, Y2 + 1); + Canvas.LineTo(X2 - 1, Y2 + 1); + Canvas.LineTo(X2 - 1, Y3); + Canvas.MoveTo(X2 + 1, Y1); + Canvas.LineTo(X2 + 1, Y2 - 1); + Canvas.LineTo(X3, Y2 - 1); + Canvas.MoveTo(X2 + 1, Y3); + Canvas.LineTo(X2 + 1, Y2 + 1); + Canvas.LineTo(X3, Y2 + 1); + end; + #$D8: begin { Cross Double Horizontal Single vertical } + Canvas.MoveTo(X1, Y2 + 1); + Canvas.LineTo(X3, Y2 + 1); + Canvas.MoveTo(X1, Y2 - 1); + Canvas.LineTo(X3, Y2 - 1); + Canvas.MoveTo(X2, Y1); + Canvas.LineTo(X2, Y3); + end; + #$D7: begin { Cross Single Horizontal Double Vertical } + Canvas.MoveTo(X2 + 1, Y1); + Canvas.LineTo(X2 + 1, Y3); + Canvas.MoveTo(X2 - 1, Y1); + Canvas.LineTo(X2 - 1, Y3); + Canvas.MoveTo(X1, Y2); + Canvas.LineTo(X3, Y2); + end; + #$CA: begin { Double T bottom } + Canvas.MoveTo(X1, Y2 - 1); + Canvas.LineTo(X2 - 1, Y2 - 1); + Canvas.LineTo(X2 - 1, Y1); + Canvas.MoveTo(X2 + 1, Y1); + Canvas.LineTo(X2 + 1, Y2 - 1); + Canvas.LineTo(X3, Y2 - 1); + Canvas.MoveTo(X1, Y2 + 1); + Canvas.LineTo(X3, Y2 + 1); + end; + #$CB: begin { Double T } + Canvas.MoveTo(X1, Y2 + 1); + Canvas.LineTo(X2 - 1, Y2 + 1); + Canvas.LineTo(X2 - 1, Y3); + Canvas.MoveTo(X2 + 1, Y3); + Canvas.LineTo(X2 + 1, Y2 + 1); + Canvas.LineTo(X3, Y2 + 1); + Canvas.MoveTo(X1, Y2 - 1); + Canvas.LineTo(X3, Y2 - 1); + end; + #$B0: begin + Co := Canvas.Pen.Color; + for Y := Y1 to Y3 do begin + X := X1 + (Y mod 3); + while X < X3 do begin + Canvas.Pixels[X, Y] := Co; + X := X + 3; + end; + end; + end; + #$B1: begin + Co := Canvas.Pen.Color; + for Y := Y1 to Y3 do begin + X := X1 + (Y and 1); + while X < X3 do begin + Canvas.Pixels[X, Y] := Co; + X := X + 2; + end; + end; + end; + #$B2: begin + Co := Canvas.Pen.Color; + for Y := Y1 to Y3 do begin + X := X1 + (Y mod 3); + while X < X3 do begin + Canvas.Pixels[X, Y] := Co; + Inc(X); + if X < X3 then + Canvas.Pixels[X, Y] := Co; + Inc(X); + Inc(X); + end; + end; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.PaintOneLine( + DC : HDC; + Y, Y1 : Integer; + const Line : TLine; + nColFrom : Integer; + nColTo : Integer; + Blank : Boolean); +var + rc : TRect; + nCnt : Integer; + nAtt : Byte; + X : Integer; + nChr : Integer; + Ch : Char; +const + BlankLine : array [0..MAX_COL] of char = ''; +begin + nAtt := Line.Att[nColFrom]; + +{ if nAtt = $0B then + X := 0; } +{ + SetBkColor(DC, PALETTEINDEX(nAtt div $0F)); + SetTextColor(DC, PALETTEINDEX(nAtt and $0F)); +} + if not FMonoChrome then begin + with FPaletteEntries[(nAtt shr 4) and $0F] do + SetBkColor(DC, PALETTERGB(peRed, peGreen, peBlue)); + with FPaletteEntries[nAtt and $0F] do begin + SetTextColor(DC, PALETTERGB(peRed, peGreen, peBlue)); + Canvas.Pen.Color := PALETTERGB(peRed, peGreen, peBlue); + Canvas.Brush.Color := PALETTERGB(peRed, peGreen, peBlue); + end; + end + else begin + if (nAtt div $0F) <> 0 then + SetBkColor(DC, RGB(127, 127, 127)) + else + SetBkColor(DC, RGB(255, 255, 255)); + + if (nAtt and $0F) <> 0 then + SetTextColor(DC, RGB(0, 0, 0)) + else + SetTextColor(DC, RGB(255, 255, 255)); + end; + + nCnt := nColTo - nColFrom; + nChr := 0; +{$IFDEF SINGLE_CHAR_PAINT} + while nChr < nCnt do begin +{$IFDEF CHAR_ZOOM} + X := FLeftMargin + FCharPos[nColFrom + nChr]; + rc.Top := Y + FInternalLeading; + rc.Bottom := Y1 + FInternalLeading; + rc.Left := X; + rc.Right := FLeftMargin + FCharPos[nColFrom + nChr + 1]; +{$ELSE} + X := FLeftMargin + (nColFrom + nChr) * FCharWidth; + rc.Top := Y + FInternalLeading; + rc.Bottom := Y1 + FInternalLeading; + rc.Left := X; + rc.Right := rc.Left + FCharWidth; +{$ENDIF} + if (nColFrom + nChr) = 0 then + rc.Left := rc.Left - FLeftMargin; + if (nColFrom + nChr) >= FScreen.FColCount then + rc.Right := rc.Right + FRightMargin; + if Blank then + Ch := ' ' + else + Ch := Line.Txt[nColFrom + nChr]; + if FGraphicDraw and + (FScreen.FXlatOutputTable = @ibm_iso8859_1_G0) and + (Ch >= #$B0) and (Ch <= #$DF) and + (Ch in [#$B3, #$C4, #$DA, #$C0, #$C1, #$C2, #$C3, #$B4, #$BF, #$D9, + #$DB, #$DC, #$DD, #$DE, #$DF, + #$BA, #$CD, #$C9, #$C8, #$BB, #$BC, + #$CC, #$B9, #$C7, #$B6, #$D2, #$D0, + #$D5, #$D4, #$B8, #$BE, + #$C6, #$D1, #$B5, #$CF, + #$D6, #$B7, #$D3, #$BD, + #$C5, #$CE, #$D8, #$D7, #$CA, #$CB, + #$B0, #$B1, #$B2]) then + PaintGraphicChar(DC, X, Y, @rc, Ch) + else + ExtTextOut(DC, X, Y, ETO_OPAQUE or ETO_CLIPPED, @rc, @Ch, 1, nil); + Inc(nChr); + end; +{$ELSE} +{$IFDEF CHAR_ZOOM} + X := LeftMargin + FCharPos[nColFrom]; + rc.Top := Y + FInternalLeading; + rc.Bottom := Y1 + FInternalLeading; + rc.Left := X; + rc.Right := LeftMargin + FCharPos[nColFrom + nCnt]; +{$ELSE} + X := LeftMargin + nColFrom * FCharWidth; + rc.Top := Y + FInternalLeading; + rc.Bottom := Y1 + FInternalLeading; + rc.Left := X; + rc.Right := rc.Left + nCnt * FCharWidth; +{$ENDIF} + if nColFrom = 0 then + rc.Left := rc.Left - LeftMargin; + if nColTo >= FScreen.FColCount then + rc.Right := rc.Right + RightMargin; + if Blank then + ExtTextOut(DC, + X, Y, + ETO_OPAQUE or ETO_CLIPPED, @rc, + @BlankLine[0], nCnt, nil) + else + ExtTextOut(DC, + X, Y, + ETO_OPAQUE or ETO_CLIPPED, @rc, + @Line.Txt[nColFrom], nCnt, nil); +{$ENDIF} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomEmulVT.WMPaint(var Message: TWMPaint); +var + DC : HDC; + PS : TPaintStruct; + Y, Y1 : Integer; + rc : TRect; + OldPen : THandle; + OldBrush : THandle; + OldFont : THandle; + rcPaint : TRect; + DrawRct : TRect; + nRow : Integer; + nCol : Integer; + nColFrom : Integer; + Line : TLine; + BackBrush : HBrush; + BackIndex : Integer; +begin + { This may be a bit of overkill but we have to keep the scrollbar tracking + with the number of lines visible on the screen. The calling program can + change the Height of the screen and we don't have a good way to know that. + This routine will get called whenever the screen gets updated so it is a + good time to update the scrollbar. } + AdjustScrollBar; + + if not GetUpdateRect(WindowHandle, rc, FALSE) then + Exit; + + BackBrush := 0; + OldBrush := 0; + + DC := Message.DC; + if DC = 0 then + DC := BeginPaint(WindowHandle, PS); + try + if not FMonoChrome then begin + SelectPalette(DC, FPal, FALSE); + RealizePalette(DC); + if FMarginColor = -1 then + BackIndex := FScreen.FAttribute div $0F + else + BackIndex := FMarginColor mod NumPaletteEntries; + with FPaletteEntries[BackIndex] do + BackBrush := CreateSolidBrush(PALETTERGB(peRed, peGreen, peBlue)); + OldBrush := SelectObject(DC, BackBrush); + end; + + WinProcs.GetClientRect(WindowHandle, DrawRct); + rcPaint := PS.rcPaint; + rc.Left := 2; + rc.Right := DrawRct.Right - 2; + nRow := PixelToRow(rcPaint.top); + nRow := nRow - 1; + if nRow < 0 then + nRow := 0; + +{$IFDEF CHAR_ZOOM} + Y := FTopMargin + FLinePos[nRow]; + Y1 := FTopMargin + FLinePos[nRow + 1]; +{$ELSE} + Y := FTopMargin + nRow * FLineHeight; + Y1 := Y + FLineHeight; +{$ENDIF} + + if rcPaint.Top <= FTopMargin then begin + OldPen := SelectObject(DC, GetStockObject(NULL_PEN)); + WinProcs.Rectangle(DC, rcPaint.left, rcPaint.Top, + rcPaint.Right + 1, + FTopMargin + FInternalLeading + 1); + SelectObject(DC, OldPen); + end; + + if (nRow = 0) and (FInternalLeading > 0) then begin + OldPen := SelectObject(DC, GetStockObject(NULL_PEN)); + WinProcs.Rectangle(DC, rcPaint.left, rcPaint.Top, + rcPaint.Right + 1, + Y + FInternalLeading + 1); + SelectObject(DC, OldPen); + end; + + OldFont := SelectObject(DC, FFont.Handle); + nRow := nRow + FTopLine; + while nRow < FScreen.FRowCount do begin + rc.Top := Y; + rc.Bottom := Y + FLineHeight; + if rc.Bottom > (DrawRct.Bottom - FBottomMargin) then begin + OldPen := SelectObject(DC, GetStockObject(NULL_PEN)); + WinProcs.Rectangle(DC, rc.Left - 2, rc.Top, rc.Right + 1, + DrawRct.Bottom - 1); + SelectObject(DC, OldPen); + Break; + end; + Line := FScreen.Lines[nRow]; + + nCol := 0; + nColFrom := 0; + while nCol < FScreen.FColCount do begin + while (nCol < FScreen.FColCount) and + (Line.Att[nCol] = Line.Att[nColFrom]) do + Inc(nCol); + + PaintOneLine(DC, Y, Y1, Line, nColFrom, nCol, FALSE); + nColFrom := nCol; + end; + + nRow := nRow + 1; +{$IFDEF CHAR_ZOOM} + Y := FTopMargin + FLinePos[nRow - FTopLine]; + Y1 := FTopMargin + FLinePos[nRow + 1 - FTopLine]; +{$ELSE} + Y := Y + FLineHeight; + Y1 := Y + FLineHeight; +{$ENDIF} + if Y > rcPaint.Bottom then + Break; + end; + + { Fill region between last text line and bottom of the window } + OldPen := SelectObject(DC, GetStockObject(NULL_PEN)); + if (FScreen.FRowCount - FTopLine) <= MAX_ROW then begin { WM + SE 09/08/00 } + WinProcs.Rectangle(DC, rc.Left - 2, + FTopMargin + FLinePos[FScreen.FRowCount - FTopLine]{ + 1}, + rc.Right + 3, DrawRct.Bottom + 1); +{ + Line := FScreen.Lines[FScreen.FRowCount - 1]; + nCol := 0; + nColFrom := 0; + while nCol < FScreen.FColCount do begin + while (nCol < FScreen.FColCount) and + (Line.Att[nCol] = Line.Att[nColFrom]) do + Inc(nCol); + + PaintOneLine(DC, Y, Y1, Line, nColFrom, nCol, TRUE); + nColFrom := nCol; + end; +} + end; + SelectObject(DC, OldPen); + +{$IFDEF CHAR_ZOOM} + if (FLeftMargin + FCharPos[FScreen.FColCount]) < rc.Right then begin + OldPen := SelectObject(DC, GetStockObject(NULL_PEN)); + WinProcs.Rectangle(DC, FLeftMargin + FCharPos[FScreen.FColCount], + FTopMargin, { 09/03/99 } + rcPaint.Right + 1, DrawRct.Bottom + 1); + SelectObject(DC, OldPen); + end; +{$ELSE} + if (FLeftMargin + FScreen.FColCount * FCharWidth) < rc.Right then begin + OldPen := SelectObject(DC, GetStockObject(NULL_PEN)); + WinProcs.Rectangle(DC, FLeftMargin + FScreen.FColCount * FCharWidth, + FTopMargin, rc.Right + 1, DrawRct.Bottom - 1); + SelectObject(DC, OldPen); + end; +{$ENDIF} + + if FSelectRect.Top <> -1 then begin + SelectObject(DC, GetStockObject(NULL_BRUSH)); + SelectObject(DC, GetStockObject(BLACK_PEN)); + WinProcs.Rectangle(DC, FSelectRect.Left, + FSelectRect.Top, + FSelectRect.Right + 1, + FSelectRect.Bottom - 1); + SelectObject(DC, GetStockObject(WHITE_PEN)); + WinProcs.Rectangle(DC, FSelectRect.Left - 1, + FSelectRect.Top - 1, + FSelectRect.Right + 2, + FSelectRect.Bottom); + end; + + SelectObject(DC, OldFont); + if OldBrush <> 0 then + SelectObject(DC, OldBrush); + if BackBrush <> 0 then + DeleteObject(BackBrush); + finally + if Message.DC = 0 then + EndPaint(WindowHandle, PS); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Vc32/FingCli.dcu b/ICS_zlog/Delphi/Vc32/FingCli.dcu new file mode 100644 index 0000000000000000000000000000000000000000..f3818c274858dc21fcb5b8f359427a6ab6a8171b GIT binary patch literal 5930 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 + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: +Aug 20, 1999 V1.01 Added compile time options. Revised for BCB4. +Aug 18, 2001 V1.02 Angus Robertson removed + @domain from the request. + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit FingCli; + +interface + +{$B-} { Enable partial boolean evaluation } +{$T-} { Untyped pointers } +{$X+} { Enable extended syntax } +{$IFNDEF VER80} { Not for Delphi 1 } + {$H+} { Use long strings } + {$J+} { Allow typed constant to be modified } +{$ENDIF} +{$IFDEF VER110} { C++ Builder V3.0 } + {$ObjExportAll On} +{$ENDIF} +{$IFDEF VER125} { C++ Builder V4.0 } + {$ObjExportAll On} +{$ENDIF} + +uses + WinTypes, WinProcs, SysUtils, Messages, Classes, Graphics, Controls, + WSocket; + +const + FingCliVersion = 102; + CopyRight : String = ' FingCli (c) 1997-2001 F. Piette V1.02 '; + +type + TFingerCli = class(TComponent) + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure StartQuery; + function Receive(Buffer : Pointer; Len : Integer) : Integer; + procedure Abort; + protected + FWSocket : TWSocket; + FQuery : String; + FQueryDoneFlag : Boolean; + FOnSessionConnected : TSessionConnected; + FOnDataAvailable : TDataAvailable; + FOnQueryDone : TSessionClosed; + procedure WSocketDnsLookupDone(Sender: TObject; Error: Word); + procedure WSocketSessionConnected(Sender: TObject; Error: Word); + procedure WSocketDataAvailable(Sender: TObject; Error: Word); + procedure WSocketSessionClosed(Sender: TObject; Error: Word); + procedure TriggerQueryDone(Error: Word); + published + property Query : String read FQuery + write FQuery; + property OnSessionConnected : TSessionConnected read FOnSessionConnected + write FOnSessionConnected; + property OnDataAvailable : TDataAvailable read FOnDataAvailable + write FOnDataAvailable; + property OnQueryDone : TSessionClosed read FOnQueryDone + write FOnQueryDone; + end; + +procedure Register; + +implementation + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure Register; +begin + RegisterComponents('FPiette', [TFingerCli]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TFingerCli.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FWSocket := TWSocket.Create(Self); + FWSocket.OnSessionConnected := WSocketSessionConnected; + FWSocket.OnDataAvailable := WSocketDataAvailable; + FWSocket.OnSessionClosed := WSocketSessionClosed; + FWSocket.OnDnsLookupDone := WSocketDnsLookupDone; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor TFingerCli.Destroy; +begin + if Assigned(FWSocket) then + FWSocket.Destroy; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFingerCli.StartQuery; +var + I : Integer; + Host : String; +begin + I := Pos('@', FQuery); + if I <= 0 then + raise Exception.CreateFmt('TFingerCli, Invalid Query: %s', [FQuery]); + Host := Copy(FQuery, I + 1, Length(FQuery)); + if Length(Host) <= 0 then + raise Exception.CreateFmt('TFingerCli, Invalid Host in query: %s', [FQuery]); + FQueryDoneFlag := FALSE; + FWSocket.DnsLookup(Host); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFingerCli.Abort; +begin + FWSocket.CancelDnsLookup; + FWSocket.Abort; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFingerCli.Receive(Buffer : Pointer; Len : Integer) : Integer; +begin + Result := FWSocket.Receive(Buffer, Len); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFingerCli.WSocketDnsLookupDone(Sender: TObject; Error: Word); +begin + if Error <> 0 then + TriggerQueryDone(Error) + else begin + FWSocket.Addr := FWSocket.DnsResult; + FWSocket.Proto := 'tcp'; + FWSocket.Port := 'finger'; + FWSocket.Connect; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFingerCli.WSocketSessionConnected(Sender: TObject; Error: Word); +var + I: integer ; +begin + if Assigned(FOnSessionConnected) then + FOnSessionConnected(Self, Error); + + if Error <> 0 then begin + TriggerQueryDone(Error); + FWSocket.Close + end + else + begin + I := Pos('@', FQuery); { angus } + FWSocket.SendStr(copy (FQuery, 1, pred (I)) + #13 + #10); + end ; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFingerCli.WSocketDataAvailable(Sender: TObject; Error: Word); +begin + if Assigned(FOnDataAvailable) then + FOnDataAvailable(Self, Error); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFingerCli.TriggerQueryDone(Error: Word); +begin + if (FQueryDoneFlag = FALSE) and Assigned(FOnQueryDone) then + FOnQueryDone(Self, Error); + FQueryDoneFlag := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFingerCli.WSocketSessionClosed(Sender: TObject; Error: Word); +begin + TriggerQueryDone(Error); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Vc32/FtpCli.dcu b/ICS_zlog/Delphi/Vc32/FtpCli.dcu new file mode 100644 index 0000000000000000000000000000000000000000..2fe45bebfe3fcd2c153dfecbccdc120ae79f95fe GIT binary patch literal 78444 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 + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Quick Reference: + +Properties: + HostName - FTP server host name or IP address + UserName - User name for authentication on FTP server + PassWord - Passwor needed for user, can be blank + HostDirName - Directory as knwon of FTP server + HostFileName - File name as known on FTP server + LocalFileName - Local file name (complete path) + Binary - Select binary or ascii file transfert (Need to call TypeSet + or TypeSetAsync to send it to FTP server). + (There are other less used properties, see code below) + +Methods: + Open - Open the connection with the FTP server + User - Send username + Pass - Send password + Connect - Open the connection, send username and password + Quit - Disconnect gracefully from FTP server + Abort - Disconnect (close connection) immediately + AbortXfer - Abort file transfer without disconnecting. + Warning: LocalFilename property is lost after this command. + Pwd - Get current working directory + Cwd - Change Working Directory + CDup - Change to parent directory + TypeSet - Set type for file transfert (see Binary property) + TypeBinary - Set to binary type transfert and call TypeSet + TypeAscii - Set to ascii type transfert and call TypeSet + + Put - Upload a file + Transmit - Connect, Cwd, Upload a file & Quit + + Append - Upload a file, appending to existing + AppendFile - Connect, Cwd, Append a file & Quit + + Get - Download a file + Receive - Connect, Cwd, Download a file & Quit + + RestGet - Download a file, restarting from current local file size + RestartGet - Connect, Cwd, Restart downloading a file & Quit + + RestPut - Upload a file, restarting from ResumeAt property value + RestartPut - Connect, Cwd, Restart uploading a file & Quit + + Dir - Download a directory listing to a file + Directory - Connect, Cwd, Download a directory listing to a file & Quit + + Ls - Download a file name listing to a file + List - Connect, Cwd, Download a file name listing to a file & Quit + + Mkd - Create a directory on the server + Mkdir - Connect, Cwd, Create a directory on the server & Quit + + Ren - Rename a file or directory on the server + Rename - Connect, Cwd, Rename a file or directory on the server & Quit + + Dele - Delete a file on the server + Delete - Connect, Cwd, Delete a file on the server & Quit + + Rmd - Remove a directoy from the server + Rmdir - Connect, Cwd, Remove a directoy from the server & Quit + + Syst - Get system information from the server + System - Connect, Cwd, Get system information from the server & Quit + + Size - Get file size + FileSize - Connect, Cwd, get file size & Quit + + Quote - Send literal command (use LocalFileName as command to send) + DoQuote - Connect, Cwd, send literal command & Quit + + (There are two set of methods: Async and Sync. The Async are the prefered + ones to build robust applications. Their name end with Async like GetAsync) + (There are other less used methods, see code below) + +How to use a Proxy or Firewall ? + First of all, not all proxies or firewalls are the same. So have a look at + product documentation. However, most products support a transparent proxy + which doesn't require any special programming: + 1) Instead of connection to a remote FTP server, you connect to the proxy + 2) User name is replaced by user name, followed by '@' sign then followed + by target remote FTP server host name. + 3) Password is usual remote FTP server password. + 4) Most require using Passive mode. + Example: You want to connect to ftp.borland.com, using anonymous connection, + company firewall/proxy is running on host named proxyserver. + FtpCli1.HostName := 'proxyserver'; + FtpCli1.UserName := 'anonymous@ftp.borland.com'; + FtpCli1.Password := 'your.email@company'; + FtpCli1.Passive := TRUE; + +History: +Nov 04, 1996 Better error handling + Property for timeout, default to 15 sec +Dec 03, 1996 Adapted display functionnality for Delphi 2 +Dec 27, 1996 Added transmit functions + Changed all procedure to function returning boolean status +Aug 13, 1997 Added multiline response support + Added support for strange Microsoft PWS FTP behaviour +Sep 10, 1997 Added support for Dir and Ls commands + Corrected bugs to enable correct use of separate commands +Oct 16, 1997 V2.07 Adapted for changes in TWSocket object + Added FtpCliVersion constant +Nov 25, 1997 V2.08 Accept 250 as well as 226 for succesfull file transfert + Suggested by fdragon@world-net.net +Nov 26, 1997 V2.09 don't display error message in the receive event when + the socket is no more connected. +Nov 29, 1997 V2.10 added Mkd and Mkdir functions to create a directory. + As suggested by Christian Rösner +Dec 04, 1997 V2.11 Added Ren, Dele, Rmd functions + As suggested by Frank Riemann + Changed Mkd and Mkdir functions to take HostFileName to + specify the directory name. This is more consistent with the + rest of the component usage. +Dec 29, 1997 V2.12 Added a TrimLeft function for Delphi 1 +Dec 30, 1997 V2.13 Added Syst and System commands as suggested by + Fire Dragon + Added the LastResponse property + Corrected a message ("Daniel Fazekas" ) +Jan 10, 1998 V2.14 Accept response 150 and 125 for Get Submitted by Fire + Dragon . + Added a quick reference for most used properties and methods. + Made TFtpCli a TComponent descendant. + Added the Size, FileSize, Quote, DoQuote, RestartGet method. + Made ControlSocket a readonly property (allow easy DNSLookup). + Added a Port property. +Jan 25, 1998 V2.15 + Completely revised to make it asynchronous. + This means that a new set of functions is born. They all have + a name ending with Async. For example GetAsync. Asynchronous + means that when you call the function, it returns almost + immediately. The operation is done in the background. + The asynchronous operation allows to make several request + simultaneously WITHOUT using threads. Just use two or more + TFtpClient and call each GetAsync (or other) method as those + method returns almost instantly, all the request will be done + in the background, generating the OnRequestDone when finished. + Added a State property + This allows to check for component work in the background. + You can call methods only when State = ftpReady (except the + Abort method which can be called at any time) + The Asynchronous methods are the prefered ones. + + Added Pwd command + Returns the current working directory on the server. + + Added CDup command + Change to parrent directory on FTP server. + + Added DirResult property + Parse the LastResponse property to return the directory. + Do no always work when the server returns multi-line responses. + (updated by Pwd, Cwd, CDup and Mkd commands). + + Changed function IsConnected to Connected, a read-only property. + It's more object oriented. + + Replaced file I/O by stream I/O. + It's the first step to allow Stream I/O outside of the component. + + New sample application (Delphi only now, CPP later). + Every command has now a button to excercize it + (async version only) + + The synchronous commands (old commands) are implemented by + calling the asynchronous version and waiting. + + Multi-threaded property + Tells the component how to wait for command completion. + + Removed the TWait component use. + No need to have a TWait component. +Jan 31, 1998 V2.16 Accept response 150 and 125 for Put. +Feb 01, 1998 V2.17 Added intermediate message for OnRequestDone event +Feb 02, 1998 V2.18 Corrected a bug: all sync function returned always FALSE. + Added User and Pass synchronous functions. + Made PutAsync return ftpPutAsync in the OnrequestDone event. +Feb 04, 1998 V2.19 Added an OnCommand event to give a chance to the user to + modify the commands to make some custom commands. Also added the + OnResponse event to allow custom commands to get the response + and alter it as necessary. +Feb 15, 1998 V2.20 Added a FindClose after the FindFirst in GetFileSize routine + as pointed by "Daniel Fazekas" +Feb 21, 1998 V2.21 Enabled progress updated on put +Feb 22, 1998 V2.22 Accept result code 250 after Put command + Implemented Append and AppendFile commands +Mar 07, 1998 V2.23 Made RequestType a R/O property +Mar 15, 1998 V2.24 Reordered PORT/REST/RETR + Added a port command + The ByteCount passed to OnProgress now take into account the + restart byte offset. + Renamed Display to TriggerDisplay and made it virtual + Used TriggerDisplay everywhere. + Modified the Timeout mechanism to reset the timeout each + time the OnProgress event is called. + Abort command call CancelDnsLookup approprietedly +Mar 27, 1998 V2.25 Adapted for C++Builder 3 +Avr 01, 1998 V2.26 Made a valid LastResponse and ErrorMessage when DNS lookup + failed. Added some compiler options. +Apr 10, 1998 V2.27 Added some ftpFctCwd in some highlevel functions. + Suggested by Ray Andrews . +Apr 13, 1998 V2.28 Save error code when the data connection is closed to use + it later to return the status for file transfert. + Implemented passive mode, with help from Yaron Golan + . A new property Passive enable this mode. + Put do not work [yet] is passive mode. +Apr 14, 1998 V2.29 Made passive mode PUT work. + Added ShareMode property (see TFileStream.Create on-line help) + Made ResumeAt property. +Apr 15, 1998 V2.30 Added the OnReadyToTransmit event. + Correctly handled error when local file not found. + Checked if socket connected in SendCommand +Apr 22, 1998 V2.31 Corrected CDupAsync procedure (thanks to Eric + Engler englere@swcp.com) +Apr 26, 1998 V2.32 Added TypeBinary and TypeAscii just to help a little bit. +May 01, 1998 V2.33 Added check for continuation lines in NextxPutAsync +May 05, 1998 V2.34 Added some more delay in WMFtpCloseData. +May 13, 1998 V2.35 In passive mode STOR or APPE, changed the sequence: now + wait for connection established before sending the STOR or APPE + command to FTP server. +May 19, 1998 V2.36 TransfertStats made virtual. +Jun 25, 1998 V2.37 Revised code for 'connection reset by peer' syndrome +Jul 09, 1998 V2.38 Adpted for Delphi 4 +Jul 23, 1998 V2.39 Made ResumeAt property R/W + Added code from Yaron Golan to fix PASV + REST + and to add OnDisplayFile code to view a file on the fly. +Aug 04, 1998 V2.40 Frank Neuhaus found a problem in Put command + for some FTP server. See V240 in the comments. +Aug 12, 1998 V2.41 Added 200 to the valid CWD responses. +Aug 18, 1998 V2.42 Added code to accept continuation lines not beginning by + a number and a dash. Thanks to Al Cantu + for pointing this problem. +Sep 16, 1998 V2.43 Made Synchronize and WaitUntilReady virtual function in + protected section. +Oct 01, 1998 V2.44 Checked for errors in TriggerRequestDone. +Nov 09, 1998 V2.45 Reverted V2.40 changes ! Thanks to Grant Walker + for his help in testing. + Made block size equal to 1514 to minimize packet fragmentation + on ethernet. +Nov 22, 1998 V2.46 changed GetTickCount cast from Integer to LongInt because + of overflows with Delphi 1. Suggested by Terry Byrne + +Dec 22, 1998 V2.47 Corrected DisplayFile which forgot the last character. + Thanks to max@zab1.chita.ru for the bug report. + Handled exceptions while trying to connect data session. + Replaced DisplayFlag by DysplayFileFlag. +Feb 14, 1999 V2.48 Indirectly call winsock functions using wsocket because + wsocket provide runtime dynamic link instead of loadtime link. + This allows a program to use FTP if it discover that winsock is + installed and still run if winsock is not installed. +Mar 13, 1999 V2.49 Added FPutSessionOpened flag and combine it with + FStorAnswerRcvd flag to synchronize start of data sending. + Thanks to Frank Neuhaus for his clear analysis. +Mar 20, 1999 V2.50 Added Options property +Mar 23, 1999 V2.51 Corrected a bug introcuded in last version which truncated + the first character of the second line of a multiline answer on + some servers. +May 04, 1999 V2.52 Corrected an access violation in DataSocketGetDataAvailable. + Thanks to Steve Plegge for pointing that bug. +May 21, 1999 V2.53 Added FRequestResult to ControlSocketDnsLookupDone. Thanks + to Wu'hao for finding this bug. +Jul 17, 1999 V2.54 Added OnError event and DisplayFileMode property. Thanks to + Pieter Snyman for his work. + Accepted answer 200 for successful rename. + Leho Kraav found that some FTP server return + this code. + Cleared FByteCount from PortAsync as suggested by Simon Hoerup + to help some progress indicator implementation. +Aug 04, 1999 V2.55 Corrected a bug with Delphi 1 where a buffer overflow may + occurs when receiving commands longer than 254 bytes. + Thanks to Craig Johnson for finding it. + Also casted FTimeOut to LongInt for computation to prevent + overflow with Delphi 1 for long timeout. +Aug 12, 1999 V2.56 HandleError was not correctly handling error message ! + thank to Kim Mølgård Nielsen +Aug 20, 1999 V2.57 Revised conditional compilation, adapted for BCB4, set + compile options same as TWSocket. + Added DnsResult property as suggested by Heedong Lim + . This property is accessible from + OnStateChange when state is ftpWaitingBanner. + Added checks for FLocalStream being destroyed. +Sep 5, 1999 V2.58 Heedong Lim found a missing + assignation to FRequestResult in ControlSocketSessionConnected. +Sep 11, 1999 V2.59 Added OnBgException. Thanks to William Sorensen + for suggesting it. +Oct 30, 1999 V2.60 Changed TargetPort and DataPort from integer to WORD so + that Delphi 1 is able to handle port greater than 32K. Bug and + and fix by Duncan Gold . +Nov 22, 1999 V2.61 Allow continuation lines in all responses. +Nov 24, 1999 V2.62 RestPut command by Alexander Burlakov + Added RestartPut. Added ftpNoAutoResumeAt option. +Dec 26, 1999 V2.63 Corrected a bug in DoPutAppendAsync. +Jan 24, 1999 V2.64 Added LongInt cast to all GetTickCount. +Apr 01, 2000 V2.65 Removed any set of integer. + Thanks to Grant Black , + Davie and + Stephen Williams for their work on + this subject. +Apr 09, 2000 V2.66 Proxy / Socks / Local streams support added. + Pieter Snyman added proxy and socks support. + Eric added stream support (assign LocalStream + property to switch to stream mode and LocalFileName to switch to + normal file mode). +Jun 10, 2000 V2.67 Added NOFORMS conditional compile to be able to build a + program (console mode, dll or other) without using the forms unit + (because forms unit makes programs much bigger). See NOFORMS + related comments in wsocket.pas source file for correct use. + See also OnMessagePump event and Terminated property. +Jul 15, 2000 V2.68 Added ProxyPort property. Handled non standard port when + connecting thru proxy. +Jul 21, 2000 V2.69 Implemented check for ABOR, STAT and QUIT commands so that + it doesn't check if previous command is done. + By Davie . + Tomas Lannestedt found a bug when using + streams. Now it correctly handled stream clearing. +Sep 17, 2000 V2.70 Eugene Mayevski moved Controls use + out of NOFORMS way. +Nov 11, 2000 V2.71 Cleared FErrorMessage in ExecAsync. Thanks to Jake Traynham + for finding this bug. +Nov 30, 2000 V2.72 Added a Sleep in DataSocketPutDataSent, and use CloseDelayed + this will prevent some trucated file transfers. +Feb 17, 2001 V2.73 Better WaitUntilReady: check also ftpInternalReady. + By Davie . +Jun 16, 2001 V2.74 Added conditional compile for Delphi 6 +Jun 18, 2001 V2.75 Use AllocateHWnd and DeallocateHWnd from wsocket. +Jul 26, 2001 V2.76 Accept range 150-159 for status code after RETR command. + Peter Calum found some FTP server returning + unusual status code (and not conforming to RFC !). I don't like to + work arround other's bugs, but in this case this shouldn't hurt + anything. +Jul 28, 2001 V2.77 Cleared FNextRequest in HighLevelAsync and TriggerRequestDone + as suggested by Davie . + Added AbortXfer and AbortXferAsync to abort a running transfert + without breaking connection. +Sep 09, 2001 V2.78 Beat Boegli added LocalAddr property + for multihomed hosts. +Sep 13, 2001 V2.79 Bug fix by Beat Boegli related to + his previous changes. Now works with passive mode put. +Nov 02, 2001 V2.80 Added DisplayLastResponse in ControlSocketDataAvailable to + give continuation lines to OnDisplay event. + Accept 250 answer as well as 257 for MKD command as suggested by + Simon Horup . +Feb 12, 2002 V2.82 "Soltann" added code to extract IP + from passive mode reply so that transfer from another server is + possible (See TargetIP in code). +Apr 06, 2002 V2.83 Added code 257 to allowed code list for CDUpAsync as + suggest by . + Fixed a problem in ControlSocketSessionClosed where error code was + not checked. Bug found by . +Apr 20, 2002 V2.84 Removed useless units from uses clause. +Jun 28, 2002 V2.85 Removed check for ftpFctPut and FPassive in + TriggerRequestDone which cause trouble with passive mode and sync + operation. Thanks to "Gunnar" . +Oct 26, 2002 V2.85 Use wsoNoReceiveLoop option with data session. + Set OnSessionAvalable hanlder before calling listen as suggested + by Gunnar . +Nov 11, 2002 V2.86 Changed FtpCliDeallocateHWnd argument from HWND to Cardinal + becasue BCB doesn't like HWND when deriving acomponent from + TFtpCli (BCB bug ?). + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit FtpCli; + +{$B-} { Enable partial boolean evaluation } +{$T-} { Untyped pointers } +{$X+} { Enable extended syntax } +{$IFNDEF VER80} { Not for Delphi 1 } + {$H+} { Use long strings } + {$J+} { Allow typed constant to be modified } +{$ENDIF} +{$IFDEF VER110} { C++ Builder V3.0 } + {$ObjExportAll On} +{$ENDIF} +{$IFDEF VER125} { C++ Builder V4.0 } + {$ObjExportAll On} +{$ENDIF} +{$IFDEF VER130} { C++ Builder V5.0 } + {$ObjExportAll On} +{$ENDIF} +{$IFDEF VER140} { C++ Builder V6.0 } + {$ObjExportAll On} +{$ENDIF} +{_DEFINE TRACE} + + +interface + +uses + SysUtils, WinTypes, WinProcs, Messages, Classes, +{$IFNDEF NOFORMS} + Forms, Controls, +{$ENDIF} + WSocket; + +const + FtpCliVersion = 286; + CopyRight : String = ' TFtpCli (c) 1996-2002 F. Piette V2.86 '; + +const + BLOCK_SIZE = 1460; { 1514 - TCP header size } + WM_FTP_REQUEST_DONE = WM_USER + 1; + WM_FTP_SENDDATA = WM_USER + 2; +{$IFDEF VER80} + { Delphi 1 has a 255 characters string limitation } + FTP_RCV_BUF_SIZE = 255; +{$ELSE} + FTP_RCV_BUF_SIZE = 4096; +{$ENDIF} + +type + TFtpOption = (ftpAcceptLF, ftpNoAutoResumeAt); + TFtpOptions = set of TFtpOption; + TFtpState = (ftpNotConnected, ftpReady, ftpInternalReady, + ftpDnsLookup, ftpConnected, ftpAbort, + ftpInternalAbort, ftpWaitingBanner, ftpWaitingResponse, + ftpPasvReady); + TFtpRequest = (ftpNone, ftpOpenAsync, ftpUserAsync, + ftpPassAsync, ftpCwdAsync, ftpConnectAsync, + ftpReceiveAsync, ftpDirAsync, ftpLsAsync, + ftpPortAsync, ftpGetAsync, ftpDirectoryAsync, + ftpListAsync, ftpSystemAsync, ftpSystAsync, + ftpQuitAsync, ftpAbortXferAsync, + ftpSizeAsync, ftpPutAsync, ftpAppendAsync, + ftpFileSizeAsync, ftpRqAbort, ftpMkdAsync, + ftpRmdAsync, ftpRenameAsync, ftpDeleAsync, + ftpRenAsync, ftpRenToAsync, ftpRenFromAsync, + ftpDeleteAsync, ftpMkdirAsync, ftpRmdirAsync, + ftpPwdAsync, ftpQuoteAsync, ftpCDupAsync, + ftpDoQuoteAsync, ftpTransmitAsync, ftpTypeSetAsync, + ftpRestAsync, ftpRestGetAsync, ftpRestartGetAsync, + ftpRestPutAsync, ftpRestartPutAsync); + TFtpFct = (ftpFctNone, ftpFctOpen, ftpFctUser, + ftpFctPass, ftpFctCwd, ftpFctSize, + ftpFctMkd, ftpFctRmd, ftpFctRenFrom, + ftpFctRenTo, ftpFctGet, ftpFctDir, + ftpFctQuit, ftpFctSyst, ftpFctDele, + ftpFctPwd, ftpFctQuote, ftpFctPut, + ftpFctTypeSet, ftpFctRest, ftpFctCDup, + ftpFctLs, ftpFctAppend, ftpFctPort, + ftpFctAbortXfer); + TFtpFctSet = set of TFtpFct; + TFtpShareMode = (ftpShareCompat, ftpShareExclusive, + ftpShareDenyWrite, ftpShareDenyRead, + ftpShareDenyNone); + TFtpDisplayFileMode = (ftpLineByLine, ftpBinary); + TFtpConnectionType = (ftpDirect, ftpProxy, ftpSocks4, ftpSocks4A, ftpSocks5); + TFtpDisplay = procedure(Sender : TObject; + var Msg : String) of object; + TFtpProgress = procedure(Sender : TObject; + Count : LongInt; + var Abort : Boolean) of object; + TFtpCommand = procedure(Sender : TObject; + var Cmd : String) of object; + TFtpRequestDone = procedure(Sender : TObject; + RqType : TFtpRequest; + Error : Word) of object; + TFtpReadyToTransmit = procedure(Sender : TObject; + var bCancel : Boolean) of object; + TFtpNextProc = procedure of object; + + FtpException = class(Exception); + + TCustomFtpCli = class(TComponent) + protected + FWindowHandle : HWND; + FHostName : String; + FPort : String; + FLocalAddr : String; {bb} + FUserName : String; + FPassWord : String; + FLocalFileName : String; + FHostFileName : String; + FHostDirName : String; + FDnsResult : String; + FType : Char; + FShareMode : Word; + FDisplayFileMode : TFtpDisplayFileMode; + FConnectionType : TFTPConnectionType; + FProxyServer : String; + FProxyPort : String; + FAppendFlag : Boolean; + FDisplayFileFlag : Boolean; + FControlSocket : TWSocket; + FDataSocket : TWSocket; + FStartTime : LongInt; + FStopTime : LongInt; + FState : TFtpState; + FStatusCode : LongInt; + FRequestResult : Integer; + FFctSet : TFtpFctSet; + FFctPrv : TFtpFct; + FHighLevelResult : Integer; + FHighLevelFlag : Boolean; + FRestartFlag : Boolean; + FOptions : TFtpOptions; + FOnDisplay : TFtpDisplay; + FOnDisplayFile : TFtpDisplay; + FOnError : TFtpDisplay; + FOnCommand : TFtpCommand; + FOnResponse : TNotifyEvent; + FOnSessionConnected : TSessionConnected; + FOnSessionClosed : TSessionClosed; + FOnStateChange : TNotifyEvent; + FOnRequestDone : TFtpRequestDone; + FOnProgress : TFtpProgress; + FOnReadyToTransmit : TFtpReadyToTransmit; + FOnBgException : TBgExceptionEvent; + FLocalStream : TStream; + FRequestType : TFtpRequest; + FRequestDoneFlag : Boolean; + FReceiveBuffer : array [0..FTP_RCV_BUF_SIZE - 1] of char; + FReceiveLen : Integer; + FLastResponse : String; + FLastResponseSave : String; { To save FLastResponse when quitting } + FPasvResponse : String; { To fix REST + PASV transfers } + FStatusCodeSave : LongInt; { To save FStatusCode when quitting } + FErrorMessage : String; + FError : Word; { To save Error when data connection closed } + FGetCommand : String; + FConnected : Boolean; + FSendBuffer : array [0..BLOCK_SIZE - 1] of char; + FByteCount : LongInt; + FSizeResult : LongInt; + FDirResult : String; + FResumeAt : LongInt; + FNext : TFtpNextProc; + FWhenConnected : TFtpNextProc; + FDoneAsync : TFtpNextProc; + FOkResponses : array [0..15] of Integer; + FNextRequest : TFtpNextProc; + FServerSaidDone : Boolean; + FFileReceived : Boolean; + FFileSent : Boolean; + FPassive : Boolean; + FEofFlag : Boolean; + FStorAnswerRcvd : Boolean; + FPutSessionOpened : Boolean; + FStreamFlag : Boolean; + procedure SetErrorMessage; + procedure DataSocketGetDataAvailable(Sender: TObject; Error : word); + procedure DataSocketGetSessionConnected(Sender: TObject; Error : word); + procedure DataSocketPutSessionConnected(Sender: TObject; Error : word); + procedure DataSocketGetSessionAvailable(Sender: TObject; Error : word); + procedure DataSocketGetSessionClosed(Sender: TObject; Error : word); + procedure DataSocketPutDataAvailable(Sender: TObject; Error : word); + procedure DataSocketPutDataSent(Sender: TObject; Error : word); + procedure DataSocketPutSessionAvailable(Sender: TObject; Error : word); + procedure DataSocketPutSessionClosed(Sender: TObject; Error : word); + procedure SendCommand(Cmd : String); virtual; + procedure TriggerDisplay(Msg : String); virtual; + procedure TriggerReadyToTransmit(var bCancel : Boolean); virtual; + procedure TriggerDisplayFile(Msg : String); virtual; + procedure TriggerError(Msg: string); virtual; + procedure DisplayLastResponse; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + function Progress : Boolean; virtual; + procedure ControlSocketDnsLookupDone(Sender: TObject; Error: Word); + procedure ControlSocketSessionConnected(Sender: TObject; Error: Word); + procedure ControlSocketDataAvailable(Sender: TObject; Error: Word); + procedure ControlSocketSessionClosed(Sender: TObject; Error: Word); + procedure TriggerRequestDone(Error: Word); + procedure TriggerStateChange; + procedure StateChange(NewState : TFtpState); + procedure PortAsync; virtual; + procedure DoneQuitAsync; + procedure ExecAsync(RqType : TFtpRequest; + Cmd : String; + OkResponses : array of Word; + DoneAsync : TFtpNextProc); + procedure NextExecAsync; + procedure DoGetAsync(RqType : TFtpRequest); + procedure Next1GetAsync; + procedure Next2GetAsync; + procedure Next3GetAsync; + procedure Next1PutAsync; + procedure Next2PutAsync; + procedure Next3PutAsync; + procedure DoHighLevelAsync; + procedure DoPutAppendAsync; + procedure HighLevelAsync(RqType : TFtpRequest; Fcts : TFtpFctSet); + procedure HandleError(const Msg : String); + function CheckReady : Boolean; + procedure TransfertStats; virtual; + procedure ExtractMoreResults; + procedure SetBinary(Value: Boolean); + function GetBinary: Boolean; + function GetConnected: Boolean; + procedure SetShareMode(newValue: TFtpShareMode); + function GetShareMode: TFtpShareMode; + procedure SetDisplayFileMode(NewValue: TFtpDisplayFileMode); + function GetDisplayFileMode: TFtpDisplayFileMode; + procedure SetConnectionType(NewValue: TFtpConnectionType); + function GetConnectionType: TFtpConnectionType; + procedure SetSocksPassword(NewValue: string); + function GetSocksPassword: string; + procedure SetSocksPort(NewValue: string); + function GetSocksPort: string; + procedure SetSocksServer(NewValue: string); + function GetSocksServer: string; + procedure SetSocksUserCode(NewValue: string); + function GetSocksUserCode: string; + procedure SetPassive(NewValue: Boolean); + procedure WndProc(var MsgRec: TMessage); virtual; + function FtpCliAllocateHWnd(Method: TWndMethod): HWND; virtual; + procedure FtpCliDeallocateHWnd(WHandle: Cardinal); virtual; + procedure HandleBackGroundException(E: Exception); virtual; + procedure WMFtpRequestDone(var msg: TMessage); + message WM_FTP_REQUEST_DONE; + procedure WMFtpSendData(var msg: TMessage); + message WM_FTP_SENDDATA; + procedure DestroyLocalStream; + procedure SetLocalStream (Stream:TStream); + procedure SetLocalFileName (FileName:String); + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + + procedure OpenAsync; virtual; + procedure UserAsync; virtual; + procedure PassAsync; virtual; + procedure ConnectAsync; virtual; + procedure QuitAsync; virtual; + procedure AbortAsync; virtual; + procedure GetAsync; virtual; + procedure ExecGetAsync; virtual; + procedure ReceiveAsync; virtual; + procedure PutAsync; virtual; + procedure ExecPutAsync; virtual; + procedure TransmitAsync; virtual; + procedure AppendAsync; virtual; + procedure ExecAppendAsync; virtual; + procedure AppendFileAsync; virtual; + procedure ExecDirAsync; virtual; + procedure DirAsync; virtual; + procedure ExecLsAsync; virtual; + procedure LsAsync; virtual; + procedure TypeSetAsync; virtual; + procedure TypeBinaryAsync; virtual; + procedure TypeAsciiAsync; virtual; + procedure PwdAsync; virtual; + procedure CwdAsync; virtual; + procedure CDupAsync; virtual; + procedure DirectoryAsync; virtual; + procedure ListAsync; virtual; + procedure SystAsync; virtual; + procedure SystemAsync; virtual; + procedure SizeAsync; virtual; + procedure FileSizeAsync; virtual; + procedure MkdAsync; virtual; + procedure MkdirAsync; virtual; + procedure RmdAsync; virtual; + procedure RmdirAsync; virtual; + procedure DeleAsync; virtual; + procedure DeleteAsync; virtual; + procedure RenFromAsync; virtual; + procedure RenToAsync; virtual; + procedure RenAsync; virtual; + procedure RenameAsync; virtual; + procedure QuoteAsync; virtual; + procedure DoQuoteAsync; virtual; + procedure AbortXferAsync; virtual; + procedure RestAsync; virtual; + procedure RestGetAsync; virtual; + procedure RestartGetAsync; virtual; + procedure RestPutAsync; virtual; + procedure RestartPutAsync; virtual; + + property Handle : HWND read FWindowHandle; + property LastResponse : String read FLastResponse; + property ErrorMessage : String read FErrorMessage; + property DnsResult : String read FDnsResult; + property SizeResult : LongInt read FSizeResult; + property DirResult : String read FDirResult; + property ControlSocket : TWSocket read FControlSocket; + property DataSocket : TWSocket read FDataSocket; + property Connected : Boolean read GetConnected; + property StatusCode : LongInt read FStatusCode; + property ByteCount : LongInt read FByteCount; + property State : TFtpState read FState; + property RequestType : TFtpRequest read FRequestType; + property Options : TFtpOptions read FOptions + write FOptions; + property LocalStream : TStream read FLocalStream + write SetLocalStream; + property ResumeAt : LongInt read FResumeAt + write FResumeAt; + property HostName : String read FHostName + write FHostName; + property Port : String read FPort + write FPort; + property LocalAddr : String read FLocalAddr + write FLocalAddr; {bb} + property UserName : String read FUserName + write FUserName; + property PassWord : String read FPassWord + write FPassWord; + property HostDirName : String read FHostDirName + write FHostDirName; + property HostFileName : String read FHostFileName + write FHostFileName; + property LocalFileName : String read FLocalFileName + write SetLocalFileName; + property DisplayFileFlag : Boolean read FDisplayFileFlag + write FDisplayFileFlag; + property Binary : Boolean read GetBinary + write SetBinary; + property Passive : Boolean read FPassive + write SetPassive; + property ShareMode : TFtpShareMode read GetShareMode + write SetShareMode; + property DisplayFileMode : TFtpDisplayFileMode read GetDisplayFileMode + write SetDisplayFileMode; + property ConnectionType : TFtpConnectionType read GetConnectionType + write SetConnectionType; + property ProxyServer : string read FProxyServer + write FProxyServer; + property ProxyPort : string read FProxyPort + write FProxyPort; + property SocksPassword : string read GetSocksPassword + write SetSocksPassword; + property SocksPort : string read GetSocksPort + write SetSocksPort; + property SocksServer : string read GetSocksServer + write SetSocksServer; + property SocksUserCode : string read GetSocksUserCode + write SetSocksUserCode; + property OnDisplay : TFtpDisplay read FOnDisplay + write FOnDisplay; + property OnDisplayFile : TFtpDisplay read FOnDisplayFile + write FOnDisplayFile; + property OnError : TFTPDisplay read FOnError + write FOnError; + property OnCommand : TFtpCommand read FOnCommand + write FOnCommand; + property OnResponse : TNotifyEvent read FOnResponse + write FOnResponse; + property OnProgress : TFtpProgress read FOnProgress + write FOnProgress; + property OnSessionConnected : TSessionConnected read FOnSessionConnected + write FOnSessionConnected; + property OnSessionClosed : TSessionClosed read FOnSessionClosed + write FOnSessionClosed; + property OnRequestDone : TFtpRequestDone read FOnRequestDone + write FOnRequestDone; + property OnStateChange : TNotifyEvent read FOnStateChange + write FOnStateChange; + property OnReadyToTransmit : TFtpReadyToTransmit read FOnReadyToTransmit + write FOnReadyToTransmit; + property OnBgException : TBgExceptionEvent read FOnBgException + write FOnBgException; + end; + + TFtpClient = class(TCustomFtpCli) + protected + FTimeout : Integer; { Given in seconds } + FTimeStop : LongInt; { Milli-seconds } + FMultiThreaded : Boolean; + FTerminated : Boolean; + FOnMessagePump : TNotifyEvent; + function Progress : Boolean; override; + function Synchronize(Proc : TFtpNextProc) : Boolean; virtual; + function WaitUntilReady : Boolean; virtual; + public + constructor Create(AOwner: TComponent); override; + procedure MessagePump; + function Open : Boolean; + function User : Boolean; + function Pass : Boolean; + function Connect : Boolean; + function Cwd : Boolean; + function Pwd : Boolean; + function CDup : Boolean; + function TypeSet : Boolean; + function TypeBinary : Boolean; + function TypeAscii : Boolean; + function Get : Boolean; + function Put : Boolean; + function RestPut : Boolean; + function RestartPut : Boolean; + function Quit : Boolean; + function Abort : Boolean; + function Receive : Boolean; + function Transmit : Boolean; + function Append : Boolean; + function AppendFile : Boolean; + function Dir : Boolean; + function Directory : Boolean; + function Ls : Boolean; + function List : Boolean; + function Mkd : Boolean; + function Mkdir : Boolean; + function Ren : Boolean; + function Rename : Boolean; + function Dele : Boolean; + function Delete : Boolean; + function Rmd : Boolean; + function Rmdir : Boolean; + function Syst : Boolean; + function System : Boolean; + function Size : Boolean; + function FileSize : Boolean; + function Quote : Boolean; + function DoQuote : Boolean; + function AbortXfer : Boolean; + function RestGet : Boolean; + function RestartGet : Boolean; +{$IFDEF NOFORMS} + property Terminated : Boolean read FTerminated + write FTerminated; + property OnMessagePump : TNotifyEvent read FOnMessagePump + write FOnMessagePump; +{$ENDIF} + published + property Timeout : Integer read FTimeout write FTimeout; + property MultiThreaded : Boolean read FMultiThreaded write FMultiThreaded; + property HostName; + property Port; + property LocalAddr; {bb} + property UserName; + property PassWord; + property HostDirName; + property HostFileName; + property LocalFileName; + property DisplayFileFlag; + property Binary; + property ErrorMessage; + property ShareMode; + property Options; + property ConnectionType; + property ProxyServer; + property SocksPassword; + property SocksPort; + property SocksServer; + property SocksUserCode; + property OnDisplay; + property OnDisplayFile; + property OnCommand; + property OnResponse; + property OnProgress; + property OnSessionConnected; + property OnSessionClosed; + property OnRequestDone; + property OnStateChange; + property OnReadyToTransmit; + property OnBgException; + end; + +procedure Register; + +implementation + +uses WinSock; + +{$IFNDEF WIN32} +const + HFILE_ERROR = $FFFF; +{$ENDIF} + +{$B-} { Do not evaluate boolean expressions more than necessary } + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure Register; +begin + RegisterComponents('FPiette', [TFtpClient]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFNDEF WIN32} +procedure SetLength(var Str : String; Len : Integer); +begin + Str[0] := chr(Len); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +function TrimLeft(Str : String) : String; +var + i : Integer; +begin + if Str[1] <> ' ' then + Result := Str + else begin + i := 1; + while (i <= Length(Str)) and (Str[i] = ' ') do + i := i + 1; + Result := Copy(Str, i, Length(Str) - i + 1); + end; +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function GetFileSize(const FileName: string): LongInt; +var + SearchRec: TSearchRec; +begin + if FindFirst(ExpandFileName(FileName), faAnyFile, SearchRec) = 0 then begin + Result := SearchRec.Size; + SysUtils.FindClose(SearchRec); + end + else + Result := -1; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Step over blank spaces } +function StpBlk(Data : PChar) : PChar; +begin + Result := Data; + if Result <> nil then begin + while (Result^ <> #0) and (Result^ in [' ', #9, #13, #10]) do + Inc(Result); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function GetInteger(Data : PChar; var Number : LongInt) : PChar; +var + bSign : Boolean; +begin + Number := 0; + Result := StpBlk(Data); + + if (Result = nil) then + Exit; + + { Remember the sign } + if Result^ in ['-', '+'] then begin + bSign := (Result^ = '-'); + Inc(Result); + end + else + bSign := FALSE; + + { Convert any number } + while (Result^ <> #0) and (Result^ in ['0'..'9']) do begin + Number := Number * 10 + ord(Result^) - ord('0'); + Inc(Result); + end; + + { Correct for sign } + if bSign then + Number := -Number; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function GetQuotedString(Data : PChar; var Dst : String) : PChar; +begin + Dst := ''; + Result := StpBlk(Data); + + if (Result = nil) then + Exit; + + if Result^ <> '"' then + Exit; + Inc(Result); + + while Result^ <> #0 do begin + if Result^ <> '"' then + Dst := Dst + Result^ + else begin + Inc(Result); + if Result^ <> '"' then + Break; + Dst := Dst + Result^; + end; + Inc(Result); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* * * *} +{* * TCustomFtpCli * *} +{* * * *} +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF NOFORMS} +{ This function is a callback function. It means that it is called by } +{ windows. This is the very low level message handler procedure setup to } +{ handle the message sent by windows (winsock) to handle messages. } +function FtpCliWindowProc( + ahWnd : HWND; + auMsg : Integer; + awParam : WPARAM; + alParam : LPARAM): Integer; stdcall; +var + Obj : TObject; + MsgRec : TMessage; +begin + { At window creation asked windows to store a pointer to our object } + Obj := TObject(GetWindowLong(ahWnd, 0)); + + { If the pointer doesn't represent a TCustomFtpCli, just call the default procedure} + if not (Obj is TCustomFtpCli) then + Result := DefWindowProc(ahWnd, auMsg, awParam, alParam) + else begin + { Delphi use a TMessage type to pass parameter to his own kind of } + { windows procedure. So we are doing the same... } + MsgRec.Msg := auMsg; + MsgRec.wParam := awParam; + MsgRec.lParam := alParam; + { May be a try/except around next line is needed. Not sure ! } + TCustomFtpCli(Obj).WndProc(MsgRec); + Result := MsgRec.Result; + end; +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomFtpCli.FtpCliAllocateHWnd(Method: TWndMethod) : HWND; +begin +{$IFDEF NOFORMS} + Result := XSocketAllocateHWnd(Self); + SetWindowLong(Result, GWL_WNDPROC, LongInt(@FtpCliWindowProc)); +{$ELSE} + { If you have AllocateHWnd undifined, then your last project was } + { compiled with NOFORMS defined. Just recompile everything for } + { the new project. This will recompile wsocket.pas according to } + { this project settings. } + Result := WSocket.AllocateHWnd(Method); +{$ENDIF} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.FtpCliDeallocateHWnd(WHandle : Cardinal); +begin +{$IFDEF NOFORMS} + XSocketDeallocateHWnd(WHandle); +{$ELSE} + WSocket.DeallocateHWnd(WHandle); +{$ENDIF} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TCustomFtpCli.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + + FWindowHandle := FtpCliAllocateHWnd(WndProc); + FOnDisplay := nil; + FOnDisplayFile := nil; + FType := 'I'; + FPort := 'ftp'; + FProxyPort := 'ftp'; + FState := ftpReady; + FShareMode := fmShareExclusive; + FConnectionType:= ftpDirect; + FProxyServer := ''; { Should Socks properties be set to '' as well? } + FOptions := [ftpAcceptLF]; + FLocalAddr := '0.0.0.0'; {bb} + FControlSocket := TWSocket.Create(Self); + FControlSocket.OnSessionConnected := ControlSocketSessionConnected; + FControlSocket.OnDataAvailable := ControlSocketDataAvailable; + FControlSocket.OnSessionClosed := ControlSocketSessionClosed; + FControlSocket.OnDnsLookupDone := ControlSocketDnsLookupDone; + FDataSocket := TWSocket.Create(Self); + FStreamFlag := False; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor TCustomFtpCli.Destroy; +begin + FtpCliDeallocateHWnd(FWindowHandle); + { Be sure to have LocalStream closed } +{ FStreamFlag := FALSE; } + DestroyLocalStream; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.WndProc(var MsgRec: TMessage); +begin + try + with MsgRec do begin + case Msg of + WM_FTP_REQUEST_DONE : WMFtpRequestDone(MsgRec); + WM_FTP_SENDDATA : WMFtpSendData(MsgRec); + else + Result := DefWindowProc(Handle, Msg, wParam, lParam); + end; + end; + except + on E:Exception do + HandleBackGroundException(E); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ All exceptions *MUST* be handled. If an exception is not handled, the } +{ application will be shut down ! } +procedure TCustomFtpCli.HandleBackGroundException(E: Exception); +var + CanAbort : Boolean; +begin + CanAbort := TRUE; + { First call the error event handler, if any } + if Assigned(FOnBgException) then begin + try + FOnBgException(Self, E, CanAbort); + except + end; + end; + { Then abort the component } + if CanAbort then begin + try + Abort; + except + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.WMFtpRequestDone(var msg: TMessage); +begin + if Assigned(FOnRequestDone) then + FOnRequestDone(Self, FRequestType, Msg.LParam); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if Operation = opRemove then begin + if AComponent = FControlSocket then + FControlSocket := nil + else if AComponent = FDataSocket then + FDataSocket := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SetErrorMessage; +begin + if FErrorMessage = '' then + FErrorMessage := FLastResponse; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DestroyLocalStream; +begin + if Assigned(FLocalStream) and (FStreamFlag = FALSE) then begin + FLocalStream.Destroy; + FLocalStream := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SetLocalFileName(FileName: String); +begin + FLocalFileName := FileName; + if FileName <> '' then + FStreamFlag := FALSE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SetLocalStream(Stream: TStream); +begin + FLocalStream := Stream; + FStreamFlag := (Stream <> nil); + if FStreamFlag then + FLocalFileName := ''; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.TriggerDisplay(Msg : String); +begin + if Assigned(FOnDisplay) then + FOnDisplay(Self, Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.TriggerDisplayFile(Msg : String); +begin + if Assigned(FOnDisplayFile) then + FOnDisplayFile(Self, Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.TriggerError(Msg : String); +begin + if Assigned(FOnError) then + FOnError(Self, Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DisplayLastResponse; +begin + TriggerDisplay('< ' + FLastResponse); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.StateChange(NewState : TFtpState); +begin + if FState <> NewState then begin + FState := NewState; + TriggerStateChange; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomFtpCli.GetBinary : Boolean; +begin + Result := (FType = 'I'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SetBinary(Value : Boolean); +begin + if Value then + FType := 'I' + else + FType := 'A'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomFtpCli.Progress : Boolean; +var + Abort : Boolean; +begin + Abort := FALSE; + if Assigned(FOnProgress) then + FOnProgress(Self, FByteCount + FResumeAt, Abort); + + if Abort then begin + TriggerDisplay('! Abort requested'); + FDataSocket.Close; + end; + + Result := not Abort; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SendCommand(Cmd : String); +begin + if Assigned(FOnCommand) then + FOnCommand(Self, Cmd); + TriggerDisplay('> ' + Cmd); + if FControlSocket.State = wsConnected then + FControlSocket.SendStr(Cmd + #13 + #10); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.HandleError(const Msg : String); +begin + if Assigned(FOnError) then + TriggerError(Msg) + else + raise FtpException.Create(Msg); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* Return TRUE if component is ready for next operation. } +{* Trigger an error or return FALSE if not ready } +function TCustomFtpCli.CheckReady : Boolean; +begin + Result := (FState in [ftpReady, ftpInternalReady]); + if not Result then + HandleError('FTP component not ready'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.OpenAsync; +begin + if not CheckReady then + Exit; + if FConnected then begin + HandleError('FTP component already connected'); + Exit; + end; + + if not FHighLevelFlag then + FRequestType := ftpOpenAsync; + + FRequestDoneFlag := FALSE; + FReceiveLen := 0; + FRequestResult := 0; + FDnsResult := ''; + StateChange(ftpDnsLookup); + case FConnectionType of + ftpDirect, ftpSocks4, ftpSocks4A, ftpSocks5: FControlSocket.DnsLookup(FHostName); + ftpProxy: FControlSocket.DnsLookup(FProxyServer); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.ExecAsync( + RqType : TFtpRequest; + Cmd : String; { Command to execute } + OkResponses : array of Word; { List of responses like '200 221 342' } + DoneAsync : TFtpNextProc); { What to do when done } +var + I : Integer; +begin + if not((Cmd = 'ABOR') or (Cmd = 'STAT') or (Cmd = 'QUIT')) then begin + if not CheckReady then + Exit; + + if not FConnected then begin + HandleError('FTP component not connected'); + Exit; + end; + end; + + if not FHighLevelFlag then + FRequestType := RqType; + + for I := 0 to High(OkResponses) do + FOkResponses[I] := OkResponses[I]; + FOkResponses[High(OkResponses) + 1] := 0; + + FRequestDoneFlag := FALSE; + FNext := NextExecAsync; + FDoneAsync := DoneAsync; + FErrormessage := ''; + StateChange(ftpWaitingResponse); + SendCommand(Cmd); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.ExtractMoreResults; +var + NumericCode : LongInt; + p : PChar; +begin + if FRequestResult = 0 then begin + if FFctPrv in [ftpFctSize] then begin + p := GetInteger(@FLastResponse[1], NumericCode); + GetInteger(p, FSizeResult); + end; + if FFctPrv in [ftpFctCDup, ftpFctPwd, ftpFctMkd, ftpFctCwd] then begin + p := GetInteger(@FLastResponse[1], NumericCode); + GetQuotedString(p, FDirResult); + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.NextExecAsync; +var + I : Integer; + p : PChar; +begin + DisplayLastResponse; + if not (FLastResponse[1] in ['0'..'9']) then + Exit; { Continuation line, nothing to do } + p := GetInteger(@FLastResponse[1], FStatusCode); + if p^ = '-' then + Exit; { Continuation line, nothing to do } + + if FOkResponses[0] = 0 then begin + { The list of ok responses is empty } + if FStatusCode >= 500 then begin + { Not a good response } + FRequestResult := FStatusCode; + SetErrorMessage; + end + else + FRequestResult := 0; + end + else begin + { We have a list of ok response codes } + for I := 0 to High(FOkResponses) do begin + if FOkResponses[I] = 0 then begin + { No good response found } + FRequestResult := FStatusCode; + SetErrorMessage; + break; + end; + if FOkResponses[I] = FStatusCode then begin + { Good response found } + FRequestResult := 0; + Break; + end; + end; + end; + + if FPassive and (FStatusCode = 227) then begin + StateChange(ftpPasvReady); { 19.09.2002 } + FPasvResponse := FLastResponse; + end; + + ExtractMoreResults; + + if Assigned(FDoneAsync) then + FDoneAsync + else + TriggerRequestDone(FRequestResult); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.QuitAsync; +begin + DestroyLocalStream; + FFctPrv := ftpFctQuit; + ExecAsync(ftpQuitAsync, 'QUIT', [221], DoneQuitAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DoneQuitAsync; +begin + FControlSocket.Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.CwdAsync; +begin + if Length(FHostDirName) <= 0 then begin + HandleError('HostDirName emtpy'); + Exit; + end; + + FFctPrv := ftpFctCwd; + ExecAsync(ftpCwdAsync, 'CWD '+ FHostDirName, [200, 250, 257], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.UserAsync; +var + CmdBuf : String; +begin + if Length(FUserName) <= 0 then begin + HandleError('UserName emtpy'); + Exit; + end; + FFctPrv := ftpFctUser; + if FConnectionType = ftpProxy then begin + if (CompareText(FPort, 'ftp') = 0) or + (CompareText(FPort, '21') = 0) then + CmdBuf := 'USER ' + FUserName + '@' + FHostName + else + CmdBuf := 'USER ' + FUserName + '@' + FHostName + ':' + FPort; + end + else + CmdBuf := 'USER ' + FUserName; + ExecAsync(ftpUserAsync, CmdBuf, [331, 230], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.PassAsync; +begin + if Length(FPassword) <= 0 then begin + HandleError('Password emtpy'); + Exit; + end; + FFctPrv := ftpFctPass; + ExecAsync(ftpPassAsync, 'PASS '+ FPassword, [230], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SystAsync; +begin + FFctPrv := ftpFctSyst; + ExecAsync(ftpSystAsync, 'SYST', [215], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.RestAsync; +begin + FFctPrv := ftpFctRest; + { When restarting a download, we always start from current local file } + { size. When restarting a upload, we restart from ResumeAt property } + { value. This property could be initialized using Size command. } + if (not (FRequestType in [ftpRestartPutAsync, ftpRestPutAsync])) and + (not (ftpNoAutoResumeAt in FOptions)) then + FResumeAt := GetFileSize(FLocalFileName); + if FResumeAt > 0 then + ExecAsync(ftpRestAsync, 'REST ' + IntToStr(FResumeAt), [0], nil) + else begin + FRequestDoneFlag := FALSE; + FNext := NextExecAsync; + FDoneAsync := nil; + TriggerRequestDone(0); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SizeAsync; +begin + FSizeResult := 0; + FFctPrv := ftpFctSize; + ExecAsync(ftpSizeAsync, 'SIZE ' + FHostFileName, [213], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.TypeSetAsync; +begin + FFctPrv := ftpFctTypeSet; + ExecAsync(ftpTypeSetAsync, 'TYPE ' + FType, [200], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.TypeBinaryAsync; +begin + Binary := TRUE; + TypeSetAsync; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.TypeAsciiAsync; +begin + Binary := FALSE; + TypeSetAsync; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.MkdAsync; +begin + FFctPrv := ftpFctMkd; + ExecAsync(ftpMkdAsync, 'MKD ' + FHostFileName, [250, 257], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.RmdAsync; +begin + FFctPrv := ftpFctRmd; + ExecAsync(ftpRmdAsync, 'RMD ' + FHostFileName, [250, 257], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DeleAsync; +begin + FFctPrv := ftpFctDele; + ExecAsync(ftpDeleAsync, 'DELE ' + FHostFileName, [250, 257], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.AbortXferAsync; +begin + FFctPrv := ftpFctAbortXfer; + ExecAsync(ftpAbortXferAsync, 'ABOR', [0], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.QuoteAsync; +begin + FFctPrv := ftpFctQuote; + ExecAsync(ftpQuoteAsync, FLocalFileName, [0], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.PwdAsync; +begin + FFctPrv := ftpFctPwd; + ExecAsync(ftpPwdAsync, 'PWD', [250, 257], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.CDupAsync; +begin + FFctPrv := ftpFctCDup; + ExecAsync(ftpCDupAsync, 'CDUP', [250, 257], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.RenFromAsync; +begin + FFctPrv := ftpFctRenFrom; + ExecAsync(ftpRenFromAsync, 'RNFR ' + FHostFileName, [350], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.RenToAsync; +begin + FFctPrv := ftpFctRenTo; + ExecAsync(ftpRenToAsync, 'RNTO ' + FLocalFileName, [200, 250, 257], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.AbortAsync; +var + bFlag : Boolean; +begin +{$IFDEF TRACE} TriggerDisplay('! Aborting'); {$ENDIF} + bFlag := (FState = ftpDnsLookup); + StateChange(ftpAbort); + DestroyLocalStream; + if bFlag then + FControlSocket.CancelDnsLookup; + if FControlSocket.State <> wsClosed then + FControlSocket.Close; + if FDataSocket.State <> wsClosed then + FDataSocket.Close; + DestroyLocalStream; + FConnected := FALSE; + StateChange(ftpReady); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DoHighLevelAsync; +begin +{$IFDEF TRACE} TriggerDisplay('! HighLevelAsync ' + IntToStr(FRequestResult)); {$ENDIF} + if FState = ftpAbort then begin + {$IFDEF TRACE} TriggerDisplay('! Abort detected'); {$ENDIF} + FFctSet := []; + FHighLevelResult := 426; + FErrorMessage := '426 Operation aborted.'; + end; + + FNextRequest := DoHighLevelAsync; + + if FRequestResult <> 0 then begin + { Previous command had errors } + FHighLevelResult := FRequestResult; + if (FFctPrv = ftpFctQuit) or (not (ftpFctQuit in FFctSet)) then + FFctSet := [] + else + FFctSet := [ftpFctQuit]; + end; + + ExtractMoreResults; + + if ftpFctOpen in FFctSet then begin + FFctPrv := ftpFctOpen; + FFctSet := FFctSet - [FFctPrv]; + OpenAsync; + Exit; + end; + + if ftpFctUser in FFctSet then begin + FFctPrv := ftpFctUser; + FFctSet := FFctSet - [FFctPrv]; + UserAsync; + Exit; + end; + + if ftpFctPass in FFctSet then begin + FFctSet := FFctSet - [ftpFctPass]; + if (FFctPrv <> ftpFctUser) or + ((FfctPrv = ftpFctUser) and (FStatusCode = 331)) then begin + FFctPrv := ftpFctPass; + PassAsync; + Exit; + end; + end; + + if ftpFctCwd in FFctSet then begin + FFctSet := FFctSet - [ftpFctCwd]; + if Length(FHostDirName) > 0 then begin + FFctPrv := ftpFctCwd; + CwdAsync; + Exit; + end; + end; + + if ftpFctCDup in FFctSet then begin + FFctPrv := ftpFctCDup; + FFctSet := FFctSet - [FFctPrv]; + CDupAsync; + Exit; + end; + + if ftpFctTypeSet in FFctSet then begin + FFctPrv := ftpFctTypeSet; + FFctSet := FFctSet - [FFctPrv]; + TypeSetAsync; + Exit; + end; + + if ftpFctPort in FFctSet then begin + FFctPrv := ftpFctPort; + FFctSet := FFctSet - [FFctPrv]; + PortAsync; + Exit; + end; + + if ftpFctRest in FFctSet then begin + FFctPrv := ftpFctRest; + FFctSet := FFctSet - [FFctPrv]; + RestAsync; + Exit; + end; + + if ftpFctGet in FFctSet then begin + if (FFctPrv <> ftpFctRest) or + (FResumeAt < 0) or + ((FFctPrv = ftpFctRest) and (FStatusCode <> 350)) then + FResumeAt := 0; + + FFctPrv := ftpFctGet; + FFctSet := FFctSet - [FFctPrv]; + ExecGetAsync; + Exit; + end; + + if ftpFctPut in FFctSet then begin + FFctPrv := ftpFctPut; + FFctSet := FFctSet - [FFctPrv]; + ExecPutAsync; + Exit; + end; + + if ftpFctAppend in FFctSet then begin + FFctPrv := ftpFctAppend; + FFctSet := FFctSet - [FFctPrv]; + ExecAppendAsync; + Exit; + end; + + if ftpFctDir in FFctSet then begin + FFctPrv := ftpFctDir; + FFctSet := FFctSet - [FFctPrv]; + ExecDirAsync; + Exit; + end; + + if ftpFctLs in FFctSet then begin + FFctPrv := ftpFctLs; + FFctSet := FFctSet - [FFctPrv]; + ExecLsAsync; + Exit; + end; + + if ftpFctSyst in FFctSet then begin + FFctPrv := ftpFctSyst; + FFctSet := FFctSet - [FFctPrv]; + SystAsync; + Exit; + end; + + if ftpFctMkd in FFctSet then begin + FFctPrv := ftpFctMkd; + FFctSet := FFctSet - [FFctPrv]; + MkdAsync; + Exit; + end; + + if ftpFctRmd in FFctSet then begin + FFctPrv := ftpFctRmd; + FFctSet := FFctSet - [FFctPrv]; + RmdAsync; + Exit; + end; + + if ftpFctRenFrom in FFctSet then begin + FFctPrv := ftpFctRenFrom; + FFctSet := FFctSet - [FFctPrv]; + RenFromAsync; + Exit; + end; + + if ftpFctRenTo in FFctSet then begin + FFctPrv := ftpFctRenTo; + FFctSet := FFctSet - [FFctPrv]; + RenToAsync; + Exit; + end; + + if ftpFctSize in FFctSet then begin + FFctPrv := ftpFctSize; + FFctSet := FFctSet - [FFctPrv]; + SizeAsync; + Exit; + end; + + if ftpFctDele in FFctSet then begin + FFctPrv := ftpFctDele; + FFctSet := FFctSet - [FFctPrv]; + DeleAsync; + Exit; + end; + + if ftpFctPwd in FFctSet then begin + FFctPrv := ftpFctPwd; + FFctSet := FFctSet - [FFctPrv]; + PwdAsync; + Exit; + end; + + if ftpFctAbortXfer in FFctSet then begin + FFctPrv := ftpFctAbortXfer; + FFctSet := FFctSet - [FFctPrv]; + AbortXferAsync; + Exit; + end; + + if ftpFctQuote in FFctSet then begin + FFctPrv := ftpFctQuote; + FFctSet := FFctSet - [FFctPrv]; + QuoteAsync; + Exit; + end; + + if ftpFctQuit in FFctSet then begin + FFctPrv := ftpFctQuit; + FFctSet := FFctSet - [FFctPrv]; + FLastResponseSave := FLastResponse; + FStatusCodeSave := FStatusCode; + QuitAsync; + Exit; + end; + + {$IFDEF TRACE} TriggerDisplay('! HighLevelAsync done'); {$ENDIF} + FFctSet := []; + FNextRequest := nil; + FRequestDoneFlag := FALSE; + TriggerRequestDone(FHighLevelResult); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.HighLevelAsync(RqType : TFtpRequest; Fcts : TFtpFctSet); +begin + if FConnected and (ftpFctOpen in Fcts) then begin + HandleError('FTP component already connected'); + Exit; + end; + if not CheckReady then + Exit; + FLastResponseSave := FLastResponse; + FStatusCodeSave := -1; + FRequestType := RqType; + FRequestResult := 0; + FFctSet := Fcts; + FFctPrv := ftpFctNone; + FHighLevelResult := 0; + FHighLevelFlag := TRUE; + FLastResponse := ''; + FErrorMessage := ''; + FRestartFlag := FALSE; + FNextRequest := nil; + DoHighLevelAsync; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.ConnectAsync; +begin + HighLevelAsync(ftpConnectAsync, [ftpFctOpen, ftpFctUser, ftpFctPass]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.ReceiveAsync; +begin + HighLevelAsync(ftpReceiveAsync, + [ftpFctOpen, ftpFctUser, ftpFctPass, + ftpFctCwd, ftpFctTypeSet, ftpFctPort, ftpFctGet, ftpFctQuit]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.PutAsync; +begin + HighLevelAsync(ftpPutAsync, + [ftpFctPort, ftpFctPut]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ By A.Burlakov: new procedure for resuming uploads } +{ Uses REST + STOR commands instead APPEND } +procedure TCustomFtpCli.RestPutAsync; +begin + HighLevelAsync(ftpRestPutAsync, + [ftpFctRest, ftpFctPort, ftpFctPut]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.RestartPutAsync; +begin + HighLevelAsync(ftpRestartPutAsync, + [ftpFctOpen, ftpFctUser, ftpFctPass, ftpFctCwd, + ftpFctTypeSet, ftpFctRest, ftpFctPort, ftpFctPut, + ftpFctQuit]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.TransmitAsync; +begin + HighLevelAsync(ftpTransmitAsync, + [ftpFctOpen, ftpFctUser, ftpFctPass, + ftpFctCwd, ftpFctTypeSet, ftpFctPort, + ftpFctPut, ftpFctQuit]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.AppendAsync; +begin + HighLevelAsync(ftpAppendAsync, + [ftpFctPort, ftpFctAppend]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.AppendFileAsync; +begin + HighLevelAsync(ftpTransmitAsync, + [ftpFctOpen, ftpFctUser, ftpFctPass, + ftpFctCwd, ftpFctTypeSet, ftpFctPort, + ftpFctAppend, ftpFctQuit]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DirAsync; +begin + HighLevelAsync(ftpDirAsync, + [ftpFctPort, ftpFctDir]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DirectoryAsync; +begin + HighLevelAsync(ftpDirectoryAsync, + [ftpFctOpen, ftpFctUser, ftpFctPass, + ftpFctCwd, ftpFctPort, ftpFctDir, ftpFctQuit]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.LsAsync; +begin + HighLevelAsync(ftpLsAsync, + [ftpFctPort, ftpFctLs]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.ListAsync; +begin + HighLevelAsync(ftpListAsync, + [ftpFctOpen, ftpFctUser, ftpFctPass, + ftpFctCwd, ftpFctPort, ftpFctLs, ftpFctQuit]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SystemAsync; +begin + HighLevelAsync(ftpSystemAsync, + [ftpFctOpen, ftpFctUser, ftpFctPass, + ftpFctSyst, ftpFctQuit]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.RestartGetAsync; +begin + HighLevelAsync(ftpRestartGetAsync, + [ftpFctOpen, ftpFctUser, ftpFctPass, ftpFctCwd, + ftpFctTypeSet, ftpFctRest, ftpFctPort, ftpFctGet, + ftpFctQuit]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.RestGetAsync; +begin + HighLevelAsync(ftpRestGetAsync, + [ftpFctRest, ftpFctPort, ftpFctGet]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.GetAsync; +begin + HighLevelAsync(ftpGetAsync, + [ftpFctPort, ftpFctGet]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.MkdirAsync; +begin + HighLevelAsync(ftpMkdirAsync, + [ftpFctOpen, ftpFctUser, ftpFctPass, + ftpFctCwd, ftpFctMkd, ftpFctQuit]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.RmdirAsync; +begin + HighLevelAsync(ftpRmdirAsync, + [ftpFctOpen, ftpFctUser, ftpFctPass, + ftpFctCwd, ftpFctRmd, ftpFctQuit]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DeleteAsync; +begin + HighLevelAsync(ftpDeleteAsync, + [ftpFctOpen, ftpFctUser, ftpFctPass, + ftpFctCwd, ftpFctDele, ftpFctQuit]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DoQuoteAsync; +begin + HighLevelAsync(ftpDoQuoteAsync, + [ftpFctOpen, ftpFctUser, ftpFctPass, + ftpFctCwd, ftpFctQuote, ftpFctQuit]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.RenameAsync; +begin + HighLevelAsync(ftpRenameAsync, + [ftpFctOpen, ftpFctUser, ftpFctPass, ftpFctCwd, + ftpFctRenFrom, ftpFctRenTo, ftpFctQuit]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.RenAsync; +begin + HighLevelAsync(ftpRenAsync, [ftpFctRenFrom, ftpFctRenTo]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.FileSizeAsync; +begin + HighLevelAsync(ftpSizeAsync, + [ftpFctOpen, ftpFctUser, ftpFctPass, + ftpFctCwd, ftpFctSize, ftpFctQuit]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DataSocketGetDataAvailable(Sender: TObject; Error : word); +var + Len : Integer; + Buffer : array [1..4096] of Char; { Should use a dynamic buffer instead... } + aSocket : TWSocket; + I, J : Integer; + Line : String; +begin + if not Progress then + Exit; + + aSocket := Sender as TWSocket; + + Len := aSocket.Receive(@Buffer[1], High(Buffer)); +{TriggerDisplay('! Data received ' + IntToStr(Len));} + if Len = 0 then + { Remote has closed, ignore } + else if Len < 0 then begin + { An error has occured } + if (aSocket.State = wsConnected) and + (aSocket.LastError <> WSAEWOULDBLOCK) then begin + TriggerDisplay('! Data: Receive error ' + IntToStr(aSocket.LastError)); + aSocket.Shutdown(2); + Exit; + end; + end + else begin + { Update our statistics } + FByteCount := FByteCount + Len; + + if FLocalStream <> nil then begin + try + FLocalStream.WriteBuffer(Buffer, Len); + except + TriggerDisplay('! Error writing local file'); + aSocket.Shutdown(2); + Exit; + end; + end; + + { If requested to display the received data, do it line by line } + if FDisplayFileFlag then begin + case FDisplayFileMode of + ftpBinary: + begin + {$IFDEF VER80} + { 16 bit has max 255 characters per string } + if Len > 255 then + SetLength(Line, 255) + else + {$ENDIF} + SetLength(Line, Len); + Move(Buffer[1], Line[1], Length(Line)); + TriggerDisplayFile(Line); + end; + ftpLineByLine: + if Len > 0 then begin + i := 1; + while (i <= Len) do begin + j := 1; + while (i <= Len) and (Buffer[i] <> #10) and (Buffer[i] <> #13) do begin + i := i + 1; + j := j + 1; + end; + {$IFDEF VER80} + if (j - 1) > 255 then + SetLength(Line, 255) + else + {$ENDIF} + SetLength(Line, j - 1); + if Length(Line) > 0 then + Move(Buffer[i - j + 1], Line[1], Length(Line)); + TriggerDisplayFile(Line); + while (i <= Len) and ((Buffer[i] = #10) or (Buffer[i] = #13)) do + i := i + 1; + end; + end; + end; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DataSocketGetSessionConnected( + Sender: TObject; + Error : word); +begin + {$IFDEF TRACE} TriggerDisplay('! Data Session opened (Get)'); {$ENDIF} + + { Use the socket for the data transmission } + FDataSocket.OnSessionClosed := DataSocketGetSessionClosed; + FDataSocket.OnDataAvailable := DataSocketGetDataAvailable; + FDataSocket.OnDataSent := nil; + + { Record the starting time } + FStartTime := LongInt(GetTickCount); + + if Error <> 0 then begin + FLastResponse := 'Unable to establish data connection, error #' + + IntToStr(Error); + FStatusCode := 550; + SetErrorMessage; + FDataSocket.Close; + FRequestResult := FStatusCode; + TriggerRequestDone(FRequestResult); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Used for passive mode } +procedure TCustomFtpCli.DataSocketPutSessionConnected( + Sender: TObject; + Error : word); +begin + {$IFDEF TRACE} TriggerDisplay('! Data Session opened (Put)'); {$ENDIF} + + { Use the socket for the data transmission } + FDataSocket.OnSessionClosed := DataSocketPutSessionClosed; + FDataSocket.OnDataAvailable := nil; + FDataSocket.OnDataSent := nil; + + { Record we opened data session } + FPutSessionOpened := TRUE; + + { Record the starting time } + FStartTime := LongInt(GetTickCount); + + if Error <> 0 then begin + FLastResponse := 'Unable to establish data connection, error #' + + IntToStr(Error); + FStatusCode := 550; + SetErrorMessage; + FDataSocket.Close; + FRequestResult := FStatusCode; + TriggerRequestDone(FRequestResult); + Exit; + end; + + StateChange(ftpWaitingResponse); + FNext := Next1PutAsync; + + if FAppendFlag then + SendCommand('APPE ' + FHostFileName) + else + SendCommand('STOR ' + FHostFileName); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DataSocketGetSessionAvailable(Sender: TObject; Error : word); +var + aSocket : TSocket; +begin + {$IFDEF TRACE} TriggerDisplay('! Data Session requested'); {$ENDIF} + { Accept the incomming connection initiated by the FTP server for data } + aSocket := FDataSocket.Accept; + + { Close the listening socket, we don't need it anymore } + FDataSocket.Close; + + { Reuse the socket for the data transmission } + FDataSocket.OnSessionClosed := DataSocketGetSessionClosed; + FDataSocket.OnDataAvailable := DataSocketGetDataAvailable; + FDataSocket.OnDataSent := nil; + FDataSocket.HSocket := aSocket; + FDataSocket.ComponentOptions := [wsoNoReceiveLoop]; { 26/10/02 } + + { Record the starting time } + FStartTime := LongInt(GetTickCount); + {$IFDEF TRACE} TriggerDisplay('! Data Session opened'); {$ENDIF} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DataSocketGetSessionClosed( + Sender: TObject; + Error : word); +begin + {$IFDEF TRACE} TriggerDisplay('! Data Session closed'); {$ENDIF} + + DestroyLocalStream; + FFileReceived := TRUE; + FError := Error; + Next3GetAsync; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DataSocketPutSessionAvailable(Sender: TObject; Error : word); +var + aSocket : TSocket; + SndBufSize : Integer; + OptLen : Integer; +begin + {$IFDEF TRACE} TriggerDisplay('! Data Session requested'); {$ENDIF} + { Accept the incomming connection initiated by the FTP server for data } + aSocket := FDataSocket.Accept; + + { Close the listening socket, we don't need it anymore } + FDataSocket.Close; + + { Reuse the socket for the data transmission } + FDataSocket.OnSessionClosed := DataSocketPutSessionClosed; + FDataSocket.OnDataAvailable := DataSocketPutDataAvailable; + FDataSocket.OnDataSent := DataSocketPutDataSent; +{ FDataSocket.OnDisplay := FOnDisplay; } { Debugging only } + FDataSocket.HSocket := aSocket; + FDataSocket.ComponentOptions := [wsoNoReceiveLoop]; { 26/10/02 } + + OptLen := SizeOf(SndBufSize); + if WSocket_getsockopt(FDataSocket.HSocket, SOL_SOCKET, + SO_SNDBUF, + @SndBufSize, OptLen) = SOCKET_ERROR then begin + HandleError('winsock.getsockopt(SO_SNDBUF) failed'); + Exit; + end; + + { Be sure to gracefully close the socket } + FDataSocket.LingerOnOff := wsLingerOff; + FDataSocket.LingerTimeout := 10; + FDataSocket.SetLingerOption; +{ FStorAnswerRcvd := TRUE; } { V240 INSERTED line } + FPutSessionOpened := TRUE; + if FStorAnswerRcvd and (FStartTime = 0) then + PostMessage(Handle, WM_FTP_SENDDATA, 0, 0); + + {$IFDEF TRACE} TriggerDisplay('! Data Session opened'); {$ENDIF} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.WMFtpSendData(var msg: TMessage); +begin + { Record the starting time } + FStartTime := LongInt(GetTickCount); + + { Send first data block } + DataSocketPutDataSent(FDataSocket, 0); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DataSocketPutDataSent(Sender: TObject; Error : word); +var + Count : Integer; +begin + if (FLocalStream = nil) or (not Progress) then + Exit; + if FLocalStream = nil then + Exit; { Could be set to nil by Progress function } + + if Error <> 0 then begin + TriggerDisplay('! Error #' + IntToStr(Error) + ' sending data'); + FDataSocket.Close; + Exit; + end; + + if FEofFlag or (not FStorAnswerRcvd) or (not FPutSessionOpened) then + Exit; + + try + Count := FLocalStream.Read(FSendBuffer, BLOCK_SIZE); + if Count > 0 then begin + FByteCount := FByteCount + Count; + FDataSocket.Send(@FSendBuffer, Count); + end + else begin { EOF } + {$IFNDEF VER80} + { For an unknown reason, winsock need time to send last data } + { buffer. Without this delay, we may end with a partial file } + { transfer. See comments in DoPutAppendAsync function. } + { Normally using Linger option would handle this case. But } + { many winsock implementations will end with a 10055 error } + { after a lot of consecutive file transfers. } + Sleep(100); + {$ENDIF} + FDataSocket.CloseDelayed; + FEofFlag := TRUE; + end; + except + TriggerDisplay('! Error reading file'); + FDataSocket.Close; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DataSocketPutSessionClosed(Sender: TObject; Error : word); +begin + {$IFDEF TRACE} TriggerDisplay('! Data Session closed'); {$ENDIF} + { close the local file } + DestroyLocalStream; + FFileSent := TRUE; + FError := Error; + Next3PutAsync; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DataSocketPutDataAvailable(Sender: TObject; Error : word); +var + Buffer : array [1..2048] of Char; + aSocket : TWSocket; +begin + { We don't wants to receive data here because we are sending, not } + { receiving. But in order to not crash if we receive somthing, just } + { get it and do nothing with it ! } + aSocket := Sender as TWSocket; + aSocket.Receive(@Buffer[1], High(Buffer)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.TransfertStats; +var + Buffer : String; + BytesSec : LongInt; +begin + FStopTime := LongInt(GetTickCount); + Buffer := IntToSTr(FByteCount) + ' bytes received/sent in ' + + IntToStr((FStopTime - FStartTime) div 1000) + ' seconds'; + + if FStopTime <> FStartTime then begin + if FByteCount > 32767 then + BytesSec := 1000 * (FByteCount div (FStopTime - FStartTime)) + else + BytesSec := (1000 * FByteCount) div (FStopTime - FStartTime); + Buffer := Buffer + ' (' + IntToStr(BytesSec) + ' Bytes/sec)'; + end; + TriggerDisplay('! ' + Buffer); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.ExecGetAsync; +begin + DoGetAsync(ftpGetAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.ExecDirAsync; +begin + DoGetAsync(ftpDirAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.ExecLsAsync; +begin + DoGetAsync(ftpLsAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SetShareMode(newValue : TFtpShareMode); +begin +{$IFNDEF VER80}{$WARNINGS OFF}{$ENDIF} + case newValue of + ftpShareCompat : FShareMode := fmShareCompat; + ftpShareExclusive : FShareMode := fmShareExclusive; + ftpShareDenyWrite : FShareMode := fmShareDenyWrite; + ftpShareDenyRead : FShareMode := fmShareDenyRead; + ftpShareDenyNone : FShareMode := fmShareDenyNone; + else + FShareMode := fmShareExclusive; + end; +{$IFNDEF VER80}{$WARNINGS ON}{$ENDIF} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomFtpCli.GetShareMode : TFtpShareMode; +begin +{$IFNDEF VER80}{$WARNINGS OFF}{$ENDIF} + case FShareMode of + fmShareCompat : Result := ftpShareCompat; + fmShareExclusive : Result := ftpShareExclusive; + fmShareDenyWrite : Result := ftpShareDenyWrite; + fmShareDenyRead : Result := ftpShareDenyRead; + fmShareDenyNone : Result := ftpShareDenyNone; + else + Result := ftpShareExclusive; + end; +{$IFNDEF VER80}{$WARNINGS ON}{$ENDIF} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SetDisplayFileMode(NewValue : TFtpDisplayFileMode); +begin + case NewValue of + ftpLineByLine, ftpBinary : FDisplayFileMode := NewValue; + else + FDisplayFileMode := ftpLineByLine; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomFtpCli.GetDisplayFileMode : TFtpDisplayFileMode; +begin + case FDisplayFileMode of + ftpLineByLine: Result := ftpLineByLine; + ftpBinary: Result := ftpBinary; + else + Result := ftpLineByLine; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SetConnectionType(NewValue: TFtpConnectionType); +begin + { Must be disconnected to change the connection type } + if FConnected then begin + HandleError('FTP component connected'); + Exit; + end; + { Change connection type } + case NewValue of + ftpDirect: begin + FConnectionType := NewValue; + FControlSocket.SocksAuthentication := socksNoAuthentication; + FDataSocket.SocksAuthentication := socksNoAuthentication; + end; + ftpProxy: begin + FConnectionType := NewValue; + FPassive := True; + FControlSocket.SocksAuthentication := socksNoAuthentication; + FDataSocket.SocksAuthentication := socksNoAuthentication; + end; + ftpSocks4: begin + FConnectionType := NewValue; + FPassive := True; + with FControlSocket do begin + SocksLevel := '4'; + SocksAuthentication := socksAuthenticateUsercode; + end; + with FDataSocket do begin + SocksLevel := '4'; + SocksAuthentication := socksAuthenticateUsercode; + end; + end; + ftpSocks4A: begin + FConnectionType := NewValue; + FPassive := True; + with FControlSocket do begin + SocksLevel := '4A'; + SocksAuthentication := socksAuthenticateUsercode; + end; + with FDataSocket do begin + SocksLevel := '4A'; + SocksAuthentication := socksAuthenticateUsercode; + end; + end; + ftpSocks5: begin + FConnectionType := NewValue; + FPassive := True; + with FControlSocket do begin + SocksLevel := '5'; + SocksAuthentication := socksAuthenticateUsercode; + end; + with FDataSocket do begin + SocksLevel := '5'; + SocksAuthentication := socksAuthenticateUsercode; + end; + end; + else + FConnectionType := ftpDirect; + FControlSocket.SocksAuthentication := socksNoAuthentication; + FDataSocket.SocksAuthentication := socksNoAuthentication; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomFtpCli.GetConnectionType: TFtpConnectionType; +begin + case FConnectionType of + ftpDirect: Result := ftpDirect; + ftpProxy: Result := ftpProxy; + ftpSocks4: Result := ftpSocks4; + ftpSocks4A: Result := ftpSocks4A; + ftpSocks5: Result := ftpSocks5; + else + Result := ftpDirect; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SetSocksPassword(NewValue: string); +begin + FControlSocket.SocksPassword := NewValue; + FDataSocket.SocksPassword := NewValue; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomFtpCli.GetSocksPassword: string; +begin + Result := FControlSocket.SocksPassword; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SetSocksPort(NewValue: string); +begin + FControlSocket.SocksPort := NewValue; + FDataSocket.SocksPort := NewValue; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomFtpCli.GetSocksPort: string; +begin + Result := FControlSocket.SocksPort; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SetSocksServer(NewValue: string); +begin + FControlSocket.SocksServer := NewValue; + FDataSocket.SocksServer := NewValue; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomFtpCli.GetSocksServer: string; +begin + Result := FControlSocket.SocksServer; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SetSocksUserCode(NewValue: string); +begin + FControlSocket.SocksUserCode := NewValue; + FDataSocket.SocksUserCode := NewValue; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomFtpCli.GetSocksUserCode: string; +begin + Result := FControlSocket.SocksUserCode; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.SetPassive(NewValue: Boolean); +begin + { Passive state must not be changed if Proxy or Socks connection type is selected } + case FConnectionType of + ftpDirect: FPassive := NewValue; + ftpProxy, ftpSocks4, ftpSocks4A, ftpSocks5: FPassive := True; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Receive a file or a directory list of a file list } +procedure TCustomFtpCli.DoGetAsync(RqType : TFtpRequest); +{$IFDEF VER80} +const + FILE_END = 2; +{$ENDIF} +var + Temp : String; + I : Integer; + TargetPort : WORD; { 10/30/99 } + TargetIP : String; +begin + if not FConnected then begin + HandleError(FGetCommand + ': not connected'); + Exit; + end; + + { If no filename was assigned, check if maybe we wanna view it, } + { meaning - FDisplayFileFlag } + if (Length(FLocalFileName) <= 0) and + not (FDisplayFileFlag or FStreamFlag) then begin + HandleError('LocalFileName empty'); + Exit; + end; + + if not FHighLevelFlag then + FRequestType := RqType; + + case RqType of + ftpGetAsync: FGetCommand := 'RETR'; + ftpDirAsync: FGetCommand := 'LIST'; + ftpLsAsync: FGetCommand := 'NLST'; + end; + + FServerSaidDone := FALSE; + FFileReceived := FALSE; + FRequestDoneFlag := FALSE; + FByteCount := 0; + FError := 0; + + FDataSocket.OnSessionAvailable := DataSocketGetSessionAvailable; + +{$IFDEF VER80} + { With Delphi 1 you need to nul terminate each string } + FLocalFileName[Length(FLocalFileName) + 1] := chr(0); +{$ENDIF} + + { open the destination file } + { Don't open a file if we're on FDisplayFileFlag } + if not FDisplayFileFlag then + try + DestroyLocalStream; + if FResumeAt <= 0 then begin + if not Assigned(FLocalStream) and not FStreamFlag then begin + FLocalStream := TFileStream.Create(FLocalFileName, fmCreate); + if FShareMode <> 0 then begin + { Not default mode, need to close and reopen file with } + { the given mode } + FLocalStream.Destroy; + FLocalStream := TFileStream.Create(FLocalFileName, + fmOpenWrite + FShareMode); + end; + end; + end + else begin + if not Assigned(FLocalStream) and not FStreamFlag then + FLocalStream := TFileStream.Create(FLocalFileName, + fmOpenWrite + FShareMode); + FLocalStream.Seek(FResumeAt, soFromBeginning) + end; + except + FLastResponse := 'Unable to open local file ' + FLocalFileName; + FStatusCode := 550; + SetErrorMessage; + FDataSocket.Close; + FRequestResult := FStatusCode; + TriggerRequestDone(FRequestResult); + exit; + end; + + if FPassive then begin + Temp := FPasvResponse; + Delete(Temp, 1, Pos('(', Temp)); + + TargetIP := ''; + for I := 1 to 4 do begin + TargetIP := TargetIP + Copy(Temp, 1, Pos(',',Temp) - 1) + '.'; + Delete(Temp, 1, Pos(',', Temp)); + end; + TargetIP := Copy(TargetIP, 1, Length(TargetIP) - 1); + + TargetPort := StrToInt(Copy(Temp, 1, Pos(',', Temp) - 1)) * 256; + Delete(Temp, 1, Pos(',', Temp)); + TargetPort := TargetPort + StrToInt(Copy(Temp, 1, Pos(')', Temp) - 1)); + + FDataSocket.Port := IntToStr(TargetPort); + FDataSocket.Addr := TargetIP; {ControlSocket.Addr;} + FDataSocket.LocalAddr := FLocalAddr; {bb} + FDataSocket.OnSessionConnected := DataSocketGetSessionConnected; + FDataSocket.LingerOnOff := wsLingerOff; + FDataSocket.LingerTimeout := 0; + FDataSocket.ComponentOptions := [wsoNoReceiveLoop]; { 26/10/02 } + try + FDataSocket.Connect; + except + on E:Exception do begin + FLastResponse := '550 ' + E.ClassName + ': ' + E.Message; + FStatusCode := 550; + SetErrorMessage; + FDataSocket.Close; + FRequestResult := FStatusCode; + TriggerRequestDone(FRequestResult); + exit; + end; + end; + end; + + StateChange(ftpWaitingResponse); + FNext := Next1GetAsync; + if Length(FHostFileName) > 0 then + SendCommand(FGetCommand + ' ' + FHostFileName) + else + SendCommand(FGetCommand); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ We comes here when receiving the response for the RETR command we sent } +procedure TCustomFtpCli.Next1GetAsync; +begin + DisplayLastResponse; + GetInteger(@FLastResponse[1], FStatusCode); + if not (((FStatusCode div 10) = 15) or { Accept range 150-159 } + (FStatusCode = 125)) then begin { Accept code 125 } + SetErrorMessage; + FNext := nil; + FDataSocket.Close; + DestroyLocalStream; + { Reset the starting position } + FResumeAt := 0; + FRequestResult := FStatusCode; + TriggerRequestDone(FRequestResult); + Exit; + end; + FNext := Next2GetAsync; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ We comes here when the FTP server has sent the file we asked to GET } +procedure TCustomFtpCli.Next2GetAsync; +begin + DisplayLastResponse; + GetInteger(@FLastResponse[1], FStatusCode); + if not ((FStatusCode = 125) or (FStatusCode = 226) or + (FStatusCode = 250)) then begin + SetErrorMessage; + DestroyLocalStream; + FDataSocket.Close; + TriggerDisplay('! RETR/LIST/NLST Failed'); + FRequestResult := FStatusCode; + TriggerRequestDone(FRequestResult); + Exit; + end; + FServerSaidDone := TRUE; + Next3GetAsync; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ We comes here either if the file has been received of the FTP server has } +{ his response. } +procedure TCustomFtpCli.Next3GetAsync; +begin + {$IFDEF TRACE} TriggerDisplay('! Next3GetAsync'); {$ENDIF} + if (not FServerSaidDone) or (not FFileReceived) then + Exit; + + { Display statistics } + TransfertStats; + + { Reset the starting position } + FResumeAt := 0; + FRequestResult := FError; + TriggerRequestDone(FRequestResult); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.ExecPutAsync; +begin + FAppendFlag := FALSE; + FRequestType := ftpPutAsync; + DoPutAppendAsync; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.ExecAppendAsync; +begin + FAppendFlag := TRUE; + FRequestType := ftpAppendAsync; + DoPutAppendAsync; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.DoPutAppendAsync; +{$IFDEF VER80} +const + FILE_END = 2; +{$ENDIF} +var + Temp : String; + I : Integer; + TargetPort : WORD; { 10/30/99 } + TargetIP : String; + bCancel : Boolean; +begin + if not FConnected then begin + HandleError('STOR/APPE: not connected'); + Exit; + end; + + if (not FStreamFlag) and (Length(FLocalFileName) <= 0) then begin + HandleError('LocalFileName empty'); + Exit; + end; + + FServerSaidDone := FALSE; + FFileSent := FALSE; + FRequestDoneFlag := FALSE; + FPutSessionOpened := FALSE; + FStorAnswerRcvd := FALSE; + FStartTime := 0; + FByteCount := 0; + FError := 0; + + bCancel := FALSE; + TriggerReadyToTransmit(bCancel); + if bCancel then begin + FErrorMessage := '426 Transmit cancelled by application'; + FStatusCode := 426; + TriggerDisplay('! ' + FErrorMessage); + FRequestResult := FStatusCode; + TriggerRequestDone(FRequestResult); + Exit; + end; + + FDataSocket.OnSessionAvailable := DataSocketPutSessionAvailable; +{$IFDEF VER80} + { With Delphi 1 you need to nul terminate each string } + FLocalFileName[Length(FLocalFileName) + 1] := chr(0); +{$ENDIF} + + { open the local source file } + try + { Be sure to have previous instance closed } + DestroyLocalStream; + if not Assigned(FLocalStream) and not FStreamFlag then + FLocalStream := TFileStream.Create(FLocalFileName, + fmOpenRead + FShareMode); + FEofFlag := FALSE; + if FResumeAt > 0 then + FLocalStream.Seek(FResumeAt, soFromBeginning); + except + FErrorMessage := '426 Unable to open local file ' + FLocalFileName; + FStatusCode := 426; + TriggerDisplay('! ' + FErrorMessage); + FDataSocket.Close; + FRequestResult := FStatusCode; + TriggerRequestDone(FRequestResult); + Exit; + end; + + if FPassive then begin + Temp := FPasvResponse; { 26/12/99 } + Delete(Temp, 1, Pos('(', Temp)); + TargetIP := ''; + for I := 1 to 4 do begin + TargetIP := TargetIP + Copy(Temp, 1, Pos(',',Temp) - 1) + '.'; + Delete(Temp, 1, Pos(',', Temp)); + end; + TargetIP := Copy(TargetIP, 1, Length(TargetIP) - 1); + + TargetPort := StrToInt(Copy(Temp, 1, Pos(',', Temp) - 1)) * 256; + Delete(Temp, 1, Pos(',', Temp)); + TargetPort := TargetPort + StrToInt(Copy(Temp, 1, Pos(')', Temp) - 1)); + + FDataSocket.Port := IntToStr(TargetPort); + FDataSocket.Addr := TargetIP; {ControlSocket.Addr;} + FDataSocket.LocalAddr := FLocalAddr; {bb} + FDataSocket.OnSessionConnected := DataSocketPutSessionConnected; + { Normally we should use LingerOn with a timeout. But doing so will } + { often result in error 10055 triggered after a lot of consecutive } + { file transfers. There is code in DataSocketPutDataSent to make } + { sure last packet is sent completely. } + FDataSocket.LingerOnOff := wsLingerOff; + FDataSocket.LingerTimeout := 0; + FDataSocket.ComponentOptions := [wsoNoReceiveLoop]; { 26/10/02 } + try + FDataSocket.Connect; + except + on E:Exception do begin + FLastResponse := '426 ' + E.ClassName + ': ' + E.Message; + FStatusCode := 426; + SetErrorMessage; + FDataSocket.Close; + FRequestResult := FStatusCode; + TriggerRequestDone(FRequestResult); + Exit; + end; + end; + Exit; + end; + + StateChange(ftpWaitingResponse); + FNext := Next1PutAsync; + + if FAppendFlag then + SendCommand('APPE ' + FHostFileName) + else + SendCommand('STOR ' + FHostFileName); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ We comes here when receiving the response for the STOR command we sent } +procedure TCustomFtpCli.Next1PutAsync; +var + p : PChar; +begin + DisplayLastResponse; + if not (FLastResponse[1] in ['0'..'9']) then + Exit; { Continuation line, nothing to do } + p := GetInteger(@FLastResponse[1], FStatusCode); + if p^ = '-' then + Exit; { Continuation line, nothing to do } + + if not ((FStatusCode = 150) or (FStatusCode = 125)) then begin + SetErrorMessage; + FNext := nil; + FDataSocket.Close; + DestroyLocalStream; + { Reset the starting position } + FResumeAt := 0; + FRequestResult := FStatusCode; + TriggerRequestDone(FRequestResult); + Exit; + end; + + if FPassive then begin + { Send the first data block } + {$IFDEF TRACE} TriggerDisplay('! Send first block'); {$ENDIF} + FStorAnswerRcvd := TRUE; + FDataSocket.OnDataSent := DataSocketPutDataSent; + DataSocketPutDataSent(FDataSocket, 0); + end + else begin + { V240 FStorAnswerRcvd := TRUE; } + FStorAnswerRcvd := TRUE; + if FPutSessionOpened and (FStartTime = 0) then + PostMessage(Handle, WM_FTP_SENDDATA, 0, 0); + end; + + + FNext := Next2PutAsync; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ We comes here when the FTP server has received the file we sent (STOR) } +procedure TCustomFtpCli.Next2PutAsync; +var + p : PChar; +begin + DisplayLastResponse; + if not (FLastResponse[1] in ['0'..'9']) then + Exit; { Continuation line, nothing to do } + p := GetInteger(@FLastResponse[1], FStatusCode); + if p^ = '-' then + Exit; { Continuation line, nothing to do } + if not ((FStatusCode = 226) or (FStatusCode = 250)) then begin + SetErrorMessage; + DestroyLocalStream; + FDataSocket.Close; + TriggerDisplay('! STOR Failed'); + FRequestResult := FStatusCode; + TriggerRequestDone(FRequestResult); + Exit; + end; + FServerSaidDone := TRUE; + Next3PutAsync; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ We comes here when the file has been sent or when the FTP server tell us } +{ he recived the file. } +procedure TCustomFtpCli.Next3PutAsync; +begin + {$IFDEF TRACE} TriggerDisplay('! Next3PutAsync'); {$ENDIF} + if (not FServerSaidDone) or (not FFileSent) then + Exit; + + { Display statistics } + TransfertStats; + + { Reset the starting position } + FResumeAt := 0; + FRequestResult := FError; + TriggerRequestDone(FRequestResult); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.PortAsync; +var + Msg : String; + saddr : TSockAddrIn; + saddrlen : Integer; + DataPort : DWORD; { 10/30/99 } + IPAddr : TInAddr; +begin + { Makes the data socket listening for data connection } + FDataSocket.Proto := 'tcp'; + FDataSocket.Addr := '0.0.0.0'; { INADDR_ANY } + FDataSocket.Port := '0'; { IPPORT_ANY } + FDataSocket.OnSessionAvailable := nil; + FDataSocket.OnSessionClosed := nil; + FDataSocket.OnDataAvailable := nil; + + if FPassive then + DataPort := 0 { Not needed, makes compiler happy } + else begin + if (ftpFctGet in FFctSet) or (ftpFctDir in FFctSet) then {G.B. 2002/07/12} + FDataSocket.OnSessionAvailable := DataSocketGetSessionAvailable + else if ftpFctPut in FFctSet then + FDataSocket.OnSessionAvailable := DataSocketPutSessionAvailable; + FDataSocket.LingerOnOff := wsLingerOn; + FDataSocket.LingerTimeout := 10; + FDataSocket.Listen; + + { Get the port number as assigned by Windows } + saddrLen := SizeOf(saddr); + FDataSocket.GetSockName(saddr, saddrLen); + DataPort := WSocket_ntohs(saddr.sin_port); + end; + + { Get our IP address from our control socket } + saddrlen := SizeOf(saddr); + FControlSocket.GetSockName(saddr, saddrlen); + IPAddr := saddr.sin_addr; + + { Strange behaviour of PWS (FrontPage 97 Web Server for W95) } + { which do not like effective address when localhost is used } + if FPassive then + Msg := 'PASV' + else begin + if FControlSocket.sin.sin_addr.s_addr = WSocket_htonl($7F000001) then + Msg := Format('PORT 127,0,0,1,%d,%d', + [HiByte(DataPort), + LoByte(DataPort)]) + else + Msg := Format('PORT %d,%d,%d,%d,%d,%d', + [ord(IPAddr.S_un_b.s_b1), + ord(IPAddr.S_un_b.s_b2), + ord(IPAddr.S_un_b.s_b3), + ord(IPAddr.S_un_b.s_b4), + HiByte(DataPort), + LoByte(DataPort)]); + end; + + FByteCount := 0; + FFctPrv := ftpFctPort; + ExecAsync(ftpPortAsync, Msg, [200, 227], nil); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.ControlSocketDnsLookupDone(Sender: TObject; Error: Word); +begin + if Error <> 0 then begin + FLastResponse := '500 ' + WSocketErrorDesc(Error) + + ' (Winsock error #' + IntToStr(Error) + ')'; + FStatusCode := 500; + FRequestResult := FStatusCode; { 21/05/99 } + SetErrorMessage; + TriggerRequestDone(Error); + end + else begin + FDnsResult := FControlSocket.DnsResult; + FControlSocket.Addr := FDnsResult; + FControlSocket.LocalAddr := FLocalAddr; {bb} + FControlSocket.Proto := 'tcp'; + if (FConnectionType = ftpProxy) and (FProxyPort <> '') then + FControlSocket.Port := FProxyPort + else + FControlSocket.Port := FPort; +{ FControlSocket.OnDisplay := FOnDisplay; } { Debugging only } + StateChange(ftpWaitingBanner); + try + FControlSocket.Connect; + except + on E:Exception do begin + FLastResponse := '500 ' + E.ClassName + ': ' + E.Message; + FStatusCode := 500; + FRequestResult := FStatusCode; { 21/05/99 } + SetErrorMessage; + TriggerRequestDone(FStatusCode); + end; + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.ControlSocketSessionConnected(Sender: TObject; Error: Word); +begin + { Do not trigger the client SessionConnected from here. We must wait } + { to have received the server banner. } + if Error <> 0 then begin + FLastResponse := '500 ' + WSocketErrorDesc(Error) + + ' (Winsock error #' + IntToStr(Error) + ')'; + FStatusCode := 500; + FRequestResult := FStatusCode; { Heedong Lim, 05/14/1999 } + SetErrorMessage; { Heedong Lim, 05/14/1999 } + FNextRequest := nil; + TriggerRequestDone(Error); + FControlSocket.Close; + StateChange(ftpReady); + end + else + FConnected := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.ControlSocketDataAvailable(Sender: TObject; Error: Word); +var + Len : Integer; + I, J : Integer; + p : PChar; +begin + Len := FControlSocket.Receive(@FReceiveBuffer[FReceiveLen], + sizeof(FReceiveBuffer) - FReceiveLen - 1); + + if FRequestType = ftpRqAbort then + Exit; + + if Len = 0 then begin + FControlSocket.Close; + Exit; + end; + if Len < 0 then + Exit; + + FReceiveBuffer[FReceiveLen + Len] := #0; + FReceiveLen := FReceiveLen + Len; + + while FReceiveLen > 0 do begin + if ftpAcceptLF in FOptions then begin + I := Pos(#10, FReceiveBuffer); + J := I; + end + else begin + I := Pos(#13#10, FReceiveBuffer); + J := I + 1; + end; + if I <= 0 then + break; + if I > FReceiveLen then + break; + + FLastResponse := Copy(FReceiveBuffer, 1, I - 1); + { Remove trailing control chars } + while (Length(FLastResponse) > 0) and + (FLastResponse[Length(FLastResponse)] in [#10, #13]) do + SetLength(FLastResponse, Length(FLastResponse) - 1); + + if Assigned(FOnResponse) then + FOnresponse(Self); + +{$IFDEF DUMP} + FDumpBuf := '>|'; + FDumpStream.WriteBuffer(FDumpBuf[1], Length(FDumpBuf)); + FDumpStream.WriteBuffer(FLastResponse[1], Length(FLastResponse)); + FDumpBuf := '|' + #13#10; + FDumpStream.WriteBuffer(FDumpBuf[1], Length(FDumpBuf)); +{$ENDIF} +{$IFDEF VER80} + { Add a nul byte at the end of string for Delphi 1 } + FLastResponse[Length(FLastResponse) + 1] := #0; +{$ENDIF} + FReceiveLen := FReceiveLen - J; + if FReceiveLen > 0 then + Move(FReceiveBuffer[J], FReceiveBuffer[0], FReceiveLen + 1) + else if FReceiveLen < 0 then + FReceiveLen := 0; + + if FState = ftpWaitingBanner then begin + DisplayLastResponse; + if not (FLastResponse[1] in ['0'..'9']) then + Continue; { Continuation line, ignore } + p := GetInteger(@FLastResponse[1], FStatusCode); + if p^ = '-' then + Continue; { Continuation line, ignore } + if FStatusCode <> 220 then begin + SetErrorMessage; + FRequestResult := FStatusCode; + FControlSocket.Close; + Exit; + end; + + StateChange(ftpConnected); + if Assigned(FOnSessionConnected) then + FOnSessionConnected(Self, Error); + + if Assigned(FWhenConnected) then + FWhenConnected + else begin + TriggerRequestDone(0); + end; + end + else if FState = ftpWaitingResponse then begin + if not (FLastResponse[1] in ['0'..'9']) then begin { 22/11/99 } + DisplayLastResponse; { 02/11/01 } + Continue; { Continuation line, ignore } + end; + p := GetInteger(@FLastResponse[1], FStatusCode); + if p^ = '-' then begin + DisplayLastResponse; { 02/11/01 } + Continue; { Continuation line, ignore } + end; + if Assigned(FNext) then + FNext + else + HandleError('Program error: FNext is nil'); + end + else { Unexpected data received } + DisplayLastResponse; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.ControlSocketSessionClosed(Sender: TObject; Error: Word); +begin + if FConnected then begin + FConnected := FALSE; + if FState <> ftpAbort then + StateChange(ftpNotConnected); + if Assigned(FOnSessionClosed) then + FOnSessionClosed(Self, Error); + end; + if FState <> ftpAbort then + StateChange(ftpInternalReady); + if not (FRequestType in [ftpRqAbort]) then begin + if Error <> 0 then begin + FLastResponse := '500 Control connection closed. ' + + WSocketErrorDesc(Error) + + ' (Winsock error #' + IntToStr(Error) + ')'; + FStatusCode := 500; + FRequestResult := FStatusCode; { 06 apr 2002 } + SetErrorMessage; + end; + TriggerRequestDone(FRequestResult); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.TriggerStateChange; +begin + if Assigned(FOnStateChange) then + FOnStateChange(Self); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.TriggerRequestDone(Error: Word); +begin + if not FRequestDoneFlag then begin + FRequestDoneFlag := TRUE; + if (Error = 0) and Assigned(FNextRequest) then begin + if (FState <> ftpAbort) + and (FState <> ftpPasvReady) { 19.09.2002 } + { and 28/06/2002 + not ((ftpFctPut in FFctSet) and (FPassive = true))} then + StateChange(ftpInternalReady); + FNextRequest; + end + else begin + StateChange(ftpReady); + if FDataSocket.State <> wsClosed then + FDataSocket.Close; + { Restore the lastresponse saved before quit command } + if FHighLevelFlag and (FStatusCodeSave >= 0) then begin + FLastResponse := FLastResponseSave; + FStatusCode := FStatusCodeSave; + end; + FHighLevelFlag := FALSE; + FNextRequest := nil; + PostMessage(Handle, WM_FTP_REQUEST_DONE, 0, Error); + { if Assigned(FOnRequestDone) then + FOnRequestDone(Self, FRequestType, Error); } + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomFtpCli.TriggerReadyToTransmit(var bCancel : Boolean); +begin + if Assigned(FOnReadyToTransmit) then + FOnReadyToTransmit(Self, bCancel); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomFtpCli.GetConnected : Boolean; +begin + Result := FControlSocket.State <> wsClosed; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* * * *} +{* * TFtpClient * *} +{* * * *} +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TFtpClient.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FTimeout := 15; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Open : Boolean; +begin + Result := Synchronize(OpenAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.User : Boolean; +begin + Result := Synchronize(UserAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Pass : Boolean; +begin + Result := Synchronize(PassAsync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Connect : Boolean; +begin + Result := Synchronize(ConnectASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Cwd : Boolean; +begin + Result := Synchronize(CwdASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Pwd : Boolean; +begin + Result := Synchronize(PwdASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.CDup : Boolean; +begin + Result := Synchronize(CDupASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.TypeSet : Boolean; +begin + Result := Synchronize(TypeSetASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.TypeBinary : Boolean; +begin + Binary := TRUE; + Result := Synchronize(TypeSetASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.TypeAscii : Boolean; +begin + Binary := FALSE; + Result := Synchronize(TypeSetASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Get : Boolean; +begin + Result := Synchronize(GetASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Put : Boolean; +begin + Result := Synchronize(PutASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ By A.Burlakov: new function for resuming uploads } +{ Uses REST + STOR commands instead APPEND } +function TFtpClient.RestPut : Boolean; +begin + Result := Synchronize(RestPutASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.RestartPut : Boolean; +begin + Result := Synchronize(RestartPutASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Append : Boolean; +begin + Result := Synchronize(AppendASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Quit : Boolean; +begin + Result := Synchronize(QuitASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Abort : Boolean; +begin + Result := Synchronize(AbortASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Receive : Boolean; +begin + Result := Synchronize(ReceiveASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Transmit : Boolean; +begin + Result := Synchronize(TransmitASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.AppendFile : Boolean; +begin + Result := Synchronize(AppendFileASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Dir : Boolean; +begin + Result := Synchronize(DirASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Directory : Boolean; +begin + Result := Synchronize(DirectoryASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Ls : Boolean; +begin + Result := Synchronize(LsASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.List : Boolean; +begin + Result := Synchronize(ListASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Mkd : Boolean; +begin + Result := Synchronize(MkdASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Mkdir : Boolean; +begin + Result := Synchronize(MkdirASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Ren : Boolean; +begin + Result := Synchronize(RenASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Rename : Boolean; +begin + Result := Synchronize(RenameASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Dele : Boolean; +begin + Result := Synchronize(DeleASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Delete : Boolean; +begin + Result := Synchronize(DeleteASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Rmd : Boolean; +begin + Result := Synchronize(RmdASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Rmdir : Boolean; +begin + Result := Synchronize(RmdirASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Syst : Boolean; +begin + Result := Synchronize(SystASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.System : Boolean; +begin + Result := Synchronize(SystemASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Size : Boolean; +begin + Result := Synchronize(SizeASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.FileSize : Boolean; +begin + Result := Synchronize(FileSizeASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.AbortXfer: Boolean; +begin + Result := Synchronize(AbortXferASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Quote : Boolean; +begin + Result := Synchronize(QuoteASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.DoQuote : Boolean; +begin + Result := Synchronize(DoQuoteASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.RestGet : Boolean; +begin + Result := Synchronize(RestGetASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.RestartGet : Boolean; +begin + Result := Synchronize(RestartGetASync); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Progress : Boolean; +begin + Result := inherited Progress; + { Evaluate the timeout period again } + if FTimeout > 0 then + FTimeStop := LongInt(GetTickCount) + LongInt(FTimeout) * 1000; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpClient.MessagePump; +begin +{$IFDEF VER80} + Application.ProcessMessages; +{$ELSE} + if FMultiThreaded then + FControlSocket.ProcessMessages + else +{$IFDEF NOFORMS} + { The Forms unit (TApplication object) has not been included. } + { We used either an external message pump or our internal message pump. } + { External message pump has to set Terminated property to TRUE when the } + { application is terminated. } + if Assigned(FOnMessagePump) then + FOnMessagePump(Self) + else + FControlSocket.ProcessMessages; +{$ELSE} + Application.ProcessMessages; +{$ENDIF} +{$ENDIF} +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.WaitUntilReady : Boolean; +begin + Result := TRUE; { Assume success } + FTimeStop := LongInt(GetTickCount) + LongInt(FTimeout) * 1000; + while TRUE do begin + if FState in [ftpReady, ftpInternalReady] then begin + { Back to ready state, the command is finished } + Result := (FRequestResult = 0); + break; + end; + + if {$IFNDEF NOFORMS} Application.Terminated or + {$ELSE} Terminated or + {$ENDIF} + ((FTimeout > 0) and (LongInt(GetTickCount) > FTimeStop)) then begin + { Timeout occured } + AbortAsync; + FErrorMessage := '426 Timeout'; + FStatusCode := 426; + Result := FALSE; { Command failed } + break; + end; + MessagePump; + { Do not use 100% CPU, but slow down transfert on high speed LAN } + {$IFNDEF VER80} + Sleep(0); + {$ENDIF} + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpClient.Synchronize(Proc : TFtpNextProc) : Boolean; +begin + try + Proc; + Result := WaitUntilReady; + except + Result := FALSE; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + + diff --git a/ICS_zlog/Delphi/Vc32/FtpSrvC.dcu b/ICS_zlog/Delphi/Vc32/FtpSrvC.dcu new file mode 100644 index 0000000000000000000000000000000000000000..1e6a1c12e0af03989328c5c22d4e4d06c61fa298 GIT binary patch literal 16720 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 M`+LS!*)ZS#0jdNm;s5{u literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/FtpSrvC.pas b/ICS_zlog/Delphi/Vc32/FtpSrvC.pas new file mode 100644 index 00000000..2698c12c --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/FtpSrvC.pas @@ -0,0 +1,579 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: TFtpCtrlSocket component. It handle the client connection for + the TFtpServer component. +Creation: April 21, 1998 +Version: 1.09 +EMail: http://www.overbyte.be francois.piette@overbyte.be + http://www.rtfm.be/fpiette francois.piette@rtfm.be +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997-2001 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +History: +Apr 29, 1998 V0.90 released for beta testing. +May 03, 1998 V0.93 Adapted for Delphi 2.0 and C++Builder +May 04, 1998 V0.94 Added support for UNC (not finished !) +Jul 09, 1998 V1.00 Adapted for Delphi 4, removed beta status. +Jul 21, 1998 V1.01 Publised TrumpetCompatibility property. +Aug 06, 1998 V1.02 Verified that FRcvCnt was 0 in SetRcvSize. Suggested + by Nick MacDonald +Mar 06, 1999 V1.03 Added code from Plegge, Steve to add + APPE and STRU support. +Aug 20, 1999 V1.04 Revised compile time options. Adapted for BCB4. +Nov 24, 1999 V1.05 Added MTDM support. Thanks to Bruce Christensen + for his code. +Jan 24, 2000 V1.06 Patch IE5 bug in file names. Thanks to +Nov 11, 2000 V1.07 Checked for DOS attack. Close connection when buffer + overflow occured. Thanks to Lester for finding + this security hole. +Jul 28, 2001 V1.08 Added ID property to uniquely indentify the client. +Sep 09, 2001 V1.09 Eric Pascual changed TFtpCmdType type + to make it a Byte so that new values can be added by + sub-components which add new commands. + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit FtpSrvC; + +interface + +{$B-} { Enable partial boolean evaluation } +{$T-} { Untyped pointers } +{$X+} { Enable extended syntax } +{$IFNDEF VER80} { Not for Delphi 1 } + {$H+} { Use long strings } + {$J+} { Allow typed constant to be modified } +{$ENDIF} +{$IFDEF VER110} { C++ Builder V3.0 } + {$ObjExportAll On} +{$ENDIF} +{$IFDEF VER125} { C++ Builder V4.0 } + {$ObjExportAll On} +{$ENDIF} + +uses + WinTypes, WinProcs, Messages, Classes, SysUtils, Winsock, WSocket; + +const + FtpCtrlSocketVersion = 109; + CopyRight : String = ' TFtpCtrlSocket (c) 1998-2001 F. Piette V1.09 '; + DefaultRcvSize = 2048; + +type + EFtpCtrlSocketException = class(Exception); + TFtpCtrlState = (ftpcInvalid, ftpcWaitingUserCode, ftpcWaitingPassword, + ftpcReady, ftpcWaitingAnswer); + + { TFtpCmdType is now defined as a byte and enumerated items as constants, } + { so that new values can be added by sub-components who add new commands } + TFtpCmdType = Byte; + +const + ftpcPORT = 0; + ftpcSTOR = 1; + ftpcRETR = 2; + ftpcCWD = 3; + ftpcXPWD = 4; + ftpcPWD = 5; + ftpcUSER = 6; + ftpcPASS = 7; + ftpcLIST = 8; + ftpcRMD = 9; + ftpcTYPE = 10; + ftpcSYST = 11; + ftpcQUIT = 12; + ftpcDELE = 13; + ftpcRNFR = 14; + ftpcMKD = 15; + ftpcRNTO = 16; + ftpcNOOP = 17; + ftpcNLST = 18; + ftpcABOR = 19; + ftpcCDUP = 20; + ftpcSIZE = 21; + ftpcREST = 22; + ftpcAPPE = 23; + ftpcSTRU = 24; {jsp - Added APPE and STRU types } + ftpcMDTM = 25; {bkc - Added MDTM type } + ftpcSTOU = 26; {ep - Added STOU type } + ftpcFEAT = 27; {SSV - Added FEAT type } + +type + TFtpOption = (ftpcUNC); + TFtpOptions = set of TFtpOption; + TDisplayEvent = procedure (Sender : TObject; Msg : String) of object; + TCommandEvent = procedure (Sender : TObject; CmdBuf : PChar; CmdLen : Integer) of object; + + TFtpCtrlSocket = class(TCustomWSocket) + protected + FDataSocket : TWSocket; + FRcvBuf : PChar; + FRcvCnt : Integer; + FRcvSize : Integer; + FBusy : Boolean; + FConnectedSince : TDateTime; + FLastCommand : TDateTime; + FCommandCount : LongInt; + FBanner : String; + FUserName : String; + FPassWord : String; + FCloseRequest : Boolean; + FHomeDir : String; + FDirectory : String; + FFtpState : TFtpCtrlState; + FAbortingTransfer : Boolean; + FUserData : LongInt; { Reserved for component user } + FPeerAddr : String; + FID : LongInt; + FOnDisplay : TDisplayEvent; + FOnCommand : TCommandEvent; + procedure TriggerSessionConnected(Error : Word); override; + function TriggerDataAvailable(Error : Word) : boolean; override; + procedure TriggerCommand(CmdBuf : PChar; CmdLen : Integer); virtual; + procedure SetRcvSize(newValue : Integer); + public + BinaryMode : Boolean; + DataAddr : String; + DataPort : String; + FileName : String; + FilePath : String; + DataSessionActive : Boolean; + DataStream : TStream; + HasOpenedFile : Boolean; + TransferError : String; + ByteCount : LongInt; + DataSent : Boolean; + CurCmdType : TFtpCmdType; + RestartPos : LongInt; + FromFileName : String; + ToFileName : String; + PassiveMode : Boolean; + PassiveStart : Boolean; + PassiveConnected : Boolean; + Options : TFtpOptions; + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Dup(newHSocket : TSocket); override; + procedure StartConnection; virtual; + procedure SendAnswer(Answer : String); + procedure SetDirectory(newValue : String); + procedure SetAbortingTransfer(newValue : Boolean); + function GetPeerAddr: string; override; + property DataSocket : TWSocket read FDataSocket; + property ConnectedSince : TDateTime read FConnectedSince; + property LastCommand : TDateTime read FLastCommand; + property CommandCount : LongInt read FCommandCount; + property RcvBuf : PChar read FRcvBuf; + property RcvdCount; + property CloseRequest : Boolean read FCloseRequest + write FCloseRequest; + property Directory : String read FDirectory + write SetDirectory; + property HomeDir : String read FHomeDir + write FHomeDir; + property AbortingTransfer : Boolean read FAbortingTransfer + write SetAbortingTransfer; + property ID : LongInt read FID + write FID; + published + property FtpState : TFtpCtrlState read FFtpState + write FFtpState; + property Banner : String read FBanner + write FBanner; + property RcvSize : integer read FRcvSize + write SetRcvSize; + property Busy : Boolean read FBusy + write FBusy; + property UserName : String read FUserName + write FUserName; + property PassWord : String read FPassWord + write FPassWord; + property UserData : LongInt read FUserData + write FUserData; + property OnDisplay : TDisplayEvent read FOnDisplay + write FOnDisplay; + property OnCommand : TCommandEvent read FOnCommand + write FOnCommand; + property OnSessionClosed; + property OnDataSent; + property HSocket; + property AllSent; + property State; +{$IFDEF VER80} + property TrumpetCompability; +{$ENDIF} + end; + +function IsUNC(S : String) : Boolean; +procedure PatchIE5(var S : String); +{$IFDEF VER80} +function ExtractFileDir(const FileName: String): String; +function ExtractFileDrive(const FileName: String): String; +{$ENDIF} + +implementation + +const + DefaultBanner = '220-ICS FTP Server ready'; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +procedure SetLength(var S: string; NewLength: Integer); +begin + S[0] := chr(NewLength); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ ExtractFileDir extracts the drive and directory parts of the given } +{ filename. The resulting string is a directory name suitable for passing } +{ to SetCurrentDir, CreateDir, etc. The resulting string is empty if } +{ FileName contains no drive and directory parts. } +function ExtractFileDir(const FileName: String): String; +var + I: Integer; +begin + I := Length(FileName); + while (I > 0) and (not (FileName[I] in ['\', ':'])) do + Dec(I); + if (I > 1) and (FileName[I] = '\') and + (not (FileName[I - 1] in ['\', ':'])) then + Dec(I); + Result := Copy(FileName, 1, I); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ ExtractFileDrive extracts the drive part of the given filename. For } +{ filenames with drive letters, the resulting string is ':'. } +{ For filenames with a UNC path, the resulting string is in the form } +{ '\\\'. If the given path contains neither } +{ style of filename, the result is an empty string. } +function ExtractFileDrive(const FileName: String): String; +var + I : Integer; +begin + if Length(FileName) <= 1 then + Result := '' + else begin + if FileName[2] = ':' then + Result := Copy(FileName, 1, 2) + else if (FileName[2] = '\') and (FileName[1] = '\') then begin + { UNC file name } + I := 3; + while (I <= Length(FileName)) and (FileName[I] <> '\') do + Inc(I); + Inc(I); + while (I <= Length(FileName)) and (FileName[I] <> '\') do + Inc(I); + Result := Copy(FileName, 1, I - 1); + end + else + Result := ''; + end; +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TFtpCtrlSocket.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FDataSocket := TWSocket.Create(Self); + FDataSocket.Name := 'DataWSocket'; + FBanner := DefaultBanner; + FFtpState := ftpcInvalid; + FHomeDir := 'C:\TEMP\'; + FDirectory := FHomeDir; + SetRcvSize(DefaultRcvSize); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor TFtpCtrlSocket.Destroy; +begin + FRcvCnt := 0; { Clear received data } + SetRcvSize(0); { Free the buffer } + if Assigned(FDataSocket) then begin + FDataSocket.Destroy; + FDataSocket := nil; + end; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpCtrlSocket.SetRcvSize(newValue : Integer); +begin + if FRcvCnt <> 0 then + raise EFtpCtrlSocketException.Create('Data in buffer, can''t change size'); + + if FRcvSize < 0 then + FRcvSize := 0; + + if FRcvSize = newValue then + Exit; { No change, nothing to do } + + { Free previously allocated buffer } + if FRcvBuf <> nil then begin + FreeMem(FRcvBuf, FRcvSize); + FRcvBuf := nil; + end; + + { Allocate new buffer } + FRcvSize := newValue; + + { If size is nul, then do not allocated the buffer } + if newValue > 0 then + GetMem(FRcvBuf, FRcvSize); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpCtrlSocket.StartConnection; +begin + FConnectedSince := Now; + FLastCommand := 0; + FCommandCount := 0; + FFtpState := ftpcWaitingUserCode; + SendStr(FBanner + #13#10); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpCtrlSocket.GetPeerAddr: String; +begin + Result := FPeerAddr; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpCtrlSocket.Dup(newHSocket : TSocket); +begin + inherited Dup(newHSocket); + FPeerAddr := inherited GetPeerAddr; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpCtrlSocket.TriggerSessionConnected(Error : Word); +begin + FPeerAddr := inherited GetPeerAddr; + inherited TriggerSessionConnected(Error); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpCtrlSocket.TriggerCommand(CmdBuf : PChar; CmdLen : Integer); +begin + if Assigned(FOnCommand) then + FOnCommand(Self, CmdBuf, CmdLen); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TFtpCtrlSocket.TriggerDataAvailable(Error : Word) : Boolean; +var + Len : Integer; + I : Integer; +begin + Result := TRUE; { We read data } + + Len := Receive(@FRcvBuf[FRcvCnt], FRcvSize - FRcvCnt - 1); + if Len <= 0 then + Exit; + + FRcvCnt := FRcvCnt + Len; + FRcvBuf[FRcvCnt] := #0; + + while TRUE do begin + I := 0; + while (I < FRcvCnt) and (FRcvBuf[I] <> #10) do + Inc(I); + if I >= FRcvCnt then begin + { Check line overflow. } + if FRcvCnt >= (FRcvSize - 1) then begin + StrPCopy(FRcvBuf, 'OVER' + #13#10); + FRcvCnt := StrLen(FRcvBuf); + I := FRcvCnt - 1; + end + else + Exit; + end; + FRcvBuf[I] := #0; + FLastCommand := Now; + Inc(FCommandCount); + if (I > 1) and (FRcvBuf[I - 1] = #13) then begin + FRcvBuf[I - 1] := #0; + TriggerCommand(FRcvBuf, I - 1); + FRcvBuf[I - 1] := #13; + end + else + TriggerCommand(FRcvBuf, I); + + FRcvBuf[I] := #10; + if I >= (FRcvCnt - 1) then begin + FRcvCnt := 0; + FRcvBuf[0] := #0; + break; + end; + Move(FRcvBuf[I + 1], FRcvBuf^, FRcvCnt - I); + FRcvCnt := FRcvCnt - I - 1; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpCtrlSocket.SendAnswer(Answer : String); +begin + SendStr(Answer + #13#10); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function IsUNC(S : String) : Boolean; +begin + Result := (Length(S) >= 2) and (S[2] = '\') and (S[1] = '\'); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure PatchIE5(var S : String); +begin + { \c:\Temp\ -> c:\Temp\ IE5 like this invalid syntax !} + if (Length(S) >= 3) and (S[3] = ':') and (S[1] = '\') then + Delete(S, 1, 1); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpCtrlSocket.SetDirectory(newValue : String); +var + newDrive : String; + newPath : String; + I : Integer; +begin + if FDirectory = newValue then + Exit; + + PatchIE5(newValue); + newDrive := ExtractFileDrive(newValue); + if IsUNC(newDrive) then begin + if not (ftpcUNC in Options) then + raise Exception.Create('Cannot accept UNC path'); + FDirectory := newValue; + { Always terminate with a backslash } + if (Length(FDirectory) > 0) and (FDirectory[Length(FDirectory)] <> '\') then + FDirectory := FDirectory + '\'; + Exit; + end; + + if Length(newDrive) = 0 then begin + newDrive := ExtractFileDrive(FDirectory); + newPath := newValue; + end + else + newPath := Copy(newValue, 3, Length(newValue)); + + if Pos(':', newPath) <> 0 then + raise Exception.Create('Invalid directory name syntax'); + + if newPath = '..' then begin + if IsUNC(FDirectory) then begin + I := Length(FDirectory) - 1; + while (I > 0) and (FDirectory[I] <> '\') do + Dec(I); + if I > Length(newDrive) then + SetLength(FDirectory, I); + Exit; + end + else begin + newPath := Copy(FDirectory, 3, Length(FDirectory)); + I := Length(newPath) - 1; + while (I > 0) and (newPath[I] <> '\') do + Dec(I); + SetLength(newPath, I); + end; + end; + + if (Length(newPath) > 0) and (newPath[1] <> '\') then begin + { Relative path } + if IsUNC(FDirectory) then begin + FDirectory := FDirectory + newPath; + { Always terminate with a backslash } + if (Length(FDirectory) > 0) and (FDirectory[Length(FDirectory)] <> '\') then + FDirectory := FDirectory + '\'; + Exit; + end + else begin + if UpperCase(newDrive[1]) <> UpperCase(FDirectory[1]) then + raise Exception.Create('Cannot accept path not relative to current directory'); + if Pos('.\', newPath) <> 0 then + raise Exception.Create('Cannot accept relative path using dot notation'); + if newPath = '.' then + newPath := Copy(FDirectory, 3, Length(FDirectory)) + else + newPath := Copy(FDirectory, 3, Length(FDirectory)) + newPath; + end; + end + else begin + if Pos('.\', newPath) <> 0 then + raise Exception.Create('Cannot accept relative path using dot notation'); + end; + + if Length(newPath) = 0 then begin + if UpperCase(newDrive[1]) <> UpperCase(FDirectory[1]) then + newPath := '\' + else + newPath := Copy(FDirectory, 3, Length(FDirectory)); + end; + + { Always terminate with a backslash } + if (Length(newPath) > 0) and (newPath[Length(newPath)] <> '\') then + newPath := newPath + '\'; + + FDirectory := newDrive + newPath; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TFtpCtrlSocket.SetAbortingTransfer(newValue : Boolean); +begin + FAbortingTransfer := newValue; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + + diff --git a/ICS_zlog/Delphi/Vc32/FtpSrvT.dcu b/ICS_zlog/Delphi/Vc32/FtpSrvT.dcu new file mode 100644 index 0000000000000000000000000000000000000000..382560895aceb4857b6d69c28742df8c4df0989c GIT binary patch literal 2701 zcmZuy4NP0t6~6Ca8{;_66JpFmD0(o~c`We^BrGgZhlx$?2pa}=0@aG99AQ=R9N5Ifouf6TXlXsT*kcp0kx@jhc8qJ+DF3Af2F*&;O&no-}v*tPKQmc zu7DhhiS1E25Q`-#Un=uC0;=eX4vB;A^S^tb=4EPInYdk10!bA4=}WV}luA3|ayTlh z=Z^mV?QstFcY2+JZpUDc&+c{DyB)7N<}XNCwdQbIH& zB7n6)sw5UeS0IE#>lc+cAq}8`8m&z4k)&I%(aDFRAvGfDKm53^TO3KmR0&pv(qQp< zIcV8JcTDGnGsk=l=9h(v^Lxy|KS<09TDeaQD3WeX(8->-jKaEAK_fc?NlAAXF;_gH zj7Yj=K`(ovazYi+xr0s*o}wH==eA(LNGujb1l`4;WgE`CBOVOI+MSp zDdB5)bI?J6RFVzu^A4gXmD>;=-&&TPP)D z{A=5O?!3QD`73Awuj(VjWLf`9JB2Px+|?PC>@d>^@lF_+M1Jnv`x*^Ki; zCRV_l_qsBk)r|kWVv&qz`Km@rZ?cv%o;z0ofovh|PR4Va0q+-p+ZoRy1M*$w5{ntn zO$NMIVBE}j-etgQ0eCl}$KErZ`Ku+Ue6N7cr=9E5dhD9{O~n!X8I7 z$1qFj?EL5~toXrMoVeD7!^xbYYZudUsalu%(Utl%!%Cble_6|LoYczpBA9&$EX#u! z$DZi8^T%CCTD#?3ySdwf)fS!lrGe}VOL%g{W?pkJZZ@CGG9JAZsL0T?f8BLzLDlYU zTUYY!w4QN5ZpUX-&5oUktr;A~vsfa}E##z}+0D7+uSQ<0cs1~t`uYau{%0g7uVqvI z|8D6ps^>3Au_aauxl7e`FFgEQJpIkuVNAsa8K+pA7RIg9%{FW*=d}1p5{4;i7=2S? z4@0(xZWz*j{IhAtQPj!ptc@r8?}lFVrEWh)Q(ocV>~xn4SXF~ z>bX$^)bp@Q;70RRnzdsBC5%-AhMLWwY=_<|ZY&?I&`y}R2{YGW;#>x(tl}oH5U-uo za2-b720e%DITjbkMFHGXE*i-GeJmbP;VvK0u^f~Yno}9h$=38&SGrwRUnvIgP zZx{(|l)Tu5|C!ES?8f!QOFmrBUpYt&Vo?NvI*T&? z^!|M}w16Fkv5&hAkas>uqj&ewwE-TdW;c#VM-An+>KW2T11->MVn#vX0r)Yf%!+Un zZ2&|VMVo}nP)FHGIEE#YZ~{(23XWswYiM`TPzuJ;J%`L^&|ZL7pqav#VFCwx9lj%Y n1vBBxdxgV1DUS)i0zyC$%shcnfhVMKjI9#_URHjRt|agunLTyR literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/FtpSrvT.pas b/ICS_zlog/Delphi/Vc32/FtpSrvT.pas new file mode 100644 index 00000000..43a2378e --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/FtpSrvT.pas @@ -0,0 +1,178 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: Time functions. +EMail: francois.piette@pophost.eunet.be francois.piette@swing.be + francois.piette@rtfm.be http://www.rtfm.be/fpiette +Creation: Nov 24, 1999 from Bruce Christensen + code used with his permission. Thanks. +Version: 1.02 +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1999-2000 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +History: +Apr 02, 2000 V1.01 Added definition for TIME_ZONE_ID_STANDARD for BCB1 and BCB3 +May 20, 2000 V1.01 Added definition for TIME_ZONE_ID_STANDARD for Delphi 3 + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit FtpSrvT; + +interface + +{$B-} { Enable partial boolean evaluation } +{$T-} { Untyped pointers } +{$X+} { Enable extended syntax } +{$IFNDEF VER80} { Not for Delphi 1 } + {$H+} { Use long strings } + {$J+} { Allow typed constant to be modified } +{$ENDIF} +{$IFDEF VER110} { C++ Builder V3.0 } + {$ObjExportAll On} +{$ENDIF} +{$IFDEF VER125} { C++ Builder V4.0 } + {$ObjExportAll On} +{$ENDIF} + +const + FtpSrvT_Unit = 102; + CopyRight : String = ' FtpSrvT (c) 1999-2000 F. Piette V1.02 '; + +function FileUtcStr(cFileName : String) : String; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +implementation +uses + WinTypes, WinProcs, SysUtils; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function PadIntZero(nWord : Word; + nWidth : Byte): String; +var + cResult : String; +begin + cResult := IntToStr(nWord); + while Length(cResult) < nWidth do + cResult := '0' + cResult; + + Result := cResult; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TimeDateStr(dDateTime : TDateTime) : String; +var + nYear, nMonth, nDay, nHours, nMinutes, nSeconds, nMilliSecs : Word; +begin + DecodeDate(dDateTime, nYear, nMonth, nDay); + DecodeTime(dDateTime, nHours, nMinutes, nSeconds, nMilliSecs); + + Result := PadIntZero(nYear, 4) + + PadIntZero(nMonth, 2) + + PadIntZero(nDay, 2) + + PadIntZero(nHours, 2) + + PadIntZero(nMinutes, 2) + + PadIntZero(nSeconds, 2) + '.' + + PadIntZero(nMilliSecs, 3); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function GetLocalBiasUTC : LongInt; +{$IFDEF VER80} +{ Delphi 1 doesn't support GetTimeZoneInformation } +begin + Result := 0; +end; +{$ELSE} +var + tzInfo : TTimeZoneInformation; +{$IFDEF VER93} {BCB1} +const + TIME_ZONE_ID_STANDARD = 1; + TIME_ZONE_ID_DAYLIGHT = 2; +{$ENDIF} +{$IFDEF VER110} {BCB3} +const + TIME_ZONE_ID_STANDARD = 1; + TIME_ZONE_ID_DAYLIGHT = 2; +{$ENDIF} +{$IFDEF VER90} {D2} +const + TIME_ZONE_ID_STANDARD = 1; + TIME_ZONE_ID_DAYLIGHT = 2; +{$ENDIF} +{$IFDEF VER100} {D3} +const + TIME_ZONE_ID_STANDARD = 1; + TIME_ZONE_ID_DAYLIGHT = 2; +{$ENDIF} +begin + case GetTimeZoneInformation(tzInfo) of + TIME_ZONE_ID_STANDARD: Result := tzInfo.Bias + tzInfo.StandardBias; + TIME_ZONE_ID_DAYLIGHT: Result := tzInfo.Bias + tzInfo.DaylightBias; + else + Result := tzInfo.Bias; + end; +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function DateTimeToUTC(dtDT : TDateTime) : TDateTime; +begin + Result := dtDT + GetLocalBiasUTC / (60.0 * 24.0); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function GetFileAge(cFile : String) : Integer; +begin + if cFile[Length(cFile)] in ['\', '/'] then + cFile := cFile + '.'; + Result := FileAge(cFile); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function FileUtcStr(cFileName : String) : String; +begin + Result := TimeDateStr( + DateTimeToUTC( + FileDateToDateTime(GetFileAge(cFileName)))); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Vc32/HttpSrv.dcr b/ICS_zlog/Delphi/Vc32/HttpSrv.dcr new file mode 100644 index 0000000000000000000000000000000000000000..3064c3682ca3b0da95e9abfa9fc7324aac8e54a9 GIT binary patch literal 476 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 literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/HttpSrv.pas b/ICS_zlog/Delphi/Vc32/HttpSrv.pas new file mode 100644 index 00000000..472a5b96 --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/HttpSrv.pas @@ -0,0 +1,1347 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: THttpServer implement the HTTP server protocol, that is a + web server kernel. +Creation: Oct 10, 1999 +Version: 1.06 +EMail: http://www.overbyte.be francois.piette@overbyte.be + http://www.rtfm.be/fpiette francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Support: Use the mailing list twsocket@elists.org + Follow "support" link at http://www.overbyte.be for subscription. +Legal issues: Copyright (C) 1999-2001 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +History: +Nov 12, 1999 Beta 3 Added Linger properties +Apr 23, 2000 Beta 4 Added Delphi 1 compatibility + Made everything public in THttpConnection because BCB has problems + when deriving a component from Delphi and protected functions. +Oct 29, 2000 Beta 5 Added Client[] property and IsClient() method. +Nov 11, 2000 Beta 6 Added code from Sven to set + Last-Modified header line. Need some more changes ! +Nov 12, 2000 Beta 7 Finished Last-Modified implementation. + Corrected TriggerServerStopped. +Jun 18, 2001 V1.01 Check if still connected before sending any data. +Jul 31, 2001 V1.02 Handle URL encoded document file (for example when there is + a space in the file name). Bug reported by Stian Grønland + . + Better handling of non existant documents or documents with invalid + file name. +Jan 13, 2002 V1.03 Changed SetPort() to SetPortValue() to avoid a conflict with + BCB6 which has a macro to replace SetPort with SetPortA ! +Apr 15, 2002 V1.04 In SendDocument, avoid calling Send(nil, 0) when a document + has to be sent. Bug and fix by Adam Laforge . +Jul 06, 2002 V1.05 Thomas Smyth fixed + ExtractURLEncodedValue which had problem with names beginning with + same sequence of chars. +Oct 12, 2002 V1.06 Added THttpConnection.PostedDataReceived to be called from + OnPostedData event handler when application has received all data + from client. + Added read/only property SrcVersion with component source version + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit HttpSrv; + +interface + +uses + WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, + Dialogs, WSocket, WSocketS; + +const + THttpServerVersion = 106; + CopyRight : String = ' THttpServer (c) 1999-2002 F. Piette V1.06 '; + WM_HTTP_DONE = WM_USER + 40; + +type + THttpConnection = class; + THttpConnectionClass = class of THttpConnection; + THttpGetFlag = (hgSendDoc, hgSendStream, hgWillSendMySelf, hg404, hgAcceptData); + THttpSendType = (httpSendHead, httpSendDoc); + THttpGetEvent = procedure (Sender : TObject; + Client : TObject; + var Flags : THttpGetFlag) of object; + THttpGetConnEvent = procedure (Sender : TObject; + var Flags : THttpGetFlag) of object; + THttpConnectEvent = procedure (Sender : TObject; + Client : TObject; + Error : Word) of object; + THttpPostedDataEvent = procedure (Sender : TObject; + Client : TObject; + Error : Word) of object; + THttpConnectionState = (hcRequest, hcHeader, hcPostedData); + + { THttpConnection is used to handle client connections } + THttpConnection = class(TWSocketClient) + public + FRcvdLine : String; + FMethod : String; + FVersion : String; + FPath : String; + FParams : String; + FRequestHeader : TStringList; + FState : THttpConnectionState; + FDocDir : String; + FDefaultDoc : String; + FDocument : String; + FDocStream : TStream; + FDocBuf : PChar; + FLastModified : TDateTime; + FAnswerContentType : String; + FRequestContentLength : Integer; + FRequestContentType : String; + FRequestAccept : String; + FRequestReferer : String; + FRequestAcceptLanguage : String; + FRequestAcceptEncoding : String; + FRequestUserAgent : String; + FRequestHost : String; + FRequestConnection : String; + FAcceptPostedData : Boolean; + FOnGetDocument : THttpGetConnEvent; + FOnHeadDocument : THttpGetConnEvent; + FOnPostDocument : THttpGetConnEvent; + FOnPostedData : TDataAvailable; + procedure ConnectionDataAvailable(Sender: TObject; Error : Word); + procedure ConnectionDataSent(Sender : TObject; Error : WORD); + procedure ParseRequest; + procedure ProcessRequest; + procedure ProcessGet; + procedure ProcessHead; + procedure ProcessPost; + procedure SendDocument(SendType : THttpSendType); + procedure SendStream; + procedure Answer404; + procedure WndProc(var MsgRec: TMessage); override; + procedure WMHttpDone(var msg: TMessage); message WM_HTTP_DONE; + procedure TriggerGetDocument(var Flags : THttpGetFlag); virtual; + procedure TriggerHeadDocument(var Flags : THttpGetFlag); virtual; + procedure TriggerPostDocument(var Flags : THttpGetFlag); virtual; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure PostedDataReceived; virtual; + { Method contains GET/POST/HEAD as requested by client } + property Method : String read FMethod; + { Version contains HTTP version from client request } + property Version : String read FVersion; + { The whole header as received from client } + property RequestHeader : TStringList + read FRequestHeader; + { Stream used to send reply to client } + property DocStream : TStream + read FDocStream + write FDocStream; + { All RequestXXX are header fields from request header } + property RequestContentLength : Integer + read FRequestContentLength; + property RequestContentType : String read FRequestContentType; + property RequestAccept : String read FRequestAccept; + property RequestReferer : String read FRequestReferer; + property RequestAcceptLanguage : String read FRequestAcceptLanguage; + property RequestAcceptEncoding : String read FRequestAcceptEncoding; + property RequestUserAgent : String read FRequestUserAgent; + property RequestHost : String read FRequestHost; + property RequestConnection : String read FRequestConnection; + published + { Where all documents are stored. Default to c:\wwwroot } + property DocDir : String read FDocDir + write FDocDir; + { Default document name. Default to index.html } + property DefaultDoc : String read FDefaultDoc + write FDefaultDoc; + { Complete document path and file name on local file system } + property Document : String read FDocument + write FDocument; + { Document path as requested by client } + property Path : String read FPath + write FPath; + { Parameters in request (Question mark is separator) } + property Params : String read FParams + write FParams; + { Triggered when client sent GET request } + property OnGetDocument : THttpGetConnEvent read FOnGetDocument + write FOnGetDocument; + { Triggered when client sent HEAD request } + property OnHeadDocument : THttpGetConnEvent read FOnHeadDocument + write FOnHeadDocument; + { Triggered when client sent POST request } + property OnPostDocument : THttpGetConnEvent read FOnPostDocument + write FOnPostDocument; + { Triggered when client sent POST request and data is available } + property OnPostedData : TDataAvailable read FOnPostedData + write FOnPostedData; + end; + + { This is the HTTP server component handling all HTTP connection } + { service. Most of the work is delegated to a TWSocketServer } + THttpServer = class(TComponent) + protected + { FWSocketServer will handle all client management work } + FWSocketServer : TWSocketServer; + FPort : String; + FAddr : String; + FClientClass : THttpConnectionClass; + FDocDir : String; + FDefaultDoc : String; + FLingerOnOff : TSocketLingerOnOff; + FLingerTimeout : Integer; { In seconds, 0 = disabled } + FOnServerStarted : TNotifyEvent; + FOnServerStopped : TNotifyEvent; + FOnClientConnect : THttpConnectEvent; + FOnClientDisconnect : THttpConnectEvent; + FOnGetDocument : THttpGetEvent; + FOnHeadDocument : THttpGetEvent; + FOnPostDocument : THttpGetEvent; + FOnPostedData : THttpPostedDataEvent; + procedure Notification(AComponent: TComponent; operation: TOperation); override; + procedure WSocketServerClientConnect(Sender : TObject; + Client : TWSocketClient; + Error : Word); + procedure WSocketServerClientCreate(Sender : TObject; + Client : TWSocketClient); + procedure WSocketServerClientDisconnect(Sender : TObject; + Client : TWSocketClient; + Error : Word); + procedure WSocketServerSessionClosed(Sender : TObject; + Error : Word); + procedure WSocketServerChangeState(Sender : TObject; + OldState, NewState : TSocketState); + procedure TriggerServerStarted; virtual; + procedure TriggerServerStopped; virtual; + procedure TriggerClientConnect(Client : TObject; Error : Word); virtual; + procedure TriggerClientDisconnect(Client : TObject; Error : Word); virtual; + procedure TriggerGetDocument(Sender : TObject; + var Flags : THttpGetFlag); virtual; + procedure TriggerHeadDocument(Sender : TObject; + var Flags : THttpGetFlag); virtual; + procedure TriggerPostDocument(Sender : TObject; + var Flags : THttpGetFlag); virtual; + procedure TriggerPostedData(Sender : TObject; + Error : WORD); virtual; + procedure SetPortValue(newValue : String); + procedure SetAddr(newValue : String); + function GetClientCount : Integer; + function GetClient(nIndex : Integer) : THttpConnection; + function GetSrcVersion: String; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Start; virtual; + procedure Stop; virtual; + { Check if a given object is one of our clients } + function IsClient(SomeThing : TObject) : Boolean; + { Runtime readonly property which gives number of connected clients } + property ClientCount : Integer read GetClientCount; + { Client[] give direct access to anyone of our clients } + property Client[nIndex : Integer] : THttpConnection + read GetClient; + { Runtime property which tell the component class which has to be } + { instanciated to handle client connection } + property ClientClass : THttpConnectionClass + read FClientClass + write FClientClass; + published + { Component source version } + property SrcVersion : String read GetSrcVersion; + { We will listen to that port. Default to 80 for http service } + property Port : String read FPort + write SetPortValue; + { We will use that interface to listen. 0.0.0.0 means all } + { available interfaces } + property Addr : String read FAddr + write SetAddr; + { Where all documents are stored. Default to c:\wwwroot } + property DocDir : String read FDocDir + write FDocDir; + { Default document name. Default to index.html } + property DefaultDoc : String read FDefaultDoc + write FDefaultDoc; + property LingerOnOff : TSocketLingerOnOff + read FLingerOnOff + write FLingerOnOff; + property LingerTimeout : Integer read FLingerTimeout + write FLingerTimeout; + { OnServerStrated is triggered when server has started listening } + property OnServerStarted : TNotifyEvent + read FOnServerStarted + write FOnServerStarted; + { OnServerStopped is triggered when server has stopped listening } + property OnServerStopped : TNotifyEvent + read FOnServerStopped + write FOnServerStopped; + { OnClientConnect is triggered when a client has connected } + property OnClientConnect : THttpConnectEvent + read FOnClientConnect + write FOnClientConnect; + { OnClientDisconnect is triggered when a client is about to } + { disconnect. } + property OnClientDisconnect : THttpConnectEvent + read FOnClientDisconnect + write FOnClientDisconnect; + { OnGetDocument is triggered when a client sent GET request } + { You can either do nothing and let server handle all work, or } + { you can build a document on the fly or refuse access. } + property OnGetDocument : THttpGetEvent + read FOnGetDocument + write FOnGetDocument; + { OnGetDocument is triggered when a client sent HEAD request } + { You can either do nothing and let server handle all work, or } + { you can build a document header on the fly or refuse access. } + property OnHeadDocument : THttpGetEvent + read FOnHeadDocument + write FOnHeadDocument; + { OnGetDocument is triggered when a client sent POST request } + { You have to tell if you accept data or not. If you accept, } + { you'll get OnPostedData event with incomming data. } + property OnPostDocument : THttpGetEvent + read FOnPostDocument + write FOnPostDocument; + { On PostedData is triggered when client post data and you } + { accepted it from OnPostDocument event. } + { When you've got all data, you have to build a reply to be } + { sent to client. } + property OnPostedData : THttpPostedDataEvent + read FOnPostedData + write FOnPostedData; + end; + +{ Retrieve a single value by name out of an URL encoded data stream. } +function ExtractURLEncodedValue( + Msg : PChar; { URL Encoded stream } + Name : String; { Variable name to look for } + var Value : String): Boolean; { Where to put variable value } +{ Decode an URLEncoded string } +function UrlDecode(const Url : String) : String; +procedure Register; + +implementation + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure Register; +begin + RegisterComponents('FPiette', [THttpServer]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +procedure SetLength(var S: string; NewLength: Integer); +begin + S[0] := chr(NewLength); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{$IFDEF VER80} +function TrimRight(Str : String) : String; +var + i : Integer; +begin + i := Length(Str); + while (i > 0) and (Str[i] = ' ') do + i := i - 1; + Result := Copy(Str, 1, i); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TrimLeft(Str : String) : String; +var + i : Integer; +begin + if Str[1] <> ' ' then + Result := Str + else begin + i := 1; + while (i <= Length(Str)) and (Str[i] = ' ') do + i := i + 1; + Result := Copy(Str, i, Length(Str) - i + 1); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function Trim(Str : String) : String; +begin + Result := TrimLeft(TrimRight(Str)); +end; +{$ENDIF} + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor THttpServer.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FWSocketServer := TWSocketServer.Create(Self); + FClientClass := THttpConnection; + FAddr := '0.0.0.0'; + FPort := '80'; + FDefaultDoc := 'index.html'; + FDocDir := 'c:\wwwroot'; + FLingerOnOff := wsLingerNoSet; + FLingerTimeout := 0; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor THttpServer.Destroy; +begin + if Assigned(FWSocketServer) then begin + FWSocketServer.Destroy; + FWSocketServer := nil; + end; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Called by destructor when child component is created or destroyed. } +procedure THttpServer.Notification( + AComponent : TComponent; + Operation : TOperation); +begin + inherited Notification(AComponent, Operation); + if Operation = opRemove then begin + if AComponent = FWSocketServer then + FWSocketServer := nil; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Start the server. That is make FWSocketServer listening to the port. } +procedure THttpServer.Start; +begin + { Create a new FWSocketServer if needed } + if not Assigned(FWSocketServer) then + FWSocketServer := TWSocketServer.Create(Self); + { If already listening, then do nothing } + if FWSocketServer.State = wsListening then + Exit; + { Pass al parameters to FWSocketServer and make it listen } + FWSocketServer.ClientClass := FClientClass; + FWSocketServer.OnClientCreate := WSocketServerClientCreate; + FWSocketServer.OnClientConnect := WSocketServerClientConnect; + FWSocketServer.OnClientDisconnect := WSocketServerClientDisconnect; + FWSocketServer.OnSessionClosed := WSocketServerSessionClosed; + FWSocketServer.OnChangeState := WSocketServerChangeState; + FWSocketServer.Banner := ''; + FWSocketServer.Proto := 'tcp'; + FWSocketServer.Port := FPort; + FWSocketServer.Addr := FAddr; + FWSocketServer.Listen; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpServer.Stop; +var + I : Integer; +begin + if not Assigned(FWSocketServer) then + Exit; + FWSocketServer.Close; + { Disconnect all clients } + for I := FWSocketServer.ClientCount - 1 downto 0 do begin + try + FWSocketServer.Client[I].Abort; + except + { Ignore any exception here } + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpServer.SetPortValue(newValue : String); +begin + if newValue = FPort then + Exit; + FPort := newValue; + { If server is already listening, then stop it and restart it with } + { new port. Do not disconnect already connected clients. } + if Assigned(FWSocketServer) and + (FWSocketServer.State = wsListening) then begin + FWSocketServer.Close; + Start; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpServer.SetAddr(newValue : String); +begin + if newValue = FAddr then + Exit; + FAddr := newValue; + { If server is already listening, then stop it and restart it with } + { new Addr. Do not disconnect already connected clients. } + if Assigned(FWSocketServer) and + (FWSocketServer.State = wsListening) then begin + FWSocketServer.Close; + Start; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Get function for ClientCount property. Just return value from } +{ FWSocketServer. } +function THttpServer.GetClientCount; +begin + if not Assigned(FWSocketServer) then + Result := 0 + else + Result := FWSocketServer.ClientCount; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Get function for Client[] property. Just return value from } +{ FWSocketServer. } +function THttpServer.GetClient(nIndex : Integer) : THttpConnection; +begin + if not Assigned(FWSocketServer) then + Result := nil + else + Result := THttpConnection(FWSocketServer.Client[nIndex]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Check is an object is one of our clients. Just return value from } +{ FWSocketServer. } +function THttpServer.IsClient(SomeThing : TObject) : Boolean; +begin + if not Assigned(FWSocketServer) then + Result := FALSE + else + Result := FWSocketServer.IsClient(SomeThing); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This event handler is triggered when state of server socket has changed. } +{ We use it to trigger our OnServerStarted event. } +procedure THttpServer.WSocketServerChangeState( + Sender : TObject; + OldState, NewState : TSocketState); +begin + if newState = wsListening then + TriggerServerStarted; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpServer.WSocketServerSessionClosed( + Sender : TObject; + Error : Word); +begin + TriggerServerStopped; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ A new client component has been created } +procedure THttpServer.WSocketServerClientCreate( + Sender : TObject; + Client : TWSocketClient); +begin + Client.LingerOnOff := FLingerOnOff; + Client.LingerTimeout := FLingerTimeout; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ A new client just connected. Setup things to handle his requests. } +{ HTTP header is line oriented so we turn line mode on. We use LF as end of } +{ line character altough HTTP uses CR/LF pair as end of line, because many } +{ Unix client do not respect standards and use single LF... } +{ HTTP is not interactive, so we turn line editing to false (faster). } +procedure THttpServer.WSocketServerClientConnect( + Sender : TObject; + Client : TWSocketClient; + Error : Word); +begin + THttpConnection(Client).LineMode := TRUE; + THttpConnection(Client).LineEdit := FALSE; + THttpConnection(Client).LineEnd := #10; + THttpConnection(Client).DocDir := Self.DocDir; + THttpConnection(Client).DefaultDoc := Self.DefaultDoc; + THttpConnection(Client).OnGetDocument := TriggerGetDocument; + THttpConnection(Client).OnHeadDocument := TriggerHeadDocument; + THttpConnection(Client).OnPostDocument := TriggerPostDocument; + THttpConnection(Client).OnPostedData := TriggerPostedData; + TriggerClientConnect(Client, Error); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ A client is about to disconnect. } +procedure THttpServer.WSocketServerClientDisconnect( + Sender : TObject; + Client : TWSocketClient; + Error : Word); +begin + TriggerClientDisconnect(Client, Error); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpServer.TriggerServerStarted; +begin + if Assigned(FOnServerStarted) then + FOnServerStarted(Self); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpServer.TriggerServerStopped; +begin + if Assigned(FOnServerStopped) then + FOnServerStopped(Self); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpServer.TriggerClientConnect( + Client : TObject; + Error : Word); +begin + if Assigned(FOnClientConnect) then + FOnClientConnect(Self, Client, Error); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpServer.TriggerClientDisconnect( + Client : TObject; + Error : Word); +begin + if Assigned(FOnClientDisconnect) then + FOnClientDisconnect(Self, Client, Error); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpServer.TriggerGetDocument( + Sender : TObject; + var Flags : THttpGetFlag); +begin + if Assigned(FOnGetDocument) then + FOnGetDocument(Self, Sender, Flags); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpServer.TriggerHeadDocument( + Sender : TObject; + var Flags : THttpGetFlag); +begin + if Assigned(FOnHeadDocument) then + FOnHeadDocument(Self, Sender, Flags); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpServer.TriggerPostedData(Sender : TObject; + Error : WORD); +begin + if Assigned(FOnPostedData) then + FOnPostedData(Self, Sender, Error); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpServer.TriggerPostDocument( + Sender : TObject; + var Flags : THttpGetFlag); +begin + if Assigned(FOnPostDocument) then + FOnPostDocument(Self, Sender, Flags); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor THttpConnection.Create(AOwner : TComponent); +begin + inherited Create(AOwner); + LineMode := TRUE; + LineEdit := FALSE; + LineEnd := #10; + FRequestHeader := TStringList.Create; + FState := hcRequest; + OnDataAvailable := ConnectionDataAvailable; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor THttpConnection.Destroy; +begin + if Assigned(FRequestHeader) then begin + FRequestHeader.Destroy; + FRequestHeader := nil; + end; + if Assigned(FDocStream) then begin + FDocStream.Destroy; + FDocStream := nil; + end; + if Assigned(FDocBuf) then begin + FreeMem(FDocBuf, BufSize); + FDocBuf := nil; + end; + inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpConnection.WndProc(var MsgRec: TMessage); +begin + with MsgRec do begin + { We *MUST* handle all exception to avoid application shutdown } + try + if Msg = WM_HTTP_DONE then + WMHttpDone(MsgRec) + else + inherited WndProc(MsgRec); + except + on E:Exception do + HandleBackGroundException(E); + end; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpConnection.WMHttpDone(var msg: TMessage); +begin + FState := hcRequest; + if CompareText(FRequestConnection, 'Keep-Alive') <> 0 then + CloseDelayed; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This procedure is called each time data is available from a client. } +{ We use FState variable to keep track of the where we are in the http } +{ protocol: request command, header line or posted data. } +procedure THttpConnection.ConnectionDataAvailable(Sender: TObject; Error : Word); +var + Len : Integer; + I : Integer; +begin + { If we are in data state, then the application has to receive data } + if FState = hcPostedData then begin + if FAcceptPostedData and Assigned(FOnPostedData) then + FOnPostedData(Self, Error) + else + { No one is willing data, received it and throw it away } + FRcvdLine := ReceiveStr; + Exit; + end; + { We use line mode. We will receive complete lines } + FRcvdLine := ReceiveStr; + { Remove trailing CR/LF } + Len := Length(FRcvdLine); + if (Len > 0) and (FRcvdLine[Len] = #10) then begin + Dec(Len); + if (Len > 0) and (FRcvdLine[Len] = #13) then + Dec(Len); + SetLength(FRcvdLine, Len); + end; + if FState = hcRequest then begin + { We just start a new request. Initialize all header variables } + FRequestContentType := ''; + FRequestContentLength := 0; + FRequestContentType := ''; + FRequestAccept := ''; + FRequestReferer := ''; + FRequestAcceptLanguage := ''; + FRequestAcceptEncoding := ''; + FRequestUserAgent := ''; + FRequestHost := ''; + FRequestConnection := ''; + { The line we just received is HTTP command, parse it } + ParseRequest; + { Next lines will be header lines } + FState := hcHeader; + Exit; + end; + { We can comes here only in hcHeader state } + if FRcvdLine = '' then begin + { Last header line is an empty line. Then we enter data state } + FState := hcPostedData; + { We will process request before receiving data because application } + { has to setup things to be able to receive posted data } + ProcessRequest; + Exit; + end; + { We comes here for normal header line. Extract some interesting variables } + I := Pos(':', FRcvdLine); + if I > 0 then begin + try + repeat + Inc(I); + until (I > Length(FRcvdLine)) or (FRcvdLine[I] <> ' '); + if StrLIComp(@FRcvdLine[1], 'content-type:', 13) = 0 then + FRequestContentType := Copy(FRcvdLine, I, Length(FRcvdLine)) + else if StrLIComp(@FRcvdLine[1], 'content-length:', 15) = 0 then + FRequestContentLength := StrToInt(Copy(FRcvdLine, I, Length(FRcvdLine))) + else if StrLIComp(@FRcvdLine[1], 'Accept:', 7) = 0 then + FRequestAccept:= Copy(FRcvdLine, I, Length(FRcvdLine)) + else if StrLIComp(@FRcvdLine[1], 'Referer:', 8) = 0 then + FRequestReferer := Copy(FRcvdLine, I, Length(FRcvdLine)) + else if StrLIComp(@FRcvdLine[1], 'Accept-Language:', 16) = 0 then + FRequestAcceptLanguage := Copy(FRcvdLine, I, Length(FRcvdLine)) + else if StrLIComp(@FRcvdLine[1], 'Accept-Encoding:', 16) = 0 then + FRequestAcceptEncoding := Copy(FRcvdLine, I, Length(FRcvdLine)) + else if StrLIComp(@FRcvdLine[1], 'User-Agent:', 11) = 0 then + FRequestUserAgent := Copy(FRcvdLine, I, Length(FRcvdLine)) + else if StrLIComp(@FRcvdLine[1], 'Host:', 5) = 0 then + FRequestHost := Copy(FRcvdLine, I, Length(FRcvdLine)) + else if StrLIComp(@FRcvdLine[1], 'Connection:', 11) = 0 then + FRequestConnection := Copy(FRcvdLine, I, Length(FRcvdLine)); + except + { Ignore any exception in parsing header line } + end; + end; + FRequestHeader.Add(FRcvdLine); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Request is in FRcvdLine property. } +{ Split it into FMethod, FPath, FVersion and parameters. } +procedure THttpConnection.ParseRequest; +var + I, J : Integer; +begin + I := 1; + while (I <= Length(FRcvdLine)) and (FRcvdLine[I] <> ' ') do + Inc(I); + FMethod := UpperCase(Copy(FRcvdLine, 1, I - 1)); + Inc(I); + while (I <= Length(FRcvdLine)) and (FRcvdLine[I] = ' ') do + Inc(I); + J := I; + while (I <= Length(FRcvdLine)) and (FRcvdLine[I] <> ' ') do + Inc(I); + FPath := Copy(FRcvdLine, J, I - J); + { Find parameters } + J := Pos('?', FPath); + if J <= 0 then + FParams := '' + else begin + FParams := Copy(FPath, J + 1, Length(FPath)); + FPath := Copy(FPath, 1, J - 1); + end; + Inc(I); + while (I <= Length(FRcvdLine)) and (FRcvdLine[I] = ' ') do + Inc(I); + J := I; + while (I <= Length(FRcvdLine)) and (FRcvdLine[I] <> ' ') do + Inc(I); + FVersion := Trim(UpperCase(Copy(FRcvdLine, J, I - J))); + if FVersion = '' then + FVersion := 'HTTP/1.0'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpConnection.Answer404; +var + Body : String; +begin + Body := '404 Not Found' + + '

404 Not Found

The requested URL ' + FPath + + ' was not found on this server.

' + #13#10; + PutStringInSendBuffer(FVersion + ' 404 Not Found' + #13#10 + + 'Content-Type: text/html' + #13#10 + + 'Content-Length: ' + IntToStr(Length(Body)) + #13#10 + + #13#10); + SendStr(Body); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ As its name implies... } +procedure THttpConnection.ProcessRequest; +var + I : Integer; +begin + if FPath[1] = '/' then + FDocument := FDocDir + FPath + else + FDocument := FDocDir + '\' + FPath; + { Check for default document } + if FDocument[Length(FDocument)] = '/' then + FDocument := FDocument + FDefaultDoc; + { Change slashes to backslashes } + for I := 1 to Length(FDocument) do begin + if FDocument[I] = '/' then + FDocument[I] := '\'; + end; + + FDocument := URLDecode(FDocument); + + if FMethod = 'GET' then + ProcessGet + else if FMethod = 'POST' then + ProcessPost + else if FMethod = 'HEAD' then + ProcessHead + else begin + Answer404; + CloseDelayed; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpConnection.TriggerGetDocument(var Flags : THttpGetFlag); +begin + if Assigned(FOnGetDocument) then + FOnGetDocument(Self, Flags); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpConnection.TriggerHeadDocument(var Flags : THttpGetFlag); +begin + if Assigned(FOnHeadDocument) then + FOnHeadDocument(Self, Flags); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpConnection.TriggerPostDocument(var Flags : THttpGetFlag); +begin + if Assigned(FOnPostDocument) then + FOnPostDocument(Self, Flags); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpConnection.ProcessPost; +var + Flags : THttpGetFlag; +begin + Flags := hg404; + TriggerPostDocument(Flags); + if Flags = hg404 then begin + Answer404; + CloseDelayed; + Exit; + end + else if Flags = hgAcceptData then + FAcceptPostedData := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ This method has to be called by main code when all posted data has been } +{ received. } +procedure THttpConnection.PostedDataReceived; +begin + LineMode := TRUE; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpConnection.ProcessHead; +var + Flags : THttpGetFlag; +begin + Flags := hgSendDoc; + TriggerHeadDocument(Flags); + case Flags of + hg404: + begin + Answer404; + CloseDelayed; + end; + hgSendDoc: + begin + if FileExists(FDocument) then + SendDocument(httpSendHead) + else begin + Answer404; + CloseDelayed; + end; + end; + hgSendStream: + SendStream; + hgWillSendMySelf: + { Nothing to do }; + else + CloseDelayed; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpConnection.ProcessGet; +var + Flags : THttpGetFlag; + TempStream : TFileStream; + OK : Boolean; +begin + Flags := hgSendDoc; + TriggerGetDocument(Flags); + case Flags of + hg404: + begin + Answer404; + CloseDelayed; + end; + hgSendDoc: + begin + OK := FALSE; + try + if not FileExists(FDocument) then begin + { File not found } + Answer404; + CloseDelayed; + end + else begin + TempStream := TFileStream.Create(FDocument, fmOpenRead + fmShareDenyWrite); + TempStream.Destroy; + OK := TRUE; + end; + except + Answer404; + CloseDelayed; + end; + if OK then + SendDocument(httpSendDoc) + end; + hgSendStream: + SendStream; + hgWillSendMySelf: + { Nothing to do }; + else + CloseDelayed; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function DocumentToContentType(FileName : String) : String; +var + Ext : String; +begin + { We probably should the registry to find MIME type for known file types } + Ext := LowerCase(ExtractFileExt(FileName)); + if Length(Ext) > 1 then + Ext := Copy(Ext, 2, Length(Ext)); + if (Ext = 'htm') or (Ext = 'html') then + Result := 'text/html' + else if Ext = 'gif' then + Result := 'image/gif' + else if Ext = 'bmp' then + Result := 'image/bmp' + else if (Ext = 'jpg') or (Ext = 'jpeg') then + Result := 'image/jpeg' + else if Ext = 'txt' then + Result := 'text/plain' + else + Result := 'application/binary'; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function RFC1123_Date(aDate : TDateTime) : String; +const + StrWeekDay : String = 'MonTueWedThuFriSatSun'; + StrMonth : String = 'JanFebMarAprMayJunJulAugSepOctNovDec'; +var + Year, Month, Day : Word; + Hour, Min, Sec, MSec : Word; + DayOfWeek : Word; +begin + DecodeDate(aDate, Year, Month, Day); + DecodeTime(aDate, Hour, Min, Sec, MSec); + DayOfWeek := ((Trunc(aDate) - 2) mod 7); + Result := Copy(StrWeekDay, 1 + DayOfWeek * 3, 3) + ', ' + + Format('%2.2d %s %4.4d %2.2d:%2.2d:%2.2d', + [Day, Copy(StrMonth, 1 + 3 * (Month - 1), 3), + Year, Hour, Min, Sec]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Return document file date from document filename. } +{ Return 0 if file not found. } +function FileDate(FileName : String) : TDateTime; +var + SearchRec : TSearchRec; + Status : Integer; +begin + Status := FindFirst(FileName, faAnyFile, SearchRec); + try + if Status <> 0 then + Result := 0 + else + Result := FileDateToDateTime(SearchRec.Time); + finally + FindClose(SearchRec); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ SendDocument will send FDocument file to remote client, build header and } +{ sending data (if required) } +procedure THttpConnection.SendDocument(SendType : THttpSendType); +var + DocSize : Integer; +begin + FLastModified := FileDate(FDocument); + FAnswerContentType := DocumentToContentType(FDocument); + + if Assigned(FDocStream) then begin + FDocStream.Destroy; + FDocStream := nil; + end; + FDocStream := TFileStream.Create(FDocument, fmOpenRead + fmShareDenyWrite); + DocSize := FDocStream.Size; + { Seek to end of document because HEAD will not send actual document } + if SendType = httpSendHead then + FDocStream.Seek(0, soFromEnd); + OnDataSent := ConnectionDataSent; + { Send Header } + PutStringInSendBuffer( + FVersion + ' 200 OK' + #13#10 + + 'Content-Type: ' + FAnswerContentType + #13#10 + + 'Content-Length: ' + IntToStr(DocSize) + #13#10); + if FLastModified <> 0 then + PutStringInSendBuffer( + 'Last-Modified: ' + RFC1123_Date(FLastModified) + 'GMT' + #13#10); + PutStringInSendBuffer(#13#10); + { Send(nil, 0); Removed 15/04/02 } + if SendType = httpSendDoc then + SendStream + else + Send(nil, 0); { Added 15/04/02 } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure THttpConnection.SendStream; +begin + if not Assigned(FDocStream) then begin + CloseDelayed; + Exit; + end; + if not Assigned(FDocBuf) then + GetMem(FDocBuf, BufSize); + OnDataSent := ConnectionDataSent; + ConnectionDataSent(Self, 0); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ All data in TWSocket has been sent. Read next lock from stream and send. } +{ When end of stream is reached, closed communication. } +procedure THttpConnection.ConnectionDataSent(Sender : TObject; Error : WORD); +var + Count : Integer; +begin + if not Assigned(FDocStream) then begin + { End of file has been reached } + Exit; + end; + Count := FDocStream.Read(FDocBuf^, BufSize); + if Count <= 0 then begin + { End of file found } + FDocStream.Destroy; + FDocStream := nil; + ShutDown(1); +{$IFNDEF VER80} + Sleep(0); +{$ENDIF} + PostMessage(Handle, WM_HTTP_DONE, 0, 0); + Exit; + end; + if State = wsConnected then { Be sure to be still connected... } + Send(FDocBuf, Count); { before actually send any data. } +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function xdigit(Ch : char) : Integer; +begin + if ch in ['0'..'9'] then + Result := ord(Ch) - ord('0') + else + Result := (ord(Ch) and 15) + 9; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function isxdigit(Ch : char) : Boolean; +begin + Result := (ch in ['0'..'9']) or (ch in ['a'..'z']) or (ch in ['A'..'Z']); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function htoin(value : PChar; len : Integer) : Integer; +var + i : Integer; +begin + Result := 0; + i := 0; + while (i < len) and (Value[i] = ' ') do + i := i + 1; + while (i < len) and (isxDigit(Value[i])) do begin + Result := Result * 16 + xdigit(Value[i]); + i := i + 1; + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function htoi2(value : PChar) : Integer; +begin + Result := htoin(value, 2); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ Retrieve a single value by name out of an URL encoded data stream } +{ In the stream, every space is replaced by a '+'. The '%' character is } +{ an escape character. The next two are 2 digits hexadecimal codes ascii } +{ code value. The stream is constitued by name=value couples separated } +{ by a single '&' character. The special characters are coded by the '%' } +{ followed by hex-ascii character code. } +function ExtractURLEncodedValue( + Msg : PChar; { URL Encoded stream } + Name : String; { Variable name to look for } + var Value : String) { Where to put variable value } + : Boolean; { Found or not found that's the question } +var + NameLen : Integer; + FoundLen : Integer; {tps} + Ch : Char; + P, Q : PChar; +begin + Result := FALSE; + Value := ''; + if Msg = nil then { Empty source } + Exit; + + NameLen := Length(Name); + + P := Msg; + while P^ <> #0 do begin + Q := P; + while (P^ <> #0) and (P^ <> '=') do + Inc(P); + FoundLen := P - Q; {tps} + if P^ = '=' then + Inc(P); + if (StrLIComp(Q, @Name[1], NameLen) = 0) and + (NameLen = FoundLen) then begin {tps} + while (P^ <> #0) and (P^ <> '&') do begin + Ch := P^; + if Ch = '%' then begin + Ch := chr(htoi2(P + 1)); + Inc(P, 2); + end + else if Ch = '+' then + Ch := ' '; + Value := Value + Ch; + Inc(P); + end; + Result := TRUE; + break; + end; + while (P^ <> #0) and (P^ <> '&') do + Inc(P); + if P^ = '&' then + Inc(P); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function UrlDecode(const Url : String) : String; +var + I, J, K, L : Integer; +begin + Result := Url; + L := Length(Result); + I := 1; + K := 1; + while TRUE do begin + J := I; + while (J <= Length(Result)) and (Result[J] <> '%') do begin + if J <> K then + Result[K] := Result[J]; + Inc(J); + Inc(K); + end; + if J > Length(Result) then + break; { End of string } + if J > (Length(Result) - 2) then begin + while J <= Length(Result) do begin + Result[K] := Result[J]; + Inc(J); + Inc(K); + end; + break; + end; + Result[K] := Char(htoi2(@Result[J + 1])); + Inc(K); + I := J + 3; + Dec(L, 2); + end; + SetLength(Result, L); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function THttpServer.GetSrcVersion: String; +begin + Result := Format('%d.%02.2d', [THttpServerVersion div 100, + THttpServerVersion mod 100]); + +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. diff --git a/ICS_zlog/Delphi/Vc32/IcsBcb30.bpk b/ICS_zlog/Delphi/Vc32/IcsBcb30.bpk new file mode 100644 index 00000000..e0d53d8f --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/IcsBcb30.bpk @@ -0,0 +1,186 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE SECTION +# --------------------------------------------------------------------------- +# The following section of the project makefile is managed by the BCB IDE. +# It is recommended to use the IDE to change any of the values in this +# section. +# --------------------------------------------------------------------------- + +VERSION = BCB.03 +# --------------------------------------------------------------------------- +PROJECT = IcsBcb30.bpl +OBJFILES = WSocket.obj WSockets.obj httpprot.obj ftpcli.obj wait.obj tnscript.obj \ + fingcli.obj nntpcli.obj ping.obj tncnx.obj tnemulvt.obj emulvt.obj FtpSrv.obj \ + SmtpProt.obj wsockbuf.obj Pop3Prot.obj MimeDec.obj DnsQuery.obj IcsBcb30.obj +RESFILES = IcsBcb30.res WSocket.dcr WSockets.dcr httpprot.dcr ftpcli.dcr wait.dcr \ + tnscript.dcr fingcli.dcr nntpcli.dcr ping.dcr tncnx.dcr tnemulvt.dcr emulvt.dcr \ + FtpSrv.dcr SmtpProt.dcr Pop3Prot.dcr MimeDec.dcr DnsQuery.dcr +DEFFILE = +RESDEPEN = $(RESFILES) +LIBFILES = +LIBRARIES = VCLX35.lib VCLDB35.lib +SPARELIBS = VCL35.lib VCLDB35.lib VCLX35.lib +PACKAGES = VCL35.bpi +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .; +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +# --------------------------------------------------------------------------- +CFLAG1 = -Od -Hc -w -Ve -r- -k -y -v -vi- -c -b- -w-par -w-inl -Vx +CFLAG2 = -D_RTLDLL;USEPACKAGES \ + -I..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\include;$(BCB)\include\vcl \ + -H=$(BCB)\lib\vcl35.csm +CFLAG3 = -Tkh30000 +PFLAGS = -D_RTLDLL;USEPACKAGES \ + -U..\vc32;..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \ + -I..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\include;$(BCB)\include\vcl -$Y \ + -$W -$O- -v -JPHN -M +RFLAGS = -D_RTLDLL;USEPACKAGES \ + -i..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\include;$(BCB)\include\vcl +AFLAGS = /i..\..\internet /i.. /i..\..\..\delphi\vc32 /i$(BCB)\include \ + /i$(BCB)\include\vcl /d_RTLDLL /dUSEPACKAGES /mx /w2 /zd +LFLAGS = -L..\vc32;..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \ + -D"ICS components by F. Piette" -aa -Tpp -x -Gn -Gl -Gi -v +IFLAGS = +# --------------------------------------------------------------------------- +ALLOBJ = c0pkg32.obj $(PACKAGES) sysinit.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mti.lib +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=1 +AutoIncBuild=1 +MajorVer=1 +MinorVer=0 +Release=0 +Build=3 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=2060 +CodePage=1252 + +[Version Info Keys] +CompanyName=OverByte (F. Piette) +FileDescription=ICS Components for BCB3 +FileVersion=1.0.0.3 +InternalName=IcsBcb30 +LegalCopyright=(c) 97'-'98 by F. Piette +LegalTrademarks= +OriginalFilename= +ProductName=ICS +ProductVersion=1.0.0.0 +Comments=http://www.rtfm.be/fpiette/indexuk.htm + +[HistoryLists\hlIncludePath] +Count=1 +Item0=..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\include;$(BCB)\include\vcl + +[HistoryLists\hlLibraryPath] +Count=2 +Item0=..\vc32;..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\lib\obj;$(BCB)\lib +Item1=..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[HistoryLists\hlConditionals] +Count=1 +Item0=_RTLDLL;USEPACKAGES + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +HostApplication= + +!endif + +# --------------------------------------------------------------------------- +# MAKE SECTION +# --------------------------------------------------------------------------- +# This section of the project file is not used by the BCB IDE. It is for +# the benefit of building from the command-line using the MAKE utility. +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = ilink32 +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- diff --git a/ICS_zlog/Delphi/Vc32/IcsBcb30.cpp b/ICS_zlog/Delphi/Vc32/IcsBcb30.cpp new file mode 100644 index 00000000..26a9d12d --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/IcsBcb30.cpp @@ -0,0 +1,50 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +USERES("IcsBcb30.res"); +USEUNIT("WSocket.pas"); +USERES("WSocket.dcr"); +USEUNIT("WSockets.pas"); +USERES("WSockets.dcr"); +USEUNIT("httpprot.pas"); +USERES("httpprot.dcr"); +USEUNIT("ftpcli.pas"); +USERES("ftpcli.dcr"); +USEUNIT("wait.pas"); +USERES("wait.dcr"); +USEUNIT("tnscript.pas"); +USERES("tnscript.dcr"); +USEUNIT("fingcli.pas"); +USERES("fingcli.dcr"); +USEUNIT("nntpcli.pas"); +USERES("nntpcli.dcr"); +USEUNIT("ping.pas"); +USERES("ping.dcr"); +USEUNIT("tncnx.pas"); +USERES("tncnx.dcr"); +USEUNIT("tnemulvt.pas"); +USERES("tnemulvt.dcr"); +USEUNIT("emulvt.pas"); +USERES("emulvt.dcr"); +USEUNIT("FtpSrv.pas"); +USERES("FtpSrv.dcr"); +USEUNIT("SmtpProt.pas"); +USERES("SmtpProt.dcr"); +USEPACKAGE("VCL35.bpi"); +USEUNIT("wsockbuf.pas"); +USEUNIT("Pop3Prot.pas"); +USERES("Pop3Prot.dcr"); +USEUNIT("MimeDec.pas"); +USERES("MimeDec.dcr"); +USEUNIT("DnsQuery.pas"); +USERES("DnsQuery.dcr"); +//--------------------------------------------------------------------------- +#pragma package(smart_init) +//--------------------------------------------------------------------------- +// Package source. +//--------------------------------------------------------------------------- +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} +//--------------------------------------------------------------------------- diff --git a/ICS_zlog/Delphi/Vc32/IcsBcb30.res b/ICS_zlog/Delphi/Vc32/IcsBcb30.res new file mode 100644 index 0000000000000000000000000000000000000000..80f0f431b5892bc5f9728e3ddc603cbc1eb94af8 GIT binary patch literal 1764 zcma)5OHUI~7(Jy;?1E@x+&c>s!9=J?qPRiJ$PB(ptZCShg5?otnUt#o!K7WVm>r2f zM!PZTPjTVGo$R_Hj_12GcOF8bxBccm&bjA%+kKN=Ybb^XFgls zc{v;oeShqaGdR%%cfJl?q6w}}l$*mH*UsU->mCLC#rlq8yXT@;zR>=aAM?v&?cZ@+ zHLvT*d9pvAhjM<7?`!W2C}0(RpMwYof*{~k zF|&X4!pm5Zjyv8%E;0REZ#i1g9@e$LWsaqNEB*Q{dg+Uc zUf!Zcfs#hzN!)$WZ?XY}9(K{iHkR4%qfO;5ws1h+XU(bNF*9AF%`*mx=mqZ4+Y&h) zcxaJ-%&c3SwY7R3A35rw#&yM!g(<4fuwSK*HrHfzT65Q^TS$D{TtCF7j>#iymp;0h zC$()*!FZMRHcgRl>3DnWYs71K$Q@NwGP+H2dt|114;W81HpyuYH_4aWCAJ>>7ORnF zwZfdVQ?$;@%jEAqEBTVnH=vs82&J5&NQ-(;p17Vrpnai6xpdRkOD=J#?{ zM0c91S>1P3Y~elqblCT>$4E?zxb@hloTS8U&QfOPR3w%%byvwfpxOsUrZO3V*-MSV zGnU%rd4E?hTR*AB7M0AM5RcKxKvzMrDo-%WpRa#2j6iWmhxOkeca~!>b2DZ+?&^Gx o808*WQp=7`+1B5tu7k-ky|KU@ecPjoby=r + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[Version Info] +IncludeVerInfo=1 +AutoIncBuild=1 +MajorVer=2 +MinorVer=0 +Release=0 +Build=16 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=2060 +CodePage=1252 + +[Version Info Keys] +CompanyName=OverByte (F. Piette) +FileDescription=ICS Components for BCB5 +FileVersion=2.0.0.16 +InternalName=IcsBcb50 +LegalCopyright=(c) 1997-2000 by François PIETTE +LegalTrademarks= +OriginalFilename= +ProductName=ICS +ProductVersion=2.0.0.0 +Comments=http://www.rtfm.be/fpiette/indexuk.htm + +[HistoryLists\hlIncludePath] +Count=4 +Item0=..\..\internet;..;D:\delphi\vc32\;$(BCB)\include;$(BCB)\include\vcl +Item1=..\..\internet;..\..\Delphi;D:\delphi\vc32\;$(BCB)\include;$(BCB)\include\vcl +Item2=..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\include;$(BCB)\include\vcl +Item3=..\..\internet;..\..\DELPHI;..\..\..\delphi\vc32;$(BCB)\include;$(BCB)\include\vcl + +[HistoryLists\hlLibraryPath] +Count=7 +Item0=$(BCB)\Projects\Lib;..\..\internet;..;D:\delphi\vc32\;$(BCB)\lib\obj;$(BCB)\lib;$(BCB)\Source\ToolsAPI +Item1=$(BCB)\Projects\Lib;..\..\internet;..;D:\delphi\vc32\;$(BCB)\lib\obj;$(BCB)\lib +Item2=$(BCB)\Projects\Lib;..\..\internet;..\..\Delphi;D:\delphi\vc32\;$(BCB)\lib\obj;$(BCB)\lib +Item3=$(BCB)\Projects\Lib;..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\lib\obj;$(BCB)\lib +Item4=$(BCB)\Projects\Lib;..\..\internet;..\..\DELPHI;..\..\..\delphi\vc32;$(BCB)\lib\obj;$(BCB)\lib +Item5=..\vc32;..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\lib\obj;$(BCB)\lib +Item6=..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[HistoryLists\hlConditionals] +Count=1 +Item0=_RTLDLL;USEPACKAGES + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +HostApplication= +RemoteHost= +RemotePath= +RemoteDebug=0 + +[Compiler] +ShowInfoMsgs=0 +LinkDebugVcl=0 +LinkCGLIB=0 + +[CORBA] +AddServerUnit=1 +AddClientUnit=1 +PrecompiledHeaders=1 + +[Language] +ActiveLang= +ProjectLang= +RootDir= + + \ No newline at end of file diff --git a/ICS_zlog/Delphi/Vc32/IcsBcb50.cpp b/ICS_zlog/Delphi/Vc32/IcsBcb50.cpp new file mode 100644 index 00000000..da11507b --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/IcsBcb50.cpp @@ -0,0 +1,53 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +USERES("IcsBcb50.res"); +USEUNIT("WSocket.pas"); +USERES("WSocket.dcr"); +USEUNIT("Httpprot.pas"); +USERES("Httpprot.dcr"); +USEUNIT("Ftpcli.pas"); +USERES("Ftpcli.dcr"); +USEUNIT("Wait.pas"); +USERES("Wait.dcr"); +USEUNIT("TnScript.pas"); +USERES("TnScript.dcr"); +USEUNIT("Fingcli.pas"); +USERES("Fingcli.dcr"); +USEUNIT("Nntpcli.pas"); +USERES("Nntpcli.dcr"); +USEUNIT("Ping.pas"); +USERES("Ping.dcr"); +USEUNIT("TnCnx.pas"); +USERES("TnCnx.dcr"); +USEUNIT("TnEmulVT.pas"); +USERES("TnEmulVT.dcr"); +USEUNIT("EmulVT.pas"); +USERES("EmulVT.dcr"); +USEUNIT("FtpSrv.pas"); +USERES("FtpSrv.dcr"); +USEUNIT("SmtpProt.pas"); +USERES("SmtpProt.dcr"); +USEUNIT("WSockBuf.pas"); +USEUNIT("Pop3Prot.pas"); +USERES("Pop3Prot.dcr"); +USEUNIT("MimeDec.pas"); +USERES("MimeDec.dcr"); +USEUNIT("DnsQuery.pas"); +USERES("DnsQuery.dcr"); +USEUNIT("WSocketS.pas"); +USERES("WSocketS.dcr"); +USEUNIT("HttpSrv.pas"); +USERES("HttpSrv.dcr"); +USEPACKAGE("vcl50.bpi"); +USEUNIT("WSocketE.pas"); +//--------------------------------------------------------------------------- +#pragma package(smart_init) +//--------------------------------------------------------------------------- +// Package source. +//--------------------------------------------------------------------------- +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} +//--------------------------------------------------------------------------- diff --git a/ICS_zlog/Delphi/Vc32/IcsBcb50.res b/ICS_zlog/Delphi/Vc32/IcsBcb50.res new file mode 100644 index 0000000000000000000000000000000000000000..21465a1dd6bde888a4e8c70d2a05b65d3ec1e401 GIT binary patch literal 1784 zcma)5O-~b16g{O)tO-#}G;!ycn207qAsEyR3Ij9v1rb8r5k3kM+A=9m2ZBjiu$UeH z!oOfQCSCh0T$t!ic5H~_xp(GGr$VCd_4dB^&bgm&9soF$I8KDip7FEK;ze=_iVY0( zmn>!xOk(#%s$;`_US&B`}4w3qcfq1T?|7m5*&!4 zh@Xnx{X+{cCq=F=l1n_lO1VXuI7DBob54qJ2VMEb^%+|6bpRDg9ACjJJi{zrQ>HLS zZAboH$ZIITaZ36s;Hrs9o*S+l4AT1$^*m!#c_yd#l=~Jp>C47;dA^G^ z%_$&ji!mC?lin`SgN-WZRf-|s(R`cKlf)No54%8Y8ih z`X#?6^$I)Et!$Q=?b81mRvANXAB=pPabA+YscgwFVBONyO}wKgu=+Jt>tF{f7VC^#r)3k{w6Y`N&ZRlX?MfZC z$Fj3GCArBLIZy5m*72U1nq0+T7Sea{-pl8Be|I(CQ|ZnI?$Rc?F^QPm7PKpdU3!9H z&QRwNGcdHM^G;UD9p*Y + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[Version Info] +IncludeVerInfo=1 +AutoIncBuild=1 +MajorVer=2 +MinorVer=1 +Release=0 +Build=11 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=2060 +CodePage=1252 + +[Version Info Keys] +CompanyName=OverByte (F. Piette) +FileDescription=ICS Components for BCB6 +FileVersion=2.1.0.11 +InternalName=IcsBcb60 +LegalCopyright=(c) 1997-2002 by Francois PIETTE +LegalTrademarks= +OriginalFilename= +ProductName=ICS +ProductVersion=1.0.0.0 +Comments=http://www.overbyte.be + +[Excluded Packages] +d:\program files\borland\cbuilder6\Projects\Bpl\PXPPkg.bpl=PXPPkg +D:\PROGRAM FILES\BORLAND\CBUILDER6\BIN\DCLSTD60.BPL=Borland Standard Components +d:\program files\borland\cbuilder6\Bin\idefilters60.bpl=IDE Filter for CPP32 +d:\program files\borland\cbuilder6\Bin\dcl31w60.bpl=Delphi 1.0 Compatibility Components +d:\program files\borland\cbuilder6\Bin\dclado60.bpl=Borland ADO DB Components +D:\PROGRAM FILES\BORLAND\CBUILDER6\BIN\DCLDB60.BPL=Borland Database Components +d:\program files\borland\cbuilder6\Bin\dclbde60.bpl=Borland BDE DB Components +D:\PROGRAM FILES\BORLAND\CBUILDER6\BIN\DBX60.BPL=Borland SQL Explorer UI Package +d:\program files\borland\cbuilder6\Bin\DCLIB60.bpl=InterBase Data Access Components +d:\program files\borland\cbuilder6\Bin\dclcds60.bpl=Borland Base Cached ClientDataset Component +D:\PROGRAM FILES\BORLAND\CBUILDER6\BIN\DCLMID60.BPL=Borland MyBase DataAccess Components +d:\program files\borland\cbuilder6\Bin\dclbdecds60.bpl=Borland Local BDE ClientDataset Components +d:\program files\borland\cbuilder6\Bin\dclqrt60.bpl=QuickReport Components +d:\program files\borland\cbuilder6\Bin\dcltee60.bpl=TeeChart Components +d:\program files\borland\cbuilder6\Bin\dcldss60.bpl=Borland Decision Cube Components +d:\program files\borland\cbuilder6\Bin\dcltqr60.bpl=TeeChart for QuickReport Components +d:\program files\borland\cbuilder6\Bin\dclclxdb60.bpl=Borland CLX Database Components +D:\PROGRAM FILES\BORLAND\CBUILDER6\BIN\DCLCLXSTD60.BPL=Borland CLX Standard Components +d:\program files\borland\cbuilder6\Bin\dclmcn60.bpl=Borland DataSnap Connection Components +d:\program files\borland\cbuilder6\Bin\dclsmpedit60.bpl=Borland Editor Script Enhancements +d:\program files\borland\cbuilder6\Bin\applet60.bpl=Borland Control Panel Applet Package +d:\program files\borland\cbuilder6\Bin\dclemacsedit60.bpl=Borland Editor Emacs Enhancements +d:\program files\borland\cbuilder6\Bin\dclact60.bpl=Borland ActionBar Components +d:\program files\borland\cbuilder6\Bin\dclmlwiz60.bpl=Borland Markup Language Wizards +d:\program files\borland\cbuilder6\Bin\dclbcbsmp60.bpl=Borland Sample Controls Design Time Package +d:\program files\borland\cbuilder6\Bin\dclnet60.bpl=Borland Internet Components +d:\program files\borland\cbuilder6\Bin\DBWEBXPRT.BPL=Borland Web Wizard Package +d:\program files\borland\cbuilder6\Bin\DCLNMF60.bpl=NetMasters Fastnet Tools +d:\program files\borland\cbuilder6\Bin\dclwbm60.bpl=Borland InternetExpress Components +d:\program files\borland\cbuilder6\Bin\dclwebsnap60.bpl=Borland WebSnap Components +d:\program files\borland\cbuilder6\Bin\dclsoap60.bpl=Borland SOAP Components +d:\program files\borland\cbuilder6\Bin\dclocx60.bpl=Borland Sample Imported ActiveX Controls +d:\program files\borland\cbuilder6\Bin\dclite60.bpl=Borland Integrated Translation Environment +d:\program files\borland\cbuilder6\Bin\dcldbx60.bpl=Borland dbExpress Components +d:\program files\borland\cbuilder6\Bin\dcldbxcds60.bpl=Borland Local DBX ClientDataset Components +d:\program files\borland\cbuilder6\Bin\dclindy60.bpl=Internet Direct (Indy) for D6 Property and Component Editors +d:\program files\borland\cbuilder6\Bin\bcb2kaxserver60.bpl=Borland C++Builder COM Server Components Sample Package +d:\program files\borland\cbuilder6\Bin\bcbie60.bpl=Borland C++Builder Internet Explorer 5 Components Package +d:\program files\borland\cbuilder6\Projects\Bpl\MwBcb60.bpl=MwBcb60 + +[HistoryLists\hlIncludePath] +Count=1 +Item0=D:\FPiette\Delphi\VC32;D:\FPiette\cpp;$(BCB)\include;$(BCB)\include\vcl + +[HistoryLists\hlLibraryPath] +Count=4 +Item0=$(BCB)\Projects\Lib;D:\FPiette\Delphi\VC32;d:\program files\borland\cbuilder6\lib\debug;$(BCB)\lib\obj;$(BCB)\lib;$(BCB)\Source\ToolsAPI +Item1=D:\FPiette\Delphi\VC32;d:\program files\borland\cbuilder6\lib\debug;$(BCB)\lib\obj;$(BCB)\lib;$(BCB)\Source\ToolsAPI +Item2=D:\FPiette\Delphi\VC32;d:\program files\borland\cbuilder6\lib\debug;$(BCB)\lib\obj;$(BCB)\lib +Item3=D:\FPiette\Delphi\VC32;d:\program files\borland\cbuilder6\lib\debug;D:\FPiette\cpp;$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[HistoryLists\hlConditionals] +Count=1 +Item0=_DEBUG + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +Launcher= +UseLauncher=0 +DebugCWD= +HostApplication= +RemoteHost= +RemotePath= +RemoteLauncher= +RemoteCWD= +RemoteDebug=0 + +[Compiler] +ShowInfoMsgs=0 +LinkDebugVcl=0 +LinkCGLIB=0 + +[CORBA] +AddServerUnit=1 +AddClientUnit=1 +PrecompiledHeaders=1 + +[Linker] +LibPrefix= +LibSuffix= +LibVersion= + + \ No newline at end of file diff --git a/ICS_zlog/Delphi/Vc32/IcsBcb60.cpp b/ICS_zlog/Delphi/Vc32/IcsBcb60.cpp new file mode 100644 index 00000000..30689a63 --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/IcsBcb60.cpp @@ -0,0 +1,19 @@ +//--------------------------------------------------------------------------- + +#include +#pragma hdrstop +USEFORMNS("TnOptFrm.pas", Tnoptfrm, OptForm); +//--------------------------------------------------------------------------- +#pragma package(smart_init) +//--------------------------------------------------------------------------- + +// Package source. +//--------------------------------------------------------------------------- + +#pragma argsused +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} +//--------------------------------------------------------------------------- + \ No newline at end of file diff --git a/ICS_zlog/Delphi/Vc32/IcsBcb60.res b/ICS_zlog/Delphi/Vc32/IcsBcb60.res new file mode 100644 index 0000000000000000000000000000000000000000..09b4dd969ffcede2f561dbbaaa040b75ce451367 GIT binary patch literal 1752 zcmb`G%}!H66vzLCE-)dc3ytoqi3>ClYaxEcgh~qmgF=K5cLYm8A{0`pjgbW_(u6*V zPe9U`bm4-Uqo_o)nIWzzBIWv-!g`+4i)8FXZK)gQ)Cgt}s znc<-rG{Phc7vPlAj1V?4W#WmK2NJ&y4uW80s!peav<*wbL=*&L$jcW054Bvo8yiodVAA@t*y0P@i^$8*f;x`!(eYV28`{^#^T5JrYG%9Z@7k=X`PGj&flbK`R0rVqu*F0$kz2Wx_8gwSM4|N1}gKkq#-gm70MMf7$H@F*p7IPRk zG23PR2Y#B0l;jEA!#%o!vm6{nm-Rx=G^>|zQS-={lJCMoro3&!I_+}O(+dp;Ys@J-{hj| zs%cYIZD<;~r3#*_TGtNXLyyVn5tSC$^Dj zp$oY4U5)!`J+l!xU#4KVsE%~n0>CzM3<7@bDl=$J+SVye?qx2@+r;;yh+1D9Y Z(Z8kAEq}v9N2>H;3uN-{3=f^Ae*pqjqq_hA literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/IcsDel30.dpk b/ICS_zlog/Delphi/Vc32/IcsDel30.dpk new file mode 100644 index 00000000..2d2edbab --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/IcsDel30.dpk @@ -0,0 +1,79 @@ +package IcsDel30; + +{$R *.RES} +{$R 'wsocket.dcr'} +{$R 'wsockets.dcr'} +{$R 'wait.dcr'} +{$R 'fingcli.dcr'} +{$R 'FtpCli.dcr'} +{$R 'HttpProt.dcr'} +{$R 'MimeDec.dcr'} +{$R 'NntpCli.dcr'} +{$R 'ping.dcr'} +{$R 'tncnx.dcr'} +{$R 'tnemulvt.dcr'} +{$R 'tnscript.dcr'} +{$R 'emulvt.dcr'} +{$R 'ftpsrv.dcr'} +{$R 'MbxFile.dcr'} +{$R 'SmtpProt.dcr'} +{$R 'Pop3prot.dcr'} +{$R 'dnsquery.dcr'} +{$R 'Httpsrv.dcr'} +{$ALIGN ON} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS ON} +{$REFERENCEINFO OFF} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $00400000} +{$DESCRIPTION 'Internet Component Suite (by F. Piette)'} +{$IMPLICITBUILD ON} + +requires + vcl30; + +contains + wsocket, + wsockete, + wsockbuf, + wait, + wsockets, + fingcli, + formpos, + FtpCli, + HttpProt, + icmp, + md5, + MimeDec, + NntpCli, + ping, + tncnx, + tnemulvt, + tnoptfrm, + tnscript, + emulvt, + ftpsrv, + ftpsrvc, + MbxFile, + SmtpProt, + dnsquery, + Pop3prot, + Httpsrv, + FtpSrvT; + +end. diff --git a/ICS_zlog/Delphi/Vc32/IcsDel40.dpk b/ICS_zlog/Delphi/Vc32/IcsDel40.dpk new file mode 100644 index 00000000..2f291734 --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/IcsDel40.dpk @@ -0,0 +1,79 @@ +package IcsDel40; + +{$R *.RES} +{$R 'WSocket.dcr'} +{$R 'fingcli.dcr'} +{$R 'FtpCli.dcr'} +{$R 'FtpSrv.dcr'} +{$R 'HttpProt.dcr'} +{$R 'MimeDec.dcr'} +{$R 'NntpCli.dcr'} +{$R 'ping.dcr'} +{$R 'pop3prot.dcr'} +{$R 'TnCnx.dcr'} +{$R 'tnemulvt.dcr'} +{$R 'tnscript.dcr'} +{$R 'emulvt.dcr'} +{$R 'SmtpProt.dcr'} +{$R 'MbxFile.dcr'} +{$R 'wait.dcr'} +{$R 'DnsQuery.dcr'} +{$R 'WSocketS.dcr'} +{$R 'HttpSrv.dcr'} +{$ALIGN ON} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS ON} +{$RANGECHECKS ON} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $00400000} +{$DESCRIPTION 'ICS components (Freeware from F. Piette) Delphi 4'} +{$IMPLICITBUILD OFF} + +requires + vcl40; + +contains + WSockBuf in 'WSockBuf.pas', + WSocket in 'WSocket.pas', + WSocketE in 'WSocketE.pas', + FingCli in 'fingcli.pas', + Formpos in 'formpos.pas', + FtpCli in 'FtpCli.pas', + FtpSrv in 'FtpSrv.pas', + FtpSrvC in 'FtpSrvC.pas', + HttpProt in 'HttpProt.pas', + icmp in 'icmp.pas', + MD5 in 'MD5.pas', + MimeDec in 'MimeDec.pas', + NntpCli in 'NntpCli.pas', + Ping in 'ping.pas', + TnCnx in 'TnCnx.pas', + TnEmulVT in 'TnEmulVT.pas', + Tnoptfrm in 'tnoptfrm.pas' {OptForm}, + TnScript in 'TnScript.pas', + Emulvt in 'emulvt.pas', + SmtpProt in 'SmtpProt.pas', + MbxFile in 'MbxFile.pas', + Pop3Prot in 'Pop3Prot.pas', + Wait in 'wait.pas', + DnsQuery in 'DnsQuery.pas', + WSocketS in 'WSocketS.pas', + HttpSrv in 'HttpSrv.pas', + FtpSrvT in 'FtpSrvT.pas'; + +end. diff --git a/ICS_zlog/Delphi/Vc32/IcsDel40.res b/ICS_zlog/Delphi/Vc32/IcsDel40.res new file mode 100644 index 0000000000000000000000000000000000000000..16221e3b711e6feebc79af09a7fb229f01bc7c19 GIT binary patch literal 1844 zcmah|O;1x%5IwbxtqHL#+?bfqg$cOfLs^I$P>_$LiV?%Y4OS>0u`NyekjIL;dL=Bn zBrjdKd(Vgrlf$%&t_q|e(=xyiDy?4&coSFMB03;}$XN1d3_87K4xwb~+A|`V&O#m;ixu)a9TefTS6+|1aR6ErK{C+ainrk%j^qI_dyp zSL|llPa$>!oN@^YP&)xO8yTHQCe_|JXgVbadCO`Td(tV#?C93|gl})ycBN$3+?IW^ z+^lS$)^=KU$7$}@+#UL3jANp_xqW(CbC0-}yq444+uyJ1J|cE!YkzOgbwATif(@(b z?wwQ_KpezA;c{11JH){{ajV3u-3PdC&Dhn$Iwr!m%fZNWe6#9qGF)pMoBXYPJaG3< zPLy8DjJSAz^*ry>QQRxl!(NGB2xYSl41WWUrmJ>MrWxI{^AAo_8BB@Dx*cNg2g7builBg}jCk5{Zbu3VB5#?1tgL zwa#nb(r$Q=p=L3IInK}VnyV?zFsJ#(xt8%I@>}R~6+*Y37(J|O-lSUmjjwJpHyF=C z0V~L13FFimq!~GfMXb{LUEgg#9<$O>${;xiqldV~OrykPkw=R74OX4vE-gXH>LXVL zJmb0LpS{Ih`UE+~cv{4~=FStd!dN-=mF(hEpiXm@Xyp+^TCEB4UZYPC+wciu&#HH^ zE#?4v$==8#3~3(Y)1EEG>MyF8BD*4lXNEP)O@o}eSwoU%ORP4d%<`;JI=F;o@`274 zyYd8m{H^P+mk5hJ&62}=diQair;pSpHS}?v!va?}>-s>H#L8;Ucer;c=NraKDK<-8 zAiAiy9`b#_ZVj-$A>LSmnKn3&D?W#x?C=V)3A}2{4Dyt_oF+x<-@^>q4I=gz?&>YI-;s2CQG0E^F<~HIg;bg*pA>m!$b8YS zZQie~_fl6!xLc(xb1u@mm%eL^BV9N5AdMT7iLXm~8B{G_g?RzMeSJNq>p8~B5ZV5{ JcEo-}{s7+$peg_W literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/IcsDel50.dpk b/ICS_zlog/Delphi/Vc32/IcsDel50.dpk new file mode 100644 index 00000000..06b589b8 --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/IcsDel50.dpk @@ -0,0 +1,79 @@ +package IcsDel50; + +{$R *.RES} +{$R 'WSocket.dcr'} +{$R 'FingCli.dcr'} +{$R 'FtpCli.dcr'} +{$R 'FtpSrv.dcr'} +{$R 'HttpProt.dcr'} +{$R 'MimeDec.dcr'} +{$R 'NntpCli.dcr'} +{$R 'Ping.dcr'} +{$R 'Pop3Prot.dcr'} +{$R 'TnCnx.dcr'} +{$R 'TnEmulVT.dcr'} +{$R 'TnScript.dcr'} +{$R 'EmulVT.dcr'} +{$R 'SmtpProt.dcr'} +{$R 'MbxFile.dcr'} +{$R 'Wait.dcr'} +{$R 'DnsQuery.dcr'} +{$R 'WSocketS.dcr'} +{$R 'HttpSrv.dcr'} +{$ALIGN ON} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS ON} +{$RANGECHECKS ON} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DESCRIPTION 'ICS components (Freeware from F. Piette)'} +{$IMPLICITBUILD ON} + +requires + vcl50; + +contains + WSockBuf in 'WSockBuf.pas', + WSocket in 'WSocket.pas', + FingCli in 'FingCli.pas', + FormPos in 'FormPos.pas', + FtpCli in 'FtpCli.pas', + FtpSrv in 'FtpSrv.pas', + FtpSrvC in 'FtpSrvC.pas', + HttpProt in 'HttpProt.pas', + Icmp in 'Icmp.pas', + MD5 in 'MD5.pas', + MimeDec in 'MimeDec.pas', + NntpCli in 'NntpCli.pas', + Ping in 'Ping.pas', + TnCnx in 'TnCnx.pas', + TnEmulVT in 'TnEmulVT.pas', + TnOptFrm in 'TnOptFrm.pas' {OptForm}, + TnScript in 'TnScript.pas', + Emulvt in 'EmulVT.pas', + SmtpProt in 'SmtpProt.pas', + MbxFile in 'MbxFile.pas', + Pop3Prot in 'Pop3Prot.pas', + Wait in 'Wait.pas', + DnsQuery in 'DnsQuery.pas', + WSocketS in 'WSocketS.pas', + HttpSrv in 'HttpSrv.pas', + FtpSrvT in 'FtpSrvT.pas', + WSocketE in 'WSocketE.pas'; + +end. diff --git a/ICS_zlog/Delphi/Vc32/IcsDel50.res b/ICS_zlog/Delphi/Vc32/IcsDel50.res new file mode 100644 index 0000000000000000000000000000000000000000..e644ad107e974dc7f581cfecb33bf6feb30d4323 GIT binary patch literal 1900 zcmbVLO;1x%5Iwa`S`%VfxY3yK7DjPl`3M+gAt=a4QpJd2;RY*|kJy%`eaK@)UA+<( zU6PkB{2dK3ZDJQJ_z^5jbSFDXAUw~^do2ZtCf;`5+w68mU?Xdqby}k2SQV#b zpDZ>?+b5Nsmff}+)rzx2e~fWV6gRg|PAbkJ*OJ$?8@ttNS=S-4+gsJ$UB~%CI|KIW&m*z`-H<)S?v%9^Vlg9uXZ2cI2F&X9_A4dzFjs(rlXr>XOrPtq1;T2^R)6~t;{x0M-1Yj5;eHHSG0yqf5 ze`}przNLfU07K1U26Ozrz#Gn{G{czpS^?Y&fggX$@B zgYit{u!0PhFixF9l94l5#44?~71N8ytaOwzKn}tvg?o%QN=zDAB#7T&)d{YW5|pey zahAh#?wgz$ct~01+$4SoJ^ZcfFGiHfY-z;sfyf@tv*eLftVDZC>Jq!G4@q zKSg$V2+tG-^@f0)?lVuEdrRz6N||NZ8|nO#_67gdogVsUu)w$$>-tEh(&Mz&_8xaG z>Y zldQbka8*CLc_Raimt*V&GM^{w^A1Aa(G1xQAo2(9@+tMTosqo9MeVhBH-&-R3aKj#r literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/IcsDel60.cfg b/ICS_zlog/Delphi/Vc32/IcsDel60.cfg new file mode 100644 index 00000000..246427c5 --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/IcsDel60.cfg @@ -0,0 +1,35 @@ +-$A8 +-$B- +-$C+ +-$D+ +-$E- +-$F- +-$G+ +-$H+ +-$I+ +-$J+ +-$K- +-$L+ +-$M- +-$N+ +-$O- +-$P+ +-$Q+ +-$R+ +-$S- +-$T- +-$U- +-$V+ +-$W- +-$X+ +-$YD +-$Z1 +-cg +-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +-H+ +-W+ +-M +-$M16384,1048576 +-K$00400000 +-LE"f:\program files\borland\delphi6\Projects\Bpl" +-LN"f:\program files\borland\delphi6\Projects\Bpl" diff --git a/ICS_zlog/Delphi/Vc32/IcsDel60.dcu b/ICS_zlog/Delphi/Vc32/IcsDel60.dcu new file mode 100644 index 0000000000000000000000000000000000000000..3a959569edea7bfc93b91eed72804bc0b58d107e GIT binary patch literal 4288 zcmeHJeTY<56o2RK&dhIjM=?<`@nh9h*H27y$xqhZb#-D_CudwO*XZq=w=>Uu^WJ#p z?Yb)>CSqnGeq|yO5>X-&B_<*zVksdZX(1*hAt5TEAt51Qox3}uX5Q(a{&a@(n>*)s z?m6e3d*40xCr#^pvX7=Y$7AC)`Pm(um6=*Qqq)Wtj^QSn>ntaeva6b#Y8#quGn@P0 z++9NcxV0^N$3=#UndR=rbED#8nVKNA&Rx0`T#=g6=qYqZl= zon=a+<~LIny+zqV_ko|!mhBwbMSN~D2cnZZl^Rk z-StKJ01=M6^V023Q(UV0zjb%SK>E!p?NZPR7nu3=*XeZN}Okl@Au-So&dpw_`=4 zhH`!_o%Ob3Nk@nFWk!|@EH&(IC!6N18a6_N>)h;1?Uv}07N$3IbcG1#iWQTp__|?Z zMvF4}svxuT*xhy@jOT6p+s(xi0ij1T?85} zw_V9XZk`4^t1J;}J=YhWdIgIj>9i_4G`2gwU1)(K>EwSzPp4&tRS`lmJy%`8;zq+y zsU~B-F!&%gmDLHd_pGm^`PDJ9*#ZXu7uW8vmZ{>0;$6IUt)7Z6SsZUDoB^5)VH>VG zMQKp*^+%(X%^FGdLm<|bE$o2}y0cV0hI|VX-fCqT16&4m{1EpsKC0ugkv{1d4&}~r z6_5P!uQbTF43$B#Y%wYl`SzzW2<2LqibuZ7sSJWWeNjat-$@G?EXw%xB3;0saEL&6 zKUYmJmiGY_8OmKBlzi^Oq2h}g>!zu=;)t2fs7T~5H!6eNzN%I6!Jd6ri000zqC>K` zN4>0?@42rj`P{Bm@jbh`roB~V5aPFzFDU-)Ni%==_iK|3S4R!AjoSUxpT3oTvP&~nBz#Av!=nzfXH=;bX~o*ylFEM7^DRFY zQXYA6qs6h-%Zrp2?xUNP|H!9DKS1gq%jyvZ`D^id8B;4A&gRuTu#vl}S(dKZrSbvz z0%NbS4F3DXG*;-EbGl>!&jriV&(jM09~C$zoqXAi*B>9=kcxD>t_5D!K~ko%OlOI( zG_rgQ`UG?kbO`hz=m6+_&N3+QdoCeUWk z2GB;(I?#I18qiu$2dEPyKt9L?Wk4%I4yYBB0=0k=pjSb!fnEVMgPK6gK#M_f&_YlY z^dhJMR1aDJssYu3=76d}GeEOIRiGC@Q$WvyCV?h{#(^e)MuRFrBS00Pp`dcmAkbjY z0MI~CUr;|#Z%`jlDJTpYrGv(@3}G405(EL%pGVKK^kR9299D8Qofrz2?V+w|G= zX~}k7->>b^c2-r{y2js$5>uljt{fuK=`YdkB{36_DDE@(_ZT|vGIZWySaXYE?M;St z*BI7cW!P|qVdG_nO&1w9UtrjBj^XXI3|r4IY&*rU;{?O5;|#lxGVD3buy>bc{0;5| Bne6}o literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/IcsDel60.dof b/ICS_zlog/Delphi/Vc32/IcsDel60.dof new file mode 100644 index 00000000..cdc0eaa3 --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/IcsDel60.dof @@ -0,0 +1,108 @@ +[FileVersion] +Version=6.0 + +[Compiler] +A=8 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=1 +K=0 +L=1 +M=0 +N=1 +O=0 +P=1 +Q=1 +R=1 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=1 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; + +[Linker] +MapFile=0 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=4194304 +ExeDescription=Internet Component Suite (ICS) for Delphi 6 + +[Directories] +OutputDir= +UnitOutputDir= +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath= +Packages= +Conditionals= +DebugSourceDirs= +UsePackages=0 + +[Parameters] +RunParams= +HostApplication= +Launcher= +UseLauncher=0 +DebugCWD= + +[Language] +ActiveLang= +ProjectLang=$0000080C +RootDir= + +[Version Info] +IncludeVerInfo=1 +AutoIncBuild=1 +MajorVer=3 +MinorVer=0 +Release=0 +Build=4 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=2060 +CodePage=1252 + +[Version Info Keys] +CompanyName=OverByte - http://www.overbyte.be +FileDescription=Internet Component Suite +FileVersion=3.0.0.4 +InternalName=IcsDel60 +LegalCopyright=http://www.overbyte.be +LegalTrademarks=(c) 1996-2002 by François Piette +OriginalFilename=IcsDel60 +ProductName=ICS +ProductVersion=3.0.0.0 +Comments=email:francois.piette@overbyte.be + +[Excluded Packages] +d:\program files\borland\delphi6\Bin\dclmcn60.bpl=Borland DataSnap Connection Components +d:\program files\borland\delphi6\Bin\dclwbm60.bpl=Borland InternetExpress Components +d:\program files\borland\delphi6\Bin\dclwebsnap60.bpl=Borland WebSnap Components + +[HistoryLists\hlConditionals] +Count=2 +Item0=NOFORMS +Item1=NOFORMSA + +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; diff --git a/ICS_zlog/Delphi/Vc32/IcsDel60.dpk b/ICS_zlog/Delphi/Vc32/IcsDel60.dpk new file mode 100644 index 00000000..ffd3a3a7 --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/IcsDel60.dpk @@ -0,0 +1,81 @@ +package IcsDel60; + +{$R *.res} +{$R 'WSocket.dcr'} +{$R 'FingCli.dcr'} +{$R 'FtpCli.dcr'} +{$R 'FtpSrv.dcr'} +{$R 'HttpProt.dcr'} +{$R 'MimeDec.dcr'} +{$R 'NntpCli.dcr'} +{$R 'Ping.dcr'} +{$R 'Pop3Prot.dcr'} +{$R 'TnCnx.dcr'} +{$R 'TnEmulVT.dcr'} +{$R 'TnScript.dcr'} +{$R 'EmulVT.dcr'} +{$R 'SmtpProt.dcr'} +{$R 'MbxFile.dcr'} +{$R 'Wait.dcr'} +{$R 'DnsQuery.dcr'} +{$R 'WSocketS.dcr'} +{$R 'HttpSrv.dcr'} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS ON} +{$RANGECHECKS ON} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DESCRIPTION 'Internet Component Suite (ICS) for Delphi 6'} +{$IMPLICITBUILD ON} + +requires + vcl, + rtl, + designide; + +contains + WSockBuf in 'WSockBuf.pas', + WSocket in 'WSocket.pas', + FingCli in 'FingCli.pas', + FormPos in 'FormPos.pas', + FtpCli in 'FtpCli.pas', + FtpSrv in 'FtpSrv.pas', + FtpSrvC in 'FtpSrvC.pas', + HttpProt in 'HttpProt.pas', + Icmp in 'Icmp.pas', + MD5 in 'MD5.pas', + MimeDec in 'MimeDec.pas', + NntpCli in 'NntpCli.pas', + Ping in 'Ping.pas', + TnCnx in 'TnCnx.pas', + TnEmulVT in 'TnEmulVT.pas', + TnOptFrm in 'TnOptFrm.pas' {OptForm}, + TnScript in 'TnScript.pas', + EmulVT in 'EmulVT.pas', + SmtpProt in 'SmtpProt.pas', + MbxFile in 'MbxFile.pas', + Pop3Prot in 'Pop3Prot.pas', + Wait in 'Wait.pas', + DnsQuery in 'DnsQuery.pas', + WSocketS in 'WSocketS.pas', + HttpSrv in 'HttpSrv.pas', + FtpSrvT in 'FtpSrvT.pas', + WSocketE in 'WSocketE.pas'; + +end. diff --git a/ICS_zlog/Delphi/Vc32/IcsDel60.res b/ICS_zlog/Delphi/Vc32/IcsDel60.res new file mode 100644 index 0000000000000000000000000000000000000000..46e849aa5c249e5b446f5658b8dc5144b2238d86 GIT binary patch literal 1856 zcmb7DzfV(96#iv@1X1A6=cz);J*YY5Z#?zj6?mg!_KkvN&V2~Y0GneP+*QK7_ zPmE95hKGkjJ?xnG+Wx9w927EaAzyw+FOM}rBtZdefwOw zTiHFX?e*=J)os-5J^EvYlqeT>kB@71n|sM?THSi1QC0hZ*sYyLy>8oIXlH>fvuoFn zsth0wVo%uIRh1p$U>@03;+5S6*mh0Zm513O!nKPcwh%5>?IOeVsiX7v_u-zqt2t8T z_00&2_czCJKDWb8sp)r0ydmUb6PW%EjI!9U%R%mi{eNR(gTh_n$i5TGQ%c@4ztf~_ z&-oqaBQs8HAqEkxWRaFV%{T%6!F{aI>lXDg0iYlT;=hI zdXp;yx5;m~Hi@6Y9sah|FTxlayW(OaSW!`4;u>@GYMP;L6RWD$9HVT|FROA%wUQ%G zndZvq*CmLwvKs93BYgxX6h+7rdr5h3dSc!~gc!}z?>H_K@6D9rq|Q2?XJwm^8Z(%r zr_ds<(kDsXIwzA+Rpr>DOnY6;0{=M?;4QA7i}`}lQap_`C!gZ_9jg!;V?DPxiMx2f z-z29$&Z?sP8l3Jnzq86Si=Uk12E7bCqm=peW;CUGUU2J`8zNow&O>(kv@8VGCN8k_kxuLxP literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/IcsDel70.dof b/ICS_zlog/Delphi/Vc32/IcsDel70.dof new file mode 100644 index 00000000..bb1eb6a5 --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/IcsDel70.dof @@ -0,0 +1,152 @@ +[FileVersion] +Version=7.0 + +[Compiler] +A=8 +B=0 +C=1 +D=1 +E=0 +F=0 +G=1 +H=1 +I=1 +J=1 +K=0 +L=1 +M=0 +N=1 +O=0 +P=1 +Q=1 +R=1 +S=0 +T=0 +U=0 +V=1 +W=0 +X=1 +Y=1 +Z=1 +ShowHints=1 +ShowWarnings=1 +UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; +NamespacePrefix= +SymbolDeprecated=0 +SymbolLibrary=1 +SymbolPlatform=0 +UnitLibrary=1 +UnitPlatform=1 +UnitDeprecated=1 +HResultCompat=1 +HidingMember=1 +HiddenVirtual=1 +Garbage=1 +BoundsError=1 +ZeroNilCompat=1 +StringConstTruncated=1 +ForLoopVarVarPar=1 +TypedConstVarPar=1 +AsgToTypedConst=1 +CaseLabelRange=1 +ForVariable=1 +ConstructingAbstract=1 +ComparisonFalse=1 +ComparisonTrue=1 +ComparingSignedUnsigned=1 +CombiningSignedUnsigned=1 +UnsupportedConstruct=1 +FileOpen=1 +FileOpenUnitSrc=1 +BadGlobalSymbol=1 +DuplicateConstructorDestructor=1 +InvalidDirective=1 +PackageNoLink=1 +PackageThreadVar=1 +ImplicitImport=1 +HPPEMITIgnored=1 +NoRetVal=1 +UseBeforeDef=1 +ForLoopVarUndef=1 +UnitNameMismatch=1 +NoCFGFileFound=1 +MessageDirective=1 +ImplicitVariants=1 +UnicodeToLocale=1 +LocaleToUnicode=1 +ImagebaseMultiple=1 +SuspiciousTypecast=1 +PrivatePropAccessor=1 +UnsafeType=0 +UnsafeCode=0 +UnsafeCast=0 + +[Linker] +MapFile=0 +OutputObjs=0 +ConsoleApp=1 +DebugInfo=0 +RemoteSymbols=0 +MinStackSize=16384 +MaxStackSize=1048576 +ImageBase=4194304 +ExeDescription=Internet Component Suite (ICS) for Delphi 7 + +[Directories] +OutputDir= +UnitOutputDir= +PackageDLLOutputDir= +PackageDCPOutputDir= +SearchPath= +Packages= +Conditionals= +DebugSourceDirs= +UsePackages=0 + +[Parameters] +RunParams= +HostApplication= +Launcher= +UseLauncher=0 +DebugCWD= + +[Language] +ActiveLang= +ProjectLang= +RootDir= + +[Version Info] +IncludeVerInfo=1 +AutoIncBuild=1 +MajorVer=3 +MinorVer=0 +Release=0 +Build=96 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=2060 +CodePage=1252 + +[Version Info Keys] +CompanyName=OverByte - http://www.overbyte.be +FileDescription=Internet Component Suite +FileVersion=3.0.0.96 +InternalName=IcsDel70 +LegalCopyright=http://www.overbyte.be +LegalTrademarks=(c) 1996-2002 by François Piette +OriginalFilename=IcsDel70 +ProductName=ICS +ProductVersion=3.0.0.0 +Comments=email:francois.piette@overbyte.be + +[HistoryLists\hlConditionals] +Count=2 +Item0=NOFORMS +Item1=NOFORMSA + +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; diff --git a/ICS_zlog/Delphi/Vc32/IcsDel70.dpk b/ICS_zlog/Delphi/Vc32/IcsDel70.dpk new file mode 100644 index 00000000..c13069da --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/IcsDel70.dpk @@ -0,0 +1,81 @@ +package IcsDel70; + +{$R *.res} +{$R 'WSocket.dcr'} +{$R 'FingCli.dcr'} +{$R 'FtpCli.dcr'} +{$R 'FtpSrv.dcr'} +{$R 'HttpProt.dcr'} +{$R 'MimeDec.dcr'} +{$R 'NntpCli.dcr'} +{$R 'Ping.dcr'} +{$R 'Pop3Prot.dcr'} +{$R 'TnCnx.dcr'} +{$R 'TnEmulVT.dcr'} +{$R 'TnScript.dcr'} +{$R 'EmulVT.dcr'} +{$R 'SmtpProt.dcr'} +{$R 'MbxFile.dcr'} +{$R 'Wait.dcr'} +{$R 'DnsQuery.dcr'} +{$R 'WSocketS.dcr'} +{$R 'HttpSrv.dcr'} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS ON} +{$RANGECHECKS ON} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES OFF} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DESCRIPTION 'Internet Component Suite (ICS) for Delphi 7'} +{$IMPLICITBUILD ON} + +requires + vcl, + rtl, + designide; + +contains + WSockBuf in 'WSockBuf.pas', + WSocket in 'wsocket.pas', + FingCli in 'FingCli.pas', + FormPos in 'FormPos.pas', + FtpCli in 'FtpCli.pas', + FtpSrv in 'FtpSrv.pas', + FtpSrvC in 'FtpSrvC.pas', + HttpProt in 'HttpProt.pas', + Icmp in 'Icmp.pas', + MD5 in 'MD5.pas', + MimeDec in 'MimeDec.pas', + NntpCli in 'NntpCli.pas', + Ping in 'Ping.pas', + TnCnx in 'TnCnx.pas', + TnEmulVT in 'TnEmulVT.pas', + TnOptFrm in 'TnOptFrm.pas' {OptForm}, + TnScript in 'TnScript.pas', + EmulVT in 'EmulVT.pas', + SmtpProt in 'SmtpProt.pas', + MbxFile in 'MbxFile.pas', + Pop3Prot in 'Pop3Prot.pas', + Wait in 'Wait.pas', + DnsQuery in 'DnsQuery.pas', + WSocketS in 'WSocketS.pas', + HttpSrv in 'HttpSrv.pas', + FtpSrvT in 'FtpSrvT.pas', + WSocketE in 'WSocketE.pas'; + +end. diff --git a/ICS_zlog/Delphi/Vc32/IcsDel70.res b/ICS_zlog/Delphi/Vc32/IcsDel70.res new file mode 100644 index 0000000000000000000000000000000000000000..b561f81a5c4bae5e68bb2683dcdba943503d1c62 GIT binary patch literal 1860 zcmb7D&rcIk5dLbLv?j!IFi}se#seO#hy;ZTRggkb#fafxOt3&jwAQAqvYc8^Tf(77 zvgyHpgQhWUVhM>Y)v?c% z+U4z|>Q2XQn(cbk+Mz$DNQqKm`{<}@9dIvsb+cWo*DGot61%xouhlH;Bke4(skg1# zVTA$2LF@^OyNa?y9P~r0LcFrO0L!X6cIBbBh;Z$qh|fg}6|2B-9cnrGJNu~T?rIKI zc^xyN;{DmS?GFc0yVwZYMZOSnp#e;M0R~uX)a5Yu!oj~Wv0>phapb@;-^uDfC0i$E~!>> z+l#xeLntdDR!%S>RDE|4yiMP z+v;V2_jQ4JlGLrTI~i43j^~t)ud06FKf40F!sSyjpD7{ql?nD4r)igO>&oXOR literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/Icsbcb40.bpk b/ICS_zlog/Delphi/Vc32/Icsbcb40.bpk new file mode 100644 index 00000000..ce54f2fb --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/Icsbcb40.bpk @@ -0,0 +1,221 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE SECTION +# --------------------------------------------------------------------------- +# The following section of the project makefile is managed by the BCB IDE. +# It is recommended to use the IDE to change any of the values in this +# section. +# --------------------------------------------------------------------------- + +VERSION = BCB.04.04 +# --------------------------------------------------------------------------- +PROJECT = Icsbcb40.bpl +OBJFILES = WSocket.obj httpprot.obj ftpcli.obj wait.obj tnscript.obj fingcli.obj \ + nntpcli.obj ping.obj tncnx.obj tnemulvt.obj emulvt.obj FtpSrv.obj SmtpProt.obj \ + wsockbuf.obj Pop3Prot.obj MimeDec.obj DnsQuery.obj WSocketE.obj WSocketS.obj \ + HttpSrv.obj Icsbcb40.obj +RESFILES = Icsbcb40.res WSocket.dcr httpprot.dcr ftpcli.dcr wait.dcr tnscript.dcr \ + fingcli.dcr nntpcli.dcr ping.dcr tncnx.dcr tnemulvt.dcr emulvt.dcr FtpSrv.dcr \ + SmtpProt.dcr Pop3Prot.dcr MimeDec.dcr DnsQuery.dcr WSocketS.dcr HttpSrv.dcr +DEFFILE = +RESDEPEN = $(RESFILES) +LIBFILES = +IDLGENFILES = +IDLFILES = +LIBRARIES = vcljpg40.lib vcldbx40.lib vclmid40.lib vclx40.lib vcldb40.lib +SPARELIBS = vcl40.lib vcldb40.lib vclx40.lib vclmid40.lib vcldbx40.lib vcljpg40.lib +PACKAGES = vcl40.bpi bcbsmp40.bpi +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .; +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +SYSDEFINES = NO_STRICT;_RTLDLL;USEPACKAGES +USERDEFINES = +# --------------------------------------------------------------------------- +CFLAG1 = -I..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\include;$(BCB)\include\vcl -Od \ + -Hc -H=$(BCB)\lib\vcl40.csm -w -Ve -Tkh30000 -r- -a8 -k -y -v -vi- \ + -D$(SYSDEFINES);$(USERDEFINES) -c -b- -w-par -w-inl -Vx -tWM +CFLAG2 = +CFLAG3 = +IDLCFLAGS = -I..\..\internet -I.. -I..\..\..\delphi\vc32 -I$(BCB)\include \ + -I$(BCB)\include\vcl -src_suffixcpp +PFLAGS = -U$(BCB)\Projects\Lib;..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \ + -I..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\include;$(BCB)\include\vcl -$YD \ + -$W -$O- -v -M -JPHNE +RFLAGS = -i..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\include;$(BCB)\include\vcl +AFLAGS = /i..\..\internet /i..\..\DELPHI /i..\..\..\delphi\vc32 /i$(BCB)\include \ + /i$(BCB)\include\vcl /mx /w2 /zd /d_RTLDLL /dUSEPACKAGES +LFLAGS = -L$(BCB)\Projects\Lib;..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \ + -D"ICS components by F. Piette" -aa -Tpp -x -Gn -Gl -Gi -v +IFLAGS = +# --------------------------------------------------------------------------- +ALLOBJ = c0pkg32.obj Memmgr.Lib $(PACKAGES) sysinit.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mti.lib +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=1 +AutoIncBuild=1 +MajorVer=2 +MinorVer=0 +Release=0 +Build=6 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=2060 +CodePage=1252 + +[Version Info Keys] +CompanyName=OverByte (F. Piette) +FileDescription=ICS Components for BCB4 +FileVersion=2.0.0.6 +InternalName=IcsBcb40 +LegalCopyright=(c) 97'-'99 by F. Piette +LegalTrademarks= +OriginalFilename= +ProductName=ICS +ProductVersion=2.0.0.0 +Comments=http://www.rtfm.be/fpiette/indexuk.htm + +[Excluded Packages] +$(BCB)\Bin\dcl31w40.bpl=Delphi 1.0 Compatibility Components +$(BCB)\Bin\bcbsmp40.bpl=Borland C++ Sample Components +$(BCB)\Bin\dclint40.bpl=Borland Resource DLL Wizard +C:\WINDOWS\SYSTEM\\ibsmp40.bpl=Borland C++ InterBase Alerter Component +$(BCB)\Bin\rcexpert.bpl=Borland Resource Expert +$(BCB)\Bin\dcldb40.bpl=Borland Database Components +$(BCB)\Bin\dclqrt40.bpl=QuickReport Components +$(BCB)\Bin\mfcowlwizard.bpl=MFC/OWL Wizard +$(BCB)\Bin\dcltee40.bpl=Borland TeeChart Components +$(BCB)\Bin\dcldss40.bpl=Borland Decision Cube Components + +[HistoryLists\hlIncludePath] +Count=2 +Item0=..\..\internet;..\..\DELPHI;..\..\..\delphi\vc32;$(BCB)\include;$(BCB)\include\vcl +Item1=..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\include;$(BCB)\include\vcl + +[HistoryLists\hlLibraryPath] +Count=3 +Item0=$(BCB)\Projects\Lib;..\..\internet;..\..\DELPHI;..\..\..\delphi\vc32;$(BCB)\lib\obj;$(BCB)\lib +Item1=..\vc32;..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\lib\obj;$(BCB)\lib +Item2=..\..\internet;..;..\..\..\delphi\vc32;$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[HistoryLists\hlConditionals] +Count=1 +Item0=_RTLDLL;USEPACKAGES + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +HostApplication= +RemoteHost= +RemotePath= +RemoteDebug=0 + +[Compiler] +InMemoryExe=0 +ShowInfoMsgs=0 + +[CORBA] +AddServerUnit=1 +AddClientUnit=1 +PrecompiledHeaders=1 + +!endif + +# --------------------------------------------------------------------------- +# MAKE SECTION +# --------------------------------------------------------------------------- +# This section of the project file is not used by the BCB IDE. It is for +# the benefit of building from the command-line using the MAKE utility. +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = ilink32 +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif + +!if !$d(IDL2CPP) +IDL2CPP = idl2cpp +!endif +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +$(PROJECT): $(IDLGENFILES) $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- diff --git a/ICS_zlog/Delphi/Vc32/Icsbcb40.cpp b/ICS_zlog/Delphi/Vc32/Icsbcb40.cpp new file mode 100644 index 00000000..4cc8fdcb --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/Icsbcb40.cpp @@ -0,0 +1,53 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +USERES("Icsbcb40.res"); +USEUNIT("WSocket.pas"); +USERES("WSocket.dcr"); +USEUNIT("httpprot.pas"); +USERES("httpprot.dcr"); +USEUNIT("ftpcli.pas"); +USERES("ftpcli.dcr"); +USEUNIT("wait.pas"); +USERES("wait.dcr"); +USEUNIT("tnscript.pas"); +USERES("tnscript.dcr"); +USEUNIT("fingcli.pas"); +USERES("fingcli.dcr"); +USEUNIT("nntpcli.pas"); +USERES("nntpcli.dcr"); +USEUNIT("ping.pas"); +USERES("ping.dcr"); +USEUNIT("tncnx.pas"); +USERES("tncnx.dcr"); +USEUNIT("tnemulvt.pas"); +USERES("tnemulvt.dcr"); +USEUNIT("emulvt.pas"); +USERES("emulvt.dcr"); +USEUNIT("FtpSrv.pas"); +USERES("FtpSrv.dcr"); +USEUNIT("SmtpProt.pas"); +USERES("SmtpProt.dcr"); +USEUNIT("wsockbuf.pas"); +USEUNIT("Pop3Prot.pas"); +USERES("Pop3Prot.dcr"); +USEUNIT("MimeDec.pas"); +USERES("MimeDec.dcr"); +USEUNIT("DnsQuery.pas"); +USERES("DnsQuery.dcr"); +USEPACKAGE("vcl40.bpi"); +USEPACKAGE("bcbsmp40.bpi"); +USEUNIT("WSocketS.pas"); +USERES("WSocketS.dcr"); +USEUNIT("HttpSrv.pas"); +USERES("HttpSrv.dcr"); +//--------------------------------------------------------------------------- +#pragma package(smart_init) +//--------------------------------------------------------------------------- +// Package source. +//--------------------------------------------------------------------------- +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} +//--------------------------------------------------------------------------- diff --git a/ICS_zlog/Delphi/Vc32/Icsbcb40.res b/ICS_zlog/Delphi/Vc32/Icsbcb40.res new file mode 100644 index 0000000000000000000000000000000000000000..8af8373bba00bc9703898cde650000fb065368cd GIT binary patch literal 1764 zcma)5&rcIU6#hz^hzU^+n&`cA-bksX5@^|!(JjHGJ#g3? ziGPgtV$wgwg9mSN<3e1&H@mYxghZ!(``*m^=6gS81^_Hd7)C-fH-1hSf03Ai_DxSu zl?-TxhDCWoDIi|vp3BD&;2*P5tFZ94mwl7j2S1yXHb9h>|M%ow?bRSx6-fQ z!Us&m-HPs& zag%&iVmk29ApVe5H#lqQ05yE1)kB5rik5{Lvd>blF-D7PvU*=*>$pWO6Wiwc0h&4| zkEk8S=xUtwcAX3+s;svtig-)s+oP_~U(q?1*@={QgV-LCDc?NvDaW$N2=ll~ywona z^{5-{Mq1S>vpOJm6I#V=CNk!XdCaz1XkW;r52X(2>0-ivc#W7 zmP39oc13s}kTuKumW&O&W1J3k54+67j0jtcW6DWN-lm^2Gp8cC$n9GrcAsn?n3>8{ z2v#pW2J4gF<#B&^Fxx-r#x^T6cS0gYCj;FD#jZTY9Dlz4%`yYU9Ub<6i`Y5ZUgl=Z t(eCPc`^<8eDCuQKmu&0rhVFx@GQF|DU47f5j&<3mJtDLBXln9D=?`~*f#U!G literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/Icsdel30.res b/ICS_zlog/Delphi/Vc32/Icsdel30.res new file mode 100644 index 0000000000000000000000000000000000000000..36f26e234a8ac66a47e95cec6d496cf2f1442471 GIT binary patch literal 32 UcmZQzU|>)H;{X347|28c09i@|9RL6T literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/MD5.dcu b/ICS_zlog/Delphi/Vc32/MD5.dcu new file mode 100644 index 0000000000000000000000000000000000000000..a40fa9e86c68a5b940555d7ac90f598f50d8a607 GIT binary patch literal 8371 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 eXqFNXN + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: +Oct 26, 1997 Changed MD5Final form function to procedure to be compatible + with C++Builder. +Jul 09, 1998 V1.01 Adapted for Delphi 4 +Aug 06, 1998 V1.02 Added R- Q- directive +Jun 05, 1999 V1.03 Wolfgang Klein found a bug in MD5Update. + +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit MD5; + +interface + +uses + SysUtils; + +const + MD5Version = 102; + CopyRight : String = ' MD5 Message-Digest (c) 97-98 F. Piette V1.02 '; + +{$Q-} +{$R-} + +type + TMD5Context = record + State: array[0..3] of LongInt; + Count: array[0..1] of LongInt; + case Integer of + 0: (BufChar: array[0..63] of Byte); + 1: (BufLong: array[0..15] of LongInt); + end; + TMD5Digest = array[0..15] of Char; + +procedure MD5Init(var MD5Context: TMD5Context); +procedure MD5Update(var MD5Context: TMD5Context; + const Data; + Len: Integer); +procedure MD5Transform(var Buf: array of LongInt; + const Data: array of LongInt); +procedure MD5UpdateBuffer(var MD5Context: TMD5Context; + Buffer: Pointer; + BufSize: Integer); +procedure MD5Final(var Digest: TMD5Digest; var MD5Context: TMD5Context); + +function GetMD5(Buffer: Pointer; BufSize: Integer): string; +function StrMD5(Buffer : String): string; + +implementation + +const + MaxBufSize = 16384; + +type + PMD5Buffer = ^TMD5Buffer; + TMD5Buffer = array[0..(MaxBufSize - 1)] of Char; + + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ MD5 initialization. Begins an MD5 operation, writing a new context. } +procedure MD5Init(var MD5Context: TMD5Context); +begin + FillChar(MD5Context, SizeOf(TMD5Context), #0); + with MD5Context do begin + { Load magic initialization constants. } + State[0] := LongInt($67452301); + State[1] := LongInt($EFCDAB89); + State[2] := LongInt($98BADCFE); + State[3] := LongInt($10325476); + end +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ MD5 block update operation. Continues an MD5 message-digest operation, } +{ processing another message block, and updating the context. } +procedure MD5Update( + var MD5Context: TMD5Context; { Context } + const Data; { Input block } + Len: Integer); { Length of input block } +type + TByteArray = array[0..0] of Byte; +var + Index: Word; + T: LongInt; +begin + with MD5Context do begin + T := Count[0]; + Inc(Count[0], LongInt(Len) shl 3); + if Count[0] < T then + Inc(Count[1]); + Inc(Count[1], Len shr 29); + T := (T shr 3) and $3F; + Index := 0; + if T <> 0 then begin + Index := T; + T := 64 - T; + if Len < T then begin + Move(Data, BufChar[Index], Len); + Exit; + end; + Move(Data, BufChar[Index], T); + MD5Transform(State, BufLong); + Dec(Len, T); + Index := T; { Wolfgang Klein, 05/06/99 } + end; + while Len >= 64 do begin + Move(TByteArray(Data)[Index], BufChar, 64); + MD5Transform(State, BufLong); + Inc(Index, 64); + Dec(Len, 64); + end; + Move(TByteArray(Data)[Index], BufChar, Len); + end +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ MD5 finalization. Ends an MD5 message-digest operation, writing the message } +{ digest and zeroizing the context. } +procedure MD5Final(var Digest: TMD5Digest; var MD5Context: TMD5Context); +var + Cnt : Word; + P : Byte; +begin + with MD5Context do begin + Cnt := (Count[0] shr 3) and $3F; + P := Cnt; + BufChar[P] := $80; + Inc(P); + Cnt := 64 - 1 - Cnt; + if Cnt < 8 then begin + FillChar(BufChar[P], Cnt, #0); + MD5Transform(State, BufLong); + FillChar(BufChar, 56, #0); + end + else + FillChar(BufChar[P], Cnt - 8, #0); + BufLong[14] := Count[0]; + BufLong[15] := Count[1]; + MD5Transform(State, BufLong); + Move(State, Digest, 16) + end; + FillChar(MD5Context, SizeOf(TMD5Context), #0) +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +{ MD5 basic transformation. Transforms state based on block. } +procedure MD5Transform( + var Buf: array of LongInt; + const Data: array of LongInt); +var + A, B, C, D: LongInt; + + procedure Round1(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte); + begin + Inc(W, (Z xor (X and (Y xor Z))) + Data); + W := (W shl S) or (W shr (32 - S)); + Inc(W, X) + end; + + procedure Round2(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte); + begin + Inc(W, (Y xor (Z and (X xor Y))) + Data); + W := (W shl S) or (W shr (32 - S)); + Inc(W, X) + end; + + procedure Round3(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte); + begin + Inc(W, (X xor Y xor Z) + Data); + W := (W shl S) or (W shr (32 - S)); + Inc(W, X) + end; + + procedure Round4(var W: LongInt; X, Y, Z, Data: LongInt; S: Byte); + begin + Inc(W, (Y xor (X or not Z)) + Data); + W := (W shl S) or (W shr (32 - S)); + Inc(W, X) + end; +begin + A := Buf[0]; + B := Buf[1]; + C := Buf[2]; + D := Buf[3]; + + Round1(A, B, C, D, Data[ 0] + LongInt($d76aa478), 7); + Round1(D, A, B, C, Data[ 1] + LongInt($e8c7b756), 12); + Round1(C, D, A, B, Data[ 2] + LongInt($242070db), 17); + Round1(B, C, D, A, Data[ 3] + LongInt($c1bdceee), 22); + Round1(A, B, C, D, Data[ 4] + LongInt($f57c0faf), 7); + Round1(D, A, B, C, Data[ 5] + LongInt($4787c62a), 12); + Round1(C, D, A, B, Data[ 6] + LongInt($a8304613), 17); + Round1(B, C, D, A, Data[ 7] + LongInt($fd469501), 22); + Round1(A, B, C, D, Data[ 8] + LongInt($698098d8), 7); + Round1(D, A, B, C, Data[ 9] + LongInt($8b44f7af), 12); + Round1(C, D, A, B, Data[10] + LongInt($ffff5bb1), 17); + Round1(B, C, D, A, Data[11] + LongInt($895cd7be), 22); + Round1(A, B, C, D, Data[12] + LongInt($6b901122), 7); + Round1(D, A, B, C, Data[13] + LongInt($fd987193), 12); + Round1(C, D, A, B, Data[14] + LongInt($a679438e), 17); + Round1(B, C, D, A, Data[15] + LongInt($49b40821), 22); + + Round2(A, B, C, D, Data[ 1] + LongInt($f61e2562), 5); + Round2(D, A, B, C, Data[ 6] + LongInt($c040b340), 9); + Round2(C, D, A, B, Data[11] + LongInt($265e5a51), 14); + Round2(B, C, D, A, Data[ 0] + LongInt($e9b6c7aa), 20); + Round2(A, B, C, D, Data[ 5] + LongInt($d62f105d), 5); + Round2(D, A, B, C, Data[10] + LongInt($02441453), 9); + Round2(C, D, A, B, Data[15] + LongInt($d8a1e681), 14); + Round2(B, C, D, A, Data[ 4] + LongInt($e7d3fbc8), 20); + Round2(A, B, C, D, Data[ 9] + LongInt($21e1cde6), 5); + Round2(D, A, B, C, Data[14] + LongInt($c33707d6), 9); + Round2(C, D, A, B, Data[ 3] + LongInt($f4d50d87), 14); + Round2(B, C, D, A, Data[ 8] + LongInt($455a14ed), 20); + Round2(A, B, C, D, Data[13] + LongInt($a9e3e905), 5); + Round2(D, A, B, C, Data[ 2] + LongInt($fcefa3f8), 9); + Round2(C, D, A, B, Data[ 7] + LongInt($676f02d9), 14); + Round2(B, C, D, A, Data[12] + LongInt($8d2a4c8a), 20); + + Round3(A, B, C, D, Data[ 5] + LongInt($fffa3942), 4); + Round3(D, A, B, C, Data[ 8] + LongInt($8771f681), 11); + Round3(C, D, A, B, Data[11] + LongInt($6d9d6122), 16); + Round3(B, C, D, A, Data[14] + LongInt($fde5380c), 23); + Round3(A, B, C, D, Data[ 1] + LongInt($a4beea44), 4); + Round3(D, A, B, C, Data[ 4] + LongInt($4bdecfa9), 11); + Round3(C, D, A, B, Data[ 7] + LongInt($f6bb4b60), 16); + Round3(B, C, D, A, Data[10] + LongInt($bebfbc70), 23); + Round3(A, B, C, D, Data[13] + LongInt($289b7ec6), 4); + Round3(D, A, B, C, Data[ 0] + LongInt($eaa127fa), 11); + Round3(C, D, A, B, Data[ 3] + LongInt($d4ef3085), 16); + Round3(B, C, D, A, Data[ 6] + LongInt($04881d05), 23); + Round3(A, B, C, D, Data[ 9] + LongInt($d9d4d039), 4); + Round3(D, A, B, C, Data[12] + LongInt($e6db99e5), 11); + Round3(C, D, A, B, Data[15] + LongInt($1fa27cf8), 16); + Round3(B, C, D, A, Data[ 2] + LongInt($c4ac5665), 23); + + Round4(A, B, C, D, Data[ 0] + LongInt($f4292244), 6); + Round4(D, A, B, C, Data[ 7] + LongInt($432aff97), 10); + Round4(C, D, A, B, Data[14] + LongInt($ab9423a7), 15); + Round4(B, C, D, A, Data[ 5] + LongInt($fc93a039), 21); + Round4(A, B, C, D, Data[12] + LongInt($655b59c3), 6); + Round4(D, A, B, C, Data[ 3] + LongInt($8f0ccc92), 10); + Round4(C, D, A, B, Data[10] + LongInt($ffeff47d), 15); + Round4(B, C, D, A, Data[ 1] + LongInt($85845dd1), 21); + Round4(A, B, C, D, Data[ 8] + LongInt($6fa87e4f), 6); + Round4(D, A, B, C, Data[15] + LongInt($fe2ce6e0), 10); + Round4(C, D, A, B, Data[ 6] + LongInt($a3014314), 15); + Round4(B, C, D, A, Data[13] + LongInt($4e0811a1), 21); + Round4(A, B, C, D, Data[ 4] + LongInt($f7537e82), 6); + Round4(D, A, B, C, Data[11] + LongInt($bd3af235), 10); + Round4(C, D, A, B, Data[ 2] + LongInt($2ad7d2bb), 15); + Round4(B, C, D, A, Data[ 9] + LongInt($eb86d391), 21); + + Inc(Buf[0], A); + Inc(Buf[1], B); + Inc(Buf[2], C); + Inc(Buf[3], D); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure MD5UpdateBuffer( + var MD5Context: TMD5Context; + Buffer: Pointer; + BufSize: Integer); +var + BufTmp : PMD5Buffer; + BufPtr : PChar; + Bytes : Word; +begin + New(BufTmp); + BufPtr := Buffer; + try + repeat + if BufSize > MaxBufSize then + Bytes := MaxBufSize + else + Bytes := BufSize; + Move(BufPtr^, BufTmp^, Bytes); + Inc(BufPtr, Bytes); + Dec(BufSize, Bytes); + if Bytes > 0 then + MD5Update(MD5Context, BufTmp^, Bytes); + until Bytes < MaxBufSize; + finally + Dispose(BufTmp); + end; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function GetMD5(Buffer: Pointer; BufSize: Integer): string; +var + I : Integer; + MD5Digest : TMD5Digest; + MD5Context : TMD5Context; +begin + for I := 0 to 15 do + Byte(MD5Digest[I]) := I + 1; + MD5Init(MD5Context); + MD5UpdateBuffer(MD5Context, Buffer, BufSize); + MD5Final(MD5Digest, MD5Context); + Result := ''; + for I := 0 to 15 do + Result := Result + IntToHex(Byte(MD5Digest[I]), 2); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function StrMD5(Buffer : String): string; +begin + Result := GetMD5(@Buffer[1], Length(Buffer)); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Vc32/MbxFile.dcr b/ICS_zlog/Delphi/Vc32/MbxFile.dcr new file mode 100644 index 0000000000000000000000000000000000000000..f4f484fe39036a57b9c6b3eab3a708f6ea0f3bd2 GIT binary patch literal 476 zcmaKnF%H5o3`JiNQWzLIGIrzuTmS?T127;4j*-o4M~>B-h3}-505w>(|C94;Cjgx? zrINz0cr~z7C#3}st{ixBX3vcy7f#$qciXO4(~n!hX3U0VZg-k9A3f-!?~AAk8HPdX z2YxY^R7ADhHDT2V79)Y|a5f9sTVsNI$fl}??D@0RLNqN^)jDU5auq0kIBJ=<^)z$# PI(a_XZPU!^d*=_{0WF3k literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/MbxFile.dcu b/ICS_zlog/Delphi/Vc32/MbxFile.dcu new file mode 100644 index 0000000000000000000000000000000000000000..0173bacf670b0f89f6c54b4403adba8a5a561590 GIT binary patch literal 8578 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 literal 0 HcmV?d00001 diff --git a/ICS_zlog/Delphi/Vc32/MbxFile.pas b/ICS_zlog/Delphi/Vc32/MbxFile.pas new file mode 100644 index 00000000..8ff14f44 --- /dev/null +++ b/ICS_zlog/Delphi/Vc32/MbxFile.pas @@ -0,0 +1,355 @@ +{*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +Author: François PIETTE +Description: TMbxFile handle the MBX file format (read only) + The MBX file format is used by Microsoft Internet Mail. +Warning: This component is based on my interpretation of the MBX file + format. I did'nt find any info about it. So there may be errors ! + Currently, no provision is made for deleted messages. + If you find a problem, please EMail me a description and attach + the MBX file in error. +EMail: http://users.swing.be/francois.piette francois.piette@swing.be + http://www.rtfm.be/fpiette francois.piette@rtfm.be + francois.piette@pophost.eunet.be +Creation: November 16, 1997 +Version: 1.00 +Support: Use the mailing list twsocket@rtfm.be See website for details. +Legal issues: Copyright (C) 1997, 1998 by François PIETTE + Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56 + + + This software is provided 'as-is', without any express or + implied warranty. In no event will the author be held liable + for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it + and redistribute it freely, subject to the following + restrictions: + + 1. The origin of this software must not be misrepresented, + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + 4. You must register this software by sending a picture postcard + to the author. Use a nice stamp and mention your name, street + address, EMail address and any comment you like to say. + +Updates: + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +unit MbxFile; + +interface + +uses + SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, + Forms, Dialogs, ExtCtrls; + +const + MbxFileVersion = 100; + MSG_SIGNATURE = $7F007F00; + +type + TMbxHeader = packed record + Signature : array [0..3] of char; + Reserved1 : Word; + Reserved2 : Word; + MsgCount : LongInt; + Reserved3 : LongInt; { A MsgCount copy ? } + EndPointer : LongInt; + Reserved4 : array [0..15] of LongInt; + end; + + TMsgHeader = packed record + Signature : LongInt; { $7F007F00 } + MsgNum : LongInt; + MsgSize : LongInt; + Reserved1 : LongInt; + end; + + TCustomMbxHandler = class(TComponent) + protected + FFileHdr : TMbxHeader; + FFileName : String; + FFileStream : TFileStream; + FMsgHeader : TMsgHeader; + FMsgStream : TMemoryStream; + FMsgStreamSize : Integer; + FCurPos : LongInt; + procedure InternalPrior; + procedure ReadNextMessage; + procedure SetActive(newValue : Boolean); + function GetActive : Boolean; + function GetMsgCount : Integer; + function GetMsgNum : Integer; + function GetEof : Boolean; + function GetBof : Boolean; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure Open; + procedure Close; + procedure First; + procedure Next; + procedure Prior; + procedure Last; + property FileName : String read FFileName write FFileName; + property Active : Boolean read GetActive write SetActive; + property MsgCount : Integer read GetMsgCount; + property MsgNum : Integer read GetMsgNum; + property MsgStream : TMemoryStream read FMsgStream; + property Eof : Boolean read GetEof; + property Bof : Boolean read GetBof; + end; + + TMbxHandler = class(TCustomMbxHandler) + published + property FileName : String read FFileName write FFileName; + property Active : Boolean read GetActive write SetActive; + end; + +procedure Register; + +implementation + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure Register; +begin + RegisterComponents('FPiette', [TMbxHandler]); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +constructor TCustomMbxHandler.Create(AOwner : TComponent); +begin + Inherited Create(AOwner); + FMsgStreamSize := 4096; + FMsgStream := TMemoryStream.Create; + FMsgStream.SetSize(FMsgStreamSize); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +destructor TCustomMbxHandler.Destroy; +begin + Close; + FMsgStream.Free; + FMsgStreamSize := 0; + Inherited Destroy; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomMbxHandler.Open; +begin + Close; + FFileStream := TFileStream.Create(FFileName, fmOpenRead + fmShareDenyNone); + FFileStream.Read(FFileHdr, SizeOf(FFileHdr)); + if FFileHdr.Signature <> 'JMF6' then begin + Close; + raise Exception.Create('Not an EMail file'); + end; + + if MsgCount <= 0 then + Exit; + ReadNextMessage; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomMbxHandler.Close; +begin + if Assigned(FFileStream) then begin + FFileStream.Free; + FFileStream := nil; + end;; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomMbxHandler.First; +begin + if not Assigned(FFileStream) then + raise Exception.Create('Message file not opened'); + if MsgCount <= 0 then + Exit; + FFileStream.Position := SizeOf(TMbxHeader); + ReadNextMessage; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomMbxHandler.Last; +begin + if not Assigned(FFileStream) then + raise Exception.Create('Message file not opened'); + if MsgCount <= 0 then + Exit; + FCurPos := FFileStream.Seek(0, soFromEnd); + InternalPrior; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomMbxHandler.Next; +begin + if not Assigned(FFileStream) then + raise Exception.Create('Message file not opened'); + + if Eof then + raise Exception.Create('No more message'); + + ReadNextMessage; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomMbxHandler.Prior; +begin + if not Assigned(FFileStream) then + raise Exception.Create('Message file not opened'); + + if Bof then + raise Exception.Create('No more message'); + InternalPrior; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomMbxHandler.ReadNextMessage; +begin + FCurPos := FFileStream.Position; + FFileStream.Read(FMsgHeader, SizeOf(FMsgHeader)); + if FMsgHeader.Signature <> MSG_SIGNATURE then begin + Close; + raise Exception.Create('Invalid signature in message header'); + end; + if FMsgStreamSize <= FMsgHeader.MsgSize then begin + FMsgStreamSize := (((FMsgHeader.MsgSize + 1) div 4096) + 1) * 4096; + FMsgStream.SetSize(FMsgStreamSize); + end; + FMsgStream.Seek(0, soFromBeginning); + FFileStream.Read(FMsgStream.Memory^, FMsgHeader.MsgSize - 16); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomMbxHandler.SetActive(newValue : Boolean); +begin + if newValue = Assigned(FFileStream) then + Exit; + if newValue then + Open + else + Close; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomMbxHandler.GetActive : Boolean; +begin + Result := Assigned(FFileStream); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomMbxHandler.GetMsgCount : Integer; +begin + if not Assigned(FFileStream) then + raise Exception.Create('Message file not opened'); + Result := FFileHdr.MsgCount; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomMbxHandler.GetMsgNum : Integer; +begin + if not Assigned(FFileStream) then + raise Exception.Create('Message file not opened'); + Result := FMsgHeader.MsgNum; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomMbxHandler.GetEof : Boolean; +begin + Result := (not Assigned(FFileStream)) or + (MsgCount <= 0) or (MsgNum >= MsgCount); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +function TCustomMbxHandler.GetBof : Boolean; +begin + Result := (not Assigned(FFileStream)) or + (MsgCount <= 0) or (MsgNum <= 1); +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} +procedure TCustomMbxHandler.InternalPrior; +var + NewPos : LongInt; + Buf : PChar; + p : PChar; + More : Boolean; + Sign : LongInt; + Cnt : Integer; +begin + Buf := FMsgStream.Memory; + + Cnt := 4096; + NewPos := FCurPos - Cnt; + More := TRUE; + while More do begin + if NewPos < SizeOf(TMbxHeader) then begin + Cnt := Cnt - SizeOf(TMbxHeader) + NewPos; + NewPos := SizeOf(TMbxHeader); + end; + FFileStream.Position := NewPos; + FFileStream.Read(Buf^, Cnt); + p := Buf + Cnt - 1; + while (p > Buf) do begin + while (p >= Buf) and (p^ <> #$7F) do + Dec(p); + if p^ = #$7F then begin + FFileStream.Position := NewPos + p - Buf - 3; + FFileStream.Read(Sign, SizeOf(Sign)); + if Sign = MSG_SIGNATURE then begin + NewPos := NewPos + p - Buf - 3; + More := FALSE; + Break; + end; + end; + Dec(p); + end; + + if not More then + Break; + + if NewPos <= SizeOf(TMbxHeader) then + break; + + Cnt := 4096; + NewPos := NewPos - Cnt; + end; + FFileStream.Position := NewPos; + ReadNextMessage; +end; + + +{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} + +end. + diff --git a/ICS_zlog/Delphi/Vc32/NntpCli.dcu b/ICS_zlog/Delphi/Vc32/NntpCli.dcu new file mode 100644 index 0000000000000000000000000000000000000000..486d3fc33cdcfa752358742424555aa0a7cd3bc9 GIT binary patch literal 32946 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