/** * @param string $pageId wiki page ID to check * @throws Exception exception on error or nothing */ protected function checkPage($pageId) { if (empty($pageId)) { throw new Exception('No page ID was sent to delete.'); } if (auth_quickaclcheck($pageId) < AUTH_DELETE) { throw new Exception("You do not have permissions to delete page <b>{$pageId}</b>. You need AUTH_DELETE or higher rights"); } if (checklock($pageId)) { throw new Exception('Page is locked by another user'); } if (!checklock($pageId) && file_exists(wikiLockFN($pageId))) { throw new Exception('Page is locked by You. You cannot delete page during edit.'); } }
function clearLock($WIKI_ID) { global $USERNAME; if (!file_exists(wikiFN($WIKI_ID))) { fwrite(STDERR, "{$WIKI_ID} does not yet exist\n"); } $_SERVER['REMOTE_USER'] = $USERNAME; if (checklock($WIKI_ID)) { fwrite(STDERR, "Page {$WIKI_ID} is locked by another user\n"); exit(1); } unlock($WIKI_ID); if (file_exists(wikiLockFN($WIKI_ID))) { fwrite(STDERR, "Unable to clear lock for {$WIKI_ID}\n"); exit(1); } }
/** * Checks if 'newentry' was given as action, if so we * do handle the event our self and no further checking takes place */ function handle_act_preprocess(&$event, $param) { //if ($event->data != 'newentry') return; // nothing to do for us global $ACT; global $ID; echo "param={$param}"; return; // we can handle it -> prevent others $event->stopPropagation(); $event->preventDefault(); $ns = $_REQUEST['ns']; $title = str_replace(':', '', $_REQUEST['title']); $id = ($ns ? $ns . ':' : '') . cleanID($title); // check if we are allowed to create this file if (auth_quickaclcheck($id) >= AUTH_CREATE) { $back = $ID; $ID = $id; $file = wikiFN($ID); //check if locked by anyone - if not lock for my self if (checklock($ID)) { $ACT = 'locked'; } else { lock($ID); } // prepare the new thread file with default stuff if (!@file_exists($file)) { global $TEXT; global $INFO; global $conf; $TEXT = pageTemplate($ns . ':' . $title); if (!$TEXT) { $TEXT = "====== {$title} ======\n\n\n\n" . "~~DISCUSSION~~\n"; } $ACT = 'preview'; } else { $ACT = 'edit'; } } else { $ACT = 'show'; } }
/** * Rewrite pages when they are read and they need to be updated. * * @param Doku_Event $event The event object * @param mixed $param Optional parameters (not used) */ function handle_read(Doku_Event $event, $param) { global $ACT, $conf; static $stack = array(); // handle only reads of the current revision if ($event->data[3]) { return; } // only rewrite if not in move already $save = true; if (helper_plugin_move_rewrite::isLocked()) { $save = false; } $id = $event->data[2]; if ($event->data[1]) { $id = $event->data[1] . ':' . $id; } if (!$id) { // try to reconstruct the id from the filename $path = $event->data[0][0]; if (strpos($path, $conf['datadir']) === 0) { $path = substr($path, strlen($conf['datadir']) + 1); $id = pathID($path); } } if (isset($stack[$id])) { return; } // Don't change the page when the user is currently changing the page content or the page is locked $forbidden_actions = array('save', 'preview', 'recover', 'revert'); if (isset($ACT) && (in_array($ACT, $forbidden_actions) || is_array($ACT) && in_array(key($ACT), $forbidden_actions)) || checklock($id) !== false || @file_exists(wikiLockFN($id))) { return; } /** @var helper_plugin_move_rewrite $helper */ $helper = plugin_load('helper', 'move_rewrite', true); if (!is_null($helper)) { $stack[$id] = true; $event->result = $helper->rewritePage($id, $event->result, $save); unset($stack[$id]); } }
/** * Rewrite pages when they are read and they need to be updated. * * @param Doku_Event $event The event object * @param mixed $param Optional parameters (not used) */ function handle_read(Doku_Event $event, $param) { global $ACT, $conf; static $stack = array(); // handle only reads of the current revision if ($event->data[3]) return; $id = $event->data[2]; if ($event->data[1]) $id = $event->data[1].':'.$id; if (!$id) { // try to reconstruct the id from the filename $path = $event->data[0][0]; if (strpos($path, $conf['datadir']) === 0) { $path = substr($path, strlen($conf['datadir'])+1); $id = pathID($path); } } if (isset($stack[$id])) return; // Don't change the page when the user is currently changing the page content or the page is locked $forbidden_actions = array('save', 'preview', 'recover', 'revert'); if ((isset($ACT) && ( in_array($ACT, $forbidden_actions) || (is_array($ACT) && in_array(key($ACT), $forbidden_actions) ))) // checklock checks if the page lock hasn't expired and the page hasn't been locked by another user // the file exists check checks if the page is reported unlocked if a lock exists which means that // the page is locked by the current user || checklock($id) !== false || @file_exists(wikiLockFN($id))) return; /** @var helper_plugin_move $helper */ $helper = $this->loadHelper('move', true); if(!is_null($helper)) { $stack[$id] = true; $event->result = $helper->execute_rewrites($id, $event->result); unset($stack[$id]); } }
/** * Create the form to edit schemadata * * @param string $tablename * @return string The HTML for this schema's form */ protected function createForm($tablename) { global $ID; global $REV; global $INPUT; if (auth_quickaclcheck($ID) == AUTH_READ) { return ''; } if (checklock($ID)) { return ''; } $schema = AccessTable::byTableName($tablename, $ID, $REV); if (!$schema->getSchema()->isEditable()) { return ''; } $schemadata = $schema->getData(); $structdata = $INPUT->arr(self::$VAR); if (isset($structdata[$tablename])) { $postdata = $structdata[$tablename]; } else { $postdata = array(); } // we need a short, unique identifier to use in the cookie. this should be good enough $schemaid = 'SRCT' . substr(str_replace(array('+', '/'), '', base64_encode(sha1($tablename, true))), 0, 5); $html = '<fieldset data-schema="' . $schemaid . '">'; $html .= '<legend>' . hsc($tablename) . '</legend>'; foreach ($schemadata as $field) { $label = $field->getColumn()->getLabel(); if (isset($postdata[$label])) { // posted data trumps stored data $field->setValue($postdata[$label], true); } $html .= $this->makeField($field, self::$VAR . "[{$tablename}][{$label}]"); } $html .= '</fieldset>'; return $html; }
/** * Check if the given page can be moved to the given destination * * @param $src * @param $dst * @return bool */ public function checkPage($src, $dst) { // Check we have rights to move this document if (!page_exists($src)) { msg(sprintf($this->getLang('notexist'), $src), -1); return false; } if (auth_quickaclcheck($src) < AUTH_EDIT) { msg(sprintf($this->getLang('norights'), $src), -1); return false; } // Check file is not locked // checklock checks if the page lock hasn't expired and the page hasn't been locked by another user // the file exists check checks if the page is reported unlocked if a lock exists which means that // the page is locked by the current user if (checklock($src) !== false || @file_exists(wikiLockFN($src))) { msg(sprintf($this->getLang('filelocked'), $src), -1); return false; } // Has the document name and/or namespace changed? if ($src == $dst) { msg(sprintf($this->getLang('notchanged'), $src), -1); return false; } // Check the page does not already exist if (page_exists($dst)) { msg(sprintf($this->getLang('exists'), $src, $dst), -1); return false; } // Check if the current user can create the new page if (auth_quickaclcheck($dst) < AUTH_CREATE) { msg(sprintf($this->getLang('notargetperms'), $dst), -1); return false; } return true; }
/** * Return info about the current document as associative * array. * * @author Andreas Gohr <*****@*****.**> * * @return array with info about current document */ function pageinfo() { global $ID; global $REV; global $RANGE; global $lang; /* @var Input $INPUT */ global $INPUT; $info = basicinfo($ID); // include ID & REV not redundant, as some parts of DokuWiki may temporarily change $ID, e.g. p_wiki_xhtml // FIXME ... perhaps it would be better to ensure the temporary changes weren't necessary $info['id'] = $ID; $info['rev'] = $REV; if ($INPUT->server->has('REMOTE_USER')) { $sub = new Subscription(); $info['subscribed'] = $sub->user_subscription(); } else { $info['subscribed'] = false; } $info['locked'] = checklock($ID); $info['filepath'] = fullpath(wikiFN($ID)); $info['exists'] = file_exists($info['filepath']); $info['currentrev'] = @filemtime($info['filepath']); if ($REV) { //check if current revision was meant if ($info['exists'] && $info['currentrev'] == $REV) { $REV = ''; } elseif ($RANGE) { //section editing does not work with old revisions! $REV = ''; $RANGE = ''; msg($lang['nosecedit'], 0); } else { //really use old revision $info['filepath'] = fullpath(wikiFN($ID, $REV)); $info['exists'] = file_exists($info['filepath']); } } $info['rev'] = $REV; if ($info['exists']) { $info['writable'] = is_writable($info['filepath']) && $info['perm'] >= AUTH_EDIT; } else { $info['writable'] = $info['perm'] >= AUTH_CREATE; } $info['editable'] = $info['writable'] && empty($info['locked']); $info['lastmod'] = @filemtime($info['filepath']); //load page meta data $info['meta'] = p_get_metadata($ID); //who's the editor $pagelog = new PageChangeLog($ID, 1024); if ($REV) { $revinfo = $pagelog->getRevisionInfo($REV); } else { if (!empty($info['meta']['last_change']) && is_array($info['meta']['last_change'])) { $revinfo = $info['meta']['last_change']; } else { $revinfo = $pagelog->getRevisionInfo($info['lastmod']); // cache most recent changelog line in metadata if missing and still valid if ($revinfo !== false) { $info['meta']['last_change'] = $revinfo; p_set_metadata($ID, array('last_change' => $revinfo)); } } } //and check for an external edit if ($revinfo !== false && $revinfo['date'] != $info['lastmod']) { // cached changelog line no longer valid $revinfo = false; $info['meta']['last_change'] = $revinfo; p_set_metadata($ID, array('last_change' => $revinfo)); } $info['ip'] = $revinfo['ip']; $info['user'] = $revinfo['user']; $info['sum'] = $revinfo['sum']; // See also $INFO['meta']['last_change'] which is the most recent log line for page $ID. // Use $INFO['meta']['last_change']['type']===DOKU_CHANGE_TYPE_MINOR_EDIT in place of $info['minor']. if ($revinfo['user']) { $info['editor'] = $revinfo['user']; } else { $info['editor'] = $revinfo['ip']; } // 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; } } return $info; }
/** * Determines if it would be okay to show a rename page button for the given page and current user * * @param $id * @return bool */ public function renameOkay($id) { global $ACT; global $USERINFO; if (!($ACT == 'show' || empty($ACT))) { return false; } if (!page_exists($id)) { return false; } if (auth_quickaclcheck($id) < AUTH_EDIT) { return false; } if (checklock($id) !== false || @file_exists(wikiLockFN($id))) { return false; } if (!isset($_SERVER['REMOTE_USER'])) { return false; } if (!auth_isMember($this->getConf('allowrename'), $_SERVER['REMOTE_USER'], (array) $USERINFO['grps'])) { return false; } return true; }
/** * Save a wiki page * * @author Michael Klier <*****@*****.**> */ function putPage($id, $text, $params) { global $TEXT; global $lang; global $conf; $id = cleanID($id); $TEXT = trim($text); $sum = $params['sum']; $minor = $params['minor']; if (empty($id)) { return new IXR_Error(1, 'Empty page ID'); } if (!page_exists($id) && empty($TEXT)) { return new IXR_ERROR(1, 'Refusing to write an empty new wiki page'); } if (auth_quickaclcheck($id) < AUTH_EDIT) { return new IXR_Error(1, 'You are not allowed to edit this page'); } // Check, if page is locked if (checklock($id)) { return new IXR_Error(1, 'The page is currently locked'); } // SPAM check if (checkwordblock()) { return new IXR_Error(1, 'Positive wordblock check'); } // autoset summary on new pages if (!page_exists($id) && empty($sum)) { $sum = $lang['created']; } // autoset summary on deleted pages if (page_exists($id) && empty($TEXT) && empty($sum)) { $sum = $lang['deleted']; } lock($id); saveWikiText($id, $TEXT, $sum, $minor); unlock($id); // run the indexer if page wasn't indexed yet if (!@file_exists(metaFN($id, '.indexed'))) { // try to aquire a lock $lock = $conf['lockdir'] . '/_indexer.lock'; while (!@mkdir($lock, $conf['dmode'])) { usleep(50); if (time() - @filemtime($lock) > 60 * 5) { // looks like a stale lock - remove it @rmdir($lock); } else { return false; } } if ($conf['dperm']) { chmod($lock, $conf['dperm']); } require_once DOKU_INC . 'inc/indexer.php'; // do the work idx_addPage($id); // we're finished - save and free lock io_saveFile(metaFN($id, '.indexed'), INDEXER_VERSION); @rmdir($lock); } return 0; }
/** * Lock files that will be modified on either side. * * Lock fails are printed and removed from synclist * * @returns list of locked files */ function _lockFiles(&$synclist) { if (!$this->_connect()) { return array(); } // lock the files $lock = array(); foreach ((array) $synclist as $id => $dir) { if ($dir == 0) { continue; } if (checklock($id)) { $this->_listOut($this->getLang('lockfail') . ' ' . hsc($id), 'error'); unset($synclist[$id]); } else { lock($id); // lock local $lock[] = $id; } } // lock remote files $ok = $this->client->query('dokuwiki.setLocks', array('lock' => $lock, 'unlock' => array())); if (!$ok) { $this->_listOut('failed RPC communication'); $synclist = array(); return array(); } $data = $this->client->getResponse(); foreach ((array) $data['lockfail'] as $id) { $this->_listOut($this->getLang('lockfail') . ' ' . hsc($id), 'error'); unset($synclist[$id]); } return $lock; }
function a_control($p) {//{{{ global $cf_datadir,$SCRIPT_NAME, $action; if (is_file("$cf_datadir$p")) { $r = checklock($p); if ($r) { $cm_nav.= "<div class=menu>"; $cm_nav.= "<img src=/picto/locked.png width=8 height=8 vspace=2 hspace=3 border=0 alt='' align=left>"; $cm_nav.= "Fichier Vérouillé<br clear=all></div><div class=file><b>$r[who]</b><br>$r[when]</div>\n"; $cm_nav.= "<a href='$SCRIPT_NAME?p=".urlencode($p)."&action=ulk' class=bmenu>"; $cm_nav.= "<img src=/picto/unlocked.png width=8 height=8 vspace=2 hspace=3 border=0 alt='' align=left>Dévérouiller</a><br clear=all>"; $cm_nav.= "</div><br><div class=file>"; $cm_nav.= a_listhistory($p,'his'); $cm_nav.= "</div>"; } else { $cm_nav = "<div class=menu>"; $cm_nav.= "<a href='$SCRIPT_NAME?p=".urlencode($p)."&action=ren' class=bmenu>"; $cm_nav.= "<img src=/picto/pencil.png width=8 height=8 vspace=2 hspace=3 border=0 alt='' align=left>Renommer</a><br clear=all>"; if (((strstr($p,'_images')) or (strstr($p,'_docs'))) && (!is_file("$cf_datadir$p"))){ $cm_nav.= "<a href='$SCRIPT_NAME?p=".urlencode($p)."&action=upl' class=bmenu>"; $cm_nav.= "<img src=/picto/newfile.png width=8 height=8 vspace=2 hspace=3 border=0 alt='' align=left>Uploader</a><br clear=all>"; } elseif ((!strstr($p,'_images')) && (!strstr($p,'_docs'))) { $cm_nav.= "<a href='$SCRIPT_NAME?p=".urlencode($p)."&action=dit' class=bmenu>"; $cm_nav.= "<img src=/picto/pencil.png width=8 height=8 vspace=2 hspace=3 border=0 alt='' align=left>Editer</a><br clear=all>"; $cm_nav.= "<a href='$SCRIPT_NAME?p=".urlencode($p)."&action=dix' class=bmenu>"; $cm_nav.= "<img src=/picto/pencil.png width=8 height=8 vspace=2 hspace=3 border=0 alt='' align=left>Editer (brut)</a><br clear=all>"; } $cm_nav.= "</div>"; $cm_nav.= "<div class=menu>"; $cm_nav.= "<a href='$SCRIPT_NAME?p=".urlencode($p)."&action=arc' class=bmenu>"; $cm_nav.= "<img src=/picto/kill.png width=8 height=8 vspace=2 hspace=3 border=0 alt='' align=left>Effacer</a><br clear=all>"; $cm_nav.= "</div><br><div class=file>"; $cm_nav.= a_listhistory($p,'his'); $cm_nav.= "</div>"; } } elseif (is_dir("$cf_datadir$p")) { $cm_nav = "<div class=menu>"; $cm_nav.= "<a href='$SCRIPT_NAME?p=".urlencode($p)."&action=ren' class=bmenu>"; $cm_nav.= "<img src=/picto/pencil.png width=8 height=8 vspace=2 hspace=3 border=0 alt='' align=left>Renommer <u>".basename($p)."</u></a><br clear=all>"; $cm_nav.= "<a href='$SCRIPT_NAME?p=".urlencode($p)."&action=arc' class=bmenu>"; $cm_nav.= "<img src=/picto/kill.png width=8 height=8 vspace=2 hspace=3 border=0 alt='' align=left>Effacer <u>".basename($p)."</u></a><br clear=all>"; $cm_nav.= "</div>"; $cm_nav.= "<div class=menu>"; $cm_nav.= "<a href='$SCRIPT_NAME?p=".urlencode($p)."&action=mkd' class=bmenu>"; $cm_nav.= "<img src=/picto/newfolder2.png width=8 height=8 vspace=2 hspace=3 border=0 alt='' align=left>Nouveau Dossier</a><br clear=all>"; if ((strstr($p,'_images')) or (strstr($p,'_docs'))) { $cm_nav.= "<a href='$SCRIPT_NAME?p=".urlencode($p)."&action=upl' class=bmenu>"; $cm_nav.= "<img src=/picto/newfile.png width=8 height=8 vspace=2 hspace=3 border=0 alt='' align=left>Uploader</a><br clear=all>"; } else { $cm_nav.= "<a href='$SCRIPT_NAME?p=".urlencode($p)."&action=new' class=bmenu>"; $cm_nav.= "<img src=/picto/newfile.png width=8 height=8 vspace=2 hspace=3 border=0 alt='' align=left>Nouveau Fichier</a><br clear=all>"; } $cm_nav.= "<a href='$SCRIPT_NAME?p=".urlencode($p)."&action=idx' class=bmenu>"; $cm_nav.= "<img src=/picto/regen.png width=8 height=8 vspace=2 hspace=3 border=0 alt='' align=left>Recalculer</a><br clear=all>"; $cm_nav.= "</div>"; } elseif ($action == "new") { $cm_nav = "Nouveau Fichier"; } else { $cm_nav = "error"; } return $cm_nav; }//}}}
/** * Locks or unlocks a given batch of pages * * Give an associative array with two keys: lock and unlock. Both should contain a * list of pages to lock or unlock * * Returns an associative array with the keys locked, lockfail, unlocked and * unlockfail, each containing lists of pages. */ function setLocks($set) { $locked = array(); $lockfail = array(); $unlocked = array(); $unlockfail = array(); foreach ((array) $set['lock'] as $id) { if (checklock($id)) { $lockfail[] = $id; } else { lock($id); $locked[] = $id; } } foreach ((array) $set['unlock'] as $id) { if (unlock($id)) { $unlocked[] = $id; } else { $unlockfail[] = $id; } } return array('locked' => $locked, 'lockfail' => $lockfail, 'unlocked' => $unlocked, 'unlockfail' => $unlockfail); }
/** * Return info about the current document as associative * array. * * @author Andreas Gohr <*****@*****.**> */ function pageinfo() { global $ID; global $REV; global $RANGE; global $USERINFO; global $lang; // include ID & REV not redundant, as some parts of DokuWiki may temporarily change $ID, e.g. p_wiki_xhtml // FIXME ... perhaps it would be better to ensure the temporary changes weren't necessary $info['id'] = $ID; $info['rev'] = $REV; // set info about manager/admin status. $info['isadmin'] = false; $info['ismanager'] = false; if (isset($_SERVER['REMOTE_USER'])) { $info['userinfo'] = $USERINFO; $info['perm'] = auth_quickaclcheck($ID); $info['subscribed'] = get_info_subscribed(); $info['client'] = $_SERVER['REMOTE_USER']; if ($info['perm'] == AUTH_ADMIN) { $info['isadmin'] = true; $info['ismanager'] = true; } elseif (auth_ismanager()) { $info['ismanager'] = true; } // if some outside auth were used only REMOTE_USER is set if (!$info['userinfo']['name']) { $info['userinfo']['name'] = $_SERVER['REMOTE_USER']; } } else { $info['perm'] = auth_aclcheck($ID, '', null); $info['subscribed'] = false; $info['client'] = clientIP(true); } $info['namespace'] = getNS($ID); $info['locked'] = checklock($ID); $info['filepath'] = fullpath(wikiFN($ID)); $info['exists'] = @file_exists($info['filepath']); if ($REV) { //check if current revision was meant if ($info['exists'] && @filemtime($info['filepath']) == $REV) { $REV = ''; } elseif ($RANGE) { //section editing does not work with old revisions! $REV = ''; $RANGE = ''; msg($lang['nosecedit'], 0); } else { //really use old revision $info['filepath'] = fullpath(wikiFN($ID, $REV)); $info['exists'] = @file_exists($info['filepath']); } } $info['rev'] = $REV; if ($info['exists']) { $info['writable'] = is_writable($info['filepath']) && $info['perm'] >= AUTH_EDIT; } else { $info['writable'] = $info['perm'] >= AUTH_CREATE; } $info['editable'] = $info['writable'] && empty($info['locked']); $info['lastmod'] = @filemtime($info['filepath']); //load page meta data $info['meta'] = p_get_metadata($ID); //who's the editor if ($REV) { $revinfo = getRevisionInfo($ID, $REV, 1024); } else { if (is_array($info['meta']['last_change'])) { $revinfo = $info['meta']['last_change']; } else { $revinfo = getRevisionInfo($ID, $info['lastmod'], 1024); // cache most recent changelog line in metadata if missing and still valid if ($revinfo !== false) { $info['meta']['last_change'] = $revinfo; p_set_metadata($ID, array('last_change' => $revinfo)); } } } //and check for an external edit if ($revinfo !== false && $revinfo['date'] != $info['lastmod']) { // cached changelog line no longer valid $revinfo = false; $info['meta']['last_change'] = $revinfo; p_set_metadata($ID, array('last_change' => $revinfo)); } $info['ip'] = $revinfo['ip']; $info['user'] = $revinfo['user']; $info['sum'] = $revinfo['sum']; // See also $INFO['meta']['last_change'] which is the most recent log line for page $ID. // Use $INFO['meta']['last_change']['type']===DOKU_CHANGE_TYPE_MINOR_EDIT in place of $info['minor']. if ($revinfo['user']) { $info['editor'] = $revinfo['user']; } else { $info['editor'] = $revinfo['ip']; } // 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; } } // mobile detection $info['ismobile'] = clientismobile(); return $info; }
/** * Refresh a page lock and save draft * * Andreas Gohr <*****@*****.**> */ function ajax_lock() { global $conf; global $lang; $id = cleanID($_POST['id']); if (empty($id)) { return; } if (!checklock($id)) { lock($id); echo 1; } if ($conf['usedraft'] && $_POST['wikitext']) { $client = $_SERVER['REMOTE_USER']; if (!$client) { $client = clientIP(true); } $draft = array('id' => $id, 'prefix' => substr($_POST['prefix'], 0, -1), 'text' => $_POST['wikitext'], 'suffix' => $_POST['suffix'], 'date' => (int) $_POST['date'], 'client' => $client); $cname = getCacheName($draft['client'] . $id, '.draft'); if (io_saveFile($cname, serialize($draft))) { echo $lang['draftdate'] . ' ' . dformat(); } } }
/** * Return info about the current document as associative * array. * * @author Andreas Gohr <*****@*****.**> */ function pageinfo() { global $ID; global $REV; global $USERINFO; global $conf; // include ID & REV not redundant, as some parts of DokuWiki may temporarily change $ID, e.g. p_wiki_xhtml // FIXME ... perhaps it would be better to ensure the temporary changes weren't necessary $info['id'] = $ID; $info['rev'] = $REV; if ($_SERVER['REMOTE_USER']) { $info['userinfo'] = $USERINFO; $info['perm'] = auth_quickaclcheck($ID); $info['subscribed'] = is_subscribed($ID, $_SERVER['REMOTE_USER']); $info['client'] = $_SERVER['REMOTE_USER']; // if some outside auth were used only REMOTE_USER is set if (!$info['userinfo']['name']) { $info['userinfo']['name'] = $_SERVER['REMOTE_USER']; } } else { $info['perm'] = auth_aclcheck($ID, '', null); $info['subscribed'] = false; $info['client'] = clientIP(true); } $info['namespace'] = getNS($ID); $info['locked'] = checklock($ID); $info['filepath'] = realpath(wikiFN($ID)); $info['exists'] = @file_exists($info['filepath']); if ($REV) { //check if current revision was meant if ($info['exists'] && @filemtime($info['filepath']) == $REV) { $REV = ''; } else { //really use old revision $info['filepath'] = realpath(wikiFN($ID, $REV)); $info['exists'] = @file_exists($info['filepath']); } } $info['rev'] = $REV; if ($info['exists']) { $info['writable'] = is_writable($info['filepath']) && $info['perm'] >= AUTH_EDIT; } else { $info['writable'] = $info['perm'] >= AUTH_CREATE; } $info['editable'] = $info['writable'] && empty($info['lock']); $info['lastmod'] = @filemtime($info['filepath']); //load page meta data $info['meta'] = p_get_metadata($ID); //who's the editor if ($REV) { $revinfo = getRevisionInfo($ID, $REV, 1024); } else { $revinfo = isset($info['meta']['last_change']) ? $info['meta']['last_change'] : getRevisionInfo($ID, $info['lastmod'], 1024); } $info['ip'] = $revinfo['ip']; $info['user'] = $revinfo['user']; $info['sum'] = $revinfo['sum']; // See also $INFO['meta']['last_change'] which is the most recent log line for page $ID. // Use $INFO['meta']['last_change']['type']==='e' in place of $info['minor']. if ($revinfo['user']) { $info['editor'] = $revinfo['user']; } else { $info['editor'] = $revinfo['ip']; } // 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; } } return $info; }
/** * Handle 'edit', 'preview', 'recover' * * @author Andreas Gohr <*****@*****.**> */ function act_edit($act) { global $ID; global $INFO; global $TEXT; global $RANGE; global $PRE; global $SUF; global $REV; global $SUM; global $lang; global $DATE; if (!isset($TEXT)) { if ($INFO['exists']) { if ($RANGE) { list($PRE, $TEXT, $SUF) = rawWikiSlices($RANGE, $ID, $REV); } else { $TEXT = rawWiki($ID, $REV); } } else { $TEXT = pageTemplate($ID); } } //set summary default if (!$SUM) { if ($REV) { $SUM = $lang['restored']; } elseif (!$INFO['exists']) { $SUM = $lang['created']; } } // Use the date of the newest revision, not of the revision we edit // This is used for conflict detection if (!$DATE) { $DATE = $INFO['meta']['date']['modified']; } //check if locked by anyone - if not lock for my self $lockedby = checklock($ID); if ($lockedby) { return 'locked'; } lock($ID); return $act; }
/** * Handle 'edit', 'preview', 'recover' * * @author Andreas Gohr <*****@*****.**> */ function act_edit($act) { global $ID; global $INFO; global $TEXT; global $RANGE; global $PRE; global $SUF; global $REV; global $SUM; global $lang; global $DATE; if (!isset($TEXT)) { if ($INFO['exists']) { if ($RANGE) { list($PRE, $TEXT, $SUF) = rawWikiSlices($RANGE, $ID, $REV); } else { $TEXT = rawWiki($ID, $REV); } } else { $TEXT = pageTemplate($ID); } } //set summary default if (!$SUM) { if ($REV) { $SUM = sprintf($lang['restored'], dformat($REV)); } elseif (!$INFO['exists']) { $SUM = $lang['created']; } } // Use the date of the newest revision, not of the revision we edit // This is used for conflict detection if (!$DATE) { $DATE = @filemtime(wikiFN($ID)); } //check if locked by anyone - if not lock for my self //do not lock when the user can't edit anyway if ($INFO['writable']) { $lockedby = checklock($ID); if ($lockedby) { return 'locked'; } lock($ID); } return $act; }
/** * move page * * @author Gary Owen <*****@*****.**>, modified by Kay Roesler * @author Michael Hamann <*****@*****.**> * * @param array $opts * @param bool $checkonly Only execute the checks if the page can be moved * @return bool If the move was executed */ public function move_page(&$opts, $checkonly = false) { global $ID; // Check we have rights to move this document if ( !page_exists($ID)) { msg(sprintf($this->getLang('notexist'), $ID), -1); return false; } if ( auth_quickaclcheck($ID) < AUTH_EDIT ) { msg(sprintf($this->getLang('norights'), hsc($ID)), -1); return false; } // Check file is not locked // checklock checks if the page lock hasn't expired and the page hasn't been locked by another user // the file exists check checks if the page is reported unlocked if a lock exists which means that // the page is locked by the current user if (checklock($ID) !== false || @file_exists(wikiLockFN($ID))) { msg( sprintf($this->getLang('filelocked'), hsc($ID)), -1); return false; } // Assemble fill document name and path $opts['new_id'] = cleanID($opts['newns'].':'.$opts['newname']); $opts['new_path'] = wikiFN($opts['new_id']); // Has the document name and/or namespace changed? if ( $opts['newns'] == $opts['ns'] && $opts['newname'] == $opts['name'] ) { msg($this->getLang('nochange'), -1); return false; } // Check the page does not already exist if ( @file_exists($opts['new_path']) ) { msg(sprintf($this->getLang('existing'), $opts['newname'], ($opts['newns'] == '' ? $this->getLang('root') : $opts['newns'])), -1); return false; } // Check if the current user can create the new page if (auth_quickaclcheck($opts['new_id']) < AUTH_CREATE) { msg(sprintf($this->getLang('notargetperms'), $opts['new_id']), -1); return false; } if ($checkonly) return true; /** * End of init (checks) */ $page_meta = $this->getMoveMeta($ID); if (!$page_meta) $page_meta = array(); if (!isset($page_meta['old_ids'])) $page_meta['old_ids'] = array(); $page_meta['old_ids'][$ID] = time(); // ft_backlinks() is not used here, as it does a hidden page and acl check but we really need all pages $affected_pages = idx_get_indexer()->lookupKey('relation_references', $ID); $data = array('opts' => &$opts, 'old_ids' => $page_meta['old_ids'], 'affected_pages' => &$affected_pages); // give plugins the option to add their own meta files to the list of files that need to be moved // to the oldfiles/newfiles array or to adjust their own metadata, database, ... // and to add other pages to the affected pages // note that old_ids is in the form 'id' => timestamp of move $event = new Doku_Event('PLUGIN_MOVE_PAGE_RENAME', $data); if ($event->advise_before()) { // Open the old document and change forward links lock($ID); $text = rawWiki($ID); $text = $this->rewrite_content($text, $ID, array($ID => $opts['new_id'])); $oldRev = getRevisions($ID, -1, 1, 1024); // from changelog // Move the Subscriptions & Indexes if (method_exists('Doku_Indexer', 'renamePage')) { // new feature since Spring 2013 release $Indexer = idx_get_indexer(); } else { $Indexer = new helper_plugin_move_indexer(); // copy of the new code } if (($idx_msg = $Indexer->renamePage($ID, $opts['new_id'])) !== true || ($idx_msg = $Indexer->renameMetaValue('relation_references', $ID, $opts['new_id'])) !== true) { msg('Error while updating the search index '.$idx_msg, -1); return false; } if (!$this->movemeta($opts)) { msg('The meta files of page '.$ID.' couldn\'t be moved', -1); return false; } // Save the updated document in its new location if ($opts['ns'] == $opts['newns']) { $lang_key = 'renamed'; } elseif ( $opts['name'] == $opts['newname'] ) { $lang_key = 'moved'; } else { $lang_key = 'move_rename'; } // Wait a second when the page has just been rewritten if ($oldRev == time()) sleep(1); $summary = sprintf($this->getLang($lang_key), $ID, $opts['new_id']); saveWikiText($opts['new_id'], $text, $summary); // Delete the orginal file if (@file_exists(wikiFN($opts['new_id']))) { saveWikiText($ID, '', $this->getLang('delete') ); } // Move the old revisions if (!$this->moveattic($opts)) { // it's too late to stop the move, so just display a message. msg('The attic files of page '.$ID.' couldn\'t be moved. Please move them manually.', -1); } foreach ($affected_pages as $id) { if (!page_exists($id, '', false) || $id == $ID || $id == $opts['new_id']) continue; // we are only interested in persistent metadata, so no need to render anything. $meta = $this->getMoveMeta($id); if (!$meta) $meta = array('moves' => array()); if (!isset($meta['moves'])) $meta['moves'] = array(); $meta['moves'] = $this->resolve_moves($meta['moves'], $id); $meta['moves'][$ID] = $opts['new_id']; //if (empty($meta['moves'])) unset($meta['moves']); p_set_metadata($id, array('plugin_move' => $meta), false, true); } p_set_metadata($opts['new_id'], array('plugin_move' => $page_meta), false, true); unlock($ID); } $event->advise_after(); return true; }
/** * */ function _isEditAllowed($page) { $allowed = TRUE; if (auth_quickaclcheck($page) < AUTH_EDIT) { $this->warning[] = $this->getLang('war_norights', $page); $allowed = FALSE; } if ($allowed) { $lockedBy = checklock($page); if ($lockedBy != FALSE) { $this->warning[] = $this->getLang('war_pagelock', $page, $lockedBy); $allowed = FALSE; } } return $allowed; }
/** * Clear the lock on the given page * * @param string $wiki_id */ protected function clearLock($wiki_id) { if ($this->force) { $this->deleteLock($wiki_id); } $_SERVER['REMOTE_USER'] = $this->username; if (checklock($wiki_id)) { $this->error("Page {$wiki_id} is locked by another user"); exit(1); } unlock($wiki_id); if (file_exists(wikiLockFN($wiki_id))) { $this->error("Unable to clear lock for {$wiki_id}"); exit(1); } }
/** * Handle 'edit', 'preview' * * @author Andreas Gohr <*****@*****.**> */ function act_edit($act) { global $ID; global $INFO; //check if locked by anyone - if not lock for my self $lockedby = checklock($ID); if ($lockedby) { return 'locked'; } lock($ID); return $act; }
/** * Locks or unlocks a given batch of pages * * Give an associative array with two keys: lock and unlock. Both should contain a * list of pages to lock or unlock * * Returns an associative array with the keys locked, lockfail, unlocked and * unlockfail, each containing lists of pages. */ function setLocks($set) { $locked = array(); $lockfail = array(); $unlocked = array(); $unlockfail = array(); foreach ((array) $set['lock'] as $id) { $id = $this->resolvePageId($id); if (auth_quickaclcheck($id) < AUTH_EDIT || checklock($id)) { $lockfail[] = $id; } else { lock($id); $locked[] = $id; } } foreach ((array) $set['unlock'] as $id) { $id = $this->resolvePageId($id); if (auth_quickaclcheck($id) < AUTH_EDIT || !unlock($id)) { $unlockfail[] = $id; } else { $unlocked[] = $id; } } return array('locked' => $locked, 'lockfail' => $lockfail, 'unlocked' => $unlocked, 'unlockfail' => $unlockfail); }
/** * main functions */ function _rename_page(&$opts) { // check old page if (!$opts['oldpage']) { $this->errors[] = $this->getLang('rp_msg_old_empty'); } else { if (!page_exists($opts['oldpage'])) { $this->errors[] = sprintf($this->getLang('rp_msg_old_noexist'), $opts['oldpage']); } else { if (!$this->_auth_can_rename($opts['oldpage'])) { $this->errors[] = sprintf($this->getLang('rp_msg_auth'), $opts['oldpage']); } else { if (checklock($opts['oldpage'])) { $this->errors[] = sprintf($this->getLang('rp_msg_locked'), $opts['oldpage']); } } } } // check noredirect if ($opts['nr'] && !$this->_auth_can_rename_nr($opts['oldpage'])) { $this->errors[] = $this->getLang('rp_msg_auth_nr'); } // check new page if (!$opts['newpage']) { $this->errors[] = $this->getLang('rp_msg_new_empty'); } else { if (page_exists($opts['newpage'])) { $this->errors[] = sprintf($this->getLang('rp_msg_new_exist'), $opts['newpage']); } else { if (!$this->_auth_can_rename($opts['newpage'])) { $this->errors[] = sprintf($this->getLang('rp_msg_auth'), $opts['newpage']); } else { if (checklock($opts['newpage'])) { $this->errors[] = sprintf($this->getLang('rp_msg_locked'), $opts['newpage']); } } } } // try to locate moves if (!$this->errors) { $opts['move'] = true; $opts['oldname'] = $this->_FN(noNS($opts['oldpage'])); $opts['newname'] = $this->_FN(noNS($opts['newpage'])); $opts['oldns'] = $this->_FN(getNS($opts['oldpage'])); $opts['newns'] = $this->_FN(getNS($opts['newpage'])); if ($opts['oldns']) { $opts['oldns'] .= '/'; } if ($opts['newns']) { $opts['newns'] .= '/'; } $this->_locate_filepairs($opts, 'metadir', '/^' . $opts['oldname'] . '\\.(?!mlist|meta|indexed)\\w*?$/'); $this->_locate_filepairs($opts, 'olddir', '/^' . $opts['oldname'] . '\\.\\d{10}\\.txt(\\.gz|\\.bz2)?$/'); } // if no error do rename if (!$this->errors) { // move meta and attic $this->_apply_moves($opts); // save to newpage $text = rawWiki($opts['oldpage']); if ($opts['summary']) { $summary = sprintf($this->getLang('rp_newsummaryx'), $opts['oldpage'], $opts['newpage'], $opts['summary']); } else { $summary = sprintf($this->getLang('rp_newsummary'), $opts['oldpage'], $opts['newpage']); } saveWikiText($opts['newpage'], $text, $summary); // purge or recreate old page $summary = $opts['summary'] ? sprintf($this->getLang('rp_oldsummaryx'), $opts['oldpage'], $opts['newpage'], $opts['summary']) : sprintf($this->getLang('rp_oldsummary'), $opts['oldpage'], $opts['newpage']); if ($opts['nr']) { $this->_custom_delete_page($opts['oldpage'], $summary); // write change log afterwards, or it would be deleted addLogEntry(null, $opts['oldpage'], DOKU_CHANGE_TYPE_DELETE, $summary); // also writes to global changes unlink(metaFN($opts['oldpage'], '.changes')); // purge page changes } else { $text = $this->getConf('redirecttext'); if (!$text) { $text = $this->getLang('redirecttext'); } $text = str_replace('@ID@', $opts['newpage'], $text); @unlink(wikiFN($opts['oldpage'])); // remove old page file so no additional history saveWikiText($opts['oldpage'], $text, $summary); } } // show messages if ($this->errors) { foreach ($this->errors as $error) { msg($error, -1); } } else { $msg = sprintf($this->getLang('rp_msg_success'), $opts['oldpage'], $opts['newpage']); msg($msg, 1); } // display form and table $data = array(rp_newpage => $opts['newpage'], rp_summary => $opts['summary'], rp_nr => $opts['rp_nr']); $this->_print_form($data); }
/** * Checks if a page can be edited * * @throws StructException when check fails */ protected function checkPage() { if (!page_exists($this->pid)) { throw new StructException('inline save error: no such page'); } if (auth_quickaclcheck($this->pid) < AUTH_EDIT) { throw new StructException('inline save error: acl'); } if (checklock($this->pid)) { throw new StructException('inline save error: lock'); } }
/** * Refresh a page lock and save draft * * Andreas Gohr <*****@*****.**> */ function ajax_lock() { global $conf; global $lang; global $ID; global $INFO; global $INPUT; $ID = cleanID($INPUT->post->str('id')); if (empty($ID)) { return; } $INFO = pageinfo(); if (!$INFO['writable']) { echo 'Permission denied'; return; } if (!checklock($ID)) { lock($ID); echo 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(); } } }