mirror of
https://github.com/vichan-devel/vichan.git
synced 2024-11-25 07:50:23 +01:00
This commit is contained in:
commit
e074d5ebae
@ -317,6 +317,9 @@ FLAGS;
|
|||||||
$code_tags = isset($_POST['code_tags']) ? '$config[\'additional_javascript\'][] = \'js/code_tags/run_prettify.js\';$config[\'markup\'][] = array("/\[code\](.+?)\[\/code\]/ms", "<code><pre class=\'prettyprint\' style=\'display:inline-block\'>\$1</pre></code>");' : '';
|
$code_tags = isset($_POST['code_tags']) ? '$config[\'additional_javascript\'][] = \'js/code_tags/run_prettify.js\';$config[\'markup\'][] = array("/\[code\](.+?)\[\/code\]/ms", "<code><pre class=\'prettyprint\' style=\'display:inline-block\'>\$1</pre></code>");' : '';
|
||||||
$katex = isset($_POST['katex']) ? '$config[\'katex\'] = true;$config[\'additional_javascript\'][] = \'js/katex/katex.min.js\'; $config[\'markup\'][] = array("/\[tex\](.+?)\[\/tex\]/ms", "<span class=\'tex\'>\$1</span>"); $config[\'additional_javascript\'][] = \'js/katex-enable.js\';' : '';
|
$katex = isset($_POST['katex']) ? '$config[\'katex\'] = true;$config[\'additional_javascript\'][] = \'js/katex/katex.min.js\'; $config[\'markup\'][] = array("/\[tex\](.+?)\[\/tex\]/ms", "<span class=\'tex\'>\$1</span>"); $config[\'additional_javascript\'][] = \'js/katex-enable.js\';' : '';
|
||||||
$user_flags = isset($_POST['user_flags']) ? "if (file_exists('$b/flags.php')) { include 'flags.php'; }\n" : '';
|
$user_flags = isset($_POST['user_flags']) ? "if (file_exists('$b/flags.php')) { include 'flags.php'; }\n" : '';
|
||||||
|
$captcha = isset($_POST['captcha']) ? 'true' : 'false';
|
||||||
|
$captcha_charset = base64_encode(isset($_POST['captcha_charset']) && $_POST['captcha_charset'] ? $_POST['captcha_charset'] : 'abcdefghijklmnopqrstuvwxyz');
|
||||||
|
|
||||||
|
|
||||||
$oekaki_js = <<<OEKAKI
|
$oekaki_js = <<<OEKAKI
|
||||||
\$config['additional_javascript'][] = 'js/jquery-ui.custom.min.js';
|
\$config['additional_javascript'][] = 'js/jquery-ui.custom.min.js';
|
||||||
@ -392,6 +395,8 @@ OEKAKI;
|
|||||||
\$config['blotter'] = base64_decode('$blotter');
|
\$config['blotter'] = base64_decode('$blotter');
|
||||||
\$config['stylesheets']['Custom'] = 'board/$b.css';
|
\$config['stylesheets']['Custom'] = 'board/$b.css';
|
||||||
\$config['default_stylesheet'] = array('Custom', \$config['stylesheets']['Custom']);
|
\$config['default_stylesheet'] = array('Custom', \$config['stylesheets']['Custom']);
|
||||||
|
\$config['captcha']['enabled'] = $captcha;
|
||||||
|
\$config['captcha']['extra'] = base64_decode('$captcha_charset');
|
||||||
$code_tags $katex $oekaki $replace $multiimage $allow_flash $allow_pdf $user_flags
|
$code_tags $katex $oekaki $replace $multiimage $allow_flash $allow_pdf $user_flags
|
||||||
if (\$config['disable_images'])
|
if (\$config['disable_images'])
|
||||||
\$config['max_pages'] = 10000;
|
\$config['max_pages'] = 10000;
|
||||||
@ -412,7 +417,11 @@ EOT;
|
|||||||
openBoard($b);
|
openBoard($b);
|
||||||
|
|
||||||
// be smarter about rebuilds...only some changes really require us to rebuild all threads
|
// be smarter about rebuilds...only some changes really require us to rebuild all threads
|
||||||
if ($_config['blotter'] != $config['blotter'] || $_config['field_disable_name'] != $config['field_disable_name'] || $_config['show_sages'] != $config['show_sages']) {
|
if ($_config['captcha']['enabled'] != $config['captcha']['enabled']
|
||||||
|
|| $_config['captcha']['extra'] != $config['captcha']['extra']
|
||||||
|
|| $_config['blotter'] != $config['blotter']
|
||||||
|
|| $_config['field_disable_name'] != $config['field_disable_name']
|
||||||
|
|| $_config['show_sages'] != $config['show_sages']) {
|
||||||
buildIndex();
|
buildIndex();
|
||||||
$query = query(sprintf("SELECT `id` FROM ``posts_%s`` WHERE `thread` IS NULL", $b)) or error(db_error());
|
$query = query(sprintf("SELECT `id` FROM ``posts_%s`` WHERE `thread` IS NULL", $b)) or error(db_error());
|
||||||
while ($post = $query->fetch(PDO::FETCH_ASSOC)) {
|
while ($post = $query->fetch(PDO::FETCH_ASSOC)) {
|
||||||
|
@ -272,6 +272,8 @@
|
|||||||
'embed',
|
'embed',
|
||||||
'recaptcha_challenge_field',
|
'recaptcha_challenge_field',
|
||||||
'recaptcha_response_field',
|
'recaptcha_response_field',
|
||||||
|
'captcha_cookie',
|
||||||
|
'captcha_text',
|
||||||
'spoiler',
|
'spoiler',
|
||||||
'page',
|
'page',
|
||||||
'file_url',
|
'file_url',
|
||||||
@ -300,6 +302,19 @@
|
|||||||
$config['recaptcha_public'] = '6LcXTcUSAAAAAKBxyFWIt2SO8jwx4W7wcSMRoN3f';
|
$config['recaptcha_public'] = '6LcXTcUSAAAAAKBxyFWIt2SO8jwx4W7wcSMRoN3f';
|
||||||
$config['recaptcha_private'] = '6LcXTcUSAAAAAOGVbVdhmEM1_SyRF4xTKe8jbzf_';
|
$config['recaptcha_private'] = '6LcXTcUSAAAAAOGVbVdhmEM1_SyRF4xTKe8jbzf_';
|
||||||
|
|
||||||
|
$config['captcha'] = array();
|
||||||
|
|
||||||
|
// Enable custom captcha provider
|
||||||
|
$config['captcha']['enabled'] = false;
|
||||||
|
|
||||||
|
// Custom captcha provider path
|
||||||
|
$config['captcha']['provider_get'] = 'http://8chan.vichan.net/captcha/entrypoint.php';
|
||||||
|
$config['captcha']['provider_check'] = 'http://8chan.vichan.net/captcha/entrypoint.php';
|
||||||
|
|
||||||
|
// Custom captcha extra field (eg. charset)
|
||||||
|
$config['captcha']['extra'] = 'abcdefghijklmnopqrstuvwxyz';
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Custom filters detect certain posts and reject/ban accordingly. They are made up of a condition and an
|
* Custom filters detect certain posts and reject/ban accordingly. They are made up of a condition and an
|
||||||
* action (for when ALL conditions are met). As every single post has to be put through each filter,
|
* action (for when ALL conditions are met). As every single post has to be put through each filter,
|
||||||
@ -602,6 +617,17 @@
|
|||||||
|
|
||||||
// How many ban appeals can be made for a single ban?
|
// How many ban appeals can be made for a single ban?
|
||||||
$config['ban_appeals_max'] = 1;
|
$config['ban_appeals_max'] = 1;
|
||||||
|
|
||||||
|
// Blacklisted board names. Default values to protect existing folders in the core codebase.
|
||||||
|
$config['banned_boards'] = array(
|
||||||
|
'.git',
|
||||||
|
'inc',
|
||||||
|
'js',
|
||||||
|
'static',
|
||||||
|
'stylesheets',
|
||||||
|
'templates',
|
||||||
|
'tools'
|
||||||
|
);
|
||||||
|
|
||||||
// Show moderator name on ban page.
|
// Show moderator name on ban page.
|
||||||
$config['show_modname'] = false;
|
$config['show_modname'] = false;
|
||||||
@ -1326,8 +1352,8 @@
|
|||||||
// Capcode permissions.
|
// Capcode permissions.
|
||||||
$config['mod']['capcode'] = array(
|
$config['mod']['capcode'] = array(
|
||||||
// JANITOR => array('Janitor'),
|
// JANITOR => array('Janitor'),
|
||||||
MOD => array('Mod'),
|
MOD => array('Mod'),
|
||||||
ADMIN => true
|
ADMIN => true
|
||||||
);
|
);
|
||||||
|
|
||||||
// Example: Allow mods to post with "## Moderator" as well
|
// Example: Allow mods to post with "## Moderator" as well
|
||||||
@ -1410,7 +1436,7 @@
|
|||||||
$config['mod']['view_banlist'] = MOD;
|
$config['mod']['view_banlist'] = MOD;
|
||||||
// View the username of the mod who made a ban
|
// View the username of the mod who made a ban
|
||||||
$config['mod']['view_banstaff'] = MOD;
|
$config['mod']['view_banstaff'] = MOD;
|
||||||
// If the moderator doesn't fit the $config['mod']['view_banstaff''] (previous) permission, show him just
|
// If the moderator doesn't fit the $config['mod']['view_banstaff'] (previous) permission, show him just
|
||||||
// a "?" instead. Otherwise, it will be "Mod" or "Admin".
|
// a "?" instead. Otherwise, it will be "Mod" or "Admin".
|
||||||
$config['mod']['view_banquestionmark'] = false;
|
$config['mod']['view_banquestionmark'] = false;
|
||||||
// Show expired bans in the ban list (they are kept in cache until the culprit returns)
|
// Show expired bans in the ban list (they are kept in cache until the culprit returns)
|
||||||
|
@ -91,6 +91,7 @@
|
|||||||
$config['additional_javascript'][] = 'js/jquery.min.js';
|
$config['additional_javascript'][] = 'js/jquery.min.js';
|
||||||
$config['additional_javascript'][] = 'js/jquery.mixitup.min.js';
|
$config['additional_javascript'][] = 'js/jquery.mixitup.min.js';
|
||||||
$config['additional_javascript'][] = 'js/catalog.js';
|
$config['additional_javascript'][] = 'js/catalog.js';
|
||||||
|
$config['additional_javascript'][] = 'js/captcha.js';
|
||||||
$config['additional_javascript'][] = 'js/jquery.tablesorter.min.js';
|
$config['additional_javascript'][] = 'js/jquery.tablesorter.min.js';
|
||||||
$config['additional_javascript'][] = 'js/options.js';
|
$config['additional_javascript'][] = 'js/options.js';
|
||||||
$config['additional_javascript'][] = 'js/style-select.js';
|
$config['additional_javascript'][] = 'js/style-select.js';
|
||||||
|
@ -495,7 +495,15 @@ function mod_new_board() {
|
|||||||
if (openBoard($_POST['uri'])) {
|
if (openBoard($_POST['uri'])) {
|
||||||
error(sprintf($config['error']['boardexists'], $board['url']));
|
error(sprintf($config['error']['boardexists'], $board['url']));
|
||||||
}
|
}
|
||||||
|
foreach ($config['banned_boards'] as $i => $w) {
|
||||||
|
if ($w[0] !== '/') {
|
||||||
|
if (strpos($_POST['uri'],$w) !== false)
|
||||||
|
error(_("Cannot create board with banned word $w"));
|
||||||
|
} else {
|
||||||
|
if (preg_match($w,$_POST['uri']))
|
||||||
|
error(_("Cannot create board matching banned pattern $w"));
|
||||||
|
}
|
||||||
|
}
|
||||||
$query = prepare('INSERT INTO ``boards`` (``uri``, ``title``, ``subtitle``) VALUES (:uri, :title, :subtitle)');
|
$query = prepare('INSERT INTO ``boards`` (``uri``, ``title``, ``subtitle``) VALUES (:uri, :title, :subtitle)');
|
||||||
$query->bindValue(':uri', $_POST['uri']);
|
$query->bindValue(':uri', $_POST['uri']);
|
||||||
$query->bindValue(':title', $_POST['title']);
|
$query->bindValue(':title', $_POST['title']);
|
||||||
|
@ -220,6 +220,7 @@ CREATE TABLE IF NOT EXISTS `reports` (
|
|||||||
`board` varchar(58) CHARACTER SET utf8 DEFAULT NULL,
|
`board` varchar(58) CHARACTER SET utf8 DEFAULT NULL,
|
||||||
`post` int(11) NOT NULL,
|
`post` int(11) NOT NULL,
|
||||||
`reason` text NOT NULL,
|
`reason` text NOT NULL,
|
||||||
|
`local` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
`global` tinyint(1) NOT NULL DEFAULT '0',
|
`global` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ;
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ;
|
||||||
|
44
js/captcha.js
Normal file
44
js/captcha.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
var tout;
|
||||||
|
|
||||||
|
function redo_events(provider, extra) {
|
||||||
|
$('.captcha .captcha_text, textarea[id="body"]').off("focus").one("focus", function() { actually_load_captcha(provider, extra); });
|
||||||
|
}
|
||||||
|
|
||||||
|
function actually_load_captcha(provider, extra) {
|
||||||
|
$('.captcha .captcha_text, textarea[id="body"]').off("focus");
|
||||||
|
|
||||||
|
if (tout !== undefined) {
|
||||||
|
clearTimeout(tout);
|
||||||
|
}
|
||||||
|
|
||||||
|
$.getJSON(provider, {mode: 'get', extra: extra}, function(json) {
|
||||||
|
$(".captcha .captcha_cookie").val(json.cookie);
|
||||||
|
$(".captcha .captcha_html").html(json.captchahtml);
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
redo_events(provider, extra);
|
||||||
|
}, json.expires_in * 1000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function load_captcha(provider, extra) {
|
||||||
|
$(function() {
|
||||||
|
$(".captcha>td").html("<input class='captcha_text' type='text' name='captcha_text' size='25' maxlength='6' autocomplete='off'>"+
|
||||||
|
"<input class='captcha_cookie' name='captcha_cookie' type='hidden'>"+
|
||||||
|
"<div class='captcha_html'></div>");
|
||||||
|
|
||||||
|
$("#quick-reply .captcha .captcha_text").prop("placeholder", _("Verification"));
|
||||||
|
|
||||||
|
$(".captcha .captcha_html").on("click", function() { actually_load_captcha(provider, extra); });
|
||||||
|
$(document).on("ajax_after_post", function() { actually_load_captcha(provider, extra); });
|
||||||
|
redo_events(provider, extra);
|
||||||
|
|
||||||
|
$(window).on("quick-reply", function() {
|
||||||
|
redo_events(provider, extra);
|
||||||
|
$("#quick-reply .captcha .captcha_html").html($("form:not(#quick-reply) .captcha .captcha_html").html());
|
||||||
|
$("#quick-reply .captcha .captcha_cookie").val($("form:not(#quick-reply) .captcha .captcha_cookie").html());
|
||||||
|
$("#quick-reply .captcha .captcha_html").on("click", function() { actually_load_captcha(provider, extra); });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
4
js/jquery.tablesorter.min.js
vendored
Normal file
4
js/jquery.tablesorter.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -149,14 +149,14 @@
|
|||||||
.removeAttr('size')
|
.removeAttr('size')
|
||||||
.attr('placeholder', $th.clone().children().remove().end().text());
|
.attr('placeholder', $th.clone().children().remove().end().text());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move anti-spam nonsense and remove <th>
|
// Move anti-spam nonsense and remove <th>
|
||||||
$th.contents().filter(function() {
|
$th.contents().filter(function() {
|
||||||
return this.nodeType == 3; // Node.TEXT_NODE
|
return this.nodeType == 3; // Node.TEXT_NODE
|
||||||
}).remove();
|
}).remove();
|
||||||
$th.contents().appendTo($dummyStuff);
|
$th.contents().appendTo($dummyStuff);
|
||||||
$th.remove();
|
$th.remove();
|
||||||
|
|
||||||
if ($td.find('input[name="password"]').length) {
|
if ($td.find('input[name="password"]').length) {
|
||||||
// Hide password field
|
// Hide password field
|
||||||
$(this).hide();
|
$(this).hide();
|
||||||
@ -280,7 +280,7 @@
|
|||||||
|
|
||||||
$postForm.find('textarea[name="body"]').removeAttr('id').removeAttr('cols').attr('placeholder', _('Comment'));
|
$postForm.find('textarea[name="body"]').removeAttr('id').removeAttr('cols').attr('placeholder', _('Comment'));
|
||||||
|
|
||||||
$postForm.find('textarea:not([name="body"]),input[type="hidden"]').removeAttr('id').appendTo($dummyStuff);
|
$postForm.find('textarea:not([name="body"]),input[type="hidden"]:not(.captcha_cookie)').removeAttr('id').appendTo($dummyStuff);
|
||||||
|
|
||||||
$postForm.find('br').remove();
|
$postForm.find('br').remove();
|
||||||
$postForm.find('table').prepend('<tr><th colspan="2">\
|
$postForm.find('table').prepend('<tr><th colspan="2">\
|
||||||
|
@ -79,6 +79,7 @@ $(document).ready(function(){
|
|||||||
}
|
}
|
||||||
$('#thread_stats_page').text(page);
|
$('#thread_stats_page').text(page);
|
||||||
if (!found) $('#thread_stats_page').css('color','red');
|
if (!found) $('#thread_stats_page').css('color','red');
|
||||||
|
else $('#thread_stats_page').css('color','');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// load the current page the thread is on.
|
// load the current page the thread is on.
|
||||||
@ -99,6 +100,7 @@ $(document).ready(function(){
|
|||||||
}
|
}
|
||||||
$('#thread_stats_page').text(page);
|
$('#thread_stats_page').text(page);
|
||||||
if (!found) $('#thread_stats_page').css('color','red');
|
if (!found) $('#thread_stats_page').css('color','red');
|
||||||
|
else $('#thread_stats_page').css('color','');
|
||||||
});
|
});
|
||||||
},30000);
|
},30000);
|
||||||
$('body').append('<style>.posts_by_id{display:none;}.poster_id:hover+.posts_by_id{display:initial}</style>');
|
$('body').append('<style>.posts_by_id{display:none;}.poster_id:hover+.posts_by_id{display:initial}</style>');
|
||||||
|
15
post.php
15
post.php
@ -232,6 +232,21 @@ elseif (isset($_POST['post'])) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same, but now with our custom captcha provider
|
||||||
|
if ($config['captcha']['enabled']) {
|
||||||
|
$resp = file_get_contents($config['captcha']['provider_check'] . "?" . http_build_query([
|
||||||
|
'mode' => 'check',
|
||||||
|
'text' => $_POST['captcha_text'],
|
||||||
|
'extra' => $config['captcha']['extra'],
|
||||||
|
'cookie' => $_POST['captcha_cookie']
|
||||||
|
]));
|
||||||
|
|
||||||
|
if ($resp !== '1') {
|
||||||
|
error($config['error']['captcha'] .
|
||||||
|
'<script>if (actually_load_captcha !== undefined) actually_load_captcha("'.$config['captcha']['provider_get'].'", "'.$config['captcha']['extra'].'");</script>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//if (!(($post['op'] && $_POST['post'] == $config['button_newtopic']) ||
|
//if (!(($post['op'] && $_POST['post'] == $config['button_newtopic']) ||
|
||||||
//(!$post['op'] && $_POST['post'] == $config['button_reply'])))
|
//(!$post['op'] && $_POST['post'] == $config['button_reply'])))
|
||||||
//error($config['error']['bot']);
|
//error($config['error']['bot']);
|
||||||
|
@ -127,6 +127,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if mod|hasPermission(config.mod.manageboards) %}
|
{% if mod|hasPermission(config.mod.manageboards) %}
|
||||||
<a href="?/edit/{{ board.uri }}"><small>[{% trans 'edit' %}]</small></a>
|
<a href="?/edit/{{ board.uri }}"><small>[{% trans 'edit' %}]</small></a>
|
||||||
|
<a href="?/settings/{{ board.uri }}"><small>[{% trans 'settings' %}]</small></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -44,6 +44,8 @@
|
|||||||
<tr><th>{% trans %}Enable dice rolling{% endtrans %}</th><td><input type="checkbox" name="allow_roll" {% if config.allow_roll %}checked{% endif %}></td></tr>
|
<tr><th>{% trans %}Enable dice rolling{% endtrans %}</th><td><input type="checkbox" name="allow_roll" {% if config.allow_roll %}checked{% endif %}></td></tr>
|
||||||
<tr><th>{% trans %}Don't allow users to repost images{% endtrans %}</th><td><input type="checkbox" name="image_reject_repost" {% if config.image_reject_repost %}checked{% endif %}></td></tr>
|
<tr><th>{% trans %}Don't allow users to repost images{% endtrans %}</th><td><input type="checkbox" name="image_reject_repost" {% if config.image_reject_repost %}checked{% endif %}></td></tr>
|
||||||
<tr><th>{% trans %}Allow a poster to delete his own posts{% endtrans %}</th><td><input type="checkbox" name="allow_delete" {% if config.allow_delete %}checked{% endif %}></td></tr>
|
<tr><th>{% trans %}Allow a poster to delete his own posts{% endtrans %}</th><td><input type="checkbox" name="allow_delete" {% if config.allow_delete %}checked{% endif %}></td></tr>
|
||||||
|
<tr><th>{% trans %}Enable captcha{% endtrans %}</th><td><input type="checkbox" name="captcha" {% if config.captcha.enabled %}checked{% endif %}></td></tr>
|
||||||
|
<tr><th>{% trans %}Captcha charset{% endtrans %}</th><td><input type="text" name="captcha_charset" value="{{ config.captcha.extra|e }}"></td></tr>
|
||||||
<tr><th>{% trans %}Language{% endtrans %}<br/><span class="unimportant">{% trans %}To contribute translations, register at <a href="https://www.transifex.com/projects/p/tinyboard-vichan-devel/">Transifex</a>{% endtrans %}</span></th><td>
|
<tr><th>{% trans %}Language{% endtrans %}<br/><span class="unimportant">{% trans %}To contribute translations, register at <a href="https://www.transifex.com/projects/p/tinyboard-vichan-devel/">Transifex</a>{% endtrans %}</span></th><td>
|
||||||
<select name="locale">
|
<select name="locale">
|
||||||
<option value="en" {% if "en" == config.locale %}selected{% endif %}>en</option>
|
<option value="en" {% if "en" == config.locale %}selected{% endif %}>en</option>
|
||||||
|
@ -80,6 +80,17 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if config.captcha.enabled %}
|
||||||
|
<tr class='captcha'>
|
||||||
|
<th>
|
||||||
|
{% trans %}Verification{% endtrans %}
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<script>load_captcha("{{ config.captcha.provider_get }}", "{{ config.captcha.extra }}");</script>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if config.user_flag %}
|
{% if config.user_flag %}
|
||||||
<tr>
|
<tr>
|
||||||
<th>{% trans %}Flag{% endtrans %}</th>
|
<th>{% trans %}Flag{% endtrans %}</th>
|
||||||
|
Loading…
Reference in New Issue
Block a user