/**
  * @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.');
     }
 }
Example #2
0
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);
    }
}
Example #3
0
 /**
  * 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]);
     }
 }
Example #5
0
    /**
     * 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;
 }
Example #7
0
 /**
  * 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;
 }
Example #8
0
/**
 * 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;
}
Example #9
0
 /**
  * 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;
 }
Example #10
0
 /**
  * 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;
 }
Example #11
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;
 }
Example #12
0
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;
}//}}}
Example #13
0
 /**
  * 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);
 }
Example #14
0
/**
 * 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;
}
Example #15
0
/**
 * 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();
        }
    }
}
Example #16
0
/**
 * 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;
}
Example #17
0
/**
 * 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;
}
Example #18
0
/**
 * 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;
}
Example #19
0
    /**
     * 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;
    }
Example #20
0
 /**
  *
  */
 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;
 }
Example #21
0
 /**
  * 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);
     }
 }
Example #22
0
/**
 * 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;
}
Example #23
0
 /**
  * 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);
 }
Example #24
0
 /**
  * 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');
     }
 }
Example #26
0
/**
 * 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();
        }
    }
}