# FQDN-alias override
#
# This is the simple interface to the db/fqdnalias file in classical
# aliasing style.
#
# call point:
#    fqdn_neighbour(domain, address, attrvarname)
#        return (((address quad)),((or list)))
#
#
# We check in order following:
#
#   - address existing (in lower-case) in the  fqdnaliases  database
#   - address existing (in lower-case) in the  fqdnroutes   database
#
#   - address existing (in lower-case) in the MAILVAR/fqlists/ -directory
#     in similar manner to those in  MAILVAR/lists/  at the  aliases.cf
#   - owner-*, *-owner, and *-request -relation of the MAILVAR/fqlists/
#     likewise
#
#   - address domain-part existing (@domain) in the  fqdnaliases  database
#   - address domain-part existing (@domain) in the  fqdnroutes   database
#
# We do not support '+'-selectors in similar manner to those that aliases
# processing does!
#

# FQDN-aliases initializations
#
# Relations: fqdnalias


#
# Can externally (at router.cf) disable the fqlists sub-mechanism.
#
if [ -z "$nofqlists" ]; then
    dofqlists=1
fi


provide fqdnaliasdb

#
#  FQDN-aliases, in autoconfigured dbase type
#

if [ -f $MAILVAR/db/fqdnaliases.zmsh ]; then
	. $MAILVAR/db/fqdnaliases.zmsh
else
    if [ -f $MAILVAR/db/fqdnaliases ]; then
	# Need to be updated at boot ?
	if [ ! -f $MAILVAR/db/fqdnaliases$DBEXTtest -o \
	     $MAILVAR/db/fqdnaliases -nt $MAILVAR/db/fqdnaliases$DBEXTtest ]; then
		# Yes, so update!
		$MAILBIN/zmailer newfqdnaliases
	fi
	relation -lmt $DBTYPE -f $MAILVAR/db/fqdnaliases$DBEXT fqdnaliases_1
	fqdnaliases (key, o1, o2, o3, o4, o5, o6, o7, o8, o9) {
	    local a
	    if a="$(fqdnaliases_1 $key $o1 $o2 $o3 $o4 $o5 $o6 $o7 $o8 $o9)"; then
		priv="$(filepriv -M 644 $MAILVAR/db/fqdnaliases$DBEXTtest \
				  $(db owner fqdnaliases_1))" &&
		returns "$a"
	    fi
	    return 1
	}
    else
	fqdnaliases () { return 1 }
    fi
fi

#
# Define an LDAP hook, just in case...
#

if [ -f $MAILVAR/db/fqdnaliasesldap.zmsh ]; then
	. $MAILVAR/db/fqdnaliasesldap.zmsh
else
    if [ -f $MAILVAR/db/fqdnalias.ldap ]; then
	relation -lmt ldap -s 9999 -e 2000 \
		 -f $MAILVAR/db/fqdnalias.ldap fqdnaliasesldap
    else
	fqdnaliasesldap () { return 1 }
    fi
fi

#
# Define an FQDNROUTES hook, just in case...

if [ -f $MAILVAR/db/fqdnroutes.zmsh ]; then
	. $MAILVAR/db/fqdnroutes.zmsh
else
    if [ -f $MAILVAR/db/fqdnroutes ]; then
	# Need to be updated at boot ?
	if [ ! -f $MAILVAR/db/fqdnroutes$DBEXTtest -o \
	     $MAILVAR/db/fqdnroutes -nt $MAILVAR/db/fqdnroutes$DBEXTtest ]; then
		# Yes, so update!
		$MAILBIN/zmailer newfqdnroutes
	fi
	relation -lmt $DBTYPE -f $MAILVAR/db/fqdnroutes$DBEXT fqdnroutes_1
	fqdnroutes (key) {
	  local a
	  if a="$(fqdnroutes_1 $*)"; then
	    priv="$(filepriv -M 644 $MAILVAR/db/fqdnroutes$DBEXTtest \
			$(db owner fqdnroutes_1))" &&
	    returns "$a"
	  fi
	  return 1
	}
    else
	fqdnroutes () { return 1 }
    fi
fi


# a=$(fqdnroutes_neighbour "$lcaddress" "$user" "" "$athost" $domain $A) && return $a


fqdnroutes_neighbour (key, user, plustail, athost, domain, A) {
	local tmp

#
# The percent-substitutions are supported at these datatabases.
#   %0   =  used lookup key
#   %1   =  user (sans possible "+tail")
#   %2   =  possible "+tail"
#   %3   =  athost ("@domain")
#   %4   =  domain ("domain")  (possible dummy..)
#   %5   =  address  -  the full original address
#

	# Gets 'address' from callers variables

	# We have Alternate default-lookup for cases of locally generated
	# ERROR MESSAGES -- for case where the dot (.) leads to error!
	# and we want to reply with DIFFERENT address, thus:  '.:ERROR' key.

	$(iserrormsg) &&
		tmp=$(fqdnroutes "$key" -: '.:ERROR' -- "$user" "$plustail" \
				 "$athost" "$domain" "$address") &&
			tmp=$(fqdnroutes_spec "$tmp" "$address" $A) &&
				returns $tmp

	tmp="$(get $A type)"
	tmp=$(fqdnroutes "$key" -: ".:$tmp" -: '.' -- "$user" "$plustail" \
			 "$athost" "$domain" "$address") &&
		tmp=$(fqdnroutes_spec "$tmp" "$address" $A) &&
			returns $tmp

#| The fqdnroutes_spec function interprets the return value from the
#| fqdnroutes  lookup.

	return 1
}


fqdnroutes_spec (rtedata, address, A) {
	local tmp channel rscshost

	ssift "$rtedata" in
	ERROR
		break
		;;
	ignore!.*
		break
		;;

	error!(.+)
		returns (((error "\1" "$address" $A)))
		;;

	(smtpgw.*)!
		tmp="\1"
		tsift "$address" in
		(.*)@(.+)
			returns ((("$tmp" "\1" "$address" $A)))
			;;
		tfist
		;;
	(smtp.*)!
		tmp="\1"
		tsift "$address" in
		(.*)@(.+)
			returns ((("$tmp" "\2" "$address" $A)))
			;;
		tfist
		;;
	dns!
		tsift "$address" in
		(.*)@(.+)
			returns (((smtp "\2" "$address" $A)))
			;;
		tfist
		;;
	(.+)!
		# "CHANNEL!"  cases
		returns ((("\1" - "$address" $A)))
		;;

	lotusgw!(.+)!(.+)
		# Map user@domain to user%gwdom@gateway
		tmp="\1"; channel="\2" # Variable name reuse..
		tsift "$address" in
		(.+)@(.+)
			returns (((smtp "$channel" "\1%$tmp@$channel" $A)))
			;;
		tfist
		;;

#	delay!(.+)
#		# NB! envelopeinfo *must* also be defined in interactive mode
#		tmp="$(/bin/expr $(get envelopeinfo now) + "\1")"
#		returns (((hold "$tmp" "$address" $A))) ;;

	([^!]+)!([^!]+)
		# "CHANNEL!HOST"  type cases
		returns ((("\1" "\2" "$address" $A))) ;;

	([^!]+)!([^!]+)!(.*)
		# "CHANNEL!HOST!MORE"  type cases
		returns ((("\1" "\2" "\3" $A))) ;;


#	(.+)!(.+)
#		# "CHANNEL!HOST!MORE..."  type cases
#		# BEWARE LOOPS
#		tmp=$(rrouter "\2!$(uucproute "$address")" "$address" $A "" "$rtedata") && \
#			returns $tmp
#		return $tmp # error code return
#		;;

	tfiss
	return 1 # error code return
}





require fqdnaliasdb
provide fqdnalias

fqdn_neighbour (domain, address, A) {
	# "domain" is dummy..
	local lcaddress key l a priv nattr user u1 athost
	local plustail

	lcaddress="$(recase -l -- "$address")"
	key="$lcaddress"

	plustail=""

	tsift "$lcaddress" in
	@(.*):(.+)@(.+)
		return 1   # Source route
		;;
	(.+)@(.+)
		user="\1"
		athost="@\2"
		break
		;;
	.*
		return 1 # Not in  uu@hh  form!
		;;
	tfist

	# It may be a "sender" address!

	case "$(get $A type)" in
	sender)
		if $(didexpand userdbmailname) && 
		   a="$(userdb "$lcaddress:mailname" -- "$user")" ; then

		  db add expansions "$key.userdbmailname" 1
		  nattr=$(newattribute $A privilege $priv)
		  $(zapDSNnotify $nattr) ## FIXME!FIXME!
		  if a=$(echo -- "$a" |				\
		      listexpand -c "$a sender fqdn userdb mailname" \
				 -e root -N -			 	\
				$nattr "sender-fqdn-userdb-mailname"	\
					"$address" "$plustail" "$athost")
		  then
		    postzapDSNnotify a
		    returns $a
		  fi
		  return $a # error code return
		fi
		return 1
		;;
	esac


	# For a recipient address we may do a FQDN-aliasing
	# We are better NOT to have aliasing loops here, though
	# we do expansion recursion pruning by falling thru to
	# normal target address locality testing, and such...

	# Already expanded ?  If yes, go away!
	#if [ -n "$(expansions "$lcaddress")" ] ; then
	#	return 1
	#fi

	#   Yes, add to the expansions.  Success ?
	#     Yes, Any success with filepriv from the alias db ?
	#       Yes, generate new privilege attribute for it. Success ?
	#         Yes, do the expansion! (echo .. | listexpand ...)
	#

	# key="$lcaddress"
	if $(didexpand fqdnaliases) ; then
	  if a="$(fqdnaliases "$lcaddress" -- "$user")" ; then
		db add expansions "$key.fqdnaliases" 1
		nattr=$(newattribute $A privilege $priv)
		$(zapDSNnotify $nattr) ## FIXME!FIXME!
		if a=$(echo -- "$a" |					\
		       listexpand -c "$a fqdn alias expansion" 		\
				-e root -N -	 			\
				$nattr "fqdnalias" "$address"		\
				"$plustail" "$athost")
		then
		  postzapDSNnotify a
		  returns $a
		fi
		return $a # error code return
	  fi
	else
	  # DID EXPAND !
	  returns (((bitbucket "duplicate-$key.fqdnaliases"  "$address" $A)))
	fi

	if $(didexpand fqdnaliasesldap); then
	  if a="$(fqdnaliasesldap "$lcaddress" -- "$user")" ; then
		db add expansions "$key.fqdnaliasesldap" 1
		nattr=$(newattribute $A privilege $nobodypriv)
		$(zapDSNnotify $nattr) ## FIXME!FIXME!
		if a=$(echo -- "$a" |					\
		       listexpand -c "$a fqdn ldap expansion" 		\
				-e root -N -				\
				$nattr "fqdnalias" "$address"		\
				"$plustail" "$athost")
		then
		  postzapDSNnotify a
		  returns $a
		fi
		return $a # error code return
	  fi
	else
	  # DID EXPAND !
	  returns (((bitbucket "duplicate-$key.fqdnaliasesldap"  "$address" $A)))
	fi


	a=$(fqdnroutes_neighbour "$lcaddress" "$user" "" "$athost" $domain $A) && returns $a

	# Didn't match,

	# Plusfull usernames ??

	u1="$user"
	ssift "$u1" in # Just in case:  user--.*
	(.+)--(.*)
	    u1="\1+\2"
	    ;;
	tfiss

	ssift "$u1" in
	([^+]+)\+(.*)
	    local u2 pl2
	    u2="\1"
	    pl2="+\2"
	    key="$u2$athost"

	    if $(didexpand fqdnaliases) ; then
	      if a="$(fqdnaliases "$key")" ; then
		db add expansions "$key.fqdnaliases" 1
		nattr=$(newattribute $A privilege $priv)
		$(zapDSNnotify $nattr) ## FIXME!FIXME!
		if a=$(echo -- "$a" |					\
		       listexpand -c "$a fqdn+ alias expansion" 	\
				-e root -N -		 		\
				$nattr "fqdnalias" "$address"		\
				"$pl2" "$athost")
		then
		  postzapDSNnotify a
		  returns $a
		fi
		return $a # error code return
	      fi
	    else
	      # DID EXPAND !
	      return (((bitbucket "duplicate-$key.fqdnaliases" "$address" $A)))
	    fi

	    if $(didexpand fqdnaliasesldap) ; then
	      if a="$(fqdnaliasesldap "$key" -- "$user")" ; then
		db add expansions "$key.fqdnaliasesldap" 1
		nattr=$(newattribute $A privilege $nobodypriv)
		$(zapDSNnotify $nattr) ## FIXME!FIXME!
		if a=$(echo -- "$a" |					\
			 listexpand	-c "$a fqdn+ ldap expansion" 	\
					-e root -N -		 	\
					$nattr "fqdnalias" "$address"	\
					"$plustail" "$athost")
		then
		  postzapDSNnotify a
		  returns $a
		fi
		return $a # error code return
	      fi
	    else
	      # DID EXPAND !
	      returns (((bitbucket "duplicate-$key.fqdnaliasesldap" "$address" $A)))
	    fi

	    a=$(fqdnroutes_neighbour "$key" "$u2" "$pl2" "$athost" $domain $A) && returns $a

	    ;;
	tfiss

	# Didn't match,

	priv=$(get $A privilege)

	if [ -n "$dofqlists" ]; then

	    # Do we have a file with that name ?
	    a="$MAILVAR/fqlists/$lcaddress"
	    key="$lcaddress"
	    l="$preowner$user$postowner$athost"
	    nattr=()
	    if $(didexpand fqlists); then
		if [ -f "$a" ] ; then
		    db add expansions "$key.fqlists" 1
		    priv=$(getpriv "644" $priv "$a" maillist)
		    nattr=$(newattribute $A privilege $priv sender "$l")
		    $(zapDSNnotify $nattr) ## FIXME!FIXME!
		    a=$(runas $priv cat "$a" |				\
			listexpand	-E "$l" -e "$l" -p $priv	\
					-c "$a file expansion" $nattr	\
					"$a" "$user$athost" "$plustail"	\
					"$athost") &&
			returns $a
		    return $a # error code return
		fi
	    else
		# DID EXPAND !
		returns (((bitbucket "duplicate-$key.fqlists" "$address" $A)))
	    fi

	    # Ok, if the list (MAILVAR/fqlists/user@host) did exist, we did
	    # process it's expansion above.  See if we are looking for *-owner,
	    # owner-*, or *-request of same lists.

	    ssift "$user" in
	    (.+)-owner
		a="$MAILVAR/fqlists/\1$athost"
		key="\1$athost"
		if $(didexpand fqlistowner); then
		  if [ -f "$a" ]; then
		    db add expansions "$key.fqlistowner" 1
		    nattr=$(newattribute $A privilege $nobodypriv)
		    $(zapDSNnotify $nattr) ## FIXME!FIXME!
		    a=$(rrouter "$(uid2login $(filepriv -M 664 "$a"))" \
				"$address" $nattr "" "" "$domain") &&
			returns $a
		    return $a # error code return
		  fi
		else
		  # DID EXPAND !
		  returns (((bitbucket "duplicate-$key.fqlists-owner" \
			   "$address" $A)))
		fi
		break
		;;
	    (.+)-request
		a="$MAILVAR/fqlists/\1$athost"
		key="\1$athost"
		if $(didexpand fqlistrequest); then
		  if [ -f "$a" ] ; then
		    db add expansions "$key.fqlistrequest" 1
		    nattr=$(newattribute $A privilege $nobodypriv)
		    $(zapDSNnotify $nattr) ## FIXME!FIXME!
		    a=$(rrouter "$(uid2login $(filepriv -M 664 "$a"))" \
				"$address" $nattr "" "" "$domain") &&
			returns $a
		    return $a # error code return
		  fi
		else
		  # DID EXPAND !
		  returns (((bitbucket "duplicate-$key.fqlists-request" "$address" $A)))
		fi
		break
		;;
	    owner-(.+)
		a="$MAILVAR/fqlists/\1$athost"
		key="\1$athost"
		if $(didexpand ownerfqlists); then
		  if [ -f "$a" ] ; then
		    db add expansions "$key.ownerfqlists" 1
		    nattr=$(newattribute $A privilege $nobodypriv)
		    $(zapDSNnotify $nattr) ## FIXME!FIXME!
		    a=$(rrouter "$(uid2login $(filepriv -M 664 "$a"))" \
				"$address" $nattr "" "" "$domain") &&
			returns $a
		    return $a # error code return
		  fi
		else
		  # DID EXPAND !
		  returns (((bitbucket "duplicate-$key.owner-fqlists" "$address" $A)))
		fi
		;;
	    tfiss

	fi
	###  end of  if [ -n "$dofqlists" ]


	# We may also match for:  "@domain.name"

	#   Yes, add to the expansions.  Success ?
	#     Yes, Any success with filepriv from the alias db ?
	#       Yes, generate new privilege attribute for it. Success ?
	#         Yes, do the expansion! (echo .. | listexpand ...)
	#
	key="$athost"
	if $(didexpand fqdnaliases) ; then
	  if a="$(fqdnaliases "$key" -- "$user")" ; then
		db add expansions "$key.fqdnaliases" 1
		nattr=$(newattribute $A privilege $priv) &&
		$(zapDSNnotify $nattr) ## FIXME!FIXME!
		if a=$(echo -- "$a" |					\
		       listexpand	-c "$a fqdn alias expansion" 	\
					-e root -N -		 	\
					$nattr "fqdnalias" "$address"	\
					"$plustail" "$athost")
		then
		  postzapDSNnotify a
		  returns $a
		fi
		return $a # error code return
	  fi
	else
	  # DID EXPAND !
	  returns (((bitbucket "duplicate-$key.fqdnaliases" "$address" $A)))
	fi
	if $(didexpand fqdnaliasesldap) ; then
	  if a="$(fqdnaliasesldap "$key" -- "$user")" ; then
		db add expansions "$key.fqdnaliasesldap" 1
		nattr=$(newattribute $A privilege $nobodypriv) &&
		$(zapDSNnotify $nattr) ## FIXME!FIXME!
		if a=$(echo -- "$a" |					\
		       listexpand -c "$a fqdn ldap expansion" 		\
				  -e root -N -			 	\
				$nattr "fqdnalias" "$address"		\
				"$plustail" "$athost")
		then
		  postzapDSNnotify a
		  returns $a
		fi
		return $a # error code return
	  fi
	else
	  # DID EXPAND !
	  returns (((bitbucket "duplicate-$key.fqdnaliasesldap" "$address" $A)))
	fi

	a=$(fqdnroutes_neighbour "$key" "$user" "" "$athost" $domain $A) && returns $a

	return 1
}
