mirror of
https://github.com/PrivateBin/PrivateBin.git
synced 2024-10-01 01:26:10 -04:00
Merge branch 'qrcode'
This commit is contained in:
commit
dae11fdd16
@ -56,6 +56,10 @@ languageselection = false
|
|||||||
; the pastes encryption key
|
; the pastes encryption key
|
||||||
; urlshortener = "https://shortener.example.com/api?link="
|
; urlshortener = "https://shortener.example.com/api?link="
|
||||||
|
|
||||||
|
; (optional) Let users create a QR code for sharing the paste URL with one click.
|
||||||
|
; It works both when a new paste is created and when you view a paste.
|
||||||
|
; qrcode = true
|
||||||
|
|
||||||
; (optional) IP based icons are a weak mechanism to detect if a comment was from
|
; (optional) IP based icons are a weak mechanism to detect if a comment was from
|
||||||
; a different user when the same username was used in a comment. It might be
|
; a different user when the same username was used in a comment. It might be
|
||||||
; used to get the IP of a non anonymous comment poster if the server salt is
|
; used to get the IP of a non anonymous comment poster if the server salt is
|
||||||
|
@ -76,6 +76,16 @@ body.loading {
|
|||||||
|
|
||||||
#deletelink {
|
#deletelink {
|
||||||
float: right;
|
float: right;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#qrcodemodalClose {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
#qrcode-display {
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pastelink {
|
#pastelink {
|
||||||
|
@ -132,7 +132,7 @@ h3.title {
|
|||||||
|
|
||||||
#toolbar, #status { margin-bottom: 5px; }
|
#toolbar, #status { margin-bottom: 5px; }
|
||||||
|
|
||||||
#copyhint { color: #666; font-size: 0.85em; }
|
#copyhint { color: #666; font-size: 0.85em }
|
||||||
|
|
||||||
button, .button {
|
button, .button {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
BIN
img/icon_qr.png
Normal file
BIN
img/icon_qr.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 437 B |
2
js/kjua-0.1.2.js
Normal file
2
js/kjua-0.1.2.js
Normal file
File diff suppressed because one or more lines are too long
@ -21,6 +21,7 @@
|
|||||||
/** global: prettyPrintOne */
|
/** global: prettyPrintOne */
|
||||||
/** global: showdown */
|
/** global: showdown */
|
||||||
/** global: sjcl */
|
/** global: sjcl */
|
||||||
|
/** global: kjua */
|
||||||
|
|
||||||
// Immediately start random number generator collector.
|
// Immediately start random number generator collector.
|
||||||
sjcl.random.startCollectors();
|
sjcl.random.startCollectors();
|
||||||
@ -2408,6 +2409,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
|||||||
$password,
|
$password,
|
||||||
$passwordInput,
|
$passwordInput,
|
||||||
$rawTextButton,
|
$rawTextButton,
|
||||||
|
$qrCodeLink,
|
||||||
$sendButton;
|
$sendButton;
|
||||||
|
|
||||||
var pasteExpiration = '1week';
|
var pasteExpiration = '1week';
|
||||||
@ -2585,6 +2587,22 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the QR code of the current paste (URL).
|
||||||
|
*
|
||||||
|
* @name TopNav.displayQrCode
|
||||||
|
* @function
|
||||||
|
* @param {Event} event
|
||||||
|
*/
|
||||||
|
function displayQrCode(event)
|
||||||
|
{
|
||||||
|
var qrCanvas = kjua({
|
||||||
|
render: 'canvas',
|
||||||
|
text: window.location.href
|
||||||
|
});
|
||||||
|
$('#qrcode-display').html(qrCanvas);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows all elements belonging to viwing an existing pastes
|
* Shows all elements belonging to viwing an existing pastes
|
||||||
*
|
*
|
||||||
@ -2601,6 +2619,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
|||||||
$newButton.removeClass('hidden');
|
$newButton.removeClass('hidden');
|
||||||
$cloneButton.removeClass('hidden');
|
$cloneButton.removeClass('hidden');
|
||||||
$rawTextButton.removeClass('hidden');
|
$rawTextButton.removeClass('hidden');
|
||||||
|
$qrCodeLink.removeClass('hidden');
|
||||||
|
|
||||||
viewButtonsDisplayed = true;
|
viewButtonsDisplayed = true;
|
||||||
}
|
}
|
||||||
@ -2621,6 +2640,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
|||||||
$newButton.addClass('hidden');
|
$newButton.addClass('hidden');
|
||||||
$cloneButton.addClass('hidden');
|
$cloneButton.addClass('hidden');
|
||||||
$rawTextButton.addClass('hidden');
|
$rawTextButton.addClass('hidden');
|
||||||
|
$qrCodeLink.addClass('hidden');
|
||||||
|
|
||||||
viewButtonsDisplayed = false;
|
viewButtonsDisplayed = false;
|
||||||
}
|
}
|
||||||
@ -2871,6 +2891,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
|||||||
$passwordInput = $('#passwordinput');
|
$passwordInput = $('#passwordinput');
|
||||||
$rawTextButton = $('#rawtextbutton');
|
$rawTextButton = $('#rawtextbutton');
|
||||||
$sendButton = $('#sendbutton');
|
$sendButton = $('#sendbutton');
|
||||||
|
$qrCodeLink = $('#qrcodelink');
|
||||||
|
|
||||||
// bootstrap template drop down
|
// bootstrap template drop down
|
||||||
$('#language ul.dropdown-menu li a').click(setLanguage);
|
$('#language ul.dropdown-menu li a').click(setLanguage);
|
||||||
@ -2885,6 +2906,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
|
|||||||
$cloneButton.click(Controller.clonePaste);
|
$cloneButton.click(Controller.clonePaste);
|
||||||
$rawTextButton.click(rawText);
|
$rawTextButton.click(rawText);
|
||||||
$fileRemoveButton.click(removeAttachment);
|
$fileRemoveButton.click(removeAttachment);
|
||||||
|
$qrCodeLink.click(displayQrCode);
|
||||||
|
|
||||||
// bootstrap template drop downs
|
// bootstrap template drop downs
|
||||||
$('ul.dropdown-menu li a', $('#expiration').parent()).click(updateExpiration);
|
$('ul.dropdown-menu li a', $('#expiration').parent()).click(updateExpiration);
|
||||||
|
@ -52,6 +52,7 @@ class Configuration
|
|||||||
'languageselection' => false,
|
'languageselection' => false,
|
||||||
'languagedefault' => '',
|
'languagedefault' => '',
|
||||||
'urlshortener' => '',
|
'urlshortener' => '',
|
||||||
|
'qrcode' => true,
|
||||||
'icon' => 'identicon',
|
'icon' => 'identicon',
|
||||||
'cspheader' => 'default-src \'none\'; manifest-src \'self\'; connect-src *; script-src \'self\'; style-src \'self\'; font-src \'self\'; img-src \'self\' data:; referrer no-referrer; sandbox allow-same-origin allow-scripts allow-forms allow-popups',
|
'cspheader' => 'default-src \'none\'; manifest-src \'self\'; connect-src *; script-src \'self\'; style-src \'self\'; font-src \'self\'; img-src \'self\' data:; referrer no-referrer; sandbox allow-same-origin allow-scripts allow-forms allow-popups',
|
||||||
'zerobincompatibility' => false,
|
'zerobincompatibility' => false,
|
||||||
|
@ -448,6 +448,7 @@ class PrivateBin
|
|||||||
$page->assign('EXPIREDEFAULT', $this->_conf->getKey('default', 'expire'));
|
$page->assign('EXPIREDEFAULT', $this->_conf->getKey('default', 'expire'));
|
||||||
$page->assign('EXPIRECLONE', !$this->_doesExpire || ($this->_doesExpire && $this->_conf->getKey('clone', 'expire')));
|
$page->assign('EXPIRECLONE', !$this->_doesExpire || ($this->_doesExpire && $this->_conf->getKey('clone', 'expire')));
|
||||||
$page->assign('URLSHORTENER', $this->_conf->getKey('urlshortener'));
|
$page->assign('URLSHORTENER', $this->_conf->getKey('urlshortener'));
|
||||||
|
$page->assign('QRCODE', $this->_conf->getKey('qrcode'));
|
||||||
$page->draw($this->_conf->getKey('template'));
|
$page->draw($this->_conf->getKey('template'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,11 @@ endif;
|
|||||||
<script type="text/javascript" src="js/jquery-3.1.1.js" integrity="sha512-U6K1YLIFUWcvuw5ucmMtT9HH4t0uz3M366qrF5y4vnyH6dgDzndlcGvH/Lz5k8NFh80SN95aJ5rqGZEdaQZ7ZQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" src="js/jquery-3.1.1.js" integrity="sha512-U6K1YLIFUWcvuw5ucmMtT9HH4t0uz3M366qrF5y4vnyH6dgDzndlcGvH/Lz5k8NFh80SN95aJ5rqGZEdaQZ7ZQ==" crossorigin="anonymous"></script>
|
||||||
<script type="text/javascript" src="js/sjcl-1.0.6.js" integrity="sha512-DsyxLV/uBoQlRTJmW5Gb2SxXUXB+aYeZ6zk+NuXy8LuLyi8oGti9AGn6He5fUY2DtgQ2//RjfaZog8exFuunUQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" src="js/sjcl-1.0.6.js" integrity="sha512-DsyxLV/uBoQlRTJmW5Gb2SxXUXB+aYeZ6zk+NuXy8LuLyi8oGti9AGn6He5fUY2DtgQ2//RjfaZog8exFuunUQ==" crossorigin="anonymous"></script>
|
||||||
<?php
|
<?php
|
||||||
|
if ($QRCODE):
|
||||||
|
?>
|
||||||
|
<script async type="text/javascript" src="js/kjua-0.1.2.js" integrity="sha512-hmvfOhcr4J8bjQ2GuNVzfSbuulv72wgQCJpgnXc2+cCHKqvYo8pK2nc0Q4Esem2973zo1radyIMTEkt+xJlhBA==" crossorigin="anonymous"></script>
|
||||||
|
<?php
|
||||||
|
endif;
|
||||||
if ($ZEROBINCOMPATIBILITY):
|
if ($ZEROBINCOMPATIBILITY):
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" src="js/base64-1.7.js" integrity="sha512-JdwsSP3GyHR+jaCkns9CL9NTt4JUJqm/BsODGmYhBcj5EAPKcHYh+OiMfyHbcDLECe17TL0hjXADFkusAqiYgA==" crossorigin="anonymous"></script>
|
<script type="text/javascript" src="js/base64-1.7.js" integrity="sha512-JdwsSP3GyHR+jaCkns9CL9NTt4JUJqm/BsODGmYhBcj5EAPKcHYh+OiMfyHbcDLECe17TL0hjXADFkusAqiYgA==" crossorigin="anonymous"></script>
|
||||||
@ -70,7 +75,7 @@ if ($MARKDOWN):
|
|||||||
<?php
|
<?php
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-51v9MtL1fUeIOp2VekfHq4VR6kdR/SyYqkAT1WGRZXDP5+ct6A1qktVW9HNNL6EXYQbMpzgVuYUIZ6HhULcGSA==" crossorigin="anonymous"></script>
|
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-ongf6gpLgDPRVlBPaFlvxyDu3rCb1APhvzJLUFj9JuXCi6Zd0vqxt//vR8Zz3Ez9Fq+mw14HU8z52H7EjZewfA==" crossorigin="anonymous"></script>
|
||||||
<!--[if lt IE 10]>
|
<!--[if lt IE 10]>
|
||||||
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
|
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
@ -88,8 +93,8 @@ if ($isCpct):
|
|||||||
?> class="navbar-spacing"<?php
|
?> class="navbar-spacing"<?php
|
||||||
endif;
|
endif;
|
||||||
?>>
|
?>>
|
||||||
<div id="passwordmodal" class="modal fade" role="dialog">
|
<div id="passwordmodal" tabindex="-1" class="modal fade" role="dialog" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form id="passwordform" role="form">
|
<form id="passwordform" role="form">
|
||||||
@ -103,6 +108,22 @@ endif;
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<?php
|
||||||
|
if ($QRCODE):
|
||||||
|
?>
|
||||||
|
<div id="qrcodemodal" tabindex="-1" class="modal fade" aria-labelledby="qrcodemodalTitle" role="dialog" aria-hidden="true">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="mx-auto" id="qrcode-display"></div>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn btn-primary btn-block" data-dismiss="modal"><?php echo I18n::_('Close') ?></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
endif;
|
||||||
|
?>
|
||||||
<nav class="navbar navbar-<?php echo $isDark ? 'inverse' : 'default'; ?> navbar-<?php echo $isCpct ? 'fixed' : 'static'; ?>-top"><?php
|
<nav class="navbar navbar-<?php echo $isDark ? 'inverse' : 'default'; ?> navbar-<?php echo $isCpct ? 'fixed' : 'static'; ?>-top"><?php
|
||||||
if ($isCpct):
|
if ($isCpct):
|
||||||
?><div class="container"><?php
|
?><div class="container"><?php
|
||||||
@ -150,6 +171,15 @@ endif;
|
|||||||
<button id="rawtextbutton" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?> navbar-btn">
|
<button id="rawtextbutton" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?> navbar-btn">
|
||||||
<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo I18n::_('Raw text'), PHP_EOL; ?>
|
<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo I18n::_('Raw text'), PHP_EOL; ?>
|
||||||
</button>
|
</button>
|
||||||
|
<?php
|
||||||
|
if ($QRCODE):
|
||||||
|
?>
|
||||||
|
<button id="qrcodelink" type="button" data-toggle="modal" data-target="#qrcodemodal" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?> navbar-btn">
|
||||||
|
<span class="glyphicon glyphicon-qrcode" aria-hidden="true"></span> <?php echo I18n::_('QR code'), PHP_EOL; ?>
|
||||||
|
</button>
|
||||||
|
<?php
|
||||||
|
endif;
|
||||||
|
?>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<select id="pasteExpiration" name="pasteExpiration" class="hidden">
|
<select id="pasteExpiration" name="pasteExpiration" class="hidden">
|
||||||
|
23
tpl/page.php
23
tpl/page.php
@ -22,6 +22,7 @@ endif;
|
|||||||
?>
|
?>
|
||||||
<script type="text/javascript" src="js/jquery-3.1.1.js" integrity="sha512-U6K1YLIFUWcvuw5ucmMtT9HH4t0uz3M366qrF5y4vnyH6dgDzndlcGvH/Lz5k8NFh80SN95aJ5rqGZEdaQZ7ZQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" src="js/jquery-3.1.1.js" integrity="sha512-U6K1YLIFUWcvuw5ucmMtT9HH4t0uz3M366qrF5y4vnyH6dgDzndlcGvH/Lz5k8NFh80SN95aJ5rqGZEdaQZ7ZQ==" crossorigin="anonymous"></script>
|
||||||
<script type="text/javascript" src="js/sjcl-1.0.6.js" integrity="sha512-DsyxLV/uBoQlRTJmW5Gb2SxXUXB+aYeZ6zk+NuXy8LuLyi8oGti9AGn6He5fUY2DtgQ2//RjfaZog8exFuunUQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" src="js/sjcl-1.0.6.js" integrity="sha512-DsyxLV/uBoQlRTJmW5Gb2SxXUXB+aYeZ6zk+NuXy8LuLyi8oGti9AGn6He5fUY2DtgQ2//RjfaZog8exFuunUQ==" crossorigin="anonymous"></script>
|
||||||
|
<script type="text/javascript" src="js/kjua.min.js" integrity="sha512-hmvfOhcr4J8bjQ2GuNVzfSbuulv72wgQCJpgnXc2+cCHKqvYo8pK2nc0Q4Esem2973zo1radyIMTEkt+xJlhBA==" crossorigin="anonymous"></script>
|
||||||
<?php
|
<?php
|
||||||
if ($ZEROBINCOMPATIBILITY):
|
if ($ZEROBINCOMPATIBILITY):
|
||||||
?>
|
?>
|
||||||
@ -47,8 +48,13 @@ if ($MARKDOWN):
|
|||||||
<script type="text/javascript" src="js/purify-1.0.3.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-uhzhZJSgc+XJoaxCOjiuRzQaf5klPlSSVKGw69+zT72hhfLbVwB4jbwI+f7NRucuRz6u0aFGMeZ+0PnGh73iBQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" src="js/purify-1.0.3.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-uhzhZJSgc+XJoaxCOjiuRzQaf5klPlSSVKGw69+zT72hhfLbVwB4jbwI+f7NRucuRz6u0aFGMeZ+0PnGh73iBQ==" crossorigin="anonymous"></script>
|
||||||
<?php
|
<?php
|
||||||
endif;
|
endif;
|
||||||
|
if ($QRCODE):
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-51v9MtL1fUeIOp2VekfHq4VR6kdR/SyYqkAT1WGRZXDP5+ct6A1qktVW9HNNL6EXYQbMpzgVuYUIZ6HhULcGSA==" crossorigin="anonymous"></script>
|
<script async type="text/javascript" src="js/kjua-0.1.2.js" integrity="sha512-hmvfOhcr4J8bjQ2GuNVzfSbuulv72wgQCJpgnXc2+cCHKqvYo8pK2nc0Q4Esem2973zo1radyIMTEkt+xJlhBA==" crossorigin="anonymous"></script>
|
||||||
|
<?php
|
||||||
|
endif;
|
||||||
|
?>
|
||||||
|
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-ongf6gpLgDPRVlBPaFlvxyDu3rCb1APhvzJLUFj9JuXCi6Zd0vqxt//vR8Zz3Ez9Fq+mw14HU8z52H7EjZewfA==" crossorigin="anonymous"></script>
|
||||||
<!--[if lt IE 10]>
|
<!--[if lt IE 10]>
|
||||||
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
|
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
@ -99,6 +105,13 @@ if ($EXPIRECLONE):
|
|||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
<button id="rawtextbutton" class="hidden"><img src="img/icon_raw.png" width="15" height="15" alt="" /><?php echo I18n::_('Raw text'); ?></button>
|
<button id="rawtextbutton" class="hidden"><img src="img/icon_raw.png" width="15" height="15" alt="" /><?php echo I18n::_('Raw text'); ?></button>
|
||||||
|
<?php
|
||||||
|
if ($QRCODE):
|
||||||
|
?>
|
||||||
|
<button id="qrcodelink" class="hidden"><img src="img/icon_qr.png" width="15" height="15" alt="" /><?php echo I18n::_('QR code'); ?></button>
|
||||||
|
<?php
|
||||||
|
endif;
|
||||||
|
?>
|
||||||
<div id="expiration" class="hidden button"><?php echo I18n::_('Expires'); ?>:
|
<div id="expiration" class="hidden button"><?php echo I18n::_('Expires'); ?>:
|
||||||
<select id="pasteExpiration" name="pasteExpiration">
|
<select id="pasteExpiration" name="pasteExpiration">
|
||||||
<?php
|
<?php
|
||||||
@ -185,7 +198,13 @@ if (strlen($LANGUAGESELECTION)):
|
|||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
</div>
|
</div>
|
||||||
<div id="pastesuccess" class="hidden">
|
<?php
|
||||||
|
if ($QRCODE):
|
||||||
|
?>
|
||||||
|
<div id="qrcode-display"></div>
|
||||||
|
<?php
|
||||||
|
endif;
|
||||||
|
?> <div id="pastesuccess" class="hidden">
|
||||||
<div id="deletelink"></div>
|
<div id="deletelink"></div>
|
||||||
<div id="pastelink">
|
<div id="pastelink">
|
||||||
<?php
|
<?php
|
||||||
|
@ -56,6 +56,7 @@ class ViewTest extends PHPUnit_Framework_TestCase
|
|||||||
$page->assign('EXPIREDEFAULT', self::$expire_default);
|
$page->assign('EXPIREDEFAULT', self::$expire_default);
|
||||||
$page->assign('EXPIRECLONE', true);
|
$page->assign('EXPIRECLONE', true);
|
||||||
$page->assign('URLSHORTENER', '');
|
$page->assign('URLSHORTENER', '');
|
||||||
|
$page->assign('QRCODE', true);
|
||||||
|
|
||||||
$dir = dir(PATH . 'tpl');
|
$dir = dir(PATH . 'tpl');
|
||||||
while (false !== ($file = $dir->read())) {
|
while (false !== ($file = $dir->read())) {
|
||||||
|
Loading…
Reference in New Issue
Block a user