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

📄 b9ddns-lib.pl

📁 BIND 9 dynamic DNS webmin module. This module supports both static and dynamic zones, and IPv4 and I
💻 PL
📖 第 1 页 / 共 4 页
字号:
#! /usr/bin/perl##    B9DDNS - BIND 9 dynamic DNS webmin module.#    Copyright (C) 2003 John Horne. <john.horne@plymouth.ac.uk>#    Copyright (C) 2004 John Horne. <john.horne@plymouth.ac.uk>##    This program is free software; you can redistribute it and/or modify#    it under the terms of the GNU General Public License as published by#    the Free Software Foundation; either version 2 of the License, or#    (at your option) any later version.##    This program is distributed in the hope that it will be useful,#    but WITHOUT ANY WARRANTY; without even the implied warranty of#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the#    GNU General Public License for more details.##    You should have received a copy of the GNU General Public License#    along with this program; if not, write to the Free Software#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.### Common functions for the dynamic DNS module#use strict;no strict 'vars';no strict 'refs';do '../web-lib.pl';&init_config();do 'records-lib.pl';## This returns an array of references to assocations,# each containing the details of one named directive.## get_config()#sub get_config {	unless (@get_config_cache) {		@get_config_cache = &read_config_file($config{'named_conf'});	}	return \@get_config_cache;}## This returns a structure containing the top-level config as members.## get_config_parent()#sub get_config_parent {	local $conf = &get_config();	return { 'file' => $config{'named_conf'}, 'type' => 1, 'line' => -1,		 'eline' => $lines_count{$config{'named_conf'}},		 'members' => $conf };}## Reads a named config file and returns an array of values.## read_config_file(file, [do not expand includes])#sub read_config_file {	my $i = my $j = 0;	my $lnum = my $line = 0;	my $dir = my $str = '';	my @inc = my @ltok = my @lnum = my @tok = ();	my @rv = ();	if (open(FILE, $config{'chroot'} . $_[0])) {		$dir = $1 if ($_[0] =~ /^(.*)\/[^\/]+$/o);	}	else {		return @rv;	}	while (defined($line = <FILE>)) {		chomp($line);		$line =~ s/#.*$//o;		# Strip out comments.		$line =~ s://.*$::o if ($line !~ m:".*//.*":o);		$line =~ s:/\*.*?\*/::go;		$line =~ s/\s+$//o;		# Split the line into tokens.		while ($line =~ /^\s*"([^"]*)"(.*)$/o ||		       $line =~ /^\s*([{};])(.*)$/o ||		       $line =~ /^\s*((?:!)?[^{};\s]+)(.*)$/o) {				push(@tok, $1);				push(@lnum, $lnum);				$line = $2;		}		$lnum++;	}	close(FILE);	$lines_count{$_[0]} = $lnum;	#	# Now parse the tokens into data structures.	#	while ($i < @tok) {		$str = &parse_struct(\@tok, \@lnum, \$i, $j++, $_[0]);		push(@rv, $str) if (defined($str));	}	unless ($_[1]) {		#		# Expand any INCLUDE directives.		#		&recursive_includes(\@rv, $dir);	}	return @rv;}## recursive_includes(&dirs, base)#sub recursive_includes {	my $i = my $j = 0;	my $ifile = my $dir = '';	my @inc = ();	$dir = $_[1];	for ($i = 0; $i < @{ $_[0] }; $i++) {		if (lc($_[0]->[$i]->{'name'}) eq 'include') {			#			# Found one...replace the INCLUDE directive with it.			#			$ifile = $_[0]->[$i]->{'value'};			if ($ifile !~ /^\//o) {				$ifile = $dir . '/' . $ifile;			}			@inc = &read_config_file($ifile, 1);			#			# Update the index of included structures.			#			for ($j = 0; $j < @inc; $j++) {				$inc[$j]->{'index'} += $_[0]->[$i]->{'index'};			}			#			# Update the index of structures after the include.			#			for ($j = $i + 1; $j < @{ $_[0] }; $j++) {				$_[0]->[$j]->{'index'} += $#inc;			}			splice(@{ $_[0] }, $i--, 1, @inc);		}		elsif ($_[0]->[$i]->{'type'} == 1) {			#			# Check sub-structures too.			#			&recursive_includes($_[0]->[$i]->{'members'}, $dir);		}	}	return;}## A structure can either have one value or a list of values.## parse_struct(&tokens, &lines, &line_num, index, file)#sub parse_struct {	my $i = my $j = 0;	my $struct = my $token = '';	local @vals = ();	local %str = ();	$i = ${$_[2]};	$str{'name'} = lc($_[0]->[$i]);	$str{'line'} = $_[1]->[$i];	while (1) {		$token = $_[0]->[++$i];		if ($token eq '{' || $token eq ';' || $token eq '}') {			last;		}		elsif (! defined($token)) {			${$_[2]} = $i;			return undef;		}		else {			push(@vals, $token);		}	}	$str{'values'} = \@vals;	$str{'value'} = $vals[0];	$str{'index'} = $_[3];	$str{'file'} = $_[4];	if ($token eq '{') {	    # It contains sub-structures...parse them		local @members = ();		$i++;		    # Skip the {		$j = 0;		$str{'type'} = 1;		while ($_[0]->[$i] ne '}') {			unless (defined($_[0]->[$i])) {				${$_[2]} = $i;				return undef;			}			$struct = &parse_struct($_[0], $_[1], \$i, $j++, $_[4]);			push(@members, $struct) if (defined($struct));		}		$str{'members'} = \@members;		$i++;	# Skip the trailing }		$i++ if ($_[0]->[$i] eq ';');	# Skip any trailing ';'	}	else {			# only a single value...		$str{'type'} = 0;		$i++ if ($token eq ';');	# Skip the trailing ;	}	# 'ending line' is the line number the trailing ; is on.	$str{'eline'} = $_[1]->[$i - 1];	${$_[2]} = $i;	return \%str;}## Find a named entry.## find(name, &array)#sub find {	my $c = '';	my @rv = ();	my $name = lc($_[0]);	foreach $c (@{ $_[1] }) {		push(@rv, $c) if (lc($c->{'name'}) eq $name);	}	return (@rv) ? (wantarray ? @rv : $rv[0]) : (wantarray ? () : undef);}## Find the value of an entry.## find_value(name, &array)#sub find_value {	my $value = '';	my @values = ();	my $name = lc($_[0]);	@values = &find($name, $_[1]);	unless (@values) {		return undef;	}	elsif (wantarray) {		return map { $_->{'value'} } @values;	}	else {		$value = $values[0]->{'value'};		#		# We must leave filenames as they are.		#		$value = lc($value) if ($name !~ /file$/o &&					$name ne 'directory');		return $value;	}}## Returns the base directory for named files.## base_directory([&config])#sub base_directory {	my $opts = my $dir = my $conf = '';	$conf = $_[0] ? $_[0] : &get_config();	$opts = &find('options', $conf);	if (defined($opts)) {		$dir = &find('directory', $opts->{'members'});		$dir = (defined($dir)) ? $dir->{'values'}->[0] : '';	}	return $dir;}## Given a structure containing a directive name, type, values and members,# add, update or remove that directive in the config structure and data files.# The updating of files assumes that there is no overlap between directives -# each line in the config file must contain part or all of only one directive.## The position argument takes the values:##	 1: directive is to be placed at the top of the file#	 0: directive is to be placed at the bottom of the file (default)#	-1: directive is to be appended to end of file (regardless of whether#	    any directives of the same name exist).## save_directive(&parent, name|&old, &values, indent, [structonly], [position])#sub save_directive {	my $pm = my $lref = my $ol = my $pos = my $i = my $n = 0;	my @oldv = my @newv = my @nl = ();	$pm = $_[0]->{'members'};	$pos = $_[5] if (defined($_[5]));	@oldv = ref($_[1]) ? @{ $_[1] } : &find($_[1], $pm) unless ($pos == -1);	@newv = @{ $_[2] };	for($i = 0; $i < @oldv || $i < @newv; $i++) {		if ($i >= @oldv && $pos <= 0) {			#			# A new directive is being added.			# Put it at the end of the parent.			#			unless ($_[4]) {				$lref = &read_file_lines($config{'chroot'} .							 $_[0]->{'file'});				@nl = &directive_lines($newv[$i], $_[3]);				splice(@$lref, $_[0]->{'eline'}, 0, @nl);				$newv[$i]->{'file'} = $_[0]->{'file'};				$newv[$i]->{'line'} = $_[0]->{'eline'};				$newv[$i]->{'eline'} = $_[0]->{'eline'} + $#nl;				&renumber(&get_config(), $_[0]->{'eline'},					  $_[0]->{'file'}, scalar(@nl));			}			push(@$pm, $newv[$i]);		}		elsif ($i >= @oldv && $pos == 1) {			#			# A new directive is being added.			# Put it at the start of the parent.			#			unless ($_[4]) {				$lref = &read_file_lines($config{'chroot'} .							 $_[0]->{'file'});				@nl = &directive_lines($newv[$i], $_[3]);				splice(@$lref, $_[0]->{'line'} + 1, 0, @nl);				$newv[$i]->{'file'} = $_[0]->{'file'};				$newv[$i]->{'line'} = $_[0]->{'line'} + 1;				$newv[$i]->{'eline'} = $_[0]->{'line'} +						       scalar(@nl);				&renumber(&get_config(), $_[0]->{'line'},					  $_[0]->{'file'}, scalar(@nl));			}			splice(@$pm, 0, 0, $newv[$i]);		}		elsif ($i >= @newv) {			#			# A directive was deleted.			#			unless ($_[4]) {				$lref = &read_file_lines($config{'chroot'} .							 $oldv[$i]->{'file'});				$ol = $oldv[$i]->{'eline'} -				      $oldv[$i]->{'line'} + 1;				splice(@$lref, $oldv[$i]->{'line'}, $ol);				&renumber(&get_config(), $oldv[$i]->{'eline'},					  $oldv[$i]->{'file'}, -$ol);			}			splice(@$pm, &indexof($oldv[$i], @$pm), 1);		}		else {			#			# Updating some directive.			#			unless ($_[4]) {				$lref = &read_file_lines($config{'chroot'} .							 $oldv[$i]->{'file'});				@nl = &directive_lines($newv[$i], $_[3]);				$ol = $oldv[$i]->{'eline'} -				      $oldv[$i]->{'line'} + 1;				splice(@$lref, $oldv[$i]->{'line'}, $ol, @nl);				$newv[$i]->{'file'} = $_[0]->{'file'};				$newv[$i]->{'line'} = $oldv[$i]->{'line'};				$newv[$i]->{'eline'} = $oldv[$i]->{'line'} + $#nl;				&renumber(&get_config(), $oldv[$i]->{'eline'},					  $oldv[$i]->{'file'},					  scalar(@nl) - $ol);			}			$pm->[&indexof($oldv[$i], @$pm)] = $newv[$i];		}	}	return;}## Renders some directive into a number of lines of text.## directive_lines(&directive, tabs)#sub directive_lines {	my $first = my $quoteit = 0;	my $dir_name = my $v = '';	my @rv = ();	my %need_quote = ( 'file' => 1, 'zone' => 1, 'pid-file' => 1,			   'statistics-file' => 1, 'dump-file' => 1,			   'directory' => 1, 'secret' => 1, 'view' => 1,			   'version' => 1, 'random-device' => 1);	if ($_[0]->{'name'}) {		$dir_name = lc($_[0]->{'name'});		$quoteit = exists($need_quote{$dir_name});		$rv[0] = "\t" x $_[1];		$rv[0] .= $dir_name;	}	foreach $v (@{ $_[0]->{'values'} }) {		if ($quoteit && ! $first) {			$rv[0] .= ' "' . $v . '"';		}		else {			$rv[0] .= ' ' . $v;		}		$first++;	}	if ($_[0]->{'type'}) {		# Multiple values should be included as well.		$rv[0] .= ' in' if ($dir_name eq 'zone');		$rv[0] .= ' {';		foreach $v (@{ $_[0]->{'members'} }) {			push(@rv, &directive_lines($v, $_[1] + 1));		}		push(@rv, ("\t" x ($_[1] + 1)) . '}');	}	$rv[$#rv] .= ';' if ($dir_name && $dir_name ne 'inet');	return @rv;}## Runs through a given array of directives and increases the line numbers# of all those greater than some given line by the given count.## renumber(&directives, line, file, count)#sub renumber {	my $d = '';	foreach $d (@{ $_[0] }) {		if ($d->{'file'} eq $_[2]) {			if ($d->{'line'} > $_[1]) {				$d->{'line'} += $_[3];			}			if ($d->{'eline'} > $_[1]) {				$d->{'eline'} += $_[3];			}		}		if ($d->{'type'}) {			&renumber($d->{'members'}, $_[1], $_[2], $_[3]);		}	}	return;}## Output HTML for multiple input choices.## choice_input(text, name, &config, disabled, [display, option]+)#sub choice_input {	my $i = 0;	my $str = my $disabled = my $v = '';	$disabled = 'disabled' if ($_[3]);	$v = &find_value($_[1], $_[2]);	$str = '<td valign=top><b>' . $_[0] . '</b></td><td valign=top>';	for($i = 4; $i < @_; $i += 2) {		$str .= sprintf "<input type=radio $disabled name=%s value='%s' %s> %s\n",				$_[1], $_[$i + 1], &checked($v eq $_[$i + 1]),				$_[$i];	}	return $str . "</td>\n";}## save_choice(name, &parent, indent)#sub save_choice {	my $nd = 0;	if ($in{$_[0]}) {		$nd = { 'name' => $_[0], 'values' => [ $in{$_[0]} ] };	}	&save_directive($_[1], $_[0], $nd ? [ $nd ] : [ ], $_[2]);	return;}## Output a field for editing a list of addresses, partial addresses and ACL's.## addr_match_input(text, name, &config, ip_only, disabled)#sub addr_match_input {	my $i = 0;	my $name = my $disabled = my $rv = my $v = my $n = '';	my @av = ();	$disabled = 'disabled' if ($_[4]);	$v = &find($_[1], $_[2]);	$rv = '<td valign=top><b>' . $_[0] . '</b></td><td valign=top>';	unless ($_[3]) {		$rv .= sprintf "<input type=radio $disabled name=%s_def value=1 %s> %s ",		       $_[1], &checked(! $v), $text{'default'};		$rv .= sprintf "<input type=radio $disabled name=%s_def value=0 %s> %s<br>",		       $_[1], &checked($v), $text{'listed'};	}	if (defined($v)) {		foreach $name (@{ $v->{'values'} }) {			$n .= $name . ' ';		}		push (@av, $n) if ($n);		foreach $name (@{ $v->{'members'} }) {			$n = $name->{'name'};	                for ($i = 0; $i < @{ $name->{'values'} }; $i++) {                                $n .= ' ' . $name->{'values'}->[$i];                        }			push(@av, $n);		}	}	$rv .= "<textarea $disabled name=" . $_[1] . ' rows=3 cols=25>' .	       join("\n", @av) . "</textarea></td>\n";	return $rv;}## save_addr_match(name, &config, indent, ip_only, port_allowed)#sub save_addr_match {	my $master_port = my $port_allowed = my $ip_only = my $i = 0;	my $ip_seen = 0;	my $dir = my $ip = my $not = '';	my @vals = my @addr = ();	my $has_port = sub {			# Anonymous subroutine.		if ($port_allowed && $i + 1 < @addr && $addr[$i+1] eq 'port') {			if ($i + 2 >= @addr || $addr[$i + 2] =~ /\D/o) {				&terror('controls_eport');			}			else {				$i += 2;

⌨️ 快捷键说明

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