| 1 |
/////////////////////////////////////////////////////////// |
|---|
| 2 |
// CodeFromLCL // |
|---|
| 3 |
// Ìîäóëü ñ êóñî÷êàìè êîäà, âûäðàííûìè èç LCL // |
|---|
| 4 |
// Copyright (C) 1999-2000 Free Pascal development team // |
|---|
| 5 |
// Ðàñïðîñòðàíÿåòñÿ íà óñëîâèÿõ // |
|---|
| 6 |
// LGPL v2.1 // |
|---|
| 7 |
// // |
|---|
| 8 |
// www.gipatgroup.org // |
|---|
| 9 |
/////////////////////////////////////////////////////////// |
|---|
| 10 |
|
|---|
| 11 |
//Ê ðàáîòå íàä äàííûì ôàéëîì ïðèëîæèëè ðóêè, íîãè.... êîðî÷å àôôòàðû: |
|---|
| 12 |
// 1) Free Pascal development team |
|---|
| 13 |
// 2) Sagrer (sagrer@yandex.ru) |
|---|
| 14 |
|
|---|
| 15 |
//Included code from LCL's FileUtil, SysUtils modules. |
|---|
| 16 |
|
|---|
| 17 |
//////////////////////////////////////////////////////////////////////// |
|---|
| 18 |
|
|---|
| 19 |
unit CodeFromLCL; |
|---|
| 20 |
|
|---|
| 21 |
{$IFDEF FPC} |
|---|
| 22 |
{$mode objfpc} |
|---|
| 23 |
{$ENDIF FPC} |
|---|
| 24 |
|
|---|
| 25 |
{$H+} |
|---|
| 26 |
|
|---|
| 27 |
interface |
|---|
| 28 |
|
|---|
| 29 |
uses Windows, SysUtils, StrUtils; |
|---|
| 30 |
|
|---|
| 31 |
const |
|---|
| 32 |
AllDirectoryEntriesMask = '*'; |
|---|
| 33 |
|
|---|
| 34 |
Type |
|---|
| 35 |
TGetAppNameEvent = Function : String; |
|---|
| 36 |
TGetTempDirEvent = Function (Global : Boolean) : String; |
|---|
| 37 |
TGetTempFileEvent = Function (Const Dir,Prefix : String) : String; |
|---|
| 38 |
|
|---|
| 39 |
Var |
|---|
| 40 |
OnGetApplicationName : TGetAppNameEvent; |
|---|
| 41 |
OnGetTempDir : TGetTempDirEvent; |
|---|
| 42 |
OnGetTempFile : TGetTempFileEvent; |
|---|
| 43 |
|
|---|
| 44 |
//Ôóíêöèè SysUtils èç LCL |
|---|
| 45 |
Function GetTempDir(Global : Boolean) : String; overload; |
|---|
| 46 |
Function GetTempDir : String; overload; |
|---|
| 47 |
Function GetEnvironmentVariable(Const EnvVar : String) : String; |
|---|
| 48 |
//Ôóíêöèè FileUtil èç LCL |
|---|
| 49 |
function ChompPathDelim(const Path: string): string; |
|---|
| 50 |
function AppendPathDelim(const Path: string): string; |
|---|
| 51 |
function GetAllFilesMask: string; |
|---|
| 52 |
function TrimFilename(const AFilename: string): string; |
|---|
| 53 |
function CleanAndExpandFilename(const Filename: string): string; |
|---|
| 54 |
function CleanAndExpandDirectory(const Filename: string): string; |
|---|
| 55 |
function DeleteDirectory(const DirectoryName: string; OnlyChilds: boolean): boolean; |
|---|
| 56 |
|
|---|
| 57 |
implementation |
|---|
| 58 |
|
|---|
| 59 |
///////////////////////////////////////////////// |
|---|
| 60 |
// Ôóíêöèè SysUtils èç LCL // |
|---|
| 61 |
///////////////////////////////////////////////// |
|---|
| 62 |
|
|---|
| 63 |
Function GetEnvironmentVariable(Const EnvVar : String) : String; |
|---|
| 64 |
|
|---|
| 65 |
var |
|---|
| 66 |
s : string; |
|---|
| 67 |
i : longint; |
|---|
| 68 |
hp,p : pchar; |
|---|
| 69 |
begin |
|---|
| 70 |
Result:=''; |
|---|
| 71 |
p:=GetEnvironmentStrings; |
|---|
| 72 |
hp:=p; |
|---|
| 73 |
while hp^<>#0 do |
|---|
| 74 |
begin |
|---|
| 75 |
s:=strpas(hp); |
|---|
| 76 |
i:=pos('=',s); |
|---|
| 77 |
if uppercase(copy(s,1,i-1))=uppercase(envvar) then |
|---|
| 78 |
begin |
|---|
| 79 |
Result:=copy(s,i+1,length(s)-i); |
|---|
| 80 |
break; |
|---|
| 81 |
end; |
|---|
| 82 |
{ next string entry} |
|---|
| 83 |
hp:=hp+strlen(hp)+1; |
|---|
| 84 |
end; |
|---|
| 85 |
FreeEnvironmentStrings(p); |
|---|
| 86 |
end; |
|---|
| 87 |
|
|---|
| 88 |
{$ifndef HAS_TEMPDIR} |
|---|
| 89 |
Function GetTempDir(Global : Boolean) : String; overload; |
|---|
| 90 |
|
|---|
| 91 |
begin |
|---|
| 92 |
If Assigned(OnGetTempDir) then |
|---|
| 93 |
Result:=OnGetTempDir(Global) |
|---|
| 94 |
else |
|---|
| 95 |
begin |
|---|
| 96 |
Result:=GetEnvironmentVariable('TEMP'); |
|---|
| 97 |
If (Result='') Then |
|---|
| 98 |
Result:=GetEnvironmentVariable('TMP'); |
|---|
| 99 |
end; |
|---|
| 100 |
if (Result<>'') then |
|---|
| 101 |
Result:=IncludeTrailingPathDelimiter(Result); |
|---|
| 102 |
end; |
|---|
| 103 |
{$endif} |
|---|
| 104 |
|
|---|
| 105 |
Function GetTempDir : String; overload; |
|---|
| 106 |
|
|---|
| 107 |
begin |
|---|
| 108 |
Result:=GetTempDir(True); |
|---|
| 109 |
end; |
|---|
| 110 |
|
|---|
| 111 |
///////////////////////////////////////////////// |
|---|
| 112 |
// Ôóíêöèè FileUtil èç LCL // |
|---|
| 113 |
///////////////////////////////////////////////// |
|---|
| 114 |
|
|---|
| 115 |
{------------------------------------------------------------------------------ |
|---|
| 116 |
function ChompPathDelim(const Path: string): string; |
|---|
| 117 |
------------------------------------------------------------------------------} |
|---|
| 118 |
function ChompPathDelim(const Path: string): string; |
|---|
| 119 |
begin |
|---|
| 120 |
if (Path<>'') and (Path[length(Path)]=PathDelim) then |
|---|
| 121 |
Result:=LeftStr(Path,length(Path)-1) |
|---|
| 122 |
else |
|---|
| 123 |
Result:=Path; |
|---|
| 124 |
end; |
|---|
| 125 |
|
|---|
| 126 |
{------------------------------------------------------------------------------ |
|---|
| 127 |
function AppendPathDelim(const Path: string): string; |
|---|
| 128 |
------------------------------------------------------------------------------} |
|---|
| 129 |
function AppendPathDelim(const Path: string): string; |
|---|
| 130 |
begin |
|---|
| 131 |
if (Path<>'') and (Path[length(Path)]<>PathDelim) then |
|---|
| 132 |
Result:=Path+PathDelim |
|---|
| 133 |
else |
|---|
| 134 |
Result:=Path; |
|---|
| 135 |
end; |
|---|
| 136 |
|
|---|
| 137 |
{------------------------------------------------------------------------------ |
|---|
| 138 |
function TrimFilename(const AFilename: string): string; |
|---|
| 139 |
------------------------------------------------------------------------------} |
|---|
| 140 |
function TrimFilename(const AFilename: string): string; |
|---|
| 141 |
// trim double path delims, heading and trailing spaces |
|---|
| 142 |
// and special dirs . and .. |
|---|
| 143 |
|
|---|
| 144 |
function FilenameIsTrimmed(const TheFilename: string): boolean; |
|---|
| 145 |
var |
|---|
| 146 |
l: Integer; |
|---|
| 147 |
i: Integer; |
|---|
| 148 |
begin |
|---|
| 149 |
Result:=false; |
|---|
| 150 |
if TheFilename='' then begin |
|---|
| 151 |
Result:=true; |
|---|
| 152 |
exit; |
|---|
| 153 |
end; |
|---|
| 154 |
// check heading spaces |
|---|
| 155 |
if TheFilename[1]=' ' then exit; |
|---|
| 156 |
// check trailing spaces |
|---|
| 157 |
l:=length(TheFilename); |
|---|
| 158 |
if TheFilename[l]=' ' then exit; |
|---|
| 159 |
i:=1; |
|---|
| 160 |
while i<=l do begin |
|---|
| 161 |
case TheFilename[i] of |
|---|
| 162 |
|
|---|
| 163 |
PathDelim: |
|---|
| 164 |
// check for double path delimiter |
|---|
| 165 |
if (i<l) and (TheFilename[i+1]=PathDelim) then exit; |
|---|
| 166 |
|
|---|
| 167 |
'.': |
|---|
| 168 |
if (i=1) or (TheFilename[i-1]=PathDelim) then begin |
|---|
| 169 |
// check for . directories |
|---|
| 170 |
if ((i<l) and (TheFilename[i+1]=PathDelim)) or ((i=l) and (i>1)) then exit; |
|---|
| 171 |
// check for .. directories |
|---|
| 172 |
if (i<l) and (TheFilename[i+1]='.') |
|---|
| 173 |
and ((i+1=l) or ((i+2<=l) and (TheFilename[i+2]=PathDelim))) then exit; |
|---|
| 174 |
end; |
|---|
| 175 |
|
|---|
| 176 |
end; |
|---|
| 177 |
inc(i); |
|---|
| 178 |
end; |
|---|
| 179 |
Result:=true; |
|---|
| 180 |
end; |
|---|
| 181 |
|
|---|
| 182 |
var SrcPos, DestPos, l, DirStart: integer; |
|---|
| 183 |
c: char; |
|---|
| 184 |
MacroPos: LongInt; |
|---|
| 185 |
begin |
|---|
| 186 |
Result:=AFilename; |
|---|
| 187 |
if FilenameIsTrimmed(Result) then exit; |
|---|
| 188 |
|
|---|
| 189 |
l:=length(AFilename); |
|---|
| 190 |
SrcPos:=1; |
|---|
| 191 |
DestPos:=1; |
|---|
| 192 |
|
|---|
| 193 |
// skip trailing spaces |
|---|
| 194 |
while (l>=1) and (AFilename[l]=' ') do dec(l); |
|---|
| 195 |
|
|---|
| 196 |
// skip heading spaces |
|---|
| 197 |
while (SrcPos<=l) and (AFilename[SrcPos]=' ') do inc(SrcPos); |
|---|
| 198 |
|
|---|
| 199 |
// trim double path delims and special dirs . and .. |
|---|
| 200 |
while (SrcPos<=l) do begin |
|---|
| 201 |
c:=AFilename[SrcPos]; |
|---|
| 202 |
// check for double path delims |
|---|
| 203 |
if (c=PathDelim) then begin |
|---|
| 204 |
inc(SrcPos); |
|---|
| 205 |
{$IFDEF WINDOWS} |
|---|
| 206 |
if (DestPos>2) |
|---|
| 207 |
{$ELSE} |
|---|
| 208 |
if (DestPos>1) |
|---|
| 209 |
{$ENDIF} |
|---|
| 210 |
and (Result[DestPos-1]=PathDelim) then begin |
|---|
| 211 |
// skip second PathDelim |
|---|
| 212 |
continue; |
|---|
| 213 |
end; |
|---|
| 214 |
Result[DestPos]:=c; |
|---|
| 215 |
inc(DestPos); |
|---|
| 216 |
continue; |
|---|
| 217 |
end; |
|---|
| 218 |
// check for special dirs . and .. |
|---|
| 219 |
if (c='.') then begin |
|---|
| 220 |
if (SrcPos<l) then begin |
|---|
| 221 |
if (AFilename[SrcPos+1]=PathDelim) |
|---|
| 222 |
and ((DestPos=1) or (AFilename[SrcPos-1]=PathDelim)) then begin |
|---|
| 223 |
// special dir ./ |
|---|
| 224 |
// -> skip |
|---|
| 225 |
inc(SrcPos,2); |
|---|
| 226 |
continue; |
|---|
| 227 |
end else if (AFilename[SrcPos+1]='.') |
|---|
| 228 |
and (SrcPos+1=l) or (AFilename[SrcPos+2]=PathDelim) then |
|---|
| 229 |
begin |
|---|
| 230 |
// special dir .. |
|---|
| 231 |
// 1. .. -> keep |
|---|
| 232 |
// 2. /.. -> skip .., keep / |
|---|
| 233 |
// 3. C:.. -> keep |
|---|
| 234 |
// 4. C:\.. -> skip .., keep C:\ |
|---|
| 235 |
// 5. \\.. -> skip .., keep \\ |
|---|
| 236 |
// 6. xxx../.. -> keep |
|---|
| 237 |
// 7. xxxdir$Macro/.. -> keep |
|---|
| 238 |
// 8. xxxdir/.. -> trim dir and skip .. |
|---|
| 239 |
if DestPos=1 then begin |
|---|
| 240 |
// 1. .. -> keep |
|---|
| 241 |
end else if (DestPos=2) and (Result[1]=PathDelim) then begin |
|---|
| 242 |
// 2. /.. -> skip .., keep / |
|---|
| 243 |
inc(SrcPos,2); |
|---|
| 244 |
continue; |
|---|
| 245 |
{$IFDEF WINDOWS} |
|---|
| 246 |
end else if (DestPos=3) and (Result[2]=':') |
|---|
| 247 |
and (Result[1] in ['a'..'z','A'..'Z']) then begin |
|---|
| 248 |
// 3. C:.. -> keep |
|---|
| 249 |
end else if (DestPos=4) and (Result[2]=':') and (Result[3]=PathDelim) |
|---|
| 250 |
and (Result[1] in ['a'..'z','A'..'Z']) then begin |
|---|
| 251 |
// 4. C:\.. -> skip .., keep C:\ |
|---|
| 252 |
inc(SrcPos,2); |
|---|
| 253 |
continue; |
|---|
| 254 |
end else if (DestPos=3) and (Result[1]=PathDelim) |
|---|
| 255 |
and (Result[2]=PathDelim) then begin |
|---|
| 256 |
// 5. \\.. -> skip .., keep \\ |
|---|
| 257 |
inc(SrcPos,2); |
|---|
| 258 |
continue; |
|---|
| 259 |
{$ENDIF} |
|---|
| 260 |
end else if (DestPos>1) and (Result[DestPos-1]=PathDelim) then begin |
|---|
| 261 |
if (DestPos>3) |
|---|
| 262 |
and (Result[DestPos-2]='.') and (Result[DestPos-3]='.') |
|---|
| 263 |
and ((DestPos=4) or (Result[DestPos-4]=PathDelim)) then begin |
|---|
| 264 |
// 6. ../.. -> keep |
|---|
| 265 |
end else begin |
|---|
| 266 |
// 7. xxxdir/.. -> trim dir and skip .. |
|---|
| 267 |
DirStart:=DestPos-2; |
|---|
| 268 |
while (DirStart>1) and (Result[DirStart-1]<>PathDelim) do |
|---|
| 269 |
dec(DirStart); |
|---|
| 270 |
MacroPos:=DirStart; |
|---|
| 271 |
while MacroPos<DestPos do begin |
|---|
| 272 |
if (Result[MacroPos]='$') |
|---|
| 273 |
and (Result[MacroPos+1] in ['(','a'..'z','A'..'Z']) then begin |
|---|
| 274 |
// 8. directory contains a macro -> keep |
|---|
| 275 |
break; |
|---|
| 276 |
end; |
|---|
| 277 |
inc(MacroPos); |
|---|
| 278 |
end; |
|---|
| 279 |
if MacroPos=DestPos then begin |
|---|
| 280 |
DestPos:=DirStart; |
|---|
| 281 |
inc(SrcPos,2); |
|---|
| 282 |
continue; |
|---|
| 283 |
end; |
|---|
| 284 |
end; |
|---|
| 285 |
end; |
|---|
| 286 |
end; |
|---|
| 287 |
end else begin |
|---|
| 288 |
// special dir . at end of filename |
|---|
| 289 |
if DestPos=1 then begin |
|---|
| 290 |
Result:='.'; |
|---|
| 291 |
exit; |
|---|
| 292 |
end else begin |
|---|
| 293 |
// skip |
|---|
| 294 |
break; |
|---|
| 295 |
end; |
|---|
| 296 |
end; |
|---|
| 297 |
end; |
|---|
| 298 |
// copy directory |
|---|
| 299 |
repeat |
|---|
| 300 |
Result[DestPos]:=c; |
|---|
| 301 |
inc(DestPos); |
|---|
| 302 |
inc(SrcPos); |
|---|
| 303 |
if (SrcPos>l) then break; |
|---|
| 304 |
c:=AFilename[SrcPos]; |
|---|
| 305 |
if c=PathDelim then break; |
|---|
| 306 |
until false; |
|---|
| 307 |
end; |
|---|
| 308 |
// trim result |
|---|
| 309 |
if DestPos<=length(AFilename) then |
|---|
| 310 |
SetLength(Result,DestPos-1); |
|---|
| 311 |
end; |
|---|
| 312 |
|
|---|
| 313 |
{------------------------------------------------------------------------------ |
|---|
| 314 |
function CleanAndExpandFilename(const Filename: string): string; |
|---|
| 315 |
------------------------------------------------------------------------------} |
|---|
| 316 |
function CleanAndExpandFilename(const Filename: string): string; |
|---|
| 317 |
begin |
|---|
| 318 |
Result:=ExpandFilename(TrimFileName(Filename)); |
|---|
| 319 |
end; |
|---|
| 320 |
|
|---|
| 321 |
{------------------------------------------------------------------------------ |
|---|
| 322 |
function CleanAndExpandDirectory(const Filename: string): string; |
|---|
| 323 |
------------------------------------------------------------------------------} |
|---|
| 324 |
function CleanAndExpandDirectory(const Filename: string): string; |
|---|
| 325 |
begin |
|---|
| 326 |
Result:=AppendPathDelim(CleanAndExpandFilename(Filename)); |
|---|
| 327 |
end; |
|---|
| 328 |
|
|---|
| 329 |
function GetAllFilesMask: string; |
|---|
| 330 |
begin |
|---|
| 331 |
{$IFDEF WINDOWS} |
|---|
| 332 |
Result:='*.*'; |
|---|
| 333 |
{$ELSE} |
|---|
| 334 |
Result:='*'; |
|---|
| 335 |
{$ENDIF} |
|---|
| 336 |
end; |
|---|
| 337 |
|
|---|
| 338 |
{------------------------------------------------------------------------------ |
|---|
| 339 |
function DeleteDirectory(const DirectoryName: string; |
|---|
| 340 |
OnlyChilds: boolean): boolean; |
|---|
| 341 |
------------------------------------------------------------------------------} |
|---|
| 342 |
function DeleteDirectory(const DirectoryName: string; |
|---|
| 343 |
OnlyChilds: boolean): boolean; |
|---|
| 344 |
var |
|---|
| 345 |
FileInfo: TSearchRec; |
|---|
| 346 |
CurSrcDir: String; |
|---|
| 347 |
CurFilename: String; |
|---|
| 348 |
begin |
|---|
| 349 |
Result:=false; |
|---|
| 350 |
CurSrcDir:=CleanAndExpandDirectory(DirectoryName); |
|---|
| 351 |
if SysUtils.FindFirst(CurSrcDir+GetAllFilesMask,faAnyFile,FileInfo)=0 then begin |
|---|
| 352 |
repeat |
|---|
| 353 |
// check if special file |
|---|
| 354 |
if (FileInfo.Name='.') or (FileInfo.Name='..') or (FileInfo.Name='') then |
|---|
| 355 |
continue; |
|---|
| 356 |
CurFilename:=CurSrcDir+FileInfo.Name; |
|---|
| 357 |
if (FileInfo.Attr and faDirectory)>0 then begin |
|---|
| 358 |
if not DeleteDirectory(CurFilename,false) then exit; |
|---|
| 359 |
end else begin |
|---|
| 360 |
if not DeleteFile(CurFilename) then exit; |
|---|
| 361 |
end; |
|---|
| 362 |
until SysUtils.FindNext(FileInfo)<>0; |
|---|
| 363 |
end; |
|---|
| 364 |
SysUtils.FindClose(FileInfo); |
|---|
| 365 |
if (not OnlyChilds) and (not RemoveDir(DirectoryName)) then exit; |
|---|
| 366 |
Result:=true; |
|---|
| 367 |
end; |
|---|
| 368 |
|
|---|
| 369 |
end. |
|---|