<?php
// ft_react.php - Tepki ekleme / değiştirme / kaldırma (vB 3.8.x + vBSEO likes tabanlı)
//Geliştirme: atmaca
define('THIS_SCRIPT', 'ft_react');
// JSON bozulmasın diye mümkün olduğunca erken buffer başlat
if (!headers_sent()) {
@ob_start();
}
require_once('./global.php');
global $vbulletin;
/**
* BOM / uyarı çıktılarını JSON'u bozmadan temizlemek için.
*/
function ft_json_exit($payload)
{
// Eğer bir şeyler çıktıysa JSON'dan önce temizle
if (function_exists('ob_get_length') && ob_get_length()) {
@ob_clean();
}
header('Content-Type: application/json; charset=utf-8');
echo json_encode($payload);
exit;
}
/**
* Forum charset'inden UTF-8'e çevir.
* (TR genelde ISO-8859-9, EN ISO-8859-1 vb.)
*/
function ft_to_utf8($str)
{
if ($str === '' || $str === null) {
return '';
}
// Zaten geçerli UTF-8 ise hiç dokunma
if (preg_match('//u', $str)) {
return $str;
}
// Önce Türkçe paket (ISO-8859-9) olarak dene
$tmp = @iconv('ISO-8859-9', 'UTF-8//IGNORE', $str);
if ($tmp !== false) {
return $tmp;
}
// Olmazsa İngilizce paket (ISO-8859-1) olarak dene
$tmp = @iconv('ISO-8859-1', 'UTF-8//IGNORE', $str);
if ($tmp !== false) {
return $tmp;
}
return $str;
}
/**
* Tepki config'ini yükle.
* Beklenen: $ft_reactions = array( rid => array('file'=>..., 'alt'=>...), ... );
*/
function ft_load_reactions()
{
$reactions = array();
$config = dirname(__FILE__) . '/ft_reactions_config.php';
if (file_exists($config)) {
$ft_reactions = array();
include($config);
if (isset($ft_reactions) && is_array($ft_reactions)) {
foreach ($ft_reactions as $rid => $info) {
$rid = intval($rid);
if ($rid <= 0) { continue; }
if (!is_array($info)) { continue; }
if (empty($info['file'])) { continue; }
$reactions[$rid] = array(
'file' => (string)$info['file'],
'alt' => isset($info['alt']) ? (string)$info['alt'] : '',
);
}
}
}
// Fallback: config yoksa en azından boş dönme
if (!$reactions) {
$reactions = array(
1 => array('file'=>'like.png','alt'=>'Beğen'),
2 => array('file'=>'heart.png','alt'=>'Muhteşem'),
3 => array('file'=>'haha.png','alt'=>'Hahaha'),
4 => array('file'=>'wow.png','alt'=>'Şaşkın'),
5 => array('file'=>'sad.png','alt'=>'Üzgün'),
6 => array('file'=>'sad2.png','alt'=>'Üzüntülü'),
7 => array('file'=>'angry.png','alt'=>'Kızgın'),
8 => array('file'=>'care.png','alt'=>'Yanındayım'),
9 => array('file'=>'dislike.png','alt'=>'Beğenmedim'),
10 => array('file'=>'cool.png','alt'=>'Havalı'),
11 => array('file'=>'100.png','alt'=>'Kesinlikle'),
12 => array('file'=>'thinking.png','alt'=>'Düşünceli'),
13 => array('file'=>'brokenheart.png','alt'=>'Kalbi Kırılmış'),
14 => array('file'=>'cursing.png','alt'=>'Çok Tepkili'),
15 => array('file'=>'explodinghead.png','alt'=>'Beyni Yanmış'),
16 => array('file'=>'party.png','alt'=>'Parti'),
17 => array('file'=>'clap.png','alt'=>'Alkış'),
18 => array('file'=>'hearteyes.png','alt'=>'Kalpli Göz'),
19 => array('file'=>'smilingfacewithheart.png','alt'=>'Sevgi Dolu'),
20 => array('file'=>'coldface.png','alt'=>'Üşüyen Yüz'),
);
}
return $reactions;
}
/**
* vBulletin Security Token doğrulaması
*/
function ft_verify_token($request_token, $vbulletin)
{
$request_token = trim((string)$request_token);
if ($request_token === '') {
return false;
}
// vB3'te güvenli doğrulama için doğru karşılaştırma: securitytoken_raw
$raw = '';
if (!empty($vbulletin->userinfo['securitytoken_raw'])) {
$raw = $vbulletin->userinfo['securitytoken_raw'];
} else {
// Bazı kurulumlarda raw ayrı değil; güvenli tarafta kalmak için hash kısmını dene
$raw = (string)$vbulletin->userinfo['securitytoken'];
if (strpos($raw, '-') !== false) {
$parts = explode('-', $raw, 2);
$raw = isset($parts[1]) ? $parts[1] : $raw;
}
}
if (function_exists('verify_security_token') && $raw !== '') {
return (bool) verify_security_token($request_token, $raw);
}
// Fallback: sadece hash karşılaştır (TTL kontrolü yok)
if ($raw !== '' && strpos($request_token, '-') !== false) {
$parts = explode('-', $request_token, 2);
$hash = isset($parts[1]) ? $parts[1] : '';
return ($hash !== '' && hash_equals($raw, $hash));
}
return false;
}
// -------------------------
// 1) Giriş kontrolü
// -------------------------
$userid = intval($vbulletin->userinfo['userid']);
if (!$userid) {
ft_json_exit(array('success' => false, 'error' => 'not_logged_in'));
}
// -------------------------
// 2) Parametreleri al (eski+yeni uyumluluk)
// -------------------------
$vbulletin->input->clean_array_gpc('p', array(
'type' => TYPE_STR, // yeni
'ctype' => TYPE_STR, // eski (JS'in gönderdiği)
'postid' => TYPE_UINT, // yeni
'contentid' => TYPE_UINT, // eski (JS'in gönderdiği)
'reactionid' => TYPE_UINT,
'securitytoken' => TYPE_STR,
));
$type = $vbulletin->GPC['type'] ? $vbulletin->GPC['type'] : $vbulletin->GPC['ctype'];
$postid = intval($vbulletin->GPC['postid'] ? $vbulletin->GPC['postid'] : $vbulletin->GPC['contentid']);
$reactionid = intval($vbulletin->GPC['reactionid']);
$token = $vbulletin->GPC['securitytoken'];
if ($type !== 'post') {
ft_json_exit(array('success' => false, 'error' => 'invalid_type'));
}
if (!$postid || !$reactionid) {
ft_json_exit(array('success' => false, 'error' => 'invalid_params'));
}
// -------------------------
// 3) Token doğrula
// -------------------------
if (!ft_verify_token($token, $vbulletin)) {
ft_json_exit(array('success' => false, 'error' => 'bad_token'));
}
// -------------------------
// 4) Tepki ID geçerli mi? (config'ten)
// -------------------------
$reactions = ft_load_reactions();
if (!isset($reactions[$reactionid])) {
ft_json_exit(array('success' => false, 'error' => 'invalid_reaction'));
}
// -------------------------
// 5) Post var mı / sahibi kim?
// -------------------------
$post = $vbulletin->db->query_first("
SELECT userid
FROM " . TABLE_PREFIX . "post
WHERE postid = $postid
LIMIT 1
");
if (!$post) {
ft_json_exit(array('success' => false, 'error' => 'invalid_post'));
}
$dest_userid = intval($post['userid']);
if ($dest_userid && $dest_userid == $userid) {
ft_json_exit(array('success' => false, 'error' => 'own_post'));
}
$now = TIMENOW;
$username = $vbulletin->userinfo['username'];
// -------------------------
// 6) Kullanıcının mevcut tepkisi var mı?
// -------------------------
$existing = $vbulletin->db->query_first("
SELECT reactionid
FROM vbseo_likes
WHERE l_contentid = $postid
AND l_ctype = 1
AND l_cgroup = 0
AND l_from_userid = $userid
LIMIT 1
");
// Aynı tepkiye tekrar basarsa -> kaldır
if ($existing && intval($existing['reactionid']) === $reactionid) {
$vbulletin->db->query_write("
DELETE FROM vbseo_likes
WHERE l_contentid = $postid
AND l_ctype = 1
AND l_cgroup = 0
AND l_from_userid = $userid
LIMIT 1
");
ft_json_exit(array(
'success' => true,
'removed' => true,
'user_reactionid' => 0,
));
}
// Var ama farklıysa -> update
if ($existing) {
$vbulletin->db->query_write("
UPDATE vbseo_likes
SET reactionid = $reactionid,
l_dateline = $now
WHERE l_contentid = $postid
AND l_ctype = 1
AND l_cgroup = 0
AND l_from_userid = $userid
LIMIT 1
");
} else {
// Yeni
$vbulletin->db->query_write("
INSERT INTO vbseo_likes
(l_contentid, l_ctype, l_cgroup,
l_from_userid, l_from_username,
l_dest_userid, l_dateline, reactionid)
VALUES
($postid, 1, 0,
$userid, '" . $vbulletin->db->escape_string($username) . "',
$dest_userid, $now, $reactionid)
");
}
ft_json_exit(array(
'success' => true,
'removed' => false,
'user_reactionid' => $reactionid,
));Add a code snippet to your website: www.paste.org