Check the keywords are sane.
359 {
360 foreach ($this->langdata[
'KEYWORDS'] as
$key => $keywords) {
361 if (!isset($this->langdata[
'CASE_SENSITIVE'][
$key])) {
362 $this->
issue(
self::TYPE_ERROR,
"Language file contains no \$language_data['CASE_SENSITIVE'] specification for keyword group $key!");
363 }
364 if (!isset($this->langdata[
'URLS'][
$key])) {
365 $this->
issue(
self::TYPE_ERROR,
"Language file contains no \$language_data['URLS'] specification for keyword group $key!");
366 }
367 if (empty($keywords)) {
368 $this->
issue(
self::TYPE_WARNING,
"Language file contains an empty keyword list in \$language_data['KEYWORDS'] for group $key!");
369 }
370 foreach ($keywords as
$id => $kw) {
371 if (!is_string($kw)) {
372 $this->
issue(
self::TYPE_WARNING,
"Language file contains an non-string entry at \$language_data['KEYWORDS'][$key][$id]!");
373 } elseif (!strlen($kw)) {
374 $this->
issue(
self::TYPE_ERROR,
"Language file contains an empty string entry at \$language_data['KEYWORDS'][$key][$id]!");
375 } elseif (preg_match('/^([\(\)\{\}\[\]\^=.,:;\-+\*\/%\$\"\'\?]|&[\w#]\w*;)+$/i', $kw)) {
376 $this->
issue(
self::TYPE_NOTICE,
"Language file contains an keyword ('$kw') at \$language_data['KEYWORDS'][$key][$id] which seems to be better suited for the symbols section!");
377 }
378 }
379 if (isset($this->langdata[
'CASE_SENSITIVE'][
$key]) && !$this->langdata[
'CASE_SENSITIVE'][
$key]) {
380 array_walk($keywords, array($this, 'strtolower'));
381 }
382 if (count($keywords) != count(array_unique($keywords))) {
383 $kw_diffs = array_count_values($keywords);
384 foreach ($kw_diffs as $kw => $kw_count) {
385 if ($kw_count > 1) {
386 $this->
issue(
self::TYPE_WARNING,
"Language file contains per-group duplicate keyword '$kw' in \$language_data['KEYWORDS'][$key]!");
387 }
388 }
389 }
390 }
391
392 $disallowed_before = '(?<![a-zA-Z0-9\$_\|\#;>|^&';
393 $disallowed_after = '(?![a-zA-Z0-9_\|%\\-&;';
394
395 foreach ($this->langdata[
'KEYWORDS'] as
$key => $keywords) {
396 foreach ($this->langdata['KEYWORDS'] as $key2 => $keywords2) {
398 continue;
399 }
400 $kw_diffs = array_intersect($keywords, $keywords2);
401 foreach ($kw_diffs as $kw) {
402 if (isset($this->langdata['PARSER_CONTROL']['KEYWORDS'])) {
403
404 $g1_pre = $disallowed_before;
405 $g2_pre = $disallowed_before;
406 $g1_post = $disallowed_after;
407 $g2_post = $disallowed_after;
408 if (isset($this->langdata['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'])) {
409 $g1_pre = $this->langdata['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'];
410 $g2_pre = $this->langdata['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'];
411 }
412 if (isset($this->langdata['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'])) {
413 $g1_post = $this->langdata['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'];
414 $g2_post = $this->langdata['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'];
415 }
416
417 if (isset($this->langdata[
'PARSER_CONTROL'][
'KEYWORDS'][
$key][
'DISALLOWED_BEFORE'])) {
418 $g1_pre = $this->langdata[
'PARSER_CONTROL'][
'KEYWORDS'][
$key][
'DISALLOWED_BEFORE'];
419 }
420 if (isset($this->langdata[
'PARSER_CONTROL'][
'KEYWORDS'][
$key][
'DISALLOWED_AFTER'])) {
421 $g1_post = $this->langdata[
'PARSER_CONTROL'][
'KEYWORDS'][
$key][
'DISALLOWED_AFTER'];
422 }
423
424 if (isset($this->langdata['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_BEFORE'])) {
425 $g2_pre = $this->langdata['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_BEFORE'];
426 }
427 if (isset($this->langdata['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_AFTER'])) {
428 $g2_post = $this->langdata['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_AFTER'];
429 }
430
431 if ($g1_pre != $g2_pre || $g1_post != $g2_post) {
432 continue;
433 }
434 }
435 $this->
issue(
self::TYPE_WARNING,
"Language file contains cross-group duplicate keyword '$kw' in \$language_data['KEYWORDS'][$key] and \$language_data['KEYWORDS'][$key2]!");
436 }
437 }
438 }
439 foreach ($this->langdata[
'CASE_SENSITIVE'] as
$key => $keywords) {
441 $this->
issue(
self::TYPE_WARNING,
"Language file contains an superfluous \$language_data['CASE_SENSITIVE'] specification for non-existing keyword group $key!");
442 }
443 }
444 foreach ($this->langdata[
'URLS'] as
$key => $keywords) {
445 if (!isset($this->langdata[
'KEYWORDS'][
$key])) {
446 $this->
issue(
self::TYPE_WARNING,
"Language file contains an superfluous \$language_data['URLS'] specification for non-existing keyword group $key!");
447 }
448 }
449 foreach ($this->langdata[
'STYLES'][
'KEYWORDS'] as
$key => $keywords) {
450 if (!isset($this->langdata[
'KEYWORDS'][
$key])) {
451 $this->
issue(
self::TYPE_WARNING,
"Language file contains an superfluous \$language_data['STYLES']['KEYWORDS'] specification for non-existing keyword group $key!");
452 }
453 }
454
455 foreach ($this->langdata['COMMENT_SINGLE'] as $ck => $cv) {
456 if (!is_int($ck)) {
457 $this->
issue(
self::TYPE_WARNING,
"Language file contains an key '$ck' in \$language_data['COMMENT_SINGLE'] that is not integer!");
458 }
459 if (!is_string($cv)) {
460 $this->
issue(
self::TYPE_WARNING,
"Language file contains an non-string entry at \$language_data['COMMENT_SINGLE'][$ck]!");
461 }
462 if (!isset($this->langdata['STYLES']['COMMENTS'][$ck])) {
463 $this->
issue(
self::TYPE_WARNING,
"Language file contains no \$language_data['STYLES']['COMMENTS'] specification for comment group $ck!");
464 }
465 }
466 if (isset($this->langdata['COMMENT_REGEXP'])) {
467 foreach ($this->langdata['COMMENT_REGEXP'] as $ck => $cv) {
468 if (!is_int($ck)) {
469 $this->
issue(
self::TYPE_WARNING,
"Language file contains an key '$ck' in \$language_data['COMMENT_REGEXP'] that is not integer!");
470 }
471 if (!is_string($cv)) {
472 $this->
issue(
self::TYPE_WARNING,
"Language file contains an non-string entry at \$language_data['COMMENT_REGEXP'][$ck]!");
473 }
474 if (!isset($this->langdata['STYLES']['COMMENTS'][$ck])) {
475 $this->
issue(
self::TYPE_WARNING,
"Language file contains no \$language_data['STYLES']['COMMENTS'] specification for comment group $ck!");
476 }
477 }
478 }
479 foreach ($this->langdata['STYLES']['COMMENTS'] as $ck => $cv) {
480 if ($ck != 'MULTI' && !isset($this->langdata['COMMENT_SINGLE'][$ck]) &&
481 !isset($this->langdata['COMMENT_REGEXP'][$ck])
482 ) {
483 $this->
issue(
self::TYPE_NOTICE,
"Language file contains an superfluous \$language_data['STYLES']['COMMENTS'] specification for Single Line or Regular-Expression Comment key $ck!");
484 }
485 }
486 if (isset($this->langdata['STYLES']['STRINGS']['HARD'])) {
487 if (empty($this->langdata['HARDQUOTE'])) {
488 $this->
issue(
self::TYPE_NOTICE,
"Language file contains superfluous \$language_data['STYLES']['STRINGS'] specification for key 'HARD', but no 'HARDQUOTE's are defined!");
489 }
490 unset($this->langdata['STYLES']['STRINGS']['HARD']);
491 }
492 foreach ($this->langdata['STYLES']['STRINGS'] as $sk => $sv) {
493 if ($sk && !isset($this->langdata['QUOTEMARKS'][$sk])) {
494 $this->
issue(
self::TYPE_NOTICE,
"Language file contains an superfluous \$language_data['STYLES']['STRINGS'] specification for non-existing quotemark key $sk!");
495 }
496 }
497
498 foreach ($this->langdata['REGEXPS'] as $rk => $rv) {
499 if (!is_int($rk)) {
500 $this->
issue(
self::TYPE_WARNING,
"Language file contains an key '$rk' in \$language_data['REGEXPS'] that is not integer!");
501 }
502 if (is_string($rv)) {
503
504 if (empty($rv)) {
505 $this->
issue(
self::TYPE_WARNING,
"Language file contains an empty regular expression at \$language_data['REGEXPS'][$rk]!");
506 } else {
507 if (preg_match("/(?<!\\\\)\//s", $rv)) {
508 $this->
issue(
self::TYPE_WARNING,
"Language file contains a regular expression with an unmasked / character at \$language_data['REGEXPS'][$rk]!");
509 } elseif (preg_match("/(?<!<)(\\\\\\\\)*\\\\\|(?!>)/s", $rv)) {
510 $this->
issue(
self::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]!");
511 }
512 }
513 } elseif (is_array($rv)) {
515 $this->
issue(
self::TYPE_ERROR,
"Language file contains no GESHI_SEARCH entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
517 $this->
issue(
self::TYPE_ERROR,
"Language file contains a GESHI_SEARCH entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
518 } else {
520 $this->
issue(
self::TYPE_WARNING,
"Language file contains a regular expression with an unmasked / character at \$language_data['REGEXPS'][$rk]!");
521 } elseif (preg_match(
"/(?<!<)(\\\\\\\\)*\\\\\|(?!>)/s", $rv[
GESHI_SEARCH])) {
522 $this->
issue(
self::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]!");
523 }
524 }
526 $this->
issue(
self::TYPE_WARNING,
"Language file contains no GESHI_REPLACE entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
528 $this->
issue(
self::TYPE_ERROR,
"Language file contains a GESHI_REPLACE entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
529 }
531 $this->
issue(
self::TYPE_WARNING,
"Language file contains no GESHI_MODIFIERS entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
533 $this->
issue(
self::TYPE_ERROR,
"Language file contains a GESHI_MODIFIERS entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
534 }
536 $this->
issue(
self::TYPE_WARNING,
"Language file contains no GESHI_BEFORE entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
538 $this->
issue(
self::TYPE_ERROR,
"Language file contains a GESHI_BEFORE entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
539 }
541 $this->
issue(
self::TYPE_WARNING,
"Language file contains no GESHI_AFTER entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
543 $this->
issue(
self::TYPE_ERROR,
"Language file contains a GESHI_AFTER entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
544 }
545 } else {
546 $this->
issue(
self::TYPE_WARNING,
"Language file contains an non-string and non-array entry at \$language_data['REGEXPS'][$rk]!");
547 }
548 if (!isset($this->langdata['STYLES']['REGEXPS'][$rk])) {
549 $this->
issue(
self::TYPE_WARNING,
"Language file contains no \$language_data['STYLES']['REGEXPS'] specification for regexp group $rk!");
550 }
551 }
552 foreach ($this->langdata['STYLES']['REGEXPS'] as $rk => $rv) {
553 if (!isset($this->langdata['REGEXPS'][$rk])) {
554 $this->
issue(
self::TYPE_NOTICE,
"Language file contains an superfluous \$language_data['STYLES']['REGEXPS'] specification for regexp key $rk!");
555 }
556 }
557 }
if(!array_key_exists('StateId', $_REQUEST)) $id
const GESHI_BEFORE
The key of the regex array defining what bracket group in a matched search to put before the replacem...
const GESHI_SEARCH
The key of the regex array defining what to search for.
const GESHI_AFTER
The key of the regex array defining what bracket group in a matched search to put after the replaceme...
const GESHI_REPLACE
The key of the regex array defining what bracket group in a matched search to use as a replacement.
const GESHI_COMMENTS
Used in language files to mark comments.
const GESHI_MODIFIERS
The key of the regex array defining any modifiers to the regular expression.