Extension:PageProtection/Sourcecode (Jonabbey)

From MediaWiki.org
Jump to navigation Jump to search
Extension:PageProtection PageProtection extension (modified source code)
This is a modified version of the MediaWiki PageProtection extension source code which supports protection from viewing and editing.


<?php
/**
* Mediawiki-extension for page-protection. This extension allows protecting
* single areas by spanning them with <protect>-tags. The tag has the following
* parameters:
* users: Comma-separated list of usernames who are allowed to read and edit
*        the area.
* groups: Comma-separated lsit of groupnames who are allowed to read and edit
*         the area.
* The text between the opening and closing 'protect'-tags will be hidden for
* users not in the specified lists. Members of 'sysop' always have access.
*
* Example:
*   <protect users="admin1,admin2" groups="sysop">
*   Database-Settings
*   ;Server
*   : localhost
*   ...
*   </protect>
*
* With this extension, it is possible to mark single sections of pages as
* protected and thus leaving the other sections editable to all users.
* Access to sections containing <protect>-tags is only permitted for users
* having access to all protected areas in the specified section  / article.
*
* TODO Editing sections within protected areas is possible by supplying
*      section=X to URL! So we need to check permissions of protect-tags
*       surrounding the current section.
*
* TODO Searching for protected text is possible.
*
* @author Copyright (C) 2006 Fabian Schmitt (fs@u4m.de)
* @version 0.7
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/

define("PROTECT_TAG", "protect");
define("PROTECT_EDIT_TAG", "protect-edit");
define("VAR_USERS",   "{{{USERS}}}");
define("VAR_GROUPS",  "{{{GROUPS}}}");
define('MSG_NO_ACCESS',
" This area is [[Page Protection|protected]].
 You are not allowed to read or edit this area.<br/>
 Allowed users: ".VAR_USERS.
" <br/>Allowed groups: ".VAR_GROUPS);

define('MSG_NO_EDIT_ACCESS',
" This page is [[Page Protection|protected]].
 You are not allowed to edit this page.<br/>
 Allowed users: ".VAR_USERS.
" <br/>Allowed groups: ".VAR_GROUPS);

$wgExtensionFunctions[] = "wfPageProtection";

$wgExtensionCredits['parserhook'][] = array(
    'name' => 'ProtectPage',
    'author' => 'Fabian Schmitt (http://meta.wikimedia.org/wiki/User:Sirius_gd)',
    'version' => '0.7',
    'url' => 'http://meta.wikimedia.org/wiki/PageProtection'
);

/**
* Extension-function. Registers parser, hook, messages.
*/
function wfPageProtection() {
    global $wgParser;

    $msgs = array (
		   'ProtectedSite' => MSG_NO_ACCESS,
		   'ProtectedEditSite' => MSG_NO_EDIT_ACCESS
        );

    global $wgMessageCache;
    $wgMessageCache->addMessages($msgs);

    // set a hook on our parser to protect content that is protected
    // both from viewing and editing

    $wgParser->setHook( PROTECT_TAG, "protectPage" );
    $wgParser->setHook( PROTECT_EDIT_TAG, "protectEditPage" );

    global $wgHooks;
    $wgHooks['AlternateEdit'][] = 'protectedEdit';
}

/**
* Splits the users that are allowed to acces the protected area from a
* parameter.
* @param params The parameters as given to the hook-function
* @return Array with user-names
*/
function getAllowedUsers($params) {
  if (isset($params["users"])) {
    return explode(",", $params["users"]);
  } else {
    return array();
  }
}

/**
* Splits the groups that are allowed to acces the protected area from a
* parameter. If the group sysop is not supplied as parameter, it will be
* added automatically.
* @param params The parameters as given to the hook-function
* @return Array with group-names including sysop.
*/
function getAllowedGroups($params) {
  if (isset($params["groups"])) {
    $groups = explode(",", $params["groups"]);
  }

  // sysops always have access
  if (!isset($groups) || !in_array("sysop", $groups )) {
    $groups[] = "sysop";
  }
  return $groups;
}

/**
* Checks if a given user has access to a protected area.
* @param user User-object to check for.
* @param users Array containing allowed user-names.
* @param groups Array containing allowed group-names.
* @return true, if user is in list of users or in one of the allowed groups,
*         false otherwise.
*/
function hasAccess(&$user, &$users, &$groups) {
    // Check Group access
    foreach($groups as $group) {
        if(in_array($group, $user->mGroups)){
            return true;
        }
    }

    if (isset($users) && in_array($user->getName(), $users)) {
        return true;
    }

    return false;
}

/**
* Reads the error-message 'ProtectedSite' from the message-cache and replaces
* all {{{USERS}}} by a comma-separated list of allowed users and all
* {{{GROUPS}}} by a comma-separated lsit of allowed groups.
* @param users List of allowed users.
* @param groups list of allowed groups
* @param parseWiki If true, the text will be parsed before returning.
* @return Error-message.
*/
function getErrorMessage(&$users, &$groups, $parseWiki = true, $edit_protected = false) {
    global $wgOut;
    if ($edit_protected) {
      $msg = wfMsg("ProtectedEditSite");
    } else {
      $msg = wfMsg("ProtectedSite");
    }
    $usersString = "";

    foreach($users as $user) {
        if ($user == "") {
            continue;
        }
        if ($usersString != "") {
            $usersString = $usersString.", ";
        }
        // make link to user-page
        $u = User::newFromName($user);
	$title = Title::makeTitle(NS_USER,$user);
        $userPage = "[[".$title->getNsText().":".$user."|".$user."]]";
        $usersString = $usersString.$userPage;
    }

    $groupsString = "";
    foreach($groups as $group) {
        if ($groupsString != "") {
            $groupsString = $groupsString.", ";
        }
        $groupsString = $groupsString.$group;
    }

    $msg = str_replace(VAR_USERS, $usersString, $msg);
    $msg = str_replace(VAR_GROUPS, $groupsString, $msg);

    if ($parseWiki) {
        return $wgOut->parse($msg);
    } else {
        return $msg;
    }
}

/**
* Callback function for the hook to the protect-tag.
* @param text Text to be protected
* @param params Parameters supplied to the tag
* @param parser Global parser-object
* @return If current use is allowed to read the page, $text will be returned.
*         Otherwise,  an error-page will be returned.
*/
function protectPage( $text, $params, &$parser) {
    global $wgUser;
    global $wgOut;

    $parser->disableCache();

    $users = getAllowedUsers($params);
    $groups = getAllowedGroups($params);

    if (hasAccess($wgUser, $users, $groups)) {
        return $wgOut->parse($text);
    }

    return getErrorMessage($users, $groups);
}


/**
* Callback function for the hook to the protect-edit tag.
* @param text Text to be protected
* @param params Parameters supplied to the tag
* @param parser Global parser-object
* @return If current use is allowed to read the page, $text will be returned.
*         Otherwise,  an error-page will be returned.
*/
function protectEditPage( $text, $params, &$parser) {
    global $wgOut;
    $parser->disableCache();

    // we don't protect viewing, so show it here

    return $wgOut->parse($text);
}


/**
* Reads currently displayed or edited section from request.
* @return Current section or 0 if no section is beeing edited.
*/
function getSection()
{
    global $wgRequest;
    require_once("includes/WebRequest.php");
    // section when editing
    $section = $wgRequest->getVal('section');
    if (!$section) {
        // for preview and finish editing, section is in wpSection
        $section = $wgRequest->getVal('wpSection');
        if (!$section) {
            $section = 0;
        }
    }

    return $section - 1;
}

/**
* Intersects two array and returns the result. If one of the given arrays
* is empty, the other one will be returned.
* @param a1 First array
* @param a2 Second array
* @return Intersection
*/
function intersect($a1, $a2) {
    if (count($a1) == 0) {
        return $a2;
    }
    if (count($a2) == 0) {
        return $a1;
    }
    return array_intersect($a1, $a2);
}

/**
* Cancels the editing and prints error message.
* @param users List of allowed users
* @param groups List of allowed groups
*/
function stopEditing($users, $groups, $edit_protected=false) {
    global $wgOut;
    $wgOut->setPageTitle( "Page is protected" );
    $wgOut->setRobotpolicy( 'noindex,nofollow' );
    $wgOut->setArticleRelated( false );
    $wgOut->addWikiText( getErrorMessage($users, $groups, false, $edit_protected) );
    $wgOut->returnToMain( false );
}

/**
* Callback-function for hook to 'AlternateEdit'. Checks if the current user
* is allowed to edit the current article / section and if so returns the
* current editpage-object.
* TODO make the error-page nicer.
* @param editpage EditPage-object
* @return editpage if user is allowed to edit the section, null otherwise.
*/
function protectedEdit($editpage) {
    global $wgUser;
    global $wgRequest;
    global $_REQUEST;
    global $_GET;

    $section = getSection();

    if ($section != -1) {
      $old_section = $section + 1;
    }

    // wipe out the section request for now

    if (is_array($_REQUEST) && isset($_REQUEST['section'])) {
      unset($_REQUEST['section']);
    } elseif (is_array($_GET) && isset($_GET['section'])) {
      unset($_GET['section']);
    }

    // Now get the full page content and see if we've got a protected
    // bit anywhere in it

    // Get text to be edited.. because we've cleared $_REQUEST and
    // $_GET of 'section', Article.php#getContent() will give us the
    // full text of the page

    $text = $editpage->mArticle->getContent();

    $edit_protected = false;

    // find protected tags
    $content = '';
    $tags = '';
    $params = array();

    // we check first for edit protection with the PROTECT_EDIT_TAG

    Parser::extractTagsAndParams(PROTECT_EDIT_TAG, $text, $content, $tags, $params );

    if (count($tags) == 0) {

      // No edit protection sections.. are there any view/edit
      // protection sections?

      $content = '';
      $tags = '';
      $params = array();

      Parser::extractTagsAndParams(PROTECT_TAG, $text, $content, $tags, $params );

      if (count($tags) == 0) {
	if (isset($old_section)) {
	  $_REQUEST['section'] = $old_section; // reset our section
	}
	
	return $editpage;	// no protected text was found so continue editing
      }
    } else {
      $edit_protected = true;
    }

     // get intersections of allowed users and groups for all
     // protected areas in text-block.

    $users = array();
    $groups = array();
    foreach ($params as $param) {
        $users = intersect($users, getAllowedUsers($param));
        $groups = intersect($groups, getAllowedGroups($param));
    }

    if (hasAccess($wgUser, $users, $groups)) {
      if (isset($old_section)) {
	$_REQUEST['section'] = $old_section; // reset our section
      }

      return $editpage;
    }

    stopEditing($users, $groups, $edit_protected);
}