⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expn.pl

📁 < linux网络编程工具>>配套源码
💻 PL
📖 第 1 页 / 共 3 页
字号:
}
#
# This routine is used only within &giveup.  It checks to
# see if we really have to giveup or if there is a second
# chance because we did something before that can be 
# backtracked.
#
# %fallback{"$user *** $host"} tracks what is able to fallback
# %fellback{"$user *** $host"} tracks what has fallen back
#
# If there is a valid backtrack, then queue up the new possibility
#
sub try_fallback
{
	local($method,$user,*host,*fall_table,*fellback) = @_;
	local($us,$fallhost,$oldhost,$ft,$i);

	if ($debug > 8) {
		print "Fallback table $method:\n";
		for $i (sort keys %fall_table) {
			print "\t'$i'\t\t'$fall_table{$i}'\n";
		}
		print "Fellback table $method:\n";
		for $i (sort keys %fellback) {
			print "\t'$i'\t\t'$fellback{$i}'\n";
		}
		print "U: $user H: $host\n";
	}
	
	$us = "$user *** $host";
	if (defined $fellback{$us}) {
		#
		# Undo a previous fallback so that we can try again
		# Nested fallbacks are avoided because they could
		# lead to infinite loops
		#
		$fallhost = $fellback{$us};
		print "Already $method fell back from $us -> \n" if $debug;
		$us = "$user *** $fallhost";
		$oldhost = $fallhost;
	} elsif (($method eq 'mx') && (defined $mxbacktrace{$us}) && (defined $mx_secondary{$mxbacktrace{$us}})) {
		print "Fallback an MX expansion $us -> \n" if $debug;
		$oldhost = $mxbacktrace{$us};
	} else {
		print "Oldhost($host, $us) = " if $debug;
		$oldhost = $host;
	}
	print "$oldhost\n" if $debug;
	if (((defined $fall_table{$us}) && ($ft = $us)) || ((defined $fall_table{$oldhost}) && ($ft = $oldhost))) {
		print "$method Fallback = ".$fall_table{$ft}."\n" if $debug;
		local(@so,$newhost);
		@so = split(' ',$fall_table{$ft});
		$newhost = shift(@so);
		print "Falling back ($method) $us -> $newhost (from $oldhost)\n" if $debug;
		if ($method eq 'mx') {
			if (! defined ($mxbacktrace{"$user *** $newhost"})) {
				if (defined $mxbacktrace{"$user *** $oldhost"}) {
					print "resetting oldhost $oldhost to the original: " if $debug;
					$oldhost = $mxbacktrace{"$user *** $oldhost"};
					print "$oldhost\n" if $debug;
				}
				$mxbacktrace{"$user *** $newhost"} = $oldhost;
				print "mxbacktrace $user *** $newhost -> $oldhost\n" if $debug;
			}
			$mx{&trhost($oldhost)} = $newhost;
		} else {
			$temporary_redirect{$us} = $newhost;
		}
		if (@so) {
			print "Can still $method  $us: @so\n" if $debug;
			$fall_table{$ft} = join(' ',@so);
		} else {
			print "No more fallbacks for $us\n" if $debug;
			delete $fall_table{$ft};
		}
		if (defined $create_host_backtrack{$us}) {
			$create_host_backtrack{"$user *** $newhost"} 
				= $create_host_backtrack{$us};
		}
		$fellback{"$user *** $newhost"} = $oldhost;
		&expn($newhost,$user,$names{$us},$level{$us});
		return 1;
	}
	delete $temporary_redirect{$us};
	$host = $oldhost;
	return 0;
}
# return 1 if you could send mail to the address as is.
sub validAddr
{
	local($addr) = @_;
	$res = &do_validAddr($addr);
	print "validAddr($addr) = $res\n" if $debug;
	$res;
}
sub do_validAddr
{
	local($addr) = @_;
	local($urx) = "[-A-Za-z_.0-9+]+";

	# \u
	return 0 if ($addr =~ /^\\/);
	# ?@h
	return 1 if ($addr =~ /.\@$urx$/);
	# @h:?
	return 1 if ($addr =~ /^\@$urx\:./);
	# h!u
	return 1 if ($addr =~ /^$urx!./);
	# u
	return 1 if ($addr =~ /^$urx$/);
	# ?
	print "validAddr($addr) = ???\n" if $debug;
	return 0;
}
# Some systems use expn and vrfy interchangeably.  Some only
# implement one or the other.  Some check expn against mailing
# lists and vrfy against users.  It doesn't appear to be
# consistent.
#
# So, what do we do?  We try everything!
#
#
# Ranking of result codes: good: 250, 251/551, 252, 550, anything else
#
# Ranking of inputs: best: user@host.domain, okay: user
#
# Return value: $error_string, @responses_from_server
sub expn_vrfy
{
	local($u,$server) = @_;
	local(@c) = ('expn', 'vrfy');
	local(@try_u) = $u;
	local(@ret,$code);

	if (($u =~ /(.+)@(.+)/) && (&trhost($2) eq &trhost($server))) {
		push(@try_u,$1);
	}

	TRY:
	for $c (@c) {
		for $try_u (@try_u) {
			&alarm("${c}'ing $try_u on $server",'',$u);
			&ps("$c $try_u");
			alarm(0);
			$s = <$S>;
			if ($s eq '') {
				return "$server: lost connection";
			}
			if ($s !~ /^(\d+)([- ])/) {
				return "$server: garbled reply to '$c $try_u'";
			}
			if ($1 == 250) {
				$code = 250;
				@ret = ("",$s);
				push(@ret,&read_response($2,$debug));
				return (@ret);
			} 
			if ($1 == 551 || $1 == 251) {
				$code = $1;
				@ret = ("",$s);
				push(@ret,&read_response($2,$debug));
				next;
			}
			if ($1 == 252 && ($code == 0 || $code == 550)) {
				$code = 252;
				@ret = ("",$s);
				push(@ret,&read_response($2,$watch));
				next;
			}
			if ($1 == 550 && $code == 0) {
				$code = 550;
				@ret = ("",$s);
				push(@ret,&read_response($2,$watch));
				next;
			}
			&read_response($2,$watch);
		}
	}
	return "$server: expn/vrfy not implemented" unless @ret;
	return @ret;
}
# sometimes the old parse routine (now parse2) didn't
# reject funky addresses. 
sub parse
{
	local($oldaddr,$server,$oldname,$one_to_one) = @_;
	local($newhost, $newaddr, $newname, $um) =  &parse2($oldaddr,$server,$oldname,$one_to_one);
	if ($newaddr =~ m,^["/],) {
		return (undef, $oldaddr, $newname) if $valid;
		return (undef, $um, $newname);
	}
	return ($newhost, $newaddr, $newname);
}

# returns ($new_smtp_server,$new_address,$new_name)
# given a response from a SMTP server ($newaddr), the 
# current host ($server), the old "name" and a flag that
# indicates if it is being called during the initial 
# command line parsing ($parsing_args)
sub parse2
{
	local($newaddr,$context_host,$old_name,$parsing_args) = @_;
	local(@names) = $old_name;
	local($urx) = "[-A-Za-z_.0-9+]+";
	local($unmangle);

	#
	# first, separate out the address part.
	#

	#
	# [NAME] <ADDR [(NAME)]>
	# [NAME] <[(NAME)] ADDR
	# ADDR [(NAME)]
	# (NAME) ADDR
	# [(NAME)] <ADDR>
	#
	if ($newaddr =~ /^\<(.*)\>$/) {
		print "<A:$1>\n" if $debug;
		($newaddr) = &trim($1);
		print "na = $newaddr\n" if $debug;
	}
	if ($newaddr =~ /^([^\<\>]*)\<([^\<\>]*)\>([^\<\>]*)$/) {
		# address has a < > pair in it.
		print "N:$1 <A:$2> N:$3\n" if $debug;
		($newaddr) = &trim($2);
		unshift(@names, &trim($3,$1));
		print "na = $newaddr\n" if $debug;
	}
	if ($newaddr =~ /^([^\(\)]*)\(([^\(\)]*)\)([^\(\)]*)$/) {
		# address has a ( ) pair in it.
		print "A:$1 (N:$2) A:$3\n" if $debug;
		unshift(@names,&trim($2));
		local($f,$l) = (&trim($1),&trim($3));
		if (($f && $l) || !($f || $l)) {
			# address looks like:
			# foo (bar) baz  or (bar)
			# not allowed!
			print STDERR "Could not parse $newaddr\n" if $vw;
			return(undef,$newaddr,&firstname(@names));
		}
		$newaddr = $f if $f;
		$newaddr = $l if $l;
		print "newaddr now = $newaddr\n" if $debug;
	}
	#
	# @foo:bar
	# j%k@l
	# a@b
	# b!a
	# a
	#
	$unmangle = $newaddr;
	if ($newaddr =~ /^\@($urx)\:(.+)$/) {
		print "(\@:)" if $debug;
		# this is a bit of a cheat, but it seems necessary
		return (&domainify($1,$context_host,$2),$2,&firstname(@names),$unmangle);
	}
	if ($newaddr =~ /^(.+)\@($urx)$/) {
		print "(\@)" if $debug;
		return (&domainify($2,$context_host,$newaddr),$newaddr,&firstname(@names),$unmangle);
	}
	if ($parsing_args) {
		if ($newaddr =~ /^($urx)\!(.+)$/) {
			return (&domainify($1,$context_host,$newaddr),$newaddr,&firstname(@names),$unmangle);
		}
		if ($newaddr =~ /^($urx)$/) {
			return ($context_host,$newaddr,&firstname(@names),$unmangle);
		}
		print STDERR "Could not parse $newaddr\n";
	}
	print "(?)" if $debug;
	return(undef,$newaddr,&firstname(@names),$unmangle);
}
# return $u (@$server) unless $u includes reference to $server
sub compact
{
	local($u, $server) = @_;
	local($se) = $server;
	local($sp);
	$se =~ s/(\W)/\\$1/g;
	$sp = " (\@$server)";
	if ($u !~ /$se/i) {
		return "$u$sp";
	}
	return $u;
}
# remove empty (spaces don't count) members from an array
sub trim
{
	local(@v) = @_;
	local($v,@r);
	for $v (@v) {
		$v =~ s/^\s+//;
		$v =~ s/\s+$//;
		push(@r,$v) if ($v =~ /\S/);
	}
	return(@r);
}
# using the host part of an address, and the server name, add the
# servers' domain to the address if it doesn't already have a 
# domain.  Since this sometimes fails, save a back reference so
# it can be unrolled.
sub domainify
{
	local($host,$domain_host,$u) = @_;
	local($domain,$newhost);

	# cut of trailing dots 
	$host =~ s/\.$//;
	$domain_host =~ s/\.$//;

	if ($domain_host !~ /\./) {
		#
		# domain host isn't, keep $host whatever it is
		#
		print "domainify($host,$domain_host) = $host\n" if $debug;
		return $host;
	}

	# 
	# There are several weird situtations that need to be 
	# accounted for.  They have to do with domain relay hosts.
	#
	# Examples: 
	#	host		server		"right answer"
	#	
	#	shiva.cs	cs.berkeley.edu	shiva.cs.berkeley.edu
	#	shiva		cs.berkeley.edu	shiva.cs.berekley.edu
	#	cumulus		reed.edu	@reed.edu:cumulus.uucp
	# 	tiberius	tc.cornell.edu	tiberius.tc.cornell.edu
	#
	# The first try must always be to cut the domain part out of 
	# the server and tack it onto the host.
	#
	# A reasonable second try is to tack the whole server part onto
	# the host and for each possible repeated element, eliminate 
	# just that part.
	#
	# These extra "guesses" get put into the %domainify_fallback
	# array.  They will be used to give addresses a second chance
	# in the &giveup routine
	#

	local(%fallback);

	local($long); 
	$long = "$host $domain_host";
	$long =~ tr/A-Z/a-z/;
	print "long = $long\n" if $debug;
	if ($long =~ s/^([^ ]+\.)([^ ]+) \2(\.[^ ]+\.[^ ]+)/$1$2$3/) {
		# matches shiva.cs cs.berkeley.edu and returns shiva.cs.berkeley.edu
		print "condensed fallback $host $domain_host -> $long\n" if $debug;
		$fallback{$long} = 9;
	}

	local($fh);
	$fh = $domain_host;
	while ($fh =~ /\./) {
		print "FALLBACK $host.$fh = 1\n" if $debug > 7;
		$fallback{"$host.$fh"} = 1;
		$fh =~ s/^[^\.]+\.//;
	}

	$fallback{"$host.$domain_host"} = 2;

	($domain = $domain_host) =~ s/^[^\.]+//;
	$fallback{"$host$domain"} = 6
		if ($domain =~ /\./);

	if ($host =~ /\./) {
		#
		# Host is already okay, but let's look for multiple
		# interpretations
		#
		print "domainify($host,$domain_host) = $host\n" if $debug;
		delete $fallback{$host};
		$domainify_fallback{"$u *** $host"} = join(' ',sort {$fallback{$b} <=> $fallback{$a};} keys %fallback) if %fallback;
		return $host;
	}

	$domain = ".$domain_host"
		if ($domain !~ /\..*\./);
	$newhost = "$host$domain";

	$create_host_backtrack{"$u *** $newhost"} = $domain_host;
	print "domainify($host,$domain_host) = $newhost\n" if $debug;
	delete $fallback{$newhost};
	$domainify_fallback{"$u *** $newhost"} = join(' ',sort {$fallback{$b} <=> $fallback{$a};} keys %fallback) if %fallback;
	if ($debug) {
		print "fallback = ";
		print $domainify_fallback{"$u *** $newhost"} 
			if defined($domainify_fallback{"$u *** $newhost"});
		print "\n";
	}
	return $newhost;
}
# return the first non-empty element of an array
sub firstname
{
	local(@names) = @_;
	local($n);
	while(@names) {
		$n = shift(@names);
		return $n if $n =~ /\S/;
	}
	return undef;
}
# queue up more addresses to expand
sub expn
{
	local($host,$addr,$name,$level) = @_;
	if ($host) {
		$host = &trhost($host);

		if (($debug > 3) || (defined $giveup{$host})) {
			unshift(@hosts,$host) unless $users{$host};
		} else {
			push(@hosts,$host) unless $users{$host};
		}
		$users{$host} .= " $addr";
		$names{"$addr *** $host"} = $name;
		$level{"$addr *** $host"} = $level + 1;
		print "expn($host,$addr,$name)\n" if $debug;
		return "\t$addr\n";
	} else {
		return &final($addr,'NONE',$name);
	}
}
# compute the numerical average value of an array
sub average
{
	local(@e) = @_;
	return 0 unless @e;
	local($e,$sum);
	for $e (@e) {
		$sum += $e;
	}
	$sum / @e;
}
# print to the server (also to stdout, if -w)
sub ps
{
	local($p) = @_;
	print ">>> $p\n" if $watch;
	print $S "$p\n";
}
# return case-adjusted name for a host (for comparison purposes)
sub trhost 
{
	# treat foo.bar as an alias for Foo.BAR
	local($host) = @_;
	local($trhost) = $host;
	$trhost =~ tr/A-Z/a-z/;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -