Netgate Discussion Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Search
    • Register
    • Login

    Shaw cable traffic dashboard widget

    Scheduled Pinned Locked Moved webGUI
    4 Posts 2 Posters 3.2k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • D
      derekr
      last edited by

      Hi all,

      I've created a dashboard widget (for v2.x) that will log into the Shaw cable secure website, and extract the internet traffic chart data, and display the results in a quick-reference table in a dashboard widget.  I figured I'd share it with this group in case someone else might find it useful.

      Code for the widget is below, save the file as shawtraffic.widget.php and place under /usr/local/www/widgets/widgets/ on your pfSense system.

      Cheers,
      Derek.

      
      /*
              Shaw traffic dashboard widget for pfsense v0.1
              Copyright 2013 Derek Rachul (drachul@gmail.com)
      
              All rights reserved.
      
              Redistribution and use in source and binary forms, with or without
              modification, are permitted provided that the following conditions are met:
      
              1\. Redistributions of source code must retain the above copyright notice,
                 this list of conditions and the following disclaimer.
      
              2\. Redistributions in binary form must reproduce the above copyright
                 notice, this list of conditions and the following disclaimer in the
                 documentation and/or other materials provided with the distribution.
      
              THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
              INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
              AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
              AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
              OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
              SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
              INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
              CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
              ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
              POSSIBILITY OF SUCH DAMAGE.
      */
      $nocsrf = true;
      
      require_once("guiconfig.inc");
      require_once("pfsense-utils.inc");
      require_once("functions.inc");
      
      // configuration defaults
      $displayentries = 1000;
      $refresh = 3600;
      $username = "";
      $password = "";
      
      // save configuration for shaw traffic
      if(isset($_POST['shawtrafficsubmit'])) {
        $config['widgets']['shawtrafficrefresh'] = $_POST['shawtrafficrefresh'];
        $config['widgets']['shawtrafficentries'] = $_POST['shawtrafficentries'];
        $config['widgets']['shawtrafficusername'] = $_POST['shawtrafficusername'];
        $config['widgets']['shawtrafficpassword'] = $_POST['shawtrafficpassword'];
        write_config("Saved Shaw traffic Widget via Dashboard");
        header("Location: /");
      } 
      
      // update configuration variables if available
      if (isset($config['widgets']['shawtrafficrefresh']))
        $refresh = $config['widgets']['shawtrafficrefresh'];
      
      if (isset($config['widgets']['shawtrafficentries']))
        $displayentries = $config['widgets']['shawtrafficentries'];
      
      if (isset($config['widgets']['shawtrafficusername']))
        $username = $config['widgets']['shawtrafficusername'];
      
      if (isset($config['widgets']['shawtrafficpassword']))
        $password = $config['widgets']['shawtrafficpassword'];
      
      // output a table with 
      if ($_REQUEST['getshawtraf']) {
        $xml = get_chartdata($username,$password);
        $traffic = parse_chartdata($xml);
        $content = traffic_content($traffic,$displayentries);
        output_table($content);
        // exit so we don't output any of the content below
        exit;
      }
      else {
        $nocollect = 0;
        $waitmessage = "collecting traffic data...";
        if (!strlen($username) or !strlen($password)) {
          $nocollect = 1;
          $waitmessage = "!!! must configure username/password !!!";
        }
      }
      ?>
      
      <form action="/widgets/widgets/shawtraffic.widget.php" method="post" name="iforma">
      
      | Username: |  |
      | Password: |  |
      | Most recent entries to display: | 
              <select name="shawtrafficentries" class="formfld" id="shawtrafficentries"><option value="1" <?php="" if="" ($displayentries="=" "1")="" echo="" "selected";?="">>1</option>          <option value="3" <?php="" if="" ($displayentries="=" "3")="" echo="" "selected";?="">>3</option>          <option value="5" <?php="" if="" ($displayentries="=" "5")="" echo="" "selected";?="">>5</option>          <option value="10" <?php="" if="" ($displayentries="=" "10")="" echo="" "selected";?="">>10</option>          <option value="1000" <?php="" if="" ($displayentries="=" "1000")="" echo="" "selected";?="">>All</option></select> 
             |
      | Refresh time: | 
              <select name="shawtrafficrefresh" class="formfld" id="shawtrafficrefresh"><option value="600" <?php="" if="" ($refresh="=" "600")="" echo="" "selected";?="">>10 mins</option>          <option value="3600" <?php="" if="" ($refresh="=" "3600")="" echo="" "selected";?="">>1 hour</option></select> 
             |
      
        </form>
      
      | period | download | upload | total | limit |
      |  |
      
      /* Support functionality for traffic reading/parsing/output */
      function output_table($content) {
        echo '' .
             '' .
             $content .
             '
      
      | period | download | upload | total | limit |
      
      ';
      }
      function traffic_content($traffic,$maxentries) {
        $content = "";
        $traffic_count = count($traffic);
        if ($traffic_count) {
          $last_idx = $traffic_count - 1;
          for ($idx = $last_idx, $displayed = 0; ($idx >= 0) && ($displayed < $maxentries); $idx--, $displayed++) {
            $total = $traffic[$idx]['Total'];
            $limit = $traffic[$idx]['Limit'];
            $ratio = $total / $limit;
            $bgcolor = 'lightgreen';
      
            if ($ratio > 0.9) {
              $bgcolor = '#ef6666';
            }
            else if ($ratio > 0.75) {
              $bgcolor = 'khaki';
            } 
            $content .= '' .
                        '' . $traffic[$idx]['Period'] . '' .
                        '' . $traffic[$idx]['Download'] . 'GB' .
                        '' . $traffic[$idx]['Upload'] . 'GB' .
                        '
      
      | ' . $total . 'GB |
      
      ' .
                        '' . $limit . 'GB' .
                        '';
          }
        }
        else {
          $content = 'no data available';
        }
        return $content;
      }
      
      function get_chartdata($user,$pass) {
        $login_url = "https://signon.shaw.ca/?application=manage";
        $usage_url = "https://my.shaw.ca/CustomerCentre/InternetModemUsage/SplitUsage";
      
        $cookie_file_path = "/tmp/cookies.txt";
      
        // begin script
        $ch = curl_init();
      
        // extra headers
        $headers[] = "Accept: */*";
        $headers[] = "Connection: Keep-Alive";
      
        // basic curl options for all requests
        curl_setopt($ch, CURLOPT_HTTPHEADER,  $headers);
        curl_setopt($ch, CURLOPT_HEADER,  0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); # mirror the user agent from the browser
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        #curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file_path);
        curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file_path);
      
        $postfields="username=" . $user . "&password=" . $pass . "&signon=Sign+In&realm=occ&persistent=checked";
      
        // do login
        curl_setopt($ch, CURLOPT_URL, $login_url);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
        curl_setopt($ch, CURLOPT_POST, 1);
        $result = curl_exec($ch);
      
        if ($result === false) {
          output_table('failed to get traffic data: ' . curl_error($ch) . '');
          exit;
        } 
        else if (preg_match('/The sign in attempt was not successful/i', $result)) {
          output_table('failed to get traffic data: invalid Shaw user/pass');
          exit;
        }
      
        // fetch traffic page
        curl_setopt($ch, CURLOPT_URL, $usage_url);
        curl_setopt($ch, CURLOPT_POST, 0);
        $result = curl_exec($ch);
      
        if ($result === false) {
          output_table('failed to get traffic data: ' . curl_error($ch) . '');
          exit;
        }
      
        curl_close($ch);
      
        // extract traffic data
        preg_match('/chart_modemUsageChart\.setDataXML\("([^"]+)"\)/is', $result, $matches);
      
        // replace linefeeds with dashes
        $xml = str_replace('
      ', '-', $matches[1]);
      
        return $xml;
      }
      
      function parse_chartdata($xml) {
        $parser = new xmlToArrayParser($xml);
        if ($parser->parse_error) {
          output_table('failed to parse traffic data: ' . $parser->get_xml_error() . '');
          exit;
        }
        $data = $parser->array;
        $traffic = array();
        $categories = $data['chart']['categories']['category'];
        $dataset = $data['chart']['dataset'];
        $uploads = 0;
        $downloads = 0;
        $limits = 0;
        for ($set = 0; $set < count($dataset); $set++) {
          $_set = $dataset[$set];
          $_set_data = $_set['set'];
          switch ($_set['attrib']['seriesName']) {
            case "Downloads": $downloads = $_set_data; break;
            case "Uploads": $uploads = $_set_data; break;
            case "Usage Limit": $limits = $_set_data; break;
            default: break;
          }
        }
      
        for ($cat = 0; $cat < count($categories); $cat++) {
          $down = $downloads[$cat]['attrib']['value'];
          $up = $uploads[$cat]['attrib']['value'];
          $tot = sprintf("%.2f", $down + $up);
          $traffic[] = array(
            "Period" => $categories[$cat]['attrib']['label'],
            "Download" => $down,
            "Upload" => $up,
            "Total" => $tot,
            "Limit" => $limits[$cat]['attrib']['value']
          );
        }
        return $traffic;
      }
      
      /* code taken from http://php.net/manual/en/ref.xml.php#106743 */
      class xmlToArrayParser {
        /** The array created by the parser can be assigned to any variable: $anyVarArr = $domObj->array.*/
        public  $array = array();
        public  $parse_error = false;
        private $parser;
        private $pointer;
      
        /** Constructor: $domObj = new xmlToArrayParser($xml); */
        public function __construct($xml) {
          $this->pointer =& $this->array;
          $this->parser = xml_parser_create("UTF-8");
          xml_set_object($this->parser, $this);
          xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
          xml_set_element_handler($this->parser, "tag_open", "tag_close");
          xml_set_character_data_handler($this->parser, "cdata");
          $this->parse_error = xml_parse($this->parser, ltrim($xml))? false : true;
        }
      
        /** Free the parser. */
        public function __destruct() { xml_parser_free($this->parser);}
      
        /** Get the xml error if an an error in the xml file occured during parsing. */
        public function get_xml_error() {
          if($this->parse_error) {
            $errCode = xml_get_error_code ($this->parser);
            $thisError =  "Error Code [". $errCode ."] \"**" . xml_error_string($errCode)."**\",
                                  at char ".xml_get_current_column_number($this->parser) . "
                                  on line ".xml_get_current_line_number($this->parser)."";
          }else $thisError = $this->parse_error;
          return $thisError;
        }
      
        private function tag_open($parser, $tag, $attributes) {
          $this->convert_to_array($tag, 'attrib');
          $idx=$this->convert_to_array($tag, 'cdata');
          if(isset($idx)) {
            $this->pointer[$tag][$idx] = Array('@idx' => $idx,'@parent' => &$this->pointer);
            $this->pointer =& $this->pointer[$tag][$idx];
          }else {
            $this->pointer[$tag] = Array('@parent' => &$this->pointer);
            $this->pointer =& $this->pointer[$tag];
          }
          if (!empty($attributes)) { $this->pointer['attrib'] = $attributes; }
        }
        /** Adds the current elements content to the current pointer[cdata] array. */
        private function cdata($parser, $cdata) { $this->pointer['cdata'] = trim($cdata); }
      
        private function tag_close($parser, $tag) {
          $current = & $this->pointer;
          if(isset($this->pointer['@idx'])) {unset($current['@idx']);}
      
          $this->pointer = & $this->pointer['@parent'];
          unset($current['@parent']);
      
          if(isset($current['cdata']) && count($current) == 1) { $current = $current['cdata'];}
          else if(empty($current['cdata'])) {unset($current['cdata']);}
        }
      
        /** Converts a single element item into array(element[0]) if a second element of the same name is encountered. */
        private function convert_to_array($tag, $item) {
          if(isset($this->pointer[$tag][$item])) {
            $content = $this->pointer[$tag];
            $this->pointer[$tag] = array((0) => $content);
            $idx = 1;
          }else if (isset($this->pointer[$tag])) {
            $idx = count($this->pointer[$tag]);
            if(!isset($this->pointer[$tag][0])) {
              foreach ($this->pointer[$tag] as $key => $value) {
                  unset($this->pointer[$tag][$key]);
                  $this->pointer[$tag][0][$key] = $value;
          }}}else $idx = null;
          return $idx;
        }
      }
      ?>
      
      
      1 Reply Last reply Reply Quote 0
      • D
        derekr
        last edited by

        Small update to handle unlimited tiers.

        *edit:  another small change to remove a div-by-zero error

        
        /*
                Shaw traffic dashboard widget for pfsense v0.3
                Copyright 2013 Derek Rachul (drachul@gmail.com)
        
                All rights reserved.
        
                Redistribution and use in source and binary forms, with or without
                modification, are permitted provided that the following conditions are met:
        
                1\. Redistributions of source code must retain the above copyright notice,
                   this list of conditions and the following disclaimer.
        
                2\. Redistributions in binary form must reproduce the above copyright
                   notice, this list of conditions and the following disclaimer in the
                   documentation and/or other materials provided with the distribution.
        
                THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
                AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
                AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
                OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                POSSIBILITY OF SUCH DAMAGE.
        */
        $nocsrf = true;
        
        require_once("guiconfig.inc");
        require_once("pfsense-utils.inc");
        require_once("functions.inc");
        
        // configuration defaults
        $displayentries = 1000;
        $refresh = 3600;
        $username = "";
        $password = "";
        
        // save configuration for shaw traffic
        if(isset($_POST['shawtrafficsubmit'])) {
          $config['widgets']['shawtrafficrefresh'] = $_POST['shawtrafficrefresh'];
          $config['widgets']['shawtrafficentries'] = $_POST['shawtrafficentries'];
          $config['widgets']['shawtrafficusername'] = $_POST['shawtrafficusername'];
          $config['widgets']['shawtrafficpassword'] = $_POST['shawtrafficpassword'];
          write_config("Saved Shaw traffic Widget via Dashboard");
          header("Location: /");
        } 
        
        // update configuration variables if available
        if (isset($config['widgets']['shawtrafficrefresh']))
          $refresh = $config['widgets']['shawtrafficrefresh'];
        
        if (isset($config['widgets']['shawtrafficentries']))
          $displayentries = $config['widgets']['shawtrafficentries'];
        
        if (isset($config['widgets']['shawtrafficusername']))
          $username = $config['widgets']['shawtrafficusername'];
        
        if (isset($config['widgets']['shawtrafficpassword']))
          $password = $config['widgets']['shawtrafficpassword'];
        
        // output a table with 
        if ($_REQUEST['getshawtraf']) {
          $xml = get_chartdata($username,$password);
          $traffic = parse_chartdata($xml);
          $content = traffic_content($traffic,$displayentries);
          output_table($content);
          // exit so we don't output any of the content below
          exit;
        }
        else {
          $nocollect = 0;
          $waitmessage = "collecting traffic data...";
          if (!strlen($username) or !strlen($password)) {
            $nocollect = 1;
            $waitmessage = "!!! must configure username/password !!!";
          }
        }
        ?>
        
        <form action="/widgets/widgets/shawtraffic.widget.php" method="post" name="iforma">
        
        | Username: |  |
        | Password: |  |
        | Most recent entries to display: | 
                <select name="shawtrafficentries" class="formfld" id="shawtrafficentries"><option value="1" <?php="" if="" ($displayentries="=" "1")="" echo="" "selected";?="">>1</option>          <option value="3" <?php="" if="" ($displayentries="=" "3")="" echo="" "selected";?="">>3</option>          <option value="5" <?php="" if="" ($displayentries="=" "5")="" echo="" "selected";?="">>5</option>          <option value="10" <?php="" if="" ($displayentries="=" "10")="" echo="" "selected";?="">>10</option>          <option value="1000" <?php="" if="" ($displayentries="=" "1000")="" echo="" "selected";?="">>All</option></select> 
               |
        | Refresh time: | 
                <select name="shawtrafficrefresh" class="formfld" id="shawtrafficrefresh"><option value="600" <?php="" if="" ($refresh="=" "600")="" echo="" "selected";?="">>10 mins</option>          <option value="3600" <?php="" if="" ($refresh="=" "3600")="" echo="" "selected";?="">>1 hour</option></select> 
               |
        
          </form>
        
        | period | download | upload | total | limit |
        |  |
        
        /* Support functionality for traffic reading/parsing/output */
        function output_table($content) {
          echo '' .
               '' .
               $content .
               '
        
        | period | download | upload | total | limit |
        
        ';
        }
        function traffic_content($traffic,$maxentries) {
          $content = "";
          $traffic_count = count($traffic);
          if ($traffic_count) {
            $last_idx = $traffic_count - 1;
            for ($idx = $last_idx, $displayed = 0; ($idx >= 0) && ($displayed < $maxentries); $idx--, $displayed++) {
              $total = $traffic[$idx]['Total'];
              $limit = $traffic[$idx]['Limit'];
              $bgcolor = 'lightgreen';
        
              if ($limit != 0) {
                $ratio = $total / $limit;
                if ($ratio > 0.9) {
                  $bgcolor = '#ef6666';
                }
                else if ($ratio > 0.75) {
                  $bgcolor = 'khaki';
                }
                $limit .= 'GB';
              } 
              else {
                $limit = 'Unlimited';
              }
              $content .= '' .
                          '' . $traffic[$idx]['Period'] . '' .
                          '' . $traffic[$idx]['Download'] . 'GB' .
                          '' . $traffic[$idx]['Upload'] . 'GB' .
                          '
        
        | ' . $total . 'GB |
        
        ' .
                          '' . $limit . '' .
                          '';
            }
          }
          else {
            $content = 'no data available';
          }
          return $content;
        }
        
        function get_chartdata($user,$pass) {
          $login_url = "https://signon.shaw.ca/?application=manage";
          $usage_url = "https://my.shaw.ca/CustomerCentre/InternetModemUsage/SplitUsage";
        
          $cookie_file_path = "/tmp/cookies.txt";
        
          // begin script
          $ch = curl_init();
        
          // extra headers
          $headers[] = "Accept: */*";
          $headers[] = "Connection: Keep-Alive";
        
          // basic curl options for all requests
          curl_setopt($ch, CURLOPT_HTTPHEADER,  $headers);
          curl_setopt($ch, CURLOPT_HEADER,  0);
          curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
          curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
          curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); # mirror the user agent from the browser
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
          curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
          #curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file_path);
          curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file_path);
        
          $postfields="username=" . $user . "&password=" . $pass . "&signon=Sign+In&realm=occ&persistent=checked";
        
          // do login
          curl_setopt($ch, CURLOPT_URL, $login_url);
          curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
          curl_setopt($ch, CURLOPT_POST, 1);
          $result = curl_exec($ch);
        
          if ($result === false) {
            output_table('failed to get traffic data: ' . curl_error($ch) . '');
            exit;
          } 
          else if (preg_match('/The sign in attempt was not successful/i', $result)) {
            output_table('failed to get traffic data: invalid Shaw user/pass');
            exit;
          }
        
          // fetch traffic page
          curl_setopt($ch, CURLOPT_URL, $usage_url);
          curl_setopt($ch, CURLOPT_POST, 0);
          $result = curl_exec($ch);
        
          if ($result === false) {
            output_table('failed to get traffic data: ' . curl_error($ch) . '');
            exit;
          }
        
          curl_close($ch);
        
          // extract traffic data
          preg_match('/chart_modemUsageChart\.setDataXML\("([^"]+)"\)/is', $result, $matches);
        
          // replace linefeeds with dashes
          $xml = str_replace('
        ', '-', $matches[1]);
        
          return $xml;
        }
        
        function parse_chartdata($xml) {
          $parser = new xmlToArrayParser($xml);
          if ($parser->parse_error) {
            output_table('failed to parse traffic data: ' . $parser->get_xml_error() . '');
            exit;
          }
          $data = $parser->array;
          $traffic = array();
          $categories = $data['chart']['categories']['category'];
          $dataset = $data['chart']['dataset'];
          $uploads = 0;
          $downloads = 0;
          $limits = 0;
          for ($set = 0; $set < count($dataset); $set++) {
            $_set = $dataset[$set];
            $_set_data = $_set['set'];
            switch ($_set['attrib']['seriesName']) {
              case "Downloads": $downloads = $_set_data; break;
              case "Uploads": $uploads = $_set_data; break;
              case "Usage Limit": $limits = $_set_data; break;
              default: break;
            }
          }
        
          for ($cat = 0; $cat < count($categories); $cat++) {
            $down = $downloads[$cat]['attrib']['value'];
            $up = $uploads[$cat]['attrib']['value'];
            $tot = sprintf("%.2f", $down + $up);
            $traffic[] = array(
              "Period" => $categories[$cat]['attrib']['label'],
              "Download" => $down,
              "Upload" => $up,
              "Total" => $tot,
              "Limit" => $limits[$cat]['attrib']['value']
            );
          }
          return $traffic;
        }
        
        /* code taken from http://php.net/manual/en/ref.xml.php#106743 */
        class xmlToArrayParser {
          /** The array created by the parser can be assigned to any variable: $anyVarArr = $domObj->array.*/
          public  $array = array();
          public  $parse_error = false;
          private $parser;
          private $pointer;
        
          /** Constructor: $domObj = new xmlToArrayParser($xml); */
          public function __construct($xml) {
            $this->pointer =& $this->array;
            $this->parser = xml_parser_create("UTF-8");
            xml_set_object($this->parser, $this);
            xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
            xml_set_element_handler($this->parser, "tag_open", "tag_close");
            xml_set_character_data_handler($this->parser, "cdata");
            $this->parse_error = xml_parse($this->parser, ltrim($xml))? false : true;
          }
        
          /** Free the parser. */
          public function __destruct() { xml_parser_free($this->parser);}
        
          /** Get the xml error if an an error in the xml file occured during parsing. */
          public function get_xml_error() {
            if($this->parse_error) {
              $errCode = xml_get_error_code ($this->parser);
              $thisError =  "Error Code [". $errCode ."] \"**" . xml_error_string($errCode)."**\",
                                    at char ".xml_get_current_column_number($this->parser) . "
                                    on line ".xml_get_current_line_number($this->parser)."";
            }else $thisError = $this->parse_error;
            return $thisError;
          }
        
          private function tag_open($parser, $tag, $attributes) {
            $this->convert_to_array($tag, 'attrib');
            $idx=$this->convert_to_array($tag, 'cdata');
            if(isset($idx)) {
              $this->pointer[$tag][$idx] = Array('@idx' => $idx,'@parent' => &$this->pointer);
              $this->pointer =& $this->pointer[$tag][$idx];
            }else {
              $this->pointer[$tag] = Array('@parent' => &$this->pointer);
              $this->pointer =& $this->pointer[$tag];
            }
            if (!empty($attributes)) { $this->pointer['attrib'] = $attributes; }
          }
          /** Adds the current elements content to the current pointer[cdata] array. */
          private function cdata($parser, $cdata) { $this->pointer['cdata'] = trim($cdata); }
        
          private function tag_close($parser, $tag) {
            $current = & $this->pointer;
            if(isset($this->pointer['@idx'])) {unset($current['@idx']);}
        
            $this->pointer = & $this->pointer['@parent'];
            unset($current['@parent']);
        
            if(isset($current['cdata']) && count($current) == 1) { $current = $current['cdata'];}
            else if(empty($current['cdata'])) {unset($current['cdata']);}
          }
        
          /** Converts a single element item into array(element[0]) if a second element of the same name is encountered. */
          private function convert_to_array($tag, $item) {
            if(isset($this->pointer[$tag][$item])) {
              $content = $this->pointer[$tag];
              $this->pointer[$tag] = array((0) => $content);
              $idx = 1;
            }else if (isset($this->pointer[$tag])) {
              $idx = count($this->pointer[$tag]);
              if(!isset($this->pointer[$tag][0])) {
                foreach ($this->pointer[$tag] as $key => $value) {
                    unset($this->pointer[$tag][$key]);
                    $this->pointer[$tag][0][$key] = $value;
            }}}else $idx = null;
            return $idx;
          }
        }
        ?>
        
        
        1 Reply Last reply Reply Quote 0
        • N
          neewbie
          last edited by

          Not working on 2.0.3
          Parshe error: syntax error, unexpected T_LNUMBER, expecting ',' or ';'

          1 Reply Last reply Reply Quote 0
          • D
            derekr
            last edited by

            @Lolipop:

            Not working on 2.0.3
            Parshe error: syntax error, unexpected T_LNUMBER, expecting ',' or ';'

            I had another small issue where it'd complain about a division by zero error (fixed in edited code in above post), but it's working here on 2.0.2 - I'll have to install 2.0.3 to see what else changed.

            1 Reply Last reply Reply Quote 0
            • First post
              Last post
            Copyright 2025 Rubicon Communications LLC (Netgate). All rights reserved.