#!/bin/sh
##
## Script to check WCAG 1.0 Checklist on openacs (functions)
## ---------------------------------------------------------
## Copyright (C) 2008 Hector Romojaro
##
##-------------------------------------------------------------------------------##
#
# 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 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.
#
##-------------------------------------------------------------------------------##

### Useful functions ######################################################################
function checkOk() { if [ "$PASSED" == "true" ]; then echo -e "[\033[32mOk!\033[m]"; fi; }
function setOk() { PASSED="true"; }
function setFail() { PASSED="false"; }
function printDescription() {  if [ "$VERBOSE" == "false" ]; then echo -ne "\033[34m-- $1...\033[m"; else echo -ne "\033[34m-- $1\033[m" ; fi }
function printDescriptionVerbose() { if [ "$VERBOSE" == "true" ]; then echo -en "\n$1... " | sed 's/^/\t/g'; fi; }
function printDescriptionAll() {
	printDescription "$1"
	printDescriptionVerbose "$2"
}
function checkTest() {
	if [ x"$TEST" != "x" ]; then
                setFail
                echo -e "\n\n########################## Warning! #################################################\n$TEST \n########################## End Warning ##############################################\n" | sed 's/^/\t/g'
        fi
}
function notImplemented() { echo -e "[Not implemented]"; }

### Tests #################################################################################
## Priority 1
# [1.1] Provide a text equivalent for every non-text element.
function test1dot1() {
        setOk
	printDescriptionAll "$DESC_1_1" "$DESC_1_1_VERBOSE"

	# img, applet, area, input type image without alt
	TEST=$(
		$GREP  '<img src\|<applet\|<area' $DIR/* | grep -vi 'alt=' | grep -vf $EXCEPTIONS_1_1 | grep -vf $EXCEPTIONS_GLOBAL ;	
		$GREP  '<input' $DIR/* | grep 'type=image\|type="image"' | grep -vi 'alt=' | grep -vf $EXCEPTIONS_1_1 | grep -vf $EXCEPTIONS_GLOBAL 
	)

	checkTest
	checkOk
}

# [2.1] Ensure that all information conveyed with color is also available without color.
function test2dot1() { printDescriptionAll "$DESC_2_1" "$DESC_2_1_VERBOSE"; notImplemented; }

# [4.1] Clearly identify changes in the natural language of a document text and any text equivalents (e.g., captions).
function test4dot1() { printDescriptionAll "$DESC_4_1" "$DESC_4_1_VERBOSE"; notImplemented; }

# [6.1] Organize documents so they may be read without style sheets.
function test6dot1() { printDescriptionAll "$DESC_6_1" "$DESC_6_1_VERBOSE"; notImplemented; }

# [6.2] Ensure that equivalents for dynamic content are updated when the dynamic content changes.
function test6dot2() { printDescriptionAll "$DESC_6_2" "$DESC_6_2_VERBOSE"; notImplemented; }

# [7.1] Until user agents allow users to control flickering, avoid causing the screen to flicker.
function test7dot1() { printDescriptionAll "$DESC_7_1" "$DESC_7_1_VERBOSE"; notImplemented; }

# [14.1] Use the clearest and simplest language appropriate for a site content.
function test14dot1() { printDescriptionAll "$DESC_14_1" "$DESC_14_1_VERBOSE"; notImplemented; }

# [1.2] Provide redundant text links for each active region of a server-side image map.
function test1dot2() { printDescriptionAll "$DESC_1_2" "$DESC_1_2_VERBOSE"; notImplemented; }

# [9.1] Provide client-side image maps instead of server-side image maps except where the regions cannot be defined with an available geometric shape.
function test9dot1() { printDescriptionAll "$DESC_9_1" "$DESC_9_1_VERBOSE"; notImplemented; }

# [5.1] For data tables, identify row and column headers.
function test5dot1() { 
	setOk
	printDescriptionAll "$DESC_5_1" "$DESC_5_1_VERBOSE";

	# TH without id
	TEST=$($GREP  '<th[[:space:]].*\|<th>' $DIR/* | grep -vi 'id=' | grep -vf $EXCEPTIONS_5_1 | grep -vf $EXCEPTIONS_GLOBAL)

        checkTest
        checkOk
}

# [5.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.
function test5dot2() {
	setOk
 	printDescriptionAll "$DESC_5_2" "$DESC_5_2_VERBOSE"
	
	# TD without headers
	TEST=$($GREP  '<td' $DIR/* | grep -iv 'headers=' | grep -vf $EXCEPTIONS_5_2 | grep -vf $EXCEPTIONS_GLOBAL)

	checkTest
        checkOk
}

# [12.1] Title each frame to facilitate frame identification and navigation. 
function test12dot1() { 
	setOk	
	printDescriptionAll "$DESC_12_1" "$DESC_12_1_VERBOSE"; 

	# FRAME and FRAMESET without title
        TEST=$($GREP  '<frame' $DIR/* | grep -iv 'title=' | grep -vf $EXCEPTIONS_5_2 | grep -vf $EXCEPTIONS_GLOBAL)

        checkTest
        checkOk
}

# [6.3] Ensure that pages are usable when scripts, applets, or other programmatic objects are turned off or not supported.
function test6dot3() { printDescriptionAll "$DESC_6_3" "$DESC_6_3_VERBOSE"; notImplemented; }

# [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.
function test1dot3() { printDescriptionAll "$DESC_1_3" "$DESC_1_3_VERBOSE"; notImplemented; }

# [1.4] For any time-based multimedia presentation, synchronize equivalent alternatives with the presentation.
function test1dot4() { printDescriptionAll "$DESC_1_4" "$DESC_1_4_VERBOSE"; notImplemented; }

# [11.4] If, after best efforts, you cannot create an accessible page, provide a link to an alternative page that uses W3C technologies, is accessible, has equivalent information (or functionality), and is updated as often as the inaccessible (original) page.
function test11dot4() { printDescriptionAll "$DESC_11_4" "$DESC_11_4_VERBOSE"; notImplemented; }

## Priority 2
# [2.2] 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 2 for images, Priority 3 for text].
function test2dot2() { 
	setOk
	printDescriptionAll "$DESC_2_2" "$DESC_2_2_VERBOSE";

	# Colors should be defined by numbers, not names. 
        TEST=$($GREP  'aqua\|black\|blue\|fuchsia\|gray\|green\|lime\|maroon\|navy\|olive\|orange\|purple\|red;\|silver\|teal\|white;\|yellow' $DIR/* |  grep -vf $EXCEPTIONS_2_2 | grep -vf $EXCEPTIONS_GLOBAL)

        checkTest
        checkOk
}

# [3.1] When an appropriate markup language exists, use markup rather than images to convey information. 
function test3dot1() { printDescriptionAll "$DESC_3_1" "$DESC_3_1_VERBOSE"; notImplemented; }

# [3.2] Create documents that validate to published formal grammars. 
function test3dot2() { printDescriptionAll "$DESC_3_2" "$DESC_3_2_VERBOSE"; notImplemented; }

# [3.3] Use style sheets to control layout and presentation. 
function test3dot3() { 
	setOk
	printDescriptionAll "$DESC_3_3" "$DESC_3_3_VERBOSE"; 

	# <i> and <b> should be changed for <em> and <strong>
        TEST=$($GREP  '<i>\|</i>\|<b>\|</b>' $DIR/* | grep -vf $EXCEPTIONS_3_3 | grep -vf $EXCEPTIONS_GLOBAL)

        checkTest
        checkOk
}

# [3.4] Use relative rather than absolute units in markup language attribute values and style sheet property values. 
function test3dot4() { 
	setOk
	printDescriptionAll "$DESC_3_4" "$DESC_3_4_VERBOSE"; 

	# Avoid absolute units: in, cm, mm, pt, pc 
        TEST=$($GREP  "[[:digit:]]\(mm\|cm\|pt\|pc\)" $DIR/* | grep "[[:space:]]*[[:alnum:]]*.css" |  grep -vf $EXCEPTIONS_3_4 | grep -vf $EXCEPTIONS_GLOBAL)

        checkTest
        checkOk
}

# [3.5] Use header elements to convey document structure and use them according to specification. 
function test3dot5() { printDescriptionAll "$DESC_3_5" "$DESC_3_5_VERBOSE"; notImplemented; }

# [3.6] Mark up lists and list items properly. 
function test3dot6() { printDescriptionAll "$DESC_3_6" "$DESC_3_6_VERBOSE"; notImplemented; }

# [3.7] Mark up quotations. Do not use quotation markup for formatting effects such as indentation. 
function test3dot7() { 
	setOk
	printDescriptionAll "$DESC_3_7" "$DESC_3_7_VERBOSE";  

	# <q> and <blockquote> should be used only for quotations, not for indentation
        TEST=$($GREP  '<q\|</q>\|<blockquote\|</blockquote>' $DIR/* | grep -v "[[:space:]]*[[:alnum:]]*.xql" | grep -vf $EXCEPTIONS_3_7 | grep -vf $EXCEPTIONS_GLOBAL)

        checkTest
        checkOk
}

# [6.5] Ensure that dynamic content is accessible or provide an alternative presentation or page. 
function test6dot5() { printDescriptionAll "$DESC_6_5" "$DESC_6_5_VERBOSE"; notImplemented; }

# [7.2] Until user agents allow users to control blinking, avoid causing content to blink (i.e., change presentation at a regular rate, such as turning on and off).
function test7dot2() { 
	setOk
	printDescriptionAll "$DESC_7_2" "$DESC_7_2_VERBOSE";

	# <marquee> and <blink> should not be used
        TEST=$($GREP  '<marquee\|<blink\|</blink\|</marquee' $DIR/* | grep -vf $EXCEPTIONS_7_2 | grep -vf $EXCEPTIONS_GLOBAL)

        checkTest
        checkOk
}

# [7.4] Until user agents provide the ability to stop the refresh, do not create periodically auto-refreshing pages.
function test7dot4() { 
	setOk
	printDescriptionAll "$DESC_7_4" "$DESC_7_4_VERBOSE";

	# <meta ... refresh
        TEST=$($GREP  '<meta http-equiv=refresh\|<meta http-equiv="refresh"' $DIR/* | grep -vf $EXCEPTIONS_7_4 | grep -vf $EXCEPTIONS_GLOBAL)
	
	checkTest
	checkOk
}

# [7.5] Until user agents provide the ability to stop auto-redirect, do not use markup to redirect pages automatically. Instead, configure the server to perform redirects.
function test7dot5() { 
	setOk
	printDescriptionAll "$DESC_7_5" "$DESC_7_5_VERBOSE";

	# <meta .. refresh ... url
	TEST=$($GREP  '<meta http-equiv=refresh\|<meta http-equiv="refresh"' $DIR/* | grep -i "url=" | grep -vf $EXCEPTIONS_7_5 | grep -vf $EXCEPTIONS_GLOBAL)

	checkTest
	checkOk
}

# [10.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.
function test10dot1() { printDescriptionAll "$DESC_10_1" "$DESC_10_1_VERBOSE"; notImplemented; }

# [11.1] Use W3C technologies when they are available and appropriate for a task and use the latest versions when supported. 
function test11dot1() { printDescriptionAll "$DESC_11_1" "$DESC_11_1_VERBOSE"; notImplemented; }

# [11.2] Avoid deprecated features of W3C technologies
function test11dot2() {
        setOk
        printDescriptionAll "$DESC_11_2" "$DESC_11_2_VERBOSE"

        # Deprecated tags: center, applet, basefont, dir, font, isindex, menu, s, strike, u
	# Deprecated attributes (only on some tags, check exceptions carefully!): 
		# align (caption,  iframe, img, input, object, legend, table, hr, div, h*, p) 
		# alink (body) 
		# background (body) 
		# bgcolor (table, tr, td, th, body) 
		# border (img, object) 
		# clear (br) 
		# compact (dl, menu, ol, ul) 
		# height (td, th) 
		# hspace (img, object) 
		# language (script) 
		# link (body) 
		# noshade (hr) 
		# nowrap (td,th) 
		# size (hr) 
		# start (ol) 
		# text (body)
		# type (li,ol,ul) 
		# value (li) 
		# version (html) 
		# vlink (body) 
		# vspace (img, object) 
		# width (hr, td, th, pre)  
        TEST=$(
		$GREP  '<center>\|</center>\|<applet\|</applet>\|<basefont\|</basefont>\|<dir\|</dir>\|<font\|</font>\|<isindex\|</isindex>\|<menu\|</menu>\|\<s>\|</s>\|<strike\|</strike>\|<u>\|</u>' $DIR/* | grep -vf $EXCEPTIONS_11_2 | grep -vf $EXCEPTIONS_GLOBAL ;
		$GREP  'align=' $DIR/* | grep -i '<caption\|<iframe\|<img\|<input\|<object\|<legend\|<table\|<hr\|<div\|<h[1-6]\|<p' | grep -vf $EXCEPTIONS_11_2 | grep -vf $EXCEPTIONS_GLOBAL ;
		$GREP  'alink=\|background=\|link=\|text=' $DIR/* | grep -i '<body' | grep -vf $EXCEPTIONS_11_2 | grep -vf $EXCEPTIONS_GLOBAL ;
		$GREP  'bgcolor=' $DIR/* | grep -i '<table\|<tr\|<td\|<th\|<body' | grep -vf $EXCEPTIONS_11_2 | grep -vf $EXCEPTIONS_GLOBAL ;
		$GREP  'border=\|hspace=\|vspace=' $DIR/* | grep -i '<img\|<object' | grep -vf $EXCEPTIONS_11_2 | grep -vf $EXCEPTIONS_GLOBAL ;
		$GREP  'clear=' $DIR/* | grep -i '<br' | grep -vf $EXCEPTIONS_11_2 | grep -vf $EXCEPTIONS_GLOBAL ;
		$GREP  'compact=' $DIR/* | grep -i '<dl\|<menu\|<ol\|<ul' | grep -vf $EXCEPTIONS_11_2 | grep -vf $EXCEPTIONS_GLOBAL ;
		$GREP  'height=\|nowrap=' $DIR/* | grep -i '<td\|<th' | grep -vf $EXCEPTIONS_11_2 | grep -vf $EXCEPTIONS_GLOBAL ;
                $GREP  'language=' $DIR/* | grep -i '<script' | grep -vf $EXCEPTIONS_11_2 | grep -vf $EXCEPTIONS_GLOBAL ;
                $GREP  'noshade=\|size=' $DIR/* | grep -i '<hr' | grep -vf $EXCEPTIONS_11_2 | grep -vf $EXCEPTIONS_GLOBAL ;
                $GREP  'start=' $DIR/* | grep -i '<ol' | grep -vf $EXCEPTIONS_11_2 | grep -vf $EXCEPTIONS_GLOBAL ;
                $GREP  'type=' $DIR/* | grep -i '<li \|<li>\|<ol\|<ul' | grep -vf $EXCEPTIONS_11_2 | grep -vf $EXCEPTIONS_GLOBAL ;
		$GREP  'value=' $DIR/* | grep -i '<li \|<li> ' | grep -vf $EXCEPTIONS_11_2 | grep -vf $EXCEPTIONS_GLOBAL ;
                $GREP  'version=' $DIR/* | grep -i '<html' | grep -vf $EXCEPTIONS_11_2 | grep -vf $EXCEPTIONS_GLOBAL ;
                $GREP  'width=' $DIR/* | grep -i '<hr\|<td\|<th\|<pre' | grep -vf $EXCEPTIONS_11_2 | grep -vf $EXCEPTIONS_GLOBAL ;
	)
        checkTest
        checkOk
}
# [12.3] Divide large blocks of information into more manageable groups where natural and appropriate. 
function test12dot3() { printDescriptionAll "$DESC_12_3" "$DESC_12_3_VERBOSE"; notImplemented; }

# [13.1] Clearly identify the target of each link. 
function test13dot1() { 
	setOk
	printDescriptionAll "$DESC_13_1" "$DESC_13_1_VERBOSE";

	# links MAY have a title attribute
	TEST=$($GREP  '<a href=' $DIR/* | grep -vi 'title=' | grep -vf $EXCEPTIONS_13_1 | grep -vf $EXCEPTIONS_GLOBAL ;)

	checkTest
	checkOk
}

# [13.2] Provide metadata to add semantic information to pages and sites. 
function test13dot2() { printDescriptionAll "$DESC_13_2" "$DESC_13_2_VERBOSE"; notImplemented; }

# [13.3] Provide information about the general layout of a site (e.g., a site map or table of contents). 
function test13dot3() { printDescriptionAll "$DESC_13_3" "$DESC_13_3_VERBOSE"; notImplemented; }

# [13.4] Use navigation mechanisms in a consistent manner.               
function test13dot4() { printDescriptionAll "$DESC_13_4" "$DESC_13_4_VERBOSE"; notImplemented; }

# [5.3] Do not use tables for layout unless the table makes sense when linearized. Otherwise, if the table does not make sense, provide an alternative equivalent (which may be a linearized version).
function test5dot3() { printDescriptionAll "$DESC_5_3" "$DESC_5_3_VERBOSE"; notImplemented; }

# [5.4] If a table is used for layout, do not use any structural markup for the purpose of visual formatting. 
function test5dot4() { printDescriptionAll "$DESC_5_4" "$DESC_5_4_VERBOSE"; notImplemented; }

# [12.2] Describe the purpose of frames and how frames relate to each other if it is not obvious by frame titles alone. 
function test12dot2() { printDescriptionAll "$DESC_12_2" "$DESC_12_2_VERBOSE"; notImplemented; }

# [10.2] 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.
function test10dot2() { printDescriptionAll "$DESC_10_2" "$DESC_10_2_VERBOSE"; notImplemented; }

# [12.4] Associate labels explicitly with their controls. 
function test12dot4() { printDescriptionAll "$DESC_12_4" "$DESC_12_4_VERBOSE"; notImplemented; }

# [6.4] For scripts and applets, ensure that event handlers are input device-independent. 
function test6dot4() { printDescriptionAll "$DESC_6_4" "$DESC_6_4_VERBOSE"; notImplemented; }

# [7.3] Until user agents allow users to freeze moving content, avoid movement in pages. 
function test7dot3() { printDescriptionAll "$DESC_7_3" "$DESC_7_3_VERBOSE"; notImplemented; }

# [8.1] Make programmatic elements such as scripts and applets directly accessible or compatible with assistive technologies [Priority 1 if functionality is important and not presented elsewhere, otherwise Priority 2.]
function test8dot1() { printDescriptionAll "$DESC_8_1" "$DESC_8_1_VERBOSE"; notImplemented; }

# [9.2] Ensure that any element that has its own interface can be operated in a device-independent manner.
function test9dot2() { printDescriptionAll "$DESC_9_2" "$DESC_9_2_VERBOSE"; notImplemented; }

# [9.3] For scripts, specify logical event handlers rather than device-dependent event handlers. 
function test9dot3() { printDescriptionAll "$DESC_9_3" "$DESC_9_3_VERBOSE"; notImplemented; }

## Priority 3....
