/ProSnooperFx_src/indy10.0.52_source/Protocols/IdDNSServer.pas
Pascal | 4049 lines | 3310 code | 269 blank | 470 comment | 196 complexity | 578e8e1fa30ee866d6d6ba8e0a7036dd MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- { $HDR$}
- {**********************************************************************}
- { Unit archived using Team Coherence }
- { Team Coherence is Copyright 2002 by Quality Software Components }
- { }
- { For further information / comments, visit our WEB site at }
- { http://www.TeamCoherence.com }
- {**********************************************************************}
- {}
- { $Log: 13802: IdDNSServer.pas
- {
- { Rev 1.33 2004.10.27 9:17:46 AM czhower
- { For TIdStrings
- }
- {
- { Rev 1.32 10/26/2004 9:06:32 PM JPMugaas
- { Updated references.
- }
- {
- { Rev 1.31 2004.10.26 1:06:26 PM czhower
- { Further fixes for aliaser
- }
- {
- { Rev 1.30 2004.10.26 12:01:32 PM czhower
- { Resolved alias conflict.
- }
- {
- Rev 1.29 9/15/2004 4:59:52 PM DSiders
- Added localization comments.
- }
- {
- { Rev 1.28 22/07/2004 18:14:22 ANeillans
- { Fixed compile error.
- }
- {
- { Rev 1.27 7/21/04 2:38:04 PM RLebeau
- { Removed redundant string copying in TIdDNS_ProcessThread constructor and
- { procedure QueryDomain() method
- {
- { Removed local variable from TIdDNS_ProcessThread.SendData(), not needed
- }
- {
- { Rev 1.26 2004/7/21 ¤U¤È 06:37:48 DChang
- { Fix compile error in TIdDNS_ProcessThread.SendData, and mark a case statment
- { to comments in TIdDNS_ProcessThread.SaveToCache.
- }
- {
- { Rev 1.25 2004/7/19 ¤U¤È 09:55:52 DChang
- { 1. Move all textmoderecords to IdDNSCommon.pas
- { 2.Making DNS Server load the domain definition file while DNS Server
- { component is active.
- { 3. Add a new event : OnAfterCacheSaved
- { 4. Add Full name condition to indicate if a domain is empty
- { (ConvertDNtoString)
- { 5. Make Query request processed with independent thread.
- { 6. Rewrite TIdDNSServer into multiple thread mode, all queries will search
- { and assemble the answer, and then share the TIdSocketHandle to send answer
- { back.
- { 7. Add version information in TIdDNSServer, so class CHAOS can be taken, but
- { only for the label : "version.bind.".
- { 8. Fix TIdRR_TXT.BinQueryRecord, to make sure it can be parsed in DNS client.
- { 9. Modify the AXFR function, reduce the response data size and quantity.
- { 10. Move all TIdTextModeResourceRecord and derived classes to IdDNSCommon.pas
- }
- {
- { Rev 1.24 7/8/04 11:43:54 PM RLebeau
- { Updated TIdDNS_TCPServer.DoConnect() to use new BytesToString() parameters
- }
- {
- { Rev 1.23 7/7/04 1:45:16 PM RLebeau
- { Compiler fixes
- }
- {
- { Rev 1.22 6/29/04 1:43:30 PM RLebeau
- { Bug fixes for various property setters
- }
- {
- { Rev 1.21 2004.05.20 1:39:32 PM czhower
- { Last of the IdStream updates
- }
- {
- { Rev 1.20 2004.03.01 9:37:06 PM czhower
- { Fixed name conflicts for .net
- }
- {
- { Rev 1.19 2004.02.07 5:03:32 PM czhower
- { .net fixes.
- }
- {
- { Rev 1.18 2/7/2004 5:39:44 AM JPMugaas
- { IdDNSServer should compile in both DotNET and WIn32.
- }
- {
- { Rev 1.17 2004.02.03 5:45:58 PM czhower
- { Name changes
- }
- {
- { Rev 1.16 1/22/2004 8:26:40 AM JPMugaas
- { Ansi* calls changed.
- }
- {
- { Rev 1.15 1/21/2004 2:12:48 PM JPMugaas
- { InitComponent
- }
- {
- { Rev 1.14 12/7/2003 8:07:26 PM VVassiliev
- { string -> TIdBytes
- }
- {
- { Rev 1.13 2003.10.24 10:38:24 AM czhower
- { UDP Server todos
- }
- {
- Rev 1.12 10/19/2003 12:16:30 PM DSiders
- Added localization comments.
- }
- {
- { Rev 1.11 2003.10.12 3:50:40 PM czhower
- { Compile todos
- }
- {
- { Rev 1.10 2003/5/14 ¤W¤È 01:17:36 DChang
- { Fix a flag named denoted in the function which check if a domain correct.
- { Update the logic of UpdateTree functions (make them unified).
- { Update the TextRecord function of all TIdRR_ classes, it checks if the RRName
- { the same as FullName, if RRName = FullName, it will not append the Fullname
- { to RRName.
- }
- {
- { Rev 1.9 2003/5/10 ¤W¤È 01:09:42 DChang
- { Patch the domainlist update when axfr action.
- }
- {
- { Rev 1.8 2003/5/9 ¤W¤È 10:03:36 DChang
- { Modify the sequence of records. To make sure when we resolve MX record, the
- { mail host A record can be additional record section.
- }
- {
- { Rev 1.7 2003/5/8 ¤U¤È 08:11:34 DChang
- { Add TIdDNSMap, TIdDomainNameServerMapping to monitor primary DNS, and
- { detecting if the primary DNS record changed, it will update automatically if
- { necessary.
- }
- {
- { Rev 1.6 2003/5/2 ¤U¤È 03:39:38 DChang
- { Fix all compile warnings and hints.
- }
- {
- { Rev 1.5 4/29/2003 08:26:30 PM DenniesChang
- { Fix TIdDNSServer Create, the older version miss to create the FBindings.
- { fix AXFR procedure, fully support BIND 8 AXFR procedures.
- }
- { Rev 1.4 4/28/2003 02:30:58 PM JPMugaas
- { reverted back to the old one as the new one checked will not compile, has
- { problametic dependancies on Contrs and Dialogs (both not permitted).
- }
- { Rev 1.3 04/28/2003 01:15:10 AM DenniesChang
- }
- {
- { Rev 1.2 4/28/2003 07:00:18 AM JPMugaas
- { Should now compile.
- }
- {
- { Rev 1.0 11/14/2002 02:18:42 PM JPMugaas
- }
- {
- // Ver: 2003-04-28-0115
- // Combine TCP, UDP Tunnel into single TIdDNSServer component.
- // Update TIdDNSServer from TIdUDPServer to TComponent.
- // Ver: 2003-04-26-1810
- // Add AXFR command.
- // Ver: 2002-10-30-1253
- // Add TIdRR_AAAA class, RFC 1884 (Ipv6 AAAA)
- // and add the coresponding fix in TIdDNSServer, but left
- // external search option for future.
- // Ver: 2002-07-10-1610
- // Add a new event : OnAfterSendBack to handle all
- // data logged after query result is sent back to
- // the client.
- // Ver: 2002-05-27-0910
- // Add a check function in SOA loading function.
- // Ver: 2002-04-25-1530
- // IdDNSServer. Ver: 2002-03-12-0900
- // To-do: RFC 2136 Zone transfer must be implemented.
- // Add FindHandedNodeByName to pass the TIdDNTreeNode Object back.
- // Append a blank char when ClearQuota, to avoid the possible of
- // losting a field.
- // Add IdDNTree.SaveToFile
- // Fix SOA RRName assignment.
- // Fix PTRName RRName assignment.
- // Fix TIdDNTreeNode RemoveChild
- // IdDNSServer. Ver: 2002-02-26-1420
- // Convert the DN Tree Node type, earlier verison just
- // store the A, PTR in the upper domain node, current
- // version save SOA and its subdomain in upper node.
- //
- // Moreover, move Cached_Tree, Handed_Tree to public
- // section, for using convinent.
- //
- // I forget return CName data, fixed.
- // Seperate the seaching of Cache and handled tree into 2
- // parts with a flag.
- //IdDNSServer. Ver: 2002-02-24-1715
- // Move TIdDNSServer protected property RootDNS_NET to public
- //IdDNSServer. Ver: 2002-02-23-1800
- Original Programmer: Dennies Chang <dennies@ms4.hinet.net>
- No Copyright. Code is given to the Indy Pit Crew.
- This DNS Server supports only IN record, but not Chaos system.
- Most of resource records in DNS server was stored with text mode,
- event the TREE structure, it's just for convininet.
- Why I did it with this way is tring to increase the speed for
- implementation, with Delphi/Kylix internal class and object,
- we can promise the compatible in Windows and Linux.
- Started: Jan. 20, 2002.
- First Finished: Feb. 23, 2002.
- RFC 1035 WKS record is not implemented.
- ToDO: Load Master File automaticlly when DNS Server Active.
- ToDO: patch WKS record data type.
- ToDO: prepare a Tree Editor for DNS Server Construction. (optional)
- }
- unit IdDNSServer;
- interface
- uses
- Classes,
- IdContainers,
- SysUtils,
- IdAssignedNumbers,
- IdSocketHandle,
- IdIOHandlerSocket,
- IdGlobal,
- IdGlobalProtocols,
- IdBaseComponent,
- IdComponent,
- IdContext,
- IdUDPBase, IdResourceStrings,
- IdExceptionCore,
- IdDNSResolver,
- IdUDPServer,
- IdTCPServer,
- IdThread,
- IdDNSCommon,
- IdTStrings;
- type
- TIdDomainExpireCheckThread = class (TIdThread)
- protected
- FInterval: Cardinal;
- FSender: TObject;
- FTimerEvent: TNotifyEvent;
- FBusy : boolean;
- FDomain : string;
- FHost : string;
- //
- procedure Run; override;
- procedure TimerEvent;
- end;
- // forward declaration.
- TIdDNSMap = class;
- TIdDNS_UDPServer = class;
- // This class is to record the mapping of Domain and its primary DNS IP
- TIdDomainNameServerMapping = class (TObject)
- private
- FHost: string;
- FDomainName: string;
- FBusy : boolean;
- FInterval: Cardinal;
- FList: TIdDNSMap;
- procedure SetHost(const Value: string);
- procedure SetInterval(const Value: Cardinal);
- protected
- CheckScheduler : TIdDomainExpireCheckThread;
- property Interval : Cardinal read FInterval write SetInterval;
- property List : TIdDNSMap read FList write FList;
- public
- constructor Create(List :TIdDNSMap);
- destructor Destroy; override;
- published
- procedure SyncAndUpdate (Sender : TObject);
- property Host : string read FHost write SetHost;
- property DomainName : string read FDomainName write FDomainName;
- end;
- TIdDNSMap = class (TIdObjectList)
- private
- FServer: TIdDNS_UDPServer;
- function GetItem(Index: Integer): TIdDomainNameServerMapping;
- procedure SetItem(Index: Integer;
- const Value: TIdDomainNameServerMapping);
- procedure SetServer(const Value: TIdDNS_UDPServer);
- public
- constructor Create(Server: TIdDNS_UDPServer);
- destructor Destroy; override;
- property Server : TIdDNS_UDPServer read FServer write SetServer;
- property Items[Index: Integer]: TIdDomainNameServerMapping read GetItem write SetItem; default;
- end;
- TIdMWayTreeNodeClass = class of TIdMWayTreeNode;
- TIdMWayTreeNode = class (TObject)
- private
- SubTree : TIdObjectList;
- FFundmentalClass: TIdMWayTreeNodeClass;
- function GetTreeNode(Index: integer): TIdMWayTreeNode;
- procedure SetFundmentalClass(const Value: TIdMWayTreeNodeClass);
- procedure SetTreeNode(Index: integer; const Value: TIdMWayTreeNode);
- public
- constructor Create(NodeClass : TIdMWayTreeNodeClass); virtual;
- destructor Destroy; override;
- property FundmentalClass : TIdMWayTreeNodeClass read FFundmentalClass write SetFundmentalClass;
- property Children[Index : integer] : TIdMWayTreeNode read GetTreeNode write SetTreeNode;
- function AddChild : TIdMWayTreeNode;
- function InsertChild(Index : integer) : TIdMWayTreeNode;
- procedure RemoveChild(Index : integer);
- end;
- TIdDNTreeNode = class (TIdMWayTreeNode)
- private
- FCLabel : AnsiString;
- FRRs: TIdTextModeRRs;
- FChildIndex: TStrings;
- FParentNode: TIdDNTreeNode;
- FAutoSortChild: boolean;
- procedure SetCLabel(const Value: AnsiString);
- procedure SetRRs(const Value: TIdTextModeRRs);
- function GetNode(Index: integer): TIdDNTreeNode;
- procedure SetNode(Index: integer; const Value: TIdDNTreeNode);
- procedure SetChildIndex(const Value: TStrings);
- function GetFullName: string;
- function ConvertToDNString : string;
- function DumpAllBinaryData(var RecordCount:integer) : TIdBytes;
- public
- property ParentNode : TIdDNTreeNode read FParentNode write FParentNode;
- property CLabel : AnsiString read FCLabel write SetCLabel;
- property RRs : TIdTextModeRRs read FRRs write SetRRs;
- property Children[Index : integer] : TIdDNTreeNode read GetNode write SetNode;
- property ChildIndex : TStrings read FChildIndex write SetChildIndex;
- property AutoSortChild : boolean read FAutoSortChild write FAutoSortChild;
- property FullName : string read GetFullName;
- constructor Create(ParentNode : TIdDNTreeNode); reintroduce;
- destructor Destroy; override;
- function AddChild : TIdDNTreeNode;
- function InsertChild(Index : integer) : TIdDNTreeNode;
- procedure RemoveChild(Index : integer);
- procedure SortChildren;
- procedure Clear;
- procedure SaveToFile(Filename : TFilename);
- function IndexByLabel(CLabel : AnsiString): integer;
- function IndexByNode(ANode : TIdDNTreeNode) : integer;
- end;
- TIdDNS_TCPServer = class (TIdTCPServer)
- protected
- FAccessList: TIdStrings;
- FAccessControl: boolean;
- //
- procedure DoConnect(AThread: TIdContext); override;
- procedure InitComponent; override;
- procedure SetAccessList(const Value: TIdStrings);
- public
- destructor Destroy; override;
- published
- property AccessList : TIdStrings read FAccessList write SetAccessList;
- property AccessControl : boolean read FAccessControl write FAccessControl;
- end;
- TIdDNS_ProcessThread = class (TIdThread)
- protected
- FMyBinding: TIdSocketHandle;
- FMainBinding: TIdSocketHandle;
- FMyData: TStream;
- FData : string;
- FDataSize : integer;
- FServer: TIdDNS_UDPServer;
- procedure SetMyBinding(const Value: TIdSocketHandle);
- procedure SetMyData(const Value: TStream);
- procedure SetServer(const Value: TIdDNS_UDPServer);
- procedure ComposeErrorResult(var Final: TIdBytes;
- OriginalHeader: TDNSHeader; OriginalQuestion : TIdBytes;
- ErrorStatus: integer);
- function CombineAnswer(Header : TDNSHeader; EQuery, Answer : TIdBytes): TIdBytes;
- procedure InternalSearch(Header: TDNSHeader; QName: string; QType: Word;
- var Answer: TIdBytes; IfMainQuestion: boolean; IsSearchCache: boolean = false;
- IsAdditional: boolean = false; IsWildCard : boolean = false;
- WildCardOrgName: string = '');
- procedure ExternalSearch(aDNSResolver: TIdDNSResolver; Header: TDNSHeader;
- Question: TIdBytes; var Answer: TIdBytes);
- function CompleteQuery(DNSHeader: TDNSHeader; Question: string;
- OriginalQuestion: TIdBytes; var Answer : TIdBytes; QType, QClass : word;
- DNSResolver : TIdDNSResolver) : string;
- procedure SaveToCache(ResourceRecord : string; QueryName : string; OriginalQType : Word);
- function SearchTree(Root : TIdDNTreeNode; QName : String; QType : Word): TIdDNTreeNode;
- procedure Run; override;
- procedure QueryDomain;
- procedure SendData;
- public
- property MyBinding : TIdSocketHandle read FMyBinding write SetMyBinding;
- property MyData: TStream read FMyData write SetMyData;
- property Server : TIdDNS_UDPServer read FServer write SetServer;
- constructor Create(ACreateSuspended: Boolean = True;
- Data : String = ''; DataSize : integer = 0;
- MainBinding : TIdSocketHandle = nil;
- Binding : TIdSocketHandle = nil;
- Server : TIdDNS_UDPServer = nil); reintroduce; overload;
- destructor Destroy; override;
- end;
- TIdDNSBeforeQueryEvent = procedure(ABinding: TIdSocketHandle;
- ADNSHeader: TDNSHeader; var ADNSQuery: string) of object;
- TIdDNSAfterQueryEvent = procedure(ABinding: TIdSocketHandle;
- ADNSHeader: TDNSHeader; var QueryResult: string; ResultCode: string;
- Query : string) of object;
- TIdDNSAfterCacheSaved = procedure(CacheRoot : TIdDNTreeNode) of object;
- TIdDNS_UDPServer = class (TIdUDPServer)
- private
- FBusy: boolean;
- protected
- FAutoUpdateZoneInfo: boolean;
- FZoneMasterFiles: TIdStrings;
- FRootDNS_NET: TIdStrings;
- FCacheUnknowZone: boolean;
- FCached_Tree: TIdDNTreeNode;
- FHanded_Tree: TIdDNTreeNode;
- FHanded_DomainList: TIdStrings;
- FAutoLoadMasterFile: Boolean;
- FOnAfterQuery: TIdDNSAfterQueryEvent;
- FOnBeforeQuery: TIdDNSBeforeQueryEvent;
- FCS: TIdCriticalSection;
- FOnAfterSendBack: TIdDNSAfterQueryEvent;
- FOnAfterCacheSaved: TIdDNSAfterCacheSaved;
- FGlobalCS: TIdCriticalSection;
- FDNSVersion: string;
- FofferDNSVersion: boolean;
- procedure DoBeforeQuery(ABinding: TIdSocketHandle;
- ADNSHeader: TDNSHeader; var ADNSQuery : String); dynamic;
- procedure DoAfterQuery(ABinding: TIdSocketHandle;
- ADNSHeader: TDNSHeader; var QueryResult : String;
- ResultCode : String; Query : string); dynamic;
- procedure DoAfterSendBack(ABinding: TIdSocketHandle;
- ADNSHeader: TDNSHeader; var QueryResult : String;
- ResultCode : String; Query : string); dynamic;
- procedure DoAfterCacheSaved(CacheRoot : TIdDNTreeNode); dynamic;
- procedure SetZoneMasterFiles(const Value: TIdStrings);
- procedure SetRootDNS_NET(const Value: TIdStrings);
- procedure SetHanded_DomainList(const Value: TIdStrings);
- procedure InternalSearch(Header: TDNSHeader; QName: string; QType: Word;
- var Answer: TIdBytes; IfMainQuestion: boolean; IsSearchCache: boolean = false;
- IsAdditional: boolean = false; IsWildCard : boolean = false;
- WildCardOrgName: string = '');
- procedure ExternalSearch(aDNSResolver: TIdDNSResolver; Header: TDNSHeader;
- Question: TIdBytes; var Answer: TIdBytes);
- //modified in May 2004 by Dennies Chang.
- //procedure SaveToCache(ResourceRecord : string);
- procedure SaveToCache(ResourceRecord : string; QueryName : string; OriginalQType : Word);
- procedure UpdateTree(TreeRoot : TIdDNTreeNode; RR : TResultRecord); overload;
- procedure InitComponent; override;
- // Hide this property temporily, this property is prepared to maintain the
- // TTL expired record auto updated;
- property AutoUpdateZoneInfo : boolean read FAutoUpdateZoneInfo write FAutoUpdateZoneInfo;
- property CS: TIdCriticalSection read FCS;
- public
- destructor Destroy; override;
- function AXFR(Header : TDNSHeader; Question : string; var Answer :TIdBytes) : string;
- function CompleteQuery(DNSHeader: TDNSHeader; Question: string;
- OriginalQuestion: TIdBytes; var Answer : TIdBytes; QType, QClass : word;
- DNSResolver : TIdDNSResolver) : string;
- function LoadZoneFromMasterFile(MasterFileName : TFileName) : boolean;
- function LoadZoneStrings(FileStrings: TIdStrings; Filename : TFilename;
- TreeRoot : TIdDNTreeNode): boolean;
- function SearchTree(Root : TIdDNTreeNode; QName : String; QType : Word): TIdDNTreeNode;
- procedure UpdateTree(TreeRoot : TIdDNTreeNode; RR : TIdTextModeResourceRecord); overload;
- function FindNodeFullName(Root : TIdDNTreeNode; QName : String; QType : Word) : string;
- function FindHandedNodeByName(QName : String; QType : Word) : TIdDNTreeNode;
- //procedure DoUDPRead(AData: TStream; ABinding: TIdSocketHandle); override;
- property RootDNS_NET : TIdStrings read FRootDNS_NET write SetRootDNS_NET;
- property Cached_Tree : TIdDNTreeNode read FCached_Tree {write SetCached_Tree};
- property Handed_Tree : TIdDNTreeNode read FHanded_Tree {write SetHanded_Tree};
- property Busy : boolean read FBusy;
- property GlobalCS : TIdCriticalSection read FGlobalCS;
- published
- property DefaultPort default IdPORT_DOMAIN;
- property AutoLoadMasterFile : Boolean read FAutoLoadMasterFile write FAutoLoadMasterFile Default False;
- //property AutoUpdateZoneInfo : boolean read FAutoUpdateZoneInfo write SetAutoUpdateZoneInfo;
- property ZoneMasterFiles : TIdStrings read FZoneMasterFiles write SetZoneMasterFiles;
- property CacheUnknowZone : boolean read FCacheUnknowZone write FCacheUnknowZone default False;
- property Handed_DomainList : TIdStrings read FHanded_DomainList write SetHanded_DomainList;
- property DNSVersion : string read FDNSVersion write FDNSVersion;
- property offerDNSVersion : boolean read FofferDNSVersion write FofferDNSVersion;
- property OnBeforeQuery : TIdDNSBeforeQueryEvent read FOnBeforeQuery write FOnBeforeQuery;
- property OnAfterQuery :TIdDNSAfterQueryEvent read FOnAfterQuery write FOnAfterQuery;
- property OnAfterSendBack :TIdDNSAfterQueryEvent read FOnAfterSendBack write FOnAfterSendBack;
- property OnAfterCacheSaved : TIdDNSAfterCacheSaved read FOnAfterCacheSaved write FOnAfterCacheSaved;
- end;
- TIdDNSServer = class (TIdComponent)
- protected
- FActive: boolean;
- FTCPACLActive: boolean;
- FServerType: TDNSServerTypes;
- FTCPTunnel: TIdDNS_TCPServer;
- FUDPTunnel: TIdDNS_UDPServer;
- FAccessList: TIdStrings;
- FBindings: TIdSocketHandles;
- procedure SetAccessList(const Value: TIdStrings);
- procedure SetActive(const Value: boolean);
- procedure SetTCPACLActive(const Value: boolean);
- procedure SetBindings(const Value: TIdSocketHandles);
- procedure TimeToUpdateNodeData(Sender : TObject);
- procedure InitComponent; override;
- public
- BackupDNSMap : TIdDNSMap;
- destructor Destroy; override;
- procedure CheckIfExpire(Sender: TObject);
- published
- property Active : boolean read FActive write SetActive;
- property AccessList : TIdStrings read FAccessList write SetAccessList;
- property Bindings: TIdSocketHandles read FBindings write SetBindings;
- property TCPACLActive : boolean read FTCPACLActive write SetTCPACLActive;
- property ServerType: TDNSServerTypes read FServerType write FServerType;
- property TCPTunnel : TIdDNS_TCPServer read FTCPTunnel write FTCPTunnel;
- property UDPTunnel : TIdDNS_UDPServer read FUDPTunnel write FUDPTunnel;
- end;
- // CompareItems is to compare TIdDNTreeNode
- function CompareItems(Item1, Item2: TObject): Integer;
- function FetchBytes(var AInput: TIdBytes; const ADelim: TIdBytes;
- const ADelete: Boolean = IdFetchDeleteDefault): TIdBytes;
- function PosBytes(const SubBytes, SBytes: TIdBytes): integer;
- function SameArray(const B1, B2: TIdBytes): boolean;
- implementation
- uses
- IdIOHandler, IdStack;
- {Common Utilities}
- function CompareItems(Item1, Item2: TObject): Integer;
- var LObj1, LObj2 : TIdDNTreeNode;
- begin
- LObj1 := Item1 as TIdDNTreeNode;
- LObj2 := Item2 as TIdDNTreeNode;
- Result := CompareText((LObj1 as TIdDNTreeNode).CLabel, (LObj2 as TIdDNTreeNode).CLabel);
- end;
- function SameArray(const B1, B2: TIdBytes): boolean;
- var
- i, l1: integer;
- begin
- Result := False;
- l1 := Length(B1);
- if l1 <> Length(B2) then
- Exit; //Different length
- for i := 0 to l1 - 1 do
- begin
- if B1[i] <> B2[i] then
- Exit;
- end;
- Result := True;
- end;
- function PosBytes(const SubBytes, SBytes: TIdBytes): integer;
- var
- i, l: integer;
- begin
- Result := -1;
- l := Length(SubBytes);
- for i := 0 to Length(SBytes) - l do
- begin
- if SameArray(SubBytes, copy(SBytes, i, l)) then
- begin
- Result := i;
- Exit;
- end;
- end;
- end;
- function FetchBytes(var AInput: TIdBytes; const ADelim: TIdBytes;
- const ADelete: Boolean = IdFetchDeleteDefault): TIdBytes;
- var
- LPos: integer;
- begin
- LPos := PosBytes(ADelim, AInput);
- if LPos = -1 then begin
- Result := AInput;
- if ADelete then begin
- SetLength(AInput, 0);
- end;
- end
- else begin
- Result := Copy(AInput, 0, LPos);
- if ADelete then begin
- //slower Delete(AInput, 1, LPos + Length(ADelim) - 1);
- AInput:=Copy(AInput, LPos + Length(ADelim), MaxInt);
- end;
- end;
- end;
- { TIdMWayTreeNode }
- function TIdMWayTreeNode.AddChild: TIdMWayTreeNode;
- begin
- Result := Self.FundmentalClass.Create(FundmentalClass);
- Self.SubTree.Add(Result);
- end;
- constructor TIdMWayTreeNode.Create(NodeClass : TIdMWayTreeNodeClass);
- begin
- inherited Create;
- Self.FundmentalClass := NodeClass;
- Self.SubTree := TIdObjectList.Create;
- end;
- destructor TIdMWayTreeNode.Destroy;
- begin
- SubTree.Free;
- inherited;
- end;
- function TIdMWayTreeNode.GetTreeNode(Index: integer): TIdMWayTreeNode;
- begin
- Result := TIdMWayTreeNode(Self.SubTree.Items[Index]);
- end;
- function TIdMWayTreeNode.InsertChild(Index: integer): TIdMWayTreeNode;
- begin
- Result := Self.FundmentalClass.Create(FundmentalClass);
- Self.SubTree.Insert(Index, Result);
- end;
- procedure TIdMWayTreeNode.RemoveChild(Index: integer);
- begin
- Self.SubTree.Remove(SubTree.Items[Index]);
- end;
- procedure TIdMWayTreeNode.SetFundmentalClass(
- const Value: TIdMWayTreeNodeClass);
- begin
- FFundmentalClass := Value;
- end;
- procedure TIdMWayTreeNode.SetTreeNode(Index: integer;
- const Value: TIdMWayTreeNode);
- begin
- Self.SubTree.Items[Index] := Value;
- end;
- { TIdDNTreeNode }
- function TIdDNTreeNode.AddChild: TIdDNTreeNode;
- begin
- Result := TIdDNTreeNode.Create(Self);
- Self.SubTree.Add(Result);
- end;
- procedure TIdDNTreeNode.Clear;
- var
- Stop, Start : integer;
- begin
- Start := Self.SubTree.Count - 1;
- for Stop := Start downto 0 do begin
- Self.RemoveChild(Stop);
- end;
- end;
- function TIdDNTreeNode.ConvertToDNString: string;
- var
- Count : integer;
- MyString, ChildString : string;
- begin
- ChildString := '';
- MyString := '';
- MyString := '$ORIGIN ' + Self.FullName + #13+#10; {do not localize}
- for Count := 0 to Self.RRs.Count -1 do begin
- MyString := MyString + Self.RRs.Items[Count].TextRecord(Self.FullName);
- end;
- for Count := 0 to Self.FChildIndex.Count -1 do begin
- ChildString := ChildString + Self.Children[Count].ConvertToDNString;
- end;
- Result := MyString + ChildString;
- end;
- constructor TIdDNTreeNode.Create(ParentNode : TIdDNTreeNode);
- begin
- Inherited Create(TIdDNTreeNode);
- Self.FRRs := TIdTextModeRRs.Create;
- Self.FChildIndex := TIdStringList.Create;
- Self.ParentNode := ParentNode;
- end;
- destructor TIdDNTreeNode.Destroy;
- begin
- Self.FRRs.Free;
- Self.FChildIndex.Free;
- inherited;
- end;
- function TIdDNTreeNode.DumpAllBinaryData(var RecordCount:integer): TIdBytes;
- var
- Count, ChildCount : integer;
- MyString, ChildString : TIdBytes;
- begin
- SetLength(ChildString, 0);
- SetLength(MyString, 0);
- RecordCount := RecordCount + Self.RRs.Count + 1;
- for Count := 0 to Self.RRs.Count -1 do
- begin
- AppendBytes(MyString, Self.RRs.Items[Count].BinQueryRecord(Self.FullName));
- end;
- for Count := 0 to Self.FChildIndex.Count -1 do
- begin
- AppendBytes(ChildString, Self.Children[Count].DumpAllBinaryData(ChildCount));
- RecordCount := RecordCount + ChildCount;
- end;
- if Self.RRs.Count > 0 then
- begin
- if (Self.RRs.Items[0] is TIdRR_SOA) then
- begin
- RecordCount := RecordCount + 1;
- AppendBytes(MyString, Self.RRs.Items[0].BinQueryRecord(Self.FullName));
- end;
- end;
- Result := MyString;
- AppendBytes(Result, ChildString);
- AppendBytes(Result, Self.RRs.Items[0].BinQueryRecord(Self.FullName));
- end;
- function TIdDNTreeNode.GetFullName: string;
- begin
- if Self.ParentNode = nil then
- if Self.CLabel = '.' then
- Result := ''
- else
- Result := Self.CLabel
- else
- Result := Self.CLabel + '.' +Self.ParentNode.FullName;
- end;
- function TIdDNTreeNode.GetNode(Index: integer): TIdDNTreeNode;
- begin
- Result := TIdDNTreeNode(Self.SubTree.Items[Index]);
- end;
- function TIdDNTreeNode.IndexByLabel(CLabel: AnsiString): integer;
- begin
- Result := Self.FChildIndex.IndexOf(CLabel);
- end;
- function TIdDNTreeNode.IndexByNode(ANode: TIdDNTreeNode): integer;
- begin
- Result := Self.SubTree.IndexOf(ANode);
- end;
- function TIdDNTreeNode.InsertChild(Index: integer): TIdDNTreeNode;
- begin
- Result := TIdDNTreeNode.Create(Self);
- Self.SubTree.Insert(Index, Result);
- end;
- procedure TIdDNTreeNode.RemoveChild(Index: integer);
- begin
- Self.SubTree.Remove(Self.SubTree.Items[Index]);
- Self.FChildIndex.Delete(Index);
- end;
- procedure TIdDNTreeNode.SaveToFile(Filename: TFilename);
- var
- DNSs : TIdStrings;
- begin
- DNSs := TIdStringList.Create;
- try
- DNSs.Add(Self.ConvertToDNString);
- DNSs.SaveToFile(Filename);
- finally
- DNSs.Free;
- end;
- end;
- procedure TIdDNTreeNode.SetChildIndex(const Value: TStrings);
- begin
- Self.FChildIndex.Assign(Value);
- end;
- procedure TIdDNTreeNode.SetCLabel(const Value: AnsiString);
- begin
- FCLabel := Value;
- if Self.ParentNode <> nil then
- Self.ParentNode.ChildIndex.Insert(ParentNode.SubTree.IndexOf(Self), Value);
- if Self.AutoSortChild then Self.SortChildren;
- end;
- procedure TIdDNTreeNode.SetNode(Index: integer;
- const Value: TIdDNTreeNode);
- begin
- Self.SubTree.Items[Index] := Value;
- end;
- procedure TIdDNTreeNode.SetRRs(const Value: TIdTextModeRRs);
- begin
- FRRs.Assign(Value);
- end;
- procedure TIdDNTreeNode.SortChildren;
- begin
- Self.SubTree.BubbleSort(CompareItems);
- TStringList(Self.FChildIndex).Sort;
- end;
- { TIdDNSServer }
- function TIdDNS_UDPServer.CompleteQuery(DNSHeader : TDNSHeader; Question: string;
- OriginalQuestion: TIdBytes; var Answer: TIdBytes; QType, QClass: word;
- DNSResolver : TIdDNSResolver): string;
- var
- IsMyDomains : boolean;
- lAnswer: TIdBytes;
- WildQuestion, TempDomain : string;
- begin
- // QClass = 1 => IN, we support only "IN" class now.
- // QClass = 2 => CS,
- // QClass = 3 => CH,
- // QClass = 4 => HS.
- TempDomain := IndyLowerCase(Question);
- IsMyDomains := (Self.Handed_DomainList.IndexOf(TempDomain) > -1);
- if not IsMyDomains then
- begin
- Fetch(TempDomain, '.');
- end;
- IsMyDomains := (Self.Handed_DomainList.IndexOf(TempDomain) > -1);
- if (QClass = 1) then begin
- if IsMyDomains then begin
- Self.InternalSearch(DNSHeader, Question, QType, lAnswer, True, False, False);
- Answer := lAnswer;
- if ((QType = TypeCode_A) or (QType = TypeCode_AAAA)) and
- (Length(Answer) = 0) then begin
- Self.InternalSearch(DNSHeader, Question, TypeCode_CNAME, lAnswer, True, False, True);
- AppendBytes(Answer, lAnswer);
- end;
- //if lAnswer = '' then begin
- WildQuestion := Question;
- fetch(WildQuestion, '.');
- WildQuestion := '*.' + WildQuestion;
- Self.InternalSearch(DNSHeader, WildQuestion, QType, lAnswer, True, False, False, true, Question);
- AppendBytes(Answer, lAnswer);
- //end;
- if Length(Answer) > 0 then
- Result := cRCodeQueryOK
- else Result := cRCodeQueryNotFound;
- end else begin
- Self.InternalSearch(DNSHeader, Question, QType, Answer, True, True, False);
- if ((QType = TypeCode_A) or (QType = TypeCode_AAAA)) and
- (Length(Answer) = 0) then begin
- Self.InternalSearch(DNSHeader, Question, TypeCode_CNAME, lAnswer, True, True, False);
- AppendBytes(Answer, lAnswer);
- end;
- if Length(Answer) > 0 then
- Result := cRCodeQueryCacheOK
- else begin
- QType := TypeCode_Error;
- Self.InternalSearch(DNSHeader, Question, QType, Answer, True, True, False);
- if BytesToString(Answer) = 'Error' then begin {do not localize}
- Result := cRCodeQueryCacheFindError;
- end else begin
- Self.ExternalSearch(DNSResolver, DNSHeader, OriginalQuestion, Answer);
- if Length(Answer) > 0 then
- Result := cRCodeQueryReturned
- else Result := cRCodeQueryNotImplement;
- end;
- end;
- end
- end else begin
- Result := cRCodeQueryNotImplement;
- end;
- end;
- procedure TIdDNS_UDPServer.InitComponent;
- begin
- inherited;
- Self.FRootDNS_NET := TIdStringList.Create;
- Self.FRootDNS_NET.Add('209.92.33.150'); // nic.net {do not localize}
- Self.FRootDNS_NET.Add('209.92.33.130'); // nic.net {do not localize}
- Self.FRootDNS_NET.Add('203.37.255.97'); // apnic.net {do not localize}
- Self.FRootDNS_NET.Add('202.12.29.131'); // apnic.net {do not localize}
- Self.FRootDNS_NET.Add('12.29.20.2'); // nanic.net {do not localize}
- Self.FRootDNS_NET.Add('204.145.119.2'); // nanic.net {do not localize}
- Self.FRootDNS_NET.Add('140.111.1.2'); // a.twnic.net.tw {do not localize}
- Self.FCached_Tree := TIdDNTreeNode.Create(nil);
- Self.FCached_Tree.AutoSortChild := True;
- Self.FCached_Tree.CLabel := '.';
- Self.FHanded_Tree := TIdDNTreeNode.Create(nil);
- Self.FHanded_Tree.AutoSortChild := True;
- Self.FHanded_Tree.CLabel := '.';
- Self.FHanded_DomainList := TIdStringList.Create;
- Self.FZoneMasterFiles := TIdStringList.Create;
- DefaultPort := IdPORT_DOMAIN;
- Self.FCS := TIdCriticalSection.Create;
- Self.FGlobalCS := TIdCriticalSection.Create;
- Self.FBusy := False;
- end;
- destructor TIdDNS_UDPServer.Destroy;
- begin
- Self.FCached_Tree.Free;
- Self.FHanded_Tree.Free;
- Self.FRootDNS_NET.Free;
- Self.FHanded_DomainList.Free;
- Self.FZoneMasterFiles.Free;
- Self.FCS.Free;
- Self.FGlobalCS.Free;
- inherited;
- end;
- procedure TIdDNS_UDPServer.DoAfterQuery(ABinding: TIdSocketHandle;
- ADNSHeader: TDNSHeader; var QueryResult: String; ResultCode : String;
- Query : string);
- begin
- if Assigned(FOnAfterQuery) then begin
- FOnAfterQuery(ABinding, ADNSHeader, QueryResult, ResultCode, Query);
- end;
- end;
- procedure TIdDNS_UDPServer.DoBeforeQuery(ABinding: TIdSocketHandle;
- ADNSHeader: TDNSHeader; var ADNSQuery: String);
- begin
- if Assigned(FOnBeforeQuery) then begin
- FOnBeforeQuery(ABinding, ADNSHeader, ADNSQuery);
- end;
- end;
- (*procedure TIdDNS_UDPServer.DoUDPRead(AData: TStream;
- ABinding: TIdSocketHandle);
- var
- ExternalQuery, QName, QLabel, Answer, RString, FinalResult : string;
- DNSHeader_Processing : TDNSHeader;
- QType, QClass : Word;
- QPos, QLength, LLength : integer;
- DNSResolver : TIdDNSResolver;
- begin
- inherited DoUDPRead(AData, ABinding);
- //Self.CS.Acquire;
- SetLength(ExternalQuery, AData.Size);
- AData.Read(ExternalQuery[1], AData.Size);
- FinalResult := '';
- if AData.Size >= 12 then begin
- DNSHeader_Processing := TDNSHeader.Create;
- DNSResolver := TIdDNSResolver.Create(Self);
- DNSResolver.WaitingTime := 10000;
- try
- if DNSHeader_Processing.ParseQuery(ExternalQuery) <> 0 then begin
- //FinalResult := ComposeErrorResult
- DoAfterQuery(ABinding, DNSHeader_Processing, FinalResult, RString, ExternalQuery)
- end else begin
- if DNSHeader_Processing.QDCount > 0 then begin
- QPos := 13;
- QLength := Length(ExternalQuery);
- if (QLength > 12) then begin
- QName := '';
- repeat
- Answer := '';
- LLength := Byte(ExternalQuery[QPos]);
- Inc(QPos);
- QLabel := Copy(ExternalQuery, QPos, LLength);
- Inc(QPos, LLength);
- if QName <> '' then
- QName := QName + QLabel + '.'
- else
- QName := QLabel + '.';
- until ((QPos >= QLength) or (ExternalQuery[QPos] = #0));
- //HD_QDPos := QPos;
- Inc(QPos);
- QType := TwoCharToWord(ExternalQuery[QPos], ExternalQuery[QPos + 1]);
- Inc(QPos, 2);
- QClass := TwoCharToWord(ExternalQuery[QPos], ExternalQuery[QPos + 1]);
- DoBeforeQuery(ABinding, DNSHeader_Processing, ExternalQuery);
- RString := Self.CompleteQuery(DNSHeader_Processing, QName, ExternalQuery, Answer, QType, QClass, DNSResolver);
- if RString = cRCodeQueryNotImplement then begin
- ComposeErrorResult(FinalResult, DNSHeader_Processing, ExternalQuery, iRCodeQueryNotImplement);
- end else begin
- if (RString = cRCodeQueryReturned) then
- FinalResult := Answer
- else begin
- if (RString = cRCodeQueryNotFound) then
- ComposeErrorResult(FinalResult, DNSHeader_Processing, ExternalQuery, iRCodeQueryNotFound)
- else
- FinalResult := CombineAnswer(DNSHeader_Processing, ExternalQuery, Answer);
- end;
- end;
- DoAfterQuery(ABinding, DNSHeader_Processing, FinalResult, RString, ExternalQuery);
- end;
- end;
- end;
- finally
- try
- //Self.SendBuffer(ABinding.PeerIP, ABinding.Port, FinalResult[1], length(FinalResult));
- with ABinding do begin
- SendTo(PeerIP, PeerPort, FinalResult[1], length(FinalResult));
- end;
- DoAfterSendBack(ABinding, DNSHeader_Processing, FinalResult, RString, ExternalQuery);
- if (((Self.CacheUnknowZone) and (RString = cRCodeQueryReturned)) or
- (RString = cRCodeQueryCacheOK)) then
- Self.SaveToCache(FinalResult);
- finally
- DNSResolver.Free;
- DNSHeader_Processing.Free;
- end;
- end;
- end;
- //Self.CS.Release;
- end;
- *)
- procedure TIdDNS_UDPServer.ExternalSearch(aDNSResolver : TIdDNSResolver;
- Header: TDNSHeader; Question: TIdBytes; var Answer: TIdBytes);
- var
- Server_Index : integer;
- MyDNSResolver : TIdDNSResolver;
- begin
- Server_Index := 0;
- if (aDNSResolver = nil) then
- begin
- MyDNSResolver := TIdDNSResolver.Create(Self);
- MyDNSResolver.WaitingTime := 5000;
- end else
- begin
- MyDNSResolver := aDNSResolver;
- end;
- repeat
- MyDNSResolver.Host := Self.RootDNS_NET.Strings[Server_Index];
- try
- MyDNSResolver.InternalQuery := Question;
- MyDNSResolver.Resolve('');
- Answer := MyDNSResolver.PlainTextResult;
- except
- // Todo: Create DNS server interal resolver error.
- on EIdDnsResolverError do
- begin
- //Empty Event, for user to custom the event handle.
- end;
- on EIdSocketError do
- begin
- end;
- else
- begin
- end;
- end;
- Inc(Server_Index);
- until ((Server_Index >= Self.RootDNS_NET.Count) or (Length(Answer) > 0));
- if (aDNSResolver = nil) then
- begin
- MyDNSResolver.Free
- end;
- end;
- function TIdDNS_UDPServer.FindHandedNodeByName(QName: String;
- QType: Word): TIdDNTreeNode;
- begin
- Result := Self.SearchTree(Self.Handed_Tree, QName, QType);
- end;
- function TIdDNS_UDPServer.FindNodeFullName(Root: TIdDNTreeNode;
- QName: String; QType : Word): string;
- var
- MyNode : TIdDNTreeNode;
- begin
- MyNode := Self.SearchTree(Root, QName, QType);
- if MyNode = nil then Result := ''
- else begin
- Result := MyNode.FullName;
- end;
- end;
- function TIdDNS_UDPServer.LoadZoneFromMasterFile(
- MasterFileName: TFileName): boolean;
- var
- FileStrings : TIdStrings;
- begin
- {MakeTagList;}
- Result := FileExists(MasterFileName);
- if Result then begin
- FileStrings := TIdStringList.Create;
- FileStrings.LoadFromFile(MasterFileName);
- Result := LoadZoneStrings(FileStrings, MasterFileName, Self.Handed_Tree);
- {
- Result := IsValidMasterFile;
- // IsValidMasterFile is used in local, so I design with not
- // any parameter.
- if Result then begin
- Result := LoadMasterFile;
- end;
- }
- FileStrings.Free;
- end;
- {FreeTagList;}
- end;
- function TIdDNS_UDPServer.LoadZoneStrings(FileStrings: TIdStrings; Filename : TFilename;
- TreeRoot : TIdDNTreeNode): boolean;
- var
- TagList : TIdStrings;
- function IsMSDNSFileName(theFileName : TFilename; var DN:string) : boolean;
- var
- namepart : TIdStrings;
- Fullname : string;
- Count : integer;
- begin
- Fullname := theFilename;
- repeat
- if (Pos('\', Fullname) > 0) then fetch(Fullname, '\');
- until (Pos('\', Fullname) = 0);
- namepart := TIdStringList.Create;
- repeat
- namepart.Add(fetch(Fullname,'.'));
- until Fullname = '';
- Result := (namepart.Strings[namepart.Count -1] = 'dns'); {do not localize}
- if Result then begin
- Count := 0;
- DN := namepart.Strings[Count];
- repeat
- Inc(Count);
- if Count <= namepart.Count -2 then begin
- DN := DN + '.' + namepart.Strings[Count];
- end;
- until Count >= namepart.Count -2;
- end;
- namepart.Free;
- end;
- procedure MakeTagList;
- begin
- TagList := TIdStringList.Create;
- TagList.Add(cAAAA);
- TagList.Add(cA);
- TagList.Add(cNS);
- TagList.Add(cMD);
- TagList.Add(cMF);
- TagList.Add(cCName);
- TagList.Add(cSOA);
- TagList.Add(cMB);
- TagList.Add(cMG);
- TagList.Add(cMR);
- TagList.Add(cNULL);
- TagList.Add(cWKS);
- TagList.Add(cPTR);
- TagList.Add(cHINFO);
- TagList.Add(cMINFO);
- TagList.Add(cMX);
- TagList.Add(cTXT);
- // The Following Tags are used in master file, but not Resource Record.
- TagList.Add(cOrigin);
- TagList.Add(cInclude);
- //TagList.Add(cAt);
- end;
- procedure FreeTagList;
- begin
- TagList.Free;
- end;
- function ClearDoubleQutoa (Strs : TIdStrings): boolean;
- var
- SSCount : integer;
- Mark : boolean;
- begin
- SSCount := 0;
- Mark := False;
- while (SSCount <= Strs.Count -1) do begin
- repeat
- if Pos('"', Strs.Strings[SSCount]) > 0 then begin
- Mark := Mark xor (Pos('"', Strs.Strings[SSCount]) > 0);
- Strs.Strings[SSCount] := ReplaceSpecString(Strs.Strings[SSCount], '"', '', False);
- end;
- until (Pos('"', Strs.Strings[SSCount]) = 0);
- if not Mark then Inc(SSCount)
- else begin
- Strs.Strings[SSCount] := Strs.Strings[SSCount] + ' ' +
- Strs.Strings[SSCount + 1];
- Strs.Delete(SSCount + 1);
- end;
- end;
- Result := not Mark;
- end;
- function IsValidMasterFile : boolean;
- var
- EachLinePart : TIdStrings;
- CurrentLineNum, TagField, Count : integer;
- LineData, DataBody, Comment, FPart, Tag : string;
- denoted, Stop, PassQuota : boolean;
- begin
- EachLinePart := TIdStringList.Create;
- CurrentLineNum := 0;
- Stop := False;
- // Check Denoted;
- denoted := false;
- if FileStrings.Count > 0 then begin
- repeat
- LineData := Trim(FileStrings.Strings[CurrentLineNum]);
- DataBody := Fetch(LineData, ';');
- Comment := LineData;
- PassQuota := Pos('(', DataBody) = 0;
- // Split each item into TIdStrings.
- repeat
- if not PassQuota then begin
- Inc(CurrentLineNum);
- LineData := Trim(FileStrings.Strings[CurrentLineNum]);
- DataBody := DataBody + ' ' + Fetch(LineData, ';');
- PassQuota := Pos(')', DataBody) > 0;
- end;
- until PassQuota or (CurrentLineNum > (FileStrings.Count -1));
- Stop := not PassQuota;
- if not Stop then begin
- EachLinePart.Clear;
- DataBody := ReplaceSpecString(DataBody, '(', '');
- DataBody := ReplaceSpecString(DataBody, ')', '');
- repeat
- DataBody := Trim(DataBody);
- FPart := Fetch(DataBody, #9);
- repeat
- FPart := Trim(FPart);
- Tag := Fetch(FPart,' ');
- if (Tag <> '') and (Tag <> '(') and (Tag <> ')') then
- EachLinePart.Add(Tag);
- until (FPart='');
- until (DataBody= '');
- if not denoted then begin
- if EachLinePart.Count > 1 then
- denoted := (EachLinePart.Strings[0] = cOrigin) or (EachLinePart.IndexOf(cSOA) <> -1)
- else
- denoted := False;
- end;
- // Check Syntax;
- if not ( (EachLinePart.Count > 0) and
- (EachLinePart.Strings[0] = cOrigin) ) then begin
- if not denoted then begin
- if EachLinePart.Count > 0 then
- Stop := ((EachLinePart.Count > 0) and (EachLinePart.IndexOf(cSOA)= -1))
- else Stop := False;
- end else begin
- //TagField := -1;
- //FieldCount := 0;
- // Search Tag Named 'IN';
- TagField := EachLinePart.IndexOf('IN'); {do not localize}
- if TagField = -1 then begin
- Count := 0;
- repeat
- if EachLinePart.Count > 0 then
- TagField := TagList.IndexOf(EachLinePart.Strings[Count]);
- Inc(Count);
- until (Count >= EachLinePart.Count -1) or (TagField <> -1);
- if TagField <> -1 then TagField := Count;
- end else begin
- if TagList.IndexOf(EachLinePart.Strings[TagField + 1]) = -1 then
- TagField := -1
- else Inc(TagField);
- end;
- if TagField > -1 then begin
- case TagList.IndexOf(EachLinePart.Strings[TagField]) of
- // Check ip
- TypeCode_A : Stop := not IsValidIP(EachLinePart.Strings[TagField + 1]);
- // Check ip v6
- 0 : Stop := not IsValidIPv6(EachLinePart.Strings[TagField + 1]);
- // Check Domain Name
- TypeCode_CName, TypeCode_NS, TypeCode_MR,
- TypeCode_MD, TypeCode_MB, TypeCode_MG,
- TypeCode_MF: Stop := not IsHostName(EachLinePart.Strings[TagField + 1]);
- // Can be anything
- TypeCode_TXT, TypeCode_NULL: Stop := False;
- // Must be FQDN.
- TypeCode_PTR: Stop := not IsFQDN(EachLinePart.Strings[TagField + 1]);
- // HINFO should has 2 fields : CPU and OS. but TIdStrings
- // is 0 base, so that we have to minus one
- TypeCode_HINFO: begin
- Stop := not (ClearDoubleQutoa(EachLinePart) and
- (EachLinePart.Count - TagField-1 = 2));
- end;
- // Check RMailBX and EMailBX but TIdStrings
- // is 0 base, so that we have to minus one
- TypeCode_MINFO: begin
- Stop := (EachLinePart.Count - TagField-1 <> 2);
- if not Stop then begin
- Stop := not (IsHostName(EachLinePart.Strings[TagField + 1]) and
- IsHostName(EachLinePart.Strings[TagField + 2]));
- end;
- end;
- // Check Pref(Numeric) and Exchange. but TIdStrings
- // is 0 base, so that we have to minus one
- TypeCode_MX: begin
- Stop := (EachLinePart.Count - TagField-1 <> 2);
- if not Stop then begin
- Stop := not (IsNumeric(EachLinePart.Strings[TagField + 1]) and
- IsHostName(EachLinePart.Strings[TagField + 2]));
- end;
- end;
- // TIdStrings is 0 base, so that we have to minus one
- TypeCode_SOA: begin
- Stop := (EachLinePart.Count - TagField-1 <> 7);
- if not Stop then begin
- Stop := not (IsHostName(EachLinePart.Strings[TagField + 1]) and
- IsHostName(EachLinePart.Strings[TagField + 2]) and
- IsNumeric(EachLinePart.Strings[TagField + 3]) and
- IsNumeric(EachLinePart.Strings[TagField + 4]) and
- IsNumeric(EachLinePart.Strings[TagField + 5]) and
- IsNumeric(EachLinePart.Strings[TagField + 6]) and
- IsNumeric(EachLinePart.Strings[TagField + 7])
- );
- end;
- end;
- TypeCode_WKS: Stop := (EachLinePart.Count - TagField = 1);
- end;
- end else begin
- if EachLinePart.Count > 0 then
- Stop := True;
- end;
- end;
- end;
- end;
- Inc(CurrentLineNum);
- until (CurrentLineNum > (FileStrings.Count -1)) or Stop;
- end;
- Result := not Stop;
- EachLinePart.Free;
- end;
- function LoadMasterFile : boolean;
- var
- Checks, EachLinePart, DenotedDomain : TIdStrings;
- CurrentLineNum, FieldCount, TagField, Count, LastTTL : integer;
- LineData, DataBody, Comment, FPart, Tag,
- RName, LastDenotedDomain, LastTag, NewDomain, SingleHostName, PrevDNTag : string;
- denoted, Stop, PassQuota, Found, canChangPrevDNTag : boolean;
- LLRR_A : TIdRR_A;
- LLRR_AAAA : TIdRR_AAAA;
- LLRR_NS : TIdRR_NS;
- LLRR_MB : TIdRR_MB;
- LLRR_Name : TIdRR_CName;
- LLRR_SOA : TIdRR_SOA;
- LLRR_MG : TIdRR_MG;
- LLRR_MR : TIdRR_MR;
- LLRR_PTR : TIdRR_PTR;
- LLRR_HINFO : TIdRR_HINFO;
- LLRR_MINFO : TIdRR_MINFO;
- LLRR_MX : TIdRR_MX;
- LLRR_TXT : TIdRR_TXT;
- begin
- EachLinePart := TIdStringList.Create;
- DenotedDomain := TIdStringList.Create;
- CurrentLineNum := 0;
- LastDenotedDomain := '';
- LastTag := '';
- NewDomain := '';
- PrevDNTag := '';
- Stop := False;
- //canChangPrevDNTag := True;
- if IsMSDNSFileName(FileName, LastDenotedDomain) then begin
- …
Large files files are truncated, but you can click here to view the full file