<?php
// ft_react.php - Tepki ekleme / değiştirme / kaldırma (vB 3.8.x + vBSEO likes tabanlı)
//Geliştirme: atmaca
define(&#039;THIS_SCRIPT&#039;, &#039;ft_react&#039;);

// JSON bozulmasın diye mümkün olduğunca erken buffer başlat
if (!headers_sent()) {
    @ob_start();
}

require_once(&#039;./global.php&#039;);
global $vbulletin;

/**
 * BOM / uyarı çıktılarını JSON&#039;u bozmadan temizlemek için.
 */
function ft_json_exit($payload)
{
    // Eğer bir şeyler çıktıysa JSON&#039;dan önce temizle
    if (function_exists(&#039;ob_get_length&#039;) && ob_get_length()) {
        @ob_clean();
    }
    header(&#039;Content-Type: application/json; charset=utf-8&#039;);
    echo json_encode($payload);
    exit;
}

/**
 * Forum charset&#039;inden UTF-8&#039;e çevir.
 * (TR genelde ISO-8859-9, EN ISO-8859-1 vb.)
 */
function ft_to_utf8($str)
{
    if ($str === &#039;&#039; || $str === null) {
        return &#039;&#039;;
    }

    // Zaten geçerli UTF-8 ise hiç dokunma
    if (preg_match(&#039;//u&#039;, $str)) {
        return $str;
    }

    // Önce Türkçe paket (ISO-8859-9) olarak dene
    $tmp = @iconv(&#039;ISO-8859-9&#039;, &#039;UTF-8//IGNORE&#039;, $str);
    if ($tmp !== false) {
        return $tmp;
    }

    // Olmazsa İngilizce paket (ISO-8859-1) olarak dene
    $tmp = @iconv(&#039;ISO-8859-1&#039;, &#039;UTF-8//IGNORE&#039;, $str);
    if ($tmp !== false) {
        return $tmp;
    }

    return $str;
}

/**
 * Tepki config&#039;ini yükle.
 * Beklenen: $ft_reactions = array( rid => array(&#039;file&#039;=>..., &#039;alt&#039;=>...), ... );
 */
function ft_load_reactions()
{
    $reactions = array();
    $config = dirname(__FILE__) . &#039;/ft_reactions_config.php&#039;;

    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[&#039;file&#039;])) { continue; }
                $reactions[$rid] = array(
                    &#039;file&#039; => (string)$info[&#039;file&#039;],
                    &#039;alt&#039;  => isset($info[&#039;alt&#039;]) ? (string)$info[&#039;alt&#039;] : &#039;&#039;,
                );
            }
        }
    }

    // Fallback: config yoksa en azından boş dönme
    if (!$reactions) {
        $reactions = array(
            1  => array(&#039;file&#039;=>&#039;like.png&#039;,&#039;alt&#039;=>&#039;Beğen&#039;),
            2  => array(&#039;file&#039;=>&#039;heart.png&#039;,&#039;alt&#039;=>&#039;Muhteşem&#039;),
            3  => array(&#039;file&#039;=>&#039;haha.png&#039;,&#039;alt&#039;=>&#039;Hahaha&#039;),
            4  => array(&#039;file&#039;=>&#039;wow.png&#039;,&#039;alt&#039;=>&#039;Şaşkın&#039;),
            5  => array(&#039;file&#039;=>&#039;sad.png&#039;,&#039;alt&#039;=>&#039;Üzgün&#039;),
            6  => array(&#039;file&#039;=>&#039;sad2.png&#039;,&#039;alt&#039;=>&#039;Üzüntülü&#039;),
            7  => array(&#039;file&#039;=>&#039;angry.png&#039;,&#039;alt&#039;=>&#039;Kızgın&#039;),
            8  => array(&#039;file&#039;=>&#039;care.png&#039;,&#039;alt&#039;=>&#039;Yanındayım&#039;),
            9  => array(&#039;file&#039;=>&#039;dislike.png&#039;,&#039;alt&#039;=>&#039;Beğenmedim&#039;),
            10 => array(&#039;file&#039;=>&#039;cool.png&#039;,&#039;alt&#039;=>&#039;Havalı&#039;),
            11 => array(&#039;file&#039;=>&#039;100.png&#039;,&#039;alt&#039;=>&#039;Kesinlikle&#039;),
            12 => array(&#039;file&#039;=>&#039;thinking.png&#039;,&#039;alt&#039;=>&#039;Düşünceli&#039;),
            13 => array(&#039;file&#039;=>&#039;brokenheart.png&#039;,&#039;alt&#039;=>&#039;Kalbi Kırılmış&#039;),
            14 => array(&#039;file&#039;=>&#039;cursing.png&#039;,&#039;alt&#039;=>&#039;Çok Tepkili&#039;),
            15 => array(&#039;file&#039;=>&#039;explodinghead.png&#039;,&#039;alt&#039;=>&#039;Beyni Yanmış&#039;),
            16 => array(&#039;file&#039;=>&#039;party.png&#039;,&#039;alt&#039;=>&#039;Parti&#039;),
            17 => array(&#039;file&#039;=>&#039;clap.png&#039;,&#039;alt&#039;=>&#039;Alkış&#039;),
            18 => array(&#039;file&#039;=>&#039;hearteyes.png&#039;,&#039;alt&#039;=>&#039;Kalpli Göz&#039;),
            19 => array(&#039;file&#039;=>&#039;smilingfacewithheart.png&#039;,&#039;alt&#039;=>&#039;Sevgi Dolu&#039;),
            20 => array(&#039;file&#039;=>&#039;coldface.png&#039;,&#039;alt&#039;=>&#039;Üşüyen Yüz&#039;),
        );
    }

    return $reactions;
}

/**
 * vBulletin Security Token doğrulaması 
*/
function ft_verify_token($request_token, $vbulletin)
{
    $request_token = trim((string)$request_token);

    if ($request_token === &#039;&#039;) {
        return false;
    }

    // vB3&#039;te güvenli doğrulama için doğru karşılaştırma: securitytoken_raw
    $raw = &#039;&#039;;
    if (!empty($vbulletin->userinfo[&#039;securitytoken_raw&#039;])) {
        $raw = $vbulletin->userinfo[&#039;securitytoken_raw&#039;];
    } else {
        // Bazı kurulumlarda raw ayrı değil; güvenli tarafta kalmak için hash kısmını dene
        $raw = (string)$vbulletin->userinfo[&#039;securitytoken&#039;];
        if (strpos($raw, &#039;-&#039;) !== false) {
            $parts = explode(&#039;-&#039;, $raw, 2);
            $raw = isset($parts[1]) ? $parts[1] : $raw;
        }
    }

    if (function_exists(&#039;verify_security_token&#039;) && $raw !== &#039;&#039;) {
        return (bool) verify_security_token($request_token, $raw);
    }

    // Fallback: sadece hash karşılaştır (TTL kontrolü yok)
    if ($raw !== &#039;&#039; && strpos($request_token, &#039;-&#039;) !== false) {
        $parts = explode(&#039;-&#039;, $request_token, 2);
        $hash  = isset($parts[1]) ? $parts[1] : &#039;&#039;;
        return ($hash !== &#039;&#039; && hash_equals($raw, $hash));
    }

    return false;
}


// -------------------------
// 1) Giriş kontrolü
// -------------------------
$userid = intval($vbulletin->userinfo[&#039;userid&#039;]);
if (!$userid) {
    ft_json_exit(array(&#039;success&#039; => false, &#039;error&#039; => &#039;not_logged_in&#039;));
}

// -------------------------
// 2) Parametreleri al (eski+yeni uyumluluk)
// -------------------------
$vbulletin->input->clean_array_gpc(&#039;p&#039;, array(
    &#039;type&#039;          => TYPE_STR,   // yeni
    &#039;ctype&#039;         => TYPE_STR,   // eski (JS&#039;in gönderdiği)
    &#039;postid&#039;        => TYPE_UINT,  // yeni
    &#039;contentid&#039;     => TYPE_UINT,  // eski (JS&#039;in gönderdiği)
    &#039;reactionid&#039;    => TYPE_UINT,
    &#039;securitytoken&#039; => TYPE_STR,
));

$type       = $vbulletin->GPC[&#039;type&#039;] ? $vbulletin->GPC[&#039;type&#039;] : $vbulletin->GPC[&#039;ctype&#039;];
$postid     = intval($vbulletin->GPC[&#039;postid&#039;] ? $vbulletin->GPC[&#039;postid&#039;] : $vbulletin->GPC[&#039;contentid&#039;]);
$reactionid = intval($vbulletin->GPC[&#039;reactionid&#039;]);
$token      = $vbulletin->GPC[&#039;securitytoken&#039;];

if ($type !== &#039;post&#039;) {
    ft_json_exit(array(&#039;success&#039; => false, &#039;error&#039; => &#039;invalid_type&#039;));
}
if (!$postid || !$reactionid) {
    ft_json_exit(array(&#039;success&#039; => false, &#039;error&#039; => &#039;invalid_params&#039;));
}

// -------------------------
// 3) Token doğrula
// -------------------------
if (!ft_verify_token($token, $vbulletin)) {
    ft_json_exit(array(&#039;success&#039; => false, &#039;error&#039; => &#039;bad_token&#039;));
}

// -------------------------
// 4) Tepki ID geçerli mi? (config&#039;ten)
// -------------------------
$reactions = ft_load_reactions();
if (!isset($reactions[$reactionid])) {
    ft_json_exit(array(&#039;success&#039; => false, &#039;error&#039; => &#039;invalid_reaction&#039;));
}

// -------------------------
// 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(&#039;success&#039; => false, &#039;error&#039; => &#039;invalid_post&#039;));
}

$dest_userid = intval($post[&#039;userid&#039;]);
if ($dest_userid && $dest_userid == $userid) {
    ft_json_exit(array(&#039;success&#039; => false, &#039;error&#039; => &#039;own_post&#039;));
}

$now      = TIMENOW;
$username = $vbulletin->userinfo[&#039;username&#039;];

// -------------------------
// 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[&#039;reactionid&#039;]) === $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(
        &#039;success&#039;         => true,
        &#039;removed&#039;         => true,
        &#039;user_reactionid&#039; => 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, &#039;" . $vbulletin->db->escape_string($username) . "&#039;,
             $dest_userid, $now, $reactionid)
    ");
}

ft_json_exit(array(
    &#039;success&#039;         => true,
    &#039;removed&#039;         => false,
    &#039;user_reactionid&#039; => $reactionid,
));

Add a code snippet to your website: www.paste.org