# vim: set et ts=4 sw=4: #***************************************************************************** # # Copyright (c) 2013 Angelo Naselli # from adduserdrake and userdrake # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2, as # published by the Free Software Foundation. # # 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 AdminPanel::Module::Users; ############################################### ## ## graphic related routines for managing user ## ############################################### use strict; # TODO evaluate if Moose is too heavy and use Moo # instead use POSIX qw(ceil); # use Time::localtime; # TODO same translation atm use lib qw(/usr/lib/libDrakX); # i18n: IMPORTANT: to get correct namespace (userdrake instead of libDrakX) BEGIN { unshift @::textdomains, 'userdrake', 'libuser', 'drakconf' } use common qw(N translate); use security::level; use run_program; ## USER is from userdrake use USER; use utf8; use log; use Glib; use yui; use AdminPanel::Shared; use AdminPanel::Shared::Users; use Moose; extends qw( AdminPanel::Module ); has '+icon' => ( default => "/usr/share/icons/userdrake.png", ); has '+name' => ( default => N("AdminUser"), ); =head1 VERSION Version 1.0.0 =cut our $VERSION = '1.0.0'; # main dialog has 'dialog' => ( is => 'rw', init_arg => undef, ); has 'widgets' => ( traits => ['Hash'], default => sub { {} }, is => 'rw', isa => 'HashRef', handles => { set_widget => 'set', get_widget => 'get', widget_pairs => 'kv', }, init_arg => undef, ); has 'action_menu' => ( traits => ['Hash'], default => sub { {} }, is => 'rw', isa => 'HashRef', handles => { set_action_menu => 'set', get_action_menu => 'get', action_menu_pairs => 'kv', }, init_arg => undef, ); ## Used by USER (for getting values? TODO need explanations, where?) has 'USER_GetValue' => ( default => -65533, is => 'ro', isa => 'Int', init_arg => undef, ); ## Used by USER (for getting values? TODO need explanations, where?) has 'ctx' => ( default => sub {USER::ADMIN->new}, is => 'ro', init_arg => undef, ); has 'edit_tab_widgets' => ( traits => ['Hash'], default => sub { {} }, is => 'rw', isa => 'HashRef', handles => { set_edit_tab_widget => 'set', get_edit_tab_widget => 'get', edit_tab_pairs => 'kv', }, init_arg => undef, ); sub start { my $self = shift; $self->manageUsersDialog(); }; # TODO move to Shared? sub labeledFrameBox { my ($parent, $label) = @_; my $factory = yui::YUI::widgetFactory; my $frame = $factory->createFrame($parent, $label); $frame->setWeight( $yui::YD_HORIZ, 1); $frame->setWeight( $yui::YD_VERT, 2); $frame = $factory->createHVCenter( $frame ); $frame = $factory->createVBox( $frame ); return $frame; } # usefull local variable to avoid duplicating # translation point for user edit labels my %userEditLabel = ( user_data => N("User Data"), account_info => N("Account Info"), password_info => N("Password Info"), groups => N("Groups"), ); # usefull local variable to avoid duplicating # translation point for group edit labels my %groupEditLabel = ( group_data => N("Group Data"), group_users => N("Group Users"), ); #============================================================= =head2 ChooseGroup =head3 INPUT $self: this object =head3 OUTPUT $choice: 0 or 1 (choice) -1 cancel or exit =head3 DESCRIPTION creates a popup dialog to ask if adding user to an existing group or to the 'users' group =cut #============================================================= sub ChooseGroup { my $self = shift; my $choice = -1; ## push application title my $appTitle = yui::YUI::app()->applicationTitle(); ## set new title to get it in dialog yui::YUI::app()->setApplicationTitle(N("Choose group")); my $factory = yui::YUI::widgetFactory; my $dlg = $factory->createPopupDialog(); my $layout = $factory->createVBox($dlg); my $frame = labeledFrameBox($layout, N("A group with this name already exists. What would you like to do?")); my $rbg = $factory->createRadioButtonGroup( $frame ); $frame = $factory->createVBox( $rbg ); my $align = $factory->createLeft($frame); my $rb1 = $factory->createRadioButton( $align, N("Add to the existing group"), 1); $rb1->setNotify(1); $rbg->addRadioButton( $rb1 ); $align = $factory->createLeft($frame); my $rb2 = $factory->createRadioButton( $align, N("Add to the 'users' group"), 0); $rb2->setNotify(1); $rbg->addRadioButton( $rb2 ); my $hbox = $factory->createHBox($layout); $align = $factory->createRight($hbox); my $cancelButton = $factory->createPushButton($align, N("Cancel")); my $okButton = $factory->createPushButton($hbox, N("Ok")); while(1) { my $event = $dlg->waitForEvent(); my $eventType = $event->eventType(); #event type checking if ($eventType == $yui::YEvent::CancelEvent) { last; } elsif ($eventType == $yui::YEvent::WidgetEvent) { # widget selected my $widget = $event->widget(); if ($widget == $cancelButton) { last; } if ($widget == $okButton) { $choice = $rb1->value() ? 0 : 1 ; last; } } } destroy $dlg; #restore old application title yui::YUI::app()->setApplicationTitle($appTitle); return $choice; } #============================================================= =head2 _updateOrDelUsersInGroup =head3 INPUT $name: username =head3 DESCRIPTION Fixes user deletion into groups. =cut #============================================================= sub _updateOrDelUserInGroup { my ($self, $name) = @_; my $groups = $self->ctx->GroupsEnumerateFull; foreach my $g (@$groups) { my $members = $g->MemberName(1, 0); if ($self->_inArray($name, $members)) { eval { $g->MemberName($name, 2) }; eval { $self->ctx->GroupModify($g) }; } } } #============================================================= =head2 _deleteGroupDialog =head3 INPUT $self: this object =head3 DESCRIPTION This method open a dialog to delete the selected group. =cut #============================================================= sub _deleteGroupDialog { my $self = shift; my $item = $self->get_widget('table')->selectedItem(); if (! $item) { return; } my $groupname = $item->label(); ## push application title my $appTitle = yui::YUI::app()->applicationTitle(); ## set new title to get it in dialog yui::YUI::app()->setApplicationTitle(N("Warning")); my $factory = yui::YUI::widgetFactory; my $dlg = $factory->createPopupDialog(); my $layout = $factory->createVBox($dlg); my $align = $factory->createLeft($layout); $factory->createLabel($align, N("Do you really want to delete the group %s?", $groupname)); $align = $factory->createRight($layout); my $hbox = $factory->createHBox($align); my $cancelButton = $factory->createPushButton($hbox, N("Cancel")); my $deleteButton = $factory->createPushButton($hbox, N("Delete")); while(1) { my $event = $dlg->waitForEvent(); my $eventType = $event->eventType(); #event type checking if ($eventType == $yui::YEvent::CancelEvent) { last; } elsif ($eventType == $yui::YEvent::WidgetEvent) { # widget selected my $widget = $event->widget(); if ($widget == $cancelButton) { last; } elsif ($widget == $deleteButton) { my $groupEnt = $self->ctx->LookupGroupByName($groupname); my $members = $self->ctx->EnumerateUsersByGroup($groupname); my $continue = 1; GLOOP: foreach my $username (@$members) { my $userEnt = $self->ctx->LookupUserByName($username); if ($userEnt && $userEnt->Gid($self->USER_GetValue) == $groupEnt->Gid($self->USER_GetValue)) { AdminPanel::Shared::msgBox(N("%s is a primary group for user %s\n Remove the user first", $groupname, $username)); $continue = 0; last GLOOP; } } if ($continue) { log::explanations(N("Removing group: %s", $groupname)); eval { $self->ctx->GroupDel($groupEnt) }; $self->_refresh(); } last; } } } destroy $dlg; #restore old application title yui::YUI::app()->setApplicationTitle($appTitle); } #============================================================= =head2 _deleteUserDialog =head3 INPUT $self: this object =head3 DESCRIPTION This method open a dialog to delete the selected user. It also asks for additional information to be removed. =cut #============================================================= sub _deleteUserDialog { my $self = shift; my $item = $self->get_widget('table')->selectedItem(); if (! $item) { return; } my $username = $item->label(); my $userEnt = $self->ctx->LookupUserByName($username); my $homedir = $userEnt->HomeDir($self->USER_GetValue); ## push application title my $appTitle = yui::YUI::app()->applicationTitle(); ## set new title to get it in dialog yui::YUI::app()->setApplicationTitle(N("Delete files or not?")); my $factory = yui::YUI::widgetFactory; my $dlg = $factory->createPopupDialog(); my $layout = $factory->createVBox($dlg); my $align = $factory->createLeft($layout); $factory->createLabel($align, N("Deleting user %s\nAlso perform the following actions\n", $username)); $align = $factory->createLeft($layout); my $checkhome = $factory->createCheckBox($align, N("Delete Home Directory: %s", $homedir, 0)); $align = $factory->createLeft($layout); my $checkspool = $factory->createCheckBox($align, N("Delete Mailbox: /var/spool/mail/%s", $username), 0); $align = $factory->createRight($layout); my $hbox = $factory->createHBox($align); my $cancelButton = $factory->createPushButton($hbox, N("Cancel")); my $deleteButton = $factory->createPushButton($hbox, N("Delete")); if ($homedir !~ m!(?:/home|/var/spool)!) { $checkhome->setDisabled(); $checkspool->setDisabled(); } while(1) { my $event = $dlg->waitForEvent(); my $eventType = $event->eventType(); #event type checking if ($eventType == $yui::YEvent::CancelEvent) { last; } elsif ($eventType == $yui::YEvent::WidgetEvent) { # widget selected my $widget = $event->widget(); if ($widget == $cancelButton) { last; } elsif ($widget == $deleteButton) { log::explanations(N("Removing user: %s", $username)); $self->ctx->UserDel($userEnt); $self->_updateOrDelUserInGroup($username); #Let's check out the user's primary group my $usergid = $userEnt->Gid($self->USER_GetValue); my $groupEnt = $self->ctx->LookupGroupById($usergid); if ($groupEnt) { my $member = $groupEnt->MemberName(1, 0); if (scalar(@$member) == 0 && $groupEnt->Gid($self->USER_GetValue) > 499) { $self->ctx->GroupDel($groupEnt); } } if ($checkhome->isChecked()) { eval { $self->ctx->CleanHome($userEnt) }; $@ and AdminPanel::Shared::msgBox($@) and last; } if ($checkspool->isChecked()) { eval { $self->ctx->CleanSpool($userEnt) }; $@ and AdminPanel::Shared::msgBox($@) and last; } $self->_refresh(); last; } } } destroy $dlg; #restore old application title yui::YUI::app()->setApplicationTitle($appTitle); } sub _addGroupDialog { my $self = shift; my $is_system = 0; ## push application title my $appTitle = yui::YUI::app()->applicationTitle(); ## set new title to get it in dialog yui::YUI::app()->setApplicationTitle(N("Create New Group")); my $factory = yui::YUI::widgetFactory; my $optional = yui::YUI::optionalWidgetFactory; my $dlg = $factory->createPopupDialog(); my $layout = $factory->createVBox($dlg); ## 'group name' my $align = $factory->createRight($layout); my $hbox = $factory->createHBox($align); my $label = $factory->createLabel($hbox, N("Group Name:") ); my $groupName = $factory->createInputField($hbox, "", 0); $label->setWeight($yui::YD_HORIZ, 1); $groupName->setWeight($yui::YD_HORIZ, 2); $factory->createVSpacing($layout, 1); # Specify group id manually $align = $factory->createLeft($layout); $hbox = $factory->createHBox($align); my $gidManually = $factory->createCheckBox($hbox, N("Specify group ID manually"), 0); $factory->createHSpacing($hbox, 2); my $GID = $factory->createIntField($hbox, N("GID"), 1, 65000, 500); $GID->setEnabled($gidManually->value()); $gidManually->setNotify(1); $hbox = $factory->createHBox($layout); $align = $factory->createRight($hbox); my $cancelButton = $factory->createPushButton($align, N("Cancel")); my $okButton = $factory->createPushButton($hbox, N("Ok")); while(1) { my $event = $dlg->waitForEvent(); my $eventType = $event->eventType(); #event type checking if ($eventType == $yui::YEvent::CancelEvent) { last; } elsif ($eventType == $yui::YEvent::WidgetEvent) { # widget selected my $widget = $event->widget(); if ($widget == $cancelButton) { last; } elsif ($widget == $gidManually) { # GID inserction enabled? $GID->setEnabled($gidManually->value()); } elsif ($widget == $okButton) { ## check data my $groupname = $groupName->value(); my ($continue, $errorString) = valid_groupname($groupname); my $nm = $continue && $self->ctx->LookupGroupByName($groupname); if ($nm) { $groupName->setValue(""); $errorString = N("Group already exists, please choose another Group Name"); $continue = 0; } my $groupEnt = $self->ctx->InitGroup($groupname, $is_system); my $gid = 0; if ($continue && $gidManually->value()) { if (($gid = $GID->value()) < 500) { $errorString = ""; my $gidchoice = AdminPanel::Shared::ask_YesOrNo(N(" Group Gid is < 500"), N("Creating a group with a GID less than 500 is not recommended.\n Are you sure you want to do this?\n\n")); $continue = $gidchoice and $groupEnt->Gid($gid); } else { my $g = $self->ctx->LookupGroupById($gid); if ($g) { $errorString = ""; my $gidchoice = AdminPanel::Shared::ask_YesOrNo(N(" Group ID is already used "), N("Creating a group with a non unique GID?\n\n")); $continue = $gidchoice and $groupEnt->Gid($gid); } else { $groupEnt and $groupEnt->Gid($gid); } } } if (!$continue) { #--- raise error AdminPanel::Shared::msgBox($errorString) if ($errorString); } else { log::explanations(N("Adding group: %s ", $groupname)); $self->ctx->GroupAdd($groupEnt); $self->_refresh(); last; } } } } destroy $dlg; #restore old application title yui::YUI::app()->setApplicationTitle($appTitle); } #============================================================= =head2 _buildUserData =head3 INPUT $self: this object $layout : layout in wich drawing graphic user data =head3 OUTPUT %userData: hash containing reference to graphical object such as: full_name, login_name, password, password1, login_shell =head3 DESCRIPTION This method is used by addUserDialog and _editUserDialog to create User Data dialog =cut #============================================================= sub _buildUserData { my ($self, $layout, $selected_shell) = @_; my @shells = @{$self->ctx->GetUserShells}; my $factory = yui::YUI::widgetFactory; ## user 'full name' my $align = $factory->createRight($layout); my $hbox = $factory->createHBox($align); my $label = $factory->createLabel($hbox, N("Full Name:") ); my $fullName = $factory->createInputField($hbox, "", 0); $label->setWeight($yui::YD_HORIZ, 1); $fullName->setWeight($yui::YD_HORIZ, 2); ## user 'login name' $align = $factory->createRight($layout); $hbox = $factory->createHBox($align); $label = $factory->createLabel($hbox, N("Login:") ); my $loginName = $factory->createInputField($hbox, "", 0); $label->setWeight($yui::YD_HORIZ, 1); $loginName->setWeight($yui::YD_HORIZ, 2); $loginName->setNotify(1); ## user 'Password' $align = $factory->createRight($layout); $hbox = $factory->createHBox($align); $label = $factory->createLabel($hbox, N("Password:") ); my $password = $factory->createInputField($hbox, "", 1); $label->setWeight($yui::YD_HORIZ, 1); $password->setWeight($yui::YD_HORIZ, 2); ## user 'confirm Password' $align = $factory->createRight($layout); $hbox = $factory->createHBox($align); $label = $factory->createLabel($hbox, N("Confirm Password:") ); my $password1 = $factory->createInputField($hbox, "", 1); $label->setWeight($yui::YD_HORIZ, 1); $password1->setWeight($yui::YD_HORIZ, 2); ## user 'Login Shell' $align = $factory->createRight($layout); $hbox = $factory->createHBox($align); $label = $factory->createLabel($hbox, N("Login Shell:") ); my $loginShell = $factory->createComboBox($hbox, "", 0); my $itemColl = new yui::YItemCollection; foreach my $shell (@shells) { my $item = new yui::YItem ($shell, 0); $item->setSelected(1) if ($selected_shell && $selected_shell eq $shell); $itemColl->push($item); $item->DISOWN(); } $loginShell->addItems($itemColl); $label->setWeight($yui::YD_HORIZ, 1); $loginShell->setWeight($yui::YD_HORIZ, 2); my %userData = ( full_name => $fullName, login_name => $loginName, password => $password, password1 => $password1, login_shell => $loginShell, ); return ( %userData ); } #============================================================= =head2 addUserDialog =head3 INPUT $self: this object $standalone: if set the application title is set from the name set in costructor =head3 DESCRIPTION This method creates and manages the dialog to add a new user. =cut #============================================================= sub addUserDialog { my $self = shift; my $standalone = shift; my $dontcreatehomedir = 0; my $is_system = 0; ## push application title my $appTitle = yui::YUI::app()->applicationTitle(); ## set new title to get it in dialog if ($standalone) { yui::YUI::app()->setApplicationTitle($self->name); } else { yui::YUI::app()->setApplicationTitle(N("Create New User")); } my $factory = yui::YUI::widgetFactory; my $optional = yui::YUI::optionalWidgetFactory; my $dlg = $factory->createPopupDialog(); my $layout = $factory->createVBox($dlg); my %userData = $self->_buildUserData($layout); ##### add a separator ## Create Home directory my $align = $factory->createLeft($layout); my $hbox = $factory->createHBox($align); my $createHome = $factory->createCheckBox($hbox, N("Create Home Directory"), 1); ## Home directory $align = $factory->createLeft($layout); $hbox = $factory->createHBox($align); my $label = $factory->createLabel($hbox, N("Home Directory:") ); my $homeDir = $factory->createInputField($hbox, "", 0); $label->setWeight($yui::YD_HORIZ, 1); $homeDir->setWeight($yui::YD_HORIZ, 2); # Create private group $align = $factory->createLeft($layout); $hbox = $factory->createHBox($align); my $createGroup = $factory->createCheckBox($hbox, N("Create a private group for the user"), 1); # Specify user id manually $align = $factory->createRight($layout); $hbox = $factory->createHBox($align); my $uidManually = $factory->createCheckBox($hbox, N("Specify user ID manually"), 0); my $UID = $factory->createIntField($hbox, N("UID"), 1, 65000, 500); $UID->setEnabled($uidManually->value()); $uidManually->setNotify(1); $uidManually->setWeight($yui::YD_HORIZ, 2); $UID->setWeight($yui::YD_HORIZ, 1); ## user 'icon' $hbox = $factory->createHBox($layout); $factory->createLabel($hbox, N("Click on icon to change it") ); my $iconFace = AdminPanel::Shared::Users::GetFaceIcon(); my $icon = $factory->createPushButton($hbox, ""); $icon->setIcon(AdminPanel::Shared::Users::face2png($iconFace)); $icon->setLabel($iconFace); $hbox = $factory->createHBox($layout); $align = $factory->createRight($hbox); my $cancelButton = $factory->createPushButton($align, N("Cancel")); my $okButton = $factory->createPushButton($hbox, N("Ok")); while(1) { my $event = $dlg->waitForEvent(); my $eventType = $event->eventType(); #event type checking if ($eventType == $yui::YEvent::CancelEvent) { last; } elsif ($eventType == $yui::YEvent::WidgetEvent) { # widget selected my $widget = $event->widget(); if ($widget == $cancelButton) { last; } elsif ($widget == $icon) { #remove shortcut from label my $iconLabel = $self->_skipShortcut($icon->label()); my $nextIcon = GetFaceIcon($icon->label(), 1); $icon->setLabel($nextIcon); $icon->setIcon(AdminPanel::Shared::Users::face2png($nextIcon)); } elsif ($widget == $uidManually) { # UID inserction enabled? $UID->setEnabled($uidManually->value()); } elsif ($widget == $userData{ login_name }) { my $username = $userData{ login_name }->value(); $homeDir->setValue("/home/$username"); } elsif ($widget == $okButton) { ## check data my $username = $userData{ login_name }->value(); my ($continue, $errorString) = valid_username($username); my $nm = $continue && $self->ctx->LookupUserByName($username); if ($nm) { $userData{ login_name }->setValue(""); $homeDir->setValue(""); $errorString = N("User already exists, please choose another User Name"); $continue = 0; } my $passwd = $continue && $userData{ password }->value(); if ($continue && $passwd ne $userData{ password1 }->value()) { $errorString = N("Password Mismatch"); $continue = 0; } my $sec = security::level::get(); if ($sec > 3 && length($passwd) < 6) { $errorString = N("This password is too simple. \n Good passwords should be > 6 characters"); $continue = 0; } my $userEnt = $continue && $self->ctx->InitUser($username, $is_system); if ($continue && $createHome->value()) { $dontcreatehomedir = 0; my $homedir = $homeDir->value(); $userEnt and $userEnt->HomeDir($homedir); } else { $dontcreatehomedir = 1; } my $uid = 0; if ($continue && $uidManually->value()) { if (($uid = $UID->value()) < 500) { $errorString = ""; my $uidchoice = AdminPanel::Shared::ask_YesOrNo(N("User Uid is < 500"), N("Creating a user with a UID less than 500 is not recommended.\nAre you sure you want to do this?\n\n")); $continue = $uidchoice and $userEnt->Uid($uid); } else { $userEnt and $userEnt->Uid($uid); } } my $gid = 0; if ($createGroup->value()) { if ($continue) { #Check if group exist my $gr = $self->ctx->LookupGroupByName($username); if ($gr) { my $groupchoice = $self->ChooseGroup(); if ($groupchoice == 0 ) { #You choose to put it in the existing group $gid = $gr->Gid($self->USER_GetValue); } elsif ($groupchoice == 1) { # Put it in 'users' group log::explanations(N("Putting %s to 'users' group", $username)); $gid = AdminPanel::Shared::Users::Add2UsersGroup($username, $self->ctx); } else { $errorString = ""; $continue = 0; } } else { #it's a new group: Add it my $newgroup = $self->ctx->InitGroup($username,$is_system); log::explanations(N("Creating new group: %s", $username)); $gid = $newgroup->Gid($self->USER_GetValue); $self->ctx->GroupAdd($newgroup); } } } else { $continue and $gid = AdminPanel::Shared::Users::Add2UsersGroup($username, $self->ctx); } if (!$continue) { #---rasie error AdminPanel::Shared::msgBox($errorString) if ($errorString); } else { ## OK let's create the user print N("Adding user: ") . $username . " \n"; log::explanations(N("Adding user: %s"), $username); my $loginshell = $userData{ login_shell }->value(); my $fullname = $userData{ full_name }->value(); $userEnt->Gecos($fullname); $userEnt->LoginShell($loginshell); $userEnt->Gid($gid); $userEnt->ShadowMin(-1); $userEnt->ShadowMax(99999); $userEnt->ShadowWarn(-1); $userEnt->ShadowInact(-1); $self->ctx->UserAdd($userEnt, $is_system, $dontcreatehomedir); $self->ctx->UserSetPass($userEnt, $passwd); defined $icon->label() and AdminPanel::Shared::Users::addKdmIcon($username, $icon->label()); ### TODO Migration wizard # # Refresh($sysfilter, $stringsearch); # transfugdrake::get_windows_disk() # and $in->ask_yesorno(N("Migration wizard"), # N("Do you want to run the migration wizard in order to import Windows documents and settings in your Mageia distribution?")) # and run_program::raw({ detach => 1 }, 'transfugdrake'); last; } } } } destroy $dlg; #restore old application title yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; } #============================================================= =head2 _createUserTable =head3 INPUT $self: this object =head3 DESCRIPTION This function create the User table to be added to the replace point of the tab widget. Note this function is meant for internal use only =cut #============================================================= sub _createUserTable { my $self = shift; $self->dialog->startMultipleChanges(); $self->get_widget('replace_pnt')->deleteChildren(); my $parent = $self->get_widget('replace_pnt'); my $factory = yui::YUI::widgetFactory; my $yTableHeader = new yui::YTableHeader(); $yTableHeader->addColumn(N("User Name"), $yui::YAlignBegin); $yTableHeader->addColumn(N("User ID"), $yui::YAlignBegin); $yTableHeader->addColumn(N("Primary Group"), $yui::YAlignBegin); $yTableHeader->addColumn(N("Full Name"), $yui::YAlignBegin); $yTableHeader->addColumn(N("Login Shell"), $yui::YAlignBegin); $yTableHeader->addColumn(N("Home Directory"), $yui::YAlignBegin); $yTableHeader->DISOWN(); $self->set_widget(table => $factory->createTable($parent, $yTableHeader)); $self->get_widget('table')->setImmediateMode(1); $self->get_widget('table')->DISOWN(); $self->get_widget('replace_pnt')->showChild(); $self->dialog->recalcLayout(); $self->dialog->doneMultipleChanges(); $self->_refreshUsers(); } #============================================================= =head2 _createGroupTable =head3 INPUT $self: this object =head3 DESCRIPTION This function create the Group table to be added to the replace point of the tab widget. Note this function is meant for internal use only =cut #============================================================= sub _createGroupTable { my $self = shift; $self->dialog->startMultipleChanges(); $self->get_widget('replace_pnt')->deleteChildren(); my $parent = $self->get_widget('replace_pnt'); my $factory = yui::YUI::widgetFactory; my $yTableHeader = new yui::YTableHeader(); $yTableHeader->addColumn(N("Group Name"), $yui::YAlignBegin); $yTableHeader->addColumn(N("Group ID"), $yui::YAlignBegin); $yTableHeader->addColumn(N("Group Members"), $yui::YAlignBegin); $yTableHeader->DISOWN(); $self->set_widget(table => $factory->createTable($parent, $yTableHeader)); $self->get_widget('table')->setImmediateMode(1); $self->get_widget('table')->DISOWN(); $self->get_widget('replace_pnt')->showChild(); $self->dialog->recalcLayout(); $self->dialog->doneMultipleChanges(); $self->_refreshGroups(); } #============================================================= =head2 _computeLockExpire =head3 INPUT $l: login user info =head3 OUTPUT $status: Locked, Expired, or empty string =head3 DESCRIPTION This method returns if the login is Locked, Expired or ok. Note this function is meant for internal use only =cut #============================================================= sub _computeLockExpire { my ( $self, $l ) = @_; my $ep = $l->ShadowExpire($self->USER_GetValue); my $tm = ceil(time()/(24*60*60)); $ep = -1 if int($tm) <= $ep; my $status = $self->ctx->IsLocked($l) ? N("Locked") : ($ep != -1 ? N("Expired") : ''); $status; } #============================================================= =head2 _refreshUsers =head3 INPUT $self: this object =head3 DESCRIPTION This method refresh user info into User tab widget. Note this function is meant for internal use only =cut #============================================================= sub _refreshUsers { my $self = shift; my $strfilt = $self->get_widget('filter')->value(); my $filterusers = $self->get_widget('filter_system')->isChecked(); my ($users, $group, $groupnm, $expr); defined $self->ctx and $users = $self->ctx->UsersEnumerateFull; $self->dialog->startMultipleChanges(); #for some reasons QT send an event using table->selectItem() # WA remove notification immediate $self->get_widget('table')->setImmediateMode(0); $self->get_widget('table')->deleteAllItems(); my @UserReal; LOOP: foreach my $l (@$users) { next LOOP if $filterusers && $l->Uid($self->USER_GetValue) <= 499 || $l->Uid($self->USER_GetValue) == 65534; push @UserReal, $l if $l->UserName($self->USER_GetValue) =~ /^\Q$strfilt/; } my $i; my $itemColl = new yui::YItemCollection; foreach my $l (@UserReal) { $i++; my $uid = $l->Uid($self->USER_GetValue); if (!defined $uid) { warn "bogus user at line $i\n"; next; } my $a = $l->Gid($self->USER_GetValue); $group = $self->ctx->LookupGroupById($a); $groupnm = ''; $expr = $self->_computeLockExpire($l); $group and $groupnm = $group->GroupName($self->USER_GetValue); my $s = $l->Gecos($self->USER_GetValue); c::set_tagged_utf8($s); my $username = $l->UserName($self->USER_GetValue); my $Uid = $l->Uid($self->USER_GetValue); my $shell = $l->LoginShell($self->USER_GetValue); my $homedir = $l->HomeDir($self->USER_GetValue); my $item = new yui::YTableItem ("$username", "$Uid", "$groupnm", "$s", "$shell", "$homedir", "$expr"); # TODO workaround to get first cell at least until we don't # a cast from YItem $item->setLabel( $username ); $itemColl->push($item); $item->DISOWN(); } $self->get_widget('table')->addItems($itemColl); my $item = $self->get_widget('table')->selectedItem(); $self->get_widget('table')->selectItem($item, 0) if $item; $self->dialog->recalcLayout(); $self->dialog->doneMultipleChanges(); $self->_refreshActions(); $self->get_widget('table')->setImmediateMode(1); } #============================================================= =head2 _refreshGroups =head3 INPUT $self: this object =head3 DESCRIPTION This method refresh group info into Group tab widget. Note this function is meant for internal use only =cut #============================================================= sub _refreshGroups { my $self = shift; my $strfilt = $self->get_widget('filter')->value(); my $filtergroups = $self->get_widget('filter_system')->isChecked(); my $groups; defined $self->ctx and $groups = $self->ctx->GroupsEnumerateFull; $self->dialog->startMultipleChanges(); #for some reasons QT send an event using table->selectItem() # WA remove notification immediate $self->get_widget('table')->setImmediateMode(0); $self->get_widget('table')->deleteAllItems(); my @GroupReal; LOOP: foreach my $g (@$groups) { next LOOP if $filtergroups && $g->Gid($self->USER_GetValue) <= 499 || $g->Gid($self->USER_GetValue) == 65534; push @GroupReal, $g if $g->GroupName($self->USER_GetValue) =~ /^\Q$strfilt/; } my $itemColl = new yui::YItemCollection; foreach my $g (@GroupReal) { my $a = $g->GroupName($self->USER_GetValue); #my $group = $ctx->LookupGroupById($a); my $u_b_g = $a && $self->ctx->EnumerateUsersByGroup($a); my $listUbyG = join(',', @$u_b_g); my $group_id = $g->Gid($self->USER_GetValue); my $groupname = $g->GroupName($self->USER_GetValue); my $item = new yui::YTableItem ("$groupname", "$group_id", "$listUbyG"); $item->setLabel( $groupname ); $itemColl->push($item); $item->DISOWN(); } $self->get_widget('table')->addItems($itemColl); my $item = $self->get_widget('table')->selectedItem(); $self->get_widget('table')->selectItem($item, 0) if $item; $self->dialog->recalcLayout(); $self->dialog->doneMultipleChanges(); $self->_refreshActions(); $self->get_widget('table')->setImmediateMode(1); } #============================================================= =head2 _getUserInfo =head3 INPUT $self: this object =head3 OUTPUT %userData: selected user info as: username: username full_name: full name of user shell: shell used homedir: home dir path UID: User identifier acc_check_exp: account expiration enabling acc_expy: account expiration year acc_expm: account expiration month acc_expd: account expiration day lockuser: account locked pwd_check_exp: password expiration enabling pwd_exp_min: days before changing password is allowed pwd_exp_max: days before changing password is required pwd_exp_warn: warning days before changing pwd_exp_inact: days before account becomes inact members: Array containing groups the user belongs to. primary_group: primary group ID for the user =head3 DESCRIPTION Retrieves the selected user info from the system Note that acc_expy, acc_expm and acc_expd are valid if acc_check_exp is enabled. Note that pwd_exp_min, pwd_exp_max, pwd_exp_warn, pwd_exp_inact are valid if pwd_check_exp is enabled. =cut #============================================================= sub _getUserInfo { my $self = shift; my $label = $self->_skipShortcut($self->get_widget('tabs')->selectedItem()->label()); if ($label ne N("Users") ) { return undef; } my $item = $self->get_widget('table')->selectedItem(); if (! $item) { return undef; } my %userData; $userData{username} = $item->label(); my $userEnt = $self->ctx->LookupUserByName($userData{username}); my $s = $userEnt->Gecos($self->USER_GetValue); c::set_tagged_utf8($s); $userData{full_name} = $s; $userData{shell} = $userEnt->LoginShell($self->USER_GetValue); $userData{homedir} = $userEnt->HomeDir($self->USER_GetValue); $userData{UID} = $userEnt->Uid($self->USER_GetValue); # default expiration time my ($day, $mo, $ye) = (localtime())[3, 4, 5]; $userData{acc_expy} = $ye+1900; $userData{acc_expm} = $mo+1; $userData{acc_expd} = $day; $userData{acc_check_exp} = 0; my $expire = $userEnt->ShadowExpire($self->USER_GetValue); if ($expire && $expire != -1) { my $times = TimeOfArray($expire, 1); $userData{acc_expy} = $times->{year}; $userData{acc_expm} = $times->{month}; $userData{acc_expd} = $times->{dayint}; $userData{acc_check_exp} = 1; } # user password are not retrieved if admin wants # to change it has to insert a new one $userData{password} = undef; $userData{password1} = undef; # Check if user account is locked $userData{lockuser} = $self->ctx->IsLocked($userEnt); $userData{icon_face} = AdminPanel::Shared::Users::GetFaceIcon($userData{username}); $userData{pwd_check_exp} = 0; $userData{pwd_exp_min} = $userEnt->ShadowMin($self->USER_GetValue); $userData{pwd_exp_max} = $userEnt->ShadowMax($self->USER_GetValue); $userData{pwd_exp_warn} = $userEnt->ShadowWarn($self->USER_GetValue); $userData{pwd_exp_inact} = $userEnt->ShadowInact($self->USER_GetValue); if ($userData{pwd_exp_min} && $userData{pwd_exp_min} != -1 || $userData{pwd_exp_max} && $userData{pwd_exp_max} != 99999 || $userData{pwd_exp_warn} && $userData{pwd_exp_warn} != 7 && $userData{pwd_exp_warn} != -1 || $userData{pwd_exp_inact} && $userData{pwd_exp_inact} != -1) { $userData{pwd_check_exp} = 1; } $userData{members} = $self->ctx->EnumerateGroupsByUser($userData{username}); $userData{primary_group} = $userEnt->Gid($self->USER_GetValue); return %userData; } #============================================================= =head2 _getUserInfo =head3 INPUT $self: this object =head3 OUTPUT %groupData: selected group info as: $groupname: group name $members: users that are members of this group =head3 DESCRIPTION Retrieves the selected group info from the system =cut #============================================================= sub _getGroupInfo { my $self = shift; my $label = $self->_skipShortcut($self->get_widget('tabs')->selectedItem()->label()); if ($label ne N("Groups") ) { return undef; } my $item = $self->get_widget('table')->selectedItem(); if (! $item) { return undef; } my %groupData; $groupData{start_groupname} = $item->label(); $groupData{groupname} = $item->label(); my $groupEnt = $self->ctx->LookupGroupByName($groupData{groupname}); $groupData{members} = $self->ctx->EnumerateUsersByGroup($groupData{groupname}); return %groupData; } sub _storeDataFromGroupEditPreviousTab { my ($self, %groupData) = @_; my $previus_tab = $self->get_edit_tab_widget('edit_tab_label'); if (!$previus_tab) { return %groupData; } elsif ($previus_tab eq $groupEditLabel{group_data}) { $groupData{groupname} = $self->get_edit_tab_widget('groupname')->value(); } elsif ($previus_tab eq $groupEditLabel{group_users}) { my $tbl = $self->get_edit_tab_widget('members'); $groupData{members} = undef; my @members; my $i; for($i=0;$i<$tbl->itemsCount();$i++) { push (@members, $tbl->item($i)->label()) if $tbl->toCBYTableItem($tbl->item($i))->checked(); } $groupData{members} = [ @members ]; } return %groupData; } sub _storeDataFromUserEditPreviousTab { my ($self, %userData) = @_; my $previus_tab = $self->get_edit_tab_widget('edit_tab_label'); if (!$previus_tab) { return %userData; } elsif ($previus_tab eq $userEditLabel{user_data}) { $userData{full_name} = $self->get_edit_tab_widget('full_name')->value(); $userData{username} = $self->get_edit_tab_widget('login_name')->value() ; $userData{shell} = $self->get_edit_tab_widget('login_shell')->value(); $userData{homedir} = $self->get_edit_tab_widget('homedir')->value(); my $passwd = $self->get_edit_tab_widget('password')->value(); $userData{password} = $passwd; $passwd = $self->get_edit_tab_widget('password1')->value(); $userData{password1} = $passwd; } elsif ($previus_tab eq $userEditLabel{account_info}) { $userData{acc_check_exp} = $self->get_edit_tab_widget('acc_check_exp')->value(); $userData{acc_expy} = $self->get_edit_tab_widget('acc_expy')->value(); $userData{acc_expm} = $self->get_edit_tab_widget('acc_expm')->value(); $userData{acc_expd} = $self->get_edit_tab_widget('acc_expd')->value(); $userData{lockuser} = $self->get_edit_tab_widget('lockuser')->value(); $userData{icon_face} = $self->get_edit_tab_widget('icon_face')->label(); } elsif ($previus_tab eq $userEditLabel{password_info}) { $userData{pwd_check_exp} = $self->get_edit_tab_widget('pwd_check_exp')->value(); $userData{pwd_exp_min} = $self->get_edit_tab_widget('pwd_exp_min')->value(); $userData{pwd_exp_max} = $self->get_edit_tab_widget('pwd_exp_max')->value(); $userData{pwd_exp_warn} = $self->get_edit_tab_widget('pwd_exp_warn')->value(); $userData{pwd_exp_inact} = $self->get_edit_tab_widget('pwd_exp_inact')->value(); } elsif ($previus_tab eq $userEditLabel{groups}) { my $tbl = $self->get_edit_tab_widget('members'); $userData{members} = undef; my @members; my $i; for($i=0;$i<$tbl->itemsCount();$i++) { push (@members, $tbl->item($i)->label()) if $tbl->toCBYTableItem($tbl->item($i))->checked(); } $userData{members} = [ @members ]; if ($self->get_edit_tab_widget('primary_group')->selectedItem()) { my $Gent = $self->ctx->LookupGroupByName($self->get_edit_tab_widget('primary_group')->selectedItem()->label()); my $primgroup = $Gent->Gid($self->USER_GetValue); $userData{primary_group} = $primgroup; } else { $userData{primary_group} = -1; } } return %userData; } #============================================================= =head2 _userDataTabWidget =head3 INPUT $self: this object $dialog: YUI dialog that owns the YUI replace point $replace_pnt: YUI replace point, needed to add a new tab widget %userData: hash containing user data info, tabs are removed and added again on selection, so data must be saved outside of widgets. $previus_tab: previous tab widget label, needed to store user data from the old tab before removing it, if user changed something. =head3 OUTPUT %userDataWidget: hash containing new YUI widget objects such as: retunred onject from _buildUserData and homedir. =head3 DESCRIPTION This internal method removes old tab widget saving its relevant data into userData and creates new selected table to be shown. =cut #============================================================= sub _userDataTabWidget { my ($self, $dialog, $replace_pnt, %userData) = @_; my $factory = yui::YUI::widgetFactory; $dialog->startMultipleChanges(); $replace_pnt->deleteChildren(); my $layout = $factory->createVBox($replace_pnt); my %userDataWidget = $self->_buildUserData($layout, $userData{shell}); ## user 'login name' my $align = $factory->createRight($layout); my $hbox = $factory->createHBox($align); my $label = $factory->createLabel($hbox, N("Home:") ); $userDataWidget{homedir} = $factory->createInputField($hbox, "", 0); $label->setWeight($yui::YD_HORIZ, 1); $userDataWidget{homedir}->setWeight($yui::YD_HORIZ, 2); # fill data into widgets ## # full_name, login_name, password, password1, # login_shell $userDataWidget{full_name}->setValue($userData{full_name}); $userDataWidget{login_name}->setValue($userData{username}); $userDataWidget{password}->setValue($userData{password}) if $userData{password}; $userDataWidget{password1}->setValue($userData{password1}) if $userData{password1}; $userDataWidget{homedir}->setValue($userData{homedir}); $replace_pnt->showChild(); $dialog->recalcLayout(); $dialog->doneMultipleChanges(); return %userDataWidget; } #============================================================= =head2 _groupDataTabWidget =head3 INPUT $self: this object $dialog: YUI dialog that owns the YUI replace point $replace_pnt: YUI replace point, needed to add a new tab widget %groupData: hash containing group data info, tabs are removed and added again on selection, so data must be saved outside of widgets. $previus_tab: previous tab widget label, needed to store group data from the old tab before removing it, if user changed something. =head3 OUTPUT %groupDataWidget: hash containing new YUI widget objects such as: groupname. =head3 DESCRIPTION This internal method removes old tab widget saving its relevant data into groupData and creates new selected table to be shown. =cut #============================================================= sub _groupDataTabWidget { my ($self, $dialog, $replace_pnt, %groupData) = @_; my $factory = yui::YUI::widgetFactory; $dialog->startMultipleChanges(); $replace_pnt->deleteChildren(); my $layout = $factory->createVBox($replace_pnt); my %groupDataWidget; ## user 'login name' my $align = $factory->createRight($layout); my $hbox = $factory->createHBox($align); my $label = $factory->createLabel($hbox, N("Group Name:") ); $groupDataWidget{groupname} = $factory->createInputField($hbox, "", 0); $label->setWeight($yui::YD_HORIZ, 1); $groupDataWidget{groupname}->setWeight($yui::YD_HORIZ, 2); $groupDataWidget{groupname}->setValue($groupData{groupname}); $replace_pnt->showChild(); $dialog->recalcLayout(); $dialog->doneMultipleChanges(); return %groupDataWidget; } sub _userAccountInfoTabWidget { my ($self, $dialog, $replace_pnt, %userData) = @_; my $factory = yui::YUI::widgetFactory; $dialog->startMultipleChanges(); $replace_pnt->deleteChildren(); my $layout = $factory->createVBox($replace_pnt); my %userAccountWidget; $userAccountWidget{acc_check_exp} = $factory->createCheckBoxFrame($layout, N("Enable account expiration"), 1); my $align = $factory->createRight($userAccountWidget{acc_check_exp}); my $hbox = $factory->createHBox($align); my $label = $factory->createLabel($hbox, N("Account expires (YYYY-MM-DD):")); $userAccountWidget{acc_expy} = $factory->createIntField($hbox, "", 1970, 9999, $userData{acc_expy}); $userAccountWidget{acc_expm} = $factory->createIntField($hbox, "", 1, 12, $userData{acc_expm}); $userAccountWidget{acc_expd} = $factory->createIntField($hbox, "", 1, 31, $userData{acc_expd}); $userAccountWidget{acc_check_exp}->setValue($userData{acc_check_exp}); $label->setWeight($yui::YD_HORIZ, 2); $align = $factory->createLeft($layout); $userAccountWidget{lockuser} = $factory->createCheckBox($align, N("Lock User Account"), $userData{lockuser}); $align = $factory->createLeft($layout); $hbox = $factory->createHBox($align); $label = $factory->createLabel($hbox, N("Click on the icon to change it")); $userAccountWidget{icon_face} = $factory->createPushButton($hbox, ""); $userAccountWidget{icon_face}->setIcon(AdminPanel::Shared::Users::face2png($userData{icon_face})); $userAccountWidget{icon_face}->setLabel($userData{icon_face}); $replace_pnt->showChild(); $dialog->recalcLayout(); $dialog->doneMultipleChanges(); return %userAccountWidget; } sub _userPasswordInfoTabWidget { my ($self, $dialog, $replace_pnt, %userData) = @_; my $factory = yui::YUI::widgetFactory; $dialog->startMultipleChanges(); $replace_pnt->deleteChildren(); my $layout = $factory->createVBox($replace_pnt); my %userPasswordWidget; my $userEnt = $self->ctx->LookupUserByName($userData{username}); my $lastchg = $userEnt->ShadowLastChange($self->USER_GetValue); my $align = $factory->createLeft($layout); my $hbox = $factory->createHBox($align); my $label = $factory->createLabel($hbox, N("User last changed password on: ")); my $dayStr = $factory->createLabel($hbox, ""); my $month = $factory->createLabel($hbox, ""); my $dayInt = $factory->createLabel($hbox, ""); my $year = $factory->createLabel($hbox, ""); if ($lastchg) { my $times = TimeOfArray($lastchg, 0); $dayStr->setValue($times->{daystr}); $month->setValue($times->{month}); $dayInt->setValue($times->{dayint}); $year->setValue($times->{year}); } $userPasswordWidget{pwd_check_exp} = $factory->createCheckBoxFrame($layout, N("Enable Password Expiration"), 1); $layout = $factory->createVBox($userPasswordWidget{pwd_check_exp}); $align = $factory->createLeft($layout); $hbox = $factory->createHBox($align); $label = $factory->createLabel($hbox, N("Days before change allowed:")); $userPasswordWidget{pwd_exp_min} = $factory->createInputField($hbox, "", 0); $userPasswordWidget{pwd_exp_min}->setValue("$userData{pwd_exp_min}"); $label->setWeight($yui::YD_HORIZ, 1); $userPasswordWidget{pwd_exp_min}->setWeight($yui::YD_HORIZ, 2); $align = $factory->createLeft($layout); $hbox = $factory->createHBox($align); $label = $factory->createLabel($hbox, N("Days before change required:")); $userPasswordWidget{pwd_exp_max} = $factory->createInputField($hbox, "", 0); $userPasswordWidget{pwd_exp_max}->setValue("$userData{pwd_exp_max}"); $label->setWeight($yui::YD_HORIZ, 1); $userPasswordWidget{pwd_exp_max}->setWeight($yui::YD_HORIZ, 2); $align = $factory->createLeft($layout); $hbox = $factory->createHBox($align); $label = $factory->createLabel($hbox, N("Days warning before change:")); $userPasswordWidget{pwd_exp_warn} = $factory->createInputField($hbox, "", 0); $userPasswordWidget{pwd_exp_warn}->setValue("$userData{pwd_exp_warn}"); $label->setWeight($yui::YD_HORIZ, 1); $userPasswordWidget{pwd_exp_warn}->setWeight($yui::YD_HORIZ, 2); $align = $factory->createLeft($layout); $hbox = $factory->createHBox($align); $label = $factory->createLabel($hbox, N("Days before account inactive:")); $userPasswordWidget{pwd_exp_inact} = $factory->createInputField($hbox, "", 0); $userPasswordWidget{pwd_exp_inact}->setValue("$userData{pwd_exp_inact}"); $label->setWeight($yui::YD_HORIZ, 1); $userPasswordWidget{pwd_exp_inact}->setWeight($yui::YD_HORIZ, 2); $userPasswordWidget{pwd_check_exp}->setValue($userData{pwd_check_exp}); $replace_pnt->showChild(); $dialog->recalcLayout(); $dialog->doneMultipleChanges(); return %userPasswordWidget; } sub _groupUsersTabWidget { my ($self, $dialog, $replace_pnt, %groupData) = @_; my $factory = yui::YUI::widgetFactory; my $mageiaPlugin = "mga"; my $mgaFactory = yui::YExternalWidgets::externalWidgetFactory($mageiaPlugin); $mgaFactory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($mgaFactory); $dialog->startMultipleChanges(); $replace_pnt->deleteChildren(); my %groupUsersWidget; my $layout = labeledFrameBox($replace_pnt, N("Select the users to join this group:")); my $yTableHeader = new yui::YTableHeader(); $yTableHeader->addColumn("", $yui::YAlignBegin); $yTableHeader->addColumn(N("User"), $yui::YAlignBegin); $groupUsersWidget{members} = $mgaFactory->createCBTable($layout, $yTableHeader, $yui::YCBTableCheckBoxOnFirstColumn); my $groupEnt = $self->ctx->LookupGroupByName($groupData{groupname}); my $users = $self->ctx->UsersEnumerate; my @susers = sort(@$users); my $itemCollection = new yui::YItemCollection; my $members = $groupData{members}; foreach my $user (@susers) { my $item = new yui::YCBTableItem($user); $item->check(member($user, @$members)); $item->setLabel($user); $itemCollection->push($item); $item->DISOWN(); } $groupUsersWidget{members}->addItems($itemCollection); $replace_pnt->showChild(); $dialog->recalcLayout(); $dialog->doneMultipleChanges(); return %groupUsersWidget; } sub _userGroupsTabWidget { my ($self, $dialog, $replace_pnt, %userData) = @_; my $factory = yui::YUI::widgetFactory; my $mageiaPlugin = "mga"; my $mgaFactory = yui::YExternalWidgets::externalWidgetFactory($mageiaPlugin); $mgaFactory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($mgaFactory); $dialog->startMultipleChanges(); $replace_pnt->deleteChildren(); my %userGroupsWidget; my $userEnt = $self->ctx->LookupUserByName($userData{username}); my $lastchg = $userEnt->ShadowLastChange($self->USER_GetValue); my $layout = labeledFrameBox($replace_pnt, N("Select groups that the user will be member of:")); my $yTableHeader = new yui::YTableHeader(); $yTableHeader->addColumn("", $yui::YAlignBegin); $yTableHeader->addColumn(N("Group"), $yui::YAlignBegin); $userGroupsWidget{members} = $mgaFactory->createCBTable($layout, $yTableHeader, $yui::YCBTableCheckBoxOnFirstColumn); my $grps = $self->ctx->GroupsEnumerate; my @sgroups = sort @$grps; my $itemCollection = new yui::YItemCollection; my $members = $userData{members}; foreach my $group (@sgroups) { my $item = new yui::YCBTableItem($group); $item->check(member($group, @$members)); $item->setLabel($group); $itemCollection->push($item); $item->DISOWN(); } $userGroupsWidget{members}->addItems($itemCollection); $userGroupsWidget{members}->setNotify(1); my $primgroup = ''; if ($userData{primary_group} != -1) { my $Gent = $self->ctx->LookupGroupById($userData{primary_group}); $primgroup = $Gent->GroupName($self->USER_GetValue); } my $align = $factory->createLeft($layout); my $hbox = $factory->createHBox($align); my $label = $factory->createLabel($hbox, N("Primary Group")); $userGroupsWidget{primary_group} = $factory->createComboBox($hbox, "", 0); my $itemColl = new yui::YItemCollection; foreach my $member (@$members) { my $item = new yui::YItem ($member, 0); $item->setSelected(1) if ($item->label() eq $primgroup); $itemColl->push($item); $item->DISOWN(); } $userGroupsWidget{primary_group}->addItems($itemColl); $label->setWeight($yui::YD_HORIZ, 1); $userGroupsWidget{primary_group}->setWeight($yui::YD_HORIZ, 2); $replace_pnt->showChild(); $dialog->recalcLayout(); $dialog->doneMultipleChanges(); return %userGroupsWidget; } sub _groupEdit_Ok { my ($self, %groupData) = @_; # update last changes if any %groupData = $self->_storeDataFromGroupEditPreviousTab(%groupData); my ($continue, $errorString) = valid_groupname($groupData{groupname}); if (!$continue) { AdminPanel::Shared::msgBox($errorString) if ($errorString); return $continue; } my $groupEnt = $self->ctx->LookupGroupByName($groupData{start_groupname}); if ($groupData{start_groupname} ne $groupData{groupname}) { $groupEnt->GroupName($groupData{groupname}); } my $members = $groupData{members}; my $gid = $groupEnt->Gid($self->USER_GetValue); my $users = $self->ctx->UsersEnumerate; my @susers = sort(@$users); foreach my $user (@susers) { my $uEnt = $self->ctx->LookupGroupByName($user); if ($uEnt) { my $ugid = $uEnt->Gid($self->USER_GetValue); my $m = $self->ctx->EnumerateUsersByGroup($groupData{start_groupname}); if (member($user, @$members)) { if (!$self->_inArray($user, $m)) { if ($ugid != $gid) { eval { $groupEnt->MemberName($user,1) }; } } } else { if ($self->_inArray($user, $m)) { if ($ugid == $gid) { AdminPanel::Shared::msgBox(N("You cannot remove user '%s' from their primary group", $user)); return 0; } else { eval { $groupEnt->MemberName($user,2) }; } } } } } $self->ctx->GroupModify($groupEnt); $self->_refresh(); return 1; } sub _userEdit_Ok { my ($self, %userData) = @_; # update last changes if any %userData = $self->_storeDataFromUserEditPreviousTab(%userData); my ($continue, $errorString) = valid_username($userData{username}); if (!$continue) { AdminPanel::Shared::msgBox($errorString) if ($errorString); return $continue; } if ( $userData{password} ne $userData{password1}) { AdminPanel::Shared::msgBox(N("Password Mismatch")); return 0; } my $userEnt = $self->ctx->LookupUserByName($userData{username}); if ($userData{password} ne '') { my $sec = security::level::get(); if ($sec > 3 && length($userData{password}) < 6) { AdminPanel::Shared::msgBox(N("This password is too simple. \n Good passwords should be > 6 characters")); return 0; } $self->ctx->UserSetPass($userEnt, $userData{password}); } $userEnt->UserName($userData{username}); $userEnt->Gecos($userData{full_name}); $userEnt->HomeDir($userData{homedir}); $userEnt->LoginShell($userData{shell}); my $username = $userEnt->UserName($self->USER_GetValue); my $grps = $self->ctx->GroupsEnumerate; my @sgroups = sort @$grps; my $members = $userData{members}; foreach my $group (@sgroups) { my $gEnt = $self->ctx->LookupGroupByName($group); my $ugid = $gEnt->Gid($self->USER_GetValue); my $m = $gEnt->MemberName(1,0); if (member($group, @$members)) { if (!$self->_inArray($username, $m) && $userData{primary_group} != $ugid) { eval { $gEnt->MemberName($username, 1) }; $self->ctx->GroupModify($gEnt); } } else { if ($self->_inArray($username, $m)) { eval { $gEnt->MemberName($username, 2) }; $self->ctx->GroupModify($gEnt); } } } if ($userData{primary_group} == -1) { AdminPanel::Shared::msgBox(N("Please select at least one group for the user")); return 0; } $userEnt->Gid($userData{primary_group}); if ($userData{acc_check_exp}) { my $yr = $userData{acc_expy}; my $mo = $userData{acc_expm}; my $dy = $userData{acc_expd}; if (!ValidInt($yr, $dy, $mo)) { AdminPanel::Shared::msgBox(N("Please specify Year, Month and Day \n for Account Expiration ")); return 0; } my $Exp = ConvTime($dy, $mo, $yr); $userEnt->ShadowExpire($Exp); } else { $userEnt->ShadowExpire(ceil(-1)) } if ($userData{pwd_check_exp}) { my $allowed = int($userData{pwd_exp_min}); my $required = int($userData{pwd_exp_max}); my $warning = int($userData{pwd_exp_warn}); my $inactive = int($userData{pwd_exp_inact}); if ($allowed && $required && $warning && $inactive) { $userEnt->ShadowMin($allowed); $userEnt->ShadowMax($required); $userEnt->ShadowWarn($warning); $userEnt->ShadowInact($inactive); } else { AdminPanel::Shared::msgBox(N("Please fill up all fields in password aging\n")); return 0; } } else { $userEnt->ShadowMin(-1); $userEnt->ShadowMax(99999); $userEnt->ShadowWarn(-1); $userEnt->ShadowInact(-1); } $self->ctx->UserModify($userEnt); if ($userData{lockuser}) { !$self->ctx->IsLocked($userEnt) and $self->ctx->Lock($userEnt); } else { $self->ctx->IsLocked($userEnt) and $self->ctx->UnLock($userEnt); } defined $userData{icon_face} and AdminPanel::Shared::Users::addKdmIcon($userData{username}, $userData{icon_face}); $self->_refresh(); return 1; } sub _editUserDialog { my $self = shift; my $dontcreatehomedir = 0; my $is_system = 0; ## push application title my $appTitle = yui::YUI::app()->applicationTitle(); ## set new title to get it in dialog yui::YUI::app()->setApplicationTitle(N("Edit User")); my $factory = yui::YUI::widgetFactory; my $optional = yui::YUI::optionalWidgetFactory; my $dlg = $factory->createPopupDialog(); my $layout = $factory->createVBox($dlg); my %tabs; if ($optional->hasDumbTab()) { my $hbox = $factory->createHBox($layout); my $align = $factory->createHCenter($hbox); $tabs{widget} = $optional->createDumbTab($align); $tabs{user_data} = new yui::YItem($userEditLabel{user_data}); $tabs{user_data}->setSelected(); $tabs{used} = $tabs{user_data}->label(); $tabs{widget}->addItem( $tabs{user_data} ); $tabs{user_data}->DISOWN(); $tabs{account_info} = new yui::YItem($userEditLabel{account_info}); $tabs{widget}->addItem( $tabs{account_info} ); $tabs{account_info}->DISOWN(); $tabs{password_info} = new yui::YItem($userEditLabel{password_info}); $tabs{widget}->addItem( $tabs{password_info} ); $tabs{password_info}->DISOWN(); $tabs{groups} = new yui::YItem($userEditLabel{groups}); $tabs{widget}->addItem( $tabs{groups} ); $tabs{groups}->DISOWN(); my $vbox = $factory->createVBox($tabs{widget}); $align = $factory->createLeft($vbox); $tabs{replace_pnt} = $factory->createReplacePoint($align); $hbox = $factory->createHBox($vbox); $align = $factory->createRight($hbox); my $cancelButton = $factory->createPushButton($align, N("Cancel")); my $okButton = $factory->createPushButton($hbox, N("Ok")); my %userData = $self->_getUserInfo(); # userData here should be tested because it could be undef # Useful entry point for the current edit user/group tab widget $self->set_edit_tab_widget( $self->_userDataTabWidget($dlg, $tabs{replace_pnt}, %userData) ); $self->set_edit_tab_widget( edit_tab_label => $userEditLabel{user_data}); while(1) { my $event = $dlg->waitForEvent(); my $eventType = $event->eventType(); #event type checking if ($eventType == $yui::YEvent::CancelEvent) { last; } elsif ($eventType == $yui::YEvent::MenuEvent) { ### MENU ### my $item = $event->item(); if ($item->label() eq $tabs{user_data}->label()) { %userData = $self->_storeDataFromUserEditPreviousTab(%userData); my %edit_tab = $self->_userDataTabWidget($dlg, $tabs{replace_pnt}, %userData ); $self->edit_tab_widgets( {} ); $self->set_edit_tab_widget(%edit_tab); $self->set_edit_tab_widget( edit_tab_label => $userEditLabel{user_data}); } elsif ($item->label() eq $tabs{account_info}->label()) { %userData = $self->_storeDataFromUserEditPreviousTab(%userData); my %edit_tab = $self->_userAccountInfoTabWidget($dlg, $tabs{replace_pnt}, %userData ); $self->edit_tab_widgets( {} ); $self->set_edit_tab_widget(%edit_tab); $self->set_edit_tab_widget( edit_tab_label => $userEditLabel{account_info}); } elsif ($item->label() eq $tabs{password_info}->label()) { %userData = $self->_storeDataFromUserEditPreviousTab(%userData); my %edit_tab = $self->_userPasswordInfoTabWidget($dlg, $tabs{replace_pnt}, %userData ); $self->edit_tab_widgets( {} ); $self->set_edit_tab_widget(%edit_tab); $self->set_edit_tab_widget( edit_tab_label => $userEditLabel{password_info}); } elsif ($item->label() eq $tabs{groups}->label()) { %userData = $self->_storeDataFromUserEditPreviousTab(%userData); my %edit_tab = $self->_userGroupsTabWidget($dlg, $tabs{replace_pnt}, %userData ); $self->edit_tab_widgets( {} ); $self->set_edit_tab_widget(%edit_tab); $self->set_edit_tab_widget( edit_tab_label => $userEditLabel{groups}); } } elsif ($eventType == $yui::YEvent::WidgetEvent) { ### widget my $widget = $event->widget(); if ($widget == $cancelButton) { last; } elsif ($widget == $okButton) { ## save changes if ($self->_userEdit_Ok(%userData)) { last; } } # last: managing tab widget events else { my $current_tab = $self->get_edit_tab_widget('edit_tab_label'); if ($current_tab && $current_tab eq $userEditLabel{account_info}) { if ($widget == $self->get_edit_tab_widget('icon_face')) { my $iconLabel = $self->_skipShortcut($self->get_edit_tab_widget('icon_face')->label()); my $nextIcon = GetFaceIcon($iconLabel, 1); $self->get_edit_tab_widget('icon_face')->setLabel($nextIcon); $self->get_edit_tab_widget('icon_face')->setIcon(AdminPanel::Shared::Users::face2png($nextIcon)); } } elsif ($current_tab && $current_tab eq $userEditLabel{groups}) { if ($widget == $self->get_edit_tab_widget('members')) { my $item = $self->get_edit_tab_widget('members')->changedItem(); if ($item) { if ($item->checked()) { # add it to possible primary groups my $pgItem = new yui::YItem ($item->label(), 0); $self->get_edit_tab_widget('primary_group')->addItem($pgItem); } else { # remove it to possible primary groups $dlg->startMultipleChanges(); my $itemColl = new yui::YItemCollection; my $tbl = $self->get_edit_tab_widget('members'); for(my $i=0;$i < $tbl->itemsCount();$i++) { if ($tbl->toCBYTableItem($tbl->item($i))->checked()) { my $pgItem = new yui::YItem ($tbl->item($i)->label(), 0); my $Gent = $self->ctx->LookupGroupById($userData{primary_group}); my $primgroup = $Gent->GroupName($self->USER_GetValue); $pgItem->setSelected(1) if ($pgItem->label() eq $primgroup); $itemColl->push($pgItem); $pgItem->DISOWN(); } } $self->get_edit_tab_widget('primary_group')->deleteAllItems(); $self->get_edit_tab_widget('primary_group')->addItems($itemColl); $dlg->recalcLayout(); $dlg->doneMultipleChanges(); } } } } } } } } else { AdminPanel::Shared::warningMsgBox(N("Cannot create tab widgets")); } destroy $dlg; #restore old application title yui::YUI::app()->setApplicationTitle($appTitle); } sub _editGroupDialog { my $self = shift; ## push application title my $appTitle = yui::YUI::app()->applicationTitle(); ## set new title to get it in dialog yui::YUI::app()->setApplicationTitle(N("Edit Group")); my $factory = yui::YUI::widgetFactory; my $optional = yui::YUI::optionalWidgetFactory; my $dlg = $factory->createPopupDialog(); my $layout = $factory->createVBox($dlg); my %tabs; if ($optional->hasDumbTab()) { my $hbox = $factory->createHBox($layout); my $align = $factory->createHCenter($hbox); $tabs{widget} = $optional->createDumbTab($align); $tabs{group_data} = new yui::YItem($groupEditLabel{group_data}); $tabs{group_data}->setSelected(); $tabs{widget}->addItem( $tabs{group_data} ); $tabs{group_data}->DISOWN(); $tabs{group_users} = new yui::YItem($groupEditLabel{group_users}); $tabs{widget}->addItem( $tabs{group_users} ); $tabs{group_users}->DISOWN(); my $vbox = $factory->createVBox($tabs{widget}); $align = $factory->createLeft($vbox); $tabs{replace_pnt} = $factory->createReplacePoint($align); $hbox = $factory->createHBox($vbox); $align = $factory->createRight($hbox); my $cancelButton = $factory->createPushButton($align, N("Cancel")); my $okButton = $factory->createPushButton($hbox, N("Ok")); my %groupData = $self->_getGroupInfo(); # groupData here should be tested because it could be undef # %groupData: selected group info as: # $groupname: group name # $members: users that are members of this group # Useful entry point for the current edit user/group tab widget $self->set_edit_tab_widget( $self->_groupDataTabWidget($dlg, $tabs{replace_pnt}, %groupData) ); $self->set_edit_tab_widget( edit_tab_label => $groupEditLabel{group_data}); while(1) { my $event = $dlg->waitForEvent(); my $eventType = $event->eventType(); #event type checking if ($eventType == $yui::YEvent::CancelEvent) { last; } elsif ($eventType == $yui::YEvent::MenuEvent) { ### MENU ### my $item = $event->item(); if ($item->label() eq $tabs{group_data}->label()) { %groupData = $self->_storeDataFromGroupEditPreviousTab(%groupData); my %edit_tab = $self->_groupDataTabWidget($dlg, $tabs{replace_pnt}, %groupData ); $self->edit_tab_widgets( {} ); $self->set_edit_tab_widget(%edit_tab); $self->set_edit_tab_widget( edit_tab_label => $groupEditLabel{group_data}); } elsif ($item->label() eq $tabs{group_users}->label()) { %groupData = $self->_storeDataFromGroupEditPreviousTab(%groupData); my %edit_tab = $self->_groupUsersTabWidget($dlg, $tabs{replace_pnt}, %groupData ); $self->edit_tab_widgets( {} ); $self->set_edit_tab_widget(%edit_tab); $self->set_edit_tab_widget( edit_tab_label => $groupEditLabel{group_users}); } } elsif ($eventType == $yui::YEvent::WidgetEvent) { ### widget my $widget = $event->widget(); if ($widget == $cancelButton) { last; } elsif ($widget == $okButton) { ## save changes if ($self->_groupEdit_Ok(%groupData)) { last; } } } } } else { AdminPanel::Shared::warningMsgBox(N("Cannot create tab widgets")); } destroy $dlg; #restore old application title yui::YUI::app()->setApplicationTitle($appTitle); } sub _editUserOrGroup { my $self = shift; # TODO item management avoid label if possible my $label = $self->_skipShortcut($self->get_widget('tabs')->selectedItem()->label()); if ($label eq N("Users") ) { $self->_editUserDialog(); } else { $self->_editGroupDialog(); } $self->_refresh(); } sub _deleteUserOrGroup { my $self = shift; # TODO item management avoid label if possible my $label = $self->_skipShortcut($self->get_widget('tabs')->selectedItem()->label()); if ($label eq N("Users") ) { $self->_deleteUserDialog(); $self->_refresh(); } else { $self->_deleteGroupDialog(); $self->_refresh(); } } sub _refresh { my $self = shift; # TODO item management avoid label if possible my $label = $self->_skipShortcut($self->get_widget('tabs')->selectedItem()->label()); if ($label eq N("Users") ) { $self->_refreshUsers(); } else { $self->_refreshGroups(); } # TODO xguest # RefreshXguest(1); } # TODO context menu creation is missed in libyui sub _contextMenuActions { my $self = shift; my $item = $self->get_widget('table')->selectedItem(); if ($item) { } } sub _refreshActions { my $self = shift; my $item = $self->get_widget('table')->selectedItem(); $self->dialog->startMultipleChanges(); $self->get_widget('action_menu')->deleteAllItems(); # do we need to undef them first? $self->set_action_menu( add_user => undef, add_group => undef, edit => undef, del => undef, inst => undef, ); $self->set_action_menu( add_user => new yui::YMenuItem(N("Add User")), add_group => new yui::YMenuItem(N("Add Group")), edit => new yui::YMenuItem(N("&Edit")), del => new yui::YMenuItem(N("&Delete")), inst => new yui::YMenuItem(N("Install guest account")), ); my $itemColl = new yui::YItemCollection; for my $pair ( $self->action_menu_pairs ) { my $menuItem = $pair->[1]; if ($pair->[0] eq 'edit' || $pair->[0] eq 'del') { if ($item) { $itemColl->push($menuItem); } } else { $itemColl->push($menuItem); } $menuItem->DISOWN(); } $self->get_widget('action_menu')->addItems($itemColl); $self->get_widget('action_menu')->rebuildMenuTree(); if ($item) { $self->get_widget('edit')->setEnabled(); $self->get_widget('del')->setEnabled(); } else { $self->get_widget('edit')->setDisabled(); $self->get_widget('del')->setDisabled(); } $self->dialog->doneMultipleChanges(); } sub manageUsersDialog { my $self = shift; ## TODO fix for adminpanel my $pixdir = '/usr/share/userdrake/pixmaps/'; ## push application title my $appTitle = yui::YUI::app()->applicationTitle(); ## set new title to get it in dialog yui::YUI::app()->setApplicationTitle($self->name); ## set icon if not already set by external launcher yui::YUI::app()->setApplicationIcon($self->icon); my $factory = yui::YUI::widgetFactory; my $optional = yui::YUI::optionalWidgetFactory; $self->dialog($factory->createMainDialog()); my $layout = $factory->createVBox($self->dialog); my $hbox_headbar = $factory->createHBox($layout); my $head_align_left = $factory->createLeft($hbox_headbar); my $head_align_right = $factory->createRight($hbox_headbar); my $headbar = $factory->createHBox($head_align_left); my $headRight = $factory->createHBox($head_align_right); my %fileMenu = ( widget => $factory->createMenuButton($headbar,N("File")), refresh => new yui::YMenuItem(N("Refresh")), quit => new yui::YMenuItem(N("&Quit")), ); $fileMenu{ widget }->addItem($fileMenu{ refresh }); $fileMenu{ widget }->addItem($fileMenu{ quit }); $fileMenu{ widget }->rebuildMenuTree(); my $actionMenu = $factory->createMenuButton($headbar, N("Actions")); $actionMenu->DISOWN(); my %helpMenu = ( widget => $factory->createMenuButton($headRight, N("&Help")), help => new yui::YMenuItem(N("Help")), report_bug => new yui::YMenuItem(N("Report Bug")), about => new yui::YMenuItem(N("&About")), ); while ( my ($key, $value) = each(%helpMenu) ) { if ($key ne 'widget' ) { $helpMenu{ widget }->addItem($value); } } $helpMenu{ widget }->rebuildMenuTree(); my $hbox = $factory->createHBox($layout); $hbox = $factory->createHBox($factory->createLeft($hbox)); $self->set_widget( add_user => $factory->createIconButton($hbox, $pixdir . 'user_add.png', N("Add User")), add_group => $factory->createIconButton($hbox, $pixdir . 'group_add.png', N("Add Group")), edit => $factory->createIconButton($hbox, $pixdir . 'user_conf.png', N("Edit")), del => $factory->createIconButton($hbox, $pixdir . 'user_del.png', N("Delete")), refresh => $factory->createIconButton($hbox, $pixdir . 'refresh.png', N("Refresh")), action_menu => $actionMenu, ); $hbox = $factory->createHBox($layout); $head_align_left = $factory->createLeft($hbox); $self->set_widget(filter_system => $factory->createCheckBox($head_align_left, N("Filter system users"), 1)); $factory->createHSpacing($hbox, 3); $head_align_right = $factory->createRight($hbox); $headRight = $factory->createHBox($head_align_right); $factory->createLabel($headRight, N("Search:")); $self->set_widget(filter => $factory->createInputField($headRight, "", 0)); $self->set_widget(apply_filter => $factory->createPushButton($headRight, N("Apply filter"))); $self->get_widget('filter')->setWeight($yui::YD_HORIZ, 2); $self->get_widget('apply_filter')->setWeight($yui::YD_HORIZ, 1); $self->get_widget('filter_system')->setNotify(1); my %tabs; if ($optional->hasDumbTab()) { $hbox = $factory->createHBox($layout); my $align = $factory->createHCenter($hbox); $self->set_widget(tabs => $optional->createDumbTab($align)); $tabs{users} = new yui::YItem(N("Users")); $tabs{users}->setSelected(); $self->get_widget('tabs')->addItem( $tabs{users} ); $tabs{users}->DISOWN(); $tabs{groups} = new yui::YItem(N("Groups")); $self->get_widget('tabs')->addItem( $tabs{groups} ); $tabs{groups}->DISOWN(); my $vbox = $factory->createVBox($self->get_widget('tabs')); $align = $factory->createLeft($vbox); $self->set_widget(replace_pnt => $factory->createReplacePoint($align)); $self->_createUserTable(); $self->get_widget('table')->setImmediateMode(1); $self->get_widget('table')->DISOWN(); } $self->_refreshActions(); # main loop while(1) { my $event = $self->dialog->waitForEvent(); my $eventType = $event->eventType(); #event type checking if ($eventType == $yui::YEvent::CancelEvent) { last; } elsif ($eventType == $yui::YEvent::MenuEvent) { ### MENU ### my $item = $event->item(); my $menuLabel = $item->label(); if ($menuLabel eq $fileMenu{ quit }->label()) { last; } elsif ($menuLabel eq $helpMenu{about}->label()) { my $license = translate($AdminPanel::Shared::License); AboutDialog({ name => N("AdminUser"), version => $self->VERSION, copyright => N("Copyright (C) %s Mageia community", '2013-2014'), license => $license, comments => N("AdminUser is a Mageia user management tool \n(from the original idea of Mandriva userdrake)."), website => 'http://www.mageia.org', website_label => N("Mageia"), authors => "Angelo Naselli \nMatteo Pasotti ", translator_credits => #-PO: put here name(s) and email(s) of translator(s) (eg: "John Smith ") N("_: Translator(s) name(s) & email(s)\n")} ); } elsif ($menuLabel eq $self->get_action_menu('add_user')->label()) { $self->addUserDialog(); $self->_refresh(); } elsif ($menuLabel eq $self->get_action_menu('add_group')->label()) { $self->_addGroupDialog(); $self->_refresh(); } elsif ($menuLabel eq $self->get_action_menu('del')->label()) { $self->_deleteUserOrGroup(); } elsif ($menuLabel eq $self->get_action_menu('edit')->label()) { $self->_editUserOrGroup(); } elsif ($self->get_widget('tabs') && $menuLabel eq $tabs{groups}->label()) { $self->_createGroupTable(); } elsif ($self->get_widget('tabs') && $menuLabel eq $tabs{users}->label()) { $self->_createUserTable(); } elsif ($menuLabel eq $fileMenu{refresh}->label()) { $self->_refresh(); } } elsif ($eventType == $yui::YEvent::WidgetEvent) { ### Buttons and widgets ### my $widget = $event->widget(); if ($widget == $self->get_widget('add_user')) { $self->addUserDialog(); $self->_refresh(); } elsif ($widget == $self->get_widget('del')) { $self->_deleteUserOrGroup(); } elsif ($widget == $self->get_widget('table')) { $self->_refreshActions(); my $wEvent = yui::YMGAWidgetFactory::getYWidgetEvent($event); if ($wEvent && $wEvent->reason() == $yui::YEvent::Activated) { $self->_editUserOrGroup(); } } elsif ($widget == $self->get_widget('add_group')) { $self->_addGroupDialog(); $self->_refresh(); } elsif ($widget == $self->get_widget('edit')) { $self->_editUserOrGroup(); } elsif ( $widget == $self->get_widget('filter_system') || $widget == $self->get_widget('refresh') || $widget == $self->get_widget('apply_filter') ) { $self->_refresh(); } } } $self->dialog->destroy() ; #restore old application title yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; } #============================================================= =head2 _skipShortcut =head3 INPUT $self: this object $label: an item label to be cleaned by keyboard shortcut "&" =head3 OUTPUT $label: cleaned label =head3 DESCRIPTION This internal method is a workaround to label that are changed by "&" due to keyborad shortcut. =cut #============================================================= sub _skipShortcut { my ($self, $label) = @_; $label =~ s/&// if ($label); return ($label); } #============================================================= =head2 _inArray =head3 INPUT $self: this object $item: item to search $arr: array container =head3 OUTPUT true: if the array contains the item =head3 DESCRIPTION This method returns if an item is into the array container =cut #============================================================= sub _inArray { my ($self, $item, $arr) = @_; return grep( /^$item$/, @$arr ); } sub ValidInt { foreach my $i (@_) { $i =~ /\d+/ or return 0 } return 1; } sub ConvTime { my ($day, $month, $year) = @_; my ($tm, $days, $mon, $yr); $mon = $month - 1; $yr = $year - 1900; $tm = POSIX::mktime(0, 0, 0, $day, $mon, $yr); $days = ceil($tm / (24 * 60 * 60)); return $days; } sub TimeOfArray { my ($reltime, $cm) = @_; my $h; my %mth = (Jan => 1, Feb => 2, Mar => 3, Apr => 4, May => 5, Jun => 6, Jul => 7, Aug => 8, Sep => 9, Oct => 10, Nov => 11, Dec => 12); my $_t = localtime($reltime * 24 * 60 * 60) =~ /(\S+)\s+(\S+)\s+(\d+)\s+(\S+)\s+(\d+)/; $h->{daystr} = $1; $h->{month} = $2; $h->{dayint} = $3; $h->{year} = $5; $cm and $h->{month} = $mth{$2}; $h; } no Moose; __PACKAGE__->meta->make_immutable; 1; oÿ|+aY4o=pgE=chYs]d3BxfQlB#N`!pZO@&A:EV6ұ 8[}yLPq%!YEaG2J46taDp;5{eA>=xy!YJ1Ѯx&E<DFm̢KΞAc";]@ޭ0'7"q0%R0q2Am ИHܖFOw0߸u_b\ j4Lӧ_92^\f"Y:H L|$^y?7ImwkMAK<L'YuO ]2jH-:17^u14T/f,qI !nB+̈y}\!vz`G!!4m̆ ,1Qgȏ 6t pi^]VaS&Q[b5$c4$7։C$ XwQϓWbR0~%. JlD}(d\G$da]T~57Z`_g]+6 =V∥AzSQ/~Rj0@l]EJүyL[J~LIF,I@[6tM5*uc)+sUQrڍ`m?ܓ6;xHky/ΫX BȁB $j>dy̛G䄽5}0҂pΓx$D } IޖnǵSF#3$AOHw&bHѪRYGN8~p(d1brd5OTחžmK$[:QMJNe'=N/Վ ]LB`P+l]snTTL> 6" !3H3^IUւ8hc n`qzP"M^n]n;B^$Ea P9`M\&0~stu, l4vVa$ ! <TiDә8 9tJs߬7Xr^~$5YlyŬq֓ݚ0aN!eE[aY1>6/H c;5AțK*$λyp0"%Ӎ즉GXTi^Xs RRjeTD$2:"Q7F97yt)LJFB,T֦0Z{-)/ SLu!_ ,\"yHvnW Ғ<`f+yA+(ES~qR$ W>U8g(-;nԺc4^7CGAĸ7 pmZǙ'ba/f̍VT^G>)hUxf~5Mpi*~x>^*jW^^zZ^ވZɒf`-P漾mL[  21Q[CaśL+3 5A I%w>J&JG:,h|R[cjQ}F0Zm&i>"ԋ,G|3!mM$me$\AuaX@շrФ{3?)KC0t<7q$*au9U1^ Q5X\:/hiկѢ=ɋ||A*c)iBLUiyN8tm80],o)Q/BrqG3 UODJBM,lV d5C?2!`͊vV;ߟrE|v\0TWY)qғ淎bݧ'_lik"Hv+5\|q{=c/p]%4Q9@S|;k]k#aiYv)!8+~΅rǑc(;C \X<- @l0Ypb a{G셼K;UYC0QuHB\`9D)'E,U>1Wj(2 .;uCܝB.{*KlfDo ]e_>ڻ rj2 LV4Uz>ℽҏǚ`Oxz4,c7lC j:8QXI{} RJ+s`cӦ;!mbuQ{yvu&BɚZJṣ>x(&|xz+F=6^BoW!-J" &? CpkR*4L g  K^d qXdz_2`m)G{r|pCL~4"~?O"6xt%%ju]1L߄*Iܲ=FSPkIpo@Hτ~:/cթ dlSǛsxI=77F.87L3"QvO1#D\sQ lDg[`xHh+~I v%UC dJ,9|"ժ +Sy]Ex}#'Pg* bV @BD[〲C| < Ӏ%ٟr Y$/Ip%3 ]";{/! tGvYg^b#ѹ6 DfB?,;3AG&FwksM)=LؔB_!)v[ț1wlY.j,РEͿl$D)8+cu[4h[Z_{flBzX Tah#^"D~>$켜u8Ɨz6(n9HF?2`YޕP0w,wԐ72!X,: 'GH\=Ot1*T.FqkUxWКِhhe9@ txu4;> *9%/s7z*>deyLⷛDit jhPi<dw].膒Wfo%GL[ZQ9Sk;<;Ԏ~藫(,by-wt ~"}I~d/2oR@#.Y:) ~N)wcg#jX z^xt#w4 }8~h^KKL?=mv}+cj~PXfc{C݇fK5 !Xx~l"` AnGD VH6]P^RBQ4wQeJ;bĠ1I$|eЈ5R~#F@V>>UeQ;h姠MŨY#i;RtWQeKq .ȱNmG%}pv"؟ļ%*k,*~'rgyؗIө\z[օ(<1D`4{I D9;iN,Ry鏐 -WWxj 뙒2 z]h@sHSҴ~łUEu/&TQfu+.BKTMn_@m[դۂwr(cҶ.ME2.sZG}u$$houFy1Lԉ ++\{@/o ytE峧lT2% hK#$U4ԫ+`@]d }e췤CTmeZae`j %d(_} V4E|*p<,/). ~ݙ;O|Mjn9:NC;K$L\l~JF ټ%_*p}e.&Z/a pY"o\| FBu>jF„ z=EP.n%!zq^|0}3Bb3.,QO?S9dj]ziaʧW/^;?QǬNg04ho>=VecK߄|)bq%CCy\[WT-H!ӹ p6-SVq{.+y;wP!s=}t0<Ql1O*O\ cm~!HzzQȏK}XLOnȕ`1d—}YXZDZ:ѮEQJ'f3*AnGo3(}rv|co6 0νP7@Eym]l;`&^)U%(x#<L$4 j2P-Ĺc9%kR.= I]S)ӌ-CUYq놥ܵPW>C>.ܜup5c~L?Je<41z$DEm0[=]fn۱@:z4L3K/LFc0Ƃ=)rEO|yKVēl9KEFAѫVIe;,} |nHpkT7Х}EG !<ߊB"fiI[oT:/` G;WKmLsAFX>|>6ʕ 3Y ] !a7ZK@XLFKfG(z3g?D'1G@ Ɠ߰>"A]Wٴ `Ec`|UKТ VK{gRP|Gz/Ximba7 5rh6UK;ҏ+n_hEV_N \I w׿;d_*kr5~z`bE ; ܘ5N6cK n&լ{ƯpSZ&Pm("od;9Y]l=C Qܹod#BiӜ#ƉW>H7/voN)JQzzrCS,G7H};ۼl48:$r+T0ĠObi`Լgt3N}=494hs:˂LɓLaq_|Nj9E#V|1E |MR98X'&?%, R,۩av<:b8{9l5߯(a}/] }?΢}?[<j4BunA'@mۧ;bK^-yfn衣nc^&dbox u^kr|"%D趼TkBR&e lwNVoĪ}{5qg7Xn GXETJDc3hnCx4_[?B>o<ke)P)m v9%Ml@?C %}Y(/*l?s$ָ,-Fw/D94PT,ΗS +ˑеj^wg@Ra䡶2FEm:}$qj7PeɱUxgA?X]=.EYC2d1U$TDrZ1 ո51 y =`1f]IV>W Etcpғ;CdE6)O3{FT1 9`?=ک_TDM4+X$9i_lĄZxT㙑bI߁9fs}M+֑Im'_e`x̣X)HSsEfﭗ"AhS0CD9+AwҡrUjLSC[$>o2ݛD},JǕށSr$M*"Aڅf.ߎٌ01[4**n q'&9DCR* (vffw@u(G~7 &AV%2KkQE#Rգ̔<Ig8n4l#Ce~Szj8U(\S3aꭨ{(k(\^Zn -N4SF ]g^"w8=_OT g'ݓ]XB;aq8ʄkd+PZ#zAg;%O;i - D٥hAKYGc"l G[1_U?Rw`fprt⟔ GtD@^G5f!U+;Ļ&veM@2;0 %PiHTޠi;,Dn;y9,A)_g />dQ~U43b`K %WbE.rYVNyHnpHY ކ+:N)^[vIp_\=׸BlD"ӎZ}$v%l@Bh24] LO0Z6\ &E4U>鮁1 B|cW;CL1mMY{riL=UZ5|ƥN7b\Wmy~W^ϖy F28]^(P{NV2y0V+PU>_lNlNn6L3,=6A-Y3Zu3vqzvnE5\#/lT#S_?5лm)pϯFzgϬ+dP-N:ʽͨ_ FyxCLLt'wr03>}ga~{E儍2Fh08lɟ-M] }h*WrG2Г FT_%F1+u܇wKXmVĈ8ˠ6Vg{ܪ՛>vvB!_']VPoAjQHG>>Vp.^Ӕ(ƅӡKH]*^oR[^J2qUgw)TzaZs+/|i>\8 5FEc)kd%ml|[dLKԆFSl-'=*;D|\LxvP(3ΛW$J -+Õ1`B{ POm ̳ ɾ0p.s) j6/^jV"j]25zpA{!+φx/%?}:gP LIH #_Vq6{$oC &OAhx) E,^Tx3elb}3:5aBzM\5w㎙ t kGHT(yS6Ϥ1120on~$M N`t]ǟ:UrR:CR}jCH4l)ckrħ\/xPתT9%,I$'Br}3*L%8>hLQu93޷ %Q[92<Qպj"4]Oq]zLhHco:Q9}F1"z4`dz~zU9e&efs)ӁB+. pI`}+e9pf@]ᒷ>WmHŵ/oiH>b-)ٗ8)Z: N˷$M]x*$?9):jhDAiP쬃VZ0l.rP0* x^YBVX>R'c)..IUHWW Kv7dz1QIKQ;{9!O>} h1C6Z/e,nRe = fѦG:مn`()q~@jg18ɀ=dY5w<{iܻ6f$QN2ws3Jz##qS{wґ a >s f ZF/$*f !kMOc%rco_ Mz{d[V+tf:mm>|s(:)iT^Ɓ/{dgRsyыV ܭ2y0xJ(<&Sdr3|6P8t>\Ic?pÊb1Sb8sӁ(Wvpk@Oب ^?79"9O.Ml%9$7ЮALgw:1L4 5#-fGRCIg \&P3rwsTV"țމ;#9IZʼ}MsA?J1eLl1fjЩR8L:uDAw{fWK]?Ը|o]~]v6vk#ߝyAE #p(K ;,'ERWn8^ٌ=[hAI bED[8O X .=7'-+PVe5TN=u[c6!%.2~JI";7eC P[*-모/!Q_̸ÔĖ fTE%”RXo|͗5N*JjM6JGZSpub1q;4seݪG5Uޕ;}"E+@ΣEl#|Wxp!`-4k/`7 /0\m<:s6/·l/Sdۑ@uWt_XHڍǠP23ւ| ګ}wz7I&oTD WNYfA=J0 ]pO[4@ {݈+v+nɗ|Z [kd/R mӓ^iK-a`Ҵ $n8 V|+ߥu+ɏh<{s}*y03Eڠ TspHE2sw{C7 oaEt;O$P#Bb= baY8`^ /3+~*-sYS4y0" ~k5Hy97FHH=877g+s;Oo:|*LvWȡIpX#(| beΣyKv_1粫Y*[d:{806͍\U!oT'nU"1'C[RִLDi܈#jzTKFgRFPrY#lJ UD-}9$mí c].b$gwӓYLtF7ӅyP\2yjI%r0l.M\w㹿' ߳tRA ^7ߎʔwI7& h@t:Q*!'ٻ+1Z ^B/sZ"Jɘ  a$ps{-m!%JXh"4Nc3݇pYq?)&*UIY;ژ9,M _ȧ83ϫ7n>ŒDSդjN)o 䭔`rrfh"1ב=LI[^@Y= xI}kp!몈{oJ IqSg7`^F_;HCJy珬;HeLi7Qo`e7s?Q9,DN#MfkqHy)ZvFy[_|Fm+X)_"M=Xe4M@U!cdBFwLO8[!ٳb&:@ϻ M&Hd IҮ(8@bb?] { 4TT s%aB,u޵,;,z_TفŪkŔGneg,2#}a*s@UTJXjMNv@U VmU<(;v bN'6f=%+k?su]_|ẳŔ=eKON'rtOiL}?jU\WC:=fv5%jIu)3!T-lu]-Y8{xW 0򙪿]8>}ry\aꑵ5[ A)Sz}֞ >^ ظ~ƛ $5]iT X,FE?苼49Bm}L}_q]e4T؁P5o:ؤ_n`mKY~䩌&:yCbxR|Z]bmP fd 7Dz$Cmޫ)Gz7XR׿ٍM!jseSQAt%2>sNs`ΘUHr߈o&HߧQ_2)>,vǔmC'z{<.C5 9oViI~e)ba,NK]'VykN! j7KVXA7rz:2<&n~1;5F}" B;K0-=[9T^?,WϿ,ɗRP2ZЈhW_6 S4ةw2fQǠŢ BR1\V&EZBLvega,oX~Y=bղRak?'LY}kuZtV'@I\GZ4 iYM~v/Lݬ l"|ȴ_M,~i4 ˯r:aE\J؞EM"ELa{fx4g&(, ( @$- ?9g)k(XUDP^N(gg }uK @mƝ)뫜lǐT;5]z .]J z|lhO9y_m˄2p aUl d:LD:4}^)+,Hɜhy)kPOБs2!7g[(E;OtȘ<ು'JqQw[EQ<"쵘DQalwז{][rԈSoPDy &O$Y{fʭ6:qeYPfZ=I4z݃> n:l]`ejiy=#+.+UGv68- 1DNcf:~!t`´ۤ9 /[Hnyek_E_G{#l`# ?Eڕaȡ P%7~_ssDyƨ?'/y'Dz,v6yځ]NW~d<휞9f\0] ii) W+m4& j5MѿĝS {,Tmv($_S kõ/yZ"z1cky@ACWѣMlgˑʐB4nd)@UUv QKZ%G#ffE__ ӚʩFes[mWP{o Кn&tC٧"쐒2\ E>XWGF_\ƉΙKG(0`y)f稑#,x{3}* t0@rKӁmpud#!3xNb#j" l {*21э 2\KK;b ]BዴI bNnk+*ig+}lr0* ^iQ-.t ]XR;}`aW Z[S~zo8EZ0@Lb $[ 0F`Gw<PFmJd`sa_qDYEVLO=F%Lz&<&ǰC5}# њ̝,J}6SSӚTR4:e Vg\Y%x=-'-] (^gy;`lAigT6z0 XAbZ(.\K'br#Y" \- \PNߵJBn!Ԧ ;'4րb>h嘬hѿjzw m6FFP8sK`јeNj\E|2*{ )U~ O+!P+^(oZ 9Z,! P d= E;-ZٙV5TꏯlվU<[gt3~hg1N.46kG1RJ)zQV0seջEHnA][A f b}6B+ijc"\lG+!F~'D4ۿHi+]^ ^$%0q}0lDeaFQį%6qoיyl~i֘LJ6V%VT#l>I::4GM#KVx6j-2R&Y%i)bRc1G !1|^K0޲RsqH>LJxNb@ũPwUa+U"ts@}=ǣB7oy vO4%DB % T8qSlUָ'mKOa%eT5}EAհh/,OR\ ̞Dz4/^Q!M=m&$txzd("%BaѷTOhXB2ءy! EoeD\i%ۧߑTNHY[a5Gd$ 5S$0 `l`x=g!KHUX_O&& AVBwt$#aE/".;ܡO(4Vbש7H-oMv3'B%ԣk!WQZ׸Tu e&47`5Nq1®?>x79)S3{hRΖn9j_<;pow@J7>*+dj$t4lG "T%F3 4"Bs @%Br'I466kn1֜ H3.A%!@o KNAB"HtV"ޮLS_O p]{&C($%| 7Rb繁M3K(\=j ,&˛w]¶6fgGPd#ٴoRE uPo} "^սK(7 x),KLpg?UR{ q?KI=p/(n$J i]fW1FRb?8RCz'Q J7]~M6p+eC3n!0ܣM} [$% ܪU?op;=M %YЈc! ]7[)h`Z +3ow\.`'1/HYPāi.[_gB`fMȪsYD9JMrzJY!FsوBŕ-?- :K\=u!Q3Ej򚮬g[>:?un.Ҏ  b])..$Nd_`h~K 8#?E6AUYEzDu׬09mGiM#*zozkct>vi?2Ly6A3KBh8F1{KF_gI˦:;oh?,jPҕ '`DY$qb t0W%_+Q!RaJWTk:UTdr{)9Hco59S˜ s6qyƓ.6,^̡lG_`?j 4wgm "T`}ZQEwtMeER2)m81YҌU.yB#>85$m`/~/|9I5yLꜵ®Զ;oWF^|Zr9"Pxdp5n Nz#[Z(,Jrs{!S:D7.]LhoaQVzm_ ٽ&-SY^Ub/̶CMlojo.9 P̅@vG3Q b%-qu~`a ,3]ke>^c%Ī0h%416kݎ2Tz|!OTnVҒl6r3"JHPc Sl\Vd{iQH6N Mt ߸~9U`]N c 29#V҉YM6z̮x5,GAo  tceT1=T +K v R˂߳drw:Cn <*GèͥS.lv lٜ?NoyCXPA5ae5 ٖ"Iz "ۜ Y˼ ȦkmH3#QRJu.+hWާTL:×kqmC& 8_+.hU$\5oDYFBTJh> vC6H+m~ag]JЫoğR7OQ7kTq~/A{`}'ɖPOtqwaZ $]z')& WW ʗj.Z~ UJ?HP\K@JT-JAE+c!ŢcTœ0"MOw0"K S3}%^˖^1Kƙ9QDōTa)Gi(,?ʧ&m?S{ws,̸27_%LCEy 2żkfknй\O@>udX2b6b5T%JF|_XٞyL?L+0J3?9U~hr.Er %'qX7jX9BE~.Idj׭g=ƶ#jdeНQ6d(N $ ʐlAe)(3sVsS rr%ͽeݰD# L7RUykTgfۧup|maHtj@Ż4ӌc KoU=Xa ttwZn"b$/:Kۂ+L.(aJiDsBI6*oC-\ vk-TOU)#*V:Jb `kad4B ӟبxX[ʋ&Rj25u;1eĉ*Bi^>m*K:_ҡɘW˕; %)-xA6TvB ˆ5,T[@{<ގֻ(ܽ(ĆJVB`tJobiN#9hͅ4D9G>;aق1I zSwtaӓ^w&XjoN`k]<YRĻhKm(ӡvn|O *@ՑI2z g\gǓ=>cj[^kۭΑl4;pC}jgJNm ʰo "Iْm._B틙Lq0M$톉g~@4ʅZcp2|Die5O?UN<ŗ!QE*p<у|BAbI ֜( [/i˃㭆KIV-AP䞵)%[d '38T2%wdBuoG+P hE3=l= l?IQԓ;g[gtT?V~W0<{we>h>L?4]/BAL!bz6^52PwA3?X❳!FLP=gC'"Br_D/__ϰP֕/am6AthP(mi,is:nKH"#ݴ@>i,GeVT9Xn.h=ـW8،T,=,#ڷIp hA4wܿ/e5@;lRt-xClӾ\+tj=w7ZbOY>]=9r53г-s !:mG Nx1b(slS7]h"VjP{66ڟĆ;0/s`99!O1V)IXQB"۠vod( 0V@q@Tuũϣ-san7տA> {nL2D%FvetNN<>&/r(dQܖ6kVGjdv'<2s.C5FYD+/WZ^2~W{h~87fi8rTIFCAk^hc rq XS!]:4~93pmK7- #?8m- Ef-BF㟾C+W b6oLܓ}ldCr%k "^4kK= _ 6te\Ӛ~ ʓx}%]oO 粭i4eח6E'|"/D=hxWٿ(GVh0g<}8?(\,uIScD;l*َd .p]wN0B`Х94r:vfFovOXf-Tp0Ty}rرWu?yU4t􉛹&I-zpHFc"<10!33.x6 HX+d5v9cVfMCȐ9oq,]_>yPe)wak%W, l`gZ w3I+@9YdUdѮ췇_j!h/3{Afwfsl4hMInb}q=@Di@wm}6|eN2 8&Q.PuvHS>OhY}:B)-cW6uȎEYI1mrߕu{ RF:07@h5omn(jFq21T0W1Gg&82F^%ij>v%thdvg:?>Hfy:Q,=̀rkx  ~U{IK/~ecm╴ 6 90 EV`4OѴ G:짃uaUгݼs_{=4]m 0~[E- r5 4AK_BF\~KJFQo6g&l2dBr ;,4/3֋wB_&ZaMT&}!,ݒHlqz;͉¯_U2#-zJ㓗\[H\rv蹖K%[gO9$(|}\W+@^>{&5ԉ6(UuCv:Mfw@%ءZNډY`$^wqX2pE;T!"adQLNSao0uAӇdI(HQjٸ25;0};c,IEЧ2܃hq[Qk^f6 :[Eft2:Is2E"hM*^c ^@3atO`_*xegIl27"A<@l^xAH9a_JB(Kd.!B2 m!x~(Ow,Q!Ŧ:P~H;^'󤸮]P 9D(±f$ 찜m[%s=3ut͸ыp; =t؝0mu""p=f>Eľ^ Wzu>3(XPrìYG7@LV%5CភU>zV3RY Bj(@u/L x/ Q:agkEP }mn tAa%J?a8g0lB3B05"e!K|sNFLh2.W]edMK1)UL% )Ae\}M. 5H➨:1mpM-&0g9YE=hiBFob3~{RT0*3>'˧t<2""\s8W5n~U RqNU슝؂c/\pIȲNpRƃEI؜q_>T!Yv?8nPtvrHF9%ĆxCg$~5x]K(&f\4,ƩH2%NBuCF#k Ո=e )x;ߵ宼`vVd6CI볠uJ gĥe dRBmxlj9eg痎mcPxiꋠ.@;[ 1ҁЀ8V.A`g" ЇoNq '%y7; 9}F$=rt5]'(;[6/܅_>XʡH1Cm _tXw@ƭ♱^@U'3X `tccNk1G1Z[5)9HqmDLG0-,'tzeN>\M߲-iu_(6۰޻a,(3Bu'0!*Xa]F˕UvtGD z yQIɂu2 ftȩMx1{dAG䰄UEKV (agG4rMdϝV^ ֋!bB 駴tY!!_XJ7\giuh[r{bЮ+9cEz]6TV` >]iWҷ g̷nȴFX A=;ygS`mэP{,)Ɏe0V:,1Aj& Og"5B i0@[<5񫮸M)RgtM0ՑI/,VԳi`7(/="U2ΉEhD2)hƩVuE&mlP nI"79p{v J@ߣ1K~4vvC / n3 0^[U@,Frd['3su\|⺾uCGc ݠ1h S;v$d§(9I 1bgb 0F' ^b\G2X-tUi TQtSOL&Zllf⥲p2zR/|7e]3GQ)Y_ά O;Br::"Q2{2o+)iPܨoY/%.bB~_ O&}MϾVeє ڿ'bܹHYJ1vAɺx/]&n\A41dQ׶) ~IYjB9 S HjeE \od_x)Vyl yLLYc@pN-wcʗvKt @7䞦iX2;GX r5R)79,tǍ;'VuT !jYAS=PN^G/m5Q ט@'v`Zϛ [U lg.#$3lovx dYq8|득=uRysQ q+4RP4 <]GhUc2;"#93Xw{A*3 Һ:{HR@O.7WNLmv-엮B+^;P>hj !V ,۳`uVtHFUW Md UQ>3 eRFSh]Vd1A>|LZՖ!YMkggx&@p #˽Wa`#ӦXKTS~Ã)_aQ#=Зb+oqϪ{FnpHm+g*7yBtvFDNZYF&KQ0Tq+&9íe-gښUY!y4/nc|DF TG$V;5 K?xEqG.ޖ|[X%}Sߠ 됍!AHsjS+5nD(^%|뷡I^B=좤ӆm-󼋪a-6ɀN%U2jajGf3JG!]{Ax*E-#xM4U~j~>7 kHwn~vUeKAZr0Ig).0Fir^%#XZN\%婥_-n0?GˆFx9xqo"D᭡Е/Κ% vvZ(x6py xWy(ǻnP7,4 CPv32>տ'<7Z,TsT~;>%7żvs {<܅WWY=h~JboIѲV_4bWAsK uv&$)+E\kb!6}4`Þ''?L®>$J wMЍI#]0/#nȞ&n=x5k؄E ^{?⥤FCjn6* *a^|o9*db)14 =#FOtԿ^T]m^bX`=eF}]-0}Ɵ ƌ &\ŭ^!{b C1Q9ˍ)k_ ئ{O=pcт2Z~4VYHO^lz왩I=[/2 ͸gXD!KƞZW%կߴNfl%WZܗ>KT W#guvpY =2}.8Nl m)  bP {[2sT@i Öv(A]tJk|2-s2mv>`/C/v`2)յڥL5_ڇ"JfonR@q/2(;9BXMOtEvP+1O_A/O?PFYeRtVZDk:n-o\ mm69}CJ_htނ|abw1N*ddkk}>/m4͐-[І^O^v^-WA31TZf+ף5d4}G?d&G_6<5j%~cyjG+@NC( VɅ`%VgqW4 B͌u،29BG}B2҆a㠛ީWF$zO5ӦH4?.?kݚ7&  ܅Njbyڎ\t8:l EUа_ JBMt#w>cO+a.EGԝtY'+y@Rw?%]E֥<Ka!FfUwʭݦ-cnshErBPw'/!F26)4g;mh0}BϨ\?ҴҡUQ;8 u& ,jX;X>}N%2A-!9(gtt5zoj[` J3K~!/:gTB ¡dk:E=ht{m@οa١f鿎 #3p^ӜOPR5CRy#++G8^!GiQfNrF7D/+z֪kMs}L{݀#:I$i|^_(M-SJDSnoi[<|4uWC=*[?dx $|S⠰A½sʡB6}3S{n8Qt1OuIbWgk~2C/W6S4RB<#&o` q͚u$+RhݚGi{a ΥÞl 3b 239Q_ɱt Gv)뫘\%JL8[qIg *=)JE%*J@_C(+dR &oHעx[`<<Ӻ& 1OIoi5@*J8l[(EBLnA(gLHd gIAEYډsB329$ TR҇ L^Q[o@2!ہd)A1rkm@I:z@gv<$UpU-դHcѫEKETI3FL$ƥ\ZB9(- $HVDAa$a0ʯ#hBɃ1%#ˆ@ 'Oa9)h`#Wn#g1ֲiP?upDQh(Ǧ ^]qv)͖Eo1]j17:Kܩ;~ @zG}1pK@u n0-"OMeF9RH[se18ƇHbTAM9̈́]b7E ;͒ߊrL,3Ac*,l{Q^^D̃WmpT-es|aksٚFM5ys=!=,6QG mmϠif(fT,F ,;^8ǎ4w.[Ҿv)@\zwuh#_^2ȫc/ l9K)~5 4Fй٤cXft| =v7]=0 vbg%> vt9Qq.#;I~r!Z+Pz<-š8EnDѪ̕){!=P̭YZ41Þ<|߮4TV3|;߮dF(V.ʷ.GCEZ#@U-kA5 BD)I{ns;fQ"0' mb2[ $qUͯ&$Xql;m!pN_4g L!u|px o!lTQhU _[>*MA"kh92۰ $5ۡߒ"#x:orqD'VXtS_9$נ'E pGW U"'}r.m^%ý:z¨P$z݇\'D(zvΗ +Tr#7J)W$C8\a;x&vr{ʤR]`eWu1RZ%tI(m僝!┺ [MCR-L.L\F5Bg"RD^"ih4S'!hpJ)g9up-*?צZ]&ġ"a^.S|漘F$z +TT;8ok~&Fq)y#Uc_]Z>?_q=-5P몲bMl< 1 hR}gj-P;=PSz#$.Hʓ?kv±Uł Ro659VRD7v3e mEjפ3YO#7x?DT_`EP ߙ%osIХڈ&Dn^v>`mK9q)JH-;gS- MאtSBV^V /Lui ~w&wԹy#5>ϊ|ٹ kv+qri-/b-~ƀ }Zqj*wgm&M?˭%DcC?[Mq4!@.7g'ӑSŒ&UsK{.[zp%stfh;{yX :AnZfXU\1Z>?h@]94aT;Rdcl*9r O1|kQ9 O!gߝf+mjw7g~^VZ44ӕ㔨gv&H7e# Қn .Qk411 lC4!)uW n fKL=VEEŊmCu~d+}s\C?B O\DRNPR$d$x+1#SQW^yԫZogf;ç)Z0Cc z\iC里WZ ǢaH$Xkս&.s}QD0uf a4֐5I1λ>k٠߳[& &z[?a57{<߅iLq*Lb[1{wa2QޘKmg ˕Or]8c4E!ȐRNR $3E͎2eڠ3#WnP]brUJïV`:2.H bwOzH ci0DXRSzb8.j?,P?l1FdjW{ִg9M_P\_CŒtbs<9Ucn!AJn9e~)VpD3Vpjqd+wKqFFk-|9%Џh,ґD R_ .XSӮ O͢dTFMf Ԍy`UUHupʹ_$C+>&Q3%kg3 bDt32Y/:t%b3O4a>0Jogfn{/7UF|p사WpC\X.h\;a|>yU(j@ dϳ6C;ǐMY75y!u="R^}P3%VSUk.Hon' B$iDcGX9\w)$) @LRT[bGm[{%">e҇[֯5u H<^^ĨAM_*󽊩&6}\r9x0VxCh6zC(UgXm9XI9ZZN&)I99Bħ2i$NCx!J4Js:Sh_#qu_W6 ߣbXLV'3( @eeI'1SkzP*k'D f/#`.ygog^LK'ExI ,&̵^ʲ|6-s;.E$%X<օ+ ~3rfV@郲#_D/T,VKc∅q5  |hY"]G\AoO,FcDpQ >J~MZ3vȥisn7dayK@bnQ: dsdE~ٞOĂ_ZѻO Ckϥ{Ѣ2wNגtDMаǕu~f"T ǃ0B)» tc _1GI"lW2q 9@ax Bd[v`|6Ee ۯGSzkiN+rY*1g#s7ZB6yMR(t#EZ6l aUu :h^( %ﵸ0/U;)_M+=6~+{wĶ8ExF͓Hy(zJt(_"1;}NT;yƒyRu_{h7QEuHƚ$ -Uj2NER8Щ=O 9F7@Y!ioWtKr ԘJ.>Kk mB^Y׭ ԥ <ҭSDr+Y޲HKc_[K޴f+n!SM$ 1(醞>T-y2FzQ+r<8K}G۽U8fU*¾+ Ў/fUx xή#h9IdV]r%>8TKO19EAƁ'$O™GG̼R6je,Ыw"b;Lk?μwc-wx.>j(8xfr01W[uS 󻜻$KcCJv\\4WX3 p)goeeD-#UIdv'h!^o R2r1Aie)ԟɧ.=TjE)Q7ІLTȸp]@u!&ЄG^=re_K_mA N[MéСEM>|x~r#C܁}Y8rSQs4R>y)}eM|G!qhBΆt>2v ?r<xOyh$=S™W}O1ŞѨQMMk lb>>pNXS˧n`ɦ,Iօ"xOp"}Sm&Ymz H>B:I*6s|_Uª`$7Di*wɽp1.#Rܪ&/` v3N@- ]o!m=kJANu2 @ /ɳy\[>U@ښM7{ VN"<( 5xݝ}gkpj^_X 0p{PݓNFK%IgbhEZyW$!HDW䆱pਗ#u~4.EZRQ -CLvȍjZu6{K9 ڞ.*Ue1 VٴіWkVft4/=9xd`W"!tL<_s7]c.atIMǞ6٬%:r]0#ÑgI=6d%>hspQ4paQeMlb8C;]XX=tǮeS=`f˳Xj`+_nFhݎWn?h:?KSŌ_PgXzT9ӿ:KdnYE[E߄2Ð5ͬQw|l=h5/jRʿQ,Oh-M[eE\G @̻v74fH ]Mī"MXl~I_uTgvivx]3ak5i'{nK־_o&9lV>yn{Oo`:e*?:.,5N {1C9;6D흯x!nܓvIقzB'#0iZ;*Qs\ x7P@d3EldOiǯCFP:k$Z=opp)FO _5@lɫ9b̽:ddpҖ~c[&$U囹34rBC;DwU OP밓hU6}WaX--G;>~Ʌl&TzQPku!R\kА#F)/ C`M7'qZa]y# 3~WG?ƛ]l H9eSQeJ+!~'G7W]=^ G*] +S5'.m3}GgtmEHp@ghqˑ/dRSz~PiRӈ|N\2&SqOk>7qE[~eϒ:]{-2a4$2܂AҊd|h @?ZokPۙ0pż~+U"=uτ`<ߖr~ FIcyG%j IehSlDF[19|3g?Ï Wa&$y' 4ٿev+֌<.vPPɕ„DZ,~qLiSah.MSLk0"6R1yOԽ@W,-O.w(LtkPSj~zzZ ^lʐVR!ksd\1wN形MVo^ªt>1#OﲾsMړsn'=1Qb4j⽤p0C[qIKN(*\"zsx%x 2\V~B@z\44 h۸PGH%bӧ/(ԗe3:^IhxB5QS-HEB dhj^ju=:K4+u~ExDF/ƬvmbJlmP<@@0u`v2U"!{ dx#8WyQ~OyŽdopއi_@ ÿ-EN\)(!T?c?1_^rt,gЊmB;-s.>=):mu!~]pPZVoCn`Zw6wtqM8֓1w?R11^iJ=#K!J?#R|9C"U&grzc5}( [|ߡۃR՘P% Գs0cP]9袢E6qZn8$S4y^jSdg7$c㽡DLtbW酡6h=2W~04vld4ollUE-k`D|rK64Sfr 30hӪpҘ'py%Tz/Jo'Ib"A[lryh%N;B(GrsǺwf  F軑3U[8E97L.GP,|1oy 4UrР`+* 3Xnga.b1b ;JV/SօV: ч Jm&`+W|7Sm!׳ [ ݺLzƎfD){,ɬFN͚fK:vk3MX-k&I܀€[,LR]dw\&vqy0ښW)) ɇP*d8-D5C==Q| d l;V@`h$9'n_vO!-~Ƈqbis&@sH| ]h?͖sBe&MA9`&\.R+ PԸy֢1kSm4#J?z"CƘ@4Tl^HZݜ`C"'6eqBـ%!gFuon.1f==w̥y O 4|2(F~F;e^F;vIĪQhVJ:% Ys^L 9W>FoԼ]dQUtޕ6eAY`kin #qzH B 7x{SSW=݀ (ڿ._\zcp9YÈ1uFI\LUpQs!si=0n 32ӂ'c1k {!GAEu:ב V-mj|+H0|ckUoAѥAM\ugnɉQn}&qzP(X+@$0o.SCۊr&s>~wX%OpR lӲ0@[댞}хǸ[nAvZ]=$}' 50^0%Gj̖jOsɸ30y ZITA\8Eu`%$X{'}h>ׂPy atAjhtNɧ ?S[(1\KkpClU_gTIBت8Ϟ,~oZa][ |=D8}T:{=\a|Q5tYM" 7 Z"BsZKE#d`[K"ܬ=Y.;C[Eg$#&T2\ʮ?O/D6C61sati {? CLuo5nڅŽcVTHzI^k1)˝5\yeCSY)=ʄ8 Ǟggҽi#e5@cԝ3P7+R<' UuLEp3$Sh0`]XdwxWt3x;?_FVt2  Q3P00͘h0Уӻ^3>w6VHp!K`? )^i:Ut\%5]vWG1q!HJoQs!؛}O/WdƸ)aRR3T]:Uaqnfd^$2KB>l:نUtQT@`U&.>.4^F@ZfͦHQZlh 9ATø$mv6Wl!mqz Nrt D#18 NPTZ@ZD"raL4yN I뾘3MwFDN+,8V Pd-lzi)ueCyߴA2uW) Ww=47Q~(YKпL [E5~cRz,}/Y169Ɏ}3⬫][WLqb2x֚$N?::ybG+&>y$Kݢhr0ZSvlpHEѵBlњSi.f{ _j4p|Vtҫ/J^\"p^^JMfNϊhEUܠӁqۥ/4Yn rp%蒙89ue~lDGVh㖃a&{օ,ʌelSGHz y'rVK?H̪J䱠kS~Ohf?y27CWc"Vx(/vl^o4꨸ eu6n0 s-f낈}( *Q5)^~8<;QX1C)^˯gӊh-u况C6 YԐ>܌~[qv;oHf0s5xiΟX l-A9Il3"%yf7M7Gg 6AyEܰYy֔9[CYa1I΍^,z0u+TF@2Q\DS.UVO沾F)ꖹ^WJXl@S vPHPt<~)5ֱ{2 ^9۽ /̰]Y*Ϭ g/ǔ \bk.{hĤi<\Asg3# V)6um<X7c  YQKEZucWP(1qX;"˨QArJ$ !8J8DvK4CXMN8J6X2n+G>ؖEP-1BȒi6n#_ZixKoJe"rKz< W}"H^"p:VA`~% UUMf[>D7oLh#zy4{\!USӉtп&/!MTEn1<LLρ}GPJˈlVku[g-Lrr__aRit&Z*%鲳zy:x҇3ϭ"ǥ^iH㚤'D>g{=4;Cj_ qg(-F<%Dha蜘5+>7wVWqv޼%pf߇F<ޗX1,;38;&N /Gz\VP4/58 FۘKn!XFH|&ySx{!Y8^fE,&zAs*MKdzi|%r?6ʬea-Yv㈆ДahLIN廀T `6'K@WmMwd.SgL3r3) zn,%Il\] nS@XO:G3KV@ s)l$Pf aVݠ)~R?Nt4QwKr\y'g{\Xkxa #L{#y MN_kawl!òY*jؿ4uN'yfr:;Y+1'BUR6Tp3H[ e0< ,z.v4>y|yUd{t8,(*phL#. % Lw#]nĜ<lrpHlJ2ɶ)!NZYr<9 IЗB(4@RG),='+*|gB]mڳ޶}N-7%]!#$%0|}!3G ( z eޫQUZp+ gWlw{7}bC"DOxݛ\&B_QЀPO*-W-⽯a}:Vw-pN%IJLi~;>!Zax\):f b%C(mZ[nl)99>'rޫyǻXhb!8n(pD2gYE+, gouhg$jAnjnaxaDuL^TNУp c/v^_]]b!J=Coa~HI:bBEG}ҏG-1 NM0'k:q$ib֣7&Bf5?,-oF憽YY")Fc6@#4+G"g Qr/e5y}OrkNnVa%V+3ip5U3/Dƴ.Mb! -N,dxO;>uETmn lk!{' 8^TxHOM`WZhݿ= ë)xT5J/Xz#$n k|B.zd@F(&gO1‘reR:Yn`qƽ;gNWE/ u~n07$ZeGNP9ekO_U H̐u;hB}70U@G/j$76psbpT]x^^)Z~iO@ VllCG |郬XU#h JI޷`;J Rvsȓ ] !/^X/$m5~/#.,6xI̿BXMG+O㓮cC#"g?n ̃a{uQXd,.{91ihGVhc{n1~"ZsX =K>99 [73֌p&*yj`,:%!cdR?:͹[CӷnY3YnH8.ezf,3mNv݂ (;ҷV1d#=%!5E`0x"3:<`*n] ShDfos̱h;IDY6;[e1PE"S5&UTL[Tgf}Gou{ShCdѻQqf{s?,( {s ڛE2,:вyR$v/K+ޮDi 튞f_W5?\i/X?eotN#=QK >MS?5 ؤR-"wq|aJ :^K䳡UH3; <,<_Ft$mOBX3 U47rpN['\[%>;%51.o4VFvXOf4lp/v̑{FKbI~Kcʒ0/U#%:R=V.]_9oc<&"#d"o E߼o5057[@įp"h6;~_C0-mzc5_96,3qn\ӵ:Gbq&6]pT^mp7@O("0MZ9eb<,E9@?4 [j O]8#zIJY]* z,ҍqeʷ2`ZR:}x@-̊<٥Xb.Ղd&)0by`a172at>6ƚQV}z`Ynf/%Il?Ѐ0C1 µPWmͨw%-EX2"G]`92B_^̙`؝D eRk_NZ[m⮇v,8&1Fwq0SSEkë&u UϦ3E`^|PяU>WwX0Kr`eN>#R=aQ@*ƝÉPsVF4N~;7x ًJ8uȲ%{M-l~ڹ<31-qmM(C ߑ²Jb;|_@CR$&Tz[Ѹ\( PSfA\nms鍃;*I!с zſggf/FTW@|f-G#0 (Lrޫ^J!ȮN}P3)[x9oŮ1|wx>4ճ\qFt d d@'qk_5tT[ )Gт" YT"o? K0&ms쾫 Ic;*ޝ1JihѪ[$x|J/|Q:{S#Ik6<"&騕oZKi}靑;>9&4ocY; qLxÇ6+ӛ=UA3( JKVLb'DDM|"S3mg`/r:s%iV\a&?½!qc^%ٖ{̸t;a3sY^ùK~ػB :2;*.aΗV% <bN5CJ!^NwBxCCGL8$6E̎chq]i P3wuxWd7BG56:X'7OJKsi^lt0QVzk3|ݔSe.xe6)>([.dN]s .J%\k%V˵3-Lg25GtOH3v]7LyAXVLA |ۋtɯGTTNᙠp%!u&+Y Qoeݒ#IR'۲1u?ik^i{ǥSL4UOz{ɶ%3i ?8CȞsNg MC%I ;W"HIY$4t~ IĔ_/ 6;4Ho LY 6w tde>?P6 <YGiRXfs¯Qy'((gS^:^*eB RC˖6?tYtd! [#pGj#"ɥEnmK1^e/ٽ JoXYM&RS>^/,ki4 )bY}9:h=_4R2be:Mj8w7e㤰_B8FID;0n0|WC}73o^9he5}D8t+D=~a|XXP>'_.+# c({`q^op%Wd݃.T{5Γ[QNj@V-F'yFHAQKmjwNg&z \0%*Y:AsM< %6!qLHMN!Mن֔ct3$yDS]]/+&~c1v8Utnc|W@͡tg畕/Nj߮X釾Y]6K>'DXTDU6UƬ~},7\¡;w@ gqu>S:%U5tF2d_3,`n{> oؘm8rSL/zتAa uq&F)TDbj_ߏՇK.ٽwb&:m7{l۲K6?s@<,Jɷ fFϯL>Nv+S@2tKʔot<8*'?X[y8ig(Z~ge֦Ys9˘:Clbc>M2"b|rI`΀1Hkch-FN^%Dǩs]ZE=`^9'fx%dJT1[8~-SJ#V ]d!frUm/"fձT!z2GUjg@;Wf\AG08X\zKGDdA,5ɓ[Q+S#z$XkD2Aq/?EXLS3\7ʨxa{SU gsD%lA)!';pGC("nP]:X3RãKdᚇN~k'ô0*~XqY酖w7x⻞ {ehm~x!Uh-i=˸zvXH3f+H#>$( [uTcR/P13:#Vt-ª례6u/zܮɷ4e%.g >GPa/9@<< ȟ?R%2q-Fr, G|i%V=rI%ם5"+Ί OT)^ocG~(_5ԅ:nhуb,e-ߧJg=K1mjO7q51`tC{Iϸe7 b` YqZa上>$ eZQcH\'#bU|W!Ҡ=)X/ GF9ә-uWֱrCMBrRIx7$/9NaCK$Q}6VKO'~^30jNQA`qbی5 e[f=Rш۹L_e۶w+i&`p> si'pJ풔CFhp<ݡ{{(-owSy c"}Sun_)?(3e;j."C#ѕDa:1侎#M+n yR#^gm y*@:liȤV5"#>kF`0A\O$sp;"-,tzBGLL'X;,/Ҕy-n6ϦJ\`u 06y=F(%װ "*J (kW Qyv@̼(M;I;3'%E`vd|訋GA7_`-%dd.v(p,3tE IuM7yʼzD;YC=pd:7m`h6tY[C$z":wſq]GrL|z @ݓCɹ;oo_W3UY Jܒ8{'o^EF PR5+Qq,Um+aW@d^J#@2R=e Zv"ԓP--1=L iW+]}UYR¸pm7juɼR\΋eܾoł_DaޑбS,6 ğOjP`i?$t:h m\mLjK ý(r›geE@[TzeaZ eR1mS<'U": n yBNFuh%X5ρ.;3I75n"Uۡ& fJksez)E"fB-pa3˨'VQZis>yTI8 z[1irhmwJN(YrJ a>܅')lZ+~>,D[Mx-֚b/o o\x O5>%kȲ& _!'a nު<& ᪖ńz!Sfkn~(y@)7AG7HiUp:wSDԬm6+`>~$6,͢ 9.jsU tS0,8_T2')HT8O\Q{5bܙcJ8.TEͯ#8d@W{|j5rzI 4LԣoVL#oMh]>f C .g))Bq 6a) , TV25zZ(D"xA RPhlݣȊIUńܼú&U4D^ӡ܆)n+$晀ѱ١):'k>Cs?LPIl*>Bp;HJljq55Qi`C}*F9y74+. P 4נtR\\rY:@l5W C,}UFK%S,Ϛ&~ixB@1v S~"P5iw-ջB)N]s4Ѩ*M{*]Tѷ=iKv4N1UAb$[iXUk$xn݁p +k4iDՊZ@@rqovAk%z=QƁTNܻ~W5}lZ+1[KjRx:l =!" ;%w<2Voj2W@we^C@Ι]'#f YAd/:`^XX?= 񬼕H=N-oeOȝ1,9 cÙ )3])2Z)!ӡj.GzRs5Ml>NdS?H|[S/> (iX?Ŝ ;Hu/M! RKn^̐g%sd]^GN^žDnc\[צU`'UdNu PŔlHŢu$baIYgVɚ\;ç ;<hD1*U&LXE_[^M [$v]oFU4 T-[3+ 1p4<7*o. 8G]!hXbo\Ǩ }>*u$L|3<9S?z6969]z@3ʉ:N7nl;ld4ﱁ 2qO8Q5xRml}Yl'\#y 4.wv%Z]d ӣ0ŞlVEj}QҗFvK@BLpBEGjrnY ]HX&h5G+ɨ|ƓI1O;C:DLB> ̏96co$̲1"*Fr9vR C[E=q$={F]Ö~>-HC}(+׆ZN9\~H fT$rd'5٨6C79_E\$N x(tcKQ05ϠsjV"Z|zKX~; |Y$D*@n$#e <>t-^.YrěUɾw-*EU.d?OUF [CSjKXXY}!ѿqO63݊F20^d=ĨQ/SeҼ; ӍʐFmKS" 5ZSl&KQF0إ@<:>1\Iߪ/u hL"b08ņKf\Ul'&m!-u>\ [=}KD/dy)3@q`9?72|iG4ӊ*+ rE[u?1:0vyp[|ȨQۡEF}Il3_N c `2 fT,5B6PޘJeeHv! "NPxSγO۔D|-6\'cHfWdCkژ][T9YJy8@Ww3n3%̥lMطy^  {,jLG **n"gPöxfhR9,kubv X 6ݗ'Hww7HCAy,d3ȧ$noXeJ|{F`:p7|T{)s5 Ll 5aFZ lCG;ΎSG T];{3^b|wSɣ([0EcեJph)۳ێ">oX9FĖوC.r%;Y{(WM@]0lS|%9BcĪI Qu 46[[_w.ۭl8|gADwxMpaFJхѶ=ɏ0 fr@R $!&eq%X+S ܸiۍח;ǣ |bEX]hogA8}R^jSH5pX |wu.z,8v!z>zgdZL2;J }\d26ȅfŹjFQg*:D ?N񔌚9:@cDqywE=33L`18-9Φc/`y6\E#jﲲ^~îab,`QM`dGj73D5u؉ WU_ގFP3ƌo.JzKx# _`ט:xr|ׅC +F>Hk3UXG!!Np3wiAX0)8y$gGX"W뫙cV7xʽ$@GΚ s>w8Z,2rh*ck#qu>m4BNF!z"=ihmqAph/}Au]Sg_ ЯmmW:I%Cb /ֲ[ZQs m1 &o[ ҵa<\7;t+W'^vA%2ٿOD-RI %/iSobJK:'n [RC :^4E^M ga}-}50Kdb ^I Xx<%j}93Dz34fG䫁^:!Lf5Qp m<Zs91y~itͽyJs w`׷|AW!n~n!L.J}Zz>H@ǃu4&壧瑇lJO@ɬ)fFU s/XM()^%7E?vEhKPl8%*. .*ms]4E^bpu99;q*pfneIB{bB0R\A-M2+ң@ej~XMk,&A͛Vݠ 3)qt Mybw uVat]1֧cl$>WWehO$QC Zu5*z]yzK@v;ὐg>1Åglf cdF.?'3(nL_{L 2A0Mz0VE@+ӲORaub%]s޷c9, k-Z\h/Aqr.xk^]b % 0c=yQ-RN^AcԲs!,걳SYT}QJ"' PbOQ*@|QnKGlv$Hfp2O*[~5k9/Y?_rFh9rbTu:xo41Xc2 n%zT|>iZc,tJ""[12<>^ZkHw;StsL9BeTE oX6-vs1AuߥϢP]> q?K_>MʡGf BuSZ]͇Dv/L> PF`x,H7bi 4!> 8l!T`.{32 O͉5>wnb?-30;{49h-l[9xe 10J̌-䍽/ 'O vӢPjXB;nC_;QqjjDQm#&ݐfC^DHr_U,]qSCe@ oGWMGq8Z͙\G`Vg]!IY3R̲UTfw` DL$ eui'Lg &7Ẍ́\ޭO/302a;_/"Ӳd:Okp_*]{gT.DxMdJ1txb?yz-^l[݄%_&9D)5qc CC&xB!.ņ_2{wKOZVڜ=n<M ܽ+˯7c_Wds zZZҸ)mŏu=oa%rUu%":kg [u N:Cu`PXbxWQ [eN6 oi.UQWU+wrJB"XҒlK:[FIeIƟyl@%|;a9`ΖU C9#Ǥ`\donҥsKv +Zt&c䐬)M i-~)̬- XiIY'bE,O6(P8!dۛ~kSKPN~k tZ{bzRUT Ppv[ljg|Hhf_ (k^2׫qrD/էpƶ.fVLkѴ8b>057S59<ϭ77].TJ]VY=Ir6& z;t4M38{yv '; YAΓ7}K6 Ix[IigLRuz瘝b~EG8,&ǿ[i e#戇!Y7)MMRk~~]A;nNͨ-'8]lkwB9q߁{^p7! 4n]>I} $\:(^(lLb4E&\mZl4+ ,hSP${S] ӴUG#Z5,),~-xGhay4񬌒e;}*f d-]XWZ:2|̮Ty$6kn/#d0DS 4v=YbȒ͚%D>`Sc:=XIo=J-t>T:űrTB+\Ȁ}%ҍ{L;Ƽw6&4l;ӂOڮ,6nH>NzGI«5!] WsMD}7H}{WSkQun6xg@]Loww~l/ޞ{`̘gA ׵!!2tAƒۺiԿk;Y4Sﬗ 0C9aLFq^/*¬1Hro6bPkzJtOs$`!M@0vdFET||\J$c wFͅ!sc -}?$s~cLE7 ca/q=qIbnл1 ӽ@T}gK&FfLaPs]:B}\M)sp#T%3s ̊s0(1C-YLoDP0fYIoVp}|{}e) 6')J#gޕǂʠb\M7d \{\w)-:͜ӕ+ - |žXSҍc鱒đ l lgaQ"O+y xop|=.ll/TXAĦ)(L~FFI^~e-גiOPּ}o;B<+|}A`˂]ގnWS=Ľv`r"ÿp<ƦqΔ n~g'& ١d.ErLKY6/VD=ISB1al v`J0^^[vSN|g_QC3,`HF(g=Q;ŧͫ0uhROq>R5]͟l˭^ 84g/r<>AͫMٷ v7_nO(˟g\lQ߶k h~(9\jv  ˄ƭN5KwǓ(ݹ/u)P+uO)R:i1 ]2)*ef%' !Xdkv⌜ٙ5rb(Eтਐl7W~Vzッ)$ӻOѣzl f|+^r~HWq>cf| :͌BgQĮ>Ԥ0A.tigXY Ho?[Ո+Ĵ_vj).P~0CNxa1TÐ34OϯuPif4\W{0|,|NDŽ.x8:^85A'4T5h)6+#ΰNm 7Cn#!1gr25GG47')X)B0f'A v ^Y4+ʷ{vo`- ;]Qkn.F:jb*oD3*6ϼ Ã.RqDtBbITz r!?5&wbT7w(G0VJ-\_^ UlWF1k&7K+T H^۴OkޣeKc6 *ѐ4ۻ_Y? eeMB|s rġuML;N/iKumZV+OL NU ؾ̿׏8vqړ r|4*o;m[ԜA+ռ^׈&CC/rxd#gJܡ>$adc\4Y%`8p\zRvZu佀{̶d6P2#~EbK/ǿvĸwlhqdz{^{r*MWd'pޗ^%!=A(DrUvWͯ0`XXOs0)2z7z jXy 'rp,^gB ʊFrz̕)_3ST:R_GVOʒv -T\ɧ5 gq.Շ{^J2plҁ꬐^Xzk]NRl<>T|u!c{aC  _uݒQ\FoWX-G==SnEKCH򿗏DXÛ.?}.!vR2R'MuT[Whw3m }/$H# 9/WmM9^V꿱gBLIY]C5lщDֈԧ>f:H@r; 4OG94fAaVk֔OFY1(O=4Gxd9l>M7YR6Cq\M$oM ^жMD} v1On6)8<9K) * h9j*GZ.@JKyr-G^`-ZgAˬM|F^{kF;.H}"q5W0_a[\o ,>vW>' 1MK.`!l9qTNBL2@=4t(H k)m?y8$ɱG~Pѭw(Pʊ&FGf` f-hP?Ґh˃ڿq}`K_AMխl{'ujg$.nv&:&k݂htPia#Syo|#8ҋGԂmI&\ `qHYO> ]YaVd"IJE~$rce.E%((ҴJ/OyE:h -onvV/s646 aOuլ𞧇E'雌X1tx{b#}ntN/ ,lr5%1̶vͦ¤GT@eUk6N0db{qeFCMhBM_݇{-Nm .@eFuܤSP"ECAeL(|՛ըԏލQB&smu b<Е=]@<9f>jߌie|1p)CkСFwj_D@Xnz*_6077{^)Ύ[81XrѴZіvH15ďJRiI4)|֥<&>Ta[xZF5aRzx9wسO:4>߸jrSU!u!̌xs T@Q TXɾ>zьIa#l$NIBﮟN3}C g !@Kf1ֿ?$yȖν6z}w HX̙(vFicfH0zc|.ރJY786? 5rd2KȒsR~$ۧ+V-Ѯmh _:ӮP _6NI~id7ߛ_$}ԊK\[JMAiWzCu9^f2mDd|ć_!=N]X]G$̀qZT&OӟOg {EY?J{QEFLX1`K0b<*&gq*G~WJ7NT Z[(~JI. `$of~U7țQB>Y\\i5kx:OP|va V~ ݀gk-+9Сz>Q@:ɬB|10ٻ%w8jwZx t :#j.o'{ B&s0D~0VD.vbqJ Fv l_, Z'& 7Vn5'-5q%Ns'NPb纨Z&OnbB:EL8 ռduW0 ,5)FڸcbQFbR d6-Us2 |༻=DոK18gLN4肢ӚЬjAP!IF3D$U%o=ᢨ|R S&;a/†]ĉ.g˛;q_Y/ზ bDHVD$Bu>.]p/^9wܸR AЉcWS:gIʁ`c Տ+ZFn 6R8Ee-0mq]fm].݊dvJa?}&߼Fr^FC>RGHXE"0WnEGϓVnrZĘ* rL}5z,GdPК( 5,iNNNZd C?BV'4?rc퇥S!  .Yp]-y׷-(>F#t[.OeY >o[O)2Ii++yJ:R2P%Bie(ƀkDXT6Y[Ӭ+QL v<ξvBvq^4940m&m>Nk@̛VR"{Y 0d2"Egl4BFQTg][Œō 1E%T'N_|'tuɶRFi^Q!YV~ H@O=@(j.q{in.C6ڛ y8/fˠ۞c)֥Y$apZ!ik>8 H F/ dkT|/,f7ġ&tyS}zoCP) Bm){bX ?@po/M+0rGtޕljHuخa2ͱNm%.ߑ>awj)hY?Q%')sj< WUP7vɎ b|~2& x$h/v0ts(2Й"N׵9ȿn{\9-0zH "PO[^tػۮa O1n'2jMtAy%`:aD3v%i0eΑ903B`BĹxB3CD32h6x/=N("DЀï}r:W%M+?{$}d0" $43^ r̝#?Nmp־`]q l*\hP쯵#c\Œ! _e f%{s)"Fl6b7"KC ml+I#_/Zok/ys[LJxc6l*\0`Tet;d1lyȟpedȜ7o)T]ƭߤe6@47_eFS鉖DDתg[*6>zp;mSa$(y@H[4Qri3pR%ƍ,*"[Pso S^KŎS82=g6.6cBABb °MqJC5J  nFae *LޯC7,$y,S G<1:7:) cl|ބ 9m%Y-m"cY]F(en9~ܖ+;ܟHFn3U7Ý^2._/ڣ I{PY㊛Ϗm#(g9*sM @Yf,!H"Ge@`:"m0" ?MZ#oCQZzE轱#zÌ9pݘ#_ox &z8Bb`lqUa"'ni&$% &}.xG'lڼʟ+F=0,h3C>^#$KCnj zFL4.a0ȡ=?V BR8$G<7M% c" f2Ɍ]M_bWxYM6("f;%0Y].4BObS_8| o0#[=0.g6Hя* j( 9TЀLc/.f>TE!>Z-ZV~ՄX0N1h /%u׀R$q K )s aАNÚ>~0/oz>Q?J8E=Q2 a屏*EgbVGg )Qm;r@)n?Sf52 cE#YAxkhOHMnh)uυze,ׂW7uGV%Vն~2;)xOV=~@f#f T٫dyB.MH{২>M(ΣG7=̟\ʔdZYD)GKx"P|Y_^k7fvg^JKrp(qla(AzX[-2WPmQvq8utC@ &N^/*إ[,f4d}.˨F2@E"P[@дpS(uCb ,m8ƂJA ^AcsN}~?ㅉU% NLGF_% )jVtGߗA*Uȋ_6`4=]gc+aAOI7k[\AtiK4}{sMyt:yhO3PBW͐iiH}+ؚ:4JM!6J √j )v}'Raq[ ϕCC%,S[crhF`$_ MnA뙤A-O7̉(dX֪l"|/pv`a(zJl VqX$| e}q h!LQqp(a%}Sb#rT Bh|(3OvCR:{'`=Q@,DSa^hVq $GYu)IHD hNlEx&fS ĺ::6ޖ3#cwKUrLtAГJM4$:Λ%+jބ`7=G aBE,`Ȗ30ys1TnBkx#DdLJK>|aSTr"?7N,BI-LzqPޑQEnreZF2aSmr,&3}X_aċ6($9H~ Sfʭ&!N|Thb-XgC:sy@ ^'M|ٱNAhdN|e)f>zt*>f1"rj#'F82mK%%0i_S&5>je0kD Rjl " GAIMq|lS*Za[c7ZHJ2ApG9gMSh4Ig%#%-\nJr]TՅTpO_c7DMVrb-66I9:>mjXxeJЉB[޽=e{ߑB(8s hiIPT+ nX#Hjɽ@gnNC=7#uWKe4T,,èaZPڀqՅ|3AJCq Zh>(Fi 7u 7)sٺgMd\Cpt/w%= ֙3X:gǪʖoAuJl^ҡƤxK%ϰ J% [$} 82S~h'.H3*2ԥUu8zhƞ !ǪS>)^;;S!IzIO1pF!^Ɍw|1M>kEPgo:B :">k͘4~p1+@tHM2Ubј+VQr'AȖnwmg햩(}YG~_b؁&RR]3V㱟J⣍_(ae1&oiȆEŐ.g+3K@ Ρn8'04!_y 3I7>QN XnL5~`cZ W2I'O9%3s2.CO0q2ZxhIAC?fdǬ.okSI׭A[Tl5dӋ}djNs[)\s~sP|wL㋆v(]@s׳pBHȗV4]e<σ%K5HAv̅}Tc[2W aV^!|IQg=!ȫkgflpNu4U0.JaA`ǗG.+8s.+5ӯꋔ\70L~a*%NnSKi2)A{4b,.p b`/aG:T^JJ[ݫ5փ;yL1S.OS|E }9P~<BAyd +|n75t ՗g 2vP1b.BeV@2 LyΒF =>qB)'v}IJRJEZnPľ |blꫪZuvJ<?3;%JԘ\`QÒ_w5+ẘR=t-CjndAZڐ:, @v\ꔺ/1}H=}D<1Zd1tb&oy sm`6mgXL2Fd* _!ZnH&.gvNdD! Rĉqӌ]}(Wq]91l =}ߗVVy3Rp)I.m7AQ G=GiZXtFBT<&Z5kp2Y \"%"NtWGj$M"bI䠂qf 嶋iL\(8h#k&>hb'~gB(汩:UyxA ʷzz}Nq ƽޟ lc.6\Y/>,^M ܏BvNU|B 3tԐp%I)AC\V肠[ܭe'S hp0c{75 Ϳ?,]Azݏ\x!agG>B49M}̻@!$Heqh3uDW3b1sq=HÜjLFgUՍ|9` j^R*YW{bbM|SSj:}T0+ X/&sli|eHaKwi\G3` 44unziykP]u;bP34t]<ƍi[`R&.\Z|qT ;Hb'a1ǥXh.X@O KItWÊ!j]F@Ԝ&NC.ߔr"t2"d} ξc&{\xj+9:I`%cx3[navá貌~rF5/MԷKo0۪mJ#U>-4uU׼0/Vh}~ntuw%:hYb1Mw$.I\/:{4j: o7E-wMvo |_;Ň'?w6ZOxrCrLG=A`i`=K,LqkW5u)Z8QnfA]ܾ?GVea/ZKq[=F]wBoEdng9ĦL`z\v9cm\yCre`ꤙXmd!j/=Dx8i/~gbisd6kGg(_( MtɦiUFZ[@mۂ,Mbrd0"AX>BwƸuj^a#hUtS"<<\2^J-}祇 +ytK{b" Q(M'w߳c'?D\C(+ut]3ld( s ]%)% $spkAiFХ Ho`wWh` kLl1Hp 1-Xs~Zڎ?"gQEoRY4CeSBz1XZ NVprw׻:uZ>/ѫK}.5 4 <;J8E1qxb6TࡀD2=! f`LsTit!8vF 6U.hp2l\Lt)2[ f`2{,CI6I\֋H]xg'bd KjBW7už!Td cg4UV  TK%w :#(}X[¶V+A6xH=0<}:GU%E Sfㆳۃ F֋*~Uٕ7+]h0m %;܍}*D֛ʟ"jGBЬGO6>iC,2zB1x쪐a{DN|_/dzO_wa7u.#`>q=Ba wA\cY,*[ЩXB\>fC$),W_BS9︳}E0:'I 6x,9?19,x硬'MJxc5]N "h6U!q9Un SCulO UɃgbieOxϿs?ˎb2ɧp TIGU3eDxi0^4Uz| >LT&L^DG25wώ'mDa߶AY TiTyN6~:3YtYJA@,Xr]Ǜ3{ߊ=gmkr,9L v1d%MLз&ˁO5BfMYX !iV껏=*4C^XdP7U@iLVsI3nI 'h.˙n4j2aJ/Dcכ7-”} DnrB%ttTx_0Gb/#4𝓗S3_(b?aQXmZL_vI[xs,02F UvXbyJMpGiq稅q,u2&ij {O 50|{ ~?k1ڥ ^xǴ[wmܕz1 Z:FHfƖs*!l655/HQx T7p+uG|&ٙ_>ԢU8ccMˆM'/{k !Pi|{ol6+htMSo1Vrrܹotxmxm; B%2&JC"N}e>T΋j%YDHi3qH>KC[dk IP" ȟtnJAU:Yڹj-Am;YeQO_IUemfvu:)z 7'En_>!/0&VbFBOC3a5*drg%ܣ~DJmÀVb,ؠ?WvOG?olv$d[|qOM=ӟ&UٰiN"?5i%=7pȓbsӵL^ZXHJ4~x$K* V,/ށ{H+QWL CUNw MWfZ/W!,PV|D0seQ :YMaTW\n&B4J&^^DMTDk$5gtrvxhڼ! g0EDY?G3pXr(غIx c]r=NiKlh]rT [?"ʰ.$}%o8ba*`2V7w ܒMv\tw]eeZ\2,#}[1]a%~wrpKu!RwGjV %T,,xm|_=D,y4h2OXᥕaaLHOʋ@-.C/ G[]$W<$cxHǽF,m I&>c^GW,7@Ӝ^O%Cr:yK땵+f 0d xCvW٧P>-֫wsj½VqWas#Os D߱usu씝dDItANp!{5ԧh!ME, ĕ/$!2_o:JSpako]ʕv)R,^"^h1׽jAAxh#,Vd߈o!N"t*- TbrڃiU ’վBש >[Ϭ*Q22jwI(hj0pu$~54- oK|:+@(D;TU3 ~R)ǰ&kaUױ.Zk?Dtf|"/~dfl,>lanyL jÀ,LZ Mt&ق* YmE@gYC5MSMf>)gZYZ,˓Ý`Lk_~"3pjUvsdˈmGq2+S"QØUЊjwar\š+=g4 z^ -M1JdIy'{ !Bsui'M=KZȂAcy: R(TX^ 9=8,DuFTpx2 v9{,h#`|GOH>ald%n[ЊrQǂskm_Hyd%/,.STw߾=@촪֨g(D|{(tkjUMK@}#1;%}SM( ygkI,dٴ'F6E1>M3b1".edV/\JudV(4X 캗LVqNMcD8zii2V[AEvY`}ěu?{; 0-P]&l̳V Y<8ub !\d1 ,̨l:7G!3\ ʖI)TSoC1s\-Y+V繶6+Ef3C㎻`!E3F V#봵%1#=ϗCq B`SQPE@00\pѦsҗyEO`j__RD=t,xŌJ~e<9xٿyW8MiKCg=v̓*@KAl9Gɯ}_Ik$m S_[;Nk:O(]ĭ8-J}ͅIWxV/)}GTƓBEFe8{,GY8 Y@*4P!g ɤP Uv' jġTwh`1!/WHOXW޲kese8iSZ=0xj/C3ιD~ج X>ߓfF6YR[7 ?7AmuritHJtw_LG=87h xRqň"CX"Rvo3p ci4Wz-+n¬1Z7>a(9gV)V"3.'#~ix1ѱ,/ُyPQ 1r=!M9{#Ȓ M7@>kxA46"( ?k`Bdpbiu^O8Y+\͹+V!EkyJ~f<ؼz堪w A8N #+u]k'=c[y8*gey3bu}4T_{aVɅwȽZ>G$6qy%A5Ë!"f?l8ubiVOrM7ɧ;βM5r"]")cTbPi1/(+dӖФw$D~0VW~ՏuF\&KfCV#TJ6{*˲ޒF@\3Z}HDZѣP#6یȤ.-ǰ%9K._zIBMl}'p%( =1$=jjk<ڞM'!nO5YLTHnoG#9{=!g 2T2JN9 GlrOÂSFz¨!X-9A7Bl/xUDIT8ZwL؞^HĮ5BLq Ǻ4>ԙm' yvh_BM)Eq K̮bo!n+*ڀ"~)cw,h5J'5M7MSב2޲s`i:4ny< .o Oh28i!fI=̏p쥬aY>ԛ(o)/%SMV%$FKnThV:ݦ6bqNoSW7s@ʳpFhtKm5v<"#jS"}r$0L' SY46\cHaNnDo%A{<_ ƹocEs> RK[ +@#$IK{'JLHy E6"n\YIΙ񩲒hƨCh=&1 S hQ(w;7k$,A1t0螽Z/3T,okm%4UέCx-ݘ KR;ֱ;0DlN[jYeR{*۝\%E mylDeK22QA*7IՁ jRC>& afˌspF}‘#jٕj )K`уQ»`W40}?c+ gBĒNoDi567#0ci;lUI *wzN1!Q@I3gq+FΈPϰQBVxOPwɳ{٠ j)2О[+<1 us:1Q}1*n/2.ųBW*'T6 SǢ^qhd!EhВ*7SE5OH r֔_$y+?嗳j !xoS #k^Trj651 =VzkR:ckIЋݡ缜 ( n"OKNv-CҲo`b=c]7E/+tPHS-mR.TCͥ ۇ[H@rtjJHjr*5Lр1o$dBWi}^lTY#N|ۥU%ܮK$MG?`:Ll?pF276ZcpTv6uh̹ SS»Tx8."U 8=с2VUB 3 av1Rż#"G-T*,Zn`VNa,B0?_m B P.>$W|O&l\y !Sf`m2~Cre̞ҥ:EJ]إ;{X;Ծ0({zPzze{x P\گ3OrE[[e_cvy?MipdO\1٢opnXiYב VTP>#Tq zrz\QMY78CutY7o<-uRNd}2Qp^@592Bn&R?8?kw~.T59ƚTT1XzXڦ-A>\4~f*`F1LޙU ͓m~`mirK_Qh5Ƨ8^7PinG۱Sg~u!"z ΰɻ߁B$b{Փm' hff_4~9;J\qA~zo]D*V d 0T䣼!wO؎($WȡHyS;X-PB$!9Vd1`0䠴-lR lY'5y[;D=l6Ѭyr=l.s["%O IsAL ƆQƤ;t0MZX ,SPiC~RqP4KBULsI:t*`5y-ϨdR="p12oXwNeN-h8 zY>7}DƬP4Uwj r8(Sp R߀n'[MPk=2_TEsWVf>Q"-yq(K};G裈OW @)G-Z+vՃӄ7`Q51eЃڌO1FJZU*2ja,%%DFMCC'[7lbaxVO'bgqJ\LN^X,4+g #ݳ2[PxΎ<'{-ѨlzЫ4VŸIycJai|p}.d ^\(U y_z^wQĭ@kϽ3,A.;hfP{d,%9jYxQ+ď"*gK8&vt x"`` V26e&-nҒi'$5n@m<"k. 5B8kImvrړ84!1T>&':fylďw^e)(v+\ֶJAՕҀoO%{%d廤ާ*U GB Hw/ _DMB!kФT;s|RS+*cmå|Q5ē*"D2Mei ] ,s?hzIj*r?(G̋[RC+}.+s$ 5Z4mw#4-YAUgK#lcy @,& L;3x?(cp+_5≹YmocWh\j4^:`f"K5%(V"6?0`>WFE6Yֲ _+cm(]mr%G|KmJ%gs^%9? ۔qbIR+/*H&|us_f 1G HT) v7_ +EZkF I]1s.AKpSKAb5wn5>0=5J8xE3F V;1EK)/x(Ѷ8$PY\=w)@Rqf轥fPchgl|_ގ;[pc{'Hbxdp4T[^zccJjSf7|2AcZ&ԛ ]Aik tzj$`VY,|Ru|}E7NJTʪD+%,̋*]rAb ,nb9`}:O\U'sq! +lb;zC2x?dm/nOU߫!g9^tdP{lw<|}.<E:!NFx!:P&ڧ l W[vRYǩ7 ( ьymwu4dRr]Eo49^ H3BseSnD` iz"r,ˍђP&6: [-9R;Ԣ|@XgF2Dhoax[ ^[t5r=˶X|t)Tڄ.FhisTպ|y+l.3~Gڴ!Ʒ] DF{im:|AwjZwzb|%(eÎ ~?oAYዴ)ƼT"YQt9\4lX,s2hyu"/̘iT~ZcXT+R}[j`r͂_Dv7`;ppGQ1YԶq?mcMkWȫQ9}4:__\nFSP`PS9S3,BichVɭܗS~r~RH1ekF+7Iq~eXKoBUj3P[E1o+8Fhw%f, Ob^SXJ*%)?,NJݯOZ|P-8k, N黽:" ?E'ZKJ)XWg!Thi9UU #GH,zy@Ov)&SrS Y^\ov/EZɓaGXeu02BӠ({'*(uPJ{ .ngUոZji_cq Dќ(qT Aok\ߣӹ K>:ln` E{9#foDW.}p?*!:% ]CX?#tmkY;e@sQg`)lzGNstmȮb;)^gF>d\}f=pG$|ZT󎮚(oZj:*(&̗ord߂x-24Z`r{Ӆ-.QD;F%0K26}+&n%;1-M2)'+K&Wnc˦AIƒ}%X Fuĺ2ti+:ơDjyCr6kpH}扃zJԪ'qL}ª.DTWK] c0^눦a*OaЅ oe sr$^ o\YDϹ353@* co>}ɜkr[|Yk8vU 6 A*{JEm}Q-iq!1h_ά&Փ۔FXPO1]4YI,}VOWLN ZLGW5LmrbxЊhSRC%Mrכ$G k@oS05f񑁂VJFK m̑Bv?|?gN!1.ܟXfLcޣ5itCQth}.=wɕxWYxDyY4-;$6 _ʞ"w &hTfA3}rw-֍oJ&>9}M%`"M-ۢd7H /-M)]_+B/ȟ:A0R ,ڭIVgS$:VˊSya(NGg!EʭW(*Q!Jg,yu Ei(EH 9Ѹ!H|X/MaLlse?"R*)$qʆSHY ' |yo]e>g -V;P۬HH'b1#f`Q7K" A%2&g?$qY˞R(Ynq&ylҺ[< }}V wTu)/"Ö[eutޔgL뱒և㤶> !`X~>K))2jR<7稤Z#d\&xNh/[s~AuM`xucP\rӃנ325C̋G l"]= +X%ZMbP 1iY W+#2ikZ[OH,Hra5[Z4R [p 9Փ~ZRkCPwp>'5OU$(ޘANZ&3&v1Mwk*֟#Ɋzd;]Xb6~xS¼X6z*\_l.*ֳ^J;- X(~|q1ޯN$" $b~_7W]f:> ~!cE.JB3%j|{9*|[.oZL|ZLgGfC I sP QI 6BI =vcid׍VgYQ}.<(BO9F.s$0e8Kqs+H "sA]{P=Nv8 ַZ?4%V%?l>=;Kl_lPֶIǐX+x0ftm0YvIN3Lax 87:T*caU-^=C8OF/mۻOvK(No3mKe`-6\W0\cSzHͺ5ı#Kٕ]3K#MUF &BG-Lm'İtQ}Yn|Pɴ\LqUd-ȪqX2![)_HoRb Fi99!yĊzO  Zkumu}aіս%,Bwy <$.NJk>?d9 VDYZz.ЕVUjq>j-BDŽ~8/C-e@FaeII?n3GtXEe>@P@6ճ.~UV֕zSTˏ^1~A)9 p>԰;ɧ $}qkͷ[԰a%X8LŠz=W^Lp:Fj:VT!seT='=ҝC%f;Tn߁g)5m5='qfUuMVh)L#U5"Q򩱫ey cK^H9t"lOd>l):OG. qRyTImu4W^GY5mG]˧IWeʨLki dP,_5_b%Q{k=LWC鍵7&eWjccF@K^"SoOEF]qh\|>ڔ b`9BВ^4t@3GKXd)%.j:.П\Ɖj.jv6 vljXhs[a&3-?*ya)VqyUVw!C6?2 邷`+!抵s}^U{7yCUBmC |6 9Nl:`e$g“ Oz"pPJvN0-OJ%N^u:Ӹu߄y/w  㙷*{ͳAVʕ^{yP%# Eb0o xzWw|ëԾ}1{.8I661&ZS: P: CHr9&rBMgyuNH4{q$ӟ UtȉkZXE"q;1DP{r %11zzHk;6YޤODn7c?B9&6$JD0_] p%D.VzښdgoЁ3@πEЛl 5TوO gîR !B)c(V 򄉩@!j#sfV>+'T!|_Qq^ê;5A _ c㠪*Ԃt+D:ODeT2xo]EqO1ڊs5=옽V~Y (6q~EBl,E5%rn*1ma:|2viJ'j1!D7k{&03OTq". md 3M12U J9t&]#pͿݖ~PTFbc~ QAKue),3CKw8 -0VSLm0PDWp~85%:`.xʏ] 7O5'@G%Oj@!!E`{|(l"{+huQR{>ʝcG;- te7: Rѹw2G~&QE߽}t' VV8QT'^"Q0v%]a¬Sph,^;yŧꑧ^rd>E;^\%slѰV+1lol#ϋoibhhZ$թɹr;i⋯I9f-; ŸN%NjyW SS6yǍpeRt%@vKmPZI{սMĪi'UϻQ@1;fk㶼Ze i8j3bz@㕢#] Oof,FtSн1rr؜,M+4ʚI݁9?K62*^W4<;e !^XQ&[cP 䴳ਫ਼YthD,=wj? X ^ߤWԩen#Β$‘z+むصB"9ֻ֬C.z(HnI닔luas,yomޚv}?G70H^rY\qRyYj%p^7njT) &`_ĺJ`}1şSo+W~d2QМkM#_6о+D)?\{K3,X+ЋȒ _`}_6lYYRG=Z,r\tR%g4 `6ǩZr z" %T7Xdɏ DSզnw%ЉۀptHugB?(xҗgj]1^Ŀ=I20^&zn܅1Ldz;?}^`z2Ǥżl_ZppGNDtso aeRE'iZǗ8-{\s;Ikؾ eQcMZTb9D+E{ܥr$k=n8mF /K罣0x6]IzkVܜ5}̏$6v֑pȲRP!3 !J{(Xvcۑerr] k1[Lcբw_^ͣ9H9ޫ/RnIxYM1)m"f2՘QFT l@{bs e!\"8=$kJL<$ In;zK-" `-N,yWBMiWjC|5IJO0 P J4;KJoUN5O].t1NԍO2<,z@æh ɕ)(s?ayuH(z2_m ^{[ ~ňOxr6K="Z7zPmdҮD8>h*ʞY<@$1hhw"/Iv|Hqtv;CN@T7x+3}fO;zѕZ,j5U0F P45𚠜1YeZmD< 6券},3}oIkoE8]AY fKxHU@_qon8S() ޙǾ(AHk *-˥IyPhB-94E[ߪ<U46A4L Gn ]BSVQ_d5fXʪ4> K Nnsa@޶z_V9kxprڻ(@:N<toW(‰ 4hCj4<eϼqV{6'[:&r (`'oܗ :D\9uq%u-C4xA-',~Y  O}T nCyL'6"2_5_&xm+Os8U}7[G`U$*z2~xߘN0f*RdIgF6zvP痳U+<nhY̽ EJ4 T~AKW$7*v|9%GeӲ]b)!7K4i# 3$*Rmt80Cv#F?GQ;"h[̍i[ĕPyC ٩~ K Bt-m8;[O•/ _x1;0煕{Ϗ5baUtQkJMCY+5@2o,!s3ѧhO[ _( ҕ!8G(+H'a1%>o; Fs)82sg\Q m , 8`|ty:(K%แ<;;G⮘;1W2dl;]TqvP n~9#N wd Һe襨z:>: 57(zeU4\iL-2hfO40C\DK}`)efVgg ΐa< E?\Y#M!/J:W䰾R'Bfث4fmI,J*&Y$g@Te&yBt 3[1l F~ Cʄ18]z;> ad1FSw T݇y"!;¢"Z'?=,s9s~f+l+Pn,{P0GryQŻFu\bMt / 8XcS;Gl/ԅs%dp^_x{̌}A|րojeRN)"3wg*jxCnK@S E'|n?{]ZOk2ǏoQa(: PJ^' |3qw 'Y#$B`kIEN_~(ӳҧT;P-߅RHFW#&u+5z:cT`HL^B|G<>yHdM{d2OoBӐu'gr5҃C^QE]ٴYČx,KX^l(vݹ /oW^/ŋɊ:wҰ ʻ_VꑬM,JpRVFj< c򟱵}yFJۯи 8(DZ14%1)UxY4XXa{}(g5vͻy2^ѐx3gE!&j@HUY 345>N٩~/=Ovu[]ƅBdӝ:IR&ž!F8O>ITx~tjz6aM˴Wh'BA OK-drEa-&nY+ם=)8ݭoi/ҸZAe NM w9j`GE9uBXJnCx?}UdCٞ;SP0 ){vՓݨNLs0mAɍ3d餿'FsJ59sȻ!bfğ~g,˕\C)4]T5F%X\LEK#]b!`S Zn7> xVČܼOC ^ :dF큵0}t0vm{IA5b^~u4tʇ=8'4҇.SSgv2Cm/0cHu"%DS^^"D.35#H"]tsjFTo48a3uU.y v Cӓz!zQ ů2Wr%䡩*gUt0a coy!억5KRg\-Pu#.$[=k;KEB t O j ӻX=ז<6nc,𨀐 cvp%z"VX .O"A*9t$*O ߙ t|NԫC`|lG3IUnRÐ*d1ޗk@mmsރ%넓LW'gYg$`x8gD Xlef17Ճ݄ 2HLC$ M:A(j2H$klEpYkgh{- .gE6u5l..ū3 搉qa=skC~ & QpW7tʳ_wQ7g p/"'*}ɟ? `hF N|a`#:]7B(M{/p82v:kQ:&Nz~pP .aڱA'\p{g0RgXkl2pogj֮P+fqqFEaJnNf1?.N! b":}s2v ğG"R[xc(,A ; mրF{dHnUdЏ\,b0p]<6zr3]kP6/DC(/qj,WKR iB0rnґk>#b(Mo BࡎnKEQH_$qrɌSC9\֒k:e;y> a0A9 !T˷J\8<’UEƳ| VxBP[aUo[ПEe10x8eٕ(DHMΟs#f'nm.@bC#gP×Bj|f "3[jġs7h _d'RWmJ!I^a:QXgQ{7X-)!nH6껨w-h p\W'n%. UY&@ vĪ5\_a;[x+1c1'gqy âWޥ O=7^i L|r/ni5b"Y4 `šUc",ˆ;wDzgzML;@-Q_ѠKNjGL7/]f:[%t8GkؑSPhL>$ӀBO|[Ňd᧩qlU*+}OI} !G[srx}{̭m??G`R~z9.yeu2 .{Mln9TRd-)=-{V#g4=^M&gFADAU_B#4 b =h 3LʭykHHn.<9n9h }+q2p^{:<ܶNL羊` |u')̗7XM(F<6%Mx{tlҚ|bWm7Te܉mHU ,Uɑ[x/ҏ1&6/6ut6ZQA&Z/A0ҲBο+)L^;ASo;G֏^ I¦l"Sمi3 >Z&2Z3!u DcPž\*ߜ T&ʮ~#֣/bRؘ׋4tX@V iiSN+08%qNyS@C+8Рd͍-F_1bVg[~=$&%|0i*sJHk< M=Sf|F|i%G>/Ir!(;=3a9QW/m+.OF5eD×"NL<. Ĺ/3Ic 祃LοMVI,osz4 ;?yJ7qqhqtzVe7;xlP`qDOF)b`M]3iD6NG$hJ+ Z8 ]STϫз.vXAQ~ӨF22 ,NR qw;xg"!Q|q'Be(QQ_$u-HYX>̼ xsQ#bruuW 5gگp%=/"Vn"IC:!>?f\!c@$<F!2~H`DŽ?UO{[/m7mk(<!< ]ޯa'*Z#(}FtӼ$"#`Zr7݄c-e^^mB ʀk}nj\Hm+PO Д 8̺7 HLVE|H-3|w2ˍpTL}mB2 z48HeHsSXJ%A{,v@TWF/M=kxX^l;k\9a,XH2'9Qv`j%vֱyKf-&BMUP #jbjO]U[][H6 +/ %Uש>gt,{7>C;>n&bEE)5D.ָ /Ldwr@L @8+49g_ S`:[?)Op9 UuY(}LjzF/8ċjA{C/*$ Ħ?h)' ـl?`Z$Rtq㜞.r|iØ1i+0'2Ε< ~CI+Hv;eL/.kmv\pY6PA19,,b&_ggC@9ӟ$SWbw >U܀ aEuҟ!ťHaxI+24D1pq:ɮl`:m /LV煄mE fO/ɸ]f]kT1W4ʍVwNfW4(+ә[ex"ůD~@dt6;Abpb N)%:; !e)Xʛ_~i( |>QZ$?10VLOZ VCv%Ofᴐ$9ZE 2fTp6 2BnVUB.zAW$M'Cy&TIyQaP^HM_TŬO0DC7NP L#X6vHJ3d"c<XnF*$/?Q`k]&09Sn- 8~*އTOѭir * 0uֳl##Ckf>~eV̥+ÇfOjb0 9H,&ӘI-&vɅ&f"i R.b;p #*˘V"(k P}"FڡB)f.{(u6;MD]Է]>376ƓjYE/ȸI -OKEi(S bНA{c{5VCOCLέ;jrXVA]̿+xMAHOy& 4{#9K'bUnjAb>Ab콺ӧN3^!qjVq{T+D-V|GxY.? !>bܗ^]l~VfBDeļ"1%UM9ۀQ| :Z@ G෵c|J/t`}_E#dKF*4DMʛG\= t|~F'+DCCR#ImBS%TQbk}j{̻ cN;d6;xmזDoR k׀n+aUR|is-v2Odwuu>$gi364_{zp5Y N5yj H~>|KM, "n6113Ff>? 5JpD\_5&k` 0$}ܑ 4G64^PZ؇] 0X5MI*m}Yͱz54o`!UϢ2C8ȭ?tĬVv>i皗EP|㨒mUXd:Hpv\ IG3[ [z!LcI~dɒC!W4K4ӧ:gbjSA`6$+l 0\sýhh')IqD'SbroOUd S\+81)#S'R_~g`33Vf &ٞryd֊ٖl]LP6ޭ¥&#!M'ɝ?I/|IWϝ;=6 c\~ TVk;ymt)[71 T11)+L }v"ӟ3i9glYA"fH~|y xκϳ2^ั{MTWr1F6M1 $/F'Vt!=~3RL>VL{2]?F!U4yax h|dis u*"$ {%/)vK4-#k#=]ZXh!X=ڦ}6"ge$v6UNzz:roB⽴2.̼+ rR|kUd0|H {K)YY[ܗ=y/T> [u5PixkK#@SN!c-s4=_RH̫x_rj&'iM)H?q/|Ø}yd/]YL՞}4__ "S;,>HdЮ. Qd5U j͒ځͼ:)n6l_pl%>%!wB:%}"XAq[Tiɳ<bL2wq%8fJ5>L-Bd*ڋ 6ȿ嵥<15[Pbɮ"|fJJze\Q| 6zTEQTxa=U~zA6cmdXI⊯c)1Ŗ vsOP1b?mٹ Lf! d6 wS)OԌVf>-@+#_/?1zё[uGJV`:ŷY%(hj~o2j^35ᤌ4r]݀OK=I GmM&V %_+Ѐ+Jq>$4FctO%p9^cR'.eXGG/! B_}`*6mďa}Y>>TS& ǡ] D3,H?Q#Fޣ݃<04=":V񋵫=fp7ZÚZ{N#o=3FИ0P3P-( vtTY0,hCun'FyT) -1Qsd8ě fǘ.ZԨm⵽;:rUOG,᧥P¥y\)DOgP!J1ۖ SwZζYI `o4)fL[4E5.js;#+=vàl҈W_0&q(qY\P%నΣ& [sTU]06^A0 ,]tXC" t1LLݹ0 31mnK)7֭dKPɐ}nڛR("2E d!ec[m !GL >L݌ӠLĽ4+pc Y 7m 㞼;`vdjCr3# Ѯ"Bbqҗ4rke vb2Kl攋X*:Hyd{zry(JXmw2;dУ" k.T\*Bn+FWur)\~θ.LmvlBi^ -o(QrFv U2> S!ɿ964 [iP\ek+BXI ~#,0fiȡˆu;S\_=a@w{rn f[K͸M}qytqSA.H`1p+9,ɳBBAj6WCALs5e &$(ؐ$/a{- aQ҉`̶2Bf'G+ tƈ-qo n'='B`7$ؓinCA䆌Ys -wO#O%/ ?Q %Y&TYQnWO%Lg#|1kN`D$v|A˗;pzȉ)Ivm| i4%DzO!2P"nlW!QÌ:t18֘TA&MRf:zߐ> >СLG?/߃<)μ[61rP(j@;l'%QdWluEb5s,xYAQOj5"lYwnj+M "9A.9֭adMOS4yrp_>lozK@KN+JsћQuIEHx gÎV8 hҟ{`[o3l-dtk>'Qv['t3O酏$k-ZDS{ʨp3T dt;aGQBx9XVĆk%L: TMk7^/}H9Ձ3א*3NTQd-2lp) Iqdӱl 96l{hNzWao pC޿wψtnXFZ1*DBbP7\ցS7@3.<~Ka5sD^J K{C;g :%ӈɭ %ڡ9 =,0Iy@1ș*"W'a>{6hB reJF~>=*(3h]7m.٦s3k)RUc{\%>)̭y$6ѻ:E*ccLN-mYWΟdW?yn4}Q*#(c| 6Qb=;y\`;6>RxB>p+3y7Ys gLJh rM&(r]q^J*lt#b뎚0s>rE`(r^ȫ"}iE)ov8S}O*P} QYv~ǁvuđ5ₔW?>>&* y%i@OEGk^^y9) ) @1lK(5rjVAѣzC Ö1R_>-yPo7sdvfgZPy }ietо˦ Ev[qq!-RG@?yz54t@M* '{G{CW|X~Djq`55=p\o^/ji,xcpqG}nJEfqƱICIpr lq#볗a|"QCiRys,މZf1 Ԧj_H"Ǹ$!Xw5C]=À !<1BWb1z`\ yGlAuFS#&{9R$Yi3v!8Cd_\y57}Uj|XJg{If4@XaM)kؼc]֠7cFH]SQ?tV&Ŋ$hMxfSP=cX~NGh2'(l>z>nmbgQ"ȋ(?u;ޡ_q}W]x,8$rawZ}?s^ ϶tR?0Cs$!{[Ajv ?XB8]*=LABWwOAIWXF`:gtM[oR4W֗j: ->(0h[FX'DܻE"ӠAk@x-cýU$R!۞6 ZeW<٪k)loW'c ̃E<\!j!^Q)D j'nV>L!vYSl/ᨄ HE ,wu8.Bv|%TDuCia-.B' 7Pw@t4 8\B_~ nPv&-F#wS0NxˉTBa(XB2_iwI#B["T T/*[j)0f.֐\ T\br2FpuȦm`r59ܟ`$S.SR>tv_P9$of5t{gxdNYCPyp S435 uGC,+C.MjWa]kAOID!rW_}N\QOL3/YI텽Â'ۖA Trt@2)V)?qC;_55 2q5EQUN}&Bx3qY8j{4?D Py5A)̗Bf1Oq} QI>}7, 9o7SNv-}[[[u*"Fġ$IW+TN/z6DNTu[i]ZQ^=ߠKJ5BKe0 QI1-rP1tF}Mw9XFpm#~ Jyk qU36]CLU)z %qAZPZRH ܽ7W.f HBk-*عX~75.29e;ΘC5a4M\ R 4'©&&P7߳&|INɦKF=;^Wo0pPM. ] pftŎC} -ӣV1ϩ|SSmkJr몄6J{7S`-(9I1{(1T .a4\n$M8li!$m$oEЮᱪcelO FAAV%b1ʣVJ`5!1I-$Vb\1uOZa)d|(;#D(, x{|mh$,rM5yRWc0҆FPȏ @*ѥ= ">TҰ$8ȈQ Dv{2!;(l+7tNjg i)PI8e_eu ucݐ-Á55B>֬L^& @er 9)4z u(~k#SF}:ZŎ[ZbTHfBT"<-ҪdrD,fI# 0#W22Dwq^s?T\|,y{+UZSˏ **Txխl66%ӧ4U1aʇ4C }ډ#Tq;[?Jj=Bl iºpC_QBu쀌kcz.-Q3H p'\G}!I()A+]e ˑnU`^ҥ _q4$ !1:1;V%Ǒ&#Վd悹_CS:D*/?w]uG[ mpSgp=Ϟ SS񼦂8NB;brK .h9soj!Ӝ#KUB ^t8%)#bS2pFJy 2/O*Έ] 8$FvxN-qSn^B44Dig#0V vGb< 1IgZNƁAR,^%+cOlsa{|Cޥ֧bX9htp.^aFko/^Oh8[b#2(oџtj `Z,w09R8\CqKVH:N$5Q 6(]0{? ŽОlܘjDv_Qoi"N KWI9v|d4fi8ЋKՄ)(qV'V}iӌ:N}c}\,BB]БsrvYW^z 4T"fi: qNJF:~`(k^ĠQMYDQ1lt1a]JC]X7W6OH]'VOK"k[QEh@†#ƕnSJIlAxe/>ztlݴ46?r$ >DPDɬO7̳#Gӭ8?vYՈ3퍳SD'){R@5GOЗ|Ǡ%zX_Y{.ȧS%\w0БoqH|@w_#xN؈\y#p&C ,3s2zܼ>N|bM~DLPUkOI_G+cڄ4Ou!rd.eB;5kiKW|>U-2n0|HU'jk}WrG(٪Of,pͣ=LJ6pn5ٿ—RIV1uϨOáMoRͨa#ृ% $f?$|="pZ]אܬ[V툷kթi{/6W\<O! ĦDAϑ2wW16dn~ALgؒY_;w 6&!2: '|RCBaSwB tBmTxV:Hf`0<7+ń]N?W[6`\cAr0 )ZvsF0,-djTs`BLB,"n,yFU{ Y( y!)=k䮲 qksBCac-#o6[ڜ-wN9 kKj鑧S+3eO7)s)ν"bŤ$2e"+*\o9;~G eòxae*.;`$%ҫ˸W LtVՇe0;TK@b8LxA es)GN;*-ul\vn}"pfZ&2|Qϫ?-IIU>8&ָoku kIsD^Soy`\Co *Z-3"BAzO "Wc<_`qPl R/=x3 тj`%ό/ $>gRI1T}‡H\p"Ǻh?RLG]AQʗk_HWTrj2(ERu^2*$ULa<%.́2/B&(]lR39dT)):.FX !>go[ tZ6Br$NnzB0M䖋sSO<#m:\Q+L aoow$3*yx`KZ@t+"]Bf"PԌ<膜:sl2ܢ)W`ys%hH6`'^%AIku~h@}iYU5*R|V' uYgМFn mwbI&A@7{{fa\m/誰C Mvv -3|'8 rKk,?K[zRw؈F(DT00e[W{D9W1ag2vb2)[!DQYUeG-eQTwOBg},y%뱆 _Qf=6::0}Yla Äs^ͦyQf扖.B4s>TfaH}@0⺉>eVgBkٙa>([oAn]HqY4aUjɁe*q`gju@o6'r_ϸYO^^{o nYC%'꛽ O^3WrV(&kCE9K5^g*F~X7v#EM фge9!Lu#:g㿼 w׀}p]̓ c[罻&n)vo}WS|Jax z!9$s8[>֢s}|>g\UޅhH''eJ"́dMPyz@[DzX/Do:y'>`[,3e4bn'O5$KC^$xV F9 SRy*[&%9إ5ai/%|VC!fJmoa ̈ ҅y_Q!3)]o63@}zi<7{cK9#'4s3Y oqNmÅ*OF=gt'S?0(HcӇ<ƫuxNI S:zO']=~Rh뽄I. d]UG&aزip %1-:ɤ1ʽd'aыVɓnbm0(H,yo6NAA0ZNzxP@:j[~CZ`@U!^E?7sw~^>graX#KbYTV8I2TCHu 8jT'c}ߍ<9/࿉?5ωz!q %PY@-Zus#ToiS(/z{q|bqMk_ӌQ/cNͻHH?^/X4yCNor1{H(KE8E]m͍fKLSHbBy%uv@#X-aEm*ī,6R^zѠN3qi?KfI8㰨uϵrg|OtG,)1/ 0&1!yReMS9uCMޓ೶#`ʀ[ݛÏػ<ȥ-+zvK:E';kys%r:7eԎgd}=4ᑽRdHLd;H43c.atCąhd`܌f7[YCd{Ls a=x2-)‹XdUHQD}Axp6 ٿ)*xoc}]i/'5ukd,so36:\B/#U& }і4=Q}bd}Bڽ#F|%oV't}=R)!x3g=S(0@kN?`/<7`tU@(GD8R"-MVvͼ+q,l|F# XjkpLc ࣎4rxZ(3e'tgLYcY0(zz@pFؘy'ʤ'9cێς-;l|?i[~s[S FTAM-(54o#RϮDX Q%?u.!6bhѬUWd,b([\d2n5 D( (gh;Ə0B:(4[d"2z'  {D(T>>SF`Ul-s37Nև@M$P)ek2LB/@#!Rl5 Q:!r Rfq#xKjJg[G{:?Up`*ǭJ9Mq0(6M" Z1/ٶcy?W<՛ޯ4F [0~+$6>ǖ[%Qbr.9ᖧ$HV؛aZ@gO&: -LK ?w0(ץЩi9;ܔDDj;UӥE9C ={A'&;3zy8AF{v|"L]z8vC/N',t0g8G{=+YKLU|qvTųG=_4|ow0ju) 1nY.~ĉ}wK6z% ʳ*:? 6A !]8HN8KM1} 6'K(ɘJ4L^Zw;W=`=wu- N>S=8@K;Ul*<9ыq4G>\Y]9Pg%<ҕe2%bɊw fUtA3@#lݮO`B^cЩY[O%qF fg~Wö-{BQG$8N}.I_J/2B@ i%`q0c˼EYL'z.;]W̭eN!DzA0< rwih}/KQwyq>bdÛ $abT֪9B1#c$D439C2*z{iZ{Q vS9Y.Pܚ߶U>>*5$\sO K%sl_@ꞹ9Ojbǎ-;6T\7Mlf6h3yCS\3-sUui`/6̞Dnjj뗚51!owaz͢*}33}$?V%D zY1l h%{8 :CB1]K_ oJeU߂[uz(.L)RK((?Έn6e%#k0*%:U;Ӿ 9Չr_)5f@p-F)]H"?{T'0J ?ᲈyOAΫsVA?X`mjÿrT)BwVeqjwgSu4wkZv.wu~NNHY" /7adXA뤈ݳFzO}No>RH2ā y@ ADrS< %ռJu2!Bqr֤u: BK}P "E J^} eA8 $$L?F"QV"5:! qe1r$Mi AZ'{x+#q _Expiah8:CtiF"٢%չ'>d>E~>^*8eTm: mؾ11/Fg}冿P+£m!˙X"6E.XýK*wE{zgf}΍[9+1_9Ա-a=S`~ciGNJH=B<¹TMwvr"a2 ljΚBܐ==X=J/WЭ-}q쏛X9דʳ0ϱY馠QF~:ɻyh0b\E64,~4qydoŽ6d@($ouRnw%MnJ|Dń*l@̦k9hjz2UݮjQ NB*6W'ld~϶PyG^WRI-Ϸng`X`U UtKgX: $fB-b'AͶ奩^8 sW!|7MexB\G̠,sc~M B+Nwk+nIAsxa1M!cd6\4i\ņZz[9`_؏f,b"-B)8Sa&i䥹ai]U텥}10~LyT_]^Vab$ }3 УNDO) -f,ea^ju%[J3sO)5P79e#y,U Plr/)ioOyWh :+[1vc)d Wwƥaqfij -F9~O5Nqvb$ҋe4cZ682l+)߲qslwoEQ{x xn5]ǀ_=kTfCAJy׿v# nÒi"pj)bޑ{*~rzHU >(LLD:~0#X&ƹ'pnE{4k@`BĖP{ﻂv%hZH -[.jp01PGLt +{("j,2?FbYFy;D)v 7MWM7FȠE:ڭ~mY@%ݸRzb[`qiV}eKEG e"g"VmHj@tQ$F 01rƿO}27s[ >A;My4<%]_b/=RK%Am$ĊԖz&Q"jUfeҌiNÙgPmCS{Afߥ$9#RٝՖo#&H-!9*e-?<75L@OZK\3 T(Z퇺"Լ`M9ʰWE!Ku>~@>[dd7CaBwwhؽ&! =S#u_>ay}xPj-CBD./HM ⿛\m:Oob$W;ѡ6*#  ccCU>[HN}f%tXVD굶5G!^^\34.{;X6᳭< zE|W A$gR_IG):#]|'!~`nFm>nf=A2X$X25D9p^d^/}LsW6ZOw(!.I SPJ2[՛U<ԀNE49FPvA>_hqYQK}R|†UT35 蠍wN Ŭyx΃NY*5Pa^OI BSs<w;3xmhP},`H5M"9ìXy;P {zrlR?v&i%p@O'4LULDO%|W'@`:CմP!l֯+mq9M'X} (Il~SAnXX4 `O}TUo)Ӷ2ޤ W>f9Ҥ\ErWpg):zeUٷS"5yzԱq(nͶg><(8[gb(Ux6U|N#1£\) M!.$UvdzE<#ܛо׈)J#d퓥۩zny6K=}f%@lEWΔ/$sJA*%ѪQ6.I={,=)=+vt/@uAÌZpȜS0UJSY\6pٚz0ݝ QHrJ(h7|-po~cu K]^h(DunYn9?dTPS&Ȫ?Fdž[T4ΒnNaQDTYϺq_!vA97xZŚgئq6l*cG:XUkpj""tc_t%EVw{.].gpzu/)8ow M$N=( Lr@%@FC/Z ["-y <_E2Q$&Jx9LOHq(?1粁+B8b+x(vQ$R"-..qߣѩJף1u}hY9&5ϱ ~n wKaM얫9!:?~sXT5h;+օ=E7dfo~ h&,U<݇S'ls H|lߴ7^Ve /E Z|g-y\e:qք 2J{z"ptUu"w.B!e{k#l Q\0YF Fhq omn}IW2g Y#tB۹yVmBdȵ|W"5/@(_6I1g^}[G=-)/RR5h [.n*eQK DytE@GE$<'4/~IEЫ%M4lčD8h AC ˰zX[۫INM1OWjTR- 1A'h/?«W$ |Q-+R;X9cc"EGoD0H%  9#C^Ea n}2$>iVV"DZ*H9Z<> }vyxQdu ͩ9j c`wqPLY( _K|=4~}S P!"mxm }ŝƮJ6-'A'V5a Q\] T^]َ hq.C!%}>.Kv7_=z-OUgb5pq 0C~轊0HxHZNGhsj5}4Jq`wA*?uV:u^=WĠYOj [1|;yzJV`xGWet7%${| j1 a5?7_qB֛2I1t+v 9oAA DluyMT*>cHBbݧ]B: !dQIl bCTIhTD(xnU` tf޸l7]E@|GInvxMTTr:aæR' DmgH8`Ep?3pr'7rw_x"ş/\c$^R!$XR=fH(<Og{Ϟ"87&4>. ௦}VK/9"s1/te!Cb&cTƏ Z;H)ClK[(uPn [.ګcݬQ7hxd;9$[X&sB uF#o*fgWW8Zz̳i.儋I}c)LV,OzA bm5 dЫ SfsAo<oc"XkۦD785KF97eHֈա7"TmiXsÿg^0jwJ\@ yP[bNʘjuQa1N{w |x+oȀ?r5C)y>3o[ 2l+ࣄ;XjA ?gN@aSݾW7?4X!R .O`/0\A;;>i-v0~τyfk]~aOk*EG^e:ڠdG YYͶģOedcfLG /(c zBQ0Bl51bigszD5>qFgGE 5 #uw_W=syYBx+lŋTbgX"bF#GV00C3m.&}\]2Ay +GO[r ֎#Q-KWZ>B[AG=6ENޞ1k;C sM ʛ km ZSfk 3Bɏ!sM;ζyNb H-P0@vw_g)d߾E-L.ܬ"aO^mYtxF g7,0p{t52O<=,ՑDb$X|? 0ܫ0FNZJ sC#N< {.h<#u%֨1@WY,5x%XќnF^6hW;lY[I9E!m 3kb'Dԇ4r[8'G{yLң1hg_ˇ6 7zd<[W;}́G&(%m);`+Jn*r(AGK@讘ﻥRZp'U|dy*rn,ܷ+%떀+GAf*).Jiն%+嵤SJOxasn٦ԮjޚJP?;|P_=V!b=fpXr8"7b$ +Yah]VzlM.L l}BHQ0H3 aۤ_RQfū}=Q hMGC*yԆg$Abm ~ef:BO~]{f~`&H߀\6SkJȺ3w[g |{]S gC ra r m醝FDtHt;fJJIYGvjWh|Gq\?ls(ӕ*.ל`_Nz:鴸 4"c9Ei%4PW'ZDZF/au,T*$ q ҈(g?Gϒ쐢 .-F.[=_eS RĘG$:V_=+Aw@dAw,*,Grkެh8Cf+МϴL&ev*A-p*# \<a{[c@76^g7ȌjmN^dYO>ޝ$nv)|0k۵, uS.d1ަ/ l^j S&ʌx֐q#=4r 6Q\gUBXn ntnyHyvnI7t붪 K]~A=>@^2f%us?܌ g ._^xjm2(oW_ȁdm%+wH~R]I1% s2*Q6R[H}u䇼DGC5Z[KN`48;psw*)iT&vQ{˒e$= -gȺn w>s%VsQ?Ymm4uʺ= 3~eAn1o<@qq ՟.T0/t~3fOX[5wĄć^)KHz},i*֭B5ַ(L`9! M98+,P%܌1y/%B#ة`^q!awR2=@_c^iu}kHkj?)BR!Z#\) riWjC֤T@H̼sD6؆Qg}!H$[y5n% o Ry@\ >yus0+Hz:#|=eo޿Zڅ^X3ŭ8X=vsߓӧ!Ra D\ER;}!iքCJwqrOY48$$n\>ٹZt,U] "g}>G,\ٓoшyסZXaJ+6!<p5Gp3u 9򒤃?GP$T^ɼrV뽽C6X{2wJ>*Eg$ DeN3C+&Ė/3H(pzt%3e5|ߟPTA Ԗ=ASt!$7|u= }1{xQHA!OEig?Y8D û[Ҽpo'du:~!HUօoP^dL!+JԵ1xTJq14IFjYh}h*[{s:cA)u t-8E 'ԣ JefRMgGܩ{P')4dǁwNjgg1ms%KAp4v.p>Q9;;%pSBCYL{vf~$ם$—nIqH58|*$xKbL@spmCDIΨ,R_cG *Z5oB)CvⲔvrC~p@l" lNH*23ci{PgBXaNmҽn‘fj>:tӅ;WFUIV(f0;?e5522Y]$*#:Z*pjL{z3y""osˡ8[,jG TEoЪ)fgAm tX1oLaa1H%{vbåWI}d?RУ.oỜ \;$2tWQEt]b!ҎieF^Bc!߲!L/VéH\q10ϳ5V9TG}J?nwTX{(])6=KK'F?4G1.kI+%R zTv{ygrP1Xh֞)Ƞ]%<*`~PŒ.9l M;0 F[TcW:ky]4Oga>rGYB^񉖹a`~Cfˍoޤ`M+厩ť,Ⱦ=y t*8WDEω:l?l Rևd: 6_ˑ>M9١E`]B8.=(}cbsrqZ0  Y557m_"e]?S3-)Kk2^X["+prKe@zGXSFVƹ}Z!WQqA1Ŷc)IL̹w zfw2uN"BT#GHL [d1wJ p>""$uC&Rmb%6r0i]Qx ű$G6Gb=m%eu6GKfގEFiϪ!؏&LWPԼU?fF\435߆>xS_|9ZeֻhI>1Ү^t! ԱkSg4na0X $1 鯦?Bc S?Y?&Lr0@Cہ^n$m)^onGC9E0U>Q;JJ+&6 O܋۪) l]h]φty-RCQ9bdq1O6^)x&>y{ZΠ3/-WNoӉRF1{4@ DchPRV)7In<$k$|Y<}u2}a݌cO/Nt5[7IcP<1b犊VWP'v9:FpƶU svP~/EPx-\Vئ #nbo%_Ԃt7>K/3;$kmN{2@pG!9眪܊{$ z-~bleܮJ*wWl z*E=ʧI7ǚ vjf<%fLF\UPC>d"hޤ$7Cv/iQP V {>7 GlUq 5EsQ4?k5!;wN0-ՏYHYXyOHR6Nc$B\k0?=> t"-1 X>\CM1{1؟ ”j2SdN(N͠Y?6F[>/IƔ<;&RDrWOjJ8Ä́ k/Q۸_'XpYs(zbeLE`hGU׷dZR&QÏ0/ؗ0CYfHhhq3Xu0kOs b[Ccp߁Y+$HWCKbHpsP*$VFYm#lrm.O_!D+\J{WP@_ Yz-spY@k;fB? .s%1Hf:kzg3t-mޟ捓Xڊ76ߓ id>V.5ϢbUYNËenZ@ 4J%_uk5dZr}MkyW9dbd]C~@|]kKQ܀ִ˃~GV܌p=FϒG-0:L;gZkvѢNȾN ҽ&\lW 3$a9[xCo8TeW^ύT֘y'{8h}}emBth%\0{YNkQNE',_Cl% %I(X6Lx*6!grQRzR-'43L(_A8x-vӘTDk=ZڽVv.TWC3fT! q%T]X0 ?+b74!YN\T2jB, 1Iq,Vidbxїv(K>EDSxᥢġ݀op ^T0RPQ \6StDVBѡG 6O8q~/qOѧA6Iju}Px:E>\wH5a.Yaroa_y=\ baBP؆DJ7R^V4nӖi^^9êEioȕv3-@H.)P{LNTqD!GzW8ʤ) u'xW [!ڱ-lMV2Dh%8K+S+9ZF?T}y%U }f 1e *monf]QџW qZMb680p kEnii~.cm,cYG*')7Y qQ(:`i 0^l֓Ff3N믽^ ,ε4g |xW :7 e?z*Uc?FK{ue#2.Qc :ψvTO".{r3 lG( i2@7|f zT*|Nǻ/&4n#}s'9x?֐\âǾ}Fr! 5V /<}{<}ghcfќt-p]Ά^ǥ) ܁mb#_=2 Q *)\\p镡Sk׾z[ACXN Oasj= qYU4ф?,A#&/p>Oy߃QXOoA$H%CUm#&{Bw,ć[P 1G[ =Ďv7]푬= v[2bfk=Zh îkc:D0W6aˀwѲ3*}`NVp: (H^9p ہ{gJ,.^a7eʄ=CI0ǵ9}msgO[dT }Ƀ@.vbi/+ e°cLIsϜ3;#٤˽:ϼ`KQԾWl/RI 3j(e>n[S]TC!l 3|PE22r> ՗^;ͽg2fھ ΗԴKs\;LE[s4Q?n`]d"dJJXN*!g7=mYKcQ5DRO%t q8\67M8kbU *m)IuilMn@{l>LӘp}O:ס:eIّ><ל>$.Ɨe'nX_Ck|ootٱ&&8c#9bq"KeFz-|} AiyI?-+ DyNĀ3HM׆Gj::yekcugmk1R?HGY_6g]^נ KRm;h>BjZ%Hɢfʥ8ƼJ6BEdi \$ B3*b/(G?L틲F+&-Vn[.t5gLRSfV"خrK,$Bd: QWiG,mܒ3B?QXC?pam)Mɨf\*EAr'ͬ%:SξI]Ë0WpH.#_0;>Box^l%^q۱Vڹ}eم_m}qoךE[׀=d}6l)E=JmUGYi'mIBlȽ`Z^Q"vR7; MpbV FU+Hg0V rkf >|rC.4:4~"e%gNv.j5r/kz K=c," Dִip+< %⣴yFP_9.2 8i(5Bh`wVQKl.|s"nudi^B1F\:-@>KP94O U-8"ж=N.G,NpVw7>49[W,$un*N /2 g`(.]+CGJǕWp<ʗg3ERpnh1M!bKRset)sa;Ad L x4Gzqϟ4i{Jߘ][A9wWǬ>^\#O $C1,Ls5̣H7l#hdUImvqW-?}c>]B\-qY'A7L)¢{Z\o3ə!D cm pye:t8NF##Fn~h? tDbxS̃#&"͛#Oɾ'nAK1ajǹ;C4;FPGZDf`U3G-I 黀sqSᜣj<| s.t+ɱF⑳},$ 92ˡYQ焅 xO`yA.ځ}AKCgEtϏ[}:H'YHzN?uiۿK 2զKnm^m˛M) lq{&KG`F<}ʷ]q",T }hJ?5!/v*Qlb{{gl_Lo..=%+m#ͷr_#omM7w.`H39ܿAşI ]sҾ0c]pFv`dwyJl"Ytl㆗+x9KBQJ@ja!xй BO QFXB렅 &aT )aM@}1EN8sI(=060Pu0IC=qYNʇV؄ J&`|A;VϒdlܐL@p{;2fc1F1bjmaݱ*,^7O*,\z9X-R. {Dd5lD KnN/0,Pv:ս%JyÈNhֆXAYRT8^,=tvH\ed[:AG ȇgEtw B:jE!:/pugs!{L]dZwwBv0?ͣUys,e !U\E'(>`;H?AO2dIf}ԳMh<"/04"S "mg֘o3/C QO*C̚-·przA.ĝ:: JW0bo G\ڕgǠV1!J6Fu}5;a˳ŅЇfC}]@7 x$n;ĥ4X^?憑}=-{>@ o&RsR5/_(0ĩ3wNՂ{8f~in i/ct' FDBKF_ o2nwLw΢=o89G{f,{@G6>Y8X''=O ,44RCz^W^<6T'Urc ]i7[#1,iQlO$( ,&-޺7La 9kզ<_'R|x v'<4\>NJ&:$#;8x9J"Ij M@Xqo;n`8'$,v|3||ef[_mڗeҪr =gPa7A5Og5y0z D*woz_޳ej7~4i1|x/~<#f`q޼qpҩL'$~]79ühT{a,od#\nGy.nFDVY O㏑Əf{u`HwǕI[3Xi迥ɐ-63DtnAwM:F(;x/[iEH0Av;AapýlD ƦvG"hp2RƷs!.m($ގRt?\=Z, !NN`SRUH,zɢt RDf 9¾~ta/[*;^3T^H8͢m5렋;} i._?Dj! Ber+닗*j'T}!\;M`k9"Zy'Q,msӗ!Ud;5=`#O=K(i+i,֠˕z֟?V\ʰz1``ݢ@e ^OHI' [˿LI"KzЂQ/b2[Z cOUcxbc̚eEnd} ֦&AA?>E(g&SeK8'd1LZsR6U=aBT(A~β,[l7 X-lb~)(FbVD;xLmX@% "n”DZG_S`g:Vyڰ/i+6\傋QuF]tE,.u8?!|ЋFz_\7;j;@ MbC\ˇ$dn9,u ܗa/άEF;1kVtt_- $l^=`8"ܡ {Qs\)WS֟99[iŷ?AhEeeENs+#Q?>|%fsD U$)/< Yym([ `]&7mk=SUI5%_W=#Ѕv[Ęq uwR& 8ƝGI~wIߠza1e|JG\; isc""c~ffJ_B+*x,bJNE8pg@E{6b&b՘GG-#iOF:+p˨Z,F:}Q^3xFkZb̖͉+RT>YsT./{o]yp׺04 [ĽD3kOĖAVKfMb%pJ YFFߟW4Ȕ7)2"$8QoɖGwY?}bHń, 65G06{^]k1p9% =lOᕕ$'.ʩ jm@]KE'W l6mW f.VX6B% ׉+m<6ɷGHbtA.587QH]Yץt&-d̽ҙh ^MG:Z) ^D@D CmwNcE{ړy‹8@FP14MxT0y;}ʿ}emv|˽c}uZé _Y_j 􊷈ݗZ4^n:^Ɣ-#;F<SK_fcDVTVMU@eW2{Yn+~EJ1֠ ABȸ88 lvn+PvPJZa-"\N8e4>!%&!~LE+%1fD)n";GU%`~H jX?3/fHx<㾚Z:xs4Gp^S6=+-`o:.miPɬ.l*3UF68% jIJ#[-G ,YrؔTqCޢlzjlecxǓ׉ph9;j!9V2󯶒;[&0D"(E(؆^<&w&;CĤ66fLUgb%sJN_l iB=i?Kز.՗xqV`HJͱY/@xk]&OC]VFE.3 oM+͌?A!tN]f+A2(:iWEg9N*@}ϵS-~ ?ٽ, oҎ:YmMRv?܋+ݨҫK?ع/48͗ _ogZL: =Yd !li۵~MFD(kZ ~HTNs$Gֱuӌ|SnyG}quhj>R <]e\5zP@REcQ`l70˕X.חoȫ, ZlW>کPu_܅n&|--IGDv LGwyԳ7;_2z8ms"OOkQJ3_km&c TeOfRn]t' =  b I>1E 9Mrrjo!PȀk{jq񘇦[]]HMY|-"'{n-GݘďUb nY0^F&i yI(8/aXS1OmplPSyh'!E!g*#BE@wNxl8h&΅Y5_Y?P\E, >v^Z8LT}ꌔFÉ;?O7Tj \C +dmQ)-rM)?F`w;6|}~ fmduGOF65P0Ǿrl\3bYxq z! 2:#Eb s"/wS>bj"ę C`ci*ٓXsːiE`hRj1|M Id36ΑTmeP$zkU; ?] 5Iymݛ_ \iNPm6hw kIk81{/K 3)J LJJĠZ)k5h0A7s@e:=b[Wqi1(81qHLn3f-[  =k yuZ|hEmӮPsƮ;9J7X? cdw(**wH(~y!2Ji5_Z3*^`𱑗#un:PNjwh8AǧB"j uPmo{]>ڒ' z95ʋG"{SM/=2t&c=<fB33;Io+ v]|O j% A;}'>C)Hh7l|6]pȮꁏJ]uj 9u?6DCXk1GdfO5)|xHD aUƧ,A$i+VN0"ZkVqj- `z8RF>mGc,XWPP, M۰Pٜ%o-Yօx0?"amGsP q) =^oZLD?f9D[t[ul#7Aev>i' $$AvYe${bGv0!ژ#&9RAe,TIRʦ0{}. @Ö7/J0pX  - O O;+_S<'thQomЎx^.e ?@v+zƷ'}Q |4ލWSl^8wF_(Y5Za ;z,8`!jZgtzWp3s[aNQ/'?/uQ-vSt>} t?N^]Rd 1X"X\U R(Ņs}7jpYQTC~NX}VZ׾VMް;Ur‚6T4Y ͳc$8h_m \ad̻?ǖ4fP.(ؿ'<8'G16*H&ԡOYa*cŶ[]큑ʫ50(SK@l0"AD:L6hgPx[, k=CX;4oDd%y5.h#9;]?3d2r;8W~?.C0&& s:c8ÍN"TXYc"qR At># crH'w-W+ݼR}'*[-wºP K$UDY {h+kfV(IKOԋRO8T^{|=2Q@#Xmݴ%6%4TUvY+ܬ(& Z[pIġ}4IFĶf~Y@s7ڰf+|砿j##j '#Mk\ACM7'& خ#ijZx¬AA~}+f&#`3lO9Vl1"Ŋy UxiBPOFx 쮀9U{Dd!Y_~(;DnA Hp8Ѿy=Z#ɛ]9g^QX0F@{kh1'o#]K?`cq9!#$k>њ:_G4~ޜ0A*,bFis^2=R&ϼW!.G/lt-]@QliGB- @O2)ɦU}x0;触(, ;FX7E_JRS4ۿ3b}`Cw]:@u~) /r=UFڄ˒xPj-29PMZ?Nz{EVx PYXPd\8mmGC,ˣp OE$ޗuQId,WY5jH'HWFoy$ FZr(h-_+ =٭h1K_P 6d[aW@l`*l<624!bgGu.áіkYۇ׀7xo/Cqt-+|W,[%`?AP$o}9xs%u;X6q` 8^9E|+lc\ZDzrk·]Ү ^ ӱҲą5 7h`OVvu& +ٗa`KE/uy^Tjf-6#G \X,iw>В"3jst/O55E>oKP" A-!ܦ uڙ%(NmɐЕ|;N>jn?G+3 RrE68t WB:F^/|؃8B7FK6di?G!s:avr]3ͦ3^`BIg10-pfin#7> 8&W^uRhl˒V6Tf({?ȐԊ n=vd/t8w}({>ΦIlmW|M3;@ak&<3HL}Θ;{#7 D}x@ LHd ϻW*sÛA}G[*yܞ7{15sb{ckCЍ{;dP㹳/l~0NFVD3\:#њj[4˖HAӉ4=Mhn=G;; }ȫBAZD;kr&Hէ0icyA>M"I;|(JkZL>s (~ ,_N^7*x' g*gx% CkQ0G: sOga݌ˑG&|)EMG7=LpTYyЯB՜Eŕ=te5)ڛ-|'dV4-*b@*- ?pM Cn݇ U%H\r G޷E%-pٮoU_ITR 0([Bm9uыUo A$?}^RU,1}7\ЭݭeUX6reY_s:bLdjv(+J)Vq/'n|u!"N|RUl7\KqJ"߼OزYlYC8&&Lz()&|Vtؓ$q&H6Tty! <9] >w䧯m?& !(u*(CovгJ NQB ?bΎ!YG ų $;\^glĹ̵AKDD1&R/IQ \`΋Z=OyxƱM i`EgxS|HU*!8.zD\mQ̜sqIbp{z<썧`{DBuNƖ Vݼ u-vnOz`[ Xe*H12AL,֡IĔ1:jYb:S5F~uorŃZWb_v b%H"ʔGy^O?-5KTu_XR‚K K~lf;n}C5~ڊC[WDM7AVR HL 0@ e>Cb޷BD"dI*_5vZ+1RKTc deIxZ<~"J3Q2("kؙV6P]&1k\3l3Lny Y]`p+=t(uɊAҨhaxl1Ă׃N5'1C0)4y}sjf y_yH '5lAioEߟ/HD fIO?EY 6lLLx/-eeM!Z) 8C7(W,q;Ϗ CmMzl'!O% ً{4&B!xx||M#2TKUSM"?Dl/RGm_R;n-u J, +2y{}lb8wRڳ<7csqj \] 9iI2 5o[+S]\dJ֏6X&q12Q5{>o!'=Al屈l<xsFY/T3ϗr6\TPYb&v&FK: ^K|)ɮFLᇮ@{զ"|z)Fܗ%wA.rb5ݝkXTn*M2"tcա2% P8{r iv]z{&ZѱT\#d`n.M:,d2勘jKW^wWeRl%$iyV)e!<_t6DX ~`–`UnefW 33 hqM3ghT^#Jʼj+7eUgJǏ*z{='ё䩰NpsB!>D(]RK giqȿfMtӳ?ID*#&SVf^ U?bD<^d4vma5Da H{,)u#baN Ufsw ~IMVtE "`m+KMtaF^]ښ%;+CN^-7Ts"a^eoUWؿCNM n}a ;)0lUfp v<]'FLT+dҁ/!:fqboZ7+ V.de:\)7(8̏8!56 F.ڂ8^{A{ PԌ=I[{}Z[CIGWqmCVnT=e㎐<,Z_x [9Yk;!&} ڭp!5m]nѯZMW7|NgYϪQ[TBN' }`^BR<YhPfӴ@_L d(x5'+:-NjBHZ ɫUYhvjɯJ"m ڸރ΁l Twz|lA~Ͷ!yY-b׏ 2\RzjDMa%V XBNG%Zr]L0jCli^ 9:0ԁ4UHƧ]jي_lA w>7{lrF'O}Zg'ޗi&8J*_s`y8"TsANBY: o譙Er _y†sw*{ _ј ~$yi9(G$s^aHc9$ZO4aEϹ#w&_Y yM+ ɹ=&i.-CB&tSh@pmwf@i{Fϔ;6;4+]:V4ᅳJV؀s`"0"FR0{Yʐ,&2ع 4` {x:mWG.mPnQabdEUPcɝ}Y-ӡGw-!pӛ& xBF8<`w9-.mĸ:F3Lb'zQ./yUH먕QEww5󧗃eay=/N<Wvas#=ާP^SfQ/r~|<9dWJ.h{ڿe3h t#ݏsL$dEM-7n0ÒL(V vAaF+$xk]{W7v)mGUlU=%{V} q,·H"\W7trAflj\؝P aDȈP;``)DC0`0` e|dRΛ{=mC1ӹ7HPy D:N IMxi,uO| *Bb0AE\ ĠI3Ŷjn~Ndqv̎Wk ?% h6e~ Γ](#Io ,މ+uD/ w{uoR̻ryhSz9vճQs 09˅61{h23|zYg=u0z8kJVzf]q'` VyH v!ѼG"GOns_Aܸk gA~7f=T9ѓ7!vc쾐\դ8UB+, mNVW7L_ (u5ۤD|HUF9e%돳2ц7AG9TSv*[!&쾪hr]aչâmc4ܰ>9L Oz~MަZgL|㷚 EoHtYeӈmۿ+LW'_ ܄xwjOʹvOqC'rVۮiS*(4ػު> 3g)m:vx:t_3I#͙qTDd:ΕD½cb]R֠ =oC1E:&Rz`9 D^Ե^?X[. $eVA[ Qj%duff gz1ddMG, ]u}X'A<$~XXPo>)]%<'1?NlS%vwVt<}QVj71v+cԉBVs9yze;L3zxo1ZJ*rW:g0Yrp=EJ|A_2Ʃ{KgAEljJEEK_K)boJ@a,=\5tF&[p*D(-Lk?IP0SCw3h 3XotBg6bqW\#. aV,zml\PIg`cHBŘu.$);9ly_ʸ&O<ӻģ۹Z͕N0\t% I??Ge%k{ZQ] TB2oO~y4yLg.]d1w h!m(ڨc܁ c:6<>-G]Z^<:' _;K33٠mdx|8ND#bZM&P6nHgD̲<3C&]*U`iر<EQXR[rtqbIxX?M9pEMd{ه+<ΫxH׏> JXGdZ8cZ%- >c'RH}7Glpbv?RsJ sb2[1)'"mX7A~++՟Ei ]ZYF&HTܔj7#RD7<ޙ7[0a2uOR ;F1ƹ?FHMXLB.L1{2rQ;;J܅Z?5 OvpR qoސMoxE`;Fg'R.]p^ڣ~En|Nsg(lqsX^sDj#Zn&5I, ;6'{1޸(tB~!DX$6%E`]aOǽ3YTk~ o,!=Fe0z^cQ%IzTwzm@}Z7& m?᫛>ˑtO5uizAT֞eT"2ȊMOG +Cs. 0lymA3xy?VZ[HЎ٠~NAhWXz6Qd '7$JLu4ّ!P#U%0_Ԏ4hU-/8HNӣ\ϨgT 2 F9a÷*׀Y`rNJOFojn>Q+i$v\eᴵ׎CA:.q^=C*(Y5,ž쁋a:7p'֚쯓(O\0 78T)t˽e"fZ?2^#'W,FȠ^brv5Z;*\)*Hn1M;-^0Yny8$^Tt0}=J; ?"@7v!׌e̺q7O@5 MRw93pUS [Iܠ sb @D++T6c&KB4G828P,p0+ Lf w cr)VZ#bԣJi.A7DL#\%Im CKe,KP"ŗ-aPoB@D"AN *ٝU# K内'oZEu'uN$:Ţe& ky{WIY _+}|-[o!-g1~^vܮZHK)LC Cʚt[7 %<ŻGSHݛx" p@N8ʚbj |bY*ᯘ}P?PYFVؖbyx kBgTm,鎁plǪ3Bĩ':V'+Bx8MNi9n=C&A_kr~ j_\ף-B٪^c`_**<)O-Dt xc_UGc2<]^|eq$JqyRBRkE"A+OэJVj^,)iN+I&!Bm"Va;e9}N HsỳDߡѵOԭdulU߿Ka?өCAG`I mې%"6yDX/hn5\r3hh~d8ъR!]5~ ,4Oh89?#i6w5yПFY}p)Í7vL t^W|JM[ȕk2iafPw#uQ(Ks# }/TӪHTr&+ ǩfH&Ѹ^+A0N& Veml SQrYp<ŝʾ#9h|[?h>MJ"Gh?^)3Q-\iT9ۆy,N-f/(>U"> 0:^"DR&\;cj5bъK2Tg\?4~QB瘞4P}q)hj0 :`4o׿]is?d\wtwedZ4-dv@PGjOepN oC ;j!ﵾ~%鄵-YCش4iK-:iŪ96 lՔېhDEm|:fId*5.`5LeG"qoY#Q_C;U$|6"jX2ƺ"WO(DƓd#84#!_/Lu 4Ӕ@ʿ!# ې|F) n+jۼA> 7 6c1 xr̓,KGwɯgW.@Rg,&P{N|ե-`ggFH" ]?{'6'9AܸG es0dǞ{͡2io =x&+XYիYObXRiߛ:$i!B2;CRl *9VF8 Z]>SC1ždNȧG]c>c nf8klLGv_ViO3$Aq*SIBle:>B*"EchIuyM(_[r|`aujZ5)ʠP}$ c=6aϯJ!dD-QԄچ v7~OLK*$R& ɇL !uyVYa˵'Z}kSu7v-=:hBked-]+֞䭏ѣp4j=aOY5D|T^UY P3-`7੆sۗxŇl|9m]Pg=or0[)1unFHx*$mح ce0QDYx6a3ș)n N lMU 9ܨ_Q{#kv j ̀Z5M?; 4PD5ݡ35"M'hYۂ5TNNñk*pWQnP^r 4?FD*ۺS \6 \G-Q:T)⧾׭w+hJ'8r?qHCV)"'/+A/XԀIf[!hQu{Ť[&|cBi.Z o.w~C :x+8%#_4*֨R.(AE 2P<(^ɴ9BJuV:i[ko'pka4=쟷f#JQ-SiM!EQKs+1x:q'<D`g?D5K7C; ]LM@Ul)Hv:M?I<3e ~U<3ʒQ-rJoYAI*ڪ6Qp2iO0z0S˕FqrS L-o>n.ֵgLڤ"Ao}swr&(!6 :d=_Y6H*s(.eB\,;tR}H&e 9Űeh|,GY<> A ٗw!ĐtEӻbeY FGwڀ.UIF~/A+QY hN+\q_~iKm{eWΧu‰yk(kpT0P-2cqErHx} )smBL^bXQ+ǿ|a.eHxs!  pâ VA _X /onaKd)1QD^M"g W tfm X6x qɯN_ȍm (_mQE~1o8X.7ؠ\d>݇2z-A. ~$W`iسoh_XD"ե6iK^;ovKOƌr&0ұp*8 Dc?TbA]n:?|謢`1eU$(d|,ʕ N k&)fR\~"oT; 2M=g02Exq^BqՅyթڬc4}k/_$() m>lh&м/Mʈ;4*ꌍ;R=J"opHK֢_9H29mްqjƆj3@JkIB5ɖwRY `#xTqf_OGZYjJaF8)~*.v8XToUm4FBj`.5FZ2ˬET.:^gι=뤟bx8S~,)- ;zL_V@fG,i6[+J1/E/#Aށ=YdNyJ*cև[>4;O@q ੩kx@)bpQ|)ߑ^xnR_/!fb\K) cCB©;LNLgԀ6[Sb6bexrɫzB9NPуf(Hֹ(=|R!h)༱׿J^"Y1`7  {:\ծß4!C2dӆmtܫ8OxVMZ'V/72QCp-KEQdl<9u[%-O!]>`eh9pBl;?XA ]g""#`D8rlSˊX¯7{sl2|r eP}o,G.^MGd{!B3:?zUym7phIa2[ _B.u{h \uej:N;Y]dxus#A݄Áerp߂^ Zsi"1))%.ZRO<,Obo}c̑q2,)&V轏( hlyi9L@ڸ0t Vb/-(pcثqt(czn8oDG>;@%=Ͳ`z|:Pw*? AٳQ=s>%$dhr{GKGtCB&=@om.ANe2RJs| .ߌ%#;7Qttw ?4QΓJmIT(w('n gKðFo :򽄒'=EaƬk$zc YN4"3ѯ .دQA(8&-d%2͐'аmR[$n7(3I:dK_fES¢2؈cHÅs?zA84Ay!-s>J'n("̈́*jֳ7&EAQ* tx=̚-/.y?|csrb}R2ˀ;5wp:Vy%tW x2uVYFt,(ȯ e? l$4Yyq5HA5Oyg2`׽߬z0>IKsV|v\j3GRLnok9ష: ɲ2Ky$g8;mv 3 h(AKL_Bfw`SC0ʮ: =~ "֍8 0b[b h͊!)k/k,q2W0(!xc*F lN_Ls7!/5 23*Uys:sR>)q &kNOܮ-niuȥ|9V-|P̹濌^}$k;˺P(};Uq5嫱ߵZ)<9BQ=oլT;Wg.+ UTWpRK5]0?z<<|TO×"#>h \S-InЮiN fT .V{횛:'0TNMp }%QEA$ De M?dvNjA?8h^1kqrv̧j}qX }՗i5{}:"ڐm_J7FA=Mtm!;YΜ7u&.gSWpbrYta~]DA9j}J\oȝ:ڑ4 I1>gDҎ VƫE "iQ0b6B >ϳPh FhuGWBjνUKmw0BB?%qMlPs@_c,4)K+D0?a"a\4¬8[D G})һw )>ją22&l&gm3$i٦^KUZ\SGLڗ[7F#?{Pv&T̅@1`Vŀ|;WEDq r:qZ!&# -!S=<Q"{ȤJSQ卬=eQ)Br!G A篏֜Xh`'!*BRlֆkG#`p:\%i+fiU vS\6C}-ciKBG ^>^81?pߐA`{z.4U`tS._!*Xc$o<[lxed!5Ѧ\zseAMB[[; C?p5N ?*wgv"ԁ,(Y/:<~g h3RpA=|LQʱh45}s-l})'Qhe2IQnoOƓ7FROPM񿳯M2><^C9+j,!gl ViWFV7ms{+2ģ&:`g'; xǾP'jeϾCW׈1)=ҿ4ˏG8t}7ղ ^)(.2/n;g]%_#\ٕ"<*D-t~4'kĉ~v4ڵ+!L!'!?riBA>ܚC M9u 2e^4OB5w4}ek@1\ȻMĕٺ[4|{kG1Spska{:!o۷$acN /TS-ʔ3WG+zŗ`y$d-X#FHhr1(0wiMnWN:j$ GC/5׈ٝ wdٟӃoCn)gϜ޽;cߵ+* {|Xy>a;~!A$?4v{VR PԾ9gkx4N6~M50R #A+oVMiȏ@Ԉ@c_rjI7C+7CwdD@ۊr*H8| m! A޽_ B!x/@yYuVXJiI@ wXG@JW8$ @; b_g{סRnG>cަGMa؈~Sq}>0 Q:>8.LqZ(唧 X ;sn!˞jr.♠Mo(3_e?,(nz4  5 /]6NF0|B3p#w7VQ`ӅVsL/{q74D,b@j&dIĶߏzOqxp=TZk v1S.1;Xax$ c=b(RBCKL0,_ | c N&= X}O R]0651l6XO,kWANB5! C]eS}# ʃtqq9V'*yee2C`7 Ȣ~ \b^vs(";=!n-y5a>nD;`nGhXW'w[D ÂYR"wt#a#L?SMB LS및R1oKىsKs|86lZA$f@B(^.9L4hjVMo(<禜WމM50z7z*WKyhbh<+@Ȅwn.ȋі] SfT:^m(dOTS妞ge-^O|T<$cn{}o>>!Q= yZ Dv?baUy,L6,ۘuGxXСK]7_ $ۤ/꧿[X(D) q_r`.,ڟ MӱjhHqb5Kz[;}C3l檠BR9MhCbf+}F&)<ژdz-m@Dtekv)٠{q:vj@&j-.i ӽ"Km OALQA eWut-%G o5 vWűzB59ܫ2'c=;c)c2k6׉钭(J} +Qߓ3; Lt3]S LMcw_\6ד@?@0O_̲PHhP&w&ݸFx@Ez1-[V8q voladV+w-2^6pU4m,R`́s4a;ŸvŹα?ì-̌(%{.Co>(;z괘p &BpFv0xeku#h1UWk\kU.%ͽeQ"5q>2-hpwjx* n¦c.6'C}ѯa5.!>²<Č#^F>RZ o{U Ilȳv݅5H':PNE_ )_B8(Ouq=ڞW}@_s{>cer sU@D35+LGHjTY ^QFqF#SR7bNaQ]\y'1BKǯy,Pp7bXHc=ez KG?dȵ7\QNuc$Q\ыCd>m~H.e@8X%IH=mM)ѯ ud!+%dkHX7rRUu]p$k|fͮPEOt:4Lg=۶@1eEX G@sfy1fG@eˑ/ېǘa6X{o\C~C?sHxqv`AW5:Z7Zn !GI _󲆂[ͪQD}p3٘GFYE ]:}v"\NcB/ F yp aG p nSU,kS1:),B(K Pt1w2:납%loyg&d}tzVC!Z6;}'> x#d碄D>0p~Bg\X%am"E{Hu<,q/X)MZ3ۀR3,Q\C: ,2XV7F8UE2ԞW`YcR5K咡Kj6տNϥ)lLtܝl`Jak"a`[US=~S`pk0,m^, w }3^J$2h_6N)}*ݹ-yFm4fJJ/ FWzRK"9[QS#ƻhbbʝ^q~-׮IM:ƛzwoP\W'9LYJ`h'H⼤L?׉A5jOʦ.Cf-ͅ 9秼KH ,t*>uh~ =:`uRg tS.(LJ2!h)5ޜ`U"x0lp^dͮH[( -+!+m#}0Oo]Gk3jrHݛ*fj k9 YQ] .p^ A0*}vD9H؊jđD.eQ(q_gh^N$*E9J ߭%Emo"b45_,I2x}jkn4|I$xGb$#BhAez%b[,f?hifN`)*ƦLC=JH]`<$)٫~iݟ7iFP!;W\U(WGTK*t: }5S'sWK*`k8_CB[ny^~8K"vdViW aXioRH!J^E{it 8}땴ޜhPdC;BLU4%p\oЋ@fV jk D\{ji \ʼnA0fx4&ÄAwu$Mg"PUDH5Ft;z"|kdSK6iYŲ'DQوrμ !]D*]&>[hs-NSpsSK|iT_Db]g߬µ8MQPJ-q_gB$a?ڭ .Hd=Gdk +E%_mn8(e: #SJԏrb$" xݔ @>WώM-ۗ~- ڀ5¸#{,f7:̊HUG+ y7էEڹ1PA HD G!%&Ô9 E'M)ZPjw1Iky) zh %_J<BZ@VjQgϜGFK`S$.5|r~]1Cd52!6\.V;Bz0s(Pg Y=bhaÁ7Tm$mnndmz萨W0&`]{>k;juT5phXVH]z<ݥ' ").OGqF,j_zORBԓh 7(lk(ћ9PhlY Pt-RZĶ# m>۪*@,Sj=r_ÚZGB OpõaK"4o-;n->Zޭr}BsVnY;_.P@P.Xf9+m(zeilX \AkLdϣZcYb%A¥GtNg7=O(iaM7/mZ߿KKC"5i/ }oNvnh_|t pnԩWeISkn⡂#i%r4bX*4PVDF7t.tм&xdwە ZS‹?G?BC&#鮜1rjT\J`ԤW~,2zAP?_{<㤈D5C-hڋ=KT$3 7) uI5/cr"Ch_SmЏ . »[jUrK8̣HI:&td zx8.2/T/-xcCy'"THx3tz{'̇6Ε!x-׿Lh"ʈxHQ^1?im~tC]9hi5Cu^-!)8 IEPBfp@D|I˅q8k) TERFq93 'iE U@.aʳڤcy&:kC@F%V%i`Db@D X~H3;49V`JeTxPC|GŃŵ:mcr0  hCdZaU0smхYOYyHwen,_q"p<5A:0 5OS^4ZREW:'~'nx>֗!/9>+%c}Z%& 6)%njE!kc5! T,2$h5XbPXz=ҎtEx%+XD]O E8m0uړnKe@cB`1hO1ϴ^PR:i#o!%a'yGZQ((΄ 8Άb .D^Gf?ZA= xx`n*MFyH"|nDcb[2_L"Jr4zP"ՌA9IMIo#zz :> Tķ}n]_ &%/W10L84ZӴܐC\1BL^ BZj%ͱ`QP#HYۼc #ay5)lY SA{({n=]xMMJ^r=1^{qAyJW50c[Qo1(ʊ!%JB¶xtBSpFJ&)f3xߥ*APc7 RCŁsφwAHUmSonY&g_>=U8Q㹁>RGy%'@T8? d/W- Lt|uzOl8ēd'>˫2#h2Tl˟+$v#di-ieϙ҃Ԩet3Q淺Fd*k& Y'[*4[ f-ܥ1rnb+db%m W[כ\=/Gwr]?)O0f{9 R^Ly20/a-X{݆3}FNJ" |Ņ WU`B￞]"R}myd;9}Ivj[Շoy>YEQdcnv5z$uBR"MkM<6o`L4{X-AJ0|rn0hcnNbCɬ|`2؅o 9="uNfF=}YT>w|P;}~ '!-^20ոyk|@$* 5lFRpҊ[ۅ9R:KdzDNR.WhD;Bx>Gß}t2ٸ󐎋H}x?vmJ(6d*wɏ"nM-H3sS9w)*ʎԝqsܸo<hb5Zgg_џQ.J6y%#Hr>n`p+)~ܺZrۇ,)PL4شr0y ;QrYLNNs$F6dYzp ~ /z]P ʕ,Z0HVZhfu:nK$gۈ2V{j_ epRıh_N~xgqi%5xOLDPm <רהXZnjJ/&ԏ+Ñ~z¬!CoK(jP8\GEg~4+8`k$"hQ]SM)ZOz0 a;,jtwim}q 5lOU$s\Z %+^I9)q.BK;ىf+7s}V@OR}ȝGKoP_|z`{$nICYR?3?+ZR?513=v]jqweϸZ t/=B7xuдu;]t?٧4A=vSU^$vAMx/QL5]R-uU<94*U;-~ٖhkSVt6wy(SD'CrBdVEzm<8ǞKPۮ HzywJ(3s8gVDHvBv$\>p>__Ү3;(R">{R{y0?&:Hdۗ ^dF995{FS IǼDYb8T~aLy;:I(]sҧ" 0䏊qNxZ\3 KzTP %@'cߧaެQH~ OEu=Cdj?=@rxRV\OSu6J'߼1Kh%9kDՈ!9. B#X (4*\w,\8c5Y3R D@D(N͕v)<y_)JH 8[ʋKɑ)@D5dd=3n~\>Wo淹t5a M Ӵ)}6&⋁C)~9dcdrW'I5' H=0Cٝ,  Lp҈UZީV|m!wtǭiWFq7j>|#C3> 䌟=@2Q9ptމ,{)kxmO 1}A%gfw6TaXSf7$;ݺΛGBn% /X'heP.(/mA_̑(J7@HC@  ,O;(Y\ujW]AGN9hh\@$ UݕyS+_'ǗP!{R)E^`~?x^(pgL7Ԟ.:!nq]V.00yvSKWww}bZÄO/6;7`&[[u9eڐ$EZ#$dgr BK]dwPiyia )uZ5Lփt""F =s8"{0b4IeAoDoyPs|RD9QO8P/mixuDjkX/s1CpXe6ݍdn:QZcpf˻4-[M;V|QC -iA4pCZ&zZ;w9lO-U\TDcpܸ}xZ, uf4F㈴wz]nZknmS'-kʽ?.Љ]%XwjK,r7S7kΗJ3%A D])Z\TJt<J`줎HӒ:^C9z[R+ uUsaX]qZɦM El3W,^Dn٣tLi|wY/Ťvp$_(؆s[懛VTj^gBك X ߱yr~2L/(7 X},^˳!GotYҪ`Mp=&FGּaVAcZ=NO+PG+bbc&* :!HKRp9 `.K5&JSve;IKsEҹy~5"XڰGz =>$M1k!_A}\۪Z,ceɃ7̯Ce(/x_?@Fqc+K!iy#t(dVoFy@ A M9#C `*XFmgQ 0i?{up$߲TzG^Im2\EcRzD{(,e+UA{?elOTt0 YHc,Xia "%xm 7ɑܝA Wy9yqWvJSϫqR440@ɞ%+*JrR⦻YX4H :&(~b=H|jLOE]8t ݡ3 H M YU !vF` ,@ىdbgD|)\wz61GU"z^eP 0|FŮgPUmඅF+wg2$ zaB΢H /%-ν'd&c<1?tqTު/2jZ8n/bshꚺr Y9jVnBڊj`LXd[ ;4!H޵pGO!*\*v%7^1P[s켸,ߙo՗h۝ѣMX2CY4%ʾLCHGߋVG*uv؉1+4Cs} ɓh늄űiYzW};Ub6 _9}J~֖;ӁFFͩ?9s>ʒrUN=stez%5d{8gl>9 A=d5w:Zsldȱ 'SǶ̜69;/O2}gJC~A@ک; pٯ(w?pS&.db*[#=XMs.7h1[ bwTEeMFphlDCAz!`s>Q残#f%R ܏ N ?=?%ԄP*, FTE'& P>>wIpzӜ7$MEcN‚O悆&z2)>XYz @!d0o5Y8@P{42M9u8wÔ'px\ vaLt!R71i1s#:g/TI2KمJws\,K.)LU99Fv0tFeeߒ_/?%xg=[n8%~[ ߄o#0YH2`bQ د6<4opIU,GvcѤm0݀ͣ Sf̰o mc.~xKmR0h"#9$|=B:TkVЯcJ*a MTF}ABG̲ M.*c"&s_b5!lb{^RĆy}nȔ/#/P{ lg%*T.畦o:Bɶ+͞/%ud^=NxZ}#KvŖ;YfØkz7)ѹF-M[gjz߱2DDw-wrU2YB#_=g9bIpҠn+2\ܜկJxKH#u& qrAP*.Q7/ AHށPIjZ P5IGEg$ɣ򺕓Ej ]ӺAcpcbv-y-}sinFݕQx?'|+I%5Qr‘[Ʈ0P,-+MS?򵏨qzK Jw¡P;R% v6ȁ$/o]۴`?Kn~/JY3Eϋ_lv; 憤Zk?g!Ym[%f̆w2~#׬Z0eT N9hқ!$vkj%Jbs~SSJ`o?]4Wn97vPR x|{JN=9tOp a{٤>)9.t_c]>?E1`+I1w?i/1vcWz(2N KHI8 I*&"[']6]m4nψdPѭIf +;c)~O/18</1XOi?QܒPׅ,2v :[92ꀛv \זƎ3ldEVTd"I!.zChDn-})F:raFqS>vt,u>+3%(zzv=ÔV1+w{"0E|[ȄGp֎ðL9foKS1*S~il`58i[֮>9eW+Djq,n -lr|D#ɸS `39-ŽfZHl#V\g \2crXܣB6u[!&ٸGz,'{i n/B!//iОs"a|D0EmyrVY1c8v e^ZHxآ/;s"A$ZW ?g9V ;e˄'H wF`ٟדraCTi/уUf2B#/nm10-Z343jŋ۞+q#N[Ժ-L+O 9}dJ. O&ͧѹB,Ϊ0C Z6Tμ 6~9yHH=;}&凧 ={ەw"p)'yM Rl3X\ґ0 e˪v<,6XyQ* @^ҢNlXpEf鐜wE}g7fk • rWHvYXTiҏctTD7] iB]EYDȟ#ߦܻj,el4hiPs!i2!vRQ@$Jάau۟Td:Ҥ:7x>-$G9iN9>#S,]7MjkRvqJdFr.99.y}E>D<܉8vG$bYqfjcЀb c}N g+׸談紑J@˫=N[ʝT͗5ЄO'{:"ŠsbBxÕoL*)(a4,Q[ MQ~n $n%öak ╀*JqJ8%ӑ0xp=7\n+W@'"}-4׾GC>nQH} hsYw_ SjUUt'e7[K*fY8Ӊ~HaL1}w Ez\#0I[2i^ӅˌBRl(nEIʫÕDr:/_ڙХL6jXwϦ`72M Sxn{Df]'Q(W SGO+dcU\==s^&*eykpǧvJ\APKvWBVe2Օ@hMX3,9fv$(V@0qvLӀ*8saͺtWxODABY6>ogȎ%WD1U(wwG7*6M0])rsYW4 TEh\1;=I ?6a~<}f%blR]+תߤ0FaUl<-Ӝ_^O-҃Z<5Jj*N2fru <-ȸ[O~>../*`5 Uw^v58kהgq4 ]T^NKq(J NR"OWFZ3QlvI4y[Jܑz$*DOA }B @dd%?00^@d4ʚs-;mO*~BZSGHm b%`@*؈%"unD"ΓhI+I> c^U*|k*kT,O̷КY"^y&1Q7~Wa.12t,83B~^`JKm)"{А*8#5_}#j d/k] L(p;^b ~Rv5In+Dm#' M/N6GMoťc~al,CoK@B?caMpw&]Pox? 1'GQR TߐhȣJ2KnzP1} L"Jw# UԌ&@s 4ƾg 2|f}vhٖK>"]ag U= +a'EBԌWw4c¢h×p4 NX?6ЅN*0ڟfߢ$b3"ş LI%+FH$1kU |{\ )60AKT$b9 P |5SCѤިkk R#h9ƇA!v`X6V㷾2:HybD<lvW|ҥ>Goa[Kخ<UOB[d5+!Q`]!؅.~U~uG7ġg0&m&)'0FnX ʾgVUfd6hݷҙyhq68`}n?@Kpecņj D+c"'*-kޅ~+NǴFЉf!tvsB*.3LPnSO\'^[*ȷڟ.)އfWB*Jzэ gg+JE^_f߫F@)0 dz5i?*pyli8ة͝!A,BKe|gzp6q|6HZ(M:%Q[m%;m笆x| p-$g\|5"1}qE+a>BTjSJuq0 s$)+[d;$/bլpzg9 7BAh㝦Snf{O|9Z hV)-qf&K^tӔ}1/DV:MUkIhe)"}_|Dedq E\9,I^@A <#8];? O=} k76[wцu%6"˴;Z!Lf5O+ $ǹhBk8 =J HC]}1شa/h :E_Q-w0^-QuVj=)QR"z~ `sx⩬;&lAv}L;j%{ _<t!r0Fk*}(Pt@%f zPC[AH)1[Cw\Ц7]C?\7+eD*tk;F![{o}_[8X`. &/1_k'O2 eGjZp:PEruL_W(xn *])gR#؉!Oc{B{T{ {rEqє4eRQE Hl>J!GmUL q߀_1=bsmL<؋ i/o{>g8NuWѯ:p|\ ǯm7cBmZ;-N<3^pA]1,NV?EpR焞R`-r,ajWW΁NʫxlmjiQ& | ăCɪ#TW4N1|@Eg*ًlQ-RVoi%1ˤV?Ș]g$U՞NsU7}HJh.䃕WCQJs?ʅƏ$k*q: Vr;՟].g*9`glZQ;]H\-/It[gb#&~sEGvM͓Mt SRS9'`6AqW *Zqm^`+{l_}Y7(Iuce,GmԐU̴5+\+=a,]|0О h9B4:ց,,h+?U\uWȚf~MKw09;Ad&K RcИTT4jEQ9~]K/p/$ }w5M:&=3;{X' Iǒ 엂hOt/  ]a+u;ћ.nԟs/;J PFѳu @{-dpOBuPbN 0)sZ9|T+=v QrId9y4' rx3 n&suц0JXb1Au\YI[\Drn)$jeI .4Ksu(]*u@%؎DnVɟs/ ˨M_wZ@TXqb0ǙB?龼NӏSlKjZ )_Ό%b/J#9s[ }!vIz)sl76;(hD?sd)da-# Ѩ:-߉:IiK%I{3Q^N[Hͣle^m/EkK~Po ?k<^${ ٪uA7/VPx&x}BT=pOb"ǧbcz,'N &׍ 5O)_ЊZ̽ jXCA;;ʩJ,CuPr8e'\4$B7*=~92˞KtT9B a?\& <' `7]vs/OJECQh]wq,a&}c-OPsk5K~?|U̳y#ҵf‘pUn Ѥ)>ːˊ~l%)U^ut|Κ>wI33'$~\._Lo1>iAaT35V8tf.aW?l𮓴lQ<2G Wÿ X"i%zh 3\f lX HǚrTHd8/ƕʚFn EDxiIt_RRjuu-ea3+ri̕-jU-!XR"Y"*t"M%Ceka4؏/r:#w"-n }ȣvQL}%mCrjP:Mdr6Ji%9Cd}٧z-mv ?BAydDz{j%QbP1tD.\''U >^@Sqn礕c{Vd%73efw"Oӎvnn딪_4# eTt>qSQ`]&ݖ, ˜E4( rb1> Mwgh>j&ʘA.~T}< Yyt<>RbŽؿȂ(㹰yBe))(NR6˜Kyfy/'2=F,)pXi'ޤBUDrT7y*:8hnw9%AwYa|n'nD|a ZΙw!A6<ꆁ?|0O?I7mI*"xAjtdkxF#.10Vϸ$p<]@mQD/-+)-r^jQM> 8玶6,R Lq8Faff)sy:I:=S|7}Dό>͹6KsNvUzޫNaGiFy^eܓd@\C.= lI0\0jLQPg%"U O΍u/ffE- hnTZ%|Ze^4JM_ΌVDLLѦJDӘT@fm(lƠi ѱ">J?Y]wKI YK&f/`mIEqnZ i=^$@l!&߶I2]Ͽ+bԂ:_^3va l8u}md=\/Kl:U/S1PoԮeaa,L~0;~L'lsDXVmf~F[he(Jq &]<|H[n[b"~VSCIu\L&N{T_[iǁ}hY4Éw:hfP  pŨu'!_+?5zS;TN-Rm љq>d|ڻ5b"EHĆBاN*PwF!_F13`K&At膣#X=ۘAsU-.D < {L涢-w$@=衻KJY/4Z{Uvi:_}ұC3U gskWybf%)u!ߵ.s(YT -%ք dVqyœ6yj*u W+G.D$0K&Iٰ6?V[u!݊c`h$ z`~Kib՜}@zCZ/ iԳ.\J̬6‹gVtH홿zUIt~IVҠE{6{D[Deh$1݀GZSaٙa@\8[:(@Q _idQ`H0nia)3eH^;+Z|" {ȕ*l0uҢR{4af -B> oiӪDb^S-!jC9TFCsVkjܤMU7,{& *z'#ؓQK(X|ʔ )G- C kbÌ@UoBLvP6zN=޵F}'Aw,W9]FQ|4tJ`+ͤݪlHX-|l094)nk^0axVN[9 ⧹MԄИѵ#԰*TWV[)Ⱥ9j8 $eN ]yñfV.-̀E/7,l 4붟VT=/#]Mj|)4e6T5,M \27/u &|CD!#ʺXHüΪ h u:zQ<s0GS幀G7y󇆔B;(邭h*t91& &z;’oAْt w]:.W -:qxАk!ZPr_[2/W, /8M+ ]gKj1b>EZ| 89 ֿ&+/:4)P2"!ÃrϮ2%zK~@;Mza!s#>(!ϴkc52 o!L,)&hO .U"҉&L$LMķTfYr2x7ՒU5^h5"ljEpϱF}.ߊAeYRKͅXH0=ٶ JrG>j R X"Э5;jUʞ`hXY9'BuK%%O^On.H+}37 r%L9SX%?R)#aNaS?Eat4gZ-H̐玜1lCEr'BR|=quH9LݲP܉%/ρ!h67f:?검S Pp=~3R\BRV^"%Hj$obF6$`F$x A6^q4T5d$- g6e N.mY򄊐ۓtm*h' җ,2QUy0،d>L$OXVH{+:DYg2-#컈\B07ː=FJw#a(]iֿ봢ھU_`S}P{JMZI~BRȂn(Zp/opv,d *HF[n +,4rriX'3D*S{ {Y<JhzEeH oFqbÌpp6GTPT3~#{>9iW&@b9F8`dVCaz1eVB\eXrasQ!/I`Ci h?0?OZ#vx#IV6kM׾A#+@}AqHS2&`x;Y)ypfiz ,-`hzF~؁ly]҆qT #\U3b/  LFNRYi#8qM)sU_hܮO3BW!:_,!΢!0 ,0;Ŋ#M5 jmi d^v٭a!x%iInw9 W@uܟH1qP-O\]5T˻iNKwi`i^Uk) [FNgXmψ5+@ V3D7K"p#ld3:N )STzr!F Z`;BLØ.ۍ==}E R+ ·]։AbFsdK O6FVVO#Ƴ=Mʪ[cLt~çR=XZZyήAM:=vG&`VB#kx^ڵw`mp3p+wU(zvG/ˠjWY!AFqZjY:E!-ŵ~lLȍ׌,Hu( =1ixTAk_eNiu_PDAU3 xZ&'#fX'WqIk-?2BfKVeѿYZ04tVƆ'Š4S bFfv~x UQ|EN1By/qoi@=1nN)poMQKE`'CGvV 7mE&,-I EDҪ"ư kx#imPN)ƁlbAr6!y5 ժCt$ىf]U4,$i)i&l ̕&@yJMPJ3cMÄn 3+b:uX|EDoVRo9jojÅ(h~a@_$5YcH:6C,{?&9U ]E(iҍgV?ޠ{hĨ7gQ,Ľڱ)Zb'V-pvC3%R#>)گrbJjbT3.3tgxӶ[LJNbR\uhWg-wfЫOeI!&+Q~$2)f-ҜӶ^ ӂ?J[Q>GjtyS<.v.k*㤟ȹ^Ozs Fayi'#Ύi?&FI{Œ>]wdV tǑ"bKOa:2Ug!\y4 d&.V̽@9 Nt >RQծ^K9on։Kq:ßqQԗ!|>_wTU@s`fQm:3 Zf(Gw${Yca@ꐽa}̨TW݌YЪasf G}"&ZW'6> Hįzc5wҳS2mɣx gpx[fGNӷ $E咝l`kZX͆SRK ;^VM-@M-X,+s (#iЋB؃?Tΰ(8§F)[3\ovi-e (7h^Pn<1Nf ~{" 5 a دpR\0s۴ U@I0L<z rx{u…LgX-Txq 2;xeUOs<[]kK(tIsz7 3<0wIglx_.p]$c)v1ua("|'ׁNSRC&_9ȇU*iL WMQn߽iٱʢbb h_l ǡ߱s6 p|}XqHlf  O<C":?&ur'1m+a,:˂R/_W^;4èN f~Dw = LH7`1% -&0\!@.%(7BwRXqdBj'U(r;٫G+fr<=ᭈXtrzꌙq=7rūƜǤDnZ%_AaR]F{PCd"Q_k5iQmA,4ڵ_~faOʻ hr/YnGf rt sVs6_;bc<բACn-2Y^s  ;1|–j'pf#(qgN9;y߳ALӠTRG{oaoI7bf,MZBlg^Rj Im_ G )&n&_S[JKNvl9WV3=$e):VOvn|k4o^BA cz Êd9r$/s7ȷ\l푤BA.>出ޓeϩ"/IKcgG {toJ[_iiϦżM@A M莸)Si?Xa>)k(拽OP\Õ4qkkǽ|}FT&nW:[[{rt`ދKI~ !3$ I+vH>Of|7/&vc (N±_'rwI*鑱 o){:Ddy֌4ar~fjf_+SKp+{3)Gyfd:a.Q{RLoli{lB%]wdFAaЁЫqڎ7=шM PԨQl?ƶ6υ2Ne^ p5d9f@X=)`4?X[[szh1mP z]t@bҙE T\ڍ}X~aeWפ)ܕ1O <j5/OL/BMiEH qb]Y+c{ޑ AuQ^}ʑ#ЇG51o>W.4j6 2JR.N-HE8v_OȨ$a8ۤO GCۡ*]Y#D퉻w߇1,E!̓|\T-tGC,q1#{EBc:6,Ew(:kI;W\sq+JmW]YVZyA ݢ1@6|G~n7{7d`1g2XdwFda$= [F,|:~Y!_RHMiM[=F vY(s?}h}"BԗPvVT+cʳl,|hmB`qQۜ'@Zť{āszަSm qs[U%ojޮ‘4'T{&x-g/cM!teC@ӷ:J807GźP. (ШD&KPץo?2+"7%@~m{7”vq\H ;p_%;o$E\b6\p5q_|a$Nyyq 35<U5|B^")Ƴ~.Ft0>xz2+M%yA?`(: ׷KJgW =*` aV2 e U0*2Z-_%_N'TPtR4,y)e;r^/MЌz*=!OԵǢ˻6R'r;bAWR@̠tEl ЗuBuh) nMPBA8UBt 23 ʉoP$GTq"jCbq iBs-i8P>g9( ' ꩮјiPt~kpk;ޏM7dâ9,̨] k ] "BGǁ pa{>c߁qO2c}$M~M0IYPJ.xRz""֓Y GzdCy.JǏz9뽯lw;b"e "17lb8w$NcLMfhV j t!?Q}\O؃g?9]df2=?_ܜX';O 2^l@ _W9v-<.u qroBCYdE|)-AWXQZjhWή6ӧZUmTcN{H 橳v<4 d[Ya#X+vˮ= _%a/9쑿%;u 0TK-6j (<}? !RB ۟qU?xmEN'ht8JFpV&@Q 4fBۨ2Qx*7$۳!-nǃـM1B!tqKZQ& xY-Rdžª>$GsruhSſteCf&OJ/J"S_,9-g7s{$0L}XӪCF[Ut'j/{f)1KCĒ p#6BS`O#!r0soa&G%!u9h(&#}ahY&uN_"+\ `$-/4z9$%otGp\ð&gxcR>WSt $3'hr)zgO̙·uѷ|gTx#E ];ǔDR}ubmA3h%U7؄vvVTswO(C 4QY¾^*.!tem3EUf$@_C%5*#>I4?UПǫqax\p>2 )+h უܮe aǶ׫IKZUZ<@G sfO>WMm(:*6[{*u$:RcU.Bhv`?F?N`ĭH<$,r{enA { =$\y )ĈIץ7bH\SY5A{@a^ZM}ouu?q _[o -!J\2:8ra'=UA/Wzoz1} 8竅D̸} ߜ JWM/t5kH 㚕$DŽub:|kЈl$ﴌLxfJQq'!TUҸ6Zͱg%W1DoInhA.1M⫿jۣc؞ʜw!JqyW=f/l/ĭp!0:b *jqQ ĝؠ ㆦH27Y"ʊc{9 t|*z+h,Gx dmʼnR&h|^,cuKq]!' Q{: s3Y.AfsTϥMXHY3죛DmU3 bK:/!QL1W:(@&\#Q躐}1$S4@/p6K+rzz_Gҭ!iwEpfLYI-ֳbh*5V[h`Phzqqp~ '8[Z ݶXgn'8