
Code: Select all
;MicroPack.pbi
;(c) 2008 Trutia Alexandru
;PB4.20 B1
;www.bytessence.com
;
;Small include file for packing/depacking folders, recursive and with password
;The filenames are stored too, like in regular archives
;Very easy to extend
;License: Free for any use, credits appreciated but not necessary
;
;MP_PackFolder(Folder.s,Pack.s,Level) ;Pack a folder, level 0-9 (9 = best)
;MP_UnpackFolder(Pack.s,Folder.s) ;Unpack the files to a folder
;MP_GetPackFileCount(Pack.s) ;Count the files in a pack
;MP_SetPassword(Password.s) ;Set password for compression/decompression
;--------------------------------------------------
Global NewList FullPath.s()
Global NewList RelativePath.s()
Global MP_Internal_Pass.s
;Procedure MP_CRC32(fname.s)
; BufferSize = 1024000 ;1mb
; FileCRCH = ReadFile(#PB_Any,fname)
; If IsFile(FileCRCH)
; SizeToCheck = Lof(FileCRCH)
; *mem = AllocateMemory(BufferSize)
; If *mem
; While SizeToCheck
; chunk = SizeToCheck
; If chunk > BufferSize
; chunk = BufferSize
; EndIf
; ReadData(FileCRCH,*mem,chunk)
; crc = CRC32Fingerprint(*mem,chunk,crc) ; initially crc=0
; SizeToCheck - chunk
; Wend
; If *mem
; FreeMemory(*mem)
; EndIf
; If IsFile(FileCRCH)
; CloseFile(FileCRCH)
; EndIf
; ProcedureReturn crc
; Else
; ProcedureReturn -1
; EndIf
; Else
; ProcedureReturn -2
; EndIf
;EndProcedure
Procedure MP_FileList(EntryPath.s,OldPath.s)
If Right(EntryPath.s,1) <> "\"
EntryPath + "\"
EndIf
UsedDirectory = ExamineDirectory(#PB_Any, EntryPath, "*.*")
While NextDirectoryEntry(UsedDirectory)
EntryType.l = DirectoryEntryType(UsedDirectory)
EntryName.s = DirectoryEntryName(UsedDirectory)
If EntryName = "." Or EntryName = ".."
Continue
EndIf
If EntryType = #PB_DirectoryEntry_File
FName.s = RemoveString(EntryPath + EntryName,OldPath)
AddElement(FullPath())
FullPath() = EntryPath + EntryName
AddElement(RelativePath())
RelativePath() = FName
EndIf
If EntryType = #PB_DirectoryEntry_Directory
MP_FileList(EntryPath + EntryName,OldPath)
EndIf
Wend
FinishDirectory(UsedDirectory)
ProcedureReturn 1
EndProcedure
Procedure MP_RC4(Mem.l, memLen.l, Key.s)
;RC4Mem For PB by Pille, 15.07.2003
;Special Thanks to Rings
;Modded by Inf0Byte
Dim S.w(255)
Dim K.w(255)
;A little hack to strenghten it up a bit
KeySha1.s = SHA1Fingerprint(@Key,Len(Key))
For EnhanceKey = 1 To Len(Key)
NewKey.s + Mid(Key,EnhanceKey,1) + KeySha1
Next
Key = NewKey
For i = 0 To 255
S(i) = i
Next
j = 1
For i = 0 To 255
If j > Len(key)
j = 1
EndIf
K(i) = Asc(Mid(key, j, 1))
j = j + 1
Next i
j = 0
For i = 0 To 255
j = (j + S(i) + K(i)) & 255
temp = S(i)
S(i) = S(j)
S(j) = temp
Next i
i = 0
j = 0
For x = 0 To memLen-1
i = (i + 1) & 255
j = (j + S(i)) & 255
temp = S(i)
S(i) = S(j)
S(j) = temp
t = (S(i) + (S(j) & 255)) & 255
Y = S(t)
PokeB(Mem+x, PeekB(Mem+x)!Y)
Next
Key = ""
ProcedureReturn Mem
EndProcedure
;--------------------------------------------------
Procedure MP_SetPassword(Password.s)
MP_Internal_Pass.s = Password
ProcedureReturn 1
EndProcedure
Procedure MP_PackFolder(Folder.s,Pack.s,Level)
ClearList(FullPath())
ClearList(RelativePath())
If Right(folder.s,1) <> "\"
Folder.s+"\"
EndIf
If MP_FileList(folder.s,folder.s) = 1
ForEach RelativePath()
FileTable.s + RelativePath() + #LF$
Made + 1
Next
If CreatePack(pack.s)
AddPackMemory(@FileTable,Len(Filetable),9)
ForEach FullPath()
If MP_Internal_Pass <> ""
FLR = ReadFile(#PB_Any,FullPath())
If IsFile(FLR)
LenFile = Lof(FLR)
*Temp = AllocateMemory(LenFile)
ReadData(FLR,*Temp,LenFile)
MP_RC4(*Temp,LenFile, MP_Internal_Pass)
CloseFile(FLR)
EndIf
AddPackMemory(*Temp,LenFile,level)
If *Temp
FreeMemory(*Temp)
EndIf
Else
AddPackFile(FullPath(),level)
EndIf
Next
ClosePack()
ProcedureReturn Made
EndIf
EndIf
ProcedureReturn -1
EndProcedure
Procedure MP_UnpackFolder(Pack.s,Folder.s)
ClearList(FullPath())
ClearList(RelativePath())
If Right(Folder.s,1) <> "\"
Folder.s + "\"
EndIf
If FileSize(Folder) <> -2
CreateDirectory(Folder)
EndIf
If OpenPack(Pack)
*FileList = NextPackFile()
Size = PackFileSize()
If *FileList And Size
DataString.s = PeekS(*FileList,Size)
TotalFiles = CountString(DataString,#LF$)
For SplitFiles = 1 To TotalFiles
FName.s = StringField(DataString,SplitFiles,#LF$)
AddElement(FullPath())
FullPath() = Folder + FName
Next
ForEach FullPath()
FolderName.s = GetPathPart(FullPath())
If FileSize(FolderName) <> -2
CreateDirectory(FolderName)
EndIf
*File = NextPackFile()
Size = PackFileSize()
FileOut = CreateFile(#PB_Any,FullPath())
If IsFile(FileOut)
If MP_Internal_Pass <> ""
MP_RC4(*File,Size, MP_Internal_Pass)
EndIf
WriteData(FileOut,*File,Size)
CloseFile(FileOut)
Made + 1
EndIf
Next
EndIf
ClosePack()
EndIf
ProcedureReturn Made
EndProcedure
Procedure MP_GetPackFileCount(Pack.s)
If OpenPack(Pack)
*FileList = NextPackFile()
Size = PackFileSize()
If *FileList And Size
DataString.s = PeekS(*FileList,Size)
TotalFiles = CountString(DataString,#LF$)-1
EndIf
ClosePack()
EndIf
ProcedureReturn TotalFiles
EndProcedure
;--------------------------------------------------
;Example
;MP_SetPassword("TestPass")
MP_PackFolder("C:\Test\","C:\Test.pack",9) ;Pack all contents of "C:\MyFiles\"
;MP_SetPassword("TestPassa") ;1 letter changed and the files will be corrupted as the pass is different ;)
MP_UnpackFolder("C:\Test.pack","C:\Out\") ;And unpack the contents back to "C:\Out\"
[Edit]
Code updated to support password, but it kinda needs a crc32 check there. If I have some time i'll find a fix.