Advertisement
ItsPingu

Untitled

Jul 4th, 2025
345
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ' Append data to uncompressed test.txt inside a ZIP (no external libs)
  2.  
  3. Type ZipFileEntry
  4.     filename As String
  5.     method As UShort
  6.     crc As UInteger
  7.     compSize As UInteger
  8.     uncompSize As UInteger
  9.     localHeaderOffset As UInteger
  10.     data As String
  11. End Type
  12.  
  13. Function ReadUInt32(f As Integer) As UInteger
  14.     Dim As UInteger val
  15.     Dim As UByte b(3)
  16.     For i As Integer = 0 To 3
  17.         Get #f, , b(i)
  18.     Next
  19.     val = b(0) Or (b(1) << 8) Or (b(2) << 16) Or (b(3) << 24)
  20.     Return val
  21. End Function
  22.  
  23. Function ReadUInt16(f As Integer) As UShort
  24.     Dim As UShort val
  25.     Dim As UByte b(1)
  26.     For i As Integer = 0 To 1
  27.         Get #f, , b(i)
  28.     Next
  29.     val = b(0) Or (b(1) << 8)
  30.     Return val
  31. End Function
  32.  
  33. Function ReadString(f As Integer, length As Integer) As String
  34.     Dim As String s
  35.     Dim As UByte b
  36.     For i As Integer = 1 To length
  37.         Get #f, , b
  38.         s += Chr(b)
  39.     Next
  40.     Return s
  41. End Function
  42.  
  43. ' Find EOCD (End of central directory) from the end of file
  44. Function FindEOCD(f As Integer) As UInteger
  45.     Dim As Integer filesize = Lof(f)
  46.     Dim As Integer maxSearch = Min(filesize, 65536)
  47.     Dim As Integer pos = filesize - maxSearch
  48.  
  49.     Dim As UByte b1, b2, b3, b4
  50.     For offset As Integer = maxSearch To 0 Step -1
  51.         Seek #f, pos + offset
  52.         Get #f, , b1
  53.         Get #f, , b2
  54.         Get #f, , b3
  55.         Get #f, , b4
  56.         If b1 = &H50 And b2 = &H4B And b3 = &H05 And b4 = &H06 Then
  57.             Return pos + offset
  58.         End If
  59.     Next
  60.     Return 0
  61. End Function
  62.  
  63. Sub AppendToUncompressedFileInZip(ByVal zipPath As String, ByVal targetFile As String, ByVal appendData As String, ByVal outputZip As String)
  64.     Dim As Integer f = FreeFile()
  65.     Open zipPath For Binary Access Read As #f
  66.  
  67.     Dim As UInteger eocdPos = FindEOCD(f)
  68.     If eocdPos = 0 Then
  69.         Print "EOCD not found. Not a valid ZIP?"
  70.         Close #f
  71.         Exit Sub
  72.     End If
  73.  
  74.     ' Read EOCD (22 bytes min)
  75.     Seek #f, eocdPos + 4
  76.     Dim totalEntries As UShort = ReadUInt16(f)
  77.     Dim centralDirSize As UInteger = ReadUInt32(f)
  78.     Dim centralDirOffset As UInteger = ReadUInt32(f)
  79.  
  80.     ' Read central directory entries
  81.     Seek #f, centralDirOffset
  82.     Dim entries() As ZipFileEntry
  83.     Redim entries(totalEntries - 1)
  84.  
  85.     For i As Integer = 0 To totalEntries - 1
  86.         Dim As UInteger sig = ReadUInt32(f)
  87.         If sig <> &H2014B50 Then ' Central dir file header signature 0x02014b50
  88.             Print "Invalid central directory signature"
  89.             Close #f
  90.             Exit Sub
  91.         End If
  92.  
  93.         ' Skip version made by(2), version needed(2), flags(2)
  94.         Seek #f, Seek(#f) + 6
  95.  
  96.         Dim method As UShort = ReadUInt16(f)
  97.         ' Skip mod time/date
  98.         Seek #f, Seek(#f) + 4
  99.  
  100.         Dim crc As UInteger = ReadUInt32(f)
  101.         Dim compSize As UInteger = ReadUInt32(f)
  102.         Dim uncompSize As UInteger = ReadUInt32(f)
  103.  
  104.         Dim fnameLen As UShort = ReadUInt16(f)
  105.         Dim extraLen As UShort = ReadUInt16(f)
  106.         Dim commentLen As UShort = ReadUInt16(f)
  107.  
  108.         ' Skip disk start(2), internal attr(2), external attr(4)
  109.         Seek #f, Seek(#f) + 10
  110.  
  111.         Dim localHdrOffset As UInteger = ReadUInt32(f)
  112.  
  113.         Dim fname As String = ReadString(f, fnameLen)
  114.  
  115.         ' Skip extra and comment
  116.         Seek #f, Seek(#f) + extraLen + commentLen
  117.  
  118.         entries(i).filename = fname
  119.         entries(i).method = method
  120.         entries(i).crc = crc
  121.         entries(i).compSize = compSize
  122.         entries(i).uncompSize = uncompSize
  123.         entries(i).localHeaderOffset = localHdrOffset
  124.     Next
  125.  
  126.     ' Find target file index
  127.     Dim targetIdx As Integer = -1
  128.     For i As Integer = 0 To totalEntries - 1
  129.         If entries(i).filename = targetFile Then
  130.             targetIdx = i
  131.             Exit For
  132.         End If
  133.     Next
  134.  
  135.     If targetIdx = -1 Then
  136.         Print "File not found in archive: "; targetFile
  137.         Close #f
  138.         Exit Sub
  139.     End If
  140.  
  141.     ' Read target file local header and data
  142.     Seek #f, entries(targetIdx).localHeaderOffset
  143.     Dim localSig As UInteger = ReadUInt32(f)
  144.     If localSig <> &H4034B50 Then ' Local file header signature 0x04034b50
  145.         Print "Invalid local file header signature"
  146.         Close #f
  147.         Exit Sub
  148.     End If
  149.  
  150.     ' Skip version needed(2), flags(2), method(2), time(2), date(2)
  151.     Seek #f, Seek(#f) + 10
  152.  
  153.     Dim localCRC As UInteger = ReadUInt32(f)
  154.     Dim localCompSize As UInteger = ReadUInt32(f)
  155.     Dim localUncompSize As UInteger = ReadUInt32(f)
  156.  
  157.     Dim localNameLen As UShort = ReadUInt16(f)
  158.     Dim localExtraLen As UShort = ReadUInt16(f)
  159.  
  160.     Dim localName As String = ReadString(f, localNameLen)
  161.  
  162.     ' Read file data (uncompressed)
  163.     Dim As String fileData
  164.     Seek #f, Seek(#f) + localExtraLen
  165.     fileData = String(entries(targetIdx).compSize, Chr(0))
  166.     Get #f, , fileData
  167.  
  168.     Close #f
  169.  
  170.     ' Check compression method = 0 (stored)
  171.     If entries(targetIdx).method <> 0 Then
  172.         Print "File is compressed; this method only works with uncompressed files."
  173.         Exit Sub
  174.     End If
  175.  
  176.     ' Append new data
  177.     fileData += appendData
  178.  
  179.     ' Recalculate CRC32 (simple, just demo: you can implement full CRC32 if needed)
  180.     ' Here we'll keep old CRC to keep example simple.
  181.  
  182.     ' Update sizes
  183.     entries(targetIdx).compSize = Len(fileData)
  184.     entries(targetIdx).uncompSize = Len(fileData)
  185.  
  186.     ' Now rebuild the ZIP
  187.     Dim outf = FreeFile()
  188.     Open outputZip For Binary Access Write As #outf
  189.  
  190.     Dim localOffsets(totalEntries - 1) As UInteger
  191.     Dim curOffset As UInteger = 0
  192.  
  193.     ' Write all local file headers + data (replace target file with new data)
  194.     For i As Integer = 0 To totalEntries - 1
  195.         localOffsets(i) = curOffset
  196.  
  197.         ' Local file header signature
  198.         Put #outf, , &H4034B50
  199.  
  200.         ' Version needed
  201.         Put #outf, , CType(20, UShort)
  202.         ' Flags
  203.         Put #outf, , CType(0, UShort)
  204.         ' Method
  205.         Put #outf, , entries(i).method
  206.         ' Mod time/date
  207.         Put #outf, , mod_time
  208.         Put #outf, , mod_date
  209.  
  210.         ' CRC, sizes
  211.         Dim writeCRC As UInteger = entries(i).crc
  212.         Dim writeCompSize As UInteger = entries(i).compSize
  213.         Dim writeUncompSize As UInteger = entries(i).uncompSize
  214.  
  215.         ' If this is target file, update sizes and fake CRC
  216.         If i = targetIdx Then
  217.             writeCompSize = Len(fileData)
  218.             writeUncompSize = Len(fileData)
  219.             writeCRC = 0 ' TODO: calculate real CRC if you want
  220.         End If
  221.  
  222.         Put #outf, , writeCRC
  223.         Put #outf, , writeCompSize
  224.         Put #outf, , writeUncompSize
  225.  
  226.         ' File name length and extra length
  227.         Put #outf, , CType(Len(entries(i).filename), UShort)
  228.         Put #outf, , CType(0, UShort)
  229.  
  230.         ' File name
  231.         Put #outf, , entries(i).filename
  232.  
  233.         ' File data
  234.         Dim writeData As String
  235.         If i = targetIdx Then
  236.             writeData = fileData
  237.         Else
  238.             ' Open old ZIP and read data for this entry
  239.             Dim oldf = FreeFile()
  240.             Open zipPath For Binary Access Read As #oldf
  241.             Seek #oldf, entries(i).localHeaderOffset
  242.  
  243.             ' Skip local header
  244.             ReadUInt32(oldf) : Seek #oldf, Seek(oldf) + 26 ' Skip 26 bytes after signature
  245.             Dim nlen As UShort = ReadUInt16(oldf)
  246.             Dim nextra As UShort = ReadUInt16(oldf)
  247.             Seek #oldf, Seek(oldf) + nlen + nextra
  248.  
  249.             Dim dataStr As String = String(entries(i).compSize, Chr(0))
  250.             Get #oldf, , dataStr
  251.             Close #oldf
  252.             writeData = dataStr
  253.         End If
  254.  
  255.         Put #outf, , writeData
  256.  
  257.         curOffset = Seek(#outf)
  258.     Next
  259.  
  260.     ' Write central directory
  261.     Dim centralDirStart = curOffset
  262.  
  263.     For i As Integer = 0 To totalEntries - 1
  264.         Put #outf, , &H2014B50  ' Central dir signature
  265.         Put #outf, , CType(20, UShort) ' version made by
  266.         Put #outf, , CType(20, UShort) ' version needed
  267.         Put #outf, , CType(0, UShort)  ' flags
  268.         Put #outf, , entries(i).method
  269.         Put #outf, , mod_time
  270.         Put #outf, , mod_date
  271.  
  272.         Dim writeCRC As UInteger = entries(i).crc
  273.         Dim writeCompSize As UInteger = entries(i).compSize
  274.         Dim writeUncompSize As UInteger = entries(i).uncompSize
  275.  
  276.         If i = targetIdx Then
  277.             writeCompSize = Len(fileData)
  278.             writeUncompSize = Len(fileData)
  279.             writeCRC = 0 ' TODO: real CRC
  280.         End If
  281.  
  282.         Put #outf, , writeCRC
  283.         Put #outf, , writeCompSize
  284.         Put #outf, , writeUncompSize
  285.         Put #outf, , CType(Len(entries(i).filename), UShort)
  286.         Put #outf, , CType(0, UShort) ' extra length
  287.         Put #outf, , CType(0, UShort) ' comment length
  288.         Put #outf, , CType(0, UShort) ' disk number start
  289.         Put #outf, , CType(0, UShort) ' internal attr
  290.         Put #outf, , CType(0, UInteger) ' external attr
  291.         Put #outf, , localOffsets(i)
  292.         Put #outf, , entries(i).filename
  293.     Next
  294.  
  295.     Dim centralDirEnd = Seek(#outf)
  296.  
  297.     ' Write EOCD
  298.     Put #outf, , &H6054B50
  299.     Put #outf, , CType(0, UShort) ' disk number
  300.     Put #outf, , CType(0, UShort) ' disk with central dir
  301.     Put #outf, , CType(totalEntries, UShort) ' entries on disk
  302.     Put #outf, , CType(totalEntries, UShort) ' total entries
  303.     Put #outf, , CType(centralDirEnd - centralDirStart, UInteger) ' central dir size
  304.     Put #outf, , CType(centralDirStart, UInteger) ' offset central dir
  305.     Put #outf, , CType(0, UShort) ' zip comment length
  306.  
  307.     Close #outf
  308.  
  309.     Print "Appended data to '"; targetFile; "' and saved as: "; outputZip
  310. End Sub
  311.  
  312.  
  313. ' --- Example Usage ---
  314. Dim as String zipFile = "input.zip"
  315. Dim as String outputFile = "output.zip"
  316. Dim as String targetFileInZip = "test.txt"
  317. Dim as String dataToAppend = " <-- appended text"
  318.  
  319. AppendToUncompressedFileInZip(zipFile, targetFileInZip, dataToAppend, outputFile)
  320.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement