[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/mnet/xmlrpc/ -> xmlparser.php (source)

   1  <?php
   2  /**
   3   * Custom XML parser for signed and/or encrypted XML Docs
   4   *
   5   * @author  Donal McMullan  [email protected]
   6   * @version 0.0.1
   7   * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
   8   * @package mnet
   9   */
  10  
  11  /**
  12   * Custom XML parser class for signed and/or encrypted XML Docs
  13   */
  14  class mnet_encxml_parser {
  15      /**
  16       * Constructor creates and initialises parser resource and calls initialise
  17       *
  18       * @return bool True
  19       */
  20      function mnet_encxml_parser() {
  21          return $this->initialise();
  22      }
  23  
  24      /**
  25       * Set default element handlers and initialise properties to empty.
  26       *
  27       * @return bool True
  28       */
  29      function initialise() {
  30          $this->parser = xml_parser_create();
  31          xml_set_object($this->parser, $this);
  32  
  33          xml_set_element_handler($this->parser, "start_element", "end_element");
  34          xml_set_character_data_handler($this->parser, "discard_data");
  35  
  36          $this->tag_number        = 0; // Just a unique ID for each tag
  37          $this->digest            = '';
  38          $this->remote_timestamp  = '';
  39          $this->remote_wwwroot    = '';
  40          $this->signature         = '';
  41          $this->data_object       = '';
  42          $this->key_URI           = '';
  43          $this->payload_encrypted = false;
  44          $this->cipher            = array();
  45          $this->error             = array();
  46          $this->remoteerror       = null;
  47          $this->errorstarted      = false;
  48          return true;
  49      }
  50  
  51      /**
  52       * Parse a block of XML text
  53       *
  54       * The XML Text will be an XML-RPC request which is wrapped in an XML doc
  55       * with a signature from the sender. This envelope may be encrypted and
  56       * delivered within another XML envelope with a symmetric key. The parser
  57       * should first decrypt this XML, and then place the XML-RPC request into
  58       * the data_object property, and the signature into the signature property.
  59       *
  60       * See the W3C's {@link http://www.w3.org/TR/xmlenc-core/ XML Encryption Syntax and Processing}
  61       * and {@link http://www.w3.org/TR/2001/PR-xmldsig-core-20010820/ XML-Signature Syntax and Processing}
  62       * guidelines for more detail on the XML.
  63       *
  64       * -----XML-Envelope---------------------------------
  65       * |                                                |
  66       * |    Symmetric-key--------------------------     |
  67       * |    |_____________________________________|     |
  68       * |                                                |
  69       * |    Encrypted data-------------------------     |
  70       * |    |                                     |     |
  71       * |    |  -XML-Envelope------------------    |     |
  72       * |    |  |                             |    |     |
  73       * |    |  |  --Signature-------------   |    |     |
  74       * |    |  |  |______________________|   |    |     |
  75       * |    |  |                             |    |     |
  76       * |    |  |  --Signed-Payload--------   |    |     |
  77       * |    |  |  |                      |   |    |     |
  78       * |    |  |  |   XML-RPC Request    |   |    |     |
  79       * |    |  |  |______________________|   |    |     |
  80       * |    |  |                             |    |     |
  81       * |    |  |_____________________________|    |     |
  82       * |    |_____________________________________|     |
  83       * |                                                |
  84       * |________________________________________________|
  85       *
  86       * @param   string  $data   The XML that you want to parse
  87       * @return  bool            True on success - false on failure
  88       */
  89      function parse($data) {
  90          $p = xml_parse($this->parser, $data);
  91  
  92          if ($p == 0) {
  93              // Parse failed
  94              $errcode = xml_get_error_code($this->parser);
  95              $errstring = xml_error_string($errcode);
  96              $lineno = xml_get_current_line_number($this->parser);
  97              if ($lineno !== false) {
  98                  $error = array('lineno' => $lineno);
  99                  $lineno--; // Line numbering starts at 1.
 100                  while ($lineno > 0) {
 101                      $data = strstr($data, "\n");
 102                      $lineno--;
 103                  }
 104                  $data .= "\n"; // In case there's only one line (no newline)
 105                  $line = substr($data, 0, strpos($data, "\n"));
 106                  $error['code']   = $errcode;
 107                  $error['string'] = $errstring;
 108                  $error['line']   = $line;
 109                  $this->error[] = $error;
 110              } else {
 111                  $this->error[] = array('code' => $errcode, 'string' => $errstring);
 112              }
 113          }
 114  
 115          if (!empty($this->remoteerror)) {
 116              return false;
 117          }
 118  
 119          if (count($this->cipher) > 0) {
 120              $this->cipher = array_values($this->cipher);
 121              $this->payload_encrypted = true;
 122          }
 123  
 124          return (bool)$p;
 125      }
 126  
 127      /**
 128       * Destroy the parser and free up any related resource.
 129       */
 130      function free_resource() {
 131          $free = xml_parser_free($this->parser);
 132      }
 133  
 134      /**
 135       * Set the character-data handler to the right function for each element
 136       *
 137       * For each tag (element) name, this function switches the character-data
 138       * handler to the function that handles that element. Note that character
 139       * data is referred to the handler in blocks of 1024 bytes.
 140       *
 141       * @param   mixed   $parser The XML parser
 142       * @param   string  $name   The name of the tag, e.g. method_call
 143       * @param   array   $attrs  The tag's attributes (if any exist).
 144       * @return  bool            True
 145       */
 146      function start_element($parser, $name, $attrs) {
 147          $this->tag_number++;
 148          $handler = 'discard_data';
 149          switch(strtoupper($name)) {
 150              case 'DIGESTVALUE':
 151                  $handler = 'parse_digest';
 152                  break;
 153              case 'SIGNATUREVALUE':
 154                  $handler = 'parse_signature';
 155                  break;
 156              case 'OBJECT':
 157                  $handler = 'parse_object';
 158                  break;
 159              case 'RETRIEVALMETHOD':
 160                  $this->key_URI = $attrs['URI'];
 161                  break;
 162              case 'TIMESTAMP':
 163                  $handler = 'parse_timestamp';
 164                  break;
 165              case 'WWWROOT':
 166                  $handler = 'parse_wwwroot';
 167                  break;
 168              case 'CIPHERVALUE':
 169                  $this->cipher[$this->tag_number] = '';
 170                  $handler = 'parse_cipher';
 171                  break;
 172              case 'FAULT':
 173                  $handler = 'parse_fault';
 174              default:
 175                  break;
 176          }
 177          xml_set_character_data_handler($this->parser, $handler);
 178          return true;
 179      }
 180  
 181      /**
 182       * Add the next chunk of character data to the remote_timestamp string
 183       *
 184       * @param   mixed   $parser The XML parser
 185       * @param   string  $data   The content of the current tag (1024 byte chunk)
 186       * @return  bool            True
 187       */
 188      function parse_timestamp($parser, $data) {
 189          $this->remote_timestamp .= $data;
 190          return true;
 191      }
 192  
 193      /**
 194       * Add the next chunk of character data to the cipher string for that tag
 195       *
 196       * The XML parser calls the character-data handler with 1024-character
 197       * chunks of data. This means that the handler may be called several times
 198       * for a single tag, so we use the concatenate operator (.) to build the
 199       * tag content into a string.
 200       * We should not encounter more than one of each tag type, except for the
 201       * cipher tag. We will often see two of those. We prevent the content of
 202       * these two tags being concatenated together by counting each tag, and
 203       * using its 'number' as the key to an array of ciphers.
 204       *
 205       * @param   mixed   $parser The XML parser
 206       * @param   string  $data   The content of the current tag (1024 byte chunk)
 207       * @return  bool            True
 208       */
 209      function parse_cipher($parser, $data) {
 210          $this->cipher[$this->tag_number] .= $data;
 211          return true;
 212      }
 213  
 214      /**
 215       * Add the next chunk of character data to the remote_wwwroot string
 216       *
 217       * @param   mixed   $parser The XML parser
 218       * @param   string  $data   The content of the current tag (1024 byte chunk)
 219       * @return  bool            True
 220       */
 221      function parse_wwwroot($parser, $data) {
 222          $this->remote_wwwroot .= $data;
 223          return true;
 224      }
 225  
 226      /**
 227       * Add the next chunk of character data to the digest string
 228       *
 229       * @param   mixed   $parser The XML parser
 230       * @param   string  $data   The content of the current tag (1024 byte chunk)
 231       * @return  bool            True
 232       */
 233      function parse_digest($parser, $data) {
 234          $this->digest .= $data;
 235          return true;
 236      }
 237  
 238      /**
 239       * Add the next chunk of character data to the signature string
 240       *
 241       * @param   mixed   $parser The XML parser
 242       * @param   string  $data   The content of the current tag (1024 byte chunk)
 243       * @return  bool            True
 244       */
 245      function parse_signature($parser, $data) {
 246          $this->signature .= $data;
 247          return true;
 248      }
 249  
 250      /**
 251       * Add the next chunk of character data to the data_object string
 252       *
 253       * @param   mixed   $parser The XML parser
 254       * @param   string  $data   The content of the current tag (1024 byte chunk)
 255       * @return  bool            True
 256       */
 257      function parse_object($parser, $data) {
 258          $this->data_object .= $data;
 259          return true;
 260      }
 261  
 262      /**
 263       * Discard the next chunk of character data
 264       *
 265       * This is used for tags that we're not interested in.
 266       *
 267       * @param   mixed   $parser The XML parser
 268       * @param   string  $data   The content of the current tag (1024 byte chunk)
 269       * @return  bool            True
 270       */
 271      function discard_data($parser, $data) {
 272          if (!$this->errorstarted) {
 273              // Not interested
 274              return true;
 275          }
 276          $data = trim($data);
 277          if (isset($this->errorstarted->faultstringstarted) && !empty($data)) {
 278              $this->remoteerror .= ', message: ' . $data;
 279          } else if (isset($this->errorstarted->faultcodestarted)) {
 280              $this->remoteerror = 'code: ' . $data;
 281              unset($this->errorstarted->faultcodestarted);
 282          } else if ($data == 'faultCode') {
 283              $this->errorstarted->faultcodestarted = true;
 284          } else if ($data == 'faultString') {
 285              $this->errorstarted->faultstringstarted = true;
 286          }
 287          return true;
 288  
 289      }
 290  
 291      function parse_fault($parser, $data) {
 292          $this->errorstarted = new StdClass;
 293          return true;
 294      }
 295  
 296      /**
 297       * Switch the character-data handler to ignore the next chunk of data
 298       *
 299       * @param   mixed   $parser The XML parser
 300       * @param   string  $name   The name of the tag, e.g. method_call
 301       * @return  bool            True
 302       */
 303      function end_element($parser, $name) {
 304          $ok = xml_set_character_data_handler($this->parser, "discard_data");
 305          return true;
 306      }
 307  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1