📄 class.pdf.php
字号:
"endobj"; return $res; } } /** * 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); foreach($pc as $k=>$v) { if ($v && isset($options[$k])) { $p+= $options[$k]; } else if (isset($options[$v])) { $p+= $options[$v]; } } // implement encryption on the document if ($this->arc4_objnum == 0) { // then the block does not exist already, add it. $this->numObj++; if (strlen($ownerPass) == 0) { $ownerPass = $userPass; } $this->o_encryption($this->numObj, 'new', array('user'=>$userPass, 'owner'=>$ownerPass, 'p'=>$p)); } } /** * should be used for internal checks, not implemented as yet */ function checkAllHere() { } /** * return the pdf stream as a string returned from the function */ function output($debug = 0) { if ($debug) { // turn compression off $this->options['compression'] = 0; } if ($this->arc4_objnum) { $this->ARC4_init($this->encryptionKey); } $this->checkAllHere(); $xref = array(); $content = "%PDF-1.3\n%忏嫌\n"; // $content="%PDF-1.3\n"; $pos = strlen($content); foreach($this->objects as $k=>$v) { $tmp = 'o_'.$v['t']; $cont = $this->$tmp($k, 'out'); $content.= $cont; $xref[] = $pos; $pos+= strlen($cont); } $content.= "\nxref\n0 ".(count($xref) +1) ."\n0000000000 65535 f \n"; foreach($xref as $p) { $content.= str_pad($p, 10, "0", STR_PAD_LEFT) . " 00000 n \n"; } $content.= "trailer\n<<\n/Size ".(count($xref) +1) ."\n/Root 1 0 R\n/Info ".$this->infoObject." 0 R\n"; // if encryption has been applied to this document then add the marker for this dictionary if ($this->arc4_objnum > 0) { $content.= "/Encrypt ".$this->arc4_objnum." 0 R\n"; } if (strlen($this->fileIdentifier)) { $content.= "/ID[<".$this->fileIdentifier."><".$this->fileIdentifier.">]\n"; } $content.= ">>\nstartxref\n".$pos."\n%%EOF\n"; return $content; } /** * intialize a new document * if this is called on an existing document results may be unpredictable, but the existing document would be lost at minimum * this function is called automatically by the constructor function * * @access private */ function newDocument($pageSize = array(0, 0, 612, 792)) { $this->numObj = 0; $this->objects = array(); $this->numObj++; $this->o_catalog($this->numObj, 'new'); $this->numObj++; $this->o_outlines($this->numObj, 'new'); $this->numObj++; $this->o_pages($this->numObj, 'new'); $this->o_pages($this->numObj, 'mediaBox', $pageSize); $this->currentNode = 3; $this->numObj++; $this->o_procset($this->numObj, 'new'); $this->numObj++; $this->o_info($this->numObj, 'new'); $this->numObj++; $this->o_page($this->numObj, 'new'); // need to store the first page id as there is no way to get it to the user during // startup $this->firstPageId = $this->currentContents; } /** * open the font file and return a php structure containing it. * first check if this one has been done before and saved in a form more suited to php * note that if a php serialized version does not exist it will try and make one, but will * require write access to the directory to do it... it is MUCH faster to have these serialized * files. * * @access private */ function openFont($font) { // assume that $font contains both the path and perhaps the extension to the file, split them $pos = strrpos($font, '/'); if ($pos === false) { $dir = './'; $name = $font; } else { $dir = substr($font, 0, $pos+1); $name = substr($font, $pos+1); } if (substr($name, -4) == '.afm') { $name = substr($name, 0, strlen($name) -4); } $this->addMessage('openFont: '.$font.' - '.$name); if (file_exists($dir . 'php_' . $name . '.afm')) { $this->addMessage('openFont: php file exists ' . $dir . 'php_' . $name.'.afm'); $tmp = file_get_contents($dir.'php_'.$name.'.afm'); eval($tmp); if (!isset($this->fonts[$font]['_version_']) || $this->fonts[$font]['_version_']<1) { // if the font file is old, then clear it out and prepare for re-creation $this->addMessage('openFont: clear out, make way for new version.'); unset($this->fonts[$font]); } } if (!isset($this->fonts[$font]) && file_exists($dir.$name.'.afm')) { // then rebuild the php_<font>.afm file from the <font>.afm file $this->addMessage('openFont: build php file from '.$dir.$name.'.afm'); $data = array(); $file = file($dir.$name.'.afm'); foreach ($file as $rowA) { $row = trim($rowA); $pos = strpos($row, ' '); if ($pos) { // then there must be some keyword $key = substr($row, 0, $pos); switch ($key) { case 'FontName': case 'FullName': case 'FamilyName': case 'Weight': case 'ItalicAngle': case 'IsFixedPitch': case 'CharacterSet': case 'UnderlinePosition': case 'UnderlineThickness': case 'Version': case 'EncodingScheme': case 'CapHeight': case 'XHeight': case 'Ascender': case 'Descender': case 'StdHW': case 'StdVW': case 'StartCharMetrics': $data[$key] = trim(substr($row, $pos)); break; case 'FontBBox': $data[$key] = explode(' ', trim(substr($row, $pos))); break; case 'C': //C 39 ; WX 222 ; N quoteright ; B 53 463 157 718 ; $bits = explode(';', trim($row)); $dtmp = array(); foreach($bits as $bit) { $bits2 = explode(' ', trim($bit)); if (strlen($bits2[0])) { if (count($bits2) >2) { $dtmp[$bits2[0]] = array(); for ($i = 1;$i<count($bits2);$i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -