Ooops
January 26, 2021, 06:01:33 AM

Author Topic: [bmx] Pack file class by JoshK [ 1+ years ago ]  (Read 658 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
[bmx] Pack file class by JoshK [ 1+ years ago ]
« on: June 29, 2017, 12:28:42 AM »
Title : Pack file class
Author : JoshK
Posted : 1+ years ago

Description : By itself, this offers little or no protection.  However it can be combined with any kind of compression and encryption routines by using bank streams, as the advanced example shows.  Customize to your liking.

Code :
Code: BlitzMax
  1. SuperStrict
  2.  
  3. Framework brl.bankstream
  4. Import brl.filesystem
  5. Import brl.standardio
  6. 'Import "bank-utilities.bmx" 'http://blitzmax.com/codearcs/codearcs_bmx/2558.bmx
  7.  
  8. Local pak:TPackFile
  9.  
  10.  
  11. 'Simple example
  12. pak=New TPackFile
  13. pak.AddFile("packfile.bmx","testfile.txt")
  14. pak.Save("data.pak")
  15.  
  16. pak=TPackFile.Load("data.pak")
  17. Print pak.unpack()
  18.  
  19. Rem
  20. 'Advanced example (requires bank-utilities.bmx)
  21. Const ENCRYPTIONKEY:String="BlitzMax is the best programming language in the world!"
  22.  
  23. pak=New TPackFile
  24.  
  25. 'Pack the source code of this program
  26. pak.AddFile("packfile.bmx")
  27.  
  28. Local bank:TBank=New TBank
  29. Local bankstream:TBankStream=CreateBankStream(bank)
  30. pak.save(bankstream)
  31. bankstream.close()
  32. bank=CompressBank(bank)
  33. EncryptBank(bank,ENCRYPTIONKEY)
  34. SaveBank(bank,"data.pak")
  35.  
  36. bank=LoadBank("data.pak")
  37. DecryptBank(bank,ENCRYPTIONKEY)
  38. bank=DecompressBank(bank)
  39. bankstream=CreateBankStream(bank)
  40. pak=TPackFile.Load(bankstream)
  41. Print pak.unpack("unpack        eststuff")
  42. EndRem
  43.  
  44. SuperStrict
  45.  
  46. Import brl.bankstream
  47. Import brl.filesystem
  48.  
  49. Type TPackFile
  50.        
  51.         Field filecount:Int
  52.         Field filename:String[]
  53.         Field filebank:TBank[]
  54.        
  55.         Method AddFile:Int(src:String,dst:String="")
  56.                 Local bank:TBank
  57.  
  58.                 If Not dst dst=src
  59.                 dst=dst.Replace("","/")
  60.                 If Chr(dst[0])+Chr(dst[1])="./"
  61.                         dst=dst[2..]
  62.                 EndIf
  63.                
  64.                 bank=LoadBank(src)
  65.                 If Not bank
  66.                         DebugLog "Failed to load file ~q"+src+"~q."
  67.                         Return False
  68.                 EndIf
  69.                 filecount:+1
  70.                 filename=filename[..filecount]
  71.                 filename[filecount-1]=dst
  72.                 filebank=filebank[..filecount]
  73.                 filebank[filecount-1]=bank
  74.                 Return True
  75.         EndMethod
  76.        
  77.         Method AddDir:Int(path:String="")
  78.                 Local n:Int
  79.                 Local files:String[]
  80.                
  81.                 'Correct path string
  82.                 If path="" path="."
  83.                 path=path.Replace("","/")
  84.                 If path
  85.                         If Chr(path[path.length-1])<>"/" path:+"/"
  86.                 EndIf
  87.                
  88.                 files=LoadDir(path)
  89.                 If Not files
  90.                         DebugLog "Failed to load directory ~q"+path+"~q."
  91.                         Return False
  92.                 EndIf
  93.                
  94.                 For n=0 To files.length-1
  95.                        
  96.                         Select FileType(path+files[n])
  97.                         Case 1
  98.                                 DebugLog "Adding file ~q"+path+files[n]+"~q..."
  99.                                 If Not AddFile(path+files[n])
  100.                                         Return False
  101.                                 EndIf
  102.                         Case 2
  103.                                 DebugLog "Adding directory ~q"+path+files[n]+"~q..."
  104.                                 If Not AddDir(path+files[n]) Return False
  105.                         EndSelect
  106.                 Next
  107.                 Return True
  108.         EndMethod
  109.        
  110.         Function Load:TPackFile(url:Object)
  111.                 Local n:Int
  112.                 Local packfile:TPackFile
  113.                 Local size:Int
  114.                 Local stream:TStream
  115.                
  116.                 stream=ReadStream(url)
  117.                 If Not stream Return Null
  118.                 packfile=New TPackFile
  119.                 packfile.filecount=stream.ReadInt()
  120.                 packfile.filename=packfile.filename[..packfile.filecount]
  121.                 packfile.filebank=packfile.filebank[..packfile.filecount]
  122.                 For n=0 To packfile.filecount-1
  123.                         packfile.filename[n]=stream.ReadLine()
  124.                         size=stream.ReadInt()
  125.                         packfile.filebank[n]=CreateBank(size)
  126.                         stream.readbytes(packfile.filebank[n].buf(),size)
  127.                 Next
  128.                 stream.close()
  129.                 Return packfile
  130.         EndFunction
  131.        
  132.         Method Unpack:Int(path:String="",ShowProgress(progress:Float)=Null)
  133.                 Local n:Int
  134.                 Local stream:TStream
  135.                 Local size:Int
  136.                 Local totalsize:Int
  137.                 Local bytesunpacked:Int
  138.                 Local dir:String
  139.                
  140.                 'Correct path string
  141.                 path=path.Replace("","/")
  142.                 If path
  143.                         If Chr(path[path.length-1])<>"/" path:+"/"
  144.                 EndIf
  145.  
  146.                 'Make sure unpack folder exists
  147.                 If path
  148.                         If FileType(path)<>2
  149.                                 If Not CreateDir(path,1)
  150.                                         DebugLog "Failed to create directory ~q"+path+"~q."
  151.                                         Return False
  152.                                 EndIf
  153.                         EndIf
  154.                 EndIf
  155.                
  156.                 totalsize=GetDataSize()
  157.                 For n=0 To filecount-1
  158.                         dir=ExtractDir(path+filename[n])
  159.                         If FileType(dir)<>2
  160.                                 If Not CreateDir(dir,1)
  161.                                         DebugLog "Failed to create directory ~q"+dir+"~q."
  162.                                         Return False
  163.                                 EndIf
  164.                         EndIf
  165.                         stream=WriteFile(path+filename[n])
  166.                         If Not stream
  167.                                 DebugLog "Failed to write file ~q"+path+filename[n]+"~q."
  168.                                 Return False
  169.                         EndIf
  170.                         size=filebank[n].size()
  171.                         stream.writebytes(filebank[n].buf(),size)
  172.                         stream.close()
  173.                         bytesunpacked:+size
  174.                         If ShowProgress ShowProgress(Float(bytesunpacked)/Float(totalsize))
  175.                 Next
  176.                
  177.                 Return True
  178.         EndMethod
  179.        
  180.         Method GetDataSize:Int()
  181.                 Local size:Int,n:Int
  182.                
  183.                 For n=0 To filecount-1
  184.                         size:+filebank[n].size()
  185.                 Next
  186.                 Return size
  187.         EndMethod
  188.        
  189.         Method Save:Int(url:Object)
  190.                 Local n:Int
  191.                 Local size:Int
  192.                 Local ownstream:Int
  193.                 Local stream:TStream
  194.                
  195.                 stream=TStream(url)
  196.                 If Not stream
  197.                         stream=WriteStream(url)
  198.                         ownstream=1
  199.                 EndIf
  200.                 If Not stream Return 0
  201.                 stream.WriteInt(filecount)
  202.                 For n=0 To filecount-1
  203.                         stream.WriteLine(filename[n])
  204.                         size=filebank[n].size()
  205.                         stream.WriteInt(size)
  206.                         stream.writebytes(filebank[n].buf(),size)
  207.                 Next
  208.                 If ownstream
  209.                         stream.close()
  210.                 EndIf
  211.                 Return 1
  212.         EndMethod
  213.        
  214. EndType


Comments :


Filax(Posted 1+ years ago)

 HiHere is some modifications to include packing and encrypting directly under the class.PS : Thanks josh for this piece of code
Code: [Select]
SuperStrict

Framework brl.bankstream
Import "PackUtil.bmx"

Local pak:TPackFile

'Simple example
pak=New TPackFile

pak.AddDir("Cadres","2111")
'pak.AddFile("pack/IMG_0242.bmp","","2111")
'pak.AddFile("pack/IMG_0265.bmp","","2111")
'pak.AddFile("pack/IMG_0267.bmp","","2111")
pak.Save("data.pak")

Print ""
pak=TPackFile.Load("data.pak")
Print ">"+pak.unpack("unpack",Null,"2111")
Code: [Select]
SuperStrict

Import brl.bank
Import pub.zlib
Import brl.filesystem
Import brl.standardio
Import brl.bankstream
Import brl.filesystem
Import BRL.Retro


Type TPackFile

Field filecount:Int
Field filename:String[]
Field filebank:TBank[]

Method AddFile:Int(src:String,dst:String,key:String)
Local bank:TBank

' Nettoyage des path
If Not dst dst=src
dst=dst.Replace("","/")

If Chr(dst[0])+Chr(dst[1])="./"
dst=dst[2..]
EndIf

' Compression et encryptage
bank=LoadBank(src)

Local originalSize:Int=BankSize(bank)
Local compLevel:Int

' On skipe le fichier
If Not bank
Print "Failed to load file ["+src+"]"
Return False
Else
' selection du taux de compression selon les fichiers
Select Upper(Right$(src,4))
Case ".ZIP"
compLevel=0
Case ".TAR"
compLevel=0
Case ".RAR"
compLevel=0
Default
compLevel=9
End Select

' Compression de la banque
bank=CompressBank(bank,compLevel)
EncryptBank(bank,key)

Local bufferSize:Int=BankSize(bank)
Local percent:Float=0

Print ""
Print "Adding file ["+src+"]"

' Prevent division by zero
If originalSize>0 Then
percent=(bufferSize*100)/originalSize
EndIf

Print "Original: "+originalSize+" bytes / Compressed: "+bufferSize+" bytes ("+Int(percent)+"%)"
EndIf

' Sinon on l'ajoute
filecount:+1
filename=filename[..filecount]
filename[filecount-1]=dst
filebank=filebank[..filecount]
filebank[filecount-1]=bank

Return True
EndMethod

' Ajoute tout les fichiers d'un repertoire
Method AddDir:Int(path:String="",key:String)
Local n:Int
Local files:String[]

'Correct path string
If path="" path="."
path=path.Replace("","/")

If path
If Chr(path[path.length-1])<>"/" path:+"/"
EndIf

files=LoadDir(path)

For n=0 To files.length-1

Select FileType(path+files[n])
Case 1
If Not AddFile(path+files[n],"",Key) Then
Return False
EndIf
Case 2
If Not AddDir(path+files[n],Key) Then
Return False
EndIf
EndSelect
Next

Return True
EndMethod

' Charge un fichier pack
Function Load:TPackFile(url:Object)
Local n:Int
Local packfile:TPackFile
Local size:Int
Local stream:TStream

stream=ReadStream(url)
If Not stream Return Null

packfile=New TPackFile
packfile.filecount=stream.ReadInt()

packfile.filename=packfile.filename[..packfile.filecount]
packfile.filebank=packfile.filebank[..packfile.filecount]

For n=0 To packfile.filecount-1
packfile.filename[n]=stream.ReadLine()
size=stream.ReadInt()
packfile.filebank[n]=CreateBank(size)
stream.readbytes(packfile.filebank[n].buf(),size)
Next

stream.close()
Return packfile

EndFunction

' Decompresse tout un pack dans un rep
Method Unpack:Int(path:String="",ShowProgress(progress:Float)=Null,key:String)
Local n:Int
Local stream:TStream
Local size:Int
Local totalsize:Int
Local bytesunpacked:Int
Local dir:String

'Correct path string
path=path.Replace("","/")
If path
If Chr(path[path.length-1])<>"/" path:+"/"
EndIf

'Make sure unpack folder exists
If path
If FileType(path)<>2
If Not CreateDir(path,1)
Print "Failed to create directory ~q"+path+"~q."
Return False
EndIf
EndIf
EndIf

totalsize=GetDataSize()

For n=0 To filecount-1
dir=ExtractDir(path+filename[n])

If FileType(dir)<>2
If Not CreateDir(dir,1)
Print "Failed to create directory ~q"+dir+"~q."
Return False
Else
Print "Create directory: "+dir
EndIf
EndIf

stream=WriteFile(path+filename[n])

If Not stream
Print "Failed to write file ~q"+path+filename[n]+"~q."
Return False
Else
Print "Create file: "+path+filename[n]
EndIf

' Decompression
DecryptBank(filebank[n],key)
filebank[n]=DecompressBank(filebank[n])
size=filebank[n].size()

' Ecriture du fichier de sortie
stream.writebytes(filebank[n].Buf(),size)

' fermeture du fichier
stream.close()
bytesunpacked:+size

If ShowProgress Then ShowProgress(Float(bytesunpacked)/Float(totalsize))

Next

Return True
EndMethod

' Recuperation de la taille de toutes les banques en ram
Method GetDataSize:Int()
Local size:Int,n:Int

For n=0 To filecount-1
size:+filebank[n].size()
Next

Return size
EndMethod

' Sauvegarde du pack
Method Save:Int(url:Object)
Local n:Int
Local size:Int
Local ownstream:Int
Local stream:TStream

stream=TStream(url)

If Not stream
stream=WriteStream(url)
ownstream=1
EndIf

If Not stream Return 0
stream.WriteInt(filecount)

For n=0 To filecount-1

' Si le nom contient : on clean...
If Instr(filename[n],":")>0 Then
stream.WriteLine(Right$(filename[n],Len(filename[n])-(Instr(filename[n],":")+1)))
Else
stream.WriteLine(filename[n])
EndIf

size=filebank[n].size()
stream.WriteInt(size)
stream.writebytes(filebank[n].buf(),size)
Next

If ownstream
stream.close()
EndIf

Return 1
EndMethod

EndType

' Compress bank functions
Function CompressBank:TBank( bank:TBank, level:Int=9 )
Local size:Int=bank.Size()
Local out_size:Int=size+size/10+32
Local out:TBank=TBank.Create( out_size )
compress2 out.Buf()+4,out_size,bank.Buf(),size,level
out.PokeByte 0,size
out.PokeByte 1,size Shr 8
out.PokeByte 2,size Shr 16
out.PokeByte 3,size Shr 24
out.Resize out_size+4
Return out
End Function

Function DecompressBank:TBank( bank:TBank )
Local out_size:Int
out_size:|bank.PeekByte(0)
out_size:|bank.PeekByte(1) Shl 8
out_size:|bank.PeekByte(2) Shl 16
out_size:|bank.PeekByte(3) Shl 24
Local out:TBank=TBank.Create( out_size )
uncompress out.Buf(),out_size,bank.Buf()+4,bank.Size()-4
Return out
EndFunction

' Encrypting bank
Function EncryptBank(bank:TBank,key:String)
Local c$
Local i:Int

For i = 0 To bank.size()-1
c = Chr$(PeekByte(bank,i))
PokeByte(bank,i,Asc(XorCrypt(c,key)))
Next

Function XorCrypt:String(str$, key$)
Local ml%, pl%, i%, result$,k:Int,c:Byte
ml% = str.length
pl% = key.length
For i = 0 Until ml
c=str$[i]
k=key$[i Mod pl]
c = c ~ k
result$ :+ Chr(c)
Next
Return result$
EndFunction

EndFunction

Function DecryptBank(bank:TBank,key:String)
EncryptBank(bank,key)
EndFunction




Richard Betson(Posted 1+ years ago)

 This all works great! Thanks. :) [/i]

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal