mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
- implemented screenshot handling, inclding
* editing after upload * reputation gain for approved uploads * moderator interface (albeit a bit wonky) I still do not speak French, Spanish or Russian, so translations are appreciated
This commit is contained in:
@@ -323,7 +323,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
{
|
||||
case AUTH_OK:
|
||||
if (!User::$ip)
|
||||
return Lang::$account['intError'];
|
||||
return Lang::$main['intError'];
|
||||
|
||||
// reset account status, update expiration
|
||||
DB::Aowow()->query('UPDATE ?_account SET prevIP = IF(curIp = ?, prevIP, curIP), curIP = IF(curIp = ?, curIP, ?), allowExpire = ?d, status = 0, statusTimer = 0, token = "" WHERE user = ?',
|
||||
@@ -354,7 +354,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
return sprintf(Lang::$account['loginExceeded'], Util::formatTime(CFG_FAILED_AUTH_EXCLUSION * 1000));
|
||||
case AUTH_INTERNAL_ERR:
|
||||
User::destroy();
|
||||
return Lang::$account['intError'];
|
||||
return Lang::$main['intError'];
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@@ -391,7 +391,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
|
||||
// check ip
|
||||
if (!User::$ip)
|
||||
return Lang::$account['intError'];
|
||||
return Lang::$main['intError'];
|
||||
|
||||
// limit account creation
|
||||
$ip = DB::Aowow()->selectRow('SELECT ip, count, unbanDate FROM ?_account_bannedips WHERE type = 1 AND ip = ?', User::$ip);
|
||||
@@ -420,7 +420,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
$token
|
||||
);
|
||||
if (!$id) // something went wrong
|
||||
return Lang::$account['intError'];
|
||||
return Lang::$main['intError'];
|
||||
else if ($_ = $this->sendMail($email, Lang::$mail['accConfirm'][0], sprintf(Lang::$mail['accConfirm'][1], $token), CFG_ACCOUNT_CREATE_SAVE_DECAY))
|
||||
{
|
||||
// success:: update ip-bans
|
||||
@@ -460,7 +460,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
return Lang::$account['newPassDiff'];
|
||||
|
||||
if (!DB::Aowow()->query('UPDATE ?_account SET passHash = ?, status = ?d WHERE id = ?d', User::hashcrypt($newPass), ACC_STATUS_OK, $uRow['id']))
|
||||
return Lang::$account['intError'];
|
||||
return Lang::$main['intError'];
|
||||
}
|
||||
|
||||
private function doRecoverUser($target)
|
||||
@@ -475,7 +475,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
private function initRecovery($type, $target, $delay, &$token)
|
||||
{
|
||||
if (!$type)
|
||||
return Lang::$account['intError'];
|
||||
return Lang::$main['intError'];
|
||||
|
||||
// check if already processing
|
||||
if ($_ = DB::Aowow()->selectCell('SELECT statusTimer - UNIX_TIMESTAMP() FROM ?_account WHERE email = ? AND status <> ?d AND statusTimer > UNIX_TIMESTAMP()', $target, ACC_STATUS_OK))
|
||||
@@ -484,7 +484,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
// create new token and write to db
|
||||
$token = Util::createHash();
|
||||
if (!DB::Aowow()->query('UPDATE ?_account SET token = ?, status = ?d, statusTimer = UNIX_TIMESTAMP() + ?d WHERE email = ?', $token, $type, $delay, $target))
|
||||
return Lang::$account['intError'];
|
||||
return Lang::$main['intError'];
|
||||
}
|
||||
|
||||
private function sendMail($target, $subj, $msg, $delay = 300)
|
||||
@@ -497,7 +497,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
'X-Mailer: PHP/' . phpversion();
|
||||
|
||||
if (!mail($target, $subj, $msg, $header))
|
||||
return sprintf(Lang::$account['intError2'], 'send mail');
|
||||
return sprintf(Lang::$main['intError2'], 'send mail');
|
||||
}
|
||||
|
||||
private function getNext($forHeader = false)
|
||||
|
||||
@@ -19,6 +19,14 @@ class AdminPage extends GenericPage
|
||||
{
|
||||
switch ($pageParam)
|
||||
{
|
||||
case 'screenshots':
|
||||
$this->reqUGroup = U_GROUP_STAFF | U_GROUP_SCREENSHOT;
|
||||
$this->generator = 'handleScreenshots';
|
||||
$this->tpl = 'admin/screenshots';
|
||||
|
||||
array_push($this->path, 1, 5);
|
||||
$this->name = 'Screenshot Manager';
|
||||
break;
|
||||
case 'phpinfo':
|
||||
$this->reqUGroup = U_GROUP_ADMIN | U_GROUP_DEV;
|
||||
$this->generator = 'handlePhpInfo';
|
||||
@@ -439,6 +447,45 @@ class AdminPage extends GenericPage
|
||||
}
|
||||
}
|
||||
|
||||
private function handleScreenshots()
|
||||
{
|
||||
$this->addJS('screenshot.js');
|
||||
$this->addCSS(array(
|
||||
['string' => '.layout {margin: 0px 25px; max-width: inherit; min-width: 1200px; }'],
|
||||
['string' => '#highlightedRow { background-color: #322C1C; }']
|
||||
));
|
||||
|
||||
$ssGetAll = isset($_GET['all']) && empty($_GET['all']);
|
||||
$ssPages = [];
|
||||
$ssData = [];
|
||||
$nMatches = 0;
|
||||
|
||||
if (!empty($_GET['type']) && !empty($_GET['typeid']))
|
||||
{
|
||||
$ssData = CommunityContent::getScreenshotsForManager(intVal($_GET['type']), intVal($_GET['typeid']));
|
||||
$nMatches = count($ssData);
|
||||
}
|
||||
else if (!empty($_GET['user']))
|
||||
{
|
||||
$name = urldecode($_GET['user']);
|
||||
if (strlen($name) > 3)
|
||||
{
|
||||
if ($uId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE displayName = ?', ucFirst($name)))
|
||||
{
|
||||
$ssData = CommunityContent::getScreenshotsForManager(0, 0, $uId);
|
||||
$nMatches = count($ssData);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
$ssPages = CommunityContent::getScreenshotPagesForManager($ssGetAll, $nMatches);
|
||||
|
||||
$this->getAll = $ssGetAll;
|
||||
$this->ssPages = $ssPages;
|
||||
$this->ssData = $ssData;
|
||||
$this->ssNFound = $nMatches; // ssm_numPagesFound
|
||||
}
|
||||
|
||||
private function configAddRow($r)
|
||||
{
|
||||
$buff = '<tr>';
|
||||
@@ -487,7 +534,7 @@ class AdminPage extends GenericPage
|
||||
else
|
||||
$buff .= '|<a class="icon-refresh tip disabled"></a>';
|
||||
|
||||
if (!($r['flags'] & CON_FLAG_PERSISTANT))
|
||||
if (!($r['flags'] & CON_FLAG_PERSISTENT))
|
||||
$buff .= '|<a class="icon-delete tip" onclick="cfg_remove.bind(this, \''.$key.'\')()" onmouseover="$WH.Tooltip.showAtCursor(event, \'Remove Setting\', 0, 0, \'q\')" onmousemove="$WH.Tooltip.cursorUpdate(event)" onmouseout="$WH.Tooltip.hide()"></a>';
|
||||
|
||||
$buff .= '<span class="status"></span></td></tr>';
|
||||
|
||||
301
pages/screenshot.php
Normal file
301
pages/screenshot.php
Normal file
@@ -0,0 +1,301 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
// filename: Username-type-typeId-<hash>[_original].jpg
|
||||
|
||||
class ScreenshotPage extends GenericPage
|
||||
{
|
||||
protected $tpl = 'screenshot';
|
||||
protected $js = ['Cropper.js'];
|
||||
protected $css = [['path' => 'Cropper.css']];
|
||||
protected $reqAuth = true;
|
||||
|
||||
private $tmpPath = 'static/uploads/temp/';
|
||||
private $pendingPath = 'static/uploads/screenshots/pending/';
|
||||
private $destination = null;
|
||||
protected $destType = 0;
|
||||
protected $destTypeId = 0;
|
||||
|
||||
public function __construct($pageCall, $pageParam)
|
||||
{
|
||||
parent::__construct($pageCall, $pageParam);
|
||||
|
||||
$this->name = Lang::$main['ssEdit'];
|
||||
$this->caption = @$_POST['screenshotcaption']; // do not htmlEscape. It's applied as textnode
|
||||
|
||||
// what are its other uses..? (finalize is custom)
|
||||
if ($pageParam == 'finalize')
|
||||
{
|
||||
if (!$this->handleFinalize())
|
||||
$this->error();
|
||||
}
|
||||
else if ($pageParam != 'add')
|
||||
$this->error();
|
||||
|
||||
// get screenshot destination
|
||||
foreach ($_GET as $k => $v)
|
||||
{
|
||||
if ($v) // taret delivered as empty type.typeId key
|
||||
continue;
|
||||
|
||||
$x = explode('_', $k); // . => _ as array key
|
||||
if (count($x) != 2)
|
||||
continue;
|
||||
|
||||
// no such type
|
||||
if (empty(Util::$typeClasses[$x[0]]))
|
||||
continue;
|
||||
|
||||
$t = Util::$typeClasses[$x[0]];
|
||||
$c = [['id', intVal($x[1])]];
|
||||
if ($x[0] == TYPE_WORLDEVENT) // ohforfsake..
|
||||
$c = array_merge($c, ['OR', ['holidayId', intVal($x[1])]]);
|
||||
|
||||
$this->destination = new $t($c);
|
||||
|
||||
// no such typeId
|
||||
if ($this->destination->error)
|
||||
continue;
|
||||
|
||||
$this->destType = intVal($x[0]);
|
||||
$this->destTypeId = intVal($x[1]);
|
||||
}
|
||||
}
|
||||
|
||||
private function handleFinalize()
|
||||
{
|
||||
if (empty($_SESSION['ssUpload']))
|
||||
return false;
|
||||
|
||||
// as its saved in session it should be valid
|
||||
$file = $_SESSION['ssUpload']['file'];
|
||||
|
||||
// check tmp file
|
||||
$fullPath = $this->tmpPath.$file.'_original.jpg';
|
||||
if (!file_exists($fullPath))
|
||||
return false;
|
||||
|
||||
// check post data
|
||||
if (empty($_POST) || empty($_POST['selection']))
|
||||
return false;
|
||||
|
||||
$dims = explode(',', $_POST['selection']);
|
||||
if (count($dims) != 4)
|
||||
return false;
|
||||
|
||||
Util::checkNumeric($dims);
|
||||
|
||||
// actually crop the image
|
||||
$srcImg = imagecreatefromjpeg($fullPath);
|
||||
|
||||
$x = (int)(imagesx($srcImg) * $dims[0]);
|
||||
$y = (int)(imagesy($srcImg) * $dims[1]);
|
||||
$w = (int)(imagesx($srcImg) * $dims[2]);
|
||||
$h = (int)(imagesy($srcImg) * $dims[3]);
|
||||
|
||||
$destImg = imagecreatetruecolor($w, $h);
|
||||
|
||||
imagefill($destImg, 0, 0, imagecolorallocate($destImg, 255, 255, 255));
|
||||
imagecopy($destImg, $srcImg, 0, 0, $x, $y, $w, $h);
|
||||
imagedestroy($srcImg);
|
||||
|
||||
// write to db
|
||||
$newId = DB::Aowow()->query(
|
||||
'INSERT INTO ?_screenshots (type, typeId, uploader, date, width, height, caption) VALUES (?d, ?d, ?d, UNIX_TIMESTAMP(), ?d, ?d, ?)',
|
||||
$_SESSION['ssUpload']['type'], $_SESSION['ssUpload']['typeId'],
|
||||
User::$id,
|
||||
$w, $h,
|
||||
$this->caption
|
||||
);
|
||||
|
||||
// write to file
|
||||
if (is_int($newId)) // 0 is valid, NULL or FALSE is not
|
||||
imagejpeg($destImg, $this->pendingPath.$newId.'.jpg', 100);
|
||||
|
||||
unset($_SESSION['ssUpload']);
|
||||
header('Location: ?user='.User::$displayName.'#screenshots');
|
||||
}
|
||||
|
||||
protected function generateContent()
|
||||
{
|
||||
$maxW = 488;
|
||||
$maxH = 325;
|
||||
$minCrop = CFG_SCREENSHOT_MIN_SIZE;
|
||||
|
||||
if ($minCrop <= 0)
|
||||
{
|
||||
Util::addNote(U_GROUP_DEV | U_GROUP_ADMIN, 'ScreenshotPage::generateContent() - config error: dimensions for uploaded screenshots egual or less than zero. Value forced to 200');
|
||||
$minCrop = 200;
|
||||
}
|
||||
|
||||
if (!$this->destType)
|
||||
{
|
||||
$this->error = Lang::$main['ssErrors']['noDest'];
|
||||
return;
|
||||
}
|
||||
|
||||
if (User::$banStatus & ACC_BAN_SCREENSHOT)
|
||||
{
|
||||
$this->error = Lang::$main['ssErrors']['notAllowed'];
|
||||
return;
|
||||
}
|
||||
|
||||
if ($_ = $this->validateScreenshot($isPNG))
|
||||
{
|
||||
$this->error = $_;
|
||||
return;
|
||||
}
|
||||
|
||||
$im = $isPNG ? $this->loadFromPNG() : $this->loadFromJPG();
|
||||
if (!$im)
|
||||
{
|
||||
$this->error = Lang::$main['ssErrors']['load'];
|
||||
return;
|
||||
}
|
||||
|
||||
$name = User::$displayName.'-'.$this->destType.'-'.$this->destTypeId.'-'.Util::createHash(16);
|
||||
$oSize = $rSize = [imagesx($im), imagesy($im)];
|
||||
$rel = $oSize[0] / $oSize[1];
|
||||
|
||||
// not sure if this is the best way
|
||||
$_SESSION['ssUpload'] = array(
|
||||
'file' => $name,
|
||||
'type' => $this->destType,
|
||||
'typeId' => $this->destTypeId
|
||||
);
|
||||
|
||||
// check for oversize and refit to crop-screen
|
||||
if ($rel >= 1.5 && $oSize[0] > $maxW)
|
||||
$rSize = [$maxW, $maxW / $rel];
|
||||
else if ($rel < 1.5 && $oSize[1] > $maxH)
|
||||
$rSize = [$maxH * $rel, $maxH];
|
||||
|
||||
$this->writeImage($im, $oSize, $name.'_original'); // use this image for work
|
||||
$this->writeImage($im, $rSize, $name); // use this image to display
|
||||
|
||||
// r: resized; o: original
|
||||
// r: x <= 488 && y <= 325 while x proportional to y
|
||||
// mincrop is optional and specifies the minimum resulting image size
|
||||
$this->cropper = [
|
||||
'url' => $this->tmpPath.$name.'.jpg',
|
||||
'parent' => 'ss-container',
|
||||
'oWidth' => $oSize[0],
|
||||
'rWidth' => $rSize[0],
|
||||
'oHeight' => $oSize[1],
|
||||
'rHeight' => $rSize[1],
|
||||
];
|
||||
|
||||
$infobox = [];
|
||||
|
||||
// target
|
||||
$infobox[] = sprintf(Lang::$main['displayOn'], Util::ucFirst(Lang::$game[Util::$typeStrings[$this->destType]]), Util::$typeStrings[$this->destType], $this->destTypeId);
|
||||
$this->extendGlobalIds($this->destType, $this->destTypeId);
|
||||
|
||||
// dimensions
|
||||
$infobox[] = Lang::$main['originalSize'].Lang::$main['colon'].$oSize[0].' x '.$oSize[1];
|
||||
$infobox[] = Lang::$main['targetSize'].Lang::$main['colon'].'[span id=qf-newSize][/span]';
|
||||
|
||||
// minimum dimensions
|
||||
if (!User::isInGroup(U_GROUP_STAFF))
|
||||
{
|
||||
$infobox[] = Lang::$main['minSize'].Lang::$main['colon'].$minCrop.' x '.$minCrop;
|
||||
$this->cropper['minCrop'] = $minCrop;
|
||||
}
|
||||
|
||||
$this->infobox = '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]';
|
||||
}
|
||||
|
||||
private function loadFromPNG()
|
||||
{
|
||||
$image = imagecreatefrompng($_FILES['screenshotfile']['tmp_name']);
|
||||
$bg = imagecreatetruecolor(imagesx($image), imagesy($image));
|
||||
|
||||
imagefill($bg, 0, 0, imagecolorallocate($bg, 255, 255, 255));
|
||||
imagealphablending($bg, true);
|
||||
imagecopy($bg, $image, 0, 0, 0, 0, imagesx($image), imagesy($image));
|
||||
imagedestroy($image);
|
||||
|
||||
return $bg;
|
||||
}
|
||||
|
||||
private function loadFromJPG()
|
||||
{
|
||||
return imagecreatefromjpeg($_FILES['screenshotfile']['tmp_name']);
|
||||
}
|
||||
|
||||
private function writeImage($im, $dims, $file)
|
||||
{
|
||||
if ($res = imagecreatetruecolor($dims[0], $dims[1]))
|
||||
if (imagecopyresampled($res, $im, 0, 0, 0, 0, $dims[0], $dims[1], imagesx($im), imagesy($im)))
|
||||
if (imagejpeg($res, $this->tmpPath.$file.'.jpg', 100))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function validateScreenshot(&$isPNG = false)
|
||||
{
|
||||
// no upload happened or some error occured
|
||||
if (!$_FILES || empty($_FILES['screenshotfile']))
|
||||
return Lang::$main['ssErrors']['noUpload'];
|
||||
|
||||
switch ($_FILES['screenshotfile']['error'])
|
||||
{
|
||||
case 1:
|
||||
return sprintf(Lang::$main['ssErrors']['maxSize'], ini_get('upload_max_filesize'));;
|
||||
case 3:
|
||||
return Lang::$main['ssErrors']['interrupted'];
|
||||
case 4:
|
||||
return Lang::$main['ssErrors']['noFile'];
|
||||
case 6:
|
||||
Util::addNote(U_GROUP_ADMIN, 'ScreenshotPage::validateScreenshot() - temporary upload directory is not set');
|
||||
return Lang::$main['intError'];
|
||||
case 7:
|
||||
Util::addNote(U_GROUP_ADMIN, 'ScreenshotPage::validateScreenshot() - could not write temporary file to disk');
|
||||
return Lang::$main['genericError'];
|
||||
}
|
||||
|
||||
// points to invalid file (hack attempt)
|
||||
if (!is_uploaded_file($_FILES['screenshotfile']['tmp_name']))
|
||||
{
|
||||
Util::addNote(U_GROUP_ADMIN, 'ScreenshotPage::validateScreenshot() - uploaded file not in upload directory');
|
||||
return Lang::$main['genericError'];
|
||||
}
|
||||
|
||||
// invalid file
|
||||
$is = getimagesize($_FILES['screenshotfile']['tmp_name']);
|
||||
if (!$is || empty($is['mime']))
|
||||
return Lang::$main['ssErrors']['notImage'];
|
||||
|
||||
// allow jpeg, png
|
||||
switch ($is['mime'])
|
||||
{
|
||||
case 'image/png':
|
||||
$isPNG = true;
|
||||
case 'image/jpg':
|
||||
case 'image/jpeg':
|
||||
break;
|
||||
default:
|
||||
return Lang::$main['ssErrors']['wrongFormat'];
|
||||
}
|
||||
|
||||
// size-missmatch: 4k UHD upper limit; 150px lower limit
|
||||
if ($is[0] < 150 || $is[1] < 150)
|
||||
return sprintf(Lang::$main['ssErrors']['tooSmall'], 150, 150);
|
||||
|
||||
if ($is[0] > 3840 || $is[1] > 2160)
|
||||
return sprintf(Lang::$main['ssErrors']['tooLarge'], 150, 150);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function generatePath() { }
|
||||
protected function generateTitle()
|
||||
{
|
||||
array_unshift($this->title, Lang::$main['ssUpload']);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user