MediaWiki  REL1_21
RecentChange.php
Go to the documentation of this file.
00001 <?php
00066 class RecentChange {
00067         var $mAttribs = array(), $mExtra = array();
00068 
00072         var $mTitle = false;
00073 
00077         private $mPerformer = false;
00078 
00082         var $mMovedToTitle = false;
00083         var $numberofWatchingusers = 0; # Dummy to prevent error message in SpecialRecentchangeslinked
00084         var $notificationtimestamp;
00085 
00086         # Factory methods
00087 
00092         public static function newFromRow( $row ) {
00093                 $rc = new RecentChange;
00094                 $rc->loadFromRow( $row );
00095                 return $rc;
00096         }
00097 
00102         public static function newFromCurRow( $row ) {
00103                 $rc = new RecentChange;
00104                 $rc->loadFromCurRow( $row );
00105                 $rc->notificationtimestamp = false;
00106                 $rc->numberofWatchingusers = false;
00107                 return $rc;
00108         }
00109 
00116         public static function newFromId( $rcid ) {
00117                 return self::newFromConds( array( 'rc_id' => $rcid ), __METHOD__ );
00118         }
00119 
00127         public static function newFromConds( $conds, $fname = __METHOD__ ) {
00128                 $dbr = wfGetDB( DB_SLAVE );
00129                 $row = $dbr->selectRow( 'recentchanges', self::selectFields(), $conds, $fname );
00130                 if ( $row !== false ) {
00131                         return self::newFromRow( $row );
00132                 } else {
00133                         return null;
00134                 }
00135         }
00136 
00142         public static function selectFields() {
00143                 return array(
00144                         'rc_id',
00145                         'rc_timestamp',
00146                         'rc_cur_time',
00147                         'rc_user',
00148                         'rc_user_text',
00149                         'rc_namespace',
00150                         'rc_title',
00151                         'rc_comment',
00152                         'rc_minor',
00153                         'rc_bot',
00154                         'rc_new',
00155                         'rc_cur_id',
00156                         'rc_this_oldid',
00157                         'rc_last_oldid',
00158                         'rc_type',
00159                         'rc_patrolled',
00160                         'rc_ip',
00161                         'rc_old_len',
00162                         'rc_new_len',
00163                         'rc_deleted',
00164                         'rc_logid',
00165                         'rc_log_type',
00166                         'rc_log_action',
00167                         'rc_params',
00168                 );
00169         }
00170 
00171         # Accessors
00172 
00176         public function setAttribs( $attribs ) {
00177                 $this->mAttribs = $attribs;
00178         }
00179 
00183         public function setExtra( $extra ) {
00184                 $this->mExtra = $extra;
00185         }
00186 
00191         public function &getTitle() {
00192                 if ( $this->mTitle === false ) {
00193                         $this->mTitle = Title::makeTitle( $this->mAttribs['rc_namespace'], $this->mAttribs['rc_title'] );
00194                 }
00195                 return $this->mTitle;
00196         }
00197 
00203         public function getPerformer() {
00204                 if ( $this->mPerformer === false ) {
00205                         if ( $this->mAttribs['rc_user'] ) {
00206                                 $this->mPerformer = User::newFromID( $this->mAttribs['rc_user'] );
00207                         } else {
00208                                 $this->mPerformer = User::newFromName( $this->mAttribs['rc_user_text'], false );
00209                         }
00210                 }
00211                 return $this->mPerformer;
00212         }
00213 
00218         public function save( $noudp = false ) {
00219                 global $wgLocalInterwiki, $wgPutIPinRC, $wgUseEnotif, $wgShowUpdatedMarker, $wgContLang;
00220 
00221                 $dbw = wfGetDB( DB_MASTER );
00222                 if ( !is_array( $this->mExtra ) ) {
00223                         $this->mExtra = array();
00224                 }
00225                 $this->mExtra['lang'] = $wgLocalInterwiki;
00226 
00227                 if ( !$wgPutIPinRC ) {
00228                         $this->mAttribs['rc_ip'] = '';
00229                 }
00230 
00231                 # If our database is strict about IP addresses, use NULL instead of an empty string
00232                 if ( $dbw->strictIPs() and $this->mAttribs['rc_ip'] == '' ) {
00233                         unset( $this->mAttribs['rc_ip'] );
00234                 }
00235 
00236                 # Trim spaces on user supplied text
00237                 $this->mAttribs['rc_comment'] = trim( $this->mAttribs['rc_comment'] );
00238 
00239                 # Make sure summary is truncated (whole multibyte characters)
00240                 $this->mAttribs['rc_comment'] = $wgContLang->truncate( $this->mAttribs['rc_comment'], 255 );
00241 
00242                 # Fixup database timestamps
00243                 $this->mAttribs['rc_timestamp'] = $dbw->timestamp( $this->mAttribs['rc_timestamp'] );
00244                 $this->mAttribs['rc_cur_time'] = $dbw->timestamp( $this->mAttribs['rc_cur_time'] );
00245                 $this->mAttribs['rc_id'] = $dbw->nextSequenceValue( 'recentchanges_rc_id_seq' );
00246 
00247                 ## If we are using foreign keys, an entry of 0 for the page_id will fail, so use NULL
00248                 if ( $dbw->cascadingDeletes() and $this->mAttribs['rc_cur_id'] == 0 ) {
00249                         unset( $this->mAttribs['rc_cur_id'] );
00250                 }
00251 
00252                 # Insert new row
00253                 $dbw->insert( 'recentchanges', $this->mAttribs, __METHOD__ );
00254 
00255                 # Set the ID
00256                 $this->mAttribs['rc_id'] = $dbw->insertId();
00257 
00258                 # Notify extensions
00259                 wfRunHooks( 'RecentChange_save', array( &$this ) );
00260 
00261                 # Notify external application via UDP
00262                 if ( !$noudp ) {
00263                         $this->notifyRC2UDP();
00264                 }
00265 
00266                 # E-mail notifications
00267                 if ( $wgUseEnotif || $wgShowUpdatedMarker ) {
00268                         $editor = $this->getPerformer();
00269                         $title = $this->getTitle();
00270 
00271                         if ( wfRunHooks( 'AbortEmailNotification', array( $editor, $title ) ) ) {
00272                                 # @todo FIXME: This would be better as an extension hook
00273                                 $enotif = new EmailNotification();
00274                                 $enotif->notifyOnPageChange( $editor, $title,
00275                                         $this->mAttribs['rc_timestamp'],
00276                                         $this->mAttribs['rc_comment'],
00277                                         $this->mAttribs['rc_minor'],
00278                                         $this->mAttribs['rc_last_oldid'],
00279                                         $this->mExtra['pageStatus'] );
00280                         }
00281                 }
00282         }
00283 
00284         public function notifyRC2UDP() {
00285                 global $wgRC2UDPAddress, $wgRC2UDPOmitBots;
00286                 # Notify external application via UDP
00287                 if ( $wgRC2UDPAddress && ( !$this->mAttribs['rc_bot'] || !$wgRC2UDPOmitBots ) ) {
00288                         self::sendToUDP( $this->getIRCLine() );
00289                 }
00290         }
00291 
00301         public static function sendToUDP( $line, $address = '', $prefix = '', $port = '' ) {
00302                 global $wgRC2UDPAddress, $wgRC2UDPPrefix, $wgRC2UDPPort;
00303                 # Assume default for standard RC case
00304                 $address = $address ? $address : $wgRC2UDPAddress;
00305                 $prefix = $prefix ? $prefix : $wgRC2UDPPrefix;
00306                 $port = $port ? $port : $wgRC2UDPPort;
00307                 # Notify external application via UDP
00308                 if ( $address ) {
00309                         $conn = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );
00310                         if ( $conn ) {
00311                                 $line = $prefix . $line;
00312                                 wfDebug( __METHOD__ . ": sending UDP line: $line\n" );
00313                                 socket_sendto( $conn, $line, strlen( $line ), 0, $address, $port );
00314                                 socket_close( $conn );
00315                                 return true;
00316                         } else {
00317                                 wfDebug( __METHOD__ . ": failed to create UDP socket\n" );
00318                         }
00319                 }
00320                 return false;
00321         }
00322 
00328         public static function cleanupForIRC( $text ) {
00329                 return Sanitizer::decodeCharReferences( str_replace( array( "\n", "\r" ), array( "", "" ), $text ) );
00330         }
00331 
00339         public static function markPatrolled( $change, $auto = false ) {
00340                 global $wgUser;
00341 
00342                 $change = $change instanceof RecentChange
00343                         ? $change
00344                         : RecentChange::newFromId( $change );
00345 
00346                 if ( !$change instanceof RecentChange ) {
00347                         return null;
00348                 }
00349                 return $change->doMarkPatrolled( $wgUser, $auto );
00350         }
00351 
00360         public function doMarkPatrolled( User $user, $auto = false ) {
00361                 global $wgUseRCPatrol, $wgUseNPPatrol;
00362                 $errors = array();
00363                 // If recentchanges patrol is disabled, only new pages
00364                 // can be patrolled
00365                 if ( !$wgUseRCPatrol && ( !$wgUseNPPatrol || $this->getAttribute( 'rc_type' ) != RC_NEW ) ) {
00366                         $errors[] = array( 'rcpatroldisabled' );
00367                 }
00368                 // Automatic patrol needs "autopatrol", ordinary patrol needs "patrol"
00369                 $right = $auto ? 'autopatrol' : 'patrol';
00370                 $errors = array_merge( $errors, $this->getTitle()->getUserPermissionsErrors( $right, $user ) );
00371                 if ( !wfRunHooks( 'MarkPatrolled', array( $this->getAttribute( 'rc_id' ), &$user, false ) ) ) {
00372                         $errors[] = array( 'hookaborted' );
00373                 }
00374                 // Users without the 'autopatrol' right can't patrol their
00375                 // own revisions
00376                 if ( $user->getName() == $this->getAttribute( 'rc_user_text' ) && !$user->isAllowed( 'autopatrol' ) ) {
00377                         $errors[] = array( 'markedaspatrollederror-noautopatrol' );
00378                 }
00379                 if ( $errors ) {
00380                         return $errors;
00381                 }
00382                 // If the change was patrolled already, do nothing
00383                 if ( $this->getAttribute( 'rc_patrolled' ) ) {
00384                         return array();
00385                 }
00386                 // Actually set the 'patrolled' flag in RC
00387                 $this->reallyMarkPatrolled();
00388                 // Log this patrol event
00389                 PatrolLog::record( $this, $auto, $user );
00390                 wfRunHooks( 'MarkPatrolledComplete', array( $this->getAttribute( 'rc_id' ), &$user, false ) );
00391                 return array();
00392         }
00393 
00398         public function reallyMarkPatrolled() {
00399                 $dbw = wfGetDB( DB_MASTER );
00400                 $dbw->update(
00401                         'recentchanges',
00402                         array(
00403                                 'rc_patrolled' => 1
00404                         ),
00405                         array(
00406                                 'rc_id' => $this->getAttribute( 'rc_id' )
00407                         ),
00408                         __METHOD__
00409                 );
00410                 return $dbw->affectedRows();
00411         }
00412 
00431         public static function notifyEdit( $timestamp, &$title, $minor, &$user, $comment, $oldId,
00432                 $lastTimestamp, $bot, $ip = '', $oldSize = 0, $newSize = 0, $newId = 0, $patrol = 0 ) {
00433                 $rc = new RecentChange;
00434                 $rc->mTitle = $title;
00435                 $rc->mPerformer = $user;
00436                 $rc->mAttribs = array(
00437                         'rc_timestamp'  => $timestamp,
00438                         'rc_cur_time'   => $timestamp,
00439                         'rc_namespace'  => $title->getNamespace(),
00440                         'rc_title'      => $title->getDBkey(),
00441                         'rc_type'       => RC_EDIT,
00442                         'rc_minor'      => $minor ? 1 : 0,
00443                         'rc_cur_id'     => $title->getArticleID(),
00444                         'rc_user'       => $user->getId(),
00445                         'rc_user_text'  => $user->getName(),
00446                         'rc_comment'    => $comment,
00447                         'rc_this_oldid' => $newId,
00448                         'rc_last_oldid' => $oldId,
00449                         'rc_bot'        => $bot ? 1 : 0,
00450                         'rc_ip'         => self::checkIPAddress( $ip ),
00451                         'rc_patrolled'  => intval( $patrol ),
00452                         'rc_new'        => 0,  # obsolete
00453                         'rc_old_len'    => $oldSize,
00454                         'rc_new_len'    => $newSize,
00455                         'rc_deleted'    => 0,
00456                         'rc_logid'      => 0,
00457                         'rc_log_type'   => null,
00458                         'rc_log_action' => '',
00459                         'rc_params'     => ''
00460                 );
00461 
00462                 $rc->mExtra = array(
00463                         'prefixedDBkey' => $title->getPrefixedDBkey(),
00464                         'lastTimestamp' => $lastTimestamp,
00465                         'oldSize'       => $oldSize,
00466                         'newSize'       => $newSize,
00467                         'pageStatus'   => 'changed'
00468                 );
00469                 $rc->save();
00470                 return $rc;
00471         }
00472 
00490         public static function notifyNew( $timestamp, &$title, $minor, &$user, $comment, $bot,
00491                 $ip = '', $size = 0, $newId = 0, $patrol = 0 ) {
00492                 $rc = new RecentChange;
00493                 $rc->mTitle = $title;
00494                 $rc->mPerformer = $user;
00495                 $rc->mAttribs = array(
00496                         'rc_timestamp'      => $timestamp,
00497                         'rc_cur_time'       => $timestamp,
00498                         'rc_namespace'      => $title->getNamespace(),
00499                         'rc_title'          => $title->getDBkey(),
00500                         'rc_type'           => RC_NEW,
00501                         'rc_minor'          => $minor ? 1 : 0,
00502                         'rc_cur_id'         => $title->getArticleID(),
00503                         'rc_user'           => $user->getId(),
00504                         'rc_user_text'      => $user->getName(),
00505                         'rc_comment'        => $comment,
00506                         'rc_this_oldid'     => $newId,
00507                         'rc_last_oldid'     => 0,
00508                         'rc_bot'            => $bot ? 1 : 0,
00509                         'rc_ip'             => self::checkIPAddress( $ip ),
00510                         'rc_patrolled'      => intval( $patrol ),
00511                         'rc_new'            => 1, # obsolete
00512                         'rc_old_len'        => 0,
00513                         'rc_new_len'        => $size,
00514                         'rc_deleted'        => 0,
00515                         'rc_logid'          => 0,
00516                         'rc_log_type'       => null,
00517                         'rc_log_action'     => '',
00518                         'rc_params'         => ''
00519                 );
00520 
00521                 $rc->mExtra = array(
00522                         'prefixedDBkey' => $title->getPrefixedDBkey(),
00523                         'lastTimestamp' => 0,
00524                         'oldSize' => 0,
00525                         'newSize' => $size,
00526                         'pageStatus' => 'created'
00527                 );
00528                 $rc->save();
00529                 return $rc;
00530         }
00531 
00547         public static function notifyLog( $timestamp, &$title, &$user, $actionComment, $ip, $type,
00548                 $action, $target, $logComment, $params, $newId = 0, $actionCommentIRC = '' )
00549         {
00550                 global $wgLogRestrictions;
00551                 # Don't add private logs to RC!
00552                 if ( isset( $wgLogRestrictions[$type] ) && $wgLogRestrictions[$type] != '*' ) {
00553                         return false;
00554                 }
00555                 $rc = self::newLogEntry( $timestamp, $title, $user, $actionComment, $ip, $type, $action,
00556                         $target, $logComment, $params, $newId, $actionCommentIRC );
00557                 $rc->save();
00558                 return true;
00559         }
00560 
00576         public static function newLogEntry( $timestamp, &$title, &$user, $actionComment, $ip,
00577                 $type, $action, $target, $logComment, $params, $newId = 0, $actionCommentIRC = '' ) {
00578                 global $wgRequest;
00579 
00580                 ## Get pageStatus for email notification
00581                 switch ( $type . '-' . $action ) {
00582                         case 'delete-delete':
00583                                 $pageStatus = 'deleted';
00584                                 break;
00585                         case 'move-move':
00586                         case 'move-move_redir':
00587                                 $pageStatus = 'moved';
00588                                 break;
00589                         case 'delete-restore':
00590                                 $pageStatus = 'restored';
00591                                 break;
00592                         case 'upload-upload':
00593                                 $pageStatus = 'created';
00594                                 break;
00595                         case 'upload-overwrite':
00596                         default:
00597                                 $pageStatus = 'changed';
00598                                 break;
00599                 }
00600 
00601                 $rc = new RecentChange;
00602                 $rc->mTitle = $target;
00603                 $rc->mPerformer = $user;
00604                 $rc->mAttribs = array(
00605                         'rc_timestamp'  => $timestamp,
00606                         'rc_cur_time'   => $timestamp,
00607                         'rc_namespace'  => $target->getNamespace(),
00608                         'rc_title'      => $target->getDBkey(),
00609                         'rc_type'       => RC_LOG,
00610                         'rc_minor'      => 0,
00611                         'rc_cur_id'     => $target->getArticleID(),
00612                         'rc_user'       => $user->getId(),
00613                         'rc_user_text'  => $user->getName(),
00614                         'rc_comment'    => $logComment,
00615                         'rc_this_oldid' => 0,
00616                         'rc_last_oldid' => 0,
00617                         'rc_bot'        => $user->isAllowed( 'bot' ) ? $wgRequest->getBool( 'bot', true ) : 0,
00618                         'rc_ip'         => self::checkIPAddress( $ip ),
00619                         'rc_patrolled'  => 1,
00620                         'rc_new'        => 0, # obsolete
00621                         'rc_old_len'    => null,
00622                         'rc_new_len'    => null,
00623                         'rc_deleted'    => 0,
00624                         'rc_logid'      => $newId,
00625                         'rc_log_type'   => $type,
00626                         'rc_log_action' => $action,
00627                         'rc_params'     => $params
00628                 );
00629 
00630                 $rc->mExtra = array(
00631                         'prefixedDBkey' => $title->getPrefixedDBkey(),
00632                         'lastTimestamp' => 0,
00633                         'actionComment' => $actionComment, // the comment appended to the action, passed from LogPage
00634                         'pageStatus'    => $pageStatus,
00635                         'actionCommentIRC' => $actionCommentIRC
00636                 );
00637                 return $rc;
00638         }
00639 
00645         public function loadFromRow( $row ) {
00646                 $this->mAttribs = get_object_vars( $row );
00647                 $this->mAttribs['rc_timestamp'] = wfTimestamp( TS_MW, $this->mAttribs['rc_timestamp'] );
00648                 $this->mAttribs['rc_deleted'] = $row->rc_deleted; // MUST be set
00649         }
00650 
00656         public function loadFromCurRow( $row ) {
00657                 $this->mAttribs = array(
00658                         'rc_timestamp' => wfTimestamp( TS_MW, $row->rev_timestamp ),
00659                         'rc_cur_time' => $row->rev_timestamp,
00660                         'rc_user' => $row->rev_user,
00661                         'rc_user_text' => $row->rev_user_text,
00662                         'rc_namespace' => $row->page_namespace,
00663                         'rc_title' => $row->page_title,
00664                         'rc_comment' => $row->rev_comment,
00665                         'rc_minor' => $row->rev_minor_edit ? 1 : 0,
00666                         'rc_type' => $row->page_is_new ? RC_NEW : RC_EDIT,
00667                         'rc_cur_id' => $row->page_id,
00668                         'rc_this_oldid' => $row->rev_id,
00669                         'rc_last_oldid' => isset( $row->rc_last_oldid ) ? $row->rc_last_oldid : 0,
00670                         'rc_bot' => 0,
00671                         'rc_ip' => '',
00672                         'rc_id' => $row->rc_id,
00673                         'rc_patrolled' => $row->rc_patrolled,
00674                         'rc_new' => $row->page_is_new, # obsolete
00675                         'rc_old_len' => $row->rc_old_len,
00676                         'rc_new_len' => $row->rc_new_len,
00677                         'rc_params' => isset( $row->rc_params ) ? $row->rc_params : '',
00678                         'rc_log_type' => isset( $row->rc_log_type ) ? $row->rc_log_type : null,
00679                         'rc_log_action' => isset( $row->rc_log_action ) ? $row->rc_log_action : null,
00680                         'rc_logid' => isset( $row->rc_logid ) ? $row->rc_logid : 0,
00681                         'rc_deleted' => $row->rc_deleted // MUST be set
00682                 );
00683         }
00684 
00691         public function getAttribute( $name ) {
00692                 return isset( $this->mAttribs[$name] ) ? $this->mAttribs[$name] : null;
00693         }
00694 
00698         public function getAttributes() {
00699                 return $this->mAttribs;
00700         }
00701 
00708         public function diffLinkTrail( $forceCur ) {
00709                 if ( $this->mAttribs['rc_type'] == RC_EDIT ) {
00710                         $trail = "curid=" . (int)( $this->mAttribs['rc_cur_id'] ) .
00711                                 "&oldid=" . (int)( $this->mAttribs['rc_last_oldid'] );
00712                         if ( $forceCur ) {
00713                                 $trail .= '&diff=0';
00714                         } else {
00715                                 $trail .= '&diff=' . (int)( $this->mAttribs['rc_this_oldid'] );
00716                         }
00717                 } else {
00718                         $trail = '';
00719                 }
00720                 return $trail;
00721         }
00722 
00726         public function getIRCLine() {
00727                 global $wgUseRCPatrol, $wgUseNPPatrol, $wgRC2UDPInterwikiPrefix, $wgLocalInterwiki,
00728                         $wgCanonicalServer, $wgScript;
00729 
00730                 if ( $this->mAttribs['rc_type'] == RC_LOG ) {
00731                         // Don't use SpecialPage::getTitleFor, backwards compatibility with
00732                         // IRC API which expects "Log".
00733                         $titleObj = Title::newFromText( 'Log/' . $this->mAttribs['rc_log_type'], NS_SPECIAL );
00734                 } else {
00735                         $titleObj =& $this->getTitle();
00736                 }
00737                 $title = $titleObj->getPrefixedText();
00738                 $title = self::cleanupForIRC( $title );
00739 
00740                 if ( $this->mAttribs['rc_type'] == RC_LOG ) {
00741                         $url = '';
00742                 } else {
00743                         $url = $wgCanonicalServer . $wgScript;
00744                         if ( $this->mAttribs['rc_type'] == RC_NEW ) {
00745                                 $query = '?oldid=' . $this->mAttribs['rc_this_oldid'];
00746                         } else {
00747                                 $query = '?diff=' . $this->mAttribs['rc_this_oldid'] . '&oldid=' . $this->mAttribs['rc_last_oldid'];
00748                         }
00749                         if ( $wgUseRCPatrol || ( $this->mAttribs['rc_type'] == RC_NEW && $wgUseNPPatrol ) ) {
00750                                 $query .= '&rcid=' . $this->mAttribs['rc_id'];
00751                         }
00752                         // HACK: We need this hook for WMF's secure server setup
00753                         wfRunHooks( 'IRCLineURL', array( &$url, &$query ) );
00754                         $url .= $query;
00755                 }
00756 
00757                 if ( $this->mAttribs['rc_old_len'] !== null && $this->mAttribs['rc_new_len'] !== null ) {
00758                         $szdiff = $this->mAttribs['rc_new_len'] - $this->mAttribs['rc_old_len'];
00759                         if ( $szdiff < -500 ) {
00760                                 $szdiff = "\002$szdiff\002";
00761                         } elseif ( $szdiff >= 0 ) {
00762                                 $szdiff = '+' . $szdiff;
00763                         }
00764                         // @todo i18n with parentheses in content language?
00765                         $szdiff = '(' . $szdiff . ')';
00766                 } else {
00767                         $szdiff = '';
00768                 }
00769 
00770                 $user = self::cleanupForIRC( $this->mAttribs['rc_user_text'] );
00771 
00772                 if ( $this->mAttribs['rc_type'] == RC_LOG ) {
00773                         $targetText = $this->getTitle()->getPrefixedText();
00774                         $comment = self::cleanupForIRC( str_replace( "[[$targetText]]", "[[\00302$targetText\00310]]", $this->mExtra['actionCommentIRC'] ) );
00775                         $flag = $this->mAttribs['rc_log_action'];
00776                 } else {
00777                         $comment = self::cleanupForIRC( $this->mAttribs['rc_comment'] );
00778                         $flag = '';
00779                         if ( !$this->mAttribs['rc_patrolled'] && ( $wgUseRCPatrol || $this->mAttribs['rc_type'] == RC_NEW && $wgUseNPPatrol ) ) {
00780                                 $flag .= '!';
00781                         }
00782                         $flag .= ( $this->mAttribs['rc_type'] == RC_NEW ? "N" : "" ) . ( $this->mAttribs['rc_minor'] ? "M" : "" ) . ( $this->mAttribs['rc_bot'] ? "B" : "" );
00783                 }
00784 
00785                 if ( $wgRC2UDPInterwikiPrefix === true && $wgLocalInterwiki !== false ) {
00786                         $prefix = $wgLocalInterwiki;
00787                 } elseif ( $wgRC2UDPInterwikiPrefix ) {
00788                         $prefix = $wgRC2UDPInterwikiPrefix;
00789                 } else {
00790                         $prefix = false;
00791                 }
00792                 if ( $prefix !== false ) {
00793                         $titleString = "\00314[[\00303$prefix:\00307$title\00314]]";
00794                 } else {
00795                         $titleString = "\00314[[\00307$title\00314]]";
00796                 }
00797 
00798                 # see http://www.irssi.org/documentation/formats for some colour codes. prefix is \003,
00799                 # no colour (\003) switches back to the term default
00800                 $fullString = "$titleString\0034 $flag\00310 " .
00801                         "\00302$url\003 \0035*\003 \00303$user\003 \0035*\003 $szdiff \00310$comment\003\n";
00802 
00803                 return $fullString;
00804         }
00805 
00813         public function getCharacterDifference( $old = 0, $new = 0 ) {
00814                 if ( $old === 0 ) {
00815                         $old = $this->mAttribs['rc_old_len'];
00816                 }
00817                 if ( $new === 0 ) {
00818                         $new = $this->mAttribs['rc_new_len'];
00819                 }
00820                 if ( $old === null || $new === null ) {
00821                         return '';
00822                 }
00823                 return ChangesList::showCharacterDifference( $old, $new );
00824         }
00825 
00826         private static function checkIPAddress( $ip ) {
00827                 global $wgRequest;
00828                 if ( $ip ) {
00829                         if ( !IP::isIPAddress( $ip ) ) {
00830                                 throw new MWException( "Attempt to write \"" . $ip . "\" as an IP address into recent changes" );
00831                         }
00832                 } else {
00833                         $ip = $wgRequest->getIP();
00834                         if ( !$ip ) {
00835                                 $ip = '';
00836                         }
00837                 }
00838                 return $ip;
00839         }
00840 }