Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /*
- * Copyright (c) 2011 University of Macau
- *
- * Licensed under the Educational Community License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License. You may
- * obtain a copy of the License at
- *
- * http://www.osedu.org/licenses/ECL-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an "AS IS"
- * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
- /* File name: AccessLog.body.php
- * Purpose: Implementation of AccessLog class
- * Author: Aleksandar Bojinovic, Peter Kin-Fong Fong
- */
- class AccessLog extends SpecialPage {
- const DEFAULT_LOGS_PER_PAGE = 20;
- const DAY_IN_SECS = 86400;
- private $logsPerPageOptions = array(10, 20, 50, 100, 250, 500, 1000, 2000);
- private $logsPerPage = self::DEFAULT_LOGS_PER_PAGE;
- private $fUser, $fAccess, $fNamespaces, $fDays, $fPage, $fAnons;
- private $totalResults, $totalPages, $page = 1;
- function AccessLog() {
- SpecialPage::SpecialPage('AccessLog', 'protect');
- wfLoadExtensionMessages('AccessLog');
- }
- /**
- * Generate the HTML fragment for disclamar on top of the log page.
- */
- private function getLogDisclaimer() {
- global $wgScriptPath, $wgEmergencyContact;
- $out = Xml::openElement( 'table', array( 'border' => '0', 'cellpadding' => '0', 'cellspacing' => '0', 'width' => '100%' ) );
- $out .= Xml::openElement( 'tr' );
- $out .= Xml::openElement( 'td', array( 'width' => '32px' ) );
- $out .= Xml::element( 'img', array ( 'src' => $wgScriptPath .'/extensions/UMEduWiki/images/log.png' ) );
- $out .= Xml::closeElement( 'td' );
- $out .= Xml::openElement( 'td', array( 'bgcolor' => '#F5F5F5' ) );
- $out .= Xml::openElement( 'p', array( 'style' => 'margin-left: 5px; font-style: italic' ) );
- $out .= "This special page lists the access log. For any questions or troubleshooting, please <a href=\"mailto:$wgEmergencyContact\">contact</a> the administrator.";
- $out .= Xml::closeElement( 'p' );
- $out .= Xml::closeElement( 'td' );
- $out .= Xml::closeElement( 'tr' );
- $out .= Xml::closeElement( 'table' );
- return $out;
- }
- /**
- * Generate the HTML fragment for control forms.
- */
- private function getLogControler() {
- global $wgScript, $wgTitle;
- $dbr = wfGetDB( DB_SLAVE );
- // Logs per page setting
- $out = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) );
- $out .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() );
- $out .= Xml::openElement( 'table', array( 'border' => '0', 'cellpadding' => '2', 'cellspacing' => '0' ) );
- $out .= Xml::openElement( 'tr' );
- $out .= Xml::openElement( 'td' );
- $out .= Xml::openElement( 'p' );
- $out .= '<b>Display</b> ';
- $out .= Xml::openElement( 'select', array( 'id' => 'limit', 'name' => 'limit' ) );
- {
- foreach ($this->logsPerPageOptions as $n) {
- $out .= Xml::option( $n, $n, $this->logsPerPage == $n );
- }
- }
- $out .= Xml::closeElement( 'select' );
- $out .= ' logs per page ';
- $out .= Xml::submitButton( 'Update' );
- $out .= Xml::closeElement( 'p' );
- $out .= Xml::closeElement( 'td' );
- $out .= Xml::closeElement( 'tr' );
- $out .= Xml::closeElement( 'table' );
- // Filter setting
- $out .= Xml::openElement( 'table', array( 'border' => '0', 'cellpadding' => '2', 'cellspacing' => '0' ) );
- $out .= Xml::openElement( 'tr' );
- $out .= Xml::openElement( 'td', array( 'valign' => 'middle' ) );
- $out .= Xml::openElement( 'p' );
- $out .= '<b>Filter</b> ';
- $out .= 'user: ';
- $out .= Xml::input('user', 20, $this->fUser);
- $out .= ' access:';
- $out .= Xml::openElement( 'select', array('size' => '1', 'name' => 'access' ) );
- $out .= Xml::option( '*', 'both', $this->fAccess == 'both' || $this->fAccess == '' );
- $out .= Xml::option( 'view', 'view', $this->fAccess == 'view' );
- $out .= Xml::option( 'edit', 'edit', $this->fAccess == 'edit' );
- $out .= Xml::closeElement( 'select' );
- $out .= ' page: ';
- $out .= Xml::input('pageviewed', 20, $this->fPage);
- $out .= ' namespace: ';
- $out .= Xml::openElement( 'select', array('size' => '1', 'name' => 'ns' ) );
- $out .= Xml::option( '*', 'all' );
- $namespaces = $this->getAllNamespaces();
- foreach( $namespaces as $ns => $name ) {
- $out .= Xml::option( $name, $name, $this->fNamespaces == $name );
- }
- $out .= Xml::closeElement( 'select' );
- $out .= ' in last: ';
- $out .= Xml::input('days', 2, $this->fDays);
- $out .= ' day(s)<br>';
- $out .= Xml::check( 'anons', $this->fAnons);
- $out .= ' Display only anonymous users?';
- $out .= Xml::submitButton( 'Filter' );
- $out .= Xml::closeElement( 'p' );
- $out .= Xml::closeElement( 'td' );
- $out .= Xml::closeElement( 'tr' );
- $out .= Xml::closeElement( 'table' );
- $out .= Xml::closeElement( 'form' );
- // Purge old logs
- $out .= Xml::openElement( 'form', array( 'method' => 'post', 'action' => $wgScript . '?title=' . $this->getTitle()->getPrefixedText() . '&action=purge&value=ask' ) );
- $out .= Xml::openElement( 'table', array( 'border' => '0', 'cellpadding' => '2', 'cellspacing' => '0' ) );
- $out .= Xml::openElement( 'tr' );
- $out .= Xml::openElement( 'td' );
- $out .= '<b>Purge log </b> older than ';
- $out .= Xml::input('pDays', 2);
- $out .= ' day(s) ';
- $out .= Xml::submitButton( 'Purge', array('name' => 'submit') );
- $out .= Xml::closeElement( 'td' );
- $out .= Xml::closeElement( 'tr' );
- $out .= Xml::closeElement( 'table' );
- $out .= Xml::closeElement( 'form' );
- $out .= "<p style=\"color: #999999\"><i><b> Note: </b>Click 'Filter' to apply filter settings to the log display.</i></p>";
- $out = Xml::fieldset( 'Log display control', $out );
- return $out;
- }
- /**
- * Ask for confirmation before purging the old log entries. Return a
- * page with a choice of "Yes" or "No".
- *
- * @param $pDays Number of days before execution time
- */
- private function displayAsk( $pDays ) {
- global $wgScriptPath, $wgScript;
- $out = Xml::openElement( 'table', array( 'border' => '0', 'cellpadding' => '2', 'cellspacing' => '0' ) );
- $out .= Xml::openElement( 'tr' );
- $out .= Xml::openElement( 'td', array( 'valign' => 'top' ) );
- $out .= Xml::element( 'img', array ( 'src' => $wgScriptPath .'/extensions/UMEduWiki/images/sure.png' ) );
- $out .= Xml::closeElement( 'td' );
- $out .= Xml::openElement( 'td', array( 'valign' => 'top' ) );
- $out .= Xml::openElement( 'form', array( 'method' => 'post', 'action' => $wgScript . '?title=' . $this->getTitle()->getPrefixedText() . '&action=purge&value=confirmed' ) );
- if ( empty($pDays) ) {
- $out .= "<p><b><i>Are you sure you want to purge the entire log?</i></b></p>";
- } else {
- $out .= "<p><b><i>Are you sure you want to purge entries older than $pDays day(s)?</i></b></p>";
- }
- $out .= Xml::element( 'input' , array('type' => 'hidden', 'name' => 'pDays', 'value'=> $pDays) );
- $out .= Xml::openElement( 'p' );
- $out .= Xml::submitButton( 'Yes', array('name' => 'submit') );
- $out .= Xml::submitButton( 'No', array('name' => 'submit') );
- $out .= Xml::closeElement( 'p' );
- $out .= Xml::closeElement( 'form' );
- $out .= Xml::closeElement( 'td' );
- $out .= Xml::closeElement( 'tr' );
- $out .= Xml::closeElement( 'table' );
- return $out;
- }
- /**
- * Format the log entries into a table.
- *
- * @param $result An array with number of entries as $result[0] and the log entries in $result[1]
- * @return An HTML fragment that contains formatted log.
- */
- private function getLog( $result ) {
- global $wgScript;
- $out = '<fieldset style="padding: 2"><legend><b>Log</b></legend>';
- // Render navigation links (previous / next page)
- if ($this->page > 1) {
- $prev = $this->page - 1;
- $nav = '<span style="color: #C0C0C0"><a href="' . $wgScript .
- '?title=' . $this->getTitle()->getPrefixedText() .
- '&page=' . $prev .
- '&limit=' . $this->logsPerPage .
- ( empty($this->fUser) ? '' : ('&user=' . $this->fUser) ) .
- ( empty($this->fAccess) ? '' : ('&access=' . $this->fAccess) ) .
- ( empty($this->fNamespaces) ? '' : ('&ns=' . $this->fNamespaces) ) .
- ( ($this->fDays == null) ? '' : ('&days=' . $this->fDays) ) .
- '">Previous ' . $this->logsPerPage . ' results</a> | ';
- } else {
- $nav = '<span style="color: #C0C0C0">Previous ' . $this->logsPerPage . ' results | ';
- }
- if ($this->page < $this->totalPages){
- $next = $this->page + 1;
- $nav .= '<a href="' . $wgScript .
- '?title=' . $this->getTitle()->getPrefixedText() .
- '&page=' . $next .
- '&limit=' . $this->logsPerPage .
- ( empty($this->fUser) ? '' : ('&user=' . $this->fUser) ) .
- ( empty($this->fAccess) ? '' : ('&access=' . $this->fAccess) ) .
- ( empty($this->fNamespaces) ? '' : ('&ns=' . $this->fNamespaces) ) .
- ( ($this->fDays == null) ? '' : ('&days=' . $this->fDays) ) .
- '">Next ' . $this->logsPerPage . ' results</a> of a total <b>' . $this->totalResults . '</b> results</span>';
- } else {
- $nav .= 'Next ' . $this->logsPerPage . ' results of a total <b>' . $this->totalResults .'</b> results</span>';
- }
- $out .= $nav;
- // Output log entries
- $out .= '<table border="0" cellpadding="2" cellspacing="0">';
- if ($result[0] == 0) {
- $out .= '<p style="font-size: small">There are no entries in the log.</p>';
- }
- foreach ($result[1] as $row) {
- $time = wfTimestamp( TS_DB, $row->tw_log_timestamp );
- $user = $row->tw_log_username;
- $action = $row->tw_log_action;
- $title = Title::newFromText($row->tw_log_title);
- $out .= '<tr>
- <td><span style="color: #808080"><b>' . $time . '</b></font></td>
- <td><a href="../' . $wgScript . '?title=User:' . $user . '">' . $user . '</a><i> has ' . $action . 'ed</i> <a href="' . $title->getLocalURL() .'">' . $title->getPrefixedText() . '</a></td>
- </tr>';
- }
- $out .= '</table>';
- $out .= $nav;
- $out .= '</fieldset>';
- return $out;
- }
- /**
- * Get all namespaces' name into an array.
- */
- private function getAllNamespaces() {
- global $wgContLang;
- $arr = array();
- foreach( $wgContLang->getNamespaces() as $ns => $name ) {
- if ( $ns != 0 )
- $arr[$ns] = $name;
- else
- $arr[$ns] = 'Main';
- }
- return $arr;
- }
- /**
- * Check if a user is in a designated group.
- *
- * @param $userGroups Groups a user is belongs to
- * @param $designatedGroup The groups to check (string or array)
- */
- private function checkUser($userGroups, $designatedGroups) {
- if (!is_array($designatedGroups)) {
- $designatedGroups = array($designatedGroups);
- }
- foreach ($userGroups as $userGroup) {
- foreach ($designatedGroups as $designatedGroup) {
- if (strcmp($userGroup, $designatedGroup) == 0) {
- return true;
- }
- }
- }
- return false;
- }
- /**
- * Returns true if the request contains POST data
- */
- private function isPosted() {
- if (isset($_POST['submit'])) {
- return true;
- }
- return false;
- }
- /**
- * Main entry point of the special page.
- */
- function execute( $par ) {
- global $wgRequest, $wgOut, $wgUser, $wgAccessControlPanelAllowedGroup;
- $this->setHeaders();
- // Check user privileges
- $wgUser->load();
- $userGroups = $wgUser->getGroups();
- if ( isset($wgAccessControlPanelAllowedGroup) ) {
- $checkGroup = array('sysop', $wgAccessControlPanelAllowedGroup);
- } else {
- $checkGroup = array('sysop');
- }
- if ( ! $this->checkUser($userGroups, $checkGroup) ) {
- $wgOut->addHTML( "You don't have access rights to this page." );
- return;
- }
- // Get a writable database instance
- $dbw = wfGetDB( DB_MASTER );
- // Always get the header first
- $output = $this->getLogDisclaimer();
- // Check if some contents was posted
- if ($this->isPosted()) {
- $action = $_GET['action'];
- $value = $_GET['value'];
- # Purging log
- if ($action == 'purge' && $value == 'ask') {
- $pDays = $_POST['pDays'];
- $wgOut->addHTML( $this->displayAsk( $pDays ) );
- return;
- } else if ($action == 'purge' && $value == 'confirmed') {
- $confirm = $_POST['submit'];
- $pDays = $_POST['pDays'];
- if ($confirm == 'Yes' && empty($pDays) ) {
- $dbw->delete('tw_accesslog', '*');
- } else if ($confirm == 'Yes' && !empty($pDays) ) {
- $cutoffTime = wfTimestamp( TS_MW, wfTimestamp() - intval($pDays) * self::DAY_IN_SECS );
- $dbw->delete('tw_accesslog', array("tw_log_timestamp < '$cutoffTime'") );
- }
- }
- }
- // Get all parameters
- $this->fUser = $wgRequest->getText( 'user', '' );
- $this->fAccess = $wgRequest->getText( 'access', 'both' );
- $this->fNamespaces = $wgRequest->getText( 'ns', 'all' );
- $this->fDays = $wgRequest->getIntOrNull( 'days' );
- $this->fPage = $wgRequest->getText ( 'pageviewed', '' );
- $this->fAnons = $wgRequest->getCheck ( 'anons' ) ? 1 : 0;
- $this->page = $wgRequest->getInt( 'page', 1 );
- $this->logsPerPage = max( 1, $wgRequest->getInt( 'limit', $wgUser->getOption( 'rclimit' ) ) );
- // Now we read the proper controler display
- $output .= $this->getLogControler();
- # And at this time we are able to read the proper section from database,
- # including all the settings
- # All the query conditions in WHERE clause is recorded in $queryConds
- $queryConds = array();
- if ( !empty($this->fUser) ) {
- $queryConds['tw_log_username'] = $this->fUser;
- }
- if ( $this->fAnons > 0 ) {
- $queryConds[] = "tw_log_username REGEXP '^([0-9]{1,3})[.period.]([0-9]{1,3})[.period.]([0-9]{1,3})[.period.]([0-9]{1,3})'";
- }
- if ( !empty($this->fAccess) && $this->fAccess != 'both' ) {
- $queryConds['tw_log_action'] = $this->fAccess;
- }
- if ( !empty($this->fNamespaces) && $this->fNamespaces != 'all' ) {
- if ($this->fNamespaces == 'Main') {
- $queryConds[] = "tw_log_title NOT LIKE '%:%'";
- }
- else {
- $queryConds[] = "tw_log_title LIKE '$this->fNamespaces:%'";
- }
- }
- if ( !empty($this->fPage) ) {
- $queryConds[] = "tw_log_title LIKE '%$this->fPage$'";
- }
- if ( $this->fDays !== null ) {
- $prevTs = wfTimestamp( TS_MW, wfTimestamp() - intval($this->fDays) * self::DAY_IN_SECS );
- $queryConds[] = "tw_log_timestamp > '$prevTs'";
- }
- $from = ($this->page - 1) * $this->logsPerPage;
- # We need this result, to render properly Previous | Next links
- $this->totalResults = $dbw->selectField('tw_accesslog', 'COUNT(*)', $queryConds);
- $query = $dbw->select('tw_accesslog', '*', $queryConds, __METHOD__, array('ORDER BY' => 'tw_log_timestamp DESC', 'OFFSET' => $from, 'LIMIT' => $this->logsPerPage) );
- $result = array($query->numRows(), $query);
- # Total number of pages will be like this
- $this->totalPages = ceil($this->totalResults / $this->logsPerPage);
- # Now, I send the array object to getLog function, that should render the output properly
- $output .= $this->getLog($result);
- # Finally, generate the acquired content
- $wgOut->addHTML( $output );
- }
- }
- ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement