#       misc - miscellaneaous functions
#
#	$RCSfile: misc.pl,v $
#	$Revision: 0.45 $
#	$Author: ripe-dbm $
#	$Date: 1995/05/31 12:04:40 $
#

require "defines.pl";

sub trailzero {

    local($quad) = @_;

    if ($quad =~ s/\.0\.0\.0$//) {}
    elsif ($quad =~ s/\.0\.0$//) {}	
    elsif ($quad =~ s/\.0$//) {}

    return $quad;

}
# 
#  A load of silly syntax check subroutines - TB
#
#  isnetnum() - Is is a valid netnumber
#  isdonname() - Is it a valid domainname
#  isname() - Is it a personal name.
#  isphone() - Is is a valid phone or fax format.
#  isemail() -  Is is a valid RFC822 address
#  isasnum() - Is it a valid AS number
#  isaspref() - Is is a valid preference cost
#  isaskeyword() - Is it one of the askeywords (needs to be done somewhat
#                  differently later
#  isasmacro() - Is it a valid as-macro.
#  isclnsprefix() - Is it a CLNS prefix
#  isclnskeyowrd() - Is it one of the CLNS keywords (from Henk S' paper)
#  iscommunity() - got to check it doesn't with a RIPE-81 KEYWORD yuck.
#  ishandle() - check the handle syntax. REMEMBER TO UPDATE the postfix array.
#  ishandser() - check the actual handle serial
#  isnetlist() - Is this a valid netlist
#  ishostaddr() - Is this a valid hostaddress
#  ispeerkeyword() - check list of peer keywords
#
sub isasnum {
    local($str) = @_;
    if($str !~ /^AS[1-9]+\d*$/ ) {
	return 0;
    }
    $str =~ s/AS//;
    if($str =~ /[A-z]+/ ) {
	return 0;
    }
    $str = $str + 0 ;
    if ( $str < 1 || $str > 65535 ) {
	return 0; 
    }
    return 1;
}
#
# HANDLE Postfixes.
#
%POSTFIX = (
	    "INIC", 1,
	    "RIPE", 1,
	    "JPNIC", 1,
	    "AU", 1,
	    "JP", 1,
	    );

sub ishandle {
    local($str) = @_;
    local($serial,$postfix) = "";
    if( $str !~ /^[A-Z][A-Z]/) {
	return 0;
    }
    if ($str !~ /\-/) {
	if (&ishandser($str)) {
	    return 1;
	} else {
	    return 0;
	}
    } 
    if ($str =~ /^RIPE\-(.*)$/ ) {
	return &ishandle($1);
    } else {
	($serial, $postfix) = split(/\-/, $str);
	if(&ishandser($serial) && $POSTFIX{$postfix}) {
	    return 1;
	}
	return 0;
    }
}

sub ishandser {
    local($str) = @_;
    if ($str =~ /^([A-Z][A-Z][A-Z]*)([1-9][0-9]*)*$/) {
	if ((length($1) > 4) || (($2+0) > 9999)) {     # Hardcoded ;-(
	    return 0;
	}
	return 1;
    } else {
	return 0;
    }
}
#
# Current RIPE-81 KEYWORDS
#
%KEYWORD = (
#
# Now gone for RIPE-81++
#
#           "RIPE-DB", 1,
#	    "LOCAL", 1,
	    "ANY", 1,
	    "AND", 1,
	    "NOT", 1,
	    "(", 1,
	    ")", 1,
	    );
sub isaskeyword {
    local($str) = @_;
    if( $str !~ /^\($/ ) {
	$str =~ s/^\(//;
    }
    if ($str !~ /^\)$/ ) {
	$str =~ s/\)$//;
    }
    
    if (&isasnum($str) || ($KEYWORD{$str}) || &iscommunity($str) || 
	&isasmacro($str) || &isnetlist($str)) {
	return 1;
    }
    return 0;
}

sub isasmacro {
    local($str) = @_;
    if ($str =~ /^AS\-[A-Z]+$/) {
	return 1;
    }
    return 0;
}
#
# CLNS KEYWORDS
#
%CLNSWORD = (
	     "ANY", 1, 
	     "AND", 1,
	     "NOT", 1,
	     "(", 1,
	     ")", 1,
	     );
sub isclnskeyword {
    local($str) = @_;
        if( $str !~ /^\($/ ) {
	$str =~ s/^\(//;
    }
    if ($str !~ /^\)$/ ) {
	$str =~ s/\)$//;
    }
    if(&isclnsprefix($str) || ($CLNSWORD{$str})) {
	return 1;
    }
    return 0;
}
#
# Peer KEYWORDS
#
%PEERWORD = (
	     "EGP", 1, 
	     "BGP", 1,
	     "BGP4", 1,
	     "IDRP", 1,
	     "IGP", 1,
	     "HELLO", 1,
	     "IGRP", 1,
	     "EIGRP", 1,
	     "OSPF", 1,
	     "ISIS", 1,
	     "RIP", 1,
	     "RIP2", 1,
	     "OTHER", 1,
	     );
sub ispeerkeyword {
    local($str) = @_;
    return 0 if !$PEERWORD{$str};
    return 1;
}

#
sub isnetlist {
    local($str) = @_;
    local($NET) = "\\d+\\.\\d+\\.\\d+\\.\\d+\\/\\d+";
    return 0 if $str !~ /^\s*{\s*$NET\s*(\s*,\s*$NET\s*)*}\s*$/;
    return 1;
}
#
sub iscommunity {
    local($str) = @_;
    return 0 if $str !~ /[A-Z]+/;
    foreach $_ ((keys %KEYWORD, "AS")) {
	if (($_ eq "(") || ($_ eq ")")) {
	    $_ = "\\".$_;
	}
	if ($str =~ /^$_.*/ ) {
	    return 0;
	}
    }				
    return 1;
}
#
sub isaspref {
    local($str) = @_;
    $str = $str + 0 ;
    if ( $str < 1 ) {
	return 0;
    }
    return 1;
}
#
sub hasdelete {
    local(*entry) = @_;
    return 0 if !defined $entry{"ud"};
    if ($entry{"ud"} eq "") {
	&adderror(*entry, "delete attribute must contain email address and reason for delete");
	return 0;
    }
    return 1;
}
#
sub isnetnum {
    local($str) = @_;
    local($ind) = 0;
#
# check for trailing dot before doing the split
# not nice but needed
#
    return 0 if $str =~ /^.*\.$/;
    local(@add) = split(/\./, $str);
    if ($#add != 3) {
	return 0;
    }
    foreach (@add) {
	if (($_ !~ /^[0-9]+$/) || ($_ > 255) || ($_ < 0)) {
	    return 0;
	}
    }

    if (($add[0] > 223) || ($add[0] == 0)) {
	return 0;
    }
    
    return 1;
}
#
sub isipaddr {
    local($str) = @_;
    local($i) = 0;
    local($net) = "";
    if($str =~ /^(\d+\.\d+\.\d+\.\d+)\/(\d+)$/) {
	$net = $1; 
	local($pref) = $2;
	if($pref != 32) {
	    return 0;
	}
    } else {
	$net = "$str";
    }
    if($net !~ /^(\d+\.\d+\.\d+\.\d+)$/) {
	return 0;
    }
    local(@add) = split(/\./, "$net");

    if ($#add != 3) {
	return 0;
    }
    if($add[0] > 223) {
	return 0;
    }
    foreach $i (0..$#add) {
	$add[$i] +=0;
	if ($add[$i] < 0 || $add[$i] > 255 ) {
	    return 0;
	}
    }
    return 1;
}
sub ismask {
    local($str) = @_;
    local($i) = 0;
    local($net) = "";
    if($str !~ /^(\d+\.\d+\.\d+\.\d+)$/) {
	return 0;
    }
    local(@add) = split(/\./, $str);
    if ($#add != 3) {
	return 0;
    }
    foreach $i (0..$#add) {
	$add[$i] +=0;
	if ($add[$i] < 0 || $add[$i] > 255 ) {
	    return 0;
	}
    }
    return 1;
}
#
sub isclnsprefix {
    local($str) = @_;
    local($i);
    $str =~ tr/A-Z/a-z/;

    return 0 if $str =~ /\.$/;

    local(@parts) = split(/\./, $str);

    return 0 if $parts[0] !~ /^[0-9a-f][0-9a-f]$/;
    return 0 if $parts[1] !~ /^[0-9a-f][0-9a-f][0-9a-f][0-9a-f]$/;
    foreach $i (2..$#parts-1) {
        return 0 if $parts[$i] !~ /^[0-9a-f]+$/;
        return 0 if length($parts[$i]) != 4;
    }
    return 0 if $parts[$#parts] !~ /^[0-9a-f]+$/;
    return 1;
}
#
sub issubdomname {
    local($str) = @_;

    return 1 if
	$str =~ /^[a-zA-Z0-9\-\.\_]*\.*[a-zA-Z0-9-\_]+$/;
    return 0;
}
#
sub isdomname {
    local($str) = @_;
    if ($str !~ /^[a-zA-Z0-9\-\.\_]*\.*[a-zA-Z]+$/) {
	return 0;
    }
    return 1;
}
#
sub isname {
    local($str) = @_;
    if ($str !~ /^[a-zA-Z0-9_\-\.\ \'\|\`]+$/) {
	return 0;
    }
    return 1;
}
#
sub isphone {
    local($str) = @_;
    if ($str !~ /^\+[\d\s-\(\)\[\](ext)(EXT)\.]+$/) {
	return 0;
    }
    return 1;
}
#
sub isemail {
    local($str) = @_;
    local($ok) = 1;
    
    local($localpart, $domainpart) = split(/\@/, $str, 2);

    $localpart =~ s/^\<//;
    $domainpart =~ s/\>$//;
    
    if ($localpart =~ /^"[a-zA-Z0-9\-\.\_\/\=\ %]+"$/) {}
    elsif ($localpart =~ /^[a-zA-Z0-9\-\.\_\/\=%]+$/) {}
    else {return 0;}

    if ($domainpart =~ /^[a-zA-Z0-9\_\-]+(\.[a-zA-Z0-9\_\-]+)+$/) {}
    else {return 0;}

    return 1;
}
#
sub quad2int {
    local($quad) = @_;
    local(@quads);
    local($i, $j, $result);

    @quads = split(/\./, $quad);

    $result = 0;
    for ($i=0; $i<4; $i++) {
	$j = $quads[$i];
	if (!(($j>=0)&&($j<256))) {
	    &syslog("ERRLOG", "quad2int: illegal ip number \"$quad\"");
	    return -1;
	}
	$result += ($j<<(8*(3-$i)));
    }
    return $result;
}
#
sub int2quad {
    local($int) = @_;
    local($i, $j, $result);

    $result = "";
    for ($i=3; $i>=0; $i--) {
	$j = ($int>>($i*8))&0xff;
	$result = $result . "$j.";
    }
    chop($result);
    return $result;
}
sub isbracket {
    local($str) = @_;
    local($BRACKET) = "[^\\(^\\)]*";
    while ($str =~ s/$BRACKET\($BRACKET\)$BRACKET//g) {}
    return 0 if $str =~ /[()]/;
    return 1;
}
sub isbrace {
   local($str) = @_;
   local($BRACE) = "[^\\{^\\}]*";
   while ($str =~ s/$BRACE\{$BRACE\}$BRACE//g) {}
   return 0 if $str =~ /[{}]/;
   return 1;
}
#
# exclusive locking
#
sub lock {

    local($file) = @_;

    flock($file, $LOCK_EX);
}
#
sub unlock {

    local($file) = @_;

    flock($file, $LOCK_UN);
}
1;
