Skip to content

Commit

Permalink
Fix: directory change to non-normalized paths - issue #130
Browse files Browse the repository at this point in the history
  • Loading branch information
TheNicker committed Jul 29, 2023
1 parent efe7b77 commit 0ce3464
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 4 deletions.
40 changes: 38 additions & 2 deletions components/doublecmd/dcstrutils.pas
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@
interface

uses
Classes, SysUtils, DCBasicTypes, LazUtf8;
Classes
{$IFDEF MSWINDOWS}
,Windows
{$ENDIF}
,SysUtils, DCBasicTypes,LazUtf8;


const
NoQuotesSpecialChars = [' ', '"', '''', '(', ')', ':', '&', '!', '$', '*', '?', '=', '`', '\', '|', ';', #10];
Expand Down Expand Up @@ -658,12 +663,42 @@ function RemoveInvalidCharsFromFileName(const FileName: String): String;
Result:=Result+FileName[I];
end;

{
Currently use 'GetFullPathName' for windows for a more robust path normalization.
TODO: find a cross platform solution for normalizing paths properly!
STL of the GCC at the function path::lexically_normal does the following to normalized paths:
Normalization steps:
- If the path is empty, stop.
- Replace each slash character in the root-name with a preferred-separator.
- Replace each directory-separator with a preferred-separator.
- Remove each dot filename and any immediately following directory-separator.
- As long as any appear, remove a non-dot-dot filename immediately followed
by a directory-separator and a dot-dot filename, along with any immediately
following directory-separator.
- If there is a root-directory, remove all dot-dot filenames and any
directory-separators immediately following them.
- If the last filename is dot-dot, remove any trailing directory-separator.
- If the path is empty, add a dot.
}

function ExpandAbsolutePath(const Path: String): String;
var
{$IFDEF MSWINDOWS}
data : array [0..MAX_PATH] of char;
{$ELSE}
I, J: Integer;
{$ENDIF}

begin
{$IFDEF MSWINDOWS}
if (GetFullPathNameA(PChar(Path),MAX_PATH,data,PLPSTR(nil)) > 0) then
Result:= data
else
Result:= Path;
{$ELSE}
Result := Path;

{First remove all references to '\.\'}
I := Pos (DirectorySeparator + '.' + DirectorySeparator, Result);
while I <> 0 do
Expand All @@ -687,6 +722,7 @@ function ExpandAbsolutePath(const Path: String): String;
Delete (Result, J, I - J + 3);
I := Pos (DirectorySeparator + '..', Result);
end;
{$ENDIF}
end;

function HasPathInvalidCharacters(Path: String): Boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/fileviews/ufileviewheader.pas
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ procedure TFileViewHeader.onKeyRETURN(Sender: TObject);
NewPath: String;
AClass: TFileSourceClass;
begin
NewPath:= NormalizePathDelimiters(FPathEdit.Text);
NewPath:= ExpandAbsolutePath(FPathEdit.Text);
NewPath:= ReplaceEnvVars(ReplaceTilde(NewPath));
AClass:= gVfsModuleList.GetFileSource(NewPath);

Expand Down
2 changes: 1 addition & 1 deletion src/fmain.pas
Original file line number Diff line number Diff line change
Expand Up @@ -5903,7 +5903,7 @@ function TfrmMain.ExecuteCommandFromEdit(sCmd: String; bRunInTerm: Boolean): Boo
else
begin
sDir:= RemoveQuotation(Copy(sCmd, iIndex + 3, Length(sCmd)));
sDir:= NormalizePathDelimiters(Trim(sDir));
sDir:= ExpandAbsolutePath(Trim(sDir));

if (sDir = DirectorySeparator) or (sDir = '..') then
begin
Expand Down

0 comments on commit 0ce3464

Please sign in to comment.