2
$Id: uriparser.pp,v 1.4 2003/08/14 14:27:21 michael Exp $
3
This file is part of the Free Pascal run time library.
4
Copyright (c) 2003 by the Free Pascal development team
5
Original author: Sebastian Guenther
7
Unit to parse complete URI in its parts or to reassemble an URI
9
See the file COPYING.FPC, included in this distribution,
10
for details about the copyright.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
**********************************************************************}
37
function EncodeURI(const URI: TURI): String;
38
function ParseURI(const URI: String): TURI;
39
function ParseURI(const URI, DefaultProtocol: String; DefaultPort: Word): TURI;
47
HexTable: array[0..15] of Char = '0123456789abcdef';
50
function EncodeURI(const URI: TURI): String;
52
function Escape(const s: String): String;
57
for i := 1 to Length(s) do
58
if not (s[i] in ['0'..'9', 'A'..'Z', 'a'..'z', ',', '-', '.', '_',
60
Result := Result + '%' + HexTable[Ord(s[i]) shr 4] +
61
HexTable[Ord(s[i]) and $f]
63
Result := Result + s[i];
68
if Length(URI.Protocol) > 0 then
69
Result := LowerCase(URI.Protocol) + ':';
70
if Length(URI.Host) > 0 then
72
Result := Result + '//';
73
if Length(URI.Username) > 0 then
75
Result := Result + URI.Username;
76
if Length(URI.Password) > 0 then
77
Result := Result + ':' + URI.Password;
78
Result := Result + '@';
80
Result := Result + URI.Host;
83
Result := Result + ':' + IntToStr(URI.Port);
84
Result := Result + Escape(URI.Path);
85
if Length(URI.Document) > 0 then
87
if (Length(Result) = 0) or (Result[Length(Result)] <> '/') then
88
Result := Result + '/';
89
Result := Result + Escape(URI.Document);
91
if Length(URI.Params) > 0 then
92
Result := Result + '?' + URI.Params;
93
if Length(URI.Bookmark) > 0 then
94
Result := Result + '#' + Escape(URI.Bookmark);
97
function ParseURI(const URI: String): TURI;
99
Result := ParseURI(URI, '', 0);
102
function ParseURI(const URI, DefaultProtocol: String; DefaultPort: Word): TURI;
104
function Unescape(const s: String): String;
106
function HexValue(c: Char): Integer;
108
if (c >= '0') and (c <= '9') then
109
Result := Ord(c) - Ord('0')
110
else if (c >= 'A') and (c <= 'F') then
111
Result := Ord(c) - Ord('A') + 10
112
else if (c >= 'a') and (c <= 'f') then
113
Result := Ord(c) - Ord('a') + 10
119
i, RealLength: Integer;
121
SetLength(Result, Length(s));
124
while i <= Length(s) do
129
Result[RealLength] := Chr(HexValue(s[i + 1]) shl 4 or HexValue(s[i + 2]));
133
Result[RealLength] := s[i];
137
SetLength(Result, RealLength);
142
i, LastValidPos: Integer;
144
Result.Protocol := LowerCase(DefaultProtocol);
145
Result.Port := DefaultPort;
149
// Extract the protocol
151
for i := 1 to Length(s) do
154
Result.Protocol := Copy(s, 1, i - 1);
155
s := Copy(s, i + 1, Length(s));
157
end else if not (s[i] in ['0'..'9', 'A'..'Z', 'a'..'z']) then
160
// Extract the bookmark name
162
for i := Length(s) downto 1 do
165
Result.Bookmark := Unescape(Copy(s, i + 1, Length(s)));
166
s := Copy(s, 1, i - 1);
168
end else if s[i] = '/' then
171
// Extract the params
173
for i := Length(s) downto 1 do
176
Result.Params := Copy(s, i + 1, Length(s));
177
s := Copy(s, 1, i - 1);
179
end else if s[i] = '/' then
182
// Extract the document name
184
for i := Length(s) downto 1 do
187
Result.Document := Unescape(Copy(s, i + 1, Length(s)));
188
s := Copy(s, 1, i - 1);
190
end else if s[i] = ':' then
196
for i := Length(s) downto 1 do
198
and ((I>1) and (S[i-1]<>'/'))
199
and ((I<Length(S)) and (S[I+1]<>'/')) then
201
else if s[i] in [':', '@'] then
204
if (LastValidPos > 0) and
205
(Length(S)>LastValidPos) and
206
(S[LastValidPos+1]<>'/') then
208
Result.Path := Unescape(Copy(s, LastValidPos, Length(s)));
209
s := Copy(s, 1, LastValidPos - 1);
212
// Extract the port number
214
for i := Length(s) downto 1 do
217
Result.Port := StrToInt(Copy(s, i + 1, Length(s)));
218
s := Copy(s, 1, i - 1);
220
end else if s[i] in ['@', '/'] then
223
// Extract the hostname
225
if ((Length(s) > 2) and (s[1] = '/') and (s[2] = '/')) or
226
((Length(s) > 1) and (s[1] <> '/')) then
230
for i := Length(s) downto 1 do
231
if s[i] in ['@', '/'] then
233
Result.Host := Copy(s, i + 1, Length(s));
234
s := Copy(s, 3, i - 3);
238
// Extract username and password
239
if Length(s) > 0 then
246
Result.Username := Copy(s, 1, i - 1);
247
Result.Password := Copy(s, i + 1, Length(s));