#!/usr/bin/perl

# Created by Evgeny Vetrov (2:6037/7)

my $out_error	= 0 if (!defined $out_error);
my $out_format	= 0 if (!defined $out_format);	# 1 - boss; (2 - point; 3 - fakenet)?
my $pntseg	= "r50pnt" if (!defined $pntseg);

my $nlfile	= "/home/vea/fido/spool/NODELIST" if (!defined $nlfile);

sub find_node {
	local($addr)=@_;
	my ($z,$n,$f)=split(/:|\//,$addr);
	open(NL,"<",$nlfile);
	while(<NL>) {
		last if /^Zone,$z/i;
	}
	while(<NL>) {
		last if /^(Region|Host),$n/i;
	}
	if ($f eq "0") {
		return $_;
	}
	while(<NL>) {
		last if /^(Zone|Region|Host),/i;
		if ( /^(Hub|Pvt|Hold|Down)?,$f,/i ) {
			close(NL);
			return $_;
		}
	}
	close(NL);
	return "";
}


sub check_plist {
	local($file,$net,$format,$error)=@_;
	my @valid_speed=(
"300", "1200", "2400", "4800", "9600", "14400", "16800", "19200", "28800", "33600"
);
	my @valid_flags=(
"CM","ICM","MO","LO","MN",
"V22","V29","V32","V32(b|B)","V34","V90(c|C)","V90(s|S)",
"V32T","VFC",
"HST","H14","H16","X2C","X2S","ZYX","Z19","H96","PEP","CSP",
"MNP","V42","V42(b|B)",
"XA","XB","XC","XP","XR","XW","XX",
"T[A-Xa-x]{2}",
"V110L","V110H","V120L","V120H","X75","ISDN",
"(INA|IP|IBN|IFC|IFT|ITN|IVM)(:[A-Za-z1-9\.-_]+)?(:[0-9]+)?",
"(IEM|ITX|IUC|IMI|ISE):[A-Za-z1-9\.-_@]+",
"PING"
);
	my @valid_user_flags=(
"ZEC","REC","NEC","NC","SDS","SMH","RPK","NPK","ENC","CDP","T[A-Xa-x]{2}"
);
	my $in_format = 0;
	my $ret = "";
	my $z = 2, $n = 0, $f = 0;
	open(PLIST,$file);
	while(<PLIST>) {
		my $r = "";
		my $e = "";
		if ($_=~/\A\;(S|U|F|A|E)*([^\r\n]*)/) {
			$ret.=";$1$2\r\n";
		} else {
			my ($kw,$point,$sysname,$location,$name,$phone,$speed,@flags) = split(/,|\r|\n/,$_);
			# check phone string
			if ( !($phone=~/^([0-9-]{3,29}|-Unpublished-)$/) && defined $sysname ) {
				$e .= ";E Phone $phone not correct\r\n" ;
				$phone = "-Unpublished-";
			}
			# check speed string
			my $valid=0;
			foreach $rule(@valid_speed) {
				if ($speed=~/^$rule$/) {
					$valid=1;
					last;
				}
			}
			if ( !$valid && defined $sysname) {
				$e .= ";E Speed $speed not correct\r\n" ;
				$speed = "300";
			}
			# check flags
			my $user=0;
			my @flags_c;
			foreach $flag (@flags) {
				my $valid=0;
				if($user==0) {
					foreach $rule(@valid_flags) {
						if ($flag eq "U") {
							push(@flags_c,$flag);
							$valid=1;
							$user=1;
							last;
						} elsif ($flag=~/^$rule$/) {
							push(@flags_c,$flag);
							$valid=1;
							last;
						}
					}
				} else {
					foreach $rule(@valid_user_flags) {
						if ($flag=~/^$rule$/) {
							push(@flags_c,$flag);
							$valid=1;
							last;
						}
					}
				}
				if ( !$valid && defined $sysname) {
					$e .= ";E Flag $flag not correct\r\n" ;
				}
			}

			if (($in_format==0 || $in_format==1) && $kw=~/^Boss$/i) {
				if ($point =~ /^([0-9]{1,5}):([0-9]{1,5})\/([0-9]{1,5})$/) {
					$in_format=1;
					$z=$1;
					$n=$2;
					$f=$3;
					undef $skip_node;
					$nlstring = find_node("$z:$n/$f");
					if ($net && $n!=$net) {
						$e .= ";E Boss $z:$n/$f not from $net network\r\n";
						$skip_node=1;
					} elsif ($nlstring=~/^(Down|Hold)/i || $nlstring eq '') {
						$e .= ";E Boss $z:$n/$f Hold|Down|Not in Nodelist\r\n";
						$skip_node=1;
					} else {
						$r.= "Boss,$point,";
						if (defined $sysname && defined $location && defined $name && defined $phone && defined $speed) {
							$r.="$sysname,$location,$name,$phone,$speed".((scalar @flag_c)?",". join(",", @flag_c):"");
						}
						$r.="\r\n";
					}
				} else {
					$e .= ";E Wrong Boss Address $point\r\n"
				}
			} elsif (($in_format==0 || $in_format==2) && $kw=~/^(Region|Host)/i) {
				if ($point>0 && $point<65536) {
					$in_format=2;
					$n=$point;
				} else {
					$e.=";E Wrong Net Number: $point\r\n";
				}
			} elsif ($in_format==2 && $kw eq "") {
				if ($point>0 && $point<65536) {
                			$in_format=2;
					undef $skip_node;
					$f=$point;
					$nlstring = find_node("$z:$n/$f");
					if ($net && $n!=$net) {
						$e.=";E Boss $z:$n/$f not from $net network\r\n";
						$skip_node=1;
					} elsif ($nlstring=~/^(Down|Hold)/i || $nlstring eq '') {
						$e.=";E Boss $z:$n/$f Hold|Down|Not in Nodelist\r\n";
						$skip_node=1;
					} else {
						$r.= "Boss,$z:$n/$f,";
						if (defined $sysname && defined $location && defined $name && defined $phone && defined $speed) {
							$r.="$sysname,$location,$name,$phone,$speed".((scalar @flag_c)?",". join(",", @flag_c):"");
						}
						$r.="\r\n";
					}
				} else {
					$e.=";E Wrong Node Number: $point\r\n";
				}
			} elsif ( $_ =~ /^[\r\n]*$/ || $skip_node ) {
				$e="";
				# Пропуск пустых строк или поинтов нод в режимах hold|down|not in nodelist
			} elsif (
				($in_format==1 && ($kw eq '' || $kw=~/^point$/i)) ||
				($in_format==2 && $kw=~/^point$/i )
				) {
				# check point number
				if ( !($point>0 && $point<32768) ) {
					$e.=";E Point $point not correct\r\n" ;
					$point = "65536";
				} else {
					$r.=",$point,$sysname,$location,$name,$phone,$speed".((scalar @flags_c)?",". join(",", @flags_c):"") . "\r\n";
				}
			} else {
				$e.=";E Wrong Line: ".$_;
			}
		}
		if ($format) {
			$ret.=$r;
		}
		if ($error) {
			$ret.=$e;
		} 
		if (!$error && !$format && length($e)>0) {
			close(PLIST);
			return $e;
		}
	}
	close(PLIST);
	return $ret;
}


if( $#ARGV <0 ) {
#    exit;
} else { 
	for (my $i=0; $i<=$#ARGV; $i++) {
		if ($ARGV[$i] eq "-h" || $ARGV[$i] eq "--help") {
			print <<USAGE;
Usage: pntcheck.pl [OPTION] pntseg
Option:
  -h, --help            This usage.
  -n[NET], --net[NET]   Specify net number.
  -e, --error           Output Error.
  -b, --boss            Output Boss format pntlist. (If specify this flag without -e return allways 0)
USAGE
		} elsif ($ARGV[$i]=~/(-n|--net)([0-9]+)/) {
			$net=$2;
		} elsif ($ARGV[$i] eq "-e" || $ARGV[$i] eq "--error") {
			$out_error++;
		} elsif ($ARGV[$i] eq "-b" || $ARGV[$i] eq "--boss") {
			$out_format=1;
		} elsif ($ARGV[$i] =~ /^-.*/) {
			print STDERR "Unknown option: ",$ARGV[$i],"\r\n";
		} else {
			$pntseg=$ARGV[$i];
		}
	}
	if ( -f $pntseg ) {
		my $ret = check_plist($pntseg,$net,$out_format,$out_error);
		if ($out_format || $out_error) {
			print $ret;
		}
		if ($ret =~ /^\;E/g) {
			exit 1;
		}
	} else {
		print STDERR "File $pntseg Not Found\r\n";
		exit 1;
	}
}