forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
193
Kha/Tools/macos/std/haxe/zip/Writer.hx
Normal file
193
Kha/Tools/macos/std/haxe/zip/Writer.hx
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (C)2005-2019 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package haxe.zip;
|
||||
|
||||
import haxe.ds.List;
|
||||
|
||||
class Writer {
|
||||
/**
|
||||
The next constant is required for computing the Central
|
||||
Directory Record(CDR) size. CDR consists of some fields
|
||||
of constant size and a filename. Constant represents
|
||||
total length of all fields with constant size for each
|
||||
file in archive
|
||||
**/
|
||||
inline static var CENTRAL_DIRECTORY_RECORD_FIELDS_SIZE = 46;
|
||||
|
||||
/**
|
||||
The following constant is the total size of all fields
|
||||
of Local File Header. It's required for calculating
|
||||
offset of start of central directory record
|
||||
**/
|
||||
inline static var LOCAL_FILE_HEADER_FIELDS_SIZE = 30;
|
||||
|
||||
var o:haxe.io.Output;
|
||||
var files:List<{
|
||||
name:String,
|
||||
compressed:Bool,
|
||||
clen:Int,
|
||||
size:Int,
|
||||
crc:Int,
|
||||
date:Date,
|
||||
fields:haxe.io.Bytes
|
||||
}>;
|
||||
|
||||
public function new(o:haxe.io.Output) {
|
||||
this.o = o;
|
||||
files = new List();
|
||||
}
|
||||
|
||||
function writeZipDate(date:Date) {
|
||||
var hour = date.getHours();
|
||||
var min = date.getMinutes();
|
||||
var sec = date.getSeconds() >> 1;
|
||||
o.writeUInt16((hour << 11) | (min << 5) | sec);
|
||||
var year = date.getFullYear() - 1980;
|
||||
var month = date.getMonth() + 1;
|
||||
var day = date.getDate();
|
||||
o.writeUInt16((year << 9) | (month << 5) | day);
|
||||
}
|
||||
|
||||
public function writeEntryHeader(f:Entry) {
|
||||
var o = this.o;
|
||||
var flags = 0;
|
||||
if (f.extraFields != null) {
|
||||
for (e in f.extraFields)
|
||||
switch (e) {
|
||||
case FUtf8:
|
||||
flags |= 0x800;
|
||||
default:
|
||||
}
|
||||
}
|
||||
o.writeInt32(0x04034B50);
|
||||
o.writeUInt16(0x0014); // version
|
||||
o.writeUInt16(flags); // flags
|
||||
if (f.data == null) {
|
||||
f.fileSize = 0;
|
||||
f.dataSize = 0;
|
||||
f.crc32 = 0;
|
||||
f.compressed = false;
|
||||
f.data = haxe.io.Bytes.alloc(0);
|
||||
} else {
|
||||
if (f.crc32 == null) {
|
||||
if (f.compressed)
|
||||
throw "CRC32 must be processed before compression";
|
||||
f.crc32 = haxe.crypto.Crc32.make(f.data);
|
||||
}
|
||||
if (!f.compressed)
|
||||
f.fileSize = f.data.length;
|
||||
f.dataSize = f.data.length;
|
||||
}
|
||||
o.writeUInt16(f.compressed ? 8 : 0);
|
||||
writeZipDate(f.fileTime);
|
||||
o.writeInt32(f.crc32);
|
||||
o.writeInt32(f.dataSize);
|
||||
o.writeInt32(f.fileSize);
|
||||
o.writeUInt16(f.fileName.length);
|
||||
var e = new haxe.io.BytesOutput();
|
||||
if (f.extraFields != null) {
|
||||
for (f in f.extraFields)
|
||||
switch (f) {
|
||||
case FInfoZipUnicodePath(name, crc):
|
||||
var namebytes = haxe.io.Bytes.ofString(name);
|
||||
e.writeUInt16(0x7075);
|
||||
e.writeUInt16(namebytes.length + 5);
|
||||
e.writeByte(1); // version
|
||||
e.writeInt32(crc);
|
||||
e.write(namebytes);
|
||||
case FUnknown(tag, bytes):
|
||||
e.writeUInt16(tag);
|
||||
e.writeUInt16(bytes.length);
|
||||
e.write(bytes);
|
||||
case FUtf8:
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
var ebytes = e.getBytes();
|
||||
o.writeUInt16(ebytes.length);
|
||||
o.writeString(f.fileName);
|
||||
o.write(ebytes);
|
||||
files.add({
|
||||
name: f.fileName,
|
||||
compressed: f.compressed,
|
||||
clen: f.data.length,
|
||||
size: f.fileSize,
|
||||
crc: f.crc32,
|
||||
date: f.fileTime,
|
||||
fields: ebytes
|
||||
});
|
||||
}
|
||||
|
||||
public function write(files:List<Entry>) {
|
||||
for (f in files) {
|
||||
writeEntryHeader(f);
|
||||
o.writeFullBytes(f.data, 0, f.data.length);
|
||||
}
|
||||
writeCDR();
|
||||
}
|
||||
|
||||
public function writeCDR() {
|
||||
var cdr_size = 0;
|
||||
var cdr_offset = 0;
|
||||
for (f in files) {
|
||||
var namelen = f.name.length;
|
||||
var extraFieldsLength = f.fields.length;
|
||||
o.writeInt32(0x02014B50); // header
|
||||
o.writeUInt16(0x0014); // version made-by
|
||||
o.writeUInt16(0x0014); // version
|
||||
o.writeUInt16(0); // flags
|
||||
o.writeUInt16(f.compressed ? 8 : 0);
|
||||
writeZipDate(f.date);
|
||||
o.writeInt32(f.crc);
|
||||
o.writeInt32(f.clen);
|
||||
o.writeInt32(f.size);
|
||||
o.writeUInt16(namelen);
|
||||
o.writeUInt16(extraFieldsLength);
|
||||
o.writeUInt16(0); // comment length always 0
|
||||
o.writeUInt16(0); // disk number start
|
||||
o.writeUInt16(0); // internal file attributes
|
||||
o.writeInt32(0); // external file attributes
|
||||
o.writeInt32(cdr_offset); // relative offset of local header
|
||||
o.writeString(f.name);
|
||||
o.write(f.fields);
|
||||
cdr_size += CENTRAL_DIRECTORY_RECORD_FIELDS_SIZE + namelen + extraFieldsLength;
|
||||
cdr_offset += LOCAL_FILE_HEADER_FIELDS_SIZE + namelen + extraFieldsLength + f.clen;
|
||||
}
|
||||
// end of central dir signature
|
||||
o.writeInt32(0x06054B50);
|
||||
// number of this disk
|
||||
o.writeUInt16(0);
|
||||
// number of the disk with the start of the central directory
|
||||
o.writeUInt16(0);
|
||||
// total number of entries in the central directory on this disk
|
||||
o.writeUInt16(files.length);
|
||||
// total number of entries in the central directory
|
||||
o.writeUInt16(files.length);
|
||||
// size of the central directory record
|
||||
o.writeInt32(cdr_size);
|
||||
// offset of start of central directory with respect to the starting disk number
|
||||
o.writeInt32(cdr_offset);
|
||||
// .ZIP file comment length
|
||||
o.writeUInt16(0);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user