IdDsnPropEdBindingVCL.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. Rev 1.9 10/26/2004 8:45:26 PM JPMugaas
  18. Should compile.
  19. Rev 1.8 10/26/2004 8:42:58 PM JPMugaas
  20. Should be more portable with new references to TIdStrings and TIdStringList.
  21. Rev 1.7 5/19/2004 10:44:28 PM DSiders
  22. Corrected spelling for TIdIPAddress.MakeAddressObject method.
  23. Rev 1.6 2/3/2004 11:34:26 AM JPMugaas
  24. Should compile.
  25. Rev 1.5.1.0 2/3/2004 11:32:26 AM JPMugaas
  26. Should compile.
  27. Rev 1.5 2/1/2004 2:44:20 AM JPMugaas
  28. Bindings editor should be fully functional including IPv6 support.
  29. Rev 1.4 2/1/2004 1:03:34 AM JPMugaas
  30. This now work properly in both Win32 and DotNET. The behavior had to change
  31. in DotNET because of some missing functionality and because implementing that
  32. functionality creates more problems than it would solve.
  33. Rev 1.3 2003.12.31 10:42:22 PM czhower
  34. Warning removed
  35. Rev 1.2 10/15/2003 10:12:32 PM DSiders
  36. Added localization comments.
  37. Rev 1.1 2003.10.11 5:47:46 PM czhower
  38. -VCL fixes for servers
  39. -Chain suport for servers (Super core)
  40. -Scheduler upgrades
  41. -Full yarn support
  42. Rev 1.0 11/13/2002 08:43:58 AM JPMugaas
  43. }
  44. unit IdDsnPropEdBindingVCL;
  45. interface
  46. {$I IdCompilerDefines.inc}
  47. uses
  48. Classes,
  49. {$IFDEF WIDGET_KYLIX}
  50. QActnList, QStdCtrls, QForms, QExtCtrls, QControls, QComCtrls, QGraphics, Qt,
  51. {$ENDIF}
  52. {$IFDEF WIDGET_VCL_LIKE}
  53. ActnList, StdCtrls, Buttons, ExtCtrls, Graphics, Controls, ComCtrls, Forms, Dialogs,
  54. {$ENDIF}
  55. {$IFDEF HAS_UNIT_Types}
  56. Types,
  57. {$ENDIF}
  58. {$IFDEF WINDOWS}
  59. Windows,
  60. {$ENDIF}
  61. {$IFDEF LCL}
  62. LResources,
  63. {$ENDIF}
  64. IdSocketHandle;
  65. {
  66. Design Note: It turns out that in DotNET, there are no services file functions and
  67. IdPorts does not work as expected in DotNET. It is probably possible to read the
  68. services file ourselves but that creates some portability problems as the placement
  69. is different in every operating system.
  70. e.g.
  71. Linux and Unix-like systems - /etc
  72. Windows 95, 98, and ME - c:\windows
  73. Windows NT systems - c:\winnt\system32\drivers\etc
  74. Thus, it will undercut whatever benefit we could get with DotNET.
  75. About the best I could think of is to use an edit control because
  76. we can't offer anything from the services file in DotNET.
  77. TODO: Maybe there might be a way to find the location in a more elegant
  78. manner than what I described.
  79. }
  80. type
  81. TIdDsnPropEdBindingVCL = class(TForm)
  82. {$IFDEF USE_TBitBtn}
  83. btnOk: TBitBtn;
  84. btnCancel: TBitBtn;
  85. {$ELSE}
  86. btnOk: TButton;
  87. btnCancel: TButton;
  88. {$ENDIF}
  89. lblBindings: TLabel;
  90. edtPort: TComboBox;
  91. rdoBindingType: TRadioGroup;
  92. lblIPAddress: TLabel;
  93. lblPort: TLabel;
  94. btnNew: TButton;
  95. btnDelete: TButton;
  96. ActionList1: TActionList;
  97. btnBindingsNew: TAction;
  98. btnBindingsDelete: TAction;
  99. edtIPAddress: TComboBox;
  100. lbBindings: TListBox;
  101. procedure btnBindingsNewExecute(Sender: TObject);
  102. procedure btnBindingsDeleteExecute(Sender: TObject);
  103. procedure btnBindingsDeleteUpdate(Sender: TObject);
  104. procedure edtPortKeyPress(Sender: TObject; var Key: Char);
  105. procedure edtIPAddressChange(Sender: TObject);
  106. procedure edtPortChange(Sender: TObject);
  107. procedure rdoBindingTypeClick(Sender: TObject);
  108. procedure lbBindingsClick(Sender: TObject);
  109. private
  110. procedure SetHandles(const Value: TIdSocketHandles);
  111. procedure SetIPv4Addresses(const Value: TStrings);
  112. procedure SetIPv6Addresses(const Value: TStrings);
  113. procedure UpdateBindingList;
  114. protected
  115. FInUpdateRoutine : Boolean;
  116. FHandles : TIdSocketHandles;
  117. FDefaultPort : Integer;
  118. FIPv4Addresses : TStrings;
  119. FIPv6Addresses : TStrings;
  120. fCreatedStack : Boolean;
  121. FCurrentHandle : TIdSocketHandle;
  122. procedure UpdateEditControls;
  123. function PortDescription(const PortNumber: integer): string;
  124. public
  125. Constructor Create(AOwner : TComponent); overload; override;
  126. constructor Create; reintroduce; overload;
  127. Destructor Destroy; override;
  128. function Execute : Boolean;
  129. function GetList: string;
  130. procedure SetList(const AList: string);
  131. property Handles : TIdSocketHandles read FHandles write SetHandles;
  132. property DefaultPort : Integer read FDefaultPort write FDefaultPort;
  133. property IPv4Addresses : TStrings read FIPv4Addresses write SetIPv4Addresses;
  134. property IPv6Addresses : TStrings read FIPv6Addresses write SetIPv6Addresses;
  135. end;
  136. var
  137. IdPropEdBindingEntry: TIdDsnPropEdBindingVCL;
  138. procedure FillHandleList(const AList: string; ADest: TIdSocketHandles);
  139. function GetListValues(const ASocketHandles : TIdSocketHandles) : String;
  140. implementation
  141. uses
  142. IdGlobal,
  143. IdIPAddress,
  144. IdDsnCoreResourceStrings,
  145. IdStack,
  146. IdStackBSDBase,
  147. SysUtils;
  148. const
  149. IPv6Wildcard1 = '::'; {do not localize}
  150. IPv6Wildcard2 = '0:0:0:0:0:0:0:0'; {do not localize}
  151. IPv6Loopback = '::1'; {do not localize}
  152. IPv4Wildcard = '0.0.0.0'; {do not localize}
  153. IPv4Loopback = '127.0.0.1'; {do not localize}
  154. function IsValidIP(const AAddr : String): Boolean;
  155. var
  156. LIP : TIdIPAddress;
  157. begin
  158. LIP := TIdIPAddress.MakeAddressObject(AAddr);
  159. Result := Assigned(LIP);
  160. if Result then begin
  161. FreeAndNil(LIP);
  162. end;
  163. end;
  164. procedure FillHandleList(const AList: string; ADest: TIdSocketHandles);
  165. var
  166. LItems: TStringList;
  167. i: integer;
  168. LIPVersion: TIdIPVersion;
  169. LAddr, LText: string;
  170. LPort: integer;
  171. LSocket: TIdSocketHandle;
  172. begin
  173. ADest.BeginUpdate;
  174. try
  175. ADest.Clear;
  176. LItems := TStringList.Create;
  177. try
  178. LItems.CommaText := AList;
  179. for i := 0 to LItems.Count-1 do begin
  180. if Length(LItems[i]) > 0 then begin
  181. if TextStartsWith(LItems[i], '[') then begin
  182. // ipv6
  183. LIPVersion := Id_IPv6;
  184. LText := Copy(LItems[i], 2, MaxInt);
  185. LAddr := Fetch(LText, ']:');
  186. LPort := StrToIntDef(LText, -1);
  187. end else begin
  188. // ipv4
  189. LIPVersion := Id_IPv4;
  190. LText := LItems[i];
  191. LAddr := Fetch(LText, ':');
  192. LPort := StrToIntDef(LText, -1);
  193. //Note that 0 is legal and indicates the server binds to a random port
  194. end;
  195. if IsValidIP(LAddr) and (LPort > -1) and (LPort < 65536) then begin
  196. LSocket := ADest.Add;
  197. LSocket.IPVersion := LIPVersion;
  198. LSocket.IP := LAddr;
  199. LSocket.Port := LPort;
  200. end;
  201. end;
  202. end;
  203. finally
  204. LItems.Free;
  205. end;
  206. finally
  207. ADest.EndUpdate;
  208. end;
  209. end;
  210. { TIdDsnPropEdBindingVCL }
  211. function NumericOnly(const AText : String) : String;
  212. var
  213. i : Integer;
  214. begin
  215. Result := '';
  216. for i := 1 to Length(AText) do
  217. begin
  218. if IsNumeric(AText[i]) then begin
  219. Result := Result + AText[i];
  220. end else begin
  221. Break;
  222. end;
  223. end;
  224. if Length(Result) = 0 then begin
  225. Result := '0';
  226. end;
  227. end;
  228. function IndexOfNo(const ANo : Integer; AStrings : TStrings) : Integer;
  229. begin
  230. for Result := 0 to AStrings.Count-1 do
  231. begin
  232. if ANo = IndyStrToInt(NumericOnly(AStrings[Result])) then begin
  233. Exit;
  234. end;
  235. end;
  236. Result := -1;
  237. end;
  238. function GetDisplayString(ASocketHandle: TIdSocketHandle): string;
  239. begin
  240. Result := '';
  241. case ASocketHandle.IPVersion of
  242. Id_IPv4 : Result := Format('%s:%d',[ASocketHandle.IP, ASocketHandle.Port]);
  243. Id_IPv6 : Result := Format('[%s]:%d',[ASocketHandle.IP, ASocketHandle.Port]);
  244. end;
  245. end;
  246. function GetListValues(const ASocketHandles : TIdSocketHandles) : String;
  247. var i : Integer;
  248. begin
  249. Result := '';
  250. for i := 0 to ASocketHandles.Count -1 do begin
  251. Result := Result + ',' + GetDisplayString(ASocketHandles[i]);
  252. end;
  253. Delete(Result,1,1);
  254. end;
  255. constructor TIdDsnPropEdBindingVCL.Create(AOwner: TComponent);
  256. var
  257. i : Integer;
  258. LLocalAddresses: TIdStackLocalAddressList;
  259. begin
  260. inherited CreateNew(AOwner, 0);
  261. {$IFNDEF WIDGET_KYLIX}
  262. Borderstyle := bsDialog;
  263. {$ENDIF}
  264. BorderIcons := [biSystemMenu];
  265. // Width := 480;
  266. // Height := 252;
  267. ClientWidth := 472;
  268. {$IFDEF USE_TBitBtn}
  269. ClientHeight := 230;
  270. {$ELSE}
  271. ClientHeight := 225;
  272. {$ENDIF}
  273. Constraints.MaxWidth := Width;
  274. Constraints.MaxHeight := Height;
  275. Constraints.MinWidth := Width;
  276. Constraints.MinHeight := Height;
  277. Position := poScreenCenter;
  278. lblBindings := TLabel.Create(Self);
  279. lbBindings := TListBox.Create(Self);
  280. ActionList1 := TActionList.Create(Self);
  281. btnBindingsNew := TAction.Create(Self);
  282. btnBindingsDelete := TAction.Create(Self);
  283. btnNew := TButton.Create(Self);
  284. btnDelete := TButton.Create(Self);
  285. lblIPAddress := TLabel.Create(Self);
  286. edtIPAddress := TComboBox.Create(Self);
  287. lblPort := TLabel.Create(Self);
  288. edtPort := TComboBox.Create(Self);
  289. rdoBindingType := TRadioGroup.Create(Self);
  290. {$IFDEF USE_TBitBtn}
  291. btnOk := TBitBtn.Create(Self);
  292. btnCancel := TBitBtn.Create(Self);
  293. {$ELSE}
  294. btnOk := TButton.Create(Self);
  295. btnCancel := TButton.Create(Self);
  296. {$ENDIF}
  297. lblBindings.Name := 'lblBindings'; {do not localize}
  298. lblBindings.Parent := Self;
  299. lblBindings.Left := 8;
  300. lblBindings.Top := 8;
  301. lblBindings.Width := 35;
  302. lblBindings.Height := 13;
  303. lblBindings.Caption := '&Binding'; {do not localize}
  304. lbBindings.Name := 'lbBindings'; {do not localize}
  305. lbBindings.Parent := Self;
  306. lbBindings.Left := 8;
  307. lbBindings.Top := 24;
  308. lbBindings.Width := 137;
  309. lbBindings.Height := 161;
  310. lbBindings.ItemHeight := 13;
  311. lbBindings.TabOrder := 8;
  312. lbBindings.OnClick := lbBindingsClick;
  313. ActionList1.Name := 'ActionList1'; {do not localize}
  314. {
  315. ActionList1.Left := 152;
  316. ActionList1.Top := 32;
  317. }
  318. btnBindingsNew.Name := 'btnBindingsNew'; {do not localize}
  319. btnBindingsNew.Caption := RSBindingNewCaption;
  320. btnBindingsNew.OnExecute := btnBindingsNewExecute;
  321. btnBindingsDelete.Name := 'btnBindingsDelete'; {do not localize}
  322. btnBindingsDelete.Caption := RSBindingDeleteCaption;
  323. btnBindingsDelete.OnExecute := btnBindingsDeleteExecute;
  324. btnBindingsDelete.OnUpdate := btnBindingsDeleteUpdate;
  325. btnNew.Name := 'btnNew'; {do not localize}
  326. btnNew.Parent := Self;
  327. btnNew.Left := 152;
  328. btnNew.Top := 72;
  329. btnNew.Width := 75;
  330. btnNew.Height := 25;
  331. btnNew.Action := btnBindingsNew;
  332. btnNew.TabOrder := 6;
  333. btnDelete.Name := 'btnDelete'; {do not localize}
  334. btnDelete.Parent := Self;
  335. btnDelete.Left := 152;
  336. btnDelete.Top := 104;
  337. btnDelete.Width := 75;
  338. btnDelete.Height := 25;
  339. btnDelete.Action := btnBindingsDelete;
  340. btnDelete.TabOrder := 7;
  341. lblIPAddress.Name := 'lblIPAddress'; {do not localize}
  342. lblIPAddress.Parent := Self;
  343. lblIPAddress.Left := 240;
  344. lblIPAddress.Top := 8;
  345. lblIPAddress.Width := 54;
  346. lblIPAddress.Height := 13;
  347. lblIPAddress.Caption := RSBindingHostnameLabel;
  348. lblIPAddress.Enabled := False;
  349. edtIPAddress.Name := 'edtIPAddress'; {do not localize}
  350. edtIPAddress.Parent := Self;
  351. edtIPAddress.Left := 240;
  352. edtIPAddress.Top := 24;
  353. edtIPAddress.Width := 221;
  354. edtIPAddress.Height := 21;
  355. edtIPAddress.Enabled := False;
  356. edtIPAddress.ItemHeight := 13;
  357. edtIPAddress.TabOrder := 3;
  358. edtIPAddress.OnChange := edtIPAddressChange;
  359. lblPort.Name := 'lblPort'; {do not localize}
  360. lblPort.Parent := Self;
  361. lblPort.Left := 240;
  362. lblPort.Top := 56;
  363. lblPort.Width := 22;
  364. lblPort.Height := 13;
  365. lblPort.Caption := RSBindingPortLabel;
  366. lblPort.Enabled := False;
  367. lblPort.FocusControl := edtPort;
  368. edtPort.Name := 'edtPort'; {do not localize}
  369. edtPort.Parent := Self;
  370. edtPort.Left := 240;
  371. edtPort.Top := 72;
  372. edtPort.Width := 221;
  373. edtPort.Height := 21;
  374. edtPort.Enabled := False;
  375. edtPort.ItemHeight := 13;
  376. edtPort.TabOrder := 4;
  377. edtPort.OnChange := edtPortChange;
  378. edtPort.OnKeyPress := edtPortKeyPress;
  379. rdoBindingType.Name := 'rdoBindingType'; {do not localize}
  380. rdoBindingType.Parent := Self;
  381. rdoBindingType.Left := 240;
  382. rdoBindingType.Top := 120;
  383. rdoBindingType.Width := 221;
  384. rdoBindingType.Height := 65;
  385. rdoBindingType.Caption := RSBindingIPVerLabel;
  386. rdoBindingType.Enabled := False;
  387. rdoBindingType.Items.Add(RSBindingIPV4Item);
  388. rdoBindingType.Items.Add(RSBindingIPV6Item);
  389. rdoBindingType.TabOrder := 5;
  390. rdoBindingType.OnClick := rdoBindingTypeClick;
  391. btnOk.Name := 'btnOk'; {do not localize}
  392. btnOk.Parent := Self;
  393. btnOk.Anchors := [akRight, akBottom];
  394. btnOk.Left := 306;
  395. btnOk.Top := 193;
  396. btnOk.Width := 75;
  397. {$IFDEF USE_TBitBtn}
  398. btnOk.Height := 30;
  399. btnOk.Kind := bkOk;
  400. {$ELSE}
  401. btnOk.Height := 25;
  402. btnOk.Caption := RSOk;
  403. btnOk.Default := True;
  404. btnOk.ModalResult := 1;
  405. {$ENDIF}
  406. btnOk.TabOrder := 0;
  407. btnCancel.Name := 'btnCancel'; {do not localize}
  408. btnCancel.Parent := Self;
  409. btnCancel.Anchors := [akRight, akBottom];
  410. btnCancel.Left := 386;
  411. btnCancel.Top := 193;
  412. btnCancel.Width := 75;
  413. {$IFDEF USE_TBitBtn}
  414. btnCancel.Height := 30;
  415. btnCancel.Kind := bkCancel;
  416. {$ELSE}
  417. btnCancel.Height := 25;
  418. btnCancel.Cancel := True;
  419. btnCancel.Caption := RSCancel;
  420. btnCancel.ModalResult := 2;
  421. {$ENDIF}
  422. btnCancel.Anchors := [akRight, akBottom];
  423. btnCancel.TabOrder := 1;
  424. FHandles := TIdSocketHandles.Create(nil);
  425. FIPv4Addresses := TStringList.Create;
  426. FIPv6Addresses := TStringList.Create;
  427. SetIPv4Addresses(nil);
  428. SetIPv6Addresses(nil);
  429. TIdStack.IncUsage;
  430. try
  431. LLocalAddresses := TIdStackLocalAddressList.Create;
  432. try
  433. GStack.GetLocalAddressList(LLocalAddresses);
  434. for i := 0 to LLocalAddresses.Count-1 do
  435. begin
  436. case LLocalAddresses[i].IPVersion of
  437. Id_IPv4: FIPv4Addresses.Add(LLocalAddresses[i].IPAddress);
  438. Id_IPv6: FIPv6Addresses.Add(LLocalAddresses[i].IPAddress);
  439. end;
  440. end;
  441. finally
  442. LLocalAddresses.Free;
  443. end;
  444. finally
  445. TIdStack.DecUsage;
  446. end;
  447. edtPort.Items.BeginUpdate;
  448. try
  449. edtPort.Items.Add(PortDescription(0));
  450. for i := 0 to IdPorts.Count - 1 do begin
  451. edtPort.Items.Add(
  452. PortDescription(
  453. {$IFDEF HAS_GENERICS_TList}
  454. IdPorts[i]
  455. {$ELSE}
  456. PtrInt(IdPorts[i])
  457. {$ENDIF}
  458. )
  459. );
  460. end;
  461. finally
  462. edtPort.Items.EndUpdate;
  463. end;
  464. AutoScroll := False;
  465. Caption := RSBindingFormCaption;
  466. {$IFDEF WIDGET_VCL}
  467. Scaled := False;
  468. {$ENDIF}
  469. Font.Color := clBtnText;
  470. Font.Height := -11;
  471. Font.Name := 'MS Sans Serif'; {Do not Localize}
  472. Font.Style := [];
  473. Position := poScreenCenter;
  474. PixelsPerInch := 96;
  475. FInUpdateRoutine := False;
  476. UpdateEditControls;
  477. end;
  478. destructor TIdDsnPropEdBindingVCL.Destroy;
  479. begin
  480. FreeAndNil(FIPv4Addresses);
  481. FreeAndNil(FIPv6Addresses);
  482. FreeAndNil(FHandles);
  483. inherited Destroy;
  484. end;
  485. function TIdDsnPropEdBindingVCL.PortDescription(const PortNumber: integer): string;
  486. var
  487. LList: TStringList;
  488. begin
  489. if PortNumber = 0 then begin
  490. Result := IndyFormat('%d: %s', [PortNumber, RSBindingAny]);
  491. end else begin
  492. Result := ''; {Do not Localize}
  493. LList := TStringList.Create;
  494. try
  495. GBSDStack.AddServByPortToList(PortNumber, LList);
  496. if LList.Count > 0 then begin
  497. Result := Format('%d: %s', [PortNumber, LList.CommaText]); {Do not Localize}
  498. end;
  499. finally
  500. LList.Free;
  501. end;
  502. end;
  503. end;
  504. procedure TIdDsnPropEdBindingVCL.SetHandles(const Value: TIdSocketHandles);
  505. begin
  506. FHandles.Assign(Value);
  507. UpdateBindingList;
  508. end;
  509. procedure TIdDsnPropEdBindingVCL.btnBindingsNewExecute(Sender: TObject);
  510. begin
  511. FCurrentHandle := FHandles.Add;
  512. case FCurrentHandle.IPVersion of
  513. Id_IPv4: FCurrentHandle.IP := IPv4Wildcard;
  514. Id_IPv6: FCurrentHandle.IP := IPv6Wildcard1;
  515. end;
  516. FCurrentHandle.Port := FDefaultPort;
  517. UpdateBindingList;
  518. edtIPAddress.Items.Assign(FIPv4Addresses);
  519. UpdateEditControls;
  520. end;
  521. procedure TIdDsnPropEdBindingVCL.UpdateEditControls;
  522. var
  523. i : Integer;
  524. begin
  525. if Assigned(FCurrentHandle) then
  526. begin
  527. i := IndexOfNo(FCurrentHandle.Port,edtPort.Items);
  528. if i = -1 then begin
  529. edtPort.Text := IntToStr(FCurrentHandle.Port);
  530. end else begin
  531. edtPort.ItemIndex := i;
  532. end;
  533. case FCurrentHandle.IPVersion of
  534. Id_IPv4 :
  535. begin
  536. rdoBindingType.ItemIndex := 0;
  537. edtIPAddress.Items.Assign(FIPv4Addresses);
  538. end;
  539. Id_IPv6 :
  540. begin
  541. rdoBindingType.ItemIndex := 1;
  542. edtIPAddress.Items.Assign(FIPv6Addresses);
  543. end;
  544. end;
  545. if edtIPAddress.Style = csDropDown then begin
  546. edtIPAddress.Text := FCurrentHandle.IP;
  547. end else begin
  548. edtIPAddress.ItemIndex := edtIPAddress.Items.IndexOf(FCurrentHandle.IP);
  549. end;
  550. end
  551. else
  552. begin
  553. edtIPAddress.Text := '';
  554. //in LCL, the line below caused an index out of range error.
  555. {$IFDEF WIDGET_VCL}
  556. edtPort.ItemIndex := -1; //-2;
  557. {$ENDIF}
  558. edtPort.Text := '';
  559. end;
  560. lblIPAddress.Enabled := Assigned(FCurrentHandle);
  561. edtIPAddress.Enabled := Assigned(FCurrentHandle);
  562. lblPort.Enabled := Assigned(FCurrentHandle);
  563. edtPort.Enabled := Assigned(FCurrentHandle);
  564. rdoBindingType.Enabled := Assigned(FCurrentHandle);
  565. {$IFDEF WIDGET_KYLIX}
  566. //WOrkaround for CLX quirk that might be Kylix 1
  567. for i := 0 to rdoBindingType.ControlCount -1 do begin
  568. rdoBindingType.Controls[i].Enabled := Assigned(FCurrentHandle);
  569. end;
  570. {$ENDIF}
  571. {$IFDEF WIDGET_VCL_LIKE}
  572. //The Win32 VCL does not change the control background to a greyed look
  573. //when controls are disabled. This quirk is not present in CLX.
  574. if Assigned(FCurrentHandle) then
  575. begin
  576. edtIPAddress.Color := clWindow;
  577. edtPort.Color := clWindow;
  578. end else
  579. begin
  580. edtIPAddress.Color := clBtnFace;
  581. edtPort.Color := clBtnFace;
  582. end;
  583. {$ENDIF}
  584. end;
  585. procedure TIdDsnPropEdBindingVCL.btnBindingsDeleteExecute(Sender: TObject);
  586. var
  587. LSH : TIdSocketHandle;
  588. begin
  589. if lbBindings.ItemIndex >= 0 then
  590. begin
  591. // Delete is not available in D4's collection classes
  592. // This should work just as well.
  593. LSH := Handles[lbBindings.ItemIndex];
  594. FreeAndNil(LSH);
  595. FCurrentHandle := nil;
  596. UpdateBindingList;
  597. end;
  598. lbBindingsClick(nil);
  599. UpdateEditControls;
  600. end;
  601. procedure TIdDsnPropEdBindingVCL.btnBindingsDeleteUpdate(Sender: TObject);
  602. begin
  603. btnBindingsDelete.Enabled := lbBindings.ItemIndex >= 0;
  604. end;
  605. procedure TIdDsnPropEdBindingVCL.SetIPv4Addresses(const Value: TStrings);
  606. begin
  607. if Assigned(Value) then begin
  608. FIPv4Addresses.Assign(Value);
  609. end;
  610. // Ensure that these two are always present
  611. if FIPv4Addresses.IndexOf(IPv6Loopback) = -1 then begin
  612. FIPv4Addresses.Insert(0, IPv4Loopback);
  613. end;
  614. if FIPv4Addresses.IndexOf(IPv4Wildcard) = -1 then begin
  615. FIPv4Addresses.Insert(0, IPv4Wildcard);
  616. end;
  617. end;
  618. procedure TIdDsnPropEdBindingVCL.SetIPv6Addresses(const Value: TStrings);
  619. begin
  620. if Assigned(Value) then begin
  621. FIPv6Addresses.Assign(Value);
  622. end;
  623. // Ensure that these two are always present
  624. if FIPv6Addresses.IndexOf(IPv6Loopback) = -1 then begin
  625. FIPv6Addresses.Insert(0, IPv6Loopback);
  626. end;
  627. if FIPv6Addresses.IndexOf(IPv6Wildcard1) = -1 then begin
  628. FIPv6Addresses.Insert(0, IPv6Wildcard1);
  629. end;
  630. end;
  631. procedure TIdDsnPropEdBindingVCL.edtPortKeyPress(Sender: TObject; var Key: Char);
  632. begin
  633. // RLebeau 1/7/09: using Char() for #128-#255 because in D2009, the compiler
  634. // may change characters >= #128 from their Ansi codepage value to their true
  635. // Unicode codepoint value, depending on the codepage used for the source code.
  636. // For instance, #128 may become #$20AC...
  637. if (Key > Chr(31)) and (Key < Chr(128)) then begin
  638. if not IsNumeric(Key) then begin
  639. Key := #0;
  640. end;
  641. end;
  642. end;
  643. procedure TIdDsnPropEdBindingVCL.edtIPAddressChange(Sender: TObject);
  644. begin
  645. FCurrentHandle.IP := edtIPAddress.Text;
  646. UpdateBindingList;
  647. end;
  648. procedure TIdDsnPropEdBindingVCL.edtPortChange(Sender: TObject);
  649. begin
  650. if Assigned(FCurrentHandle) then begin
  651. FCurrentHandle.Port := IndyStrToInt(NumericOnly(edtPort.Text), 0);
  652. end;
  653. UpdateBindingList;
  654. end;
  655. procedure TIdDsnPropEdBindingVCL.rdoBindingTypeClick(Sender: TObject);
  656. begin
  657. case rdoBindingType.ItemIndex of
  658. 0 :
  659. begin
  660. if FCurrentHandle.IPVersion <> Id_IPv4 then
  661. begin
  662. FCurrentHandle.IPVersion := Id_IPv4;
  663. edtIPAddress.Items.Assign(FIPv4Addresses);
  664. FCurrentHandle.IP := IPv4Wildcard;
  665. end;
  666. end;
  667. 1 :
  668. begin
  669. if FCurrentHandle.IPVersion <> Id_IPv6 then
  670. begin
  671. FCurrentHandle.IPVersion := Id_IPv6;
  672. edtIPAddress.Items.Assign(FIPv6Addresses);
  673. FCurrentHandle.IP := IPv6Wildcard1;
  674. end;
  675. end;
  676. end;
  677. UpdateEditControls;
  678. UpdateBindingList;
  679. end;
  680. function TIdDsnPropEdBindingVCL.GetList: string;
  681. begin
  682. Result := GetListValues(Handles);
  683. end;
  684. procedure TIdDsnPropEdBindingVCL.lbBindingsClick(Sender: TObject);
  685. begin
  686. if lbBindings.ItemIndex >= 0 then begin
  687. FCurrentHandle := FHandles[lbBindings.ItemIndex];
  688. end else begin
  689. FCurrentHandle := nil;
  690. end;
  691. UpdateEditControls;
  692. end;
  693. procedure TIdDsnPropEdBindingVCL.SetList(const AList: string);
  694. begin
  695. FCurrentHandle := nil;
  696. FillHandleList(AList, Handles);
  697. UpdateBindingList;
  698. UpdateEditControls;
  699. end;
  700. procedure TIdDsnPropEdBindingVCL.UpdateBindingList;
  701. var
  702. i: integer;
  703. selected: integer;
  704. s: string;
  705. begin
  706. //in Lazarus, for some odd reason, if you have more than one binding,
  707. //the routine is called while the items are updated
  708. if FInUpdateRoutine then begin
  709. Exit;
  710. end;
  711. FInUpdateRoutine := True;
  712. try
  713. selected := lbBindings.ItemIndex;
  714. lbBindings.Items.BeginUpdate;
  715. try
  716. if lbBindings.Items.Count = FHandles.Count then begin
  717. for i := 0 to FHandles.Count - 1 do begin
  718. s := GetDisplayString(FHandles[i]);
  719. if s <> lbBindings.Items[i] then begin
  720. lbBindings.Items[i] := s;
  721. end;
  722. end;
  723. end else begin
  724. lbBindings.Items.Clear;
  725. for i := 0 to FHandles.Count-1 do begin
  726. lbBindings.Items.Add(GetDisplayString(FHandles[i]));
  727. end;
  728. end;
  729. finally
  730. lbBindings.Items.EndUpdate;
  731. if Assigned(FCurrentHandle) then begin
  732. lbBindings.ItemIndex := FCurrentHandle.Index;
  733. end else begin
  734. lbBindings.ItemIndex := IndyMin(selected, lbBindings.Items.Count-1);
  735. end;
  736. end;
  737. finally
  738. FInUpdateRoutine := False;
  739. end;
  740. end;
  741. function TIdDsnPropEdBindingVCL.Execute: Boolean;
  742. begin
  743. Result := ShowModal = mrOk;
  744. end;
  745. constructor TIdDsnPropEdBindingVCL.Create;
  746. begin
  747. Create(nil);
  748. end;
  749. end.