Home | History | Annotate | Download | only in contrib
      1 <?php
      2 /**
      3  * GeSHi example script
      4  *
      5  * Just point your browser at this script (with geshi.php in the parent directory,
      6  * and the language files in subdirectory "../geshi/")
      7  *
      8  * @author  Nigel McNie
      9  * @version $Id: langcheck.php 1971 2008-12-25 15:14:14Z benbe $
     10  */
     11 header('Content-Type: text/html; charset=utf-8');
     12 
     13 set_time_limit(0);
     14 error_reporting(E_ALL);
     15 $time_start = explode(' ', microtime());
     16 
     17 define ('TYPE_NOTICE', 0);
     18 define ('TYPE_WARNING', 1);
     19 define ('TYPE_ERROR', 2);
     20 
     21 $error_abort = false;
     22 $error_cache = array();
     23 function output_error_cache(){
     24     global $error_cache, $error_abort;
     25 
     26     if(count($error_cache)) {
     27         echo "<span style=\"color: #F00; font-weight: bold;\">Failed</span><br />";
     28         echo "<ol>\n";
     29         foreach($error_cache as $error_msg) {
     30             echo "<li>";
     31             switch($error_msg['t']) {
     32                 case TYPE_NOTICE:
     33                     echo "<span style=\"color: #080; font-weight: bold;\">NOTICE:</span>";
     34                     break;
     35                 case TYPE_WARNING:
     36                     echo "<span style=\"color: #CC0; font-weight: bold;\">WARNING:</span>";
     37                     break;
     38                 case TYPE_ERROR:
     39                     echo "<span style=\"color: #F00; font-weight: bold;\">ERROR:</span>";
     40                     break;
     41             }
     42             echo " " . $error_msg['m'] . "</li>";
     43         }
     44         echo "</ol>\n";
     45     } else {
     46         echo "<span style=\"color: #080; font-weight: bold;\">OK</span><br />";
     47     }
     48     echo "\n";
     49 
     50     $error_cache = array();
     51 }
     52 
     53 function report_error($type, $message) {
     54     global $error_cache, $error_abort;
     55 
     56     $error_cache[] = array('t' => $type, 'm' => $message);
     57     if(TYPE_ERROR == $type) {
     58         $error_abort = true;
     59     }
     60 }
     61 
     62 ?>
     63 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     64      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
     65 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
     66 <head>
     67     <title>GeSHi Language File Validation Script</title>
     68     <style type="text/css">
     69     <!--
     70     html {
     71         background-color: #f0f0f0;
     72     }
     73     body {
     74         font-family: Verdana, Arial, sans-serif;
     75         margin: 10px;
     76         border: 2px solid #e0e0e0;
     77         background-color: #fcfcfc;
     78         padding: 5px;
     79         font-size: 10pt;
     80     }
     81     h2 {
     82         margin: .1em 0 .2em .5em;
     83         border-bottom: 1px solid #b0b0b0;
     84         color: #b0b0b0;
     85         font-weight: normal;
     86         font-size: 150%;
     87     }
     88     h3 {
     89         margin: .1em 0 .2em .5em;
     90         color: #b0b0b0;
     91         font-weight: normal;
     92         font-size: 120%;
     93     }
     94     #footer {
     95         text-align: center;
     96         font-size: 80%;
     97         color: #a9a9a9;
     98     }
     99     #footer a {
    100         color: #9999ff;
    101     }
    102     textarea {
    103         border: 1px solid #b0b0b0;
    104         font-size: 90%;
    105         color: #333;
    106         margin-left: 20px;
    107     }
    108     select, input {
    109         margin-left: 20px;
    110     }
    111     p {
    112         font-size: 90%;
    113         margin-left: .5em;
    114     }
    115     -->
    116     </style>
    117 </head>
    118 <body>
    119 <h2>GeSHi Language File Validation Script</h2>
    120 <p>To use this script, make sure that <strong>geshi.php</strong> is in the
    121 parent directory or in your include_path, and that the language files are in a
    122 subdirectory of GeSHi's directory called <strong>geshi/</strong>.</p>
    123 <p>Everything else will be done by this script automatically. After the script
    124 finished you should see messages of what could cause trouble with GeSHi or where
    125 your language files can be improved. Please be patient, as this might take some time.</p>
    126 
    127 <ol>
    128 <li>Checking where to find GeSHi installation ... <?php
    129 // Rudimentary checking of where GeSHi is. In a default install it will be in ../, but
    130 // it could be in the current directory if the include_path is set. There's nowhere else
    131 // we can reasonably guess.
    132 if (is_readable('../geshi.php')) {
    133     $path = '../';
    134 } elseif (is_readable('geshi.php')) {
    135     $path = './';
    136 } else {
    137     report_error(TYPE_ERROR, 'Could not find geshi.php - make sure it is in your include path!');
    138 }
    139 
    140 if(!$error_abort) {
    141     require $path . 'geshi.php';
    142 
    143     if(!class_exists('GeSHi')) {
    144         report_error(TYPE_ERROR, 'The GeSHi class was not found, although it seemed we loaded the correct file!');
    145     }
    146 }
    147 
    148 if(!$error_abort) {
    149     if(!defined('GESHI_LANG_ROOT')) {
    150         report_error(TYPE_ERROR, 'There\'s no information present on where to find the language files!');
    151     } else if(!is_dir(GESHI_LANG_ROOT)) {
    152         report_error(TYPE_ERROR, 'The path "'.GESHI_LANG_ROOT.'" given, does not ressemble a directory!');
    153     } else if(!is_readable(GESHI_LANG_ROOT)) {
    154         report_error(TYPE_ERROR, 'The path "'.GESHI_LANG_ROOT.'" is not readable to this script!');
    155     }
    156 }
    157 
    158 output_error_cache();
    159 
    160 if(!$error_abort) {
    161     echo "</li>\n<li>Listing available language files ... ";
    162 
    163     if (!($dir = @opendir(GESHI_LANG_ROOT))) {
    164         report_error(TYPE_ERROR, 'Error requesting listing for available language files!');
    165     }
    166 
    167     $languages = array();
    168 
    169     if(!$error_abort) {
    170         while ($file = readdir($dir)) {
    171             if (!$file || $file[0] == '.' || strpos($file, '.') === false) {
    172                 continue;
    173             }
    174             $lang = substr($file, 0,  strpos($file, '.'));
    175             $languages[] = $lang;
    176         }
    177         closedir($dir);
    178     }
    179 
    180     $languages = array_unique($languages);
    181     sort($languages);
    182 
    183     if(!count($languages)) {
    184         report_error(TYPE_WARNING, 'Unable to locate any usable language files in "'.GESHI_LANG_ROOT.'"!');
    185     }
    186 
    187     output_error_cache();
    188 }
    189 
    190 if (isset($_REQUEST['show']) && in_array($_REQUEST['show'], $languages)) {
    191     $languages = array($_REQUEST['show']);
    192 }
    193 
    194 if(!$error_abort) {
    195     foreach ($languages as $lang) {
    196         echo "</li>\n<li>Validating language file for '$lang' ... ";
    197 
    198         $langfile = GESHI_LANG_ROOT . $lang . '.php';
    199 
    200         unset($language_data);
    201 
    202         if(!is_file($langfile)) {
    203             report_error(TYPE_ERROR, 'The path "' .$langfile. '" does not ressemble a regular file!');
    204         } else if(!is_readable($langfile)) {
    205             report_error(TYPE_ERROR, 'Cannot read file "' .$langfile. '"!');
    206         } else {
    207             $langfile_content = file_get_contents($langfile);
    208             if(preg_match("/\?>(?:\r?\n|\r(?!\n)){2,}\Z/", $langfile_content)) {
    209                 report_error(TYPE_ERROR, 'Language file contains trailing empty lines at EOF!');
    210             }
    211             if(!preg_match("/\?>(?:\r?\n|\r(?!\n))?\Z/", $langfile_content)) {
    212                 report_error(TYPE_ERROR, 'Language file contains no PHP end marker at EOF!');
    213             }
    214             if(preg_match("/\t/", $langfile_content)) {
    215                 report_error(TYPE_NOTICE, 'Language file contains unescaped tabulator chars (probably for indentation)!');
    216             }
    217             if(preg_match('/^(?:    )*(?!    )(?! \*) /m', $langfile_content)) {
    218                 report_error(TYPE_NOTICE, 'Language file contains irregular indentation (other than 4 spaces per indentation level)!');
    219             }
    220 
    221             if(!preg_match("/\/\*\*((?!\*\/).)*?Author:((?!\*\/).)*?\*\//s", $langfile_content)) {
    222                 report_error(TYPE_WARNING, 'Language file does not contain a specification of an author!');
    223             }
    224             if(!preg_match("/\/\*\*((?!\*\/).)*?Copyright:((?!\*\/).)*?\*\//s", $langfile_content)) {
    225                 report_error(TYPE_WARNING, 'Language file does not contain a specification of the copyright!');
    226             }
    227             if(!preg_match("/\/\*\*((?!\*\/).)*?Release Version:((?!\*\/).)*?\*\//s", $langfile_content)) {
    228                 report_error(TYPE_WARNING, 'Language file does not contain a specification of the release version!');
    229             }
    230             if(!preg_match("/\/\*\*((?!\*\/).)*?Date Started:((?!\*\/).)*?\*\//s", $langfile_content)) {
    231                 report_error(TYPE_WARNING, 'Language file does not contain a specification of the date it was started!');
    232             }
    233             if(!preg_match("/\/\*\*((?!\*\/).)*?This file is part of GeSHi\.((?!\*\/).)*?\*\//s", $langfile_content)) {
    234                 report_error(TYPE_WARNING, 'Language file does not state that it belongs to GeSHi!');
    235             }
    236             if(!preg_match("/\/\*\*((?!\*\/).)*?language file for GeSHi\.((?!\*\/).)*?\*\//s", $langfile_content)) {
    237                 report_error(TYPE_WARNING, 'Language file does not state that it is a language file for GeSHi!');
    238             }
    239             if(!preg_match("/\/\*\*((?!\*\/).)*?GNU General Public License((?!\*\/).)*?\*\//s", $langfile_content)) {
    240                 report_error(TYPE_WARNING, 'Language file does not state that it is provided under the terms of the GNU GPL!');
    241             }
    242 
    243             unset($langfile_content);
    244 
    245             include $langfile;
    246 
    247             if(!isset($language_data)) {
    248                 report_error(TYPE_ERROR, 'Language file does not contain a $language_data structure to check!');
    249             } else if (!is_array($language_data)) {
    250                 report_error(TYPE_ERROR, 'Language file contains a $language_data structure which is not an array!');
    251             }
    252         }
    253 
    254         if(!$error_abort) {
    255             if(!isset($language_data['LANG_NAME'])) {
    256                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'LANG_NAME\'] specification!');
    257             } else if (!is_string($language_data['LANG_NAME'])) {
    258                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'LANG_NAME\'] specification which is not a string!');
    259             }
    260 
    261             if(!isset($language_data['COMMENT_SINGLE'])) {
    262                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'COMMENT_SIGNLE\'] structure to check!');
    263             } else if (!is_array($language_data['COMMENT_SINGLE'])) {
    264                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'COMMENT_SINGLE\'] structure which is not an array!');
    265             }
    266 
    267             if(!isset($language_data['COMMENT_MULTI'])) {
    268                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'COMMENT_MULTI\'] structure to check!');
    269             } else if (!is_array($language_data['COMMENT_MULTI'])) {
    270                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'COMMENT_MULTI\'] structure which is not an array!');
    271             }
    272 
    273             if(isset($language_data['COMMENT_REGEXP'])) {
    274                 if (!is_array($language_data['COMMENT_REGEXP'])) {
    275                     report_error(TYPE_ERROR, 'Language file contains a $language_data[\'COMMENT_REGEXP\'] structure which is not an array!');
    276                 }
    277             }
    278 
    279             if(!isset($language_data['QUOTEMARKS'])) {
    280                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'QUOTEMARKS\'] structure to check!');
    281             } else if (!is_array($language_data['QUOTEMARKS'])) {
    282                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'QUOTEMARKS\'] structure which is not an array!');
    283             }
    284 
    285             if(isset($language_data['HARDQUOTE'])) {
    286                 if (!is_array($language_data['HARDQUOTE'])) {
    287                     report_error(TYPE_ERROR, 'Language file contains a $language_data[\'HARDQUOTE\'] structure which is not an array!');
    288                 }
    289             }
    290 
    291             if(!isset($language_data['ESCAPE_CHAR'])) {
    292                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'ESCAPE_CHAR\'] specification to check!');
    293             } else if (!is_string($language_data['ESCAPE_CHAR'])) {
    294                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'ESCAPE_CHAR\'] specification which is not a string!');
    295             } else if (1 < strlen($language_data['ESCAPE_CHAR'])) {
    296                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'ESCAPE_CHAR\'] specification is not empty or exactly one char!');
    297             }
    298 
    299             if(!isset($language_data['CASE_KEYWORDS'])) {
    300                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'CASE_KEYWORDS\'] specification!');
    301             } else if (!is_int($language_data['CASE_KEYWORDS'])) {
    302                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'CASE_KEYWORDS\'] specification which is not an integer!');
    303             } else if (GESHI_CAPS_NO_CHANGE != $language_data['CASE_KEYWORDS'] &&
    304                 GESHI_CAPS_LOWER != $language_data['CASE_KEYWORDS'] &&
    305                 GESHI_CAPS_UPPER != $language_data['CASE_KEYWORDS']) {
    306                 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!');
    307             }
    308 
    309             if(!isset($language_data['KEYWORDS'])) {
    310                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'KEYWORDS\'] structure to check!');
    311             } else if (!is_array($language_data['KEYWORDS'])) {
    312                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'KEYWORDS\'] structure which is not an array!');
    313             } else {
    314                 foreach($language_data['KEYWORDS'] as $kw_key => $kw_value) {
    315                     if(!is_integer($kw_key)) {
    316                         report_error(TYPE_WARNING, "Language file contains an key '$kw_key' in \$language_data['KEYWORDS'] that is not integer!");
    317                     } else if (!is_array($kw_value)) {
    318                         report_error(TYPE_ERROR, "Language file contains a \$language_data['CASE_SENSITIVE']['$kw_value'] structure which is not an array!");
    319                     }
    320                 }
    321             }
    322 
    323             if(!isset($language_data['SYMBOLS'])) {
    324                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'SYMBOLS\'] structure to check!');
    325             } else if (!is_array($language_data['SYMBOLS'])) {
    326                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'SYMBOLS\'] structure which is not an array!');
    327             }
    328 
    329             if(!isset($language_data['CASE_SENSITIVE'])) {
    330                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'CASE_SENSITIVE\'] structure to check!');
    331             } else if (!is_array($language_data['CASE_SENSITIVE'])) {
    332                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'CASE_SENSITIVE\'] structure which is not an array!');
    333             } else {
    334                 foreach($language_data['CASE_SENSITIVE'] as $cs_key => $cs_value) {
    335                     if(!is_integer($cs_key)) {
    336                         report_error(TYPE_WARNING, "Language file contains an key '$cs_key' in \$language_data['CASE_SENSITIVE'] that is not integer!");
    337                     } else if (!is_bool($cs_value)) {
    338                         report_error(TYPE_ERROR, "Language file contains a Case Sensitivity specification for \$language_data['CASE_SENSITIVE']['$cs_value'] which is not a boolean!");
    339                     }
    340                 }
    341             }
    342 
    343             if(!isset($language_data['URLS'])) {
    344                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'URLS\'] structure to check!');
    345             } else if (!is_array($language_data['URLS'])) {
    346                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'URLS\'] structure which is not an array!');
    347             } else {
    348                 foreach($language_data['URLS'] as $url_key => $url_value) {
    349                     if(!is_integer($url_key)) {
    350                         report_error(TYPE_WARNING, "Language file contains an key '$url_key' in \$language_data['URLS'] that is not integer!");
    351                     } else if (!is_string($url_value)) {
    352                         report_error(TYPE_ERROR, "Language file contains a Documentation URL specification for \$language_data['URLS']['$url_value'] which is not a string!");
    353                     } else if (preg_match('#&([^;]*(=|$))#U', $url_value)) {
    354                         report_error(TYPE_ERROR, "Language file contains unescaped ampersands (&amp;) in \$language_data['URLS']!");
    355                     }
    356                 }
    357             }
    358 
    359             if(!isset($language_data['OOLANG'])) {
    360                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'OOLANG\'] specification!');
    361             } else if (!is_int($language_data['OOLANG']) && !is_bool($language_data['OOLANG'])) {
    362                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'OOLANG\'] specification which is neither boolean nor integer!');
    363             } else if (false !== $language_data['OOLANG'] &&
    364                 true !== $language_data['OOLANG'] &&
    365                 2 !== $language_data['OOLANG']) {
    366                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'OOLANG\'] specification which is neither of false, true or 2!');
    367             }
    368 
    369             if(!isset($language_data['OBJECT_SPLITTERS'])) {
    370                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'OBJECT_SPLITTERS\'] structure to check!');
    371             } else if (!is_array($language_data['OBJECT_SPLITTERS'])) {
    372                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'OBJECT_SPLITTERS\'] structure which is not an array!');
    373             }
    374 
    375             if(!isset($language_data['REGEXPS'])) {
    376                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'REGEXPS\'] structure to check!');
    377             } else if (!is_array($language_data['REGEXPS'])) {
    378                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'REGEXPS\'] structure which is not an array!');
    379             }
    380 
    381             if(!isset($language_data['STRICT_MODE_APPLIES'])) {
    382                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'STRICT_MODE_APPLIES\'] specification!');
    383             } else if (!is_int($language_data['STRICT_MODE_APPLIES'])) {
    384                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'STRICT_MODE_APPLIES\'] specification which is not an integer!');
    385             } else if (GESHI_MAYBE != $language_data['STRICT_MODE_APPLIES'] &&
    386                 GESHI_ALWAYS != $language_data['STRICT_MODE_APPLIES'] &&
    387                 GESHI_NEVER != $language_data['STRICT_MODE_APPLIES']) {
    388                 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!');
    389             }
    390 
    391             if(!isset($language_data['SCRIPT_DELIMITERS'])) {
    392                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'SCRIPT_DELIMITERS\'] structure to check!');
    393             } else if (!is_array($language_data['SCRIPT_DELIMITERS'])) {
    394                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'SCRIPT_DELIMITERS\'] structure which is not an array!');
    395             }
    396 
    397             if(!isset($language_data['HIGHLIGHT_STRICT_BLOCK'])) {
    398                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'HIGHLIGHT_STRICT_BLOCK\'] structure to check!');
    399             } else if (!is_array($language_data['HIGHLIGHT_STRICT_BLOCK'])) {
    400                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'HIGHLIGHT_STRICT_BLOCK\'] structure which is not an array!');
    401             }
    402 
    403             if(isset($language_data['TAB_WIDTH'])) {
    404                 if (!is_int($language_data['TAB_WIDTH'])) {
    405                     report_error(TYPE_ERROR, 'Language file contains a $language_data[\'TAB_WIDTH\'] specification which is not an integer!');
    406                 } else if (1 > $language_data['TAB_WIDTH']) {
    407                     report_error(TYPE_ERROR, 'Language file contains a $language_data[\'TAB_WIDTH\'] specification which is less than 1!');
    408                 }
    409             }
    410 
    411             if(isset($language_data['PARSER_CONTROL'])) {
    412                 if (!is_array($language_data['PARSER_CONTROL'])) {
    413                     report_error(TYPE_ERROR, 'Language file contains a $language_data[\'PARSER_CONTROL\'] structure which is not an array!');
    414                 }
    415             }
    416 
    417             if(!isset($language_data['STYLES'])) {
    418                 report_error(TYPE_ERROR, 'Language file contains no $language_data[\'STYLES\'] structure to check!');
    419             } else if (!is_array($language_data['STYLES'])) {
    420                 report_error(TYPE_ERROR, 'Language file contains a $language_data[\'STYLES\'] structure which is not an array!');
    421             } else {
    422                 $style_arrays = array('KEYWORDS', 'COMMENTS', 'ESCAPE_CHAR',
    423                     'BRACKETS', 'STRINGS', 'NUMBERS', 'METHODS', 'SYMBOLS',
    424                     'REGEXPS', 'SCRIPT');
    425                 foreach($style_arrays as $style_kind) {
    426                     if(!isset($language_data['STYLES'][$style_kind])) {
    427                         report_error(TYPE_ERROR, "Language file contains no \$language_data['STYLES']['$style_kind'] structure to check!");
    428                     } else if (!is_array($language_data['STYLES'][$style_kind])) {
    429                         report_error(TYPE_ERROR, "Language file contains a \$language_data['STYLES\']['$style_kind'] structure which is not an array!");
    430                     } else {
    431                         foreach($language_data['STYLES'][$style_kind] as $sk_key => $sk_value) {
    432                             if(!is_int($sk_key) && ('COMMENTS' != $style_kind && 'MULTI' != $sk_key)
    433                                 && !(('STRINGS' == $style_kind || 'ESCAPE_CHAR' == $style_kind) && 'HARD' == $sk_key)) {
    434                                 report_error(TYPE_WARNING, "Language file contains an key '$sk_key' in \$language_data['STYLES']['$style_kind'] that is not integer!");
    435                             } else if (!is_string($sk_value)) {
    436                                 report_error(TYPE_WARNING, "Language file contains a CSS specification for \$language_data['STYLES']['$style_kind'][$key] which is not a string!");
    437                             }
    438                         }
    439                     }
    440                 }
    441 
    442                 unset($style_arrays);
    443             }
    444         }
    445 
    446         if(!$error_abort) {
    447             //Initial sanity checks survived? --> Let's dig deeper!
    448             foreach($language_data['KEYWORDS'] as $key => $keywords) {
    449                 if(!isset($language_data['CASE_SENSITIVE'][$key])) {
    450                     report_error(TYPE_ERROR, "Language file contains no \$language_data['CASE_SENSITIVE'] specification for keyword group $key!");
    451                 }
    452                 if(!isset($language_data['URLS'][$key])) {
    453                     report_error(TYPE_ERROR, "Language file contains no \$language_data['URLS'] specification for keyword group $key!");
    454                 }
    455                 if(empty($keywords)) {
    456                     report_error(TYPE_WARNING, "Language file contains an empty keyword list in \$language_data['KEYWORDS'] for group $key!");
    457                 }
    458                 foreach($keywords as $id => $kw) {
    459                     if(!is_string($kw)) {
    460                         report_error(TYPE_WARNING, "Language file contains an non-string entry at \$language_data['KEYWORDS'][$key][$id]!");
    461                     } else if (!strlen($kw)) {
    462                         report_error(TYPE_ERROR, "Language file contains an empty string entry at \$language_data['KEYWORDS'][$key][$id]!");
    463                     } else if (preg_match('/^([\(\)\{\}\[\]\^=.,:;\-+\*\/%\$\"\'\?]|&[\w#]\w*;)+$/i', $kw)) {
    464                         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!");
    465                     }
    466                 }
    467                 if(count($keywords) != count(array_unique($keywords))) {
    468                     $kw_diffs = array_count_values($keywords);
    469                     foreach($kw_diffs as $kw => $kw_count) {
    470                         if($kw_count > 1) {
    471                             report_error(TYPE_WARNING, "Language file contains per-group duplicate keyword '$kw' in \$language_data['KEYWORDS'][$key]!");
    472                         }
    473                     }
    474                 }
    475             }
    476 
    477             $disallowed_before = "(?<![a-zA-Z0-9\$_\|\#;>|^&";
    478             $disallowed_after = "(?![a-zA-Z0-9_\|%\\-&;";
    479 
    480             foreach($language_data['KEYWORDS'] as $key => $keywords) {
    481                 foreach($language_data['KEYWORDS'] as $key2 => $keywords2) {
    482                     if($key2 <= $key) {
    483                         continue;
    484                     }
    485                     $kw_diffs = array_intersect($keywords, $keywords2);
    486                     foreach($kw_diffs as $kw) {
    487                         if(isset($language_data['PARSER_CONTROL']['KEYWORDS'])) {
    488                             //Check the precondition\post-cindition for the involved keyword groups
    489                             $g1_pre = $disallowed_before;
    490                             $g2_pre = $disallowed_before;
    491                             $g1_post = $disallowed_after;
    492                             $g2_post = $disallowed_after;
    493                             if(isset($language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'])) {
    494                                 $g1_pre = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'];
    495                                 $g2_pre = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'];
    496                             }
    497                             if(isset($language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'])) {
    498                                 $g1_post = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'];
    499                                 $g2_post = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'];
    500                             }
    501 
    502                             if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_BEFORE'])) {
    503                                 $g1_pre = $language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_BEFORE'];
    504                             }
    505                             if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_AFTER'])) {
    506                                 $g1_post = $language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_AFTER'];
    507                             }
    508 
    509                             if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_BEFORE'])) {
    510                                 $g2_pre = $language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_BEFORE'];
    511                             }
    512                             if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_AFTER'])) {
    513                                 $g2_post = $language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_AFTER'];
    514                             }
    515 
    516                             if($g1_pre != $g2_pre || $g1_post != $g2_post) {
    517                                 continue;
    518                             }
    519                         }
    520                         report_error(TYPE_WARNING, "Language file contains cross-group duplicate keyword '$kw' in \$language_data['KEYWORDS'][$key] and \$language_data['KEYWORDS'][$key2]!");
    521                     }
    522                 }
    523             }
    524             foreach($language_data['CASE_SENSITIVE'] as $key => $keywords) {
    525                 if(!isset($language_data['KEYWORDS'][$key]) && $key != GESHI_COMMENTS) {
    526                     report_error(TYPE_WARNING, "Language file contains an superfluous \$language_data['CASE_SENSITIVE'] specification for non-existing keyword group $key!");
    527                 }
    528             }
    529             foreach($language_data['URLS'] as $key => $keywords) {
    530                 if(!isset($language_data['KEYWORDS'][$key])) {
    531                     report_error(TYPE_WARNING, "Language file contains an superfluous \$language_data['URLS'] specification for non-existing keyword group $key!");
    532                 }
    533             }
    534             foreach($language_data['STYLES']['KEYWORDS'] as $key => $keywords) {
    535                 if(!isset($language_data['KEYWORDS'][$key])) {
    536                     report_error(TYPE_WARNING, "Language file contains an superfluous \$language_data['STYLES']['KEYWORDS'] specification for non-existing keyword group $key!");
    537                 }
    538             }
    539 
    540             foreach($language_data['COMMENT_SINGLE'] as $ck => $cv) {
    541                 if(!is_int($ck)) {
    542                     report_error(TYPE_WARNING, "Language file contains an key '$ck' in \$language_data['COMMENT_SINGLE'] that is not integer!");
    543                 }
    544                 if(!is_string($cv)) {
    545                     report_error(TYPE_WARNING, "Language file contains an non-string entry at \$language_data['COMMENT_SINGLE'][$ck]!");
    546                 }
    547                 if(!isset($language_data['STYLES']['COMMENTS'][$ck])) {
    548                     report_error(TYPE_WARNING, "Language file contains no \$language_data['STYLES']['COMMENTS'] specification for comment group $ck!");
    549                 }
    550             }
    551             if(isset($language_data['COMMENT_REGEXP'])) {
    552                 foreach($language_data['COMMENT_REGEXP'] as $ck => $cv) {
    553                     if(!is_int($ck)) {
    554                         report_error(TYPE_WARNING, "Language file contains an key '$ck' in \$language_data['COMMENT_REGEXP'] that is not integer!");
    555                     }
    556                     if(!is_string($cv)) {
    557                         report_error(TYPE_WARNING, "Language file contains an non-string entry at \$language_data['COMMENT_REGEXP'][$ck]!");
    558                     }
    559                     if(!isset($language_data['STYLES']['COMMENTS'][$ck])) {
    560                         report_error(TYPE_WARNING, "Language file contains no \$language_data['STYLES']['COMMENTS'] specification for comment group $ck!");
    561                     }
    562                 }
    563             }
    564             foreach($language_data['STYLES']['COMMENTS'] as $ck => $cv) {
    565                 if($ck != 'MULTI' && !isset($language_data['COMMENT_SINGLE'][$ck]) &&
    566                     !isset($language_data['COMMENT_REGEXP'][$ck])) {
    567                     report_error(TYPE_NOTICE, "Language file contains an superfluous \$language_data['STYLES']['COMMENTS'] specification for Single Line or Regular-Expression Comment key $ck!");
    568                 }
    569             }
    570             if (isset($language_data['STYLES']['STRINGS']['HARD'])) {
    571                 if (empty($language_data['HARDQUOTE'])) {
    572                     report_error(TYPE_NOTICE, "Language file contains superfluous \$language_data['STYLES']['STRINGS'] specification for key 'HARD', but no 'HARDQUOTE's are defined!");
    573                 }
    574                 unset($language_data['STYLES']['STRINGS']['HARD']);
    575             }
    576             foreach($language_data['STYLES']['STRINGS'] as $sk => $sv) {
    577                 if($sk && !isset($language_data['QUOTEMARKS'][$sk])) {
    578                     report_error(TYPE_NOTICE, "Language file contains an superfluous \$language_data['STYLES']['STRINGS'] specification for non-existing quotemark key $sk!");
    579                 }
    580             }
    581 
    582             foreach($language_data['REGEXPS'] as $rk => $rv) {
    583                 if(!is_int($rk)) {
    584                     report_error(TYPE_WARNING, "Language file contains an key '$rk' in \$language_data['REGEXPS'] that is not integer!");
    585                 }
    586                 if(is_string($rv)) {
    587                     //Check for unmasked / in regular expressions ...
    588                     if(empty($rv)) {
    589                         report_error(TYPE_WARNING, "Language file contains an empty regular expression at \$language_data['REGEXPS'][$rk]!");
    590                     } else {
    591                         if(preg_match("/(?<!\\\\)\//s", $rv)) {
    592                             report_error(TYPE_WARNING, "Language file contains a regular expression with an unmasked / character at \$language_data['REGEXPS'][$rk]!");
    593                         } elseif (preg_match("/(?<!<)(\\\\\\\\)*\\\\\|(?!>)/s", $rv)) {
    594                             report_error(TYPE_WARNING, "Language file contains a regular expression with an unescaped match for a pipe character '|' which needs escaping as '&lt;PIPE&gt;' instead at \$language_data['REGEXPS'][$rk]!");
    595                         }
    596                     }
    597                 } elseif(is_array($rv)) {
    598                     if(!isset($rv[GESHI_SEARCH])) {
    599                         report_error(TYPE_ERROR, "Language file contains no GESHI_SEARCH entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
    600                     } elseif(!is_string($rv[GESHI_SEARCH])) {
    601                         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!");
    602                     } else {
    603                         if(preg_match("/(?<!\\\\)\//s", $rv[GESHI_SEARCH])) {
    604                             report_error(TYPE_WARNING, "Language file contains a regular expression with an unmasked / character at \$language_data['REGEXPS'][$rk]!");
    605                         } elseif (preg_match("/(?<!<)(\\\\\\\\)*\\\\\|(?!>)/s", $rv[GESHI_SEARCH])) {
    606                             report_error(TYPE_WARNING, "Language file contains a regular expression with an unescaped match for a pipe character '|' which needs escaping as '&lt;PIPE&gt;' instead at \$language_data['REGEXPS'][$rk]!");
    607                         }
    608                     }
    609                     if(!isset($rv[GESHI_REPLACE])) {
    610                         report_error(TYPE_WARNING, "Language file contains no GESHI_REPLACE entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
    611                     } elseif(!is_string($rv[GESHI_REPLACE])) {
    612                         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!");
    613                     }
    614                     if(!isset($rv[GESHI_MODIFIERS])) {
    615                         report_error(TYPE_WARNING, "Language file contains no GESHI_MODIFIERS entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
    616                     } elseif(!is_string($rv[GESHI_MODIFIERS])) {
    617                         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!");
    618                     }
    619                     if(!isset($rv[GESHI_BEFORE])) {
    620                         report_error(TYPE_WARNING, "Language file contains no GESHI_BEFORE entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
    621                     } elseif(!is_string($rv[GESHI_BEFORE])) {
    622                         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!");
    623                     }
    624                     if(!isset($rv[GESHI_AFTER])) {
    625                         report_error(TYPE_WARNING, "Language file contains no GESHI_AFTER entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
    626                     } elseif(!is_string($rv[GESHI_AFTER])) {
    627                         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!");
    628                     }
    629                 } else {
    630                     report_error(TYPE_WARNING, "Language file contains an non-string and non-array entry at \$language_data['REGEXPS'][$rk]!");
    631                 }
    632                 if(!isset($language_data['STYLES']['REGEXPS'][$rk])) {
    633                     report_error(TYPE_WARNING, "Language file contains no \$language_data['STYLES']['REGEXPS'] specification for regexp group $rk!");
    634                 }
    635             }
    636             foreach($language_data['STYLES']['REGEXPS'] as $rk => $rv) {
    637                 if(!isset($language_data['REGEXPS'][$rk])) {
    638                     report_error(TYPE_NOTICE, "Language file contains an superfluous \$language_data['STYLES']['REGEXPS'] specification for regexp key $rk!");
    639                 }
    640             }
    641 
    642 
    643         }
    644 
    645         output_error_cache();
    646 
    647         flush();
    648 
    649         if($error_abort) {
    650             break;
    651         }
    652     }
    653 }
    654 ?></li>
    655 </ol>
    656 
    657 <p>Validation process completed in <?
    658 $time_end = explode(' ', microtime());
    659 $time_diff = $time_end[0] + $time_end[1] - $time_start[0] - $time_start[1];
    660 
    661 echo sprintf("%.2f", $time_diff);
    662 ?> seconds.</p>
    663 
    664 <div id="footer">GeSHi &copy; 2004-2007 Nigel McNie, 2007-2008 Benny Baumann, released under the GNU GPL</div>
    665 </body>
    666 </html>
    667