1# -*- indent-tabs-mode: nil; -*- 2# vim:ft=perl:et:sw=4 3# $Id$ 4 5# Sympa - SYsteme de Multi-Postage Automatique 6# 7# Copyright 2017, 2018 The Sympa Community. See the AUTHORS.md file at the 8# top-level directory of this distribution and at 9# <https://github.com/sympa-community/sympa.git>. 10# 11# This program is free software; you can redistribute it and/or modify 12# it under the terms of the GNU General Public License as published by 13# the Free Software Foundation; either version 2 of the License, or 14# (at your option) any later version. 15# 16# This program is distributed in the hope that it will be useful, 17# but WITHOUT ANY WARRANTY; without even the implied warranty of 18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19# GNU General Public License for more details. 20# 21# You should have received a copy of the GNU General Public License 22# along with this program. If not, see <http://www.gnu.org/licenses/>. 23 24package Sympa::Aliases; 25 26use strict; 27use warnings; 28use English qw(-no_match_vars); 29 30use Conf; 31use Sympa::Constants; 32use Sympa::List; 33use Sympa::Log; 34use Sympa::Regexps; 35 36my $log = Sympa::Log->instance; 37 38# Sympa::Aliases is the proxy class of subclasses. 39# The constructor may be overridden by _new() method. 40sub new { 41 my $class = shift; 42 my $type = shift; 43 my %options = @_; 44 45 return undef unless $type; 46 47 # Special cases: 48 # - To disable aliases management, specify "none" as $type. 49 # - "External" module is used for full path to program. 50 # - However, "Template" module is used instead of obsoleted program 51 # alias_manager.pl. 52 return $class->_new if $type eq 'none'; 53 54 if ($type eq Sympa::Constants::SBINDIR() . '/alias_manager.pl') { 55 $type = 'Sympa::Aliases::Template'; 56 } elsif (0 == index $type, '/' and -x $type) { 57 $options{program} = $type; 58 $type = 'Sympa::Aliases::External'; 59 } 60 61 # Returns appropriate subclasses. 62 if ($type !~ /[^\w:]/) { 63 $type = sprintf 'Sympa::Aliases::%s', $type unless $type =~ /::/; 64 unless (eval sprintf('require %s', $type) 65 and $type->isa('Sympa::Aliases')) { 66 $log->syslog( 67 'err', 'Unable to use %s module: %s', 68 $type, $EVAL_ERROR || 'Not a Sympa::Aliases class' 69 ); 70 return undef; 71 } 72 return $type->_new(%options); 73 } 74 75 return undef; 76} 77 78sub _new { 79 my $class = shift; 80 my %options = @_; 81 82 return bless {%options} => $class; 83} 84 85sub check {0} 86 87sub add {0} 88 89sub del {0} 90 91# Check listname. 92sub check_new_listname { 93 my $listname = shift; 94 my $robot_id = shift; 95 96 unless (defined $listname and length $listname) { 97 $log->syslog('err', 'No listname'); 98 return ('user', 'listname_needed'); 99 } 100 101 $listname = lc $listname; 102 103 my $listname_re = Sympa::Regexps::listname(); 104 unless (defined $listname 105 and $listname =~ /^$listname_re$/i 106 and length $listname <= Sympa::Constants::LIST_LEN()) { 107 $log->syslog('err', 'Incorrect listname %s', $listname); 108 return ('user', 'incorrect_listname', {bad_listname => $listname}); 109 } 110 111 my $regx = Conf::get_robot_conf($robot_id, 'list_check_regexp'); 112 if ($regx) { 113 if ($listname =~ /^(\S+)-($regx)$/) { 114 $log->syslog('err', 115 'Incorrect listname %s matches one of service aliases', 116 $listname); 117 return ('user', 'listname_matches_aliases', 118 {new_listname => $listname}); 119 } 120 } 121 122 # Avoid "sympa", "listmaster", "bounce" and "bounce+XXX". 123 if ( $listname eq Conf::get_robot_conf($robot_id, 'email') 124 or $listname eq Conf::get_robot_conf($robot_id, 'listmaster_email') 125 or $listname eq Conf::get_robot_conf($robot_id, 'bounce_email_prefix') 126 or 0 == index( 127 $listname, 128 Conf::get_robot_conf($robot_id, 'bounce_email_prefix') . '+' 129 ) 130 ) { 131 $log->syslog('err', 132 'Incorrect listname %s matches one of service aliases', 133 $listname); 134 return ('user', 'listname_matches_aliases', 135 {new_listname => $listname}); 136 } 137 138 # Check listname on SMTP server. 139 my $aliases = 140 Sympa::Aliases->new(Conf::get_robot_conf($robot_id, 'alias_manager')); 141 my $res = $aliases->check($listname, $robot_id) if $aliases; 142 unless (defined $res) { 143 $log->syslog('err', 'Can\'t check list %.128s on %s', 144 $listname, $robot_id); 145 return ('intern'); 146 } 147 148 # Check this listname doesn't exist already. 149 if ($res or Sympa::List->new($listname, $robot_id, {'just_try' => 1})) { 150 $log->syslog('err', 151 'Could not create list %s: list on %s already exist', 152 $listname, $robot_id); 153 return ('user', 'list_already_exists', {new_listname => $listname}); 154 } 155 156 return; 157} 158 1591; 160__END__ 161 162=encoding utf-8 163 164=head1 NAME 165 166Sympa::Aliases - Base class for alias management 167 168=head1 SYNOPSIS 169 170 package Sympa::Aliases::FOO; 171 172 use base qw(Sympa::Aliases); 173 174 sub check { ... } 175 sub add { ... } 176 sub del { ... } 177 178 1; 179 180=head1 DESCRIPTION 181 182This module is the base class for subclasses to manage list aliases of Sympa. 183 184=head2 Methods 185 186=over 187 188=item new ( $type, [ key =E<gt> value, ... ] ) 189 190I<Constructor>. 191Creates new instance of L<Sympa::Aliases>. 192 193Returns one of appropriate subclasses according to $type: 194 195=over 196 197=item C<'none'> 198 199No aliases management. 200 201=item Full path to executable 202 203Use external program to manage aliases. 204See L<Sympa::Aliases::External>. 205 206=item Name of subclass 207 208Use a subclass C<Sympa::Aliases::I<name>> to manage aliases. 209 210=back 211 212For invalid types returns C<undef>. 213 214Note: 215For compatibility to the earlier versions of Sympa, 216if a string C<SBINDIR/alias_manager.pl> was given as $type, 217L<Sympa::Aliases::Template> subclass will be used. 218 219Optional C<I<key> =E<gt> I<value>> pairs are included in the instance as 220hash entries. 221 222=item check ($listname, $robot_id) 223 224I<Instance method>, I<overridable>. 225Checks if the addresses of requested list exist already. 226 227Parameters: 228 229=over 230 231=item $listname 232 233Name of the list. 234Mandatory. 235 236=item $robot_id 237 238List's robot. 239 240=back 241 242Returns: 243 244True value if one of addresses exists. 245C<0> if none found. 246C<undef> if something wrong happened. 247 248By default, this method always returns C<0>. 249 250=item add ($list) 251 252I<Instance method>, I<overridable>. 253Installs aliases for the list $list. 254 255Parameters: 256 257=over 258 259=item $list 260 261An instance of L<Sympa::List>. 262 263=back 264 265Returns: 266 267C<1> if installation succeeded. 268C<0> if there were no aliases to be installed. 269C<undef> if not applicable. 270 271By default, this method always returns C<0>. 272 273=item del ($list) 274 275I<Instance method>, I<overridable>. 276Removes aliases for the list $list. 277 278Parameters: 279 280=over 281 282=item $list 283 284An instance of L<Sympa::List>. 285 286=back 287 288Returns: 289 290C<1> if removal succeeded. 291C<0> if there were no aliases to be removed. 292C<undef> if not applicable. 293 294By default, this method always returns C<0>. 295 296=back 297 298=head2 Function 299 300=over 301 302=item check_new_listname ( $listname, $robot ) 303 304I<Function>. 305Checks if a new listname is allowed. 306 307TBD. 308 309Parameteres: 310 311=over 312 313=item $listname 314 315A list name to be checked. 316 317=item $robot 318 319Robot context. 320 321=back 322 323Returns: 324 325If check fails, an array including information of errors. 326If it succeeds, empty array. 327 328B<Note>: 329This should be used to check name of list to be created. 330Names of existing lists may not necessarily pass checks by this function. 331 332This function was added on Sympa 6.2.37b.2. 333 334=back 335 336=head1 SEE ALSO 337 338L<Sympa::Aliases::CheckSMTP>, 339L<Sympa::Aliases::External>, 340L<Sympa::Aliases::Template>. 341 342=head1 HISTORY 343 344F<alias_manager.pl> as a program to automate alias management appeared on 345Sympa 3.1b.13. 346 347L<Sympa::Aliases> module as an OO-based class appeared on Sympa 6.2.23b, 348and it obsoleted F<alias_manager.pl>. 349 350=cut 351