Location: PHPKode > projects > OpenWolf Guidelines Validator > openWolf 0.9.9/nz/rules.php
<?php

/*************************************************

openWolf - an HTML accessibility guidelines validator
Author: Geoff Munn (hide@address.com)
Version: 0.9.9

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.

You may contact the author of openWolf by e-mail at: hide@address.com

The latest version of openWolf can be obtained from:
http://openwolf.sourceforge.net/

*************************************************/

//GLOBAL TODO LIST:
/*
Check that all user checks are actually appropriately labeled... some could be warnings for instance.
Remove all examples of getAllElements.  The lookup tables are much faster
Fix up all the dictionaries to not use byref arrays
*/

function rules($parse, $colours){
	
	$results=Array();
	
	$results['NZ_S_1_1']=NZ_S_1_1($parse);
	$results['NZ_S_1_2']=NZ_S_1_2($parse);
	$results['NZ_S_1_3']=NZ_S_1_3($parse);
	$results['NZ_S_1_4']=NZ_S_1_4($parse);
	$results['NZ_S_2_1']=NZ_S_2_1($parse, $colours);
	$results['NZ_S_2_2']=NZ_S_2_2($parse, $colours);
	$results['NZ_S_3_1']=NZ_S_3_1($parse);
	$results['NZ_S_3_2']=NZ_S_3_2($parse);
	$results['NZ_S_3_3']=NZ_S_3_3($parse);
	$results['NZ_S_3_4']=NZ_S_3_4($parse);
	$results['NZ_S_4_1']=NZ_S_4_1($parse);
	$results['NZ_S_4_2']=NZ_S_4_2($parse);
	$results['NZ_S_4_3']=NZ_S_4_3($parse);
	$results['NZ_S_4_4']=NZ_S_4_4($parse);
	$results['NZ_S_4_5']=NZ_S_4_5($parse);
	$results['NZ_S_5_1']=NZ_S_5_1($parse);
	$results['NZ_S_5_2']=NZ_S_5_2($parse);
	$results['NZ_S_5_3']=NZ_S_5_3($parse);
	$results['NZ_S_5_4']=NZ_S_5_4($parse);
	$results['NZ_S_5_6']=NZ_S_5_6($parse);
	$results['NZ_S_5_7']=NZ_S_5_7($parse);
	$results['NZ_S_6_1']=NZ_S_6_1($parse);
	$results['NZ_S_6_2']=NZ_S_6_2($parse);
	$results['NZ_S_6_3']=NZ_S_6_3($parse);
	$results['NZ_S_6_4']=NZ_S_6_4($parse);
	$results['NZ_S_6_5']=NZ_S_6_5($parse);
	$results['NZ_S_6_6']=NZ_S_6_6($parse);
	$results['NZ_S_7_1']=NZ_S_7_1($parse);
	$results['NZ_S_7_2']=NZ_S_7_2($parse);
	$results['NZ_S_7_3']=NZ_S_7_3($parse);
	$results['NZ_S_7_4']=NZ_S_7_4($parse);
	$results['NZ_S_8_1']=NZ_S_8_1($parse);
	$results['NZ_S_8_2']=NZ_S_8_2($parse);
	$results['NZ_S_8_3']=NZ_S_8_3($parse);
	$results['NZ_S_8_4']=NZ_S_8_4($parse);
	$results['NZ_S_9_1']=NZ_S_9_1($parse);
	$results['NZ_S_9_2']=NZ_S_9_2($parse);
	$results['NZ_S_10_1']=NZ_S_10_1($parse);
	$results['NZ_S_10_2']=NZ_S_10_2($parse);
	$results['NZ_S_11_1']=NZ_S_11_1($parse);
	$results['NZ_S_11_2']=NZ_S_11_2($parse);
	$results['NZ_S_11_3']=NZ_S_11_3($parse);
	$results['NZ_S_11_4']=NZ_S_11_4($parse);
	$results['NZ_S_12_1']=NZ_S_12_1($parse);
	$results['NZ_S_13_1']=NZ_S_13_1($parse);
	$results['NZ_S_13_2']=NZ_S_13_2($parse);
	$results['NZ_S_14_1']=NZ_S_14_1($parse);
	$results['NZ_S_14_2']=NZ_S_14_2($parse);
	$results['NZ_S_15_1']=NZ_S_15_1($parse);
	$results['NZ_S_15_2']=NZ_S_15_2($parse);
	$results['NZ_S_15_3']=NZ_S_15_3($parse);
	$results['NZ_S_15_4']=NZ_S_15_4($parse);
	$results['NZ_S_16_1']=NZ_S_16_1($parse);
	$results['NZ_S_16_2']=NZ_S_16_2($parse);
	$results['NZ_S_16_3']=NZ_S_16_3($parse);
	$results['NZ_S_16_4']=NZ_S_16_4($parse);
	$results['NZ_S_16_5']=NZ_S_16_5($parse);
	$results['NZ_S_16_6']=NZ_S_16_6($parse);
	$results['NZ_S_16_7']=NZ_S_16_7($parse);
	$results['NZ_S_17_1']=NZ_S_17_1($parse);
	$results['NZ_S_18_1']=NZ_S_18_1($parse);
	$results['NZ_S_19_1']=NZ_S_19_1($parse);
	$results['NZ_S_19_2']=NZ_S_19_2($parse);
	$results['NZ_S_19_3']=NZ_S_19_3($parse);
	$results['NZ_S_19_4']=NZ_S_19_4($parse);
	$results['NZ_S_20_1']=NZ_S_20_1($parse);
	$results['NZ_S_21_1']=NZ_S_21_1($parse);
	$results['NZ_S_21_2']=NZ_S_21_2($parse);
	$results['NZ_S_22_1']=NZ_S_22_1($parse);
	$results['NZ_S_22_2']=NZ_S_22_2($parse);
	$results['NZ_S_22_3']=NZ_S_22_3($parse);
	$results['NZ_S_23_1']=NZ_S_23_1($parse);
	$results['NZ_S_23_2']=NZ_S_23_2($parse);
	$results['NZ_S_23_3']=NZ_S_23_3($parse);
	//create anchors for each of these:
	foreach($results as $rule_key => $val){
		$anchor=substr($rule_key,3);
		$results[$rule_key]['anchor']=$anchor;
	}
	
	return $results;
}

function NZ_S_1_1($parse){
	//Provide a text equivalent for every non-text element (for example alt, longdesc or in element content). This includes: images, graphical representations of text (including symbols),
	//image map regions, animations (for example, animated GIFs), applets and programmatic options, ASCII art, frames, scripts, images used as list bullets, spacers, graphical buttons, 
	//sounds (played with or without user interaction), standalone audio files, audio tracks of video, and video.
	
	//Priority:		Standard

	//Techniques:	

	//TODO: check that the longdesc is a valid URI and that it is HTML
	//TODO:	The file size check on alt text will not detect anything in shorthand, ie 10KB
	//TODO:	Should the long alt text check apply for applets and objects?
	
	$timeout=get_timeout();
	
	create_message('1.1', 'Provide a text equivalent for every non-text element (for example alt, longdesc or in element content). This includes: images, graphical representations of text (including symbols), image map regions, animations (for example, animated GIFs), applets and programmatic options, ASCII art, frames, scripts, images used as list bullets, spacers, graphical buttons, sounds (played with or without user interaction), standalone audio files, audio tracks of video, and video.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h1';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagName('img');
	
	//Put all of the images into an array so we can identify decorative images
	$images=Array();
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$src=$parse->src($this_element);
		
		if(!isset($images[$src]))
			$images[$src]=false;
		else
			$images[$src]=true;
		
	}
	
	$timeout=get_timeout();
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
		
		$alt=trim($parse->getAttribute($this_element, 'alt', true));
		$specified=$parse->specified($this_element, 'alt');
		$src=$parse->src($this_element);
		
		if(!$specified){
			$result_key='This image is missing an \'alt\' attribute.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='If this image is not purely decorative, then you could put a short description of the image in an alt attribute, for example, alt=&quot;Company logo&quot;<br>If it is decorative, then an empty alt attribute should be fine.';
			$hasFailed=true;
		}
		if($alt=='' && $specified && $images[$src]==false){
			//check to see if the height and width attributes are both less than 10 pixels
			$width=$parse->getAttribute($this_element, 'width');
			$height=$parse->getAttribute($this_element, 'height');
			if($width>10 || $height>10 || $width=='' || $height==''){
				$result_key='The \'alt\' attribute value is empty.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
				$results['instances'][$result_key]['highlight_attribute'][]='alt';
				$results['instances'][$result_key]['info'][]='If this image is not purely decorative, then you could put a short description of the image in an alt attribute, for example, alt=&quot;Company logo&quot;<br>If it is decorative, then an empty alt attribute should be fine.';
				$hasFailed=true;
			}
		}
		if(substr($alt, -5)=='bytes'){
			$result_key='The \'alt\' attribute value seems to be a file size (it ends with \'bytes\').';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='alt';
			$results['instances'][$result_key]['info'][]='Alt text should not consist solely of the image file name or file size.  Try using a more descriptive sentence.';
		}
		if(substr($alt,-3)=='jpg' || substr($alt,-3)=='gif' || substr($alt, -4)=='jpeg' || substr($alt, -3)=='png' || substr($alt, -3)=='bmp'){
			$result_key='The \'alt\' attribute value ends with an image file suffix.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='alt';
			$results['instances'][$result_key]['info'][]='Alt text should not consist solely of the image file name or file size.  Try using a more descriptive sentence.';
			$hasFailed=true;
		}
		if(strlen($alt)>150){
			$result_key='The \'alt\' attribute value is longer than 150 characters. Perhaps a description file could be created.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='alt';
			$results['instances'][$result_key]['info'][]='Very long alt text should be moved into a separate file, and referenced through the longdesc attribute.';
			$hasFailed=true;
		}
	}
	
	$temp=$parse->getElementsByTagname('input');
	
	$timeout=get_timeout();
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$type=$parse->getAttribute($this_element, 'type');
		if($type=='image'){
			$alt=trim($parse->getAttribute($this_element, 'alt', true));
			$specified=$parse->specified($this_element, 'alt');
			if(!$specified){
				$result_key='This form image is missing an \'alt\' attribute.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$results['instances'][$result_key]['info'][]='If this image is not purely decorative, then you could put a short description of the image in an alt attribute, for example, alt=&quot;Company logo&quot;<br>If it is decorative, then an empty alt attribute should be fine.';
				$hasFailed=true;
			}
			if($alt==''  && $specified){
				$result_key='The \'alt\' attribute value is empty.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
				$results['instances'][$result_key]['highlight_attribute'][]='alt';
				$results['instances'][$result_key]['info'][]='If this image is not purely decorative, then you could put a short description of the image in an alt attribute, for example, alt=&quot;Company logo&quot;<br>If it is decorative, then an empty alt attribute should be fine.';
				$hasFailed=true;
			}
			if(substr($alt, -5)=='bytes'){
				$result_key='The \'alt\' attribute value seems to be a file size (it ends with \'bytes\').';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
				$results['instances'][$result_key]['highlight_attribute'][]='alt';
				$results['instances'][$result_key]['info'][]='Alt text should not consist solely of the image file name or file size.  Try using a more descriptive sentence.';
				$hasFailed=true;
			}
			if(substr($alt,-3)=='jpg' || substr($alt,-3)=='gif' || substr($alt, -4)=='jpeg' || substr($alt, -3)=='png' || substr($alt, -3)=='bmp'){
				$result_key='The \'alt\' attribute value ends with an image file suffix.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
				$results['instances'][$result_key]['highlight_attribute'][]='alt';
				$results['instances'][$result_key]['info'][]='Alt text should not consist solely of the image file name or file size.  Try using a more descriptive sentence.';
				$hasFailed=true;
			}
		}		
	}
	
	$temp=$parse->getElementsByTagname('applet');
	
	$timeout=get_timeout();
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$type=$parse->getAttribute($this_element, 'type');
		$text=trim($parse->innerText($this_element));
		
		if(!$parse->specified($this_element, 'alt') && $text==''){
			$result_key='This applet is missing a text equivalent.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='This applet element should contain some text describing the applet either within the alt attribute, or within the element itself.';
			$hasFailed=true;
		}
		
		//TODO: won't the next rule get triggered at the same time as the one above?
		$alt=trim($parse->getAttribute($this_element, 'alt', true));
		$specified=$parse->specified($this_element, 'alt');
		if(!$specified){
			$result_key='The \'alt\' attribute value is not specified.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='This applet element should include an alt attribute describing what the applet does.';
			$hasFailed=true;
		}
		if(trim($alt)=='' && $specified){
			$result_key='The \'alt\' attribute value is empty.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='alt';
			$hasFailed=true;
		}
		if(substr($alt, -5)=='bytes'){
			$result_key='The \'alt\' attribute value seems to be a file size (it ends with \'bytes\').';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='alt';
			$hasFailed=true;
		}
		if(substr($alt,-6)=='.class' || substr($alt,-5)=='.java' || substr($alt, -4)=='.jar' || substr($alt, -4)=='.zip'){
			$result_key='The \'alt\' attribute value ends with a java file suffix.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='alt';
			$hasFailed=true;
		}
	}
	
	$temp=$parse->getElementsByTagname('object');
	
	$timeout=get_timeout();
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$type=$parse->getAttribute($this_element, 'type', true);
		$mime=substr($type, 0, 6);
		
		if($mime=='image/'){
			//does this object element contain at least one word of text or an image element:
			$innerText=$parse->innerText($this_element);
			$imgs=$parse->all_descendants($this_element, 'img');
			if(strlen(trim($innerText))==0 && count($imgs)==0){
				$result_key='This object element is missing an alternative representation.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
		
		if($mime=='audio/' || $mime=='video/'){
			$result_key='Audio and video files require a text equivalent. Is there an associated text equivalent for this audio or video file?';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='data';
			$hasFailed=true;
		}	
	}
	
	$temp=$parse->getElementsByTagname('a');
	$sound_files=load_sound_extensions();
	
	$timeout=get_timeout();
		
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$href=$parse->href($this_element);
		$href2=$parse->getAttribute($this_element, 'href');
		$extension=strtolower(get_extension($href));
		if(array_key_exists($extension, $sound_files)){
			$result_key='Audio files require a text equivalent. Is there an associated text equivalent for this audio file: ' . $href2 . '?';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='href';
			$hasFailed=true;
		}
	}
	
	$temp=$parse->getElementsByTagname('frame');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		//TODO: check that the longdesc is a valid URI and that it is HTML
		$longdesc=trim($parse->getAttribute($this_element, 'longdesc'));
		if($longdesc==''){
			$result_key='This frame is missing a longdesc attribute.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}	
	}
	
	$temp=$parse->getElementsByTagname('frameset');
	
	$timeout=get_timeout();
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$frames=$parse->all_descendants($this_element, 'frame');
		if(count($frames)>2){
			for($i=0;$i<count($frames);$i++){
				$longdesc=trim($parse->getAttribute($this_element, 'longdesc'));
				if($longdesc==''){
					$result_key='Is the relationship between the frames clear for the user?';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_WARNING;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
					break;					
				}
			}
		}
	}
	
	$temp=$parse->getElementsByTagname('iframe');
	
	$timeout=get_timeout();
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$longdesc=trim($parse->getAttribute($this_element, 'longdesc'));
		//TODO: check that the longdesc is a valid URI and that it is HTML
		if($longdesc==''){
			$result_key='This iframe is missing a longdesc attribute.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}	
	}
	
	//NOTE: perhaps this should use the specifed approach instead? And also check for empty alt text
	$temp=$parse->getElementsByTagname('area');
	
	$timeout=get_timeout();
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$alt=$parse->getAttribute($this_element, 'alt');
		//Todo: put in suspicious placeholder text
		if(trim($alt)==''){
			$result_key='This image map area is missing an \'alt\' text attribute.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	$temp=$parse->getElementsByTagname('script');
	$bodys=$parse->getElementsByTagname('body');
	$all=$parse->getAllElements();
	
	$timeout=get_timeout();
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		if($this_element>$bodys[0]){
			//is the next element a <noscript> element?
			//checking for a closing tag will stop the {else} bit from working (false positives are generated)
			if($all[$this_element+2]['tagname']!='noscript'){
				$result_key='This script element is missing a <code>noscript</code> alternative.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			} else {
				$innerHTML=$parse->innerHTML($this_element+2);
				if(trim($innerHTML)==''){
					$result_key='This noscript element does not contain accessible HTML.';
					$results['instances'][$result_key]['indices'][]=$this_element+2;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
				}				
			}
		}	
	}
	
	if(!$hasFailed){
		$result_key='A text equivalent was provided for every non-text element.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('1.1', $error_type);
	
	return $results;
}

function NZ_S_1_2($parse){
	//Client side image maps are preferred over server side image maps. You must also provide redundant text links for each active region of any image map, and locate the links as close as possible to the image map they relate to.
	
	//Priority:		Must
	
	//Techniques:	Find any <img> elements with ismap=true
	
	//Comments:		Server side image maps don't reveal their destinations, so I can't check to see if there are redundant links present
	$timeout=get_timeout();
	
	create_message('1.2', 'Client side image maps are preferred over server side image maps. You must also provide redundant text links for each active region of any image map, and locate the links as close as possible to the image map they relate to.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h1';
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('img');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->specified($this_element, 'ismap')==true){
				$result_key='All server-side image maps should have associated text links in the document.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$results['instances'][$result_key]['info'][]='Try placing a text link to the same destination elsewhere in this document.';
				$hasFailed=true;
			}
		} 
		if(!$hasFailed){
			$result_key='No server-side image maps were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No server-side image maps were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('1.2', $error_type);
	
	return $results;
}

function NZ_S_1_3($parse){
	//Until user agents can automatically read aloud the text equivalent of a visual track, provide an auditory description of the important information of the visual track of a multimedia presentation.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#auditory-descriptions
	
	$timeout=get_timeout();
	
	create_message('1.3', 'Until user agents can automatically read aloud the text equivalent of a visual track, provide an auditory description of the important information of the visual track of a multimedia presentation.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h1';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('object');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$type=$parse->getAttribute($this_element, 'type', true);
		if(substr($type, 0, 5)=='video'){
			$result_key='All multimedia presentations should have an associated audio description.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	if(!$hasFailed){
		$result_key='No multimedia presentations were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('1.3', $error_type);
	
	return $results;
}

function NZ_S_1_4($parse){
	//The dimensions applied should be the actual dimensions of the image.
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		We get each image and check the height and width attributes
	
	//NOTE:			This does not check to see if it is the precise, actual dimensions of the image, just that there
	//				are some specified...
	
	$timeout=get_timeout();
	
	create_message('1.4', 'The dimensions applied should be the actual dimensions of the image.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h1';
	
	$hasFailed=false;
	$temp=$parse->getElementsByTagname("img");
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			//Note; an unspecified height or width attribute will return blank as well
			$width=$parse->getAttribute($this_element, 'width');
			$height=$parse->getAttribute($this_element, 'height');
			
			if($width==''){
				$result_key='Images with a missing width attribute were found.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				
				$hasFailed=true;
			}
			
			if($height==''){
				$result_key='Images with missing a height attributes were found.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
		if(!$hasFailed){
				$result_key='All images have height and width attributes.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No images were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('1.4', $error_type);
	
	return $results;
}

function NZ_S_2_1($parse, $colours){
	//Ensure that all information conveyed with color is also available without color, for example from context or markup.

	//Priority:		Must
	
	//Techniques:	http://www.w3.org/TR/AERT#color-convey
	
	//Note:			This should try to match an element to the colour
	//TODO:			This should apply primarily to navigation labels and error messages	
	//TODO:			This should confirm that the colour that has been mentioned actually appears somewhere in the page
	
	//NOTE:			We are not checking for background colours, or anything else; just font colours
	
	$timeout=get_timeout();
	
	create_message('2.1', 'Ensure that all information conveyed with color is also available without color, for example from context or markup.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h2';
	
	$hasFailed=false;
		
	$colour_list=Array();
	
	$temp=$parse->getElementsByTagname('font');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$colour=$parse->getAttribute($this_element, 'color');
		if($colour!=''){
			$colour_details=$colours->get_colour_details($colour);
			$colour_list[$colour_details['colour']]=$colour_details['colour'];
		}
	}
	
	//check each element for styles:
	
	$all_colour_styles=$parse->getStylesByProperty('color');
	foreach($all_colour_styles as $this_style){
		
		if(time()>$timeout)
			break;
				
		$colour_details=$colours->get_colour_details($this_style['value']);
		
		if(!in_array($colour_details['colour'], $colour_list))
			$colour_list[$colour_details['colour']]=$colour_details['colour'];
		
	}
	
	//so now we have all the colours:
	$innerText=strtolower($parse->bodyInnerText());
	$all_words=str_word_count($innerText, 1);
	
	foreach($colour_list as $this_colour){
		
		if(time()>$timeout)
			break;
				
		if(in_array(strtolower($this_colour), $all_words)){
			$result_key="The colour '<span class=\"quote\">" . $this_colour . "</span>' is referred to in the text of the page.";
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='This colour reference may not be helpful for people with vision problems.';
			$hasFailed=true;
			$listed_colours[$this_colour]=true;
		}
	}
	
	if(!$hasFailed){
		$result_key='Font colour was not relied upon to impart meaning.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('2.1', $error_type);
	
	return $results;
}

function NZ_S_2_2($parse, $colours){
	//Ensure that foreground and background color combinations provide sufficient contrast when viewed by someone having color deficits or when viewed on a black and white screen.
	
	//Priority:		Standard
	
	//Techniques: 	http://www.w3.org/TR/AERT#color-contrast
	
	//NOTE:			How do we highlight stylesheet colors?
	
	//TODO:			Perhaps we should include a visual example of the text colour on the background colour
	//				to demonstrate the colour contrast
	
	//TODO:			How do form <input> elements and so forth interact with this?
	//TODO:			Check this rule against the suggested technique
	//TODO:			Put the contrast number in the result, put link in to describe how it's measured
	
	$timeout=get_timeout();
	
	create_message('2.2', 'Ensure that foreground and background colour combinations provide sufficient contrast when viewed by someone having colour deficits or when viewed on a black and white screen.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h2';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('body');
	
	if(count($temp)>0){
		$body_source_index=$temp[0];
		$all_elements=$parse->getAllElements();
		$length=$all_elements[$body_source_index]['closingIndex'];
		
		$default_background='white';
		$default_text='black';
		
		$void_tagnames=Array();
		$void_tagnames[]='script';
		$void_tagnames[]='style';
		$void_tagnames[]='object';
		$void_tagnames[]='embed';
		$void_tagnames[]='noscript';
		$void_tagnames[]='select';
		$void_tagnames[]='option';
		$void_tagnames[]='textarea';
		
		for($i=$body_source_index; $i<$length; $i++){
			
			if(time()>$timeout)
				break;
							
			$tagname=$all_elements[$i]['tagname'];
			
			if(!$all_elements[$i]['is_closing'] && $tagname!='!' && !$all_elements[$i]['is_self_closing'] && !in_array($tagname, $void_tagnames)){
				//get the innertext value:
				$text=$parse->text($i, true);
				if($text!=''){
					//get the background and text colours for this element:
					//we store them in the _orig variables because for comparison purposes we need to convert
					//them to hex values and we want to use their original values for display purposes
					
					$text_orig='';
					$background_orig='';
					
					//Get the background colour details:
					$temp=$parse->getComputedStyle($all_elements[$i]['elementIndex'], 'background-color');
										
					if(isset($temp['value']))
						$background_orig=$temp['value'];
					
					//Get the text colour details:
					$temp=$parse->getComputedStyle($all_elements[$i]['elementIndex'], 'color');
					
					if(isset($temp['value']))
						$text_orig=$temp['value'];
					
						
					//If no background or text colours have been specified, then use the default colours (usually white and black respectively).
					if($background_orig=='')
						$background_orig=$default_background;
					
					if($text_orig=='')
						$text_orig=$default_text;
								
					//The returned results may be in a different format after being standardised for the contrast test
					//That is why the _orig variables were created for reporting purposes
					$background_colour=$colours->get_colour_details($background_orig, false);
					$text_colour=$colours->get_colour_details($text_orig, false);
					
					if(!$colours->does_contrast($background_colour, $text_colour)){
						//Is this element actually visible?
						$hidden=false;
						$temp=$parse->getComputedStyle($all_elements[$i]['elementIndex'], 'display');
						
						if(@$temp['value']=='none')
							$hidden=true;
							
						if(!$hidden){
							$temp=$parse->getComputedStyle($all_elements[$i]['elementIndex'], 'visibility');
							
							if(@$temp['value']=='hidden' || @$temp['value']=='collapse')
								$hidden=true;
								
						}
						
						if(!$hidden){
							$result_key='The text colour does not contrast well with the background colour.';
							$results['instances'][$result_key]['indices'][]=$all_elements[$i]['elementIndex'];
							$results['instances'][$result_key]['type'][]=RESULT_WARNING;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_TEXT_NOT_CHILDREN;
							$results['instances'][$result_key]['highlight_attribute'][]='';
							$results['instances'][$result_key]['info'][]='The text colour \'' . $text_orig . '\' does not contrast well with the background colour \'' . $background_orig . '\'.';
							$hasFailed=true;
						}
					}
				
				}
			}
		}
		
		if(!$hasFailed){
			$result_key='All text colours contrasted well with the background colours.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;			
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('2.2', $error_type);
	
	return $results;
}

function NZ_S_3_1($parse){
	//Create documents that validate to published formal grammars.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#document
	
	//TODO:			Actually validate the document, and fix the occasional doctype which can't be properly identified
	//				in the is_doctype_valid function
	
	//NOTE:			The number of errors returned is indicitive only.
	
	$timeout=get_timeout();
	
	create_message('3.1', 'Create documents that validate to published formal grammars.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h3';
	
	$docType=$parse->docType();
	
	if($docType!=''){
		$bits=getDocType($docType['docType']);
		if(!is_doctype_valid($bits)){
			$result_key='The document type must conform to the HTML specification and the list of public text identifiers.';
			$results['instances'][$result_key]['indices'][]=$docType['elementIndex'];
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='';
		} else {
			//ok so the doctype is fine, does it validate?
			$w3=new w3;
			$w3->is_xml=true;
			$w3->validate_page($parse->currentPage);
			$status=$w3->validStatus();
			
			$errors=$w3->getErrorCount();
			
			if(strtolower($status)=='valid'){
				$result_key='This HTML is valid.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$results['instances'][$result_key]['info'][]='';
			} else {
				$result_key='This HTML is not valid.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$results['instances'][$result_key]['info'][]='There are ' . $errors . " problems in this page. <a href=\"http://validator.w3.org/check?uri=" . urlencode($parse->getCurrentPage()) . "\">Click here</a> to see the full results.";
			}
		}
	} else {
		$result_key='The document must contain a <code>!doctype ...</code> declaration.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_FAIL;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$results['instances'][$result_key]['info'][]="Here is an example doctype: <code>&lt;!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\"&gt;</code>";
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('3.1', $error_type);
	
	return $results;
}

function NZ_S_3_2($parse){
	//Use header elements, H1, H2... H6, to convey document structure and use them according to specification.

	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#logical-heading
	
	//TODO:			Not highlight elements as possibly being good for headers if they contain links
	//TODO:			If a page has no <Hx> elements at all, should this be a pass (currently the situation) or a warning?
	//TODO:			Labels inside paragraphs being incorreclty picked up (ignore anything inside label)
	
	$timeout=get_timeout();
	
	create_message('3.2', 'Use header elements, H1, H2... H6, to convey document structure and use them according to specification.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h3';
	
	$hasFailed=false;
	$found=false;
	
	$headers['h1']['next']='h2';
	$headers['h1']['others']=Array('h3', 'h4', 'h5', 'h6');
	$headers['h2']['next']='h3';
	$headers['h2']['others']=Array('h4', 'h5', 'h6');
	$headers['h3']['next']='h4';
	$headers['h3']['others']=Array('h5', 'h6');
	$headers['h4']['next']='h5';
	$headers['h4']['others']=Array('h6');
	//$headers['h5']['next']='h6';
	//$headers['h5']['others']=Array();
	//Get all the <h1> elements and check that the next header element is an <h2>
	foreach($headers as $key => $this_header){
		$temp=$parse->getElementsByTagname($key);
		foreach($temp as $this_element){
			$found=true;
			$next=$parse->getNextElement($this_element);
			while($next){
				$tagname=$parse->tagname($next);
				
				if($tagname!=$key && $tagname!=$this_header['next'] && (in_array($tagname, $this_header['others']))){
					$result_key='Header levels must not increase by more than one level per heading. Do not use headings to create font effects; use style sheets to change font styles.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$results['instances'][$result_key]['info'][]='The next header element is: <code>' . htmlspecialchars($parse->outerHTML($next)) . '</code>';
					
					$hasFailed=true;
				}
				
				if($tagname=='h1' || $tagname=='h2' || $tagname=='h3' || $tagname=='h4' || $tagname=='h5' || $tagname=='h6'){
					break;
				}
				$next=$parse->getNextElement($next);
			}
			
			//verify that header is not used for formatting:
			//get the inner text of this element:
			$innerText=strip_spaces($parse->innerText($this_element), true);
									
			if(str_word_count($innerText)>20){
				$result_key='Header elements (<code>h1</code> - <code>h6</code>) should be used to define headers and should not be used for formatting text.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$results['instances'][$result_key]['info'][]='This header could be converted to either a paragraph or blockquote.';
				$hasFailed=true;
			}
		}
	}
	
	//now check <p> elements for formatting:
	$temp=$parse->getElementsByTagname('p');
	foreach($temp as $this_element){
		$found=true;
		$p_text_orig=$parse->innerText($this_element);
		$p_text=trim(strip_spaces($p_text_orig, true));
		
		if($p_text!='' && str_word_count($p_text)<10){
			$all_descendants=$parse->all_descendants($this_element);
			
			if(sizeof($all_descendants)==0)
				$all_descendants[]=$this_element;
			
			$descendant_count=count($all_descendants);
			$descendant_found=false;
			for($i=0; $i<$descendant_count; $i++){
				
				$tag_name=$parse->tagname($all_descendants[$i]);
				if($tag_name=='b' || $tag_name=='strong' || $tag_name=='u' || $tag_name=='em' || $tag_name=='u'){
					$text=strip_spaces($parse->innerText($all_descendants[$i]), true);
					if($text==$p_text){
						//$result_key='Text has been identified that could possibly be a header. Is this text used as a header: <em>' . $p_text_orig . '</em>?';
						$result_key='Text has been identified that could possibly be a header.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$results['instances'][$result_key]['info'][]='Is this text used as a header: <em>' . $p_text_orig . '</em>?<br>If so, you could change this &lt;p&gt; element to an element from the &lt;h1&gt; - &lt;h6&gt; range.';
						$hasFailed=true;
						$descendant_found=true;
					}
				}
				
				//check the styles:
				$text=strip_spaces($parse->innerText($all_descendants[$i]), true);
				if($text==$p_text){
					$applied=$parse->getStyleValue($all_descendants[$i], 'font-weight', 'screen');
					if(strtolower($applied['value'])=='bold' || strtolower($applied['value'])=='bolder' || $applied['value']=='700' || $applied['value']=='800' || $applied['value']=='900'){
						$result_key='Text has been identified that could possibly be a header.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$results['instances'][$result_key]['info'][]='Is this text used as a header: <em>' . $p_text_orig . '</em>?<br>If so, you could change this &lt;p&gt; element to an element from the &lt;h1&gt; - &lt;h6&gt; range.';
						$hasFailed=true;
						$descendant_found=true;
					}
					
					$applied=$parse->getStyleValue($all_descendants[$i], 'font-style', 'screen');
					if(strtolower($applied['value'])=='italic'){
						$result_key='Text has been identified that could possibly be a header.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$results['instances'][$result_key]['info'][]='Is this text used as a header: <em>' . $p_text_orig . '</em>?<br>If so, you could change this &lt;p&gt; element to an element from the &lt;h1&gt; - &lt;h6&gt; range.';
						$hasFailed=true;
						$descendant_found=true;
					}
				
					$applied=$parse->getStyleValue($all_descendants[$i], 'text-decoration', 'screen');
					if(strtolower($applied['value'])=='underline'){
						$result_key='Text has been identified that could possibly be a header.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$results['instances'][$result_key]['info'][]='Is this text used as a header: <em>' . $p_text_orig . '</em>?<br>If so, you could change this &lt;p&gt; element to an element from the &lt;h1&gt; - &lt;h6&gt; range.';
						$hasFailed=true;
						$descendant_found=true;
					}
					
					if($descendant_found)
						break;
				}
			}
		}
	}
	if($found){
		if(!$hasFailed){
			$result_key='All heading elements were used in the correct fashion.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		
	} else {
		$result_key='No heading elements were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('3.2', $error_type);
	
	return $results;
}

function NZ_S_3_3($parse){
	//Avoid deprecated features of W3C technologies.

	//Priority:		Standard
	
	//Techniques:	Use CR_6_3_3_d
	
	$timeout=get_timeout();
	
	create_message('3.3', 'Avoid deprecated features of W3C technologies.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h3';
	
	$hasFailed=false;
	$deprecated=Array();
	$deprecated=load_deprecated_elements();

	foreach($deprecated as $this_deprecated){
		
		if(time()>$timeout)
			break;
			
		$temp=$parse->getElementsByTagname($this_deprecated['element']);
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='This HTML element <code>' . $this_deprecated['element'] . '</code> is now deprecated and should not be used.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='Use this element instead: <code>' . $this_deprecated['replacement'] . '</code>.';
			$hasFailed=true;
		}
	}
	
	if(!$hasFailed){
		$result_key='No deprecated elements were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('3.3', $error_type);
	
	return $results;
}

function NZ_S_3_4($parse){
	//Use relative rather than absolute units in markup language attribute values and style sheet property values.
	
	//Priority:		Standard
	
	//Techniques:	http://www.w3.org/TR/AERT#relative-units.
	
	//				Check font-size, margin-left, margin-right, margin-top, margin-bottom, padding-left, padding-right,
	//				padding-top, padding-bottom, border-left-width, border-right-width, border-top-width, border-bottom-width,
	//				word-spacing, letter-spacing, text-indent, background-position, background-position-x, background-position-y, outline-width, marker-offset, border-spacing, top, left, bottom, right, width, height, min-width, min-height, max-width, max-height, line-height, vertical-align, clip, 
	
	//Exception: "width" and "height" attributes of IMG, OBJECT, and APPLET elements.
	
	//NOTE:			I have excluded the border measurements from this test
	
	//TODO:			Include html tags and their measurements in this check
	//TODO:			When checking stylesheet rules, check to see if they're actually used...
	//TODO:			Change this to not use the attribute in the result string... move the attribute to an info field
		
	$timeout=get_timeout();
	
	create_message('3.4', 'Use relative rather than absolute units in markup language attribute values and style sheet property values.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h3';
	
	$hasFailed=false;
	
	//We can use our new handy-dandy property lookup for the stylesheets
	$properties[]='font-size';
	//$properties[]='margin-top';
	//$properties[]='margin-right';
	//$properties[]='margin-bottom';
	//$properties[]='margin-left';
	//$properties[]='padding-top';
	//$properties[]='padding-right';
	//$properties[]='padding-bottom';
	//$properties[]='padding-left';
	//$properties[]='border-top-width';
	//$properties[]='border-right-width';
	//$properties[]='border-bottom-width';
	//$properties[]='border-left-width';
	$properties[]='word-spacing';
	$properties[]='letter-spacing';
	$properties[]='text-indent';
	$properties[]='background-position';
	$properties[]='background-position-x';
	$properties[]='background-position-y';
	$properties[]='outline-width';
	$properties[]='marker-offset';
	$properties[]='border-spacing';
	//$properties[]='top';
	//$properties[]='left';
	//$properties[]='bottom';
	//$properties[]='right';
	$properties[]='width';
	$properties[]='height';
	$properties[]='min-width';
	$properties[]='min-height';
	$properties[]='max-width';
	$properties[]='max-height';
	$properties[]='line-height';
	$properties[]='vertical-align';
	$properties[]='clip'; 	
	
	foreach($properties as $this_property){

		$values=$parse->getStylesByProperty($this_property, 'screen');

		foreach($values as $this_value){

			if(time()>$timeout)
				break;
			
			if(!is_unit_relative($this_value['value'])){
				if(is_array($this_value['value']))
					$value_string=join($this_value['value'], ' ');
				else $value_string=$this_value['value'];
				
				if($this_value['inline']){
					$result_key='This element uses absolute units of measure rather than relative units of measure.';
					$results['instances'][$result_key]['indices'][]=$this_value['selector'];
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
					$results['instances'][$result_key]['highlight_attribute'][]='style';
					$results['instances'][$result_key]['rule'][]='';
					$results['instances'][$result_key]['selector_group'][]='';
					$results['instances'][$result_key]['info'][]='The ' . $this_property . ' value  ' . $value_string . ' has been used.';
				} else {
					$result_key='This style uses absolute units of measure rather than relative units of measure.';
					$results['instances'][$result_key]['indices'][]=-2;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_CSS;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$results['instances'][$result_key]['stylesheet'][]=$this_value['stylesheet'];
					$results['instances'][$result_key]['rule'][]=$this_value['rule'];
					$results['instances'][$result_key]['selector_group'][]=$this_value['selector_group'];
					$results['instances'][$result_key]['info'][]='The ' . $this_property . ' value  ' . $value_string . ' has been used.';
				}
				$hasFailed=true;
			}
		}
	}
	
	//Check the HTML elements
	$temp=$parse->getElementsByTagname('frameset');
	foreach($temp as $this_element){
		$rows=$parse->getAttribute($this_element, 'rows', true);
		$bits=explode(',', $rows);
		foreach($bits as $this_bit){
			if($this_bit!='*' && !is_relative($this_bit)){
				$result_key='This frameset row attribute uses absolute units of measure rather than relative units of measure.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
				$results['instances'][$result_key]['highlight_attribute'][]='rows';
				$results['instances'][$result_key]['stylesheet'][]=-1;
				$results['instances'][$result_key]['rule'][]=-1;
				$results['instances'][$result_key]['selector_group'][]=-1;
				//$results['instances'][$result_key]['info'][]='The ' . $this_property . ' value  ' . $value_string . ' has been used.';
				$hasFailed=true;
			}
		}
		
		$cols=$parse->getAttribute($this_element, 'cols', true);
		$bits=explode(',', $cols);
		foreach($bits as $this_bit){
			if($this_bit!='*' && !is_relative($this_bit)){
				$result_key='This frameset col attribute uses absolute units of measure rather than relative units of measure.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
				$results['instances'][$result_key]['highlight_attribute'][]='cols';
				$results['instances'][$result_key]['stylesheet'][]=-1;
				$results['instances'][$result_key]['rule'][]=-1;
				$results['instances'][$result_key]['selector_group'][]=-1;
				//$results['instances'][$result_key]['info'][]='The ' . $this_property . ' value  ' . $value_string . ' has been used.';
				$hasFailed=true;
			}
		}
	}
	
	$table_tags[]='table';
	$table_tags[]='tr';
	$table_tags[]='th';
	$table_tags[]='td';

	$attributes[]='bottompadding';
	$attributes[]='cellspacing';
	$attributes[]='cellpadding';
	$attributes[]='height';
	$attributes[]='hspace';
	$attributes[]='leftpadding';
	$attributes[]='rightpadding';
	$attributes[]='toppadding';
	$attributes[]='vspace';
	$attributes[]='width';
	
	foreach($table_tags as $this_table_tag){
		$temp=$parse->getElementsByTagname($this_table_tag);
		foreach($temp as $this_element){
			foreach($attributes as $this_attribute){
				$value=$parse->getAttribute($this_element, $this_attribute, true);
				if(!is_relative($value)){
					$result_key='This ' . $this_table_tag . ' ' . $this_attribute . ' attribute uses absolute units of measure rather than relative units of measure.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
					$results['instances'][$result_key]['highlight_attribute'][]=$this_attribute;
					$results['instances'][$result_key]['stylesheet'][]=-1;
					$results['instances'][$result_key]['rule'][]=-1;
					$results['instances'][$result_key]['selector_group'][]=-1;
					$hasFailed=true;
				}	
			}		
		}
	}
	
	$temp=$parse->getElementsByTagname('font');
	foreach($temp as $this_element){
		$value=$parse->getAttribute($this_element, 'size');
		if(!is_relative($value)){
			$result_key='This font size attribute uses absolute units of measure rather than relative units of measure.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='size';
			$results['instances'][$result_key]['stylesheet'][]=-1;
			$results['instances'][$result_key]['rule'][]=-1;
			$results['instances'][$result_key]['selector_group'][]=-1;
			$hasFailed=true;
		}
		
		$value=$parse->getAttribute($this_element, 'point-size');
		if(!is_relative($value)){
			$result_key='This font point-size attribute uses absolute units of measure rather than relative units of measure.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
			$results['instances'][$result_key]['highlight_attribute'][]='point-size';
			$results['instances'][$result_key]['stylesheet'][]=-1;
			$results['instances'][$result_key]['rule'][]=-1;
			$results['instances'][$result_key]['selector_group'][]=-1;
			$hasFailed=true;
		}
	}
	
	if(!$hasFailed){
		$result_key='No absolute unit measurements were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['instances'][]='All measurements used relative units.';
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
	}	
	
	$error_type=get_error_type($results['instances']);
	update_message('3.4', $error_type);
	
	return $results;
}

function NZ_S_4_1($parse){
	//Links to web documents indicate as a minimum the document size and type, which must either be included in the link itself and/or in the TITLE tag.
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//NOTE:			This only checks http: links, not https or anything else
	
	$timeout=get_timeout();
	
	create_message('4.1', 'Links to web documents indicate as a minimum the document size and type, which must either be included in the link itself and/or in the TITLE tag.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h4';
	
	$extensions=Array();
	$names=Array();
	$extensions=load_common_extensions();
	$names=load_format_names();
	
	$temp=$parse->getElementsByTagname('a');
	
	$hasFailed=false;
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			//$link=$parse->href($this_element);
			//The ->href method has problems with files ending in '/', like CNN, which often ends up misidentifying extensions
			$link=$parse->getAttribute($this_element, 'href');
			$protocol=get_protocol($link);
			
			if($link!='' && ($protocol=='http' || $protocol=='https')){
				$this_extension=get_extension($link);
				if($this_extension!='' && $this_extension!=false){
					if(!isset($extensions[$this_extension])){
						//get the link text and see if there's some kind of file format and size indicator
						$text=strtolower($parse->innerText($this_element));
						$title=strtolower($parse->getAttribute($this_element, 'title'));
						if($text=='' && $title==''){
							$result_key='Links to alternative formats were found.';
							$results['instances'][$result_key]['indices'][]=$this_element;
							$results['instances'][$result_key]['instances'][]='This is a link to an alternative format (' . $this_extension . ').';
							$results['instances'][$result_key]['type'][]=RESULT_FAIL;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE_INCLUDE_CONTENTS;
							$results['instances'][$result_key]['highlight_attribute'][]='href';
							$hasFailed=true;
						} else {
							//find the words kb, mb, kilobyte or megabyte
							$size_pos=strpos($text, 'kb');
							$title_pos=strpos($title, 'kb');
							
							if($size_pos===false && $title_pos===false){
								$size_pos=strpos($text, 'mb');
								$title_pos=strpos($title, 'mb');
							}
							
							if($size_pos===false && $title_pos===false){
								$size_pos=strpos($text, 'kilobyte');
								$title_pos=strpos($title, 'kb');
							}
																				
							if($size_pos===false && $title_pos===false){
								$size_pos=strpos($text, 'megabyte');
								$title_pos=strpos($title, 'megabyte');
							}
							
							if($size_pos!==false || $title_pos!==false){
								//so we have a size specification, now check for the format
								$found=false;
								
								if(isset($names[$this_extension])){
									foreach($names[$this_extension] as $this_format){
										$name_pos=strpos($text, $this_format);
										if($name_pos!==false){
											$found=true;
											break;
										}
									}
									
									if(!$found){
										foreach($names[$this_extension] as $this_format){
											$name_pos=strpos($title, $this_format);
											if($name_pos!==false){
												$found=true;
												break;
											}
										}
									}
								}
								
								if(!$found){
									$result_key='Links to alternative formats were found.';
									$results['instances'][$result_key]['indices'][]=$this_element;
									$results['instances'][$result_key]['instances'][]='This is a link to an alternative format (' . $this_extension . ').';
									$results['instances'][$result_key]['type'][]=RESULT_FAIL;
									$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE_INCLUDE_CONTENTS;
									$results['instances'][$result_key]['highlight_attribute'][]='href';
									$hasFailed=true;
								}
							} else {
								//no size specified
								$result_key='Links to alternative formats were found.';
								$results['instances'][$result_key]['indices'][]=$this_element;
								$results['instances'][$result_key]['instances'][]='This is a link to an alternative format (' . $this_extension . ').';
								$results['instances'][$result_key]['type'][]=RESULT_FAIL;
								$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE_INCLUDE_CONTENTS;
								$results['instances'][$result_key]['highlight_attribute'][]='href';
								$hasFailed=true;
							}
						}
					}
				}
			}
			
		}
		if(!$hasFailed){
			$result_key='No links to alternative formats where found';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['instances'][]='No links to alternative formats were found.';
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
		}
	} else {
		$result_key='No links where found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['instances'][]='No links were found.';
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('4.1', $error_type);
	
	return $results;
}

function NZ_S_4_2($parse){
	//If you cannot publish a document that validates to the approved formal grammars as stated in standard 3.1 on page 16, then publish the document in the most accessible format possible.
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Note:			We are going to find all alternative formats and raise warnings for each of them except for images, rtf and csv files
	//TODO:			Should .zip, .rar, .tar etc files be in the ok_extensions list?
	
	$timeout=get_timeout();
	
	create_message('4.2', 'If you cannot publish a document that validates to the approved formal grammars as stated in standard 3.1 on page 16, then publish the document in the most accessible format possible.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h4';
	
	$extensions=Array();
	$names=Array();
	$extensions=load_common_extensions();
	$names=load_format_names();
	
	$ok_extensions[]='rtf';
	$ok_extensions[]='csv';
	$ok_extensions[]='jpeg';
	$ok_extensions[]='jpg';
	$ok_extensions[]='gif';
	$ok_extensions[]='png';
	$ok_extensions[]='bmp';

	$temp=$parse->getElementsByTagname('a');
	
	$hasFailed=false;
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			//$link=$parse->href($this_element);
			//The ->href method has problems with files ending in '/', like CNN, which often ends up misidentifying extensions
			$link=$parse->getAttribute($this_element, 'href');
			$protocol=get_protocol($link);
			
			if($link!='' && ($protocol=='http' || $protocol=='https')){
				$this_extension=get_extension($link);
				if($this_extension!='' && $this_extension!=false){
					if(!isset($extensions[$this_extension]) && !in_array($this_extension, $ok_extensions)){
						//this is an an alternative format.  Raise a warning.
						$result_key='Links to non-accessible documents were found.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['instances'][]='This is a link to a file which could be in a non-accessible format.';
						$results['instances'][$result_key]['type'][]=RESULT_WARNING;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE_INCLUDE_CONTENTS;
						$results['instances'][$result_key]['highlight_attribute'][]='href';
						$hasFailed=true;
					}
				}
			}
			
		}
		if(!$hasFailed){
			$result_key='No links to non-accessible documents were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['instances'][]='No links to non-accessible documents were found.';
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
		}
	} else {
		$result_key='No links where found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['instances'][]='No links were found.';
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('4.2', $error_type);
	
	return $results;
}

function NZ_S_4_3($parse){
	//PDF can be used to publish a document but it must be assisted with at least one other accessible format
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	$timeout=get_timeout();
	
	create_message('4.3', 'PDF can be used to publish a document but it must be assisted with at least one other accessible format.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h4';
	
	$hasFailed=false;
	$temp=$parse->getElementsByTagname('a');
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			//$link=$parse->href($this_element);
			//The ->href method has problems with files ending in '/', like CNN, which often ends up misidentifying extensions
			$link=$parse->getAttribute($this_element, 'href');
			$protocol=get_protocol($link);
			
			if($link!='' && ($protocol=='http' || $protocol=='https')){
				$this_extension=get_extension($link);
				if($this_extension=='pdf'){
					//this is an PDF document.  Raise a warning.
					$result_key='Links to PDF documents were found.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['instances'][]='Please ensure that the PDF version number is displayed and that there is an HTML summary available.';
					$results['instances'][$result_key]['type'][]=RESULT_WARNING;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE_INCLUDE_CONTENTS;
					$results['instances'][$result_key]['highlight_attribute'][]='href';
					$hasFailed=true;
				}
			}
			
		}
		if(!$hasFailed){
			$result_key='No links to PDF documents were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['instances'][]='No links to PDF documents were found.';
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
		}
	} else {
		$result_key='No links where found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['instances'][]='No links were found.';
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('4.3', $error_type);
		
	return $results;
}

function NZ_S_4_4($parse){
	//Any document, content and/or forms/applications on an agency web site that is deemed for a specialist audience (as defined in the Glossary of key concepts, page 141) must state that the document/content/application is for a specialist audience, and have no ambiguity as to what part of on the web site (i.e., document, content) applies to the specialist audience.
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Note:			We are going to find all alternative formats and raise warnings for each of them except for images, rtf and csv files
	
	//TODO:			Does this sync with the glossary concept (page 141)?
	//TODO:			Should .zip, .rar, .tar etc files be in the ok_extensions list?
	
	$timeout=get_timeout();
	
	create_message('4.4', 'Any document, content and/or forms/applications on an agency web site that is deemed for a specialist audience (as defined in the Glossary of key concepts, page 141) must state that the document/content/application is for a specialist audience, and have no ambiguity as to what part of on the web site (i.e., document, content) applies to the specialist audience.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h4';
	
	$extensions=load_common_extensions();
	$names=load_format_names();
	
	$ok_extensions[]='rtf';
	$ok_extensions[]='csv';
	$ok_extensions[]='jpeg';
	$ok_extensions[]='jpg';
	$ok_extensions[]='gif';
	$ok_extensions[]='png';
	$ok_extensions[]='bmp';
	
	$temp=$parse->getElementsByTagname('a');
	
	$hasFailed=false;
	if(count($temp)>0){
		foreach($temp as $this_element){
			//$link=$parse->href($this_element);
			//The ->href method has problems with files ending in '/', like CNN, which often ends up misidentifying extensions
			$link=$parse->getAttribute($this_element, 'href');
			$protocol=get_protocol($link);
			
			if($link!='' && ($protocol=='http' || $protocol=='https')){
				$this_extension=get_extension($link);
				if($this_extension!='' && $this_extension!=false){
					if(!isset($extensions[$this_extension]) && !in_array($this_extension, $ok_extensions)){
						//this is an an specialist document.  Raise a warning.
						$result_key='Links to specialist documents were found.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['instances'][]='This is a link to a specialist document.';
						$results['instances'][$result_key]['type'][]=RESULT_WARNING;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE_INCLUDE_CONTENTS;
						$results['instances'][$result_key]['highlight_attribute'][]='href';
						$hasFailed=true;
					}
				}
			}
			
		}
		if(!$hasFailed){
			$result_key='No links to specialist documents were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['instances'][]='No links to specialist documents were found.';
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
		}
	} else {
		$result_key='No links where found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['instances'][]='No links were found.';
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('4.4', $error_type);
	
	return $results;
}

function NZ_S_4_5($parse){
	//Any document, content and/or forms/applications on an agency web site that is deemed a special-purpose document (as defined in the Glossary of key concepts, page 142) must state that •	the document/content/application is a special-purpose document, and •	why it is a special-purpose document and have no ambiguity as to what part thereof on the web site (i.e., document, content) is special-purpose. 
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Note:			We are going to find all alternative formats and raise warnings for each of them except for images, rtf and csv files
	
	//TODO:			Does this sync with the glossary concept (page 141)?
	//TODO:			Should .zip, .rar, .tar etc files be in the ok_extensions list?
	
	$timeout=get_timeout();
	
	create_message('4.5', 'Any document, content and/or forms/applications on an agency web site that is deemed a special-purpose document (as defined in the Glossary of key concepts, page 142) must state that •	the document/content/application is a special-purpose document, and •	why it is a special-purpose document and have no ambiguity as to what part thereof on the web site (i.e., document, content) is special-purpose.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h4';
	
	$extensions=Array();
	$names=Array();
	$extensions=load_common_extensions();
	$names=load_format_names();
	
	$ok_extensions[]='rtf';
	$ok_extensions[]='csv';
	$ok_extensions[]='jpeg';
	$ok_extensions[]='jpg';
	$ok_extensions[]='gif';
	$ok_extensions[]='png';
	$ok_extensions[]='bmp';
	
	$temp=$parse->getElementsByTagname('a');
	
	$hasFailed=false;
	if(count($temp)>0){
		foreach($temp as $this_element){
			//$link=$parse->href($this_element);
			//The ->href method has problems with files ending in '/', like CNN, which often ends up misidentifying extensions
			$link=$parse->getAttribute($this_element, 'href');
			$protocol=get_protocol($link);
			
			if($link!='' && ($protocol=='http' || $protocol=='https')){
				$this_extension=get_extension($link);
				if($this_extension!='' && $this_extension!=false){
					if(!isset($extensions[$this_extension]) && !in_array($this_extension, $ok_extensions)){
						//this is an an specilist document.  Raise a warning.
						$result_key='Links to specialist documents were found.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['instances'][]='This is a link to a specialist document.';
						$results['instances'][$result_key]['type'][]=RESULT_WARNING;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE_INCLUDE_CONTENTS;
						$results['instances'][$result_key]['highlight_attribute'][]='href';
						$hasFailed=true;
					}
				}
			}
			
		}
		if(!$hasFailed){
			$result_key='No links to specialist documents were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['instances'][]='No links to specialist documents were found.';
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
		}
	} else {
		$result_key='No links where found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['instances'][]='No links were found.';
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('4.5', $error_type);
	
	return $results;
}

function NZ_S_5_1($parse){
	//Clearly identify changes in the natural language of a document's text and any text equivalents, for example captions.
	
	//Priority:		Standard
	
	//Techniques:	http://www.w3.org/TR/AERT#language
	
	//TODO:			Check to see if the lang attribute has been used somewhere, possibly display a different message?
	
	$timeout=get_timeout();
	
	create_message('5.1', 'Clearly identify changes in the natural language of a document\'s text and any text equivalents, for example captions.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h5';
		
	$text=$parse->bodyInnerText();
	if(str_word_count($text)>2){
		$result_key='Any words or phrases in a document that are not in the primary language of the document should be identified.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_USER;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$results['instances'][$result_key]['info'][]="Suggestions:</p><ul><li>For blocks of text that are not in the primary language and are already enclosed by markup elements such as Paragraph, DIV or EM, set the \"lang\" attribute of the markup element.</li><li>For words or phrases that are not in the primary language, enclose them with a SPAN element and set the SPAN element's \"lang\" attribute.</li><li>Ensure that all captions and other text equivalents are checked.</li></ul><p>";
	} else {
		$result_key='No need for language identification was found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('5.1', $error_type);
	
	return $results;
}

function NZ_S_5_2($parse) {
	//Identify the primary natural language of a document.

	//Priority:		Standard
	
	//Techniques:	http://www.w3.org/TR/AERT#identify-lang
	
	//Methods:		As per http://www.w3.org/TR/NOTE-html-lan, we are checking the meta tags for a language value
	
	//TODO:			Extend this to check all the parts of the language value, not just the first
	
	$timeout=get_timeout();
	
	create_message('5.2', 'Identify the primary natural language of a document.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h5';
	
	$hasFailed=false;
	$found=false;
	
	$temp=$parse->getElementsByTagname('html');
	//only check the first instance:
	$lang_codes=Array();
	$lang_codes=language_codes();
	
	if(count($temp)>0){
		$lang=$parse->getAttribute($temp[0], 'lang', true);
		//check that it is a valid two-letter code:
		if($lang!=''){
			$bits=explode('-',$lang);
			if($bits[0]!='i' && $bits[0]!='x'){
				$found=true;
				//if(strlen($lang)!=2 || !array_key_exists($lang, $lang_codes)){
				if(!array_key_exists($bits[0], $lang_codes)){
					$result_key='The primary language of this document does not appear to be valid.';
					$results['instances'][$result_key]['indices'][]=$temp[0];
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
					$results['instances'][$result_key]['highlight_attribute'][]='lang';
					$hasFailed=true;
				}				
			}
		}
	}
	
	if(!$found){
		$temp=$parse->getElementsByTagName('meta');
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$http_equiv=$parse->getAttribute($this_element, 'http-equiv', true);
			$content=$parse->getAttribute($this_element, 'content', true);
			if(strtolower($http_equiv)=='content-language'){
				$bits=explode('-',$content);
				if($bits[0]!='i' && $bits[0]!='x'){
					//if(strlen($content)!=2 || !array_key_exists($content, $lang_codes)){
					if(!array_key_exists($bits[0], $lang_codes)){
						$result_key='The primary language of this document does not appear to be valid.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
						$results['instances'][$result_key]['highlight_attribute'][]='content';
						$hasFailed=true;
					}
					$found=true;
				}
			}
		}
	}
	
	if(!$found){	
		$result_key='The primary language of this document has not been set.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_FAIL;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$results['instances'][$result_key]['info'][]="The easiest way to fix this is to include the \"lang\" attribute (lang=\"en-nz\") in the &lt;HTML&gt; element";
		$hasFailed=true;
	} else {
		if(!$hasFailed){
			$result_key='This document contains a primary language value.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('5.2', $error_type);
	
	return $results;
}

function NZ_S_5_3($parse){
	//Specify the expansion of each abbreviation or acronym in a document where it first occurs.
	
	//Priority:		Standard
	
	//Techniques:	http://www.w3.org/TR/AERT#expand-abbr
	
	//NOTE:			No attempt to get the first instance of an acronym is made.  Perhaps the str_word_count function can be used for this
	//				Also, perhaps we could trim trailing letters, like URLs to get URL.  And convert other characters such as dashes to spaces to increase the haul
	//				Is it not possible to highlight the acronym?
	//				This will detect words inside comments (bad) and hex values inside <style> elements contained within
	//				the body element (annoying)
	//TODO:			style elements seem to be picked up in the innerHTML function (www.stuff.co.nz)
	
	$timeout=get_timeout();
	
	create_message('5.3', 'Specify the expansion of each abbreviation or acronym in a document where it first occurs.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h5';
	
	$found=false;
	
	$temp=$parse->getElementsByTagName('body');
	
	if(count($temp)>0){
		$innerText=strip_spaces($parse->innerText($temp[0]));
				
		$words=str_word_count($innerText, 1);
		
		$acronyms=Array();
		
		//get each word and see if it's in all caps
		foreach($words as $this_word){
			
			if(time()>$timeout)
				break;
				
			if(strlen($this_word)>2){
				if($this_word==strtoupper($this_word)){
					//we need to check that this word has at least one letter in it, otherwise 'words' such as '----' will be picked up:
					for($i=0;$i<strlen($this_word);$i++){
						
						if(time()>$timeout)
							break;
			
						$ord=ord(strtoupper(substr($this_word, $i,1)));
						if($ord>64 && $ord<91){
							//this word is probably an acronym
							$acronyms[$this_word]=$this_word;
							break;		
						}
					}						
				}	
			}
		}	
		
		//now check to see if any of the words have an acronym attribute associated with it
		if(count($acronyms)>0)
			$found=true;
				
		$all_acronyms=$parse->getElementsByTagname('acronym');
		foreach($all_acronyms as $this_acronym){
			
			if(time()>$timeout)
				break;
			
			$innerText=trim($parse->innerText($this_acronym));
			$words=str_word_count($innerText,1);
			//assumes that the whole innerText is the complete acronym:
			if(isset($acronyms[$words[0]]))
				unset($acronyms[$words[0]]);
			
		}
		
		//The following acronyms do not have expanded definitions:
		if(count($acronyms)>0){
			reset($acronyms);
			foreach($acronyms as $this_acronym){
				
				if(time()>$timeout)
					break;
			
				$result_key="Potential acronym/abbreviation have been discovered.";
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$results['instances'][$result_key]['info'][]="Is this an acronym? <span class=\"quote\">" . key($acronyms) . "</span><br>If it is, you should use the &lt;acronym&gt; element to describe it, eg: &lt;acronym title=\"World Wide Web\"&gt;WWW&lt;acronym&gt;.";
				next($acronyms);
			}
			
		} else {
			if($found){
				$result_key='All acronyms have been defined.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;			
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			} else {
				$result_key='No acronyms were found.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			}
		}
	} else {
		$result_key='No acronyms were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('5.3', $error_type);
	
	return $results;
}

function NZ_S_5_4($parse){
	//Authors do not use altered fonts that substitute umlauted vowels for macronised vowels.
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		I'm not sure how to detect this, so I'm going to just raise a user check
	
	//TODO:			Check for umluates (two dots about maori a instead of line &#257;)
	
	$timeout=get_timeout();
	
	create_message('5.4', 'Authors do not use altered fonts that substitute umlauted vowels for macronised vowels.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h5';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';	
	
	$error_type=get_error_type($results['instances']);
	update_message('5.4', $error_type);
	
	return $results;
}

function NZ_S_5_6($parse){
	//Underlining is not used for any items making up text or headings
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		Get all the <u> elements and mark as failed, and then check the stylesheets for instances of underlining
	
	//Notes:		anchor styles are ignored for this test, as are pseudo-classes
	//TODO:			If inline instances are found, make sure that they are not nested inside an <a> element
	
	$timeout=get_timeout();
	
	create_message('5.6', 'Underlining is not used for any items making up text or headings.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h5';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('u');
	if(count($temp)>0){
		//mark each element as having failed
		foreach($temp as $this_element){
			$result_key='Underline elements were found.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	//are there any instances in the stylesheets?
	$values=$parse->getStylesByProperty('text-decoration', 'screen', Array('a'));

	foreach($values as $this_value){

		if(time()>$timeout)
			break;
		
		if($this_value['value']=='underline'){	
			
			if($this_value['inline']){
				$result_key='This element uses the underline style property.';
				$results['instances'][$result_key]['indices'][]=$this_value['selector'];
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
				$results['instances'][$result_key]['highlight_attribute'][]='style';
				$results['instances'][$result_key]['stylesheet'][]='';
				$results['instances'][$result_key]['rule'][]='';
				$results['instances'][$result_key]['selector_group'][]='';
			} else {
				$result_key='This style uses the underline property.';
				$results['instances'][$result_key]['indices'][]=-2;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_CSS;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$results['instances'][$result_key]['stylesheet'][]=$this_value['stylesheet'];
				$results['instances'][$result_key]['rule'][]=$this_value['rule'];
				$results['instances'][$result_key]['selector_group'][]=$this_value['selector_group'];
			}
			$hasFailed=true;
		}
	}
	
	if(!$hasFailed){
		$result_key='No instances of underlining were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('5.6', $error_type);
	
	return $results;
}

function NZ_S_5_7($parse){
	//Provide metadata to add semantic information to pages and sites. As a minimum, provide metadata for page title, keywords and descriptions.
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		Check for the presence of a meta tag of each of the three required types
	
	//TODO:			Empty meta tags will display a message saying they weren't found... perhaps that should be more specific?
	
	$timeout=get_timeout();
	
	create_message('5.7', 'Provide metadata to add semantic information to pages and sites. As a minimum, provide metadata for page title, keywords and descriptions.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h5';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('title');
	if(count($temp)==0){
		$result_key='No TITLE element was found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_FAIL;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$results['instances'][$result_key]['info'][]='This page does not have a title.';
		$hasFailed=true;
	}
	
	$temp=$parse->getElementsByTagname('meta');
	$description_found=false;
	$keywords_found=false;
	foreach($temp as $this_element){
		$name=$parse->getAttribute($this_element, 'name', true);
		$content=$parse->getAttribute($this_element, 'content');
		
		if($name=='description' && $content!='')
			$description_found=true;
			
		if($name=='keywords' && $content!='')
			$keywords_found=true;
				
	}
	
	if(!$description_found){
		$result_key='No description meta tag was found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_FAIL;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$results['instances'][$result_key]['info'][]="This page should have a description meta tag such as this: <code>&lt;meta name=\"description\" content=\"description goes here\" /&gt;</code>.";
		$hasFailed=true;
	}

	if(!$keywords_found){
		$result_key='No keyword meta tag was found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_FAIL;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$results['instances'][$result_key]['info'][]="This page should have a keywords meta tag such as this: <code>&lt;meta name=\"keywords\" content=\"keywords go here\" /&gt;</code>.";
		$hasFailed=true;
	}
	
	if(!$hasFailed){
		$result_key='All the required meta tags were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('5.7', $error_type);
	
	return $results;
}

function NZ_S_6_1($parse){
	//Agency sites provide any publicly available reports the agency is required to produce by statute on their web site. Refer to your communications department, legal teams or representative to determine what these reports are for your agency.
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		This can't be automatically checked
	
	$timeout=get_timeout();
	
	create_message('6.1', 'Agency sites provide any publicly available reports the agency is required to produce by statute on their web site. Refer to your communications department, legal teams or representative to determine what these reports are for your agency.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h6';
	
	$result_key=NOT_CHECKED;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_NOT_CHECKED;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';	
	
	$error_type=get_error_type($results['instances']);
	update_message('6.1', $error_type);
	
	return $results;
}

function NZ_S_6_2($parse){
	//Agency sites provide any publicly available reports the agency is required to produce by statute on their web site. Refer to your communications department, legal teams or representative to determine what these reports are for your agency.
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		This can't be automatically checked
	
	create_message('6.2', 'Agency sites provide any publicly available reports the agency is required to produce by statute on their web site. Refer to your communications department, legal teams or representative to determine what these reports are for your agency.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h6';
	
	$result_key=NOT_CHECKED;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_NOT_CHECKED;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';	
	
	$error_type=get_error_type($results['instances']);
	update_message('6.2', $error_type);
	
	return $results;
}

function NZ_S_6_3($parse){
	//Agency sites provide press notices from the agency, and links to press notices from the minister, for instances that set the context for a specific release of information where relevant (E.g. Budget).
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		This can't be automatically checked
	
	create_message('6.3', 'Agency sites provide press notices from the agency, and links to press notices from the minister, for instances that set the context for a specific release of information where relevant (E.g. Budget).');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h6';
	
	$result_key=NOT_CHECKED;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_NOT_CHECKED;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';	
	
	$error_type=get_error_type($results['instances']);
	update_message('6.3', $error_type);
	
	return $results;
}

function NZ_S_6_4($parse){
	//The site provides an email address for each of the following: •	info@<domain> •	postmaster@<domain> •	webmaster@<domain> •	privacy@<domain> •	complaints by at least one of: o	complaints@<domain> o	abuse@<domain> •	general enquiries by at least one of: o	enquiries@<domain>, or o	enquiry@<domain> 

	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		This can't be automatically checked
	//TODO:			Perhaps pages could be checked for these email addresses, although they're probably only going to be found on the contact page...
	
	create_message('6.4', 'The site provides all of the required email addresses');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h6';
	
	$result_key=NOT_CHECKED;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_NOT_CHECKED;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';	
	
	$error_type=get_error_type($results['instances']);
	update_message('6.4', $error_type);
	
	return $results;
}

function NZ_S_6_5($parse){
	//Superseded material is marked as superseded

	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		This can't be automatically checked
	
	create_message('6.5', 'Superseded material is marked as superseded.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h6';
	
	$result_key=NOT_CHECKED;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_NOT_CHECKED;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';	
	
	$error_type=get_error_type($results['instances']);
	update_message('6.5', $error_type);
	
	return $results;
	
}

function NZ_S_6_6($parse){
	//Paid advertising is not carried, including advertorial that is unrelated to an agency's core business, unless the agency has significant involvement in a commercial event, such as a conference, where it may be appropriate to promote the event and link to a commercial web site.

	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		This can't be automatically checked
	
	create_message('6.6', 'Paid advertising is not carried, including advertorial that is unrelated to an agency\'s core business, unless the agency has significant involvement in a commercial event, such as a conference, where it may be appropriate to promote the event and link to a commercial web site.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h6';
	
	$result_key=NOT_CHECKED;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_NOT_CHECKED;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';	
	
	$error_type=get_error_type($results['instances']);
	update_message('6.6', $error_type);
	
	return $results;
}

function NZ_S_7_1($parse){
	//Until user agents support explicit associations between labels and form controls, for all form controls with implicitly associated labels, ensure that the label is properly positioned.
	
	//Priority:		Standard
	
	//Techniques:	http://www.w3.org/TR/AERT#associate-labels
	
	//Methods:		We are ignoring submit, reset and hidden inputs, as well as buttons and images (often used as buttons)
		
	//TODO:			This does not check to make sure that the text is immediately next to the element
	
	//NOTE:			If the text is contained within <div> element, then the next parent is selected.  This could include much more text than is strictly relevant
	//				See NZ_S_7_1 test page for an example.
	
	//TODO:			Perhaps not trigger a failure/warning when the entire text is a link?
	//				(example: e.govt.nz and the link 'advanced search')
	
	$timeout=get_timeout();
	
	create_message('7.1', 'Until user agents support explicit associations between labels and form controls, for all form controls with implicitly associated labels, ensure that the label is properly positioned.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h7';
	
	$hasFailed=false;
	
	$blocks=load_block_elements(false);
	//Div tags frequently prevent this rule from identifying associated text, so we are going to ignore them here
	unset($blocks['div']);
	
	$temp=$parse->getElementsByTagname('input');
	$temp=array_merge($temp, $parse->getElementsByTagName('select'));
	$temp=array_merge($temp, $parse->getElementsByTagName('textarea'));
	
	if(count($temp)>0){
		$allLabels=$parse->getElementsByTagname('label');
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$found=false;
			$type=$parse->getAttribute($this_element, 'type', true);
			
			//we are not checking hidden elements, as well as submit and cancel buttons
			if($type!='hidden' && $type!='submit' && $type!='reset' && $type!='button' && $type!='image'){
				//Does this element have an id?
				$id=$parse->getAttribute($this_element, 'id', true);
				//if so, is there a label with this id as a 'for' attribute value?
				if($id!=''){
					foreach($allLabels as $this_label){
						
						if(time()>$timeout)
							break;
			
						$for=$parse->getAttribute($this_label, 'for', true);
						if($for==$id){
							$found=true;
							break;
						}
					}
				}
				if(!$found){
					//Is this element's parent element a label?
					$parent=$parse->parentElement($this_element);
					$tagname=$parse->tagname($parent);
					if($tagname!='label'){
						//move up the list until a block element is found
						if(!isset($blocks[$tagname])){
							while(!isset($blocks[$tagname])){
								
								if(time()>$timeout)
									break;
								
								$parent=$parse->parentElement($parent);
								$tagname=$parse->tagname($parent);
								
								if($tagname=='label'){
									$found=true;
									break;
								}
								
								if($parent==0)
									break;
								
							}
						} 
						
					} else $found=true;
										
					if(!$found){
						$innerText_orig=$parse->innerText($parent, Array('legend'));
						$innerText=trim(strip_spaces($innerText_orig));
						if($innerText!=''){
							$result_key='This input field appears to have text associated with it which is not in a label associated with this input field.';
							$results['instances'][$result_key]['indices'][]=$this_element;
							$results['instances'][$result_key]['type'][]=RESULT_WARNING;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
							$results['instances'][$result_key]['highlight_attribute'][]='';
							$results['instances'][$result_key]['info'][]="The text is &quot;<span class=\"quote\">" . $innerText_orig . "&quot;</span>";
							$hasFailed=true;
						}
					}
				}
			}
		
		}
		if(!$hasFailed){
			$result_key='No input fields had unassociated text';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No form elements were found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('7.1', $error_type);
	
	return $results;
}

function NZ_S_7_2($parse){
	//Create a logical tab order through links, form controls and objects.

	//Priority:		May
	
	//Techniques:	http://www.w3.org/TR/AERT#forms-keyboard
	//				If there is a tab index on any of these elements, then a warning is raised if any element of the same type does not carry a tabindex.
	//				Forms get a warning if no elements have a tabindex
	//				warnings are only raised for links without tabindexes if a tabindex is already present on another link
	
	//				http://unfortunatelypaul.com/2005/03/16/tabindex/
	
	//TODO:			What is the maximum allowed tab index?
	
	$timeout=get_timeout();
	
	create_message('7.2', 'Create a logical tab order through links, form controls and objects.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h7';
	
	$hasFailed=false;
	$required=false;
	
	//get all the links:
	$temp=$parse->getElementsByTagname('a');
	if(count($temp)>0){
		$required=false;
		$links=Array();
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$tab_index=$parse->getAttribute($this_element, 'tabindex');
			if($tab_index==''){
				//this link has no tab index.. store it in the array incase we find a tab index later
				$links[]=$this_element;
			} else {
				if($tab_index<0 || !is_numeric($tab_index)){
					$result_key='This link has an invalid tab order value.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
					$results['instances'][$result_key]['highlight_attribute'][]='tabindex';
					$hasFailed=true;
				} else
					$required=true;
				
			}
		}
		if($required){
			foreach($links as $this_link){
				
				if(time()>$timeout)
					break;
				
				$result_key='This link is missing a tab order. A tab order makes links easier to navigate for many users.';
				$results['instances'][$result_key]['indices'][]=$this_link;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
	}
	//get all the area map hotspots:
	//we want to restrict this to a per-map basis
	
	$temp=$parse->getElementsByTagname('map');
	foreach($temp as $this_map){
		
		if(time()>$timeout)
			break;
			
		$all_areas=$parse->all_descendants($this_map, 'area');
		$links=Array();
		$required=false;
		foreach($all_areas as $this_area){
			
			if(time()>$timeout)
				break;
				
			$tab_index=$parse->getAttribute($this_area, 'tabindex');
			if($tab_index==''){
				//this link has no tab index.. store it in the array incase we find a tab index later
				$links[]=$this_area;
			} else {
				if($tab_index<0 || !is_numeric($tab_index)){
					$result_key='This area link has an invalid tab order value.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
					$results['instances'][$result_key]['highlight_attribute'][]='tabindex';
					$hasFailed=true;
				} else
					$required=true;
				
			}
		}
		if($required){
			foreach($links as $this_link){
				
				if(time()>$timeout)
					break;
				
				$result_key='This area link is missing a tab order. A tab order makes links easier to navigate for many users.';
				$results['instances'][$result_key]['indices'][]=$this_link;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
		
	}
	
	$all_forms=$parse->getElementsByTagname('form');
	foreach($all_forms as $this_form){
		
		if(time()>$timeout)
			break;
				
		//The problem here is that we need to check all the different input types in this form for any instances of tabindex attributes
		$required=false;
		$links=Array();
		//get all the form controls:
		$temp=$parse->all_descendants($this_form, 'input');
		if(count($temp)>0){
			foreach($temp as $this_element){

				if(time()>$timeout)
					break;
				
				$type=$parse->getAttribute($this_element, 'hidden', true);
				if($type!='hidden'){
					$tab_index=$parse->getAttribute($this_element, 'tabindex');
					if($tab_index==''){	
						//this link has no tab index, store it in the array incase we find a tab index later
						$links[]['indice']=$this_element;
						$links[count($links)-1]['type']='form';
					} else {
						if($tab_index<0 || !is_numeric($tab_index)){
							$result_key='This form control has an invalid tab order value.';
							$results['instances'][$result_key]['indices'][]=$this_element;
							$results['instances'][$result_key]['type'][]=RESULT_FAIL;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
							$results['instances'][$result_key]['highlight_attribute'][]='tabindex';
							$hasFailed=true;
						} else
							$required=true;
						
					}
				}
			}
		}
		
		//get all the button controls:
		$temp=$parse->all_descendants($this_form, 'button');
		if(count($temp)>0){
			foreach($temp as $this_element){
				
				if(time()>$timeout)
					break;
					
				$tab_index=$parse->getAttribute($this_element, 'tabindex');
				if($tab_index==''){	
					//this link has no tab index.. store it in the array incase we find a tab index later
					$links[]['indice']=$this_element;
					$links[count($links)-1]['type']='button';
				} else {
					if($tab_index<0 || !is_numeric($tab_index)){
						$result_key='This button control has an invalid tab order value.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
						$results['instances'][$result_key]['highlight_attribute'][]='tabindex';
						$hasFailed=true;
					} else
						$required=true;
					
				}
			
			}
		}
		//get all the select controls:
		$temp=$parse->all_descendants($this_form, 'select');
		if(count($temp)>0){
			foreach($temp as $this_element){
				
				if(time()>$timeout)
					break;
				
				$tab_index=$parse->getAttribute($this_element, 'tabindex');
				if($tab_index==''){	
					//this link has no tab index.. store it in the array incase we find a tab index later
					$links[]['indice']=$this_element;
					$links[count($links)-1]['type']='select';
				} else {
					if($tab_index<0 || !is_numeric($tab_index)){
						$result_key='This select control has an invalid tab order value.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
						$results['instances'][$result_key]['highlight_attribute'][]='tabindex';
						$hasFailed=true;
					} else
						$required=true;
					
				}
			
			}
		}
		//get all the textarea controls:
		$temp=$parse->all_descendants($this_form, 'textarea');
		if(count($temp)>0){
			foreach($temp as $this_element){
				
				if(time()>$timeout)
					break;
				
				$tab_index=$parse->getAttribute($this_element, 'tabindex');
				if($tab_index==''){	
					//this link has no tab index.. store it in the array incase we find a tab index later
					$links[]['indice']=$this_element;
					$links[count($links)-1]['type']='textarea';
				} else {
					if($tab_index<0 || !is_numeric($tab_index)){
						$result_key='This textarea control has an invalid tab order value.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
						$results['instances'][$result_key]['highlight_attribute'][]='tabindex';
						$hasFailed=true;
					} else
						$required=true;
					
				}
			
			}
		}
		if($required){
			foreach($links as $this_link){
				
				if(time()>$timeout)
					break;
				
				$result_key='This ' . $this_link['type'] . ' control is missing a tab order. A tab order makes form controls easier to navigate for many users.';
				$results['instances'][$result_key]['indices'][]=$this_link['indice'];
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
	}
	
	//get all the objects:
	$temp=$parse->getElementsByTagname('object');
	if(count($temp)>0){
		$required=false;
		$links=Array();
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$tab_index=$parse->getAttribute($this_element, 'tabindex');
			if($tab_index==''){
				//this link has no tab index.. store it in the array incase we find a tab index later
				$links[]=$this_element;
			} else {
				if($tab_index<0 || !is_numeric($tab_index)){
					$result_key='This form control has an invalid tab order value.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
					$results['instances'][$result_key]['highlight_attribute'][]='tabindex';
					$hasFailed=true;
				} else
					$required=true;
				
			}		
		}
		if($required){
			foreach($links as $this_link){
				
				if(time()>$timeout)
					break;
				
				$result_key='This object control is missing a tab order. A tab order makes form controls easier to navigate for many users.';
				$results['instances'][$result_key]['indices'][]=$this_link;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
	}

	if(!$hasFailed && $required){
		$result_key='All required elements had tab orders.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	if(!$hasFailed && !$required){
		$result_key='No elements required tab orders.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('7.2', $error_type);
	
	return $results;
}

function NZ_S_7_3($parse){
	//Include non-link, printable characters (surrounded by spaces) between adjacent links and also have a space between links.
	
	//Priority:		Standard
	
	//Techniques:	http://www.w3.org/TR/AERT#divide-links
	
	//Methods:		If two <a> tags are found in sequential order, then this is raised as an error.
	
	//TODO:			Perhaps check to see if the elements have been redefined as block/inline elements?
	
	//TODO:			I have disabled the 'space on each side of separator' requirement because it's a bit vague
	
	$timeout=get_timeout();
	
	create_message('7.3', 'Include non-link, printable characters (surrounded by spaces) between adjacent links and also have a space between links.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h7';
	
	$hasFailed=false;
	
	//get all the anchor tags, and check to see if the next tag is another anchor tag... if so, it has failed.
	$temp=$parse->getElementsByTagname('a');
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			if(time()>$timeout)
				break;
			
			$innerText=strip_spaces($parse->innerText($this_element), true);
			if($innerText!='' && $parse->specified($this_element, 'href')){
				//okay, so this link has text, let's see if the very next element is also a link
				//get the closing index
				$closing_index=$parse->allElements[$this_element]['closingIndex'];
				
				//ok, so get the next element after this closing element
				//if it is a block element (opening or closing), then exit
				$not_link=true;
				$link_found=false;
				$next=$closing_index;
				
				$tagname=$parse->tagname($next);
				do {
					$next=$parse->getNextElement($next, 'forward', true);
					
					if(!$next)
						break;
					
					$tagname=$parse->tagname($next);
					
					if(tagType($tagname)==PARSE_BLOCK_ELEMENT && !$parse->isOrphan($next))
						break;
						
					if($tagname=='a' && !$parse->isClosing($next)){
						$innerText=strip_spaces($parse->innerText($next), true);
						if($innerText!='' && $parse->specified($next, 'href')){
							$link_found=true;
							break;
						}
					}
					
				} while($not_link);
					
				if($link_found){
					$text=strip_spaces($parse->text($closing_index), false);
					if($text==''){
						$result_key="This link does not have a separating character between it and the next link.";
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$results['instances'][$result_key]['info'][]="The two adjacent links are:<br><span class=\"quote\">" . htmlspecialchars($parse->outerHTML($this_element)) . "</span><br>and<br><span class=\"quote\">" . htmlspecialchars($parse->outerHTML($next)) . "</span>.";
						$hasFailed=true;
					}
				}
			}
		}
	
		if(!$hasFailed){
			$result_key='No text links were found adjacent to one another.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No anchor tags were found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('7.3', $error_type);
	
	return $results;
}

function NZ_S_7_4($parse){
	//Web pages are able to be printed in whole. Where a page requires landscape orientation to achieve this, it must be made clear to the user.
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Note:			This is a user check
	
	$timeout=get_timeout();
	
	create_message('7.4', 'Web pages are able to be printed in whole. Where a page requires landscape orientation to achieve this, it must be made clear to the user.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h7';
	
	$result_key='Where a page requires landscape orientation to achieve this, it must be made clear to the user.';
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('7.4', $error_type);
	
	return $results;
}

function NZ_S_8_1($parse){
	//Clearly identify the target of each link. It must be clear to the user where that link will take them. Everything that is a link is obvious as a link.
	
	//Priority:	Standard
	
	//Techniques: http://www.w3.org/TR/AERT#meaningful-links
	
	//TODO:			Check to see that the title is not longer than 60 characters before recommending it
	//TODO:			The title switch recommendation does not appear as different messages
	
	$timeout=get_timeout();
	create_message('8.1', 'Clearly identify the target of each link. It must be clear to the user where that link will take them. Everything that is a link is obvious as a link.');
	
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h8';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('a');
	$used=Array();
	
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$text=$parse->innerText($this_element);
		$title=$parse->getAttribute($this_element, 'title');
		$link=$parse->href($this_element);
		
		$text2=strtolower(trim(strip_spaces($text)));
				
		if($text2!='' && $link!='' && isset($used[$text2]['text']) && @$used[$text2]['link']!=$link){
			$result_key="This link text ('<span class=\"quote\">" . $text . "'</span>) has already been used for a different destination.";
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='This link text has also been used for this destination: ' . $used[$text2]['link'];
			$hasFailed=true;
			
		} else {
		
			switch(TRUE){
				case($text2=='click here'):
					$result_key="This link text may not be meaningful when read on its own: <span class=\"quote\">" . $text . "</span>";
					$results['instances'][$result_key]['indices'][]=$this_element;
					
					if($title!='')
						$results['repair'][]='Perhaps the title attribute (\'' . $title . '\') could be used as the link text.';
					else
						$results['repair'][]='If you are trying to make a Level Triple A site, you could provide additional information about the link in the title attribute.';
					
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
					break;
				case($text2=='more'):
					$result_key="This link text may not be meaningful when read on its own:  <span class=\"quote\">" . $text . "</span>";
					$results['instances'][$result_key]['indices'][]=$this_element;
					
					if($title!='')
						$results['repair'][]='Perhaps the title attribute (\'' . $title . '\') could be used as the link text.';
					else
						$results['repair'][]='If you are trying to make a Level Triple A site, you could provide additional information about the link in the title attribute.';
					
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
					break;
				case($text2=='follow this'):
					$result_key="This link text may not be meaningful when read on its own:  <span class=\"quote\">" . $text . "</span>";
					$results['instances'][$result_key]['indices'][]=$this_element;
					
					if($title!='')
						$results['repair'][]='Perhaps the title attribute (\'' . $title . '\') could be used as the link text.';
					else
						$results['repair'][]='If you are trying to make a Level Triple A site, you could provide additional information about the link in the title attribute.';
					
					
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
					break;
				case(strlen($text2)>60):
					$result_key='This link text is quite long and should be shortened.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					
					if($title!='')
						$results['repair'][]='Perhaps the title attribute (\'' . $title . '\') could be used as the link text.';
					else
						$results['repair'][]='If you are trying to make a Level Triple A site, you could provide additional information about the link in the title attribute.';
					
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
					break;
			}
			
			if($text2!='' && $link!=''){
				$used[$text2]['text']=$text2;
				$used[$text2]['link']=$link;
			}
		}
	}
	if(!$hasFailed){
		$result_key='All links clearly identified their targets.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('8.1', $error_type);
	
	return $results;
}

function NZ_S_8_2($parse){
	//External and internal links should be checked regularly, or incorporate an automatic checking process to ensure that the links are valid. Broken or ‘moved’ links should be corrected, removed or the linking text updated accordingly.	
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		We are going to get all the links to destinations except for mailtos: and check the server response...
	
	//TODO:			This does not include <area> elements....
	
	//NOTE:			invalid domains such as .co.nzzzz return a 302 result which is not technically an error....
	
	$timeout=get_timeout();
	
	create_message('8.2', 'External and internal links should be checked regularly, or incorporate an automatic checking process to ensure that the links are valid. Broken or ‘moved’ links should be corrected, removed or the linking text updated accordingly.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h8';
	
	if($parse->check_links()=='t'){
		$temp=$parse->getElementsByTagname('a');
		
		$hasFailed=false;
		
		$links=Array();
		
		if(count($temp)>0){
			foreach($temp as $this_element){
				$href=$parse->href($this_element);
				//clean link:
				$href=clean_url($href);
				
				if(!isset($links[$href]) && $href!=''){
					$protocol=get_protocol($href);
					if($href!='' && $protocol!='mailto'){
						$headers=fetch_file($href);
						if(!is_response_good($headers)){
							$result_key='This link is not valid.';
							$results['instances'][$result_key]['indices'][]=$this_element;
							$results['instances'][$result_key]['type'][]=RESULT_FAIL;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE_INCLUDE_CONTENTS;
							$results['instances'][$result_key]['highlight_attribute'][]='href';
							$hasFailed=true;
						}
					}
					$links[$href]=true;
				}
			}
			
			if(!$hasFailed){
				$result_key='All links are valid.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			}
		} else {
			$result_key='No links were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key=USER_CHECK;
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_USER;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';	
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('8.2', $error_type);
	
	return $results;
}

function NZ_S_8_3($parse){
	//As a minimum, every web page under ownership of the agency must have the following links:- 1.	To a homepage. If using an agency logo on a web page, it links to the homepage and has alt text of "Go to home page - Agency Name". This is irrespective of whether the user is currently on a homepage. Note: ‘Homepage’ as defined in the Glossary of Key Concepts, page 141. 2.	To “About this Site”, as defined in standard 16.3 on page 56. The name of the link is “About this site” 3.	To a privacy notice. The name of the link must contain the word “Privacy”. The privacy notice is as per standard 16.7 on page 59 and located within a web site as per standard 16.3 on page 56. 

	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		Get all internal links and check each link text for the required words
	
	//NOTE:			Incomplete alt text for logos will still get a pass because we are not tracking the department name
	//				We are also not tracking the logo, so any image which links to the homepage will be detected
	
	//TODO:			Check to see what happens with obscure homepage links, like url.com/# and url.com/?something
	
	$timeout=get_timeout();
	
	create_message('8.3', 'As a minimum, every web page under ownership of the agency must have the following links:- 1.	To a homepage. If using an agency logo on a web page, it links to the homepage and has alt text of "Go to home page - Agency Name". This is irrespective of whether the user is currently on a homepage. Note: ‘Homepage’ as defined in the Glossary of Key Concepts, page 141. 2.	To “About this Site”, as defined in standard 16.3 on page 56. The name of the link is “About this site” 3.	To a privacy notice. The name of the link must contain the word “Privacy”. The privacy notice is as per standard 16.7 on page 59 and located within a web site as per standard 16.3 on page 56.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h8';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('a');
	
	$homepage=$parse->homepage();
	$site_domain=$parse->getDomain();
	$department_name=$parse->departmentName();
	
	$homepage_link_found=false;
	
	$about_link_found=false;
	$privacy_link_found=false;
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			$href=$parse->href($this_element);
			if(get_domain($href)==$site_domain){
				//ok, so it's a local link, lets look at the text
				$text=strtolower($parse->innerText($this_element));
				//no text link requirement for the home page, so we'll just check for anything
				//if(strip_spaces($text, true)!='' && ($href==$homepage || $href==$homepage . '/')){
				if($href==$homepage || $href==$homepage . '/'){
					//we need to check if there's an image in this link, because if there is, it needs special alt text
					//NOTE: We are allowing homepage links with no text!
					
					$homepage_link_found=true;
					
					$children=$parse->all_descendants($this_element, 'img');
					
					foreach($children as $this_child){
						$alt=strtolower($parse->getAttribute($this_child, 'alt', true));
						
						if($alt!='go to home page - ' . strtolower($department_name)){
							$result_key='The alt text is incorrect.';
							$results['instances'][$result_key]['indices'][]=$this_child;
							$results['instances'][$result_key]['type'][]=RESULT_FAIL;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
							$results['instances'][$result_key]['highlight_attribute'][]='alt';
							($department_name=='') ? $department_text='[Department name]' : $department_text=$department_name;
							$results['instances'][$result_key]['info'][]='This image links to the homepage and the alt text should say \'Go to homepage - ' . $department_text;
							$hasFailed=true;
						}
													
					}					
				}
									
				if(strpos($text, 'about this site')!==false)
					$about_link_found=true;
				
				if(strpos($text, 'privacy')!==false)
					$privacy_link_found=true;

			}
		}
		
		if(!$homepage_link_found){
			$result_key='No link to the home page was found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='This page requires a link to the homepage.';
			$hasFailed=true;
		} 
		
		if(!$about_link_found){
			$result_key='No link to the \'about\' page was found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='This page requires a link to the about page with the text \'about this site\' in it.';
			$hasFailed=true;
		}
		
		if(!$privacy_link_found){
			$result_key='No link to the privacy page was found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='This page requires a link to the privacy page with the text \'privacy\' in it.';
			$hasFailed=true;
		}
		
		if(!$hasFailed){
			$result_key='All the required links were found';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		
		
	} else {
		$result_key='No links were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('8.3', $error_type);
	
	return $results;
}

function NZ_S_8_4($parse){
	//Navigation Access keys are used within the site as follows: Access key 1 is provided for Home. Access key 2 is provided for Site Map. Access key 3 is provided for Search. Access key 9 is provided for Contact Us. Access key [ is provided for beginning of main content. This is known as a Skip Link. Access key / is provided for “Go to http://www.govt.nz” 

	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		Get all the links and check each of them for the accesskey attribute
	
	//TODO:			In the case of the .govt.nz link, make sure it actually goes to this destination
	
	$timeout=get_timeout();
	
	create_message('8.4', 'Navigation Access keys are used within the site as follows: Access key 1 is provided for Home. Access key 2 is provided for Site Map. Access key 3 is provided for Search. Access key 9 is provided for Contact Us. Access key [ is provided for beginning of main content. This is known as a Skip Link. Access key / is provided for “Go to http://www.govt.nz”.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['rule_text']='Provide metadata to add semantic information to pages and sites.';
	$results['header']='h8';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('a');
	$temp=array_merge($temp, $parse->getElementsByTagName('input'));
	$temp=array_merge($temp, $parse->getElementsByTagName('textarea'));
	$temp=array_merge($temp, $parse->getElementsByTagName('select'));
	$temp=array_merge($temp, $parse->getElementsByTagName('button'));
	
	$key1=false;
	$key2=false;
	$key3=false;
	$key4=false;
	$key5=false;
	$key6=false;
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			$accesskey=$parse->getAttribute($this_element, 'accesskey');
			switch($accesskey){
				case '1':
					$key1=true;
					break;
				case '2':
					$key2=true;
					break;
				case '3':
					$key3=true;
					break;
				case '9':
					$key4=true;
					break;
				case '[':
					$key5=true;
					break;
				case '/':
					$key6=true;
					break;
			}
		}
	
		if(!$key1){
			$result_key='The access key \'1\' was not fouund.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='A link to the homepage with the access key \'1\' needs to be included.';
			$hasFailed=true;
		}
		
		if(!$key2){
			$result_key='The access key \'2\' was not fouund.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='A link to the site map with the access key \'2\' needs to be included.';
			$hasFailed=true;
		}
		
		if(!$key3){
			$result_key='The access key \'3\' was not fouund.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='A link to the search form with the access key \'3\' needs to be included.';
			$hasFailed=true;
		}
		
		if(!$key4){
			$result_key='The access key \'9\' was not fouund.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='A link to the contact page with the access key \'9\' needs to be included.';
			$hasFailed=true;
		}
		
		if(!$key5){
			$result_key='The access key \'[\' was not fouund.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='A link to the start of the content with the access key \'[\' needs to be included.';
			$hasFailed=true;
		}
		
		if(!$key6){
			$result_key='The access key \'/\' was not fouund.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='A link to govt.nz with the access key \'/\' needs to be included.';
			$hasFailed=true;
		}
		
		if(!$hasFailed){
			$result_key='All the required access keys were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No access keys were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_FAIL;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$results['instances'][$result_key]['info'][]='All of the required access keys are missing from this page.';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('8.4', $error_type);
	
	return $results;
}

function NZ_S_9_1($parse){
	//Organise documents so they may be read without stylesheets.  For example, when an HTML document is rendered without associated style sheets, it must still be possible to read the document.

	//Priority:		Must
	
	//Techniques:	http://www.w3.org/TR/AERT#style-sheet-guidelines
	
	//TODO:			Are the text/css checks too restrictive?
	
	$timeout=get_timeout();
	
	create_message('9.1', 'Organise documents so they may be read without stylesheets.  For example, when an HTML document is rendered without associated style sheets, it must still be possible to read the document.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h9';
	
	$found=false;
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('link');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
				
		$rel=$parse->getAttribute($this_element, 'rel', true);
		$type=$parse->getAttribute($this_element, 'type', true);
		$media=$parse->getAttribute($this_element, 'media', true);
		//NOTE: This does not check to see if there is an href attribute or that it is valid
		if(($rel=='stylesheet' || $rel=='alternate' || $rel=='') && $type=='text/css' && ($media=='' || $media=='all' || $media=='screen')){
			$result_key='Please ensure that this document can be read without style sheets.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_USER;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='Try disabling stylesheets on this page or in your browser to check this requirement.';
			$hasFailed=true;
			$found=true;
			break;
		}
	}
	
	if(!$found){
		$temp=$parse->getElementsByTagname('style');
		$found=false;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$type=$parse->getAttribute($this_element, 'type', true);
			$media=$parse->getAttribute($this_element, 'media', true);
			if($type=='text/css' && ($media=='' || $media=='all' || $media=='screen')){
				$found=true;
				break;
			}
		}
		//check that at least one of these has text/css as a type
		if($found){
			$result_key='Please ensure that this document can be read without style sheets.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_USER;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='Try disabling stylesheets on this page or in your browser to check this requirement.';
			$hasFailed=true;
			$found=true;
		}
	}
	
	if(!$found){
		$temp=$parse->getElementsByAttribute('style');
		if(sizeof($temp)>0){
			$result_key='Please ensure that this document can be read without style sheets.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='Try disabling stylesheets on this page or in your browser to check this requirement.';
			$hasFailed=true;
		}
	}
	if(!$hasFailed){
		$result_key='No style sheets were used.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('9.1', $error_type);
	
	return $results;
}

function NZ_S_9_2($parse){
	//Use style sheets to control layout and presentation.

	//Priority:		Standard
	
	//NOTE:			Should a border on a table raise a warning?  How about images?
	//				How do we handle instances where a display attribute is used, but a stylesheet equivilent is also used?
	
	//TODO:			Perhaps check the stylesheets to see if this element has this display attribute specified?
	//TODO:			I think that a:hover { text-decoration: underline} is being incorrectly picked up
	//TODO:			Ignore cellspacing, cellpadding, border, etc?
	
	$timeout=get_timeout();
	
	create_message('9.2', 'Use style sheets to control layout and presentation.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h9';
	
	$hasFailed=false;
	
	$attributes=Array();
	
	$visuals=load_display_attributes();
	
	//Go through each tag and check it's attributes for visual appearance-based attributes
	$temp=$parse->getAllElements();
	for($i=0; $i<count($temp); $i++){
		
		if(time()>$timeout)
			break;
		
		//for some reason, the count() value may actually be higher than the number of elements, so
		//we need to use the isset() function (www.nytimes.com)
		if(isset($temp[$i]) && ($temp[$i]['is_closing']==false && ($temp[$i]['tagname']!='!'))){
			$attributes=$parse->getAttributes($i);
			foreach($attributes as $this_attribute){
				
				if(time()>$timeout)
					break;
			
				if(isset($visuals[strtolower($this_attribute['name'])])){
					$result_key='Visual display attributes were found in the HTML.';
					$results['instances'][$result_key]['indices'][]=$i;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
					$results['instances'][$result_key]['highlight_attribute'][]=$this_attribute['name'];
					$results['instances'][$result_key]['info'][]='This visual display attribute (\'' . $this_attribute['name'] . '\') should be specified in a stylesheet.';
					$hasFailed=true;
				}
			}
		}
	}
	if(!$hasFailed){
		$result_key='No visual display attributes found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('9.2', $error_type);
	
	return $results;
}

function NZ_S_10_1($parse){
	//Ensure that dynamic content is accessible or provide an alternative presentation or page.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#fallback-page
		
	$timeout=get_timeout();
	
	create_message('10.1', 'Ensure that dynamic content is accessible or provide an alternative presentation or page.');
	
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h10';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('frameset');
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$descendants=$parse->all_descendants($this_element, 'noframes');
			if(count($descendants)==0){
				$result_key='No <code>noframes</code> element was found within this frameset.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				
				$resul;
				$hasFailed=true;
			} else {
				//There could be many noframes, but usually only one...
				foreach($descendants as $this_element2){
					
					if(time()>$timeout)
						break;
						
					$innerText=strtolower($parse->innerText($this_element2));
					if(str_word_count($innerText)>1){
						//are there any links?
						$descendants2=$parse->all_descendants($this_element2, 'a');
						if(count($descendants2)==0){
							$result_key='This <code>noframes</code> element does not appear to contain navigation links.';
							$results['instances'][$result_key]['indices'][]=$this_element2;
							$results['instances'][$result_key]['type'][]=RESULT_WARNING;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
							$results['instances'][$result_key]['highlight_attribute'][]='';
							$hasFailed=true;
						}
						//check each word
						$words=str_word_count($innerText,1);
						for($i=0;$i<count($words);$i++){

							if(time()>$timeout)
								break;
								
							if($words[$i]=='upgrade' || $words[$i]=='missing' || ($words[$i]=='full' && @$words[$i+1]=='advantage') || ($words[$i]=='supports' && @$words[$i+1]=='frames')){
								$result_key='Does your page work if frames are not loaded?';
								$results['instances'][$result_key]['indices'][]=$this_element;
								$results['instances'][$result_key]['type'][]=RESULT_WARNING;
								$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
								$results['instances'][$result_key]['highlight_attribute'][]='';
								$hasFailed=true;
							}
						}
					} else {
						$result_key='The <code>noframes</code> element must contain some text.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT_INCLUDE_CONTENTS;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$hasFailed=true;
					}
					
				}
			}
		}
		if(!$hasFailed){
				$result_key='All framesets contain alternative text.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			}
	} else {
		$result_key='No framesets were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('10.1', $error_type);
	return $results;
}

function NZ_S_10_2($parse){
	//Web pages are not to contain any blinking or scrolling text, or flashing objects.
	
	//Priority:		Standard
	
	//Techniques:	This is a blend of two WAI rules, WAI_2_7_2 and WAI_2_7_3
	
	//Methods:		get all BLINK elements and raise fails, also get all MARQUEE, object, applet and embed elements and raise fails.
	
	//TODO:			Do we want to check stylesheets for the blink property?
	
	$timeout=get_timeout();
	
	create_message('10.2', 'Web pages are not to contain any blinking or scrolling text, or flashing objects.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h10';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('blink');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='The <code>blink</code> element is not defined in any W3C HTML specification and should not be used.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='If you really need to use blinking text, use the stylesheet property &quot;text-decoration: blink&quot;';
			$hasFailed=true;
		}
	} 
	
	$temp=$parse->getElementsByTagname('marquee');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='The <code>marquee</code> element is not defined in any W3C HTML specification and should not be used.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='Moving text is generally considered to be an annoyance.  You could use the stylesheet property &quot;text-decoration: blink&quot; instead.';
			$hasFailed=true;
		}
	}
	
	$temp=$parse->getElementsByTagname('object');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='Please confirm that this <code>object</code> element does not contain any moving text.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='Moving text is generally considered to be an annoyance.  You could use the stylesheet property &quot;text-decoration: blink&quot;.';
			$hasFailed=true;
		}
	}
	$temp=$parse->getElementsByTagname('embed');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='Please confirm that this <code>embed</code> element does not contain any moving text.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='Moving text is generally considered to be an annoyance.  You could use the stylesheet property &quot;text-decoration: blink&quot;.';
			$hasFailed=true;
		}
	}
	$temp=$parse->getElementsByTagname('applet');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='Please confirm that this <code>applet</code> element does not contain any moving text.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='Moving text is generally considered to be an annoyance.  You could use the stylesheet property &quot;text-decoration: blink&quot;.';
			$hasFailed=true;
		}
	}
	
	if(!$hasFailed){
		$result_key='No potentially moving items were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('10.2', $error_type);
	
	return $results;
}

function NZ_S_11_1($parse){
	//For data tables, identify row and column headers.
	
	//Priority:		Standard
	
	//Techniques:	http://www.w3.org/TR/AERT#table-headers
	
	//NOTE:			We are ignoring the AXIS attribute
	//TODO:			Please review
	//TODO:			Perhaps perform a check for <th> tags as well?
	
	//NOTE:			http://www.dbh.govt.nz/sector-activity-index
	
	$timeout=get_timeout();
	
	create_message('11.1', 'For data tables, identify row and column headers.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h11';
	
	$hasFailed=false;
	$found=false;
	$foundHeaders=false;
	$foundRows=false;
	
	$temp=$parse->getElementsByTagname('table');
	if(count($temp)){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			//check each td and th element and check for the presence of either 'scope' or 'headers' attributes
			if(is_data_table($parse, $this_element)){
				//this is a data table
				$found=true;
				$foundRows=false;
				$foundHeaders=false;
				$descendants=$parse->all_descendants($this_element);
				foreach($descendants as $this_descendant){
					
					if(time()>$timeout)
						break;
						
					$tagname=$parse->tagname($this_descendant);
					if($tagname=='td' || $tagname=='th'){
						$scope=$parse->getAttribute($this_descendant, 'scope');
						$headers=$parse->getAttribute($this_descendant, 'headers');
						if($scope!='' || $headers!=''){
							
							if($tagname=='th')
								$foundHeaders=true;
							else
								$foundRows=true;
							
						}
					}
				}
				
				if($foundHeaders==false && $foundRows==false){
					$result_key='This table is missing headers.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
				} else {
					
					if(!$foundHeaders){
						$result_key='This table has column headers but may require row headers.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$hasFailed=true;
					}
					if(!$foundRows){
						$result_key='This table has row headers but may require column headers.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$hasFailed=true;
					}
					//if($foundHeaders && $foundRows){
					//	$result_key='This table has identified the rows and columns.';;
					//	$results['instances'][$result_key]['indices'][]=$this_element;
					//	$results['instances'][$result_key]['type'][]=RESULT_PASS;
					//	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
					//	$results['instances'][$result_key]['highlight_attribute'][]='';
					//	$hasFailed=false;
					//}
				}
			}
		}
		
		if(!$hasFailed){
			if($found){
				$result_key='All data tables included row or column headers.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;	
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			} else {
				$result_key='No data tables were found.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;	
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			}
		}
	} else {
		$result_key='No tables were found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('11.1', $error_type);
	
	return $results;
}

function NZ_S_11_2($parse){
	//For data tables that have two or more logical levels of row or column headers, use markup to associate data cells and header cells.
	
	//Priority:		Standard
	
	//Techniques:	http://www.w3.org/TR/AERT#table-structure
	
	//NOTE:			We are ignoring the AXIS attribute
	
	$timeout=get_timeout();
	
	create_message('11.2', 'For data tables that have two or more logical levels of row or column headers, use markup to associate data cells and header cells.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h11';
	
	$hasFailed=true;
	$found=false;
	$foundHeaders=false;
	$foundRows=false;
	
	$temp=$parse->getElementsByTagname('table');
	if(count($temp)){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$row_count=0;
			$col_count=0;
			$max_cols=0;
			//check each td and th element and check for the presence of either 'scope' or 'headers' attributes
			if(is_data_table($parse, $this_element)){
				//this is a data table
				$found=true;
				$foundRows=false;
				$foundHeaders=false;
				$descendants=$parse->all_descendants($this_element);
				foreach($descendants as $this_descendant){
					
					if(time()>$timeout)
						break;
				
					$tagname=$parse->tagname($this_descendant);
					if($tagname=='td' || $tagname=='th'){
						$col_count++;
						$scope=$parse->getAttribute($this_descendant, 'scope');
						$headers=$parse->getAttribute($this_descendant, 'headers');
						if($scope!='' || $headers!=''){
							
							if($tagname=='th')
								$foundHeaders=true;
							else
								$foundRows=true;
							
						}
					}
					if($tagname=='tr'){
						
						if($col_count>$max_cols)
							$max_cols=$col_count;	
						
						$row_count++;
					}
				}
				if($row_count>1 || $max_cols>1){
					if($foundHeaders==false && $foundRows==false){
						$result_key='This table is missing headers.';
						$results['instances'][$result_key]['indices'][]=$this_element;
						$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
						$results['instances'][$result_key]['highlight_attribute'][]='';
						$hasFailed=true;
					} else {
						if(!$foundHeaders){
							$result_key='This table has column headers but may require row headers.';
							$results['instances'][$result_key]['indices'][]=$this_element;
							$results['instances'][$result_key]['type'][]=RESULT_FAIL;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
							$results['instances'][$result_key]['highlight_attribute'][]='';
							$hasFailed=true;
						}
						if(!$foundRows){
							$result_key='Table has row headers but may require column headers.';
							$results['instances'][$result_key]['indices'][]=$this_element;
							$results['instances'][$result_key]['type'][]=RESULT_FAIL;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
							$results['instances'][$result_key]['highlight_attribute'][]='';
							$hasFailed=true;
						}
						//if($foundHeaders && $foundRows){
						//	$result_key='This table has identified the rows and columns.';
						//	$results['instances'][$result_key]['indices'][]=$this_element;
						//	$results['instances'][$result_key]['type'][]=RESULT_FAIL;
						//	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
						//	$results['instances'][$result_key]['highlight_attribute'][]='';
						//	$hasFailed=true;
						//}
					}
				} else {
					$result_key='No data tables require rows or columns to be identified.';
					$results['instances'][$result_key]['indices'][]=-1;
					$results['instances'][$result_key]['type'][]=RESULT_PASS;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=false;
				}
			}
		}
		if($hasFailed){
			if($found){
				$result_key='All data tables included row or column headers.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;	
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			} else {
				$result_key='No data tables were found.';
				$results['instances'][$result_key]['indices'][]=-1;
				$results['instances'][$result_key]['type'][]=RESULT_PASS;	
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
				$results['instances'][$result_key]['highlight_attribute'][]='';
			}
		}
	} else {
		$result_key='No tables were found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('11.2', $error_type);
	
	return $results;
}

function NZ_S_11_3($parse){
	//Verify that layout tables make sense when linearized.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#avoid-table-for-layout
	
	//TODO:			Put in a linerised verison in a popup window
	
	$timeout=get_timeout();
	
	create_message('11.3', 'Verify that layout tables make sense when linearized.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h11';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('table');
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			if(!is_data_table($parse, $this_element)){
				$result_key='Tables used for layout should make sense when linearized.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
		if(!$hasFailed){
			$result_key='No layout tables were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No tables were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('11.3', $error_type);
	
	return $results;
}

function NZ_S_11_4($parse){
	//Provide summaries for tables.

	//Priority:		Standard
	
	//Techniques:	http://www.w3.org/TR/AERT#table-summaries
	
	//NOTE:			I have decided that this only applies to data tables
	
	//TODO:			Check that the summary words appear in the columns or rows at some point (ie, is an accurate description)
	
	$timeout=get_timeout();
	
	create_message('11.4', 'Provide summaries for tables.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h11';
	
	$hasFailed=false;
	$found=false;
	$temp=$parse->getElementsByTagname('table');

	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$border=$parse->getAttribute($this_element, 'border');
			if(is_data_table($parse, $this_element)){
				$found=true;
				$summary=$parse->getAttribute($this_element, 'summary');
				if(trim($summary=='')){
					$result_key='This table is missing a summary.  In the summary, describe the purpose of the table (either layout or data). For example \'This table charts the number of cups of coffee consumed by each senator, the type of coffee (decaf or regular), and whether taken with sugar.\'';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
				}
				$captions=$parse->all_descendants($this_element, 'caption');
				if(count($captions)==0){
					$result_key='This table does not have a caption: A table caption describes the nature of the table in one to three sentences. For example, \'Cups of coffee consumed by each senator.\'';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
				}
			}
		}
		if(!$hasFailed && $found){
			$result_key='All tables contained summaries';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		if(!$hasFailed && !$found){
			$result_key='No data tables were found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No tables were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('11.4', $error_type);
	
	return $results;
}

function NZ_S_12_1($parse){
	//Frames are not to be used
	
	//Priority:		Standard
	
	//Techniques:	http://www.w3.org/TR/AERT#abbreviate-labels
	
	$timeout=get_timeout();
	
	create_message('12.1', 'Frames are not to be used.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h12';
	
	$hasFailed=false;
	$temp=$parse->getElementsByTagname('frameset');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='This page contains frames.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	$temp=$parse->getElementsByTagname('iframe');
	if(count($temp)>0){
		foreach($temp as $this_element){
			$result_key='This page contains iframes.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	}
	
	if(!$hasFailed){
		$result_key='No frames were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}

	$error_type=get_error_type($results['instances']);
	update_message('12.1', $error_type);
	
	return $results;
}

function NZ_S_13_1($parse){
	//Ensure that pages are usable when scripts, applets, or other programmatic objects are turned off or not supported.  If this is not possible, provide equivalent information on an alternative accessible page.
	
	//Priority:		Standard
	
	//Techniques:	http://www.w3.org/TR/AERT#scripts
	
	//TODO:			perhaps include the actual elements in the result?
	
	$timeout=get_timeout();
	
	create_message('13.1', 'Ensure that pages are usable when scripts, applets, or other programmatic objects are turned off or not supported.  If this is not possible, provide equivalent information on an alternative accessible page.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h13';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('script');
	if(count($temp)>0){
		$result_key='Please ensure that pages are usable when scripts, applets, or other programmatic objects are turned off or not supported.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_WARNING;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$results['instances'][$result_key]['info'][]='Sometimes a link to an alternative page may be required here.';
		$hasFailed=true;
	}
	if(!$hasFailed){
		$temp=$parse->getElementsByTagname('object');
		if(count($temp)>0){
			$result_key='Please ensure that pages are usable when scripts, applets, or other programmatic objects are turned off or not supported.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='Sometimes a link to an alternative page may be required here.';
			$hasFailed=true;
		}
	}
	if(!$hasFailed){
		$temp=$parse->getElementsByTagname('applet');
		if(count($temp)>0){
			$result_key='Please ensure that pages are usable when scripts, applets, or other programmatic objects are turned off or not supported.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='Sometimes a link to an alternative page may be required here.';
			$hasFailed=true;
		}
	}
	if(!$hasFailed){
		$temp=$parse->getElementsByTagname('embed');
		if(count($temp)>0){
			$result_key='Please ensure that pages are usable when scripts, applets, or other programmatic objects are turned off or not supported.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='Sometimes a link to an alternative page may be required here.';
			$hasFailed=true;
		}
	}
	if(!$hasFailed){
		$result_key='No scripts, applets or other programmatic objects were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;	
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('13.1', $error_type);
	
	return $results;
}

function NZ_S_13_2($parse){
	//For scripts and applets, ensure that in the absence of a mouse or equivalent device - have an alternative event handler and specify logical event handlers rather than device-dependent event handlers.
	
	//Priority:		Standard
	
	//Techniques:	http://www.w3.org/TR/AERT#keyboard-operable
	
	//Methods:		This is a merge between WAI 6.4 and WAI 9.3.
	
	//TODO:			This does not detect javascript generated event handlers such as document.onload for instance
	
	$timeout=get_timeout();
	
	create_message('13.2', 'For scripts and applets, ensure that in the absence of a mouse or equivalent device - have an alternative event handler and specify logical event handlers rather than device-dependent event handlers.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h13';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('script');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='For scripts and applets, ensure that event handlers are input device-independent.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	$temp=$parse->getElementsByTagname('object');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='For scripts and applets, ensure that event handlers are input device-independent.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	$temp=$parse->getElementsByTagname('embed');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='For scripts and applets, ensure that event handlers are input device-independent.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	$temp=$parse->getElementsByTagname('applet');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$result_key='For scripts and applets, ensure that event handlers are input device-independent.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	
	$onMouseDown=$parse->getElementsByAttribute('onmousedown');
	$onMouseUp=$parse->getElementsByAttribute('onmouseup');
	$onClick=$parse->getElementsByAttribute('onclick');
	$onMouseOver=$parse->getElementsByAttribute('onmouseover');
	$onMouseOut=$parse->getElementsByAttribute('onmouseout');
	$onMouseMove=$parse->getElementsByAttribute('onmousemove');
	
	if($onMouseDown){
		$result_key='For scripts, specify logical event handlers rather than device-dependent event handlers.';
		foreach($onMouseDown as $this_element){
			
			if(time()>$timeout)
				break;
				
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='onmousedown';
			$results['instances'][$result_key]['info'][]='Try using onKeyDown as a replacement.';
		}
		$hasFailed=true;
	}
	if($onMouseUp){
		$result_key='For scripts, specify logical event handlers rather than device-dependent event handlers.';
		foreach($onMouseUp as $this_element){
			
			if(time()>$timeout)
				break;
		
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='onmouseup';
			$results['instances'][$result_key]['info'][]='Try using onKeyUp as a replacement.';
		}
		$hasFailed=true;
	}
	if($onClick){
		$result_key='For scripts, specify logical event handlers rather than device-dependent event handlers.';
		foreach($onClick as $this_element){

			if(time()>$timeout)
				break;
				
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='onclick';
			$results['instances'][$result_key]['info'][]='Try using onKeyPress as a replacement.';
		}
		$hasFailed=true;
	}
	if($onMouseOver){
		$result_key='For scripts, specify logical event handlers rather than device-dependent event handlers.';
		foreach($onMouseOver as $this_element){
			
			if(time()>$timeout)
				break;
		
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='onmouseover';
			$results['instances'][$result_key]['info'][]='Try using onFocus as a replacement.';
		}
		$hasFailed=true;
	}
	if($onMouseOut){
		$result_key='For scripts, specify logical event handlers rather than device-dependent event handlers.';
		foreach($onMouseOut as $this_element){
			
			if(time()>$timeout)
				break;
		
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='onmouseout';
			$results['instances'][$result_key]['info'][]='Try using onBlur as a replacement.';
		}
		$hasFailed=true;
	}
	if($onMouseMove){
		$result_key='For scripts, specify logical event handlers rather than device-dependent event handlers.';
		foreach($onMouseMove as $this_element){
			
			if(time()>$timeout)
				break;
		
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE;
			$results['instances'][$result_key]['highlight_attribute'][]='onmousemove';
			//No suggested replacement here
		}
		$hasFailed=true;
	}
	
	if(!$hasFailed){
		$result_key='No device-dependant event handlers were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}

	$error_type=get_error_type($results['instances']);
	update_message('13.2', $error_type);
	
	return $results;
}

function NZ_S_14_1($parse){
	//Until user agents provide the ability to stop the refresh, do not create periodically auto-refreshing pages.

	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#no-periodic-refresh
	
	//NOTE:			Snoopy MUST be configured to ignore redirects for this to work.
	//				This only addresses integer refreshes.  URL redirects are handled in NZ_S_14_2
	
	$timeout=get_timeout();
	
	create_message('14.1', 'Until user agents provide the ability to stop the refresh, do not create periodically auto-refreshing pages.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h14';
	
	$hasFailed=false;
	$found=false;
	
	$temp=$parse->getElementsByTagname('meta');
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$httpequiv=$parse->getAttribute($this_element, 'http-equiv', true);
		if($httpequiv=='refresh'){
			$content=$parse->getAttribute($this_element, 'content');
			$bits=explode(';', $content);
			if(is_numeric($bits[0]) && $bits[0]>0 && $bits[0]<300){
				$result_key='This page uses auto-refresh which can make the page difficult to read for some people.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
				$results['instances'][$result_key]['highlight_attribute'][]='content';
				$hasFailed=true;
			}
			$found=true;
		}
	}
	
	if(!$hasFailed){
		
		if(!$found)
			$result_key='No auto-refreshes were found.';
		else $result_key='The auto-refreshes meet the requirements.';
		
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('14.1', $error_type);
	
	return $results;
}

function NZ_S_14_2($parse){
	//Until user agents provide the ability to stop auto-direct, do not use markup to redirect pages automatically.  Instead, configure the server to perform redirects.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#auto-page-refresh
	
	//NOTE:			Snoopy MUST be configured to ignore redirects for this to work.
	//				Do we want to allow a check initially, and then to optionally follow the redirect?  It could be handy
	//				for url redirects that the user isn't aware of.
	//				We are ignoring integers here because we are really only interesting URL redirects.  Refreshes are
	//				handled in NZ_S_14_1
	
	$timeout=get_timeout();
	
	create_message('14.2', 'Until user agents provide the ability to stop auto-direct, do not use markup to redirect pages automatically.  Instead, configure the server to perform redirects.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h14';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('meta');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$refresh=$parse->getAttribute($this_element, 'http-equiv', true);
			if($refresh=='refresh'){
				$content=$parse->getAttribute($this_element, 'content');
				$bits=explode(';', $content);
				if($content!='' && is_numeric($content[0]) && sizeof($bits)>1){
					$result_key='This page uses auto-redirect which can make the page difficult to read for some people.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_FAIL;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_VALUE;
					$results['instances'][$result_key]['highlight_attribute'][]='content';
					$hasFailed=true;
				}
			}
		}
		
		if(!$hasFailed){
			$result_key='No auto-redirect elements found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No auto-redirect elements found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('14.2', $error_type);
	
	return $results;
}

function NZ_S_15_1($parse){
	//Until user agents allow users to turn off spawned windows, do not cause pop-ups or other windows to appear and do not change the current window without informing the user.
	
	//Priority:		Should
	
	//Techniques:	http://www.w3.org/TR/AERT#no-new-windows
	
	//NOTE:		Does not check for javascript popups
	
	//TODO:		Check for window.open?
	
	$timeout=get_timeout();
	
	create_message('15.1', 'Until user agents allow users to turn off spawned windows, do not cause pop-ups or other windows to appear and do not change the current window without informing the user.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h15';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('a');
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$target=$parse->getAttribute($this_element, 'target', true);
			if($target=='_new' || $target=='_blank'){
				$result_key='This anchor element will open a new window that can disorient some users.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ATTRIBUTE_INCLUDE_CONTENTS;
				$results['instances'][$result_key]['highlight_attribute'][]='target';
				$hasFailed=true;
			}
		}
		if(!$hasFailed){
			$result_key='No anchors spawn new windows.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No anchors were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';	
	}
		
	$error_type=get_error_type($results['instances']);
	update_message('15.1', $error_type);
	
	return $results;
}

function NZ_S_15_2($parse){
	//Make programmatic elements such as scripts and applets directly accessible or compatible with assistive technologies.
	
	//Priority:		Should
	
	//Techniques:	No link?
	
	//Methods:		This is a merge between WAI 8.1 and WAI 9.2
	
	$timeout=get_timeout();
	
	create_message('15.2', 'Make programmatic elements such as scripts and applets directly accessible or compatible with assistive technologies.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h15';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('object');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$result_key='This element may not be accessible to all users. Please ensure there is an accessible interface to this object.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	
	$temp=$parse->getElementsByTagname('applet');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$result_key='This element may not be accessible to all users. Please ensure there is an accessible interface to this object.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	
	$temp=$parse->getElementsByTagname('embed');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$result_key='This element may not be accessible to all users. Please ensure there is an accessible interface to this object.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	
	$temp=$parse->getElementsByTagname('script');
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			$result_key='This element may not be accessible to all users. Please ensure there is an accessible interface to this object.';
			$results['instances'][$result_key]['indices'][]=$this_element;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
		$hasFailed=true;
	}
	
	if(!$hasFailed){
		$result_key='No programmatic elements were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('15.2', $error_type);
	
	return $results;
}

function NZ_S_15_3($parse){
	//Provide keyboard shortcuts to important links, form controls, and groups of form controls.
	
	//Priority:		Standard
	
	//Techniques:	http://www.w3.org/TR/AERT#keyboard-shortcuts
	
	//Notes:		INPUT elements of type 'hidden' are ignored here
	//				Should this check be aware of the form in which the elements are contained?
	//				Basically a form could have text fields with no accesskeys, but a single form field elsewhere
	//				with an accesskey would mean that form inputs were passed
	
	//TODO:			This does not include selects
	
	//NOTE:			The fieldset/legend test info message assumes that fieldsets are used in forms and nothing else 
	
	//TODO:			check http://www.dbh.govt.nz/sector-activity-index for an accesskey 3 not being detected
	$timeout=get_timeout();
	
	create_message('15.3', 'Provide keyboard shortcuts to important links, form controls, and groups of form controls.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h15';
	
	$hasFailed=false;
	$found=false;
	$required=false;
	
	$temp=$parse->getElementsByTagname('a');
	if(count($temp)){
		$required=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->specified($this_element, 'accesskey')){
				$found=true;
				break;
			}
		}
		if(!$found){
			$hasFailed=true;
			$result_key='There are no keyboard shortcut keys to any of the <code>a</code> elements in this document. Important links and controls should have shortcut keys.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='You could use access keys to provide quick access to important links in this page';
		}
	}
	$temp=$parse->getElementsByTagname('area');
	if(count($temp)>0){
		$found=false;
		$required=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->specified($this_element, 'accesskey')){
				$found=true;
				break;
			}
		}
		if(!$found){
			$hasFailed=true;
			$result_key='There are no keyboard shortcut keys to any of the <code>area</code> elements in this document. Important links and controls should have shortcut keys.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='You could use access keys to provide quick access to important links in this page';
		}
	}
	
	$temp=$parse->getElementsByTagname('button');
	if(count($temp)){
		$found=false;
		$required=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->specified($this_element, 'accesskey')){
				$found=true;
				break;
			}
		}
		if(!$found){
			$hasFailed=true;
			$result_key='There are no keyboard shortcut keys to any of the <code>button</code> elements in this document. Important links and controls should have shortcut keys.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='You could use access keys to provide quick access to important form elements in this page';
		}
	}
	$temp=$parse->getElementsByTagname('input');
	if(count($temp)>0){
		$found=false;
		$required=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->getAttribute($this_element, 'type')!='hidden'){
				if($parse->specified($this_element, 'accesskey')){
					$found=true;
					break;
				}
			}
		}
		if(!$found){
			$hasFailed=true;
			$result_key='There are no keyboard shortcut keys to any of the <code>input</code> elements in this document. Important links and controls should have shortcut keys.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='You could use access keys to provide quick access to important form elements in this page';
		}
	}
	$temp=$parse->getElementsByTagname('label');
	if(count($temp)>0){
		$found=false;
		$required=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->specified($this_element, 'accesskey')){
				$found=true;
				break;
			}
		}
		if(!$found){
			$hasFailed=true;
			$result_key='There are no keyboard shortcut keys to any of the <code>label</code> elements in this document. Important links and controls should have shortcut keys.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='You could use access keys to provide quick access to important form elements in this page';
		}
	}
	$temp=$parse->getElementsByTagname('legend');
	if(count($temp)>0){
		$found=false;
		$required=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->specified($this_element, 'accesskey')){
				$found=true;
				break;
			}
		}
		if(!$found){
			$hasFailed=true;
			$result_key='There are no keyboard shortcut keys to any of the <code>legend</code> elements in this document. Important links and controls should have shortcut keys.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='You could use access keys to provide quick access to important form elements in this page';
		}
	}
	$temp=$parse->getElementsByTagname('textarea');
	if(count($temp)>0){
		$found=false;
		$required=true;
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
				
			if($parse->specified($this_element, 'accesskey')){
				$found=true;
				break;
			}
		}
		if(!$found && $required){
			$hasFailed=true;
			$result_key='There are no keyboard shortcut keys to any of the <code>textarea</code> elements in this document. Important links and controls should have shortcut keys.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_WARNING;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='You could use access keys to provide quick access to important form elements in this page';
		}
	}
	if(!$hasFailed && $required){
		$result_key='Access keys were found on all of the required element types.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;	
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	if(!$required){
		$result_key='No elements required keyboard shortcuts.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;	
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('15.3', $error_type);
	
	return $results;
}

function NZ_S_15_4($parse){
	//Group related links, identify the group (for user agents), and, until user agents do so, provide a way to bypass the group.
	
	//Priority:		Standard
	
	//Techniques:	Raise as a user check
	
	//TODO:			If the skip link accesskey is present, mark as passed
	
	$timeout=get_timeout();
	
	create_message('15.4', 'Group related links, identify the group (for user agents), and, until user agents do so, provide a way to bypass the group.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h15';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('15.4', $error_type);
	
	return $results;
}

function NZ_S_16_1($parse){
	//Any web site owned by the agency which is not the 'Main' web site of the agency (defined as an 'Other' web site of the agency) has a link, as a minimum from the homepage, to the homepage of the 'Main' agency web site.
	
	//Priority:		Standard
	
	//Techniques:	Raise as a user check
	
	$timeout=get_timeout();
	
	create_message('16.1', 'Any web site owned by the agency which is not the \'Main\' web site of the agency (defined as an \'Other\' web site of the agency) has a link, as a minimum from the homepage, to the homepage of the \'Main\' agency web site.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h16';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('16.1', $error_type);
	
	return $results;
}

function NZ_S_16_2($parse){
	//All homepages contain the following as a minimum: 1)	Contact Us. This can be a content header or a link to a page titled "Contact Us". The associated content includes full contact details, including those for feedback and complaints. 2)	Link to www.govt.nz. 3)	About this Site. This can be a content header or a link to a page titled "About this Site". The content within "About this Site" is specified in 16.3 on page 56 4)	At least the name and/or the logo of the agency.
	
	//Priority:		Standard
	
	//Techniques:	None found

	//TODO:			This does not make provision for the logo.
	//				Check that www.govt.nz and govt.nz are both detected correctly
	//TODO:			Perhaps we should check that if the words are not in a link, then they are in an <hx> tag?
	//TODO:			change the .govt.nz test to newzealand.govt.nz
	
	create_message('16.2', 'All homepages contain the following as a minimum: 1)	Contact Us. This can be a content header or a link to a page titled "Contact Us". The associated content includes full contact details, including those for feedback and complaints. 2)	Link to www.govt.nz. 3)	About this Site. This can be a content header or a link to a page titled "About this Site". The content within "About this Site" is specified in 16.3 on page 56 4)	At least the name and/or the logo of the agency.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h16';
	
	$hasFailed=false;
	
	$text=strtolower($parse->bodyInnerText());
	$pos=strpos($text, 'contact us');
	if($pos===false){
		$result_key="No 'Contact Us' link or content header was found.";
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_FAIL;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$results['instances'][$result_key]['info'][]='A link or header with the words \'contact us\' is required on this page.';
		$hasFailed=true;
	}
	
	$timeout=get_timeout();
	
	$temp=$parse->getElementsByTagname('a');
	$found_domain=false;
	foreach($temp as $this_element){
		
		if(time()>$timeout)
			break;
			
		$href=$parse->href($this_element);
		$domain=get_domain($href);
		
		if($domain=='govt.nz' || $domain=='newzealand.govt.nz'){
			$found_domain=true;
			break;	
		}
	}
	
	if(!$found_domain){
		$result_key='No link to govt.nz was found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_FAIL;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$results['instances'][$result_key]['info'][]='A link to govt.nz is required on this page.';
		$hasFailed=true;
	}
	
	$pos=strpos($text, 'about this site');
	if($pos===false){
		$result_key="No 'About this site' link or content header was found.";
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_FAIL;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$results['instances'][$result_key]['info'][]='A link or header containing the words \'About this site\' is required on this page.';
		$hasFailed=true;
	}
	
	$department_name=strtolower($parse->departmentName());
	if($department_name!=''){
		
		$pos=strpos($text, $department_name);
		if($pos===false){
			$result_key='The department name was not found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='The department name needs to be present in plain text.';
			$hasFailed=true;
		}
		$dept_set=true;
	} else {
		$dept_set=false;	
	}
	
	if(!$hasFailed){
		if($dept_set){
			$result_key='All the required content is present.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		} else {
			$result_key='All of the required content is present, except possibly the department name, which was not provided.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('16.2', $error_type);
	
	return $results;
}

function NZ_S_16_3($parse){
	/*
	The content of the section or page titled "About this Site" contains (as a minimum):
1)	"Site Owner". The associated content contains (as a minimum): 
a)	a link back to the main agency web site 
b)	site owner name (can contain a logo, but a logo alone is insufficient)
2)	Accessibility". This can be a content header or a link to a page titled "Accessibility". The associated content contains (as a minimum):
a)	Access Keys, refer standard 8.4, page 40. 
b)	Other information detailing navigational aids within the site is preferred.
3)	"Copyright". This can be a content header or a link to a page titled "Copyright".
If the agency is providing a general crown copyright statement, it is expected to reside here, refer standard 16.5, page 58 for further detail.
4)		"Privacy". This can be a content header or a link to a page titled "Privacy".
The associated content contains (as a minimum):
a)	A privacy statement, refer standard 16.7, page 59.
	*/
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		I think that this will be a user check...
	
	//TODO:			Some aspects of this rule could actually be checked, but the user will have to identify this page as being an 'about' page
	
	create_message('16.3', 'The content of the section or page titled "About this Site" contains (as a minimum):
1)	"Site Owner". The associated content contains (as a minimum): 
a)	a link back to the main agency web site 
b)	site owner name (can contain a logo, but a logo alone is insufficient)
2)	Accessibility". This can be a content header or a link to a page titled "Accessibility". The associated content contains (as a minimum):
a)	Access Keys, refer standard 8.4, page 40. 
b)	Other information detailing navigational aids within the site is preferred.
3)	"Copyright". This can be a content header or a link to a page titled "Copyright".
If the agency is providing a general crown copyright statement, it is expected to reside here, refer standard 16.5, page 58 for further detail.
4)		"Privacy". This can be a content header or a link to a page titled "Privacy".
The associated content contains (as a minimum):
a)	A privacy statement, refer standard 16.7, page 59.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h16';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('16.3', $error_type);
	
	return $results;
}

function NZ_S_16_4($parse){
	/*A homepage in the ‘Main’ agency web site must have "About Us" or "About <Agency Name>". 
	This can be a content header or a link to a page titled "About Us" or "About <Agency Name>".
	Mandatory content within the “About Us" section or the "About <Agency Name>" page contains (as a minimum):
	1)	agency purpose
	2)	a list of Minister(s) (or Mayor) relevant to the agency
	3)	agency accountability documents
	4)	A list of responsibilities for each of the relevant Ministers. The primary objective is defining what the ministers do for the agency.
	5)	Provide a list of links to the biographies (on http://www.beehive.govt.nz or equivalent) for each of the relevant Ministers.
	6)	a list of legislation or by-laws for which the agency has lead responsibility
	*/
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		I think that this will be a user check...
	
	create_message('16.4', 'A homepage in the ‘Main’ agency web site must have "About Us" or "About <Agency Name>". 
	This can be a content header or a link to a page titled "About Us" or "About <Agency Name>".
	Mandatory content within the “About Us" section or the "About <Agency Name>" page contains (as a minimum):
	1)	agency purpose
	2)	a list of Minister(s) (or Mayor) relevant to the agency
	3)	agency accountability documents
	4)	A list of responsibilities for each of the relevant Ministers. The primary objective is defining what the ministers do for the agency.
	5)	Provide a list of links to the biographies (on http://www.beehive.govt.nz or equivalent) for each of the relevant Ministers.
	6)	a list of legislation or by-laws for which the agency has lead responsibility');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h16';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('16.4', $error_type);
	
	return $results;
	
}

function NZ_S_16_5($parse){
	/*Every web site under ownership of the agency must contain a Crown copyright statement which states (as a minimum) that:-
	•	the material on the web site is protected by crown copyright, and
	•	anyone can utilise any of the material available on the web site free of charge and without permission of the agency provided 
	-	The material is not altered
	- The source and copyright status of the material is acknowledged*/

	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		I think that this will be a user check...
	
	create_message('16.5', 'Every web site under ownership of the agency must contain a Crown copyright statement which states (as a minimum) that:-
	•	the material on the web site is protected by crown copyright, and
	•	anyone can utilise any of the material available on the web site free of charge and without permission of the agency provided 
	-	The material is not altered
	- The source and copyright status of the material is acknowledged');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h16';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('16.5', $error_type);
	
	return $results;
}

function NZ_S_16_6($parse){
	/*Any web site under ownership of the agency that contains third party material, which in part or whole is copyright material, must have the permission from the copyright owner to use.
	Source and copyright status of the material on the web site, such that there is no ambiguity as to which item(s) of material on the web site the copyright pertains.
	A statement must also be made (on the agency web site) that permission to utilise such material cannot be given by the agency.*/
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		I think that this will be a user check...
	
	create_message('16.6', 'Any web site under ownership of the agency that contains third party material, which in part or whole is copyright material, must have the permission from the copyright owner to use.
	Source and copyright status of the material on the web site, such that there is no ambiguity as to which item(s) of material on the web site the copyright pertains.
	A statement must also be made (on the agency web site) that permission to utilise such material cannot be given by the agency.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h16';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('16.6', $error_type);
	
	return $results;
}

function NZ_S_16_7($parse){
	//Every page within a web site (including a home page) under ownership of the agency must link to a privacy notice. The text of the link includes the word ‘privacy’.
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		Get all the internal links and check their text for the word privacy
	
	$timeout=get_timeout();
	
	create_message('16.7', 'Every page within a web site (including a home page) under ownership of the agency must link to a privacy notice. The text of the link includes the word ‘privacy’.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h16';
	
	$hasFailed=true;
	
	$temp=$parse->getElementsByTagname('a');
	$site_domain=$parse->getDomain();
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			$href=$parse->href($this_element);
			if(get_domain($href)==$site_domain){
				//ok, so it's a local link, lets look at the text
					$text=strtolower($parse->innerText($this_element));
					
					if(strpos($text, 'privacy')!==false){
						$hasFailed=false;
						break;
					}
				}
		}
		
		if(!$hasFailed){
			$result_key='The privacy link was found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		} else {
			$result_key='The privacy link was not found.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_FAIL;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$results['instances'][$result_key]['info'][]='A link with the word \'Privacy\' is required on this page.';
		}
		
		
	} else {
		$result_key='No links were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_FAIL;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
		$results['instances'][$result_key]['info'][]='A link with the word \'Privacy\' is required on this page.';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('16.7', $error_type);
	
	return $results;
}

function NZ_S_17_1($parse){
	//The archive preserves the context in which the documents were made available.
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		I think that this will be a user check...
	
	create_message('17.1', 'The archive preserves the context in which the documents were made available.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h17';
	
	$result_key=NOT_CHECKED;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_NOT_CHECKED;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('17.1', $error_type);
	
	return $results;
}

function NZ_S_18_1($parse){
	/*Any web site that is under ownership of the agency that is
	•	a new web site, or 
	•	an existing web site, where the overall “look and feel” or functionality has been modified 
	must work satisfactorily in a minimum list of web browser types and respective versions prior to being released as a production web site.*/
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		I think that this will be a user check...
	
	create_message('18.1', 'Any web site that is under ownership of the agency that is
	•	a new web site, or 
	•	an existing web site, where the overall “look and feel” or functionality has been modified 
	must work satisfactorily in a minimum list of web browser types and respective versions prior to being released as a production web site.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h18';
	
	$result_key=NOT_CHECKED;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_NOT_CHECKED;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('18.1', $error_type);
	
	return $results;
}

function NZ_S_19_1($parse){
	/*A web site must provide the choice for a user to disable the collection of tracking data at any time during their visit. 
	Note this excludes:
	•	When the tracking data is used solely for maintaining session state of the web site
	•	Web site activity recorded in web server log(s), where the web site owner uses this data for anonymous statistical purposes.*/
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		I think that this will be a user check...
	
	create_message('19.1', 'A web site must provide the choice for a user to disable the collection of tracking data at any time during their visit. 
	Note this excludes:
	•	When the tracking data is used solely for maintaining session state of the web site
	•	Web site activity recorded in web server log(s), where the web site owner uses this data for anonymous statistical purposes.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h19';
	
	$result_key=NOT_CHECKED;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_NOT_CHECKED;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('19.1', $error_type);
	
	return $results;
}

function NZ_S_19_2($parse){
	/*If tracking data is being recorded (i.e., such as that held in a temporary client-side cookie) then
	The agency must place on the site a disclaimer stating (as a minimum):
	1.	That tracking data is being recorded,
	2.	What processes are being utilised to collect the data
	3.	How the data will be stored
	4.	The benefits to the user community of the web site resulting from the collection of such data.
	5.	How a user can prevent this data from being collected
	6.	The impact (if any) on the experience the user may have with the web site, if the user chooses to disable the tracking data.*/
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		I think that this will be a user check...
	
	create_message('19.2', 'If tracking data is being recorded (i.e., such as that held in a temporary client-side cookie) then
	The agency must place on the site a disclaimer stating (as a minimum):
	1.	That tracking data is being recorded,
	2.	What processes are being utilised to collect the data
	3.	How the data will be stored
	4.	The benefits to the user community of the web site resulting from the collection of such data.
	5.	How a user can prevent this data from being collected
	6.	The impact (if any) on the experience the user may have with the web site, if the user chooses to disable the tracking data.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h19';
	
	$result_key=NOT_CHECKED;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_NOT_CHECKED;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('19.2', $error_type);
	
	return $results;
}

function NZ_S_19_3($parse){
	//No directly readable personal information is to be persisted on the device on which the user is hosting their browser (e.g. client machine such as a user’s personal computer).
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		I think that this will be a user check...
	
	create_message('19.3', 'No directly readable personal information is to be persisted on the device on which the user is hosting their browser (e.g. client machine such as a user’s personal computer).');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h19';
	
	$result_key=NOT_CHECKED;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_NOT_CHECKED;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('19.3', $error_type);
	
	return $results;
}

function NZ_S_19_4($parse){
	//If encryption of personal information is the sole method used to prevent the information revealing identity for personal information persisted within tracking data, as required in standard 19.3 on page 65, the cryptographic specification of the encryption must meet an acceptable level of security. This can be met by utilising an approved cryptographic algorithm.
	//Refer to NZ Government Information Technology Security Manual NZSIT 400, http://www.gcsb.govt.nz/publications/nzsit/nzsit-400.pdf; chapter 9, for details of approved cryptographic algorithms.
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		I think that this will be a user check...
	
	create_message('19.4', 'If encryption of personal information is the sole method used to prevent the information revealing identity for personal information persisted within tracking data, as required in standard 19.3 on page 65, the cryptographic specification of the encryption must meet an acceptable level of security. This can be met by utilising an approved cryptographic algorithm.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h19';
	
	$result_key=NOT_CHECKED;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_NOT_CHECKED;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('19.4', $error_type);
	
	return $results;
}

function NZ_S_20_1($parse){
	//All instances of requests for users to authenticate themselves in a web site utilising either the Government Logon Service (GLS) and/or the Identity Verification Service (IVS) must comply with the standards for these services, as set by the All-of-government Authentication Programme unit of the SSC.
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		I think that this will be a user check...
	
	create_message('20.1', 'All instances of requests for users to authenticate themselves in a web site utilising either the Government Logon Service (GLS) and/or the Identity Verification Service (IVS) must comply with the standards for these services, as set by the All-of-government Authentication Programme unit of the SSC.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h20';
	
	$result_key=NOT_CHECKED;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_NOT_CHECKED;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('20.1', $error_type);
	
	return $results;
}

function NZ_S_21_1($parse){
	/*For exchange of personal information between web site user and the environment hosting the agency web site(s), the hosting environment must as a minimum:
	•	Encrypt personal information using Secure Sockets Layer (SSLv3) or Transport Layer Security (TLS), 
	•	Use certificates that have a trust chain that is available in commonly used browsers.*/
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		I think that this will be a user check...
	
	create_message('21.1', 'For exchange of personal information between web site user and the environment hosting the agency web site(s), the hosting environment must as a minimum:
	•	Encrypt personal information using Secure Sockets Layer (SSLv3) or Transport Layer Security (TLS), 
	•	Use certificates that have a trust chain that is available in commonly used browsers.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h21';
	
	$result_key=NOT_CHECKED;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_NOT_CHECKED;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('21.1', $error_type);
	return $results;
}

function NZ_S_21_2($parse){
	//Any capture of credit card details online must comply with the Payment Card Industry (PCI) Security Standards Council’s Data Security Standards (DSS). 
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		I think that this will be a user check...
	
	create_message('21.2', 'Any capture of credit card details online must comply with the Payment Card Industry (PCI) Security Standards Council’s Data Security Standards (DSS).');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h21';
	
	$result_key=NOT_CHECKED;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_NOT_CHECKED;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('21.2', $error_type);
	
	return $results;
}

function NZ_S_22_1($parse){
	//The FIELDSET element is used to group related form elements. The LEGEND attribute of the FIELDSET element is used to caption a set of related form elements and the LABEL element is used to associate controls with their associated label text.
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		We are going to get each form and check to see if there are more than three visible form fields,
	//				Not including buttons, submits, cancels etc...
	//				If there are, then there might be a need for a fieldset
	
	//Note:			Although we're checking the 'hidden' input type, we're not checking the css values...
	//				Also, the legend check just checks for the presence of a legend, when it should actually be
	//				the very next element after the fieldset
	//				We are not checking the labels in this rule, since it's not properly explained...
	
	//TODO:			This assumes that the fieldset is contained WITHIN the form
	
	$timeout=get_timeout();
	
	create_message('22.1', 'The FIELDSET element is used to group related form elements. The LEGEND attribute of the FIELDSET element is used to caption a set of related form elements and the LABEL element is used to associate controls with their associated label text.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h22';
	
	$hasFailed=false;
	$found=false;
	
	$temp=$parse->getElementsByTagname('form');
	if(count($temp)>0){
		foreach($temp as $this_element){

			if(time()>$timeout)
				break;
			
			$field_count=0;
				
			$all_inputs=$parse->all_descendants($this_element, 'input');
			foreach($all_inputs as $this_input){
				
				if(time()>$timeout)
					break;
			
				$type=$parse->getAttribute($this_input, 'type', true);
				if($type!='submit' && $type!='cancel' && $type!='hidden')
					$field_count++;
				
			}
			
			$all_inputs=$parse->all_descendants($this_element, 'textarea');
			$field_count+=count($all_inputs);
			
			$all_inputs=$parse->all_descendants($this_element, 'select');
			$field_count+=count($all_inputs);
		
			$all_inputs=$parse->all_descendants($this_element, 'button');
			$field_count+=count($all_inputs);
			
			if($field_count>3){
				$found=true;
				//are there any fieldsets in this form?
				$fieldsets=$parse->all_descendants($this_element, 'fieldset');
				if(count($fieldsets)==0){
					$result_key='This form does not use fieldsets.';
					$results['instances'][$result_key]['indices'][]=$this_element;
					$results['instances'][$result_key]['type'][]=RESULT_WARNING;
					$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
					$results['instances'][$result_key]['highlight_attribute'][]='';
					$hasFailed=true;
				}	
			}	
		}

		if(!$hasFailed){
			if(!$found)
				$result_key='No forms seem to require fieldsets.';			
			else $result_key='All forms used fieldsets if required.';
			
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}	
	} else {
		$result_key='No forms were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	//Now check that all fieldsets have legend elements
	$hasFailed=false;
	$found=false;
	
	$temp=$parse->getElementsByTagname('fieldset');
	if(count($temp)>0){
		foreach($temp as $this_element){
			$legends=$parse->all_descendants($this_element, 'legend');
			if(count($legends)==0){
				$result_key='This fieldset does not have a LEGEND element';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_FAIL;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}		
		}
		
		if(!$hasFailed){
			$result_key='All fieldsets have LEGEND elements';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
	} else {
		$result_key='No fieldsets were found.';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('22.1', $error_type);
	
	return $results;
				
}

function NZ_S_22_2($parse){
	//Every descriptive label is tagged as LABEL and associated with the name of the field.
	
	//Priority:		Standard
	
	//Techniques:	Get every <input> element.  If it is not hidden or a cancel or submit button, then check for a label.
	//				This is done by getting the ID attribute (if any), and checking for a <label> with the 'for' attribute with this ID or if this returns nothing,
	//				move up the parent list until we find an enclosing <label> element.
	//				This label must be either the immediatley preceeding element, or the next one after the label.
	
	//NOTE:			Form fields that aren't contained within proper block parent tags may detect text for other form fields

	//NOTE:			This does not actually require a form input field to be contained within a <form> element
	
	//TODO:			This is an EXACT copy of another rule (NZ_S_7_1), so they both need to be looked at to see how they should work
	
	$timeout=get_timeout();
	
	create_message('22.2', 'Every descriptive label is tagged as LABEL and associated with the name of the field.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h22';
	
	$hasFailed=false;
	
	$blocks=load_block_elements(false);
	//Div tags frequently prevent this rule from identifying associated text, so we are going to ignore them here
	unset($blocks['div']);
	
	$temp=$parse->getElementsByTagname('input');

	if(count($temp)>0){
		$allLabels=$parse->getElementsByTagname('label');
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;
			
			$found=false;
			$type=$parse->getAttribute($this_element, 'type', true);
			
			//we are not checking hidden elements, as well as submit and cancel buttons
			if($type!='hidden' && $type!='submit' && $type!='reset' && $type!='button' && $type!='image'){
				//Does this element have an id?
				$id=$parse->getAttribute($this_element, 'id', true);
				//if so, is there a label with this id as a 'for' attribute value?
				if($id!=''){
					foreach($allLabels as $this_label){
						
						if(time()>$timeout)
							break;
			
						$for=$parse->getAttribute($this_label, 'for', true);
						if($for==$id){
							$found=true;
							break;
						}
					}
				}
				if(!$found){
					//Is this element's parent element a label?
					$parent=$parse->parentElement($this_element);
					$tagname=$parse->tagname($parent);
					if($tagname!='label'){
						//move up the list until a block element is found
						if(!isset($blocks[$tagname])){
							while(!isset($blocks[$tagname])){
								
								if(time()>$timeout)
									break;
								
								$parent=$parse->parentElement($parent);
								$tagname=$parse->tagname($parent);
								
								if($tagname=='label'){
									$found=true;
									break;
								}
								
								if($parent==0)
									break;
								
							}
						} 
						
					} else $found=true;
										
					if(!$found){
						$innerText_orig=$parse->innerText($parent, Array('legend'));
						$innerText=trim(strip_spaces($innerText_orig));
						if($innerText!=''){
							$result_key='This input field appears to have text associated with it which is not in a label associated with this input field.';
							$results['instances'][$result_key]['indices'][]=$this_element;
							$results['instances'][$result_key]['type'][]=RESULT_WARNING;
							$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
							$results['instances'][$result_key]['highlight_attribute'][]='';
							$results['instances'][$result_key]['info'][]="The text is &quot;<span class=\"quote\">" . $innerText_orig . "</span>&quot;";
							$hasFailed=true;
						}
					}
				}
			}
		
		}
		if(!$hasFailed){
			$result_key='No input fields had unassociated text';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
		}
	} else {
		$result_key='No form elements were found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}
	
	$error_type=get_error_type($results['instances']);
	update_message('22.2', $error_type);
	
	return $results;
}

function NZ_S_22_3($parse){
	//Users receive online confirmation that the information they have submitted has been received, for example by displaying a web page.

	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		Here we will get every <form> element and check the action (destination).  Anything that submits
	//				back to itself will be raised as a warning
	
	$timeout=get_timeout();
	
	create_message('22.3', 'Users receive online confirmation that the information they have submitted has been received, for example by displaying a web page.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h22';
	
	$hasFailed=false;
	
	$temp=$parse->getElementsByTagname('form');
	
	if(count($temp)>0){
		foreach($temp as $this_element){
			
			if(time()>$timeout)
				break;

			$action=$parse->getAttribute($this_element, 'action');
			
			if($action=='' || strtolower($parse->href($action, true))==strtolower($parse->currentPage)){
				$result_key='This form may not notify the user clearly.';
				$results['instances'][$result_key]['indices'][]=$this_element;
				$results['instances'][$result_key]['type'][]=RESULT_WARNING;
				$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_ELEMENT;
				$results['instances'][$result_key]['highlight_attribute'][]='';
				$hasFailed=true;
			}
		}
		
		if(!$hasFailed){
			$result_key='All forms appear to notify the user.';
			$results['instances'][$result_key]['indices'][]=-1;
			$results['instances'][$result_key]['type'][]=RESULT_PASS;
			$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
			$results['instances'][$result_key]['highlight_attribute'][]='';
			$hasFailed=true;
		}
		
	} else {
		$result_key='No form elements were found';
		$results['instances'][$result_key]['indices'][]=-1;
		$results['instances'][$result_key]['type'][]=RESULT_PASS;
		$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
		$results['instances'][$result_key]['highlight_attribute'][]='';
	}

	$error_type=get_error_type($results['instances']);
	update_message('22.3', $error_type);
	
	return $results;
}

function NZ_S_23_1($parse){
	//Advertising of web site tenders and opportunities over NZ$100,000 per year are notified to Government Electronic Tendering Service.
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		This will be a user check
	
	$timeout=get_timeout();
	
	create_message('23.1', 'Advertising of web site tenders and opportunities over NZ$100,000 per year are notified to Government Electronic Tendering Service.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h23';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('23.1', $error_type);
	
	return $results;
}

function NZ_S_23_2($parse){
	//Specifying compliance with web standards and recommendations
	
	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		This will be a user check
	
	$timeout=get_timeout();
	
	create_message('23.2', 'Specifying compliance with web standards and recommendations.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h23';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('23.2', $error_type);
	
	return $results;
}

function NZ_S_23_3($parse){
	//When contracting with a service provider, the contract must specify that the provider must not independently collect or reuse data gained in the course of providing the service.
	//This does not relieve the contractor of their obligations under the Privacy Act 1993.

	//Priority:		Standard
	
	//Techniques:	None found
	
	//Methods:		This will be a user check
	
	$timeout=get_timeout();
	
	create_message('23.3', 'When contracting with a service provider, the contract must specify that the provider must not independently collect or reuse data gained in the course of providing the service.');
	$results=Array();
	$results['priority']=PRIORITY_STANDARD;
	$results['header']='h23';
	
	$result_key=USER_CHECK;
	$results['instances'][$result_key]['indices'][]=-1;
	$results['instances'][$result_key]['type'][]=RESULT_USER;
	$results['instances'][$result_key]['highlight'][]=HIGHLIGHT_NONE;
	$results['instances'][$result_key]['highlight_attribute'][]='';
	
	$error_type=get_error_type($results['instances']);
	update_message('23.3', $error_type);
	
	return $results;
}

function get_timeout(){
	return time() + LOOP_LENGTH;
}

?>
Return current item: OpenWolf Guidelines Validator