PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/indy/IdIPAddress.pas

https://code.google.com/
Pascal | 293 lines | 183 code | 22 blank | 88 comment | 28 complexity | c1f2d91dda71fdacd93ce5fd9509c8e4 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. Rev 1.10 2/8/05 5:29:16 PM RLebeau
  18. Updated GetHToNBytes() to use CopyTIdWord() instead of AppendBytes() for IPv6
  19. addresses.
  20. Rev 1.9 28.09.2004 20:54:32 Andreas Hausladen
  21. Removed unused functions that were moved to IdGlobal
  22. Rev 1.8 6/11/2004 8:48:20 AM DSiders
  23. Added "Do not Localize" comments.
  24. Rev 1.7 5/19/2004 10:44:34 PM DSiders
  25. Corrected spelling for TIdIPAddress.MakeAddressObject method.
  26. Rev 1.6 14/04/2004 17:35:38 HHariri
  27. Removed IP6 for BCB temporarily
  28. Rev 1.5 2/11/2004 5:10:40 AM JPMugaas
  29. Moved IPv6 address definition to System package.
  30. Rev 1.4 2004.02.03 4:17:18 PM czhower
  31. For unit name changes.
  32. Rev 1.3 2/2/2004 12:22:24 PM JPMugaas
  33. Now uses IdGlobal IPVersion Type. Added HToNBytes for things that need
  34. to export into NetworkOrder for structures used in protocols.
  35. Rev 1.2 1/3/2004 2:13:56 PM JPMugaas
  36. Removed some empty function code that wasn't used.
  37. Added some value comparison functions.
  38. Added a function in the IPAddress object for comparing the value with another
  39. IP address. Note that this comparison is useful as an IP address will take
  40. several forms (especially common with IPv6).
  41. Added a property for returning the IP address as a string which works for
  42. both IPv4 and IPv6 addresses.
  43. Rev 1.1 1/3/2004 1:03:14 PM JPMugaas
  44. Removed Lo as it was not needed and is not safe in NET.
  45. Rev 1.0 1/1/2004 4:00:18 PM JPMugaas
  46. An object for handling both IPv4 and IPv6 addresses. This is a proposal with
  47. some old code for conversions.
  48. }
  49. unit IdIPAddress;
  50. interface
  51. {$I IdCompilerDefines.inc}
  52. //we need to put this in Delphi mode to work
  53. uses
  54. Classes,
  55. IdGlobal;
  56. type
  57. TIdIPAddress = class(TObject)
  58. protected
  59. FIPv4 : Cardinal;
  60. FAddrType : TIdIPVersion;
  61. //general conversion stuff
  62. //property as String Get methods
  63. function GetIPv4AsString : String;
  64. function GetIPv6AsString : String;
  65. function GetIPAddress : String;
  66. public
  67. //We can't make this into a property for C++Builder
  68. IPv6 : TIdIPv6Address;
  69. constructor Create; virtual;
  70. class function MakeAddressObject(const AIP : String) : TIdIPAddress; overload;
  71. class function MakeAddressObject(const AIP : String; const AIPVersion: TIdIPVersion) : TIdIPAddress; overload;
  72. function CompareAddress(const AIP : String; var VErr : Boolean) : Integer;
  73. function HToNBytes: TIdBytes;
  74. property IPv4 : Cardinal read FIPv4 write FIPv4;
  75. property IPv4AsString : String read GetIPv4AsString;
  76. property IPv6AsString : String read GetIPv6AsString;
  77. property AddrType : TIdIPVersion read FAddrType write FAddrType;
  78. property IPAsString : String read GetIPAddress;
  79. end;
  80. implementation
  81. uses
  82. IdStack, SysUtils;
  83. //IPv4 address conversion
  84. //Much of this is based on http://www.pc-help.org/obscure.htm
  85. function CompareWord(const AWord1, AWord2 : Word) : Integer;
  86. {$IFDEF USE_INLINE}inline;{$ENDIF}
  87. {
  88. AWord1 > AWord2 > 0
  89. AWord1 < AWord2 < 0
  90. AWord1 = AWord2 = 0
  91. }
  92. begin
  93. if AWord1 > AWord2 then begin
  94. Result := 1;
  95. end else if AWord1 < AWord2 then begin
  96. Result := -1;
  97. end else begin
  98. Result := 0;
  99. end;
  100. end;
  101. function CompareCardinal(const ACard1, ACard2 : Cardinal) : Integer;
  102. {$IFDEF USE_INLINE}inline;{$ENDIF}
  103. {
  104. ACard1 > ACard2 > 0
  105. ACard1 < ACard2 < 0
  106. ACard1 = ACard2 = 0
  107. }
  108. begin
  109. if ACard1 > ACard2 then begin
  110. Result := 1;
  111. end else if ACard1 < ACard2 then begin
  112. Result := -1;
  113. end else begin
  114. Result := 0;
  115. end;
  116. end;
  117. { TIdIPAddress }
  118. function TIdIPAddress.CompareAddress(const AIP: String; var VErr: Boolean): Integer;
  119. var
  120. LIP2 : TIdIPAddress;
  121. i : Integer;
  122. {
  123. Note that the IP address in the object is S1.
  124. S1 > S2 > 0
  125. S1 < S2 < 0
  126. S1 = S2 = 0
  127. }
  128. begin
  129. Result := 0;
  130. //LIP2 may be nil if the IP address is invalid
  131. LIP2 := MakeAddressObject(AIP);
  132. VErr := not Assigned(LIP2);
  133. if not VErr then begin
  134. try
  135. // we can't compare an IPv4 address with an IPv6 address
  136. VErr := FAddrType <> LIP2.FAddrType;
  137. if not VErr then begin
  138. if FAddrType = Id_IPv4 then begin
  139. Result := CompareCardinal(FIPv4, LIP2.FIPv4);
  140. end else begin
  141. for I := 0 to 7 do begin
  142. Result := CompareWord(IPv6[i], LIP2.IPv6[i]);
  143. if Result <> 0 then begin
  144. Break;
  145. end;
  146. end;
  147. end;
  148. end;
  149. finally
  150. FreeAndNil(LIP2);
  151. end;
  152. end;
  153. end;
  154. constructor TIdIPAddress.Create;
  155. begin
  156. inherited Create;
  157. FAddrType := Id_IPv4;
  158. FIPv4 := 0; //'0.0.0.0'
  159. end;
  160. function TIdIPAddress.HToNBytes: TIdBytes;
  161. var
  162. I : Integer;
  163. begin
  164. if FAddrType = Id_IPv4 then begin
  165. Result := ToBytes(GStack.HostToNetwork(FIPv4));
  166. end else begin
  167. SetLength(Result, 16);
  168. for I := 0 to 7 do begin
  169. CopyTIdWord(GStack.HostToNetwork(IPv6[i]), Result, 2*I);
  170. end;
  171. end;
  172. end;
  173. function TIdIPAddress.GetIPAddress: String;
  174. begin
  175. if FAddrType = Id_IPv4 then begin
  176. Result := GetIPv4AsString;
  177. end else begin
  178. Result := GetIPv6AsString;
  179. end;
  180. end;
  181. function TIdIPAddress.GetIPv4AsString: String;
  182. begin
  183. if FAddrType = Id_IPv4 then begin
  184. Result := IntToStr((FIPv4 shr 24) and $FF) + '.';
  185. Result := Result + IntToStr((FIPv4 shr 16) and $FF) + '.';
  186. Result := Result + IntToStr((FIPv4 shr 8) and $FF) + '.';
  187. Result := Result + IntToStr(FIPv4 and $FF);
  188. end else begin
  189. Result := '';
  190. end;
  191. end;
  192. function TIdIPAddress.GetIPv6AsString: String;
  193. var
  194. I: Integer;
  195. begin
  196. if FAddrType = Id_IPv6 then begin
  197. Result := IntToHex(IPv6[0], 4);
  198. for i := 1 to 7 do begin
  199. Result := Result + ':' + IntToHex(IPv6[i], 4);
  200. end;
  201. end else begin
  202. Result := '';
  203. end;
  204. end;
  205. class function TIdIPAddress.MakeAddressObject(const AIP: String): TIdIPAddress;
  206. var
  207. LErr : Boolean;
  208. begin
  209. Result := TIdIPAddress.Create;
  210. try
  211. IPv6ToIdIPv6Address(AIP, Result.IPv6, LErr);
  212. if not LErr then begin
  213. Result.FAddrType := Id_IPv6;
  214. Exit;
  215. end;
  216. Result.FIPv4 := IPv4ToDWord(AIP, LErr);
  217. if not LErr then begin
  218. Result.FAddrType := Id_IPv4;
  219. Exit;
  220. end;
  221. //this is not a valid IP address
  222. FreeAndNil(Result);
  223. except
  224. FreeAndNil(Result);
  225. raise;
  226. end;
  227. end;
  228. class function TIdIPAddress.MakeAddressObject(const AIP: String; const AIPVersion: TIdIPVersion): TIdIPAddress;
  229. var
  230. LErr : Boolean;
  231. begin
  232. Result := TIdIPAddress.Create;
  233. try
  234. case AIPVersion of
  235. Id_IPV4:
  236. begin
  237. Result.FIPv4 := IPv4ToDWord(AIP, LErr);
  238. if not LErr then begin
  239. Result.FAddrType := Id_IPv4;
  240. Exit;
  241. end;
  242. end;
  243. Id_IPv6:
  244. begin
  245. IPv6ToIdIPv6Address(AIP, Result.IPv6, LErr);
  246. if not LErr then begin
  247. Result.FAddrType := Id_IPv6;
  248. Exit;
  249. end
  250. end;
  251. end;
  252. //this is not a valid IP address
  253. FreeAndNil(Result);
  254. except
  255. FreeAndNil(Result);
  256. raise;
  257. end;
  258. end;
  259. end.