zeoslib  UNKNOWN
 All Files
ZURL.pas
Go to the documentation of this file.
1 {*********************************************************}
2 { }
3 { Zeos Database Objects }
4 { Test Case for TZURL Class }
5 { }
6 {*********************************************************}
7 
8 {@********************************************************}
9 { Copyright (c) 1999-2012 Zeos Development Group }
10 { }
11 { License Agreement: }
12 { }
13 { This library is distributed in the hope that it will be }
14 { useful, but WITHOUT ANY WARRANTY; without even the }
15 { implied warranty of MERCHANTABILITY or FITNESS FOR }
16 { A PARTICULAR PURPOSE. See the GNU Lesser General }
17 { Public License for more details. }
18 { }
19 { The source code of the ZEOS Libraries and packages are }
20 { distributed under the Library GNU General Public }
21 { License (see the file COPYING / COPYING.ZEOS) }
22 { with the following modification: }
23 { As a special exception, the copyright holders of this }
24 { library give you permission to link this library with }
25 { independent modules to produce an executable, }
26 { regardless of the license terms of these independent }
27 { modules, and to copy and distribute the resulting }
28 { executable under terms of your choice, provided that }
29 { you also meet, for each linked independent module, }
30 { the terms and conditions of the license of that module. }
31 { An independent module is a module which is not derived }
32 { from or based on this library. If you modify this }
33 { library, you may extend this exception to your version }
34 { of the library, but you are not obligated to do so. }
35 { If you do not wish to do so, delete this exception }
36 { statement from your version. }
37 { }
38 { }
39 { The project web site is located on: }
40 { http://zeos.firmos.at (FORUM) }
41 { http://sourceforge.net/p/zeoslib/tickets/ (BUGTRACKER)}
42 { svn://svn.code.sf.net/p/zeoslib/code-0/trunk (SVN) }
43 { }
44 { http://www.sourceforge.net/projects/zeoslib. }
45 { }
46 { }
47 { Zeos Development Group. }
48 {********************************************************@}
49 unit ZURL;
50 
51 interface
52 {$I ZCore.inc}
53 
54 uses
55  Classes, {$IFDEF MSEgui}mclasses,{$ENDIF}
56  SysUtils;
57 
58 type
59  TZURLStringList = Class(TStringList)
60  protected
61  function GetTextStr: string; override;
62  procedure SetTextStr(const Value: string); override;
63  function GetURLText: String;
64  public
65  property URLText: String read GetURLText;
66  end;
67 
68  TZURL = class
69  private
70  FPrefix: string;
71  FProtocol: string;
72  FHostName: string;
73  FPort: Integer;
74  FDatabase: string;
75  FUserName: string;
76  FPassword: string;
77  FLibLocation: String;
78  FProperties: TZURLStringList;
79  FOnPropertiesChange: TNotifyEvent;
80  procedure SetPrefix(const Value: string);
81  procedure SetProtocol(const Value: string);
82  procedure SetHostName(const Value: string);
83  procedure SetConnPort(const Value: Integer);
84  function GetDatabase: string;
85  procedure SetDatabase(const Value: string);
86  function GetUserName: string;
87  procedure SetUserName(const Value: string);
88  function GetPassword: string;
89  procedure SetPassword(const Value: string);
90  function GetLibLocation: String;
91  procedure SetLibLocation(const Value: String);
92  function GetURL: string;
93  procedure SetURL(const Value: string);
94  procedure DoOnPropertiesChange(Sender: TObject);
95  function GetParamAndValue(AString: String; Var Param, Value: String): Boolean;
96  procedure AddValues(Values: TStrings);
97  public
98  constructor Create; overload;
99  constructor Create(const AURL: String); overload;
100  constructor Create(const AURL: String; Info: TStrings); overload;
101  constructor Create(const AURL: TZURL); overload;
102  constructor Create(Const AURL, AHostName: string; const APort: Integer;
103  const ADatabase, AUser, APassword: string; Info: TStrings); overload;
104 
105  destructor Destroy; override;
106  property Prefix: string read FPrefix write SetPrefix;
107  property Protocol: string read FProtocol write SetProtocol;
108  property HostName: string read FHostName write SetHostName;
109  property Port: Integer read FPort write SetConnPort;
110  property Database: string read GetDatabase write SetDatabase;
111  property UserName: string read GetUserName write SetUserName;
112  property Password: string read GetPassword write SetPassword;
113  property LibLocation: string read GetLibLocation write SetLibLocation;
114  property Properties: TZURLStringList read FProperties;
115  property URL: string read GetURL write SetURL;
116 
117  property OnPropertiesChange: TNotifyEvent read FOnPropertiesChange write FOnPropertiesChange;
118  end;
119 
120 implementation
121 
122 uses ZCompatibility, StrUtils;
123 
124 {TZURLStringList}
125 function TZURLStringList.GetTextStr: string;
126 begin
127  Result := inherited GetTextStr;
128  Result := StringReplace(Result, #9, ';', [rfReplaceAll]); //unescape the #9 char to ';'
129 end;
130 
131 procedure TZURLStringList.SetTextStr(const Value: string);
132 begin
133  inherited SetTextStr(StringReplace(Value, ';', #9, [rfReplaceAll])); //escape the ';' char to #9
134 end;
135 
136 function TZURLStringList.GetURLText: String;
137 begin
138  Result := StringReplace(GetTextStr, ';', #9, [rfReplaceAll]); //keep all ';' escaped
139  Result := StringReplace(Result, LineEnding, ';', [rfReplaceAll]); //return a URL-usable string
140  if Result[Length(Result)] = ';' then
141  Result := Copy(Result, 1, Length(Result)-1);
142 end;
143 
144 { TZURL }
145 
146 constructor TZURL.Create;
147 begin
148  inherited;
149 
150  FPrefix := 'zdbc';
151  FProperties := TZURLStringList.Create;
152  FProperties.CaseSensitive := False;
153  FProperties.NameValueSeparator := '=';
154  FProperties.OnChange := DoOnPropertiesChange;
155 end;
156 
157 constructor TZURL.Create(const AURL: String);
158 begin
159  Create;
160  Self.URL := AURL;
161 end;
162 
163 constructor TZURL.Create(const AURL: String; Info: TStrings);
164 begin
165  Create(AURL);
166  if Assigned(Info) then
167  AddValues(Info);
168 end;
169 
170 constructor TZURL.Create(const AURL: TZURL);
171 begin
172  Create(AURL.URL);
173 end;
174 
175 constructor TZURL.Create(Const AURL, AHostName: string; const APort: Integer;
176  const ADatabase, AUser, APassword: string; Info: TStrings);
177 begin
178  Create(AURL);
179  Self.HostName := AHostName;
180  Self.Port := APort;
181  Self.Database := ADataBase;
182  Self.UserName := AUser;
183  Self.Password := APassword;
184  if Assigned(Info) then
185  AddValues(Info);
186 end;
187 
188 destructor TZURL.Destroy;
189 begin
190  FProperties.Free;
191 
192  inherited;
193 end;
194 
195 procedure TZURL.SetPrefix(const Value: string);
196 begin
197  FPrefix := Value;
198 end;
199 
200 procedure TZURL.SetProtocol(const Value: string);
201 begin
202  FProtocol := Value;
203 end;
204 
205 procedure TZURL.SetHostName(const Value: string);
206 begin
207  FHostName := StringReplace(Value, ';', #9, [rfReplaceAll]); //escape the ';' char to #9
208 end;
209 
210 procedure TZURL.SetConnPort(const Value: Integer);
211 begin
212  FPort := Value;
213 end;
214 
215 function TZURL.GetDatabase: string;
216 begin
217  Result := StringReplace(FDatabase, #9, ';', [rfReplaceAll]); //unescape the #9 char to ';'
218 end;
219 
220 procedure TZURL.SetDatabase(const Value: string);
221 begin
222  FDatabase := StringReplace(Value, ';', #9, [rfReplaceAll]); //escape the ';' char to #9
223 end;
224 
225 function TZURL.GetUserName: string;
226 begin
227  Result := StringReplace(FUserName, #9, ';', [rfReplaceAll]); //unescape the #9 char to ';'
228 end;
229 
230 procedure TZURL.SetUserName(const Value: string);
231 begin
232  FUserName := StringReplace(Value, ';', #9, [rfReplaceAll]); //escape the ';' char to #9
233 end;
234 
235 function TZURL.GetPassword: string;
236 begin
237  Result := StringReplace(FPassword, #9, ';', [rfReplaceAll]); //unescape the #9 char to ';'
238 end;
239 
240 procedure TZURL.SetPassword(const Value: string);
241 begin
242  FPassword := StringReplace(Value, ';', #9, [rfReplaceAll]); //escape the ';' char to #9
243 end;
244 
245 function TZURL.GetLibLocation: String;
246 begin
247  Result := StringReplace(FLibLocation, #9, ';', [rfReplaceAll]); //unescape the #9 char to ';'
248 end;
249 
250 procedure TZURL.SetLibLocation(const Value: String);
251 begin
252  FLibLocation := StringReplace(Value, ';', #9, [rfReplaceAll]); //escape the ';' char to #9
253 end;
254 
255 function TZURL.GetURL: string;
256 var
257  hasParamPart : boolean;
258  procedure AddParamPart(const ParamPart: String);
259  begin
260  if hasParamPart then
261  Result := Result + ';'
262  else
263  Result := Result + '?';
264  Result := Result + ParamPart;
265  hasParamPart := True;
266  end;
267 
268 begin
269  Result := '';
270  hasParamPart := false;
271 
272  // Prefix
273  Result := Result + Prefix + ':';
274 
275  // Protocol
276  Result := Result + Protocol + ':';
277 
278  Result := Result + '//'; //Allways set the doubleslash to avoid unix '/' path issues if host is empty
279 
280  // HostName/Port
281  if HostName <> '' then
282  begin
283  Result := Result + HostName;
284  if Port <> 0 then
285  Result := Result + ':' + IntToStr(Port);
286  end;
287 
288  // Database
289  if Database <> '' then
290  Result := Result + '/' + FDatabase;
291 
292  // UserName
293  if FUserName <> '' then
294  AddParamPart('username=' + FUserName);
295 
296  // Password
297  if FPassword <> '' then
298  AddParamPart('password=' + FPassword);
299 
300  // Properties
301  if Properties.Count > 0 then
302  AddParamPart(Properties.GetURLText); //Adds the escaped string
303 
304  // LibLocation
305  if FLibLocation <> '' then
306  AddParamPart('LibLocation='+ FLibLocation);
307 end;
308 
309 procedure TZURL.SetURL(const Value: string);
310 var
311  APrefix: string;
312  AProtocol: string;
313  AHostName: string;
314  APort: string;
315  ADatabase: string;
316  AUserName: string;
317  APassword: string;
318  AProperties: TStrings;
319  AValue: string;
320  I: Integer;
321 begin
322  APrefix := '';
323  AProtocol := '';
324  AHostName := '';
325  APort := '';
326  ADatabase := '';
327  AUserName := '';
328  APassword := '';
329  AProperties := TStringList.Create;
330 
331  try
332  AValue := Value;
333 
334  // APrefix
335  I := Pos(':', AValue);
336  if I = 0 then
337  raise Exception.Create('TZURL.SetURL - The prefix is missing');
338  APrefix := Copy(AValue, 1, I - 1);
339  Delete(AValue, 1, I);
340 
341  // AProtocol
342  I := Pos(':', AValue);
343  if I = 0 then
344  raise Exception.Create('TZURL.SetURL - The protocol is missing');
345  AProtocol := Copy(AValue, 1, I - 1);
346  Delete(AValue, 1, I);
347 
348  // AHostName
349  if Pos('//', AValue) = 1 then
350  begin
351  Delete(AValue, 1, 2);
352  if (Pos(':', AValue) > 0) and ((Pos(':', AValue) < Pos('/', AValue)) or (Pos('/', AValue)=0)) then
353  AHostName := Copy(AValue, 1, Pos(':', AValue) - 1)
354  else if Pos('/', AValue) > 0 then
355  AHostName := Copy(AValue, 1, Pos('/', AValue) - 1)
356  else if Pos('?', AValue) > 0 then
357  AHostName := Copy(AValue, 1, Pos('?', AValue) - 1)
358  else
359  AHostName := AValue;
360 
361  Delete(AValue, 1, Length(AHostName));
362 
363  // APort
364  if Pos(':', AValue) = 1 then
365  begin
366  Delete(AValue, 1, 1);
367  if Pos('/', AValue) > 0 then
368  APort := Copy(AValue, 1, Pos('/', AValue) - 1)
369  else if Pos('?', AValue) > 0 then
370  APort := Copy(AValue, 1, Pos('?', AValue) - 1)
371  else
372  APort := AValue;
373 
374  Delete(AValue, 1, Length(APort));
375  end;
376  end;
377 
378  if Pos('/', AValue) = 1 then
379  Delete(AValue, 1, 1);
380 
381  // ADatabase
382  I := Pos('?', AValue);
383  if I > 0 then
384  begin
385  ADatabase := Copy(AValue, 1, I - 1);
386  Delete(AValue, 1, I);
387  AProperties.Text := StringReplace(AValue, ';', LineEnding, [rfReplaceAll]);
388  end
389  else
390  ADatabase := AValue;
391 
392  FPrefix := APrefix;
393  FProtocol := AProtocol;
394  FHostName := AHostName;
395  FPort := StrToIntDef(APort, 0);
396  FDatabase := ADatabase;
397  FUserName := AUserName;
398  FPassword := APassword;
399  FProperties.Text := AProperties.Text;
400  finally
401  AProperties.Free;
402  end;
403 end;
404 
405 procedure TZURL.DoOnPropertiesChange(Sender: TObject);
406 begin
407  FProperties.OnChange := nil;
408  try
409  if FProperties.Values['UID'] <> '' then
410  begin
411  UserName := FProperties.Values['UID'];
412  FProperties.Delete(FProperties.IndexOfName('UID'));
413  end;
414 
415  if FProperties.Values['PWD'] <> '' then
416  begin
417  Password := FProperties.Values['PWD'];
418  FProperties.Delete(FProperties.IndexOfName('PWD'));
419  end;
420 
421  if FProperties.Values['username'] <> '' then
422  begin
423  UserName := FProperties.Values['username'];
424  FProperties.Delete(FProperties.IndexOfName('username'));
425  end;
426 
427  if FProperties.Values['password'] <> '' then
428  begin
429  Password := FProperties.Values['password'];
430  FProperties.Delete(FProperties.IndexOfName('password'));
431  end;
432 
433  if FProperties.Values['LibLocation'] <> '' then
434  begin
435  LibLocation := FProperties.Values['LibLocation'];
436  FProperties.Delete(FProperties.IndexOfName('LibLocation'));
437  end;
438 
439  finally
440  FProperties.OnChange := DoOnPropertiesChange;
441  end;
442 
443  if Assigned(FOnPropertiesChange) then
444  FOnPropertiesChange(Sender);
445 end;
446 
447 function TZURL.GetParamAndValue(AString: String; Var Param, Value: String): Boolean;
448 var
449  DelimPos: Integer;
450 begin
451  DelimPos := PosEx('=', AString);
452  Result := DelimPos <> 0;
453  Param := '';
454  Value := '';
455  if DelimPos <> 0 then
456  begin
457  Param := Copy(AString, 1, DelimPos -1);
458  Value := Copy(AString, DelimPos+1, Length(AString)-DelimPos);
459  Result := Value <> ''; //avoid loosing empty but added Params. e.g TestIdentifierQuotes
460  end;
461 end;
462 
463 procedure TZURL.AddValues(Values: TStrings);
464 var
465  I: Integer;
466  Param, Value: String;
467 begin
468  for i := 0 to Values.Count -1 do
469  if GetParamAndValue(Values[i], Param, Value) then
470  FProperties.Values[Param] := Value
471  else
472  if FProperties.IndexOf(Values[i]) = -1 then //add unique params only!
473  FProperties.Add(Values[i]);
474 end;
475 
476 end.
477