117 $value = strtolower($value);
120 if ( PHP_SAPI !=
'cli' ) { ?>
121 <!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN" 122 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
123 <html xmlns=
"http://www.w3.org/1999/xhtml" xml:lang=
"en" lang=
"en">
125 <title>
GeSHi Language File Validation Script</title>
126 <
style type=
"text/css">
129 background-
color: #f0f0f0;
132 font-family: Verdana, Arial, sans-serif;
134 border: 2px solid #e0e0e0;
135 background-
color: #fcfcfc;
140 margin: .1em 0 .2em .5em;
141 border-bottom: 1px solid #b0b0b0;
147 margin: .1em 0 .2em .5em;
161 border: 1px solid #b0b0b0;
177 <h2>
GeSHi Language File Validation Script</h2>
181 <p>Everything else will be done by this script automatically. After the script 182 finished you should see messages of what could cause trouble with GeSHi or where 183 your language files can be improved. Please be patient, as this might take some time.</p> 186 <li>Checking where to find GeSHi installation ...<?php 188 <?php echo colorize(TYPE_NOTICE, "#### GeSHi Language File Validation Script ####") ?> 191 To use this script, make sure that <?php echo colorize(TYPE_NOTICE, "geshi.php"); ?> is in the 192 parent directory or in your include_path, and that the language files are in a 195 Everything
else will be done by
this script automatically. After
the script 196 finished you should see messages
of what could cause trouble with
GeSHi or where
206 if (is_readable(
'../geshi.php')) {
208 } elseif (is_readable(
'geshi.php')) {
215 require
$path .
'geshi.php';
217 if(!class_exists(
'GeSHi')) {
218 report_error(
TYPE_ERROR,
'The GeSHi class was not found, although it seemed we loaded the correct file!');
223 if(!
defined(
'GESHI_LANG_ROOT')) {
235 if ( PHP_SAPI ==
'cli' ) {
236 echo "Listing available language files ...\t\t";
238 echo "</li>\n<li>Listing available language files ... ";
248 while (
$file = readdir($dir)) {
271 if ( PHP_SAPI ==
'cli' ) {
276 if (isset($_REQUEST[
'show']) && in_array($_REQUEST[
'show'],
$languages)) {
284 if ( PHP_SAPI ==
'cli' ) {
285 echo "Validating language file for '$lang' ...\t\t";
287 echo "</li>\n<li>Validating language file for '$lang' ... ";
294 if(!is_file($langfile)) {
296 } elseif(!is_readable($langfile)) {
299 $langfile_content = file_get_contents($langfile);
300 if(preg_match(
"/\?>(?:\r?\n|\r(?!\n)){2,}\Z/", $langfile_content)) {
303 if(preg_match(
"/\?>(?:\r?\n|\r(?!\n))?\Z/", $langfile_content)) {
306 if(!preg_match(
"/(?:\r?\n|\r(?!\n))\Z/", $langfile_content)) {
309 if(preg_match(
"/(\r?\n|\r(?!\n))\\1\Z/", $langfile_content)) {
312 if(preg_match(
"/[\x20\t]$/m", $langfile_content)) {
315 if(preg_match(
"/\t/", $langfile_content)) {
318 if(preg_match(
'/^(?: )*(?! )(?! \*) /m', $langfile_content)) {
319 report_error(
TYPE_NOTICE,
'Language file contains irregular indentation (other than 4 spaces per indentation level)!');
322 if(!preg_match(
"/\/\*\*((?!\*\/).)*?Author:((?!\*\/).)*?\*\//s", $langfile_content)) {
325 if(!preg_match(
"/\/\*\*((?!\*\/).)*?Copyright:((?!\*\/).)*?\*\//s", $langfile_content)) {
328 if(!preg_match(
"/\/\*\*((?!\*\/).)*?Release Version:((?!\*\/).)*?\*\//s", $langfile_content)) {
331 if(!preg_match(
"/\/\*\*((?!\*\/).)*?Date Started:((?!\*\/).)*?\*\//s", $langfile_content)) {
334 if(!preg_match(
"/\/\*\*((?!\*\/).)*?This file is part of GeSHi\.((?!\*\/).)*?\*\//s", $langfile_content)) {
337 if(!preg_match(
"/\/\*\*((?!\*\/).)*?language file for GeSHi\.((?!\*\/).)*?\*\//s", $langfile_content)) {
340 if(!preg_match(
"/\/\*\*((?!\*\/).)*?GNU General Public License((?!\*\/).)*?\*\//s", $langfile_content)) {
344 unset($langfile_content);
359 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'LANG_NAME\'] specification which is not a string!');
363 report_error(
TYPE_ERROR,
'Language file contains no $language_data[\'COMMENT_SIGNLE\'] structure to check!');
365 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'COMMENT_SINGLE\'] structure which is not an array!');
369 report_error(
TYPE_ERROR,
'Language file contains no $language_data[\'COMMENT_MULTI\'] structure to check!');
371 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'COMMENT_MULTI\'] structure which is not an array!');
376 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'COMMENT_REGEXP\'] structure which is not an array!');
383 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'QUOTEMARKS\'] structure which is not an array!');
388 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'HARDQUOTE\'] structure which is not an array!');
393 report_error(
TYPE_ERROR,
'Language file contains no $language_data[\'ESCAPE_CHAR\'] specification to check!');
395 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'ESCAPE_CHAR\'] specification which is not a string!');
397 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'ESCAPE_CHAR\'] specification is not empty or exactly one char!');
403 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'CASE_KEYWORDS\'] specification which is not an integer!');
407 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'CASE_KEYWORDS\'] specification which is neither of GESHI_CAPS_NO_CHANGE, GESHI_CAPS_LOWER nor GESHI_CAPS_UPPER!');
413 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'KEYWORDS\'] structure which is not an array!');
416 if(!is_integer($kw_key)) {
417 report_error(
TYPE_WARNING,
"Language file contains an key '$kw_key' in \$language_data['KEYWORDS'] that is not integer!");
418 } elseif (!is_array($kw_value)) {
419 report_error(
TYPE_ERROR,
"Language file contains a \$language_data['KEYWORDS']['$kw_value'] structure which is not an array!");
427 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'SYMBOLS\'] structure which is not an array!');
431 report_error(
TYPE_ERROR,
'Language file contains no $language_data[\'CASE_SENSITIVE\'] structure to check!');
433 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'CASE_SENSITIVE\'] structure which is not an array!');
435 foreach(
$language_data[
'CASE_SENSITIVE'] as $cs_key => $cs_value) {
436 if(!is_integer($cs_key)) {
437 report_error(
TYPE_WARNING,
"Language file contains an key '$cs_key' in \$language_data['CASE_SENSITIVE'] that is not integer!");
438 } elseif (!is_bool($cs_value)) {
439 report_error(
TYPE_ERROR,
"Language file contains a Case Sensitivity specification for \$language_data['CASE_SENSITIVE']['$cs_value'] which is not a boolean!");
447 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'URLS\'] structure which is not an array!');
450 if(!is_integer($url_key)) {
451 report_error(
TYPE_WARNING,
"Language file contains an key '$url_key' in \$language_data['URLS'] that is not integer!");
452 } elseif (!is_string($url_value)) {
453 report_error(
TYPE_ERROR,
"Language file contains a Documentation URL specification for \$language_data['URLS']['$url_value'] which is not a string!");
454 } elseif (preg_match(
'#&([^;]*(=|$))#U', $url_value)) {
455 report_error(
TYPE_ERROR,
"Language file contains unescaped ampersands (&) in \$language_data['URLS']!");
463 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'OOLANG\'] specification which is neither boolean nor integer!');
467 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'OOLANG\'] specification which is neither of false, true or 2!');
471 report_error(
TYPE_ERROR,
'Language file contains no $language_data[\'OBJECT_SPLITTERS\'] structure to check!');
473 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'OBJECT_SPLITTERS\'] structure which is not an array!');
479 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'REGEXPS\'] structure which is not an array!');
483 report_error(
TYPE_ERROR,
'Language file contains no $language_data[\'STRICT_MODE_APPLIES\'] specification!');
485 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'STRICT_MODE_APPLIES\'] specification which is not an integer!');
489 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'STRICT_MODE_APPLIES\'] specification which is neither of GESHI_MAYBE, GESHI_ALWAYS nor GESHI_NEVER!');
493 report_error(
TYPE_ERROR,
'Language file contains no $language_data[\'SCRIPT_DELIMITERS\'] structure to check!');
495 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'SCRIPT_DELIMITERS\'] structure which is not an array!');
499 report_error(
TYPE_ERROR,
'Language file contains no $language_data[\'HIGHLIGHT_STRICT_BLOCK\'] structure to check!');
501 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'HIGHLIGHT_STRICT_BLOCK\'] structure which is not an array!');
506 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'TAB_WIDTH\'] specification which is not an integer!');
508 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'TAB_WIDTH\'] specification which is less than 1!');
514 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'PARSER_CONTROL\'] structure which is not an array!');
521 report_error(
TYPE_ERROR,
'Language file contains a $language_data[\'STYLES\'] structure which is not an array!');
523 $style_arrays =
array(
'KEYWORDS',
'COMMENTS',
'ESCAPE_CHAR',
524 'BRACKETS',
'STRINGS',
'NUMBERS',
'METHODS',
'SYMBOLS',
525 'REGEXPS',
'SCRIPT');
526 foreach($style_arrays as $style_kind) {
528 report_error(
TYPE_ERROR,
"Language file contains no \$language_data['STYLES']['$style_kind'] structure to check!");
530 report_error(
TYPE_ERROR,
"Language file contains a \$language_data['STYLES\']['$style_kind'] structure which is not an array!");
532 foreach(
$language_data[
'STYLES'][$style_kind] as $sk_key => $sk_value) {
533 if(!is_int($sk_key) && (
'COMMENTS' != $style_kind &&
'MULTI' != $sk_key)
534 && !((
'STRINGS' == $style_kind ||
'ESCAPE_CHAR' == $style_kind) &&
'HARD' == $sk_key)) {
535 report_error(
TYPE_WARNING,
"Language file contains an key '$sk_key' in \$language_data['STYLES']['$style_kind'] that is not integer!");
536 } elseif (!is_string($sk_value)) {
537 report_error(
TYPE_WARNING,
"Language file contains a CSS specification for \$language_data['STYLES']['$style_kind'][$key] which is not a string!");
543 unset($style_arrays);
551 report_error(
TYPE_ERROR,
"Language file contains no \$language_data['CASE_SENSITIVE'] specification for keyword group $key!");
554 report_error(
TYPE_ERROR,
"Language file contains no \$language_data['URLS'] specification for keyword group $key!");
556 if(empty($keywords)) {
557 report_error(
TYPE_WARNING,
"Language file contains an empty keyword list in \$language_data['KEYWORDS'] for group $key!");
559 foreach($keywords as $id => $kw) {
560 if(!is_string($kw)) {
561 report_error(
TYPE_WARNING,
"Language file contains an non-string entry at \$language_data['KEYWORDS'][$key][$id]!");
562 } elseif (!strlen($kw)) {
563 report_error(
TYPE_ERROR,
"Language file contains an empty string entry at \$language_data['KEYWORDS'][$key][$id]!");
564 } elseif (preg_match(
'/^([\(\)\{\}\[\]\^=.,:;\-+\*\/%\$\"\'\?]|&[\w#]\w*;)+$/i', $kw)) {
565 report_error(
TYPE_NOTICE,
"Language file contains an keyword ('$kw') at \$language_data['KEYWORDS'][$key][$id] which seems to be better suited for the symbols section!");
569 array_walk($keywords,
'dupfind_strtolower');
571 if(count($keywords) != count(array_unique($keywords))) {
572 $kw_diffs = array_count_values($keywords);
573 foreach($kw_diffs as $kw => $kw_count) {
575 report_error(
TYPE_WARNING,
"Language file contains per-group duplicate keyword '$kw' in \$language_data['KEYWORDS'][$key]!");
581 $disallowed_before =
"(?<![a-zA-Z0-9\$_\|\#;>|^&";
582 $disallowed_after =
"(?![a-zA-Z0-9_\|%\\-&;";
589 $kw_diffs = array_intersect($keywords, $keywords2);
590 foreach($kw_diffs as $kw) {
593 $g1_pre = $disallowed_before;
594 $g2_pre = $disallowed_before;
595 $g1_post = $disallowed_after;
596 $g2_post = $disallowed_after;
597 if(isset(
$language_data[
'PARSER_CONTROL'][
'KEYWORDS'][
'DISALLOWED_BEFORE'])) {
598 $g1_pre =
$language_data[
'PARSER_CONTROL'][
'KEYWORDS'][
'DISALLOWED_BEFORE'];
599 $g2_pre =
$language_data[
'PARSER_CONTROL'][
'KEYWORDS'][
'DISALLOWED_BEFORE'];
601 if(isset(
$language_data[
'PARSER_CONTROL'][
'KEYWORDS'][
'DISALLOWED_AFTER'])) {
602 $g1_post =
$language_data[
'PARSER_CONTROL'][
'KEYWORDS'][
'DISALLOWED_AFTER'];
603 $g2_post =
$language_data[
'PARSER_CONTROL'][
'KEYWORDS'][
'DISALLOWED_AFTER'];
606 if(isset(
$language_data[
'PARSER_CONTROL'][
'KEYWORDS'][$key][
'DISALLOWED_BEFORE'])) {
607 $g1_pre =
$language_data[
'PARSER_CONTROL'][
'KEYWORDS'][$key][
'DISALLOWED_BEFORE'];
609 if(isset(
$language_data[
'PARSER_CONTROL'][
'KEYWORDS'][$key][
'DISALLOWED_AFTER'])) {
610 $g1_post =
$language_data[
'PARSER_CONTROL'][
'KEYWORDS'][$key][
'DISALLOWED_AFTER'];
613 if(isset(
$language_data[
'PARSER_CONTROL'][
'KEYWORDS'][$key2][
'DISALLOWED_BEFORE'])) {
614 $g2_pre =
$language_data[
'PARSER_CONTROL'][
'KEYWORDS'][$key2][
'DISALLOWED_BEFORE'];
616 if(isset(
$language_data[
'PARSER_CONTROL'][
'KEYWORDS'][$key2][
'DISALLOWED_AFTER'])) {
617 $g2_post =
$language_data[
'PARSER_CONTROL'][
'KEYWORDS'][$key2][
'DISALLOWED_AFTER'];
620 if($g1_pre != $g2_pre || $g1_post != $g2_post) {
624 report_error(
TYPE_WARNING,
"Language file contains cross-group duplicate keyword '$kw' in \$language_data['KEYWORDS'][$key] and \$language_data['KEYWORDS'][$key2]!");
630 report_error(
TYPE_WARNING,
"Language file contains an superfluous \$language_data['CASE_SENSITIVE'] specification for non-existing keyword group $key!");
635 report_error(
TYPE_WARNING,
"Language file contains an superfluous \$language_data['URLS'] specification for non-existing keyword group $key!");
638 foreach(
$language_data[
'STYLES'][
'KEYWORDS'] as $key => $keywords) {
640 report_error(
TYPE_WARNING,
"Language file contains an superfluous \$language_data['STYLES']['KEYWORDS'] specification for non-existing keyword group $key!");
646 report_error(
TYPE_WARNING,
"Language file contains an key '$ck' in \$language_data['COMMENT_SINGLE'] that is not integer!");
648 if(!is_string($cv)) {
649 report_error(
TYPE_WARNING,
"Language file contains an non-string entry at \$language_data['COMMENT_SINGLE'][$ck]!");
652 report_error(
TYPE_WARNING,
"Language file contains no \$language_data['STYLES']['COMMENTS'] specification for comment group $ck!");
658 report_error(
TYPE_WARNING,
"Language file contains an key '$ck' in \$language_data['COMMENT_REGEXP'] that is not integer!");
660 if(!is_string($cv)) {
661 report_error(
TYPE_WARNING,
"Language file contains an non-string entry at \$language_data['COMMENT_REGEXP'][$ck]!");
664 report_error(
TYPE_WARNING,
"Language file contains no \$language_data['STYLES']['COMMENTS'] specification for comment group $ck!");
669 if($ck !=
'MULTI' && !isset(
$language_data[
'COMMENT_SINGLE'][$ck]) &&
671 report_error(
TYPE_NOTICE,
"Language file contains an superfluous \$language_data['STYLES']['COMMENTS'] specification for Single Line or Regular-Expression Comment key $ck!");
676 report_error(
TYPE_NOTICE,
"Language file contains superfluous \$language_data['STYLES']['STRINGS'] specification for key 'HARD', but no 'HARDQUOTE's are defined!");
682 report_error(
TYPE_NOTICE,
"Language file contains an superfluous \$language_data['STYLES']['STRINGS'] specification for non-existing quotemark key $sk!");
688 report_error(
TYPE_WARNING,
"Language file contains an key '$rk' in \$language_data['REGEXPS'] that is not integer!");
693 report_error(
TYPE_WARNING,
"Language file contains an empty regular expression at \$language_data['REGEXPS'][$rk]!");
695 if(preg_match(
"/(?<!\\\\)\//s", $rv)) {
696 report_error(
TYPE_WARNING,
"Language file contains a regular expression with an unmasked / character at \$language_data['REGEXPS'][$rk]!");
697 } elseif (preg_match(
"/(?<!<)(\\\\\\\\)*\\\\\|(?!>)/s", $rv)) {
698 report_error(
TYPE_WARNING,
"Language file contains a regular expression with an unescaped match for a pipe character '|' which needs escaping as '<PIPE>' instead at \$language_data['REGEXPS'][$rk]!");
701 } elseif(is_array($rv)) {
703 report_error(
TYPE_ERROR,
"Language file contains no GESHI_SEARCH entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
704 } elseif(!is_string($rv[GESHI_SEARCH])) {
705 report_error(
TYPE_ERROR,
"Language file contains a GESHI_SEARCH entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
707 if(preg_match(
"/(?<!\\\\)\//s", $rv[GESHI_SEARCH])) {
708 report_error(
TYPE_WARNING,
"Language file contains a regular expression with an unmasked / character at \$language_data['REGEXPS'][$rk]!");
709 } elseif (preg_match(
"/(?<!<)(\\\\\\\\)*\\\\\|(?!>)/s", $rv[GESHI_SEARCH])) {
710 report_error(
TYPE_WARNING,
"Language file contains a regular expression with an unescaped match for a pipe character '|' which needs escaping as '<PIPE>' instead at \$language_data['REGEXPS'][$rk]!");
714 report_error(
TYPE_WARNING,
"Language file contains no GESHI_REPLACE entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
715 } elseif(!is_string($rv[GESHI_REPLACE])) {
716 report_error(
TYPE_ERROR,
"Language file contains a GESHI_REPLACE entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
719 report_error(
TYPE_WARNING,
"Language file contains no GESHI_MODIFIERS entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
720 } elseif(!is_string($rv[GESHI_MODIFIERS])) {
721 report_error(
TYPE_ERROR,
"Language file contains a GESHI_MODIFIERS entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
724 report_error(
TYPE_WARNING,
"Language file contains no GESHI_BEFORE entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
725 } elseif(!is_string($rv[GESHI_BEFORE])) {
726 report_error(
TYPE_ERROR,
"Language file contains a GESHI_BEFORE entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
729 report_error(
TYPE_WARNING,
"Language file contains no GESHI_AFTER entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
730 } elseif(!is_string($rv[GESHI_AFTER])) {
731 report_error(
TYPE_ERROR,
"Language file contains a GESHI_AFTER entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
734 report_error(
TYPE_WARNING,
"Language file contains an non-string and non-array entry at \$language_data['REGEXPS'][$rk]!");
737 report_error(
TYPE_WARNING,
"Language file contains no \$language_data['STYLES']['REGEXPS'] specification for regexp group $rk!");
742 report_error(
TYPE_NOTICE,
"Language file contains an superfluous \$language_data['STYLES']['REGEXPS'] specification for regexp key $rk!");
762 if ( PHP_SAPI !=
'cli' ) {
768 <div
id=
"footer">
GeSHi © 2004-2007 Nigel McNie, 2007-2008 Benny Baumann, released under
the GNU GPL</div>
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
const GESHI_MODIFIERS
The key of the regex array defining any modifiers to the regular expression.
const GESHI_LANG_ROOT(!defined('GESHI_ROOT'))
The language file directory for GeSHi private.
if(PHP_SAPI !='cli') color
const GESHI_BEFORE
The key of the regex array defining what bracket group in a matched search to put before the replacem...
const GESHI_COMMENTS
Used in language files to mark comments.
const GESHI_REPLACE
The key of the regex array defining what bracket group in a matched search to use as a replacement...
const GESHI_CAPS_UPPER
Uppercase keywords found.
colorize($level, $string)
const GESHI_SEARCH
The key of the regex array defining what to search for.
Create styles array
The data for the language used.
const GESHI_CAPS_LOWER
Leave keywords found as the case that they are.
const GESHI_MAYBE
Strict mode might apply, and can be enabled or disabled by GeSHi->enable_strict_mode().
const GESHI_NEVER
#+ private
for($i=1; $i<=count($kw_cases_sel); $i+=1) $lang
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
defined( 'APPLICATION_ENV')||define( 'APPLICATION_ENV'
const GESHI_CAPS_NO_CHANGE
Lowercase keywords found.
A simple script which outputs the CSS classes for all languages supported by GeSHi.
report_error($type, $message)
const GESHI_ALWAYS
Strict mode always applies.
sprintf('%.4f', $callTime) seconds
const GESHI_AFTER
The key of the regex array defining what bracket group in a matched search to put after the replaceme...