Psst.. new poll here.
Psst.. new forums here.
Microsoft is blocking us again (TY IP Reputation!) so dont bother with any of their useless mail servers here and just use oauth login instead. Thank the nice Russians for causing that. :)
Paste
Pasted as PHP by registered user atmaca ( 3 months ago )
<?php
define('THIS_SCRIPT', 'ft_story_upload');
require_once('./global.php');
/*
FT Story Upload
- Dosya Upload:
* JPG / PNG / GIF (max 5 MB)
* MP4 (max 15 MB)
- YouTube Bağlantısı
* Sadece youtube.com / youtu.be / youtube-nocookie.com domainleri
* DB: mediatype = 4, filepath = "yt:VIDEOID"
- Görünürlük:
1 = Forum Üyeleri
3 = Sadece Arkadaşlar
Geliştirici: atmaca
*/
// ------------------------- Helpers -------------------------
function ft_utf8ize($mixed, $fromCharset)
{
if (is_array($mixed))
{
foreach ($mixed as $k => $v)
{
$mixed[$k] = ft_utf8ize($v, $fromCharset);
}
return $mixed;
}
if (is_string($mixed))
{
if (!strcasecmp($fromCharset, 'utf-8'))
{
return $mixed;
}
if (function_exists('mb_convert_encoding'))
{
return @mb_convert_encoding($mixed, 'UTF-8', $fromCharset);
}
return utf8_encode($mixed);
}
return $mixed;
}
function ft_json_exit($arr)
{
global $stylevar;
$fromCharset = 'UTF-8';
if (!empty($stylevar['charset']))
{
$fromCharset = $stylevar['charset'];
}
$json = json_encode($arr, JSON_UNESCAPED_UNICODE);
if ($json === false)
{
$arr = ft_utf8ize($arr, $fromCharset);
$json = json_encode($arr, JSON_UNESCAPED_UNICODE);
}
if (function_exists('ob_get_length') && ob_get_length())
{
@ob_clean();
}
header('Content-Type: application/json; charset=UTF-8');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
if ($json === false)
{
echo json_encode(array(
'ok' => 0,
'error' => 'JSON üretilemedi.',
'code' => json_last_error(),
));
exit;
}
echo $json;
exit;
}
function ft_upload_error_message($code)
{
$map = array(
1 => 'Dosya çok büyük (php.ini upload_max_filesize).',
2 => 'Dosya çok büyük (form MAX_FILE_SIZE).',
3 => 'Dosya kısmen yüklendi.',
4 => 'Dosya seçilmedi.',
6 => 'Geçici klasör (tmp) bulunamadı.',
7 => 'Dosya diske yazılamadı.',
8 => 'Bir PHP eklentisi yüklemeyi durdurdu.',
);
return isset($map[$code]) ? $map[$code] : ('Yükleme hatası (kod: ' . intval($code) . ').');
}
function ft_fail($code, $ajax)
{
$msg = $code;
if (is_string($code))
{
if (strpos($code, 'upload_hata_') === 0)
{
$err = intval(substr($code, strlen('upload_hata_')));
$msg = ft_upload_error_message($err);
}
else
{
$map = array(
'bad_token' => 'Oturum doğrulaması başarısız. Sayfayı yenileyip tekrar deneyin.',
'dosya_gelmedi' => 'Dosya seçilmedi.',
'dosya_5mb_ustu' => 'Görsel boyutu 5 MB sınırını aşıyor.',
'video_15mb_ustu' => 'Video boyutu 15 MB sınırını aşıyor.',
'gecersiz_resim' => 'Geçersiz resim dosyası.',
'yalnizca_jpg_png_gif' => 'Sadece JPG / PNG / GIF kabul ediliyor.',
'yalnizca_mp4' => 'Sadece MP4 video kabul ediliyor.',
'yalnizca_youtube_link' => 'Sadece YouTube bağlantıları kabul ediliyor.',
'upload_klasoru_yazilamaz' => 'Sunucuda yükleme klasörü yazılabilir değil.',
'dosya_tasinamadi' => 'Dosya sunucuya kaydedilemedi.',
'not_logged_in' => 'Bu işlem için oturum açmalısınız.',
);
if (isset($map[$code]))
{
$msg = $map[$code];
}
}
}
if ($ajax)
{
ft_json_exit(array(
'ok' => 0,
'error' => $msg,
'code' => $code,
));
}
die($msg);
}
/* Visibility normalize helper */
function ft_normalize_visibility($value)
{
$value = intval($value);
// Sadece 1 = kayıtlı üyeler, 3 = arkadaşlar
if ($value === 3)
{
return 3;
}
return 1;
}
/* Strong random token */
function ft_token_hex($bytes = 16)
{
$bytes = max(8, intval($bytes));
if (function_exists('random_bytes'))
{
try {
return bin2hex(random_bytes($bytes));
} catch (Exception $e) {}
}
if (function_exists('openssl_random_pseudo_bytes'))
{
$b = openssl_random_pseudo_bytes($bytes);
if ($b !== false)
{
return bin2hex($b);
}
}
// Son çare
return substr(md5(uniqid('', true)), 0, $bytes * 2);
}
/* Quick MP4 signature check for octet-stream cases */
function ft_looks_like_mp4($path)
{
$fh = @fopen($path, 'rb');
if (!$fh) return false;
$head = @fread($fh, 128);
@fclose($fh);
// MP4 container’da genellikle "ftyp" bulunur
return ($head !== false && strpos($head, 'ftyp') !== false);
}
/* Parse YouTube URL -> 11-char video id (only allowed domains) */
function ft_parse_youtube_id($url)
{
$url = trim((string)$url);
if ($url === '') return false;
$p = @parse_url($url);
if (!$p || empty($p['host'])) return false;
$host = strtolower($p['host']);
$host = preg_replace('/^www\./', '', $host);
$allowed = array('youtube.com', 'm.youtube.com', 'youtu.be', 'youtube-nocookie.com');
if (!in_array($host, $allowed, true)) return false;
$path = isset($p['path']) ? trim($p['path'], '/') : '';
$id = '';
if ($host === 'youtu.be')
{
// youtu.be/VIDEOID
$parts = explode('/', $path);
$id = isset($parts[0]) ? $parts[0] : '';
}
else
{
// youtube.com/watch?v=VIDEOID
if (!empty($p['query']))
{
parse_str($p['query'], $q);
if (!empty($q['v'])) $id = (string)$q['v'];
}
// youtube.com/shorts/VIDEOID veya /embed/VIDEOID
if (!$id && preg_match('~^(shorts|embed)/([A-Za-z0-9_-]{11})~', $path, $m))
{
$id = $m[2];
}
}
if (!preg_match('~^[A-Za-z0-9_-]{11}$~', $id)) return false;
return $id;
}
// ------------------------- Input -------------------------
$vbulletin->input->clean_array_gpc('p', array(
'do' => TYPE_STR, // upload | youtube
'securitytoken' => TYPE_STR,
'ajax' => TYPE_UINT,
'visibility' => TYPE_UINT,
'youtube_url' => TYPE_STR, // do=youtube için
'text_body' => TYPE_STR, // Metin hikaye için
'bg_id' => TYPE_UINT, // Metin hikaye için
'confirm_censor' => TYPE_UINT,
));
$do = $vbulletin->GPC['do'];
$ajax = ($vbulletin->GPC['ajax'] ? true : false);
if (!$vbulletin->userinfo['userid'])
{
if ($ajax)
{
ft_fail('not_logged_in', true);
}
print_no_permission();
}
$db =& $vbulletin->db;
// Ayarlar (MVP)
$MAX_IMG_BYTES = 5 * 1024 * 1024; // 5 MB
$MAX_VID_BYTES = 15 * 1024 * 1024; // 15 MB
$EXPIRE_SECS = 24 * 60 * 60; // 24 saat
$UPLOAD_DIR = DIR . '/ft_story_uploads';
$UPLOAD_URL = 'ft_story_uploads';
// ------------------------- Token verify -------------------------
function ft_verify_token_or_fail($ajax)
{
global $vbulletin;
$token = $vbulletin->GPC['securitytoken'];
$raw = (!empty($vbulletin->userinfo['securitytoken_raw']) ? $vbulletin->userinfo['securitytoken_raw'] : '');
if (!$token || $token === 'guest')
{
ft_fail('bad_token', $ajax);
}
if (!verify_security_token($token, $raw))
{
ft_fail('bad_token', $ajax);
}
}
// ------------------------- Main actions -------------------------
if ($_SERVER['REQUEST_METHOD'] === 'POST')
{
// dosya upload
if ($do === 'upload')
{
ft_verify_token_or_fail($ajax);
if (empty($_FILES['storyfile']) || !is_uploaded_file($_FILES['storyfile']['tmp_name']))
{
ft_fail('dosya_gelmedi', $ajax);
}
$f = $_FILES['storyfile'];
if (!empty($f['error']))
{
ft_fail('upload_hata_' . intval($f['error']), $ajax);
}
$tmp = $f['tmp_name'];
// ext + type detect
$ext = strtolower(pathinfo((string)$f['name'], PATHINFO_EXTENSION));
$is_video = ($ext === 'mp4');
$mediatype = 1;
$width = 0;
$height = 0;
if ($is_video)
{
if ($f['size'] <= 0 || $f['size'] > $MAX_VID_BYTES)
{
ft_fail('video_15mb_ustu', $ajax);
}
$mime = '';
if (function_exists('finfo_open'))
{
$fi = @finfo_open(FILEINFO_MIME_TYPE);
if ($fi)
{
$mime = @finfo_file($fi, $tmp);
@finfo_close($fi);
}
}
// bazı sunucular octet-stream döndürebilir -> imza kontrolü
if ($mime && $mime !== 'video/mp4')
{
if ($mime === 'application/octet-stream' && ft_looks_like_mp4($tmp))
{
// kabul
}
else
{
ft_fail('yalnizca_mp4', $ajax);
}
}
$mediatype = 2;
$ext = 'mp4';
}
else
{
// IMAGE
if ($f['size'] <= 0 || $f['size'] > $MAX_IMG_BYTES)
{
ft_fail('dosya_5mb_ustu', $ajax);
}
$img = @getimagesize($tmp);
if (!$img || empty($img[2]))
{
ft_fail('gecersiz_resim', $ajax);
}
// Sadece JPG/PNG/GIF
$allowed = array(
IMAGETYPE_JPEG => 'jpg',
IMAGETYPE_PNG => 'png',
IMAGETYPE_GIF => 'gif',
);
$type = intval($img[2]);
if (!isset($allowed[$type]))
{
ft_fail('yalnizca_jpg_png_gif', $ajax);
}
$ext = $allowed[$type];
$width = intval($img[0]);
$height = intval($img[1]);
}
if (!is_dir($UPLOAD_DIR))
{
@mkdir($UPLOAD_DIR, 0755, true);
}
if (!is_dir($UPLOAD_DIR) || !is_writable($UPLOAD_DIR))
{
ft_fail('upload_klasoru_yazilamaz', $ajax);
}
$userid = intval($vbulletin->userinfo['userid']);
$visibility = ft_normalize_visibility($vbulletin->GPC['visibility']);
// Daha güçlü ve daha az tahmin edilebilir isim
$token = ft_token_hex(16); // 32 hex
$fname = 's_' . TIMENOW . '_' . $token . '.' . $ext;
$dest_abs = $UPLOAD_DIR . '/' . $fname;
$dest_rel = $UPLOAD_URL . '/' . $fname;
if (!move_uploaded_file($tmp, $dest_abs))
{
ft_fail('dosya_tasinamadi', $ajax);
}
@chmod($dest_abs, 0644);
$dateline = TIMENOW;
$expiretime = TIMENOW + $EXPIRE_SECS;
$db->query_write("
INSERT INTO ft_story (userid, dateline, expiretime, state, privacy, visibility)
VALUES ($userid, $dateline, $expiretime, 1, 0, $visibility)
");
$storyid = intval($db->insert_id());
$filepath_sql = $db->escape_string($dest_rel);
$db->query_write("
INSERT INTO ft_story_media (storyid, mediatype, filepath, thumbpath, filesize, width, height, dateline)
VALUES ($storyid, " . intval($mediatype) . ", '$filepath_sql', '', " . intval($f['size']) . ", " . intval($width) . ", " . intval($height) . ", $dateline)
");
// kullanıcı adı + avatar
$u = $db->query_first("
SELECT u.username, u.avatarid, u.avatarrevision, a.avatarpath
FROM user u
LEFT JOIN avatar a ON (a.avatarid = u.avatarid)
WHERE u.userid = $userid
LIMIT 1
");
$username = (!empty($u['username']) ? $u['username'] : $vbulletin->userinfo['username']);
if (!empty($u['avatarpath']))
{
$avatar = $u['avatarpath'];
}
else
{
$avatar = 'image.php?u=' . $userid . '&dateline=' . intval($u['avatarrevision']);
}
// AJAX ise JSON dön
if ($ajax)
{
ft_json_exit(array(
'ok' => 1,
'storyid' => $storyid,
'url' => $dest_rel,
'visibility' => $visibility,
'mediatype' => $mediatype,
'userid' => $userid,
'username' => $username,
'avatar' => $avatar,
'story' => array(
'storyid' => $storyid,
'userid' => $userid,
'username' => $username,
'avatar' => $avatar,
'url' => $dest_rel,
'image' => $dest_rel,
'visibility' => $visibility,
'mediatype' => $mediatype,
),
));
}
// Non-AJAX: basit çıktı
echo 'OK';
exit;
}
// YouTube link story
if ($do === 'youtube')
{
ft_verify_token_or_fail($ajax);
$ytid = ft_parse_youtube_id($vbulletin->GPC['youtube_url']);
if (!$ytid)
{
ft_fail('yalnizca_youtube_link', $ajax);
}
$userid = intval($vbulletin->userinfo['userid']);
$visibility = ft_normalize_visibility($vbulletin->GPC['visibility']);
$dateline = TIMENOW;
$expiretime = TIMENOW + $EXPIRE_SECS;
$db->query_write("
INSERT INTO ft_story (userid, dateline, expiretime, state, privacy, visibility)
VALUES ($userid, $dateline, $expiretime, 1, 0, $visibility)
");
$storyid = intval($db->insert_id());
// filepath içine "yt:ID" saklıyoruz (viewer/json tarafı bunu yorumlayacak)
$filepath_sql = $db->escape_string('yt:' . $ytid);
$db->query_write("
INSERT INTO ft_story_media (storyid, mediatype, filepath, thumbpath, filesize, width, height, dateline)
VALUES ($storyid, 4, '$filepath_sql', '', 0, 0, 0, $dateline)
");
$u = $db->query_first("
SELECT u.username, u.avatarid, u.avatarrevision, a.avatarpath
FROM user u
LEFT JOIN avatar a ON (a.avatarid = u.avatarid)
WHERE u.userid = $userid
LIMIT 1
");
$username = (!empty($u['username']) ? $u['username'] : $vbulletin->userinfo['username']);
if (!empty($u['avatarpath']))
{
$avatar = $u['avatarpath'];
}
else
{
$avatar = 'image.php?u=' . $userid . '&dateline=' . intval($u['avatarrevision']);
}
if ($ajax)
{
ft_json_exit(array(
'ok' => 1,
'storyid' => $storyid,
'visibility' => $visibility,
'mediatype' => 4,
'youtube_id' => $ytid,
'userid' => $userid,
'username' => $username,
'avatar' => $avatar,
'story' => array(
'storyid' => $storyid,
'userid' => $userid,
'username' => $username,
'avatar' => $avatar,
'visibility' => $visibility,
'mediatype' => 4,
'youtube_id' => $ytid,
),
));
}
echo 'OK';
exit;
}
// Text story
if ($do === 'text')
{
ft_verify_token_or_fail($ajax);
$db->query_write("SET NAMES utf8mb4");
// Metin + bg
$text = trim((string)$vbulletin->GPC['text_body']);
$bg = intval($vbulletin->GPC['bg_id']);
if ($bg < 1 || $bg > 12) $bg = 1;
if ($text === '')
{
ft_fail('bos_metin', $ajax);
}
// uzunluk limiti (MVP)
if (function_exists('mb_strlen')) {
if (mb_strlen($text, 'UTF-8') > 240) ft_fail('metin_cok_uzun', $ajax);
} else {
if (strlen($text) > 240) ft_fail('metin_cok_uzun', $ajax);
}
// --- Censor check ---
$confirm = intval($vbulletin->GPC['confirm_censor']);
if (function_exists('fetch_censored_text'))
{
$censored = fetch_censored_text($text);
// Sansür uygulanacaksa ilk istekte uyar, kaydetme
if ($censored !== $text && !$confirm)
{
ft_json_exit(array(
'ok' => 0,
'code' => 'censor_warning',
'error' => 'Metin yasaklı sözcük içeriyor. Devam ederseniz sansür uygulanacak.'
));
}
// Kullanıcı onayladıysa sansürlü metni kaydet
if ($censored !== $text && $confirm)
{
$text = $censored;
}
}
// emoji için bu request'te utf8mb4
$db->query_write("SET NAMES utf8mb4");
$userid = intval($vbulletin->userinfo['userid']);
$visibility = ft_normalize_visibility($vbulletin->GPC['visibility']);
$dateline = TIMENOW;
$expiretime = TIMENOW + $EXPIRE_SECS;
$db->query_write("
INSERT INTO ft_story (userid, dateline, expiretime, state, privacy, visibility)
VALUES ($userid, $dateline, $expiretime, 1, 0, $visibility)
");
$storyid = intval($db->insert_id());
// media kaydı (mediatype=3)
$db->query_write("
INSERT INTO ft_story_media (storyid, mediatype, filepath, thumbpath, filesize, width, height, dateline)
VALUES ($storyid, 3, '', '', 0, 0, 0, $dateline)
");
// text kaydı (utf8mb4 tabloda)
$text_sql = $db->escape_string($text);
$db->query_write("
INSERT INTO ft_story_text (storyid, text_body, bg_id, dateline)
VALUES ($storyid, '$text_sql', " . intval($bg) . ", $dateline)
");
// avatar/username
$u = $db->query_first("
SELECT u.username, u.avatarid, u.avatarrevision, a.avatarpath
FROM user u
LEFT JOIN avatar a ON (a.avatarid = u.avatarid)
WHERE u.userid = $userid
LIMIT 1
");
$username = (!empty($u['username']) ? $u['username'] : $vbulletin->userinfo['username']);
$avatar = (!empty($u['avatarpath']))
? $u['avatarpath']
: ('image.php?u=' . $userid . '&dateline=' . intval($u['avatarrevision']));
if ($ajax)
{
ft_json_exit(array(
'ok' => 1,
'storyid' => $storyid,
'visibility' => $visibility,
'mediatype' => 3,
'text_body' => $text,
'bg_id' => $bg,
'userid' => $userid,
'username' => $username,
'avatar' => $avatar,
'story' => array(
'storyid' => $storyid,
'userid' => $userid,
'username' => $username,
'avatar' => $avatar,
'visibility' => $visibility,
'mediatype' => 3,
'text_body' => $text,
'bg_id' => $bg,
),
));
}
echo 'OK';
exit;
}
// POST ama bilinmeyen action
ft_fail('gecersiz_islem', $ajax);
}
Revise this Paste