IdDNSCommon.pas 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. Rev 1.29 1/31/2005 9:02:44 PM JPMugaas
  16. Should compile again. OOPS!!
  17. Rev 1.28 1/28/2005 8:06:08 PM JPMugaas
  18. Bug with MINFO, it was not returning the responsible E-Mail address.
  19. Rev 1.27 1/28/2005 7:12:34 PM JPMugaas
  20. Minor formatting adjustments.
  21. Rev 1.26 1/28/2005 3:46:18 PM JPMugaas
  22. Should compile.
  23. Rev 1.25 2005/1/28 ¤U¤È 12:40:08 DChang
  24. Add a new method for TIdTextModeResourceRecord to clean the created FAnswer,
  25. then while the record updated, new data can be used in the FAnswer.
  26. Rev 1.23 2005/1/25 ¤U¤È 12:24:14 DChang
  27. For speeding up the query, one private variable is added into all TIdRR_
  28. series object, only first time query will generate the binary codes, the
  29. others will read the result form the first time generated.
  30. Rev 1.22 2004/12/15 ¤W¤È 11:12:18 DChang Version: 1.22
  31. Fix all BinQueryRecord method of TIdRR_*,
  32. TIdRR_TXT.BinQueryRecord is completed,
  33. and remark the comment of TIdTextModeResourceRecord.BinQueryRecord,
  34. it's should be empty.
  35. Rev 1.21 10/26/2004 9:06:30 PM JPMugaas
  36. Updated references.
  37. Rev 1.20 9/15/2004 4:59:34 PM DSiders
  38. Added localization comments.
  39. Rev 1.19 2004/7/19 ¤U¤È 09:43:40 DChang
  40. 1. Move the TIdTextModeResourceRecords which was defined in
  41. IdDNSServer.pas to here.
  42. 2. Add a QueryType (DqtIXFR) in TDNSQueryRecordTypes.
  43. Rev 1.18 6/29/04 1:22:32 PM RLebeau
  44. Updated NormalStrToDNSStr() to use CopyTIdBytes() instead of AppendBytes()
  45. Rev 1.17 2/11/2004 5:21:12 AM JPMugaas
  46. Vladimir Vassiliev changes for removal of byte flipping. Network conversion
  47. order conversion functions are used instead.
  48. IPv6 addresses are returned in the standard form.
  49. In WKS records, Address was changed to IPAddress to be consistant with other
  50. record types. Address can also imply a hostname.
  51. Rev 1.16 2/7/2004 7:18:30 PM JPMugaas
  52. Moved some functions out of IdDNSCommon so we can use them elsewhere.
  53. Rev 1.15 2004.02.07 5:45:10 PM czhower
  54. Fixed compile error in D7.
  55. Rev 1.14 2004.02.07 5:03:26 PM czhower
  56. .net fixes.
  57. Rev 1.13 2004.02.03 5:45:56 PM czhower
  58. Name changes
  59. Rev 1.12 12/7/2003 8:07:24 PM VVassiliev
  60. string -> TIdBytes
  61. Rev 1.11 11/15/2003 1:16:06 PM VVassiliev
  62. Move AppendByte from IdDNSCommon to IdCoreGlobal
  63. Rev 1.10 11/13/2003 5:46:04 PM VVassiliev
  64. DotNet
  65. Rev 1.9 10/25/2003 06:51:50 AM JPMugaas
  66. Updated for new API changes and tried to restore some functionality.
  67. Rev 1.8 10/19/2003 11:56:12 AM DSiders
  68. Added localization comments.
  69. Rev 1.7 2003.10.12 3:50:38 PM czhower
  70. Compile todos
  71. Rev 1.6 2003/5/8 ¤U¤È 08:07:12 DChang
  72. Add several constants for IdDNSServer
  73. Rev 1.5 4/28/2003 03:34:56 PM JPMugaas
  74. Illiminated constant for the service path. IFDEF's for platforms are only
  75. allowed in designated units. Besides, the location of the services file is
  76. different in Win9x operating systems than NT operating systems.
  77. Rev 1.4 4/28/2003 02:30:46 PM JPMugaas
  78. reverted back to the old one as the new one checked will not compile, has
  79. problametic dependancies on Contrs and Dialogs (both not permitted).
  80. Rev 1.2 4/28/2003 07:00:04 AM JPMugaas
  81. Should now compile.
  82. Rev 1.0 11/14/2002 02:18:20 PM JPMugaas
  83. Rev 1.3 04/28/2003 01:15:20 AM DenniesChang
  84. // Add iRCode mode constants in May 4, 2003.
  85. // Modify all DNS relative header in IdDNSCommon.pas
  86. // Apr. 28, 2003
  87. // Jun. 03, 2002.
  88. // Add AXFR function
  89. Duplicate some varible and constants in DNSCommon,
  90. because Indy change version very frequently, these
  91. varlibles and objects are isolated.
  92. I had added some methods into IdDNSResolver of Indy 9.02,
  93. for parsing DN record directly and skip some check actions
  94. from original query, but this modification will not relfect
  95. the action of DN Query.
  96. Original Programmer: Dennies Chang <[email protected]>
  97. No Copyright. Code is given to the Indy Pit Crew.
  98. Started: Jan. 20, 2002.
  99. Finished:
  100. }
  101. unit IdDNSCommon;
  102. interface
  103. {$i IdCompilerDefines.inc}
  104. uses
  105. Classes,
  106. IdContainers,
  107. IdException,
  108. IdGlobal,
  109. IdResourceStringsProtocols;
  110. const
  111. IdDNSServerVersion = 'Indy DNSServer 20040121301'; {do not localize}
  112. cRCodeNoError = 0;
  113. cRCodeFormatErr = 1;
  114. cRCodeServerErr = 2;
  115. cRCodeNameErr = 3;
  116. cRCodeNotImplemented = 4;
  117. cRCodeRefused = 5;
  118. iRCodeQueryNotImplement = 0;
  119. iRCodeQueryReturned = 1;
  120. iRCodeQueryOK = 2;
  121. iRCodeQueryNotFound = 3;
  122. iRCodeNoError = 0;
  123. iRCodeFormatError = 1;
  124. iRCodeServerFailure = 2;
  125. iRCodeNameError = 3;
  126. iRCodeNotImplemented = 4;
  127. iRCodeRefused = 5;
  128. iQr_Question = 0;
  129. iQr_Answer = 1;
  130. iAA_NotAuthoritative = 0;
  131. iAA_Authoritative = 1;
  132. cRCodeQueryNotImplement = 'NA'; {do not localize}
  133. cRCodeQueryReturned = 'RC'; // Return Completed. {do not localize}
  134. cRCodeQueryOK = 'OK'; {do not localize}
  135. cRCodeQueryCacheOK = 'COK'; {do not localize}
  136. cRCodeQueryNotFound = 'NOTFOUND'; {do not localize}
  137. cRCodeQueryCacheFindError = 'CFoundError'; {do not localize}
  138. RSDNSServerAXFRError_QuerySequenceError = 'First record must be SOA!'; {do not localize}
  139. RSDNSServerSettingError_MappingHostError = 'Host must be an IP address'; {do not localize}
  140. cOrigin = '$ORIGIN'; {do not localize}
  141. cInclude = '$INCLUDE'; {do not localize}
  142. cAAAA = 'AAAA'; {do not localize}
  143. cAt = '@'; {do not localize}
  144. cA = 'A'; {do not localize}
  145. cNS = 'NS'; {do not localize}
  146. cMD = 'MD'; {do not localize}
  147. cMF = 'MF'; {do not localize}
  148. cCName = 'CNAME'; {do not localize}
  149. cSOA = 'SOA'; {do not localize}
  150. cMB = 'MB'; {do not localize}
  151. cMG = 'MG'; {do not localize}
  152. cMR = 'MR'; {do not localize}
  153. cNULL = 'NULL'; {do not localize}
  154. cWKS = 'WKS'; {do not localize}
  155. cPTR = 'PTR'; {do not localize}
  156. cHINFO = 'HINFO'; {do not localize}
  157. cMINFO = 'MINFO'; {do not localize}
  158. cMX = 'MX'; {do not localize}
  159. cTXT = 'TXT'; {do not localize}
  160. cNSAP = 'NSAP'; {do not localize}
  161. cNSAP_PTR = 'NSAP-PTR'; {do not localize}
  162. cLOC = 'LOC'; {do not localize}
  163. cAXFR = 'AXFR'; {do not localize}
  164. cIXFR = 'IXFR'; {do not localize}
  165. cSTAR = 'STAR'; {do not localize}
  166. cRCodeStrs : Array[cRCodeNoError..cRCodeRefused] Of String =
  167. (RSCodeNoError,
  168. RSCodeQueryFormat,
  169. RSCodeQueryServer,
  170. RSCodeQueryName,
  171. RSCodeQueryNotImplemented,
  172. RSCodeQueryQueryRefused);
  173. Class_IN = 1;
  174. Class_CHAOS = 3;
  175. TypeCode_A = 1;
  176. TypeCode_NS = 2;
  177. TypeCode_MD = 3;
  178. TypeCode_MF = 4;
  179. TypeCode_CName = 5;
  180. TypeCode_SOA = 6;
  181. TypeCode_MB = 7;
  182. TypeCode_MG = 8;
  183. TypeCode_MR = 9;
  184. TypeCode_NULL = 10;
  185. TypeCode_WKS = 11;
  186. TypeCode_PTR = 12;
  187. TypeCode_HINFO = 13;
  188. TypeCode_MINFO = 14;
  189. TypeCode_MX = 15;
  190. TypeCode_TXT = 16;
  191. TypeCode_RP = 17;
  192. TypeCode_AFSDB = 18;
  193. TypeCode_X25 = 19;
  194. TypeCode_ISDN = 20;
  195. TypeCode_RT = 21;
  196. TypeCode_NSAP = 22;
  197. TypeCode_NSAP_PTR = 23;
  198. TypeCode_SIG = 24;
  199. TypeCode_KEY = 25;
  200. TypeCode_PX = 26;
  201. TypeCode_QPOS = 27;
  202. TypeCode_AAAA = 28;
  203. TypeCode_LOC = 29;
  204. TypeCode_NXT = 30;
  205. TypeCode_R31 = 31;
  206. TypeCode_R32 = 32;
  207. TypeCode_Service = 33;
  208. TypeCode_R34 = 34;
  209. TypeCode_NAPTR = 35;
  210. TypeCode_KX = 36;
  211. TypeCode_CERT = 37;
  212. TypeCode_V6Addr = 38;
  213. TypeCode_DNAME = 39;
  214. TypeCode_R40 = 40;
  215. TypeCode_OPTIONAL = 41;
  216. TypeCode_IXFR = 251;
  217. TypeCode_AXFR = 252;
  218. TypeCode_STAR = 255;
  219. TypeCode_Error = 0;
  220. type
  221. {NormalTags = (cA, cNS, cMD, cMF, cCName, cSOA, cMB, cMG, cMR, cNULL, cWKS, cPTR,
  222. cHINFO, cMINFO, cMX, cTXT); }
  223. TDNSQueryRecordTypes = (DqtA, DqtNS, DqtMD, DqtMF, DqtName, DqtSOA, DqtMB,
  224. DqtMG, DqtMR, DqtNull, DqtWKS, DqtPTR, DqtHINFO, DqtMINFO, DqtMX, DqtTXT,
  225. DqtNSAP, DqtNSAP_PTR, DqtLOC, DqtIXFR, DqtAXFR, DqtSTAR, DqtAAAA);
  226. TDNSServerTypes = (stPrimary, stSecondary);
  227. EIdDNSServerSyncException = class(EIdSilentException);
  228. EIdDNSServerSettingException = class(EIdSilentException);
  229. // TODO: enable AD and CD properties. Those fields are reserved in RFC 1035, but defined in RFC 6895
  230. TDNSHeader = class
  231. private
  232. FID: UInt16;
  233. FBitCode: UInt16;
  234. FQDCount: UInt16;
  235. FANCount: UInt16;
  236. FNSCount: UInt16;
  237. FARCount: UInt16;
  238. function GetAA: UInt16;
  239. //function GetAD: UInt16;
  240. //function GetCD: UInt16;
  241. function GetOpCode: UInt16;
  242. function GetQr: UInt16;
  243. function GetRA: UInt16;
  244. function GetRCode: UInt16;
  245. function GetRD: UInt16;
  246. function GetTC: UInt16;
  247. procedure SetAA(const Value: UInt16);
  248. //procedure SetAD(const Value: UInt16);
  249. //procedure SetCD(const Value: UInt16);
  250. procedure SetOpCode(const Value: UInt16);
  251. procedure SetQr(const Value: UInt16);
  252. procedure SetRA(const Value: UInt16);
  253. procedure SetRCode(const Value: UInt16);
  254. procedure SetRD(const Value: UInt16);
  255. procedure SetTC(const Value: UInt16);
  256. procedure SetBitCode(const Value: UInt16);
  257. public
  258. constructor Create;
  259. procedure ClearByteCode;
  260. function ParseQuery(Data : TIdBytes) : integer;
  261. function GenerateBinaryHeader : TIdBytes;
  262. property ID: UInt16 read FID write FID;
  263. property Qr: UInt16 read GetQr write SetQr;
  264. property OpCode: UInt16 read GetOpCode write SetOpCode;
  265. property AA: UInt16 read GetAA write SetAA;
  266. //property AD: UInt16 get GetAD write SetAD;
  267. //property CD: UInt16 get GetCD write SetCD;
  268. property TC: UInt16 read GetTC write SetTC;
  269. property RD: UInt16 read GetRD write SetRD;
  270. property RA: UInt16 read GetRA write SetRA;
  271. property RCode: UInt16 read GetRCode write SetRCode;
  272. property BitCode: UInt16 read FBitCode write SetBitCode;
  273. property QDCount: UInt16 read FQDCount write FQDCount;
  274. property ANCount: UInt16 read FANCount write FANCount;
  275. property NSCount: UInt16 read FNSCount write FNSCount;
  276. property ARCount: UInt16 read FARCount write FARCount;
  277. end;
  278. TIdTextModeResourceRecord = class(TObject)
  279. protected
  280. FAnswer : TIdBytes;
  281. FRRName: string;
  282. FRRDatas: TStrings; //TODO Should not be TIdStrings
  283. FTTL: Int32;
  284. FTypeCode: Integer;
  285. FTimeOut: string;
  286. function FormatQName(const AFullName: string): string; overload;
  287. function FormatQName(const AName, AFullName: string): string; overload;
  288. function FormatQNameFull(const AFullName: string): string;
  289. function FormatRecord(const AFullName: String; const ARRData: TIdBytes): TIdBytes;
  290. procedure SetRRDatas(const Value: TStrings);
  291. procedure SetTTL(const Value: Int32);
  292. public
  293. constructor CreateInit(const ARRName: String; ATypeCode: Integer);
  294. destructor Destroy; override;
  295. property TypeCode : Integer read FTypeCode;
  296. property RRName : string read FRRName write FRRName;
  297. property RRDatas : TStrings read FRRDatas write SetRRDatas;
  298. property TTL : integer read FTTL write SetTTL;
  299. property TimeOut : string read FTimeOut write FTimeOut;
  300. function ifAddFullName(AFullName: string; AGivenName: string = ''): boolean;
  301. function GetValue(const AName: String): String;
  302. procedure SetValue(const AName: String; const AValue: String);
  303. function ItemCount : Integer;
  304. function BinQueryRecord(AFullName: string): TIdBytes; virtual;
  305. function TextRecord(AFullName: string): string; virtual;
  306. procedure ClearAnswer;
  307. end;
  308. TIdTextModeRRs = class(TIdObjectList{$IFDEF HAS_GENERICS_TObjectList}<TIdTextModeResourceRecord>{$ENDIF})
  309. private
  310. FItemNames : TStrings;
  311. {$IFNDEF HAS_GENERICS_TObjectList}
  312. function GetItem(Index: Integer): TIdTextModeResourceRecord;
  313. procedure SetItem(Index: Integer; const Value: TIdTextModeResourceRecord);
  314. {$ENDIF}
  315. procedure SetItemNames(const Value: TStrings);
  316. public
  317. constructor Create;
  318. destructor Destroy; override;
  319. property ItemNames : TStrings read FItemNames write SetItemNames;
  320. {$IFNDEF HAS_GENERICS_TObjectList}
  321. property Items[Index: Integer]: TIdTextModeResourceRecord read GetItem write SetItem; default;
  322. {$ENDIF}
  323. end;
  324. TIdRR_CName = class(TIdTextModeResourceRecord)
  325. protected
  326. function GetCName: String;
  327. procedure SetCName(const Value: String);
  328. public
  329. constructor Create;
  330. property CName : String read GetCName write SetCName;
  331. function BinQueryRecord(AFullName: string): TIdBytes; override;
  332. function TextRecord(AFullName : string) : string; override;
  333. end;
  334. TIdRR_HINFO = class(TIdTextModeResourceRecord)
  335. protected
  336. procedure SetCPU(const Value: String);
  337. function GetCPU: String;
  338. function GetOS: String;
  339. procedure SetOS(const Value: String);
  340. public
  341. constructor Create;
  342. property CPU : String read GetCPU write SetCPU;
  343. property OS : String read GetOS write SetOS;
  344. function BinQueryRecord(AFullName : string): TIdBytes; override;
  345. function TextRecord(AFullName : string) : string; override;
  346. end;
  347. TIdRR_MB = class(TIdTextModeResourceRecord)
  348. protected
  349. function GetMADName: String;
  350. procedure SetMADName(const Value: String);
  351. public
  352. constructor Create;
  353. property MADName : String read GetMADName write SetMADName;
  354. function BinQueryRecord(AFullName : string) : TIdBytes; override;
  355. function TextRecord(AFullName : string) : string; override;
  356. end;
  357. TIdRR_MG = class(TIdTextModeResourceRecord)
  358. protected
  359. function GetMGMName: String;
  360. procedure SetMGMName(const Value: String);
  361. public
  362. constructor Create;
  363. property MGMName : String read GetMGMName write SetMGMName;
  364. function BinQueryRecord(AFullName : string) : TIdBytes; override;
  365. function TextRecord(AFullName : string) : string; override;
  366. end;
  367. TIdRR_MINFO = class(TIdTextModeResourceRecord)
  368. protected
  369. procedure SetErrorHandle_Mail(const Value: String);
  370. procedure SetResponsible_Mail(const Value: String);
  371. function GetEMail: String;
  372. function GetRMail: String;
  373. public
  374. constructor Create;
  375. property Responsible_Mail : String read GetRMail write SetResponsible_Mail;
  376. property ErrorHandle_Mail : String read GetEMail write SetErrorHandle_Mail;
  377. function BinQueryRecord(AFullName : string) : TIdBytes; override;
  378. function TextRecord(AFullName : string) : string; override;
  379. end;
  380. TIdRR_MR = class(TIdTextModeResourceRecord)
  381. protected
  382. function GetNewName: String;
  383. procedure SetNewName(const Value: String);
  384. public
  385. constructor Create;
  386. property NewName : String read GetNewName write SetNewName;
  387. function BinQueryRecord(AFullName : string) : TIdBytes; override;
  388. function TextRecord(AFullName : string) : string; override;
  389. end;
  390. TIdRR_MX = class(TIdTextModeResourceRecord)
  391. protected
  392. function GetExchang: String;
  393. procedure SetExchange(const Value: String);
  394. function GetPref: String;
  395. procedure SetPref(const Value: String);
  396. public
  397. constructor Create;
  398. property Exchange : String read GetExchang write SetExchange;
  399. property Preference : String read GetPref write SetPref;
  400. function BinQueryRecord(AFullName : string) : TIdBytes; override;
  401. function TextRecord(AFullName : string) : string; override;
  402. end;
  403. TIdRR_NS = class(TIdTextModeResourceRecord)
  404. protected
  405. function GetNS: String;
  406. procedure SetNS(const Value: String);
  407. public
  408. constructor Create;
  409. property NSDName : String read GetNS write SetNS;
  410. function BinQueryRecord(AFullName : string): TIdBytes; override;
  411. function TextRecord(AFullName : string) : string; override;
  412. end;
  413. TIdRR_PTR = class(TIdTextModeResourceRecord)
  414. protected
  415. function GetPTRName: String;
  416. procedure SetPTRName(const Value: String);
  417. public
  418. constructor Create;
  419. property PTRDName : String read GetPTRName write SetPTRName;
  420. function BinQueryRecord(AFullName : string): TIdBytes; override;
  421. function TextRecord(AFullName : string) : string; override;
  422. end;
  423. TIdRR_SOA = class(TIdTextModeResourceRecord)
  424. protected
  425. function GetName(const CLabel : String): String;
  426. procedure SetName(const CLabel: String; const Value : String);
  427. function GetMName: String;
  428. function GetRName: String;
  429. procedure SetMName(const Value: String);
  430. procedure SetRName(const Value: String);
  431. function GetMin: String;
  432. function GetRefresh: String;
  433. function GetRetry: String;
  434. function GetSerial: String;
  435. procedure SetMin(const Value: String);
  436. procedure SetRefresh(const Value: String);
  437. procedure SetRetry(const Value: String);
  438. procedure SetSerial(const Value: String);
  439. function GetExpire: String;
  440. procedure SetExpire(const Value: String);
  441. public
  442. constructor Create;
  443. property MName : String read GetMName write SetMName;
  444. property RName : String read GetRName write SetRName;
  445. property Serial : String read GetSerial write SetSerial;
  446. property Refresh : String read GetRefresh write SetRefresh;
  447. property Retry : String read GetRetry write SetRetry;
  448. property Expire : String read GetExpire write SetExpire;
  449. property Minimum : String read GetMin write SetMin;
  450. function BinQueryRecord(AFullName : string) : TIdBytes; override;
  451. function TextRecord(AFullName : string) : string; override;
  452. end;
  453. TIdRR_A = class(TIdTextModeResourceRecord)
  454. protected
  455. function GetA: String;
  456. procedure SetA(const Value: String);
  457. public
  458. constructor Create;
  459. property Address : String read GetA write SetA;
  460. function BinQueryRecord(AFullName : string) : TIdBytes; override;
  461. function TextRecord(AFullName : string) : string; override;
  462. end;
  463. TIdRR_AAAA = class(TIdTextModeResourceRecord)
  464. protected
  465. function GetA: String;
  466. procedure SetA(const Value: String);
  467. public
  468. constructor Create;
  469. property Address : String read GetA write SetA;
  470. function BinQueryRecord(AFullName : string) : TIdBytes; override;
  471. function TextRecord(AFullName : string) : string; override;
  472. end;
  473. { TODO : implement WKS record class }
  474. TIdRR_WKS = class(TIdTextModeResourceRecord)
  475. public
  476. constructor Create;
  477. end;
  478. TIdRR_TXT = class(TIdTextModeResourceRecord)
  479. protected
  480. function GetTXT: String;
  481. procedure SetTXT(const Value: String);
  482. public
  483. constructor Create;
  484. property TXT : String read GetTXT write SetTXT;
  485. function BinQueryRecord(AFullName : string) : TIdBytes; override;
  486. function TextRecord(AFullName : string) : string; override;
  487. end;
  488. TIdRR_Error = class(TIdTextModeResourceRecord)
  489. public
  490. constructor Create;
  491. end;
  492. function DomainNameToDNSStr(const ADomain : String): TIdBytes;
  493. function NormalStrToDNSStr(const Str : String): TIdBytes;
  494. function IPAddrToDNSStr(const IPAddress : String): TIdBytes;
  495. function IsValidIPv6(const v6Address : String): Boolean;
  496. function ConvertToValidv6IP(const OrgIP : String) : string;
  497. function ConvertToCanonical6IP(const OrgIP : String) : string;
  498. function IPv6AAAAToDNSStr(const AIPv6Address : String): TIdBytes;
  499. function GetErrorStr(const Code, Id: Integer): String;
  500. function GetRCodeStr(RCode : Integer): String;
  501. function ReplaceSpecString(Source, Target, NewString : string; ReplaceAll : boolean = True) : string;
  502. function IsBig5(ch1, ch2: Char) : Boolean;
  503. implementation
  504. uses
  505. {$IFDEF VCL_XE3_OR_ABOVE}
  506. {$IFNDEF NEXTGEN}
  507. System.Contnrs,
  508. {$ENDIF}
  509. {$ENDIF}
  510. {$IFDEF HAS_UNIT_DateUtils}
  511. DateUtils,
  512. {$ENDIF}
  513. IdGlobalProtocols,
  514. IdStack, SysUtils;
  515. const
  516. ValidHexChars = '0123456789ABCDEFabcdef';
  517. procedure IdBytesCopyBytes(const ASource: TIdBytes; var VDest: TIdBytes; var VDestIndex: Integer);
  518. begin
  519. CopyTIdBytes(ASource, 0, VDest, VDestIndex, Length(ASource));
  520. Inc(VDestIndex, Length(ASource));
  521. end;
  522. procedure IdBytesCopyUInt16(const ASource: UInt16; var VDest: TIdBytes; var VDestIndex: Integer);
  523. begin
  524. CopyTIdUInt16(ASource, VDest, VDestIndex);
  525. Inc(VDestIndex, SizeOf(UInt16));
  526. end;
  527. procedure IdBytesCopyUInt32(const ASource: UInt32; var VDest: TIdBytes; var VDestIndex: Integer);
  528. begin
  529. CopyTIdUInt32(ASource, VDest, VDestIndex);
  530. Inc(VDestIndex, SizeOf(UInt32));
  531. end;
  532. function DomainNameToDNSStr(const ADomain : string): TIdBytes;
  533. var
  534. BufStr, LDomain : String;
  535. LIdx : Integer;
  536. LLen: Byte;
  537. begin
  538. if Length(ADomain) = 0 then begin
  539. SetLength(Result, 0);
  540. end else begin
  541. // TODO: ned to re-write this...
  542. SetLength(Result, Length(ADomain)+1);
  543. LIdx := 0;
  544. LDomain := ADomain;
  545. repeat
  546. BufStr := Fetch(LDomain, '.');
  547. LLen := Length(BufStr);
  548. Result[LIdx] := LLen;
  549. CopyTIdString(BufStr, Result, LIdx+1, LLen);
  550. Inc(LIdx, LLen+1);
  551. until LDomain = '';
  552. Result[LIdx] := 0;
  553. SetLength(Result, LIdx+1);
  554. end;
  555. end;
  556. function NormalStrToDNSStr(const Str : String): TIdBytes;
  557. var
  558. LLen: Byte;
  559. LStr: TIdBytes;
  560. begin
  561. LStr := ToBytes(Str);
  562. LLen := IndyMin(Length(LStr), $FF);
  563. SetLength(Result, 1 + LLen);
  564. Result[0] := LLen;
  565. CopyTIdBytes(LStr, 0, Result, 1, LLen);
  566. end;
  567. function IPAddrToDNSStr(const IPAddress : String): TIdBytes;
  568. Var
  569. j, i: Integer;
  570. s : string;
  571. begin
  572. SetLength(Result, 0);
  573. if IsValidIP(IPAddress) then begin
  574. s := Trim(IPAddress);
  575. SetLength(Result, 4);
  576. for i := 0 to 3 do begin
  577. j := IndyStrToInt(Fetch(s, '.'), -1); {do not localize}
  578. if (j < 0) or (j > 255) then begin
  579. Result := ToBytes('Error IP'); {do not localize}
  580. Exit;
  581. end;
  582. Result[I] := Byte(j);
  583. end;
  584. end else begin
  585. Result := ToBytes('Error IP'); {do not localize}
  586. end;
  587. end;
  588. procedure IdHexToBin(const AText: TIdBytes; var Buffer: TIdBytes; const BufSize: Integer);
  589. const
  590. Convert: array['0'..'f'] of Int16 = {do not localize}
  591. ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
  592. -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  593. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  594. -1,10,11,12,13,14,15);
  595. var
  596. BufferPos, TextPos: Integer;
  597. ValidChars: TIdBytes;
  598. begin
  599. ValidChars := ToBytes(ValidHexChars);
  600. BufferPos := 0;
  601. TextPos := 0;
  602. repeat
  603. if (not ByteIsInSet(AText, TextPos, ValidChars)) or
  604. (not ByteIsInSet(AText, TextPos+1, ValidChars)) then
  605. begin
  606. Break;
  607. end;
  608. Buffer[BufferPos] := (Convert[Char(AText[TextPos])] shl 4) + Convert[Char(AText[TextPos + 1])];
  609. Inc(BufferPos);
  610. Inc(TextPos, 2);
  611. until False;
  612. end;
  613. function IPv6AAAAToDNSStr(const AIPv6Address : String): TIdBytes;
  614. var
  615. LAddr : TIdIPv6Address;
  616. begin
  617. IPv6ToIdIPv6Address(AIPv6Address, LAddr);
  618. SetLength(Result, 16);
  619. CopyTIdIPV6Address(LAddr, Result, 0);
  620. end;
  621. function IsValidIPv6(const v6Address : String): boolean;
  622. var
  623. Temps : TStrings;
  624. Apart, All: String;
  625. Count, Loc, Goal : integer;
  626. begin
  627. All := v6Address;
  628. Temps := TStringList.Create;
  629. try
  630. // Check Double Colon existence, but only single.
  631. Count := 0;
  632. repeat
  633. Loc := IndyPos('::', All); {do not localize}
  634. if Loc > 0 then begin
  635. Count := Count + 1;
  636. IdDelete(All, Loc, 2);
  637. end;
  638. until Loc = 0;
  639. if Count <= 1 then begin
  640. // Convert Double colon into compatible format.
  641. All := ReplaceSpecString(v6Address, '::', ':Multi:'); {do not localize}
  642. repeat
  643. Apart := Fetch(All, ':'); {do not localize}
  644. Temps.Add(Apart);
  645. until All = ''; {do not localize}
  646. Loc := Temps.IndexOf('Multi'); {do not localize}
  647. if Loc > -1 then begin
  648. Goal := 8 - Temps.Count;
  649. Temps.Strings[Loc] := '0000'; {do not localize}
  650. for Count := 0 to Goal -1 do begin
  651. Temps.Insert(Loc, '0000'); {do not localize}
  652. end;
  653. if Temps.Strings[0] = '' then begin {do not localize}
  654. Temps.Strings[0] := '0000'; {do not localize}
  655. end;
  656. end;
  657. All := ReplaceSpecString(Temps.CommaText, ',', ':'); {do not localize}
  658. Result := True;
  659. Temps.Clear;
  660. repeat
  661. Apart := Trim(Fetch(All, ':')); {do not localize}
  662. if Length(Apart) <= 4 then begin
  663. Apart := '0000' + Apart; {do not localize}
  664. Apart := Copy(Apart, Length(Apart)-3, 4);
  665. Temps.Add(Apart);
  666. end else begin
  667. Result := False;
  668. end;
  669. until (All = '') or (not Result); {do not localize}
  670. if (not Result) or (Temps.Count > 8) then begin
  671. Result := False;
  672. end else begin
  673. for Count := 0 to Temps.Count -1 do begin
  674. All := All + Temps.Strings[Count];
  675. end;
  676. Result := Length(All) > 0;
  677. for Count := 1 to Length(All) do begin
  678. Result := CharIsInSet(All, Count, ValidHexChars);
  679. if not Result then begin
  680. Break;
  681. end;
  682. end;
  683. end;
  684. end else begin
  685. // mulitple Double colon, it's an incorrect IPv6 address.
  686. Result := False;
  687. end;
  688. finally
  689. FreeAndNil(Temps);
  690. end;
  691. end;
  692. function ConvertToValidv6IP(const OrgIP : String) : string;
  693. var
  694. All, Apart : string;
  695. Temps : TStrings;
  696. Count, Loc, Goal : integer;
  697. begin
  698. Result := '';
  699. All := OrgIP;
  700. Temps := TStringList.Create;
  701. try
  702. // Check Double Colon existence, but only single.
  703. // Count := 0;
  704. repeat
  705. Loc := IndyPos('::', All); {do not localize}
  706. if Loc > 0 then begin
  707. // Count := Count + 1;
  708. IdDelete(All, Loc, 2);
  709. end;
  710. until Loc = 0;
  711. // Convert Double colon into compatible format.
  712. All := ReplaceSpecString(OrgIP, '::', ':Multi:'); {do not localize}
  713. repeat
  714. Apart := Fetch(All, ':'); {do not localize}
  715. Temps.Add(Apart);
  716. until All = ''; {do not localize}
  717. Loc := Temps.IndexOf('Multi'); {do not localize}
  718. if Loc > -1 then begin
  719. Goal := 8 - Temps.Count;
  720. Temps.Strings[Loc] := '0000'; {do not localize}
  721. for Count := 0 to Goal -1 do begin
  722. Temps.Insert(Loc, '0000'); {do not localize}
  723. end;
  724. if Temps.Strings[0] = '' then begin
  725. Temps.Strings[0] := '0000'; {do not localize}
  726. end;
  727. end;
  728. Result := ReplaceSpecString(Temps.CommaText, ',', ':'); {do not localize}
  729. finally
  730. FreeAndNil(Temps);
  731. end;
  732. end;
  733. function ConvertToCanonical6IP(const OrgIP : String) : string;
  734. var
  735. All, Apart: string;
  736. begin
  737. {Supposed OrgIP is valid IPV6 string}
  738. Result := ''; {do not localize}
  739. All := ConvertToValidv6IP(OrgIP);
  740. repeat
  741. Apart := Trim(Fetch(All, ':')); {do not localize}
  742. if Length(Apart) < 4 then
  743. begin
  744. Apart := '0000' + Apart; {do not localize}
  745. Apart := Copy(Apart, Length(Apart)-3, 4);
  746. end;
  747. Result := Result + Apart + ':'; {do not localize}
  748. until (All = ''); {do not localize}
  749. SetLength(Result, Length(Result) - 1); //Remove last :
  750. end;
  751. { TODO : Move these to member }
  752. function GetErrorStr(const Code, Id: Integer): String;
  753. begin
  754. case Code of
  755. 1 : Result := IndyFormat(RSQueryInvalidQueryCount, [Id]);
  756. 2 : Result := IndyFormat(RSQueryInvalidPacketSize, [Id]);
  757. 3 : Result := IndyFormat(RSQueryLessThanFour, [Id]);
  758. 4 : Result := IndyFormat(RSQueryInvalidHeaderID, [Id] );
  759. 5 : Result := IndyFormat(RSQueryLessThanTwelve, [Id]);
  760. 6 : Result := IndyFormat(RSQueryPackReceivedTooSmall, [Id]);
  761. else
  762. Result := IndyFormat(RSQueryUnknownError, [Code, Id]);
  763. end; //case code Of
  764. end;
  765. function GetRCodeStr(RCode : Integer): String;
  766. begin
  767. if Rcode in [cRCodeNoError..cRCodeRefused] then begin
  768. Result := cRCodeStrs[Rcode];
  769. end else begin // if Rcode in [cRCodeNoError..cRCodeRefused] then
  770. Result := RSCodeQueryUnknownError;
  771. end; //else.. if Rcode in [cRCodeNoError..cRCodeRefused] then
  772. end;
  773. { TDNSHeader }
  774. procedure TDNSHeader.ClearByteCode;
  775. begin
  776. FBitCode := 0;
  777. end;
  778. constructor TDNSHeader.Create;
  779. begin
  780. inherited Create;
  781. Randomize;
  782. FId := Random(65535);
  783. end;
  784. function TDNSHeader.GenerateBinaryHeader: TIdBytes;
  785. {
  786. The header contains the following fields:
  787. 1 1 1 1 1 1
  788. 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  789. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  790. | ID |
  791. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  792. |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE |
  793. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  794. | QDCOUNT/ZOCOUNT |
  795. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  796. | ANCOUNT/PRCOUNT |
  797. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  798. | NSCOUNT/UPCOUNT |
  799. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  800. | ARCOUNT |
  801. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  802. where:
  803. ID A 16 bit identifier assigned by the program that
  804. generates any kind of query. This identifier is copied
  805. the corresponding reply and can be used by the requester
  806. to match up replies to outstanding queries.
  807. QR A one bit field that specifies whether this message is a
  808. query (0), or a response (1).
  809. OPCODE A four bit field that specifies kind of query in this
  810. message. This value is set by the originator of a query
  811. and copied into the response. The values are:
  812. 0 a standard query (QUERY)
  813. 1 an inverse query (IQUERY)
  814. 2 a server status request (STATUS)
  815. 3-15 reserved for future use
  816. AA Authoritative Answer - this bit is valid in responses,
  817. and specifies that the responding name server is an
  818. authority for the domain name in question section.
  819. Note that the contents of the answer section may have
  820. multiple owner names because of aliases. The AA bit
  821. corresponds to the name which matches the query name, or
  822. the first owner name in the answer section.
  823. TC TrunCation - specifies that this message was truncated
  824. due to length greater than that permitted on the
  825. transmission channel.
  826. RD Recursion Desired - this bit may be set in a query and
  827. is copied into the response. If RD is set, it directs
  828. the name server to pursue the query recursively.
  829. Recursive query support is optional.
  830. RA Recursion Available - this be is set or cleared in a
  831. response, and denotes whether recursive query support is
  832. available in the name server.
  833. Z Reserved for future use. Must be zero in all queries
  834. and responses.
  835. AD Authentic Data - signal indicating that the requester
  836. understands and is interested in the value of the AD bit
  837. in the response. This allows a requester to indicate that
  838. it understands the AD bit without also requesting DNSSEC
  839. data via the DO bit.
  840. CD Checking Disabled
  841. RCODE Response code - this 4 bit field is set as part of
  842. responses. The values have the following
  843. interpretation:
  844. 0 No error condition
  845. 1 Format error - The name server was
  846. unable to interpret the query.
  847. 2 Server failure - The name server was
  848. unable to process this query due to a
  849. problem with the name server.
  850. 3 Name Error - Meaningful only for
  851. responses from an authoritative name
  852. server, this code signifies that the
  853. domain name referenced in the query does
  854. not exist.
  855. 4 Not Implemented - The name server does
  856. not support the requested kind of query.
  857. 5 Refused - The name server refuses to
  858. perform the specified operation for
  859. policy reasons. For example, a name
  860. server may not wish to provide the
  861. information to the particular requester,
  862. or a name server may not wish to perform
  863. a particular operation (e.g., zone
  864. transfer) for particular data.
  865. 6-15 Reserved for future use.
  866. QDCOUNT an unsigned 16 bit integer specifying the number of
  867. entries in the question section.
  868. ANCOUNT an unsigned 16 bit integer specifying the number of
  869. resource records in the answer section.
  870. NSCOUNT an unsigned 16 bit integer specifying the number of name
  871. server resource records in the authority records
  872. section.
  873. ARCOUNT an unsigned 16 bit integer specifying the number of
  874. resource records in the additional records section.
  875. }
  876. begin
  877. SetLength(Result, 12);
  878. UInt16ToTwoBytes(GStack.HostToNetwork(ID), Result, 0);
  879. UInt16ToTwoBytes(GStack.HostToNetwork(BitCode), Result, 2);
  880. UInt16ToTwoBytes(GStack.HostToNetwork(QDCount), Result, 4);
  881. UInt16ToTwoBytes(GStack.HostToNetwork(ANCount), Result, 6);
  882. UInt16ToTwoBytes(GStack.HostToNetwork(NSCount), Result, 8);
  883. UInt16ToTwoBytes(GStack.HostToNetwork(ARCount), Result, 10);
  884. end;
  885. function TDNSHeader.GetAA: UInt16;
  886. begin
  887. Result := (FBitCode shr 10) and $0001;
  888. end;
  889. {
  890. function TDNSHeader.GetAD: UInt16;
  891. begin
  892. Result := (FBitCode shr 5) and $0001;
  893. end;
  894. function TDNSHeader.GetCD: UInt16;
  895. begin
  896. Result := (FBitCode shr 4) and $0001;
  897. end;
  898. }
  899. function TDNSHeader.GetOpCode: UInt16;
  900. begin
  901. Result := (FBitCode shr 11) and $000F;
  902. end;
  903. function TDNSHeader.GetQr: UInt16;
  904. begin
  905. Result := (FBitCode shr 15) and $0001;
  906. end;
  907. function TDNSHeader.GetRA: UInt16;
  908. begin
  909. Result := (FBitCode shr 7) and $0001;
  910. end;
  911. function TDNSHeader.GetRCode: UInt16;
  912. begin
  913. Result := FBitCode and $000F;
  914. end;
  915. function TDNSHeader.GetRD: UInt16;
  916. begin
  917. Result := (FBitCode shr 8) and $0001;
  918. end;
  919. function TDNSHeader.GetTC: UInt16;
  920. begin
  921. Result := (FBitCode shr 9) and $0001;
  922. end;
  923. function TDNSHeader.ParseQuery(Data: TIdBytes): integer;
  924. begin
  925. Result := -1;
  926. if Length(Data) >= 12 then begin
  927. try
  928. ID := GStack.NetworkToHost(BytesToUInt16(Data, 0));
  929. BitCode := GStack.NetworkToHost(BytesToUInt16(Data, 2));
  930. QDCount := GStack.NetworkToHost(BytesToUInt16(Data, 4));
  931. ANCount := GStack.NetworkToHost(BytesToUInt16(Data, 6));
  932. NSCount := GStack.NetworkToHost(BytesToUInt16(Data, 8));
  933. ARCount := GStack.NetworkToHost(BytesToUInt16(Data, 10));
  934. Result := 0;
  935. except
  936. end;
  937. end;
  938. end;
  939. procedure TDNSHeader.SetAA(const Value: UInt16);
  940. begin
  941. if Value = 0 then begin
  942. FBitCode := FBitCode and $FBFF;
  943. end else begin
  944. FBitCode := FBitCode or $0400;
  945. end;
  946. end;
  947. {
  948. procedure TDNSHeader.SetAD(const Value: UInt16);
  949. begin
  950. if Value = 0 then begin
  951. FBitCode := FBitCode and $FFDF;
  952. end else begin
  953. FBitCode := FBitCode or $0020;
  954. end;
  955. end;
  956. }
  957. procedure TDNSHeader.SetBitCode(const Value: UInt16);
  958. begin
  959. FBitCode := Value;
  960. end;
  961. {
  962. procedure TDNSHeader.SetCD(const Value: UInt16);
  963. begin
  964. if Value = 0 then begin
  965. FBitCode := FBitCode and $FFEF;
  966. end else begin
  967. FBitCode := FBitCode or $0010;
  968. end;
  969. end;
  970. }
  971. procedure TDNSHeader.SetOpCode(const Value: UInt16);
  972. begin
  973. FBitCode := (FBitCode and $87FF) or ((Value and $000F) shl 11);
  974. end;
  975. procedure TDNSHeader.SetQr(const Value: UInt16);
  976. begin
  977. if Value = 0 then begin
  978. FBitCode := FBitCode and $7FFF;
  979. end else begin
  980. FBitCode := FBitCode or $8000;
  981. end;
  982. end;
  983. procedure TDNSHeader.SetRA(const Value: UInt16);
  984. begin
  985. if Value = 0 then begin
  986. FBitCode := FBitCode and $FF7F;
  987. end else begin
  988. FBitCode := FBitCode or $0080;
  989. end;
  990. end;
  991. procedure TDNSHeader.SetRCode(const Value: UInt16);
  992. begin
  993. FBitCode := (FBitCode and $FFF0) or (Value and $000F);
  994. end;
  995. procedure TDNSHeader.SetRD(const Value: UInt16);
  996. begin
  997. if Value = 0 then begin
  998. FBitCode := FBitCode and $FEFF;
  999. end else begin
  1000. FBitCode := FBitCode or $0100;
  1001. end;
  1002. end;
  1003. procedure TDNSHeader.SetTC(const Value: UInt16);
  1004. begin
  1005. if Value = 0 then begin
  1006. FBitCode := FBitCode and $FDFF;
  1007. end else begin
  1008. FBitCode := FBitCode or $0200;
  1009. end;
  1010. end;
  1011. { TIdTextModeResourceRecord }
  1012. function TIdTextModeResourceRecord.BinQueryRecord(AFullName: string): TIdBytes;
  1013. begin
  1014. // This was empty? Where did it go?
  1015. //todo;
  1016. // Explain by Dennies : No, here must be empty, it's only a
  1017. // virtual method, for child class to implement.
  1018. Result := nil;
  1019. end;
  1020. procedure TIdTextModeResourceRecord.ClearAnswer;
  1021. begin
  1022. SetLength(FAnswer, 0);
  1023. end;
  1024. constructor TIdTextModeResourceRecord.CreateInit(const ARRName: String; ATypeCode: Integer);
  1025. begin
  1026. inherited Create;
  1027. SetLength(FAnswer, 0);
  1028. FRRName := ARRName;
  1029. FTypeCode := ATypeCode;
  1030. FRRDatas := TStringList.Create;
  1031. TTL := 0;
  1032. end;
  1033. destructor TIdTextModeResourceRecord.Destroy;
  1034. begin
  1035. FreeAndNil(FRRDatas);
  1036. inherited Destroy;
  1037. end;
  1038. function TIdTextModeResourceRecord.FormatQName(const AFullName: string): string;
  1039. begin
  1040. Result := FormatQName(FRRName, AFullName);
  1041. end;
  1042. function TIdTextModeResourceRecord.FormatQName(const AName, AFullName: string): string;
  1043. begin
  1044. if Copy(AName, Length(AName), 1) <> '.' then begin
  1045. Result := AName + '.' + AFullName;
  1046. end else begin
  1047. Result := AName;
  1048. end;
  1049. end;
  1050. function TIdTextModeResourceRecord.FormatQNameFull(const AFullName: string): string;
  1051. var
  1052. LQName: string;
  1053. begin
  1054. LQName := FRRName + '.';
  1055. if LQName <> AFullName then begin
  1056. LQName := FormatQName(AFullName);
  1057. end;
  1058. if LQName = AFullName then begin
  1059. Result := '@';
  1060. end else begin
  1061. Result := LQName;
  1062. end;
  1063. end;
  1064. function TIdTextModeResourceRecord.FormatRecord(const AFullName: String; const ARRData: TIdBytes): TIdBytes;
  1065. var
  1066. LDomain: TIdBytes;
  1067. LIdx: Integer;
  1068. begin
  1069. LDomain := DomainNameToDNSStr(FormatQName(AFullName));
  1070. SetLength(Result, Length(LDomain)+(SizeOf(UInt16)*3)+SizeOf(UInt32)+Length(ARRData));
  1071. LIdx := 0;
  1072. IdBytesCopyBytes(LDomain, Result, LIdx);
  1073. IdBytesCopyUInt16(GStack.HostToNetwork(UInt16(TypeCode)), Result, LIdx);
  1074. IdBytesCopyUInt16(GStack.HostToNetwork(UInt16(Class_IN)), Result, LIdx);
  1075. IdBytesCopyUInt32(GStack.HostToNetwork(UInt32(TTL)), Result, LIdx);
  1076. IdBytesCopyUInt16(GStack.HostToNetwork(UInt16(Length(ARRData))), Result, LIdx);
  1077. IdBytesCopyBytes(ARRData, Result, LIdx);
  1078. end;
  1079. function TIdTextModeResourceRecord.GetValue(const AName: String): String;
  1080. begin
  1081. Result := RRDatas.Values[AName];
  1082. end;
  1083. procedure TIdTextModeResourceRecord.SetValue(const AName: String; const AValue: String);
  1084. begin
  1085. RRDatas.Values[AName] := AValue;
  1086. end;
  1087. function TIdTextModeResourceRecord.ifAddFullName(AFullName, AGivenName: string): boolean;
  1088. var
  1089. LTailString, LBackString, LDestination : string;
  1090. LTS, LRR : integer;
  1091. begin
  1092. if AGivenName = '' then begin
  1093. LDestination := RRName;
  1094. end else begin
  1095. LDestination := AGivenName;
  1096. end;
  1097. if TextEndsWith(LDestination, '.') then begin
  1098. Result := False;
  1099. end else begin
  1100. if TextEndsWith(AFullName, '.') then begin
  1101. LTailString := Copy(AFullName, 1, Length(AFullName) - 1);
  1102. end else begin
  1103. LTailString := AFullName;
  1104. end;
  1105. LTS := Length(LTailString);
  1106. LRR := Length(LDestination);
  1107. if LRR >= LTS then begin
  1108. LBackString := Copy(LDestination, LRR - LTS + 1 , LTS);
  1109. Result := not (LBackString = LTailString);
  1110. end else begin
  1111. Result := True;
  1112. end;
  1113. end;
  1114. end;
  1115. function TIdTextModeResourceRecord.ItemCount: integer;
  1116. begin
  1117. Result := RRDatas.Count;
  1118. end;
  1119. procedure TIdTextModeResourceRecord.SetRRDatas(const Value: TStrings);
  1120. begin
  1121. FRRDatas.Assign(Value);
  1122. end;
  1123. procedure TIdTextModeResourceRecord.SetTTL(const Value: integer);
  1124. begin
  1125. FTTL := Value;
  1126. FTimeOut := DateTimeToStr(AddMSecToTime(Now, Value * 1000));
  1127. end;
  1128. function TIdTextModeResourceRecord.TextRecord(AFullName: string): string;
  1129. begin
  1130. Result := '';
  1131. end;
  1132. { TIdTextModeRRs }
  1133. constructor TIdTextModeRRs.Create;
  1134. begin
  1135. inherited Create;
  1136. FItemNames := TStringList.Create;
  1137. end;
  1138. destructor TIdTextModeRRs.Destroy;
  1139. begin
  1140. FreeAndNil(FItemNames);
  1141. inherited Destroy;
  1142. end;
  1143. {$IFNDEF HAS_GENERICS_TObjectList}
  1144. function TIdTextModeRRs.GetItem(Index: Integer): TIdTextModeResourceRecord;
  1145. begin
  1146. Result := TIdTextModeResourceRecord(inherited GetItem(Index));
  1147. end;
  1148. procedure TIdTextModeRRs.SetItem(Index: Integer; const Value: TIdTextModeResourceRecord);
  1149. begin
  1150. inherited SetItem(Index, Value);
  1151. end;
  1152. {$ENDIF}
  1153. procedure TIdTextModeRRs.SetItemNames(const Value: TStrings);
  1154. begin
  1155. FItemNames.Assign(Value);
  1156. end;
  1157. { TIdRR_CName }
  1158. function TIdRR_CName.BinQueryRecord(AFullName: string): TIdBytes;
  1159. var
  1160. RRData: TIdBytes;
  1161. begin
  1162. RRData := nil; // keep the compiler happy
  1163. if Length(FAnswer) = 0 then begin
  1164. RRData := DomainNameToDNSStr(CName);
  1165. FAnswer := FormatRecord(AFullName, RRData);
  1166. end;
  1167. Result := ToBytes(FAnswer, Length(FAnswer));
  1168. end;
  1169. constructor TIdRR_CName.Create;
  1170. begin
  1171. inherited CreateInit('CName', TypeCode_CName); {do not localize}
  1172. CName := '';
  1173. end;
  1174. function TIdRR_CName.GetCName: String;
  1175. begin
  1176. Result := GetValue('CName'); {do not localize}
  1177. end;
  1178. procedure TIdRR_CName.SetCName(const Value: String);
  1179. begin
  1180. SetValue('CName', Value); {do not localize}
  1181. end;
  1182. function TIdRR_CName.TextRecord(AFullName: string): string;
  1183. begin
  1184. Result := FormatQNameFull(AFullName) + Chr(9) + 'IN' + Chr(9) + 'CNAME' + Chr(9) + CName + EOL; {do not localize}
  1185. end;
  1186. { TIdRR_HINFO }
  1187. function TIdRR_HINFO.BinQueryRecord(AFullName: string): TIdBytes;
  1188. var
  1189. RRData: TIdBytes;
  1190. begin
  1191. if Length(FAnswer) = 0 then begin
  1192. RRData := NormalStrToDNSStr(CPU);
  1193. AppendBytes(RRData, NormalStrToDNSStr(OS));
  1194. FAnswer := FormatRecord(AFullName, RRData);
  1195. end;
  1196. Result := ToBytes(FAnswer, Length(FAnswer));
  1197. end;
  1198. constructor TIdRR_HINFO.Create;
  1199. begin
  1200. inherited CreateInit('HINFO', TypeCode_HINFO); {do not localize}
  1201. CPU := '';
  1202. OS := '';
  1203. end;
  1204. function TIdRR_HINFO.GetCPU: String;
  1205. begin
  1206. Result := GetValue('CPU'); {do not localize}
  1207. end;
  1208. function TIdRR_HINFO.GetOS: String;
  1209. begin
  1210. Result := GetValue('OS'); {do not localize}
  1211. end;
  1212. procedure TIdRR_HINFO.SetCPU(const Value: String);
  1213. begin
  1214. SetValue('CPU', Value); {do not localize}
  1215. end;
  1216. procedure TIdRR_HINFO.SetOS(const Value: String);
  1217. begin
  1218. SetValue('OS', Value); {do not localize}
  1219. end;
  1220. function TIdRR_HINFO.TextRecord(AFullName: string): string;
  1221. begin
  1222. Result := FormatQNameFull(AFullName) + Chr(9) + 'IN' + Chr(9) + 'HINFO' + Chr(9)
  1223. + '"' + CPU + '" "' + OS + '"' + EOL; {do not localize}
  1224. end;
  1225. { TIdRR_MB }
  1226. function TIdRR_MB.BinQueryRecord(AFullName: string): TIdBytes;
  1227. var
  1228. RRData: TIdBytes;
  1229. begin
  1230. RRData := nil; // keep the compiler happy
  1231. if Length(FAnswer) = 0 then begin
  1232. RRData := DomainNameToDNSStr(MADName);
  1233. FAnswer := FormatRecord(AFullName, RRData);
  1234. end;
  1235. Result := ToBytes(FAnswer, Length(FAnswer));
  1236. end;
  1237. constructor TIdRR_MB.Create;
  1238. begin
  1239. inherited CreateInit('MB', TypeCode_MB); {do not localize}
  1240. MADName := '';
  1241. end;
  1242. function TIdRR_MB.GetMADName: String;
  1243. begin
  1244. Result := GetValue('MADNAME'); {do not localize}
  1245. end;
  1246. procedure TIdRR_MB.SetMADName(const Value: String);
  1247. begin
  1248. SetValue('MADNAME', Value); {do not localize}
  1249. end;
  1250. function TIdRR_MB.TextRecord(AFullName: string): string;
  1251. begin
  1252. Result := FormatQNameFull(AFullName) + Chr(9) + 'IN' + Chr(9) + 'MB' + Chr(9) + MADName + EOL; {do not localize}
  1253. end;
  1254. { TIdRR_MG }
  1255. function TIdRR_MG.BinQueryRecord(AFullName: string): TIdBytes;
  1256. var
  1257. RRData: TIdBytes;
  1258. begin
  1259. RRData := nil; // keep the compiler happy
  1260. if Length(FAnswer) = 0 then begin
  1261. RRData := DomainNameToDNSStr(MGMName);
  1262. FAnswer := FormatRecord(AFullName, RRData);
  1263. end;
  1264. Result := ToBytes(FAnswer, Length(FAnswer));
  1265. end;
  1266. constructor TIdRR_MG.Create;
  1267. begin
  1268. inherited CreateInit('MG', TypeCode_MG); {do not localize}
  1269. MGMName := '';
  1270. end;
  1271. function TIdRR_MG.GetMGMName: String;
  1272. begin
  1273. Result := GetValue('MGMNAME'); {do not localize}
  1274. end;
  1275. procedure TIdRR_MG.SetMGMName(const Value: String);
  1276. begin
  1277. SetValue('MGMNAME', Value); {do not localize}
  1278. end;
  1279. function TIdRR_MG.TextRecord(AFullName: string): string;
  1280. begin
  1281. Result := FormatQNameFull(AFullName) + Chr(9) + 'IN' + Chr(9) + 'MG' + Chr(9) + MGMName + EOL; {do not localize}
  1282. end;
  1283. { TIdRR_MINFO }
  1284. function TIdRR_MINFO.BinQueryRecord(AFullName: string): TIdBytes;
  1285. var
  1286. RRData: TIdBytes;
  1287. {
  1288. From: http://www.its.uq.edu.au/DMT/RFC/rfc1035.html#MINFO_RR
  1289. 3.3.7. MINFO RDATA format (EXPERIMENTAL)
  1290. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1291. / RMAILBX /
  1292. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1293. / EMAILBX /
  1294. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  1295. }
  1296. begin
  1297. if Length(FAnswer) = 0 then begin
  1298. RRData := DomainNameToDNSStr(Responsible_Mail);
  1299. AppendBytes(RRData, DomainNameToDNSStr(ErrorHandle_Mail));
  1300. FAnswer := FormatRecord(AFullName, RRData);
  1301. end;
  1302. Result := ToBytes(FAnswer, Length(FAnswer));
  1303. end;
  1304. constructor TIdRR_MINFO.Create;
  1305. begin
  1306. inherited CreateInit('MINFO', TypeCode_MINFO); {do not localize}
  1307. Responsible_Mail := '';
  1308. ErrorHandle_Mail := '';
  1309. end;
  1310. function TIdRR_MINFO.GetEMail: String;
  1311. begin
  1312. Result := GetValue('EMAILBX'); {do not localize}
  1313. end;
  1314. function TIdRR_MINFO.GetRMail: String;
  1315. begin
  1316. Result := GetValue('RMAILBX'); {do not localize}
  1317. end;
  1318. procedure TIdRR_MINFO.SetErrorHandle_Mail(const Value: String);
  1319. begin
  1320. SetValue('EMAILBX', Value); {do not localize}
  1321. end;
  1322. procedure TIdRR_MINFO.SetResponsible_Mail(const Value: String);
  1323. begin
  1324. SetValue('RMAILBX', Value); {do not localize}
  1325. end;
  1326. function TIdRR_MINFO.TextRecord(AFullName: string): string;
  1327. begin
  1328. Result := FormatQNameFull(AFullName) + Chr(9) + 'IN' + Chr(9) + 'MINFO' + Chr(9) {do not localize}
  1329. + Responsible_Mail + ' ' + ErrorHandle_Mail + EOL; {do not localize}
  1330. end;
  1331. { TIdRR_MR }
  1332. function TIdRR_MR.BinQueryRecord(AFullName: string): TIdBytes;
  1333. var
  1334. RRData: TIdBytes;
  1335. begin
  1336. RRData := nil; // keep the compiler happy
  1337. if Length(FAnswer) = 0 then begin
  1338. RRData := DomainNameToDNSStr(NewName);
  1339. FAnswer := FormatRecord(AFullName, RRData);
  1340. end;
  1341. Result := ToBytes(FAnswer, Length(FAnswer));
  1342. end;
  1343. constructor TIdRR_MR.Create;
  1344. begin
  1345. inherited CreateInit('MR', TypeCode_MR); {do not localize}
  1346. NewName := '';
  1347. end;
  1348. function TIdRR_MR.GetNewName: String;
  1349. begin
  1350. Result := GetValue('NewName'); {do not localize}
  1351. end;
  1352. procedure TIdRR_MR.SetNewName(const Value: String);
  1353. begin
  1354. SetValue('NewName', Value); {do not localize}
  1355. end;
  1356. function TIdRR_MR.TextRecord(AFullName: string): string;
  1357. begin
  1358. Result := FormatQNameFull(AFullName) + Chr(9) + 'IN' + Chr(9) + 'MR' + Chr(9) + NewName + EOL; {do not localize}
  1359. end;
  1360. { TIdRR_MX }
  1361. function TIdRR_MX.BinQueryRecord(AFullName: string): TIdBytes;
  1362. var
  1363. RRData, Tmp: TIdBytes;
  1364. Pref : UInt16;
  1365. begin
  1366. Tmp := nil; // keep the compiler happy
  1367. if Length(FAnswer) = 0 then begin
  1368. Pref := IndyStrToInt(Preference);
  1369. RRData := ToBytes(GStack.HostToNetwork(Pref));
  1370. Tmp := DomainNameToDNSStr(FormatQName(Exchange,AFullName));
  1371. AppendBytes(RRData, Tmp);
  1372. FAnswer := FormatRecord(AFullName, RRData);
  1373. end;
  1374. Result := ToBytes(FAnswer, Length(FAnswer));
  1375. end;
  1376. constructor TIdRR_MX.Create;
  1377. begin
  1378. inherited CreateInit('MX', TypeCode_MX); {do not localize}
  1379. Exchange := '';
  1380. end;
  1381. function TIdRR_MX.GetExchang: String;
  1382. begin
  1383. Result := GetValue('EXCHANGE'); {do not localize}
  1384. end;
  1385. function TIdRR_MX.GetPref: String;
  1386. begin
  1387. Result := GetValue('PREF'); {do not localize}
  1388. end;
  1389. procedure TIdRR_MX.SetExchange(const Value: String);
  1390. begin
  1391. SetValue('EXCHANGE', Value); {do not localize}
  1392. end;
  1393. procedure TIdRR_MX.SetPref(const Value: String);
  1394. begin
  1395. SetValue('PREF', Value); {do not localize}
  1396. end;
  1397. function TIdRR_MX.TextRecord(AFullName: string): string;
  1398. begin
  1399. Result := FormatQNameFull(AFullName) + Chr(9) + 'IN' + Chr(9) + 'MX' + Chr(9) {do not localize}
  1400. + Preference + ' ' + Exchange + EOL; {do not localize}
  1401. end;
  1402. { TIdRR_NS }
  1403. function TIdRR_NS.BinQueryRecord(AFullName: string): TIdBytes;
  1404. var
  1405. RRData: TIdBytes;
  1406. begin
  1407. RRData := nil; // keep the compiler happy
  1408. if Length(FAnswer) = 0 then begin
  1409. RRData := DomainNameToDNSStr(NSDName);
  1410. FAnswer := FormatRecord(AFullName, RRData);
  1411. end;
  1412. Result := ToBytes(FAnswer, Length(FAnswer));
  1413. end;
  1414. constructor TIdRR_NS.Create;
  1415. begin
  1416. inherited CreateInit('NS', TypeCode_NS); {do not localize}
  1417. NSDName := '';
  1418. end;
  1419. function TIdRR_NS.GetNS: String;
  1420. begin
  1421. Result := GetValue('NSDNAME'); {do not localize}
  1422. end;
  1423. procedure TIdRR_NS.SetNS(const Value: String);
  1424. begin
  1425. SetValue('NSDNAME', Value); {do not localize}
  1426. end;
  1427. function TIdRR_NS.TextRecord(AFullName: string): string;
  1428. begin
  1429. Result := FormatQNameFull(AFullName) + Chr(9) + 'IN' + Chr(9) + 'NS' + Chr(9) + NSDName + EOL; {do not localize}
  1430. end;
  1431. { TIdRR_PTR }
  1432. function TIdRR_PTR.BinQueryRecord(AFullName: string): TIdBytes;
  1433. var
  1434. RRData: TIdBytes;
  1435. begin
  1436. RRData := nil; // keep the compiler happy
  1437. if Length(FAnswer) = 0 then begin
  1438. RRData := DomainNameToDNSStr(PTRDName);
  1439. FAnswer := FormatRecord(AFullName, RRData);
  1440. end;
  1441. Result := ToBytes(FAnswer, Length(FAnswer));
  1442. end;
  1443. constructor TIdRR_PTR.Create;
  1444. begin
  1445. inherited CreateInit('PTR', TypeCode_PTR); {do not localize}
  1446. PTRDName := '';
  1447. end;
  1448. function TIdRR_PTR.GetPTRName: String;
  1449. begin
  1450. Result := GetValue('PTRDNAME'); {do not localize}
  1451. end;
  1452. procedure TIdRR_PTR.SetPTRName(const Value: String);
  1453. begin
  1454. SetValue('PTRDNAME', Value); {do not localize}
  1455. end;
  1456. function TIdRR_PTR.TextRecord(AFullName: string): string;
  1457. begin
  1458. Result := FormatQNameFull(AFullName) + Chr(9) + 'IN' + Chr(9) + 'PTR' + Chr(9) + PTRDName + EOL; {do not localize}
  1459. end;
  1460. { TIdRR_SOA }
  1461. function TIdRR_SOA.BinQueryRecord(AFullName: string): TIdBytes;
  1462. var
  1463. LMName, LRName, RRData: TIdBytes;
  1464. LIdx: Integer;
  1465. begin
  1466. // keep the compiler happy
  1467. LMName := nil;
  1468. LRName := nil;
  1469. RRData := nil;
  1470. if Length(FAnswer) = 0 then begin
  1471. LMName := DomainNameToDNSStr(MName);
  1472. LRName := DomainNameToDNSStr(RName);
  1473. SetLength(RRData, Length(LMName)+Length(LRName)+(SizeOf(UInt32)*5));
  1474. LIdx := 0;
  1475. IdBytesCopyBytes(LMName, RRData, LIdx);
  1476. IdBytesCopyBytes(LRName, RRData, LIdx);
  1477. IdBytesCopyUInt32(GStack.HostToNetwork(UInt32(IndyStrToInt(Serial))), RRData, LIdx);
  1478. IdBytesCopyUInt32(GStack.HostToNetwork(UInt32(IndyStrToInt(Refresh))), RRData, LIdx);
  1479. IdBytesCopyUInt32(GStack.HostToNetwork(UInt32(IndyStrToInt(Retry))), RRData, LIdx);
  1480. IdBytesCopyUInt32(GStack.HostToNetwork(UInt32(IndyStrToInt(Expire))), RRData, LIdx);
  1481. IdBytesCopyUInt32(GStack.HostToNetwork(UInt32(IndyStrToInt(Minimum))), RRData, LIdx);
  1482. FAnswer := FormatRecord(AFullName, RRData);
  1483. end;
  1484. Result := ToBytes(FAnswer, Length(FAnswer));
  1485. end;
  1486. constructor TIdRR_SOA.Create;
  1487. begin
  1488. inherited CreateInit('SOA', TypeCode_SOA); {do not localize}
  1489. MName := '';
  1490. RName := '';
  1491. Serial := '';
  1492. Refresh := '';
  1493. Retry := '';
  1494. Expire := '';
  1495. Minimum := '';
  1496. end;
  1497. function TIdRR_SOA.GetExpire: String;
  1498. begin
  1499. Result := GetName('EXPIRE'); {do not localize}
  1500. end;
  1501. function TIdRR_SOA.GetMin: String;
  1502. begin
  1503. Result := GetName('MINIMUM'); {do not localize}
  1504. end;
  1505. function TIdRR_SOA.GetMName: String;
  1506. begin
  1507. Result := GetName('MNAME'); {do not localize}
  1508. end;
  1509. function TIdRR_SOA.GetName(const CLabel: String): String;
  1510. begin
  1511. Result := GetValue(CLabel);
  1512. end;
  1513. function TIdRR_SOA.GetRefresh: String;
  1514. begin
  1515. Result := GetName('REFRESH'); {do not localize}
  1516. end;
  1517. function TIdRR_SOA.GetRetry: String;
  1518. begin
  1519. Result := GetName('RETRY'); {do not localize}
  1520. end;
  1521. function TIdRR_SOA.GetRName: String;
  1522. begin
  1523. Result := GetName('RNAME'); {do not localize}
  1524. end;
  1525. function TIdRR_SOA.GetSerial: String;
  1526. begin
  1527. Result := GetName('SERIAL'); {do not localize}
  1528. end;
  1529. procedure TIdRR_SOA.SetExpire(const Value: String);
  1530. begin
  1531. SetName('EXPIRE', Value); {do not localize}
  1532. end;
  1533. procedure TIdRR_SOA.SetMin(const Value: String);
  1534. begin
  1535. SetName('MINIMUM', Value); {do not localize}
  1536. end;
  1537. procedure TIdRR_SOA.SetMName(const Value: String);
  1538. begin
  1539. SetName('MNAME', Value); {do not localize}
  1540. end;
  1541. procedure TIdRR_SOA.SetName(const CLabel: String; const Value: String);
  1542. begin
  1543. SetValue(CLabel, Value);
  1544. end;
  1545. procedure TIdRR_SOA.SetRefresh(const Value: String);
  1546. begin
  1547. SetName('REFRESH', Value); {do not localize}
  1548. end;
  1549. procedure TIdRR_SOA.SetRetry(const Value: String);
  1550. begin
  1551. SetName('RETRY', Value); {do not localize}
  1552. end;
  1553. procedure TIdRR_SOA.SetRName(const Value: String);
  1554. begin
  1555. SetName('RNAME', Value); {do not localize}
  1556. end;
  1557. procedure TIdRR_SOA.SetSerial(const Value: String);
  1558. begin
  1559. SetName('SERIAL', Value); {do not localize}
  1560. end;
  1561. function TIdRR_SOA.TextRecord(AFullName: string): string;
  1562. begin
  1563. Result := FormatQNameFull(AFullName) + Chr(9) + 'IN' + Chr(9) + 'SOA' + Chr(9) {do not localize}
  1564. + MName + ' ' + RName + ' ' + Serial + ' ' + Refresh + ' ' + Retry + ' ' {do not localize}
  1565. + Expire + ' ' + Minimum + EOL; {do not localize}
  1566. end;
  1567. { TIdRR_A }
  1568. function TIdRR_A.BinQueryRecord(AFullName: string): TIdBytes;
  1569. var
  1570. RRData: TIdBytes;
  1571. begin
  1572. RRData := nil; // keep the compiler happy
  1573. if Length(Self.FAnswer) = 0 then begin
  1574. RRData := IPAddrToDNSStr(Address);
  1575. FAnswer := FormatRecord(AFullName, RRData);
  1576. end;
  1577. Result := ToBytes(FAnswer, Length(FAnswer));
  1578. end;
  1579. constructor TIdRR_A.Create;
  1580. begin
  1581. inherited CreateInit('A', TypeCode_A); {do not localize}
  1582. Address := '';
  1583. end;
  1584. function TIdRR_A.GetA: String;
  1585. begin
  1586. Result := GetValue('A'); {do not localize}
  1587. end;
  1588. procedure TIdRR_A.SetA(const Value: String);
  1589. begin
  1590. SetValue('A', Value); {do not localize}
  1591. end;
  1592. function TIdRR_A.TextRecord(AFullName: string): string;
  1593. begin
  1594. Result := FormatQNameFull(AFullName) + Chr(9) + 'IN' + Chr(9) + 'A' + Chr(9) + Address + EOL; {do not localize}
  1595. end;
  1596. { TIdRR_AAAA }
  1597. function TIdRR_AAAA.BinQueryRecord(AFullName: string): TIdBytes;
  1598. var
  1599. RRData: TIdBytes;
  1600. begin
  1601. RRData := nil; // keep the compiler happy
  1602. if Length(FAnswer) = 0 then begin
  1603. RRData := IPv6AAAAToDNSStr(Address);
  1604. FAnswer := FormatRecord(AFullName, RRData);
  1605. end;
  1606. Result := ToBytes(FAnswer, Length(FAnswer));
  1607. end;
  1608. constructor TIdRR_AAAA.Create;
  1609. begin
  1610. inherited CreateInit('AAAA', TypeCode_AAAA); {do not localize}
  1611. Address := '';
  1612. end;
  1613. function TIdRR_AAAA.GetA: String;
  1614. begin
  1615. Result := GetValue('AAAA'); {do not localize}
  1616. end;
  1617. procedure TIdRR_AAAA.SetA(const Value: String);
  1618. begin
  1619. SetValue('AAAA', Value); {do not localize}
  1620. end;
  1621. function TIdRR_AAAA.TextRecord(AFullName: string): string;
  1622. begin
  1623. Result := FormatQNameFull(AFullName) + Chr(9) + 'IN' + Chr(9) + 'AAAA' + Chr(9) + Address + EOL; {do not localize}
  1624. end;
  1625. { TIdRR_TXT }
  1626. function TIdRR_TXT.BinQueryRecord(AFullName: string): TIdBytes;
  1627. var
  1628. RRData: TIdBytes;
  1629. begin
  1630. RRData := nil; // keep the compiler happy
  1631. if Length(FAnswer) = 0 then begin
  1632. //Fix here, make the RRData being DNSStr.
  1633. //Fixed in 2005 Jan 25.
  1634. RRData := NormalStrToDNSStr(TXT);
  1635. FAnswer := FormatRecord(AFullName, RRData);
  1636. end;
  1637. Result := ToBytes(FAnswer, Length(FAnswer));
  1638. end;
  1639. constructor TIdRR_TXT.Create;
  1640. begin
  1641. inherited CreateInit('TXT', TypeCode_TXT); {do not localize}
  1642. TXT := '';
  1643. end;
  1644. function TIdRR_TXT.GetTXT: String;
  1645. begin
  1646. Result := GetValue('TXT'); {do not localize}
  1647. end;
  1648. procedure TIdRR_TXT.SetTXT(const Value: String);
  1649. begin
  1650. SetValue('TXT', Value); {do not localize}
  1651. end;
  1652. function TIdRR_TXT.TextRecord(AFullName: string): string;
  1653. begin
  1654. Result := FormatQNameFull(AFullName) + Chr(9) + 'IN' + Chr(9) + 'TXT' + Chr(9) {do not localize}
  1655. + '"' + TXT + '"' + EOL; {do not localize}
  1656. end;
  1657. { TIdRR_WKS }
  1658. constructor TIdRR_WKS.Create;
  1659. begin
  1660. inherited CreateInit('WKS', TypeCode_WKS); {do not localize}
  1661. end;
  1662. { TIdRR_Error }
  1663. constructor TIdRR_Error.Create;
  1664. begin
  1665. inherited CreateInit('', TypeCode_Error); {do not localize}
  1666. end;
  1667. function ReplaceSpecString(Source, Target, NewString : string; ReplaceAll : boolean = True) : string;
  1668. var
  1669. FixingString, MiddleString, FixedString : string;
  1670. begin
  1671. if Target = NewString then begin
  1672. Result := Source;
  1673. end else begin
  1674. FixingString := Source;
  1675. MiddleString := ''; {do not localize}
  1676. FixedString := ''; {do not localize}
  1677. if Pos(Target, Source) > 0 then begin
  1678. repeat
  1679. MiddleString := Fetch(FixingString, Target);
  1680. FixedString := FixedString + MiddleString + NewString;
  1681. until (Pos(Target, FixingString) = 0) or (not ReplaceAll);
  1682. Result := FixedString + FixingString;
  1683. end else begin
  1684. Result := Source;
  1685. end;
  1686. end;
  1687. end;
  1688. function IsBig5(ch1, ch2:char) : boolean;
  1689. begin
  1690. // RLebeau 1/7/09: using Char() for #128-#255 because in D2009, the compiler
  1691. // may change characters >= #128 from their Ansi codepage value to their true
  1692. // Unicode codepoint value, depending on the codepage used for the source code.
  1693. // For instance, #128 may become #$20AC...
  1694. if (not (((ch1 >= Char(161)) and (ch1 <= Char(254))) or
  1695. ((ch1 >= Char(142)) and (ch1 <= Char(160))) or
  1696. ((ch1 >= Char(129)) and (ch1 <= Char(141)))) ) or
  1697. (not (((ch2 >= #64) and (ch2 <= #126)) or
  1698. ((ch2 >= Char(161)) and (ch2 <= Char(254)))) ) then
  1699. begin
  1700. Result := False;
  1701. end else begin
  1702. Result := True;
  1703. end;
  1704. end;
  1705. end.