📄 class.pdf.php
字号:
break;
case 'out':
$res="\n".$id." 0 obj\n<< /Type /Annot";
switch($o['info']['type']){
case 'link':
case 'ilink':
$res.= "\n/Subtype /Link";
break;
}
$res.="\n/A ".$o['info']['actionId']." 0 R";
$res.="\n/Border [0 0 0]";
$res.="\n/H /I";
$res.="\n/Rect [ ";
foreach($o['info']['rect'] as $v){
$res.= sprintf("%.4f ",$v);
}
$res.="]";
$res.="\n>>\nendobj";
return $res;
break;
}
}
/**
* a page object, it also creates a contents object to hold its contents
*/
function o_page($id,$action,$options=''){
if ($action!='new'){
$o =& $this->objects[$id];
}
switch ($action){
case 'new':
$this->numPages++;
$this->objects[$id]=array('t'=>'page','info'=>array('parent'=>$this->currentNode,'pageNum'=>$this->numPages));
if (is_array($options)){
// then this must be a page insertion, array shoudl contain 'rid','pos'=[before|after]
$options['id']=$id;
$this->o_pages($this->currentNode,'page',$options);
} else {
$this->o_pages($this->currentNode,'page',$id);
}
$this->currentPage=$id;
//make a contents object to go with this page
$this->numObj++;
$this->o_contents($this->numObj,'new',$id);
$this->currentContents=$this->numObj;
$this->objects[$id]['info']['contents']=array();
$this->objects[$id]['info']['contents'][]=$this->numObj;
$match = ($this->numPages%2 ? 'odd' : 'even');
foreach($this->addLooseObjects as $oId=>$target){
if ($target=='all' || $match==$target){
$this->objects[$id]['info']['contents'][]=$oId;
}
}
break;
case 'content':
$o['info']['contents'][]=$options;
break;
case 'annot':
// add an annotation to this page
if (!isset($o['info']['annot'])){
$o['info']['annot']=array();
}
// $options should contain the id of the annotation dictionary
$o['info']['annot'][]=$options;
break;
case 'out':
$res="\n".$id." 0 obj\n<< /Type /Page";
$res.="\n/Parent ".$o['info']['parent']." 0 R";
if (isset($o['info']['annot'])){
$res.="\n/Annots [";
foreach($o['info']['annot'] as $aId){
$res.=" ".$aId." 0 R";
}
$res.=" ]";
}
$count = count($o['info']['contents']);
if ($count==1){
$res.="\n/Contents ".$o['info']['contents'][0]." 0 R";
} else if ($count>1){
$res.="\n/Contents [\n";
foreach ($o['info']['contents'] as $cId){
$res.=$cId." 0 R\n";
}
$res.="]";
}
$res.="\n>>\nendobj";
return $res;
break;
}
}
/**
* the contents objects hold all of the content which appears on pages
*/
function o_contents($id,$action,$options=''){
if ($action!='new'){
$o =& $this->objects[$id];
}
switch ($action){
case 'new':
$this->objects[$id]=array('t'=>'contents','c'=>'','info'=>array());
if (strlen($options) && intval($options)){
// then this contents is the primary for a page
$this->objects[$id]['onPage']=$options;
} else if ($options=='raw'){
// then this page contains some other type of system object
$this->objects[$id]['raw']=1;
}
break;
case 'add':
// add more options to the decleration
foreach ($options as $k=>$v){
$o['info'][$k]=$v;
}
case 'out':
$tmp=$o['c'];
$res= "\n".$id." 0 obj\n";
if (isset($this->objects[$id]['raw'])){
$res.=$tmp;
} else {
$res.= "<<";
if (function_exists('gzcompress') && $this->options['compression']){
// then implement ZLIB based compression on this content stream
$res.=" /Filter /FlateDecode";
$tmp = gzcompress($tmp);
}
if ($this->encrypted){
$this->encryptInit($id);
$tmp = $this->ARC4($tmp);
}
foreach($o['info'] as $k=>$v){
$res .= "\n/".$k.' '.$v;
}
$res.="\n/Length ".strlen($tmp)." >>\nstream\n".$tmp."\nendstream";
}
$res.="\nendobj\n";
return $res;
break;
}
}
/**
* an image object, will be an XObject in the document, includes description and data
*/
function o_image($id,$action,$options=''){
if ($action!='new'){
$o =& $this->objects[$id];
}
switch($action){
case 'new':
// make the new object
$this->objects[$id]=array('t'=>'image','data'=>$options['data'],'info'=>array());
$this->objects[$id]['info']['Type']='/XObject';
$this->objects[$id]['info']['Subtype']='/Image';
$this->objects[$id]['info']['Width']=$options['iw'];
$this->objects[$id]['info']['Height']=$options['ih'];
if (!isset($options['type']) || $options['type']=='jpg'){
if (!isset($options['channels'])){
$options['channels']=3;
}
switch($options['channels']){
case 1:
$this->objects[$id]['info']['ColorSpace']='/DeviceGray';
break;
default:
$this->objects[$id]['info']['ColorSpace']='/DeviceRGB';
break;
}
$this->objects[$id]['info']['Filter']='/DCTDecode';
$this->objects[$id]['info']['BitsPerComponent']=8;
} else if ($options['type']=='png'){
$this->objects[$id]['info']['Filter']='/FlateDecode';
$this->objects[$id]['info']['DecodeParms']='<< /Predictor 15 /Colors '.$options['ncolor'].' /Columns '.$options['iw'].' /BitsPerComponent '.$options['bitsPerComponent'].'>>';
if (strlen($options['pdata'])){
$tmp = ' [ /Indexed /DeviceRGB '.(strlen($options['pdata'])/3-1).' ';
$this->numObj++;
$this->o_contents($this->numObj,'new');
$this->objects[$this->numObj]['c']=$options['pdata'];
$tmp.=$this->numObj.' 0 R';
$tmp .=' ]';
$this->objects[$id]['info']['ColorSpace'] = $tmp;
if (isset($options['transparency'])){
switch($options['transparency']['type']){
case 'indexed':
$tmp=' [ '.$options['transparency']['data'].' '.$options['transparency']['data'].'] ';
$this->objects[$id]['info']['Mask'] = $tmp;
break;
}
}
} else {
$this->objects[$id]['info']['ColorSpace']='/'.$options['color'];
}
$this->objects[$id]['info']['BitsPerComponent']=$options['bitsPerComponent'];
}
// assign it a place in the named resource dictionary as an external object, according to
// the label passed in with it.
$this->o_pages($this->currentNode,'xObject',array('label'=>$options['label'],'objNum'=>$id));
// also make sure that we have the right procset object for it.
$this->o_procset($this->procsetObjectId,'add','ImageC');
break;
case 'out':
$tmp=$o['data'];
$res= "\n".$id." 0 obj\n<<";
foreach($o['info'] as $k=>$v){
$res.="\n/".$k.' '.$v;
}
if ($this->encrypted){
$this->encryptInit($id);
$tmp = $this->ARC4($tmp);
}
$res.="\n/Length ".strlen($tmp)." >>\nstream\n".$tmp."\nendstream\nendobj\n";
return $res;
break;
}
}
/**
* encryption object.
*/
function o_encryption($id,$action,$options=''){
if ($action!='new'){
$o =& $this->objects[$id];
}
switch($action){
case 'new':
// make the new object
$this->objects[$id]=array('t'=>'encryption','info'=>$options);
$this->arc4_objnum=$id;
// figure out the additional paramaters required
$pad = chr(0x28).chr(0xBF).chr(0x4E).chr(0x5E).chr(0x4E).chr(0x75).chr(0x8A).chr(0x41).chr(0x64).chr(0x00).chr(0x4E).chr(0x56).chr(0xFF).chr(0xFA).chr(0x01).chr(0x08).chr(0x2E).chr(0x2E).chr(0x00).chr(0xB6).chr(0xD0).chr(0x68).chr(0x3E).chr(0x80).chr(0x2F).chr(0x0C).chr(0xA9).chr(0xFE).chr(0x64).chr(0x53).chr(0x69).chr(0x7A);
$len = strlen($options['owner']);
if ($len>32){
$owner = substr($options['owner'],0,32);
} else if ($len<32){
$owner = $options['owner'].substr($pad,0,32-$len);
} else {
$owner = $options['owner'];
}
$len = strlen($options['user']);
if ($len>32){
$user = substr($options['user'],0,32);
} else if ($len<32){
$user = $options['user'].substr($pad,0,32-$len);
} else {
$user = $options['user'];
}
$tmp = $this->md5_16($owner);
$okey = substr($tmp,0,5);
$this->ARC4_init($okey);
$ovalue=$this->ARC4($user);
$this->objects[$id]['info']['O']=$ovalue;
// now make the u value, phew.
$tmp = $this->md5_16($user.$ovalue.chr($options['p']).chr(255).chr(255).chr(255).$this->fileIdentifier);
$ukey = substr($tmp,0,5);
$this->ARC4_init($ukey);
$this->encryptionKey = $ukey;
$this->encrypted=1;
$uvalue=$this->ARC4($pad);
$this->objects[$id]['info']['U']=$uvalue;
$this->encryptionKey=$ukey;
// initialize the arc4 array
break;
case 'out':
$res= "\n".$id." 0 obj\n<<";
$res.="\n/Filter /Standard";
$res.="\n/V 1";
$res.="\n/R 2";
$res.="\n/O (".$this->filterText($o['info']['O']).')';
$res.="\n/U (".$this->filterText($o['info']['U']).')';
// and the p-value needs to be converted to account for the twos-complement approach
$o['info']['p'] = (($o['info']['p']^255)+1)*-1;
$res.="\n/P ".($o['info']['p']);
$res.="\n>>\nendobj\n";
return $res;
break;
}
}
/**
* ARC4 functions
* A series of function to implement ARC4 encoding in PHP
*/
/**
* calculate the 16 byte version of the 128 bit md5 digest of the string
*/
function md5_16($string){
$tmp = md5($string);
$out='';
for ($i=0;$i<=30;$i=$i+2){
$out.=chr(hexdec(substr($tmp,$i,2)));
}
return $out;
}
/**
* initialize the encryption for processing a particular object
*/
function encryptInit($id){
$tmp = $this->encryptionKey;
$hex = dechex($id);
if (strlen($hex)<6){
$hex = substr('000000',0,6-strlen($hex)).$hex;
}
$tmp.= chr(hexdec(substr($hex,4,2))).chr(hexdec(substr($hex,2,2))).chr(hexdec(substr($hex,0,2))).chr(0).chr(0);
$key = $this->md5_16($tmp);
$this->ARC4_init(substr($key,0,10));
}
/**
* initialize the ARC4 encryption
*/
function ARC4_init($key=''){
$this->arc4 = '';
// setup the control array
if (strlen($key)==0){
return;
}
$k = '';
while(strlen($k)<256){
$k.=$key;
}
$k=substr($k,0,256);
for ($i=0;$i<256;$i++){
$this->arc4 .= chr($i);
}
$j=0;
for ($i=0;$i<256;$i++){
$t = $this->arc4[$i];
$j = ($j + ord($t) + ord($k[$i]))%256;
$this->arc4[$i]=$this->arc4[$j];
$this->arc4[$j]=$t;
}
}
/**
* ARC4 encrypt a text string
*/
function ARC4($text){
$len=strlen($text);
$a=0;
$b=0;
$c = $this->arc4;
$out='';
for ($i=0;$i<$len;$i++){
$a = ($a+1)%256;
$t= $c[$a];
$b = ($b+ord($t))%256;
$c[$a]=$c[$b];
$c[$b]=$t;
$k = ord($c[(ord($c[$a])+ord($c[$b]))%256]);
$out.=chr(ord($text[$i]) ^ $k);
}
return $out;
}
/**
* functions which can be called to adjust or add to the document
*/
/**
* add a link in the document to an external URL
*/
function addLink($url,$x0,$y0,$x1,$y1){
$this->numObj++;
$info = array('type'=>'link','url'=>$url,'rect'=>array($x0,$y0,$x1,$y1));
$this->o_annotation($this->numObj,'new',$info);
}
/**
* add a link in the document to an internal destination (ie. within the document)
*/
function addInternalLink($label,$x0,$y0,$x1,$y1){
$this->numObj++;
$info = array('type'=>'ilink','label'=>$label,'rect'=>array($x0,$y0,$x1,$y1));
$this->o_annotation($this->numObj,'new',$info);
}
/**
* set the encryption of the document
* can be used to turn it on and/or set the passwords which it will have.
* also the functions that the user will have are set here, such as print, modify, add
*/
function setEncryption($userPass='',$ownerPass='',$pc=array()){
$p=bindec(11000000);
$options = array(
'print'=>4
,'modify'=>8
,'copy'=>16
,'add'=>32
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -