* Replaced fphttpclient with indy10.

* Added compression support
This commit is contained in:
2015-10-04 14:14:55 +02:00
parent 610c1e4108
commit b1e455022b
1330 changed files with 338589 additions and 27 deletions

View File

@@ -103,6 +103,9 @@ Once the first none-empty line is unrecognized (no command found), the parser wi
This can be repeated multiple times but will only be used when Method == POST.
The Content-Type header is set automatically too.
`Compress[ed]`
: Adds support for gzip,deflate compression to the connection.
`Call <URL>`
: This prepares the actual call by providing the URL to be called.
Variables in the form of `@<variablename>` are replaced accordingly.

View File

@@ -24,11 +24,25 @@ interface
uses
Classes, SysUtils, CustApp,
IniFiles, fphttpclient, jsonparser, JTemplate,
UFilter;
IniFiles, jsonparser, JTemplate,
UFilter, IdHTTP, IdMultipartFormData;
type
{ TRestHTTP }
TRestHTTP = class(TIdHTTP)
public
procedure Perform(AMethod, AURL: String; ARequest, AResponse: TStream);
end;
{ TRestRequest }
TRestRequest = class(TIdHTTPRequest)
public
procedure Prepare;
end;
{ TRestemplateApplication }
TRestemplateApplication = class(TCustomApplication)
@@ -38,9 +52,10 @@ type
FSessionIni: TIniFile;
FTemplateName: String;
FParser: TJTemplateParser;
FHttp: TFPHTTPClient;
FHttp: TRestHTTP;
FRequest: TRestRequest;
FContent: TStringList;
FFormFields: TStringList;
FFormFields: TIdMultiPartFormDataStream;
FFilters: TFilterList;
FBeautify: Boolean;
FURL: String;
@@ -67,7 +82,8 @@ type
implementation
uses
strutils, crt, UCRTHelper, fpjson, DOM, XMLRead, XMLWrite, vinfo;
strutils, crt, UCRTHelper, fpjson, DOM, XMLRead, XMLWrite, vinfo,
IdCompressorZLib;
type
TContentType = (ctOther, ctJSON, ctXML);
@@ -84,6 +100,22 @@ begin
Result := (ContentType <> ctOther);
end;
{ TRestRequest }
procedure TRestRequest.Prepare;
begin
//Parse RawHeaders, since they have precendence and should not be overridden!
ProcessHeaders;
end;
{ TRestHTTP }
procedure TRestHTTP.Perform(AMethod, AURL: String; ARequest, AResponse: TStream
);
begin
DoRequest(AMethod, AURL, ARequest, AResponse, []);
end;
{ TRestemplateApplication }
procedure TRestemplateApplication.DoRun;
@@ -199,6 +231,11 @@ begin
Result := True;
CmdFormField(Copy(ALine, 11, Length(ALine)));
end else
if AnsiStartsStr('Compress', ALine) then
begin
Result := True;
FHttp.Compressor := TIdCompressorZLib.Create(FHttp);
end else
if AnsiStartsStr('Call ', ALine) then
begin
Result := True;
@@ -255,7 +292,11 @@ begin
varName := Trim(Copy(AHeader, 1, i - 1));
varValue := Trim(Copy(AHeader, i + 1, Length(AHeader)));
FHttp.AddHeader(varName, varValue);
//Special handling is required for Indy
{if SameText(varName, 'Accept-Encoding') then
FHttp.Request.AcceptEncoding := varValue
else}
FRequest.RawHeaders.AddValue(varName, varValue);
end;
procedure TRestemplateApplication.CmdBasicAuth(AData: String);
@@ -268,8 +309,9 @@ begin
while (i < Length(AData)) and (AData[i] <> separator) do
Inc(i);
FHttp.UserName := Copy(AData, 2, i - 2);
FHttp.Password := Copy(AData, i + 1, Length(AData));
FRequest.Username := Copy(AData, 2, i - 2);
FRequest.Password := Copy(AData, i + 1, Length(AData));
FRequest.BasicAuthentication := True;
end;
procedure TRestemplateApplication.CmdHighlight(AData: String);
@@ -278,10 +320,18 @@ begin
end;
procedure TRestemplateApplication.CmdFormField(AData: String);
var
i: Integer;
begin
i := 1;
FParser.Content := AData;
FParser.Replace;
FFormFields.Add(FParser.Content);
AData := FParser.Content;
while (i < Length(AData)) and (AData[i] <> '=') do
Inc(i);
FFormFields.AddFormField(Copy(AData, 1, i - 1), Copy(AData, i + 1, Length(AData)));
end;
procedure TRestemplateApplication.ProcessCall(AURL: String);
@@ -304,23 +354,24 @@ begin
if FContent.Count > 0 then
begin
request := TMemoryStream.Create;
// Variable replacement
FParser.Content := FContent.Text;
FParser.Replace;
FContent.Text := FParser.Content;
FContent.SaveToStream(request);
request.Position := 0;
FHttp.RequestBody := request;
end;
try
//Special handling for formdata
if SameText('POST', FMethod) and (FFormFields.Count > 0) then
FHttp.FormPost(AURL, FFormFields, response)
else
FHttp.HTTPMethod(FMethod, AURL, response, []);
FRequest.Prepare;
FHttp.Request := FRequest;
FHttp.HTTPOptions := FHttp.HTTPOptions + [hoNoProtocolErrorException];
if FFormFields.Size > 0 then
begin
FHttp.Request.ContentType := FFormFields.RequestContentType;
FHttp.Perform(FMethod, AURL, FFormFields, response);
end else
FHttp.Perform(FMethod, AURL, request, response);
except
on E: Exception do
begin
@@ -331,16 +382,16 @@ begin
end;
writeln;
writeln('Status: ', FHttp.ResponseStatusCode, ' (', FHttp.ResponseStatusText, ')');
writeln('Status: ', FHttp.ResponseCode, ' (', FHttp.ResponseText, ')');
writeln;
writeln('Headers:');
for s in FHttp.ResponseHeaders do
for s in FHttp.Response.RawHeaders do
writeln(' ', s);
writeln;
response.Position := 0;
if FBeautify and IdentifyContentType(FHttp.GetHeader(FHttp.ResponseHeaders, 'Content-Type'), contentType) then
if FBeautify and IdentifyContentType(FHttp.Response.ContentType, contentType) then
begin
case contentType of
ctJSON:
@@ -474,8 +525,10 @@ begin
FSessionIni := TIniFile.Create(FConfigDir + 'session.ini');
FContent := TStringList.Create;
FFormFields := TStringList.Create;
FHttp := TFPHTTPClient.Create(Self);
FFormFields := TIdMultiPartFormDataStream.Create;
FHttp := TRestHTTP.Create(nil);
FRequest := TRestRequest.Create(FHttp);
FRequest.RawHeaders.AddValue('User-Agent', 'Mozilla/4.0 (compatible; restemplate ' + VersionInfo.GetProductVersionString + ')');
FFilters := TFilterList.Create;
FParser := TJTemplateParser.Create;
end;
@@ -486,6 +539,7 @@ begin
FContent.Free;
FFormFields.Free;
FHttp.Free;
//TODO Owned? FRequest.Free;
FFilters.Free;
FParser.Free;
inherited Destroy;

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 KiB

Binary file not shown.

BIN
indy/Core/AboutProg.res Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Binary file not shown.

37
indy/Core/IdAbout.pas Normal file
View File

@@ -0,0 +1,37 @@
unit IdAbout;
interface
{$I IdCompilerDefines.inc}
uses
{$IFDEF DOTNET}
IdAboutDotNET;
{$ELSE}
IdAboutVCL;
{$ENDIF}
//we have a procedure for providing a product name and version in case
//we ever want to make another product.
procedure ShowAboutBox(const AProductName, AProductName2, AProductVersion : String);
procedure ShowDlg;
implementation
{$IFDEF DOTNET}
//for some reason, the Winforms designer doesn't like this in the same unit
//as the class it's for
{$R 'IdAboutDotNET.TfrmAbout.resources' 'IdAboutDotNET.resx'}
{$ENDIF}
procedure ShowAboutBox(const AProductName, AProductName2, AProductVersion : String);
begin
TfrmAbout.ShowAboutBox(AProductName, AProductName2, AProductVersion);
end;
procedure ShowDlg;
begin
TfrmAbout.ShowDlg;
end;
end.

BIN
indy/Core/IdAbout.resources Normal file

Binary file not shown.

184
indy/Core/IdAbout.resx Normal file
View File

@@ -0,0 +1,184 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used forserialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="imgLogo.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="imgLogo.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblName.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblName.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblName2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblName2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblVersion.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblVersion.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblCopyright.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblCopyright.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblBuiltFor.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblBuiltFor.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblLicense.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblLicense.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblPleaseVisitUs.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblPleaseVisitUs.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblURL.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblURL.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="bbtnOk.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="bbtnOk.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>(Default)</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>8, 8</value>
</data>
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>80</value>
</data>
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
</root>

Binary file not shown.

332
indy/Core/IdAboutDotNET.pas Normal file
View File

@@ -0,0 +1,332 @@
unit IdAboutDotNET;
interface
uses
System.Drawing, System.Collections, System.ComponentModel,
System.Windows.Forms, System.Data;
type
TfrmAbout = class(System.Windows.Forms.Form)
{$REGION 'Designer Managed Code'}
strict private
/// <summary>
/// Required designer variable.
/// </summary>
Components: System.ComponentModel.Container;
imgLogo: System.Windows.Forms.PictureBox;
bbtnOk: System.Windows.Forms.Button;
lblName: System.Windows.Forms.Label;
lblName2: System.Windows.Forms.Label;
lblVersion: System.Windows.Forms.Label;
lblCopyright: System.Windows.Forms.Label;
lblBuiltFor: System.Windows.Forms.Label;
lblLicense: System.Windows.Forms.Label;
lblPleaseVisitUs: System.Windows.Forms.Label;
lblURL: System.Windows.Forms.LinkLabel;
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
procedure InitializeComponent;
procedure lblURL_LinkClicked(sender: System.Object; e: System.Windows.Forms.LinkLabelLinkClickedEventArgs);
{$ENDREGION}
strict protected
/// <summary>
/// Clean up any resources being used.
/// </summary>
procedure Dispose(Disposing: Boolean); override;
protected
{ Private Declarations }
function GetProductName: string;
procedure SetProductName(const AValue: string);
function GetProductName2: string;
procedure SetProductName2(const AValue: string);
function GetVersion: string;
procedure SetVersion(const AValue: string);
function LoadBitmap(AResName: string): Bitmap;
public
constructor Create;
//we have a method for providing a product name and version in case
//we ever want to make another product.
class Procedure ShowAboutBox(const AProductName, AProductName2, AProductVersion : String);
class Procedure ShowDlg;
property ProductName : String read GetProductName write SetProductName;
property ProductName2 : String read GetProductName2 write SetProductName2;
property Version : String read GetVersion write SetVersion;
end;
[assembly: RuntimeRequiredAttribute(TypeOf(TfrmAbout))]
implementation
uses
IdDsnCoreResourceStrings, System.Diagnostics,
IdGlobal, System.Reflection, System.Resources, SysUtils;
const
ResourceBaseName = 'IdAboutNET';
{$R 'AboutIndyNET.resources'}
{$AUTOBOX ON}
{$REGION 'Windows Form Designer generated code'}
/// <summary>
/// Required method for Designer support -- do not modify
/// the contents of this method with the code editor.
/// </summary>
procedure TfrmAbout.InitializeComponent;
begin
Self.imgLogo := System.Windows.Forms.PictureBox.Create;
Self.bbtnOk := System.Windows.Forms.Button.Create;
Self.lblName := System.Windows.Forms.Label.Create;
Self.lblName2 := System.Windows.Forms.Label.Create;
Self.lblVersion := System.Windows.Forms.Label.Create;
Self.lblCopyright := System.Windows.Forms.Label.Create;
Self.lblBuiltFor := System.Windows.Forms.Label.Create;
Self.lblLicense := System.Windows.Forms.Label.Create;
Self.lblPleaseVisitUs := System.Windows.Forms.Label.Create;
Self.lblURL := System.Windows.Forms.LinkLabel.Create;
Self.SuspendLayout;
//
// imgLogo
//
Self.imgLogo.Location := System.Drawing.Point.Create(0, 0);
Self.imgLogo.Name := 'imgLogo';
Self.imgLogo.Size := System.Drawing.Size.Create(388, 240);
Self.imgLogo.TabIndex := 0;
Self.imgLogo.TabStop := False;
//
// bbtnOk
//
Self.bbtnOk.Anchor := (System.Windows.Forms.AnchorStyles((System.Windows.Forms.AnchorStyles.Bottom
or System.Windows.Forms.AnchorStyles.Right)));
Self.bbtnOk.DialogResult := System.Windows.Forms.DialogResult.Cancel;
Self.bbtnOk.Location := System.Drawing.Point.Create(475, 302);
Self.bbtnOk.Name := 'bbtnOk';
Self.bbtnOk.TabIndex := 0;
Self.bbtnOk.Text := 'Button1';
//
// lblName
//
Self.lblName.Font := System.Drawing.Font.Create('Arial Black', 14.25, System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point, (Byte(0)));
Self.lblName.Location := System.Drawing.Point.Create(51, 28);
Self.lblName.Name := 'lblName';
Self.lblName.Size := System.Drawing.Size.Create(200, 101);
Self.lblName.TabIndex := 1;
Self.lblName.Text := 'Label1';
Self.lblName.TextAlign := System.Drawing.ContentAlignment.TopCenter;
//
// lblName2
//
Self.lblName.Font := System.Drawing.Font.Create('Arial', 14.25, System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point, (Byte(0)));
Self.lblName.Location := System.Drawing.Point.Create(54, 110);
Self.lblName.Name := 'lblName';
Self.lblName.Size := System.Drawing.Size.Create(192, 35);
Self.lblName.TabIndex := 2;
Self.lblName.Text := 'Label2';
Self.lblName.TextAlign := System.Drawing.ContentAlignment.TopCenter;
//
// lblVersion
//
Self.lblVersion.Font := System.Drawing.Font.Create('Arial', 14.25,
System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, (Byte(0)));
Self.lblVersion.Location := System.Drawing.Point.Create(300, 170);
Self.lblVersion.Name := 'lblVersion';
Self.lblVersion.Size := System.Drawing.Size.Create(200, 17);
Self.lblVersion.TabIndex := 3;
Self.lblVersion.Text := 'Label3';
Self.lblVersion.TextAlign := System.Drawing.ContentAlignment.TopRight;
//
// lblCopyright
//
Self.lblCopyright.Font := System.Drawing.Font.Create('Arial', 14.25,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, (Byte(0)));
Self.lblCopyright.Location := System.Drawing.Point.Create(58, 171);
Self.lblCopyright.Name := 'lblCopyright';
Self.lblCopyright.Size := System.Drawing.Size.Create(138, 15);
Self.lblCopyright.TabIndex := 6;
Self.lblCopyright.Text := 'Label6';
Self.lblCopyright.TextAlign := System.Drawing.ContentAlignment.TopCenter;
//
// lblBuiltFor
//
Self.lblBuiltFor.Anchor := (System.Windows.Forms.AnchorStyles(((System.Windows.Forms.AnchorStyles.Top
or System.Windows.Forms.AnchorStyles.Right)));
Self.lblBuiltFor.Font := System.Drawing.Font.Create('Arial', 14.25,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, (Byte(0)));
Self.lblBuiltFor.Location := System.Drawing.Point.Create(300, 188);
Self.lblBuiltFor.Name := 'lblBuiltFor';
Self.lblBuiltFor.Size := System.Drawing.Size.Create(200, 17);
Self.lblBuiltFor.TabIndex := 4;
Self.lblBuiltFor.Text := 'Label4';
Self.lblBuiltFor.TextAlign := System.Drawing.ContentAlignment.TopRight;
//
// lblLicense
//
Self.lblLicense.Anchor := (System.Windows.Forms.AnchorStyles(((System.Windows.Forms.AnchorStyles.Top
or System.Windows.Forms.AnchorStyles.Right)));
Self.lblLicense.Font := System.Drawing.Font.Create('Arial', 14.25,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, (Byte(0)));
Self.lblLicense.Location := System.Drawing.Point.Create(300, 227);
Self.lblLicense.Name := 'lblLicense';
Self.lblLicense.Size := System.Drawing.Size.Create(200, 45);
Self.lblLicense.TabIndex := 5;
Self.lblLicense.Text := 'Label5';
Self.lblBuiltFor.TextAlign := System.Drawing.ContentAlignment.TopRight;
//
// lblPleaseVisitUs
//
Self.lblPleaseVisitUs.Font := System.Drawing.Font.Create('Arial', 14.25,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, (Byte(0)));
Self.lblPleaseVisitUs.Location := System.Drawing.Point.Create(58, 278);
Self.lblPleaseVisitUs.Name := 'lblPleaseVisitUs';
Self.lblPleaseVisitUs.Size := System.Drawing.Size.Create(276, 15);
Self.lblPleaseVisitUs.TabIndex := 7;
Self.lblPleaseVisitUs.Text := 'Label7';
Self.lblPleaseVisitUs.TextAlign := System.Drawing.ContentAlignment.TopCenter;
//
// lblURL
//
Self.lblCopyright.Font := System.Drawing.Font.Create('Arial', 14.25,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, (Byte(0)));
Self.lblURL.Location := System.Drawing.Point.Create(58, 292);
Self.lblURL.Name := 'lblURL';
Self.lblURL.Size := System.Drawing.Size.Create(141, 15);
Self.lblURL.TabIndex := 8;
Self.lblURL.TabStop := True;
Self.lblURL.Text := 'LinkLabel8';
Self.lblURL.TextAlign := System.Drawing.ContentAlignment.TopCenter;
Include(Self.lblURL.LinkClicked, Self.lblURL_LinkClicked);
//
// TfrmAbout
//
Self.AcceptButton := Self.bbtnOk;
Self.AutoScaleBaseSize := System.Drawing.Size.Create(5, 13);
Self.CancelButton := Self.bbtnOk;
Self.ClientSize := System.Drawing.Size.Create(336, 554);
Self.Controls.Add(Self.lblURL);
Self.Controls.Add(Self.lblPleaseVisitUs);
Self.Controls.Add(Self.lblCopyright);
Self.Controls.Add(Self.lblVersion);
Self.Controls.Add(Self.lblName);
Self.Controls.Add(Self.lblName2);
Self.Controls.Add(Self.lblBuiltFor);
Self.Controls.Add(Self.lblLicense);
Self.Controls.Add(Self.bbtnOk);
Self.Controls.Add(Self.imgLogo);
Self.FormBorderStyle := System.Windows.Forms.FormBorderStyle.FixedDialog;
Self.MaximizeBox := False;
Self.MinimizeBox := False;
Self.Name := 'TfrmAbout';
Self.ShowInTaskbar := False;
Self.StartPosition := System.Windows.Forms.FormStartPosition.CenterScreen;
Self.Text := 'WinForm';
Self.ResumeLayout(False);
end;
{$ENDREGION}
procedure TfrmAbout.Dispose(Disposing: Boolean);
begin
if Disposing then
begin
if Components <> nil then
Components.Dispose();
end;
inherited Dispose(Disposing);
end;
constructor TfrmAbout.Create;
begin
inherited Create;
//
// Required for Windows Form Designer support
//
InitializeComponent;
//
// TODO: Add any constructor code after InitializeComponent call
//
Self.Text := RSAAboutFormCaption;
lblName.Text := RSAAboutBoxTitle1;
lblName2.Text := RSAAboutBoxTitle2;
lblBuiltFor.Text := IndyFormat(RSAAboutBoxBuiltFor, ['DotNET']);
lblLicense.Text := RSAAboutBoxLicences;
lblCopyright.Text := RSAAboutBoxCopyright;
lblPleaseVisitUs.Text := RSAAboutBoxPleaseVisit;
lblURL.Text := RSAAboutBoxIndyWebsite;
lblURL.Links.Add(0, Length(RSAABoutBoxIndyWebsite), RSAAboutBoxIndyWebsite);
bbtnOk.Text := RSOk;
imgLogo.Image := LoadBitmap('AboutBackground.bmp');
end;
procedure TfrmAbout.SetProductName(const AValue : String);
begin
Self.lblName.Text := AValue;
end;
procedure TfrmAbout.SetProductName2(const AValue : String);
begin
Self.lblName2.Text := AValue;
end;
procedure TfrmAbout.SetVersion(const AValue: string);
begin
Self.lblVersion.Text := AValue;
end;
function TfrmAbout.GetVersion: string;
begin
Result := Self.lblVersion.Text;
end;
function TfrmAbout.GetProductName: string;
begin
Result := Self.lblName.Text;
end;
function TfrmAbout.GetProductName2: string;
begin
Result := Self.lblName2.Text;
end;
class procedure TfrmAbout.ShowAboutBox(const AProductName, AProductName2,
AProductVersion: String);
begin
with TfrmAbout.Create do
try
Version := IndyFormat(RSAAboutBoxVersion, [AProductVersion]);
ProductName := AProductName;
ProductName2 := AProductName2;
Text := AProductName;
ShowDialog;
finally
Dispose;
end;
end;
class procedure TfrmAbout.ShowDlg;
begin
ShowAboutBox(RSAAboutBoxTitle1, RSAAboutBoxTitle2, gsIdVersion);
end;
procedure TfrmAbout.lblURL_LinkClicked(sender: System.Object; e: System.Windows.Forms.LinkLabelLinkClickedEventArgs);
var
LDest : String;
begin
LDest := e.Link.LinkData as string;
System.Diagnostics.Process.Start(LDest);
e.Link.Visited := True;
end;
function TfrmAbout.LoadBitmap(AResName: string): Bitmap;
var
LR: System.Resources.ResourceManager;
begin
LR := System.Resources.ResourceManager.Create('AboutIndyNET', System.Reflection.Assembly.GetExecutingAssembly);
Result := (Bitmap(LR.GetObject(AResName)));
end;
end.

Binary file not shown.

View File

@@ -0,0 +1,184 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used forserialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="imgLogo.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="imgLogo.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="bbtnOk.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="bbtnOk.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblName.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblName.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblName2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblName2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblVersion.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblVersion.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblCopyright.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblCopyright.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblBuiltFor.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblBuiltFor.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblLicense.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblLicense.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblPleaseVisitUs.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblPleaseVisitUs.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblURL.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblURL.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>(Default)</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>8, 8</value>
</data>
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>80</value>
</data>
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
</root>

Binary file not shown.

BIN
indy/Core/IdAboutVCL.RES Normal file

Binary file not shown.

5438
indy/Core/IdAboutVCL.lrs Normal file

File diff suppressed because it is too large Load Diff

420
indy/Core/IdAboutVCL.pas Normal file
View File

@@ -0,0 +1,420 @@
unit IdAboutVCL;
interface
{$I IdCompilerDefines.inc}
uses
{$IFDEF WIDGET_KYLIX}
QStdCtrls, QForms, QExtCtrls, QControls, QComCtrls, QGraphics, Qt,
{$ENDIF}
{$IFDEF WIDGET_VCL_LIKE}
StdCtrls, Buttons, ExtCtrls, Graphics, Controls, ComCtrls, Forms,
{$ENDIF}
{$IFDEF HAS_UNIT_Types}
Types,
{$ENDIF}
{$IFDEF WIDGET_LCL}
LResources,
{$ENDIF}
Classes, SysUtils;
type
TfrmAbout = class(TForm)
protected
FimLogo : TImage;
FlblCopyRight : TLabel;
FlblName : TLabel;
FlblName2 : TLabel;
FlblVersion : TLabel;
FlblBuiltFor : TLabel;
FlblLicense : TLabel;
FlblPleaseVisitUs : TLabel;
FlblURL : TLabel;
//for LCL, we use a TBitBtn to be consistant with some GUI interfaces
//and the Lazarus IDE.
{$IFDEF USE_TBitBtn}
FbbtnOk : TBitBtn;
{$ELSE}
FbbtnOk : TButton;
{$ENDIF}
procedure lblURLClick(Sender: TObject);
function GetProductName: String;
procedure SetProductName(const AValue: String);
function GetProductName2: String;
procedure SetProductName2(const AValue: String);
function GetVersion: String;
procedure SetVersion(const AValue: String);
public
//we have a method for providing a product name and version in case
//we ever want to make another product.
class procedure ShowDlg;
class procedure ShowAboutBox(const AProductName, AProductName2, AProductVersion: String);
constructor Create(AOwner : TComponent); overload; override;
constructor Create; reintroduce; overload;
property ProductName : String read GetProductName write SetProductName;
property ProductName2 : String read GetProductName2 write SetProductName2;
property Version : String read GetVersion write SetVersion;
end;
implementation
{$IFNDEF WIDGET_LCL}
{$IFDEF WIN32_OR_WIN64}
{$R IdAboutVCL.RES}
{$ENDIF}
{$IFDEF KYLIX}
{$R IdAboutVCL.RES}
{$ENDIF}
{$ENDIF}
uses
{$IFDEF WIN32_OR_WIN64}ShellApi, {$ENDIF}
{$IFNDEF WIDGET_LCL}
//done this way because we reference HInstance in Delphi for loading
//resources. Lazarus does something different.
{$IFDEF WIN32_OR_WIN64}
Windows,
{$ENDIF}
{$ENDIF}
IdDsnCoreResourceStrings,
IdGlobal;
{$IFNDEF WIDGET_LCL}
function RGBToColor(R, G, B: Byte): TColor;
begin
Result := RGB(R, G, B);
end;
{$ENDIF}
{ TfrmAbout }
constructor TfrmAbout.Create(AOwner: TComponent);
begin
inherited CreateNew(AOwner,0);
FimLogo := TImage.Create(Self);
FlblCopyRight := TLabel.Create(Self);
FlblName := TLabel.Create(Self);
FlblName2 := TLabel.Create(Self);
FlblVersion := TLabel.Create(Self);
FlblBuiltFor := TLabel.Create(Self);
FlblLicense := TLabel.Create(Self);
FlblPleaseVisitUs := TLabel.Create(Self);
FlblURL := TLabel.Create(Self);
{$IFDEF USE_TBitBtn}
FbbtnOk := TBitBtn.Create(Self);
{$ELSE}
FbbtnOk := TButton.Create(Self);
{$ENDIF}
Name := 'formAbout';
Left := 0;
Top := 0;
Anchors := [];//[akLeft, akTop, akRight,akBottom];
BorderIcons := [biSystemMenu];
BorderStyle := bsDialog;
Caption := RSAAboutFormCaption;
ClientHeight := 336;
ClientWidth := 554;
Color := 2520226; // RGBToColor(38, 116, 162)
Font.Color := 16776138; // RGBToColor(202, 251, 255)
Font.Height := -12;
Font.Size := 9;
Font.Name := 'Arial';
Font.Style := [];
Position := poScreenCenter;
{$IFDEF WIDGET_VCL}
Scaled := True;
{$ENDIF}
Constraints.MinHeight := Height;
Constraints.MinWidth := Width;
// PixelsPerInch := 96;
FimLogo.Name := 'imLogo';
FimLogo.Parent := Self;
FimLogo.Left := 0;
FimLogo.Top := 0;
FimLogo.Width := 388;
FimLogo.Height := 240;
{$IFDEF WIDGET_LCL}
FimLogo.Picture.Pixmap.LoadFromLazarusResource('IndyAboutBkgnd'); //this is XPM format, so Pixmap is used
FimLogo.Align := alClient;
FimLogo.Stretch := True;
{$ELSE} // Because Lazarus is also WIDGET_VCL_LIKE_OR_KYLIX
{$IFDEF WIDGET_VCL_LIKE_OR_KYLIX}
FimLogo.Picture.Bitmap.LoadFromResourceName(HInstance, 'INDY_ABOUT_BACKGROUND'); {Do not Localize}
FimLogo.Align := alClient;
FimLogo.Stretch := True;
{$ENDIF}
{$ENDIF}
FlblName.Name := 'lblName';
FlblName.Parent := Self;
FlblName.Left := 51;
FlblName.Top := 28;
FlblName.Width := 200;
FlblName.Height := 101;
FlblName.Anchors := [akLeft, akTop];
{$IFDEF WIDGET_VCL}
FlblName.Font.Charset := DEFAULT_CHARSET;
FlblName.Transparent := True;
{$ENDIF}
FlblName.Font.Color := clWhite;
FlblName.Font.Height := -72;
FlblName.Font.Name := 'Arial Black';
FlblName.Font.Style := [];
FlblName.ParentFont := False;
FlblName.WordWrap := False;
FlblName.Caption := RSAAboutBoxTitle1;
FlblName2.Name := 'lblName2';
FlblName2.Parent := Self;
FlblName2.Left := 54;
FlblName2.Top := 110;
FlblName2.Width := 192;
FlblName2.Height := 35;
FlblName2.Anchors := [akLeft, akTop];
{$IFDEF WIDGET_VCL}
FlblName2.Font.Charset := DEFAULT_CHARSET;
FlblName2.Transparent := True;
{$ENDIF}
FlblName2.Font.Color := clWhite;
FlblName2.Font.Height := -31;
FlblName2.Font.Name := 'Arial';
FlblName2.Font.Style := [];
FlblName2.ParentFont := False;
FlblName2.WordWrap := False;
FlblName2.Caption := RSAAboutBoxTitle2;
FlblVersion.Name := 'lblVersion';
FlblVersion.Parent := Self;
FlblVersion.Left := 300;
FlblVersion.Top := 170;
FlblVersion.Width := 200;
FlblVersion.Height := 17;
FlblVersion.Alignment := taRightJustify;
FlblVersion.AutoSize := False;
{$IFDEF WIDGET_VCL}
FlblVersion.Font.Charset := DEFAULT_CHARSET;
FlblVersion.Transparent := True;
{$ENDIF}
FlblVersion.Font.Color := 16776138; // RGBToColor(202, 251, 255)
FlblVersion.Font.Height := -15;
FlblVersion.Font.Name := 'Arial';
FlblVersion.Font.Style := [fsBold];
FlblVersion.ParentFont := False;
FlblVersion.Anchors := [akTop, akRight];
FlblBuiltFor.Name := 'lblBuiltFor';
FlblBuiltFor.Parent := Self;
FlblBuiltFor.Left := 300;
FlblBuiltFor.Top := 188;
FlblBuiltFor.Width := 200;
FlblBuiltFor.Height := 17;
FlblBuiltFor.Alignment := taRightJustify;
FlblBuiltFor.AutoSize := False;
{$IFDEF WIDGET_VCL}
FlblBuiltFor.Font.Charset := DEFAULT_CHARSET;
FlblBuiltFor.Transparent := True;
{$ENDIF}
FlblBuiltFor.Font.Color := 16776138; // RGBToColor(202, 251, 255)
FlblBuiltFor.Font.Height := -14;
FlblBuiltFor.Font.Name := 'Arial';
FlblBuiltFor.Font.Style := [];
FlblBuiltFor.ParentFont := False;
FlblBuiltFor.Anchors := [akTop, akRight];
// RLebeau: not using resouce strings for the product names because:
// 1. the names are pretty specific and not likely to change with localization;
// 2. we are trying to avoid using IFDEFs in resource units, per Embarcadero's request;
// 3. I don't want to create more product-specific resource units unless we really need them;
{$IFDEF WIDGET_KYLIX}
FlblBuiltFor.Caption := IndyFormat(RSAAboutBoxBuiltFor, ['Kylix']);
{$ELSE}
{$IFDEF WIDGET_VCL}
FlblBuiltFor.Caption := IndyFormat(RSAAboutBoxBuiltFor, ['VCL']);
{$ELSE}
{$IFDEF WIDGET_LCL}
FlblBuiltFor.Caption := IndyFormat(RSAAboutBoxBuiltFor, ['Lazarus']);
{$ELSE}
FlblBuiltFor.Caption := IndyFormat(RSAAboutBoxBuiltFor, ['Unknown']);
{$ENDIF}
{$ENDIF}
{$ENDIF}
FlblLicense.Name := 'lblLicense';
FlblLicense.Parent := Self;
FlblLicense.Left := 300;
FlblLicense.Top := 227;
FlblLicense.Width := 200;
FlblLicense.Height := 45;
FlblLicense.Alignment := taRightJustify;
FlblLicense.AutoSize := False;
{$IFDEF WIDGET_VCL}
FlblLicense.Font.Charset := DEFAULT_CHARSET;
FlblLicense.Transparent := True;
{$ENDIF}
FlblLicense.Font.Color := 16776138; // RGBToColor(202, 251, 255)
FlblLicense.Font.Height := -12;
FlblLicense.Font.Name := 'Arial';
FlblLicense.Font.Style := [];
FlblLicense.ParentFont := False;
FlblLicense.WordWrap := True;
FlblLicense.Anchors := [akTop, akRight];
FlblLicense.Caption := RSAAboutBoxLicences;
FlblCopyRight.Name := 'lblCopyRight';
FlblCopyRight.Parent := Self;
FlblCopyRight.Left := 58;
FlblCopyRight.Top := 171;
FlblCopyRight.Width := 138;
FlblCopyRight.Height := 15;
FlblCopyRight.Caption := RSAAboutBoxCopyright;
{$IFDEF WIDGET_VCL}
FlblCopyRight.Font.Charset := DEFAULT_CHARSET;
FlblCopyRight.Transparent := True;
{$ENDIF}
FlblCopyRight.Font.Color := 16776138; // RGBToColor(202, 251, 255)
FlblCopyRight.Font.Height := -12;
FlblCopyRight.Font.Name := 'Arial';
FlblCopyRight.Font.Style := [];
FlblCopyRight.ParentFont := False;
FlblCopyRight.WordWrap := True;
FlblPleaseVisitUs.Name := 'lblPleaseVisitUs';
FlblPleaseVisitUs.Parent := Self;
FlblPleaseVisitUs.Left := 58;
FlblPleaseVisitUs.Top := 278;
FlblPleaseVisitUs.Width := 276;
FlblPleaseVisitUs.Height := 15;
{$IFDEF WIDGET_VCL}
FlblPleaseVisitUs.Font.Charset := DEFAULT_CHARSET;
FlblPleaseVisitUs.Transparent := True;
{$ENDIF}
FlblPleaseVisitUs.Font.Color := 16776138; // RGBToColor(202, 251, 255)
FlblPleaseVisitUs.Font.Height := -12;
FlblPleaseVisitUs.Font.Name := 'Arial';
FlblPleaseVisitUs.ParentFont := False;
FlblPleaseVisitUs.Caption := RSAAboutBoxPleaseVisit;
FlblPleaseVisitUs.Anchors := [akLeft, akTop];
FlblURL.Name := 'lblURL';
FlblURL.Left := 58;
FlblURL.Top := 292;
FlblURL.Width := 141;
FlblURL.Height := 15;
FlblURL.Cursor := crHandPoint;
{$IFDEF WIDGET_VCL}
FlblURL.Font.Charset := DEFAULT_CHARSET;
FlblURL.Transparent := True;
{$ENDIF}
FlblURL.Font.Color := 16776138; // RGBToColor(202, 251, 255)
FlblURL.Font.Height := -12;
FlblURL.Font.Name := 'Arial';
FlblURL.ParentFont := False;
FlblURL.OnClick := lblURLClick;
FlblURL.Caption := RSAAboutBoxIndyWebsite;
FlblURL.Anchors := [akLeft, akTop];
FlblURL.Parent := Self;
FbbtnOk.Name := 'bbtnOk';
FbbtnOk.Left := 475;
{$IFDEF USE_TBitBtn}
FbbtnOk.Top := 297;
{$ELSE}
FbbtnOk.Top := 302;
FbbtnOk.Height := 25;
{$ENDIF}
FbbtnOk.Width := 75;
FbbtnOk.Anchors := [akRight, akBottom];
{$IFDEF USE_TBitBtn}
FbbtnOk.Font.Color := clBlack;
FbbtnOk.ParentFont := False;
FbbtnOk.Kind := bkOk;
{$ELSE}
FbbtnOk.Caption := RSOk;
{$ENDIF}
FbbtnOk.Cancel := True;
FbbtnOk.Default := True;
FbbtnOk.ModalResult := 1;
FbbtnOk.TabOrder := 0;
FbbtnOk.Anchors := [akLeft, akTop, akRight];
FbbtnOk.Parent := Self;
end;
function TfrmAbout.GetVersion: String;
begin
Result := FlblVersion.Caption;
end;
function TfrmAbout.GetProductName: String;
begin
Result := FlblName.Caption;
end;
function TfrmAbout.GetProductName2: String;
begin
Result := FlblName2.Caption;
end;
procedure TfrmAbout.lblURLClick(Sender: TObject);
begin
{$IFDEF WIN32_OR_WIN64}
ShellAPI.ShellExecute(Handle, nil, PChar(FlblURL.Caption), nil, nil, 0); {Do not Localize}
FlblURL.Font.Color := clPurple;
{$ENDIF}
end;
procedure TfrmAbout.SetVersion(const AValue: String);
begin
FlblVersion.Caption := AValue;
end;
procedure TfrmAbout.SetProductName(const AValue: String);
begin
FlblName.Caption := AValue;
end;
procedure TfrmAbout.SetProductName2(const AValue: String);
begin
FlblName2.Caption := AValue;
end;
class procedure TfrmAbout.ShowAboutBox(const AProductName, AProductName2, AProductVersion: String);
var
LFrm: TfrmAbout;
begin
LFrm := TfrmAbout.Create;
{$IFNDEF USE_OBJECT_ARC}
try
{$ENDIF}
LFrm.Version := IndyFormat(RSAAboutBoxVersion, [AProductVersion]);
LFrm.ProductName := AProductName;
LFrm.ProductName2 := AProductName2;
LFrm.ShowModal;
{$IFNDEF USE_OBJECT_ARC}
finally
LFrm.Free;
end;
{$ENDIF}
end;
class procedure TfrmAbout.ShowDlg;
begin
ShowAboutBox(RSAAboutBoxTitle1, RSAAboutBoxTitle2, gsIdVersion);
end;
constructor TfrmAbout.Create;
begin
Create(nil);
end;
{$IFDEF WIDGET_LCL}
initialization
{$i IdAboutVCL.lrs}
{$ENDIF}
end.

1
indy/Core/IdAboutVCL.rc Normal file
View File

@@ -0,0 +1 @@
INDY_ABOUT_BACKGROUND BITMAP AboutBackground.bmp

1469
indy/Core/IdAboutVCL.xpm Normal file

File diff suppressed because it is too large Load Diff

161
indy/Core/IdAntiFreeze.pas Normal file
View File

@@ -0,0 +1,161 @@
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.6 2004.02.03 4:16:42 PM czhower
For unit name changes.
Rev 1.5 2004.01.01 3:13:32 PM czhower
Updated comment.
Rev 1.4 2003.12.31 10:30:24 PM czhower
Comment update.
Rev 1.3 2003.12.31 7:25:14 PM czhower
Now works in .net
Rev 1.2 10/4/2003 9:52:08 AM GGrieve
add IdCoreGlobal to uses list
Rev 1.1 2003.10.01 1:12:30 AM czhower
.Net
Rev 1.0 11/13/2002 08:37:36 AM JPMugaas
}
unit IdAntiFreeze;
{
NOTE - This unit must NOT appear in any Indy uses clauses. This is a ONE way
relationship and is linked in IF the user uses this component. This is done to
preserve the isolation from the massive FORMS unit.
Because it links to Forms:
- The Application.ProcessMessages cannot be done in IdCoreGlobal as an OS
independent function, and thus this unit is allowed to violate the IFDEF
restriction.
}
interface
{$I IdCompilerDefines.inc}
uses
Classes,
IdAntiFreezeBase,
IdBaseComponent;
{ Directive needed for C++Builder HPP and OBJ files for this that will force it
to be statically compiled into the code }
{$IFDEF HAS_DIRECTIVE_HPPEMIT_LINKUNIT}
{$HPPEMIT LINKUNIT}
{$ELSE}
{$IFDEF WINDOWS}
{$HPPEMIT '#pragma link "IdAntiFreeze"'} {Do not Localize}
{$ENDIF}
{$IFDEF UNIX}
{$HPPEMIT '#pragma link "IdAntiFreeze.o"'} {Do not Localize}
{$ENDIF}
{$ENDIF}
type
{$IFDEF HAS_ComponentPlatformsAttribute}
[ComponentPlatformsAttribute(
pidWin32
{$IFDEF HAS_ComponentPlatformsAttribute_Win32} or pidWin32{$ENDIF}
{$IFDEF HAS_ComponentPlatformsAttribute_Win64} or pidWin64{$ENDIF}
{$IFDEF HAS_ComponentPlatformsAttribute_OSX32} or pidOSX32{$ENDIF}
{$IFDEF HAS_ComponentPlatformsAttribute_iOS_Simulator} or pidiOSSimulator{$ENDIF}
{$IFDEF HAS_ComponentPlatformsAttribute_Android} or pidAndroid{$ENDIF}
{$IFDEF HAS_ComponentPlatformsAttribute_Linux32} or pidLinux32{$ENDIF}
{$IFDEF HAS_ComponentPlatformsAttribute_iOS_Device32} or pidiOSDevice32{$ELSE}
{$IFDEF HAS_ComponentPlatformsAttribute_iOS_Device} or pidiOSDevice{$ENDIF}{$ENDIF}
{$IFDEF HAS_ComponentPlatformsAttribute_WinNX32} or pidWinNX32{$ENDIF}
{$IFDEF HAS_ComponentPlatformsAttribute_Linux64} or pidLinux64{$ENDIF}
{$IFDEF HAS_ComponentPlatformsAttribute_WinIoT32} or pidWinIoT32{$ENDIF}
{$IFDEF HAS_ComponentPlatformsAttribute_iOS_Device64} or pidiOSDevice64{$ENDIF}
)]
{$ENDIF}
TIdAntiFreeze = class(TIdAntiFreezeBase)
public
procedure Process; override;
end;
implementation
uses
{$IFDEF WIDGET_KYLIX}
QForms,
{$ENDIF}
{$IFDEF WIDGET_VCL_LIKE}
Forms,
{$ENDIF}
{$IFDEF WINDOWS}
{$IFNDEF FMX}
Messages,
Windows,
{$ENDIF}
{$ENDIF}
{$IFDEF WIDGET_WINFORMS}
System.Windows.Forms,
{$ENDIF}
IdGlobal;
{$IFDEF UNIX}
procedure TIdAntiFreeze.Process;
begin
//TODO: Handle ApplicationHasPriority
Application.ProcessMessages;
end;
{$ENDIF}
{$IFDEF WINDOWS}
{$IFNDEF FMX}
procedure TIdAntiFreeze.Process;
var
LMsg: TMsg;
begin
if ApplicationHasPriority then begin
Application.ProcessMessages;
end else begin
// This guarantees it will not ever call Application.Idle
if PeekMessage(LMsg, 0, 0, 0, PM_NOREMOVE) then begin
Application.HandleMessage;
end;
end;
end;
{$ELSE}
procedure TIdAntiFreeze.Process;
begin
//TODO: Handle ApplicationHasPriority
Application.ProcessMessages;
end;
{$ENDIF}
{$ENDIF}
{$IFDEF WIDGET_WINFORMS}
procedure TIdAntiFreeze.Process;
begin
//TODO: Handle ApplicationHasPriority
Application.DoEvents;
end;
{$ENDIF}
end.

File diff suppressed because it is too large Load Diff

1030
indy/Core/IdBuffer.pas Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,305 @@
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.18 2/8/05 5:24:48 PM RLebeau
Updated Disconnect() to not wait for the listening thread to terminate until
after the inherited Disconnect() is called, so that the socket is actually
disconnected and the thread can terminate properly.
Rev 1.17 2/1/05 12:38:30 AM RLebeau
Removed unused CommandHandlersEnabled property
Rev 1.16 6/11/2004 8:48:16 AM DSiders
Added "Do not Localize" comments.
Rev 1.15 5/18/04 9:12:26 AM RLebeau
Bug fix for SetExceptionReply() property setter
Rev 1.14 5/16/04 5:18:04 PM RLebeau
Added setter method to ExceptionReply property
Rev 1.13 5/10/2004 6:10:38 PM DSiders
Removed unused member var FCommandHandlersInitialized.
Rev 1.12 2004.03.06 1:33:00 PM czhower
-Change to disconnect
-Addition of DisconnectNotifyPeer
-WriteHeader now write bufers
Rev 1.11 2004.03.01 5:12:24 PM czhower
-Bug fix for shutdown of servers when connections still existed (AV)
-Implicit HELP support in CMDserver
-Several command handler bugs
-Additional command handler functionality.
Rev 1.10 2004.02.03 4:17:10 PM czhower
For unit name changes.
Rev 1.9 2004.01.20 10:03:22 PM czhower
InitComponent
Rev 1.8 1/4/04 8:46:16 PM RLebeau
Added OnBeforeCommandHandler and OnAfterCommandHandler events
Rev 1.7 11/4/2003 10:25:40 PM DSiders
Removed duplicate FReplyClass member in TIdCmdTCPClient (See
TIdTCPConnection).
Rev 1.6 10/21/2003 10:54:20 AM JPMugaas
Fix for new API change.
Rev 1.5 2003.10.18 9:33:24 PM czhower
Boatload of bug fixes to command handlers.
Rev 1.4 2003.10.02 10:16:26 AM czhower
.Net
Rev 1.3 2003.09.19 11:54:26 AM czhower
-Completed more features necessary for servers
-Fixed some bugs
Rev 1.2 7/9/2003 10:55:24 PM BGooijen
Restored all features
Rev 1.1 7/9/2003 04:36:06 PM JPMugaas
You now can override the TIdReply with your own type. This should illiminate
some warnings about some serious issues. TIdReply is ONLY a base class with
virtual methods.
Rev 1.0 7/7/2003 7:06:40 PM SPerry
Component that uses command handlers
Rev 1.0 7/6/2003 4:47:26 PM SPerry
Units that use Command handlers
}
unit IdCmdTCPClient;
{
Original author: Sergio Perry
Description: TCP client that uses CommandHandlers
}
interface
{$I IdCompilerDefines.inc}
uses
IdContext,
IdException,
IdGlobal,
IdReply,
IdResourceStringsCore,
IdThread,
IdTCPClient,
IdCommandHandlers;
type
TIdCmdTCPClient = class;
{ Events }
TIdCmdTCPClientAfterCommandHandlerEvent = procedure(ASender: TIdCmdTCPClient;
AContext: TIdContext) of object;
TIdCmdTCPClientBeforeCommandHandlerEvent = procedure(ASender: TIdCmdTCPClient;
var AData: string; AContext: TIdContext) of object;
{ Listening Thread }
TIdCmdClientContext = class(TIdContext)
protected
FClient: TIdCmdTCPClient;
public
property Client: TIdCmdTCPClient read FClient;
end;
TIdCmdTCPClientListeningThread = class(TIdThread)
protected
FContext: TIdCmdClientContext;
FClient: TIdCmdTCPClient;
FRecvData: String;
//
procedure Run; override;
public
constructor Create(AClient: TIdCmdTCPClient); reintroduce;
destructor Destroy; override;
//
property Client: TIdCmdTCPClient read FClient;
property RecvData: String read FRecvData write FRecvData;
end;
{ TIdCmdTCPClient }
TIdCmdTCPClient = class(TIdTCPClient)
protected
FExceptionReply: TIdReply;
FListeningThread: TIdCmdTCPClientListeningThread;
FCommandHandlers: TIdCommandHandlers;
FOnAfterCommandHandler: TIdCmdTCPClientAfterCommandHandlerEvent;
FOnBeforeCommandHandler: TIdCmdTCPClientBeforeCommandHandlerEvent;
//
procedure DoAfterCommandHandler(ASender: TIdCommandHandlers; AContext: TIdContext);
procedure DoBeforeCommandHandler(ASender: TIdCommandHandlers; var AData: string;
AContext: TIdContext);
procedure DoReplyUnknownCommand(AContext: TIdContext; ALine: string); virtual;
function GetCmdHandlerClass: TIdCommandHandlerClass; virtual;
procedure InitComponent; override;
procedure SetCommandHandlers(AValue: TIdCommandHandlers);
procedure SetExceptionReply(AValue: TIdReply);
public
procedure Connect; override;
destructor Destroy; override;
procedure Disconnect(ANotifyPeer: Boolean); override;
published
property CommandHandlers: TIdCommandHandlers read FCommandHandlers write SetCommandHandlers;
property ExceptionReply: TIdReply read FExceptionReply write SetExceptionReply;
//
property OnAfterCommandHandler: TIdCmdTCPClientAfterCommandHandlerEvent
read FOnAfterCommandHandler write FOnAfterCommandHandler;
property OnBeforeCommandHandler: TIdCmdTCPClientBeforeCommandHandlerEvent
read FOnBeforeCommandHandler write FOnBeforeCommandHandler;
end;
EIdCmdTCPClientError = class(EIdException);
EIdCmdTCPClientConnectError = class(EIdCmdTCPClientError);
implementation
uses
IdReplyRFC, SysUtils;
type
TIdCmdClientContextAccess = class(TIdCmdClientContext)
end;
{ Listening Thread }
constructor TIdCmdTCPClientListeningThread.Create(AClient: TIdCmdTCPClient);
begin
FClient := AClient;
FContext := TIdCmdClientContext.Create(AClient, nil, nil);
FContext.FClient := AClient;
TIdCmdClientContextAccess(FContext).FOwnsConnection := False;
//
inherited Create(False);
end;
destructor TIdCmdTCPClientListeningThread.Destroy;
begin
inherited Destroy;
FreeAndNil(FContext);
end;
procedure TIdCmdTCPClientListeningThread.Run;
begin
FRecvData := FClient.IOHandler.ReadLn;
if not FClient.CommandHandlers.HandleCommand(FContext, FRecvData) then begin
FClient.DoReplyUnknownCommand(FContext, FRecvData);
end;
//Synchronize(?);
if not Terminated then begin
FClient.IOHandler.CheckForDisconnect;
end;
end;
{ TIdCmdTCPClient }
destructor TIdCmdTCPClient.Destroy;
begin
Disconnect;
FreeAndNil(FExceptionReply);
FreeAndNil(FCommandHandlers);
inherited Destroy;
end;
procedure TIdCmdTCPClient.Connect;
begin
inherited Connect;
//
try
FListeningThread := TIdCmdTCPClientListeningThread.Create(Self);
except
Disconnect(True);
IndyRaiseOuterException(EIdCmdTCPClientConnectError.Create(RSNoCreateListeningThread));
end;
end;
procedure TIdCmdTCPClient.Disconnect(ANotifyPeer: Boolean);
begin
if Assigned(FListeningThread) then begin
FListeningThread.Terminate;
end;
try
inherited Disconnect(ANotifyPeer);
finally
if Assigned(FListeningThread) and not IsCurrentThread(FListeningThread) then begin
FListeningThread.WaitFor;
FreeAndNil(FListeningThread);
end;
end;
end;
procedure TIdCmdTCPClient.DoAfterCommandHandler(ASender: TIdCommandHandlers;
AContext: TIdContext);
begin
if Assigned(OnAfterCommandHandler) then begin
OnAfterCommandHandler(Self, AContext);
end;
end;
procedure TIdCmdTCPClient.DoBeforeCommandHandler(ASender: TIdCommandHandlers;
var AData: string; AContext: TIdContext);
begin
if Assigned(OnBeforeCommandHandler) then begin
OnBeforeCommandHandler(Self, AData, AContext);
end;
end;
procedure TIdCmdTCPClient.DoReplyUnknownCommand(AContext: TIdContext; ALine: string);
begin
end;
function TIdCmdTCPClient.GetCmdHandlerClass: TIdCommandHandlerClass;
begin
Result := TIdCommandHandler;
end;
procedure TIdCmdTCPClient.InitComponent;
var
LHandlerClass: TIdCommandHandlerClass;
begin
inherited InitComponent;
FExceptionReply := FReplyClass.Create(nil);
ExceptionReply.SetReply(500, 'Unknown Internal Error'); {do not localize}
LHandlerClass := GetCmdHandlerClass;
FCommandHandlers := TIdCommandHandlers.Create(Self, FReplyClass, nil, ExceptionReply, LHandlerClass);
FCommandHandlers.OnAfterCommandHandler := DoAfterCommandHandler;
FCommandHandlers.OnBeforeCommandHandler := DoBeforeCommandHandler;
end;
procedure TIdCmdTCPClient.SetCommandHandlers(AValue: TIdCommandHandlers);
begin
FCommandHandlers.Assign(AValue);
end;
procedure TIdCmdTCPClient.SetExceptionReply(AValue: TIdReply);
begin
FExceptionReply.Assign(AValue);
end;
end.

View File

@@ -0,0 +1,535 @@
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.42 2/1/05 12:36:36 AM RLebeau
Removed CommandHandlersEnabled property, no longer used
Rev 1.41 12/2/2004 9:26:42 PM JPMugaas
Bug fix.
Rev 1.40 2004.10.27 9:20:04 AM czhower
For TIdStrings
Rev 1.39 10/26/2004 8:42:58 PM JPMugaas
Should be more portable with new references to TIdStrings and TIdStringList.
Rev 1.38 6/21/04 10:07:14 PM RLebeau
Updated .DoConnect() to make sure the connection is still connected before
then sending the Greeting
Rev 1.37 6/20/2004 12:01:44 AM DSiders
Added "Do Not Localize" comments.
Rev 1.36 6/16/04 12:37:06 PM RLebeau
more compiler errors
Rev 1.35 6/16/04 12:30:32 PM RLebeau
compiler errors
Rev 1.34 6/16/04 12:12:26 PM RLebeau
Updated ExceptionReply, Greeting, HelpReply, MaxConnectionReply, and
ReplyUnknownCommand properties to use getter methods that call virtual Create
methods which descendants can override for class-specific initializations
Rev 1.33 5/16/04 5:16:52 PM RLebeau
Added setter methods to ExceptionReply, HelpReply, and ReplyTexts properties
Rev 1.32 4/19/2004 5:39:58 PM BGooijen
Added comment
Rev 1.31 4/18/2004 11:58:44 PM BGooijen
Wasn't thread safe
Rev 1.30 3/3/2004 4:59:38 AM JPMugaas
Updated for new properties.
Rev 1.29 2004.03.01 5:12:24 PM czhower
-Bug fix for shutdown of servers when connections still existed (AV)
-Implicit HELP support in CMDserver
-Several command handler bugs
-Additional command handler functionality.
Rev 1.28 2004.02.29 9:43:08 PM czhower
Added ReadCommandLine.
Rev 1.27 2004.02.29 8:17:18 PM czhower
Minor cosmetic changes to code.
Rev 1.26 2004.02.03 4:17:08 PM czhower
For unit name changes.
Rev 1.25 03/02/2004 01:49:22 CCostelloe
Added DoReplyUnknownCommand to allow TIdIMAP4Server set a correct reply for
unknown commands
Rev 1.24 1/29/04 9:43:16 PM RLebeau
Added setter methods to various TIdReply properties
Rev 1.23 2004.01.20 10:03:22 PM czhower
InitComponent
Rev 1.22 1/5/2004 2:35:36 PM JPMugaas
Removed of object in method declarations.
Rev 1.21 1/5/04 10:12:58 AM RLebeau
Fixed Typos in OnBeforeCommandHandler and OnAfterCommandHandler events
Rev 1.20 1/4/04 8:45:34 PM RLebeau
Added OnBeforeCommandHandler and OnAfterCommandHandler events
Rev 1.19 1/1/2004 9:33:22 PM BGooijen
the abstract class TIdReply was created sometimes, fixed that
Rev 1.18 2003.10.18 9:33:26 PM czhower
Boatload of bug fixes to command handlers.
Rev 1.17 2003.10.18 8:03:58 PM czhower
Defaults for codes
Rev 1.16 8/31/2003 11:49:40 AM BGooijen
removed FReplyClass, this was also in TIdTCPServer
Rev 1.15 7/9/2003 10:55:24 PM BGooijen
Restored all features
Rev 1.14 7/9/2003 04:36:08 PM JPMugaas
You now can override the TIdReply with your own type. This should illiminate
some warnings about some serious issues. TIdReply is ONLY a base class with
virtual methods.
Rev 1.13 2003.07.08 2:26:02 PM czhower
Sergio's update
Rev 1.0 7/7/2003 7:06:44 PM SPerry
Component that uses command handlers
Rev 1.0 7/6/2003 4:47:32 PM SPerry
Units that use Command handlers
Adapted to IdCommandHandlers.pas SPerry
Rev 1.7 4/4/2003 8:08:00 PM BGooijen
moved some consts from tidtcpserver here
Rev 1.6 3/23/2003 11:22:24 PM BGooijen
Moved some code to HandleCommand
Rev 1.5 3/22/2003 1:46:36 PM BGooijen
Removed unused variables
Rev 1.4 3/20/2003 12:18:30 PM BGooijen
Moved ReplyExceptionCode from TIdTCPServer to TIdCmdTCPServer
Rev 1.3 3/20/2003 12:14:18 PM BGooijen
Re-enabled Server.ReplyException
Rev 1.2 2/24/2003 07:21:50 PM JPMugaas
Now compiles with new core code restructures.
Rev 1.1 1/23/2003 11:06:10 AM BGooijen
Rev 1.0 1/20/2003 12:48:40 PM BGooijen
Tcpserver with command handlers, these were originally in TIdTcpServer, but
are now moved here
}
unit IdCmdTCPServer;
interface
{$I IdCompilerDefines.inc}
//Put FPC into Delphi mode
uses
Classes,
IdCommandHandlers,
IdContext,
IdIOHandler,
IdReply,
IdTCPServer,
SysUtils;
type
TIdCmdTCPServer = class;
{ Events }
TIdCmdTCPServerAfterCommandHandlerEvent = procedure(ASender: TIdCmdTCPServer;
AContext: TIdContext) of object;
TIdCmdTCPServerBeforeCommandHandlerEvent = procedure(ASender: TIdCmdTCPServer;
var AData: string; AContext: TIdContext) of object;
TIdCmdTCPServer = class(TIdTCPServer)
protected
FCommandHandlers: TIdCommandHandlers;
FCommandHandlersInitialized: Boolean;
FExceptionReply: TIdReply;
FHelpReply: TIdReply;
FGreeting: TIdReply;
FMaxConnectionReply: TIdReply;
FOnAfterCommandHandler: TIdCmdTCPServerAfterCommandHandlerEvent;
FOnBeforeCommandHandler: TIdCmdTCPServerBeforeCommandHandlerEvent;
FReplyClass: TIdReplyClass;
FReplyTexts: TIdReplies;
FReplyUnknownCommand: TIdReply;
//
procedure CheckOkToBeActive; override;
function CreateExceptionReply: TIdReply; virtual;
function CreateGreeting: TIdReply; virtual;
function CreateHelpReply: TIdReply; virtual;
function CreateMaxConnectionReply: TIdReply; virtual;
function CreateReplyUnknownCommand: TIdReply; virtual;
procedure DoAfterCommandHandler(ASender: TIdCommandHandlers; AContext: TIdContext);
procedure DoBeforeCommandHandler(ASender: TIdCommandHandlers; var AData: string;
AContext: TIdContext);
procedure DoConnect(AContext: TIdContext); override;
function DoExecute(AContext: TIdContext): Boolean; override;
procedure DoMaxConnectionsExceeded(AIOHandler: TIdIOHandler); override;
// This is here to allow servers to override this functionality, such as IMAP4 server
procedure DoReplyUnknownCommand(AContext: TIdContext; ALine: string); virtual;
function GetExceptionReply: TIdReply;
function GetGreeting: TIdReply;
function GetHelpReply: TIdReply;
function GetMaxConnectionReply: TIdReply;
function GetRepliesClass: TIdRepliesClass; virtual;
function GetReplyClass: TIdReplyClass; virtual;
function GetReplyUnknownCommand: TIdReply;
procedure InitializeCommandHandlers; virtual;
procedure InitComponent; override;
// This is used by command handlers as the only input. This can be overriden to filter, modify,
// or preparse the input.
function ReadCommandLine(AContext: TIdContext): string; virtual;
procedure Startup; override;
procedure SetCommandHandlers(AValue: TIdCommandHandlers);
procedure SetExceptionReply(AValue: TIdReply);
procedure SetGreeting(AValue: TIdReply);
procedure SetHelpReply(AValue: TIdReply);
procedure SetMaxConnectionReply(AValue: TIdReply);
procedure SetReplyUnknownCommand(AValue: TIdReply);
procedure SetReplyTexts(AValue: TIdReplies);
public
destructor Destroy; override;
published
property CommandHandlers: TIdCommandHandlers read FCommandHandlers
write SetCommandHandlers;
property ExceptionReply: TIdReply read GetExceptionReply write SetExceptionReply;
property Greeting: TIdReply read GetGreeting write SetGreeting;
property HelpReply: TIdReply read GetHelpReply write SetHelpReply;
property MaxConnectionReply: TIdReply read GetMaxConnectionReply
write SetMaxConnectionReply;
property ReplyTexts: TIdReplies read FReplyTexts write SetReplyTexts;
property ReplyUnknownCommand: TIdReply read GetReplyUnknownCommand
write SetReplyUnknownCommand;
//
property OnAfterCommandHandler: TIdCmdTCPServerAfterCommandHandlerEvent
read FOnAfterCommandHandler write FOnAfterCommandHandler;
property OnBeforeCommandHandler: TIdCmdTCPServerBeforeCommandHandlerEvent
read FOnBeforeCommandHandler write FOnBeforeCommandHandler;
end;
implementation
uses
IdGlobal,
IdResourceStringsCore,
IdReplyRFC;
function TIdCmdTCPServer.GetReplyClass: TIdReplyClass;
begin
Result := TIdReplyRFC;
end;
function TIdCmdTCPServer.GetRepliesClass: TIdRepliesClass;
begin
Result := TIdRepliesRFC;
end;
destructor TIdCmdTCPServer.Destroy;
begin
inherited Destroy;
FreeAndNil(FReplyUnknownCommand);
FreeAndNil(FReplyTexts);
FreeAndNil(FMaxConnectionReply);
FreeAndNil(FHelpReply);
FreeAndNil(FGreeting);
FreeAndNil(FExceptionReply);
FreeAndNil(FCommandHandlers);
end;
procedure TIdCmdTCPServer.DoAfterCommandHandler(ASender: TIdCommandHandlers;
AContext: TIdContext);
begin
if Assigned(OnAfterCommandHandler) then begin
OnAfterCommandHandler(Self, AContext);
end;
end;
procedure TIdCmdTCPServer.DoBeforeCommandHandler(ASender: TIdCommandHandlers;
var AData: string; AContext: TIdContext);
begin
if Assigned(OnBeforeCommandHandler) then begin
OnBeforeCommandHandler(Self, AData, AContext);
end;
end;
function TIdCmdTCPServer.DoExecute(AContext: TIdContext): Boolean;
var
LLine: string;
begin
if CommandHandlers.Count > 0 then begin
Result := True;
if AContext.Connection.Connected then begin
LLine := ReadCommandLine(AContext);
// OLX sends blank lines during reset groups (NNTP) and expects no response.
// Not sure what the RFCs say about blank lines.
// I telnetted to some newsservers, and they dont respond to blank lines.
// This unit is core and not NNTP, but we should be consistent.
if LLine <> '' then begin
if not FCommandHandlers.HandleCommand(AContext, LLine) then begin
DoReplyUnknownCommand(AContext, LLine);
end;
end;
end;
end else begin
Result := inherited DoExecute(AContext);
end;
if Result and Assigned(AContext.Connection) then begin
Result := AContext.Connection.Connected;
end;
// the return value is used to determine if the DoExecute needs to be called again by the thread
end;
procedure TIdCmdTCPServer.DoReplyUnknownCommand(AContext: TIdContext; ALine: string);
var
LReply: TIdReply;
begin
if CommandHandlers.PerformReplies then begin
LReply := FReplyClass.CreateWithReplyTexts(nil, ReplyTexts); try
LReply.Assign(ReplyUnknownCommand);
LReply.Text.Add(ALine);
AContext.Connection.IOHandler.Write(LReply.FormattedReply);
finally
FreeAndNil(LReply);
end;
end;
end;
procedure TIdCmdTCPServer.InitializeCommandHandlers;
begin
end;
procedure TIdCmdTCPServer.DoConnect(AContext: TIdContext);
var
LGreeting: TIdReply;
begin
inherited DoConnect(AContext);
// RLebeau - check the connection first in case the application
// chose to disconnect the connection in the OnConnect event handler.
if AContext.Connection.Connected then begin
if Greeting.ReplyExists then begin
ReplyTexts.UpdateText(Greeting);
LGreeting := FReplyClass.Create(nil); try // SendGreeting calls TIdReply.GetFormattedReply
LGreeting.Assign(Greeting); // and that changes the reply object, so we have to
SendGreeting(AContext, LGreeting); // clone it to make it thread-safe
finally
FreeAndNil(LGreeting);
end;
end;
end;
end;
procedure TIdCmdTCPServer.DoMaxConnectionsExceeded(AIOHandler: TIdIOHandler);
begin
inherited DoMaxConnectionsExceeded(AIOHandler);
//Do not UpdateText here - in thread. Is done in constructor
AIOHandler.Write(MaxConnectionReply.FormattedReply);
end;
procedure TIdCmdTCPServer.Startup;
var
i, j: Integer;
LDescr: TStrings;
LHelpList: TStringList;
LHandler, LAddedHandler: TIdCommandHandler;
begin
inherited Startup;
if not FCommandHandlersInitialized then begin
// InitializeCommandHandlers must be called only at runtime, and only after streaming
// has occured. This used to be in .Loaded and that worked for forms. It failed
// for dynamically created instances and also for descendant classes.
FCommandHandlersInitialized := True;
InitializeCommandHandlers;
if HelpReply.Code <> '' then begin
LAddedHandler := CommandHandlers.Add;
LAddedHandler.Command := 'Help'; {do not localize}
LAddedHandler.Description.Text := 'Displays commands that the servers supports.'; {do not localize}
LAddedHandler.NormalReply.Assign(HelpReply);
LHelpList := TStringList.Create;
try
for i := 0 to CommandHandlers.Count - 1 do begin
LHandler := CommandHandlers.Items[i];
if LHandler.HelpVisible then begin
LHelpList.AddObject(LHandler.Command+LHandler.HelpSuperScript, LHandler);
end;
end;
LHelpList.Sort;
for i := 0 to LHelpList.Count - 1 do begin
LAddedHandler.Response.Add(LHelpList[i]);
LDescr := TIdCommandHandler(LHelpList.Objects[i]).Description;
for j := 0 to LDescr.Count - 1 do begin
LAddedHandler.Response.Add(' ' + LDescr[j]); {do not localize}
end;
LAddedHandler.Response.Add(''); {do not localize}
end;
finally
FreeAndNil(LHelpList);
end;
end;
end;
end;
procedure TIdCmdTCPServer.SetCommandHandlers(AValue: TIdCommandHandlers);
begin
FCommandHandlers.Assign(AValue);
end;
function TIdCmdTCPServer.CreateExceptionReply: TIdReply;
begin
Result := FReplyClass.CreateWithReplyTexts(nil, ReplyTexts);
Result.SetReply(500, 'Unknown Internal Error'); {do not localize}
end;
function TIdCmdTCPServer.GetExceptionReply: TIdReply;
begin
if FExceptionReply = nil then begin
FExceptionReply := CreateExceptionReply;
end;
Result := FExceptionReply;
end;
procedure TIdCmdTCPServer.SetExceptionReply(AValue: TIdReply);
begin
ExceptionReply.Assign(AValue);
end;
function TIdCmdTCPServer.CreateGreeting: TIdReply;
begin
Result := FReplyClass.CreateWithReplyTexts(nil, ReplyTexts);
Result.SetReply(200, 'Welcome'); {do not localize}
end;
function TIdCmdTCPServer.GetGreeting: TIdReply;
begin
if FGreeting = nil then begin
FGreeting := CreateGreeting;
end;
Result := FGreeting;
end;
procedure TIdCmdTCPServer.SetGreeting(AValue: TIdReply);
begin
Greeting.Assign(AValue);
end;
function TIdCmdTCPServer.CreateHelpReply: TIdReply;
begin
Result := FReplyClass.CreateWithReplyTexts(nil, ReplyTexts);
Result.SetReply(100, 'Help follows'); {do not localize}
end;
function TIdCmdTCPServer.GetHelpReply: TIdReply;
begin
if FHelpReply = nil then begin
FHelpReply := CreateHelpReply;
end;
Result := FHelpReply;
end;
procedure TIdCmdTCPServer.SetHelpReply(AValue: TIdReply);
begin
HelpReply.Assign(AValue);
end;
function TIdCmdTCPServer.CreateMaxConnectionReply: TIdReply;
begin
Result := FReplyClass.CreateWithReplyTexts(nil, ReplyTexts);
Result.SetReply(300, 'Too many connections. Try again later.'); {do not localize}
end;
function TIdCmdTCPServer.GetMaxConnectionReply: TIdReply;
begin
if FMaxConnectionReply = nil then begin
FMaxConnectionReply := CreateMaxConnectionReply;
end;
Result := FMaxConnectionReply;
end;
procedure TIdCmdTCPServer.SetMaxConnectionReply(AValue: TIdReply);
begin
MaxConnectionReply.Assign(AValue);
end;
function TIdCmdTCPServer.CreateReplyUnknownCommand: TIdReply;
begin
Result := FReplyClass.CreateWithReplyTexts(nil, ReplyTexts);
Result.SetReply(400, 'Unknown Command'); {do not localize}
end;
function TIdCmdTCPServer.GetReplyUnknownCommand: TIdReply;
begin
if FReplyUnknownCommand = nil then begin
FReplyUnknownCommand := CreateReplyUnknownCommand;
end;
Result := FReplyUnknownCommand;
end;
procedure TIdCmdTCPServer.SetReplyUnknownCommand(AValue: TIdReply);
begin
ReplyUnknownCommand.Assign(AValue);
end;
procedure TIdCmdTCPServer.SetReplyTexts(AValue: TIdReplies);
begin
FReplyTexts.Assign(AValue);
end;
procedure TIdCmdTCPServer.InitComponent;
begin
inherited InitComponent;
FReplyClass := GetReplyClass;
// Before Command handlers as they need FReplyTexts, but after FReplyClass is set
FReplyTexts := GetRepliesClass.Create(Self, FReplyClass);
FCommandHandlers := TIdCommandHandlers.Create(Self, FReplyClass, ReplyTexts, ExceptionReply);
FCommandHandlers.OnAfterCommandHandler := DoAfterCommandHandler;
FCommandHandlers.OnBeforeCommandHandler := DoBeforeCommandHandler;
end;
function TIdCmdTCPServer.ReadCommandLine(AContext: TIdContext): string;
begin
Result := AContext.Connection.IOHandler.ReadLn;
end;
procedure TIdCmdTCPServer.CheckOkToBeActive;
begin
if (CommandHandlers.Count = 0) and FCommandHandlersInitialized then begin
inherited CheckOkToBeActive;
end;
end;
end.

View File

@@ -0,0 +1,682 @@
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.36 2/1/05 12:37:48 AM RLebeau
Removed IdCommandHandlersEnabledDefault variable, no longer used.
Rev 1.35 1/3/05 4:43:20 PM RLebeau
Changed use of AnsiSameText() to use TextIsSame() instead
Rev 1.34 12/17/04 12:54:04 PM RLebeau
Updated TIdCommandHandler.Check() to not match misspelled commands when a
CmdDelimiter is specified.
Rev 1.33 12/10/04 1:48:04 PM RLebeau
Bug fix for TIdCommandHandler.DoCommand()
Rev 1.32 10/26/2004 8:42:58 PM JPMugaas
Should be more portable with new references to TIdStrings and TIdStringList.
Rev 1.31 6/17/2004 2:19:50 AM JPMugaas
Problem with unparsed parameters. The initial deliniator between the command
and reply was being added to Unparsed Params leading some strange results and
command failures.
Rev 1.30 6/6/2004 11:44:34 AM JPMugaas
Removed a temporary workaround for a Telnet Sequences issue in the
TIdFTPServer. That workaround is no longer needed as we fixed the issue
another way.
Rev 1.29 5/16/04 5:20:22 PM RLebeau
Removed local variable from TIdCommandHandler constructor, no longer used
Rev 1.28 2004.03.03 3:19:52 PM czhower
sorted
Rev 1.27 3/3/2004 4:59:40 AM JPMugaas
Updated for new properties.
Rev 1.26 3/2/2004 8:10:36 AM JPMugaas
HelpHide renamed to HelpVisable.
Rev 1.25 3/2/2004 6:37:36 AM JPMugaas
Updated with properties for more comprehensive help systems.
Rev 1.24 2004.03.01 7:13:40 PM czhower
Comaptibilty fix.
Rev 1.23 2004.03.01 5:12:26 PM czhower
-Bug fix for shutdown of servers when connections still existed (AV)
-Implicit HELP support in CMDserver
-Several command handler bugs
-Additional command handler functionality.
Rev 1.22 2004.02.29 9:49:06 PM czhower
Bug fix, and now responses are also write buffered.
Rev 1.21 2004.02.03 4:17:10 PM czhower
For unit name changes.
Rev 1.20 1/29/04 10:00:40 PM RLebeau
Added setter methods to various TIdReply properties
Rev 1.19 2003.12.31 7:31:58 PM czhower
AnsiSameText --> TextIsSame
Rev 1.18 10/19/2003 11:36:52 AM DSiders
Added localization comments where setting response codes.
Rev 1.17 2003.10.18 9:33:26 PM czhower
Boatload of bug fixes to command handlers.
Rev 1.16 2003.10.18 8:07:12 PM czhower
Fixed bug with defaults.
Rev 1.15 2003.10.18 8:03:58 PM czhower
Defaults for codes
Rev 1.14 10/5/2003 03:06:18 AM JPMugaas
Should compile.
Rev 1.13 8/9/2003 3:52:44 PM BGooijen
TIdCommandHandlers can now create any TIdCommandHandler descendant. this
makes it possible to override TIdCommandHandler.check and check for the
command a different way ( binary commands, protocols where the string doesn't
start with the command )
Rev 1.12 8/2/2003 2:22:54 PM SPerry
Fixed OnCommandHandlersException problem
Rev 1.11 8/2/2003 1:43:08 PM SPerry
Modifications to get command handlers to work
Rev 1.9 7/30/2003 10:18:30 PM SPerry
Fixed AV when creating commandhandler (again) -- for some reason the bug
fixed in Rev. 1.7 was still there.
Rev 1.8 7/30/2003 8:31:58 PM SPerry
Fixed AV with LFReplyClass.
Rev 1.4 7/9/2003 10:55:26 PM BGooijen
Restored all features
Rev 1.3 7/9/2003 04:36:10 PM JPMugaas
You now can override the TIdReply with your own type. This should illiminate
some warnings about some serious issues. TIdReply is ONLY a base class with
virtual methods.
Rev 1.2 7/9/2003 01:43:22 PM JPMugaas
Should now compile.
Rev 1.1 7/9/2003 2:56:44 PM SPerry
Added OnException event
Rev 1.0 7/6/2003 4:47:38 PM SPerry
Units that use Command handlers
}
unit IdCommandHandlers;
{
Original author: Chad Z. Hower
Separate Unit : Sergio Perry
}
interface
{$I IdCompilerDefines.inc}
//Put FPC into Delphi mode
uses
Classes,
IdBaseComponent, IdComponent, IdReply, IdGlobal,
IdContext, IdReplyRFC;
const
IdEnabledDefault = True;
// DO NOT change this default (ParseParams). Many servers rely on this
IdParseParamsDefault = True;
IdHelpVisibleDef = True;
type
TIdCommandHandlers = class;
TIdCommandHandler = class;
TIdCommand = class;
{ Events }
TIdCommandEvent = procedure(ASender: TIdCommand) of object;
TIdAfterCommandHandlerEvent = procedure(ASender: TIdCommandHandlers;
AContext: TIdContext) of object;
TIdBeforeCommandHandlerEvent = procedure(ASender: TIdCommandHandlers;
var AData: string; AContext: TIdContext) of object;
TIdCommandHandlersExceptionEvent = procedure(ACommand: String; AContext: TIdContext) of object;
{ TIdCommandHandler }
TIdCommandHandler = class(TCollectionItem)
protected
FCmdDelimiter: Char;
FCommand: string;
{$IFDEF USE_OBJECT_ARC}
// When ARC is enabled, object references MUST be valid objects.
// It is common for users to store non-object values, though, so
// we will provide separate properties for those purposes
//
// TODO; use TValue instead of separating them
//
FDataObject: TObject;
FDataValue: PtrInt;
{$ELSE}
FData: TObject;
{$ENDIF}
FDescription: TStrings;
FDisconnect: boolean;
FEnabled: boolean;
FExceptionReply: TIdReply;
FHelpSuperScript : String; //may be something like * or + which should appear in help
FHelpVisible : Boolean;
FName: string;
FNormalReply: TIdReply;
FOnCommand: TIdCommandEvent;
FParamDelimiter: Char;
FParseParams: Boolean;
FReplyClass : TIdReplyClass;
FResponse: TStrings;
FTag: integer;
//
function GetDisplayName: string; override;
procedure SetDescription(AValue: TStrings);
procedure SetExceptionReply(AValue: TIdReply);
procedure SetNormalReply(AValue: TIdReply);
procedure SetResponse(AValue: TStrings);
public
function Check(const AData: string; AContext: TIdContext): boolean; virtual;
procedure DoCommand(const AData: string; AContext: TIdContext; AUnparsedParams: string); virtual;
procedure DoParseParams(AUnparsedParams: string; AParams: TStrings); virtual;
constructor Create(ACollection: TCollection); override;
destructor Destroy; override;
// function GetNamePath: string; override;
function NameIs(const ACommand: string): Boolean;
//
{$IFDEF USE_OBJECT_ARC}
property DataObject: TObject read FDataObject write FDataObject;
property DataValue: PtrInt read FDataValue write FDataValue;
{$ELSE}
property Data: TObject read FData write FData;
{$ENDIF}
published
property CmdDelimiter: Char read FCmdDelimiter write FCmdDelimiter;
property Command: string read FCommand write FCommand;
property Description: TStrings read FDescription write SetDescription;
property Disconnect: boolean read FDisconnect write FDisconnect;
property Enabled: boolean read FEnabled write FEnabled default IdEnabledDefault;
property ExceptionReply: TIdReply read FExceptionReply write SetExceptionReply;
property Name: string read FName write FName;
property NormalReply: TIdReply read FNormalReply write SetNormalReply;
property ParamDelimiter: Char read FParamDelimiter write FParamDelimiter;
property ParseParams: Boolean read FParseParams write FParseParams;
property Response: TStrings read FResponse write SetResponse;
property Tag: Integer read FTag write FTag;
//
property HelpSuperScript : String read FHelpSuperScript write FHelpSuperScript; //may be something like * or + which should appear in help
property HelpVisible : Boolean read FHelpVisible write FHelpVisible default IdHelpVisibleDef;
property OnCommand: TIdCommandEvent read FOnCommand write FOnCommand;
end;
TIdCommandHandlerClass = class of TIdCommandHandler;
{ TIdCommandHandlers }
TIdCommandHandlers = class(TOwnedCollection)
protected
FBase: TIdComponent;
FExceptionReply: TIdReply;
FOnAfterCommandHandler: TIdAfterCommandHandlerEvent;
FOnBeforeCommandHandler: TIdBeforeCommandHandlerEvent;
FOnCommandHandlersException: TIdCommandHandlersExceptionEvent;
FParseParamsDef: Boolean;
FPerformReplies: Boolean;
FReplyClass: TIdReplyClass;
FReplyTexts: TIdReplies;
//
procedure DoAfterCommandHandler(AContext: TIdContext);
procedure DoBeforeCommandHandler(AContext: TIdContext; var VLine: string);
procedure DoOnCommandHandlersException(const ACommand: String; AContext: TIdContext);
function GetItem(AIndex: Integer): TIdCommandHandler;
// This is used instead of the OwnedBy property directly calling GetOwner because
// D5 dies with internal errors and crashes
// function GetOwnedBy: TIdPersistent;
procedure SetItem(AIndex: Integer; const AValue: TIdCommandHandler);
public
function Add: TIdCommandHandler;
constructor Create(
ABase: TIdComponent;
AReplyClass: TIdReplyClass;
AReplyTexts: TIdReplies;
AExceptionReply: TIdReply = nil;
ACommandHandlerClass: TIdCommandHandlerClass = nil
); reintroduce;
function HandleCommand(AContext: TIdContext; var VCommand: string): Boolean; virtual;
//
property Base: TIdComponent read FBase;
property Items[AIndex: Integer]: TIdCommandHandler read GetItem write SetItem;
// OwnedBy is used so as not to conflict with Owner in D6
//property OwnedBy: TIdPersistent read GetOwnedBy;
property ParseParamsDefault: Boolean read FParseParamsDef write FParseParamsDef;
property PerformReplies: Boolean read FPerformReplies write FPerformReplies;
property ReplyClass: TIdReplyClass read FReplyClass;
property ReplyTexts: TIdReplies read FReplyTexts;
//
property OnAfterCommandHandler: TIdAfterCommandHandlerEvent read FOnAfterCommandHandler
write FOnAfterCommandHandler;
// Occurs in the context of the peer thread
property OnBeforeCommandHandler: TIdBeforeCommandHandlerEvent read FOnBeforeCommandHandler
write FOnBeforeCommandHandler;
property OnCommandHandlersException: TIdCommandHandlersExceptionEvent read FOnCommandHandlersException
write FOnCommandHandlersException;
end;
{ TIdCommand }
TIdCommand = class(TObject)
protected
FCommandHandler: TIdCommandHandler;
FDisconnect: Boolean;
FParams: TStrings;
FPerformReply: Boolean;
FRawLine: string;
FReply: TIdReply;
FResponse: TStrings;
FContext: TIdContext;
FUnparsedParams: string;
FSendEmptyResponse: Boolean;
//
procedure DoCommand; virtual;
procedure SetReply(AValue: TIdReply);
procedure SetResponse(AValue: TStrings);
public
constructor Create(AOwner: TIdCommandHandler); virtual;
destructor Destroy; override;
procedure SendReply;
//
property CommandHandler: TIdCommandHandler read FCommandHandler;
property Disconnect: Boolean read FDisconnect write FDisconnect;
property PerformReply: Boolean read FPerformReply write FPerformReply;
property Params: TStrings read FParams;
property RawLine: string read FRawLine;
property Reply: TIdReply read FReply write SetReply;
property Response: TStrings read FResponse write SetResponse;
property Context: TIdContext read FContext;
property UnparsedParams: string read FUnparsedParams;
property SendEmptyResponse: Boolean read FSendEmptyResponse write FSendEmptyResponse;
end;//TIdCommand
implementation
uses
SysUtils;
{ TIdCommandHandlers }
constructor TIdCommandHandlers.Create(
ABase: TIdComponent;
AReplyClass: TIdReplyClass;
AReplyTexts: TIdReplies;
AExceptionReply: TIdReply = nil;
ACommandHandlerClass: TIdCommandHandlerClass = nil
);
begin
if ACommandHandlerClass = nil then begin
ACommandHandlerClass := TIdCommandHandler;
end;
inherited Create(ABase, ACommandHandlerClass);
FBase := ABase;
FExceptionReply := AExceptionReply;
FParseParamsDef := IdParseParamsDefault;
FPerformReplies := True; // RLebeau: default to legacy behavior
FReplyClass := AReplyClass;
FReplyTexts := AReplyTexts;
end;
function TIdCommandHandlers.Add: TIdCommandHandler;
begin
Result := TIdCommandHandler(inherited Add);
end;
function TIdCommandHandlers.HandleCommand(AContext: TIdContext;
var VCommand: string): Boolean;
var
i, j: Integer;
begin
j := Count - 1;
Result := False;
DoBeforeCommandHandler(AContext, VCommand); try
i := 0;
while i <= j do begin
if Items[i].Enabled then begin
Result := Items[i].Check(VCommand, AContext);
if Result then begin
Break;
end;
end;
Inc(i);
end;
finally DoAfterCommandHandler(AContext); end;
end;
procedure TIdCommandHandlers.DoAfterCommandHandler(AContext: TIdContext);
begin
if Assigned(OnAfterCommandHandler) then begin
OnAfterCommandHandler(Self, AContext);
end;
end;
procedure TIdCommandHandlers.DoBeforeCommandHandler(AContext: TIdContext;
var VLine: string);
begin
if Assigned(OnBeforeCommandHandler) then begin
OnBeforeCommandHandler(Self, VLine, AContext);
end;
end;
procedure TIdCommandHandlers.DoOnCommandHandlersException(const ACommand: String;
AContext: TIdContext);
begin
if Assigned(FOnCommandHandlersException) then begin
OnCommandHandlersException(ACommand, AContext);
end;
end;
function TIdCommandHandlers.GetItem(AIndex: Integer): TIdCommandHandler;
begin
Result := TIdCommandHandler(inherited Items[AIndex]);
end;
{
function TIdCommandHandlers.GetOwnedBy: TIdPersistent;
begin
Result := GetOwner;
end;
}
procedure TIdCommandHandlers.SetItem(AIndex: Integer; const AValue: TIdCommandHandler);
begin
inherited SetItem(AIndex, AValue);
end;
{ TIdCommandHandler }
procedure TIdCommandHandler.DoCommand(const AData: string; AContext: TIdContext; AUnparsedParams: string);
var
LCommand: TIdCommand;
begin
LCommand := TIdCommand.Create(Self);
try
LCommand.FRawLine := AData;
LCommand.FContext := AContext;
LCommand.FUnparsedParams := AUnparsedParams;
if ParseParams then begin
DoParseParams(AUnparsedParams, LCommand.Params);
end;
// RLebeau 2/21/08: for the IRC protocol, RFC 2812 section 2.4 says that
// clients are not allowed to issue numeric replies for server-issued
// commands. Added the PerformReplies property so TIdIRC can specify
// that behavior.
if Collection is TIdCommandHandlers then begin
LCommand.PerformReply := TIdCommandHandlers(Collection).PerformReplies;
end;
try
if (LCommand.Reply.Code = '') and (NormalReply.Code <> '') then begin
LCommand.Reply.Assign(NormalReply);
end;
//if code<>'' before DoCommand, then it breaks exception handling
Assert(LCommand.Reply.Code <> '');
LCommand.DoCommand;
if LCommand.Reply.Code = '' then begin
LCommand.Reply.Assign(NormalReply);
end;
// UpdateText here in case user wants to add to it. SendReply also gets it in case
// a different reply is sent (ie exception, etc), or the user changes the code in the event
LCommand.Reply.UpdateText;
except
on E: Exception do begin
// If there is an unhandled exception, we override all replies
// If nothing specified to override with, we throw the exception again.
// If the user wants a custom value on exception other, its their responsibility
// to catch it before it reaches us
LCommand.Reply.Clear;
if LCommand.PerformReply then begin
// Try from command handler first
if ExceptionReply.Code <> '' then begin
LCommand.Reply.Assign(ExceptionReply);
// If still no go, from server
// Can be nil though. Typically only servers pass it in
end else if (Collection is TIdCommandHandlers) and (TIdCommandHandlers(Collection).FExceptionReply <> nil) then begin
LCommand.Reply.Assign(TIdCommandHandlers(Collection).FExceptionReply);
end;
if LCommand.Reply.Code <> '' then begin
//done this way in case an exception message has more than one line.
//otherwise you could get something like this:
//
// 550 System Error. Code: 2
// The system cannot find the file specified
//
//and the second line would throw off some clients.
LCommand.Reply.Text.Text := E.Message;
//Reply.Text.Add(E.Message);
LCommand.SendReply;
end else begin
raise;
end;
end else begin
raise;
end;
end else begin
raise;
end;
end;
if LCommand.PerformReply then begin
LCommand.SendReply;
end;
if (LCommand.Response.Count > 0) or LCommand.SendEmptyResponse then begin
AContext.Connection.WriteRFCStrings(LCommand.Response);
end else if Response.Count > 0 then begin
AContext.Connection.WriteRFCStrings(Response);
end;
finally
try
if LCommand.Disconnect then begin
AContext.Connection.Disconnect;
end;
finally
LCommand.Free;
end;
end;
end;
procedure TIdCommandHandler.DoParseParams(AUnparsedParams: string; AParams: TStrings);
// AUnparsedParams is not preparsed and is completely left up to the command handler. This will
// allow for future expansion such as multiple delimiters etc, and allow the logic to properly
// remain in each of the command handler implementations. In the future there may be a base type
// and multiple descendants
begin
AParams.Clear;
SplitDelimitedString(AUnparsedParams, AParams, FParamDelimiter <> #32, FParamDelimiter);
end;
function TIdCommandHandler.Check(const AData: string; AContext: TIdContext): boolean;
// AData is not preparsed and is completely left up to the command handler. This will allow for
// future expansion such as wild cards etc, and allow the logic to properly remain in each of the
// command handler implementations. In the future there may be a base type and multiple descendants
var
LUnparsedParams: string;
begin
LUnparsedParams := '';
Result := TextIsSame(AData, Command); // Command by itself
if not Result then begin
if CmdDelimiter <> #0 then begin
Result := TextStartsWith(AData, Command + CmdDelimiter);
if Result then begin
LUnparsedParams := Copy(AData, Length(Command) + 2, MaxInt);
end;
end else begin
// Dont strip any part of the params out.. - just remove the command purely on length and
// no delim
Result := TextStartsWith(AData, Command);
if Result then begin
LUnparsedParams := Copy(AData, Length(Command) + 1, MaxInt);
end;
end;
end;
if Result then begin
DoCommand(AData, AContext, LUnparsedParams);
end;
end;
constructor TIdCommandHandler.Create(ACollection: TCollection);
begin
inherited Create(ACollection);
FReplyClass := TIdCommandHandlers(ACollection).ReplyClass;
if FReplyClass = nil then begin
FReplyClass := TIdReplyRFC;
end;
FCmdDelimiter := #32;
FEnabled := IdEnabledDefault;
FName := ClassName + IntToStr(ID);
FParamDelimiter := #32;
FParseParams := TIdCommandHandlers(ACollection).ParseParamsDefault;
FResponse := TStringList.Create;
FDescription := TStringList.Create;
FNormalReply := FReplyClass.CreateWithReplyTexts(nil, TIdCommandHandlers(ACollection).ReplyTexts);
if FNormalReply is TIdReplyRFC then begin
FNormalReply.Code := '200'; {do not localize}
end;
FHelpVisible := IdHelpVisibleDef;
// Dont initialize, pulls from CmdTCPServer for defaults
FExceptionReply := FReplyClass.CreateWithReplyTexts(nil, TIdCommandHandlers(ACollection).ReplyTexts);
end;
destructor TIdCommandHandler.Destroy;
begin
FreeAndNil(FResponse);
FreeAndNil(FNormalReply);
FreeAndNil(FDescription);
FreeAndNil(FExceptionReply);
inherited Destroy;
end;
function TIdCommandHandler.GetDisplayName: string;
begin
if Command = '' then begin
Result := Name;
end else begin
Result := Command;
end;
end;
{
function TIdCommandHandler.GetNamePath: string;
begin
if Collection <> nil then begin
// OwnedBy is used because D4/D5 dont expose Owner on TOwnedCollection but D6 does
Result := TIdCommandHandlers(Collection).OwnedBy.GetNamePath + '.' + Name;
end else begin
Result := inherited GetNamePath;
end;
end;
}
function TIdCommandHandler.NameIs(const ACommand: string): Boolean;
begin
Result := TextIsSame(ACommand, FName);
end;
procedure TIdCommandHandler.SetExceptionReply(AValue: TIdReply);
begin
FExceptionReply.Assign(AValue);
end;
procedure TIdCommandHandler.SetNormalReply(AValue: TIdReply);
begin
FNormalReply.Assign(AValue);
end;
procedure TIdCommandHandler.SetResponse(AValue: TStrings);
begin
FResponse.Assign(AValue);
end;
procedure TIdCommandHandler.SetDescription(AValue: TStrings);
begin
FDescription.Assign(AValue);
end;
{ TIdCommand }
constructor TIdCommand.Create(AOwner: TIdCommandHandler);
begin
inherited Create;
FParams := TStringList.Create;
FReply := AOwner.FReplyClass.CreateWithReplyTexts(nil, TIdCommandHandlers(AOwner.Collection).ReplyTexts);
FResponse := TStringList.Create;
FCommandHandler := AOwner;
FDisconnect := AOwner.Disconnect;
end;
destructor TIdCommand.Destroy;
begin
FreeAndNil(FReply);
FreeAndNil(FResponse);
FreeAndNil(FParams);
inherited Destroy;
end;
procedure TIdCommand.DoCommand;
begin
if Assigned(CommandHandler.OnCommand) then begin
CommandHandler.OnCommand(Self);
end;
end;
procedure TIdCommand.SendReply;
begin
PerformReply := False;
Reply.UpdateText;
Context.Connection.IOHandler.Write(Reply.FormattedReply);
end;
procedure TIdCommand.SetReply(AValue: TIdReply);
begin
FReply.Assign(AValue);
end;
procedure TIdCommand.SetResponse(AValue: TStrings);
begin
FResponse.Assign(AValue);
end;
end.

File diff suppressed because it is too large Load Diff

220
indy/Core/IdContext.pas Normal file
View File

@@ -0,0 +1,220 @@
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.14 6/16/2004 2:08:48 PM JPMugaas
Binding made public for the FTP Server.
Rev 1.13 6/4/2004 1:34:24 PM DSiders
Removed unused TIdContextDoRun, TIdContextMethod types.
Rev 1.12 2004.02.03 4:17:08 PM czhower
For unit name changes.
Rev 1.11 21.1.2004 ã. 12:31:04 DBondzhev
Fix for Indy source. Workaround for dccil bug
now it can be compiled using Compile instead of build
Rev 1.10 2003.10.21 12:18:58 AM czhower
TIdTask support and fiber bug fixes.
Rev 1.9 2003.10.11 5:47:18 PM czhower
-VCL fixes for servers
-Chain suport for servers (Super core)
-Scheduler upgrades
-Full yarn support
Rev 1.8 2003.09.19 11:54:28 AM czhower
-Completed more features necessary for servers
-Fixed some bugs
Rev 1.7 3/22/2003 09:45:26 PM JPMugaas
Now should compile under D4.
Rev 1.6 3/13/2003 10:18:38 AM BGooijen
Server side fibers, bug fixes
Rev 1.5 1/31/2003 7:24:18 PM BGooijen
Added a .Binding function
Rev 1.4 1/23/2003 8:33:20 PM BGooijen
Rev 1.3 1/23/2003 11:06:06 AM BGooijen
Rev 1.2 1-17-2003 23:58:30 BGooijen
removed OnCreate/OnDestroy again, they had no use
Rev 1.0 1-17-2003 22:28:58 BGooijen
}
unit IdContext;
interface
{$i IdCompilerDefines.inc}
uses
Classes,
IdSocketHandle, IdTCPConnection, IdTask, IdYarn, IdThreadSafe,
{$IFDEF HAS_GENERICS_TThreadList}
System.Generics.Collections,
{$ENDIF}
SysUtils;
type
TIdContext = class;
TIdContextClass = class of TIdContext;
TIdContextRun = function(AContext: TIdContext): Boolean of object;
TIdContextEvent = procedure(AContext: TIdContext) of object;
TIdContextExceptionEvent = procedure(AContext: TIdContext; AException: Exception) of object;
{$IFDEF HAS_GENERICS_TThreadList}
TIdContextThreadList = TIdThreadSafeObjectList<TIdContext>;
TIdContextList = TList<TIdContext>;
{$ELSE}
// TODO: flesh out to match TThreadList<TIdContext> and TList<TIdContext> for non-Generics compilers
TIdContextThreadList = TIdThreadSafeObjectList;
TIdContextList = TList;
{$ENDIF}
TIdContext = class(TIdTask)
protected
// A list in which this context is registered, this can be nil, and should
// therefore not be used
FContextList: TIdContextThreadList;
FConnection: TIdTCPConnection; // TODO: should this be [Weak] on ARC systems?
FOwnsConnection: Boolean;
FOnRun: TIdContextRun;
FOnBeforeRun: TIdContextEvent;
FOnAfterRun: TIdContextEvent;
FOnException: TIdContextExceptionEvent;
//
procedure BeforeRun; override;
function Run: Boolean; override;
procedure AfterRun; override;
procedure HandleException(AException: Exception); override;
function GetBinding: TIdSocketHandle;
public
constructor Create(
AConnection: TIdTCPConnection;
AYarn: TIdYarn;
AList: TIdContextThreadList = nil
); reintroduce; virtual;
destructor Destroy; override;
procedure RemoveFromList;
//
property Binding: TIdSocketHandle read GetBinding;
property Connection: TIdTCPConnection read FConnection;
//
property OnAfterRun: TIdContextEvent read FOnAfterRun write FOnAfterRun;
property OnBeforeRun: TIdContextEvent read FOnBeforeRun write FOnBeforeRun;
property OnRun: TIdContextRun read FOnRun write FOnRun;
property OnException: TIdContextExceptionEvent read FOnException write FOnException;
end;
implementation
{ TIdContext }
uses
{$IFDEF VCL_XE3_OR_ABOVE}
System.Types,
{$ENDIF}
IdGlobal,
IdIOHandlerSocket;
constructor TIdContext.Create(AConnection: TIdTCPConnection; AYarn: TIdYarn;
AList: TIdContextThreadList = nil);
begin
inherited Create(AYarn);
FConnection := AConnection;
FOwnsConnection := True;
FContextList := AList;
end;
destructor TIdContext.Destroy;
begin
if Assigned(FContextList) then begin
FContextList.Remove(Self);
end;
if FOwnsConnection then begin
IdDisposeAndNil(FConnection);
end;
inherited Destroy;
end;
procedure TIdContext.RemoveFromList;
begin
FContextList := nil;
end;
procedure TIdContext.BeforeRun;
begin
//Context must be added to ContextList outside of create. This avoids
//the possibility of another thread accessing a context (specifically
//a subclass) that is still creating. similar logic for remove/destroy.
if Assigned(FContextList) then begin
FContextList.Add(Self);
end;
if Assigned(OnBeforeRun) then begin
OnBeforeRun(Self);
end;
end;
function TIdContext.Run: Boolean;
begin
if Assigned(OnRun) then begin
Result := OnRun(Self);
end else begin
Result := True;
end;
end;
procedure TIdContext.AfterRun;
begin
if Assigned(OnAfterRun) then begin
OnAfterRun(Self);
end;
if FContextList <> nil then begin
FContextList.Remove(Self);
end;
end;
procedure TIdContext.HandleException(AException: Exception);
begin
if Assigned(OnException) then begin
OnException(Self, AException);
end;
end;
function TIdContext.GetBinding: TIdSocketHandle;
begin
Result := nil;
if Connection <> nil then begin
if Connection.Socket <> nil then begin
Result := Connection.Socket.Binding;
end;
end;
end;
end.

View File

@@ -0,0 +1,12 @@
[assembly: AssemblyDescription('Internet Direct (Indy) 10.6.2 Core Run-Time Package for Borland Developer Studio')]
[assembly: AssemblyConfiguration('')]
[assembly: AssemblyCompany('Chad Z. Hower a.k.a Kudzu and the Indy Pit Crew')]
[assembly: AssemblyProduct('Indy for Microsoft .NET Framework')]
[assembly: AssemblyCopyright('Copyright © 1993 - 2015 Chad Z. Hower a.k.a Kudzu and the Indy Pit Crew')]
[assembly: AssemblyTrademark('')]
[assembly: AssemblyCulture('')]
[assembly: AssemblyTitle('Indy .NET Core Run-Time Package')]
[assembly: AssemblyVersion('10.6.2.*')]
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile('')]
[assembly: AssemblyKeyName('')]

View File

@@ -0,0 +1,244 @@
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.4 12/10/2004 15:36:40 HHariri
Fix so it works with D8 too
Rev 1.3 9/5/2004 2:08:14 PM JPMugaas
Should work in D9 NET.
Rev 1.2 2/3/2004 11:42:52 AM JPMugaas
Fixed for new design.
Rev 1.1 2/1/2004 2:44:20 AM JPMugaas
Bindings editor should be fully functional including IPv6 support.
Rev 1.0 11/13/2002 08:41:18 AM JPMugaas
}
unit IdCoreDsnRegister;
interface
{$I IdCompilerDefines.inc}
uses
{$IFDEF DOTNET}
Borland.Vcl.Design.DesignIntF,
Borland.Vcl.Design.DesignEditors
{$ELSE}
{$IFDEF FPC}
PropEdits,
ComponentEditors
{$ELSE}
{$IFDEF VCL_6_OR_ABOVE}
DesignIntf,
DesignEditors
{$ELSE}
Dsgnintf
{$ENDIF}
{$ENDIF}
{$ENDIF}
;
type
{$IFDEF FPC}
TIdBaseComponentEditor = class(TDefaultComponentEditor)
{$ELSE}
TIdBaseComponentEditor = class(TDefaultEditor)
{$ENDIF}
public
procedure ExecuteVerb(Index: Integer); override;
function GetVerb(Index: Integer): string; override;
function GetVerbCount: Integer; override;
end;
{$IFDEF FPC}
TIdPropEdBinding = class(TPropertyEditor)
protected
FValue : String;
property Value : String read FValue write FValue;
{$ELSE}
TIdPropEdBinding = class(TClassProperty)
{$ENDIF}
public
procedure Edit; override;
function GetAttributes: TPropertyAttributes; override;
function GetValue: string; override;
procedure SetValue(const Value: string); override;
end;
// Procs
procedure Register;
implementation
uses
Classes,
{$IFDEF WIDGET_WINFORMS}
IdDsnPropEdBindingNET,
IdAboutDotNET,
{$ELSE}
IdDsnPropEdBindingVCL,
IdAboutVCL,
{$ENDIF}
IdDsnCoreResourceStrings,
IdBaseComponent,
IdComponent,
IdGlobal,
IdStack,
IdSocketHandle;
{
Design Note: It turns out that in DotNET, there are no services file functions and
IdPorts does not work as expected in DotNET. It is probably possible to read the
services file ourselves but that creates some portability problems as the placement
is different in every operating system.
e.g.
Linux and Unix-like systems - /etc
Windows 95, 98, and ME - c:\windows
Windows NT systems - c:\winnt\system32\drivers\etc
Thus, it will undercut whatever benefit we could get with DotNET.
About the best I could think of is to use an edit control because
we can't offer anything from the services file in DotNET.
TODO: Maybe there might be a way to find the location in a more elegant
manner than what I described.
}
type
{$IFDEF WIDGET_WINFORMS}
TIdPropEdBindingEntry = TIdDsnPropEdBindingNET;
{$ELSE}
TIdPropEdBindingEntry = TIdDsnPropEdBindingVCL;
{$ENDIF}
procedure TIdPropEdBinding.Edit;
var
pSockets: TIdSocketHandles;
pEntry: TIdPropEdBindingEntry;
begin
inherited Edit;
{$IFNDEF DOTNET}
pSockets := TIdSocketHandles(
{$IFDEF CPU64}
GetInt64Value
{$ELSE}
GetOrdValue
{$ENDIF}
);
{$ELSE}
pSockets := GetObjValue as TIdSocketHandles;
{$ENDIF}
pEntry := TIdPropEdBindingEntry.Create;
try
pEntry.Caption := TComponent(GetComponent(0)).Name;
pEntry.DefaultPort := pSockets.DefaultPort;
Value := GetListValues(pSockets);
pEntry.SetList(Value);
if pEntry.Execute then
begin
Value := pEntry.GetList;
FillHandleList(Value, pSockets);
end;
finally
pEntry.Free;
end;
end;
function TIdPropEdBinding.GetAttributes: TPropertyAttributes;
begin
Result := inherited GetAttributes + [paDialog];
end;
function TIdPropEdBinding.GetValue: string;
var
pSockets: TIdSocketHandles;
begin
{$IFNDEF DOTNET}
pSockets := TIdSocketHandles(
{$IFDEF CPU64}
GetInt64Value
{$ELSE}
GetOrdValue
{$ENDIF}
);
{$ELSE}
pSockets := GetObjValue as TIdSocketHandles;
{$ENDIF}
Result := GetListValues(pSockets);
end;
procedure TIdPropEdBinding.SetValue(const Value: string);
var
pSockets: TIdSocketHandles;
begin
inherited SetValue(Value);
{$IFNDEF DOTNET}
pSockets := TIdSocketHandles(
{$IFDEF CPU64}
GetInt64Value
{$ELSE}
GetOrdValue
{$ENDIF}
);
{$ELSE}
pSockets := GetObjValue as TIdSocketHandles;
{$ENDIF}
pSockets.BeginUpdate;
try
FillHandleList(Value, pSockets);
finally
pSockets.EndUpdate;
end;
end;
{ TIdBaseComponentEditor }
procedure TIdBaseComponentEditor.ExecuteVerb(Index: Integer);
begin
case Index of
0 : TfrmAbout.ShowDlg;
end;
end;
function TIdBaseComponentEditor.GetVerb(Index: Integer): string;
begin
case Index of
0: Result := IndyFormat(RSAAboutMenuItemName, [gsIdVersion]);
end;
end;
function TIdBaseComponentEditor.GetVerbCount: Integer;
begin
Result := 1;
end;
procedure Register;
begin
RegisterPropertyEditor(TypeInfo(TIdSocketHandles), nil, '', TIdPropEdBinding); {Do not Localize}
RegisterComponentEditor(TIdBaseComponent, TIdBaseComponentEditor);
end;
end.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,253 @@
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.10 11/12/2004 11:30:16 AM JPMugaas
Expansions for IPv6.
Rev 1.9 11/11/2004 10:25:22 PM JPMugaas
Added OpenProxy and CloseProxy so you can do RecvFrom and SendTo functions
from the UDP client with SOCKS. You must call OpenProxy before using
RecvFrom or SendTo. When you are finished, you must use CloseProxy to close
any connection to the Proxy. Connect and disconnect also call OpenProxy and
CloseProxy.
Rev 1.8 11/11/2004 3:42:52 AM JPMugaas
Moved strings into RS. Socks will now raise an exception if you attempt to
use SOCKS4 and SOCKS4A with UDP. Those protocol versions do not support UDP
at all.
Rev 1.7 11/9/2004 8:18:00 PM JPMugaas
Attempt to add SOCKS support in UDP.
Rev 1.6 6/6/2004 11:51:56 AM JPMugaas
Fixed TODO with an exception
Rev 1.5 2004.02.03 4:17:04 PM czhower
For unit name changes.
Rev 1.4 10/15/2003 10:59:06 PM DSiders
Corrected spelling error in resource string name.
Added resource string for circular links exception in transparent proxy.
Rev 1.3 10/15/2003 10:10:18 PM DSiders
Added localization comments.
Rev 1.2 5/16/2003 9:22:38 AM BGooijen
Added Listen(...)
Rev 1.1 5/14/2003 6:41:00 PM BGooijen
Added Bind(...)
Rev 1.0 12/2/2002 05:01:26 PM JPMugaas
Rechecked in due to file corruption.
}
unit IdCustomTransparentProxy;
interface
{$I IdCompilerDefines.inc}
//we need to put this in Delphi mode to work
uses
Classes,
IdComponent,
IdException,
IdGlobal,
IdIOHandler,
IdSocketHandle,
IdBaseComponent;
type
EIdTransparentProxyCircularLink = class(EIdException);
EIdTransparentProxyUDPNotSupported = class(EIdException);
TIdCustomTransparentProxyClass = class of TIdCustomTransparentProxy;
TIdCustomTransparentProxy = class(TIdComponent)
protected
FHost: String;
FPassword: String;
FPort: TIdPort;
FIPVersion : TIdIPVersion;
FUsername: String;
{$IFDEF USE_OBJECT_ARC}[Weak]{$ENDIF} FChainedProxy: TIdCustomTransparentProxy;
//
function GetEnabled: Boolean; virtual; abstract;
procedure SetEnabled(AValue: Boolean); virtual;
procedure MakeConnection(AIOHandler: TIdIOHandler; const AHost: string; const APort: TIdPort; const AIPVersion: TIdIPVersion = ID_DEFAULT_IP_VERSION); virtual; abstract;
{$IFNDEF USE_OBJECT_ARC}
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
{$ENDIF}
procedure SetChainedProxy(const AValue: TIdCustomTransparentProxy);
public
procedure Assign(ASource: TPersistent); override;
procedure OpenUDP(AHandle : TIdSocketHandle; const AHost: string = ''; const APort: TIdPort = 0; const AIPVersion: TIdIPVersion = ID_DEFAULT_IP_VERSION); virtual;
procedure CloseUDP(AHandle: TIdSocketHandle); virtual;
function RecvFromUDP(AHandle: TIdSocketHandle; var ABuffer : TIdBytes;
var VPeerIP: string; var VPeerPort: TIdPort; var VIPVersion: TIdIPVersion;
AMSec: Integer = IdTimeoutDefault): Integer; virtual;
procedure SendToUDP(AHandle: TIdSocketHandle;
const AHost: string; const APort: TIdPort; const AIPVersion: TIdIPVersion;
const ABuffer : TIdBytes); virtual;
procedure Connect(AIOHandler: TIdIOHandler; const AHost: string; const APort: TIdPort; const AIPVersion: TIdIPVersion = ID_DEFAULT_IP_VERSION);
//
procedure Bind(AIOHandler: TIdIOHandler; const AHost: string; const APort: TIdPort; const AIPVersion: TIdIPVersion = ID_DEFAULT_IP_VERSION);overload;virtual;
procedure Bind(AIOHandler: TIdIOHandler; const APort: TIdPort); overload;
function Listen(AIOHandler: TIdIOHandler; const ATimeOut: Integer): Boolean; virtual;
//
property Enabled: Boolean read GetEnabled write SetEnabled;
property Host: String read FHost write FHost;
property Password: String read FPassword write FPassword;
property Port: TIdPort read FPort write FPort;
property IPVersion : TIdIPVersion read FIPVersion write FIPVersion default ID_DEFAULT_IP_VERSION;
property Username: String read FUsername write FUsername;
property ChainedProxy: TIdCustomTransparentProxy read FChainedProxy write SetChainedProxy;
end;
implementation
uses
IdResourceStringsCore, IdExceptionCore;
{ TIdCustomTransparentProxy }
procedure TIdCustomTransparentProxy.Assign(ASource: TPersistent);
var
LSource: TIdCustomTransparentProxy;
Begin
if ASource is TIdCustomTransparentProxy then begin
LSource := TIdCustomTransparentProxy(ASource);
FHost := LSource.Host;
FPassword := LSource.Password;
FPort := LSource.Port;
FIPVersion := LSource.IPVersion;
FUsername := LSource.Username;
end else begin
inherited Assign(ASource);
end;
End;//
procedure TIdCustomTransparentProxy.Connect(AIOHandler: TIdIOHandler; const AHost: string; const APort: TIdPort; const AIPVersion: TIdIPVersion = ID_DEFAULT_IP_VERSION);
var
// under ARC, convert a weak reference to a strong reference before working with it
LChainedProxy: TIdCustomTransparentProxy;
begin
LChainedProxy := FChainedProxy;
if Assigned(LChainedProxy) and LChainedProxy.Enabled then begin
MakeConnection(AIOHandler, LChainedProxy.Host, LChainedProxy.Port);
LChainedProxy.Connect(AIOHandler, AHost, APort, AIPVersion);
end else begin
MakeConnection(AIOHandler, AHost, APort, AIPVersion);
end;
end;
function TIdCustomTransparentProxy.Listen(AIOHandler: TIdIOHandler; const ATimeOut: integer):boolean;
begin
raise EIdTransparentProxyCantBind.Create(RSTransparentProxyCannotBind);
end;
procedure TIdCustomTransparentProxy.Bind(AIOHandler: TIdIOHandler; const AHost: string; const APort: TIdPort; const AIPVersion: TIdIPVersion = ID_DEFAULT_IP_VERSION);
begin
raise EIdTransparentProxyCantBind.Create(RSTransparentProxyCannotBind);
end;
procedure TIdCustomTransparentProxy.Bind(AIOHandler: TIdIOHandler; const APort: TIdPort);
begin
Bind(AIOHandler, '0.0.0.0', APort); {do not localize}
end;
procedure TIdCustomTransparentProxy.SetEnabled(AValue: Boolean);
Begin
End;
// under ARC, all weak references to a freed object get nil'ed automatically
{$IFNDEF USE_OBJECT_ARC}
procedure TIdCustomTransparentProxy.Notification(AComponent: TComponent; Operation: TOperation);
begin
if (Operation = opRemove) and (AComponent = FChainedProxy) then begin
FChainedProxy := nil;
end;
inherited Notification(AComponent,Operation);
end;
{$ENDIF}
procedure TIdCustomTransparentProxy.SetChainedProxy(const AValue: TIdCustomTransparentProxy);
var
LNextValue: TIdCustomTransparentProxy;
// under ARC, convert a weak reference to a strong reference before working with it
LChainedProxy: TIdCustomTransparentProxy;
begin
LChainedProxy := FChainedProxy;
if LChainedProxy <> AValue then
begin
LNextValue := AValue;
while Assigned(LNextValue) do begin
if LNextValue = Self then begin
raise EIdTransparentProxyCircularLink.CreateFmt(RSInterceptCircularLink, [ClassName]);// -> One EIDCircularLink exception
end;
LNextValue := LNextValue.ChainedProxy;
end;
// under ARC, all weak references to a freed object get nil'ed automatically
{$IFNDEF USE_OBJECT_ARC}
if Assigned(LChainedProxy) then begin
LChainedProxy.RemoveFreeNotification(Self);
end;
{$ENDIF}
FChainedProxy := AValue;
{$IFNDEF USE_OBJECT_ARC}
if Assigned(AValue) then begin
AValue.FreeNotification(Self);
end;
{$ENDIF}
end;
end;
procedure TIdCustomTransparentProxy.CloseUDP(AHandle: TIdSocketHandle);
begin
raise EIdTransparentProxyUDPNotSupported.Create(RSTransparentProxyCanNotSupportUDP);
end;
procedure TIdCustomTransparentProxy.OpenUDP(AHandle: TIdSocketHandle;
const AHost: string = ''; const APort: TIdPort = 0;
const AIPVersion: TIdIPVersion = ID_DEFAULT_IP_VERSION);
begin
raise EIdTransparentProxyUDPNotSupported.Create(RSTransparentProxyCanNotSupportUDP);
end;
function TIdCustomTransparentProxy.RecvFromUDP(AHandle: TIdSocketHandle;
var ABuffer : TIdBytes; var VPeerIP: string; var VPeerPort: TIdPort;
var VIPVersion: TIdIPVersion; AMSec: Integer = IdTimeoutDefault): Integer;
begin
raise EIdTransparentProxyUDPNotSupported.Create(RSTransparentProxyCanNotSupportUDP);
end;
procedure TIdCustomTransparentProxy.SendToUDP(AHandle: TIdSocketHandle;
const AHost: string; const APort: TIdPort; const AIPVersion: TIdIPVersion;
const ABuffer : TIdBytes);
begin
raise EIdTransparentProxyUDPNotSupported.Create(RSTransparentProxyCanNotSupportUDP);
end;
end.

View File

@@ -0,0 +1,4 @@
{$IFDEF DEPRECATED_IMPL_BUG}
{$WARN SYMBOL_DEPRECATED OFF}
{$ENDIF}

View File

@@ -0,0 +1,8 @@
{$IFDEF DEPRECATED_IMPL_BUG}
{$IFDEF HAS_DIRECTIVE_WARN_DEFAULT}
{$WARN SYMBOL_DEPRECATED DEFAULT}
{$ELSE}
{$WARN SYMBOL_DEPRECATED ON}
{$ENDIF}
{$ENDIF}

View File

@@ -0,0 +1,94 @@
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.2 9/5/2004 2:08:16 PM JPMugaas
Should work in D9 NET.
Rev 1.1 2/3/2004 11:42:50 AM JPMugaas
Fixed for new design.
Rev 1.0 11/13/2002 08:43:16 AM JPMugaas
}
unit IdDsnBaseCmpEdt;
{$I IdCompilerDefines.inc}
interface
uses
{$IFDEF DOTNET}
Borland.Vcl.Design.DesignIntF,
Borland.Vcl.Design.DesignEditors
{$ELSE}
{$IFDEF FPC}
ComponentEditors
{$ELSE}
{$IFDEF VCL_6_OR_ABOVE}
DesignIntf,
DesignEditors
{$ELSE}
Dsgnintf
{$ENDIF}
{$ENDIF}
{$ENDIF}
;
type
{$IFDEF FPC}
TIdBaseComponentEditor = class(TDefaultComponentEditor)
{$ELSE}
TIdBaseComponentEditor = class(TDefaultEditor)
{$ENDIF}
public
procedure ExecuteVerb(Index: Integer); override;
function GetVerb(Index: Integer): string; override;
function GetVerbCount: Integer; override;
end;
implementation
uses
IdAbout,
IdGlobal,
IdDsnCoreResourceStrings,
SysUtils;
{ TIdBaseComponentEditor }
procedure TIdBaseComponentEditor.ExecuteVerb(Index: Integer);
begin
case Index of
0 : ShowAboutBox(RSAAboutBoxCompName, gsIdVersion);
end;
end;
function TIdBaseComponentEditor.GetVerb(Index: Integer): string;
begin
case Index of
0: Result := IndyFormat(RSAAboutMenuItemName, [gsIdVersion]);
end;
end;
function TIdBaseComponentEditor.GetVerbCount: Integer;
begin
Result := 1;
end;
end.

View File

@@ -0,0 +1,134 @@
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.5 1/29/2004 8:54:30 AM JPMugaas
Removed myself from the distribution Team Chairperson entry as I am resigning
from that role.
Rev 1.4 10/15/2003 10:11:46 PM DSiders
Added resource string for About box credits.
Corrected spelling error in comments.
Rev 1.3 6/16/2003 12:01:44 PM JPMugaas
Updated copyright to say 2003.
Rev 1.2 6/8/2003 05:46:58 AM JPMugaas
The kitchen sink has now been implemented.
Rev 1.1 1/15/2003 08:03:56 AM JPMugaas
Updated with new website address.
Rev 1.0 11/13/2002 08:43:24 AM JPMugaas
}
unit IdDsnCoreResourceStrings;
{
Note: This unit is for resource strings that are used in the Core Design-Time
package and NOT any design-time packages. This is to prevent design-time
resource strings from being linked into the Run-Time only package.
}
interface
{$I IdCompilerDefines.inc}
const
IndyPitCrew = 'Kudzu (Chad Z. Hower)'#13#10
+ 'and the Indy Pit Crew';
resourcestring
{ About Box stuff }
RSAAboutFormCaption = 'About';
RSAAboutBoxCompName = 'Internet Direct (Indy)';
RSAAboutMenuItemName = 'About Internet &Direct (Indy) %s...';
RSAAboutBoxVersion = 'Version %s';
RSAAboutBoxCopyright = 'Copyright (c) 1993 - 2015'#13#10
+ IndyPitCrew;
RSAAboutBoxTitle1 = 'INDY';
RSAAboutBoxTitle2 = 'Internet Direct';
RSAAboutBoxLicences = 'Indy Modified BSD License'+#13#10+'Indy MPL License';
RSAAboutBoxBuiltFor = 'Indy.Sockets (%s)';
RSAAboutBoxPleaseVisit = 'For the latest updates and information please visit:';
RSAAboutBoxIndyWebsite = 'http://www.indyproject.org/'; {Do not Localize}
RSAAboutCreditsCoordinator = 'Project Coordinator';
RSAAboutCreditsCoCordinator = 'Project Co-Coordinator';
RSAAboutCreditsDocumentation = 'Documentation Coordinator';
RSAAboutCreditsDemos = 'Demos Coordinator';
RSAAboutCreditsRetiredPast = 'Retired/Past Contributors';
RSAAboutCreditsIndyCrew = 'The Indy Pit Crew';
RSAAboutKitchenSink = IndyPitCrew+#10#13+'present the'#10#13'Kitchen Sink';
{Binding Editor stuff}
{
Note to translators - Please Read!!!
For all the constants except RSBindingFormCaption, there may be an
& symbol before a letter or number. This is rendered as that character being
underlined. In addition, the character after the & symbol along with the ALT
key enables a user to move to that control. Since these are on one form, be
careful to ensure that the same letter or number does not have a & before it
in more than one string, otherwise an ALT key sequence will be broken.
}
RSBindingFormCaption = 'Binding Editor';
RSBindingNewCaption = '&New';
RSBindingDeleteCaption = '&Delete';
//RSBindingAddCaption = '&Add';
RSBindingRemoveCaption = '&Remove';
RSBindingLabelBindings = '&Bindings';
RSBindingHostnameLabel = '&IP Address';
RSBindingPortLabel = '&Port';
RSBindingIPVerLabel = 'IP &Version';
RSBindingIPV4Item = 'IPv&4 (127.0.0.1)';
RSBindingIPV6Item = 'IPv&6 (::1)';
{Design time SASLList Hints}
RSADlgSLMoveUp = 'Move Up';
RSADlgSLMoveDown = 'Move Down';
RSADlgSLAdd = 'Add';
RSADlgSLRemove = 'Remove';
//Caption that uses format with component name
RSADlgSLCaption = 'Editing SASL List for %s';
RSADlgSLAvailable = '&Available';
RSADlgSLAssigned = 'A&ssigned (tried in order listed)';
{Note that the Ampersand indicates an ALT keyboard sequence}
RSADlgSLEditList = 'Edit &List';
//Display item constants
RSBindingAll = 'All'; //all IP addresses
RSBindingAny = 'Any'; //any port
{Standard dialog stock strings}
RSOk = 'OK';
RSCancel = 'Cancel';
RSHelp = '&Help';
// IdRegister
RSRegIndyClients = 'Indy Clients';
RSRegIndyServers = 'Indy Servers';
RSRegIndyIntercepts = 'Indy Intercepts';
RSRegIndyIOHandlers = 'Indy I/O Handlers';
RSRegIndyMisc = 'Indy Misc';
{$IFDEF FPC}
CoreSuffix = ' - Core';
{$ENDIF}
implementation
end.

View File

@@ -0,0 +1,143 @@
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.9 10/26/2004 8:45:26 PM JPMugaas
Should compile.
Rev 1.8 10/26/2004 8:42:58 PM JPMugaas
Should be more portable with new references to TIdStrings and TIdStringList.
Rev 1.7 5/19/2004 10:44:28 PM DSiders
Corrected spelling for TIdIPAddress.MakeAddressObject method.
Rev 1.6 2/3/2004 11:34:26 AM JPMugaas
Should compile.
Rev 1.5.1.0 2/3/2004 11:32:26 AM JPMugaas
Should compile.
Rev 1.5 2/1/2004 2:44:20 AM JPMugaas
Bindings editor should be fully functional including IPv6 support.
Rev 1.4 2/1/2004 1:03:34 AM JPMugaas
This now work properly in both Win32 and DotNET. The behavior had to change
in DotNET because of some missing functionality and because implementing that
functionality creates more problems than it would solve.
Rev 1.3 2003.12.31 10:42:22 PM czhower
Warning removed
Rev 1.2 10/15/2003 10:12:32 PM DSiders
Added localization comments.
Rev 1.1 2003.10.11 5:47:46 PM czhower
-VCL fixes for servers
-Chain suport for servers (Super core)
-Scheduler upgrades
-Full yarn support
Rev 1.0 11/13/2002 08:43:58 AM JPMugaas
}
unit IdDsnPropEdBinding;
{
Design Note: It turns out that in DotNET, there are no services file functions and
IdPorts does not work as expected in DotNET. It is probably possible to read the
services file ourselves but that creates some portability problems as the placement
is different in every operating system.
e.g.
Linux and Unix-like systems - /etc
Windows 95, 98, and ME - c:\windows
Windows NT systems - c:\winnt\system32\drivers\etc
Thus, it will undercut whatever benefit we could get with DotNET.
About the best I could think of is to use an edit control because
we can't offer anything from the services file in DotNET.
TODO: Maybe there might be a way to find the location in a more elegant
manner than what I described.
}
interface
{$I IdCompilerDefines.inc}
{$IFDEF WIDGET_WINFORMS}
{$R 'IdDsnPropEdBindingNET.TIdDsnPropEdBindingNET.resources' 'IdDsnPropEdBindingNET.resx'}
{$ENDIF}
uses
Classes,
IdSocketHandle;
{
Design Note: It turns out that in DotNET, there are no services file functions and IdPorts
does not work as expected in DotNET. It is probably possible to read the services
file ourselves but that creates some portability problems as the placement is different
in every operating system.
e.g.
Linux and Unix-like systems - /etc
Windows 95, 98, and ME - c:\windows
Windows NT systems - c:\winnt\system32\drivers\etc
Thus, it will undercut whatever benefit we could get with DotNET.
About the best I could think of is to use an edit control because
we can't offer anything from the services file in DotNET.
TODO: Maybe there might be a way to find the location in a more eligant
manner than what I described.
}
procedure FillHandleList(const AList: string; ADest: TIdSocketHandles);
function GetListValues(const ASocketHandles : TIdSocketHandles) : String;
implementation
uses
{$IFDEF WIDGET_WINFORMS}
IdDsnPropEdBindingNET;
{$ELSE}
IdDsnPropEdBindingVCL;
{$ENDIF}
procedure FillHandleList(const AList: string; ADest: TIdSocketHandles);
begin
{$IFDEF WIDGET_WINFORMS}
IdDsnPropEdBindingNET.FillHandleList(AList,ADest);
{$ELSE}
IdDsnPropEdBindingVCL.FillHandleList(AList,ADest);
{$ENDIF}
end;
function GetListValues(const ASocketHandles : TIdSocketHandles) : String;
begin
{$IFDEF WIDGET_WINFORMS}
Result := IdDsnPropEdBindingNET.GetListValues(ASocketHandles);
{$ELSE}
Result := IdDsnPropEdBindingVCL.GetListValues(ASocketHandles);
{$ENDIF}
end;
end.

View File

@@ -0,0 +1,702 @@
unit IdDsnPropEdBindingNET;
interface
uses
Classes,
System.Drawing, System.Collections, System.ComponentModel,
System.Windows.Forms, System.Data, IdSocketHandle;
type
TIdDsnPropEdBindingNET = class(System.Windows.Forms.Form)
{$REGION 'Designer Managed Code'}
strict private
/// <summary>
/// Required designer variable.
/// </summary>
Components: System.ComponentModel.Container;
btnOk: System.Windows.Forms.Button;
btnCancel: System.Windows.Forms.Button;
lblBindings: System.Windows.Forms.Label;
lbBindings: System.Windows.Forms.ListBox;
btnNew: System.Windows.Forms.Button;
btnDelete: System.Windows.Forms.Button;
lblIPAddress: System.Windows.Forms.Label;
edtIPAddress: System.Windows.Forms.ComboBox;
lblPort: System.Windows.Forms.Label;
edtPort: System.Windows.Forms.NumericUpDown;
cboIPVersion: System.Windows.Forms.ComboBox;
lblIPVersion: System.Windows.Forms.Label;
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
procedure InitializeComponent;
procedure btnNew_Click(sender: System.Object; e: System.EventArgs);
procedure btnDelete_Click(sender: System.Object; e: System.EventArgs);
procedure edtPort_ValueChanged(sender: System.Object; e: System.EventArgs);
procedure edtIPAddress_SelectedValueChanged(sender: System.Object; e: System.EventArgs);
procedure cboIPVersion_SelectedValueChanged(sender: System.Object; e: System.EventArgs);
procedure lbBindings_SelectedValueChanged(sender: System.Object; e: System.EventArgs);
{$ENDREGION}
strict protected
/// <summary>
/// Clean up any resources being used.
/// </summary>
procedure Dispose(Disposing: Boolean); override;
private
FHandles : TIdSocketHandles;
FDefaultPort : Integer;
FIPv4Addresses : TStrings;
FIPv6Addresses : TStrings;
FCurrentHandle : TIdSocketHandle;
{ Private Declarations }
procedure SetHandles(const Value: TIdSocketHandles);
procedure SetIPv4Addresses(const Value: TStrings);
procedure SetIPv6Addresses(const Value: TStrings);
procedure UpdateBindingList;
procedure UpdateEditControls;
procedure FillComboBox(ACombo : System.Windows.Forms.ComboBox; AStrings :TStrings);
procedure SetCaption(const AValue : String);
function GetCaption : String;
public
constructor Create;
function Execute : Boolean;
function GetList: string;
procedure SetList(const AList: string);
property Handles : TIdSocketHandles read FHandles write SetHandles;
property DefaultPort : Integer read FDefaultPort write FDefaultPort;
property IPv4Addresses : TStrings read FIPv4Addresses write SetIPv4Addresses;
property IPv6Addresses : TStrings read FIPv6Addresses write SetIPv6Addresses;
property Caption : String read GetCaption write SetCaption;
end;
[assembly: RuntimeRequiredAttribute(TypeOf(TIdDsnPropEdBindingNET))]
procedure FillHandleList(const AList: string; ADest: TIdSocketHandles);
function GetListValues(const ASocketHandles : TIdSocketHandles) : String;
implementation
uses
IdGlobal,
IdIPAddress,
IdDsnCoreResourceStrings, IdStack, SysUtils;
const
IPv6Wildcard1 = '::'; {do not localize}
IPv6Wildcard2 = '0:0:0:0:0:0:0:0'; {do not localize}
IPv6Loopback = '::1'; {do not localize}
IPv4Wildcard = '0.0.0.0'; {do not localize}
IPv4Loopback = '127.0.0.1'; {do not localize}
function IsValidIP(const AAddr : String): Boolean;
var
LIP: TIdIPAddress;
begin
LIP := TIdIPAddress.MakeAddressObject(AAddr);
Result := Assigned(LIP);
if Result then
begin
FreeAndNil(LIP);
end;
end;
function StripAndSymbol(s : String) : String;
begin
Result := '';
repeat
if s='' then
begin
Break;
end;
Result := Result + Fetch(s,'&');
until False;
end;
procedure FillHandleList(const AList: string; ADest: TIdSocketHandles);
var
LItems: TStringList;
i: integer;
LIPVersion: TIdIPVersion;
LAddr, LText: string;
LPort: integer;
begin
ADest.Clear;
LItems := TStringList.Create;
try
LItems.CommaText := AList;
for i := 0 to LItems.Count-1 do begin
if Length(LItems[i]) > 0 then begin
if TextStartsWith(LItems[i], '[') then begin
// ipv6
LIPVersion := Id_IPv6;
LText := Copy(LItems[i], 2, MaxInt);
LAddr := Fetch(LText, ']:');
LPort := IndyStrToInt(LText, -1);
end else begin
// ipv4
LIPVersion := Id_IPv4;
LText := LItems[i];
LAddr := Fetch(LText, ':');
LPort := IndyStrToInt(LText, -1);
//Note that 0 is legal and indicates the server binds to a random port
end;
if IsValidIP(LAddr) and (LPort > -1) and (LPort < 65536) then begin
with ADest.Add do begin
IPVersion := LIPVersion;
IP := LAddr;
Port := LPort;
end;
end;
end;
end;
finally
LItems.Free;
end;
end;
function NumericOnly(const AText : String) : String;
var
i: Integer;
begin
Result := '';
for i := 1 to Length(AText) do
begin
if IsNumeric(AText[i]) then
begin
Result := Result + AText[i];
end
else
begin
Break;
end;
end;
if (Length(Result) = 0) then
begin
Result := '0';
end;
end;
function IndexOfNo(const ANo : Integer; AItems : System.Windows.Forms.ComboBox.ObjectCollection) : Integer;
begin
for Result := 0 to AItems.Count -1 do
begin
if ANo = IndyStrToInt( NumericOnly(AItems[Result].ToString )) then
begin
Exit;
end;
end;
Result := -1;
end;
function GetDisplayString(ASocketHandle: TIdSocketHandle): string;
begin
Result := '';
case ASocketHandle.IPVersion of
Id_IPv4 : Result := IndyFormat('%s:%d', [ASocketHandle.IP, ASocketHandle.Port]);
Id_IPv6 : Result := IndyFormat('[%s]:%d', [ASocketHandle.IP, ASocketHandle.Port]);
end;
end;
function GetListValues(const ASocketHandles : TIdSocketHandles) : String;
var
i: Integer;
begin
Result := '';
for i := 0 to ASocketHandles.Count -1 do begin
Result := Result + ',' + GetDisplayString(ASocketHandles[i]);
end;
Delete(Result,1,1);
end;
{$AUTOBOX ON}
{$REGION 'Windows Form Designer generated code'}
/// <summary>
/// Required method for Designer support -- do not modify
/// the contents of this method with the code editor.
/// </summary>
procedure TIdDsnPropEdBindingNET.InitializeComponent;
type
TArrayOfInteger = array of Integer;
begin
Self.btnOk := System.Windows.Forms.Button.Create;
Self.btnCancel := System.Windows.Forms.Button.Create;
Self.lblBindings := System.Windows.Forms.Label.Create;
Self.lbBindings := System.Windows.Forms.ListBox.Create;
Self.btnNew := System.Windows.Forms.Button.Create;
Self.btnDelete := System.Windows.Forms.Button.Create;
Self.lblIPAddress := System.Windows.Forms.Label.Create;
Self.edtIPAddress := System.Windows.Forms.ComboBox.Create;
Self.lblPort := System.Windows.Forms.Label.Create;
Self.edtPort := System.Windows.Forms.NumericUpDown.Create;
Self.cboIPVersion := System.Windows.Forms.ComboBox.Create;
Self.lblIPVersion := System.Windows.Forms.Label.Create;
(System.ComponentModel.ISupportInitialize(Self.edtPort)).BeginInit;
Self.SuspendLayout;
//
// btnOk
//
Self.btnOk.Anchor := (System.Windows.Forms.AnchorStyles((System.Windows.Forms.AnchorStyles.Bottom
or System.Windows.Forms.AnchorStyles.Right)));
Self.btnOk.DialogResult := System.Windows.Forms.DialogResult.OK;
Self.btnOk.Location := System.Drawing.Point.Create(312, 160);
Self.btnOk.Name := 'btnOk';
Self.btnOk.TabIndex := 0;
//
// btnCancel
//
Self.btnCancel.Anchor := (System.Windows.Forms.AnchorStyles((System.Windows.Forms.AnchorStyles.Bottom
or System.Windows.Forms.AnchorStyles.Right)));
Self.btnCancel.DialogResult := System.Windows.Forms.DialogResult.Cancel;
Self.btnCancel.Location := System.Drawing.Point.Create(392, 160);
Self.btnCancel.Name := 'btnCancel';
Self.btnCancel.TabIndex := 1;
//
// lblBindings
//
Self.lblBindings.AutoSize := True;
Self.lblBindings.Location := System.Drawing.Point.Create(8, 8);
Self.lblBindings.Name := 'lblBindings';
Self.lblBindings.Size := System.Drawing.Size.Create(42, 16);
Self.lblBindings.TabIndex := 2;
Self.lblBindings.Text := '&Binding';
//
// lbBindings
//
Self.lbBindings.Anchor := (System.Windows.Forms.AnchorStyles(((System.Windows.Forms.AnchorStyles.Top
or System.Windows.Forms.AnchorStyles.Bottom) or System.Windows.Forms.AnchorStyles.Left)));
Self.lbBindings.Location := System.Drawing.Point.Create(8, 24);
Self.lbBindings.Name := 'lbBindings';
Self.lbBindings.Size := System.Drawing.Size.Create(137, 121);
Self.lbBindings.TabIndex := 3;
Include(Self.lbBindings.SelectedValueChanged, Self.lbBindings_SelectedValueChanged);
//
// btnNew
//
Self.btnNew.Location := System.Drawing.Point.Create(152, 56);
Self.btnNew.Name := 'btnNew';
Self.btnNew.TabIndex := 4;
Include(Self.btnNew.Click, Self.btnNew_Click);
//
// btnDelete
//
Self.btnDelete.Location := System.Drawing.Point.Create(152, 88);
Self.btnDelete.Name := 'btnDelete';
Self.btnDelete.TabIndex := 5;
Include(Self.btnDelete.Click, Self.btnDelete_Click);
//
// lblIPAddress
//
Self.lblIPAddress.Location := System.Drawing.Point.Create(240, 8);
Self.lblIPAddress.Name := 'lblIPAddress';
Self.lblIPAddress.Size := System.Drawing.Size.Create(100, 16);
Self.lblIPAddress.TabIndex := 6;
Self.lblIPAddress.Text := 'Label1';
//
// edtIPAddress
//
Self.edtIPAddress.Anchor := (System.Windows.Forms.AnchorStyles(((System.Windows.Forms.AnchorStyles.Top
or System.Windows.Forms.AnchorStyles.Left) or System.Windows.Forms.AnchorStyles.Right)));
Self.edtIPAddress.Location := System.Drawing.Point.Create(240, 24);
Self.edtIPAddress.Name := 'edtIPAddress';
Self.edtIPAddress.Size := System.Drawing.Size.Create(224, 21);
Self.edtIPAddress.TabIndex := 7;
Include(Self.edtIPAddress.SelectedValueChanged, Self.edtIPAddress_SelectedValueChanged);
//
// lblPort
//
Self.lblPort.Location := System.Drawing.Point.Create(240, 58);
Self.lblPort.Name := 'lblPort';
Self.lblPort.Size := System.Drawing.Size.Create(100, 16);
Self.lblPort.TabIndex := 8;
Self.lblPort.Text := 'Label1';
//
// edtPort
//
Self.edtPort.Anchor := (System.Windows.Forms.AnchorStyles(((System.Windows.Forms.AnchorStyles.Top
or System.Windows.Forms.AnchorStyles.Left) or System.Windows.Forms.AnchorStyles.Right)));
Self.edtPort.Location := System.Drawing.Point.Create(240, 74);
Self.edtPort.Maximum := System.Decimal.Create(TArrayOfInteger.Create(65535,
0, 0, 0));
Self.edtPort.Name := 'edtPort';
Self.edtPort.Size := System.Drawing.Size.Create(224, 20);
Self.edtPort.TabIndex := 9;
Include(Self.edtPort.ValueChanged, Self.edtPort_ValueChanged);
//
// cboIPVersion
//
Self.cboIPVersion.DropDownStyle := System.Windows.Forms.ComboBoxStyle.DropDownList;
Self.cboIPVersion.Location := System.Drawing.Point.Create(240, 124);
Self.cboIPVersion.Name := 'cboIPVersion';
Self.cboIPVersion.Size := System.Drawing.Size.Create(224, 21);
Self.cboIPVersion.TabIndex := 10;
Include(Self.cboIPVersion.SelectedValueChanged, Self.cboIPVersion_SelectedValueChanged);
//
// lblIPVersion
//
Self.lblIPVersion.Location := System.Drawing.Point.Create(240, 108);
Self.lblIPVersion.Name := 'lblIPVersion';
Self.lblIPVersion.Size := System.Drawing.Size.Create(100, 16);
Self.lblIPVersion.TabIndex := 11;
Self.lblIPVersion.Text := 'Label1';
//
// TIdDsnPropEdBindingNET
//
Self.AcceptButton := Self.btnOk;
Self.AutoScaleBaseSize := System.Drawing.Size.Create(5, 13);
Self.CancelButton := Self.btnCancel;
Self.ClientSize := System.Drawing.Size.Create(470, 189);
Self.Controls.Add(Self.lblIPVersion);
Self.Controls.Add(Self.cboIPVersion);
Self.Controls.Add(Self.edtPort);
Self.Controls.Add(Self.lblPort);
Self.Controls.Add(Self.edtIPAddress);
Self.Controls.Add(Self.lblIPAddress);
Self.Controls.Add(Self.btnDelete);
Self.Controls.Add(Self.btnNew);
Self.Controls.Add(Self.lbBindings);
Self.Controls.Add(Self.lblBindings);
Self.Controls.Add(Self.btnCancel);
Self.Controls.Add(Self.btnOk);
Self.FormBorderStyle := System.Windows.Forms.FormBorderStyle.FixedDialog;
Self.MaximizeBox := False;
Self.MaximumSize := System.Drawing.Size.Create(480, 225);
Self.MinimizeBox := False;
Self.MinimumSize := System.Drawing.Size.Create(480, 225);
Self.Name := 'TIdDsnPropEdBindingNET';
Self.ShowInTaskbar := False;
Self.StartPosition := System.Windows.Forms.FormStartPosition.CenterScreen;
Self.Text := 'WinForm';
(System.ComponentModel.ISupportInitialize(Self.edtPort)).EndInit;
Self.ResumeLayout(False);
end;
{$ENDREGION}
procedure TIdDsnPropEdBindingNET.Dispose(Disposing: Boolean);
begin
if Disposing then
begin
if Components <> nil then
begin
Components.Dispose();
FreeAndNil(FHandles);
FreeAndNil(FIPv4Addresses);
FreeAndNil(FIPv6Addresses);
//don't free FCurrentHandle; - it's in the handles collection
TIdStack.DecUsage;
end;
end;
inherited Dispose(Disposing);
end;
constructor TIdDsnPropEdBindingNET.Create;
var
i: Integer;
LLocalAddresses: TIdStackLocalAddressList;
begin
inherited Create;
//
// Required for Windows Form Designer support
//
InitializeComponent;
//
// TODO: Add any constructor code after InitializeComponent call
//
FHandles := TIdSocketHandles.Create(nil);
FIPv4Addresses := TStringList.Create;
FIPv6Addresses := TStringList.Create;
SetIPv4Addresses(nil);
SetIPv6Addresses(nil);
TIdStack.IncUsage;
try
LLocalAddresses := TIdStackLocalAddressList.Create;
try
GStack.GetLocalAddressList(LLocalAddresses);
for i := 0 to LLocalAddresses.Count-1 do
begin
case LLocalAddresses[i].IPVersion of
Id_IPv4: FIPv4Addresses.Add(LLocalAddresses[i].IPAddress);
Id_IPv6: FIPv6Addresses.Add(LLocalAddresses[i].IPAddress);
end;
end;
finally
LLocalAddresses.Free;
end;
finally
TIdStack.DecUsage;
end;
UpdateEditControls;
//captions
btnNew.Text := RSBindingNewCaption;
btnDelete.Text := RSBindingDeleteCaption;
lblIPAddress.Text := RSBindingHostnameLabel;
lblPort.Text := RSBindingPortLabel;
lblIPVersion.Text := RSBindingIPVerLabel;
btnOk.Text := RSOk;
btnCancel.Text := RSCancel;
//IPVersion choices
//we yhave to strip out the & symbol. In Win32, we use this
//in a radio-box so a user could select by pressingg the 4 or 6
//key. For this, we don't have a radio box and I'm too lazy
//to use two Radio Buttons.
cboIPVersion.Items.Add(StripAndSymbol(RSBindingIPV4Item));
cboIPVersion.Items.Add(StripAndSymbol(RSBindingIPV6Item));
end;
procedure TIdDsnPropEdBindingNET.SetHandles(const Value: TIdSocketHandles);
begin
FHandles.Assign(Value);
UpdateBindingList;
end;
function TIdDsnPropEdBindingNET.GetList: string;
begin
Result := GetListValues(Handles);
end;
procedure TIdDsnPropEdBindingNET.SetIPv6Addresses(const Value: TStrings);
begin
if Assigned(Value) then begin
FIPv6Addresses.Assign(Value);
end;
// Ensure that these two are always present
if FIPv6Addresses.IndexOf(IPv6Loopback) = -1 then begin
FIPv6Addresses.Insert(0, IPv6Loopback);
end;
if FIPv6Addresses.IndexOf(IPv6Wildcard1) = -1 then begin
FIPv6Addresses.Insert(0, IPv6Wildcard1);
end;
end;
procedure TIdDsnPropEdBindingNET.SetIPv4Addresses(const Value: TStrings);
begin
if Assigned(Value) then begin
FIPv4Addresses.Assign(Value);
end;
// Ensure that these two are always present
if FIPv4Addresses.IndexOf(IPv6Loopback) = -1 then begin
FIPv4Addresses.Insert(0, IPv4Loopback);
end;
if FIPv4Addresses.IndexOf(IPv4Wildcard) = -1 then begin
FIPv4Addresses.Insert(0, IPv4Wildcard);
end;
end;
procedure TIdDsnPropEdBindingNET.SetList(const AList: string);
begin
FCurrentHandle := nil;
FillHandleList(AList, Handles);
UpdateBindingList;
UpdateEditControls;
end;
procedure TIdDsnPropEdBindingNET.lbBindings_SelectedValueChanged(sender: System.Object;
e: System.EventArgs);
begin
if lbBindings.SelectedIndex >= 0 then begin
btnDelete.Enabled := True;
FCurrentHandle := FHandles[lbBindings.SelectedIndex];
end else begin
btnDelete.Enabled := False;
FCurrentHandle := nil;
end;
UpdateEditControls;
end;
procedure TIdDsnPropEdBindingNET.cboIPVersion_SelectedValueChanged(sender: System.Object;
e: System.EventArgs);
begin
case cboIPVersion.SelectedIndex of
0 :
begin
if FCurrentHandle.IPVersion <> Id_IPv4 then
begin
FCurrentHandle.IPVersion := Id_IPv4;
FillComboBox(edtIPAddress,FIPv4Addresses);
FCurrentHandle.IP := IPv4Wildcard;
end;
end;
1 :
begin
if FCurrentHandle.IPVersion <> Id_IPv6 then
begin
FCurrentHandle.IPVersion := Id_IPv6;
FillComboBox(edtIPAddress,FIPv6Addresses);
FCurrentHandle.IP := IPv6Wildcard1;
end;
end;
end;
UpdateEditControls;
UpdateBindingList;
end;
procedure TIdDsnPropEdBindingNET.edtIPAddress_SelectedValueChanged(sender: System.Object;
e: System.EventArgs);
begin
FCurrentHandle.IP := edtIPAddress.SelectedItem.ToString;
UpdateBindingList;
end;
procedure TIdDsnPropEdBindingNET.edtPort_ValueChanged(sender: System.Object;
e: System.EventArgs);
begin
if Assigned(FCurrentHandle) then begin
FCurrentHandle.Port := edtPort.Value.ToInt16(edtPort.Value);
end;
UpdateBindingList;
end;
procedure TIdDsnPropEdBindingNET.btnDelete_Click(sender: System.Object; e: System.EventArgs);
var LSH : TIdSocketHandle;
i : Integer;
begin
if lbBindings.SelectedIndex >= 0 then
begin
// Delete is not available in D4's collection classes
// This should work just as well.
i := lbBindings.get_SelectedIndex;
LSH := Handles[i];
FreeAndNil(LSH);
lbBindings.Items.Remove(i);
FCurrentHandle := nil;
UpdateBindingList;
end;
lbBindings_SelectedValueChanged(nil, nil);
UpdateEditControls;
end;
procedure TIdDsnPropEdBindingNET.btnNew_Click(sender: System.Object; e: System.EventArgs);
begin
FCurrentHandle := FHandles.Add;
FCurrentHandle.IP := IPv4Wildcard;
FCurrentHandle.Port := FDefaultPort;
UpdateBindingList;
FillComboBox(edtIPAddress, FIPv4Addresses);
UpdateEditControls;
end;
procedure TIdDsnPropEdBindingNET.UpdateBindingList;
var
i: integer;
selected: integer;
s: string;
begin
selected := lbBindings.SelectedIndex;
lbBindings.BeginUpdate;
try
if lbBindings.Items.Count = FHandles.Count then begin
for i := 0 to FHandles.Count - 1 do begin
s := GetDisplayString(FHandles[i]);
if s <> lbBindings.Items[i].ToString then begin
lbBindings.Items[i] := s;
end;
end;
end else begin
lbBindings.Items.Clear;
for i := 0 to FHandles.Count-1 do begin
lbBindings.Items.Add(GetDisplayString(FHandles[i]));
end;
end;
finally
lbBindings.EndUpdate;
if Assigned(FCurrentHandle) then begin
lbBindings.SelectedIndex := FCurrentHandle.Index;
end else begin
lbBindings.SelectedIndex := IndyMin(selected, lbBindings.Items.Count-1);
end;
end;
{ selected := lbBindings.SelectedItem;
lbBindings.Items.BeginUpdate;
try
if lbBindings.Items.Count = FHandles.Count then begin
for i := 0 to FHandles.Count - 1 do begin
s := GetDisplayString(FHandles[i]);
if s <> lbBindings.Items[i] then begin
lbBindings.Items[i] := s;
end;
end;
end else begin
lbBindings.Items.Clear;
for i := 0 to FHandles.Count-1 do begin
lbBindings.Items.Add(GetDisplayString(FHandles[i]));
end;
end;
finally
lbBindings.Items.EndUpdate;
if Assigned(FCurrentHandle) then begin
lbBindings.ItemIndex := FCurrentHandle.Index;
end else begin
lbBindings.ItemIndex := IndyMin(selected, lbBindings.Items.Count-1);
end;
end; }
end;
procedure TIdDsnPropEdBindingNET.UpdateEditControls;
begin
if Assigned(FCurrentHandle) then
begin
edtPort.Text := '';
edtPort.Value := FCurrentHandle.Port;
case FCurrentHandle.IPVersion of
Id_IPv4 :
begin
FillComboBox(edtIPAddress, FIPv4Addresses);
edtIPAddress.SelectedItem := edtIPAddress.Items[0];
cboIPVersion.SelectedItem := cboIPVersion.Items[0];
end;
Id_IPv6 :
begin
FillComboBox(edtIPAddress, FIPv6Addresses);
edtIPAddress.SelectedItem := edtIPAddress.Items[0];
cboIPVersion.SelectedItem := cboIPVersion.Items[1];
end;
end;
if edtIPAddress.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDown then begin
edtIPAddress.Text := FCurrentHandle.IP;
end else begin
edtIPAddress.SelectedIndex := edtIPAddress.Items.IndexOf(FCurrentHandle.IP);
end;
end;
lblIPAddress.Enabled := Assigned(FCurrentHandle);
edtIPAddress.Enabled := Assigned(FCurrentHandle);
lblPort.Enabled := Assigned(FCurrentHandle);
edtPort.Enabled := Assigned(FCurrentHandle);
lblIPVersion.Enabled := Assigned(FCurrentHandle);
cboIPVersion.Enabled := Assigned(FCurrentHandle);
end;
procedure TIdDsnPropEdBindingNET.FillComboBox(
ACombo: System.Windows.Forms.ComboBox; AStrings: TStrings);
var
i : Integer;
begin
ACombo.Items.Clear;
for i := 0 to AStrings.Count-1 do begin
ACombo.Items.Add(AStrings[i]);
end;
end;
function TIdDsnPropEdBindingNET.Execute: Boolean;
begin
Result := Self.ShowDialog = System.Windows.Forms.DialogResult.OK;
end;
function TIdDsnPropEdBindingNET.GetCaption: String;
begin
Result := Text;
end;
procedure TIdDsnPropEdBindingNET.SetCaption(const AValue: String);
begin
Text := AValue;
end;
end.

View File

@@ -0,0 +1,196 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used forserialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="btnOk.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="btnOk.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="btnCancel.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="btnCancel.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblBindings.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblBindings.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lbBindings.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lbBindings.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="btnNew.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="btnNew.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="btnDelete.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="btnDelete.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblIPAddress.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblIPAddress.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="edtIPAddress.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="edtIPAddress.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblPort.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblPort.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="edtPort.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="edtPort.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="cboIPVersion.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="cboIPVersion.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="lblIPVersion.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="lblIPVersion.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>(Default)</value>
</data>
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>8, 8</value>
</data>
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>80</value>
</data>
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</data>
</root>

View File

@@ -0,0 +1,819 @@
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.9 10/26/2004 8:45:26 PM JPMugaas
Should compile.
Rev 1.8 10/26/2004 8:42:58 PM JPMugaas
Should be more portable with new references to TIdStrings and TIdStringList.
Rev 1.7 5/19/2004 10:44:28 PM DSiders
Corrected spelling for TIdIPAddress.MakeAddressObject method.
Rev 1.6 2/3/2004 11:34:26 AM JPMugaas
Should compile.
Rev 1.5.1.0 2/3/2004 11:32:26 AM JPMugaas
Should compile.
Rev 1.5 2/1/2004 2:44:20 AM JPMugaas
Bindings editor should be fully functional including IPv6 support.
Rev 1.4 2/1/2004 1:03:34 AM JPMugaas
This now work properly in both Win32 and DotNET. The behavior had to change
in DotNET because of some missing functionality and because implementing that
functionality creates more problems than it would solve.
Rev 1.3 2003.12.31 10:42:22 PM czhower
Warning removed
Rev 1.2 10/15/2003 10:12:32 PM DSiders
Added localization comments.
Rev 1.1 2003.10.11 5:47:46 PM czhower
-VCL fixes for servers
-Chain suport for servers (Super core)
-Scheduler upgrades
-Full yarn support
Rev 1.0 11/13/2002 08:43:58 AM JPMugaas
}
unit IdDsnPropEdBindingVCL;
interface
{$I IdCompilerDefines.inc}
uses
Classes,
{$IFDEF WIDGET_KYLIX}
QActnList, QStdCtrls, QForms, QExtCtrls, QControls, QComCtrls, QGraphics, Qt,
{$ENDIF}
{$IFDEF WIDGET_VCL_LIKE}
ActnList, StdCtrls, Buttons, ExtCtrls, Graphics, Controls, ComCtrls, Forms, Dialogs,
{$ENDIF}
{$IFDEF HAS_UNIT_Types}
Types,
{$ENDIF}
{$IFDEF WINDOWS}
Windows,
{$ENDIF}
{$IFDEF LCL}
LResources,
{$ENDIF}
IdSocketHandle;
{
Design Note: It turns out that in DotNET, there are no services file functions and
IdPorts does not work as expected in DotNET. It is probably possible to read the
services file ourselves but that creates some portability problems as the placement
is different in every operating system.
e.g.
Linux and Unix-like systems - /etc
Windows 95, 98, and ME - c:\windows
Windows NT systems - c:\winnt\system32\drivers\etc
Thus, it will undercut whatever benefit we could get with DotNET.
About the best I could think of is to use an edit control because
we can't offer anything from the services file in DotNET.
TODO: Maybe there might be a way to find the location in a more elegant
manner than what I described.
}
type
TIdDsnPropEdBindingVCL = class(TForm)
{$IFDEF USE_TBitBtn}
btnOk: TBitBtn;
btnCancel: TBitBtn;
{$ELSE}
btnOk: TButton;
btnCancel: TButton;
{$ENDIF}
lblBindings: TLabel;
edtPort: TComboBox;
rdoBindingType: TRadioGroup;
lblIPAddress: TLabel;
lblPort: TLabel;
btnNew: TButton;
btnDelete: TButton;
ActionList1: TActionList;
btnBindingsNew: TAction;
btnBindingsDelete: TAction;
edtIPAddress: TComboBox;
lbBindings: TListBox;
procedure btnBindingsNewExecute(Sender: TObject);
procedure btnBindingsDeleteExecute(Sender: TObject);
procedure btnBindingsDeleteUpdate(Sender: TObject);
procedure edtPortKeyPress(Sender: TObject; var Key: Char);
procedure edtIPAddressChange(Sender: TObject);
procedure edtPortChange(Sender: TObject);
procedure rdoBindingTypeClick(Sender: TObject);
procedure lbBindingsClick(Sender: TObject);
private
procedure SetHandles(const Value: TIdSocketHandles);
procedure SetIPv4Addresses(const Value: TStrings);
procedure SetIPv6Addresses(const Value: TStrings);
procedure UpdateBindingList;
protected
FInUpdateRoutine : Boolean;
FHandles : TIdSocketHandles;
FDefaultPort : Integer;
FIPv4Addresses : TStrings;
FIPv6Addresses : TStrings;
fCreatedStack : Boolean;
FCurrentHandle : TIdSocketHandle;
procedure UpdateEditControls;
function PortDescription(const PortNumber: integer): string;
public
Constructor Create(AOwner : TComponent); overload; override;
constructor Create; reintroduce; overload;
Destructor Destroy; override;
function Execute : Boolean;
function GetList: string;
procedure SetList(const AList: string);
property Handles : TIdSocketHandles read FHandles write SetHandles;
property DefaultPort : Integer read FDefaultPort write FDefaultPort;
property IPv4Addresses : TStrings read FIPv4Addresses write SetIPv4Addresses;
property IPv6Addresses : TStrings read FIPv6Addresses write SetIPv6Addresses;
end;
var
IdPropEdBindingEntry: TIdDsnPropEdBindingVCL;
procedure FillHandleList(const AList: string; ADest: TIdSocketHandles);
function GetListValues(const ASocketHandles : TIdSocketHandles) : String;
implementation
uses
IdGlobal,
IdIPAddress,
IdDsnCoreResourceStrings,
IdStack,
IdStackBSDBase,
SysUtils;
const
IPv6Wildcard1 = '::'; {do not localize}
{CH IPv6Wildcard2 = '0:0:0:0:0:0:0:0'; } {do not localize}
IPv6Loopback = '::1'; {do not localize}
IPv4Wildcard = '0.0.0.0'; {do not localize}
IPv4Loopback = '127.0.0.1'; {do not localize}
function IsValidIP(const AAddr : String): Boolean;
var
LIP : TIdIPAddress;
begin
LIP := TIdIPAddress.MakeAddressObject(AAddr);
Result := Assigned(LIP);
if Result then begin
FreeAndNil(LIP);
end;
end;
procedure FillHandleList(const AList: string; ADest: TIdSocketHandles);
var
LItems: TStringList;
i: integer;
LIPVersion: TIdIPVersion;
LAddr, LText: string;
LPort: integer;
LSocket: TIdSocketHandle;
begin
ADest.Clear;
LItems := TStringList.Create;
try
LItems.CommaText := AList;
for i := 0 to LItems.Count-1 do begin
if Length(LItems[i]) > 0 then begin
if TextStartsWith(LItems[i], '[') then begin
// ipv6
LIPVersion := Id_IPv6;
LText := Copy(LItems[i], 2, MaxInt);
LAddr := Fetch(LText, ']:');
LPort := StrToIntDef(LText, -1);
end else begin
// ipv4
LIPVersion := Id_IPv4;
LText := LItems[i];
LAddr := Fetch(LText, ':');
LPort := StrToIntDef(LText, -1);
//Note that 0 is legal and indicates the server binds to a random port
end;
if IsValidIP(LAddr) and (LPort > -1) and (LPort < 65536) then begin
LSocket := ADest.Add;
LSocket.IPVersion := LIPVersion;
LSocket.IP := LAddr;
LSocket.Port := LPort;
end;
end;
end;
finally
LItems.Free;
end;
end;
{ TIdDsnPropEdBindingVCL }
function NumericOnly(const AText : String) : String;
var
i : Integer;
begin
Result := '';
for i := 1 to Length(AText) do
begin
if IsNumeric(AText[i]) then begin
Result := Result + AText[i];
end else begin
Break;
end;
end;
if Length(Result) = 0 then begin
Result := '0';
end;
end;
function IndexOfNo(const ANo : Integer; AStrings : TStrings) : Integer;
begin
for Result := 0 to AStrings.Count-1 do
begin
if ANo = IndyStrToInt(NumericOnly(AStrings[Result])) then begin
Exit;
end;
end;
Result := -1;
end;
function GetDisplayString(ASocketHandle: TIdSocketHandle): string;
begin
Result := '';
case ASocketHandle.IPVersion of
Id_IPv4 : Result := Format('%s:%d',[ASocketHandle.IP, ASocketHandle.Port]);
Id_IPv6 : Result := Format('[%s]:%d',[ASocketHandle.IP, ASocketHandle.Port]);
end;
end;
function GetListValues(const ASocketHandles : TIdSocketHandles) : String;
var i : Integer;
begin
Result := '';
for i := 0 to ASocketHandles.Count -1 do begin
Result := Result + ',' + GetDisplayString(ASocketHandles[i]);
end;
Delete(Result,1,1);
end;
constructor TIdDsnPropEdBindingVCL.Create(AOwner: TComponent);
var
i : Integer;
LLocalAddresses: TIdStackLocalAddressList;
begin
inherited CreateNew(AOwner, 0);
{$IFNDEF WIDGET_KYLIX}
Borderstyle := bsDialog;
{$ENDIF}
BorderIcons := [biSystemMenu];
// Width := 480;
// Height := 252;
ClientWidth := 472;
{$IFDEF USE_TBitBtn}
ClientHeight := 230;
{$ELSE}
ClientHeight := 225;
{$ENDIF}
Constraints.MaxWidth := Width;
Constraints.MaxHeight := Height;
Constraints.MinWidth := Width;
Constraints.MinHeight := Height;
Position := poScreenCenter;
lblBindings := TLabel.Create(Self);
lbBindings := TListBox.Create(Self);
ActionList1 := TActionList.Create(Self);
btnBindingsNew := TAction.Create(Self);
btnBindingsDelete := TAction.Create(Self);
btnNew := TButton.Create(Self);
btnDelete := TButton.Create(Self);
lblIPAddress := TLabel.Create(Self);
edtIPAddress := TComboBox.Create(Self);
lblPort := TLabel.Create(Self);
edtPort := TComboBox.Create(Self);
rdoBindingType := TRadioGroup.Create(Self);
{$IFDEF USE_TBitBtn}
btnOk := TBitBtn.Create(Self);
btnCancel := TBitBtn.Create(Self);
{$ELSE}
btnOk := TButton.Create(Self);
btnCancel := TButton.Create(Self);
{$ENDIF}
lblBindings.Name := 'lblBindings'; {do not localize}
lblBindings.Parent := Self;
lblBindings.Left := 8;
lblBindings.Top := 8;
lblBindings.Width := 35;
lblBindings.Height := 13;
lblBindings.Caption := '&Binding'; {do not localize}
lbBindings.Name := 'lbBindings'; {do not localize}
lbBindings.Parent := Self;
lbBindings.Left := 8;
lbBindings.Top := 24;
lbBindings.Width := 137;
lbBindings.Height := 161;
lbBindings.ItemHeight := 13;
lbBindings.TabOrder := 8;
lbBindings.OnClick := lbBindingsClick;
ActionList1.Name := 'ActionList1'; {do not localize}
{
ActionList1.Left := 152;
ActionList1.Top := 32;
}
btnBindingsNew.Name := 'btnBindingsNew'; {do not localize}
btnBindingsNew.Caption := RSBindingNewCaption;
btnBindingsNew.OnExecute := btnBindingsNewExecute;
btnBindingsDelete.Name := 'btnBindingsDelete'; {do not localize}
btnBindingsDelete.Caption := RSBindingDeleteCaption;
btnBindingsDelete.OnExecute := btnBindingsDeleteExecute;
btnBindingsDelete.OnUpdate := btnBindingsDeleteUpdate;
btnNew.Name := 'btnNew'; {do not localize}
btnNew.Parent := Self;
btnNew.Left := 152;
btnNew.Top := 72;
btnNew.Width := 75;
btnNew.Height := 25;
btnNew.Action := btnBindingsNew;
btnNew.TabOrder := 6;
btnDelete.Name := 'btnDelete'; {do not localize}
btnDelete.Parent := Self;
btnDelete.Left := 152;
btnDelete.Top := 104;
btnDelete.Width := 75;
btnDelete.Height := 25;
btnDelete.Action := btnBindingsDelete;
btnDelete.TabOrder := 7;
lblIPAddress.Name := 'lblIPAddress'; {do not localize}
lblIPAddress.Parent := Self;
lblIPAddress.Left := 240;
lblIPAddress.Top := 8;
lblIPAddress.Width := 54;
lblIPAddress.Height := 13;
lblIPAddress.Caption := RSBindingHostnameLabel;
lblIPAddress.Enabled := False;
edtIPAddress.Name := 'edtIPAddress'; {do not localize}
edtIPAddress.Parent := Self;
edtIPAddress.Left := 240;
edtIPAddress.Top := 24;
edtIPAddress.Width := 221;
edtIPAddress.Height := 21;
edtIPAddress.Enabled := False;
edtIPAddress.ItemHeight := 13;
edtIPAddress.TabOrder := 3;
edtIPAddress.OnChange := edtIPAddressChange;
lblPort.Name := 'lblPort'; {do not localize}
lblPort.Parent := Self;
lblPort.Left := 240;
lblPort.Top := 56;
lblPort.Width := 22;
lblPort.Height := 13;
lblPort.Caption := RSBindingPortLabel;
lblPort.Enabled := False;
lblPort.FocusControl := edtPort;
edtPort.Name := 'edtPort'; {do not localize}
edtPort.Parent := Self;
edtPort.Left := 240;
edtPort.Top := 72;
edtPort.Width := 221;
edtPort.Height := 21;
edtPort.Enabled := False;
edtPort.ItemHeight := 13;
edtPort.TabOrder := 4;
edtPort.OnChange := edtPortChange;
edtPort.OnKeyPress := edtPortKeyPress;
rdoBindingType.Name := 'rdoBindingType'; {do not localize}
rdoBindingType.Parent := Self;
rdoBindingType.Left := 240;
rdoBindingType.Top := 120;
rdoBindingType.Width := 221;
rdoBindingType.Height := 65;
rdoBindingType.Caption := RSBindingIPVerLabel;
rdoBindingType.Enabled := False;
rdoBindingType.Items.Add(RSBindingIPV4Item);
rdoBindingType.Items.Add(RSBindingIPV6Item);
rdoBindingType.TabOrder := 5;
rdoBindingType.OnClick := rdoBindingTypeClick;
btnOk.Name := 'btnOk'; {do not localize}
btnOk.Parent := Self;
btnOk.Anchors := [akRight, akBottom];
btnOk.Left := 306;
btnOk.Top := 193;
btnOk.Width := 75;
{$IFDEF USE_TBitBtn}
btnOk.Height := 30;
btnOk.Kind := bkOk;
{$ELSE}
btnOk.Height := 25;
btnOk.Caption := RSOk;
btnOk.Default := True;
btnOk.ModalResult := 1;
{$ENDIF}
btnOk.TabOrder := 0;
btnCancel.Name := 'btnCancel'; {do not localize}
btnCancel.Parent := Self;
btnCancel.Anchors := [akRight, akBottom];
btnCancel.Left := 386;
btnCancel.Top := 193;
btnCancel.Width := 75;
{$IFDEF USE_TBitBtn}
btnCancel.Height := 30;
btnCancel.Kind := bkCancel;
{$ELSE}
btnCancel.Height := 25;
btnCancel.Cancel := True;
btnCancel.Caption := RSCancel;
btnCancel.ModalResult := 2;
{$ENDIF}
btnCancel.Anchors := [akRight, akBottom];
btnCancel.TabOrder := 1;
FHandles := TIdSocketHandles.Create(nil);
FIPv4Addresses := TStringList.Create;
FIPv6Addresses := TStringList.Create;
SetIPv4Addresses(nil);
SetIPv6Addresses(nil);
TIdStack.IncUsage;
try
LLocalAddresses := TIdStackLocalAddressList.Create;
try
GStack.GetLocalAddressList(LLocalAddresses);
for i := 0 to LLocalAddresses.Count-1 do
begin
case LLocalAddresses[i].IPVersion of
Id_IPv4: FIPv4Addresses.Add(LLocalAddresses[i].IPAddress);
Id_IPv6: FIPv6Addresses.Add(LLocalAddresses[i].IPAddress);
end;
end;
finally
LLocalAddresses.Free;
end;
finally
TIdStack.DecUsage;
end;
edtPort.Items.BeginUpdate;
try
edtPort.Items.Add(PortDescription(0));
for i := 0 to IdPorts.Count - 1 do begin
edtPort.Items.Add(
PortDescription(
{$IFDEF HAS_GENERICS_TList}
IdPorts[i]
{$ELSE}
PtrInt(IdPorts[i])
{$ENDIF}
)
);
end;
finally
edtPort.Items.EndUpdate;
end;
AutoScroll := False;
Caption := RSBindingFormCaption;
{$IFDEF WIDGET_VCL}
Scaled := False;
{$ENDIF}
Font.Color := clBtnText;
Font.Height := -11;
Font.Name := 'MS Sans Serif'; {Do not Localize}
Font.Style := [];
Position := poScreenCenter;
PixelsPerInch := 96;
FInUpdateRoutine := False;
UpdateEditControls;
end;
destructor TIdDsnPropEdBindingVCL.Destroy;
begin
FreeAndNil(FIPv4Addresses);
FreeAndNil(FIPv6Addresses);
FreeAndNil(FHandles);
inherited Destroy;
end;
function TIdDsnPropEdBindingVCL.PortDescription(const PortNumber: integer): string;
var
LList: TStringList;
begin
if PortNumber = 0 then begin
Result := IndyFormat('%d: %s', [PortNumber, RSBindingAny]);
end else begin
Result := ''; {Do not Localize}
LList := TStringList.Create;
try
GBSDStack.AddServByPortToList(PortNumber, LList);
if LList.Count > 0 then begin
Result := Format('%d: %s', [PortNumber, LList.CommaText]); {Do not Localize}
end;
finally
LList.Free;
end;
end;
end;
procedure TIdDsnPropEdBindingVCL.SetHandles(const Value: TIdSocketHandles);
begin
FHandles.Assign(Value);
UpdateBindingList;
end;
procedure TIdDsnPropEdBindingVCL.btnBindingsNewExecute(Sender: TObject);
begin
FCurrentHandle := FHandles.Add;
FCurrentHandle.IP := IPv4Wildcard;
FCurrentHandle.Port := FDefaultPort;
UpdateBindingList;
edtIPAddress.Items.Assign(FIPv4Addresses);
UpdateEditControls;
end;
procedure TIdDsnPropEdBindingVCL.UpdateEditControls;
var
i : Integer;
begin
if Assigned(FCurrentHandle) then
begin
i := IndexOfNo(FCurrentHandle.Port,edtPort.Items);
if i = -1 then begin
edtPort.Text := IntToStr(FCurrentHandle.Port);
end else begin
edtPort.ItemIndex := i;
end;
case FCurrentHandle.IPVersion of
Id_IPv4 :
begin
rdoBindingType.ItemIndex := 0;
edtIPAddress.Items.Assign(FIPv4Addresses);
end;
Id_IPv6 :
begin
rdoBindingType.ItemIndex := 1;
edtIPAddress.Items.Assign(FIPv6Addresses);
end;
end;
if edtIPAddress.Style = csDropDown then begin
edtIPAddress.Text := FCurrentHandle.IP;
end else begin
edtIPAddress.ItemIndex := edtIPAddress.Items.IndexOf(FCurrentHandle.IP);
end;
end
else
begin
edtIPAddress.Text := '';
//in LCL, the line below caused an index out of range error.
{$IFDEF WIDGET_VCL}
edtPort.ItemIndex := -1; //-2;
{$ENDIF}
edtPort.Text := '';
end;
lblIPAddress.Enabled := Assigned(FCurrentHandle);
edtIPAddress.Enabled := Assigned(FCurrentHandle);
lblPort.Enabled := Assigned(FCurrentHandle);
edtPort.Enabled := Assigned(FCurrentHandle);
rdoBindingType.Enabled := Assigned(FCurrentHandle);
{$IFDEF WIDGET_KYLIX}
//WOrkaround for CLX quirk that might be Kylix 1
for i := 0 to rdoBindingType.ControlCount -1 do begin
rdoBindingType.Controls[i].Enabled := Assigned(FCurrentHandle);
end;
{$ENDIF}
{$IFDEF WIDGET_VCL_LIKE}
//The Win32 VCL does not change the control background to a greyed look
//when controls are disabled. This quirk is not present in CLX.
if Assigned(FCurrentHandle) then
begin
edtIPAddress.Color := clWindow;
edtPort.Color := clWindow;
end else
begin
edtIPAddress.Color := clBtnFace;
edtPort.Color := clBtnFace;
end;
{$ENDIF}
end;
procedure TIdDsnPropEdBindingVCL.btnBindingsDeleteExecute(Sender: TObject);
var
LSH : TIdSocketHandle;
begin
if lbBindings.ItemIndex >= 0 then
begin
// Delete is not available in D4's collection classes
// This should work just as well.
LSH := Handles[lbBindings.ItemIndex];
FreeAndNil(LSH);
FCurrentHandle := nil;
UpdateBindingList;
end;
lbBindingsClick(nil);
UpdateEditControls;
end;
procedure TIdDsnPropEdBindingVCL.btnBindingsDeleteUpdate(Sender: TObject);
begin
btnBindingsDelete.Enabled := lbBindings.ItemIndex >= 0;
end;
procedure TIdDsnPropEdBindingVCL.SetIPv4Addresses(const Value: TStrings);
begin
if Assigned(Value) then begin
FIPv4Addresses.Assign(Value);
end;
// Ensure that these two are always present
if FIPv4Addresses.IndexOf(IPv6Loopback) = -1 then begin
FIPv4Addresses.Insert(0, IPv4Loopback);
end;
if FIPv4Addresses.IndexOf(IPv4Wildcard) = -1 then begin
FIPv4Addresses.Insert(0, IPv4Wildcard);
end;
end;
procedure TIdDsnPropEdBindingVCL.SetIPv6Addresses(const Value: TStrings);
begin
if Assigned(Value) then begin
FIPv6Addresses.Assign(Value);
end;
// Ensure that these two are always present
if FIPv6Addresses.IndexOf(IPv6Loopback) = -1 then begin
FIPv6Addresses.Insert(0, IPv6Loopback);
end;
if FIPv6Addresses.IndexOf(IPv6Wildcard1) = -1 then begin
FIPv6Addresses.Insert(0, IPv6Wildcard1);
end;
end;
procedure TIdDsnPropEdBindingVCL.edtPortKeyPress(Sender: TObject; var Key: Char);
begin
// RLebeau 1/7/09: using Char() for #128-#255 because in D2009, the compiler
// may change characters >= #128 from their Ansi codepage value to their true
// Unicode codepoint value, depending on the codepage used for the source code.
// For instance, #128 may become #$20AC...
if (Key > Chr(31)) and (Key < Chr(128)) then begin
if not IsNumeric(Key) then begin
Key := #0;
end;
end;
end;
procedure TIdDsnPropEdBindingVCL.edtIPAddressChange(Sender: TObject);
begin
FCurrentHandle.IP := edtIPAddress.Text;
UpdateBindingList;
end;
procedure TIdDsnPropEdBindingVCL.edtPortChange(Sender: TObject);
begin
if Assigned(FCurrentHandle) then begin
FCurrentHandle.Port := IndyStrToInt(NumericOnly(edtPort.Text), 0);
end;
UpdateBindingList;
end;
procedure TIdDsnPropEdBindingVCL.rdoBindingTypeClick(Sender: TObject);
begin
case rdoBindingType.ItemIndex of
0 :
begin
if FCurrentHandle.IPVersion <> Id_IPv4 then
begin
FCurrentHandle.IPVersion := Id_IPv4;
edtIPAddress.Items.Assign(FIPv4Addresses);
FCurrentHandle.IP := IPv4Wildcard;
end;
end;
1 :
begin
if FCurrentHandle.IPVersion <> Id_IPv6 then
begin
FCurrentHandle.IPVersion := Id_IPv6;
edtIPAddress.Items.Assign(FIPv6Addresses);
FCurrentHandle.IP := IPv6Wildcard1;
end;
end;
end;
UpdateEditControls;
UpdateBindingList;
end;
function TIdDsnPropEdBindingVCL.GetList: string;
begin
Result := GetListValues(Handles);
end;
procedure TIdDsnPropEdBindingVCL.lbBindingsClick(Sender: TObject);
begin
if lbBindings.ItemIndex >= 0 then begin
FCurrentHandle := FHandles[lbBindings.ItemIndex];
end else begin
FCurrentHandle := nil;
end;
UpdateEditControls;
end;
procedure TIdDsnPropEdBindingVCL.SetList(const AList: string);
begin
FCurrentHandle := nil;
FillHandleList(AList, Handles);
UpdateBindingList;
UpdateEditControls;
end;
procedure TIdDsnPropEdBindingVCL.UpdateBindingList;
var
i: integer;
selected: integer;
s: string;
begin
//in Lazarus, for some odd reason, if you have more than one binding,
//the routine is called while the items are updated
if FInUpdateRoutine then begin
Exit;
end;
FInUpdateRoutine := True;
try
selected := lbBindings.ItemIndex;
lbBindings.Items.BeginUpdate;
try
if lbBindings.Items.Count = FHandles.Count then begin
for i := 0 to FHandles.Count - 1 do begin
s := GetDisplayString(FHandles[i]);
if s <> lbBindings.Items[i] then begin
lbBindings.Items[i] := s;
end;
end;
end else begin
lbBindings.Items.Clear;
for i := 0 to FHandles.Count-1 do begin
lbBindings.Items.Add(GetDisplayString(FHandles[i]));
end;
end;
finally
lbBindings.Items.EndUpdate;
if Assigned(FCurrentHandle) then begin
lbBindings.ItemIndex := FCurrentHandle.Index;
end else begin
lbBindings.ItemIndex := IndyMin(selected, lbBindings.Items.Count-1);
end;
end;
finally
FInUpdateRoutine := False;
end;
end;
function TIdDsnPropEdBindingVCL.Execute: Boolean;
begin
Result := ShowModal = mrOk;
end;
constructor TIdDsnPropEdBindingVCL.Create;
begin
Create(nil);
end;
end.

View File

@@ -0,0 +1,191 @@
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.3 09/06/2004 09:52:34 CCostelloe
Kylix 3 patch
Rev 1.2 6/4/2004 5:12:56 PM SGrobety
added EIdMaxCaptureLineExceeded
Rev 1.1 2/10/2004 7:41:50 PM JPMugaas
I had to move EWrapperException down to the system package because
IdStackDotNET was using it and that would drage IdExceptionCore into the
package. Borland changed some behavior so the warning is now an error.
Rev 1.0 2004.02.03 4:19:48 PM czhower
Rename
Rev 1.15 11/4/2003 10:26:58 PM DSiders
Added exceptions moved from IdIOHandler.pas and IdTCPConnection.pas.
Rev 1.14 2003.10.16 11:24:00 AM czhower
Added IfAssigned
Rev 1.13 2003.10.11 5:47:58 PM czhower
-VCL fixes for servers
-Chain suport for servers (Super core)
-Scheduler upgrades
-Full yarn support
Rev 1.12 10/3/2003 11:38:36 PM GGrieve
Add EIdWrapperException
Rev 1.11 9/29/2003 02:56:28 PM JPMugaas
Added comment about why IdException.Create is virtual.
Rev 1.10 9/24/2003 11:42:50 PM JPMugaas
Minor changes to help compile under NET
Rev 1.9 2003.09.19 10:10:02 PM czhower
IfTrue, IfFalse
Rev 1.8 2003.09.19 11:54:28 AM czhower
-Completed more features necessary for servers
-Fixed some bugs
Rev 1.7 2003.07.17 4:57:04 PM czhower
Added new exception type so it can be added to debugger list of ignored
exceptions.
Rev 1.6 7/1/2003 8:33:02 PM BGooijen
Added EIdFibersNotSupported
Rev 1.5 2003.06.05 10:08:50 AM czhower
Extended reply mechanisms to the exception handling. Only base and RFC
completed, handing off to J Peter.
Rev 1.4 5/14/2003 2:59:58 PM BGooijen
Added exception for transparant proxy
Rev 1.3 2003.04.14 10:54:06 AM czhower
Fiber specific exceptions
Rev 1.2 4/2/2003 7:18:38 PM BGooijen
Added EIdHttpProxyError
Rev 1.1 1/17/2003 05:06:46 PM JPMugaas
Exceptions for scheduler string.
Rev 1.0 11/13/2002 08:44:10 AM JPMugaas
}
unit IdExceptionCore;
interface
{$I IdCompilerDefines.inc}
//needed to put FCP into Delphi mode
uses
IdException, IdStack;
type
// IdFiber Exceptions
EIdFiber = class(EIdException);
EIdFiberFinished = class(EIdFiber);
EIdFibersNotSupported = class(EIdFiber);
EIdAlreadyConnected = class(EIdException);
// EIdClosedSocket is raised if .Disconnect has been called and an operation is attempted
// or Connect has not been called
EIdClosedSocket = class(EIdException);
EIdResponseError = class(EIdException);
EIdReadTimeout = class(EIdException);
EIdAcceptTimeout = class(EIdException);
EIdReadLnMaxLineLengthExceeded = class(EIdException);
EIdReadLnWaitMaxAttemptsExceeded = class(EIdException);
// TIdTCPConnection exceptions
EIdPortRequired = class(EIdException);
EIdHostRequired = class(EIdException);
EIdTCPConnectionError = class(EIdException);
EIdObjectTypeNotSupported = class(EIdTCPConnectionError);
EIdInterceptPropIsNil = class(EIdTCPConnectionError);
EIdInterceptPropInvalid = class(EIdTCPConnectionError);
EIdIOHandlerPropInvalid = class(EIdTCPConnectionError);
EIdNoDataToRead = class(EIdTCPConnectionError);
EIdFileNotFound = class(EIdTCPConnectionError);
EIdNotConnected = class(EIdException);
EInvalidSyslogMessage = class(EIdException);
EIdSSLProtocolReplyError = class(EIdException);
EIdConnectTimeout = class(EIdException);
EIdConnectException = class(EIdException);
EIdTransparentProxyCantBind = class(EIdException);
EIdHttpProxyError = class(EIdException);
EIdSocksError = class(EIdException);
EIdSocksRequestFailed = class(EIdSocksError);
EIdSocksRequestServerFailed = class(EIdSocksError);
EIdSocksRequestIdentFailed = class(EIdSocksError);
EIdSocksUnknownError = class(EIdSocksError);
EIdSocksServerRespondError = class(EIdSocksError);
EIdSocksAuthMethodError = class(EIdSocksError);
EIdSocksAuthError = class(EIdSocksError);
EIdSocksServerGeneralError = class(EIdSocksError);
EIdSocksServerPermissionError = class (EIdSocksError);
EIdSocksServerNetUnreachableError = class (EIdSocksError);
EIdSocksServerHostUnreachableError = class (EIdSocksError);
EIdSocksServerConnectionRefusedError = class (EIdSocksError);
EIdSocksServerTTLExpiredError = class (EIdSocksError);
EIdSocksServerCommandError = class (EIdSocksError);
EIdSocksServerAddressError = class (EIdSocksError);
//IdIMAP4 Exception
EIdConnectionStateError = class(EIdException);
// THE EDnsResolverError is used so the resolver can repond to only resolver execeptions.
EIdDnsResolverError = Class(EIdException);
{Socket exceptions}
EIdInvalidSocket = class(EIdException);
EIdThreadMgrError = class(EIdException);
EIdThreadClassNotSpecified = class(EIdThreadMgrError);
{TIdTrivial FTP Exception }
EIdTFTPException = class(EIdException);
EIdTFTPFileNotFound = class(EIdTFTPException);
EIdTFTPAccessViolation = class(EIdTFTPException);
EIdTFTPAllocationExceeded = class(EIdTFTPException);
EIdTFTPIllegalOperation = class(EIdTFTPException);
EIdTFTPUnknownTransferID = class(EIdTFTPException);
EIdTFTPFileAlreadyExists = class(EIdTFTPException);
EIdTFTPNoSuchUser = class(EIdTFTPException);
EIdTFTPOptionNegotiationFailed = class(EIdTFTPException); // RFC 1782
{Icmp exceptions}
EIdIcmpException = class(EIdException);
EIdSetSizeExceeded = class(EIdException);
{IdMessage and things use this}
EIdMessageException = class(EIdException);
//scheduler exception
EIdSchedulerException = class(EIdException);
EIdSchedulerMaxThreadsExceeded = class(EIdSchedulerException);
{ IdIOHandler }
EIdMaxCaptureLineExceeded = class(EIdException); // S.G. 6/4/2004: triggered when a capture command exceeds the maximum number of line allowed
implementation
end.

View File

@@ -0,0 +1,48 @@
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.2 8/16/2004 1:08:46 PM JPMugaas
Failed to compile in some IDE's.
Rev 1.1 2004.08.13 21:46:20 czhower
Fix for .NET
Rev 1.0 2004.08.13 10:54:58 czhower
Initial checkin
}
unit IdGlobalCore;
interface
{$I IdCompilerDefines.inc}
uses
Classes,
IdGlobal;
const
{$IFDEF UNIX}
tpListener = tpNormal;
{$ELSE}
tpListener = tpHighest;
{$ENDIF}
implementation
end.

2695
indy/Core/IdIOHandler.pas Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,575 @@
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.38 11/10/2004 8:25:54 AM JPMugaas
Fix for AV caused by short-circut boolean evaluation.
Rev 1.37 27.08.2004 21:58:20 Andreas Hausladen
Speed optimization ("const" for string parameters)
Rev 1.36 8/2/04 5:44:40 PM RLebeau
Moved ConnectTimeout over from TIdIOHandlerStack
Rev 1.35 7/21/2004 12:22:32 PM BGooijen
Fix to .connected
Rev 1.34 6/30/2004 12:31:34 PM BGooijen
Added OnSocketAllocated
Rev 1.33 4/24/04 12:52:52 PM RLebeau
Added setter method to UseNagle property
Rev 1.32 2004.04.18 12:52:02 AM czhower
Big bug fix with server disconnect and several other bug fixed that I found
along the way.
Rev 1.31 2004.02.03 4:16:46 PM czhower
For unit name changes.
Rev 1.30 2/2/2004 11:46:46 AM BGooijen
Dotnet and TransparentProxy
Rev 1.29 2/1/2004 9:44:00 PM JPMugaas
Start on reenabling Transparant proxy.
Rev 1.28 2004.01.20 10:03:28 PM czhower
InitComponent
Rev 1.27 1/2/2004 12:02:16 AM BGooijen
added OnBeforeBind/OnAfterBind
Rev 1.26 12/31/2003 9:51:56 PM BGooijen
Added IPv6 support
Rev 1.25 11/4/2003 10:37:40 PM BGooijen
JP's patch to fix the bound port
Rev 1.24 10/19/2003 5:21:26 PM BGooijen
SetSocketOption
Rev 1.23 10/18/2003 1:44:06 PM BGooijen
Added include
Rev 1.22 2003.10.14 1:26:54 PM czhower
Uupdates + Intercept support
Rev 1.21 10/9/2003 8:09:06 PM SPerry
bug fixes
Rev 1.20 8/10/2003 2:05:50 PM SGrobety
Dotnet
Rev 1.19 2003.10.07 10:18:26 PM czhower
Uncommneted todo code that is now non dotnet.
Rev 1.18 2003.10.02 8:23:42 PM czhower
DotNet Excludes
Rev 1.17 2003.10.01 9:11:18 PM czhower
.Net
Rev 1.16 2003.10.01 5:05:12 PM czhower
.Net
Rev 1.15 2003.10.01 2:46:38 PM czhower
.Net
Rev 1.14 2003.10.01 11:16:32 AM czhower
.Net
Rev 1.13 2003.09.30 1:22:58 PM czhower
Stack split for DotNet
Rev 1.12 7/4/2003 08:26:44 AM JPMugaas
Optimizations.
Rev 1.11 7/1/2003 03:39:44 PM JPMugaas
Started numeric IP function API calls for more efficiency.
Rev 1.10 2003.06.30 5:41:56 PM czhower
-Fixed AV that occurred sometimes when sockets were closed with chains
-Consolidated code that was marked by a todo for merging as it no longer
needed to be separate
-Removed some older code that was no longer necessary
Passes bubble tests.
Rev 1.9 6/3/2003 11:45:58 PM BGooijen
Added .Connected
Rev 1.8 2003.04.22 7:45:34 PM czhower
Rev 1.7 4/2/2003 3:24:56 PM BGooijen
Moved transparantproxy from ..stack to ..socket
Rev 1.6 2/28/2003 9:51:56 PM BGooijen
removed the field: FReadTimeout: Integer, it hided the one in TIdIOHandler
Rev 1.5 2/26/2003 1:15:38 PM BGooijen
FBinding is now freed in IdIOHandlerSocket, instead of in IdIOHandlerStack
Rev 1.4 2003.02.25 1:36:08 AM czhower
Rev 1.3 2002.12.07 12:26:26 AM czhower
Rev 1.2 12-6-2002 20:09:14 BGooijen
Changed SetDestination to search for the last ':', instead of the first
Rev 1.1 12-6-2002 18:54:14 BGooijen
Added IPv6-support
Rev 1.0 11/13/2002 08:45:08 AM JPMugaas
}
unit IdIOHandlerSocket;
interface
{$I IdCompilerDefines.inc}
uses
Classes,
IdCustomTransparentProxy,
IdBaseComponent,
IdGlobal,
IdIOHandler,
IdSocketHandle;
const
IdDefTimeout = 0;
IdBoundPortDefault = 0;
type
{
TIdIOHandlerSocket is the base class for socket IOHandlers that implement a
binding.
Descendants
-TIdIOHandlerStack
-TIdIOHandlerChain
}
TIdIOHandlerSocket = class(TIdIOHandler)
protected
FBinding: TIdSocketHandle;
FBoundIP: string;
FBoundPort: TIdPort;
FBoundPortMax: TIdPort;
FBoundPortMin: TIdPort;
FDefaultPort: TIdPort;
FOnBeforeBind: TNotifyEvent;
FOnAfterBind: TNotifyEvent;
FOnSocketAllocated: TNotifyEvent;
{$IFDEF USE_OBJECT_ARC}[Weak]{$ENDIF} FTransparentProxy: TIdCustomTransparentProxy;
FImplicitTransparentProxy: Boolean;
FUseNagle: Boolean;
FReuseSocket: TIdReuseSocket;
FIPVersion: TIdIPVersion;
//
procedure ConnectClient; virtual;
procedure DoBeforeBind; virtual;
procedure DoAfterBind; virtual;
procedure DoSocketAllocated; virtual;
procedure InitComponent; override;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
function GetDestination: string; override;
procedure SetDestination(const AValue: string); override;
function GetReuseSocket: TIdReuseSocket;
procedure SetReuseSocket(AValue: TIdReuseSocket);
function GetTransparentProxy: TIdCustomTransparentProxy; virtual;
procedure SetTransparentProxy(AProxy: TIdCustomTransparentProxy); virtual;
function GetUseNagle: Boolean;
procedure SetUseNagle(AValue: Boolean);
//
function SourceIsAvailable: Boolean; override;
function CheckForError(ALastResult: Integer): Integer; override;
procedure RaiseError(AError: Integer); override;
public
procedure AfterAccept; override;
destructor Destroy; override;
function BindingAllocated: Boolean;
procedure Close; override;
function Connected: Boolean; override;
procedure Open; override;
function WriteFile(const AFile: String; AEnableTransferFile: Boolean = False): Int64; override;
//
property Binding: TIdSocketHandle read FBinding;
property BoundPortMax: TIdPort read FBoundPortMax write FBoundPortMax;
property BoundPortMin: TIdPort read FBoundPortMin write FBoundPortMin;
// events
property OnBeforeBind: TNotifyEvent read FOnBeforeBind write FOnBeforeBind;
property OnAfterBind: TNotifyEvent read FOnAfterBind write FOnAfterBind;
property OnSocketAllocated: TNotifyEvent read FOnSocketAllocated write FOnSocketAllocated;
published
property BoundIP: string read FBoundIP write FBoundIP;
property BoundPort: TIdPort read FBoundPort write FBoundPort default IdBoundPortDefault;
property DefaultPort: TIdPort read FDefaultPort write FDefaultPort;
property IPVersion: TIdIPVersion read FIPVersion write FIPVersion default ID_DEFAULT_IP_VERSION;
property ReuseSocket: TIdReuseSocket read GetReuseSocket write SetReuseSocket default rsOSDependent;
property TransparentProxy: TIdCustomTransparentProxy read GetTransparentProxy write SetTransparentProxy;
property UseNagle: boolean read GetUseNagle write SetUseNagle default True;
end;
implementation
uses
//facilitate inlining only.
{$IFDEF DOTNET}
{$IFDEF USE_INLINE}
System.IO,
{$ENDIF}
{$ENDIF}
{$IFDEF WIN32_OR_WIN64 }
Windows,
{$ENDIF}
SysUtils,
IdStack,
IdStackConsts,
IdSocks;
{ TIdIOHandlerSocket }
procedure TIdIOHandlerSocket.AfterAccept;
begin
inherited AfterAccept;
FIPVersion := FBinding.IPVersion;
end;
procedure TIdIOHandlerSocket.Close;
begin
if FBinding <> nil then begin
FBinding.CloseSocket;
end;
inherited Close;
end;
procedure TIdIOHandlerSocket.ConnectClient;
var
LBinding: TIdSocketHandle;
begin
LBinding := Binding;
DoBeforeBind;
// Allocate the socket
LBinding.IPVersion := FIPVersion;
LBinding.AllocateSocket;
DoSocketAllocated;
// Bind the socket
if BoundIP <> '' then begin
LBinding.IP := BoundIP;
end;
LBinding.Port := BoundPort;
LBinding.ClientPortMin := BoundPortMin;
LBinding.ClientPortMax := BoundPortMax;
LBinding.ReuseSocket := FReuseSocket;
// RLebeau 11/15/2014: Using the socket bind() function in a Mac OSX sandbox
// causes the Apple store to reject an app with the following error if it
// uses Indy client(s) and no Indy server(s):
//
// "This app uses one or more entitlements which do not have matching
// functionality within the app. Apps should have only the minimum set of
// entitlements necessary for the app to function properly. Please remove
// all entitlements that are not needed by your app and submit an updated
// binary for review, including the following:
//
// com.apple.security.network.server"
//
// Ideally, TIdSocketHandle.Bind() should not call TryBind() if the IP is
// blank and the Port, ClientPortMin, and ClientPortMax are all 0. However,
// TIdSocketHandle.Bind() is used for both clients and servers, and sometimes
// a server needs to bind to port 0 to get a random ephemeral port, which it
// can then report to clients. So lets do the check here instead, as this
// method is only used for clients...
{$IFDEF DARWIN}
// TODO: remove the DARWIN check and just skip the Bind() on all platforms?
if (LBinding.IP <> '') or (LBinding.Port <> 0) or
((LBinding.ClientPortMin <> 0) and (LBinding.ClientPortMax <> 0)) then
begin
LBinding.Bind;
end;
{$ELSE}
LBinding.Bind;
{$ENDIF}
// Turn off Nagle if specified
LBinding.UseNagle := FUseNagle;
DoAfterBind;
end;
function TIdIOHandlerSocket.Connected: Boolean;
begin
Result := (BindingAllocated and inherited Connected) or (not InputBufferIsEmpty);
end;
destructor TIdIOHandlerSocket.Destroy;
begin
SetTransparentProxy(nil);
FreeAndNil(FBinding);
inherited Destroy;
end;
procedure TIdIOHandlerSocket.DoBeforeBind;
begin
if Assigned(FOnBeforeBind) then begin
FOnBeforeBind(self);
end;
end;
procedure TIdIOHandlerSocket.DoAfterBind;
begin
if Assigned(FOnAfterBind) then begin
FOnAfterBind(self);
end;
end;
procedure TIdIOHandlerSocket.DoSocketAllocated;
begin
if Assigned(FOnSocketAllocated) then begin
FOnSocketAllocated(self);
end;
end;
function TIdIOHandlerSocket.GetDestination: string;
begin
Result := Host;
if (Port <> DefaultPort) and (Port > 0) then begin
Result := Host + ':' + IntToStr(Port);
end;
end;
procedure TIdIOHandlerSocket.Open;
begin
inherited Open;
if not Assigned(FBinding) then begin
FBinding := TIdSocketHandle.Create(nil);
end else begin
FBinding.Reset(True);
end;
FBinding.ClientPortMin := BoundPortMin;
FBinding.ClientPortMax := BoundPortMax;
//if the IOHandler is used to accept connections then port+host will be empty
if (Host <> '') and (Port > 0) then begin
ConnectClient;
end;
end;
procedure TIdIOHandlerSocket.SetDestination(const AValue: string);
var
LPortStart: integer;
begin
// Bas Gooijen 06-Dec-2002: Changed to search the last ':', instead of the first:
LPortStart := LastDelimiter(':', AValue);
if LPortStart > 0 then begin
Host := Copy(AValue, 1, LPortStart-1);
Port := IndyStrToInt(Trim(Copy(AValue, LPortStart + 1, $FF)), DefaultPort);
end;
end;
function TIdIOHandlerSocket.BindingAllocated: Boolean;
begin
Result := FBinding <> nil;
if Result then begin
Result := FBinding.HandleAllocated;
end;
end;
function TIdIOHandlerSocket.WriteFile(const AFile: String;
AEnableTransferFile: Boolean): Int64;
{$IFDEF WIN32_OR_WIN64}
var
LOldErrorMode : Integer;
{$ENDIF}
begin
Result := 0;
{$IFDEF WIN32_OR_WIN64}
LOldErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
try
{$ENDIF}
if FileExists(AFile) then begin
if Assigned(GServeFileProc) and (not WriteBufferingActive)
{and (Intercept = nil)} and AEnableTransferFile
then begin
Result := GServeFileProc(Binding.Handle, AFile);
Exit;
end
else
begin
Result := inherited WriteFile(AFile, AEnableTransferFile);
end;
end;
{$IFDEF WIN32_OR_WIN64}
finally
SetErrorMode(LOldErrorMode)
end;
{$ENDIF}
end;
function TIdIOHandlerSocket.GetReuseSocket: TIdReuseSocket;
begin
if FBinding <> nil then begin
Result := FBinding.ReuseSocket;
end else begin
Result := FReuseSocket;
end;
end;
procedure TIdIOHandlerSocket.SetReuseSocket(AValue: TIdReuseSocket);
begin
FReuseSocket := AValue;
if FBinding <> nil then begin
FBinding.ReuseSocket := AValue;
end;
end;
procedure TIdIOHandlerSocket.SetTransparentProxy(AProxy : TIdCustomTransparentProxy);
var
LClass: TIdCustomTransparentProxyClass;
// under ARC, convert a weak reference to a strong reference before working with it
LTransparentProxy: TIdCustomTransparentProxy;
begin
LTransparentProxy := FTransparentProxy;
if LTransparentProxy <> AProxy then
begin
// All this is to preserve the compatibility with old version
// In the case when we have SocksInfo as object created in runtime without owner form it is treated as temporary object
// In the case when the ASocks points to an object with owner it is treated as component on form.
// under ARC, all weak references to a freed object get nil'ed automatically
if Assigned(AProxy) then begin
if not Assigned(AProxy.Owner) then begin
if Assigned(LTransparentProxy) and (not FImplicitTransparentProxy) then begin
FTransparentProxy := nil;
{$IFNDEF USE_OBJECT_ARC}
LTransparentProxy.RemoveFreeNotification(Self);
{$ENDIF}
end;
LClass := TIdCustomTransparentProxyClass(AProxy.ClassType);
if Assigned(LTransparentProxy) and (LTransparentProxy.ClassType <> LClass) then begin
FTransparentProxy := nil;
FImplicitTransparentProxy := False;
IdDisposeAndNil(LTransparentProxy);
end;
if not Assigned(LTransparentProxy) then begin
LTransparentProxy := LClass.Create(Self);
FTransparentProxy := LTransparentProxy;
FImplicitTransparentProxy := True;
end;
LTransparentProxy.Assign(AProxy);
end else begin
if Assigned(LTransparentProxy) then begin
if FImplicitTransparentProxy then begin
FTransparentProxy := nil;
FImplicitTransparentProxy := False;
IdDisposeAndNil(LTransparentProxy);
end else begin
{$IFNDEF USE_OBJECT_ARC}
LTransparentProxy.RemoveFreeNotification(Self);
{$ENDIF}
end;
end;
FTransparentProxy := AProxy;
{$IFNDEF USE_OBJECT_ARC}
AProxy.FreeNotification(Self);
{$ENDIF}
end;
end
else if Assigned(LTransparentProxy) then begin
if FImplicitTransparentProxy then begin
FTransparentProxy := nil;
FImplicitTransparentProxy := False;
IdDisposeAndNil(LTransparentProxy);
end else begin
FTransparentProxy := nil;
{$IFNDEF USE_OBJECT_ARC}
LTransparentProxy.RemoveFreeNotification(Self);
{$ENDIF}
end;
end;
end;
end;
function TIdIOHandlerSocket.GetTransparentProxy: TIdCustomTransparentProxy;
var
// under ARC, convert a weak reference to a strong reference before working with it
LTransparentProxy: TIdCustomTransparentProxy;
begin
LTransparentProxy := FTransparentProxy;
// Necessary at design time for Borland SOAP support
if LTransparentProxy = nil then begin
LTransparentProxy := TIdSocksInfo.Create(Self); //default
FTransparentProxy := LTransparentProxy;
FImplicitTransparentProxy := True;
end;
Result := LTransparentProxy;
end;
function TIdIOHandlerSocket.GetUseNagle: Boolean;
begin
if FBinding <> nil then begin
Result := FBinding.UseNagle;
end else begin
Result := FUseNagle;
end;
end;
procedure TIdIOHandlerSocket.SetUseNagle(AValue: Boolean);
begin
FUseNagle := AValue;
if FBinding <> nil then begin
FBinding.UseNagle := AValue;
end;
end;
// under ARC, all weak references to a freed object get nil'ed automatically
// so this is mostly redundant
procedure TIdIOHandlerSocket.Notification(AComponent: TComponent; Operation: TOperation);
begin
if (Operation = opRemove) and (AComponent = FTransparentProxy) then begin
FTransparentProxy := nil;
FImplicitTransparentProxy := False;
end;
inherited Notification(AComponent, Operation);
end;
procedure TIdIOHandlerSocket.InitComponent;
begin
inherited InitComponent;
FUseNagle := True;
FIPVersion := ID_DEFAULT_IP_VERSION;
end;
function TIdIOHandlerSocket.SourceIsAvailable: Boolean;
begin
Result := BindingAllocated;
end;
function TIdIOHandlerSocket.CheckForError(ALastResult: Integer): Integer;
begin
Result := GStack.CheckForSocketError(ALastResult, [Id_WSAESHUTDOWN, Id_WSAECONNABORTED, Id_WSAECONNRESET, Id_WSAETIMEDOUT]);
end;
procedure TIdIOHandlerSocket.RaiseError(AError: Integer);
begin
GStack.RaiseSocketError(AError);
end;
end.

View File

@@ -0,0 +1,442 @@
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.53 3/10/05 3:23:16 PM RLebeau
Updated WriteDirect() to access the Intercept property directly.
Rev 1.52 11/12/2004 11:30:16 AM JPMugaas
Expansions for IPv6.
Rev 1.51 11/11/04 12:03:46 PM RLebeau
Updated DoConnectTimeout() to recognize IdTimeoutDefault
Rev 1.50 6/18/04 1:06:58 PM RLebeau
Bug fix for ReadTimeout property
Rev 1.49 5/4/2004 9:57:34 AM JPMugaas