accessibility.php

<?php

// $Id: accessibility.php,v 1.2 2008/03/04 10:09:27 jaburns Exp $

/**
 * @file
 * Part of accessibility.module
 * Can be used as stand alone script
 * Depends on 'browser.inc' -> list of know handheld devices
 *
 * @functions
 * is_mobi() returns TRUE or FALSE dependant on the device browsing the site
 * content_type() returns integer that should be linked to $mime['types']
 *
 * @author Jamie Burns <http://www.skiffie.com/>
 * @link http://www.skiffie.com/
 */

//~ For PHP < 5
if (!function_exists('stripos')) {
    function stripos($haystack, $needle, $offset=0) {
        return strpos(strtolower($haystack), strtolower($needle), $offset);
    }
}

//~ $mime['VARS'] must be in order
global $mime;
$mime['types'] = array (
  'none',
  'xhtml',
  'html',
  'mhtml',
  'wml',
  'chtml'
);

$mime['xml']   = array (1,3,4);
$mime['mobis'] = array (3,4,5);
$mime['mhtml'] = 3;
$mime['wml']   = 4;
$mime['chtml'] = 5;
$mime['nodes'] = 1;

$mime['theme'] = array(
  0 => 'web2', 
  1 => 'web2',
  2 => 'web2',
  3 => 'mobi',
  4 => 'wap',
  5 => 'mobi'
);


$mime['desc'] = array (
  'No Override',
  'XHTML',
  'HTML',
  'XHTML MP',
  'WML',
  'HTML BASIC'
);

$mime['content'] = array (
  'text/html',
  'application/xhtml+xml',
  'text/html',
  'application/vnd.wap.xhtml+xml',
  'text/vnd.wap.wml',
  'text/html'
);

$mime['dtds'] = array (
    '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'."\n",
    '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'."\n",
    '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'."\n",
    '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" 
    "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile11.dtd"> '."\n",
    '<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">',
    '<!DOCTYPE html PUBLIC "-//W3C//DTD Compact HTML 1.0 Draft//EN">'."\n"
            );

//~ Some extra user_agent strings to check for
global $imode;
$imode = array ('doco', 'j-pho', 'up.b', 'ddip', 'port');
global $extra;
$extra = array ('MIDP', 'symbian', 'phone', 'palm', 'ipaq', 'Googlebot-Mobile');

global $xml;
$xml   = '<?xml version="1.0" encoding="utf-8"?>'."\n";
global $dir;
$dir   = dirname(__FILE__) .'/browser.inc';
global $fix;
$fix = (isset($fix)) ? $fix : FALSE;
//~ Extra function to catch additional mobi parameters: returns > 0 if TRUE
function extra(&$extra) {
$count = 0;

if (is_array($extra)) {
  foreach($extra as $findme) {
  if ( @stripos(@$_SERVER['HTTP_USER_AGENT'], $findme) !== FALSE ) {
  $count++;
  }
  }
} else {
  if ( @stripos(@$_SERVER['HTTP_USER_AGENT'], $extra) !== FALSE ) {
  $count++;
  }
}
return $count;
}

//~ Is the device a mobile ?
function is_mobi($override = FALSE) {
global $imode, $extra, $dir;

  $browsers = file( $dir );
  foreach ($browsers as $dev) { 
    $browserlist [] = trim($dev);
  }
  if ($override == TRUE) {
  return $override;
  } elseif (
  @in_array(strtolower(substr(trim(@$_SERVER['HTTP_USER_AGENT']),0,4)), $browserlist) OR
  @in_array(strtolower(substr(trim(@$_SERVER['HTTP_USER_AGENT']),0,4)), $imode) OR 
  extra($extra) > 0  
  ) { 
  return TRUE;
  } else {
  return FALSE;
  }
}

//~ Establish best suited content type
function content_type () {
global $mime, $accessibility;
$is_mobi = (isset($accessibility['is_mobi'])) ? $accessibility['is_mobi'] : FALSE;

$accept = array();
foreach ($mime['types'] as $lang => $val){
    $accept[$val] = $mime['content'][$lang];
    }

//~ remove unwanted elements
$unused = array_shift($accept);
$unused = array_pop($accept);

$c = array();

if ( !isset($_SERVER["HTTP_ACCEPT"]) OR empty($_SERVER["HTTP_ACCEPT"]) ) {
$c['html'] = 1;
} else {

foreach ($accept as $mime_lang => $mime_type) {
  $esc_type = '/'. str_replace( array ('/','.','+'), array('\/','\.','\+'), $mime_type) .";q=0(\.[1-9]+)/i";
  $c[$mime_lang] = 1;
  if ( @stristr(@$_SERVER["HTTP_ACCEPT"], $mime_type) ) {
  $c[$mime_lang] = $c[$mime_lang] + 1;
    if (preg_match($esc_type, @$_SERVER["HTTP_ACCEPT"], $matches)) {
    $c[$mime_lang] = $c[$mime_lang] - (float)$matches[1];
    } // end if pregmatch
  } // end if stristr
} // end foreach accept

}

  arsort ($c,  SORT_NUMERIC);

  if ( array_sum($c) == count($c) ){
    unset ( $c );
    $c['html'] = 1;	
  } // end array_sum
	 
  $max = max($c);
  foreach ($c as $type => $val) {
  if ($val != $max) { unset ( $c[$type] ); }
  } // end foreach
		
    if ( array_key_exists('xhtml', $c) ) { unset ( $c ); $c['xhtml'] = 1; }
    if ( array_key_exists('html',  $c) ) { unset ( $c ); $c['html'] = 1;}            
    if ( array_key_exists('html',  $c) AND $is_mobi === TRUE ) { unset ( $c ); $c['chtml'] = 1;}            
    if ( array_key_exists('wml',   $c) ) { unset ( $c ); $c['wml'] = 1; }
    if ( array_key_exists('mhtml', $c) ) { unset ( $c ); $c['mhtml'] = 1; }
    if ( stristr(@$_SERVER["HTTP_USER_AGENT"], 'W3C_Validator') ) { unset ( $c ); $c['xhtml'] = 1; }
    
return array_search(key($c), $mime['types']);

}

//~ Make code WML compatible
function wmlfix($buffer) {
global $fix;
  $buffer = str_replace('Submitted by', '<p>Submitted by', $buffer); 
  $buffer = str_replace('<!--np-->', '<p>', $buffer); 
  $buffer = preg_replace('/<a href="\/taxonomy(.*?)class="feed-icon">(.*?)<\/a>/ims', '', $buffer); 
  $buffer = preg_replace('/<a id="comment">(.*?)<\/a>/ims', '', $buffer);  
  $buffer = preg_replace('/<span class="terms">(.*?)<\/span>/ims', '$1<br /><br />', $buffer); 
  $buffer = preg_replace('/<div class="service-label">(.*?)<\/div>/ims', '', $buffer); 
  $buffer = preg_replace('/<div class="service-links">(.*?)<\/div>/ims', '', $buffer);
  $buffer = str_replace('<div class="pager">', '<p>', $buffer);
  $buffer = str_replace('</a><', '</a> <', $buffer); 
  $buffer = preg_replace('#<div(.*?)>#', '', $buffer);
  $buffer = str_replace('</div>', ' ', $buffer); 
  $buffer = str_replace('<hr />', '', $buffer); 
  $buffer = preg_replace('# class="(.*?)"#', '', $buffer);     
  $buffer = preg_replace('# rel="(.*?)"#', '', $buffer);     
  $buffer = preg_replace('#p id="(.*?)"#', 'p', $buffer);     
  $buffer = preg_replace('#p class="(.*?)"#', 'p', $buffer);      
  $buffer = preg_replace('# style="(.*?)"#', '', $buffer); 
  $buffer = preg_replace('# title="(.*?)"#', '', $buffer);
  $buffer = preg_replace('/<a href="\/comment(.*?)<\/a>/ims', '', $buffer); 
  $buffer = preg_replace('/<a href="?q=comment(.*?)<\/a>/ims', '', $buffer); 
  $buffer = preg_replace('#<h(.*?)>#', '<p><big>', $buffer); 
  $buffer = preg_replace('#</h(.*?)>#', "</big></p>\n", $buffer); 
  $buffer = preg_replace('#<img (.*?) />#', '', $buffer); 
  $buffer = preg_replace('#<ul(.*?)>#', '<p>', $buffer);
  $buffer = preg_replace('#<ol(.*?)>#', '<p>', $buffer);
  $buffer = preg_replace('#<dl(.*?)>#', '<p>', $buffer);
  $buffer = preg_replace('/<form(.*?)\/form>/ims', '<p>Please make comments through website!</p>', $buffer);
  $buffer = str_replace('<dt>', '<strong>', $buffer); 
  $buffer = str_replace('</dt>', '</strong><br />', $buffer); 
  $buffer = str_replace('<dd>', '', $buffer); 
  $buffer = str_replace('</dd>', '<br />', $buffer); 
  $buffer = str_replace('<li>', '', $buffer); 
  $buffer = str_replace('</li>', '<br />', $buffer); 
  $buffer = str_replace('</dl>', '</p>', $buffer); 
  $buffer = str_replace('</ul>', '</p>', $buffer); 
  $buffer = str_replace('</ol>', '</p>', $buffer); 
  $buffer = str_replace('</p></p>', '</p>', $buffer); 
  $buffer = str_replace('<span>', '', $buffer); 
  $buffer = str_replace('</span>', '', $buffer);
  $buffer = str_replace('<acronym>', '(', $buffer); 
  $buffer = str_replace('</acronym>', ')', $buffer); 
  $buffer = str_replace('<code>', '<em>', $buffer); 
  $buffer = str_replace('</code>', '</em>', $buffer);
  $buffer = str_replace('<legend>', '<big>', $buffer); 
  $buffer = str_replace('</legend>', '</big><br />', $buffer);  
  $buffer = str_replace('cardid', 'id', $buffer); 
  $buffer = str_replace('cardtitle', 'title', $buffer);
  $buffer = str_replace('cardname', 'name', $buffer);
  $buffer = str_replace('cardtype', 'type', $buffer);
  $buffer = str_replace('cardlabel', 'label', $buffer);
  $buffer = str_replace('<p><big></big></p>', '', $buffer);
  $buffer = str_replace('<p></p>', '', $buffer);
  $buffer = str_replace('</strong><a', '</strong> <a', $buffer);
  $buffer = str_replace('&lt;', '&#60;', $buffer);  
  $buffer = str_replace('Dev News', 'News', $buffer);  
  $buffer = str_replace('Site Updates', 'Updates', $buffer);  
  $buffer = str_replace('>[7] Prev', ' accesskey="7">[7] Prev', $buffer);  
  $buffer = str_replace('>Next [9]', ' accesskey="9">Next  [9]', $buffer);
  
  return fix($buffer, $fix);
  
}

//~ Make code mobile compatible, strip out some extras
function mobifix($buffer) {
global $fix;
  $buffer = preg_replace('/<a href="\/comment(.*?)<\/a>/ims', '', $buffer); 
  $buffer = preg_replace('/<a href="?q=comment(.*?)<\/a>/ims', '', $buffer); 
  $buffer = str_replace('&lt;', '&#60;', $buffer);  
  $buffer = str_replace('&nbsp;', '&#160;', $buffer);  
  $buffer = preg_replace('/<div class="service-label">(.*?)<\/div>/ims', '', $buffer); 
  $buffer = preg_replace('/<div class="service-links">(.*?)<\/div>/ims', '', $buffer);
  $buffer = preg_replace('/<a id="comment">(.*?)<\/a>/ims', '', $buffer);
  $buffer = preg_replace('/<a href="\/taxonomy(.*?)class="feed-icon">(.*?)<\/a>/ims', '', $buffer); 
  $buffer = preg_replace('/<span title="comment">(.*?)<\/span>/ims', 'Visit the website to post comments', $buffer); 
  $buffer = str_replace('</a><', '</a> <', $buffer); 
  $buffer = str_replace('</strong><a', '</strong> <a', $buffer); 
  $buffer = str_replace('Dev News', 'News', $buffer);  
  $buffer = str_replace('Site Updates', 'Updates', $buffer);  
  $buffer = str_replace('>[7] Prev', ' accesskey="7">[7] Prev', $buffer);  
  $buffer = str_replace('>Next [9]', ' accesskey="9">Next  [9]', $buffer);
  return fix($buffer, $fix);
}

//~ Make code HTML compatible
function htmlfix($buffer) {
  $buffer = preg_replace("!\s*/>!", ">", $buffer);
  return mobifix($buffer);
}

//~ Make code XHTML compatible
function fix($buffer, $fix = FALSE) {

if ($fix == FALSE) {
return $buffer;
} else {

/**
 * This segment is based on htmlcorrector module was made by Steven Wittens <unconed@drop.org>
 */
 
  $nonesting = array('li', 'p');
  // Single use tags in HTML4
  $singleuse = array('base', 'meta', 'link', 'hr', 'br', 'param', 'img', 'area', 'input', 'col', 'frame', 'go');
  // Properly entify angles
  $text = preg_replace('!<([^a-zA-Z/])!', '&lt;\1', $buffer);
  // Splits tags from text
  $split = preg_split('/<([^>]+?)>/', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
  // Note: PHP ensures the array consists of alternating delimiters and literals
  // and begins and ends with a literal (inserting $null as required).
  $tag = false; // Odd/even counter. Tag or no tag.
  $stack = array();
  $output = '';
  foreach ($split as $value) {
    // HTML tag
    if ($tag) {
      list($tagname) = explode(' ', strtolower($value), 2);
      // Closing tag
      if ($tagname{0} == '/') {
        $tagname = substr($tagname, 1);
        if (!in_array($tagname, $singleuse)) {
          // See if we have other tags lingering first, and close them
          while (($stack[0] != $tagname) && count($stack)) {
            $output .= '</'. array_shift($stack) .'>';
          }
          // If the tag was not found, just leave it out;
          if (count($stack)) {
            $output .= '</'. array_shift($stack) .'>';
          }
        }
      }
      // Opening tag
      else {
        // See if we have an identical tag already open and close it if desired.
        if (count($stack) && ($stack[0] == $tagname) && in_array($stack[0], $nonesting)) {
          $output .= '</'. array_shift($stack) .'>';
        }
        // Push non-single-use tags onto the stack
        if (!in_array($tagname, $singleuse)) {
          array_unshift($stack, $tagname);
        }
        // Add trailing slash to single-use tags as per X(HT)ML.
        else {
          $value = rtrim($value, ' /') . ' /';
        }
        $output .= '<'. $value .'>';
      }
    }
    else {
      // Passthrough
      $output .= $value;
    }
    $tag = !$tag;
  }
  // Close remaining tags
  while (count($stack) > 0) {
    $output .= '</'. array_shift($stack) .'>';
  }
  return str_replace (array('&lt;','<p></p>'), array('<',''), $output );
}
}