У меня форум на forum.rcl-radio.ru, движок PunBB, база через PDO, PHP 7.4 — в общем, классика, которая вроде бы работает, но как только пытаешься что-то добавить сбоку, сразу начинаются танцы с бубном.
Идея была простая: пусть люди заходят не через форму логина, а кнопкой «Войти с Яндексом». Я думал, что самое сложное — это разобраться с OAuth у Яндекса. Оказалось, самое сложное — это не Яндекс, а сам PunBB.
PunBB не умеет «просто пускать» по токену. Ему нужна его родная кука — строка в определённом формате, которую он сам и проверяет. И если хоть один символ в этой строке не совпадёт, форум молча выдаст 500 или просто перекинет на страницу логина.
Главный камень преткновения: формула куки
Я долго не мог понять, почему кука (cookie), которую я ставлю, не работает. Казалось бы, бери ID, пароль, соль (salt), склеивай, кодируй — и всё. Но PunBB очень капризный.
Оказалось, что внутри PunBB есть функция forum_hash, и в ней — две строчки, которые всех сбивают с толку:
$return = ($hook = get_hook('fn_forum_hash_start')) ? eval($hook) : null; if ($return !== null) return $return;
Сначала я пытался их вставить в свой код. И тут же получал ошибку 500, потому что в моём скрипте нет ни get_hook, ни системы плагинов PunBB.
Как я потом понял: эти строки — это просто «дверь» для плагинов. Они говорят: «Если какой-то плагин хочет поменять формулу хеша — пусть считает сам. Если нет — считаем по стандарту». А стандарт такой:
SHA‑1(соль + SHA‑1(время))
И финальный хеш для куки:
SHA‑1(соль + пароль_SHA1 + временной_хеш)
То есть в своём скрипте я не копирую эти две строки с хуками. Я сразу беру ту ветку, которая срабатывает, если плагинов нет. Это и есть правильный путь.
Как это выглядит в реальном коде
Вот тот самый кусок, который у меня в итоге заработал. Он маленький, без лишнего, и его можно вставлять частями:
// Ищем пользователя по email, который прислал Яндекс $stmt = $pdo->prepare("SELECT id, salt, password FROM {$db_prefix}users WHERE email = ? LIMIT 1"); $stmt->execute([$yandex_email]); $row = $stmt->fetch(PDO::FETCH_ASSOC); if (!$row) { // Если пользователя нет — можно создать нового или просто отказать return false; } $user_id = (int)$row['id']; $salt = $row['salt']; $password_field = $row['password']; // В базе уже лежит SHA‑1, не трогаем // Время жизни куки — 14 дней $now = time(); $expire = $now + 1209600; // Считаем хеши ровно так, как PunBB делает по умолчанию $inner = sha1((string)$expire); $time_hash = sha1($salt . $inner); $final_hash = sha1($salt . $password_field . $time_hash); // Собираем строку и кодируем в Base64 $raw = $user_id . '|' . $password_field . '|' . $expire . '|' . $final_hash; $encoded = base64_encode($raw); // Ставим куку с правильными флагами setcookie( 'punbb_cookie', $encoded, $expire, '/', '.forum.rcl-radio.ru', true, // secure — только по HTTPS true // httponly — недоступна из JS ); header('Location: https://forum.rcl-radio.ru/'); exit;
Где я ошибался чаще всего
Если ты сейчас делаешь то же самое, проверь эти моменты — именно на них я терял больше всего времени:
- Пытался вставить хуки. В отдельном скрипте они не работают и ломают всё.
- Перехешировал пароль. В базе PunBB уже лежит SHA‑1. Если сверху сделать ещё один
sha1илиpassword_hash, хеш станет другим, и кука не подойдёт. - Не приводил
$expireк строке. PunBB явно делает(string)$expire. Если этого не сделать, хеш не совпадёт. - Порядок склейки. PunBB чувствителен к порядку:
соль + пароль + временной_хеш. Поменяешь местами — кука невалидна. - Домен куки. PunBB ожидает домен с точкой:
.forum.rcl-radio.ru. Без точки кука может не подхватиться.
Как быстро проверить, что всё считается правильно
Самый надёжный способ — взять одну рабочую куку прямо с форума (ту, с которой вход реально работает) и проверить формулу вручную.
- Декодируй куку:
$parts = explode('|', base64_decode($cookie_value)); - Возьми соль этого пользователя из базы.
- Посчитай:
php
$inner = sha1((string)$parts[2]); $time_hash = sha1($salt . $inner); $my_final = sha1($salt . $parts[1] . $time_hash);
- Сравни
$my_finalс$parts[3]. Если совпало — формула правильная.
Сейчас у меня эта схема работает стабильно: человек нажимает «Войти с Яндексом», скрипт считает куку по этой формуле, ставит её и перекидывает на форум. PunBB видит «родную» куку и сразу пускает пользователя.
Что на самом деле лежит внутри «куки» PunBB
PunBB не хранит в куке ничего лишнего. Внутри одной строки (после Base64) ровно четыре части, разделённые вертикальной чертой |:
ID_пользователя | пароль_SHA1 | время_истечения | финальный_хеш
Пример (условно):
5010|4b8123402efb5de823829985b346b106888caa42|1783920581|b717ca2b42abf8686fbdc3919fb2918b7ba270be
- ID — просто число, кто это.
- Пароль_SHA1 — в базе PunBB он уже захеширован как SHA‑1. Его не надо трогать, не надо делать ещё один
sha1()илиpassword_hash(). - Время — Unix‑время, когда кука должна «умереть». PunBB ставит 14 дней вперёд.
- Финальный хеш — вот это и есть самая хитрая часть: именно она доказывает PunBB, что строку собрал «свой», а не кто попало.
Формула финального хеша — по шагам
PunBB считает финальный хеш так (это дефолтная ветка, когда нет плагинов):
- Берём время (expire) и делаем из него внутренний хеш:
php
$inner = sha1((string)$expire);
Важно: приводим к строке
(string). Если этого не сделать, в PHP может быть разное поведение, и хеш «уедет». - Считаем «временной хеш» с солью:
php
$time_hash = sha1($salt . $inner);
Это аналог той самой функции
forum_hash($expire, $salt). - Считаем финальный хеш куки:
php
$final_hash = sha1($salt . $password_field . $time_hash);
Обрати внимание на порядок: соль + пароль + временной_хеш. PunBB очень строгий: поменяешь местами — хеш будет другой, и форум отвергнет куку.
Где тут прячется та самая «соль»
Соль (salt) — это уникальная строка из базы для конкретного пользователя. В PunBB она хранится в поле salt таблицы users.
Её роль простая, но критичная: даже если у двух пользователей одинаковый пароль, их хеши будут разными, потому что соль разная. А для PunBB это ещё и часть формулы: без правильной соли финальный хеш не совпадёт, и авторизация не пройдёт.
Регистрация приложения в Яндексе

Заходишь в консоль разработчика Яндекса, создаёшь приложение типа «Веб‑сервис». Тебе дадут:
client_id— это просто строка, её можно хранить в конфиге.client_secret— это секрет, его держишь только на сервере, в PHP.
Там же указываешь Redirect URI — адрес, куда Яндекс вернёт пользователя после входа. Для PunBB это отдельный PHP‑файл, например: https://forum.rcl-radio.ru/login_yandex_callback.php. Он должен совпадать буква в букву (протокол, домен, путь, слэш в конце — всё важно).
И выбираешь scope — какие данные просишь:
login:email— чтобы получить email (для связки с пользователем PunBB).login:info— имя и фамилию.login:avatar— аватар.
Для форума чаще всего хватает login:email login:info.
Кнопка «Войти через Яндекс»
В меню PunBB ставишь обычную ссылку, которая перенаправляет пользователя на страницу авторизации Яндекса ID.
login_yandex.php:
<?php // login_yandex.php — ТОЛЬКО РЕДИРЕКТ В ЯНДЕКС // ВСТАВЬ СЮДА НОВЫЙ client_id ИЗ КАБИНЕТА ЯНДЕКСА $client_id = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx'; $redirect_uri = 'https://forum.rcl-radio.ru/login_yandex_callback.php'; $scope = 'login:info'; $auth_url = 'https://oauth.yandex.ru/authorize?' . http_build_query([ 'client_id' => $client_id, 'response_type' => 'code', 'redirect_uri' => $redirect_uri, 'scope' => $scope ]); header('Location: ' . $auth_url); exit; ?>
$client_id — это одноразовый код, который Яндекс отдаёт только один раз и только на твой Redirect URI.
Получение Яндекс токена
Когда пользователь нажал «Войти (Яндекс ID)» Яндекс делает редирект на твой login_yandex_callback.php с параметром client_id. В этом файле ты делаешь POST‑запрос к Яндексу, чтобы обменять код на токен.
// --- OAUTH TOKEN --- $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => 'https://oauth.yandex.ru/token', CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query([ 'grant_type' => 'authorization_code', 'code' => $code, 'client_id' => $client_id, 'client_secret' => $client_secret, 'redirect_uri' => $redirect_uri ]), CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => true ]); $token_resp = curl_exec($ch); $curl_err = curl_error($ch); curl_close($ch); if ($curl_err) { log_msg('CURL token error: ' . $curl_err); header('Location: /index.php?p=login&error=oauth_token'); exit; } $token_data = json_decode($token_resp, true); if (!$token_data || isset($token_data['error'])) { log_msg('Token error data: ' . json_encode($token_data)); header('Location: /index.php?p=login&error=token_invalid'); exit; } $access_token = $token_data['access_token'];
Получаем данные пользователя
С этим access_token делаешь GET‑запрос к API Яндекс ID:
// --- USER INFO --- $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => 'https://login.yandex.ru/info?format=json', CURLOPT_HTTPHEADER => ["Authorization: OAuth {$access_token}"], CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => true ]); $user_info = curl_exec($ch); $curl_err2 = curl_error($ch); curl_close($ch); if ($curl_err2) { log_msg('CURL profile error: ' . $curl_err2); header('Location: /index.php?p=login&error=profile_fetch'); exit; } $data = json_decode($user_info, true); if (!$data || !isset($data['id'])) { log_msg('Failed to get profile: ' . $user_info); header('Location: /index.php?p=login&error=profile_invalid'); exit; } log_msg('Profile received for Yandex ID: ' . $data['id']); $yandex_id = $data['id']; $email = $data['default_email'] ?? ''; $login_raw = $data['login'] ?? 'yandex_' . $yandex_id; $login = preg_replace('/[^a-zA-Z0-9_]/', '_', $login_raw); if (strlen($login) > 200) $login = substr($login, 0, 200);
Этот код запрашивает у Яндекса данные профиля пользователя по access_token и подготавливает их для поиска/создания аккаунта в PunBB.
Поиск существующего или создание нового пользователя в PunBB по данным Яндекса
Вот код:
// --- FIND OR CREATE USER --- $stmt = $pdo->prepare("SELECT id, username, group_id, salt, password, language FROM {$db_prefix}users WHERE username = ?"); $stmt->execute([$login]); $row = $stmt->fetch(); if ($row) { $user_id = (int)$row['id']; $group_id = (int)$row['group_id']; log_msg("Existing user found: ID={$user_id}, group={$group_id}"); } else { // 1. Соль ровно 12 hex-символов $salt = bin2hex(random_bytes(6)); // 12 символов // 2. Генерируем случайный "пароль" (не показываем пользователю, нужен только для хеша PunBB) $plain_password = bin2hex(random_bytes(8)); // случайная строка // 3. Хеш по формуле PunBB: sha1(salt + plain_password) $password_hash = sha1($salt . $plain_password); // валидный хеш $stmt = $pdo->prepare("INSERT INTO {$db_prefix}users (username, group_id, email, salt, password, language) VALUES (?, 3, ?, ?, ?, ?)"); try { $stmt->execute([$login, $email, $salt, $password_hash, 'Russian']); $user_id = (int)$pdo->lastInsertId(); $group_id = 3; log_msg("New user created: ID={$user_id}, username={$login}"); } catch (PDOException $e) { log_msg('DB insert error: ' . $e->getMessage()); header('Location: /index.php?p=login&error=user_create'); exit; } }
Коротко, что делает код:
- Подключается к БД через PDO с обработкой ошибок: если база недоступна — пишет в лог и редиректит на страницу входа с ошибкой.
- Ищет пользователя в PunBB по имени (
username), полученному от Яндекса. - Если пользователь найден: берёт его
idиgroup_id, пишет в лог. Дальше можно сразу логинить. - Если не найден: создаёт нового пользователя:
- генерирует соль (12 hex‑символов) и случайный пароль;
- считает хеш по формуле PunBB:
sha1(salt . plain_password); - вставляет запись в таблицу
users(группа 3, язык Russian); - запоминает
user_idнового юзера.
- При ошибке вставки пишет в лог и редиректит с ошибкой.
Формирование и установка куки авторизации PunBB для пользователя из Яндекса
// ДЕЛАЕМ КУКИ
// Проверка: пользователь должен существовать
$stmt = $pdo->prepare("SELECT salt, password FROM {$db_prefix}users WHERE id = ? LIMIT 1");
$stmt->execute([$user_id]);
$userData = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$userData || empty($userData['salt'])) {
log_msg('CRITICAL: user not found or missing salt for ID=' . $user_id);
// Тут твоя логика ошибки (редирект на страницу ошибки или выход)
exit;
}
$salt = trim($userData['salt']); // trim обязателен: PunBB чувствителен к пробелам
$form_password_hash = $userData['password']; // хеш из базы
// Expire считаем ОДИН раз
$expire = time() + 1209600; // 14 дней
// Считаем timeHash по ТВОЕЙ формуле forum_hash ---
$inner_hash = sha1((string)$expire);
$time_hash = sha1($salt . $inner_hash);
$final_hash = sha1($salt . $form_password_hash . $time_hash);
// Собираем и кодируем
$raw_cookie = $user_id . '|' . $form_password_hash . '|' . $expire . '|' . $final_hash;
$encoded_cookie = base64_encode($raw_cookie);
// Ставим куку
$cookie_name = 'forum_cookie_ххххх';// смотри что у тебя в config.php и ставь свое $domain = '.forum.rcl-radio.ru'; // Ставим новую куку setcookie($cookie_name, $encoded_cookie, $expire, '/', $domain, false, true); header('Location: https://forum.rcl-radio.ru/index.php'); exit;
Коротко, что делает код:
- Проверяет, что пользователь существует и у него есть соль. Делает SELECT по
$user_id, если соли нет или юзер не найден — пишет критическую ошибку в лог и останавливает скрипт. - Берёт соль и хеш пароля из БД. Соль обязательно чистит через
trim()— PunBB ломается, если в соли есть лишние пробелы. - Считает время жизни куки:
$expire = time() + 1209600(14 дней). - Считает хеши строго по формуле PunBB:
$inner_hash = sha1((string)$expire)$time_hash = sha1($salt . $inner_hash)$final_hash = sha1($salt . $form_password_hash . $time_hash)
- Собирает строку куки:
id|password_hash|expire|final_hashи кодирует её в base64. - Ставит куку браузера: имя
forum_cookie_ххххх, путь/, домен.forum.rcl-radio.ru, флагиhttponly(true) и безsecure(false). - Редиректит пользователя на главную форума.
Что делает файл (кнопка Выйти) logout.php
Это полностью автономный скрипт выхода — он не требует подключения ядра PunBB (common.php и т.п.) и не выводит никакого HTML/текста в браузер. Его единственная задача — сбросить куки авторизации (и PunBB, и твой маркер Яндекса), записать отладочные данные в лог и перенаправить пользователя на главную.
<?php
// logout.php — ПОЛНОСТЬЮ АВТОНОМНЫЙ, без require, без echo
$cookie_name = 'forum_cookie_ххххх'; $ya_marker = 'ya_marker'; $path = '/'; // <-- поставь сюда реальный путь из колонки Path в браузере // Лог только в файл, НИКАКОГО echo! $log_file = '/var/www/forum.rcl-radio.ru/logout_debug.log'; file_put_contents($log_file, date('Y-m-d H:i:s') . ' - Start logout attempt' . PHP_EOL, FILE_APPEND | LOCK_EX); setcookie($cookie_name, '', time() - 3600, $path, '.forum.rcl-radio.ru', false, true); setcookie($cookie_name, '', time() - 3600, $path, 'forum.rcl-radio.ru', false, true); setcookie($cookie_name, '', time() - 3600, $path, '', false, true); file_put_contents($log_file, date('Y-m-d H:i:s') . ' - PunBB cookie set (attempt)' . PHP_EOL, FILE_APPEND | LOCK_EX); setcookie($ya_marker, '', time() - 3600, $path, '.forum.rcl-radio.ru', false, true); setcookie($ya_marker, '', time() - 3600, $path, 'forum.rcl-radio.ru', false, true); setcookie($ya_marker, '', time() - 3600, $path, '', false, true); file_put_contents($log_file, date('Y-m-d H:i:s') . ' - Ya marker set (attempt)' . PHP_EOL, FILE_APPEND | LOCK_EX); file_put_contents($log_file, date('Y-m-d H:i:s') . ' - Redirecting...' . PHP_EOL, FILE_APPEND | LOCK_EX); header('Location: https://forum.rcl-radio.ru/index.php'); file_put_contents($log_file, date('Y-m-d H:i:s') . ' - Header sent' . PHP_EOL, FILE_APPEND | LOCK_EX); exit;
Коротко, что делает код:
- Задаёт имена кук и путь:
forum_cookie_ххххх— кука PunBB, по которой движок понимает, кто залогинен.ya_marker— твоя собственная кука, чтобы помечать вход через Яндекс (для кнопки «Выйти», UI и т.д.).$path = '/'— путь, на котором действуют куки (должен совпадать с тем, как ты их ставил).
- Пишет в лог начало операции через
file_put_contentsс флагомLOCK_EX(чтобы не было конфликтов, если два пользователя выйдут одновременно). Никакихecho— иначеheaderне сработает и будет ошибка 500.

login_yandex_callback.php целиком:
<?php
// === ЛОГГЕР (самый первый, до всего остального) ===
$log_file = '/var/www/forum.rcl-radio.ru/login_yandex_callback_error.log';
function log_msg($msg) {
global $log_file;
file_put_contents($log_file, date('Y-m-d H:i:s') . ' - ' . $msg . PHP_EOL, FILE_APPEND | LOCK_EX);
}
// ================================================
// === НАСТРОЙКИ ===
$client_id = 'd4c002ххххххххххххххххххх103f0cf';
$client_secret = '47223cххххххххххххххххх802fc2331';
$redirect_uri = 'https://forum.rcl-radio.ru/login_yandex_callback.php';
$db_host = 'localhost';
$db_name = 'ххххххххх';
$db_user = 'ххххххххх';
$db_pass = 'хххххххххх';
$db_prefix = 'pp_';
// =============
if (!isset($_GET['code'])) {
log_msg('No code param');
header('Location: /index.php?p=login');
exit;
}
$code = $_GET['code'];
log_msg('Code received: ' . substr($code, 0, 10) . '...');
// --- OAUTH TOKEN ---
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://oauth.yandex.ru/token',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'grant_type' => 'authorization_code',
'code' => $code,
'client_id' => $client_id,
'client_secret' => $client_secret,
'redirect_uri' => $redirect_uri
]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => true
]);
$token_resp = curl_exec($ch);
$curl_err = curl_error($ch);
curl_close($ch);
if ($curl_err) {
log_msg('CURL token error: ' . $curl_err);
header('Location: /index.php?p=login&error=oauth_token');
exit;
}
$token_data = json_decode($token_resp, true);
if (!$token_data || isset($token_data['error'])) {
log_msg('Token error data: ' . json_encode($token_data));
header('Location: /index.php?p=login&error=token_invalid');
exit;
}
$access_token = $token_data['access_token'];
log_msg('Access token received');
// --- USER INFO ---
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://login.yandex.ru/info?format=json',
CURLOPT_HTTPHEADER => ["Authorization: OAuth {$access_token}"],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => true
]);
$user_info = curl_exec($ch);
$curl_err2 = curl_error($ch);
curl_close($ch);
if ($curl_err2) {
log_msg('CURL profile error: ' . $curl_err2);
header('Location: /index.php?p=login&error=profile_fetch');
exit;
}
$data = json_decode($user_info, true);
if (!$data || !isset($data['id'])) {
log_msg('Failed to get profile: ' . $user_info);
header('Location: /index.php?p=login&error=profile_invalid');
exit;
}
log_msg('Profile received for Yandex ID: ' . $data['id']);
$yandex_id = $data['id'];
$email = $data['default_email'] ?? '';
$login_raw = $data['login'] ?? 'yandex_' . $yandex_id;
$login = preg_replace('/[^a-zA-Z0-9_]/', '_', $login_raw);
if (strlen($login) > 200) $login = substr($login, 0, 200);
// --- DB CONNECTION ---
try {
$dsn = "mysql:host=$db_host;dbname=$db_name;charset=utf8mb4";
$pdo = new PDO($dsn, $db_user, $db_pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);
} catch (PDOException $e) {
log_msg('DB connection error: ' . $e->getMessage());
header('Location: /index.php?p=login&error=db_connection');
exit;
}
// --- FIND OR CREATE USER ---
$stmt = $pdo->prepare("SELECT id, username, group_id, salt, password, language FROM {$db_prefix}users WHERE username = ?");
$stmt->execute([$login]);
$row = $stmt->fetch();
if ($row) {
$user_id = (int)$row['id'];
$group_id = (int)$row['group_id'];
log_msg("Existing user found: ID={$user_id}, group={$group_id}");
} else {
// 1. Соль ровно 12 hex-символов
$salt = bin2hex(random_bytes(6)); // 12 символов
// 2. Генерируем случайный "пароль" (не показываем пользователю, нужен только для хеша PunBB)
$plain_password = bin2hex(random_bytes(8)); // случайная строка
// 3. Хеш по формуле PunBB: sha1(salt + plain_password)
$password_hash = sha1($salt . $plain_password); // валидный хеш
$stmt = $pdo->prepare("INSERT INTO {$db_prefix}users (username, group_id, email, salt, password, language) VALUES (?, 3, ?, ?, ?, ?)");
try {
$stmt->execute([$login, $email, $salt, $password_hash, 'Russian']);
$user_id = (int)$pdo->lastInsertId();
$group_id = 3;
log_msg("New user created: ID={$user_id}, username={$login}");
} catch (PDOException $e) {
log_msg('DB insert error: ' . $e->getMessage());
header('Location: /index.php?p=login&error=user_create');
exit;
}
}
// ДЕЛАЕМ КУКИ
// Проверка: пользователь должен существовать
$stmt = $pdo->prepare("SELECT salt, password FROM {$db_prefix}users WHERE id = ? LIMIT 1");
$stmt->execute([$user_id]);
$userData = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$userData || empty($userData['salt'])) {
log_msg('CRITICAL: user not found or missing salt for ID=' . $user_id);
// Тут твоя логика ошибки (редирект на страницу ошибки или выход)
exit;
}
$salt = trim($userData['salt']); // trim обязателен: PunBB чувствителен к пробелам
$form_password_hash = $userData['password']; // хеш из базы
// Expire считаем ОДИН раз
$expire = time() + 1209600; // 14 дней
// Считаем timeHash по ТВОЕЙ формуле forum_hash ---
$inner_hash = sha1((string)$expire);
$time_hash = sha1($salt . $inner_hash);
$final_hash = sha1($salt . $form_password_hash . $time_hash);
// Собираем и кодируем
$raw_cookie = $user_id . '|' . $form_password_hash . '|' . $expire . '|' . $final_hash;
$encoded_cookie = base64_encode($raw_cookie);
// Ставим куку
$cookie_name = 'forum_cookie_ххххх'; $domain = '.forum.rcl-radio.ru'; // Ставим новую куку setcookie($cookie_name, $encoded_cookie, $expire, '/', $domain, false, true); $_SESSION['yandex_user'] = 1; header('Location: https://forum.rcl-radio.ru/index.php'); exit;
