diff --git a/root/etc/e-smith/web/functions/expireaccounts b/root/etc/e-smith/web/functions/expireaccounts
new file mode 100755
index 0000000..cba525e
--- /dev/null
+++ b/root/etc/e-smith/web/functions/expireaccounts
@@ -0,0 +1,83 @@
+#!/usr/bin/perl -wT
+
+# vim: ft=xml ts=4 sw=4 et:
+#----------------------------------------------------------------------
+# heading : Collaboration
+# description : User Informations
+# navigation : 2000 2100
+#----------------------------------------------------------------------
+#----------------------------------------------------------------------
+# Copyright (C) 2011-2014 Firewall-Services
+# daniel@firewall-services.com
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Technical support for this program is available from Mitel Networks
+# Please visit our web site www.mitel.com/sme/ for details.
+#----------------------------------------------------------------------
+
+use strict;
+use esmith::TestUtils;
+use esmith::FormMagick::Panel::expireaccounts;
+
+my $fm = esmith::FormMagick::Panel::expireaccounts->new();
+
+$fm->display();
+
+__DATA__
+
diff --git a/root/usr/share/perl5/vendor_perl/esmith/FormMagick/Panel/expireaccounts.pm b/root/usr/share/perl5/vendor_perl/esmith/FormMagick/Panel/expireaccounts.pm
new file mode 100644
index 0000000..ba34226
--- /dev/null
+++ b/root/usr/share/perl5/vendor_perl/esmith/FormMagick/Panel/expireaccounts.pm
@@ -0,0 +1,233 @@
+#!/usr/bin/perl -w
+
+#---------------------------------------------------------------------
+# Copyright (C) 2016 Firewall-Services
+# daniel@firewall-services.com
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#----------------------------------------------------------------------
+package esmith::FormMagick::Panel::expireaccounts;
+
+use strict;
+
+use esmith::FormMagick;
+use esmith::AccountsDB;
+use esmith::ConfigDB;
+use esmith::cgi;
+use DateTime;
+use File::Basename;
+use Exporter;
+use Carp qw(verbose);
+
+our @ISA = qw(esmith::FormMagick Exporter);
+
+our @EXPORT = qw(
+ print_user_table
+ print_save_button
+ print_custom_button
+ print_section_bar
+);
+
+our $a = esmith::AccountsDB->open || die "Couldn't open AccountsDB";
+our $c = esmith::ConfigDB->open || die "Couldn't open ConfigDB";
+
+our %defaults = (
+ ExpireAutoReply => 'enabled',
+ WarnUsers => 'enabled'
+);
+
+sub new {
+ shift;
+ my $self = esmith::FormMagick->new();
+ $self->{calling_package} = (caller)[0];
+ bless $self;
+ return $self;
+}
+
+sub print_user_table {
+ my $self = shift;
+ my $q = $self->{cgi};
+
+ my @users = $a->users;
+
+ unless ( scalar @users ) {
+ print $q->Tr($q->td($self->localise('NO_USER_ACCOUNTS')));
+ return "";
+ }
+ print " \n \n ";
+ print $q->start_table ({-CLASS => "sme-border"}),"\n ";
+ print $q->Tr(
+ esmith::cgi::genSmallCell($q, $self->localise('ACCOUNT'), "header"),
+ esmith::cgi::genSmallCell($q, $self->localise('USER_NAME'), "header"),
+ esmith::cgi::genSmallCell($q, $self->localise('ACTION'), "header")
+ );
+
+ my $scriptname = basename($0);
+
+ foreach my $u (@users) {
+ my $username = $u->key();
+ my $first = $u->prop('FirstName');
+ my $last = $u->prop('LastName');
+
+ my $action = (($u->prop('PasswordSet') || 'no') eq 'yes') ? "" .
+ $self->localise('MODIFY') . "" : $self->localise('LOCKED');
+
+ print $q->Tr(
+ esmith::cgi::genSmallCell($q, $username, "normal"),
+ esmith::cgi::genSmallCell($q, "$first $last", "normal"),
+ esmith::cgi::genSmallCell($q, "$action", "normal")
+ );
+ }
+
+ print qq( |
\n);
+
+ return "";
+}
+
+sub print_save_button {
+ my ($self) = @_;
+ $self->print_button("SAVE");
+}
+
+sub print_section_bar{
+ my $self = shift;
+ print " \n \n";
+ print " \n";
+ return undef;
+}
+
+sub print_custom_button{
+ my ($self, $desc, $page) = @_;
+ my $url = basename($0) . "?page=0&page_stack=&Next=Next&wherenext=" . $page;
+
+ print " |
";
+ print $self->{cgi}->p(
+ $self->{cgi}->a({href => $url, -class => "button-like"}, $self->localise($desc))
+ );
+ print qq( |
);
+ return undef;
+}
+
+sub get_user_prop{
+ my ($self, $field) = @_;
+ return $a->get($self->{cgi}->param('acctName'))->prop("$field") || '';
+}
+
+sub get_user_bool{
+ my ($self, $field) = @_;
+ my $val = $self->get_user_prop($self, $field);
+ $val = $defaults{$field} if ($val eq '');
+ return ($val =~ m/^yes|enabled|1|on$/) ? 'enabled' : 'disabled';
+}
+
+sub get_conf_prop{
+ my ($self, $field) = @_;
+ return $c->get('ExpireAccounts')->prop($field) || '';
+}
+
+sub get_conf_bool{
+ my ($self, $field) = @_;
+ my $val = $self->get_conf_prop($self, $field);
+ $val = $defaults{$field} if ($val eq '');
+ return ($val =~ m/^yes|enabled|1|on$/) ? 'enabled' : 'disabled';
+}
+
+sub modify_config{
+ my ($self) = @_;
+ my $rec = $c->get('ExpireAccounts') || $c->new_record('ExpireAccounts', { type => 'service' });
+ my %new_props = ();
+ foreach my $prop (qw(WarningDelay DaysBetweenWarnings WarningRecipient)){
+ if (!$self->{cgi}->param($prop) || $self->{cgi}->param($prop) eq ''){
+ $rec->delete_prop($prop);
+ }
+ else{
+ $new_props{$prop} = $self->{cgi}->param($prop);
+ }
+ }
+ # Bool props
+ foreach my $prop (qw(WarnUsers)){
+ $new_props{$prop} = ($self->{cgi}->param($prop)) ? 'enabled' : 'disabled';
+ }
+ $rec->merge_props(%new_props);
+ $self->success('CONFIG_MODIFIED');
+}
+
+sub modify_user {
+ my ($self) = @_;
+ my $acctName = $self->{cgi}->param('acctName');
+
+ unless (($acctName) = ($acctName =~ /^(\w[\-\w_\.]*)$/)) {
+ return $self->error(
+ $self->localise('TAINTED_USER', { acctName => $acctName })
+ );
+ }
+ # Untaint the username before use in system()
+ $acctName = $1;
+
+ my $acct = $a->get($acctName);
+ my $type = $acct->prop('type');
+
+ unless ($type eq 'user'){
+ return $self->error(
+ $self->localise('NOT_A_USER_ACCOUNT', { acctName => $acctName })
+ );
+ }
+ my %new_props = ();
+ foreach my $prop (qw(ExpireLockOn ExpireForwardAfterLock)){
+ if (!$self->{cgi}->param($prop) || $self->{cgi}->param($prop) eq ''){
+ $acct->delete_prop($prop);
+ }
+ else{
+ $new_props{$prop} = $self->{cgi}->param($prop);
+ }
+ }
+ $acct->merge_props(%new_props);
+ $self->success('USER_MODIFIED');
+}
+
+# Validation routines
+
+# Number must be int and positive
+sub is_positive_int{
+ my ($self, $num) = @_;
+ return $self->localise('MUST_BE_POSITIVE_NUMBER') unless ($num =~ m/^\d+$/ && $num > 0);
+ return 'OK';
+}
+
+# Take a string representing a date, must be YYY-MM-DD format, and in the future, or an empty string
+sub is_future_date_or_empty {
+ my ($self, $date_string) = @_;
+ return 'OK' if ($date_string eq '');
+ return $self->localise('DATE_FORMAT_INVALID') unless ($date_string =~ /^(\d{4})\-(\d{1,2})\-(\d{1,2})$/);
+ my $date = eval {
+ DateTime->new(
+ year => $1,
+ month => $2,
+ day => $3
+ );
+ };
+ return $self->localise('DATE_FORMAT_INVALID') unless ($date);
+ my $now = DateTime->now;
+ return $self->localise('DATE_IS_PASSED') unless ($date > $now);
+ return 'OK';
+}
+
+# Take a string, must be a valid email or an empty string
+sub is_email_or_empty {
+ my ($self, $field) = @_;
+ return $self->localise('BAD_SYNTAX') unless (($field =~ m/^[a-zA-Z][a-zA-Z0-9\._\-]*\@?([a-zA-Z0-9\._\-]*)?$/) || ($field eq ''));
+ return 'OK';
+}
+