Go Back   CodingForums.com > :: Server side development > PHP > Post a PHP snippet

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rate Thread
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 01-19-2010, 10:34 AM   PM User | #1
Dormilich
Senior Coder

 
Dormilich's Avatar
 
Join Date: Jan 2010
Location: Behind the Wall
Posts: 2,857
Thanks: 9
Thanked 288 Times in 284 Posts
Dormilich is on a distinguished road
HTML Header Script

This script is intended to ease the output of HTML headers (server and client side). Just define the type, language and encoding of the document and the script will take care of the (X)HTML output. There are additional features built in (deny to serve, custom XHTML), that may come in handy.

PHP Code:
<?php
/*
 *      class.headers.php
 *      
 *      Copyright 2009 Alexander Stranzky <Dormilich@netscape.net>
 *      
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */

###########################################################
# printing DOCTYPE, <HTML>, <HEAD>, <META "content-type"> #
###########################################################

/**
 * Based on the Function by Dave Shea.
 *
 * due to IE's lack of support for "application/xhtml+xml" (XHTML 1.1
 * recommended MIME type) a browser switch (XHTML/HTML) is made. All
 * browsers accepting "application/xhtml+xml" will be served with the 
 * default output (which is currently XHTML 1.0) for all others the
 * output will be buffered and corrected towards HTML 4.01.
 *   XHTML Coders: empty elements that are not empty or don't have an
 * optional closing tag in HTML are thus likely to inflict problems.
 *
 * How to set the options
 * ======================
 * there are 5 options available:
 * - Document MIME type (HTML 4.01, HTML 5, XHTML 1.0, XHTML 1.1, XHTML)
 * - Document language
 * - Document encoding (character set)
 * - Script language MIME type
 * - Stylesheet MIME type (currently disabled)
 * - Denial to Serve (if the MIME type is not supported)
 *
 * of which the first 3 can be set using the class' constructor, but all
 * of them can be set later as they are public properties. Should you choose
 * to take the 'XHTML' MIME type, you need to set the DTD string beforehand.
 * This will be required, when you need to use 'mixed' XHTML types, such as
 * XHTML+SVG, XHTML+MathML, XHTML+RDFa, etc.
 *   You can choose to deny serving XHTML to User Agents (UA) that do not
 * support the set MIME type by setting $errorCode to a HTTP Client Error
 * Code (4xx). A denied document does not contain any data, so UA don't
 * display any message. However you can read the HTTP Response Headers. You
 * can forcibly deny a document by calling the deny() method.
 *   Note that XHTML 1.1 can only be served using "application/xhtml+xml".
 */
class Headers
{
    
/**
     * @const (string) DTD_XHTML_10      XHTML 1.0 Strict DTD
     * @const (string) DTD_XHTML_11      XHTML 1.1 DTD
     * @const (string) DTD_HTML_401      HTML 4.01 Strict DTD
     * @const (string) DTD_HTML_5        HTML 5 DTD
     * @const (string) XMLNS_XHTML       XHTML namespace
     * @const (string) META_TYPE_CSS     meta element defining the default
     *                                   style MIME type
     * @const (string) META_TYPE_JS      meta element defining the default
     *                                   script MIME type
     * @const (string) MIME_TYPE_CSS     MIME type for CSS files
     * @const (string) MIME_TYPE_JS      MIME type for JavaScript files
     * @const (string) MIME_TYPE_XML     MIME type for XML text files
     * @const (string) MIME_TYPE_HTML    MIME type for HTML files
     * @const (string) MIME_TYPE_XHTML   MIME type for XHTML files
     * @var (array) HTTP_ERROR_MSG       HTTP Error Codes 4xx series (RFC 2616)
     * @var (string) $mime               default page MIME type
     * @var (string) $mime_js            JavaScript MIME type (changeable)
     * @var (string) $mime_css           CSS MIME type (changeable)
     * @var (string) $type               default page type ((X)HTML),
     *                                   may be edited by the user
     * @var (string) $encoding           page encoding/charset, 
     *                                   may be edited by the user
     * @var (string) $language           default page language,
     *                                   may be edited by the user
     * @var (string) $dtd                used for a custom DTD
     * @var (mixed) $errorCode           HTTP Error Code to send or false
     *                                   for XHTML -> HTML conversion
     */
    
const DTD_XHTML_10    '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
    const 
DTD_XHTML_11    '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">';
    const 
DTD_HTML_401    '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">';
    const 
DTD_HTML_5      '<!DOCTYPE html>';

    const 
XMLNS_XHTML      'xmlns="http://www.w3.org/1999/xhtml"';

    const 
META_TYPE_CSS   '<meta http-equiv="content-style-type" content="text/css"/>';
    const 
META_TYPE_JS    '<meta http-equiv="content-script-type" content="%s"/>';
    const 
MIME_TYPE_JS    'text/javascript';
    const 
MIME_TYPE_CSS   'text/css';
    const 
MIME_TYPE_XML      'text/xml';
    const 
MIME_TYPE_HTML  'text/html';
    const 
MIME_TYPE_XHTML 'application/xhtml+xml';
    
    protected static 
$HTTP_ERROR_MSG = array(
        
400 => "Bad Request",
        
401 => "Unauthorized",
        
402 => "Payment Required",
        
403 => "Forbidden",
        
404 => "Not Found",
        
405 => "Method Not Allowed",
        
406 => "Not Acceptable",
        
407 => "Proxy Authentication Required",
        
408 => "Request Timeout",
        
409 => "Conflict",
        
410 => "Gone",
        
411 => "Length Required",
        
412 => "Precondition Failed",
        
413 => "Request Entity Too Large",
        
414 => "Request-URI Too Long",
        
415 => "Unsupported Media Type",
        
416 => "Requested Range Not Satisfiable",
        
417 => "Expectation Failed"
    
);

    public 
$mime          'text/html';
    public 
$mime_js       'text/javascript';
/*
    'text/ecmascript'
    'application/javascript'
    'application/ecmascript'
*/
    
public $mime_css      'text/css';
    public 
$type          'XHTML 1.0';
    public 
$encoding      'UTF-8';
    public 
$language      'de';
    public 
$dtd           '';
    public 
$errorCode     false;
    
    
/**
     * determine the supported MIME type. set defaults.
     *
     * @param (string) $encoding   encoding/charset of the document [UTF-8]
     * @param (string) $lang       used language [de]
     * @param (string) $type       used DTD/HTML version [XHTML 1.1]
     * @return (void)
     */
    
public function __construct(
        
$encoding 'UTF-8',
        
$lang     'de',
        
$type     'XHTML 1.0'
    
)
    {
        
$this->type     $type;
        
$this->encoding $encoding;
        
$this->language $lang;
        
# set defaults
        
$this->mime_css self::MIME_TYPE_CSS;
        
$this->mime_js  self::MIME_TYPE_JS;
        
# determine possible MIME type for XHTML
        
$this->changeMIME();
        
$this->specialUA();
    }
    
    
/**
     * setter method for the encoding/charset property.
     *
     * @return (Headers)           instance for chaining
     */
    
public function setEncoding(
        
$charset 'UTF-8'
    
)
    {
        
$this->encoding $charset;
        return 
$this;
    }
    
    
/**
     * setter method for language property.
     *
     * @return (Headers)           instance for chaining
     */
    
public function setLanguage(
        
$lang 'de'
    
)
    {
        
$this->language $lang;
        return 
$this;
    }
    
    
/**
     * setter method for Doctype identifyer.
     *
     * @return (Headers)           instance for chaining
     */
    
public function setDocType(
        
$type 'XHTML 1.0'
    
)
    {
        
$this->type strtoupper($type);
        return 
$this;
    }

    
/**
     * Send a HTTP Status Code of the 4xx series (Client Errors) to the client.
     *
     * @param (int) $code          HTTP Error Code Number
     * @throws (CodeException)     not a Client Error Code
     */
    
public function deny(
        
$code 406
    
)
    {
        if (!isset(
self::$HTTP_ERROR_MSG[$code]))
        {
            
$emsg "Only Client Error HTTP Status Codes supported.";
            throw new 
Exception($emsg);
        }
        
header("HTTP/1.1 $code " self::$HTTP_ERROR_MSG[$code]);
        
header("Status: $code "  self::$HTTP_ERROR_MSG[$code]);
        
header("Connection: Close");
        exit;
    }
    
    
/**
     * send PHP headers and print the (X)HTML headers. if MIME type is set to
     * HTML, start the output correction (XHTML -> HTML) via output buffer.
     *
     * @return (string)            HTML headers
     */
    
public function __toString()
    {
        
# reset MIME type for HTML documents
        
if ('HTML 4.01' == $this->type)
        {
            
$this->mime self::MIME_TYPE_HTML;
            
# otherwise leave it at XHTML
        
}
        
# convenience variable
        
$_isXHTML is_int(strpos($this->type'XHTML'));
        
        
# don't serve XHTML 1.1 to UAs that don't know "application/xhtml+xml"
        
if ('XHTML 1.1' == $this->type and self::MIME_TYPE_XHTML != $this->mime)
        {
            
$this->deny(406);
        }
        
# forcibly don't serve XHTML to UAs that don't know "application/xhtml+xml"
        
if ($_isXHTML and self::MIME_TYPE_XHTML != $this->mime and is_int($this->errorCode))
        {
            
$this->deny($this->errorCode);
        }
        
# remove empty xml tag notation ("/>" -> ">")
        
if ($_isXHTML and self::MIME_TYPE_HTML == $this->mime)
        {
            
ob_start(array($this"fix_code"));
        }
        
# send headers
        
header("Content-Type: " $this->mime ";charset=" $this->encoding);
        
header("Vary: Accept");

        
# choose page type from MIME type
        
if (self::MIME_TYPE_HTML == $this->mime)
        {
            
$type 'HTML 4.01';
        }
        else
        {
            
$type $this->type;
        }
        return 
$this->getHeader($type);
    }
    
    
/**
     * read the q-value (MIME type weighting) from HTTP_ACCEPT and set
     * the according MIME type. if support for XHTML is detected, change
     * the MIME type from HTML (default) to XHTML.
     *
     * @return (void)
     */
    
protected function changeMIME()
    {
        
$preg_xhtml "@application/xhtml\+xml;q=0(\.[1-9]+)@i";
        
$preg_html  "@text/html;q=0(\.[1-9]+)@i";
        
        
# close connection for non-browsers (no Accept header)
        
if (!isset($_SERVER["HTTP_ACCEPT"]))
        {
            
$this->deny(406);
        }
        
    
//    $this->mime = self::MIME_TYPE_HTML;
        
        // change
        # match without q-value
        
if (stristr($_SERVER["HTTP_ACCEPT"], self::MIME_TYPE_XHTML)) 
        {
            
# match with q-value
            
if (preg_match($preg_xhtml$_SERVER["HTTP_ACCEPT"], $matches)) 
            {
                
# compare html/xhtml from q-value
                
$xhtml_q $matches[1];
                if (
preg_match($preg_html$_SERVER["HTTP_ACCEPT"], $matches)) 
                {
                    
$html_q $matches[1];
                    if (
$xhtml_q >= $html_q
                    {
                        
$this->mime self::MIME_TYPE_XHTML;
                    }
                }
            }
            else 
            {
                
$this->mime self::MIME_TYPE_XHTML;
            }
        }
    }
    
    
/**
     * correct the MIME type for some special User Agents that are not
     * correctly recognized by self::changeMIME() or which contain bugs
     * that would lead to errors.
     *
     * @return (bool)              HTTP_USER_AGENT available
     */
    
protected function specialUA()
    {
        if (!isset(
$_SERVER["HTTP_USER_AGENT"]))
        {
            return 
false;
        }
        
# special check for the W3C_Validator
        
if (stristr($_SERVER["HTTP_USER_AGENT"], "W3C_Validator")) 
        {
            
$this->mime self::MIME_TYPE_XHTML;
        }
        
# special check for Shiira
        
if (stristr($_SERVER["HTTP_USER_AGENT"], "Shiira")) 
        {
            
$this->mime self::MIME_TYPE_HTML;
        }
        return 
true;
    }
    
    
/**
     * build the headers (from XML Prolog to <meta>s) according to the
     * set MIME type. 
     *
     * @param (string) $type       MIME type
     * @return (string)               headers formatted for printing
     */
    
public function getHeader(
        
$type 'XHTML'
    
)
    {
        
# XML Prolog
        
$xml '<?xml version="1.0" encoding="' $this->encoding "\" ?>\n";
        
$meta '
    <head>
        <meta http-equiv="content-type" content="' 
$this->mime ';charset=' $this->encoding '"/>';
        
        switch (
$type)
        {
            case 
'XHTML 1.1':
                
# DTD
                
$dtd  self::DTD_XHTML_11 "\n";
                
# <html>
                
$html '<html ' 
                      
self::XMLNS_XHTML 
                      
' xml:lang="' $this->language '">';
                break;

            case 
'XHTML 1.0':
                
# DTD
                
$dtd  self::DTD_XHTML_10 "\n";
                
# <html>
                
$html '<html ' 
                      
self::XMLNS_XHTML 
                      
' xml:lang="' $this->language '"'
                      
' lang="' $this->language '">';
                break;

            
// XHTML special types like XHTML+SVG, XHTML+MathML, etc.
            
case 'XHTML'
                
# DTD
                
$dtd $this->dtd;
                
# <html>
                
$html '<html ' 
                      
self::XMLNS_XHTML 
                      
' xml:lang="' $this->language '">';
                break;
            
            case 
'XHTML 5':
                
# DTD
                
$dtd self::DTD_HTML_5 "\n";;
                
# <html>
                
$html '<html ' 
                      
self::XMLNS_XHTML 
                      
' xml:lang="' $this->language '">';
                break;
            
            case 
'HTML 5':
                
# no XML prolog
                
$xml '';
                
# DTD
                
$dtd self::DTD_HTML_5 "\n";;
                
# <html>
                
$html '<html lang="' $this->language '">';
                break;
            
            case 
'HTML 4.01':
            default:
                
# no XML prolog
                
$xml '';
                
# DTD
                
$dtd  self::DTD_HTML_401 "\n";
                
# <html>
                
$html '<html lang="' $this->language '">';
                
# <meta>
                
break;
        }
        
        
$header $xml $dtd $html $meta 
                
"\n\t\t" self::META_TYPE_CSS 
                
"\n\t\t" sprintf(self::META_TYPE_JS,  $this->mime_js);
        return 
$header;
    }

    
/**
     * convert XHTML to HTML (basicly treating the empty elements)
     *
     * @param (string) $buffer     content from the output buffer
     * @return (string)               HTML code to send to the browser
     */
    
public function fix_code($buffer
    {
        return (
str_replace("/>"">"$buffer));
    }
}     
?>
example usage:
PHP Code:
<?php
echo new Headers("ISO-8859-1""en");
?>

// output IE
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
    <head>
        <meta http-equiv="content-type" content="text/html;charset=ISO-8859-1">
        <meta http-equiv="content-style-type" content="text/css">
        <meta http-equiv="content-script-type" content="text/javascript">

// output other browsers
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <meta http-equiv="content-type" content="application/xhtml+xml;charset=ISO-8859-1"/>
        <meta http-equiv="content-style-type" content="text/css"/>
        <meta http-equiv="content-script-type" content="text/javascript"/>
PHP Code:
<?php
$h 
= new Headers;
$h->setDocType("XHTML 1.1")
  ->
mime_js "application/ecmascript";
echo 
$h;
?>
// output IE

// output other browsers
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de">
    <head>
        <meta http-equiv="content-type" content="application/xhtml+xml;charset=UTF-8"/>
        <meta http-equiv="content-style-type" content="text/css"/>
        <meta http-equiv="content-script-type" content="application/ecmascript"/>
Note on the attached file: this script uses a custom Exception for better Error Handling, thus change line #218 apropriately.
Attached Files
File Type: zip class.headers.php.zip (4.8 KB, 105 views)

Last edited by Dormilich; 01-19-2010 at 10:43 AM..
Dormilich is offline   Reply With Quote
Reply

Bookmarks

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 10:06 PM.


Advertisement
Log in to turn off these ads.