iOS Question Modify iArchiver to add functions

Alessandra Pellegri

Active Member
Licensed User
Longtime User
I would like to modify iArchiver to make it similar to B4A version. I tried to open the library but I didn't find basic code.

It appears to be compiled code.

What I could do to modify it ?

Thank you
 

JanPRO

Well-Known Member
Licensed User
Longtime User
Hi,

librarys are written in Objective-C, so you can't modify a library with basic code.
When you want to modify the library in Objective-C you have to ask Erel for the Xcode project...

But why do you want to modify the library?
 
Upvote 0

Alessandra Pellegri

Active Member
Licensed User
Longtime User
I need to modify them to add this functions: see files list before uncompressing them and generate an event for each uncompressed file.

Otherwise during uncompress of big zips the app appears locked. Show some animation effect in the meanwhile is not a solution, uncompressing may require 3/4 minutes and I need percentage.

I need to see list files also to understand if zip stucture is compliant with the files that my app should open.

To compile obj-c would require mac system I guess, is there the possibility to use the cloud hosted-compiler to do that?
 
Last edited:
Upvote 0

Alessandra Pellegri

Active Member
Licensed User
Longtime User
I think that I could do this:
1 - I open the zipped file in a memory stream
2- I look for the first 0x04034b50 occurrence at offset 0
3- I read at offset 18 Compressed size (n)
4- I read at offset 26 Uncompressed size (f)
5- I read at offset 28 Extra field length (e)
6 - I copy n bytes starting from offset 0 to 28+n+f+e to a memory stream (my single file)
7 - I save this stream to disk
8 - I open and decompress it with iArchiver
9 - I generate an event for my progress bar
10 - I go on from the start with my offset starting from the last file

The question is : it will slow down very much respect using iArchiver directly ? Is there a way do uncompress directly from memory stream instead that from disk ?

Is there a container better than simple string type to save the memory stream ?
 
Last edited:
Upvote 0

Alessandra Pellegri

Active Member
Licensed User
Longtime User
I just saw that exists DecompressBytes function in iRandomAccessFile and it uses zlib/inflate algorithm.

So if I strip away header from each file contained in the zip and I pass the byte stream to DecompressBytes I should be able to unzip the file.

Is it right ?
 
Upvote 0

Alessandra Pellegri

Active Member
Licensed User
Longtime User
I wrote my code, now I can retrieve list of files and their length but when I pass the single stream to zlib it crashes. This is my code:
B4X:
'Class module
Sub Class_Globals
   Private NameList As List
   Private OffsetList As List
   Private lengthList As List
   Private zipped As RandomAccessFile
   Private aDir As String
   Private aFileName As String
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize(Dir As String, FileName As String)
   NameList.Initialize
   OffsetList.Initialize
   lengthList.Initialize
   aDir=Dir
   aFileName=FileName
   
   Dim test As Boolean = True
   zipped.Initialize(Dir,FileName,True)
   Dim a As Long = 0
   Dim b As Long = 0
   Dim lengthCompressed As Long = 0
   Dim lengthUnCompressed As Long = 0
   Dim FileNameLength As Int = 0
   Dim ExtraFieldLength As Int = 0   
   
   Do While (test=True And a < zipped.Size)
     Dim buffer(4) As Byte
     a = a + 0
     zipped.ReadBytes(buffer,0,4,a)
     If (buffer(0)=0x50 And buffer(1)=0x4b And buffer(2)=0x03 And buffer(3)=0x04) Then
       a = b+18
       zipped.ReadBytes(buffer,0,4,a)   
       lengthCompressed=buffer(3)*16777216+buffer(2)*65536+buffer(1)*256+buffer(0)
       a = b+22
       zipped.ReadBytes(buffer,0,4,a)
       lengthUnCompressed=buffer(3)*16777216+buffer(2)*65536+buffer(1)*256+buffer(0)
       a = b+26
       zipped.ReadBytes(buffer,0,2,a)
       FileNameLength=buffer(1)*256+buffer(0)
       a = b+28
       zipped.ReadBytes(buffer,0,2,a)
       ExtraFieldLength=buffer(1)*256+buffer(0)   
       Dim buffer(FileNameLength) As Byte
       a = b+30
       zipped.ReadBytes(buffer,0,FileNameLength,a)
       NameList.Add(BytesToString(buffer,0,FileNameLength,"UTF8"))
       Log(NameList.Get(NameList.Size-1))
       a=b+30+FileNameLength+ExtraFieldLength
       Log(NameList.Get(NameList.Size-1)&"  ...  "&a&"  ...  "&lengthCompressed)
       OffsetList.Add(a)
       lengthList.Add(lengthCompressed)
       Dim buffer(4) As Byte
       a=b+30+FileNameLength+ExtraFieldLength+lengthCompressed
       zipped.ReadBytes(buffer,0,4,a)
       If (buffer(0)=0x50 And buffer(1)=0x4b And buffer(2)=0x07 And buffer(3)=0x08) Then b=a+4 Else  b=a
       If (buffer(0)=0x50 And buffer(1)=0x4b And buffer(2)=0x01 And buffer(3)=0x02) Then test=False
     Else
       test=False
     End If
   Loop
End Sub

private Sub extractDirName(a As String) As String
   If a.LastIndexOf("/")=0 Then Return ""
   Return a.SubString2(0,a.LastIndexOf("/"))
End Sub

private Sub extractFileName(a As String) As String
   If a.LastIndexOf("/")=0 Then Return a
   Return a.SubString(a.LastIndexOf("/")+1)
End Sub

Public Sub extractAll(Dir As String, FileName As String)
   Dim a As Long
   Dim b As Long
   Dim c As Int = 0
   Dim cs As CompressedStreams
   'For c = 0 To NameList.Size-1
     a=OffsetList.Get(c)
     b=lengthList.Get(c)
     Dim buffer(b) As Byte
     zipped.ReadBytes(buffer,0,b,a)   
     Dim decompressed() As Byte
     decompressed=cs.DecompressBytes(buffer,"zlib")        <<<<<<<<<<<<<<<------- CRASHES HERE
     Dim kk As String =""
     For n = 0 To decompressed.Length-1
       kk=kk&" "&decompressed(n)
     Next
     Msgbox(kk,"")
   'Next
End Sub

Public Sub extractOne(Dir As String, FileName As String, number As Int)

End Sub

May be that I should adjust the header of each compressed stream before passing it to zlib ?
 
Upvote 0

Alessandra Pellegri

Active Member
Licensed User
Longtime User
I found that I have to put two header bytes to my stream 78 and 9c. In the queue I must put adler-32 checksum.

so I modified my code:
B4X:
Public Sub extractAll(Dir As String, FileName As String)

   Dim aa As ByteConverter
   Dim a As Long
   Dim b As Long
   Dim c As Int = 0
   Dim cs As CompressedStreams
   'For c = 0 To NameList.Size-1
     a=OffsetList.Get(c)
     b=lengthList.Get(c)
     Dim buffer(b+6) As Byte
     buffer(0)=120
     buffer(1)=156
     zipped.ReadBytes(buffer,0+2,b,a)
     Dim n As Int
     Dim ck1 As Int  = 1
     For n = 0 To b+1                        <<<<<<<<-- ADLER-32 algo
       ck1=((ck1+buffer(n)) Mod 65521)
     Next
     Log("-------"&ck1)                  <<<<<<<<--  ck1=52344  --- It is wrong !!! It should be 252*256+153=64665

     buffer(b+2)=138                 <<<<<<<<-- correct checksum
     buffer(b+3)=2                    <<<<<<<<-- correct checksum
     buffer(b+4)=252                 <<<<<<<<-- correct checksum
     buffer(b+5)=153                 <<<<<<<<-- correct checksum
     Dim decompressed() As Byte
     decompressed=cs.DecompressBytes(buffer,"zlib")
end sub
I tried to compress the same stream with CompressedStreams and I found correct checksum bytes.
Putting them manually decompression perfectly works.

I don't understand why checksum calculation is wrong, I took it from here: https://en.wikipedia.org/wiki/Adler-32
 
Upvote 0

Alessandra Pellegri

Active Member
Licensed User
Longtime User
I understood. Cheksum calculation comes from uncompressed data so it is very har to rebuild.

Could you Erel just give me a DecompressBytes library that doesn't chek checksum ? I think it should be sufficient to comment a row in the code.
 
Upvote 0
Top