<?php
define(&#039;THIS_SCRIPT&#039;, &#039;ft_story_upload&#039;);
require_once(&#039;./global.php&#039;);

/*
  FT Story Upload
  - Desteklenen türler: JPG / PNG / GIF (5 MB) + MP4 (15 MB)
  - Visibility:
      1 = Kayıtlı üyeler
      3 = Sadece arkadaşlar
  Geliştirici: atmaca
*/

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, &#039;utf-8&#039;))
		{
			return $mixed;
		}

		if (function_exists(&#039;mb_convert_encoding&#039;))
		{
			return @mb_convert_encoding($mixed, &#039;UTF-8&#039;, $fromCharset);
		}

		return utf8_encode($mixed);
	}

	return $mixed;
}

function ft_json_exit($arr)
{
	global $stylevar;

	$fromCharset = &#039;UTF-8&#039;;
	if (!empty($stylevar[&#039;charset&#039;]))
	{
		$fromCharset = $stylevar[&#039;charset&#039;];
	}

	$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(&#039;ob_get_length&#039;) && ob_get_length())
	{
		@ob_clean();
	}

	header(&#039;Content-Type: application/json; charset=UTF-8&#039;);

	if ($json === false)
	{
		echo json_encode(array(
			&#039;ok&#039;    => 0,
			&#039;error&#039; => &#039;JSON üretilemedi.&#039;,
			&#039;code&#039;  => json_last_error()
		));
		exit;
	}

	echo $json;
	exit;
}

function ft_upload_error_message($code)
{
	$map = array(
		1 => &#039;Dosya çok büyük (php.ini upload_max_filesize).&#039;,
		2 => &#039;Dosya çok büyük (form MAX_FILE_SIZE).&#039;,
		3 => &#039;Dosya kısmen yüklendi.&#039;,
		4 => &#039;Dosya seçilmedi.&#039;,
		6 => &#039;Geçici klasör (tmp) bulunamadı.&#039;,
		7 => &#039;Dosya diske yazılamadı.&#039;,
		8 => &#039;Bir PHP eklentisi yüklemeyi durdurdu.&#039;,
	);

	return isset($map[$code]) ? $map[$code] : (&#039;Yükleme hatası (kod: &#039; . intval($code) . &#039;).&#039;);
}

function ft_fail($code, $ajax)
{
	$msg = $code;

	if (is_string($code))
	{
		if (strpos($code, &#039;upload_hata_&#039;) === 0)
		{
			$err = intval(substr($code, strlen(&#039;upload_hata_&#039;)));
			$msg = ft_upload_error_message($err);
		}
		else
		{
			$map = array(
				&#039;bad_token&#039;                 => &#039;Oturum doğrulaması başarısız. Sayfayı yenileyip tekrar deneyin.&#039;,
				&#039;dosya_gelmedi&#039;             => &#039;Dosya seçilmedi.&#039;,

				&#039;dosya_5mb_ustu&#039;            => &#039;Görsel boyutu 5 MB sınırını aşıyor.&#039;,
				&#039;video_15mb_ustu&#039;           => &#039;Video boyutu 15 MB sınırını aşıyor.&#039;,

				&#039;gecersiz_resim&#039;            => &#039;Geçersiz resim dosyası.&#039;,
				&#039;yalnizca_jpg_png_gif&#039;      => &#039;Sadece JPG / PNG / GIF kabul ediliyor.&#039;,
				&#039;yalnizca_mp4&#039;              => &#039;Sadece MP4 video kabul ediliyor.&#039;,

				&#039;upload_klasoru_yazilamaz&#039;  => &#039;Sunucuda yükleme klasörü yazılabilir değil.&#039;,
				&#039;dosya_tasinamadi&#039;          => &#039;Dosya sunucuya kaydedilemedi.&#039;,
				&#039;not_logged_in&#039;             => &#039;Bu işlem için oturum açmalısınız.&#039;,
			);

			if (isset($map[$code]))
			{
				$msg = $map[$code];
			}
		}
	}

	if ($ajax)
	{
		ft_json_exit(array(
			&#039;ok&#039;    => 0,
			&#039;error&#039; => $msg,
			&#039;code&#039;  => $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;
}

$vbulletin->input->clean_array_gpc(&#039;p&#039;, array(
	&#039;do&#039;            => TYPE_STR,
	&#039;securitytoken&#039; => TYPE_STR,
	&#039;ajax&#039;          => TYPE_UINT,
	&#039;visibility&#039;    => TYPE_UINT,
));

$do   = $vbulletin->GPC[&#039;do&#039;];
$ajax = ($vbulletin->GPC[&#039;ajax&#039;] ? true : false);

if (!$vbulletin->userinfo[&#039;userid&#039;])
{
	if ($ajax)
	{
		ft_fail(&#039;not_logged_in&#039;, true);
	}

	print_no_permission();
}

// 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 . &#039;/ft_story_uploads&#039;;
$UPLOAD_URL    = &#039;ft_story_uploads&#039;;

if ($do == &#039;upload&#039; && $_SERVER[&#039;REQUEST_METHOD&#039;] == &#039;POST&#039;)
{
	$token = $vbulletin->GPC[&#039;securitytoken&#039;];
	$raw   = (!empty($vbulletin->userinfo[&#039;securitytoken_raw&#039;]) ? $vbulletin->userinfo[&#039;securitytoken_raw&#039;] : &#039;&#039;);

	if (!$token || $token === &#039;guest&#039;)
	{
		ft_fail(&#039;bad_token&#039;, $ajax);
	}

	if (!verify_security_token($token, $raw))
	{
		ft_fail(&#039;bad_token&#039;, $ajax);
	}

	if (empty($_FILES[&#039;storyfile&#039;]) || !is_uploaded_file($_FILES[&#039;storyfile&#039;][&#039;tmp_name&#039;]))
	{
		ft_fail(&#039;dosya_gelmedi&#039;, $ajax);
	}

	$f = $_FILES[&#039;storyfile&#039;];

	if (!empty($f[&#039;error&#039;]))
	{
		ft_fail(&#039;upload_hata_&#039; . intval($f[&#039;error&#039;]), $ajax);
	}

	$tmp = $f[&#039;tmp_name&#039;];

	$ext = strtolower(pathinfo((string)$f[&#039;name&#039;], PATHINFO_EXTENSION));
	$is_video = ($ext === &#039;mp4&#039;);

	$mediatype = 1;
	$width = 0;
	$height = 0;

	if ($is_video)
	{
		if ($f[&#039;size&#039;] <= 0 || $f[&#039;size&#039;] > $MAX_VID_BYTES)
		{
			ft_fail(&#039;video_15mb_ustu&#039;, $ajax);
		}

		$mime = &#039;&#039;;
		if (function_exists(&#039;finfo_open&#039;))
		{
			$fi = @finfo_open(FILEINFO_MIME_TYPE);
			if ($fi)
			{
				$mime = @finfo_file($fi, $tmp);
				@finfo_close($fi);
			}
		}

		if ($mime && $mime !== &#039;video/mp4&#039; && $mime !== &#039;application/octet-stream&#039;)
		{
			ft_fail(&#039;yalnizca_mp4&#039;, $ajax);
		}

		$mediatype = 2;
		$ext = &#039;mp4&#039;;
	}
	else
	{
		if ($f[&#039;size&#039;] <= 0 || $f[&#039;size&#039;] > $MAX_IMG_BYTES)
		{
			ft_fail(&#039;dosya_5mb_ustu&#039;, $ajax);
		}

		$img = @getimagesize($tmp);

		if (!$img || empty($img[2]))
		{
			ft_fail(&#039;gecersiz_resim&#039;, $ajax);
		}

		// Sadece JPG/PNG/GIF
		$allowed = array(
			IMAGETYPE_JPEG => &#039;jpg&#039;,
			IMAGETYPE_PNG  => &#039;png&#039;,
			IMAGETYPE_GIF  => &#039;gif&#039;,
		);

		$type = intval($img[2]);
		if (!isset($allowed[$type]))
		{
			ft_fail(&#039;yalnizca_jpg_png_gif&#039;, $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(&#039;upload_klasoru_yazilamaz&#039;, $ajax);
	}

	$userid     = intval($vbulletin->userinfo[&#039;userid&#039;]);
	$visibility = ft_normalize_visibility($vbulletin->GPC[&#039;visibility&#039;]);

	$rand  = substr(md5(uniqid((string)$userid, true)), 0, 12);
	$fname = &#039;s_&#039; . $userid . &#039;_&#039; . TIMENOW . &#039;_&#039; . $rand . &#039;.&#039; . $ext;

	$dest_abs = $UPLOAD_DIR . &#039;/&#039; . $fname;
	$dest_rel = $UPLOAD_URL . &#039;/&#039; . $fname;

	if (!move_uploaded_file($tmp, $dest_abs))
	{
		ft_fail(&#039;dosya_tasinamadi&#039;, $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) . ", &#039;$filepath_sql&#039;, &#039;&#039;, " . intval($f[&#039;size&#039;]) . ", " . intval($width) . ", " . intval($height) . ", $dateline)
	");

	// Kullanıcı adı + avatar (upload sonrası storybar güncellemesi için)
	$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[&#039;username&#039;]) ? $u[&#039;username&#039;] : $vbulletin->userinfo[&#039;username&#039;]);
	if (!empty($u[&#039;avatarpath&#039;]))
	{
		$avatar = $u[&#039;avatarpath&#039;];
	}
	else
	{
		$avatar = &#039;image.php?u=&#039; . $userid . &#039;&dateline=&#039; . intval($u[&#039;avatarrevision&#039;]);
	}

	// AJAX ise JSON dön
	if ($ajax)
	{
		ft_json_exit(array(
			&#039;ok&#039;         => 1,
			&#039;storyid&#039;    => $storyid,
			&#039;url&#039;        => $dest_rel,
			&#039;visibility&#039; => $visibility,
			&#039;mediatype&#039;  => $mediatype,

			&#039;userid&#039;     => $userid,
			&#039;username&#039;   => $username,
			&#039;avatar&#039;     => $avatar,

			&#039;story&#039; => array(
				&#039;storyid&#039;    => $storyid,
				&#039;userid&#039;     => $userid,
				&#039;username&#039;   => $username,
				&#039;avatar&#039;     => $avatar,
				&#039;url&#039;        => $dest_rel,
				&#039;image&#039;      => $dest_rel,
				&#039;visibility&#039; => $visibility,
				&#039;mediatype&#039;  => $mediatype
			)
		));
	}

	
	echo &#039;<h2>Hikaye yüklendi</h2>&#039;;
	echo &#039;<div>storyid: <b>&#039; . $storyid . &#039;</b></div>&#039;;
	echo &#039;<div>tür: <b>&#039; . ($mediatype == 2 ? &#039;Video (MP4)&#039; : &#039;Görsel&#039;) . &#039;</b></div>&#039;;
	echo &#039;<div>görünürlük: <b>&#039; . ($visibility == 3 ? &#039;Sadece Arkadaşlar&#039; : &#039;Forum Üyeleri&#039;) . &#039;</b></div>&#039;;
	if ($mediatype == 2)
	{
		echo &#039;<div style="margin-top:10px;"><video src="&#039; . htmlspecialchars($dest_rel) . &#039;" controls style="max-width:420px; width:100%;"></video></div>&#039;;
	}
	else
	{
		echo &#039;<div style="margin-top:10px;"><img src="&#039; . htmlspecialchars($dest_rel) . &#039;" style="max-width:360px; height:auto;"></div>&#039;;
	}
	exit;
}


$token_out = htmlspecialchars($vbulletin->userinfo[&#039;securitytoken&#039;]);
?>
<h2>Hikaye Yükle</h2>

<form action="ft_story_upload.php" method="post" enctype="multipart/form-data">
	<input type="hidden" name="do" value="upload">
	<input type="hidden" name="securitytoken" value="<?php echo $token_out; ?>">
	<input type="hidden" name="ajax" value="0">

	<div style="margin-bottom:10px;">
		<input type="file" name="storyfile" accept=".jpg,.jpeg,.png,.gif,.mp4,image/jpeg,image/png,image/gif,video/mp4" required>
	</div>

	<div style="margin-bottom:10px;">
		<label for="ftStoryVisibility" style="display:block; margin-bottom:4px;">Kimler görebilsin?</label>
		<select name="visibility" id="ftStoryVisibility">
			<option value="1">Forum Üyeleri</option>
			<option value="3">Sadece Arkadaşlar</option>
		</select>
	</div>

	<div style="margin-top:10px;">
		<button type="submit">Yükle</button>
	</div>

	<div style="margin-top:8px; font-size:12px; color:#666;">
		Maks: Görsel 5 MB / Video 15 MB | Süre: 24 saat | Tür: JPG/PNG/GIF/MP4
	</div>
</form>

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