/** * Retrieve the full size URL for a submission * * @param string $id * @param string $prov * * @return null|string */ static function getFullsizeURL($id, $prov) { $stash_url = $prov === 'sta.sh' ? "http://sta.sh/{$id}" : "http://fav.me/{$id}"; try { $stashpage = HTTP::legitimateRequest($stash_url, null, null); } catch (CURLRequestException $e) { if ($e->getCode() === 404) { return 404; } return 1; } catch (\Exception $e) { return 2; } if (empty($stashpage)) { return 3; } $STASH_DL_LINK_REGEX = '(https?://(sta\\.sh|www\\.deviantart\\.com)/download/\\d+/[a-z\\d_]+-d[a-z\\d]{6,}\\.(?:png|jpe?g|bmp)\\?[^"]+)'; $urlmatch = preg_match(new RegExp('<a\\s+class="[^"]*?dev-page-download[^"]*?"\\s+href="' . $STASH_DL_LINK_REGEX . '"'), $stashpage['response'], $_match); if (!$urlmatch) { return 4; } $fullsize_url = HTTP::findRedirectTarget(htmlspecialchars_decode($_match[1]), $stash_url); if (empty($fullsize_url)) { return 5; } global $Database; if ($Database->where('id', $id)->where('provider', $prov)->has('deviation_cache')) { $Database->where('id', $id)->where('provider', $prov)->update('deviation_cache', array('fullsize' => $fullsize_url)); } return URL::makeHttps($fullsize_url); }
/** * Checks if a user is a club member * (currently only works for recently added members, does not deal with old members or admins) * * @return bool */ function isClubMember() { $RecentlyJoined = HTTP::legitimateRequest('http://mlp-vectorclub.deviantart.com/modals/memberlist/'); return !empty($RecentlyJoined['response']) && preg_match(new RegExp('<a class="[a-z ]*username" href="http://' . strtolower($this->name) . '.deviantart.com/">' . USERNAME_PATTERN . '</a>'), $RecentlyJoined['response']); }
/** * Requests or refreshes an Access Token * $type defaults to 'authorization_code' * * @param string $code * @param null|string $type * * @return User|void */ static function getToken(string $code, string $type = null) { global $Database, $http_response_header; if (empty($type) || !in_array($type, array('authorization_code', 'refresh_token'))) { $type = 'authorization_code'; } $URL_Start = 'https://www.deviantart.com/oauth2/token?client_id=' . DA_CLIENT . '&client_secret=' . DA_SECRET . "&grant_type={$type}"; switch ($type) { case "authorization_code": $json = DeviantArt::request("{$URL_Start}&code={$code}" . OAUTH_REDIRECT_URI, false); break; case "refresh_token": $json = DeviantArt::request("{$URL_Start}&refresh_token={$code}", false); break; } if (empty($json)) { if (Cookie::exists('access')) { $Database->where('access', Cookie::get('access'))->delete('sessions'); Cookie::delete('access', Cookie::HTTPONLY); } HTTP::redirect("/da-auth?error=server_error&error_description={$http_response_header[0]}"); } if (empty($json['status'])) { HTTP::redirect("/da-auth?error={$json['error']}&error_description={$json['error_description']}"); } $userdata = DeviantArt::request('user/whoami', $json['access_token']); /** @var $User Models\User */ $User = $Database->where('id', $userdata['userid'])->getOne('users'); if (isset($User->role) && $User->role === 'ban') { $_GET['error'] = 'user_banned'; $BanReason = $Database->where('target', $User->id)->orderBy('entryid', 'ASC')->getOne('log__banish'); if (!empty($BanReason)) { $_GET['error_description'] = $BanReason['reason']; } return; } $UserID = strtolower($userdata['userid']); $UserData = array('name' => $userdata['username'], 'avatar_url' => URL::makeHttps($userdata['usericon'])); $AuthData = array('access' => $json['access_token'], 'refresh' => $json['refresh_token'], 'expires' => date('c', time() + intval($json['expires_in'])), 'scope' => $json['scope']); $cookie = bin2hex(random_bytes(64)); $AuthData['token'] = sha1($cookie); $browser = CoreUtils::detectBrowser(); foreach ($browser as $k => $v) { if (!empty($v)) { $AuthData[$k] = $v; } } if (empty($User)) { $MoreInfo = array('id' => $UserID, 'role' => 'user'); $makeDev = !$Database->has('users'); if ($makeDev) { $MoreInfo['id'] = strtoupper($MoreInfo['id']); } $Insert = array_merge($UserData, $MoreInfo); $Database->insert('users', $Insert); $User = new User($Insert); if ($makeDev) { $User->updateRole('developer'); } } else { $Database->where('id', $UserID)->update('users', $UserData); } if (empty($makeDev) && !empty($User) && Permission::insufficient('member', $User->role) && $User->isClubMember()) { $User->updateRole('member'); } if ($type === 'refresh_token') { $Database->where('refresh', $code)->update('sessions', $AuthData); } else { $Database->where('user', $User->id)->where('scope', $AuthData['scope'], '!=')->delete('sessions'); $Database->insert('sessions', array_merge($AuthData, array('user' => $UserID))); } $Database->rawQuery("DELETE FROM sessions WHERE \"user\" = ? && lastvisit <= NOW() - INTERVAL '1 MONTH'", array($UserID)); Cookie::set('access', $cookie, time() + Time::$IN_SECONDS['year'], Cookie::HTTPONLY); return $User ?? null; }
echo "pong"; break; default: CoreUtils::notFound(); } exit; } CoreUtils::notFound(); } // Static redirects switch ($do) { // PAGES case "logs": $do = 'admin'; $data = rtrim("logs/{$data}", '/'); HTTP::redirect(rtrim("/{$do}/{$data}", '/')); break; case "u": $do = 'user'; break; case "cg": case "colourguides": case "colourguide": case "colorguides": $do = 'colorguide'; break; } // Load controller $controller = INCPATH . "controllers/{$do}.php"; if (!($do === 'colorguide' && preg_match(new RegExp('\\.(svg|png)$'), $data))) { Users::authenticate();
/** * Check authentication cookie and set global */ static function authenticate() { global $Database, $signedIn, $currentUser, $Color, $color; CSRFProtection::detect(); if (!POST_REQUEST && isset($_GET['CSRF_TOKEN'])) { HTTP::redirect(CSRFProtection::removeParamFromURL($_SERVER['REQUEST_URI'])); } if (!Cookie::exists('access')) { return; } $authKey = Cookie::get('access'); if (!empty($authKey)) { if (!preg_match(new RegExp('^[a-f\\d]+$', 'iu'), $authKey)) { $oldAuthKey = $authKey; $authKey = bin2hex($authKey); $Database->where('token', sha1($oldAuthKey))->update('sessions', array('token' => sha1($authKey))); Cookie::set('access', $authKey, time() + Time::$IN_SECONDS['year'], Cookie::HTTPONLY); } $currentUser = Users::get(sha1($authKey), 'token'); } if (!empty($currentUser)) { if ($currentUser->role === 'ban') { $Database->where('id', $currentUser->id)->delete('sessions'); } else { if (strtotime($currentUser->Session['expires']) < time()) { $tokenvalid = false; try { DeviantArt::getToken($currentUser->Session['refresh'], 'refresh_token'); $tokenvalid = true; } catch (CURLRequestException $e) { $Database->where('id', $currentUser->Session['id'])->delete('sessions'); trigger_error("Session refresh failed for {$currentUser->name} ({$currentUser->id}) | {$e->getMessage()} (HTTP {$e->getCode()})", E_USER_WARNING); } } else { $tokenvalid = true; } if ($tokenvalid) { $signedIn = true; if (time() - strtotime($currentUser->Session['lastvisit']) > Time::$IN_SECONDS['minute']) { $lastVisitTS = date('c'); if ($Database->where('id', $currentUser->Session['id'])->update('sessions', array('lastvisit' => $lastVisitTS))) { $currentUser->Session['lastvisit'] = $lastVisitTS; } } $_PrefersColour = array('Pirill-Poveniy' => true, 'itv-canterlot' => true); if (isset($_PrefersColour[$currentUser->name])) { $Color = 'Colour'; $color = 'colour'; } } } } else { Cookie::delete('access', Cookie::HTTPONLY); } }
/** * Loads the episode page * * @param null|int|Episode $force If null: Parses $data and loads approperiate epaisode * If array: Uses specified arra as Episode data * @param bool $serverSideRedirect Handle redirection to the correct page on the server/client side */ static function loadPage($force = null, $serverSideRedirect = true) { global $data, $CurrentEpisode, $Database, $PrevEpisode, $NextEpisode, $LinkedPost; if ($force instanceof Episode) { $CurrentEpisode = $force; } else { $EpData = self::parseID($data); if ($EpData['season'] === 0) { error_log("Attempted visit to {$data} from " . (!empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '[unknown referrer]') . ', redirecting to /movie page'); HTTP::redirect('/movie/' . $EpData['episode']); } $CurrentEpisode = empty($EpData) ? self::getLatest() : self::getActual($EpData['season'], $EpData['episode']); } if (empty($CurrentEpisode)) { CoreUtils::notFound(); } $url = $CurrentEpisode->formatURL(); if (!empty($LinkedPost)) { $url .= '#' . $LinkedPost->getID(); } if ($serverSideRedirect) { CoreUtils::fixPath($url); } $js = array('imagesloaded.pkgd', 'jquery.ba-throttle-debounce', 'jquery.fluidbox', 'Chart', 'episode'); if (Permission::sufficient('member')) { $js[] = 'episode-manage'; } if (Permission::sufficient('staff')) { $js[] = 'moment-timezone'; $js[] = 'episodes-manage'; } if (!$CurrentEpisode->isMovie) { $PrevEpisode = $Database->where('no', $CurrentEpisode->no, '<')->where('season', 0, '!=')->orderBy('no', 'DESC')->getOne('episodes', 'season,episode,title,twoparter'); $NextEpisode = $Database->where('no', $CurrentEpisode->no, '>')->where('season', 0, '!=')->orderBy('no', 'ASC')->getOne('episodes', 'season,episode,title,twoparter'); } else { $PrevEpisode = $Database->where('season', 0)->where('episode', $CurrentEpisode->episode, '<')->orderBy('episode', 'DESC')->getOne('episodes', 'season,episode,title'); $NextEpisode = $Database->where('season', 0)->where('episode', $CurrentEpisode->episode, '>')->orderBy('episode', 'ASC')->getOne('episodes', 'season,episode,title'); } $heading = $CurrentEpisode->formatTitle(); CoreUtils::loadPage(array('title' => "{$heading} - Vector Requests & Reservations", 'heading' => $heading, 'view' => 'episode', 'css' => 'episode', 'js' => $js, 'url' => $serverSideRedirect ? null : $url)); }
$exists = 'exists on DeviantArt'; if (isset($un)) { $exists = "<a href='http://{$un}.deviantart.com/'>{$exists}</a>"; } $SubMSG = "If this user {$exists}, sign in to import their details."; } } $canEdit = $sameUser = false; } else { $sameUser = $signedIn && $User->id === $currentUser->id; $canEdit = !$sameUser && Permission::sufficient('staff') && Permission::sufficient($User->role); $pagePath = "/@{$User->name}"; CoreUtils::fixPath($pagePath); } if (isset($MSG)) { HTTP::statusCode(404); } else { if ($sameUser) { $CurrentSession = $currentUser->Session; $Database->where('id != ?', array($CurrentSession['id'])); } $Sessions = $Database->where('user', $User->id)->orderBy('lastvisit', 'DESC')->get('sessions', null, 'id,created,lastvisit,platform,browser_name,browser_ver,user_agent,scope'); } $settings = array('title' => !isset($MSG) ? ($sameUser ? 'Your' : CoreUtils::posess($User->name)) . ' ' . ($sameUser || $canEdit ? 'account' : 'profile') : 'Account', 'no-robots', 'do-css', 'js' => array('user')); if ($canEdit) { $settings['js'][] = 'user-manage'; } $showSuggestions = $User->getPendingReservationCount() < 4; if ($showSuggestions) { $settings['js'][] = 'user-suggestion'; $settings['css'][] = 'user-suggestion';
<?php use App\HTTP; /** @var $data string */ if (is_numeric($data)) { HTTP::redirect("/movie/{$data}"); } else { HTTP::redirect("/movie/equestria-girls-{$data}"); }
<?php use App\CoreUtils; use App\Episodes; use App\HTTP; use App\RegExp; if (POST_REQUEST) { HTTP::statusCode(400, AND_DIE); } /** @var $data string */ if (!preg_match(new RegExp('^(req|res)/(\\d+)$'), $data, $match)) { CoreUtils::notFound(); } $match[1] .= array('req' => 'uest', 'res' => 'ervation')[$match[1]]; /** @var $LinkedPost \App\Models\Post */ $LinkedPost = $Database->where('id', $match[2])->getOne("{$match[1]}s"); if (empty($LinkedPost)) { CoreUtils::notFound(); } $Episode = Episodes::getActual($LinkedPost->season, $LinkedPost->episode); if (empty($Episode)) { CoreUtils::notFound(); } $Episode->LinkedPost = $LinkedPost; Episodes::loadPage($Episode, false);
$errdesc = $_GET['error_description']; } global $signedIn; if ($signedIn) { HTTP::redirect($_GET['state']); } Episodes::loadPage(); } $currentUser = DeviantArt::getToken($_GET['code']); $signedIn = !empty($currentUser); if (isset($_GET['error'])) { $err = $_GET['error']; if (isset($_GET['error_description'])) { $errdesc = $_GET['error_description']; } if ($err === 'user_banned') { $errdesc .= "\n\nIf you'd like to appeal your ban, please <a href='http://mlp-vectorclub.deviantart.com/notes/'>send the group a note</a>."; } Episodes::loadPage(); } if (preg_match(new RegExp('^[a-z\\d]+$', 'i'), $_GET['state'], $_match)) { $confirm = str_replace('{{CODE}}', $_match[0], file_get_contents(INCPATH . 'views/loginConfrim.html')); $confirm = str_replace('{{USERID}}', Permission::sufficient('developer') || UserPrefs::get('p_disable_ga') ? '' : $currentUser->id, $confirm); die($confirm); } else { if (preg_match($REWRITE_REGEX, $_GET['state'])) { HTTP::redirect($_GET['state']); } } HTTP::redirect('/');
Statistics::processUsageData($RequestData, $Dataset); $Data['datasets'][] = $Dataset; } $ReservationData = $Database->rawQuery(str_replace('table_name', 'reservations', $query)); if (!empty($ReservationData)) { $Dataset = array('label' => 'Reservations', 'clrkey' => 1); Statistics::processUsageData($ReservationData, $Dataset); $Data['datasets'][] = $Dataset; } break; case 'approvals': $Labels = $Database->rawQuery("SELECT to_char(timestamp,'{$LabelFormat}') AS key\n\t\t\t\t\tFROM log\n\t\t\t\t\tWHERE timestamp > NOW() - INTERVAL '2 MONTHS' AND reftype = 'post_lock'\n\t\t\t\t\tGROUP BY key\n\t\t\t\t\tORDER BY MIN(timestamp)"); Statistics::processLabels($Labels, $Data); $Approvals = $Database->rawQuery("SELECT\n\t\t\t\t\t\tto_char(MIN(timestamp),'{$LabelFormat}') AS key,\n\t\t\t\t\t\tCOUNT(*)::INT AS cnt\n\t\t\t\t\tFROM log\n\t\t\t\t\tWHERE timestamp > NOW() - INTERVAL '2 MONTHS' AND reftype = 'post_lock'\n\t\t\t\t\tGROUP BY to_char(timestamp,'{$LabelFormat}')\n\t\t\t\t\tORDER BY MIN(timestamp)"); if (!empty($Approvals)) { $Dataset = array('label' => 'Approved posts'); Statistics::processUsageData($Approvals, $Dataset); $Data['datasets'][] = $Dataset; } break; } Statistics::postprocessTimedData($Data); CoreUtils::createUploadFolder($CachePath); file_put_contents($CachePath, JSON::encode($Data)); Response::done(array('data' => $Data)); } CoreUtils::notFound(); } HTTP::pushResource('/about/stats-posts'); HTTP::pushResource('/about/stats-approvals'); CoreUtils::loadPage(array('title' => 'About', 'do-css', 'js' => array('Chart', $do)));