PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/ProSnooperFx_src/indy10.0.52_source/Protocols/IdURI.pas

http://github.com/lookias/ProSnooper
Pascal | 385 lines | 268 code | 23 blank | 94 comment | 36 complexity | 35ac6462ea4932426c7df6f24d1ea2e3 MD5 | raw file
  1. { $HDR$}
  2. {**********************************************************************}
  3. { Unit archived using Team Coherence }
  4. { Team Coherence is Copyright 2002 by Quality Software Components }
  5. { }
  6. { For further information / comments, visit our WEB site at }
  7. { http://www.TeamCoherence.com }
  8. {**********************************************************************}
  9. {}
  10. { $Log: 11809: IdURI.pas
  11. {
  12. { Rev 1.9 10.10.2004 13:46:00 ARybin
  13. { dont add default port to URI
  14. }
  15. {
  16. { Rev 1.8 2004.02.03 5:44:40 PM czhower
  17. { Name changes
  18. }
  19. {
  20. { Rev 1.7 2004.01.22 5:27:24 PM czhower
  21. { Fixed compile errors.
  22. }
  23. {
  24. { Rev 1.6 1/22/2004 4:06:56 PM SPerry
  25. { fixed set problems
  26. }
  27. {
  28. { Rev 1.5 10/5/2003 11:44:24 PM GGrieve
  29. { Use IsLeadChar
  30. }
  31. {
  32. Rev 1.4 6/9/2003 9:35:58 PM BGooijen
  33. %00 is valid now too
  34. }
  35. {
  36. { Rev 1.3 2003.05.09 10:30:16 PM czhower
  37. }
  38. {
  39. { Rev 1.2 2003.04.11 9:41:34 PM czhower
  40. }
  41. {
  42. { Rev 1.1 29/11/2002 9:56:10 AM SGrobety Version: 1.1
  43. { Changed URL encoding
  44. }
  45. {
  46. { Rev 1.0 21/11/2002 12:42:52 PM SGrobety Version: Indy 10
  47. }
  48. {
  49. { Rev 1.0 11/13/2002 08:04:10 AM JPMugaas
  50. }
  51. unit IdURI;
  52. {Details of implementation
  53. -------------------------
  54. 2002-Apr-14 Peter Mee
  55. - Fixed reset. Now resets FParams as well - wasn't before.
  56. 2001-Nov Doychin Bondzhev
  57. - Fixes in URLEncode. There is difference when encoding Path+Doc and Params
  58. 2001-Oct-17 Peter Mee
  59. - Minor speed improvement - removed use of NormalizePath in SetURI.
  60. - Fixed bug that was cutting off the first two chars of the host when a
  61. username / password present.
  62. - Fixed bug that prevented username and password being updated.
  63. - Fixed bug that was leaving the bookmark in the document when no ? or =
  64. parameters existed.
  65. 2001-Feb-18 Doychin Bondzhev
  66. - Added UserName and Password to support URI's like
  67. http://username:password@hostname:port/path/document#bookmark
  68. }
  69. interface
  70. uses
  71. IdException, IdGlobal;
  72. type
  73. TIdURIOptionalFields = (ofAuthInfo, ofBookmark);
  74. TIdURIOptionalFieldsSet = set of TIdURIOptionalFields;
  75. TIdURI = class
  76. protected
  77. FDocument: string;
  78. FProtocol: string;
  79. FURI: String;
  80. FPort: string;
  81. Fpath: string;
  82. FHost: string;
  83. FBookmark: string;
  84. FUserName: string;
  85. FPassword: string;
  86. FParams: string;
  87. FIPVersion: TIdIPVersion;
  88. //
  89. procedure SetURI(const Value: String);
  90. function GetURI: String;
  91. public
  92. constructor Create(const AURI: string = ''); virtual; {Do not Localize}
  93. function GetFullURI(const AOptionalFields: TIdURIOptionalFieldsSet = [ofAuthInfo, ofBookmark]): String;
  94. class procedure NormalizePath(var APath: string);
  95. class function URLDecode(ASrc: string): string;
  96. class function URLEncode(const ASrc: string): string;
  97. class function ParamsEncode(const ASrc: string): string;
  98. class function PathEncode(const ASrc: string): string;
  99. //
  100. property Bookmark : string read FBookmark write FBookMark;
  101. property Document: string read FDocument write FDocument;
  102. property Host: string read FHost write FHost;
  103. property Password: string read FPassword write FPassword;
  104. property Path: string read FPath write FPath;
  105. property Params: string read FParams write FParams;
  106. property Port: string read FPort write FPort;
  107. property Protocol: string read FProtocol write FProtocol;
  108. property URI: string read GetURI write SetURI;
  109. property Username: string read FUserName write FUserName;
  110. property IPVersion : TIdIPVersion read FIPVersion write FIPVersion;
  111. end;
  112. EIdURIException = class(EIdException);
  113. implementation
  114. uses
  115. IdResourceStringsProtocols, IdGlobalProtocols,
  116. SysUtils;
  117. constructor TIdURI.Create(const AURI: string = ''); {Do not Localize}
  118. begin
  119. inherited Create;
  120. if length(AURI) > 0 then begin
  121. URI := AURI;
  122. end;
  123. end;
  124. class procedure TIdURI.NormalizePath(var APath: string);
  125. var
  126. i: Integer;
  127. begin
  128. // Normalize the directory delimiters to follow the UNIX syntax
  129. i := 1;
  130. while i <= Length(APath) do begin
  131. if IsLeadChar(APath[i]) then begin
  132. inc(i, 2)
  133. end else if APath[i] = '\' then begin {Do not Localize}
  134. APath[i] := '/'; {Do not Localize}
  135. inc(i, 1);
  136. end else begin
  137. inc(i, 1);
  138. end;
  139. end;
  140. end;
  141. procedure TIdURI.SetURI(const Value: String);
  142. var
  143. LBuffer: string;
  144. LTokenPos, LPramsPos: Integer;
  145. LURI: string;
  146. begin
  147. FURI := Value;
  148. NormalizePath(FURI);
  149. LURI := FURI;
  150. FHost := ''; {Do not Localize}
  151. FProtocol := ''; {Do not Localize}
  152. FPath := ''; {Do not Localize}
  153. FDocument := ''; {Do not Localize}
  154. FPort := ''; {Do not Localize}
  155. FBookmark := ''; {Do not Localize}
  156. FUsername := ''; {Do not Localize}
  157. FPassword := ''; {Do not Localize}
  158. FParams := ''; {Do not localise} //Peter Mee
  159. FIPVersion := Id_IPv4;
  160. LTokenPos := IndyPos('://', LURI); {Do not Localize}
  161. if LTokenPos > 0 then begin
  162. // absolute URI
  163. // What to do when data don't match configuration ?? {Do not Localize}
  164. // Get the protocol
  165. FProtocol := Copy(LURI, 1, LTokenPos - 1);
  166. Delete(LURI, 1, LTokenPos + 2);
  167. // Get the user name, password, host and the port number
  168. LBuffer := Fetch(LURI, '/', True); {Do not Localize}
  169. // Get username and password
  170. LTokenPos := IndyPos('@', LBuffer); {Do not Localize}
  171. FPassword := Copy(LBuffer, 1, LTokenPos - 1);
  172. if LTokenPos > 0 then
  173. Delete(LBuffer, 1, LTokenPos);
  174. FUserName := Fetch(FPassword, ':', True); {Do not Localize}
  175. // Ignore cases where there is only password (http://:password@host/pat/doc)
  176. if Length(FUserName) = 0 then begin
  177. FPassword := ''; {Do not Localize}
  178. end;
  179. // Get the host and the port number
  180. if (IndyPos('[',LBuffer)>0) and (IndyPos(']',LBuffer) > IndyPos('[',LBuffer)) then
  181. begin
  182. //This is for IPv6 Hosts
  183. FHost := Fetch(LBuffer,']');
  184. Fetch(FHost,'[');
  185. Fetch(LBuffer,':');
  186. FIPVersion := Id_IPv6;
  187. end
  188. else
  189. begin
  190. FHost := Fetch(LBuffer, ':', True); {Do not Localize}
  191. end;
  192. FPort := LBuffer;
  193. // Get the path
  194. LPramsPos := IndyPos('?', LURI); {Do not Localize}
  195. if LPramsPos > 0 then begin // The case when there is parameters after the document name '?' {Do not Localize}
  196. LTokenPos := RPos('/', LURI, LPramsPos); {Do not Localize}
  197. end
  198. else begin
  199. LPramsPos := IndyPos('=', LURI); {Do not Localize}
  200. if LPramsPos > 0 then begin // The case when there is parameters after the document name '=' {Do not Localize}
  201. LTokenPos := RPos('/', LURI, LPramsPos); {Do not Localize}
  202. end
  203. else begin
  204. LTokenPos := RPos('/', LURI, -1); {Do not Localize}
  205. end;
  206. end;
  207. FPath := '/' + Copy(LURI, 1, LTokenPos); {Do not Localize}
  208. // Get the document
  209. if LPramsPos > 0 then begin
  210. FDocument := Copy(LURI, 1, LPramsPos - 1);
  211. Delete(LURI, 1, LPramsPos - 1);
  212. FParams := LURI;
  213. end
  214. else
  215. FDocument := LURI;
  216. Delete(FDocument, 1, LTokenPos);
  217. FBookmark := FDocument;
  218. FDocument := Fetch(FBookmark, '#'); {Do not Localize}
  219. end else begin
  220. // received an absolute path, not an URI
  221. LPramsPos := IndyPos('?', LURI); {Do not Localize}
  222. if LPramsPos > 0 then begin // The case when there is parameters after the document name '?' {Do not Localize}
  223. LTokenPos := RPos('/', LURI, LPramsPos); {Do not Localize}
  224. end else begin
  225. LPramsPos := IndyPos('=', LURI); {Do not Localize}
  226. if LPramsPos > 0 then begin // The case when there is parameters after the document name '=' {Do not Localize}
  227. LTokenPos := RPos('/', LURI, LPramsPos); {Do not Localize}
  228. end else begin
  229. LTokenPos := RPos('/', LURI, -1); {Do not Localize}
  230. end;
  231. end;
  232. FPath := Copy(LURI, 1, LTokenPos);
  233. // Get the document
  234. if LPramsPos > 0 then begin
  235. FDocument := Copy(LURI, 1, LPramsPos - 1);
  236. Delete(LURI, 1, LPramsPos - 1);
  237. FParams := LURI;
  238. end else begin
  239. FDocument := LURI;
  240. end;
  241. Delete(FDocument, 1, LTokenPos);
  242. end;
  243. // Parse the # bookmark from the document
  244. if FBookmark = '' then begin
  245. FBookmark := FParams;
  246. FParams := Fetch(FBookmark, '#'); {Do not Localize}
  247. end;
  248. end;
  249. function TIdURI.GetURI: String;
  250. begin
  251. FURI := GetFullURI;
  252. // Result must contain only the proto://host/path/document
  253. // If you need the full URI then you have to call GetFullURI
  254. result := GetFullURI([]);
  255. end;
  256. class function TIdURI.URLDecode(ASrc: string): string;
  257. var
  258. i: integer;
  259. ESC: string[2];
  260. CharCode: integer;
  261. begin
  262. Result := ''; {Do not Localize}
  263. // S.G. 27/11/2002: Spaces is NOT to be encoded as "+".
  264. // S.G. 27/11/2002: "+" is a field separator in query parameter, space is...
  265. // S.G. 27/11/2002: well, a space
  266. // ASrc := StringReplace(ASrc, '+', ' ', [rfReplaceAll]); {do not localize}
  267. i := 1;
  268. while i <= Length(ASrc) do begin
  269. if ASrc[i] <> '%' then begin {do not localize}
  270. Result := Result + ASrc[i]
  271. end else begin
  272. Inc(i); // skip the % char
  273. ESC := Copy(ASrc, i, 2); // Copy the escape code
  274. Inc(i, 1); // Then skip it.
  275. try
  276. CharCode := StrToInt('$' + ESC); {do not localize}
  277. Result := Result + Char(CharCode);
  278. except end;
  279. end;
  280. Inc(i);
  281. end;
  282. end;
  283. class function TIdURI.ParamsEncode(const ASrc: string): string;
  284. var
  285. i: Integer;
  286. const
  287. UnsafeChars = ['*', '#', '%', '<', '>', ' ','[',']']; {do not localize}
  288. begin
  289. Result := ''; {Do not Localize}
  290. for i := 1 to Length(ASrc) do
  291. begin
  292. // S.G. 27/11/2002: Changed the parameter encoding: Even in parameters, a space
  293. // S.G. 27/11/2002: is much more likely to be meaning "space" than "this is
  294. // S.G. 27/11/2002: a new parameter"
  295. // S.G. 27/11/2002: ref: Message-ID: <3de30169@newsgroups.borland.com> borland.public.delphi.internet.winsock
  296. // S.G. 27/11/2002: Most low-ascii is actually Ok in parameters encoding.
  297. if ((CharIsInSet(ASrc, i, UnsafeChars)) or (not (CharIsInSet(ASrc, i, [#33..#128])))) then
  298. begin {do not localize}
  299. Result := Result + '%' + IntToHex(Ord(ASrc[i]), 2); {do not localize}
  300. end
  301. else
  302. begin
  303. Result := Result + ASrc[i];
  304. end;
  305. end;
  306. end;
  307. class function TIdURI.PathEncode(const ASrc: string): string;
  308. const
  309. UnsafeChars = ['*', '#', '%', '<', '>', '+', ' ','[',']']; {do not localize}
  310. var
  311. i: Integer;
  312. begin
  313. Result := ''; {Do not Localize}
  314. for i := 1 to Length(ASrc) do begin
  315. if (CharIsInSet(ASrc, i, UnsafeChars)) or (ASrc[i] >= #$80) or (ASrc[i] < #32) then begin
  316. Result := Result + '%' + IntToHex(Ord(ASrc[i]), 2); {do not localize}
  317. end else begin
  318. Result := Result + ASrc[i];
  319. end;
  320. end;
  321. end;
  322. class function TIdURI.URLEncode(const ASrc: string): string;
  323. begin
  324. with TIdURI.Create(ASrc) do try
  325. Path := PathEncode(Path);
  326. Document := PathEncode(Document);
  327. Params := ParamsEncode(Params);
  328. Result := URI;
  329. finally Free; end;
  330. end;
  331. function TIdURI.GetFullURI(
  332. const AOptionalFields: TIdURIOptionalFieldsSet): String;
  333. Var
  334. LURI: String;
  335. begin
  336. if FProtocol = '' then begin
  337. raise EIdURIException.Create(RSURINoProto);
  338. end;
  339. LURI := FProtocol + '://'; {Do not Localize}
  340. if (FUserName <> '') and (ofAuthInfo in AOptionalFields) then begin
  341. LURI := LURI + FUserName;
  342. if FPassword <> '' then begin
  343. LURI := LURI + ':' + FPassword; {Do not Localize}
  344. end;
  345. LURI := LURI + '@'; {Do not Localize}
  346. end;
  347. if FHost = '' then begin
  348. raise EIdURIException.Create(RSURINoHost);
  349. end;
  350. LURI := LURI + FHost;
  351. if (FPort <> '') and (FPort <> '80') then begin
  352. LURI := LURI + ':' + FPort; {Do not Localize}
  353. end;
  354. LURI := LURI + FPath + FDocument + FParams;
  355. if (FBookmark <> '') and (ofBookmark in AOptionalFields) then begin
  356. LURI := LURI + '#' + FBookmark; {Do not Localize}
  357. end;
  358. Result := LURI;
  359. end;
  360. end.