<?php /*~ simpledatapacker.inc.php
.---------------------------------------------------------------------------.
|  Software: Simple Data Packer Library                                     |
|   Version: 0.1.1                                                          |
|   Contact: via http://www.uniwits.com/contact                             |
|      Info: http://www.uniwits.com/                                        |
|   Support: http://www.uniwits.com/support                                 |
| ------------------------------------------------------------------------- |
|     Admin: Yuxiang Mao (project admininistrator)                          |
|   Authors: Yuxiang Mao (Uniwits) contact@uniwits.com                      |
|   Founder: Yuxiang Mao                                                    |
| Copyright (c) 2010-2012, Yuxiang Mao. All Rights Reserved.                |
| ------------------------------------------------------------------------- |
|   License: Distributed under Uniwits Shareware License (USL)              |
|            http://www.uniwits.com/licenses/shareware/                     |
| This program is distributed as a part of software provided by Uniwits     |
| System WITHOUT ANY WARRANTY; without even the implied warranty of         |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                      |
| ------------------------------------------------------------------------- |
*/ class SimpleDataPacker { private $chunkmaxsize; private $state; private $curchunkoctets; private $outputbuffer; public function __construct($chunkmaxsize=32768) { $this->chunkmaxsize=$chunkmaxsize; $this->state=1<=$chunkmaxsize && $chunkmaxsize<65536?1:0; $this->curchunkoctets=''; $this->outputbuffer.=pack('n',$chunkmaxsize); } public function writeinfo($data,$terminate=true) { if ($this->state!=1) trigger_error("Error: not state for writing info.",E_USER_ERROR); $this->curchunkoctets.=$data; if ($terminate) { if ($this->curchunkoctets>65535) { trigger_error("Error: info is too long.",E_USER_ERROR); $this->state=0; } $this->outputbuffer.=pack('n',strlen($this->curchunkoctets)); $this->outputbuffer.=$this->curchunkoctets; $this->curchunkoctets=''; $this->state=2; } } public function writedata($data,$terminate=false) { if ($this->state!=2) trigger_error("Error: not state for writing data.",E_USER_ERROR); $this->curchunkoctets.=$data; $pendingoctetlen=strlen($this->curchunkoctets); $offset=0; while ($offset+$this->chunkmaxsize<=$pendingoctetlen) { $this->outputbuffer.=pack('n',$this->chunkmaxsize); $this->outputbuffer.=substr($this->curchunkoctets,$offset,$this->chunkmaxsize); $offset+=$this->chunkmaxsize; } $this->curchunkoctets=substr($this->curchunkoctets,$offset); if ($terminate) { $this->outputbuffer.=pack('n',strlen($this->curchunkoctets)); $this->outputbuffer.=$this->curchunkoctets; $this->curchunkoctets=''; $this->state=1; } } public function get_output_clean() { $ob=$this->outputbuffer; $this->outputbuffer=''; return $ob; } }; class SimpleDataUnpacker { private $chunkmaxsize; private $state; private $octetsbuffer; private $oboffset; private $curchunksize; private $curchunkread; private $buffertrimlimit; public function __construct($buffertrimlimit=32768) { $this->state=0; $this->chunkmaxsize=0; $this->oboffset=0; $this->buffertrimlimit=$buffertrimlimit; } private function trim_if_necessary() { if ($this->oboffset>$this->buffertrimlimit) { $this->octetsbuffer=substr($this->octetsbuffer,$this->oboffset); $this->oboffset=0; } } public function put_octets($octets) { $this->octetsbuffer.=$octets; $old_oboffset=-1; while ($old_oboffset!=$this->oboffset) { $old_oboffset=$this->oboffset; switch ($this->state) { case 0: if (strlen($this->octetsbuffer)>=2) { $vals=unpack('n',substr($this->octetsbuffer,0,2)); $this->chunkmaxsize=$vals[1]; $this->oboffset=2; $this->state=1; } break; case 1: if ($this->oboffset+2<=strlen($this->octetsbuffer)) { $vals=unpack('n',substr($this->octetsbuffer,$this->oboffset,2)); $this->curchunksize=$vals[1]; $this->oboffset+=2; $this->state=2; } break; case 2: if ($this->oboffset<strlen($this->octetsbuffer)) { if ($this->oboffset+$this->curchunksize<=strlen($this->octetsbuffer)) $this->state=3; } break; case 3: case 4: case 5: break; } } $this->trim_if_necessary(); } public function infoready() { $this->put_octets(''); return $this->state==3; } public function available() { return $this->oboffset<strlen($this->octetsbuffer); } public function bufferedsize() { return strlen($this->octetsbuffer); } public function getinfo() { if ($this->state!=3) $this->put_octets(''); if ($this->state!=3) return false; $data=substr($this->octetsbuffer,$this->oboffset,$this->curchunksize); $this->oboffset+=$this->curchunksize; $this->state=4; $this->trim_if_necessary(); return $data; } public function dataready() { $this->put_octets(''); return $this->state==5; } public function getdata() { if ($this->state!=4 && $this->state!=5) $this->put_octets(''); if ($this->state!=4 && $this->state!=5) return false; $returndata==''; $old_oboffset=-1; while ($old_oboffset!=$this->oboffset) { $old_oboffset=$this->oboffset; switch ($this->state) { case 4: if ($this->oboffset+2<=strlen($this->octetsbuffer)) { $vals=unpack('n',substr($this->octetsbuffer,$this->oboffset,2)); $this->curchunksize=$vals[1]; $this->oboffset+=2; $this->state=5; $this->curchunkread=0; } break; case 5: $partlen=min(strlen($this->octetsbuffer)-$this->oboffset,$this->curchunksize-$this->curchunkread); $returndata.=substr($this->octetsbuffer,$this->oboffset,$partlen); $this->curchunkread+=$partlen; $this->oboffset+=$partlen; if ($this->curchunksize==$this->curchunkread) if ($this->curchunksize>=$this->chunkmaxsize) $this->state=4; else $this->state=1; break; } } $this->trim_if_necessary(); return $returndata; } }; ?>