}
     if (!(isset($vouchermaxmb[$key]) || isset($vouchermaxtime[$key]))) {
         $warning[] = T_("It is not recommended having vouchers without a data or time limit");
     }
     // validate limits
     //$error[] = validate_datalimit($groupdatalimit[$key]);
     // Silence warnings (@) as we don't care if they are set or not'
     if (!\Grase\Validate::numericLimit($vouchermaxtime[$key])) {
         $error[] = sprintf(T_("Invalid value '%s' for Time Limit"), $vouchermaxtime[$key]);
     }
     if (!\Grase\Validate::numericLimit($vouchermaxmb[$key])) {
         $error[] = sprintf(T_("Invalid value '%s' for Data Limit"), $vouchermaxmb[$key]);
     }
     // TODO validate groupname, it already comes in in the correct format though
     $error = array_filter($error);
     $vouchersettings[\Grase\Clean::groupName($name)] = array_filter(array('VoucherName' => \Grase\Clean::groupName($name), 'VoucherLabel' => \Grase\Clean::text($name), 'VoucherPrice' => @clean_number($voucherprice[$key]), 'VoucherGroup' => $vouchergroup[$key], 'MaxMb' => @clean_number($vouchermaxmb[$key]), 'MaxTime' => @clean_int($vouchermaxtime[$key]), 'Description' => @\Grase\Clean::text($voucherdesc[$key]), 'TopupVoucher' => $vouchertopup[$key] ? TRUE : FALSE, 'InitVoucher' => $voucherinit[$key] ? TRUE : FALSE));
 }
 if (sizeof($error) == 0) {
     // No errors. Save groups
     //$Settings->setSetting("groups", serialize($groupexpiries));
     foreach ($vouchersettings as $attributes) {
         //$Settings->setGroup($attributes);
         $Settings->setVoucher($attributes);
     }
     // Delete vouchers no longer referenced
     foreach ($Settings->getVoucher() as $oldvoucher => $oldvouchersettings) {
         if (!isset($vouchersettings[$oldvoucher])) {
             $Settings->deleteVoucher($oldvoucher);
         }
     }
     $success[] = T_("Vouchers updated");
 private function migrateGroups()
 {
     // Migrate groups to new system
     $groups = unserialize($this->Settings->getSetting('groups'));
     $groupattributes = $this->DBF->getGroupAttributes();
     foreach ($groups as $group => $expiry) {
         $attributes = array();
         $attributes['GroupName'] = \Grase\Clean::groupName($group);
         $attributes['GroupLabel'] = $group;
         $attributes['Expiry'] = @$expiry;
         $attributes['MaxOctets'] = @$groupattributes[$group]['MaxOctets'];
         $attributes['MaxSeconds'] = @$groupattributes[$group]['MaxSeconds'];
         // No comment stored, but oh well
         $attributes['Comment'] = @$groupattributes[$group]['Comment'];
         $this->rowsUpdated += $this->Settings->setGroup($attributes);
     }
     $this->Settings->setSetting('groups', serialize(''));
 }
function underscorespaces($text)
{
    //TODO this function is used in templates, so can't be moved yet
    return \Grase\Clean::groupName($text);
}
    $batches = explode(',', $_GET['batch']);
    $users = array();
    foreach ($batches as $batch) {
        $batch = clean_number($batch);
        $usersInBatch = $DBF->getMultipleUsersDetails($Settings->getBatch($batch));
        if (is_array($usersInBatch)) {
            $users = array_merge($users, $usersInBatch);
        }
    }
    // TODO: replace , with _ in below
    $title = sprintf(T_('Batch_%s_details'), implode('-', $batches));
} elseif (isset($_GET['group'])) {
    $groups = explode(',', $_GET['group']);
    $users = array();
    foreach ($groups as $group) {
        $group = \Grase\Clean::groupName($group);
        $usersInGroup = $DBF->getMultipleUsersDetails($DBF->getUsersByGroup($group));
        if (is_array($usersInGroup)) {
            $users = array_merge($users, $usersInGroup);
        }
    }
    $title = sprintf(T_('Group_%s_details'), implode('-', $groups));
} else {
    echo T_("Need a group or batch");
    // TODO Use error template
    exit;
}
if ($_GET['format'] == 'csv') {
    generate_csv($users, $title);
} elseif ($_GET['format'] == 'html') {
    printTickets($users, $title);
     if (!\Grase\Validate::bandwidthOptions($groupBandwidthDownLimit[$key], bandwidth_options())) {
         $error[] = sprintf(T_("Invalid Bandwidth Limit '%s'"), $groupBandwidthDownLimit[$key]);
     }
     if (!\Grase\Validate::bandwidthOptions($groupBandwidthUpLimit[$key], bandwidth_options())) {
         $error[] = sprintf(T_("Invalid Bandwidth Limit '%s'"), $groupBandwidthUpLimit[$key]);
     }
     //TODO we don't validate that it's not 0, relying on HTML5 to do that
     $error[] = @validate_int($groupSimultaneousUse[$key], true);
     // TODO: Validate Login-Time
     $error[] = @validate_uucptimerange($groupLoginTime[$key]);
     $error = array_filter($error);
     if (isset($groupRecurTime[$key]) xor isset($groupRecurTimeLimit[$key])) {
         $error[] = sprintf(T_("Need both a time limit and recurrance for '%s'"), \Grase\Clean::text($name));
     }
     $groups[\Grase\Clean::groupName($name)] = array_filter(array('DataRecurTime' => \Grase\Clean::text($groupRecurData[$key]), 'DataRecurLimit' => clean_number($groupRecurDataLimit[$key]), 'TimeRecurTime' => @\Grase\Clean::text($groupRecurTime[$key]), 'TimeRecurLimit' => @clean_int($groupRecurTimeLimit[$key]), 'BandwidthDownLimit' => @clean_int($groupBandwidthDownLimit[$key]), 'BandwidthUpLimit' => @clean_int($groupBandwidthUpLimit[$key]), 'SimultaneousUse' => @clean_int($groupSimultaneousUse[$key]), 'LoginTime' => @$groupLoginTime[$key], 'IdleTimeout' => @clean_int($groupIdleTimeout[$key])));
     $groupSettings[\Grase\Clean::groupName($name)] = array_filter(array('GroupName' => \Grase\Clean::groupName($name), 'Comment' => \Grase\Clean::text($groupComment[$key]), 'GroupLabel' => \Grase\Clean::text($name), 'Expiry' => @$groupExpiry[$key], 'ExpireAfter' => @$groupExpireAfter[$key], 'MaxMb' => @clean_number($groupDataLimit[$key]), 'MaxTime' => @clean_int($groupTimeLimit[$key])));
 }
 if (sizeof($error) == 0) {
     // No errors. Save groups
     foreach ($groupSettings as $attributes) {
         $Settings->setGroup($attributes);
     }
     // Delete groups no longer referenced
     foreach ($Settings->getGroup() as $oldgroup => $oldgroupsettings) {
         if (!isset($groupSettings[$oldgroup])) {
             $Settings->deleteGroup($oldgroup);
         }
     }
     // Delete groups from radgroupreply not in groupExpiries...
     // Deleting groups out of radgroupreply will modify current users
     // Need to do check for any users still using group, if no user then delete