function showList() { global $wgOut, $wgScript; $errors = array(); // Validate search IP $ip = $this->mSearchIP; if (!IP::isIPAddress($ip) && strlen($ip)) { $errors[] = array('globalblocking-list-ipinvalid', $ip); $ip = ''; } $wgOut->addWikiMsg('globalblocking-list-intro'); // Build the search form $searchForm = ''; $searchForm .= Xml::openElement('fieldset') . Xml::element('legend', null, wfMsg('globalblocking-search-legend')); $searchForm .= Xml::openElement('form', array('method' => 'get', 'action' => $wgScript, 'name' => 'globalblocklist-search')); $searchForm .= Html::hidden('title', SpecialPage::getTitleFor('GlobalBlockList')->getPrefixedText()); if (is_array($errors) && count($errors) > 0) { $errorstr = ''; foreach ($errors as $error) { if (is_array($error)) { $msg = array_shift($error); } else { $msg = $error; $error = array(); } $errorstr .= Xml::tags('li', null, wfMsgExt($msg, array('parseinline'), $error)); } $wgOut->addWikiMsg('globalblocking-unblock-errors', count($errors)); $wgOut->addHTML(Xml::tags('ul', array('class' => 'error'), $errorstr)); } $fields = array(); $fields['globalblocking-search-ip'] = Xml::input('ip', 45, $ip); $searchForm .= Xml::buildForm($fields, 'globalblocking-search-submit'); $searchForm .= Xml::closeElement('form') . Xml::closeElement('fieldset'); $wgOut->addHTML($searchForm); // Build a list of blocks. $conds = array(); if (strlen($ip)) { list($range_start, $range_end) = IP::parseRange($ip); if ($range_start != $range_end) { // They searched for a range. Match that exact range only $conds = array('gb_address' => $ip); } else { // They searched for an IP. Match any range covering that IP $hex_ip = IP::toHex($ip); $ip_pattern = substr($hex_ip, 0, 4) . '%'; // Don't bother checking blocks out of this /16. $dbr = wfGetDB(DB_SLAVE); $conds = array('gb_range_end>=' . $dbr->addQuotes($hex_ip), 'gb_range_start<=' . $dbr->addQuotes($hex_ip), 'gb_range_start like ' . $dbr->addQuotes($ip_pattern), 'gb_expiry>' . $dbr->addQuotes($dbr->timestamp(wfTimestampNow()))); } } $pager = new GlobalBlockListPager($this, $conds); $body = $pager->getBody(); if ($body != '') { $wgOut->addHTML($pager->getNavigationBar() . Html::rawElement('ul', array(), $body) . $pager->getNavigationBar()); } else { $wgOut->wrapWikiMsg("<div class='mw-globalblocking-noresults'>\n\$1</div>\n", array('globalblocking-list-noresults')); } }
function efNetworkAuth_checkForNetworkAuthUser() { global $wgNetworkAuthUsers; $ip = wfGetIP(); foreach ($wgNetworkAuthUsers as $networkAuthUser) { if (isset($networkAuthUser['user'])) { if (isset($networkAuthUser['iprange'])) { if (is_array($networkAuthUser['iprange'])) { $ranges = $networkAuthUser['iprange']; } else { $ranges = explode("\n", $networkAuthUser['iprange']); } $hex = IP::toHex($ip); foreach ($ranges as $range) { $parsedRange = IP::parseRange($range); if ($hex >= $parsedRange[0] && $hex <= $parsedRange[1]) { global $wgNetworkAuthHost; $wgNetworkAuthHost = $ip; return $networkAuthUser['user']; } } } if (isset($networkAuthUser['ippattern'])) { if (is_array($networkAuthUser['ippattern'])) { $patterns = $networkAuthUser['ippattern']; } else { $patterns = explode("\n", $networkAuthUser['ippattern']); } foreach ($patterns as $pattern) { if (preg_match($pattern, $ip)) { global $wgNetworkAuthHost; $wgNetworkAuthHost = $ip; return $networkAuthUser['user']; } } } if (isset($networkAuthUser['hostpattern'])) { if (is_array($networkAuthUser['hostpattern'])) { $patterns = $networkAuthUser['hostpattern']; } else { $patterns = explode("\n", $networkAuthUser['hostpattern']); } $host = gethostbyaddr($ip); foreach ($patterns as $pattern) { if (preg_match($pattern, $host)) { global $wgNetworkAuthHost; $wgNetworkAuthHost = $host; return $networkAuthUser['user']; } } } } else { # No user for range - useless. } } return ''; }
/** * Construct an IP address representation. * @param string $address The textual representation of an IP address or CIDR range. */ public function __construct($address) { // analyze address format $this->is_valid = IP::isIPAddress($address); if (!$this->is_valid) { return; } $this->is_ipv4 = IP::isIPv4($address); $this->is_ipv6 = !$this->is_ipv4 && IP::isIPv6($address); // analyze address range $this->is_range = IP::isValidBlock($address); $this->encoded_range = IP::parseRange($address); $this->range = array(IP::prettifyIP(IP::formatHex($this->encoded_range[self::START])), IP::prettifyIP(IP::formatHex($this->encoded_range[self::END]))); }
public function execute() { global $wgContLang; $db = $this->getDB(); $params = $this->extractRequestParams(); $this->requireMaxOneParameter($params, 'users', 'ip'); $prop = array_flip($params['prop']); $fld_id = isset($prop['id']); $fld_user = isset($prop['user']); $fld_userid = isset($prop['userid']); $fld_by = isset($prop['by']); $fld_byid = isset($prop['byid']); $fld_timestamp = isset($prop['timestamp']); $fld_expiry = isset($prop['expiry']); $fld_reason = isset($prop['reason']); $fld_range = isset($prop['range']); $fld_flags = isset($prop['flags']); $result = $this->getResult(); $this->addTables('ipblocks'); $this->addFields(array('ipb_auto', 'ipb_id', 'ipb_timestamp')); $this->addFieldsIf(array('ipb_address', 'ipb_user'), $fld_user || $fld_userid); $this->addFieldsIf('ipb_by_text', $fld_by); $this->addFieldsIf('ipb_by', $fld_byid); $this->addFieldsIf('ipb_expiry', $fld_expiry); $this->addFieldsIf('ipb_reason', $fld_reason); $this->addFieldsIf(array('ipb_range_start', 'ipb_range_end'), $fld_range); $this->addFieldsIf(array('ipb_anon_only', 'ipb_create_account', 'ipb_enable_autoblock', 'ipb_block_email', 'ipb_deleted', 'ipb_allow_usertalk'), $fld_flags); $this->addOption('LIMIT', $params['limit'] + 1); $this->addTimestampWhereRange('ipb_timestamp', $params['dir'], $params['start'], $params['end']); // Include in ORDER BY for uniqueness $this->addWhereRange('ipb_id', $params['dir'], null, null); if (!is_null($params['continue'])) { $cont = explode('|', $params['continue']); $this->dieContinueUsageIf(count($cont) != 2); $op = $params['dir'] == 'newer' ? '>' : '<'; $continueTimestamp = $db->addQuotes($db->timestamp($cont[0])); $continueId = (int) $cont[1]; $this->dieContinueUsageIf($continueId != $cont[1]); $this->addWhere("ipb_timestamp {$op} {$continueTimestamp} OR " . "(ipb_timestamp = {$continueTimestamp} AND " . "ipb_id {$op}= {$continueId})"); } if (isset($params['ids'])) { $this->addWhereFld('ipb_id', $params['ids']); } if (isset($params['users'])) { $usernames = array(); foreach ((array) $params['users'] as $u) { $usernames[] = $this->prepareUsername($u); } $this->addWhereFld('ipb_address', $usernames); $this->addWhereFld('ipb_auto', 0); } if (isset($params['ip'])) { $blockCIDRLimit = $this->getConfig()->get('BlockCIDRLimit'); if (IP::isIPv4($params['ip'])) { $type = 'IPv4'; $cidrLimit = $blockCIDRLimit['IPv4']; $prefixLen = 0; } elseif (IP::isIPv6($params['ip'])) { $type = 'IPv6'; $cidrLimit = $blockCIDRLimit['IPv6']; $prefixLen = 3; // IP::toHex output is prefixed with "v6-" } else { $this->dieUsage('IP parameter is not valid', 'param_ip'); } # Check range validity, if it's a CIDR list($ip, $range) = IP::parseCIDR($params['ip']); if ($ip !== false && $range !== false && $range < $cidrLimit) { $this->dieUsage("{$type} CIDR ranges broader than /{$cidrLimit} are not accepted", 'cidrtoobroad'); } # Let IP::parseRange handle calculating $upper, instead of duplicating the logic here. list($lower, $upper) = IP::parseRange($params['ip']); # Extract the common prefix to any rangeblock affecting this IP/CIDR $prefix = substr($lower, 0, $prefixLen + floor($cidrLimit / 4)); # Fairly hard to make a malicious SQL statement out of hex characters, # but it is good practice to add quotes $lower = $db->addQuotes($lower); $upper = $db->addQuotes($upper); $this->addWhere(array('ipb_range_start' . $db->buildLike($prefix, $db->anyString()), 'ipb_range_start <= ' . $lower, 'ipb_range_end >= ' . $upper, 'ipb_auto' => 0)); } if (!is_null($params['show'])) { $show = array_flip($params['show']); /* Check for conflicting parameters. */ if (isset($show['account']) && isset($show['!account']) || isset($show['ip']) && isset($show['!ip']) || isset($show['range']) && isset($show['!range']) || isset($show['temp']) && isset($show['!temp'])) { $this->dieUsageMsg('show'); } $this->addWhereIf('ipb_user = 0', isset($show['!account'])); $this->addWhereIf('ipb_user != 0', isset($show['account'])); $this->addWhereIf('ipb_user != 0 OR ipb_range_end > ipb_range_start', isset($show['!ip'])); $this->addWhereIf('ipb_user = 0 AND ipb_range_end = ipb_range_start', isset($show['ip'])); $this->addWhereIf('ipb_expiry = ' . $db->addQuotes($db->getInfinity()), isset($show['!temp'])); $this->addWhereIf('ipb_expiry != ' . $db->addQuotes($db->getInfinity()), isset($show['temp'])); $this->addWhereIf('ipb_range_end = ipb_range_start', isset($show['!range'])); $this->addWhereIf('ipb_range_end > ipb_range_start', isset($show['range'])); } if (!$this->getUser()->isAllowed('hideuser')) { $this->addWhereFld('ipb_deleted', 0); } // Purge expired entries on one in every 10 queries if (!mt_rand(0, 10)) { Block::purgeExpired(); } $res = $this->select(__METHOD__); $count = 0; foreach ($res as $row) { if (++$count > $params['limit']) { // We've had enough $this->setContinueEnumParameter('continue', "{$row->ipb_timestamp}|{$row->ipb_id}"); break; } $block = array(ApiResult::META_TYPE => 'assoc'); if ($fld_id) { $block['id'] = (int) $row->ipb_id; } if ($fld_user && !$row->ipb_auto) { $block['user'] = $row->ipb_address; } if ($fld_userid && !$row->ipb_auto) { $block['userid'] = (int) $row->ipb_user; } if ($fld_by) { $block['by'] = $row->ipb_by_text; } if ($fld_byid) { $block['byid'] = (int) $row->ipb_by; } if ($fld_timestamp) { $block['timestamp'] = wfTimestamp(TS_ISO_8601, $row->ipb_timestamp); } if ($fld_expiry) { $block['expiry'] = $wgContLang->formatExpiry($row->ipb_expiry, TS_ISO_8601); } if ($fld_reason) { $block['reason'] = $row->ipb_reason; } if ($fld_range && !$row->ipb_auto) { $block['rangestart'] = IP::formatHex($row->ipb_range_start); $block['rangeend'] = IP::formatHex($row->ipb_range_end); } if ($fld_flags) { // For clarity, these flags use the same names as their action=block counterparts $block['automatic'] = (bool) $row->ipb_auto; $block['anononly'] = (bool) $row->ipb_anon_only; $block['nocreate'] = (bool) $row->ipb_create_account; $block['autoblock'] = (bool) $row->ipb_enable_autoblock; $block['noemail'] = (bool) $row->ipb_block_email; $block['hidden'] = (bool) $row->ipb_deleted; $block['allowusertalk'] = (bool) $row->ipb_allow_usertalk; } $fit = $result->addValue(array('query', $this->getModuleName()), null, $block); if (!$fit) { $this->setContinueEnumParameter('continue', "{$row->ipb_timestamp}|{$row->ipb_id}"); break; } } $result->addIndexedTagName(array('query', $this->getModuleName()), 'block'); }
/** * Get the IP address at the end of the range in Hex form * @throws MWException * @return string IP in Hex form */ public function getRangeEnd() { switch ($this->type) { case self::TYPE_USER: return ''; case self::TYPE_IP: return IP::toHex($this->target); case self::TYPE_RANGE: list(, $end) = IP::parseRange($this->target); return $end; default: throw new MWException("Block with invalid type"); } }
public static function addLogEntry($logType, $targetType, $target, $reason, $targetID = 0) { global $wgUser; if ($targetType == 'ip') { list($rangeStart, $rangeEnd) = IP::parseRange($target); $targetHex = $rangeStart; if ($rangeStart == $rangeEnd) { $rangeStart = $rangeEnd = ''; } } else { $targetHex = $rangeStart = $rangeEnd = ''; } $dbw = wfGetDB(DB_MASTER); $cul_id = $dbw->nextSequenceValue('cu_log_cul_id_seq'); $dbw->insert('cu_log', array('cul_id' => $cul_id, 'cul_timestamp' => $dbw->timestamp(), 'cul_user' => $wgUser->getID(), 'cul_user_text' => $wgUser->getName(), 'cul_reason' => $reason, 'cul_type' => $logType, 'cul_target_id' => $targetID, 'cul_target_text' => $target, 'cul_target_hex' => $targetHex, 'cul_range_start' => $rangeStart, 'cul_range_end' => $rangeEnd), __METHOD__); return true; }
function showList() { # Purge expired entries on one in every 10 queries if (!mt_rand(0, 10)) { Block::purgeExpired(); } $conds = array(); # Is the user allowed to see hidden blocks? if (!$this->getUser()->isAllowed('hideuser')) { $conds['ipb_deleted'] = 0; } if ($this->target !== '') { list($target, $type) = Block::parseTarget($this->target); switch ($type) { case Block::TYPE_ID: case Block::TYPE_AUTO: $conds['ipb_id'] = $target; break; case Block::TYPE_IP: case Block::TYPE_RANGE: list($start, $end) = IP::parseRange($target); $dbr = wfGetDB(DB_SLAVE); $conds[] = $dbr->makeList(array('ipb_address' => $target, Block::getRangeCond($start, $end)), LIST_OR); $conds['ipb_auto'] = 0; break; case Block::TYPE_USER: $conds['ipb_address'] = (string) $this->target; $conds['ipb_auto'] = 0; break; } } # Apply filters if (in_array('userblocks', $this->options)) { $conds['ipb_user'] = 0; } if (in_array('tempblocks', $this->options)) { $conds['ipb_expiry'] = 'infinity'; } if (in_array('addressblocks', $this->options)) { $conds[] = "ipb_user != 0 OR ipb_range_end > ipb_range_start"; } if (in_array('rangeblocks', $this->options)) { $conds[] = "ipb_range_end = ipb_range_start"; } # Check for other blocks, i.e. global/tor blocks $otherBlockLink = array(); wfRunHooks('OtherBlockLogLink', array(&$otherBlockLink, $this->target)); $out = $this->getOutput(); # Show additional header for the local block only when other blocks exists. # Not necessary in a standard installation without such extensions enabled if (count($otherBlockLink)) { $out->addHTML(Html::element('h2', array(), $this->msg('ipblocklist-localblock')->text()) . "\n"); } $pager = new BlockListPager($this, $conds); if ($pager->getNumRows()) { $out->addHTML($pager->getNavigationBar() . $pager->getBody() . $pager->getNavigationBar()); } elseif ($this->target) { $out->addWikiMsg('ipblocklist-no-results'); } else { $out->addWikiMsg('ipblocklist-empty'); } if (count($otherBlockLink)) { $out->addHTML(Html::rawElement('h2', array(), $this->msg('ipblocklist-otherblocks', count($otherBlockLink))->parse()) . "\n"); $list = ''; foreach ($otherBlockLink as $link) { $list .= Html::rawElement('li', array(), $link) . "\n"; } $out->addHTML(Html::rawElement('ul', array('class' => 'mw-ipblocklist-otherblocks'), $list) . "\n"); } }
/** * TODO: move this list to the database in a global IP info table incorporating * trusted ISP proxies, blocked IP addresses and open proxies. */ function wfIsAOLProxy($ip) { $ranges = array('64.12.96.0/19', '149.174.160.0/20', '152.163.240.0/21', '152.163.248.0/22', '152.163.252.0/23', '152.163.96.0/22', '152.163.100.0/23', '195.93.32.0/22', '195.93.48.0/22', '195.93.64.0/19', '195.93.96.0/19', '195.93.16.0/20', '198.81.0.0/22', '198.81.16.0/20', '198.81.8.0/23', '202.67.64.128/25', '205.188.192.0/20', '205.188.208.0/23', '205.188.112.0/20', '205.188.146.144/30', '207.200.112.0/21'); static $parsedRanges; if (is_null($parsedRanges)) { $parsedRanges = array(); foreach ($ranges as $range) { $parsedRanges[] = IP::parseRange($range); } } $hex = IP::toHex($ip); foreach ($parsedRanges as $range) { if ($hex >= $range[0] && $hex <= $range[1]) { return true; } } return false; }
/** * Setup a new BlockListPager instance. * @return BlockListPager */ protected function getBlockListPager() { $conds = []; # Is the user allowed to see hidden blocks? if (!$this->getUser()->isAllowed('hideuser')) { $conds['ipb_deleted'] = 0; } if ($this->target !== '') { list($target, $type) = Block::parseTarget($this->target); switch ($type) { case Block::TYPE_ID: case Block::TYPE_AUTO: $conds['ipb_id'] = $target; break; case Block::TYPE_IP: case Block::TYPE_RANGE: list($start, $end) = IP::parseRange($target); $conds[] = wfGetDB(DB_REPLICA)->makeList(['ipb_address' => $target, Block::getRangeCond($start, $end)], LIST_OR); $conds['ipb_auto'] = 0; break; case Block::TYPE_USER: $conds['ipb_address'] = $target->getName(); $conds['ipb_auto'] = 0; break; } } # Apply filters if (in_array('userblocks', $this->options)) { $conds['ipb_user'] = 0; } if (in_array('tempblocks', $this->options)) { $conds['ipb_expiry'] = 'infinity'; } if (in_array('addressblocks', $this->options)) { $conds[] = "ipb_user != 0 OR ipb_range_end > ipb_range_start"; } if (in_array('rangeblocks', $this->options)) { $conds[] = "ipb_range_end = ipb_range_start"; } return new BlockListPager($this, $conds); }
break; } // Remove comment $hashPos = strpos( $line, '#' ); if ( $hashPos !== false ) { $line = substr( $line, 0, $hashPos ); } // Strip spaces $line = trim( $line ); if ( $line == '' ) { // Comment or blank line continue; } list( $start, $end ) = IP::parseRange( $line ); if ( $start === false ) { // Try DNS $names[] = array( $lineNum, $line ); continue; } $ranges[] = array( $lineNum, $start, $end ); } echo count( $names ) . " DNS queries to do...\n"; foreach ( $names as $i => $nameInfo ) { list( $lineNum, $name ) = $nameInfo; $ips = gethostbynamel( $name ); if ( $ips === false ) { echo "Not a valid host or IP address on line $lineNum: $name\n"; } else {
function initialiseRange() { $this->mRangeStart = ''; $this->mRangeEnd = ''; if ($this->mUser == 0) { list($this->mRangeStart, $this->mRangeEnd) = IP::parseRange($this->mAddress); } }
/** * Primitive rate limits: enforce maximum actions per time period * to put a brake on flooding. * * @note When using a shared cache like memcached, IP-address * last-hit counters will be shared across wikis. * * @param string $action Action to enforce; 'edit' if unspecified * @param integer $incrBy Positive amount to increment counter by [defaults to 1] * @return bool True if a rate limiter was tripped */ public function pingLimiter( $action = 'edit', $incrBy = 1 ) { // Call the 'PingLimiter' hook $result = false; if ( !wfRunHooks( 'PingLimiter', array( &$this, $action, &$result, $incrBy ) ) ) { return $result; } global $wgRateLimits; if ( !isset( $wgRateLimits[$action] ) ) { return false; } // Some groups shouldn't trigger the ping limiter, ever if ( !$this->isPingLimitable() ) { return false; } global $wgMemc, $wgRateLimitLog; wfProfileIn( __METHOD__ ); $limits = $wgRateLimits[$action]; $keys = array(); $id = $this->getId(); $userLimit = false; if ( isset( $limits['anon'] ) && $id == 0 ) { $keys[wfMemcKey( 'limiter', $action, 'anon' )] = $limits['anon']; } if ( isset( $limits['user'] ) && $id != 0 ) { $userLimit = $limits['user']; } if ( $this->isNewbie() ) { if ( isset( $limits['newbie'] ) && $id != 0 ) { $keys[wfMemcKey( 'limiter', $action, 'user', $id )] = $limits['newbie']; } if ( isset( $limits['ip'] ) ) { $ip = $this->getRequest()->getIP(); $keys["mediawiki:limiter:$action:ip:$ip"] = $limits['ip']; } if ( isset( $limits['subnet'] ) ) { $ip = $this->getRequest()->getIP(); $matches = array(); $subnet = false; if ( IP::isIPv6( $ip ) ) { $parts = IP::parseRange( "$ip/64" ); $subnet = $parts[0]; } elseif ( preg_match( '/^(\d+\.\d+\.\d+)\.\d+$/', $ip, $matches ) ) { // IPv4 $subnet = $matches[1]; } if ( $subnet !== false ) { $keys["mediawiki:limiter:$action:subnet:$subnet"] = $limits['subnet']; } } } // Check for group-specific permissions // If more than one group applies, use the group with the highest limit foreach ( $this->getGroups() as $group ) { if ( isset( $limits[$group] ) ) { if ( $userLimit === false || $limits[$group] > $userLimit ) { $userLimit = $limits[$group]; } } } // Set the user limit key if ( $userLimit !== false ) { list( $max, $period ) = $userLimit; wfDebug( __METHOD__ . ": effective user limit: $max in {$period}s\n" ); $keys[wfMemcKey( 'limiter', $action, 'user', $id )] = $userLimit; } $triggered = false; foreach ( $keys as $key => $limit ) { list( $max, $period ) = $limit; $summary = "(limit $max in {$period}s)"; $count = $wgMemc->get( $key ); // Already pinged? if ( $count ) { if ( $count >= $max ) { wfDebug( __METHOD__ . ": tripped! $key at $count $summary\n" ); if ( $wgRateLimitLog ) { wfSuppressWarnings(); file_put_contents( $wgRateLimitLog, wfTimestamp( TS_MW ) . ' ' . wfWikiID() . ': ' . $this->getName() . " tripped $key at $count $summary\n", FILE_APPEND ); wfRestoreWarnings(); } $triggered = true; } else { wfDebug( __METHOD__ . ": ok. $key at $count $summary\n" ); } } else { wfDebug( __METHOD__ . ": adding record for $key $summary\n" ); if ( $incrBy > 0 ) { $wgMemc->add( $key, 0, intval( $period ) ); // first ping } } if ( $incrBy > 0 ) { $wgMemc->incr( $key, $incrBy ); } } wfProfileOut( __METHOD__ ); return $triggered; }
/** * Determine if a given integer IPv4 address is in a given CIDR network * @param $addr The address to check against the given range. * @param $range The range to check the given address against. * @return bool Whether or not the given address is in the given range. */ public static function isInRange($addr, $range) { $unsignedIP = IP::toUnsigned($addr); list($start, $end) = IP::parseRange($range); $start = hexdec($start); $end = hexdec($end); return $unsignedIP >= $start && $unsignedIP <= $end; }
/** * Primitive rate limits: enforce maximum actions per time period * to put a brake on flooding. * * The method generates both a generic profiling point and a per action one * (suffix being "-$action". * * @note When using a shared cache like memcached, IP-address * last-hit counters will be shared across wikis. * * @param string $action Action to enforce; 'edit' if unspecified * @param int $incrBy Positive amount to increment counter by [defaults to 1] * @return bool True if a rate limiter was tripped */ public function pingLimiter($action = 'edit', $incrBy = 1) { // Call the 'PingLimiter' hook $result = false; if (!Hooks::run('PingLimiter', array(&$this, $action, &$result, $incrBy))) { return $result; } global $wgRateLimits; if (!isset($wgRateLimits[$action])) { return false; } // Some groups shouldn't trigger the ping limiter, ever if (!$this->isPingLimitable()) { return false; } global $wgMemc; $limits = $wgRateLimits[$action]; $keys = array(); $id = $this->getId(); $userLimit = false; if (isset($limits['anon']) && $id == 0) { $keys[wfMemcKey('limiter', $action, 'anon')] = $limits['anon']; } if (isset($limits['user']) && $id != 0) { $userLimit = $limits['user']; } if ($this->isNewbie()) { if (isset($limits['newbie']) && $id != 0) { $keys[wfMemcKey('limiter', $action, 'user', $id)] = $limits['newbie']; } if (isset($limits['ip'])) { $ip = $this->getRequest()->getIP(); $keys["mediawiki:limiter:{$action}:ip:{$ip}"] = $limits['ip']; } if (isset($limits['subnet'])) { $ip = $this->getRequest()->getIP(); $matches = array(); $subnet = false; if (IP::isIPv6($ip)) { $parts = IP::parseRange("{$ip}/64"); $subnet = $parts[0]; } elseif (preg_match('/^(\\d+\\.\\d+\\.\\d+)\\.\\d+$/', $ip, $matches)) { // IPv4 $subnet = $matches[1]; } if ($subnet !== false) { $keys["mediawiki:limiter:{$action}:subnet:{$subnet}"] = $limits['subnet']; } } } // Check for group-specific permissions // If more than one group applies, use the group with the highest limit foreach ($this->getGroups() as $group) { if (isset($limits[$group])) { if ($userLimit === false || $limits[$group][0] / $limits[$group][1] > $userLimit[0] / $userLimit[1]) { $userLimit = $limits[$group]; } } } // Set the user limit key if ($userLimit !== false) { list($max, $period) = $userLimit; wfDebug(__METHOD__ . ": effective user limit: {$max} in {$period}s\n"); $keys[wfMemcKey('limiter', $action, 'user', $id)] = $userLimit; } $triggered = false; foreach ($keys as $key => $limit) { list($max, $period) = $limit; $summary = "(limit {$max} in {$period}s)"; $count = $wgMemc->get($key); // Already pinged? if ($count) { if ($count >= $max) { wfDebugLog('ratelimit', "User '{$this->getName()}' " . "(IP {$this->getRequest()->getIP()}) tripped {$key} at {$count} {$summary}"); $triggered = true; } else { wfDebug(__METHOD__ . ": ok. {$key} at {$count} {$summary}\n"); } } else { wfDebug(__METHOD__ . ": adding record for {$key} {$summary}\n"); if ($incrBy > 0) { $wgMemc->add($key, 0, intval($period)); // first ping } } if ($incrBy > 0) { $wgMemc->incr($key, $incrBy); } } return $triggered; }
function execute($par) { $this->checkPermissions(); $out = $this->getOutput(); $request = $this->getRequest(); $this->setHeaders(); $type = $request->getVal('cuSearchType'); $target = $request->getVal('cuSearch'); $year = $request->getIntOrNull('year'); $month = $request->getIntOrNull('month'); $error = false; $dbr = wfGetDB(DB_SLAVE); $searchConds = false; if ($type === null) { $type = 'target'; } elseif ($type == 'initiator') { $user = User::newFromName($target); if (!$user || !$user->getID()) { $error = 'checkuser-user-nonexistent'; } else { $searchConds = array('cul_user' => $user->getID()); } } else { $type = 'target'; // Is it an IP? list($start, $end) = IP::parseRange($target); if ($start !== false) { if ($start == $end) { $searchConds = array('cul_target_hex = ' . $dbr->addQuotes($start) . ' OR ' . '(cul_range_end >= ' . $dbr->addQuotes($start) . ' AND ' . 'cul_range_start <= ' . $dbr->addQuotes($end) . ')'); } else { $searchConds = array('(cul_target_hex >= ' . $dbr->addQuotes($start) . ' AND ' . 'cul_target_hex <= ' . $dbr->addQuotes($end) . ') OR ' . '(cul_range_end >= ' . $dbr->addQuotes($start) . ' AND ' . 'cul_range_start <= ' . $dbr->addQuotes($end) . ')'); } } else { // Is it a user? $user = User::newFromName($target); if ($user && $user->getID()) { $searchConds = array('cul_type' => array('userips', 'useredits'), 'cul_target_id' => $user->getID()); } elseif ($target) { $error = 'checkuser-user-nonexistent'; } } } $out->addHTML(Linker::linkKnown($this->getCheckUserFormTitle(), $this->msg('checkuser-log-return'))); $searchTypes = array('initiator', 'target'); $select = "<select name=\"cuSearchType\" style='margin-top:.2em;'>\n"; foreach ($searchTypes as $searchType) { if ($type == $searchType) { $checked = 'selected="selected"'; } else { $checked = ''; } $caption = wfMsgHtml('checkuser-search-' . $searchType); $select .= "<option value=\"{$searchType}\" {$checked}>{$caption}</option>\n"; } $select .= '</select>'; $encTarget = htmlspecialchars($target); $msgSearch = wfMsgHtml('checkuser-search'); $input = "<input type=\"text\" name=\"cuSearch\" value=\"{$encTarget}\" size=\"40\"/>"; $msgSearchForm = wfMsgHtml('checkuser-search-form', $select, $input); $formAction = $this->getTitle()->escapeLocalURL(); $msgSearchSubmit = '  ' . wfMsgHtml('checkuser-search-submit') . '  '; $s = "<form method='get' action=\"{$formAction}\">\n" . "<fieldset><legend>{$msgSearch}</legend>\n" . "<p>{$msgSearchForm}</p>\n" . "<p>" . Xml::dateMenu($year, $month) . "   \n" . "<input type=\"submit\" name=\"cuSearchSubmit\" value=\"{$msgSearchSubmit}\"/></p>\n" . "</fieldset></form>\n"; $out->addHTML($s); if ($error !== false) { $out->wrapWikiMsg('<div class="errorbox">$1</div>', $error); return; } $pager = new CheckUserLogPager($this, $searchConds, $year, $month); $out->addHTML($pager->getNavigationBar() . $pager->getBody() . $pager->getNavigationBar()); }
/** * Returns the subnet of a given IP * * @param string $ip * @return string|false */ public static function getSubnet($ip) { $matches = array(); $subnet = false; if (IP::isIPv6($ip)) { $parts = IP::parseRange("{$ip}/64"); $subnet = $parts[0]; } elseif (preg_match('/^(\\d+\\.\\d+\\.\\d+)\\.\\d+$/', $ip, $matches)) { // IPv4 $subnet = $matches[1]; } return $subnet; }
static function insertBlock($address, $reason, $expiry, $options = array()) { global $wgUser; $errors = array(); ## Purge expired blocks. GlobalBlocking::purgeExpired(); ## Validate input $ip = IP::sanitizeIP($address); $anonOnly = in_array('anon-only', $options); $modify = in_array('modify', $options); if (!IP::isIPAddress($ip)) { // Invalid IP address. $errors[] = array('globalblocking-block-ipinvalid', $ip); } if (false === $expiry) { $errors[] = array('globalblocking-block-expiryinvalid', $expiry); } $existingBlock = GlobalBlocking::getGlobalBlockId($ip); if (!$modify && $existingBlock) { $errors[] = array('globalblocking-block-alreadyblocked', $ip); } // Check for too-big ranges. list($range_start, $range_end) = IP::parseRange($ip); if (substr($range_start, 0, 4) != substr($range_end, 0, 4)) { // Range crosses a /16 boundary. $errors[] = array('globalblocking-block-bigrange', $ip); } // Normalise the range if ($range_start != $range_end) { $ip = Block::normaliseRange($ip); } if (count($errors) > 0) { return $errors; } // We're a-ok. $dbw = GlobalBlocking::getGlobalBlockingMaster(); // Delete the old block, if applicable if ($modify) { $dbw->delete('globalblocks', array('gb_id' => $existingBlock), __METHOD__); } $row = array(); $row['gb_address'] = $ip; $row['gb_by'] = $wgUser->getName(); $row['gb_by_wiki'] = wfWikiId(); $row['gb_reason'] = $reason; $row['gb_timestamp'] = $dbw->timestamp(wfTimestampNow()); $row['gb_anon_only'] = $anonOnly; $row['gb_expiry'] = Block::encodeExpiry($expiry, $dbw); list($row['gb_range_start'], $row['gb_range_end']) = array($range_start, $range_end); $dbw->insert('globalblocks', $row, __METHOD__); return array(); }