Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Dateiname auf Gültigkeit prüfen (https://www.delphipraxis.net/50658-dateiname-auf-gueltigkeit-pruefen.html)

himitsu 29. Jul 2005 03:32


Dateiname auf Gültigkeit prüfen
 
Zum Beitrag "Dateiname auf Gültigkeit prüfen"

So, und hier ist mal meine Version -.-''

Delphi-Quellcode:
Type TCFNameMode = Set of (
  cnmDOSCompatible, // Tests for file modifier characters ("+", ";", "=" ...).
  cnm8Point3Names,  // Tests for short file names (8.3).
  cnmQuoteEnabled); // File name may be included into quotation marks (").

Function CheckFilename(FileName: AnsiString; Mode: TCFNameMode = []; Directory: AnsiString = ''): ByteBool;
  Var i: Integer;
    Quoted: Boolean;
    Buffer: Array[1..MAX_PATH] of AnsiChar;
    P: PAnsiChar;

  Begin
    Result := False;
    If FileName = '' Then Exit;
    Quoted := (cnmQuoteEnabled in Mode) and (FileName[1] = '"') and (FileName[Length(FileName)] = '"');
    If Quoted Then FileName := Copy(FileName, 2, Length(FileName) - 2);
    If (FileName[1] = ' ') and (FileName[Length(FileName)] = ' ') Then Exit;
    For i := Length(FileName) downto 1 do
      If (FileName[i] in [#0..#31, '"', '*', '/', ':', '<', '>', '?', '\', '|']) or
        ((cnmDOSCompatible in Mode) and (not Quoted) and (FileName[i] in ['+', ';', '=', '[', ']'])) or
        (((cnm8Point3Names in Mode) or ((cnmQuoteEnabled in Mode) and not Quoted)) and (FileName[i] = ' ')) Then Exit;
    If cnm8Point3Names in Mode Then Begin
      i := Pos('.', FileName);
      If i = 0 Then i := Length(FileName) + 1;
      If (i > 9) or (Length(FileName) - i > 3) or (PosEx('.', FileName, i + 1) > 0) Then Exit;
    End;
    If Directory <> '' Then Begin
      If Directory[Length(Directory)] <> '\' Then Directory := Directory + '\';
      FileName := Directory + FileName;
    End;
    i := GetFullPathNameA(PAnsiChar(FileName), MAX_PATH, @Buffer, P);
    If (i <= 0) or (i >= MAX_PATH) Then Exit;
    Result := True;
  End;




If not CheckFilename(FileName) Then Error...

Luckie 29. Jul 2005 04:32

Re: Dateiname auf Gültigkeit prüfen
 
Wo kommt PosEx her? Mein Delphi D6 Personal) kennt es nicht. Grml, nach langem Suchen habe ich wohl was passendes gefunden.

Du hast was vergessen:
Zitat:

The following reserved device names cannot be used as the name of a file: CON, PRN, AUX, CLOCK$, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9. Also avoid these names followed by an extension (for example, NUL.tx7).
Und:
Zitat:

Do not end a file or directory name with a trailing space or a period. Although the underlying file system may support such names, the operating system does not.
Das 'test.txt.' und das 'test.txt ' sind bei dir aber ein gültige Dateiname.

Wenn beo Directory der Pfad angegeben werden kann, dann hast du hier auch noch ein Fehler. Denn das als Pfad '\\<\D:\' word auch als gültig mit disem Dateiname 'test.txt' erkannt, obwohl der Pfad ein ungültiges Zeichen enthält.

himitsu 29. Jul 2005 05:04

Re: Dateiname auf Gültigkeit prüfen
 
Gut, dann werd' ich versuchen es noch etwas zu verbessern.

Allerdings haben die Codes der Anderen mit 'test.txt.' auch ihre Probleme.
Wobei 'test.txt.' als 8.3-Dateiname bei mir nicht durchgehen dürfte ^^


Und das mit dem PosEx vergesse ich manchmal ... da ich es aus 'ner eigenen Codesammlung importiere und weil es in D7 auch nochmal existiert hatte ich es dementsprechend geändert.

eventuell fallen da ja einige unterschiede zum obrigen Code auf ._.
Delphi-Quellcode:
    Function CheckFilename(FileName: AnsiString; Mode: TCFNameMode = []; Directory: AnsiString = ''): ByteBool;
      Var i: Integer;
        Quoted: Boolean;
        Buffer: Array[1..MaxPath] of AnsiChar;
        P: PAnsiChar;

      Begin
        Result := False;
        If FileName = '' Then Exit;
        Quoted := (cnmQuoteEnabled in Mode) and (FileName[1] = '"') and (FileName[_Length(FileName)] = '"');
        If Quoted Then FileName := _Copy(FileName, 2, _Length(FileName) - 2);
        If (FileName[1] = ' ') and (FileName[_Length(FileName)] = ' ') Then Exit;
        For i := _Length(FileName) downto 1 do
          If (FileName[i] in CFForbiddenChars) or
            ((cnmDOSCompatible in Mode) and (not Quoted) and (FileName[i] in CFForbiddenCharsDOS)) or
            (((cnm8Point3Names in Mode) or ((cnmQuoteEnabled in Mode) and not Quoted)) and (FileName[i] = ' ')) Then Exit;
        If cnm8Point3Names in Mode Then Begin
          i := _Pos('.', FileName);
          If i = 0 Then i := _Length(FileName) + 1;
          If (i > 9) or (_Length(FileName) - i > 3) or (_PosEx('.', FileName, i + 1) > 0) Then Exit;
        End;
        If Directory <> '' Then Begin
          If Directory[_Length(Directory)] <> '\' Then _ConcatV(Directory, '\');
          _Swap(FileName, Directory);
          _ConcatV(FileName, Directory);
        End;
        i := GetFullPathNameA(PAnsiChar(FileName), MaxPath, @Buffer, P);
        If (i <= 0) or (i >= MaxPath) Then Exit;
        Result := True;
      End;

Also dann mach ich mich mal wieder an's Werk und mit viel Glück kommt bald (endlich) mal meine UCC raus, wo dieses auch mit drin ist, und dort gibt es dann mit PosEx jedenfalls keine Probleme mehr ;)


[add]
[d]Ach ja, dein zweites Zitat werde ich erstmal ignorieren, da die Leerzeichen bei mir nicht nur am Namensende, sonderen auch am Anfang behandelt werden:[/d]
Delphi-Quellcode:
If (FileName[1] = ' ') and (FileName[_Length(FileName)] = ' ') Then Exit;
Und ja, die Pfadangabe kann fehlerhaft sein, da hier nur der Dateiname geprüft wird.
Aber wenn es gewünscht wird, dann kann ich auch diesen noch mit in die Prüfung aufnehmen.
Obwohl ein "total" falscher Pfadname über GetFullPathName ebenfalls mit behandelt und als Fehler quitiert wird.

[add2]
Ich hoffe es funktioniert und gefällt dir vorerst schonmal so etwas besser.
Wie gesagt, das mit dem Pfad werde ich mir auch noch auf Wunsch vornehmen.


Hab versucht die beiden Zitate mit einfließen zu lassen.
(und wie mir aufgefallen ist, sind Leerzeichen am Anfang unter Umständen auch erlaubt)
Delphi-Quellcode:
    Const CFForbiddenChars: Set of AnsiChar = [#0..#31, '"', '*', '/', ':', '<', '>', '?', '\', '|'];
      CFForbiddenCharsDOS: Set of AnsiChar = ['+', ';', '=', '[', ']'];
      CFForbiddenNames: Array[0..6] of AnsiString = ('AUX', 'CLOCK$', 'COM1', 'COM2', 'COM3', 'COM4',
        'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'CON', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6',
        'LPT7', 'LPT8', 'LPT9', 'NUL', 'PRN');

    Function CheckFilename(FileName: AnsiString; Mode: TCFNameMode = []; Directory: AnsiString = ''): ByteBool;
      Var i: Integer;
        Quoted: Boolean;
        Buffer: Array[1..MAX_PATH] of AnsiChar;
        P: PAnsiChar;

      Begin
        Result := False;
        If FileName = '' Then Exit;
        Quoted := (cnmQuoteEnabled in Mode) and (FileName[1] = '"') and (FileName[Length(FileName)] = '"');
        If Quoted Then FileName := Copy(FileName, 2, Length(FileName) - 2);
        If (FileName = '') or
          ((cnmQuoteEnabled in Mode) and (not Quoted) and (FileName[1] = ' ')) or
          ((cnmErrorLeftChar in Mode) and (FileName[Length(FileName)] in [' ', '.'])) Then Exit;
        For i := Length(FileName) downto 1 do
          If (FileName[i] in CFForbiddenChars) or
            ((cnmDOSCompatible in Mode) and (not Quoted) and (FileName[i] in CFForbiddenCharsDOS)) or
            (((cnm8Point3Names in Mode) or ((cnmQuoteEnabled in Mode) and not Quoted)) and (FileName[i] = ' ')) Then Exit;
        If cnm8Point3Names in Mode Then Begin
          i := Pos('.', FileName);
          If i = 0 Then i := Length(FileName) + 1;
          If (i > 9) or (Length(FileName) - i > 3) or (PosEx('.', FileName, i + 1) > 0) Then Exit;
        End;
        For i := 0 to High(CFForbiddenNames) do If LowerCase(FileName[1]) = CFForbiddenNames[i] Then Exit;
        If Directory <> '' Then Begin
          If Directory[Length(Directory)] <> '\' Then Directory := Directory + '\';
          FileName := Directory + FileName;
        End;
        i := GetFullPathNameA(PAnsiChar(FileName), MAX_PATH, @Buffer, P);
        If (i <= 0) or (i >= MAX_PATH) Then Exit;
        Result := True;
      End;

Ach ja, mir ist so, als wenn sich einige Derivate von PosEx in der CodeLib finden ließen ... jedenfalls ist aber im Forum dazu auch noch eine ganze Menge Code zu finden.
Dennoch kommt ihr schonmal eine Ableitung meiner PosEx-Funktion:
Delphi-Quellcode:
  Function _PosEx(Const SubStr, S: AnsiString; Offset: LongInt = 1): LongInt;
    ASM
      PUSH   ESI
      PUSH   EDI
      PUSH   EBX
      TEST   &SubStr, &SubStr
      JE     @Exit
      TEST   &S, &S
      JE     @Exit0
      TEST   &Offset, &Offset
      JG     @POff
      MOV    &Offset, 1
      @POff:
      MOV    ESI, &SubStr
      MOV    EDI, &S
      PUSH   EDI
      MOV    EAX, &Offset
      DEC    EAX
      MOV    ECX, [EDI - 4]
      MOV    EDX, [ESI - 4]
      DEC    EDX
      JS     @Fail
      SUB    ECX, EAX
      ADD    EDI, EAX
      MOV    AL, [ESI]
      INC    ESI
      SUB    ECX, EDX
      JLE    @Fail

      @Loop:
      REPNE  SCASB
      JNE    @Fail
      MOV    EBX, ECX
      PUSH   ESI
      PUSH   EDI
      MOV    ECX, EDX
      REPE   CMPSB
      POP    EDI
      POP    ESI
      JE     @Found
      MOV    ECX, EBX
      JMP    @Loop

      @Fail:
      POP    EDX

      @Exit0:
      XOR    EAX, EAX
      JMP    @Exit

      @Found:
      POP    EDX
      MOV    EAX, EDI
      SUB    EAX, EDX

      @Exit:
      POP    EBX
      POP    EDI
      POP    ESI
    End;

Luckie 29. Jul 2005 10:02

Re: Dateiname auf Gültigkeit prüfen
 
Warum läßt du den Pfad eigentlich gesondert angeben? Schön wäre, wenn man so was: 'c:\dummy\foo\bar\test.txt' zum Überprüfen oder nur 'test.txt' angeben könnte.

himitsu 29. Jul 2005 10:16

Re: Dateiname auf Gültigkeit prüfen
 
Zitat:

Zitat von Luckie
Warum läßt du den Pfad eigentlich gesondert angeben? Schön wäre, wenn man so was: 'c:\dummy\foo\bar\test.txt' zum Überprüfen oder nur 'test.txt' angeben könnte.

Das ist eigentlich 'ne interne Angelegenheit denn so kann man den Dateinamen einzeln prüfen und z.B. verhindern, das er eine Pfadangabe enthält, also dass im Dateinamen keine ":" und/oder "\" enthalten sind.
Außerdem ist dieses eine Kombination derartiger Funktionen aus meinen Programmen und wirde halt so erstellt, dass sie mit diesesn Programmen zusammenarbeitet.


Im Grunde ist "diese" Funktion "nur" da, um einen Dateinamen zu überprüfen.
Und im Endefekt reagieren die anderen TestFunktionen (hier in der DP und anderswo auch) mit einem False, wenn wie eine Pfadangabe (":" oder "\") im Namen entdecken.


Ich könnte aber auch mal über einen weiteren Parameter (Mode) nachdenken, womit man dieses Verhalten ändern könnte, so dass man auch den Dateinamen sammt Verzeichnis übergeben könnte.
(Directory braucht ja nicht angegeben zu werden)

Luckie 29. Jul 2005 10:23

Re: Dateiname auf Gültigkeit prüfen
 
Nun ja, mit Delphi-Referenz durchsuchenExtractFilename ist es aber kein Problem den Dateinamen vom Pfad zu trennen.

bigg 29. Jul 2005 10:53

Re: Dateiname auf Gültigkeit prüfen
 
Hier wäre meine Variante:

Delphi-Quellcode:
////////////////////////////////////////////////////////////////////////////////
// Dateiname auf Gültigkeit überprüfen
////////////////////////////////////////////////////////////////////////////////

function IsFileName(FileName: String): Boolean;
const ForbiddenChars = ['"', '<', '>', '|', '*', '/', '\', '?']; // verbotene Zeichen

const ForbiddenNames: Array[0..22] of String[6] = ('AUX', 'NUL', 'PRN' ,'CON', 'CLOCK$', // verbotene Namen
'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9',
'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9');

var i: Integer;
var p: PChar;
var FileNameU: String;
begin
Result := False;

  if FileName <> '' then // Name darf nicht leer sein
  begin
    i := Length(FileName);

    if FileName[i] <> '.' then // letze Zeichen darf kein Punkt sein
    begin
      p := Pointer(FileName);

      repeat if p^ in ForbiddenChars then
        Exit;
        inc(p);
      until p^ = #0;

      if (i < 7) and (i > 2) then
      begin
        FileNameU := UpperCase(FileName);
        for i := 0 to High(ForbiddenNames) do
        begin
          if CompareStr(ForbiddenNames[i], FileNameU) = 0 then
          Exit;
        end;
      end;

    Result := True;
  end;
  end;
end;
//edit: verbotene Namen hinzugefügt

himitsu 29. Jul 2005 10:55

Re: Dateiname auf Gültigkeit prüfen
 
Zitat:

Zitat von Luckie
Nun ja, mit Delphi-Referenz durchsuchenExtractFilename ist es aber kein Problem den Dateinamen vom Pfad zu trennen.

Im Grunde genommem hast du ja Recht, wobei es dann ein
Delphi-Quellcode:
CheckFilename(ExtractFilename(FileName), [], ExtractPathname(FileName))
auch machen würde.

Aber wenn ich es schon zulasse, das ein Pfad in Dateiname übergeben werden darf, dann will ich auch wenigsten den übergebenen Pfad genau überprüfen...

Luckie 29. Jul 2005 10:58

Re: Dateiname auf Gültigkeit prüfen
 
@bigg: Was ist mit den verbotenen Namen wie COM1, NUL usw.?

bigg 29. Jul 2005 11:10

Re: Dateiname auf Gültigkeit prüfen
 
@Luckie:
Die fehlen noch :coder:


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:30 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz