Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 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.
   1  <?php
   2  
   3  /**

   4   * Parses string hash files. File format is as such:

   5   *

   6   *      DefaultKeyValue

   7   *      KEY: Value

   8   *      KEY2: Value2

   9   *      --MULTILINE-KEY--

  10   *      Multiline

  11   *      value.

  12   *

  13   * Which would output something similar to:

  14   *

  15   *      array(

  16   *          'ID' => 'DefaultKeyValue',

  17   *          'KEY' => 'Value',

  18   *          'KEY2' => 'Value2',

  19   *          'MULTILINE-KEY' => "Multiline\nvalue.\n",

  20   *      )

  21   *

  22   * We use this as an easy to use file-format for configuration schema

  23   * files, but the class itself is usage agnostic.

  24   *

  25   * You can use ---- to forcibly terminate parsing of a single string-hash;

  26   * this marker is used in multi string-hashes to delimit boundaries.

  27   */
  28  class HTMLPurifier_StringHashParser
  29  {
  30  
  31      /**

  32       * @type string

  33       */
  34      public $default = 'ID';
  35  
  36      /**

  37       * Parses a file that contains a single string-hash.

  38       * @param string $file

  39       * @return array

  40       */
  41      public function parseFile($file)
  42      {
  43          if (!file_exists($file)) {
  44              return false;
  45          }
  46          $fh = fopen($file, 'r');
  47          if (!$fh) {
  48              return false;
  49          }
  50          $ret = $this->parseHandle($fh);
  51          fclose($fh);
  52          return $ret;
  53      }
  54  
  55      /**

  56       * Parses a file that contains multiple string-hashes delimited by '----'

  57       * @param string $file

  58       * @return array

  59       */
  60      public function parseMultiFile($file)
  61      {
  62          if (!file_exists($file)) {
  63              return false;
  64          }
  65          $ret = array();
  66          $fh = fopen($file, 'r');
  67          if (!$fh) {
  68              return false;
  69          }
  70          while (!feof($fh)) {
  71              $ret[] = $this->parseHandle($fh);
  72          }
  73          fclose($fh);
  74          return $ret;
  75      }
  76  
  77      /**

  78       * Internal parser that acepts a file handle.

  79       * @note While it's possible to simulate in-memory parsing by using

  80       *       custom stream wrappers, if such a use-case arises we should

  81       *       factor out the file handle into its own class.

  82       * @param resource $fh File handle with pointer at start of valid string-hash

  83       *            block.

  84       * @return array

  85       */
  86      protected function parseHandle($fh)
  87      {
  88          $state   = false;
  89          $single  = false;
  90          $ret     = array();
  91          do {
  92              $line = fgets($fh);
  93              if ($line === false) {
  94                  break;
  95              }
  96              $line = rtrim($line, "\n\r");
  97              if (!$state && $line === '') {
  98                  continue;
  99              }
 100              if ($line === '----') {
 101                  break;
 102              }
 103              if (strncmp('--#', $line, 3) === 0) {
 104                  // Comment

 105                  continue;
 106              } elseif (strncmp('--', $line, 2) === 0) {
 107                  // Multiline declaration

 108                  $state = trim($line, '- ');
 109                  if (!isset($ret[$state])) {
 110                      $ret[$state] = '';
 111                  }
 112                  continue;
 113              } elseif (!$state) {
 114                  $single = true;
 115                  if (strpos($line, ':') !== false) {
 116                      // Single-line declaration

 117                      list($state, $line) = explode(':', $line, 2);
 118                      $line = trim($line);
 119                  } else {
 120                      // Use default declaration

 121                      $state  = $this->default;
 122                  }
 123              }
 124              if ($single) {
 125                  $ret[$state] = $line;
 126                  $single = false;
 127                  $state  = false;
 128              } else {
 129                  $ret[$state] .= "$line\n";
 130              }
 131          } while (!feof($fh));
 132          return $ret;
 133      }
 134  }
 135  
 136  // vim: et sw=4 sts=4