PHP Classes

File: contrib/MultiotpXmlParser.php

Recommend this page to a friend!
  Classes of André Liechti   multiOTP PHP class   contrib/MultiotpXmlParser.php   Download  
File: contrib/MultiotpXmlParser.php
Role: Auxiliary script
Content type: text/plain
Description: Auxiliary script
Class: multiOTP PHP class
Authenticate and manage OTP strong user tokens
Author: By
Last change: Release 5.10.0.1
New release 5.9.9.1
FIX: Windows backup temp folder is now the default system temp folder
FIX: Adding -sync-delete-retention-days parameter doesn't return missing parameters error
FIX: Case sensitive issue has been fixed with MSCHAPv2 authentication (thanks Alexey)
FIX: Case sensitive issue has been fixed during FastCreateUser process
FIX: {MultiotpUserDisplayName} tag usage in templates (was not replaced in the QRcode)
ENH: Created users are trimmed to avoid bad space prefix/suffix during copy/paste
ENH: multiOTP Credential Provider enhanced support
ENH: New default-2fa-digits command line option to set the default amount of OTP digits
ENH: PHP 8.4.x deprecated code cleaned (xml_set_object removed)
ENH: New Message-Authenticator requirement support for FortiGate v7.2.10+, v7.4.5+ and v7.6.1+
ENH: New SetCurrentUserSid function for new Credential Provider -usersid option
ENH: Embedded Windows PHP edition updated to version 8.3.15
ENH: Embedded Windows nginx edition updated to version 1.27.3
Date: 1 month ago
Size: 4,927 bytes
 

Contents

Class file image Download
<?php

class MultiotpXmlParser
/**
 * @class MultiotpXmlParser
 * @brief New rewritten PHP XML parser (without eval)
 *
 * @author Andre Liechti, SysCo systemes de communication sa, <[email protected]>
 * @version 5.10.0.1
 * @date 2025-10-22
 * @since 2025-10-22
 *
 * Based on the following GNU Lesser General Public License work:
 * XML Parser Class
 * Parses an XML document into an object structure much like the SimpleXML extension.
 * @author Adam A. Flynn <[email protected]>
 * @copyright Copyright (c) 2005-2007, Adam A. Flynn
 * @version 1.3.0.1
 *
 *
 * Change Log
 *
 * 2025-10-22 5.10.0.1 SysCo/al New rewritten PHP XML parser (without eval)
 */
{
  public
$xml;
  public
$document;
  public
$stack;
  public
$cleanTagNames;

  public function
__construct(
   
$xml = '',
   
$cleanTagNames = true
 
) {
   
$this->xml = $xml;
   
$this->stack = array();
   
$this->cleanTagNames = $cleanTagNames;
  }

  public function
Parse()
  {
   
$parser = xml_parser_create();
   
xml_set_element_handler($parser, array($this, 'StartElement'), array($this, 'EndElement'));
   
xml_set_character_data_handler($parser, array($this, 'CharacterData'));

    if (!
xml_parse($parser, $this->xml)) {
     
$this->HandleError(
       
xml_get_error_code($parser),
       
xml_get_current_line_number($parser),
       
xml_get_current_column_number($parser),
       
xml_get_current_byte_index($parser)
      );
    }

   
xml_parser_free($parser);
  }

  public function
HandleError(
   
$code,
   
$line,
   
$col,
   
$byte_index = 0
 
) {
   
$sample_size = 80;
   
$sample_start = $byte_index - ($sample_size / 2);
    if (
$sample_start < 0) {
     
$sample_start = 0;
    }
   
trigger_error(
     
'XML Parsing Error at '.$line.':'.$col.
      ((
$byte_index != 0)?' (byte index: '.$byte_index.')':'').
     
'. Error '.$code.': '.xml_error_string($code).
     
' Sample: '.htmlentities(substr($this->xml, $sample_start, $sample_size)),
     
E_USER_ERROR
   
);
  }

  public function
GenerateXML()
  {
    return
$this->document->GetXML();
  }

  public function
StartElement(
   
$parser,
   
$name,
   
$attrs = array()
  ) {
   
$name = strtolower($name);

    if (
count($this->stack) === 0) {
     
// Root node
     
$this->document = new MultiotpXMLTag($name, $attrs);
     
$this->stack[] = $this->document;
      return;
    }

   
$parent = end($this->stack);
   
$child = $parent->AddChild($name, $attrs, count($this->stack), $this->cleanTagNames);
   
$this->stack[] = $child;
  }

  public function
EndElement(
   
$parser,
   
$name
 
) {
   
array_pop($this->stack);
  }

  public function
CharacterData(
   
$parser,
   
$data
 
) {
   
$current = end($this->stack);
    if (
$current !== false) {
     
$current->tagData .= trim($data);
    }
  }
}

/**
 * XML Tag Object
 */
class MultiotpXMLTag
{
  public
$tagName;
  public
$tagAttrs;
  public
$tagData;
  public
$tagChildren;
  public
$tagParents;

  public function
__construct(
   
$name,
   
$attrs = array(),
   
$parents = 0,
   
$cleanTagName = true
 
) {
   
$this->tagName = $cleanTagName ? str_replace(array(':', '-'), '_', strtolower($name)) : strtolower($name);
   
$this->tagAttrs = array_change_key_case($attrs, CASE_LOWER);
   
$this->tagData = '';
   
$this->tagChildren = array();
   
$this->tagParents = $parents;
  }

 
/**
   * Helper for legagy compatibility
   * $parent->tagChildren['foo'][0] works also like the legacy $parent->foo[0]
   */
 
public function __get(
   
$name
 
) {
   
$name = strtolower($name);
    if (isset(
$this->tagChildren[$name])) {
      return
$this->tagChildren[$name];
    }
    return array();
  }

  public function
AddChild(
   
$name,
   
$attrs = array(),
   
$parents = 0,
   
$cleanTagName = true
 
) {
   
$childName = $cleanTagName ? str_replace(array(':', '-'), '_', strtolower($name)) : strtolower($name);
   
$child = new self($name, $attrs, $parents, $cleanTagName);

    if (!isset(
$this->tagChildren[$childName])) {
     
$this->tagChildren[$childName] = array();
    }
   
$this->tagChildren[$childName][] = $child;

    return
$child;
  }

  public function
GetChild(
   
$name,
   
$index = 0
 
) {
   
$name = strtolower($name);
    return isset(
$this->tagChildren[$name][$index]) ? $this->tagChildren[$name][$index] : null;
  }

  public function
GetXML()
  {
   
$out = "\n" . str_repeat("\t", $this->tagParents) . '<'.$this->tagName;

    foreach (
$this->tagAttrs as $attr => $value) {
     
$out .= ' '.$attr.'="'.$value.'"';
    }

    if (empty(
$this->tagChildren) && $this->tagData === '') {
     
$out .= " />";
    } else {
     
$out .= ">";
      if (
$this->tagData !== '') {
       
$out .= $this->tagData;
      }
      foreach (
$this->tagChildren as $children) {
        foreach (
$children as $child) {
         
$out .= $child->GetXML();
        }
      }
     
$out .= '</'.$this->tagName.'>';
    }

    return
$out;
  }
}
?>