Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

   1  <?php
   2  /**
   3   * This file is part of FPDI
   4   *
   5   * @package   setasign\Fpdi
   6   * @copyright Copyright (c) 2019 Setasign - Jan Slabon (https://www.setasign.com)
   7   * @license   http://opensource.org/licenses/mit-license The MIT License
   8   */
   9  
  10  namespace setasign\Fpdi\PdfParser\Type;
  11  
  12  use setasign\Fpdi\PdfParser\StreamReader;
  13  
  14  /**
  15   * Class representing a PDF string object
  16   *
  17   * @package setasign\Fpdi\PdfParser\Type
  18   */
  19  class PdfString extends PdfType
  20  {
  21      /**
  22       * Parses a string object from the stream reader.
  23       *
  24       * @param StreamReader $streamReader
  25       * @return self
  26       */
  27      public static function parse(StreamReader $streamReader)
  28      {
  29          $pos = $startPos = $streamReader->getOffset();
  30          $openBrackets = 1;
  31          do {
  32              $buffer = $streamReader->getBuffer(false);
  33              for ($length = \strlen($buffer); $openBrackets !== 0 && $pos < $length; $pos++) {
  34                  switch ($buffer[$pos]) {
  35                      case '(':
  36                          $openBrackets++;
  37                          break;
  38                      case ')':
  39                          $openBrackets--;
  40                          break;
  41                      case '\\':
  42                          $pos++;
  43                  }
  44              }
  45          } while ($openBrackets !== 0 && $streamReader->increaseLength());
  46  
  47          $result = \substr($buffer, $startPos, $openBrackets + $pos - $startPos - 1);
  48          $streamReader->setOffset($pos);
  49  
  50          $v = new self;
  51          $v->value = $result;
  52  
  53          return $v;
  54      }
  55  
  56      /**
  57       * Helper method to create an instance.
  58       *
  59       * @param string $value The string needs to be escaped accordingly.
  60       * @return self
  61       */
  62      public static function create($value)
  63      {
  64          $v = new self;
  65          $v->value = $value;
  66  
  67          return $v;
  68      }
  69  
  70      /**
  71       * Ensures that the passed value is a PdfString instance.
  72       *
  73       * @param mixed $string
  74       * @return self
  75       * @throws PdfTypeException
  76       */
  77      public static function ensure($string)
  78      {
  79          return PdfType::ensureType(self::class, $string, 'String value expected.');
  80      }
  81  
  82      /**
  83       * Unescapes escaped sequences in a PDF string according to the PDF specification.
  84       *
  85       * @param string $s
  86       * @return string
  87       */
  88      public static function unescape($s)
  89      {
  90          $out = '';
  91          /** @noinspection ForeachInvariantsInspection */
  92          for ($count = 0, $n = \strlen($s); $count < $n; $count++) {
  93              if ($s[$count] !== '\\') {
  94                  $out .= $s[$count];
  95              } else {
  96                  // A backslash at the end of the string - ignore it
  97                  if ($count === ($n - 1)) {
  98                      break;
  99                  }
 100  
 101                  switch ($s[++$count]) {
 102                      case ')':
 103                      case '(':
 104                      case '\\':
 105                          $out .= $s[$count];
 106                          break;
 107  
 108                      case 'f':
 109                          $out .= "\x0C";
 110                          break;
 111  
 112                      case 'b':
 113                          $out .= "\x08";
 114                          break;
 115  
 116                      case 't':
 117                          $out .= "\x09";
 118                          break;
 119  
 120                      case 'r':
 121                          $out .= "\x0D";
 122                          break;
 123  
 124                      case 'n':
 125                          $out .= "\x0A";
 126                          break;
 127  
 128                      case "\r":
 129                          if ($count !== $n - 1 && $s[$count + 1] === "\n") {
 130                              $count++;
 131                          }
 132                          break;
 133  
 134                      case "\n":
 135                          break;
 136  
 137                      default:
 138                          $actualChar = \ord($s[$count]);
 139                          // ascii 48 = number 0
 140                          // ascii 57 = number 9
 141                          if ($actualChar >= 48 &&
 142                              $actualChar <= 57) {
 143                              $oct = '' . $s[$count];
 144  
 145                              /** @noinspection NotOptimalIfConditionsInspection */
 146                              if ($count + 1 < $n &&
 147                                  \ord($s[$count + 1]) >= 48 &&
 148                                  \ord($s[$count + 1]) <= 57
 149                              ) {
 150                                  $count++;
 151                                  $oct .= $s[$count];
 152  
 153                                  /** @noinspection NotOptimalIfConditionsInspection */
 154                                  if ($count + 1 < $n &&
 155                                      \ord($s[$count + 1]) >= 48 &&
 156                                      \ord($s[$count + 1]) <= 57
 157                                  ) {
 158                                      $oct .= $s[++$count];
 159                                  }
 160                              }
 161  
 162                              $out .= \chr(\octdec($oct));
 163                          } else {
 164                              // If the character is not one of those defined, the backslash is ignored
 165                              $out .= $s[$count];
 166                          }
 167                  }
 168              }
 169          }
 170          return $out;
 171      }
 172  }