You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
7.7 KiB

<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Pdf
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/** Zend_Pdf_Element */
// require_once 'Zend/Pdf/Element.php';
/**
* PDF file 'string' element implementation
*
* @category Zend
* @package Zend_Pdf
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Pdf_Element_String extends Zend_Pdf_Element
{
/**
* Object value
*
* @var string
*/
public $value;
/**
* Object constructor
*
* @param string $val
*/
public function __construct($val)
{
$this->value = (string)$val;
}
/**
* Return type of the element.
*
* @return integer
*/
public function getType()
{
return Zend_Pdf_Element::TYPE_STRING;
}
/**
* Return object as string
*
* @param Zend_Pdf_Factory $factory
* @return string
*/
public function toString($factory = null)
{
return '(' . self::escape((string)$this->value) . ')';
}
/**
* Escape string according to the PDF rules
*
* @param string $str
* @return string
*/
public static function escape($str)
{
$outEntries = array();
foreach (str_split($str, 128) as $chunk) {
// Collect sequence of unescaped characters
$offset = strcspn($chunk, "\n\r\t\x08\x0C()\\");
$chunkOut = substr($chunk, 0, $offset);
while ($offset < strlen($chunk)) {
$nextCode = ord($chunk[$offset++]);
switch ($nextCode) {
// "\n" - line feed (LF)
case 10:
$chunkOut .= '\\n';
break;
// "\r" - carriage return (CR)
case 13:
$chunkOut .= '\\r';
break;
// "\t" - horizontal tab (HT)
case 9:
$chunkOut .= '\\t';
break;
// "\b" - backspace (BS)
case 8:
$chunkOut .= '\\b';
break;
// "\f" - form feed (FF)
case 12:
$chunkOut .= '\\f';
break;
// '(' - left paranthesis
case 40:
$chunkOut .= '\\(';
break;
// ')' - right paranthesis
case 41:
$chunkOut .= '\\)';
break;
// '\' - backslash
case 92:
$chunkOut .= '\\\\';
break;
default:
// This code is never executed extually
//
// Don't use non-ASCII characters escaping
// if ($nextCode >= 32 && $nextCode <= 126 ) {
// // Visible ASCII symbol
// $chunkEntries[] = chr($nextCode);
// } else {
// $chunkEntries[] = sprintf('\\%03o', $nextCode);
// }
break;
}
// Collect sequence of unescaped characters
$start = $offset;
$offset += strcspn($chunk, "\n\r\t\x08\x0C()\\", $offset);
$chunkOut .= substr($chunk, $start, $offset - $start);
}
$outEntries[] = $chunkOut;
}
return implode("\\\n", $outEntries);
}
/**
* Unescape string according to the PDF rules
*
* @param string $str
* @return string
*/
public static function unescape($str)
{
$outEntries = array();
$offset = 0;
while ($offset < strlen($str)) {
// Searche for the next escaped character/sequence
$escapeCharOffset = strpos($str, '\\', $offset);
if ($escapeCharOffset === false || $escapeCharOffset == strlen($str) - 1) {
// There are no escaped characters or '\' char has came at the end of string
$outEntries[] = substr($str, $offset);
break;
} else {
// Collect unescaped characters sequence
$outEntries[] = substr($str, $offset, $escapeCharOffset - $offset);
// Go to the escaped character
$offset = $escapeCharOffset + 1;
switch ($str[$offset]) {
// '\\n' - line feed (LF)
case 'n':
$outEntries[] = "\n";
break;
// '\\r' - carriage return (CR)
case 'r':
$outEntries[] = "\r";
break;
// '\\t' - horizontal tab (HT)
case 't':
$outEntries[] = "\t";
break;
// '\\b' - backspace (BS)
case 'b':
$outEntries[] = "\x08";
break;
// '\\f' - form feed (FF)
case 'f':
$outEntries[] = "\x0C";
break;
// '\\(' - left paranthesis
case '(':
$outEntries[] = '(';
break;
// '\\)' - right paranthesis
case ')':
$outEntries[] = ')';
break;
// '\\\\' - backslash
case '\\':
$outEntries[] = '\\';
break;
// "\\\n" or "\\\n\r"
case "\n":
// skip new line symbol
if ($str[$offset + 1] == "\r") {
$offset++;
}
break;
default:
if (strpos('0123456789', $str[$offset]) !== false) {
// Character in octal representation
// '\\xxx'
$nextCode = '0' . $str[$offset];
if (strpos('0123456789', $str[$offset + 1]) !== false) {
$nextCode .= $str[++$offset];
if (strpos('0123456789', $str[$offset + 1]) !== false) {
$nextCode .= $str[++$offset];
}
}
$outEntries[] = chr(octdec($nextCode));
} else {
$outEntries[] = $str[$offset];
}
break;
}
$offset++;
}
}
return implode($outEntries);
}
}