header('Content-Disposition: attachment; filename="recovery_codes.txt"');
    header('Content-Transfer-Encoding: binary');
    header(sprintf('Content-Length: %d', strlen($response)));
    echo $response;
    die;
}
function getRecoveryCodes($userId)
{
    $codes = RecoveryCodesTable::getList(array('select' => array('CODE'), 'filter' => array('=USER_ID' => $userId, '=USED' => 'N')));
    $normalizedCodes = array();
    while ($code = $codes->fetch()) {
        $normalizedCodes[] = $code['CODE'];
    }
    return $normalizedCodes;
}
$codes = getRecoveryCodes($userId);
$issuer = $userOtp->getIssuer();
$label = $userOtp->getLabel();
$createdDate = CUserOptions::GetOption('security', 'recovery_codes_generated', null);
if ($createdDate) {
    $createdDate = FormatDate('FULL', $createdDate);
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
	<title><?php 
echo getMessage('SEC_OTP_RECOVERY_TITLE');
?>
</title>
	<meta http-equiv="Content-Type" content="text/html; charset=<?php 
function regenerateRecoveryCodes($userId)
{
    if (!Otp::getByUser($userId)->isActivated()) {
        ShowError('OTP inactive');
    }
    CUserOptions::SetOption('security', 'recovery_codes_generated', time());
    RecoveryCodesTable::regenerateCodes($userId);
    return getRecoveryCodes($userId, false);
}