# udpatecheck.pl
#
# Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 1999 by RIPE NCC
#
# All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of the author not be
# used in advertising or publicity pertaining to distribution of the
# software without specific, written prior permission.
#
# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
# AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# $Id: updatecheck.pl,v 2.5 1999/10/06 16:41:24 marek Exp $
#
#	$RCSfile: updatecheck.pl,v $
#	$Revision: 2.5 $
#	$Author: marek $
#	$Date: 1999/10/06 16:41:24 $

require "defines.pl";
require "adderror.pl";
require "notify.pl";
require "maintainer.pl";
require "dbmatch.pl";
require "enread.pl";

# In updatecheck one can do all the checks one wants because one has both
# the old and the new object. All checks in here are VERY RIPE database
# specific.

#
# This routine checks whether a specific object with a certain source
# and type exists. It will return the number of hits. Does NOT work for
# IP addresses. It will also return the first object in the list if 
# $lookup is set

sub ExistsObject {
    local($key, $type, $source, $lookup)=@_;

    local($EXISTOBJECT)="EXISTOBJECT";
    local(%EXISTOBJECT, @EXISTOBJECT);
    
    local(%nothing)=();
    local($matches,$dbfile);

    if ($SPLIT{$source}) {
       $dbfile=$DBFILE{$source}.".".$type;
    }
    else {
       $dbfile=$DBFILE{$source};
    }

    if (&dbopen(*EXISTOBJECT, *nothing, 0, $dbfile)) {
       
       local(%entry);
       local(@matches);
       
       if ($lookup) {
	  ($matches, %entry)=&ExistsEntryInOpenDB(*EXISTOBJECT, $key, $lookup);
       }
       else {
          @matches=&ExistsEntryInOpenDB(*EXISTOBJECT, $key, $lookup);
       }
       
       &dbclose(*EXISTOBJECT);
          
       return ($matches, %entry) if ($lookup);
       
       return (@matches);
       
    }

    return -1;
    
}

sub ExistsObjectInOpenDB {
    local(*EXISTDB, $key, $lookup)=@_;

    local(@keys)=($key);
    local(@matches)=&dbmatch(*EXISTDB,*keys, "", 0);
    
    if ($lookup) {
        
       local(%entry);
       &enread(EXISTDB, *entry, $matches[0]) if (@matches);

       return scalar(@matches), %entry;
    
    }
    else {
	return @matches;
    }
    
}


#
# It is supposed to be like this:
# *oldobject = empty : addition
# *newobject = empty : deletion
# none  = empty : modify

sub updatecheck {
    local(*db, *oldobject, *newobject, $type, $options)=@_;

    return $O_OK if ($options & $NOCHECKSOPTION);
#    &dpr("override option: ", ($options & $OVERRIDEOPTION), "\n");
    local($returncode)=$O_OK;
    
    #
    # don't accept auto updates/deletions of objects that require
    # a maintainer but don't have one in the old object
                
    return $E_NOAUTOUPDATE if ((!($options & $OVERRIDEOPTION)) && 
                               ($OBJMAND{$type}=~ /\bmb\b/) && 
                               (!defined($oldobject{"mb"})) &&
			       (!($options & $NEWOPTION)));

    #
    # If this is a maintainer object, bounce it of to the human mailbox
    # configured in the config and sent them a message explaining this.
    # We use the GENERAL ERROR for this (since that one can add anytext)
    #
    # note: we only add a warning when we are running a test database wit
    #       option -t
    
    if (($type eq "mt") &&
        ($options & $NEWOPTION) &&
        (!($options & $OVERRIDEOPTION))) {

       if ($opt_T) {
	  
	  #    
          # be easy when we are running a test version ;-)
	      
          &addwarning(*newobject,"Maintainer objects cannot be created automatically in");
	  &addwarning(*newobject,"the production database. They would have been");
	  &addwarning(*newobject,"forwarded to \<$HUMAILBOX\> for authorization.");
	  &addwarning(*newobject,"");
	  &addwarning(*newobject,"This security option is disabled in the TEST database ");
	  &addwarning(*newobject,"for your convenience!");
              
       }
       else {
	  
	  #    
          # don't accept automatic creations of maintainers
	      
	  &adderror(*newobject, "maintainer objects cannot be created automatically");
	      
	  if ($NETWORKUPDATE) {
	     &adderror(*newobject, "Please send your E-mail request to <$AUTOBOX>");
	     &adderror(*newobject, "It will then be automatically forwarded to");
	     &adderror(*newobject, "the right mailbox for manual authorization");
	  }
	  else {
	     
	     &adderror(*newobject, "This object has been forwarded to <$HUMAILBOX>");
	     &adderror(*newobject, "for authorisation.");
	     &adderror(*newobject, "No further action from your part is required");
	  
	     if (open (TMPMAIL, ">$TMPDIR/mtfw.$$")) {
	            
	        print TMPMAIL $MTFWHEADER, "\n";
	        print TMPMAIL $MTFWTXT;
	        &enwrite(TMPMAIL,*newobject, 1, 0, 0);
		
	        close(TMPMAIL);
		    
	        system("$MAILCMD < $TMPDIR/mtfw.$$");
	            
	        unlink("$TMPDIR/mtfw.$$");
	         
	     }
	     else {
	        &adderror(*newobject, "!! an error occured, please send object to <$HUMAILBOX> !!");
	        &syslog("ERRLOG", "updatecheck cannot open file to forward maintainer object $newobject{\"mt\"}\n");
	     }

             return $E_GENERAL;

	  }
	   
       }
	
    }

    #
    # Check authorisation by maintainer
    # and handles special (dirty trick) delete case with $newobject in $oldobject

    print STDERR "updatecheck - do authorization (no override)\n" if ($opt_V);
          
    return $E_AUTHFAIL if (!&Maintainer(*oldobject, *newobject, $options, ""));
       
    # And now the hierarchical authorization
    # only for creation right now...
       
    $hierstat = 
	&HierarchicalAuthorization(*db, *oldobject,*newobject, $type, $options);

    if ($hierstat == $O_OK) {
	&NotifyMaintainers(*oldobject, *newobject, "");
	return $returncode;
    }
    else {
	return $E_HIER_AUTHFAIL;
    }

#    return $E_HIER_AUTHFAIL 
#    if ($O_OK != &HierarchicalAuthorization
#	(*db, *oldobject, *newobject, $type, $options));
    
#    return $returncode;
    
}

1;
