Login   Register  
PHP Classes
elePHPant
Icontem

File: CFALib

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Tobias Marstaller  >  CFA Library  >  CFALib  >  Download  
File: CFALib
Role: Class source
Content type: text/plain
Description: All 4 Classes of the Library
Class: CFA Library
Compress and extract files from a single file
Author: By
Last change: Another bug has been fixed, CFAFile should now work properly.
Date: 2011-08-26 09:44
Size: 10,609 bytes
 

Contents

Class file image Download
<?php
class CFACreator {
	private $source;
	private $pw;
	public function __construct($source) {
		if (!file_exists($source)) {
			throw new Exception($source." not found.");
		}
		if (!is_dir($source)) {
			throw new Exception("There is no need to pack a single file.");
		}
		if (substr($source, strlen($source)-1)!="\\" && substr($source, strlen($source)-1)!="/") $source.="/";
		$this->source=$source;
	}
	public function setPassword($pw) {
		$this->pw=$pw;
	}
	public function packTo($file, $crypt=false) {
		$files=$this->listDir($this->source);
		if ($crypt) {
			$out_stream=tmpfile();
		} else {
			$out_stream=fopen($file, "w+");
			fwrite($out_stream, "r");
		}
		foreach ($files as $name=>$size) {
			$name=gzcompress($name);
			fwrite($out_stream, $this->compress(strlen($name)));
			fwrite($out_stream, chr(255));
			fwrite($out_stream, $name);
			fwrite($out_stream, $this->compress($size));
			fwrite($out_stream, chr(255));
		}
		fwrite($out_stream, chr(255));
		foreach ($files as $name=>$size) {
			$fp=fopen($this->source.$name, "r+");
			while ($size>=100) {
				fwrite($out_stream, fread($fp, 100));
				$size-=100;
			}
			if ($size!=0) fwrite($out_stream, fread($fp, $size));
		}
		if ($crypt) {
			rewind($out_stream);
			$tmp=$out_stream;
			$out_stream=fopen($file, "w+");
			fwrite($out_stream, "c");
			$iv=$this->pw;
			if (strlen($iv)>8) {
				$iv=substr($iv, 0, 8);
			} elseif (strlen($iv)<8) {
				$num=round(8/strlen($iv))+1;
				$iv=str_repeat($iv, $num);
				$iv=substr($iv, 0, 8);
			}
			while (!feof($tmp)) {
				$part=fread($tmp, 100);
				$part=mcrypt_encrypt(MCRYPT_BLOWFISH, $this->pw, $part, "cbc", $iv);
				$part=base64_encode($part);
				fwrite($out_stream, $part);
			}
			fclose($tmp);
		}
		fclose($out_stream);
	}
	private function listDir($path, $is_root=true, $root=null) {
		$files=array();
		if (substr($path, strlen($path)-1)!="\\" && substr($path, strlen($path)-1)!="/") $path.="/";
		if ($root==null && $is_root) $root=$path;
		if ($dir=opendir($path)) {
			while ($file=readdir($dir)) {
				if ($file!=".." && $file!=".") {
					if (is_dir($path.$file)) {
						$ar=$this->listDir($path.$file, false, $root);
						$files=array_merge($files, $ar);
					} else {
						if ($is_root) {
							$name=$file;
						} else {
							$name=substr($path.$file, strlen($root));
						}
						$files[$name]=filesize($path.$file);
					}
				}
			}
			closedir($dir);
			return $files;
		} else {
			throw new Exception("Could not open ".$path);
		}
	}
	public static function compress($int) {
		$comp="";
		$full=0;
		while ($int>=253) {
			if ($full==253) {
				$comp.=chr(253);
				$full=0;
			}
			$full++;
			$int-=253;
		}
		if ($full!=0) $comp.=chr($full);
		$comp.=chr(254);
		if ($int!=0) $comp.=chr($int);
		return $comp;
	}
}

class CFAExtractor {
	private $path;
	private $pw;
	
	public function __construct($path) {
		if (!file_exists($path)) {
			throw new Exception($path." not found.");
		}
		$this->path=$path;
	}
	public function setPassword($pw) {
		$this->pw=$pw;
	}
	public function extractTo($path) {
		if (!file_exists($this->path)) {
			throw new Exception($path." not found.");
		}
		if (substr($path, strlen($path)-1)!="\\" && substr($path, strlen($path)-1)!="/") $path.="/";
		$in_stream=fopen($this->path, "r");
		$mode=fread($in_stream, 1);
		if ($mode!="c" && $mode!="r") {
			fclose($in_stream);
			throw new Exception("Invalid file given.");
		}
		if ($mode=="c") {
			// crypted file
			if ($this->pw==null) {
				throw new Exception("File encrypted but no password given!");
			}
			$iv=$this->pw;
			if (strlen($iv)>8) {
				$iv=substr($iv, 0, 8);
			} elseif (strlen($iv)<8) {
				$num=round(8/strlen($iv))+1;
				$iv=str_repeat($iv, $num);
				$iv=substr($iv, 0, 8);
			}
			$tmp_file=tmpfile();
			while (!feof($in_stream)) {
				$part=fread($in_stream, 136);
				$part=base64_decode($part);
				$part=mcrypt_decrypt(MCRYPT_BLOWFISH, $this->pw, $part, "cbc", $iv);
				fwrite($tmp_file, $part);
			}
			fclose($in_stream);
			rewind($tmp_file);
			$in_stream=$tmp_file;
		}
		$files=array();
		$ci=ord(fread($in_stream, 1));
		while ($ci!=255) {
			$name_length="";
			while ($ci!=255) {
				$name_length.=chr($ci);
				$ci=ord(fread($in_stream, 1));
			}
			$name_length=$this->uncompress($name_length);
			$name=gzuncompress(fread($in_stream, $name_length));
			$size="";
			$ci=ord(fread($in_stream, 1));
			while ($ci!=255) {
				$size.=chr($ci);
				$ci=ord(fread($in_stream, 1));
			}
			$size=$this->uncompress($size);
			$files[$name]=$size;
			$ci=ord(fread($in_stream, 1));
		}
		$this->mkdir($path);
		foreach ($files as $name=>$size) {
			$this->mkdir(dirname($path.$name));
			$fp=fopen($path.$name, "w+");
			if (!$fp) {
				throw new Exception("Could not create ".$path.$name);
			}
			while ($size>=100) {
				fwrite($fp, fread($in_stream, 100));
				$size-=100;
			}
			if ($size!=0) fwrite($fp, fread($in_stream, $size));
			fclose($fp);
		}
		fclose($in_stream);
	}
	public static function mkdir($path, $rights=0777) {
		if (file_exists($path)) return;
		$path=str_replace("\\", "/", $path);
		if (substr($path, strlen($path)-1)=="/") $path=substr($path, 0, strlen($path)-1);
		$prev=strrpos($path, "/");
		$prev=substr($path, 0, $prev);
		if (!file_exists($prev)) {
			self::mkdir($prev, $rights);
		}
		mkdir($path);
	}
	public static function uncompress($bytes) {
		$j=strlen($bytes)-1;
		$full=0;
		$c=-1;
		$i=0;
		$c=ord($bytes[0]);
		while ($c!=254 && $i!=$j) {
			$full+=$c;
			$i++;
			$c=ord($bytes[$i]);
		}
		$size=$full*253;
		$i++;
		while ($i<=$j) {
			$c=$bytes[$i];
			$size+=ord($c);
			$i++;
		}
		return $size;
	}
}

class CFAFile {
	private $filename;
	private $filelist=array();
	private $passsword;
	
	public function __construct($filename, $pw=null) {
		$this->filename=$filename;
		$this->password=$pw;
		if (file_exists($filename)) {
			$in_stream=fopen($filename, "r");
			$mode=fread($in_stream, 1);
			if ($mode=="c") {
			} elseif ($mode!="r") {
				throw new Exception("Invalid file given.");
			}
			$ci=ord(fread($in_stream, 1));
			$pos=0;
			$files=array();
			$buffer_size=2;
			while ($ci!=255) {
				$name_length="";
				while ($ci!=255) {
					$name_length.=chr($ci);
					$ci=ord(fread($in_stream, 1));
					$buffer_size++;
				}
				$name_length=$this->uncompress($name_length);
				$name=gzuncompress(fread($in_stream, $name_length));
				$buffer_size+=$name_length;
				$size="";
				$ci=ord(fread($in_stream, 1));
				$buffer_size++;
				while ($ci!=255) {
					$size.=chr($ci);
					$ci=ord(fread($in_stream, 1));
					$buffer_size++;
				}
				$size=$this->uncompress($size);
				$files[]=array(
					"name"=>$name,
					"size"=>$size,
					"pos"=>$pos
				);
				$pos+=$size;
				$ci=ord(fread($in_stream, 1));
				$buffer_size++;
			}
			fclose($in_stream);
			foreach($files as $info) {
				$this->filelist[]=new CFAEntry($info["name"], $filename, $info["size"], $info["pos"]+$buffer_size);
				$buffer_size+=$info["size"];
			}
		}
	}
	public function getFileList() {
		return $this->filelist;
	}
	public function remove($s_entry) {
		$found=false;
		foreach ($this->filelist as $k=>$entry) {
			if ($entry===$s_entry) {
				$found=true;
				unset($this->filelist[$k]);
			}
		}
		if ($found) $this->filelist=array_merge($this->filelist, array());
	}
	public function add($entry) {
		if (!$entry instanceof CFAEntry) return;
		$this->filelist[]=$entry;
	}
	public function flushToFile() {
		if ($this->password!=null) {
			$stream=tmpfile();
		} else {
			$stream=fopen($this->filename, "w+");
			fwrite($stream, "r");
		}
		foreach ($this->filelist as $entry) {
			$name=gzcompress($entry->getName());
			fwrite($stream, $this->compress(strlen($name)));
			fwrite($stream, chr(255));
			fwrite($stream, $name);
			fwrite($stream, $this->compress($entry->getSize()));
			fwrite($stream, chr(255));
		}
		fwrite($stream, chr(255));
		foreach ($this->filelist as $entry) {
			$handle=$entry->getFileHandle();
			$POS=ftell($handle);
			rewind($handle);
			while (!feof($handle)) {
				fwrite($stream, fread($handle, 1));
			}
			fseek($handle, $POS);
		}
	}
	
	public static function uncompress($bytes) {
		$j=strlen($bytes)-1;
		$full=0;
		$c=-1;
		$i=0;
		$c=ord($bytes[0]);
		while ($c!=254 && $i!=$j) {
			$full+=$c;
			$i++;
			$c=ord($bytes[$i]);
		}
		$size=$full*253;
		$i++;
		while ($i<=$j) {
			$c=$bytes[$i];
			$size+=ord($c);
			$i++;
		}
		return $size;
	}
	public static function compress($int) {
		$comp="";
		$full=0;
		while ($int>=253) {
			if ($full==253) {
				$comp.=chr(253);
				$full=0;
			}
			$full++;
			$int-=253;
		}
		if ($full!=0) $comp.=chr($full);
		$comp.=chr(254);
		if ($int!=0) $comp.=chr($int);
		return $comp;
	}
}
class CFAEntry {
	private $sourcefile="unknown";
	private $filename;
	private $size=-1;
	private $start="unknown";
	private $handle;
	// 1 - Existiert, 2 - Muss erstellt werden
	private $mode=-1;
	
	public function __construct($name, $sourcefile=null, $size=null, $start=null) {
		if ($sourcefile==null) {
			$this->filename=$name;
			$this->mode=2;
		} else {
			if (!file_exists($sourcefile)) {
				throw new Exception($sourcefile." not found.");
			}
			$this->sourcefile=$sourcefile;
			$this->filename=$name;
			$this->size=$size;
			$this->start=$start;
			$this->mode=1;
		}
	}
	public function __destruct() {
		if ($this->handle!=null) fclose($this->handle);
	}
	public function getSize() {
		if ($this->handle==null) {
			if ($this->size!=-1) return $this->size;
			return 0;
		} else {
			$info=fstat($this->handle);
			return $info["size"];
		}
	}
	public function getName() {
		return $this->filename;
	}
	public function getSourcefile() {
		return $this->sourcefile;
	}
	public function getFileHandle() {
		if ($this->handle==null) {
			$this->handle=tmpfile();
			if ($this->mode==1) {
				$nsize=(int) "".$this->size;
				$sf_stream=fopen($this->sourcefile, "r");
				fseek($sf_stream, $this->start);
				while ($nsize>=100) {
					fwrite($this->handle, fread($sf_stream, 100));
					$nsize-=100;
				}
				if ($nsize!=0) fwrite($this->handle, fread($sf_stream, $nsize));
				fclose($sf_stream);
				rewind($this->handle);
			}
		}
		return $this->handle;
	}
}
?>