mirror of
https://github.com/Neetpone/ponepaste.git
synced 2025-03-12 14:40:09 +01:00
Rejigger the CAPTCHA a bunch, more functionality without JS
This commit is contained in:
parent
0f519a8ced
commit
86afab0458
21 changed files with 312 additions and 68 deletions
|
@ -67,10 +67,7 @@ function captcha($color, $mul, $allowed) : array {
|
||||||
}
|
}
|
||||||
|
|
||||||
$captcha_config['code'] = '';
|
$captcha_config['code'] = '';
|
||||||
$length = rand($captcha_config['min_length'], $captcha_config['max_length']);
|
|
||||||
while (strlen($captcha_config['code']) < $length) {
|
|
||||||
$captcha_config['code'] .= substr($captcha_config['characters'], rand() % (strlen($captcha_config['characters'])), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $captcha_config;
|
return $captcha_config;
|
||||||
}
|
}
|
||||||
|
@ -97,3 +94,32 @@ if (!function_exists('hex2rgb')) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupCaptcha() : string {
|
||||||
|
global $captcha_config;
|
||||||
|
global $redis;
|
||||||
|
|
||||||
|
$code = '';
|
||||||
|
for ($i = 0; $i < 5; $i++) {
|
||||||
|
$code .= substr($captcha_config['allowed'], rand() % (strlen($captcha_config['allowed'])), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = pp_random_password();
|
||||||
|
|
||||||
|
$redis->setex('captcha/' . md5($token), 600, $code);
|
||||||
|
|
||||||
|
return $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCaptcha(string $token, string $answer) : bool {
|
||||||
|
global $redis;
|
||||||
|
|
||||||
|
$redis_answer = $redis->get('captcha/' . $token);
|
||||||
|
if (!$redis_answer) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$redis->del('captcha/' . $token);
|
||||||
|
|
||||||
|
return $redis_answer === $answer;
|
||||||
|
}
|
||||||
|
|
|
@ -237,3 +237,64 @@ function addToSitemap(Paste $paste, $priority, $changefreq) {
|
||||||
function paste_protocol() : string {
|
function paste_protocol() : string {
|
||||||
return !empty($_SERVER['HTTPS']) ? 'https://' : 'http://';
|
return !empty($_SERVER['HTTPS']) ? 'https://' : 'http://';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get rid of unintended wildcards in a parameter to LIKE queries; not a security issue, just unexpected behaviour. */
|
||||||
|
function escapeLikeQuery(string $query) : string {
|
||||||
|
return str_replace(['\\', '_', '%'], ['\\\\', '\\_', '\\%'], $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
function paginate(int $current_page, int $per_page, int $total_records) : string {
|
||||||
|
$first_page = 0;
|
||||||
|
$last_page = floor($total_records / $per_page);
|
||||||
|
$window = 2;
|
||||||
|
|
||||||
|
if ($first_page == $last_page) {
|
||||||
|
// Do something?
|
||||||
|
}
|
||||||
|
|
||||||
|
$_page_button = function(int $page, string $text, bool $disabled = false) use ($current_page) : string {
|
||||||
|
/* We need to update the 'page' parameter in the request URI, or add it if it doesn't exist. */
|
||||||
|
$request_uri = parse_url($_SERVER['REQUEST_URI']);
|
||||||
|
parse_str((string) @$request_uri['query'], $parsed_query);
|
||||||
|
$parsed_query['page'] = (string) $page;
|
||||||
|
$page_uri = ((string) @$request_uri['path']) . '?' . http_build_query($parsed_query);
|
||||||
|
|
||||||
|
$selected_class = $current_page == $page ? ' paginator__button--selected' : '';
|
||||||
|
|
||||||
|
$disabled_text = $disabled ? ' aria-disabled="true"' : '';
|
||||||
|
return sprintf("<a type=\"button\" class=\"paginator__button$selected_class\" href=\"%s\"%s>%s</a>", $page_uri, $disabled_text, $text);
|
||||||
|
};
|
||||||
|
|
||||||
|
$html = '';
|
||||||
|
|
||||||
|
/* First and last page the main paginator will show */
|
||||||
|
$first_page_show = max(($current_page - $window), $first_page);
|
||||||
|
$last_page_show = min(($current_page + $window), $last_page);
|
||||||
|
|
||||||
|
/* Whether to show the first and last pages in existence at the ends of the paginator */
|
||||||
|
$show_first_page = (abs($first_page - $current_page)) > ($window);
|
||||||
|
$show_last_page = (abs($last_page - $current_page)) > ($window);
|
||||||
|
|
||||||
|
$prev_button_disabled = $current_page == $first_page ? 'disabled' : '';
|
||||||
|
$next_button_disabled = $current_page == $last_page ? 'disabled' : '';
|
||||||
|
|
||||||
|
$html .= $_page_button($current_page - 1, 'Previous', $prev_button_disabled);
|
||||||
|
|
||||||
|
if ($show_first_page) {
|
||||||
|
$html .= $_page_button($first_page, $first_page);
|
||||||
|
$html .= '<span class="ellipsis">…</span>';
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($i = $first_page_show; $i <= $last_page_show; $i++) {
|
||||||
|
$html .= $_page_button($i, $i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($show_last_page) {
|
||||||
|
$html .= '<span class="ellipsis">…</span>';
|
||||||
|
$html .= $_page_button($last_page, $last_page);
|
||||||
|
}
|
||||||
|
|
||||||
|
$html .= $_page_button($current_page + 1, 'Next', $next_button_disabled);
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
19
js/main.js
19
js/main.js
|
@ -5,6 +5,8 @@ const setupSignupModal = () => {
|
||||||
const signupButton = $('[data-target~="#signin"],[data-target~="#signup"]');
|
const signupButton = $('[data-target~="#signin"],[data-target~="#signup"]');
|
||||||
|
|
||||||
if (signupButton) {
|
if (signupButton) {
|
||||||
|
signupButton.href = 'javascript:void(0)';
|
||||||
|
|
||||||
signupButton.addEventListener('click', () => {
|
signupButton.addEventListener('click', () => {
|
||||||
$('.modal').classList.add('is-active');
|
$('.modal').classList.add('is-active');
|
||||||
});
|
});
|
||||||
|
@ -77,6 +79,23 @@ const globalSetup = () => {
|
||||||
preloader.remove();
|
preloader.remove();
|
||||||
main.id = '';
|
main.id = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const captchaContainer = $('.captcha_container');
|
||||||
|
|
||||||
|
if (captchaContainer) {
|
||||||
|
const refreshElement = captchaContainer.querySelector('a');
|
||||||
|
const imageElement = captchaContainer.querySelector('img');
|
||||||
|
|
||||||
|
if (refreshElement && imageElement) {
|
||||||
|
refreshElement.addEventListener('click', () => {
|
||||||
|
imageElement.src = imageElement.src.split('?')[0] + '?rand=' + Math.random();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Array.prototype.forEach.call($('.js-hidden'), (elem) => {
|
||||||
|
toggleEl(elem);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export { globalSetup };
|
export { globalSetup };
|
|
@ -4,11 +4,6 @@ require_once(__DIR__ . '/../includes/common.php');
|
||||||
|
|
||||||
use PonePaste\Models\Tag;
|
use PonePaste\Models\Tag;
|
||||||
|
|
||||||
/* get rid of unintended wildcards in a parameter to LIKE queries; not a security issue, just unexpected behaviour. */
|
|
||||||
function escapeLikeQuery(string $query) : string {
|
|
||||||
return str_replace(['\\', '_', '%'], ['\\\\', '\\_', '\\%'], $query);
|
|
||||||
}
|
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
if (empty($_GET['tag'])) {
|
if (empty($_GET['tag'])) {
|
||||||
|
@ -23,6 +18,8 @@ $results = Tag::select('name')
|
||||||
->fetchAll()
|
->fetchAll()
|
||||||
->toArray();
|
->toArray();
|
||||||
|
|
||||||
|
/* we want to ensure the tag name that the user input is always returned,
|
||||||
|
* even if that tag doesn't actually exist yet. */
|
||||||
$tags[] = ['name' => $tag_name];
|
$tags[] = ['name' => $tag_name];
|
||||||
|
|
||||||
echo json_encode($tags);
|
echo json_encode($tags);
|
||||||
|
|
|
@ -5,6 +5,43 @@ require_once(__DIR__ . '/../includes/common.php');
|
||||||
|
|
||||||
use PonePaste\Models\Paste;
|
use PonePaste\Models\Paste;
|
||||||
|
|
||||||
|
$per_page = 20;
|
||||||
|
$current_page = 0;
|
||||||
|
$filter_value = '';
|
||||||
|
|
||||||
|
if (!empty($_GET['page'])) {
|
||||||
|
$current_page = max(0, intval($_GET['page']));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($_GET['per_page'])) {
|
||||||
|
$per_page = max(1, min(100, intval($_GET['per_page'])));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($_GET['q'])) {
|
||||||
|
$filter_value = $_GET['q'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$pastes = Paste::with([
|
||||||
|
'user' => function($q) {
|
||||||
|
$q->select('users.id', 'username');
|
||||||
|
},
|
||||||
|
'tags' => function($q) {
|
||||||
|
$q->select('tags.id', 'name', 'slug');
|
||||||
|
}])
|
||||||
|
->select('id', 'user_id', 'title', 'created_at')
|
||||||
|
->where('visible', Paste::VISIBILITY_PUBLIC)
|
||||||
|
->whereRaw("((expiry IS NULL) OR ((expiry != 'SELF') AND (expiry > NOW())))");
|
||||||
|
|
||||||
|
|
||||||
|
if (!empty($filter_value)) {
|
||||||
|
$pastes = $pastes->where('title', 'LIKE', '%' . escapeLikeQuery($filter_value) . '%');
|
||||||
|
}
|
||||||
|
|
||||||
|
$total_results = $pastes->count();
|
||||||
|
|
||||||
|
$pastes = $pastes->limit($per_page)->offset($per_page * $current_page);
|
||||||
|
|
||||||
|
$pastes = $pastes->get();
|
||||||
|
|
||||||
// Temp count for untagged pastes
|
// Temp count for untagged pastes
|
||||||
$total_untagged = Paste::doesntHave('tags')->count();
|
$total_untagged = Paste::doesntHave('tags')->count();
|
||||||
|
|
|
@ -413,6 +413,8 @@ const setupSignupModal = () => {
|
||||||
const signupButton = $('[data-target~="#signin"],[data-target~="#signup"]');
|
const signupButton = $('[data-target~="#signin"],[data-target~="#signup"]');
|
||||||
|
|
||||||
if (signupButton) {
|
if (signupButton) {
|
||||||
|
signupButton.href = 'javascript:void(0)';
|
||||||
|
|
||||||
signupButton.addEventListener('click', () => {
|
signupButton.addEventListener('click', () => {
|
||||||
$('.modal').classList.add('is-active');
|
$('.modal').classList.add('is-active');
|
||||||
});
|
});
|
||||||
|
@ -485,6 +487,23 @@ const globalSetup = () => {
|
||||||
preloader.remove();
|
preloader.remove();
|
||||||
main.id = '';
|
main.id = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const captchaContainer = $('.captcha_container');
|
||||||
|
|
||||||
|
if (captchaContainer) {
|
||||||
|
const refreshElement = captchaContainer.querySelector('a');
|
||||||
|
const imageElement = captchaContainer.querySelector('img');
|
||||||
|
|
||||||
|
if (refreshElement && imageElement) {
|
||||||
|
refreshElement.addEventListener('click', () => {
|
||||||
|
imageElement.src = imageElement.src.split('?')[0] + '?rand=' + Math.random();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Array.prototype.forEach.call($('.js-hidden'), (elem) => {
|
||||||
|
toggleEl(elem);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
whenReady(() => {
|
whenReady(() => {
|
||||||
|
|
2
public/assets/bundle/archive.min.js
vendored
2
public/assets/bundle/archive.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -144,6 +144,8 @@ const setupSignupModal = () => {
|
||||||
const signupButton = $('[data-target~="#signin"],[data-target~="#signup"]');
|
const signupButton = $('[data-target~="#signin"],[data-target~="#signup"]');
|
||||||
|
|
||||||
if (signupButton) {
|
if (signupButton) {
|
||||||
|
signupButton.href = 'javascript:void(0)';
|
||||||
|
|
||||||
signupButton.addEventListener('click', () => {
|
signupButton.addEventListener('click', () => {
|
||||||
$('.modal').classList.add('is-active');
|
$('.modal').classList.add('is-active');
|
||||||
});
|
});
|
||||||
|
@ -216,6 +218,23 @@ const globalSetup = () => {
|
||||||
preloader.remove();
|
preloader.remove();
|
||||||
main.id = '';
|
main.id = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const captchaContainer = $('.captcha_container');
|
||||||
|
|
||||||
|
if (captchaContainer) {
|
||||||
|
const refreshElement = captchaContainer.querySelector('a');
|
||||||
|
const imageElement = captchaContainer.querySelector('img');
|
||||||
|
|
||||||
|
if (refreshElement && imageElement) {
|
||||||
|
refreshElement.addEventListener('click', () => {
|
||||||
|
imageElement.src = imageElement.src.split('?')[0] + '?rand=' + Math.random();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Array.prototype.forEach.call($('.js-hidden'), (elem) => {
|
||||||
|
toggleEl(elem);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
whenReady(globalSetup);
|
whenReady(globalSetup);
|
||||||
|
|
2
public/assets/bundle/generic.min.js
vendored
2
public/assets/bundle/generic.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -413,6 +413,8 @@ const setupSignupModal = () => {
|
||||||
const signupButton = $('[data-target~="#signin"],[data-target~="#signup"]');
|
const signupButton = $('[data-target~="#signin"],[data-target~="#signup"]');
|
||||||
|
|
||||||
if (signupButton) {
|
if (signupButton) {
|
||||||
|
signupButton.href = 'javascript:void(0)';
|
||||||
|
|
||||||
signupButton.addEventListener('click', () => {
|
signupButton.addEventListener('click', () => {
|
||||||
$('.modal').classList.add('is-active');
|
$('.modal').classList.add('is-active');
|
||||||
});
|
});
|
||||||
|
@ -485,6 +487,23 @@ const globalSetup = () => {
|
||||||
preloader.remove();
|
preloader.remove();
|
||||||
main.id = '';
|
main.id = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const captchaContainer = $('.captcha_container');
|
||||||
|
|
||||||
|
if (captchaContainer) {
|
||||||
|
const refreshElement = captchaContainer.querySelector('a');
|
||||||
|
const imageElement = captchaContainer.querySelector('img');
|
||||||
|
|
||||||
|
if (refreshElement && imageElement) {
|
||||||
|
refreshElement.addEventListener('click', () => {
|
||||||
|
imageElement.src = imageElement.src.split('?')[0] + '?rand=' + Math.random();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Array.prototype.forEach.call($('.js-hidden'), (elem) => {
|
||||||
|
toggleEl(elem);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getUserInfo = () => {
|
const getUserInfo = () => {
|
||||||
|
|
2
public/assets/bundle/user_profile.min.js
vendored
2
public/assets/bundle/user_profile.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -4,6 +4,17 @@ define('IN_PONEPASTE', 1);
|
||||||
require_once(__DIR__ . '/../includes/common.php');
|
require_once(__DIR__ . '/../includes/common.php');
|
||||||
require_once(__DIR__ . '/../includes/captcha.php');
|
require_once(__DIR__ . '/../includes/captcha.php');
|
||||||
|
|
||||||
|
if (empty($_GET['t'])) {
|
||||||
|
die('No token provided.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$captcha_token = 'captcha/' . md5($_GET['t']);
|
||||||
|
$captcha_code = $redis->get($captcha_token);
|
||||||
|
|
||||||
|
if (!$captcha_code) {
|
||||||
|
die('No token provided.');
|
||||||
|
}
|
||||||
|
|
||||||
$captcha_config = captcha($captcha_config['colour'], $captcha_config['multiple'], $captcha_config['allowed']);
|
$captcha_config = captcha($captcha_config['colour'], $captcha_config['multiple'], $captcha_config['allowed']);
|
||||||
|
|
||||||
// Pick random background, get info, and start captcha
|
// Pick random background, get info, and start captcha
|
||||||
|
@ -28,7 +39,7 @@ if (!file_exists($font)) {
|
||||||
|
|
||||||
// Set the font size
|
// Set the font size
|
||||||
$font_size = rand($captcha_config['min_font_size'], $captcha_config['max_font_size']);
|
$font_size = rand($captcha_config['min_font_size'], $captcha_config['max_font_size']);
|
||||||
$text_box_size = imagettfbbox($font_size, $angle, $font, $captcha_config['code']);
|
$text_box_size = imagettfbbox($font_size, $angle, $font, $captcha_code);
|
||||||
|
|
||||||
// Determine text position
|
// Determine text position
|
||||||
$box_width = (int) abs($text_box_size[6] - $text_box_size[2]);
|
$box_width = (int) abs($text_box_size[6] - $text_box_size[2]);
|
||||||
|
@ -44,11 +55,11 @@ $text_pos_y = rand($text_pos_y_min, $text_pos_y_max);
|
||||||
if ($captcha_config['shadow']) {
|
if ($captcha_config['shadow']) {
|
||||||
$shadow_color = hex2rgb($captcha_config['shadow_color']);
|
$shadow_color = hex2rgb($captcha_config['shadow_color']);
|
||||||
$shadow_color = imagecolorallocate($captcha, $shadow_color['r'], $shadow_color['g'], $shadow_color['b']);
|
$shadow_color = imagecolorallocate($captcha, $shadow_color['r'], $shadow_color['g'], $shadow_color['b']);
|
||||||
imagettftext($captcha, $font_size, $angle, $text_pos_x + $captcha_config['shadow_offset_x'], $text_pos_y + $captcha_config['shadow_offset_y'], $shadow_color, $font, $captcha_config['code']);
|
imagettftext($captcha, $font_size, $angle, $text_pos_x + $captcha_config['shadow_offset_x'], $text_pos_y + $captcha_config['shadow_offset_y'], $shadow_color, $font, $captcha_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw text
|
// Draw text
|
||||||
imagettftext($captcha, $font_size, $angle, $text_pos_x, $text_pos_y, $color, $font, $captcha_config['code']);
|
imagettftext($captcha, $font_size, $angle, $text_pos_x, $text_pos_y, $color, $font, $captcha_code);
|
||||||
|
|
||||||
// Output image
|
// Output image
|
||||||
header("Content-type: image/png");
|
header("Content-type: image/png");
|
||||||
|
|
|
@ -14,9 +14,8 @@ function verifyCaptcha() : string|bool {
|
||||||
global $current_user;
|
global $current_user;
|
||||||
|
|
||||||
if ($captcha_config['enabled'] && !$current_user) {
|
if ($captcha_config['enabled'] && !$current_user) {
|
||||||
$scode = strtolower(trim($_POST['scode']));
|
if (empty($_POST['captcha_answer']) ||
|
||||||
$cap_code = strtolower($_SESSION['captcha']['code']);
|
!checkCaptcha($_POST['captcha_token'], strtolower(trim($_POST['captcha_answer'])))) {
|
||||||
if ($cap_code !== $scode) {
|
|
||||||
return 'Wrong CAPTCHA.';
|
return 'Wrong CAPTCHA.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,6 +202,13 @@ button.button--no-style {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.paginator__button[aria-disabled="true"] {
|
||||||
|
display: inline-block;
|
||||||
|
pointer-events: none;
|
||||||
|
cursor: none;
|
||||||
|
color: #33333388;
|
||||||
|
}
|
||||||
|
|
||||||
.table_filterer {
|
.table_filterer {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: #3298dc;
|
background: #3298dc;
|
||||||
|
@ -219,8 +226,9 @@ button.button--no-style {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 1px solid #bdc4c9;
|
border: 1px solid #bdc4c9;
|
||||||
width: 80%;
|
width: 75%;
|
||||||
box-shadow: inset 0 1px 0 #f1f0f1;
|
box-shadow: inset 0 1px 0 #f1f0f1;
|
||||||
|
flex-grow: 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rules h2 {
|
.rules h2 {
|
||||||
|
@ -233,3 +241,18 @@ button.button--no-style {
|
||||||
margin-right: 0.5rem;
|
margin-right: 0.5rem;
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.captcha_container {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 4px;
|
||||||
|
position: relative;
|
||||||
|
padding: 1.25rem 2.5rem 1.25rem 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.captcha_container img {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.captcha_container i {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
|
@ -65,10 +65,11 @@
|
||||||
<h1 class="title is-5">This pastebin is private.</h1>
|
<h1 class="title is-5">This pastebin is private.</h1>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<h1 class="title is-4">Pastes Archive</h1>
|
<h1 class="title is-4">Pastes Archive</h1>
|
||||||
<div class="table_filterer">
|
<form class="table_filterer" method="GET">
|
||||||
<label><i class="fa fa-search"></i>
|
<label><i class="fa fa-search"></i>
|
||||||
<input class="search" type="search" name="search" placeholder="Filter..."/>
|
<input class="search" type="search" name="q" placeholder="Filter..." value="<?= $filter_value; ?>" />
|
||||||
</label>
|
</label>
|
||||||
|
<label>
|
||||||
Show
|
Show
|
||||||
<select name="per_page">
|
<select name="per_page">
|
||||||
<option value="10">10</option>
|
<option value="10">10</option>
|
||||||
|
@ -77,8 +78,10 @@
|
||||||
<option value="100">100</option>
|
<option value="100">100</option>
|
||||||
</select>
|
</select>
|
||||||
per page
|
per page
|
||||||
</div>
|
</label>
|
||||||
<table id="archive" class="table is-fullwidth is-hoverable hidden">
|
<button type="submit" class="button js-hidden">Search</button>
|
||||||
|
</form>
|
||||||
|
<table id="archive" class="table is-fullwidth is-hoverable">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="paginator__sort">
|
<tr class="paginator__sort">
|
||||||
<th data-sort-field="title">Title</th>
|
<th data-sort-field="title">Title</th>
|
||||||
|
@ -87,7 +90,13 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<!-- Filled by DataTables -->
|
<?php foreach ($pastes as $paste): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?= pp_html_escape($paste->title) ?></td>
|
||||||
|
<td><?= pp_html_escape($paste->user->username) ?></td>
|
||||||
|
<td><?= tagsToHtml($paste->tags) ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -97,10 +106,12 @@
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
<div class="loading_container">
|
<div class="loading_container is-hidden">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="paginator"></div>
|
<div class="paginator">
|
||||||
|
<?= paginate($current_page, $per_page, $total_results) ?>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -116,7 +116,7 @@ $flashes = getFlashes();
|
||||||
<span>Events</span>
|
<span>Events</span>
|
||||||
</a>
|
</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<a class="button is-info modal-button" data-target="#signin">Sign In</a>
|
<a class="button is-info modal-button" data-target="#signin" href="/login?login">Sign In / Up</a>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
@ -210,12 +210,15 @@ $flashes = getFlashes();
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="notification">
|
<div class="captcha_container">
|
||||||
<span class="tags are-large"><img src="<?= $_SESSION['captcha']['image_src'] ?>" alt="CAPTCHA" class="imagever" /></span>
|
<img src="/captcha?t=<?= setupCaptcha() ?>" alt="CAPTCHA Image" />
|
||||||
<input type="text" class="input" name="scode" value=""
|
<span id="captcha_refresh" style="height: 100%;">
|
||||||
placeholder="Enter the CAPTCHA">
|
<a href="javascript:void(0)">
|
||||||
<p class="is-size-6 has-text-grey-light has-text-left mt-2">and press
|
<i class="fa fa-refresh" style="height: 100%;"></i>
|
||||||
"Enter"</p>
|
</a>
|
||||||
|
</span>
|
||||||
|
<input type="text" class="input" name="scode" placeholder="Enter the CAPTCHA" />
|
||||||
|
<p class="is-size-6 has-text-grey-light has-text-left mt-2">and press "Enter"</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -316,7 +319,7 @@ $flashes = getFlashes();
|
||||||
</script>
|
</script>
|
||||||
<script nonce="D4rkm0d3">
|
<script nonce="D4rkm0d3">
|
||||||
const toggleSwitch = document.querySelector('.theme-switch input[type="checkbox"]');
|
const toggleSwitch = document.querySelector('.theme-switch input[type="checkbox"]');
|
||||||
const currentTheme = localStorage.getItem('theme');
|
const currentTheme = localStorage.getItem('theme') || "<?= @$_COOKIE['theme'] ?>";
|
||||||
|
|
||||||
if (currentTheme) {
|
if (currentTheme) {
|
||||||
document.documentElement.setAttribute('data-theme', currentTheme);
|
document.documentElement.setAttribute('data-theme', currentTheme);
|
||||||
|
@ -338,7 +341,5 @@ $flashes = getFlashes();
|
||||||
|
|
||||||
toggleSwitch.addEventListener('change', switchTheme, false);
|
toggleSwitch.addEventListener('change', switchTheme, false);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -161,7 +161,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<?php } else { ?>
|
<?php } ?>
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h1 class="title is-4">Where to?</h1>
|
<h1 class="title is-4">Where to?</h1>
|
||||||
|
@ -174,7 +174,6 @@
|
||||||
<div class="column">
|
<div class="column">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php } ?>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -295,12 +295,15 @@
|
||||||
<!-- CAPTCHA -->
|
<!-- CAPTCHA -->
|
||||||
<?php if ($captcha_config['enabled'] && $current_user === null): ?>
|
<?php if ($captcha_config['enabled'] && $current_user === null): ?>
|
||||||
<div class="is-one-quarter">
|
<div class="is-one-quarter">
|
||||||
<div class="notification">
|
<div class="captcha_container">
|
||||||
<span class="tags are-large"><img src="<?= $_SESSION['captcha']['image_src'] ?>" alt="CAPTCHA" class="imagever" /></span>
|
<img src="/captcha?t=<?= setupCaptcha() ?>" alt="CAPTCHA Image" />
|
||||||
<input type="text" class="input" name="scode" value=""
|
<span id="captcha_refresh" style="height: 100%;">
|
||||||
placeholder="Enter the CAPTCHA" />
|
<a href="javascript:void(0)">
|
||||||
<p class="is-size-6 has-text-grey-light has-text-left mt-2">and press
|
<i class="fa fa-refresh" style="height: 100%;"></i>
|
||||||
"Enter"</p>
|
</a>
|
||||||
|
</span>
|
||||||
|
<input type="text" class="input" name="scode" placeholder="Enter the CAPTCHA" />
|
||||||
|
<p class="is-size-6 has-text-grey-light has-text-left mt-2">and press "Enter"</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
Loading…
Add table
Reference in a new issue