IdDsnPropEdBindingVCL.pas 23 KB

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