<?php
class docType {
   public 
$htmlDT='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">';
   public 
$xhtmlDT='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">';
   public 
$xmlLang='en';
   public 
$noChild = Array();
   public 
$keywordArray=Array();
   public 
$descriptionMeta '';
   public 
$generator true;
   public 
$genstring '';
   public 
$chromeFrame false;
   
   private 
$xmlns='http://www.w3.org/1999/xhtml';
   
   public function 
docType($dom,$accept='') {
      
$this->dom $dom;
      
$mime = new stdClass;
      
// default to html
      
$mime->xhtml 0;
      
$mime->html 1;
      if (
strlen($accept) == 0) {
         if (isset(
$_SERVER['HTTP_ACCEPT'])) {
            
$accept strtolower(str_replace('\s+','',$_SERVER['HTTP_ACCEPT']));
            } else {
            
$accept 'text/html';
            }
         }
      
$acceptMime explode(','$accept);
      foreach (
$acceptMime as $a) {
         if (
strpos($a,';q=')) {
            
$foo explode(';q='$a);
            
$mtype $foo[0];
            
$mqual $foo[1];
            } else {
            
$mtype $a;
            
$mqual 1;
            }
         switch (
$mtype) {
            case 
'application/xhtml+xml' :
               
$mime->xhtml $mqual;
               break;
            case 
'text/html' :
               
$mime->html  $mqual;
               break;
            }
         } 
//end foreach
      
if ($mime->xhtml >= $mime->html) {
         
$this->usexml=1;
         } else {
         
$this->usexml=0;
         }
      }
      
   public function 
document() {
      if (
$this->usexml == 0) {
         
$docstring $this->htmlDT '<html></html>';
         } else {
         
$docstring '<?xml version="1.0" encoding="UTF-8"?>' $this->xhtmlDT '<html></html>';
         }   
      
$this->dom->loadXML($docstring);
      
$elements $this->dom->getElementsByTagName('html');
      
$xmlHtml  $elements->item(0);
      if (
$this->usexml == 1) {
         
$xmlHtml->setAttribute('xmlns',$this->xmlns);
         
$xmlHtml->setAttributeNS('http://www.w3.org/XML/1998/namespace','xml:lang',$this->xmlLang);
         }
      return(
$xmlHtml);
      }
      
   public function 
addKeyword($keyword) {
      
$this->keywordArray[] = $keyword;
      }
      
   public function 
addKeyArray($keywords) {
      for (
$i=0;$i<sizeof($keywords);$i++) {
         
$this->addKeyword($keywords[$i]);
         }
      }
      
   public function 
sendpage() {
      
$this->fixHead();
      
$this->sendheader();
      if (
$this->usexml == 1) {
         print 
$this->dom->saveXML();
         } else {
         if (
sizeof($this->noChild) == 0) {
            print 
$this->dom->saveHTML();
            } else {
            for (
$i=0;$i<sizeof($this->noChild);$i++) {
               
$search[]  = '/<\/' $this->noChild[$i] . '>/';
               
$replace[] = '';
               }
            print(
preg_replace($search,$replace,$this->dom->saveHTML()));
            }
         }
      }
      
   private function 
sendheader() {
      if (
$this->usexml == 1) {
         
header('Content-Type: application/xhtml+xml; charset=utf-8');
         } else {
         
header('Content-type: text/html; charset=utf-8');
         }
      }
   
   private function 
fixHead() {
      
$newHead $this->dom->createElement('head');
      
$metaEquiv = Array();
      
// http-equiv first, CSP if present always first
      
$metaName = Array();
      
// meta name second
      
$linkArray = Array();
      
// link third
      
$scriptArray = Array();
      
// script fourth
      
$miscArray = Array();
      
// anything else
      // title last
      
$headtags $this->dom->getElementsByTagName('head');
      
$head $headtags->item(0);
      
$children $head->childNodes;
      foreach (
$children as $child) {
         
$newChild $child->cloneNode(true);
         
$tag $newChild->tagName;
         switch (
$tag) {
            case 
'meta' :
               if (
$newChild->hasAttribute('http-equiv')) {
                  
$equiv $newChild->getAttribute('http-equiv');
                  if (
strcmp($equiv,'X-Content-Security-Policy') == 0) {
                     
$newHead->appendChild($newChild);
                     } else {
                     
$metaEquiv[] = $newChild;
                     }
                  } else {
                  
$metaName[] = $newChild;
                  }
               break;
            case 
'link' :
               
$linkArray[] = $newChild;
               break;
            case 
'script' :
               
$scriptArray[] = $newChild;
               break;
            case 
'title' :
               
$newTitle $newChild;
               break;
            default :
               
$miscArray[] = $newChild;
               break;
            }
         }
      if (
$this->usexml == 0) {
         
$meta $this->dom->createElement('meta');
         
$meta->setAttribute('http-equiv','Content-type');
         
$meta->setAttribute('content','text/html;charset=UTF-8');
         
$newHead->appendChild($meta);
         }
      
$this->detectChrome($newHead);
      for (
$i=0;$i<sizeof($metaEquiv);$i++) {
         
$newHead->appendChild($metaEquiv[$i]);
         }
      if (
$this->generator) {
         if (
strlen($this->genstring) == 0) {
            
$this->genstring 'PHP ' phpversion() . ' DOMDocument / libxml ' LIBXML_DOTTED_VERSION;
            }
         
$meta $this->dom->createElement('meta');
         
$meta->setAttribute('name','generator');
         
$meta->setAttribute('content',$this->genstring);
         
$newHead->appendChild($meta);
         }
      if (
sizeof($this->keywordArray) > 0) {
         
$content implode(',',array_unique($this->keywordArray));
         
$meta $this->dom->createElement('meta');
         
$meta->setAttribute('name','keywords');    
         
$meta->setAttribute('content',$content);
         
$newHead->appendChild($meta);
         }
      if (
strlen($this->descriptionMeta) > 0) {
         
$meta $this->dom->createElement('meta');
         
$meta->setAttribute('name','description');    
         
$meta->setAttribute('content',$this->descriptionMeta);
         
$newHead->appendChild($meta);
         }
      for (
$i=0;$i<sizeof($metaName);$i++) {
         
$newHead->appendChild($metaName[$i]);
         }
      for (
$i=0;$i<sizeof($linkArray);$i++) {
         
$newHead->appendChild($linkArray[$i]);
         }
      for (
$i=0;$i<sizeof($scriptArray);$i++) {
         
$newHead->appendChild($scriptArray[$i]);
         }
      for (
$i=0;$i<sizeof($miscArray);$i++) {
         
$newHead->appendChild($miscArray[$i]);
         }
      if (isset(
$newTitle)) {
         
$newHead->appendChild($newTitle);
         }
      
$head->parentNode->replaceChild($newHead,$head);
      }
      
   private function 
detectChrome($head) {
      if (
$this->chromeFrame) {
         if (isset(
$_SERVER['HTTP_ACCEPT'])) {
            
$accept strtolower($_SERVER['HTTP_ACCEPT']);
            
$test substr_count($accept,'chromeframe');
            if (
$test 0) {
               
$meta $this->dom->createElement('meta');
               
$meta->setAttribute('http-equiv','X-UA-Compatible');
               
$meta->setAttribute('content','chrome=1');
               
$head->appendChild($meta);
               }
            }
         }
      }
   } 
// end of class
   
class html4tranDT extends docType {
   public 
$htmlDT='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
   public 
$xhtmlDT='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
   }
   
class 
html5DT extends docType {
   public 
$htmlDT='<!DOCTYPE html>';
   public 
$xhtmlDT='<!DOCTYPE html>';
   public 
$noChild = Array('source');
   public 
$chromeFrame true;
   }
?>