Merge branch 'master' into psr2
* master: 🐛 (Draft) Fix exception when actually viewing a draft of a page 💡(Draft): Add doc block for constructor ✅ Add unittest for deleteUsers remote API call fix remote API call dokuwiki.deleteUsers translation update 🏗 Use json for the response to dw_locktimer ✨(dw_locktimer) plugins may reuse to add fields and callbacks 💄 (editor) draft status is semantically not part of the toolbar 🏗 Create new Draft class and move draft handling there translation update correctly avoid notice in init. avoid creating expensive stacktrace in dbg_deprecated() add method to EventHandler to check if an event is actually handled introduce INFO_DEPRECATION_LOG event
This commit is contained in:
commit
9ddafced33
|
@ -449,6 +449,20 @@ You can use up to five different levels of',
|
|||
$this->assertEquals(0, count($versions));
|
||||
}
|
||||
|
||||
public function test_deleteUser()
|
||||
{
|
||||
global $conf, $auth;
|
||||
$auth = new Mock_Auth_Plugin();
|
||||
$conf['remote'] = 1;
|
||||
$conf['remoteuser'] = 'testuser';
|
||||
$_SERVER['REMOTE_USER'] = 'testuser';
|
||||
$params = [
|
||||
['testuser']
|
||||
];
|
||||
$actualCallResult = $this->remote->call('dokuwiki.deleteUsers', $params);
|
||||
$this->assertTrue($actualCallResult);
|
||||
}
|
||||
|
||||
public function test_aclCheck() {
|
||||
$id = 'aclpage';
|
||||
|
||||
|
|
|
@ -19,16 +19,18 @@ class Draftdel extends AbstractAction {
|
|||
}
|
||||
|
||||
/**
|
||||
* Delete an existing draft if any
|
||||
* Delete an existing draft for the current page and user if any
|
||||
*
|
||||
* Reads draft information from $INFO. Redirects to show, afterwards.
|
||||
* Redirects to show, afterwards.
|
||||
*
|
||||
* @throws ActionAbort
|
||||
*/
|
||||
public function preProcess() {
|
||||
global $INFO;
|
||||
@unlink($INFO['draft']);
|
||||
$INFO['draft'] = null;
|
||||
global $INFO, $ID;
|
||||
$draft = new \dokuwiki\Draft($ID, $INFO['client']);
|
||||
if ($draft->isDraftAvailable()) {
|
||||
$draft->deleteDraft();
|
||||
}
|
||||
|
||||
throw new ActionAbort('redirect');
|
||||
}
|
||||
|
|
|
@ -29,29 +29,13 @@ class Preview extends Edit {
|
|||
* Saves a draft on preview
|
||||
*/
|
||||
protected function savedraft() {
|
||||
global $INFO;
|
||||
global $ID;
|
||||
global $INPUT;
|
||||
global $conf;
|
||||
|
||||
if(!$conf['usedraft']) return;
|
||||
if(!$INPUT->post->has('wikitext')) return;
|
||||
|
||||
// ensure environment (safeguard when used via AJAX)
|
||||
assert(isset($INFO['client']), 'INFO.client should have been set');
|
||||
assert(isset($ID), 'ID should have been set');
|
||||
|
||||
$draft = array(
|
||||
'id' => $ID,
|
||||
'prefix' => substr($INPUT->post->str('prefix'), 0, -1),
|
||||
'text' => $INPUT->post->str('wikitext'),
|
||||
'suffix' => $INPUT->post->str('suffix'),
|
||||
'date' => $INPUT->post->int('date'),
|
||||
'client' => $INFO['client'],
|
||||
);
|
||||
$cname = getCacheName($draft['client'] . $ID, '.draft');
|
||||
if(io_saveFile($cname, serialize($draft))) {
|
||||
$INFO['draft'] = $cname;
|
||||
global $ID, $INFO;
|
||||
$draft = new \dokuwiki\Draft($ID, $INFO['client']);
|
||||
if (!$draft->saveDraft()) {
|
||||
$errors = $draft->getErrors();
|
||||
foreach ($errors as $error) {
|
||||
msg(hsc($error), -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
35
inc/Ajax.php
35
inc/Ajax.php
|
@ -119,8 +119,6 @@ class Ajax {
|
|||
* Andreas Gohr <andi@splitbrain.org>
|
||||
*/
|
||||
protected function call_lock() {
|
||||
global $conf;
|
||||
global $lang;
|
||||
global $ID;
|
||||
global $INFO;
|
||||
global $INPUT;
|
||||
|
@ -130,34 +128,29 @@ class Ajax {
|
|||
|
||||
$INFO = pageinfo();
|
||||
|
||||
$response = [
|
||||
'errors' => [],
|
||||
'lock' => '0',
|
||||
'draft' => '',
|
||||
];
|
||||
if(!$INFO['writable']) {
|
||||
echo 'Permission denied';
|
||||
$response['errors'][] = 'Permission to write this page has been denied.';
|
||||
echo json_encode($response);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!checklock($ID)) {
|
||||
lock($ID);
|
||||
echo 1;
|
||||
$response['lock'] = '1';
|
||||
}
|
||||
|
||||
if($conf['usedraft'] && $INPUT->post->str('wikitext')) {
|
||||
$client = $_SERVER['REMOTE_USER'];
|
||||
if(!$client) $client = clientIP(true);
|
||||
|
||||
$draft = array(
|
||||
'id' => $ID,
|
||||
'prefix' => substr($INPUT->post->str('prefix'), 0, -1),
|
||||
'text' => $INPUT->post->str('wikitext'),
|
||||
'suffix' => $INPUT->post->str('suffix'),
|
||||
'date' => $INPUT->post->int('date'),
|
||||
'client' => $client,
|
||||
);
|
||||
$cname = getCacheName($draft['client'] . $ID, '.draft');
|
||||
if(io_saveFile($cname, serialize($draft))) {
|
||||
echo $lang['draftdate'] . ' ' . dformat();
|
||||
}
|
||||
$draft = new Draft($ID, $INFO['client']);
|
||||
if ($draft->saveDraft()) {
|
||||
$response['draft'] = $draft->getDraftMessage();
|
||||
} else {
|
||||
$response['errors'] = array_merge($response['errors'], $draft->getErrors());
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
<?php
|
||||
|
||||
namespace dokuwiki;
|
||||
|
||||
/**
|
||||
* Class Draft
|
||||
*
|
||||
* @package dokuwiki
|
||||
*/
|
||||
class Draft
|
||||
{
|
||||
|
||||
protected $errors = [];
|
||||
protected $cname;
|
||||
protected $id;
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* Draft constructor.
|
||||
*
|
||||
* @param string $ID the page id for this draft
|
||||
* @param string $client the client identification (username or ip or similar) for this draft
|
||||
*/
|
||||
public function __construct($ID, $client)
|
||||
{
|
||||
$this->id = $ID;
|
||||
$this->client = $client;
|
||||
$this->cname = getCacheName($client.$ID, '.draft');
|
||||
if(file_exists($this->cname) && file_exists(wikiFN($ID))) {
|
||||
if (filemtime($this->cname) < filemtime(wikiFN($ID))) {
|
||||
// remove stale draft
|
||||
$this->deleteDraft();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filename for this draft (whether or not it exists)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDraftFilename()
|
||||
{
|
||||
return $this->cname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this draft exists on the filesystem
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isDraftAvailable()
|
||||
{
|
||||
return file_exists($this->cname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a draft of a current edit session
|
||||
*
|
||||
* The draft will not be saved if
|
||||
* - drafts are deactivated in the config
|
||||
* - or the editarea is empty and there are no event handlers registered
|
||||
* - or the event is prevented
|
||||
*
|
||||
* @triggers DRAFT_SAVE
|
||||
*
|
||||
* @return bool whether has the draft been saved
|
||||
*/
|
||||
public function saveDraft()
|
||||
{
|
||||
global $INPUT, $INFO, $EVENT_HANDLER, $conf;
|
||||
if (!$conf['usedraft']) {
|
||||
return false;
|
||||
}
|
||||
if (!$INPUT->post->has('wikitext') &&
|
||||
!$EVENT_HANDLER->hasHandlerForEvent('DRAFT_SAVE')) {
|
||||
return false;
|
||||
}
|
||||
$draft = [
|
||||
'id' => $this->id,
|
||||
'prefix' => substr($INPUT->post->str('prefix'), 0, -1),
|
||||
'text' => $INPUT->post->str('wikitext'),
|
||||
'suffix' => $INPUT->post->str('suffix'),
|
||||
'date' => $INPUT->post->int('date'),
|
||||
'client' => $this->client,
|
||||
'cname' => $this->cname,
|
||||
'errors' => [],
|
||||
];
|
||||
$event = new \Doku_Event('DRAFT_SAVE', $draft);
|
||||
if ($event->advise_before()) {
|
||||
$draft['hasBeenSaved'] = io_saveFile($draft['cname'], serialize($draft));
|
||||
if ($draft['hasBeenSaved']) {
|
||||
$INFO['draft'] = $draft['cname'];
|
||||
}
|
||||
} else {
|
||||
$draft['hasBeenSaved'] = false;
|
||||
}
|
||||
$event->advise_after();
|
||||
|
||||
$this->errors = $draft['errors'];
|
||||
|
||||
return $draft['hasBeenSaved'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text from the draft file
|
||||
*
|
||||
* @throws \RuntimeException if the draft file doesn't exist
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDraftText()
|
||||
{
|
||||
if (!file_exists($this->cname)) {
|
||||
throw new \RuntimeException(
|
||||
"Draft for page $this->id and user $this->client doesn't exist at $this->cname."
|
||||
);
|
||||
}
|
||||
$draft = unserialize(io_readFile($this->cname,false));
|
||||
return cleanText(con($draft['prefix'],$draft['text'],$draft['suffix'],true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the draft from the filesystem
|
||||
*
|
||||
* Also sets $INFO['draft'] to null
|
||||
*/
|
||||
public function deleteDraft()
|
||||
{
|
||||
global $INFO;
|
||||
@unlink($this->cname);
|
||||
$INFO['draft'] = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a formatted message stating when the draft was saved
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDraftMessage()
|
||||
{
|
||||
global $lang;
|
||||
return $lang['draftdate'] . ' ' . dformat(filemtime($this->cname));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the errors that occured when saving the draft
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getErrors()
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timestamp when this draft was saved
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getDraftDate()
|
||||
{
|
||||
return filemtime($this->cname);
|
||||
}
|
||||
}
|
|
@ -596,7 +596,7 @@ class ApiCore
|
|||
}
|
||||
/** @var DokuWiki_Auth_Plugin $auth */
|
||||
global $auth;
|
||||
return (bool)$auth->triggerUserMod('deleteUsers', $usernames);
|
||||
return (bool)$auth->triggerUserMod('delete', array($usernames));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -285,14 +285,9 @@ function pageinfo() {
|
|||
}
|
||||
|
||||
// draft
|
||||
$draft = getCacheName($info['client'].$ID, '.draft');
|
||||
if(file_exists($draft)) {
|
||||
if(@filemtime($draft) < @filemtime(wikiFN($ID))) {
|
||||
// remove stale draft
|
||||
@unlink($draft);
|
||||
} else {
|
||||
$info['draft'] = $draft;
|
||||
}
|
||||
$draft = new \dokuwiki\Draft($ID, $info['client']);
|
||||
if ($draft->isDraftAvailable()) {
|
||||
$info['draft'] = $draft->getDraftFilename();
|
||||
}
|
||||
|
||||
return $info;
|
||||
|
|
|
@ -236,6 +236,24 @@ class Doku_Event_Handler {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an event has any registered handlers
|
||||
*
|
||||
* When $advise is empty, both BEFORE and AFTER events will be considered,
|
||||
* otherwise only the given advisory is checked
|
||||
*
|
||||
* @param string $name Name of the event
|
||||
* @param string $advise BEFORE, AFTER or empty
|
||||
* @return bool
|
||||
*/
|
||||
public function hasHandlerForEvent($name, $advise = '') {
|
||||
if($advise) {
|
||||
return isset($this->_hooks[$name . '_' . $advise]);
|
||||
} else {
|
||||
return isset($this->_hooks[$name . '_BEFORE']) || isset($this->_hooks[$name . '_AFTER']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
22
inc/html.php
22
inc/html.php
|
@ -314,17 +314,17 @@ function html_draft(){
|
|||
global $INFO;
|
||||
global $ID;
|
||||
global $lang;
|
||||
$draft = unserialize(io_readFile($INFO['draft'],false));
|
||||
$text = cleanText(con($draft['prefix'],$draft['text'],$draft['suffix'],true));
|
||||
$draft = new \dokuwiki\Draft($ID, $INFO['client']);
|
||||
$text = $draft->getDraftText();
|
||||
|
||||
print p_locale_xhtml('draft');
|
||||
html_diff($text, false);
|
||||
$form = new Doku_Form(array('id' => 'dw__editform'));
|
||||
$form->addHidden('id', $ID);
|
||||
$form->addHidden('date', $draft['date']);
|
||||
$form->addHidden('date', $draft->getDraftDate());
|
||||
$form->addHidden('wikitext', $text);
|
||||
$form->addElement(form_makeOpenTag('div', array('id'=>'draft__status')));
|
||||
$form->addElement($lang['draftdate'].' '. dformat(filemtime($INFO['draft'])));
|
||||
$form->addElement($draft->getDraftMessage());
|
||||
$form->addElement(form_makeCloseTag('div'));
|
||||
$form->addElement(form_makeButton('submit', 'recover', $lang['btn_recover'], array('tabindex'=>'1')));
|
||||
$form->addElement(form_makeButton('submit', 'draftdel', $lang['btn_draftdel'], array('tabindex'=>'2')));
|
||||
|
@ -1942,14 +1942,20 @@ function html_edit(){
|
|||
<div class="editBox" role="application">
|
||||
|
||||
<div class="toolbar group">
|
||||
<div id="draft__status" class="draft__status"><?php
|
||||
if(!empty($INFO['draft'])) echo $lang['draftdate'].' '.dformat();
|
||||
?></div>
|
||||
<div id="tool__bar" class="tool__bar"><?php
|
||||
if ($wr && $data['media_manager']){
|
||||
?><a href="<?php echo DOKU_BASE?>lib/exe/mediamanager.php?ns=<?php echo $INFO['namespace']?>"
|
||||
target="_blank"><?php echo $lang['mediaselect'] ?></a><?php
|
||||
}?></div>
|
||||
}?>
|
||||
</div>
|
||||
</div>
|
||||
<div id="draft__status" class="draft__status">
|
||||
<?php
|
||||
$draft = new \dokuwiki\Draft($ID, $INFO['client']);
|
||||
if ($draft->isDraftAvailable()) {
|
||||
echo $draft->getDraftMessage();
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
|
|
|
@ -444,26 +444,40 @@ function dbglog($msg,$header=''){
|
|||
* Log accesses to deprecated fucntions to the debug log
|
||||
*
|
||||
* @param string $alternative The function or method that should be used instead
|
||||
* @triggers INFO_DEPRECATION_LOG
|
||||
*/
|
||||
function dbg_deprecated($alternative = '') {
|
||||
global $conf;
|
||||
if(!$conf['allowdebug']) return;
|
||||
global $EVENT_HANDLER;
|
||||
if(!$conf['allowdebug'] && !$EVENT_HANDLER->hasHandlerForEvent('INFO_DEPRECATION_LOG')) {
|
||||
// avoid any work if no one cares
|
||||
return;
|
||||
}
|
||||
|
||||
$backtrace = debug_backtrace();
|
||||
array_shift($backtrace);
|
||||
$self = array_shift($backtrace);
|
||||
$call = array_shift($backtrace);
|
||||
$self = $backtrace[0];
|
||||
$call = $backtrace[1];
|
||||
|
||||
$called = trim($self['class'].'::'.$self['function'].'()', ':');
|
||||
$caller = trim($call['class'].'::'.$call['function'].'()', ':');
|
||||
$data = [
|
||||
'trace' => $backtrace,
|
||||
'alternative' => $alternative,
|
||||
'called' => trim($self['class'] . '::' . $self['function'] . '()', ':'),
|
||||
'caller' => trim($call['class'] . '::' . $call['function'] . '()', ':'),
|
||||
'file' => $call['file'],
|
||||
'line' => $call['line'],
|
||||
];
|
||||
|
||||
$msg = $called.' is deprecated. It was called from ';
|
||||
$msg .= $caller.' in '.$call['file'].':'.$call['line'];
|
||||
if($alternative) {
|
||||
$msg .= ' '.$alternative.' should be used instead!';
|
||||
$event = new Doku_Event('INFO_DEPRECATION_LOG', $data);
|
||||
if($event->advise_before()) {
|
||||
$msg = $event->data['called'] . ' is deprecated. It was called from ';
|
||||
$msg .= $event->data['caller'] . ' in ' . $event->data['file'] . ':' . $event->data['line'];
|
||||
if($event->data['alternative']) {
|
||||
$msg .= ' ' . $event->data['alternative'] . ' should be used instead!';
|
||||
}
|
||||
dbglog($msg);
|
||||
}
|
||||
|
||||
dbglog($msg);
|
||||
$event->advise_after();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -563,7 +563,7 @@ EOT;
|
|||
function fullpath($path,$exists=false){
|
||||
static $run = 0;
|
||||
$root = '';
|
||||
$iswin = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' || @$GLOBALS['DOKU_UNITTEST_ASSUME_WINDOWS']);
|
||||
$iswin = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' || !empty($GLOBALS['DOKU_UNITTEST_ASSUME_WINDOWS']));
|
||||
|
||||
// find the (indestructable) root of the path - keeps windows stuff intact
|
||||
if($path{0} == '/'){
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
====== Administraasje ======
|
||||
|
||||
Hjirûnder kinst in list fyne fan beskikbare administratieve taken yn DokuWiki
|
|
@ -3,6 +3,7 @@
|
|||
/**
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
*
|
||||
* @author Christian McKenna <mckchr@banenor.no>
|
||||
* @author Reidar Mosvold <Reidar.Mosvold@hit.no>
|
||||
* @author Jorge Barrera Grandon <jorge@digitalwolves.org>
|
||||
* @author Rune Rasmussen [http://www.syntaxerror.no/]
|
||||
|
@ -15,7 +16,7 @@
|
|||
* @author Knut Staring <knutst@gmail.com>
|
||||
* @author Lisa Ditlefsen <lisa@vervesearch.com>
|
||||
* @author Erik Pedersen <erik.pedersen@shaw.ca>
|
||||
* @author Rune Rasmussen syntaxerror.no@gmail.com
|
||||
* @author Rune Rasmussen <syntaxerror.no@gmail.com>
|
||||
* @author Jon Bøe <jonmagneboe@hotmail.com>
|
||||
* @author Egil Hansen <egil@rosetta.no>
|
||||
* @author Thomas Juberg <Thomas.Juberg@Gmail.com>
|
||||
|
@ -24,7 +25,6 @@
|
|||
* @author Patrick <spill.p@hotmail.com>
|
||||
* @author Danny Buckhof <daniel.raknes@hotmail.no>
|
||||
* @author Arne Hanssen <arne.hanssen@getmail.no>
|
||||
* @author Arne Hanssen <arnehans@getmail.no>
|
||||
* @author Patrick Sletvold <patricksletvold@hotmail.com>
|
||||
*/
|
||||
$lang['encoding'] = 'utf-8';
|
||||
|
@ -86,44 +86,7 @@ $lang['badpassconfirm'] = 'Beklager, passordet var feil';
|
|||
$lang['minoredit'] = 'Mindre endringer';
|
||||
$lang['draftdate'] = 'Kladd autolagret';
|
||||
$lang['nosecedit'] = 'Siden er i mellomtiden endret, seksjonsinfo har blitt foreldet - lastet full side istedet.';
|
||||
$lang['regmissing'] = 'Vennligst fyll ut alle felt.';
|
||||
$lang['reguexists'] = 'Det finnes allerede en konto med dette brukernavnet.';
|
||||
$lang['regsuccess'] = 'Brukerkonto har blitt laget og passord har blitt sendt via e-post.';
|
||||
$lang['regsuccess2'] = 'Brukeren har blitt laget.';
|
||||
$lang['regfail'] = 'Brukeren kan ikke opprettes';
|
||||
$lang['regmailfail'] = 'En feil oppstod da passordet ditt skulle sendes via e-post. Vennligst kontakt administratoren!';
|
||||
$lang['regbadmail'] = 'Den angitte e-post adressen ser ut til å være ugyldig. Vennligst kontakt administratoren om du anser dette som feilaktig.';
|
||||
$lang['regbadpass'] = 'De to angitte passordene er ikke like, vennligst forsøk igjen.';
|
||||
$lang['regpwmail'] = 'Ditt DokuWiki passord';
|
||||
$lang['reghere'] = 'Har du ikke en konto ennå? Lag deg en';
|
||||
$lang['profna'] = 'Denne wikien støtter ikke profilendringer';
|
||||
$lang['profnochange'] = 'Ingen endringer, ingenting å gjøre.';
|
||||
$lang['profnoempty'] = 'Tomt navn- eller e-postfelt er ikke tillatt.';
|
||||
$lang['profchanged'] = 'Brukerprofilen ble vellykket oppdatert.';
|
||||
$lang['profnodelete'] = 'Denne wikien støtter ikke sletting av brukere';
|
||||
$lang['profdeleteuser'] = 'Slett konto';
|
||||
$lang['profdeleted'] = 'Din brukerkonto har blitt slettet fra denne wikien';
|
||||
$lang['profconfdelete'] = 'Jeg ønsker å fjerne min konto fra denne wikien. <br/> Denne handlingen kan ikke gjøres om.';
|
||||
$lang['profconfdeletemissing'] = 'Boks for bekreftelse ikke avkrysset';
|
||||
$lang['proffail'] = 'Brukerprofilen ble ikke oppdatert';
|
||||
$lang['pwdforget'] = 'Glemt passordet ditt? Få deg et nytt';
|
||||
$lang['resendna'] = 'Denne wikien støtter ikke nyutsending av passord.';
|
||||
$lang['resendpwd'] = 'Sett nytt passord for';
|
||||
$lang['resendpwdmissing'] = 'Beklager, du må fylle inn alle felt.';
|
||||
$lang['resendpwdnouser'] = 'Beklager, vi kan ikke finne denne brukeren i vår database.';
|
||||
$lang['resendpwdbadauth'] = 'Beklager, denne autorisasjonskoden er ikke gyldig. Sjekk at du brukte hele bekreftelseslenken.';
|
||||
$lang['resendpwdconfirm'] = 'En bekreftelseslenke er blitt sendt på e-post.';
|
||||
$lang['resendpwdsuccess'] = 'Ditt nye passord er blitt sendt på e-post.';
|
||||
$lang['license'] = 'Der annet ikke er angitt, er innholdet på denne wiki utgitt under følgende lisens:';
|
||||
$lang['licenseok'] = 'Merk: Ved å endre på denne siden godtar du at ditt innhold utgis under følgende lisens:';
|
||||
$lang['searchmedia'] = 'Søk filnavn';
|
||||
$lang['searchmedia_in'] = 'Søk i %s';
|
||||
$lang['txt_upload'] = 'Velg fil som skal lastes opp:';
|
||||
$lang['txt_filename'] = 'Skriv inn wikinavn (alternativt):';
|
||||
$lang['txt_overwrt'] = 'Overskriv eksisterende fil';
|
||||
$lang['maxuploadsize'] = 'Opplast maks %s per fil.';
|
||||
$lang['lockedby'] = 'Låst av:';
|
||||
$lang['lockexpire'] = 'Låsingen utløper:';
|
||||
$lang['searchcreatepage'] = 'Hvis du ikke fant det du søkte etter kan du lage eller endre siden %s.';
|
||||
$lang['js']['willexpire'] = 'Din redigeringslås for dette dokumentet kommer snart til å utløpe.\nFor å unngå versjonskonflikter bør du forhåndsvise dokumentet ditt for å forlenge redigeringslåsen.';
|
||||
$lang['js']['notsavedyet'] = 'Ulagrede endringer vil gå tapt!
|
||||
Vil du fortsette?';
|
||||
|
@ -167,6 +130,44 @@ $lang['js']['media_done_btn'] = 'Ferdig';
|
|||
$lang['js']['media_drop'] = 'Dra filer hit for å laste dem opp';
|
||||
$lang['js']['media_cancel'] = 'fjern';
|
||||
$lang['js']['media_overwrt'] = 'Erstatt eksisterende filer';
|
||||
$lang['regmissing'] = 'Vennligst fyll ut alle felt.';
|
||||
$lang['reguexists'] = 'Det finnes allerede en konto med dette brukernavnet.';
|
||||
$lang['regsuccess'] = 'Brukerkonto har blitt laget og passord har blitt sendt via e-post.';
|
||||
$lang['regsuccess2'] = 'Brukeren har blitt laget.';
|
||||
$lang['regfail'] = 'Brukeren kan ikke opprettes';
|
||||
$lang['regmailfail'] = 'En feil oppstod da passordet ditt skulle sendes via e-post. Vennligst kontakt administratoren!';
|
||||
$lang['regbadmail'] = 'Den angitte e-post adressen ser ut til å være ugyldig. Vennligst kontakt administratoren om du anser dette som feilaktig.';
|
||||
$lang['regbadpass'] = 'De to angitte passordene er ikke like, vennligst forsøk igjen.';
|
||||
$lang['regpwmail'] = 'Ditt DokuWiki passord';
|
||||
$lang['reghere'] = 'Har du ikke en konto ennå? Lag deg en';
|
||||
$lang['profna'] = 'Denne wikien støtter ikke profilendringer';
|
||||
$lang['profnochange'] = 'Ingen endringer, ingenting å gjøre.';
|
||||
$lang['profnoempty'] = 'Tomt navn- eller e-postfelt er ikke tillatt.';
|
||||
$lang['profchanged'] = 'Brukerprofilen ble vellykket oppdatert.';
|
||||
$lang['profnodelete'] = 'Denne wikien støtter ikke sletting av brukere';
|
||||
$lang['profdeleteuser'] = 'Slett konto';
|
||||
$lang['profdeleted'] = 'Din brukerkonto har blitt slettet fra denne wikien';
|
||||
$lang['profconfdelete'] = 'Jeg ønsker å fjerne min konto fra denne wikien. <br/> Denne handlingen kan ikke gjøres om.';
|
||||
$lang['profconfdeletemissing'] = 'Boks for bekreftelse ikke avkrysset';
|
||||
$lang['proffail'] = 'Brukerprofilen ble ikke oppdatert';
|
||||
$lang['pwdforget'] = 'Glemt passordet ditt? Få deg et nytt';
|
||||
$lang['resendna'] = 'Denne wikien støtter ikke nyutsending av passord.';
|
||||
$lang['resendpwd'] = 'Sett nytt passord for';
|
||||
$lang['resendpwdmissing'] = 'Beklager, du må fylle inn alle felt.';
|
||||
$lang['resendpwdnouser'] = 'Beklager, vi kan ikke finne denne brukeren i vår database.';
|
||||
$lang['resendpwdbadauth'] = 'Beklager, denne autorisasjonskoden er ikke gyldig. Sjekk at du brukte hele bekreftelseslenken.';
|
||||
$lang['resendpwdconfirm'] = 'En bekreftelseslenke er blitt sendt på e-post.';
|
||||
$lang['resendpwdsuccess'] = 'Ditt nye passord er blitt sendt på e-post.';
|
||||
$lang['license'] = 'Der annet ikke er angitt, er innholdet på denne wiki utgitt under følgende lisens:';
|
||||
$lang['licenseok'] = 'Merk: Ved å endre på denne siden godtar du at ditt innhold utgis under følgende lisens:';
|
||||
$lang['searchmedia'] = 'Søk filnavn';
|
||||
$lang['searchmedia_in'] = 'Søk i %s';
|
||||
$lang['txt_upload'] = 'Velg fil som skal lastes opp:';
|
||||
$lang['txt_filename'] = 'Skriv inn wikinavn (alternativt):';
|
||||
$lang['txt_overwrt'] = 'Overskriv eksisterende fil';
|
||||
$lang['maxuploadsize'] = 'Opplast maks %s per fil.';
|
||||
$lang['lockedby'] = 'Låst av:';
|
||||
$lang['lockexpire'] = 'Låsingen utløper:';
|
||||
$lang['rssfailed'] = 'En feil oppstod da denne kilden skulle hentes:';
|
||||
$lang['nothingfound'] = 'Ingen data funnet.';
|
||||
$lang['mediaselect'] = 'Mediefiler';
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
* @author Knut Staring <knutst@gmail.com>
|
||||
* @author Lisa Ditlefsen <lisa@vervesearch.com>
|
||||
* @author Erik Pedersen <erik.pedersen@shaw.ca>
|
||||
* @author Erik Bjørn Pedersen <erik.pedersen@shaw.ca>
|
||||
* @author Rune Rasmussen syntaxerror.no@gmail.com
|
||||
* @author Rune Rasmussen <syntaxerror.no@gmail.com>
|
||||
* @author Jon Bøe <jonmagneboe@hotmail.com>
|
||||
* @author Egil Hansen <egil@rosetta.no>
|
||||
*/
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* @author Christopher Schive <chschive@frisurf.no>
|
||||
* @author Patrick <spill.p@hotmail.com>
|
||||
* @author Arne Hanssen <arne.hanssen@getmail.no>
|
||||
* @author Arne Hanssen <arnehans@getmail.no>
|
||||
*/
|
||||
$lang['server'] = 'Din LDAP-server. Enten vertsnavnet (<code>localhost</code>) eller hele URL (<code>ldap://server.tld:389</code>)';
|
||||
$lang['port'] = 'LDAP serverport dersom ingen full URL var gitt over.';
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
*
|
||||
* @author Arne Hanssen <arne.hanssen@getmail.no>
|
||||
*/
|
||||
$lang['connectfail'] = 'Klarte ikke koble til databasen.';
|
||||
$lang['userexists'] = 'Beklager, men en bruker med dette brukernavnet fins fra før.';
|
||||
$lang['usernotexists'] = 'Beklager med bruker fins ikke.';
|
||||
$lang['writefail'] = 'Klarte ikke endre brukerdata. Dette bør meldes til wikiens administrator';
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
*
|
||||
* @author Patrick <spill.p@hotmail.com>
|
||||
* @author Arne Hanssen <arne.hanssen@getmail.no>
|
||||
*/
|
||||
$lang['server'] = 'Din MySQL-server';
|
||||
$lang['user'] = 'Ditt MySQL-brukernavn';
|
||||
$lang['password'] = 'Passord til brukeren';
|
||||
$lang['database'] = 'Database som skal brukes';
|
||||
$lang['charset'] = 'Tegnsettet som datasen bruker';
|
||||
$lang['debug'] = 'Vis tilleggsinformasjon for feilsøking';
|
||||
$lang['forwardClearPass'] = 'Videresendt passord i klartekst til SQL-uttrykket under, i stedet for å bruke det krypterte passordet';
|
||||
$lang['TablesToLock'] = 'Kommaseparert liste over tabeller som må låses ved skriveopperasjoner';
|
||||
$lang['checkPass'] = 'SQL-uttrykk for å sjekke passord';
|
||||
$lang['getUserInfo'] = 'SQL-uttrykk for å hente informasjon om bruker';
|
||||
$lang['getGroups'] = 'SQL-uttrykk for å hente gruppene en bruker tilhører';
|
||||
$lang['getUsers'] = 'SQL-utrykk for å liste alle brukere';
|
||||
$lang['FilterLogin'] = 'SQL-utrykk for å filtrere brukere etter brukernavn';
|
||||
$lang['FilterName'] = 'SQL-utrykk for å filtrere brukere etter fult navn';
|
||||
$lang['FilterEmail'] = 'SQL-utrykk for å filtrere brukere etter e-postadresse';
|
||||
$lang['FilterGroup'] = 'SQL-uttrykk for å filtrere brukere etter hvilken grupper de tilhører';
|
||||
$lang['SortOrder'] = 'SQL-utrykk for å sortere brukere';
|
||||
$lang['addUser'] = 'SQL-utrykk for å legge til en ny bruker ';
|
||||
$lang['addGroup'] = 'SQL-utrykk for å legge til en ny gruppe';
|
||||
$lang['addUserGroup'] = 'SQL-uttrykk for å legge til en bruker i en eksisterende gruppe';
|
||||
$lang['delGroup'] = 'SQL-uttrykk for å fjerne en gruppe';
|
||||
$lang['getUserID'] = 'SQL-uttrykk for å hente primærnøkkel for en bruker';
|
||||
$lang['delUser'] = 'SQL-utrykk for å slette en bruker';
|
||||
$lang['delUserRefs'] = 'SQL-utrykk for å fjerne en bruke fra alle grupper';
|
||||
$lang['updateUser'] = 'SQL-uttrykk for å oppdatere en brukerprofil';
|
||||
$lang['UpdateLogin'] = 'Update-utrykk for å oppdatere brukernavn';
|
||||
$lang['UpdatePass'] = 'Update-utrykk for å oppdatere brukers passord';
|
||||
$lang['UpdateEmail'] = 'Update-utrykk for å oppdatere brukers e-postadresse';
|
||||
$lang['UpdateName'] = 'Update-utrykk for å oppdatere brukers fulle navn';
|
||||
$lang['UpdateTarget'] = 'Limit-uttrykk for å identifisere brukeren ved oppdatering';
|
||||
$lang['delUserGroup'] = 'SQL-uttrykk for å fjerne en bruker fra en gitt gruppe';
|
||||
$lang['getGroupID'] = 'SQL-uttrykk for å hente primærnøkkel for en gitt gruppe ';
|
||||
$lang['debug_o_0'] = 'ingen';
|
||||
$lang['debug_o_1'] = 'bare ved feil';
|
||||
$lang['debug_o_2'] = 'alle SQL-spørringer';
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
*
|
||||
* @author Arne Hanssen <arne.hanssen@getmail.no>
|
||||
*/
|
||||
$lang['server'] = 'Din PostgreSQL-server';
|
||||
$lang['port'] = 'Porten til din PostgreSQL-server';
|
||||
$lang['user'] = 'PostgreSQL-brukernavn';
|
||||
$lang['password'] = 'Passord til bruker over';
|
||||
$lang['database'] = 'Database som brukes';
|
||||
$lang['debug'] = 'Vis utvidet feilinformasjon';
|
||||
$lang['forwardClearPass'] = 'Videresendt passord i klartekst til SQL-uttrykket under, i stedet for å bruke det krypterte passordet';
|
||||
$lang['checkPass'] = 'SQL-uttrykk for å sjekke passordet';
|
||||
$lang['getUserInfo'] = 'SQL-uttrykk for å hente informasjon om en bruker';
|
||||
$lang['getGroups'] = 'SQL-uttrykk for å hente gruppene en bruker tilhører';
|
||||
$lang['getUsers'] = 'SQL-uttrykk for å liste alle brukere ';
|
||||
$lang['FilterLogin'] = 'SQL-uttrykk for å filtrere brukere etter brukernavn';
|
||||
$lang['FilterName'] = 'SQL-uttrykk for å filtrere brukere etter fult navn';
|
||||
$lang['FilterEmail'] = 'SQL-uttrykk for å filtrere brukere etter e-postadresse';
|
||||
$lang['FilterGroup'] = 'SQL-uttrykk for å filtrere brukere etter hvilken grupper de tilhører';
|
||||
$lang['SortOrder'] = 'SQL-uttrykk for å sortere brukere';
|
||||
$lang['addUser'] = 'SQL-uttrykk for å legge til en ny bruker';
|
||||
$lang['addGroup'] = 'SQL-uttrykk for å legge til en ny gruppe';
|
||||
$lang['addUserGroup'] = 'SQL-uttrykk for å legge til en bruker i en eksisterende gruppe';
|
||||
$lang['delGroup'] = 'SQL-uttrykk for å fjerne en gruppe ';
|
||||
$lang['getUserID'] = 'SQL-uttrykk for å hente primærnøkkel for en gitt bruker';
|
||||
$lang['delUser'] = 'SQL-utrykk for å slette en bruker ';
|
||||
$lang['delUserRefs'] = 'SQL-utrykk for å fjerne en bruke fra alle grupper';
|
||||
$lang['updateUser'] = 'SQL-uttrykk for å oppdatere en brukerprofil';
|
||||
$lang['UpdateLogin'] = 'Update-utrykk for å oppdatere brukernavn';
|
||||
$lang['UpdatePass'] = 'Update-utrykk for å oppdatere brukers passord';
|
||||
$lang['UpdateEmail'] = 'Update-utrykk for å oppdatere brukers e-postadresse';
|
||||
$lang['UpdateName'] = 'Update-utrykk for å oppdatere brukers fulle navn';
|
||||
$lang['UpdateTarget'] = 'Limit-uttrykk for å identifisere brukeren ved oppdatering';
|
||||
$lang['delUserGroup'] = 'SQL-uttrykk for fjerne en bruker fra gitt gruppe';
|
||||
$lang['getGroupID'] = 'SQL-uttrykk for å hente primærnøkkel for en gitt gruppe';
|
|
@ -3,6 +3,7 @@
|
|||
/**
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
*
|
||||
* @author Christian McKenna <mckchr@banenor.no>
|
||||
* @author Thomas Nygreen <nygreen@gmail.com>
|
||||
* @author Arild Burud <arildb@met.no>
|
||||
* @author Torkill Bruland <torkar-b@online.no>
|
||||
|
@ -12,12 +13,10 @@
|
|||
* @author Knut Staring <knutst@gmail.com>
|
||||
* @author Lisa Ditlefsen <lisa@vervesearch.com>
|
||||
* @author Erik Pedersen <erik.pedersen@shaw.ca>
|
||||
* @author Erik Bjørn Pedersen <erik.pedersen@shaw.ca>
|
||||
* @author Rune Rasmussen syntaxerror.no@gmail.com
|
||||
* @author Rune Rasmussen <syntaxerror.no@gmail.com>
|
||||
* @author Jon Bøe <jonmagneboe@hotmail.com>
|
||||
* @author Egil Hansen <egil@rosetta.no>
|
||||
* @author Arne Hanssen <arne.hanssen@getmail.no>
|
||||
* @author Arne Hanssen <arnehans@getmail.no>
|
||||
* @author Patrick Sletvold <patricksletvold@hotmail.com>
|
||||
*/
|
||||
$lang['menu'] = 'Konfigurasjonsinnstillinger';
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
* @author Knut Staring <knutst@gmail.com>
|
||||
* @author Lisa Ditlefsen <lisa@vervesearch.com>
|
||||
* @author Erik Pedersen <erik.pedersen@shaw.ca>
|
||||
* @author Erik Bjørn Pedersen <erik.pedersen@shaw.ca>
|
||||
* @author Rune Rasmussen syntaxerror.no@gmail.com
|
||||
* @author Rune Rasmussen <syntaxerror.no@gmail.com>
|
||||
* @author Thomas Nygreen <nygreen@gmail.com>
|
||||
* @author Jon Bøe <jonmagneboe@hotmail.com>
|
||||
* @author Egil Hansen <egil@rosetta.no>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
/**
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
*
|
||||
* @author Christian McKenna <mckchr@banenor.no>
|
||||
* @author Thomas Nygreen <nygreen@gmail.com>
|
||||
* @author Arild Burud <arildb@met.no>
|
||||
* @author Torkill Bruland <torkar-b@online.no>
|
||||
|
@ -12,8 +13,7 @@
|
|||
* @author Knut Staring <knutst@gmail.com>
|
||||
* @author Lisa Ditlefsen <lisa@vervesearch.com>
|
||||
* @author Erik Pedersen <erik.pedersen@shaw.ca>
|
||||
* @author Erik Bjørn Pedersen <erik.pedersen@shaw.ca>
|
||||
* @author Rune Rasmussen syntaxerror.no@gmail.com
|
||||
* @author Rune Rasmussen <syntaxerror.no@gmail.com>
|
||||
* @author Jon Bøe <jonmagneboe@hotmail.com>
|
||||
* @author Egil Hansen <egil@rosetta.no>
|
||||
* @author Thomas Juberg <Thomas.Juberg@Gmail.com>
|
||||
|
@ -22,7 +22,6 @@
|
|||
* @author Patrick <spill.p@hotmail.com>
|
||||
* @author Danny Buckhof <daniel.raknes@hotmail.no>
|
||||
* @author Arne Hanssen <arne.hanssen@getmail.no>
|
||||
* @author Arne Hanssen <arnehans@getmail.no>
|
||||
* @author Patrick Sletvold <patricksletvold@hotmail.com>
|
||||
*/
|
||||
$lang['menu'] = 'Tilbakestillingsbehandler';
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
*
|
||||
* @author Arne Hanssen <arne.hanssen@getmail.no>
|
||||
* @author Arne Hanssen <arnehans@getmail.no>
|
||||
*/
|
||||
$lang['menu'] = 'Innstillinger for malstil';
|
||||
$lang['js']['loader'] = 'Forhåndsvisning laster...<br />Dersom denne ikke forsvinner, kan det hende at dine verdier er feil';
|
||||
|
|
|
@ -12,8 +12,7 @@
|
|||
* @author Knut Staring <knutst@gmail.com>
|
||||
* @author Lisa Ditlefsen <lisa@vervesearch.com>
|
||||
* @author Erik Pedersen <erik.pedersen@shaw.ca>
|
||||
* @author Erik Bjørn Pedersen <erik.pedersen@shaw.ca>
|
||||
* @author Rune Rasmussen syntaxerror.no@gmail.com
|
||||
* @author Rune Rasmussen <syntaxerror.no@gmail.com>
|
||||
* @author Jon Bøe <jonmagneboe@hotmail.com>
|
||||
* @author Egil Hansen <egil@rosetta.no>
|
||||
* @author Arne Hanssen <arne.hanssen@getmail.no>
|
||||
|
|
|
@ -8,6 +8,13 @@ var dw_locktimer = {
|
|||
lasttime: null,
|
||||
msg: LANG.willexpire,
|
||||
pageid: '',
|
||||
fieldsToSaveAsDraft: [
|
||||
'input[name=prefix]',
|
||||
'textarea[name=wikitext]',
|
||||
'input[name=suffix]',
|
||||
'input[name=date]',
|
||||
],
|
||||
callbacks: [],
|
||||
|
||||
/**
|
||||
* Initialize the lock timer
|
||||
|
@ -42,6 +49,26 @@ var dw_locktimer = {
|
|||
dw_locktimer.reset();
|
||||
},
|
||||
|
||||
/**
|
||||
* Add another field of the editform to be posted to the server when a draft is saved
|
||||
*/
|
||||
addField: function(selector) {
|
||||
dw_locktimer.fieldsToSaveAsDraft.push(selector);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a callback that is executed when the post request to renew the lock and save the draft returns successfully
|
||||
*
|
||||
* If the user types into the edit-area, then dw_locktimer will regularly send a post request to the DokuWiki server
|
||||
* to extend the page's lock and update the draft. When this request returns successfully, then the draft__status
|
||||
* is updated. This method can be used to add further callbacks to be executed at that moment.
|
||||
*
|
||||
* @param {function} callback the only param is the data returned by the server
|
||||
*/
|
||||
addRefreshCallback: function(callback) {
|
||||
dw_locktimer.callbacks.push(callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* (Re)start the warning timer
|
||||
*/
|
||||
|
@ -77,25 +104,28 @@ var dw_locktimer = {
|
|||
var now = new Date(),
|
||||
params = 'call=lock&id=' + dw_locktimer.pageid + '&';
|
||||
|
||||
// refresh every minute only
|
||||
// refresh every half minute only
|
||||
if(now.getTime() - dw_locktimer.lasttime.getTime() <= 30*1000) {
|
||||
return;
|
||||
}
|
||||
|
||||
// POST everything necessary for draft saving
|
||||
if(dw_locktimer.draft && jQuery('#dw__editform').find('textarea[name=wikitext]').length > 0){
|
||||
params += jQuery('#dw__editform').find('input[name=prefix], ' +
|
||||
'textarea[name=wikitext], ' +
|
||||
'input[name=suffix], ' +
|
||||
'input[name=date]').serialize();
|
||||
params += jQuery('#dw__editform').find(dw_locktimer.fieldsToSaveAsDraft.join(', ')).serialize();
|
||||
}
|
||||
|
||||
jQuery.post(
|
||||
DOKU_BASE + 'lib/exe/ajax.php',
|
||||
params,
|
||||
dw_locktimer.refreshed,
|
||||
'html'
|
||||
);
|
||||
null,
|
||||
'json'
|
||||
).done(function dwLocktimerRefreshDoneHandler(data) {
|
||||
dw_locktimer.callbacks.forEach(
|
||||
function (callback) {
|
||||
callback(data);
|
||||
}
|
||||
);
|
||||
});
|
||||
dw_locktimer.lasttime = now;
|
||||
},
|
||||
|
||||
|
@ -103,13 +133,19 @@ var dw_locktimer = {
|
|||
* Callback. Resets the warning timer
|
||||
*/
|
||||
refreshed: function(data){
|
||||
var error = data.charAt(0);
|
||||
data = data.substring(1);
|
||||
if (data.errors.length) {
|
||||
data.errors.forEach(function(error) {
|
||||
jQuery('#draft__status').after(
|
||||
jQuery('<div class="error"></div>').text(error)
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
jQuery('#draft__status').html(data);
|
||||
if(error != '1') {
|
||||
jQuery('#draft__status').html(data.draft);
|
||||
if(data.lock !== '1') {
|
||||
return; // locking failed
|
||||
}
|
||||
dw_locktimer.reset();
|
||||
}
|
||||
};
|
||||
dw_locktimer.callbacks.push(dw_locktimer.refreshed);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
/*____________ toolbar ____________*/
|
||||
|
||||
.dokuwiki div.toolbar {
|
||||
display: inline-block;
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
#draft__status {
|
||||
|
|
Loading…
Reference in New Issue