zipFC - Dateiformat (ZIP Datei-Container) UPDATE

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Thorsten1867
Beiträge: 1360
Registriert: 04.02.2005 15:40
Computerausstattung: [Windows 10 x64] [PB V5.7x]
Wohnort: Kaufbeuren
Kontaktdaten:

zipFC - Dateiformat (ZIP Datei-Container) UPDATE

Beitrag von Thorsten1867 »

Nachdem mir das OpenDocument-Format für meine Projekte etwas zu komplex ist, habe ich mit dem zipFC-Dateiformat eine einfachere Variante eines Datei-Containers (ZIP) programmiert.
Zusätzlich ist es möglich die Dateien in einem AES-verschlüsselten Format (Header+verschlüsselte Datei) zu speichern.
  • - Die De- und Encodierung verschlüsselter Dateien erfolgt nach dem Entpacken direkt im Speicher (ohne den Umweg über die Festplatte).
    - Es können sowohl Infos zum Datei-Container als auch zu den einzelnen Dateien gespeichert und abgerufen werden. (-> content.xml)
    - Nach dem Öffnen des Datei-Containers stehen diese Infos direkt in einer Struktur zur Verfügung
    - In einer Map("Dateiname.ext") werden die Zeiger auf die einzelnen Nodes zu den Datei-Einträgen in der XML-Datei (content.xml) gespeichert
UPDATE:
  • - In der Map("Dateiname.ext") werden nun neben den XML-Nodes auch noch gespeichert, ob die Datei geöffnet und/oder verschlüsselt (AES) ist
    - Es können nun auch alle noch offenen Dateien geschlossen werden
    - Neben einzelnen Dateien können nun auch alle Dateien im Datei-Container geöffnet werden
    - Beim Schließen des Datei-Containers werden nun automatisch auch alle noch offenen Dateien geschlossen
    - Passwort und Ziel-Pfadkönnen (falls nötig) nun bei Öffnen des Datei-Containers angegeben werden, so dass man sich bei den einzelnen enthaltenen Dateien nicht mehr darum kümmern muss
    - Proceduren für normale und verschlüsselte Dateien wurden jeweils zu einer zusammerngefasst

Code: Alles auswählen

;/ *** zFC - Dateiformat ***
;/ (ZIP - FileContainer)
;/ PureBasic V5.1x
;/ Juni 2013 Thorsten Hoeppner (Thorsten1867)

UseZipPacker()

#AES = 1
#REMOVE = 1

#XmlZipFC = 0      ; #XML Nummer (ggf. anpassen)
#PackZipFC = 0     ; #Pack Nummer (ggf. anpassen)

#AESKey = "myProg1234AES5678Schluessel" ; eigenen Schlüssel festlegen !!!
#DESKey = "D12E34S"                     ; eigenen Schlüssel festlegen !!!

#AESFileExt = "acf"

Structure zipFCMapStructure
  *Node
  Open.b
  AES.b
EndStructure

Structure zipFCStructure
  ; --- Container-Infos ggf. anpassen ---
  Type.s
  Info.s
  Author.s
  ; -------------------------------------
  Path.s
  DESPassword.s
  Map File.zipFCMapStructure()
EndStructure
Global zipFC.zipFCStructure


;- Tools

Procedure.s FileNoExtension(File.s)               ; Pfad und Dateiname ohne Extension
  ProcedureReturn Left(File, Len(File)-Len(GetExtensionPart(File))-1)
EndProcedure

Procedure.s ValidPath(Path.s)                    ; gültige Pfad mit abschließendem "\"
  If Path
    If Right(Path,1) <> "\"
      ProcedureReturn Path+"\"
    Else
      ProcedureReturn Path
    EndIf
  EndIf
EndProcedure

Procedure.s zipFC_File(File.s)                    ; Datei ggf. mit Default-Pfad
  If GetPathPart(File) = ""
    ProcedureReturn zipFC\Path + File
  Else
    ProcedureReturn File
  EndIf
EndProcedure

Procedure zipFC_GetPackFileSize(FileName.s)      ; unkomprimierte Größe der Datei in der ZIP
  If ExaminePack(#PackZipFC)
    While NextPackEntry(#PackZipFC)
      If PackEntryName(#PackZipFC) = FileName
        ProcedureReturn PackEntrySize(#PackZipFC)
      EndIf
    Wend
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure zipFC_ClearFileInfo()                  ; Struktur & Map zurücksetzen
  ; --- Container-Infos ggf. anpassen ---
  zipFC\Type = ""
  zipFC\Info = ""
  zipFC\Author = ""
  ; -------------------------------------
  ClearMap(zipFC\File())
EndProcedure


;- Map / XML abfragen

Procedure.s zipFC_GetFileInfo(File.s, Attribut.s="")  ; Infos über Datei auslesen
  *File = zipFC\File(GetFilePart(File))\node
  If *File
    If Attribut
      ProcedureReturn GetXMLAttribute(*File, Attribut)
    Else
      ProcedureReturn GetXMLNodeText(*File)
    EndIf
  EndIf
EndProcedure


Procedure zipFC_AES(File.s)                           ; Datei verschlüsselt?
  ProcedureReturn zipFC\File(GetFilePart(File))\AES
EndProcedure

Procedure zipFC_Open(File.s)                          ; Datei geöffnet?
  ProcedureReturn zipFC\File(GetFilePart(File))\Open
EndProcedure


;- AES - Verschlüsselung

; Mittels FileID kann überprüft werden, ob es sich um eine gültige Datei für das Programm bzw. die Dateiaktion handelt. 

Procedure.b zipFC_WriteAESPack(File.s, DESPassword.s, FileID.s="myProg", quiet.b=#False)
  Protected FileLength.l, SFId.l, key$= #AESKey, result.b = #False
  Protected *FileMemory, *Memory, *MemoryID
  Protected FileName.s = GetFilePart(File)
  Protected AesFile.s = FileNoExtension(FileName)+"."+#AESFileExt
  ;Protected DESPassword.s = DESFingerprint(Password, #DESKey)
  
  If FileSize(File) <= 0 : ProcedureReturn #False : EndIf
  
  SFId = ReadFile(#PB_Any, File)
  If SFId
    FileLength = Lof(SFId)                                     ; Dateilänge
    *FileMemory = AllocateMemory(FileLength)
    If *FileMemory
      If ReadData(SFId, *FileMemory, FileLength)
        ; Headergröße berechnen
        HeaderLen = StringByteLength(FileID) + StringByteLength(DESPassword) + StringByteLength(FileName) + 11
        ; Speicher für Header & Datei reservieren
        MemSize = HeaderLen + MemorySize(*FileMemory)
        *Memory = AllocateMemory(MemSize)
        If *Memory
          *MemoryID = *Memory
          ;{ Header schreiben
          PokeS(*MemoryID, FileID)                       ; FileID (z.B. "myProg")
          *MemoryID + StringByteLength(FileID) + 1
          PokeL(*MemoryID, FileLength)                   ; Länge der eigentlichen Datei
          *MemoryID + 4
          PokeS(*MemoryID, DESPassword)                  ; DES-Passwort
          *MemoryID + StringByteLength(DESPassword) + 1
          PokeS(*MemoryID, FileName)                     ; Dateiname
          *MemoryID + StringByteLength(FileName) + 1
          ;}
          If AESEncoder(*FileMemory, *MemoryID, MemorySize(*FileMemory), @key$, 128, 0, #PB_Cipher_ECB)
            If AddPackMemory(#PackZipFC, *Memory, MemSize, AesFile)
              result = #True
            EndIf
          EndIf
          FreeMemory(*Memory)
        EndIf
      ElseIf quiet = #False
        MessageRequester(" zipFC - Datei öffnen", "Datei konnte nicht gelesen werden!", #MB_OK|#MB_ICONERROR)
      EndIf
      FreeMemory(*FileMemory)
    EndIf
    CloseFile(SFId)
  EndIf
  ProcedureReturn result
EndProcedure

Procedure.s zipFC_ReadAESPack(AesFile.s, DESPassword.s, TargetPath.s="", FileID.s="myProg", quiet.b=#False)
  Protected FileSize.l, MemFileID.s, MemDESPassword.s, FileName.s, FileLength.l, TFId.l, key$ = #AESKey
  Protected *FileMemory, *Memory, *MemoryID
  ; Protected DESPassword.s = DESFingerprint(Password, #DESKey)
  
  If TargetPath = "" : TargetPath = GetPathPart(AesFile) : EndIf
  
  FileSize = zipFC_GetPackFileSize(GetFilePart(AesFile))
  If FileSize
    *Memory = AllocateMemory(FileSize)
    If *Memory
      *MemoryID = *Memory
      If UncompressPackMemory(#PackZipFC, *Memory, FileSize, GetFilePart(AesFile))
        ; FileID auslesen
        MemFileID = PeekS(*MemoryID)
        *MemoryID + StringByteLength(MemFileID) + 1
        If FileID = MemFileID                         ; FileID (z.B. myProg) überprüfen
          FileLength = PeekL(*MemoryID)               ; Größe der eigentlichen Datei
          *MemoryID + 4
          ; Passwort auslesen
          MemDESPassword = PeekS(*MemoryID)
          *MemoryID + StringByteLength(MemDESPassword) + 1
          If DESPassword = MemDESPassword             ; Passwort überprüfen
            FileName = PeekS(*MemoryID)
            *MemoryID + StringByteLength(FileName) + 1
            ; --- Datei entschlüsseln ---
            *FileMemory = AllocateMemory(FileLength)
            If *FileMemory
              If AESDecoder(*MemoryID, *FileMemory, FileLength, @key$, 128, 0, #PB_Cipher_ECB)
                ; Datei auf HD schreiben
                TFId = CreateFile(#PB_Any, TargetPath+FileName)
                If TFId
                  WriteData(TFId, *FileMemory, FileLength)
                  CloseFile(TFId)
                Else
                  FileName = ""
                  If quiet = #False ;{ Datei konnte nicht erstellt werden
                    MessageRequester(" zipFC - Datei öffnen", "Fehler beim Zugriff auf die zipFC-Datei!"+#LF$+"Überprüfen Sie, ob Sie die nötigen Zugriffsrechte (RW) für folgendes Verzeichnis haben:"+#LF$+GetPathPart(AesFile), #MB_OK|#MB_ICONERROR)
                  EndIf ;}
                EndIf
              Else
                FileName = ""
                If quiet = #False ;{ Entschlüsseln/Entpacken fehlgeschlagen
                  MessageRequester(" zipFC - Datei öffnen", "Datei konnte nicht entschlüsselt werden!", #MB_OK|#MB_ICONERROR)
                EndIf ;}
              EndIf
              FreeMemory(*FileMemory)
            EndIf
          Else  
            FileName = ""
            If quiet = #False ;{ falsches Passwort
              MessageRequester(" zipFC - Datei öffnen", "Das Passwort der Datei ist ungültig! Zugriff auf die Datei wurde verweigert!", #MB_OK|#MB_ICONWARNING)
            EndIf ;}  
          EndIf
        Else ;
          FileName = ""
          If quiet = #False ;{ falsche FileID
            MessageRequester(" zipFC - Datei öffnen", "Ungültige Datei ("+FileID+")!", #MB_OK|#MB_ICONERROR)
          EndIf ;} 
        EndIf
      EndIf
      FreeMemory(*Memory)
    EndIf
  Else
    FileName = ""
    If quiet = #False ;{ Datei nicht im FileContainer
      MessageRequester(" zipFC - Datei öffnen", "Die Datei wurde nicht in der Packetdatei gefunden!", #MB_OK|#MB_ICONERROR)
    EndIf ;}
  EndIf
  ProcedureReturn FileName
EndProcedure


; Eine verschlüsselte Datei dekodieren (außerhalb des FileContainers)
Procedure.s zipFC_DecodeAESFile(AesFile.s, DESPassword.s, TargetPath.s="", FileID.s="myProg", quiet.b=#False)
  Protected AesFileSize.l, MemFileID.s, MemDESPassword.s, FileName.s, FileLength.l, SFId.l, TFId.l, key$ = #AESKey
  Protected *FileMemory, *Memory, *MemoryID
  
  If FileSize(AesFile) <= 0 : ProcedureReturn "" : EndIf
  If TargetPath = "" : TargetPath = GetPathPart(AesFile) : EndIf
  
  SFId = ReadFile(#PB_Any, AesFile)
  If SFId
    AesFileSize = Lof(SFId)
    *Memory = AllocateMemory(AesFileSize)
    If *Memory
      *MemoryID = *Memory
      If ReadData(SFId, *Memory, AesFileSize)
        MemFileID = PeekS(*MemoryID)                  ; FileID auslesen
        *MemoryID + StringByteLength(MemFileID) + 1
        If FileID = MemFileID
          FileLength = PeekL(*MemoryID)               ; Größe der eigentlichen Datei
          *MemoryID + 4
          MemDESPassword = PeekS(*MemoryID)           ; Passwort auslesen
          *MemoryID + StringByteLength(MemDESPassword) + 1
          If DESPassword = MemDESPassword             ; Passwort überprüfen
            FileName = PeekS(*MemoryID)
            *MemoryID + StringByteLength(FileName) + 1
            *FileMemory = AllocateMemory(FileLength)  ; --- Datei entschlüsseln ---
            If *FileMemory
              If AESDecoder(*MemoryID, *FileMemory, FileLength, @key$, 128, 0, #PB_Cipher_ECB)
                TFId = CreateFile(#PB_Any, TargetPath+FileName)
                If TFId
                  WriteData(TFId, *FileMemory, FileLength)
                  CloseFile(TFId)
                Else
                  FileName = "ERROR:CreateFile"
                EndIf
              Else
                FileName = "ERROR:AES"
              EndIf
              FreeMemory(*FileMemory)
            EndIf
          Else  
            FileName = "ERROR:Password" 
          EndIf
        Else ;
          FileName = "ERROR:FileID"
        EndIf
      Else
        FileName = "ERROR"
      EndIf
      FreeMemory(*Memory)
    EndIf
    CloseFile(SFId)
  Else
    FileName = "ERROR:AESFile" 
  EndIf
  
  If quiet = #False
    If Left(FileName, 5) = "ERROR" ;{ Fehlermeldung
      Select Mid(FileName, 7)
        Case "AESFile"
          FileName = ""
          MessageRequester(" zipFC - Datei öffnen", "Datei konnte nicht gelesen werden!", #MB_OK|#MB_ICONERROR)
        Case "FileID"
          FileName = ""
          MessageRequester(" zipFC - Datei öffnen", "Ungültige Datei ("+FileID+")!", #MB_OK|#MB_ICONERROR)
        Case "Password"
          FileName = ""
          MessageRequester(" zipFC - Datei öffnen", "Das Passwort der Datei ist ungültig! Zugriff auf die Datei wurde verweigert!", #MB_OK|#MB_ICONWARNING)
        Case "AES"
          FileName = ""
          MessageRequester(" zipFC - Datei öffnen", "Datei konnte nicht entschlüsselt werden!", #MB_OK|#MB_ICONERROR)
        Case "CreateFile"
          FileName = ""
          MessageRequester(" zipFC - Datei öffnen", "Fehler beim Zugriff auf die zipFC-Datei!"+#LF$+"Überprüfen Sie, ob Sie die nötigen Zugriffsrechte (RW) für folgendes Verzeichnis haben:"+#LF$+GetPathPart(AesFile), #MB_OK|#MB_ICONERROR)
        Default
          FileName = ""
          MessageRequester(" KvGS - Datei öffnen", "Beim Öffnen der Datei ist ein Fehler aufgetreten!", #MB_OK|#MB_ICONERROR)
      EndSelect
    EndIf ;}
  EndIf
  
  ProcedureReturn FileName
EndProcedure
;- "content.xml" verwalten (Infos über FileContainer-Inhalt)

Procedure zipFC_CreateContentXML(Type.s, Info.s, Author.s)             ; Neue XML-Datei erzeugnen
  ; Parameter ggf. an zipFCStructure anpassen (siehe unten)
  If CreateXML(#XmlZipFC)
    *MainNode = CreateXMLNode(RootXMLNode(#XmlZipFC))
    If *MainNode
      SetXMLNodeName(*MainNode, "Content")
      ; --- Container-Infos ggf. anpassen ---
      SetXMLAttribute(*MainNode, "type", Type)
      SetXMLAttribute(*MainNode, "info", Info)
      SetXMLAttribute(*MainNode, "author", Author)
      ; -------------------------------------
      zipFC\Type = Type
      zipFC\Info = Info
      zipFC\Author = Author
      ; -------------------------------------
      ProcedureReturn #True
    EndIf
  EndIf
  ProcedureReturn #False
EndProcedure


Procedure zipFC_OpenContentXML()                                       ; XML-Datei auslesen und in Struktur speichern
  ; Parameter nur nötig, falls 
  Protected *XmlMem, XmlSize.l, FileName.s
  
  zipFC_ClearFileInfo() ; Strukur & Map zurücksetzen/leeren
  
  ;{ Entpacken und XML laden
  XmlSize = zipFC_GetPackFileSize("content.xml")
  If XmlSize
    *XmlMem = AllocateMemory(XmlSize)
    If *XmlMem
      If UncompressPackMemory(#PackZipFC, *XmlMem, XmlSize, "content.xml")
        CatchXML(#XmlZipFC, *XmlMem, XmlSize)
      EndIf
      FreeMemory(*XmlMem)
    EndIf
  Else
    ProcedureReturn #False
  EndIf ;}
  
  ;{ "content.xml" auslesen
  If IsXML(#XmlZipFC)
    If XMLStatus(#XmlZipFC) = #PB_XML_Success
      *MainNode = MainXMLNode(#XmlZipFC)
      If *MainNode
        ; --- Container-Infos ggf. anpassen ---
        zipFC\Type = GetXMLAttribute(*MainNode, "type")
        zipFC\Info = GetXMLAttribute(*MainNode, "info")
        zipFC\Author = GetXMLAttribute(*MainNode, "author")
        ; -------------------------------------
        *Content = ChildXMLNode(*MainNode) ; Dateien im FileContainer
        While *Content
          AddMapElement(zipFC\File(), GetXMLNodeText(*Content))
          zipFC\File()\node = *Content
          zipFC\File()\AES = Val(GetXMLAttribute(*Content, "aes"))
          zipFC\File()\Open = #False
          *Content = NextXMLNode(*Content)
        Wend
        ProcedureReturn #True
      EndIf
    Else
      Debug "XML: "+XMLError(#XmlZipFC)
    EndIf
  Else
    Debug "XML: Keine gültige XML-Datei"
  EndIf ;} 
  
  ProcedureReturn #False
EndProcedure

Procedure zipFC_CloseContentXML()                                      ; XML-Datei (mit ggf. aktualiserten Daten) im FileContainer zurückschreiben 
  Protected *XmlMem, XmlSize.l, result.l = #False
  If IsXML(#XmlZipFC)
    XmlSize = ExportXMLSize(#XmlZipFC)
    *XmlMem = AllocateMemory(XmlSize)
    If *XmlMem
      If ExportXML(#XmlZipFC, *XmlMem, XmlSize)
        RemovePackFile(#PackZipFC, "content.xml")
        result = AddPackMemory(#PackZipFC, *XmlMem, XmlSize, "content.xml")
      EndIf  
      FreeMemory(*XmlMem)
    EndIf
    FreeXML(#XmlZipFC)
  EndIf
EndProcedure


Procedure zipFC_UpdateContentXML(File.s, remove.b=#False, AES.b=#False)              ; XML-Datei & Struktur aktualisieren
  If IsXML(#XmlZipFC)
    If remove ;{ Eintrag zur Datei entfernen
      *File = zipFC\File(GetFilePart(File))\node
      If *File
        If DeleteXMLNode(*File)
          DeleteMapElement(zipFC\File(), GetFilePart(File))
          ProcedureReturn #True
        EndIf 
      EndIf
      ;}
    Else      ;{ Eintrag aktualisieren oder hinzufügen
      *File = zipFC\File(GetFilePart(File))\node
      If *File
        SetXMLAttribute(*File, "modified", Str(GetFileDate(File, #PB_Date_Modified)))
        SetXMLAttribute(*File, "aes", Str(AES))
        zipFC\File(GetFilePart(File))\AES = AES
        ProcedureReturn #True
      Else
        *MainNode = MainXMLNode(#XmlZipFC)
        If *MainNode
          *Node = CreateXMLNode(*MainNode, -1)
          If *Node
            SetXMLNodeName(*Node, "File")
            SetXMLAttribute(*Node, "type", GetExtensionPart(File))
            SetXMLAttribute(*Node, "aes", Str(AES))
            SetXMLAttribute(*Node, "modified", Str(GetFileDate(File, #PB_Date_Modified)))
            SetXMLNodeText(*Node, GetFilePart(File))
            AddMapElement(zipFC\File(), GetFilePart(File))
            zipFC\File()\node = *Node
            zipFC\File()\AES = AES
            zipFC\File()\Open = #False
            ProcedureReturn #True
          EndIf  
        EndIf
      EndIf ;}
    EndIf
  EndIf
  ProcedureReturn #False
EndProcedure


;- ===== Dateien im FileContainer =====

Procedure zipFC_AddFile(File.s, AES.b=#False)    ; Neue Datei zum Container hinzufügen
  File = zipFC_File(File)
  If AES ; Datei verschlüsseln
    If zipFC_WriteAESPack(File, zipFC\DESPassword)
      zipFC_UpdateContentXML(File, #False, #AES)
      zipFC\File(GetFilePart(File))\Open = #True
      ProcedureReturn #True
    EndIf
  Else
    If AddPackFile(#PackZipFC, File, GetFilePart(File))
      zipFC_UpdateContentXML(File)
      zipFC\File(GetFilePart(File))\Open = #True
      ProcedureReturn #True
    EndIf
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure zipFC_RemoveFile(File.s)               ; Datei aus dem Container entfernen
  File = zipFC_File(File)
  If zipFC\File(GetFilePart(File))\AES
    If RemovePackFile(#PackZipFC, GetFilePart(FileNoExtension(File)+"."+#AESFileExt)) 
      zipFC_UpdateContentXML(File, #REMOVE)
      ProcedureReturn #True
    EndIf
  Else
    If RemovePackFile(#PackZipFC, GetFilePart(File)) 
      zipFC_UpdateContentXML(File, #REMOVE)
      ProcedureReturn #True
    EndIf
  EndIf
  ProcedureReturn #False
EndProcedure


Procedure zipFC_CloseFile(File.s)                ; Datei in Container verschieben
  File = zipFC_File(File) ; ggf. Default-Pfad benutzen
  If FileSize(File) > 0   ; nur existierende Dateien schließen
    If zipFC\File(GetFilePart(File))\AES
      RemovePackFile(#PackZipFC, GetFilePart(FileNoExtension(File)+"."+#AESFileExt))
      If zipFC_WriteAESPack(File, zipFC\DESPassword)
        zipFC_UpdateContentXML(File, #False, #AES)
        zipFC\File(GetFilePart(File))\Open = #False
        DeleteFile(File)
        ProcedureReturn #True
      EndIf
    Else  
      RemovePackFile(#PackZipFC, GetFilePart(File))
      If AddPackFile(#PackZipFC, File, GetFilePart(File))
        zipFC_UpdateContentXML(File)
        zipFC\File(GetFilePart(File))\Open = #False
        DeleteFile(File)
        ProcedureReturn #True
      EndIf
    EndIf
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.s zipFC_OpenFile(File.s)               ; Datei aus Container laden
  Protected FileName.s = ""
  File = zipFC_File(File) ; ggf. Default-Pfad benutzen
  If zipFC\File(GetFilePart(File))\AES
    FileName = zipFC_ReadAESPack(FileNoExtension(File)+"."+#AESFileExt, zipFC\DESPassword, GetPathPart(File))
    If FileName
      zipFC\File(GetFilePart(File))\Open = #True
    EndIf
  Else
    If UncompressPackFile(#PackZipFC, File, GetFilePart(File))
      zipFC\File(GetFilePart(File))\Open = #True
      FileName = GetFilePart(File)
    EndIf
  EndIf
  ProcedureReturn FileName
EndProcedure


Procedure zipFC_CloseAllFiles()                  ; alle geöffneten Dateien schließen
  ForEach zipFC\File()
    If zipFC\File()\Open = #True
      zipFC_CloseFile(zipFC\Path+MapKey(zipFC\File()))
    EndIf
  Next
EndProcedure

Procedure zipFC_OpenAllFiles()                   ; alle (nicht geöffneten) Dateien öffnen
  ForEach zipFC\File()
    If zipFC\File()\Open = #False
      zipFC_OpenFile(zipFC\Path+MapKey(zipFC\File()))
    EndIf  
  Next
EndProcedure


;- ===== FileContainer =====

Procedure zipFC_CloseContainer()                                     ; FileContainer schließen
  zipFC_CloseAllFiles()
  zipFC_CloseContentXML() ; content.xml speichern
  zipFC_ClearFileInfo()   ; Struktur & Map zurücksetzen
  zipFC\Path = ""
  zipFC\DESPassword = ""
  ProcedureReturn ClosePack(#PackZipFC)
EndProcedure

Procedure zipFC_OpenContainer(Container.s, Password.s="", Path.s="") ; Datei-Container öffnen
  zipFC_CloseContainer() ; ggf. offenen Container schließen
  If FileSize(Container) > 0
    If OpenPack(#PackZipFC, Container, #PB_Packer_Zip)
      If Path
        zipFC\Path = ValidPath(Path)
      Else
        zipFC\Path = GetPathPart(Container)
      EndIf
      zipFC\Path = GetPathPart(Container)
      zipFC\DESPassword = DESFingerprint(Password, #DESKey)
      ProcedureReturn zipFC_OpenContentXML()
    EndIf
  EndIf
  ProcedureReturn #False
EndProcedure


Procedure zipFC_CreateContainer(Container.s, Type.s, Info.s, Author.s, Password.s="", Path.s="") ; Neuen Datei-Container erstellen
  zipFC_CloseContainer() ; ggf. offenen Container schließen
  If FileSize(Container) < 0
    If CreatePack(#PackZipFC, Container, #PB_Packer_Zip)
      If Path
        zipFC\Path = ValidPath(Path)
      Else
        zipFC\Path = GetPathPart(Container)
      EndIf
      zipFC\DESPassword = DESFingerprint(Password, #DESKey)
      zipFC_CreateContentXML(Type, Info, Author)
      ProcedureReturn #True
    EndIf
  EndIf
  ProcedureReturn #False
EndProcedure


;- ***** Beispiele *****

; Neue zipFC-Datei (FileContainer) erstellen
If zipFC_CreateContainer("E:\Temp\TestContainerDatei.zfc", "myProg", "Dateien für myProg", "Thorsten Hoeppner", "passwort")
  
  ; Datei hinzufügen
  zipFC_AddFile("E:\Temp\Test.txt")
  ; verschlüsselte Datei hinzufügen
  zipFC_AddFile("E:\Temp\Test2.txt", #AES)
  
  ; Infos für alle Dateien mittels Map anzeigen
  ForEach zipFC\File()
    ; nur Dateiname (=MapKey)
    Debug "Datei (Map): " + MapKey(zipFC\File())
    ; weitere Infos aus content.xml auslesen
    *Node = zipFC\File()\node
    If *Node
      Debug "Datei (XML): " + GetXMLNodeText(*Node) + " (Type: " + GetXMLAttribute(*Node, "type") + ")" 
    EndIf
  Next
  
  ; Info für Datei mittels Map direkt anzeigen
  *Node = zipFC\File("Test2.txt")\node
  If *Node
    Debug "Datei (XML): " + GetXMLNodeText(*Node) + " (Type: " + GetXMLAttribute(*Node, "type") + ")" 
  EndIf
  ; --- ODER ---
  Debug "Datei-Typ: "+zipFC_GetFileInfo("Test2.txt", "type") ; einfacher Weg ;-)
  
  zipFC_CloseContainer()
Else
  Debug "zipFC-Datei existiert bereits!"
EndIf

; Vorhandenen zipFC-Datei (FileContainer) öffnen
If zipFC_OpenContainer("E:\Temp\TestContainerDatei.zfc", "passwort")
  ; direkter Zugriff auf Infos über zipFC-Datei
  Debug "----- zipFC-Datei -----"
  Debug "Typ: " + zipFC\Type
  Debug "Info: " + zipFC\Info
  Debug "Autor: " + zipFC\Author
  
  ; Dateien öffnen
  If zipFC_OpenFile("Test.txt")
    Debug "Datei entpackt: "+Str(FileSize("E:\Temp\Test.txt"))
    ;zipFC_CloseFile("Test.txt") ; geänderte Datei zurück in zipFC-Datei verschieben
  EndIf
  
  If zipFC_OpenFile("Test2.txt") ; verschlüssselte Datei (Test2.acf)
    Debug "Datei entpackt & enschlüsselt: "+Str(FileSize("E:\Temp\Test2.txt"))
    ;zipFC_CloseAESFile("Test2.txt") ; geänderte Datei verschlüsseln & zurück in zipFC-Datei verschieben
  EndIf
  
  ; verschlüsselte Datei nur entpacken
  zipFC_OpenFile("Test2.acf") ; verschlüsselte Datei auf (Un)Lesbarkeit prüfen
  
  ; Warten bevor alle Dateien mit dem Container geschlossen werden
  MessageRequester("zipFC-Datei - Test", "zipFC-Container wird geschlossen (incl. aller noch offenen Dateien)", #MB_OK|#MB_ICONINFORMATION)
  
  zipFC_CloseContainer() ; alle noch offenen Dateien werden zurück in zipFC-Datei verschoben & ggf. verschlüsselt
EndIf
Download of PureBasic - Module
Download of PureBasic - Programmes

[Windows 11 x64] [PB V6]

Bild