This script allows to protect the PDF, that is to say prevent people from copying its content, print it or modify it.
Author: Klemen Vodopivec
License: Freeware
SetProtection([array permissions [, string user_pass [, string owner_pass]]])
permissions: the set of permissions. Empty by default (only viewing is allowed).
user_pass: user password. Empty by default.
owner_pass: owner password. If not specified, a random value is used.
The permission array is composed of values taken from the following ones:
* copy: copy text and images to the clipboard
* print: print the document
* modify: modify it (except for annotations and forms)
* annot-forms: add annotations and forms
Remark: the protection against modification is for people who have the full Acrobat product.
If you don’t set any password, the document will open as usual. If you set a user password, the PDF viewer will ask for it before displaying the document. The master password, if different from the user one, can be used to get full access.
Note: protecting a document requires to encrypt it, which increases the processing time a lot. This can cause a PHP time-out in some cases, especially if the document contains images or fonts.
Source
encrypted=false;
$this->last_rc4_key='';
$this->padding="x28xBFx4Ex5Ex4Ex75x8Ax41x64x00x4Ex56xFFxFAx01x08".
"x2Ex2Ex00xB6xD0x68x3Ex80x2Fx0CxA9xFEx64x53x69x7A";
}
/**
* Function to set permissions as well as user and owner passwords
*
* - permissions is an array with values taken from the following list:
* copy, print, modify, annot-forms
* If a value is present it means that the permission is granted
* - If a user password is set, user will be prompted before document is opened
* - If an owner password is set, document can be opened in privilege mode with no
* restriction if that password is entered
*/
function SetProtection($permissions=array(),$user_pass='',$owner_pass=null)
{
$options = array('print' => 4, 'modify' => 8, 'copy' => 16, 'annot-forms' => 32 );
$protection = 192;
foreach($permissions as $permission){
if (!isset($options[$permission]))
$this->Error('Incorrect permission: '.$permission);
$protection += $options[$permission];
}
if ($owner_pass === null)
$owner_pass = uniqid(rand());
$this->encrypted = true;
$this->_generateencryptionkey($user_pass, $owner_pass, $protection);
}
/****************************************************************************
* *
* Private methods *
* *
****************************************************************************/
function _putstream($s)
{
if ($this->encrypted) {
$s = $this->_RC4($this->_objectkey($this->n), $s);
}
parent::_putstream($s);
}
function _textstring($s)
{
if ($this->encrypted) {
$s = $this->_RC4($this->_objectkey($this->n), $s);
}
return parent::_textstring($s);
}
/**
* Compute key depending on object number where the encrypted data is stored
*/
function _objectkey($n)
{
return substr($this->_md5_16($this->encryption_key.pack('VXxx',$n)),0,10);
}
/**
* Escape special characters
*/
function _escape($s)
{
$s=str_replace('','',$s);
$s=str_replace(')',')',$s);
$s=str_replace('(','(',$s);
$s=str_replace("r",'r',$s);
return $s;
}
function _putresources()
{
parent::_putresources();
if ($this->encrypted) {
$this->_newobj();
$this->enc_obj_id = $this->n;
$this->_out('<_putencryption();
$this->_out('>>');
$this->_out('endobj');
}
}
function _putencryption()
{
$this->_out('/Filter /Standard');
$this->_out('/V 1');
$this->_out('/R 2');
$this->_out('/O ('.$this->_escape($this->Ovalue).')');
$this->_out('/U ('.$this->_escape($this->Uvalue).')');
$this->_out('/P '.$this->Pvalue);
}
function _puttrailer()
{
parent::_puttrailer();
if ($this->encrypted) {
$this->_out('/Encrypt '.$this->enc_obj_id.' 0 R');
$this->_out('/ID [()()]');
}
}
/**
* RC4 is the standard encryption algorithm used in PDF format
*/
function _RC4($key, $text)
{
if ($this->last_rc4_key != $key) {
$k = str_repeat($key, 256/strlen($key)+1);
$rc4 = range(0,255);
$j = 0;
for ($i=0; $ilast_rc4_key = $key;
$this->last_rc4_key_c = $rc4;
} else {
$rc4 = $this->last_rc4_key_c;
}
$len = strlen($text);
$a = 0;
$b = 0;
$out = '';
for ($i=0; $i_md5_16($owner_pass);
$owner_RC4_key = substr($tmp,0,5);
return $this->_RC4($owner_RC4_key, $user_pass);
}
/**
* Compute U value
*/
function _Uvalue()
{
return $this->_RC4($this->encryption_key, $this->padding);
}
/**
* Compute encryption key
*/
function _generateencryptionkey($user_pass, $owner_pass, $protection)
{
// Pad passwords
$user_pass = substr($user_pass.$this->padding,0,32);
$owner_pass = substr($owner_pass.$this->padding,0,32);
// Compute O value
$this->Ovalue = $this->_Ovalue($user_pass,$owner_pass);
// Compute encyption key
$tmp = $this->_md5_16($user_pass.$this->Ovalue.chr($protection)."xFFxFFxFF");
$this->encryption_key = substr($tmp,0,5);
// Compute U value
$this->Uvalue = $this->_Uvalue();
// Compute P value
$this->Pvalue = -(($protection^255)+1);
}
}
?>
Example
This example shows how to allow only printing.
SetProtection(array('print'));
$pdf->Open();
$pdf->AddPage();
$pdf->SetFont('Arial');
$pdf->Write(10,'You can print me but not copy my text.');
$pdf->Output();
?>