File indexing completed on 2025-01-19 05:21:21

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Pdf
0017  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0018  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0019  * @version    $Id$
0020  */
0021 
0022 
0023 /** Zend_Pdf_Element */
0024 // require_once 'Zend/Pdf/Element.php';
0025 
0026 /**
0027  * PDF file 'string' element implementation
0028  *
0029  * @category   Zend
0030  * @package    Zend_Pdf
0031  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0032  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0033  */
0034 class Zend_Pdf_Element_String extends Zend_Pdf_Element
0035 {
0036     /**
0037      * Object value
0038      *
0039      * @var string
0040      */
0041     public $value;
0042 
0043     /**
0044      * Object constructor
0045      *
0046      * @param string $val
0047      */
0048     public function __construct($val)
0049     {
0050         $this->value   = (string)$val;
0051     }
0052 
0053 
0054     /**
0055      * Return type of the element.
0056      *
0057      * @return integer
0058      */
0059     public function getType()
0060     {
0061         return Zend_Pdf_Element::TYPE_STRING;
0062     }
0063 
0064 
0065     /**
0066      * Return object as string
0067      *
0068      * @param Zend_Pdf_Factory $factory
0069      * @return string
0070      */
0071     public function toString($factory = null)
0072     {
0073         return '(' . self::escape((string)$this->value) . ')';
0074     }
0075 
0076 
0077     /**
0078      * Escape string according to the PDF rules
0079      *
0080      * @param string $str
0081      * @return string
0082      */
0083     public static function escape($str)
0084     {
0085         $outEntries = array();
0086 
0087         foreach (str_split($str, 128) as $chunk) {
0088             // Collect sequence of unescaped characters
0089             $offset = strcspn($chunk, "\n\r\t\x08\x0C()\\");
0090             $chunkOut = substr($chunk, 0, $offset);
0091 
0092             while ($offset < strlen($chunk)) {
0093                 $nextCode = ord($chunk[$offset++]);
0094                 switch ($nextCode) {
0095                     // "\n" - line feed (LF)
0096                     case 10:
0097                         $chunkOut .= '\\n';
0098                         break;
0099 
0100                     // "\r" - carriage return (CR)
0101                     case 13:
0102                         $chunkOut .= '\\r';
0103                         break;
0104 
0105                     // "\t" - horizontal tab (HT)
0106                     case 9:
0107                         $chunkOut .= '\\t';
0108                         break;
0109 
0110                     // "\b" - backspace (BS)
0111                     case 8:
0112                         $chunkOut .= '\\b';
0113                         break;
0114 
0115                     // "\f" - form feed (FF)
0116                     case 12:
0117                         $chunkOut .= '\\f';
0118                         break;
0119 
0120                     // '(' - left paranthesis
0121                     case 40:
0122                         $chunkOut .= '\\(';
0123                         break;
0124 
0125                     // ')' - right paranthesis
0126                     case 41:
0127                         $chunkOut .= '\\)';
0128                         break;
0129 
0130                     // '\' - backslash
0131                     case 92:
0132                         $chunkOut .= '\\\\';
0133                         break;
0134 
0135                     default:
0136                         // This code is never executed extually
0137                         //
0138                         // Don't use non-ASCII characters escaping
0139                         // if ($nextCode >= 32 && $nextCode <= 126 ) {
0140                         //     // Visible ASCII symbol
0141                         //     $chunkEntries[] = chr($nextCode);
0142                         // } else {
0143                         //     $chunkEntries[] = sprintf('\\%03o', $nextCode);
0144                         // }
0145 
0146                         break;
0147                 }
0148 
0149                 // Collect sequence of unescaped characters
0150                 $start = $offset;
0151                 $offset += strcspn($chunk, "\n\r\t\x08\x0C()\\", $offset);
0152                 $chunkOut .= substr($chunk, $start, $offset - $start);
0153             }
0154 
0155             $outEntries[] = $chunkOut;
0156         }
0157 
0158         return implode("\\\n", $outEntries);
0159     }
0160 
0161 
0162     /**
0163      * Unescape string according to the PDF rules
0164      *
0165      * @param string $str
0166      * @return string
0167      */
0168     public static function unescape($str)
0169     {
0170         $outEntries = array();
0171 
0172         $offset = 0;
0173         while ($offset < strlen($str)) {
0174             // Searche for the next escaped character/sequence
0175             $escapeCharOffset = strpos($str, '\\', $offset);
0176             if ($escapeCharOffset === false  ||  $escapeCharOffset == strlen($str) - 1) {
0177                 // There are no escaped characters or '\' char has came at the end of string
0178                 $outEntries[] = substr($str, $offset);
0179                 break;
0180             } else {
0181                 // Collect unescaped characters sequence
0182                 $outEntries[] = substr($str, $offset, $escapeCharOffset - $offset);
0183                 // Go to the escaped character
0184                 $offset = $escapeCharOffset + 1;
0185 
0186                 switch ($str[$offset]) {
0187                     // '\\n' - line feed (LF)
0188                     case 'n':
0189                         $outEntries[] = "\n";
0190                         break;
0191 
0192                     // '\\r' - carriage return (CR)
0193                     case 'r':
0194                         $outEntries[] = "\r";
0195                         break;
0196 
0197                     // '\\t' - horizontal tab (HT)
0198                     case 't':
0199                         $outEntries[] = "\t";
0200                         break;
0201 
0202                     // '\\b' - backspace (BS)
0203                     case 'b':
0204                         $outEntries[] = "\x08";
0205                         break;
0206 
0207                     // '\\f' - form feed (FF)
0208                     case 'f':
0209                         $outEntries[] = "\x0C";
0210                         break;
0211 
0212                     // '\\(' - left paranthesis
0213                     case '(':
0214                         $outEntries[] = '(';
0215                         break;
0216 
0217                     // '\\)' - right paranthesis
0218                     case ')':
0219                         $outEntries[] = ')';
0220                         break;
0221 
0222                     // '\\\\' - backslash
0223                     case '\\':
0224                         $outEntries[] = '\\';
0225                         break;
0226 
0227                     // "\\\n" or "\\\n\r"
0228                     case "\n":
0229                         // skip new line symbol
0230                         if ($str[$offset + 1] == "\r") {
0231                             $offset++;
0232                         }
0233                         break;
0234 
0235                     default:
0236                         if (strpos('0123456789', $str[$offset]) !== false) {
0237                             // Character in octal representation
0238                             // '\\xxx'
0239                             $nextCode = '0' . $str[$offset];
0240 
0241                             if (strpos('0123456789', $str[$offset + 1]) !== false) {
0242                                 $nextCode .= $str[++$offset];
0243 
0244                                 if (strpos('0123456789', $str[$offset + 1]) !== false) {
0245                                     $nextCode .= $str[++$offset];
0246                                 }
0247                             }
0248 
0249                             $outEntries[] = chr(octdec($nextCode));
0250                         } else {
0251                             $outEntries[] = $str[$offset];
0252                         }
0253                         break;
0254                 }
0255 
0256                 $offset++;
0257             }
0258         }
0259 
0260         return implode($outEntries);
0261     }
0262 
0263 }