PageRenderTime 27ms CodeModel.GetById 12ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/bin/std/neko/zip/Writer.hx

http://github.com/Yoomee/clippy
Haxe | 134 lines | 82 code | 8 blank | 44 comment | 6 complexity | ebdd147c5b1301baac57da23d6dc1b5b MD5 | raw file
  1/*
  2 * Copyright (c) 2005-2008, The haXe Project Contributors
  3 * All rights reserved.
  4 * Redistribution and use in source and binary forms, with or without
  5 * modification, are permitted provided that the following conditions are met:
  6 *
  7 *   - Redistributions of source code must retain the above copyright
  8 *     notice, this list of conditions and the following disclaimer.
  9 *   - Redistributions in binary form must reproduce the above copyright
 10 *     notice, this list of conditions and the following disclaimer in the
 11 *     documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 16 * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
 17 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 20 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 23 * DAMAGE.
 24 */
 25package neko.zip;
 26
 27class Writer {
 28
 29	/*
 30	* The next constant is required for computing the Central
 31	* Directory Record(CDR) size. CDR consists of some fields
 32	* of constant size and a filename. Constant represents
 33	* total length of all fields with constant size for each
 34	* file in archive
 35	*/
 36	private static var CENTRAL_DIRECTORY_RECORD_FIELDS_SIZE = 46;
 37
 38	/*
 39	* The following constant is the total size of all fields
 40	* of Local File Header. It's required for calculating
 41	* offset of start of central directory record
 42	*/
 43	private static var LOCAL_FILE_HEADER_FIELDS_SIZE = 30;
 44
 45	static function writeZipDate( o : haxe.io.Output, date : Date ) {
 46		var hour = date.getHours();
 47		var min = date.getMinutes();
 48		var sec = date.getSeconds() >> 1;
 49		o.writeUInt16( (hour << 11) | (min << 5) | sec );
 50		var year = date.getFullYear() - 1980;
 51		var month = date.getMonth() + 1;
 52		var day = date.getDate();
 53		o.writeUInt16( (year << 9) | (month << 5) | day );
 54	}
 55
 56	static function writeZipEntry( o : haxe.io.Output, level, f : { data : haxe.io.Bytes, fileName : String, fileTime : Date } ) {
 57		var fdata = f.data, cdata = null, crc32, compressed = true;
 58		o.writeUInt30(0x04034B50);
 59		o.writeUInt16(0x0014); // version
 60		o.writeUInt16(0); // flags
 61		if( fdata == null ) {
 62			fdata = haxe.io.Bytes.alloc(0);
 63			cdata = haxe.io.Bytes.ofString("XXXXXX");
 64			crc32 = haxe.Int32.ofInt(0);
 65			compressed = false;
 66		} else {
 67			crc32 = CRC32.encode(f.data);
 68			cdata = Compress.run( f.data, level );
 69		}
 70		o.writeUInt16(compressed?8:0);
 71		writeZipDate(o,f.fileTime);
 72		o.writeInt32(crc32);
 73		o.writeUInt30(cdata.length - 6);
 74		o.writeUInt30(fdata.length);
 75		o.writeUInt16(f.fileName.length);
 76		o.writeUInt16(0);
 77		o.writeString(f.fileName);
 78		if( cdata != null ) o.writeFullBytes(cdata,2,cdata.length-6);
 79		return {
 80			compressed : compressed,
 81			fileName : f.fileName,
 82			dlen : fdata.length,
 83			clen : cdata.length - 6,
 84			date : f.fileTime,
 85			crc32 : crc32,
 86		};
 87	}
 88
 89	public static function writeZip( o : haxe.io.Output, files, compressionLevel : Int ) {
 90		var files = Lambda.map(files,callback(writeZipEntry,o,compressionLevel));
 91		var cdr_size = 0;
 92		var cdr_offset = 0;
 93		for( f in files ) {
 94			var namelen = f.fileName.length;
 95			o.writeUInt30(0x02014B50); // header
 96			o.writeUInt16(0x0014); // version made-by
 97			o.writeUInt16(0x0014); // version
 98			o.writeUInt16(0); // flags
 99			o.writeUInt16(f.compressed?8:0);
100			writeZipDate(o,f.date);
101			o.writeInt32(f.crc32);
102			o.writeUInt30(f.clen);
103			o.writeUInt30(f.dlen);
104			o.writeUInt16(namelen);
105			o.writeUInt16(0); //extra field length always 0
106			o.writeUInt16(0); //comment length always 0
107			o.writeUInt16(0); //disk number start
108			o.writeUInt16(0); //internal file attributes
109			o.writeUInt30(0);	//external file attributes
110			o.writeUInt30(cdr_offset); //relative offset of local header
111			o.writeString(f.fileName);
112			cdr_size += CENTRAL_DIRECTORY_RECORD_FIELDS_SIZE + namelen;
113			cdr_offset += LOCAL_FILE_HEADER_FIELDS_SIZE + namelen + f.clen;
114		}
115		//end of central dir signature
116		o.writeUInt30(0x06054B50);
117		//number of this disk
118		o.writeUInt16(0);
119		//number of the disk with the start of the central directory
120		o.writeUInt16(0);
121		//total number of entries in the central directory on this disk
122		o.writeUInt16(files.length);
123		//total number of entries in the central directory
124		o.writeUInt16(files.length);
125		//size of the central directory record
126		o.writeUInt30(cdr_size);
127		//offset of start of central directory with respect to the starting disk number
128		o.writeUInt30(cdr_offset);
129		// .ZIP file comment length
130		o.writeUInt16(0);
131	}
132
133
134}