';
}
fclose($handle);
////////////////////////////////////////////////////////////////////////////////
// Check the file at a syntactic level, line-by-line
////////////////////////////////////////////////////////////////////////////////
// Gedcom files are english, left-to-right, whatever the page language
echo '
';
$num_lines=count($gedfile);
// Ignore the Byte-Order-Mark on UTF files
if ($num_lines>0) $gedfile[0]=preg_replace('/^'.WT_UTF8_BOM.'/', '', $gedfile[0]);
$context=array('GEDCOM'); $curr_xref='';
foreach ($gedfile as $num=>$value) {
preg_match('/^(\s*)(\d*)(\s*)(@[^@#]+@)?(\s*)(\S*)(\s?)(.*)/', $value, $match);
$whitespace1=$match[1];
$tag_level =$match[2];
$whitespace2=$match[3];
$xref =$match[4];
$whitespace3=$match[5];
$tag =$match[6];
$whitespace4=$match[7];
$tag_data =$match[8];
// What sort of object would this tag point to
if (isset($XREF_LINK[$tag]))
$linked_rec=$XREF_LINK[$tag];
else
$linked_rec=$tag;
// Work out our current context
$context[$tag_level]=$tag;
$tmp=$context[0];
for ($i=1; $i<=$tag_level; ++$i)
if (isset($context[$i]))
$tmp.=':'.$context[$i];
// No errors initially
$err='';
// Huge nested if/else contruct. Handle with care!
if ($err_level>=$critical) { // CRITICAL CHECKS - links
if ($tag=='')
$err=missing(WT_I18N::translate('tag'));
elseif ($tag_level=='')
$err=missing(WT_I18N::translate('Level'));
elseif (preg_match('/^(@[^#@:!]+@)$/', $tag_data)) { // exclude external/internal XREfs with :/!
if (!isset($all_xrefs[$tag_data.$linked_rec]))
$err=missing("0 $tag_data $linked_rec");
elseif ($tag_level=='1' &&
(($tag=='FAMS' ) && !isset($xref_links[$tag_data.'HUSB'.$curr_xref]) &&
!isset($xref_links[$tag_data.'WIFE'.$curr_xref]) ||
($tag=='FAMC' ) && !isset($xref_links[$tag_data.'CHIL'.$curr_xref]) ||
($tag=='HUSB' || $tag=='WIFE') && !isset($xref_links[$tag_data.'FAMS'.$curr_xref]) ||
($tag=='CHIL' ) && !isset($xref_links[$tag_data.'FAMC'.$curr_xref])
))
$err=no_link(wt_href($XREF_LINK[$tag], $tag_data));
}
if ($err_level>=$error && $err=='') { // ERROR CHECKS - tags
if (!preg_match('/^[1-9]?[0-9]$/', $tag_level))
$err=invalid(WT_I18N::translate('Level'));
elseif (!preg_match('/^[A-Z0-9_]{1,31}$/', $tag))
$err=invalid(WT_I18N::translate('tag'));
elseif (strpos($tmp, '_')===false) {
if (!isset($CONTEXT[$tmp]))
$err=invalid(WT_I18N::translate('tag'));
}
// Check tags at level N+1
$count_plus_one=array();
if ($err=='') {
for ($i=$num+1; $i<$num_lines; ++$i) {
preg_match('/^\s*(\d*)\s*(@[^@#]+@)?\s*(\S*)/', $gedfile[$i], $m);
if ($m[1]<=$tag_level) {
break;
}
if ($m[1]==$tag_level+1) {
if (isset($count_plus_one[$m[3]])) {
$count_plus_one[$m[3]]++;
} else {
$count_plus_one[$m[3]]=1;
}
}
}
}
// Check min/max number of sub-tags at level N+1
if ($err=='') {
foreach ($count_plus_one as $tag_plus_one=>$count_plus1) {
if (isset($CONTEXT[$tmp.':'.$tag_plus_one])) {
if ($count_plus1 > $CONTEXT_MAX[$tmp.':'.$tag_plus_one]) {
$err=too_many($tmp.':'.$tag_plus_one);
} elseif ($count_plus1 < $CONTEXT_MIN[$tmp.':'.$tag_plus_one]) {
$err=too_few($tmp.':'.$tag_plus_one);
}
}
}
}
// Check for missing subordinate tag (ignore custom tags)
if ($err=='' && isset($CONTEXT[$tmp])) {
foreach ($CONTEXT_SUB[$tmp] as $sub_tag=>$full_sub_tag) {
if ($CONTEXT_MIN[$full_sub_tag]>0 && !isset($count_plus_one[$sub_tag])) {
$err=missing($full_sub_tag);
}
}
}
if ($err_level>=$warning && $err=='') { // WARNING CHECKS - data
if ((strpos($tmp, '_')===false) && !preg_match('/^'.$CONTEXT[$tmp].'$/i', $tag_data)) {
$err=invalid(WT_I18N::translate('data'));
} elseif ($tag_level=='0' && $xref!='' && !isset($used_xrefs[$xref.$tag])) {
$err=WT_I18N::translate('Nothing references this record');
}
if ($err_level>=$info && $err=='') { // INFOMATIONAL CHECKS - spacing
if ($whitespace1!='' ||
$whitespace2!=' ' ||
$whitespace3==' ' && $xref=='' ||
$whitespace4==' ' && $tag=='') {
$err=invalid(WT_I18N::translate('spacing'));
}
} // info
} // warning
} // error
} // critical
//////////////////////////////////////////////////////////////////////////////
// Record our current context for error logging and future checks.
//////////////////////////////////////////////////////////////////////////////
if ($tag_level=='0' && $tag!='') {
$curr_xref=$xref;
$curr_l0tag=$tag;
}
//////////////////////////////////////////////////////////////////////////////
// If an error was found, print it in its context
//////////////////////////////////////////////////////////////////////////////
if ($err!='') {
if (isset($last_err_num)) {
if ($num-$last_err_num>2*$context_lines && $context_lines>0)
echo '
';
for ($i=max($num-$context_lines, $last_err_num+$context_lines+1); $i<$num; ++$i)
printf("%07d %s\n", $i+1, $gedfile[$i]);
} else {
echo '';
for ($i=max(0,$num-$context_lines); $i<$num; ++$i)
printf("%07d %s\n", $i+1, $gedfile[$i]);
}
printf("%07d[[%s]] %s; ".WT_I18N::translate('see')." %s\n", $num+1, htmlspecialchars($gedfile[$num]), $err, wt_href($curr_l0tag, $curr_xref));
flush();
$last_err_num=$num;
} else
if (isset($last_err_num) && $num-$last_err_num<=$context_lines)
printf("%07d %s\n", $num+1, $gedfile[$num]);
}
if (isset($last_err_num)) {
echo '';
} else {
echo WT_I18N::translate('No errors found at this level.');
}
echo ' '; // language/direction/alignment
print_footer();