X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fapi%2FApiQueryWatchlist.php;h=b7dc86543c79571c65ba692aa9a8d4e89a013371;hb=3afc76a4b5ad2f73dd69a82ec08c0d0e4799f00f;hp=f8e521f356adc210e7d7da7b8e7a88439f1134d8;hpb=f40328ff95cdf7a238b0f3109940972b535fb900;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/api/ApiQueryWatchlist.php b/includes/api/ApiQueryWatchlist.php index f8e521f356..b7dc86543c 100644 --- a/includes/api/ApiQueryWatchlist.php +++ b/includes/api/ApiQueryWatchlist.php @@ -59,7 +59,8 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { $params = $this->extractRequestParams(); - $user = $this->getWatchlistUser( $params ); + $user = $this->getUser(); + $wlowner = $this->getWatchlistUser( $params ); if ( !is_null( $params['prop'] ) && is_null( $resultPageSet ) ) { $prop = array_flip( $params['prop'] ); @@ -89,6 +90,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { 'rc_title', 'rc_timestamp', 'rc_type', + 'rc_deleted', ) ); if ( is_null( $resultPageSet ) ) { @@ -120,7 +122,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { 'watchlist', ) ); - $userId = $user->getId(); + $userId = $wlowner->getId(); $this->addJoinConds( array( 'watchlist' => array( 'INNER JOIN', array( 'wl_user' => $userId, @@ -129,10 +131,6 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { ) ) ) ); - $this->addWhere( array( - 'rc_deleted' => 0, - ) ); - $db = $this->getDB(); $this->addTimestampWhereRange( 'rc_timestamp', $params['dir'], @@ -159,7 +157,6 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { // Check permissions. if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ) { - $user = $this->getUser(); if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) { $this->dieUsage( 'You need the patrol right to request the patrolled flag', @@ -199,6 +196,36 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { !isset( $params['start'] ) && !isset( $params['end'] ) && $db->getType() == 'mysql' ); + // Paranoia: avoid brute force searches (bug 17342) + if ( !is_null( $params['user'] ) || !is_null( $params['excludeuser'] ) ) { + if ( !$user->isAllowed( 'deletedhistory' ) ) { + $bitmask = Revision::DELETED_USER; + } elseif ( !$user->isAllowed( 'suppressrevision' ) ) { + $bitmask = Revision::DELETED_USER | Revision::DELETED_RESTRICTED; + } else { + $bitmask = 0; + } + if ( $bitmask ) { + $this->addWhere( $this->getDB()->bitAnd( 'rc_deleted', $bitmask ) . " != $bitmask" ); + } + } + + // LogPage::DELETED_ACTION hides the affected page, too. So hide those + // entirely from the watchlist, or someone could guess the title. + if ( !$user->isAllowed( 'deletedhistory' ) ) { + $bitmask = LogPage::DELETED_ACTION; + } elseif ( !$user->isAllowed( 'suppressrevision' ) ) { + $bitmask = LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED; + } else { + $bitmask = 0; + } + if ( $bitmask ) { + $this->addWhere( $this->getDB()->makeList( array( + 'rc_type != ' . RC_LOG, + $this->getDB()->bitAnd( 'rc_deleted', $bitmask ) . " != $bitmask", + ), LIST_OR ) ); + } + $this->addOption( 'LIMIT', $params['limit'] + 1 ); $ids = array(); @@ -246,6 +273,11 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { } private function extractRowInfo( $row ) { + /* Determine the title of the page that has been changed. */ + $title = Title::makeTitle( $row->rc_namespace, $row->rc_title ); + $user = $this->getUser(); + + /* Our output data. */ $vals = array(); $type = intval( $row->rc_type ); @@ -274,87 +306,131 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { $vals['type'] = $type; } - if ( $this->fld_ids ) { - $vals['pageid'] = intval( $row->rc_cur_id ); - $vals['revid'] = intval( $row->rc_this_oldid ); - $vals['old_revid'] = intval( $row->rc_last_oldid ); - } - - $title = Title::makeTitle( $row->rc_namespace, $row->rc_title ); + $anyHidden = false; - if ( $this->fld_title ) { - ApiQueryBase::addTitleInfo( $vals, $title ); + /* Create a new entry in the result for the title. */ + if ( $this->fld_title || $this->fld_ids ) { + // These should already have been filtered out of the query, but just in case. + if ( $type === RC_LOG && ( $row->rc_deleted & LogPage::DELETED_ACTION ) ) { + $vals['actionhidden'] = ''; + $anyHidden = true; + } + if ( $type !== RC_LOG || + LogEventsList::userCanBitfield( $row->rc_deleted, LogPage::DELETED_ACTION, $user ) + ) { + if ( $this->fld_title ) { + ApiQueryBase::addTitleInfo( $vals, $title ); + } + if ( $this->fld_ids ) { + $vals['pageid'] = intval( $row->rc_cur_id ); + $vals['revid'] = intval( $row->rc_this_oldid ); + $vals['old_revid'] = intval( $row->rc_last_oldid ); + } + } } + /* Add user data and 'anon' flag, if user is anonymous. */ if ( $this->fld_user || $this->fld_userid ) { - - if ( $this->fld_userid ) { - $vals['userid'] = $row->rc_user; - // for backwards compatibility - $vals['user'] = $row->rc_user; + if ( $row->rc_deleted & Revision::DELETED_USER ) { + $vals['userhidden'] = ''; + $anyHidden = true; } + if ( Revision::userCanBitfield( $row->rc_deleted, Revision::DELETED_USER, $user ) ) { + if ( $this->fld_userid ) { + $vals['userid'] = $row->rc_user; + // for backwards compatibility + $vals['user'] = $row->rc_user; + } - if ( $this->fld_user ) { - $vals['user'] = $row->rc_user_text; - } + if ( $this->fld_user ) { + $vals['user'] = $row->rc_user_text; + } - if ( !$row->rc_user ) { - $vals['anon'] = ''; + if ( !$row->rc_user ) { + $vals['anon'] = ''; + } } } + /* Add flags, such as new, minor, bot. */ if ( $this->fld_flags ) { + if ( $row->rc_bot ) { + $vals['bot'] = ''; + } if ( $row->rc_type == RC_NEW ) { $vals['new'] = ''; } if ( $row->rc_minor ) { $vals['minor'] = ''; } - if ( $row->rc_bot ) { - $vals['bot'] = ''; - } } - if ( $this->fld_patrol && isset( $row->rc_patrolled ) ) { - $vals['patrolled'] = ''; + /* Add sizes of each revision. (Only available on 1.10+) */ + if ( $this->fld_sizes ) { + $vals['oldlen'] = intval( $row->rc_old_len ); + $vals['newlen'] = intval( $row->rc_new_len ); } + /* Add the timestamp. */ if ( $this->fld_timestamp ) { $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $row->rc_timestamp ); } - if ( $this->fld_sizes ) { - $vals['oldlen'] = intval( $row->rc_old_len ); - $vals['newlen'] = intval( $row->rc_new_len ); - } - if ( $this->fld_notificationtimestamp ) { $vals['notificationtimestamp'] = ( $row->wl_notificationtimestamp == null ) ? '' : wfTimestamp( TS_ISO_8601, $row->wl_notificationtimestamp ); } - if ( $this->fld_comment && isset( $row->rc_comment ) ) { - $vals['comment'] = $row->rc_comment; + /* Add edit summary / log summary. */ + if ( $this->fld_comment || $this->fld_parsedcomment ) { + if ( $row->rc_deleted & Revision::DELETED_COMMENT ) { + $vals['commenthidden'] = ''; + $anyHidden = true; + } + if ( Revision::userCanBitfield( $row->rc_deleted, Revision::DELETED_COMMENT, $user ) ) { + if ( $this->fld_comment && isset( $row->rc_comment ) ) { + $vals['comment'] = $row->rc_comment; + } + + if ( $this->fld_parsedcomment && isset( $row->rc_comment ) ) { + $vals['parsedcomment'] = Linker::formatComment( $row->rc_comment, $title ); + } + } + } + + /* Add the patrolled flag */ + if ( $this->fld_patrol && $row->rc_patrolled == 1 ) { + $vals['patrolled'] = ''; } - if ( $this->fld_parsedcomment && isset( $row->rc_comment ) ) { - $vals['parsedcomment'] = Linker::formatComment( $row->rc_comment, $title ); + if ( $this->fld_patrol && ChangesList::isUnpatrolled( $row, $user ) ) { + $vals['unpatrolled'] = ''; } if ( $this->fld_loginfo && $row->rc_type == RC_LOG ) { - $vals['logid'] = intval( $row->rc_logid ); - $vals['logtype'] = $row->rc_log_type; - $vals['logaction'] = $row->rc_log_action; - $logEntry = DatabaseLogEntry::newFromRow( (array)$row ); - ApiQueryLogEvents::addLogParams( - $this->getResult(), - $vals, - $logEntry->getParameters(), - $logEntry->getType(), - $logEntry->getSubtype(), - $logEntry->getTimestamp() - ); + if ( $row->rc_deleted & LogPage::DELETED_ACTION ) { + $vals['actionhidden'] = ''; + $anyHidden = true; + } + if ( LogEventsList::userCanBitfield( $row->rc_deleted, LogPage::DELETED_ACTION, $user ) ) { + $vals['logid'] = intval( $row->rc_logid ); + $vals['logtype'] = $row->rc_log_type; + $vals['logaction'] = $row->rc_log_action; + $logEntry = DatabaseLogEntry::newFromRow( (array)$row ); + ApiQueryLogEvents::addLogParams( + $this->getResult(), + $vals, + $logEntry->getParameters(), + $logEntry->getType(), + $logEntry->getSubtype(), + $logEntry->getTimestamp() + ); + } + } + + if ( $anyHidden && ( $row->rc_deleted & Revision::DELETED_RESTRICTED ) ) { + $vals['suppressed'] = ''; } return $vals; @@ -374,6 +450,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { return $retval; } + switch ( $type ) { case 'edit': return RC_EDIT; @@ -383,6 +460,8 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { return RC_LOG; case 'external': return RC_EXTERNAL; + default: + ApiBase::dieDebug( __METHOD__, "Unknown type '$type'" ); } } @@ -464,7 +543,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { ), 'token' => array( ApiBase::PARAM_TYPE => 'string' - ) + ), ); } @@ -508,7 +587,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { ), 'owner' => 'The name of the user whose watchlist you\'d like to access', 'token' => 'Give a security token (settable in preferences) to ' . - 'allow access to another user\'s watchlist' + 'allow access to another user\'s watchlist', ); }