function testAposEncode() { $result = CoreUtils::aposEncode("No Man's Lie"); self::assertEquals("No Man's Lie", $result); $result = CoreUtils::aposEncode('"implying"'); self::assertEquals(""implying"", $result); }
/** * Renders the "Useful links" section of the sidebar * * @param bool $wrap * * @return string */ static function getSidebarUsefulLinksListHTML($wrap = true) { global $Database; $HTML = $wrap ? '<ol>' : ''; $UsefulLinks = $Database->orderBy('"order"', 'ASC')->get('usefullinks'); foreach ($UsefulLinks as $l) { $href = "href='" . CoreUtils::aposEncode($l['url']) . "'"; if ($l['url'][0] === '#') { $href .= " class='action--" . CoreUtils::substring($l['url'], 1) . "'"; } $title = CoreUtils::aposEncode($l['title']); $label = htmlspecialchars_decode($l['label']); $cansee = Permission::ROLES_ASSOC[$l['minrole']]; if ($l['minrole'] !== 'developer') { $cansee = self::makePlural($cansee, 0) . ' and above'; } $HTML .= "<li id='ufl-{$l['id']}'><div><a {$href} title='{$title}'>{$label}</a></div>" . "<div><span class='typcn typcn-eye'></span> {$cansee}</div>" . "<div class='buttons'><button class='blue typcn typcn-pencil edit-link'>Edit</button><button class='red typcn typcn-trash delete-link'>Delete</button></div></li>"; } return $HTML . ($wrap ? '</ol>' : ''); }
private static function _link($url, $blank = false) { return "<a href='" . CoreUtils::aposEncode($url) . "'" . ($blank ? ' target="_blank"' : '') . ">{$url}</a>"; }
/** * Redirection * * @param string $url Redirection target URL * @param int $http HTTP status code */ public static function redirect($url = '/', $http = 301) { header("Location: {$url}", true, $http); $urlenc = CoreUtils::aposEncode($url); die("Click <a href='{$urlenc}'>here</a> if you aren't redirected.<script>location.replace(" . JSON::encode($url) . ")</script>"); }
/** * Get HTML for a color group * * @param int|array $GroupID * @param array|null $AllColors * @param bool $wrap * @param bool $colon * @param bool $colorNames * @param bool $force_extra_info * * @return string */ static function getHTML($GroupID, $AllColors = null, bool $wrap = true, bool $colon = true, bool $colorNames = false, bool $force_extra_info = false) : string { global $CGDb; if (is_array($GroupID)) { $Group = $GroupID; } else { $Group = $CGDb->where('groupid', $GroupID)->getOne('colorgroups'); } $label = CoreUtils::escapeHTML($Group['label']) . ($colon ? ': ' : ''); $HTML = "<span class='cat'>{$label}" . ($colorNames && Permission::sufficient('staff') ? '<span class="admin"><button class="blue typcn typcn-pencil edit-cg"></button><button class="red typcn typcn-trash delete-cg"></button></span>' : '') . "</span>"; if (!isset($AllColors)) { $Colors = self::getColors($Group['groupid']); } else { $Colors = $AllColors[$Group['groupid']] ?? null; } if (!empty($Colors)) { $extraInfo = $force_extra_info || !UserPrefs::get('cg_hideclrinfo'); foreach ($Colors as $i => $c) { $title = CoreUtils::aposEncode($c['label']); $color = ''; if (!empty($c['hex'])) { $color = $c['hex']; $title .= "' style='background-color:{$color}' class='valid-color"; } $append = "<span title='{$title}'>{$color}</span>"; if ($colorNames) { $append = "<div class='color-line" . (!$extraInfo || empty($color) ? ' no-detail' : '') . "'>{$append}<span><span class='label'>{$c['label']}"; if ($extraInfo && !empty($color)) { $rgb = CoreUtils::hex2Rgb($color); $rgb = 'rgb(' . implode(',', $rgb) . ')'; $append .= "</span><span class='ext'>{$color} • {$rgb}"; } $append .= '</span></div>'; } $HTML .= $append; } } return $wrap ? "<li id='cg{$Group['groupid']}'>{$HTML}</li>" : $HTML; }
/full">Full List of <?php echo $EQG ? 'Equestria Girls' : 'Ponies'; ?> </a> <a class='btn darkblue typcn typcn-arrow-forward' href="/blending">Blending Calculator</a> <a class='btn darkblue typcn typcn-tags' href="/cg/tags">Tags</a> <a class='btn darkblue typcn typcn-warning' href="/cg/changes">Major Changes</a> <? if (Permission::sufficient('developer')){ ?> <button class='darkblue typcn typcn-download cg-export'>Export</button> <button class='darkblue typcn typcn-document cg-reindex'>Re-index</button> <? } ?> </p> <? if ($elasticAvail){ ?> <form id="search-form"> <input name="q" <?php echo !empty($_GET['q']) ? " value='" . CoreUtils::aposEncode($_GET['q']) . "'" : ''; ?> title='Search'> <button type='submit' class='blue'>Search</button> <button type='button' class='green typcn typcn-flash sanic-button' title="I'm feeling lucky"></button> <button type='reset' class='red typcn typcn-times' title='Clear'<?php echo empty($_GET['q']) ? ' disabled' : ''; ?> ></button> </form> <? } else echo CoreUtils::notice('warn','<span class="typcn typcn-warning"></span> <strong>ElasticSearch server is down!</strong> Please <a class="send-feedback">let us know</a>, and in the meantime, use the <a class="btn darkblue typcn typcn-th-menu" href="/cg'.($EQG?'/eqg':'').'/full">Full List</a> to find appearances faster. Sorry for the inconvenience.',true); ?> <?php echo $Pagination->HTML . Appearances::getHTML($Ponies) . $Pagination->HTML; ?> </div>
} echo Appearances::getRelatedEpisodesHTML($Appearance, $EQG); if (!empty($Appearance['notes'])){ ?> <section> <h2><span class='typcn typcn-info-large'></span>Additional notes</h2> <p id="notes"><?=Appearances::getNotesHTML($Appearance, NOWRAP, NOTE_TEXT_ONLY)?></p> </section> <? } if (!empty($Appearance['cm_favme'])){ $preview = Appearances::getCMPreviewURL($Appearance); ?> <section class="approved-cutie-mark"> <h2>Recommended cutie mark vector</h2> <?=Permission::sufficient('staff')&&!isset($Appearance['cm_dir'])?CoreUtils::notice('fail','Missing CM orientation, falling back to <strong>Tail-Head</strong>. Please edit the appaearance and provide an orientation!'):''?> <a id="pony-cm" href="http://fav.me/<?=$Appearance['cm_favme']?>" style="background-image:url('<?=Appearances::getCMPreviewSVGURL($Appearance['id'])?>')"> <div class="img cm-dir-<?=$Appearance['cm_dir']===CM_DIR_HEAD_TO_TAIL?'ht':'th'?>" style="background-image:url('<?=CoreUtils::aposEncode($preview)?>')"></div> </a> <p class="aside">This is only an illustration, the body shape & colors are <strong>not</strong> guaranteed to reflect the actual design.</p> <p>The image above links to the vector made by <?php $Vector = DeviantArt::getCachedSubmission($Appearance['cm_favme']); echo Users::get($Vector['author'],'name','name, avatar_url')->getProfileLink(User::LINKFORMAT_FULL); ?> and shows which way the cutie mark should be facing.</p> </section> <? } ?> <section class="color-list"> <h2 class="admin">Color groups</h2> <div class="admin"> <button class="darkblue typcn typcn-arrow-unsorted reorder-cgs">Re-order groups</button> <button class="green typcn typcn-plus create-cg">Create group</button> </div> <? if ($placehold = Appearances::getPendingPlaceholderFor($Appearance))
/** * Parse session array for user page * * @param array $Session * @param bool $current */ static function renderSessionLi($Session, $current = false) { $browserClass = CoreUtils::browserNameToClass($Session['browser_name']); $browserTitle = !empty($Session['browser_name']) ? "{$Session['browser_name']} {$Session['browser_ver']}" : 'Unrecognized browser'; $platform = !empty($Session['platform']) ? "<span class='platform'>on <strong>{$Session['platform']}</strong></span>" : ''; $signoutText = !$current ? 'Delete' : 'Sign out'; $buttons = "<button class='typcn remove " . (!$current ? 'typcn-trash red' : 'typcn-arrow-back') . "' data-sid='{$Session['id']}'>{$signoutText}</button>"; if (Permission::sufficient('developer') && !empty($Session['user_agent'])) { $buttons .= "<br><button class='darkblue typcn typcn-eye useragent' data-agent='" . CoreUtils::aposEncode($Session['user_agent']) . "'>UA</button>" . "<a class='btn orange typcn typcn-chevron-right' href='/browser/{$Session['id']}'>Debug</a>"; } $firstuse = Time::tag($Session['created']); $lastuse = !$current ? 'Last used: ' . Time::tag($Session['lastvisit']) : '<em>Current session</em>'; echo <<<HTML <li class="browser-{$browserClass}" id="session-{$Session['id']}"> <span class="browser">{$browserTitle}</span> {$platform}{$buttons} <span class="created">Created: {$firstuse}</span> <span class="used">{$lastuse}</span> </li> HTML; }
private function _getDirectUrl($id) { switch ($this->provider) { case 'imgur': $this->fullsize = "https://i.imgur.com/{$id}.png"; $this->preview = "https://i.imgur.com/{$id}m.png"; self::_checkImageAllowed($this->fullsize); break; case 'derpibooru': $Data = @file_get_contents("http://derpibooru.org/{$id}.json"); if (empty($Data)) { throw new \Exception('The requested image could not be found on Derpibooru'); } $Data = JSON::decode($Data); if (isset($Data['duplicate_of'])) { return $this->_getDirectUrl($Data['duplicate_of']); } if (!isset($Data['is_rendered'])) { error_log("Invalid Derpibooru response for ID {$id}\n" . var_export($Data, true)); throw new \Exception('Derpibooru returned an invalid API response. This issue has been logged, please <a class="send-feedback">remind us</a> to take a look.'); } if (!$Data['is_rendered']) { throw new \Exception('The image was found but it hasn\'t been rendered yet. Please wait for it to render and try again shortly.'); } $this->fullsize = $Data['representations']['full']; $this->preview = $Data['representations']['small']; self::_checkImageAllowed($this->fullsize, $Data['mime_type']); break; case 'puush': $path = "http://puu.sh/{$id}"; $image = @file_get_contents($path); if (empty($image) || $image === 'That puush could not be found.') { throw new \Exception('The requested image could not be found on Puu.sh'); } if ($image === 'You do not have access to view that puush.') { throw new \Exception('The requested image is a private Puu.sh and the token is missing from the URL'); } self::_checkImageAllowed($path); $this->fullsize = $this->preview = $path; break; case 'dA': case 'fav.me': case 'sta.sh': if ($this->provider === 'dA') { $id = 'd' . base_convert($id, 10, 36); $this->provider = 'fav.me'; } try { $CachedDeviation = DeviantArt::getCachedSubmission($id, $this->provider); if (!DeviantArt::isImageAvailable($CachedDeviation['preview'])) { $preview = CoreUtils::aposEncode($CachedDeviation['preview']); throw new \Exception("The preview image appears to be unavailable. Please make sure <a href='{$preview}'>this link</a> works and try again, or re-submit the deviation if this persists."); } if (!DeviantArt::isImageAvailable($CachedDeviation['fullsize'])) { $fullsize = CoreUtils::aposEncode($CachedDeviation['fullsize']); throw new \Exception("The submission appears to be unavailable. Please make sure <a href='{$fullsize}'>this link</a> works and try again, or re-submit the deviation if this persists."); } } catch (CURLRequestException $e) { if ($e->getCode() === 404) { throw new \Exception('The requested image could not be found'); } throw new \Exception($e->getMessage()); } if (empty($CachedDeviation)) { throw new \Exception("{$this->provider} submission information could not be fetched for {$id}"); } $this->preview = $CachedDeviation['preview']; $this->fullsize = $CachedDeviation['fullsize']; $this->title = $CachedDeviation['title']; $this->author = $CachedDeviation['author']; self::_checkImageAllowed($this->preview); self::_checkImageAllowed($this->fullsize); break; case 'lightshot': $page = @file_get_contents("http://prntscr.com/{$id}"); if (empty($page)) { throw new \Exception('The requested page could not be found'); } if (!preg_match(new RegExp('<img\\s+class="image__pic[^"]*"\\s+src="http://i\\.imgur\\.com/([A-Za-z\\d]+)\\.'), $page, $_match)) { throw new \Exception('The requested image could not be found'); } $this->provider = 'imgur'; $this->_getDirectUrl($_match[1]); break; default: throw new \Exception("The image could not be retrieved due to a missing handler for the provider \"{$this->provider}\""); } $this->preview = URL::makeHttps($this->preview); $this->fullsize = URL::makeHttps($this->fullsize); $this->id = $id; }
?> </head> <body class="loading"> <header> <nav><ul> <li class="sidebar-toggle"> <svg class="loading-indicator" viewBox="0 0 45 45" version="1.1" xmlns="http://www.w3.org/2000/svg"> <circle r="20" cx="22.5" cy="22.5" class="loading-circle" transform="rotate(-90 22.5 22.5)"></circle> </svg> <div class="loader"></div> <img class="avatar" src="<?php echo $signedIn ? $currentUser->avatar_url : GUEST_AVATAR; ?> " alt='<?php echo ($signedIn ? CoreUtils::aposEncode(CoreUtils::posess($currentUser->name)) : 'Guest') . ' avatar'; ?> '> </li><?php echo CoreUtils::getNavigationHTML(isset($view) && $view === 'fatalerr'); ?> </ul></nav> </header> <div id="sidebar"> <?php include INCPATH . "views/sidebar.php"; ?> </div> <div id="main">
/** * Generate HTML for post action buttons * * @param Post $Post * @param bool $isRequest * @param false|string $view_only Only show the "View" button * Contains HREF attribute of button if string * * @return string */ private static function _getPostActions(Post $Post, bool $isRequest, $view_only) : string { global $signedIn, $currentUser; $By = $Post->Reserver; $requestedByUser = $isRequest && $signedIn && $Post->requested_by === $currentUser->id; $isNotReserved = empty($By); $sameUser = $signedIn && $Post->reserved_by === $currentUser->id; $CanEdit = empty($Post->lock) && Permission::sufficient('staff') || Permission::sufficient('developer') || $requestedByUser && $isNotReserved; $Buttons = array(); $HTML = self::getPostReserveButton($Post, $By, $view_only); if (!empty($Post->reserved_by)) { $finished = !empty($Post->deviation_id); $staffOrSameUser = $sameUser && Permission::sufficient('member') || Permission::sufficient('staff'); if (!$finished) { if (!$sameUser && Permission::sufficient('member') && $Post->isTransferable() && !$Post->isOverdue()) { $Buttons[] = array('user-add darkblue pls-transfer', 'Take on'); } if ($staffOrSameUser) { $Buttons[] = array('user-delete red cancel', 'Cancel Reservation'); $Buttons[] = array('attachment green finish', ($sameUser ? "I'm" : 'Mark as') . ' finished'); } } if ($finished && empty($Post->lock)) { if (Permission::sufficient('staff')) { $Buttons[] = array((empty($Post->preview) ? 'trash delete-only red' : 'media-eject orange') . ' unfinish', empty($Post->preview) ? 'Delete' : 'Unfinish'); } if ($staffOrSameUser) { $Buttons[] = array('tick green check', 'Check'); } } } if (empty($Post->lock) && empty($Buttons) && (Permission::sufficient('staff') || $requestedByUser && $isNotReserved)) { $Buttons[] = array('trash red delete', 'Delete'); } if ($CanEdit) { array_splice($Buttons, 0, 0, array(array('pencil darkblue edit', 'Edit'))); } if ($Post->lock && Permission::sufficient('staff')) { $Buttons[] = array('lock-open orange unlock', 'Unlock'); } $HTML .= "<div class='actions'>"; if (!$view_only) { $Buttons[] = array('export blue share', 'Share'); } if (!empty($Buttons)) { if ($view_only) { $HTML .= "<div><a href='{$view_only}' class='btn blue typcn typcn-arrow-forward'>View</a></div>"; } else { $regularButton = count($Buttons) < 3; foreach ($Buttons as $b) { $WriteOut = "'" . ($regularButton ? ">{$b[1]}" : " title='" . CoreUtils::aposEncode($b[1]) . "'>"); $HTML .= "<button class='typcn typcn-{$b[0]}{$WriteOut}</button>"; } } } $HTML .= '</div>'; return $HTML; }
/** * Returns the HTML for sprite images * * @param array $Appearance * * @return string */ static function getSpriteHTML($Appearance) { $imgPth = self::getSpriteURL($Appearance['id']); if (!empty($imgPth)) { $img = "<a href='{$imgPth}' target='_blank' title='Open image in new tab'><img src='{$imgPth}' alt='" . CoreUtils::aposEncode($Appearance['label']) . "'></a>"; if (Permission::sufficient('staff')) { $img = "<div class='upload-wrap'>{$img}</div>"; } } else { if (Permission::sufficient('staff')) { $img = "<div class='upload-wrap'><a><img src='/img/blank-pixel.png'></a></div>"; } else { return ''; } } return "<div class='sprite'>{$img}</div>"; }
/** * Generates the markup for the tags sub-page * * @param array $Tags * @param bool $wrap * * @return string */ static function getTagListHTML($Tags, $wrap = WRAP) { global $CGDb; $HTML = $utils = $refresh = ''; $canEdit = Permission::sufficient('staff'); if ($canEdit) { $refresh = " <button class='typcn typcn-arrow-sync refresh' title='Refresh use count'></button>"; $utils = "<td class='utils align-center'><button class='typcn typcn-minus delete' title='Delete'></button> " . "<button class='typcn typcn-flow-merge merge' title='Merge'></button> <button class='typcn typcn-flow-children synon' title='Synonymize'></button></td>"; } if (!empty($Tags)) { foreach ($Tags as $t) { $trClass = $t['type'] ? " class='typ-{$t['type']}'" : ''; $type = $t['type'] ? self::$TAG_TYPES_ASSOC[$t['type']] : ''; $search = CoreUtils::aposEncode(urlencode($t['name'])); $titleName = CoreUtils::aposEncode($t['name']); if (!empty($t['synonym_of'])) { $Syn = self::getSynonymOf($t, 'name'); $t['title'] .= (empty($t['title']) ? '' : '<br>') . "<em>Synonym of <strong>{$Syn['name']}</strong></em>"; } $HTML .= <<<HTML \t\t\t<tr {$trClass}> \t\t\t\t<td class="tid">{$t['tid']}</td> \t\t\t\t<td class="name"><a href='/cg?q={$search}' title='Search for {$titleName}'><span class="typcn typcn-zoom"></span>{$t['name']}</a></td>{$utils} \t\t\t\t<td class="title">{$t['title']}</td> \t\t\t\t<td class="type">{$type}</td> \t\t\t\t<td class="uses"><span>{$t['uses']}</span>{$refresh}</td> \t\t\t</tr> HTML; } } return $wrap ? "<tbody>{$HTML}</tbody>" : $HTML; }