<?php
 vB_Utilities::extendMemoryLimit(); class vB_XML_Builder { use vB_Trait_NoSerialize; var $charset = 'windows-1252'; var $content_type = 'text/xml'; var $open_tags = []; var $tabs = ''; public $doc = ''; function __construct($content_type = null, $charset = null) { if ($content_type) { $this->content_type = $content_type; } if ($charset == null) { $userinfo = vB_User::fetchUserinfo(); $charset = !empty($userinfo['lang_charset']) ? $userinfo['lang_charset'] : vB_Template_Runtime::fetchStyleVar('charset'); if (empty($charset)) { $charset = 'utf-8'; } } $this->charset = (strtolower($charset) == 'iso-8859-1') ? 'windows-1252' : $charset; } public function send_content_type_header() { @header('Content-Type: ' . $this->content_type . ($this->charset == '' ? '' : '; charset=' . $this->charset)); } public function send_content_length_header() { @header('Content-Length: ' . $this->fetch_xml_content_length()); } public function fetch_xml_tag() { return '<?xml version="1.0" encoding="' . $this->charset . '"?>' . "\n"; } private function fetch_xml_content_length() { return strlen($this->doc) + strlen($this->fetch_xml_tag()); } function add_group($tag, $attr = array()) { $this->open_tags[] = $tag; $this->doc .= $this->tabs . $this->build_tag($tag, $attr) . "\n"; $this->tabs .= "\t"; } function close_group() { $tag = array_pop($this->open_tags); $this->tabs = substr($this->tabs, 0, -1); $this->doc .= $this->tabs . "</$tag>\n"; } function add_tag($tag, $content = '', $attr = [], $cdata = false, $htmlspecialchars = false) { $content = strval($content); $this->doc .= $this->tabs . $this->build_tag($tag, $attr, ($content === '')); if ($content !== '') { if ($htmlspecialchars) { $this->doc .= htmlspecialchars_uni($content); } else if ($cdata OR preg_match('/[\<\>\&\'\"\[\]]/', $content)) { $this->doc .= '<![CDATA[' . $this->escape_cdata($content) . ']]>'; } else { $this->doc .= $content; } $this->doc .= "</$tag>\n"; } } function build_tag($tag, $attr, $closing = false) { $tmp = "<$tag"; if (!empty($attr)) { foreach ($attr AS $attr_name => $attr_key) { if (strpos($attr_key, '"') !== false) { $attr_key = htmlspecialchars_uni($attr_key); } $tmp .= " $attr_name=\"$attr_key\""; } } $tmp .= ($closing ? " />\n" : '>'); return $tmp; } protected function escape_cdata($xml) { $xml = preg_replace('#[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]#', '', $xml); return str_replace(array('<![CDATA[', ']]>'), array('«![CDATA[', ']]»'), $xml); } function output() { if (!empty($this->open_tags)) { throw new Exception("There are still open tags within the document"); } return $this->doc; } function print_xml() { $GLOBALS['vbulletin']->shutdown->shutdown(); $this->send_content_type_header(); if ($this->fetch_send_content_length_header()) { $this->send_content_length_header(); } echo $this->fetch_xml(); exit; } function print_xml_header() { if ($this->fetch_send_content_length_header()) { if (!defined('SUPPRESS_KEEPALIVE_ECHO')) { define('SUPPRESS_KEEPALIVE_ECHO', true); } return false; } $this->send_content_type_header(); echo $this->fetch_xml_tag(); } function print_xml_end() { if ($this->fetch_send_content_length_header()) { return $this->print_xml(); } $GLOBALS['vbulletin']->shutdown->shutdown(); echo $this->output(); } private function fetch_send_content_length_header() { if (VB_AREA == 'Install' OR VB_AREA == 'Upgrade') { return $this->isIIS(); } else { $vboptions = vB::getDatastore()->getValue('options'); switch($vboptions['ajaxheader']) { case 0 : return true; case 1 : return false; case 2 : default: return $this->isIIS(); } } } private function isIIS() { return isset($_SERVER['SERVER_SOFTWARE']) AND (strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false); } function fetch_xml() { return $this->fetch_xml_tag() . $this->output(); } } 