/**
* Copyright uwi ( http://wonderfl.net/user/uwi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/ghlH
*/
package {
import flash.display.Sprite;
import flash.text.TextField;
import flash.utils.ByteArray;
import flash.net.*;
import flash.events.*;
import flash.system.*;
import com.bit101.components.*;
public class Test extends Sprite {
private var _tf : TextField;
public function Test() {
_tf = new TextField();
_tf.width = 465;
_tf.height = 465;
addChild(_tf);
Security.loadPolicyFile("http://wonderfl.net/crossdomain.xml");
var btn : PushButton = new PushButton(this, 200, 200, "save", onSave);
_ul = new URLLoader(new URLRequest("http://wonderfl.net/user/uwi/codes"));
_ul.addEventListener(Event.COMPLETE, onCodesLoadComplete);
_ul.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function(e:ErrorEvent):void { tr(e); });
_ul.addEventListener(IOErrorEvent.IO_ERROR, function(e:ErrorEvent):void { tr(e); });
}
private function onCodesLoadComplete(e : Event) : void
{
tr("III");
_ul.removeEventListener(Event.COMPLETE, onCodesLoadComplete);
tr(_ul.data);
}
private var _ul : URLLoader;
private function onSave(e : MouseEvent) : void
{
var zo : ZipOutput = new ZipOutput();
var fileName : String = "test.txt";
var data : ByteArray = new ByteArray();
data.writeMultiByte("おはおはよー", "UTF-8");
var ze : ZipEntry = new ZipEntry(fileName);
zo.putNextEntry(ze);
zo.write(data);
var fileName2 : String = "test2.txt";
var data2 : ByteArray = new ByteArray();
data2.writeMultiByte("おはおはよー?", "UTF-8");
var ze2 : ZipEntry = new ZipEntry(fileName2);
zo.putNextEntry(ze2);
zo.write(data2);
zo.closeEntry();
zo.finish();
var fr : FileReference = new FileReference();
fr.save(zo.byteArray, "test.zip");
}
private function tr(...o : Array) : void
{
_tf.appendText(o + "\n");
}
}
}
import flash.utils.Dictionary;
import flash.utils.Endian;
import flash.utils.ByteArray;
class ZipOutput {
private var _entry:ZipEntry;
private var _entries:Array = [];
private var _names:Dictionary = new Dictionary();
private var _def:Deflater = new Deflater();
private var _crc:CRC32 = new CRC32();
private var _buf:ByteArray = new ByteArray();
private var _comment:String = "";
public function ZipOutput() {
_buf.endian = Endian.LITTLE_ENDIAN;
}
/**
* Returns the number of entries in this zip file.
*/
public function get size():uint {
return _entries.length;
}
/**
* Returns the byte array of the finished zip.
*/
public function get byteArray():ByteArray {
_buf.position = 0;
return _buf;
}
/**
*
*/
public function set comment(value:String):void {
_comment = value;
}
public function putNextEntry(e:ZipEntry):void {
if(_entry != null) closeEntry();
// TODO:
if(e.dostime == 0) e.time = new Date().time;
if (e.method == -1) e.method = ZipConstants.DEFLATED; // use default method
switch(e.method) {
case ZipConstants.DEFLATED:
if (e.size == -1 || e.compressedSize == -1 || e.crc == 0) {
// store size, compressed size, and crc-32 in data descriptor
// immediately following the compressed entry data
e.flag = 8;
} else if (e.size != -1 && e.compressedSize != -1 && e.crc != 0) {
// store size, compressed size, and crc-32 in LOC header
e.flag = 0;
} else {
throw new ZipError("DEFLATED entry missing size, compressed size, or crc-32");
}
e.version = 20;
break;
case ZipConstants.STORED:
// compressed size, uncompressed size, and crc-32 must all be
// set for entries using STORED compression method
if (e.size == -1) {
e.size = e.compressedSize;
} else if (e.compressedSize == -1) {
e.compressedSize = e.size;
} else if (e.size != e.compressedSize) {
throw new ZipError("STORED entry where compressed != uncompressed size");
}
if (e.size == -1 || e.crc == 0) {
throw new ZipError("STORED entry missing size, compressed size, or crc-32");
}
e.version = 10;
e.flag = 0;
break;
default:
throw new ZipError("unsupported compression method");
}
e.offset = _buf.position;
if (_names[e.name] != null) {
throw new ZipError("duplicate entry: " + e.name);
} else {
_names[e.name] = e;
}
writeLOC(e);
_entries.push(e);
_entry = e;
}
public function write(b:ByteArray):void {
if (_entry == null) {
throw new ZipError("no current ZIP entry");
}
//*
switch (_entry.method) {
case ZipConstants.DEFLATED:
//super.write(b, off, len);
var cb:ByteArray = new ByteArray();
_def.setInput(b);
_def.deflate(cb);
_buf.writeBytes(cb);
// TODO: test if Deflater can deflate to the end of _buf (saves from using variable cb and an extra copy)
break;
case ZipConstants.STORED:
// TODO:
//if (written - locoff > _entry.size) {
// throw new ZipError("attempt to write past end of STORED entry");
//}
//out.write(b, off, len);
_buf.writeBytes(b);
break;
default:
throw new Error("invalid compression method");
}
/**/
_crc.update(b);
}
// check if this method is still necessary since we're not dealing with streams
// seems crc and whether a data descriptor i necessary is determined here
public function closeEntry():void {
var e:ZipEntry = _entry;
if(e != null) {
switch (e.method) {
case ZipConstants.DEFLATED:
if ((e.flag & 8) == 0) {
// verify size, compressed size, and crc-32 settings
if (e.size != _def.getBytesRead()) {
throw new ZipError("invalid entry size (expected " + e.size + " but got " + _def.getBytesRead() + " bytes)");
}
if (e.compressedSize != _def.getBytesWritten()) {
throw new ZipError("invalid entry compressed size (expected " + e.compressedSize + " but got " + _def.getBytesWritten() + " bytes)");
}
if (e.crc != _crc.getValue()) {
throw new ZipError( "invalid entry CRC-32 (expected 0x" + e.crc + " but got 0x" + _crc.getValue() + ")");
}
} else {
e.size = _def.getBytesRead();
e.compressedSize = _def.getBytesWritten();
e.crc = _crc.getValue();
writeEXT(e);
}
_def.reset();
break;
case ZipConstants.STORED:
// TODO:
break;
default:
throw new Error("invalid compression method");
}
_crc.reset();
_entry = null;
}
}
public function finish():void {
if(_entry != null) closeEntry();
if (_entries.length < 1) throw new ZipError("ZIP file must have at least one entry");
var off:uint = _buf.position;
// write central directory
for(var i:uint = 0; i < _entries.length; i++) {
writeCEN(_entries[i]);
}
writeEND(off, _buf.position - off);
}
private function writeLOC(e:ZipEntry):void {
_buf.writeUnsignedInt(ZipConstants.LOCSIG);
_buf.writeShort(e.version);
_buf.writeShort(e.flag);
_buf.writeShort(e.method);
_buf.writeUnsignedInt(e.dostime); // dostime
if ((e.flag & 8) == 8) {
// store size, uncompressed size, and crc-32 in data descriptor
// immediately following compressed entry data
_buf.writeUnsignedInt(0);
_buf.writeUnsignedInt(0);
_buf.writeUnsignedInt(0);
} else {
_buf.writeUnsignedInt(e.crc); // crc-32
_buf.writeUnsignedInt(e.compressedSize); // compressed size
_buf.writeUnsignedInt(e.size); // uncompressed size
}
_buf.writeShort(e.name.length);
_buf.writeShort(e.extra != null ? e.extra.length : 0);
_buf.writeUTFBytes(e.name);
if (e.extra != null) {
_buf.writeBytes(e.extra);
}
}
/*
* Writes extra data descriptor (EXT) for specified entry.
*/
private function writeEXT(e:ZipEntry):void {
_buf.writeUnsignedInt(ZipConstants.EXTSIG); // EXT header signature
_buf.writeUnsignedInt(e.crc); // crc-32
_buf.writeUnsignedInt(e.compressedSize); // compressed size
_buf.writeUnsignedInt(e.size); // uncompressed size
}
/*
* Write central directory (CEN) header for specified entry.
* REMIND: add support for file attributes
*/
private function writeCEN(e:ZipEntry):void {
_buf.writeUnsignedInt(ZipConstants.CENSIG); // CEN header signature
_buf.writeShort(e.version); // version made by
_buf.writeShort(e.version); // version needed to extract
_buf.writeShort(e.flag); // general purpose bit flag
_buf.writeShort(e.method); // compression method
_buf.writeUnsignedInt(e.dostime); // last modification time
_buf.writeUnsignedInt(e.crc); // crc-32
_buf.writeUnsignedInt(e.compressedSize); // compressed size
_buf.writeUnsignedInt(e.size); // uncompressed size
_buf.writeShort(e.name.length);
_buf.writeShort(e.extra != null ? e.extra.length : 0);
_buf.writeShort(e.comment != null ? e.comment.length : 0);
_buf.writeShort(0); // starting disk number
_buf.writeShort(0); // internal file attributes (unused)
_buf.writeUnsignedInt(0); // external file attributes (unused)
_buf.writeUnsignedInt(e.offset); // relative offset of local header
_buf.writeUTFBytes(e.name);
if (e.extra != null) {
_buf.writeBytes(e.extra);
}
if (e.comment != null) {
_buf.writeUTFBytes(e.comment);
}
}
/*
* Writes end of central directory (END) header.
*/
private function writeEND(off:uint, len:uint):void {
_buf.writeUnsignedInt(ZipConstants.ENDSIG); // END record signature
_buf.writeShort(0); // number of this disk
_buf.writeShort(0); // central directory start disk
_buf.writeShort(_entries.length); // number of directory entries on disk
_buf.writeShort(_entries.length); // total number of directory entries
_buf.writeUnsignedInt(len); // length of central directory
_buf.writeUnsignedInt(off); // offset of central directory
_buf.writeUTF(_comment); // zip file comment
}
}
import flash.utils.ByteArray;
/**
* This class represents a member of a zip archive. ZipFile
* will give you instances of this class as information
* about the members in an archive. On the other hand ZipOutput
* needs an instance of this class to create a new member.
*
* @author David Chang
*/
class ZipEntry {
// some members are internal as ZipFile will need to set these directly
// where their accessor does type conversion
private var _name:String;
private var _size:int = -1;
private var _compressedSize:int = -1;
private var _crc:uint;
/** @private */
internal var dostime:uint;
private var _method:int = -1; // compression method
private var _extra:ByteArray; // optional extra field data for entry
private var _comment:String; // optional comment string for entry
// The following flags are used only by ZipOutput
/** @private */
internal var flag:int; // bit flags
/** @private */
internal var version:int; // version needed to extract
/** @private */
internal var offset:int; // offset of loc header
/**
* Creates a zip entry with the given name.
* @param name the name. May include directory components separated
* by '/'.
*/
public function ZipEntry(name:String) {
_name = name;
}
/**
* Returns the entry name. The path components in the entry are
* always separated by slashes ('/').
*/
public function get name():String {
return _name;
}
/**
* Gets the time of last modification of the entry.
* @return the time of last modification of the entry, or -1 if unknown.
*/
public function get time():Number {
var d:Date = new Date(
((dostime >> 25) & 0x7f) + 1980,
((dostime >> 21) & 0x0f) - 1,
(dostime >> 16) & 0x1f,
(dostime >> 11) & 0x1f,
(dostime >> 5) & 0x3f,
(dostime & 0x1f) << 1
);
return d.time;
}
/**
* Sets the time of last modification of the entry.
* @time the time of last modification of the entry.
*/
public function set time(time:Number):void {
var d:Date = new Date(time);
dostime =
(d.fullYear - 1980 & 0x7f) << 25
| (d.month + 1) << 21
| d.day << 16
| d.hours << 11
| d.minutes << 5
| d.seconds >> 1;
}
/**
* Gets the size of the uncompressed data.
*/
public function get size():int {
return _size;
}
/**
* Sets the size of the uncompressed data.
*/
public function set size(size:int):void {
_size = size;
}
/**
* Gets the size of the compressed data.
*/
public function get compressedSize():int {
return _compressedSize;
}
/**
* Sets the size of the compressed data.
*/
public function set compressedSize(csize:int):void {
_compressedSize = csize;
}
/**
* Gets the crc of the uncompressed data.
*/
public function get crc():uint {
return _crc;
}
/**
* Sets the crc of the uncompressed data.
*/
public function set crc(crc:uint):void {
_crc = crc;
}
/**
* Gets the compression method.
*/
public function get method():int {
return _method;
}
/**
* Sets the compression method. Only DEFLATED and STORED are
* supported.
*/
public function set method(method:int):void {
_method = method;
}
/**
* Gets the extra data.
*/
public function get extra():ByteArray {
return _extra;
}
/**
* Sets the extra data.
*/
public function set extra(extra:ByteArray):void {
_extra = extra;
}
/**
* Gets the extra data.
*/
public function get comment():String {
return _comment;
}
/**
* Sets the entry comment.
*/
public function set comment(comment:String):void {
_comment = comment;
}
/**
* Gets true, if the entry is a directory. This is solely
* determined by the name, a trailing slash '/' marks a directory.
*/
public function isDirectory():Boolean {
return _name.charAt(_name.length - 1) == '/';
}
/**
* Gets the string representation of this ZipEntry. This is just
* the name as returned by name.
*/
public function toString():String {
return _name;
}
}
import flash.utils.Endian;
import flash.utils.ByteArray;
/**
* This is the Deflater class. The deflater class compresses input
* with the deflate algorithm described in RFC 1951. It uses the
* ByteArray compress method to deflate.
*
* @author David Chang
*/
class Deflater {
private var buf:ByteArray;
private var compressed:Boolean;
private var totalIn:uint;
private var totalOut:uint;
/**
* Creates a new deflater.
*/
public function Deflater() {
reset();
}
/**
* Resets the deflater. The deflater acts afterwards as if it was
* just created.
*/
public function reset():void {
buf = new ByteArray();
//buf.endian = Endian.LITTLE_ENDIAN;
compressed = false;
totalOut = totalIn = 0;
}
/**
* Sets the data which should be compressed next.
*
* @param input the buffer containing the input data.
*/
public function setInput(input:ByteArray):void {
buf.writeBytes(input);
totalIn = buf.length;
}
/**
* Deflates the current input block to the given array.
*
* @param output the buffer where to write the compressed data.
*/
public function deflate(output:ByteArray):uint {
if(!compressed) {
buf.compress();
compressed = true;
}
output.writeBytes(buf, 2, buf.length - 6); // remove 2-byte header and last 4-byte addler32 checksum
totalOut = output.length;
return 0;
}
/**
* Gets the number of input bytes.
*/
public function getBytesRead():uint {
return totalIn;
}
/**
* Gets the number of output bytes.
*/
public function getBytesWritten():uint {
return totalOut;
}
}
import flash.utils.ByteArray;
/**
* Computes CRC32 data checksum of a data stream.
* The actual CRC32 algorithm is described in RFC 1952
* (GZIP file format specification version 4.3).
*
* @author David Chang
* @date January 2, 2007.
*/
class CRC32 {
/** The crc data checksum so far. */
private var crc:uint;
/** The fast CRC table. Computed once when the CRC32 class is loaded. */
private static var crcTable:Array = makeCrcTable();
/** Make the table for a fast CRC. */
private static function makeCrcTable():Array {
var crcTable:Array = new Array(256);
for (var n:int = 0; n < 256; n++) {
var c:uint = n;
for (var k:int = 8; --k >= 0; ) {
if((c & 1) != 0) c = 0xedb88320 ^ (c >>> 1);
else c = c >>> 1;
}
crcTable[n] = c;
}
return crcTable;
}
/**
* Returns the CRC32 data checksum computed so far.
*/
public function getValue():uint {
return crc & 0xffffffff;
}
/**
* Resets the CRC32 data checksum as if no update was ever called.
*/
public function reset():void {
crc = 0;
}
/**
* Adds the complete byte array to the data checksum.
*
* @param buf the buffer which contains the data
*/
public function update(buf:ByteArray):void {
var off:uint = 0;
var len:uint = buf.length;
var c:uint = ~crc;
while(--len >= 0) c = crcTable[(c ^ buf[off++]) & 0xff] ^ (c >>> 8);
crc = ~c;
}
}
internal class ZipConstants {
/* The local file header */
internal static const LOCSIG:uint = 0x04034b50; // "PK\003\004"
internal static const LOCHDR:uint = 30; // LOC header size
internal static const LOCVER:uint = 4; // version needed to extract
//internal static const LOCFLG:uint = 6; // general purpose bit flag
//internal static const LOCHOW:uint = 8; // compression method
//internal static const LOCTIM:uint = 10; // modification time
//internal static const LOCCRC:uint = 14; // uncompressed file crc-32 value
//internal static const LOCSIZ:uint = 18; // compressed size
//internal static const LOCLEN:uint = 22; // uncompressed size
internal static const LOCNAM:uint = 26; // filename length
//internal static const LOCEXT:uint = 28; // extra field length
/* The Data descriptor */
internal static const EXTSIG:uint = 0x08074b50; // "PK\007\008"
internal static const EXTHDR:uint = 16; // EXT header size
//internal static const EXTCRC:uint = 4; // uncompressed file crc-32 value
//internal static const EXTSIZ:uint = 8; // compressed size
//internal static const EXTLEN:uint = 12; // uncompressed size
/* The central directory file header */
internal static const CENSIG:uint = 0x02014b50; // "PK\001\002"
internal static const CENHDR:uint = 46; // CEN header size
//internal static const CENVEM:uint = 4; // version made by
internal static const CENVER:uint = 6; // version needed to extract
//internal static const CENFLG:uint = 8; // encrypt, decrypt flags
//internal static const CENHOW:uint = 10; // compression method
//internal static const CENTIM:uint = 12; // modification time
//internal static const CENCRC:uint = 16; // uncompressed file crc-32 value
//internal static const CENSIZ:uint = 20; // compressed size
//internal static const CENLEN:uint = 24; // uncompressed size
internal static const CENNAM:uint = 28; // filename length
//internal static const CENEXT:uint = 30; // extra field length
//internal static const CENCOM:uint = 32; // comment length
//internal static const CENDSK:uint = 34; // disk number start
//internal static const CENATT:uint = 36; // internal file attributes
//internal static const CENATX:uint = 38; // external file attributes
internal static const CENOFF:uint = 42; // LOC header offset
/* The entries in the end of central directory */
internal static const ENDSIG:uint = 0x06054b50; // "PK\005\006"
internal static const ENDHDR:uint = 22; // END header size
//internal static const ENDSUB:uint = 8; // number of entries on this disk
internal static const ENDTOT:uint = 10; // total number of entries
//internal static const ENDSIZ:uint = 12; // central directory size in bytes
internal static const ENDOFF:uint = 16; // offset of first CEN header
//internal static const ENDCOM:uint = 20; // zip file comment length
/* Compression methods */
internal static const STORED:uint = 0;
internal static const DEFLATED:uint = 8;
}
import flash.errors.IOError;
/**
* Thrown during the creation or input of a zip file.
*/
class ZipError extends IOError {
public function ZipError(message:String = "", id:int = 0) {
super(message, id);
}
}