diff --git a/etc/admin.conf b/etc/admin.conf
index 6f3012d..b16e80c 100644
--- a/etc/admin.conf
+++ b/etc/admin.conf
@@ -21,6 +21,7 @@
audiofile_features="[% www_admin.subscriber.audiofile_features %]"
/>
diff --git a/lib/admin/Controller/domain.pm b/lib/admin/Controller/domain.pm
index d184d81..3bc446b 100644
--- a/lib/admin/Controller/domain.pm
+++ b/lib/admin/Controller/domain.pm
@@ -5,6 +5,8 @@ use warnings;
use base 'Catalyst::Controller';
use Data::Dumper;
+use admin::Utils;
+
=head1 NAME
admin::Controller::domain - Catalyst Controller
@@ -328,6 +330,283 @@ sub delete_rewrite : Local {
return;
}
+
+=head2 preferences
+
+Show preferences for a given domain.
+
+=cut
+
+sub preferences : Local {
+ my ( $self, $c ) = @_;
+ $c->stash->{template} = 'tt/domain_preferences.tt';
+
+ my $domain = $c->request->params->{domain};
+ $c->stash->{domain} = $domain;
+
+ my $preferences;
+ return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_domain_preferences',
+ {
+ domain => $domain,
+ },
+ \$preferences
+ );
+
+ my $db_prefs;
+ return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_preferences',
+ undef, \$db_prefs
+ );
+ $db_prefs = [ grep { $$_{dom_pref} } @$db_prefs ] if eval { @$db_prefs };
+
+ ### restore data entered by the user ###
+
+ if(ref $c->session->{restore_preferences_input} eq 'HASH') {
+ if(ref $preferences eq 'HASH') {
+ $preferences = { %$preferences, %{$c->session->{restore_preferences_input}} };
+ } else {
+ $preferences = $c->session->{restore_preferences_input};
+ }
+ delete $c->session->{restore_preferences_input};
+ }
+
+ if(eval { @$db_prefs }) {
+ $c->stash->{preferences_array} = admin::Utils::prepare_tt_prefs($c, $db_prefs, $preferences);
+ }
+
+ $c->stash->{edit_preferences} = $c->request->params->{edit_preferences};
+
+ return 1;
+}
+
+=head2 update_preferences
+
+Update domain preferences in the database.
+
+=cut
+
+sub update_preferences : Local {
+ my ( $self, $c ) = @_;
+
+ my $domain = $c->request->params->{domain};
+ $c->stash->{domain} = $domain;
+
+ my $preferences;
+ return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_domain_preferences',
+ {
+ domain => $domain,
+ },
+ \$preferences
+ );
+
+ my $db_prefs;
+ return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_preferences',
+ undef, \$db_prefs
+ );
+ $db_prefs = [ grep { $$_{dom_pref} } @$db_prefs ] if eval { @$db_prefs };
+
+ return unless admin::Utils::prepare_db_prefs($c, $db_prefs, $preferences, $domain);
+
+ ### save settings ###
+
+ unless(eval {keys %{$c->session->{messages}} }) {
+ if($c->model('Provisioning')->call_prov( $c, 'voip', 'set_domain_preferences',
+ { domain => $domain,
+ preferences => $preferences,
+ },
+ undef
+ ))
+ {
+ $c->session->{messages}{prefmsg} = 'Server.Voip.SavedSettings';
+ $c->response->redirect("/domain/preferences?domain=$domain");
+ return;
+
+ }
+ } else {
+ $c->session->{messages}{preferr} = 'Client.Voip.InputErrorFound';
+ }
+
+ $c->session->{restore_preferences_input} = $preferences;
+ $c->response->redirect("/domain/preferences?domain=$domain&edit_preferences=1");
+ return;
+}
+
+=head2 edit_list
+
+Add, remove or activate/deactivate entries from a number list preference.
+
+=cut
+
+sub edit_list : Local {
+ my ( $self, $c ) = @_;
+ $c->stash->{template} = 'tt/domain_edit_list.tt';
+
+ my $domain = $c->request->params->{domain};
+ $c->stash->{domain} = $domain;
+
+ my $preferences;
+ return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_domain_preferences',
+ { domain => $domain },
+ \$preferences
+ );
+
+ my $list = $c->request->params->{list_name};
+
+ if(defined $$preferences{$list}) {
+ my $block_list = ref $$preferences{$list} ? $$preferences{$list} : [ $$preferences{$list} ];
+ $c->stash->{list_data} = admin::Utils::prepare_tt_list($c, $block_list);
+ }
+
+ $c->stash->{list_name} = $list;
+
+ my $list_mode = $list;
+ $list_mode =~ s/list$/mode/;
+ $c->stash->{list_mode} = $$preferences{$list_mode};
+ $list_mode =~ s/mode$/clir/;
+ $c->stash->{block_in_clir} = $$preferences{$list_mode};
+
+ if(defined $c->session->{blockaddtxt}) {
+ $c->stash->{blockaddtxt} = $c->session->{blockaddtxt};
+ delete $c->session->{blockaddtxt};
+ }
+
+ return 1;
+}
+
+=head2 do_edit_list
+
+Update a number list preference in the database.
+
+=cut
+
+sub do_edit_list : Local {
+ my ( $self, $c ) = @_;
+
+ my $domain = $c->request->params->{domain};
+ $c->stash->{domain} = $domain;
+
+ my $preferences;
+ return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_domain_preferences',
+ { domain => $domain },
+ \$preferences
+ );
+
+ my $list = $c->request->params->{list_name};
+
+ # input text field to add new entry to block list
+ my $add = $c->request->params->{block_add};
+
+ # delete link next to entries in block list
+ my $del = $c->request->params->{block_del};
+
+ # activate/deactivate link next to entries in block list
+ my $act = $c->request->params->{block_act};
+
+ admin::Utils::addelact_blocklist($c, $preferences, $list, $add, $del, $act);
+
+ unless(eval {keys %{$c->session->{messages}} }) {
+ $c->model('Provisioning')->call_prov( $c, 'voip', 'set_domain_preferences',
+ { domain => $domain,
+ preferences => {
+ $list => $$preferences{$list},
+ },
+ },
+ undef
+ );
+ } else {
+ $c->session->{messages}{numerr} = 'Client.Voip.InputErrorFound';
+ }
+
+ $c->response->redirect("/domain/edit_list?domain=$domain&list_name=$list");
+}
+
+=head2 edit_iplist
+
+Add or remove entries from an IP list preference.
+
+=cut
+
+sub edit_iplist : Local {
+ my ( $self, $c ) = @_;
+ $c->stash->{template} = 'tt/domain_edit_iplist.tt';
+
+ my $domain = $c->request->params->{domain};
+ $c->stash->{domain} = $domain;
+
+ my $preferences;
+ return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_domain_preferences',
+ { domain => $domain },
+ \$preferences
+ );
+
+ my $list = $c->request->params->{list_name};
+ $c->stash->{list_name} = $list;
+
+ if(defined $$preferences{$list}) {
+ my $iplist = ref $$preferences{$list} ? $$preferences{$list} : [ $$preferences{$list} ];
+
+ my $bg = '';
+ my $i = 1;
+ foreach my $entry (sort @$iplist) {
+ push @{$c->stash->{list_data}}, { ipnet => $entry,
+ background => $bg ? '' : 'tr_alt',
+ id => $i++,
+ };
+ $bg = !$bg;
+ }
+ }
+
+ if(defined $c->session->{listaddtxt}) {
+ $c->stash->{listaddtxt} = $c->session->{listaddtxt};
+ delete $c->session->{listaddtxt};
+ }
+
+ return 1;
+}
+
+=head2 do_edit_iplist
+
+Update an IP list preference in the database.
+
+=cut
+
+sub do_edit_iplist : Local {
+ my ( $self, $c ) = @_;
+
+ my $domain = $c->request->params->{domain};
+ $c->stash->{domain} = $domain;
+
+ my $preferences;
+ return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_domain_preferences',
+ { domain => $domain },
+ \$preferences
+ );
+
+ my $list = $c->request->params->{list_name};
+
+ # input text field to add new entry to IP list
+ my $add = $c->request->params->{list_add};
+
+ # delete link next to entries in IP list
+ my $del = $c->request->params->{list_del};
+
+ admin::Utils::addel_iplist($c, $preferences, $list, $add, $del);
+
+ unless(eval {keys %{$c->session->{messages}} }) {
+ $c->model('Provisioning')->call_prov( $c, 'voip', 'set_domain_preferences',
+ { domain => $domain,
+ preferences => {
+ $list => $$preferences{$list},
+ },
+ },
+ undef
+ );
+ } else {
+ $c->session->{messages}{numerr} = 'Client.Voip.InputErrorFound';
+ }
+
+ $c->response->redirect("/domain/edit_iplist?domain=$domain&list_name=$list");
+}
+
=head2 audio
Show audio file details for a given domain.
diff --git a/lib/admin/Utils.pm b/lib/admin/Utils.pm
index 1bbfb87..4794fb5 100644
--- a/lib/admin/Utils.pm
+++ b/lib/admin/Utils.pm
@@ -3,6 +3,7 @@ use strict;
use warnings;
use Time::Local;
+use HTML::Entities;
# Takes a search result total count, an offset and a limit and returns
# an array containing offset values for a pagination link list
@@ -237,5 +238,302 @@ sub prepare_call_list {
return $callentries;
}
+# this prepares the list of preferences for display in the template
+sub prepare_tt_prefs {
+ my ($c, $db_prefs, $preferences) = @_;
+ my @stashprefs;
+
+ foreach my $pref (eval { @$db_prefs }) {
+ # managed separately
+ next if $$pref{preference} eq 'lock';
+
+ if($$pref{preference} eq 'cfu'
+ or $$pref{preference} eq 'cfb'
+ or $$pref{preference} eq 'cft'
+ or $$pref{preference} eq 'cfna')
+ {
+ if(defined $$preferences{$$pref{preference}} and length $$preferences{$$pref{preference}}) {
+ my $vbdom = $c->config->{voicebox_domain};
+ my $fmdom = $c->config->{fax2mail_domain};
+ my $confdom = $c->config->{conference_domain};
+ if($$preferences{$$pref{preference}} =~ /\@$vbdom$/) {
+ $$preferences{$$pref{preference}} = 'voicebox';
+ } elsif($$preferences{$$pref{preference}} =~ /\@$fmdom$/) {
+ $$preferences{$$pref{preference}} = 'fax2mail';
+ } elsif($$preferences{$$pref{preference}} =~ /\@$confdom$/) {
+ $$preferences{$$pref{preference}} = 'conference';
+ }
+ }
+ } elsif(!$c->stash->{ncos_levels} and ($$pref{preference} eq 'ncos' or $$pref{preference} eq 'adm_ncos')) {
+ my $ncoslvl;
+ return unless $c->model('Provisioning')->call_prov( $c, 'billing', 'get_ncos_levels',
+ undef,
+ \$ncoslvl
+ );
+ $c->stash->{ncos_levels} = $ncoslvl if eval { @$ncoslvl };
+ } elsif($$pref{preference} eq 'block_in_list' or $$pref{preference} eq 'block_out_list') {
+ eval { @{$$preferences{$$pref{preference}}} = map { s/^([1-9])/+$1/; $_ } @{$$preferences{$$pref{preference}}} };
+ }
+
+ push @stashprefs,
+ { key => $$pref{preference},
+ data_type => $$pref{data_type},
+ value => $$preferences{$$pref{preference}},
+ max_occur => $$pref{max_occur},
+ description => encode_entities($$pref{description}),
+ error => $c->session->{messages}{$$pref{preference}}
+ ? $c->model('Provisioning')->localize($c->view($c->config->{view})->
+ config->{VARIABLES}{site_config}{language},
+ $c->session->{messages}{$$pref{preference}})
+ : undef,
+ };
+ }
+
+ return \@stashprefs;
+}
+
+# this prepares the list of preferences for the prov. interface
+sub prepare_db_prefs {
+ my ($c, $db_prefs, $preferences, $domain, $username) = @_;
+
+ foreach my $db_pref (eval { @$db_prefs }) {
+
+ next if $$db_pref{read_only};
+
+ if($$db_pref{preference} eq 'cfu'
+ or $$db_pref{preference} eq 'cfb'
+ or $$db_pref{preference} eq 'cft'
+ or $$db_pref{preference} eq 'cfna')
+ {
+ my $vbdom = $c->config->{voicebox_domain};
+ my $fmdom = $c->config->{fax2mail_domain};
+ my $confdom = $c->config->{conference_domain};
+
+ my $fwtype = $$db_pref{preference};
+ my $fw_target_select = $c->request->params->{$fwtype .'_target'} || 'disable';
+
+ unless(defined $username) { # forwards for domains and peers are not supported
+ $c->session->{messages}{$fwtype} = 'Client.Voip.MalformedTarget';
+ next;
+ }
+
+ my $fw_target;
+ if($fw_target_select eq 'sipuri') {
+ $fw_target = $c->request->params->{$fwtype .'_sipuri'};
+
+ # normalize, so we can do some checks.
+ $fw_target =~ s/^sip://i;
+
+ if($fw_target =~ /^\+?\d+$/) {
+ $fw_target = admin::Utils::get_qualified_number_for_subscriber($c, $fw_target);
+ my $checkresult;
+ return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'check_E164_number', $fw_target, \$checkresult);
+ $c->session->{messages}{$fwtype} = 'Client.Voip.MalformedNumber'
+ unless $checkresult;
+ } elsif($fw_target =~ /^[a-z0-9&=+\$,;?\/_.!~*'()-]+\@[a-z0-9.-]+(:\d{1,5})?$/i) {
+ $fw_target = 'sip:'. lc $fw_target;
+ } elsif($fw_target =~ /^[a-z0-9&=+\$,;?\/_.!~*'()-]+$/) {
+ $fw_target = 'sip:'. lc($fw_target) .'@'. $domain;
+ } else {
+ $c->session->{messages}{$fwtype} = 'Client.Voip.MalformedTarget';
+ $fw_target = $c->request->params->{$fwtype .'_sipuri'};
+ }
+ } elsif($fw_target_select eq 'voicebox') {
+ $fw_target = 'sip:vmu'.$c->session->{subscriber}{cc}.$c->session->{subscriber}{ac}.$c->session->{subscriber}{sn}."\@$vbdom";
+ } elsif($fw_target_select eq 'fax2mail') {
+ $fw_target = 'sip:'.$c->session->{subscriber}{cc}.$c->session->{subscriber}{ac}.$c->session->{subscriber}{sn}."\@$fmdom";
+ } elsif($fw_target_select eq 'conference') {
+ $fw_target = 'sip:conf='.$c->session->{subscriber}{cc}.$c->session->{subscriber}{ac}.$c->session->{subscriber}{sn}."\@$confdom";
+ }
+ $$preferences{$fwtype} = $fw_target;
+ } elsif($$db_pref{preference} eq 'cli') {
+ $$preferences{cli} = $c->request->params->{cli} or undef;
+ unless(defined $username) { # CLI for domains and peers is not supported
+ $c->session->{messages}{cli} = 'Client.Voip.MalformedNumber';
+ next;
+ }
+ if(defined $$preferences{cli} and $$preferences{cli} =~ /^\+?\d+$/) {
+ $$preferences{cli} = admin::Utils::get_qualified_number_for_subscriber($c, $$preferences{cli});
+ my $checkresult;
+ return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'check_E164_number', $$preferences{cli}, \$checkresult);
+ $c->session->{messages}{cli} = 'Client.Voip.MalformedNumber'
+ unless $checkresult;
+ }
+ } elsif($$db_pref{preference} eq 'cc') {
+ $$preferences{$$db_pref{preference}} = $c->request->params->{$$db_pref{preference}} || undef;
+ if(defined $$preferences{$$db_pref{preference}}) {
+ my $checkresult;
+ return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'check_cc',
+ $$preferences{$$db_pref{preference}}, \$checkresult
+ );
+ $c->session->{messages}{$$db_pref{preference}} = 'Client.Voip.MalformedCc'
+ unless $checkresult;
+ }
+ } elsif($$db_pref{preference} eq 'ac'
+ or $$db_pref{preference} eq 'svc_ac'
+ or $$db_pref{preference} eq 'emerg_ac')
+ {
+ $$preferences{$$db_pref{preference}} = $c->request->params->{$$db_pref{preference}} || undef;
+ if(defined $$preferences{$$db_pref{preference}}) {
+ my $checkresult;
+ return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'check_ac',
+ $$preferences{$$db_pref{preference}}, \$checkresult
+ );
+ $c->session->{messages}{$$db_pref{preference}} = 'Client.Voip.MalformedAc'
+ unless $checkresult;
+ }
+ } elsif($$db_pref{max_occur} != 1) {
+ # multi-value preferences are handled separately
+ } elsif($$db_pref{data_type} eq 'int' or $$db_pref{data_type} eq 'string') {
+ if(length $c->request->params->{$$db_pref{preference}}) {
+ $$preferences{$$db_pref{preference}} = $c->request->params->{$$db_pref{preference}};
+ } else {
+ $$preferences{$$db_pref{preference}} = undef;
+ }
+ } elsif($$db_pref{data_type} eq 'boolean') {
+ $$preferences{$$db_pref{preference}} = $c->request->params->{$$db_pref{preference}} ? 1 : undef;
+ } else {
+ # wtf? ignoring invalid preference
+ }
+ }
+
+ if($$preferences{cft}) {
+ unless(defined $$preferences{ringtimeout} and $$preferences{ringtimeout} =~ /^\d+$/
+ and $$preferences{ringtimeout} < 301 and $$preferences{ringtimeout} > 4)
+ {
+ $c->session->{messages}{ringtimeout} = 'Client.Voip.MissingRingtimeout';
+ }
+ }
+
+ return 1;
+}
+
+# this prepares a list preferences for display in the template
+sub prepare_tt_list {
+ my ($c, $list) = @_;
+ my (@list_to_sort, @sorted_list);
+
+ foreach my $entry (@$list) {
+ my $active = $entry =~ s/^#// ? 0 : 1;
+ $entry =~ s/^([1-9])/+$1/;
+ push @list_to_sort, { entry => $entry, active => $active };
+ }
+
+ my $bg = '';
+ my $i = 1;
+ foreach my $entry (sort {$a->{entry} cmp $b->{entry}} @list_to_sort) {
+ push @sorted_list, { number => $$entry{entry},
+ background => $bg ? '' : 'tr_alt',
+ id => $i++,
+ active => $$entry{active},
+ };
+ $bg = !$bg;
+ }
+
+ return \@sorted_list;
+}
+
+# this adds, deletes, activates or deactivates entries from a block list
+sub addelact_blocklist {
+ my ($c, $preferences, $list, $add, $del, $act) = @_;
+
+ if(defined $add) {
+ if($add =~ /^\+?[?*0-9\[\]-]+$/) {
+ my $ccdp = $c->config->{cc_dial_prefix};
+ my $acdp = $c->config->{ac_dial_prefix};
+ if($add =~ /^\*/ or $add =~ /^\?/ or $add =~ /^\[/) {
+ # do nothing
+ } elsif($add =~ s/^\+// or $add =~ s/^$ccdp//) {
+ # nothing more to do
+ } elsif($add =~ s/^$acdp//) {
+ $add = $$preferences{cc} . $add;
+ } else {
+ $add = $$preferences{cc} . $$preferences{ac} . $add;
+ }
+ my $blocklist = $$preferences{$list};
+ $blocklist = [] unless defined $blocklist;
+ $blocklist = [ $blocklist ] unless ref $blocklist;
+ $$preferences{$list} = [ @$blocklist, $add ];
+ } else {
+ $c->session->{messages}{msgadd} = 'Client.Voip.MalformedNumberPattern';
+ $c->session->{blockaddtxt} = $add;
+ }
+ }
+
+ if(defined $del) {
+ my $blocklist = $$preferences{$list};
+ if(defined $blocklist) {
+ my $ccdp = $c->config->{cc_dial_prefix};
+ my $acdp = $c->config->{ac_dial_prefix};
+ if($del =~ /^\*/ or $del =~ /^\?/ or $del =~ /^\[/) {
+ # do nothing
+ } elsif($del =~ s/^\+// or $del =~ s/^$ccdp//) {
+ # nothing more to do
+ } elsif($del =~ s/^$acdp//) {
+ $del = $$preferences{cc} . $del;
+ }
+ $blocklist = [ $blocklist ] unless ref $blocklist;
+ if($c->request->params->{block_stat}) {
+ $$preferences{$list} = [ grep { $_ ne $del } @$blocklist ];
+ } else {
+ $$preferences{$list} = [ grep { $_ ne '#'.$del } @$blocklist ];
+ }
+ }
+ }
+
+ if(defined $act) {
+ my $blocklist = $$preferences{$list};
+ if(defined $blocklist) {
+ my $ccdp = $c->config->{cc_dial_prefix};
+ my $acdp = $c->config->{ac_dial_prefix};
+ if($act =~ /^\*/ or $act =~ /^\?/ or $act =~ /^\[/) {
+ # do nothing
+ } elsif($act =~ s/^\+// or $act =~ s/^$ccdp//) {
+ # nothing more to do
+ } elsif($act =~ s/^$acdp//) {
+ $act = $c->session->{subscriber}{cc} . $act;
+ }
+ $blocklist = [ $blocklist ] unless ref $blocklist;
+ if($c->request->params->{block_stat}) {
+ $$preferences{$list} = [ grep { $_ ne $act } @$blocklist ];
+ push @{$$preferences{$list}}, '#'.$act;
+ } else {
+ $$preferences{$list} = [ grep { $_ ne '#'.$act } @$blocklist ];
+ push @{$$preferences{$list}}, $act;
+ }
+ }
+ }
+
+ return 1;
+}
+
+# this adds or deletes entries from an IP list
+sub addel_iplist {
+ my ($c, $preferences, $list, $add, $del) = @_;
+
+ if(defined $add) {
+ my $checkresult;
+ return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'check_ipnet', $add, \$checkresult);
+ if($checkresult) {
+ my $iplist = $$preferences{$list};
+ $iplist = [] unless defined $iplist;
+ $iplist = [ $iplist ] unless ref $iplist;
+ $$preferences{$list} = [ @$iplist, $add ];
+ } else {
+ $c->session->{messages}{msgadd} = 'Client.Syntax.MalformedIPNet';
+ $c->session->{listaddtxt} = $add;
+ }
+ }
+
+ if(defined $del) {
+ my $iplist = $$preferences{$list};
+ if(defined $iplist) {
+ $iplist = [ $iplist ] unless ref $iplist;
+ $$preferences{$list} = [ grep { $_ ne $del } @$iplist ];
+ }
+ }
+
+ return 1;
+}
1;
diff --git a/root/tt/domain.tt b/root/tt/domain.tt
index e2df7c3..f3b5d2b 100644
--- a/root/tt/domain.tt
+++ b/root/tt/domain.tt
@@ -13,6 +13,8 @@
[% IF Catalyst.config.domain.rewrite_features %]
[% domain.domain %]
+ [% ELSIF Catalyst.config.domain.preference_features %]
+
[% domain.domain %]
[% ELSIF Catalyst.config.domain.audiofile_features %]
[% domain.domain %]
[% ELSIF Catalyst.config.domain.vsc_features %]
diff --git a/root/tt/domain_audio.tt b/root/tt/domain_audio.tt
index 42b5605..9e98eff 100644
--- a/root/tt/domain_audio.tt
+++ b/root/tt/domain_audio.tt
@@ -8,6 +8,9 @@
[% IF Catalyst.config.domain.rewrite_features %]
Rewrite Rules
[% END %]
+ [% IF Catalyst.config.domain.preference_features %]
+
Preferences
+ [% END %]
[% IF Catalyst.config.domain.audiofile_features %]
Announcements
[% END %]
diff --git a/root/tt/domain_edit_iplist.tt b/root/tt/domain_edit_iplist.tt
new file mode 100644
index 0000000..acc26b0
--- /dev/null
+++ b/root/tt/domain_edit_iplist.tt
@@ -0,0 +1,36 @@
+
Edit [% list_name %] for [% domain %]
+
+
Back
+
+ The subscribers are limited to the following list of IP addresses.
+ An empty list does not limit the subscribers at all.
+ This list can be overridden by subscriber specific settings.
+
+
+
+
+ [% FOREACH listentry = list_data %]
+ -
+
[% listentry.ipnet %]
+