Created
August 22, 2014 10:34
-
-
Save k0t0vich/6a6cc85f8799d0f4560e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ru.riot.utils.net.tar { | |
import flash.display.Shape; | |
import flash.events.Event; | |
import flash.utils.IDataInput; | |
[Event(name="fileParsed", type="ru.riot.utils.net.tar.TarParserEvent")] | |
[Event(name="archiveParsed", type="ru.riot.utils.net.tar.TarParserEvent")] | |
public class StreamTarParser extends TarParser { | |
private static const BLOCK_SIZE: int = 512; | |
private static const frameListener:Shape = new Shape(); | |
public static var checkRecursive:Boolean = false; | |
private var _operation: Function; | |
private var _needSize: uint; | |
private var _currentFile: TarFile; | |
// флаг ограничения реку | |
private var recursiveCounter:int = 0; | |
private var maxRecursiveCounter:int = 100; | |
public function StreamTarParser(bytes: IDataInput) { | |
super(bytes); | |
_needSize = BLOCK_SIZE; | |
operation = headerOperation; | |
} | |
override public function read():void { | |
if (_data.bytesAvailable >= _needSize) { | |
_operation.call(); | |
} | |
} | |
private function recursiveRead():void { | |
if (checkRecursive) { | |
recursiveCounter++; | |
if (recursiveCounter > maxRecursiveCounter){ | |
recursiveCounter = 0; | |
frameListener.addEventListener(Event.ENTER_FRAME, nextFrameRead); | |
} else { | |
read(); | |
} | |
} else { | |
read(); | |
} | |
} | |
protected function nextFrameRead(event:Event):void { | |
frameListener.removeEventListener(Event.ENTER_FRAME, nextFrameRead); | |
read(); | |
} | |
private function headerOperation():void { | |
_currentFile = readFileHeader(); | |
if (_currentFile){ | |
// если не каталог или пустой файл, читаем контент | |
if (_currentFile.size > 0) { | |
_needSize = _currentFile.size; | |
operation = contentOperation; | |
} else { | |
// иначе читаем следующий заголовок | |
recursiveRead(); | |
} | |
} else { | |
_needSize = BLOCK_SIZE * 2 - 100; | |
operation = endArchiveOperation; | |
} | |
} | |
private function contentOperation():void { | |
_data.readBytes(_currentFile.data, 0, _currentFile.size); | |
var pad:uint = getPad(_currentFile.size); | |
if (pad > 0 ) { | |
_needSize = pad; | |
operation = padOperation; | |
} else { | |
operation = endFileOperation; | |
} | |
} | |
private function padOperation():void { | |
skipBytes(_needSize); | |
operation = endFileOperation; | |
} | |
private function endArchiveOperation():void { | |
skipBytes(_needSize); | |
var event:TarParserEvent = new TarParserEvent(TarParserEvent.ARCHIVE_PARSED); | |
dispatchEvent(event); | |
} | |
private function endFileOperation():void { | |
var event:TarParserEvent = new TarParserEvent(TarParserEvent.FILE_PARSED, _currentFile); | |
dispatchEvent(event); | |
_needSize = BLOCK_SIZE; | |
operation = headerOperation; | |
} | |
private function set operation(value:Function):void { | |
if( _operation !== value){ | |
_operation = value; | |
recursiveRead(); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ru.riot.utils.net.tar { | |
import flash.utils.ByteArray; | |
public class TarFile { | |
public var name : String; | |
public var size : uint; | |
public var data : ByteArray; | |
public function TarFile(name:String) { | |
super(); | |
this.name = name; | |
data = new ByteArray(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ru.riot.utils.net.tar { | |
import flash.events.EventDispatcher; | |
import flash.utils.ByteArray; | |
import flash.utils.IDataInput; | |
public class TarParser extends EventDispatcher { | |
protected var _data: IDataInput; | |
private var _files:Array; | |
public function get files():Array { | |
return _files; | |
} | |
public function TarParser(bytes: IDataInput) { | |
super(); | |
this._data = bytes; | |
} | |
public function read():void { | |
_files = new Array(); | |
while (true) { | |
var e: TarFile = readFileHeader(); | |
if (e == null) | |
break; | |
var size: uint = e.size; | |
if (e.size > 0) { | |
_data.readBytes(e.data, 0, size); | |
_files.push(e); | |
var pad:uint = getPad(size); | |
//trace ("size", size,"pad", pad); | |
skipBytes(pad); | |
} | |
} | |
} | |
/** | |
* Parse Header and create new tar file | |
* struct header_posix_ustar { | |
char name[100]; | |
char mode[8]; | |
char uid[8]; | |
char gid[8]; | |
char size[12]; | |
char mtime[12]; | |
char checksum[8]; | |
char typeflag[1]; | |
char linkname[100]; | |
char magic[6]; | |
char version[2]; | |
char uname[32]; | |
char gname[32]; | |
char devmajor[8]; | |
char devminor[8]; | |
char prefix[155]; | |
char pad[12]; | |
}; | |
*/ | |
protected function readFileHeader():TarFile { | |
var fname: String = _data.readUTFBytes(100); | |
if (!fname || fname.length == 0) { | |
return null; | |
} | |
var tarFile: TarFile = new TarFile(fname); | |
// нам не нужны никакие данные, кроме имени и размера - скипаем | |
skipBytes( 8 + 8 + 8); | |
tarFile.size = parseOctal(12); | |
skipBytes(8 + 4 + 8 + 1 + 100 + 8 + 32 + 32 + 8 + 8 + 167); | |
return tarFile; | |
} | |
protected function getPad(size: uint):uint { | |
return Math.ceil(size / 512) * 512 - size; | |
} | |
protected function skipBytes(size: uint):void { | |
var bytes: ByteArray = new ByteArray(); | |
_data.readBytes(bytes, 0, size); | |
bytes.clear(); | |
} | |
protected function parseOctal(size: uint = 8):int { | |
var bytes: ByteArray = new ByteArray(); | |
_data.readBytes(bytes, 0, size); | |
var num: int = 0; | |
for (var p: uint = 0; p < size; p++) { | |
var c: int = bytes.readByte(); | |
if (c == 0) | |
break; | |
if (c == 32) | |
continue; | |
if (c < 48 || c > 55) { | |
return 0; | |
//throw new Error("Invalid octal char"); | |
} | |
num = (num * 8) + (c - 48); | |
} | |
bytes.clear(); | |
return num; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ru.riot.utils.net.tar { | |
import flash.events.Event; | |
public class TarParserEvent extends Event { | |
public static const FILE_PARSED: String = "fileParsed"; | |
public static const ARCHIVE_PARSED: String = "archiveParsed"; | |
private var _file: TarFile; | |
public function TarParserEvent(type: String, file: TarFile = null) { | |
super(type); | |
_file = file; | |
} | |
override public function clone():Event { | |
return new TarParserEvent(type, _file); | |
} | |
public function get file():TarFile { | |
return _file; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment