public function save() { wfProfileIn(__METHOD__); $action = ""; if ($this->data['type'] & self::TYPE_USER && User::isIP($this->data['text'])) { $this->data['ip_hex'] = IP::toHex($this->data['text']); } $dbw = wfGetDB(DB_MASTER, array(), $this->wg->ExternalSharedDB); if (empty($this->data['id'])) { /* add block */ $dbw->insert($this->db_table, $this->mapToDB(), __METHOD__); $action = 'add'; } else { $dbw->update($this->db_table, $this->mapToDB(), array('p_id' => $this->data['id']), __METHOD__); $action = 'edit'; } if ($dbw->affectedRows()) { if ($action == 'add') { $this->data['id'] = $dbw->insertId(); } $this->log($action); } else { $action = ''; } $dbw->commit(); wfProfileOut(__METHOD__); return $action ? $this->data['id'] : false; }
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 ''; }
function isTrusted( $ip ) { $cdb = $this->getCdbHandle(); // Try single host $hex = IP::toHex( $ip ); $data = dba_fetch( $hex, $cdb ); if ( $data ) { return true; } // TODO: IPv6 prefixes which aren't feasible to expand return false; }
/** * Get a block * @param string $ip The IP address to be checked * @param boolean $anon Get anon blocks only * @return object The block */ static function getGlobalBlockingBlock($ip, $anon) { $dbr = GlobalBlocking::getGlobalBlockingSlave(); $hex_ip = IP::toHex($ip); $ip_pattern = substr($hex_ip, 0, 4) . '%'; // Don't bother checking blocks out of this /16. $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()))); if (!$anon) { $conds['gb_anon_only'] = 0; } // Get the block $block = $dbr->selectRow('globalblocks', '*', $conds, __METHOD__); return $block; }
public function onCheckUserInsertForRecentChange($rc, &$fields) { $fields['cuc_ip'] = IP::sanitizeIP($this->ip); $fields['cuc_ip_hex'] = $this->ip ? IP::toHex($this->ip) : null; $fields['cuc_agent'] = $this->ua; if (method_exists('CheckUserHooks', 'getClientIPfromXFF')) { list($xff_ip, $isSquidOnly) = CheckUserHooks::getClientIPfromXFF($this->xff); $fields['cuc_xff'] = !$isSquidOnly ? $this->xff : ''; $fields['cuc_xff_hex'] = $xff_ip && !$isSquidOnly ? IP::toHex($xff_ip) : null; } else { $fields['cuc_xff'] = ''; $fields['cuc_xff_hex'] = null; } }
/** * Hook function for RecentChange_save * Saves user data into the cu_changes table */ function efUpdateCheckUserData($rc) { global $wgUser; // Extract params extract($rc->mAttribs); // Get IP $ip = wfGetIP(); // Get XFF header $xff = wfGetForwardedFor(); list($xff_ip, $trusted) = efGetClientIPfromXFF($xff); // Our squid XFFs can flood this up sometimes $isSquidOnly = efXFFChainIsSquid($xff); // Get agent $agent = wfGetAgent(); // Store the log action text for log events // $rc_comment should just be the log_comment // BC: check if log_type and log_action exists // If not, then $rc_comment is the actiontext and comment if (isset($rc_log_type) && $rc_type == RC_LOG) { $target = Title::makeTitle($rc_namespace, $rc_title); $actionText = LogPage::actionText($rc_log_type, $rc_log_action, $target, NULL, explode('\\n', $rc_params)); } else { $actionText = ''; } $dbw = wfGetDB(DB_MASTER); $cuc_id = $dbw->nextSequenceValue('cu_changes_cu_id_seq'); $rcRow = array('cuc_id' => $cuc_id, 'cuc_namespace' => $rc_namespace, 'cuc_title' => $rc_title, 'cuc_minor' => $rc_minor, 'cuc_user' => $rc_user, 'cuc_user_text' => $rc_user_text, 'cuc_actiontext' => $actionText, 'cuc_comment' => $rc_comment, 'cuc_this_oldid' => $rc_this_oldid, 'cuc_last_oldid' => $rc_last_oldid, 'cuc_type' => $rc_type, 'cuc_timestamp' => $rc_timestamp, 'cuc_ip' => IP::sanitizeIP($ip), 'cuc_ip_hex' => $ip ? IP::toHex($ip) : null, 'cuc_xff' => !$isSquidOnly ? $xff : '', 'cuc_xff_hex' => $xff_ip && !$isSquidOnly ? IP::toHex($xff_ip) : null, 'cuc_agent' => $agent); ## On PG, MW unsets cur_id due to schema incompatibilites. So it may not be set! if (isset($rc_cur_id)) { $rcRow['cuc_page_id'] = $rc_cur_id; } $dbw->insert('cu_changes', $rcRow, __METHOD__); # Every 100th edit, prune the checkuser changes table. wfSeedRandom(); if (0 == mt_rand(0, 99)) { # Periodically flush old entries from the recentchanges table. global $wgCUDMaxAge; $cutoff = $dbw->timestamp(time() - $wgCUDMaxAge); $recentchanges = $dbw->tableName('cu_changes'); $sql = "DELETE FROM {$recentchanges} WHERE cuc_timestamp < '{$cutoff}'"; $dbw->query($sql); } return true; }
/** * save * * @return boolean: true on success, false on failure */ public static function save($data, $updateCache = true) { global $wgExternalSharedDB, $wgMemc; $result = false; wfProfileIn(__METHOD__); if ($data['type'] & Phalanx::TYPE_USER && User::isIP($data['text'])) { $data['ip_hex'] = IP::toHex($data['text']); } $dbw = wfGetDB(DB_MASTER, array(), $wgExternalSharedDB); $dbw->insert('phalanx', self::convertDataToDB($data), __METHOD__); if ($dbw->affectedRows()) { $data['id'] = $result = $dbw->insertId(); $dbw->commit(); if ($updateCache) { self::updateCache(null, $data); } self::logAdd($data); self::reload($data['id']); } wfProfileOut(__METHOD__); return $result; }
public function execute() { $params = $this->extractRequestParams(); $prop = array_flip($params['prop']); $fld_id = isset($prop['id']); $fld_address = isset($prop['address']); $fld_by = isset($prop['by']); $fld_timestamp = isset($prop['timestamp']); $fld_expiry = isset($prop['expiry']); $fld_reason = isset($prop['reason']); $fld_range = isset($prop['range']); $result = $this->getResult(); $data = array(); $this->addTables('globalblocks'); if ($fld_id) { $this->addFields('gb_id'); } if ($fld_address) { $this->addFields(array('gb_address', 'gb_anon_only')); } if ($fld_by) { $this->addFields(array('gb_by', 'gb_by_wiki')); } if ($fld_timestamp) { $this->addFields('gb_timestamp'); } if ($fld_expiry) { $this->addFields('gb_expiry'); } if ($fld_reason) { $this->addFields('gb_reason'); } if ($fld_range) { $this->addFields(array('gb_range_start', 'gb_range_end')); } $this->addOption('LIMIT', $params['limit'] + 1); $this->addWhereRange('gb_timestamp', $params['dir'], $params['start'], $params['end']); if (isset($params['ids'])) { $this->addWhereFld('gb_id', $params['ids']); } if (isset($params['addresses'])) { $this->addWhereFld('gb_address', $params['addresses']); } if (isset($params['ip'])) { list($ip, $range) = IP::parseCIDR($params['ip']); if ($ip && $range) { # We got a CIDR range if ($range < 16) { $this->dieUsage('CIDR ranges broader than /16 are not accepted', 'cidrtoobroad'); } $lower = wfBaseConvert($ip, 10, 16, 8, false); $upper = wfBaseConvert($ip + pow(2, 32 - $range) - 1, 10, 16, 8, false); } else { $lower = $upper = IP::toHex($params['ip']); } $prefix = substr($lower, 0, 4); $this->addWhere(array("gb_range_start LIKE '{$prefix}%'", "gb_range_start <= '{$lower}'", "gb_range_end >= '{$upper}'")); } $res = $this->select(__METHOD__); $count = 0; foreach ($res as $row) { if (++$count > $params['limit']) { // We've had enough $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->gb_timestamp)); break; } $block = array(); if ($fld_id) { $block['id'] = $row->gb_id; } if ($fld_address) { $block['address'] = $row->gb_address; if ($row->gb_anon_only) { $block['anononly'] = ''; } } if ($fld_by) { $block['by'] = $row->gb_by; $block['bywiki'] = $row->gb_by_wiki; } if ($fld_timestamp) { $block['timestamp'] = wfTimestamp(TS_ISO_8601, $row->gb_timestamp); } if ($fld_expiry) { $block['expiry'] = Block::decodeExpiry($row->gb_expiry, TS_ISO_8601); } if ($fld_reason) { $block['reason'] = $row->gb_reason; } if ($fld_range) { $block['rangestart'] = IP::hexToQuad($row->gb_range_start); $block['rangeend'] = IP::hexToQuad($row->gb_range_end); } $data[] = $block; } $result->setIndexedTagName($data, 'block'); $result->addValue('query', $this->getModuleName(), $data); }
/** * Directly check for IP block which is quicker than looping through all filters as we don't support * anything other than exact for IP blocks, and this significantly improves performance * * @author grunny */ protected static function blockCheckIP(User $user, $text, $writeStats = true) { global $wgMemc, $wgExternalSharedDB; wfProfileIn(__METHOD__); PhalanxShadowing::setType(Phalanx::TYPE_USER); $dbr = wfGetDB(DB_SLAVE, array(), $wgExternalSharedDB); $moduleId = Phalanx::TYPE_USER; $timestampNow = wfTimestampNow(); $ipAddr = IP::toHex($text); $row = $dbr->selectRow('phalanx', '*', array("p_type & {$moduleId} = {$moduleId}", "p_lang IS NULL", 'p_ip_hex' => $ipAddr, "p_expire IS NULL OR p_expire > {$dbr->addQuotes($timestampNow)}"), __METHOD__); if ($row !== false) { $blockData = array('id' => $row->p_id, 'author_id' => $row->p_author_id, 'text' => $row->p_text, 'type' => $row->p_type, 'timestamp' => $row->p_timestamp, 'expire' => $row->p_expire, 'exact' => $row->p_exact, 'regex' => $row->p_regex, 'case' => $row->p_case, 'reason' => $row->p_reason, 'lang' => $row->p_lang); Wikia::log(__METHOD__, __LINE__, "Block '{$blockData['text']}' blocked '{$text}'."); if ($writeStats) { Phalanx::addStats($blockData['id'], $blockData['type']); } self::setUserData($user, $blockData, $text, true); $cachedState = array('timestamp' => wfTimestampNow(), 'block' => $blockData, 'return' => false); $wgMemc->set(self::getCacheKey($user), $cachedState); PhalanxShadowing::check($user->getName(), $blockData['id']); wfProfileOut(__METHOD__); return false; } PhalanxShadowing::check($user->getName(), 0); wfProfileOut(__METHOD__); return true; }
/** * Get the IP address at the start of the range in Hex form * @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"); } }
/** * 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; }
public function execute() { global $wgUser; $params = $this->extractRequestParams(); if (isset($params['users']) && isset($params['ip'])) { $this->dieUsage('bkusers and bkip cannot be used together', 'usersandip'); } $prop = array_flip($params['prop']); $fld_id = isset($prop['id']); $fld_user = isset($prop['user']); $fld_by = isset($prop['by']); $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(); $pageSet = $this->getPageSet(); $titles = $pageSet->getTitles(); $data = array(); $this->addTables('ipblocks'); if ($fld_id) { $this->addFields('ipb_id'); } if ($fld_user) { $this->addFields(array('ipb_address', 'ipb_user', 'ipb_auto')); } if ($fld_by) { $this->addTables('user'); $this->addFields(array('ipb_by', 'user_name')); $this->addWhere('user_id = ipb_by'); } if ($fld_timestamp) { $this->addFields('ipb_timestamp'); } if ($fld_expiry) { $this->addFields('ipb_expiry'); } if ($fld_reason) { $this->addFields('ipb_reason'); } if ($fld_range) { $this->addFields(array('ipb_range_start', 'ipb_range_end')); } if ($fld_flags) { $this->addFields(array('ipb_auto', 'ipb_anon_only', 'ipb_create_account', 'ipb_enable_autoblock', 'ipb_block_email', 'ipb_deleted', 'ipb_allow_usertalk')); } $this->addOption('LIMIT', $params['limit'] + 1); $this->addWhereRange('ipb_timestamp', $params['dir'], $params['start'], $params['end']); if (isset($params['ids'])) { $this->addWhereFld('ipb_id', $params['ids']); } if (isset($params['users'])) { foreach ((array) $params['users'] as $u) { $this->prepareUsername($u); } $this->addWhereFld('ipb_address', $this->usernames); } if (isset($params['ip'])) { list($ip, $range) = IP::parseCIDR($params['ip']); if ($ip && $range) { # We got a CIDR range if ($range < 16) { $this->dieUsage('CIDR ranges broader than /16 are not accepted', 'cidrtoobroad'); } $lower = wfBaseConvert($ip, 10, 16, 8, false); $upper = wfBaseConvert($ip + pow(2, 32 - $range) - 1, 10, 16, 8, false); } else { $lower = $upper = IP::toHex($params['ip']); } $prefix = substr($lower, 0, 4); $this->addWhere(array("ipb_range_start LIKE '{$prefix}%'", "ipb_range_start <= '{$lower}'", "ipb_range_end >= '{$upper}'")); } if (!$wgUser->isAllowed('suppress')) { $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; while ($row = $res->fetchObject()) { if (++$count > $params['limit']) { // We've had enough $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->ipb_timestamp)); break; } $block = array(); if ($fld_id) { $block['id'] = $row->ipb_id; } if ($fld_user && !$row->ipb_auto) { $block['user'] = $row->ipb_address; } if ($fld_by) { $block['by'] = $row->user_name; } if ($fld_timestamp) { $block['timestamp'] = wfTimestamp(TS_ISO_8601, $row->ipb_timestamp); } if ($fld_expiry) { $block['expiry'] = Block::decodeExpiry($row->ipb_expiry, TS_ISO_8601); } if ($fld_reason) { $block['reason'] = $row->ipb_reason; } if ($fld_range) { $block['rangestart'] = IP::hexToQuad($row->ipb_range_start); $block['rangeend'] = IP::hexToQuad($row->ipb_range_end); } if ($fld_flags) { // For clarity, these flags use the same names as their action=block counterparts if ($row->ipb_auto) { $block['automatic'] = ''; } if ($row->ipb_anon_only) { $block['anononly'] = ''; } if ($row->ipb_create_account) { $block['nocreate'] = ''; } if ($row->ipb_enable_autoblock) { $block['autoblock'] = ''; } if ($row->ipb_block_email) { $block['noemail'] = ''; } if ($row->ipb_deleted) { $block['hidden'] = ''; } if ($row->ipb_allow_usertalk) { $block['allowusertalk'] = ''; } } $data[] = $block; } $result->setIndexedTagName($data, 'block'); $result->addValue('query', $this->getModuleName(), $data); }
<?php /** * One-off script to populate the new IP column in the Phalanx table * * @author grunny */ require __DIR__ . '/../../../../maintenance/commandLine.inc'; $dbr = wfGetDB(DB_SLAVE, array(), $wgExternalSharedDB); $dbResult = $dbr->select(array('phalanx'), array('*'), array('p_type & 8 = 8', 'p_lang IS NULL'), __METHOD__); $toUpdate = array(); while ($row = $dbr->fetchObject($dbResult)) { if (User::isIP($row->p_text)) { $toUpdate[$row->p_id] = IP::toHex($row->p_text); } } $dbr->freeResult($dbResult); $dbr->close(); $dbw = wfGetDB(DB_MASTER, array(), $wgExternalSharedDB); $failedFilters = array(); foreach ($toUpdate as $phalId => $ipHex) { $res = (bool) $dbw->update('phalanx', array('p_ip_hex' => $ipHex), array('p_id' => $phalId)); if (!$res) { $failedFilters[] = $phalId; } } $dbw->close(); echo "Done\n"; echo count($failedFilters) . " failed to be updated!\n"; exit(0);
function showList($msg) { global $wgOut, $wgUser; $wgOut->setPagetitle(wfMsg("ipblocklist")); if ("" != $msg) { $wgOut->setSubtitle($msg); } // Purge expired entries on one in every 10 queries if (!mt_rand(0, 10)) { Block::purgeExpired(); } $conds = array(); $matches = array(); // Is user allowed to see all the blocks? if (!$wgUser->isAllowed('suppress')) { $conds['ipb_deleted'] = 0; } if ($this->ip == '') { // No extra conditions } elseif (substr($this->ip, 0, 1) == '#') { $conds['ipb_id'] = substr($this->ip, 1); // Single IPs } elseif (IP::isIPAddress($this->ip) && strpos($this->ip, '/') === false) { if ($iaddr = IP::toHex($this->ip)) { # Only scan ranges which start in this /16, this improves search speed # Blocks should not cross a /16 boundary. $range = substr($iaddr, 0, 4); // Fixme -- encapsulate this sort of query-building. $dbr = wfGetDB(DB_SLAVE); $encIp = $dbr->addQuotes(IP::sanitizeIP($this->ip)); $encRange = $dbr->addQuotes("{$range}%"); $encAddr = $dbr->addQuotes($iaddr); $conds[] = "(ipb_address = {$encIp}) OR \n\t\t\t\t\t(ipb_range_start LIKE {$encRange} AND\n\t\t\t\t\tipb_range_start <= {$encAddr}\n\t\t\t\t\tAND ipb_range_end >= {$encAddr})"; } else { $conds['ipb_address'] = IP::sanitizeIP($this->ip); } $conds['ipb_auto'] = 0; // IP range } elseif (IP::isIPAddress($this->ip)) { $conds['ipb_address'] = Block::normaliseRange($this->ip); $conds['ipb_auto'] = 0; } else { $user = User::newFromName($this->ip); if ($user && ($id = $user->getId()) != 0) { $conds['ipb_user'] = $id; } else { // Uh...? $conds['ipb_address'] = $this->ip; $conds['ipb_auto'] = 0; } } // Apply filters if ($this->hideuserblocks) { $conds['ipb_user'] = 0; } if ($this->hidetempblocks) { $conds['ipb_expiry'] = 'infinity'; } if ($this->hideaddressblocks) { $conds[] = "ipb_user != 0 OR ipb_range_end > ipb_range_start"; } $pager = new IPBlocklistPager($this, $conds); if ($pager->getNumRows()) { $wgOut->addHTML($this->searchForm() . $pager->getNavigationBar() . Xml::tags('ul', null, $pager->getBody()) . $pager->getNavigationBar()); } elseif ($this->ip != '') { $wgOut->addHTML($this->searchForm()); $wgOut->addWikiMsg('ipblocklist-no-results'); } else { $wgOut->addHTML($this->searchForm()); $wgOut->addWikiMsg('ipblocklist-empty'); } }
public function execute() { global $wgContLang; $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('ipb_auto'); $this->addFieldsIf('ipb_id', $fld_id); $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_timestamp', $fld_timestamp); $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']); $db = $this->getDB(); if (isset($params['ids'])) { $this->addWhereFld('ipb_id', $params['ids']); } if (isset($params['users'])) { foreach ((array) $params['users'] as $u) { $this->prepareUsername($u); } $this->addWhereFld('ipb_address', $this->usernames); $this->addWhereFld('ipb_auto', 0); } if (isset($params['ip'])) { list($ip, $range) = IP::parseCIDR($params['ip']); if ($ip && $range) { // We got a CIDR range if ($range < 16) { $this->dieUsage('CIDR ranges broader than /16 are not accepted', 'cidrtoobroad'); } $lower = wfBaseConvert($ip, 10, 16, 8, false); $upper = wfBaseConvert($ip + pow(2, 32 - $range) - 1, 10, 16, 8, false); } else { $lower = $upper = IP::toHex($params['ip']); } $prefix = substr($lower, 0, 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('start', wfTimestamp(TS_ISO_8601, $row->ipb_timestamp)); break; } $block = array(); if ($fld_id) { $block['id'] = $row->ipb_id; } if ($fld_user && !$row->ipb_auto) { $block['user'] = $row->ipb_address; } if ($fld_userid && !$row->ipb_auto) { $block['userid'] = $row->ipb_user; } if ($fld_by) { $block['by'] = $row->ipb_by_text; } if ($fld_byid) { $block['byid'] = $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::hexToQuad($row->ipb_range_start); $block['rangeend'] = IP::hexToQuad($row->ipb_range_end); } if ($fld_flags) { // For clarity, these flags use the same names as their action=block counterparts if ($row->ipb_auto) { $block['automatic'] = ''; } if ($row->ipb_anon_only) { $block['anononly'] = ''; } if ($row->ipb_create_account) { $block['nocreate'] = ''; } if ($row->ipb_enable_autoblock) { $block['autoblock'] = ''; } if ($row->ipb_block_email) { $block['noemail'] = ''; } if ($row->ipb_deleted) { $block['hidden'] = ''; } if ($row->ipb_allow_usertalk) { $block['allowusertalk'] = ''; } } $fit = $result->addValue(array('query', $this->getModuleName()), null, $block); if (!$fit) { $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->ipb_timestamp)); break; } } $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'block'); }
/** * @desc Add Chat log entry to "Special:Log" and Special:CheckUser; * otherwise to giving a chat moderator or banning this method isn't called via AJAX, * therefore we have to insert all information manually into DB table */ public static function addConnectionLogEntry() { $wg = F::app()->wg; // record the IP of the connecting user. // use memcache so we order only one (user, ip) pair 3 min to avoid flooding the log $ip = $wg->Request->getIP(); $memcKey = self::getUserIPMemcKey($wg->User->getID(), $ip); $entry = $wg->Memc->get($memcKey); if (empty($entry)) { $wg->Memc->set($memcKey, true, 60 * 3); $log = new LogPage('chatconnect', false, false); $log->addEntry('chatconnect', SpecialPage::getTitleFor('Chat'), '', [$ip], $wg->User); $xff = $wg->Request->getHeader(self::HTTP_HEADER_XFF); list($xff_ip, $isSquidOnly) = IP::getClientIPfromXFF($xff); $userAgent = $wg->Request->getHeader(self::HTTP_HEADER_USER_AGENT); $dbw = wfGetDB(DB_MASTER); $cuc_id = $dbw->nextSequenceValue('cu_changes_cu_id_seq'); $rcRow = ['cuc_id' => $cuc_id, 'cuc_namespace' => NS_SPECIAL, 'cuc_title' => 'Chat', 'cuc_minor' => 0, 'cuc_user' => $wg->User->getID(), 'cuc_user_text' => $wg->User->getName(), 'cuc_actiontext' => wfMessage('chat-checkuser-join-action')->inContentLanguage()->text(), 'cuc_comment' => '', 'cuc_this_oldid' => 0, 'cuc_last_oldid' => 0, 'cuc_type' => CUC_TYPE_CHAT, 'cuc_timestamp' => $dbw->timestamp(), 'cuc_ip' => IP::sanitizeIP($ip), 'cuc_ip_hex' => $ip ? IP::toHex($ip) : null, 'cuc_xff' => !$isSquidOnly ? $xff : '', 'cuc_xff_hex' => $xff_ip && !$isSquidOnly ? IP::toHex($xff_ip) : null, 'cuc_agent' => $userAgent === false ? null : $userAgent]; $dbw->insert('cu_changes', $rcRow, __METHOD__); $dbw->commit(); } }
/** * From a list of multiple blocks, find the most exact and strongest Block. * The logic for finding the "best" block is: * - Blocks that match the block's target IP are preferred over ones in a range * - Hardblocks are chosen over softblocks that prevent account creation * - Softblocks that prevent account creation are chosen over other softblocks * - Other softblocks are chosen over autoblocks * - If there are multiple exact or range blocks at the same level, the one chosen * is random * * @param array $blocks Array of blocks * @param array $ipChain List of IPs (strings). This is used to determine how "close" * a block is to the server, and if a block matches exactly, or is in a range. * The order is furthest from the server to nearest e.g., (Browser, proxy1, proxy2, * local-squid, ...) * @return Block|null The "best" block from the list */ public static function chooseBlock(array $blocks, array $ipChain) { if (!count($blocks)) { return null; } elseif (count($blocks) == 1) { return $blocks[0]; } wfProfileIn(__METHOD__); // Sort hard blocks before soft ones and secondarily sort blocks // that disable account creation before those that don't. usort($blocks, function (Block $a, Block $b) { $aWeight = (int) $a->isHardblock() . (int) $a->prevents('createaccount'); $bWeight = (int) $b->isHardblock() . (int) $b->prevents('createaccount'); return strcmp($bWeight, $aWeight); // highest weight first }); $blocksListExact = array('hard' => false, 'disable_create' => false, 'other' => false, 'auto' => false); $blocksListRange = array('hard' => false, 'disable_create' => false, 'other' => false, 'auto' => false); $ipChain = array_reverse($ipChain); foreach ($blocks as $block) { // Stop searching if we have already have a "better" block. This // is why the order of the blocks matters if (!$block->isHardblock() && $blocksListExact['hard']) { break; } elseif (!$block->prevents('createaccount') && $blocksListExact['disable_create']) { break; } foreach ($ipChain as $checkip) { $checkipHex = IP::toHex($checkip); if ((string) $block->getTarget() === $checkip) { if ($block->isHardblock()) { $blocksListExact['hard'] = $blocksListExact['hard'] ?: $block; } elseif ($block->prevents('createaccount')) { $blocksListExact['disable_create'] = $blocksListExact['disable_create'] ?: $block; } elseif ($block->mAuto) { $blocksListExact['auto'] = $blocksListExact['auto'] ?: $block; } else { $blocksListExact['other'] = $blocksListExact['other'] ?: $block; } // We found closest exact match in the ip list, so go to the next Block break; } elseif (array_filter($blocksListExact) == array() && $block->getRangeStart() <= $checkipHex && $block->getRangeEnd() >= $checkipHex) { if ($block->isHardblock()) { $blocksListRange['hard'] = $blocksListRange['hard'] ?: $block; } elseif ($block->prevents('createaccount')) { $blocksListRange['disable_create'] = $blocksListRange['disable_create'] ?: $block; } elseif ($block->mAuto) { $blocksListRange['auto'] = $blocksListRange['auto'] ?: $block; } else { $blocksListRange['other'] = $blocksListRange['other'] ?: $block; } break; } } } if (array_filter($blocksListExact) == array()) { $blocksList =& $blocksListRange; } else { $blocksList =& $blocksListExact; } $chosenBlock = null; if ($blocksList['hard']) { $chosenBlock = $blocksList['hard']; } elseif ($blocksList['disable_create']) { $chosenBlock = $blocksList['disable_create']; } elseif ($blocksList['other']) { $chosenBlock = $blocksList['other']; } elseif ($blocksList['auto']) { $chosenBlock = $blocksList['auto']; } else { wfProfileOut(__METHOD__); throw new MWException("Proxy block found, but couldn't be classified."); } wfProfileOut(__METHOD__); return $chosenBlock; }
/** * Add a vote to the database with the given unencrypted answer record. * @param $record string */ function logVote( $record ) { global $wgOut, $wgRequest; $now = wfTimestampNow(); $crypt = $this->election->getCrypt(); if ( !$crypt ) { $encrypted = $record; } else { $status = $crypt->encrypt( $record ); if ( !$status->isOK() ) { $wgOut->addWikiText( $status->getWikiText( 'securepoll-encrypt-error' ) ); return; } $encrypted = $status->value; } $dbw = $this->context->getDB(); $dbw->begin(); # Mark previous votes as old $dbw->update( 'securepoll_votes', array( 'vote_current' => 0 ), # SET array( # WHERE 'vote_election' => $this->election->getId(), 'vote_voter' => $this->voter->getId(), ), __METHOD__ ); # Add vote to log $xff = @$_SERVER['HTTP_X_FORWARDED_FOR']; if ( !$xff ) { $xff = ''; } $tokenMatch = $this->parent->getEditToken() == $wgRequest->getVal( 'edit_token' ); $voteId = $dbw->nextSequenceValue( 'securepoll_votes_vote_id' ); $dbw->insert( 'securepoll_votes', array( 'vote_id' => $voteId, 'vote_election' => $this->election->getId(), 'vote_voter' => $this->voter->getId(), 'vote_voter_name' => $this->voter->getName(), 'vote_voter_domain' => $this->voter->getDomain(), 'vote_record' => $encrypted, 'vote_ip' => IP::toHex( wfGetIP() ), 'vote_xff' => $xff, 'vote_ua' => $_SERVER['HTTP_USER_AGENT'], 'vote_timestamp' => $now, 'vote_current' => 1, 'vote_token_match' => $tokenMatch ? 1 : 0, ), __METHOD__ ); $voteId = $dbw->insertId(); $dbw->commit(); if ( $crypt ) { $receipt = sprintf( "SPID: %10d\n%s", $voteId, $encrypted ); $wgOut->addWikiMsg( 'securepoll-gpg-receipt', $receipt ); } else { $wgOut->addWikiMsg( 'securepoll-thanks' ); } $returnUrl = $this->election->getProperty( 'return-url' ); $returnText = $this->election->getMessage( 'return-text' ); if ( $returnUrl ) { if ( strval( $returnText ) === '' ) { $returnText = $returnUrl; } $link = "[$returnUrl $returnText]"; $wgOut->addWikiMsg( 'securepoll-return', $link ); } }
function showList($msg) { global $wgOut, $wgUser; $wgOut->setPagetitle(wfMsg("ipblocklist")); if ($msg != "") { $wgOut->setSubtitle($msg); } // Purge expired entries on one in every 10 queries if (!mt_rand(0, 10)) { Block::purgeExpired(); } $conds = array(); $matches = array(); // Is user allowed to see all the blocks? if (!$wgUser->isAllowed('hideuser')) { $conds['ipb_deleted'] = 0; } if ($this->ip == '') { // No extra conditions } elseif (substr($this->ip, 0, 1) == '#') { $conds['ipb_id'] = substr($this->ip, 1); // Single IPs } elseif (IP::isIPAddress($this->ip) && strpos($this->ip, '/') === false) { if ($iaddr = IP::toHex($this->ip)) { # Only scan ranges which start in this /16, this improves search speed # Blocks should not cross a /16 boundary. $range = substr($iaddr, 0, 4); // Fixme -- encapsulate this sort of query-building. $dbr = wfGetDB(DB_SLAVE); $encIp = $dbr->addQuotes(IP::sanitizeIP($this->ip)); $encAddr = $dbr->addQuotes($iaddr); $conds[] = "(ipb_address = {$encIp}) OR \n\t\t\t\t\t(ipb_range_start" . $dbr->buildLike($range, $dbr->anyString()) . " AND\n\t\t\t\t\tipb_range_start <= {$encAddr}\n\t\t\t\t\tAND ipb_range_end >= {$encAddr})"; } else { $conds['ipb_address'] = IP::sanitizeIP($this->ip); } $conds['ipb_auto'] = 0; // IP range } elseif (IP::isIPAddress($this->ip)) { $conds['ipb_address'] = Block::normaliseRange($this->ip); $conds['ipb_auto'] = 0; } else { $user = User::newFromName($this->ip); if ($user && ($id = $user->getId()) != 0) { $conds['ipb_user'] = $id; } else { // Uh...? $conds['ipb_address'] = $this->ip; $conds['ipb_auto'] = 0; } } // Apply filters if ($this->hideuserblocks) { $conds['ipb_user'] = 0; } if ($this->hidetempblocks) { $conds['ipb_expiry'] = 'infinity'; } if ($this->hideaddressblocks) { $conds[] = "ipb_user != 0 OR ipb_range_end > ipb_range_start"; } // Search form $wgOut->addHTML($this->searchForm()); // Check for other blocks, i.e. global/tor blocks $otherBlockLink = array(); wfRunHooks('OtherBlockLogLink', array(&$otherBlockLink, $this->ip)); // 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)) { $wgOut->addHTML(Html::rawElement('h2', array(), wfMsg('ipblocklist-localblock')) . "\n"); } $pager = new IPBlocklistPager($this, $conds); if ($pager->getNumRows()) { $wgOut->addHTML($pager->getNavigationBar() . Xml::tags('ul', null, $pager->getBody()) . $pager->getNavigationBar()); } elseif ($this->ip != '') { $wgOut->addWikiMsg('ipblocklist-no-results'); } else { $wgOut->addWikiMsg('ipblocklist-empty'); } if (count($otherBlockLink)) { $wgOut->addHTML(Html::rawElement('h2', array(), wfMsgExt('ipblocklist-otherblocks', 'parseinline', count($otherBlockLink))) . "\n"); $list = ''; foreach ($otherBlockLink as $link) { $list .= Html::rawElement('li', array(), $link) . "\n"; } $wgOut->addHTML(Html::rawElement('ul', array('class' => 'mw-ipblocklist-otherblocks'), $list) . "\n"); } }
/** * @param DatabaseBase $db * @param string $ip * @param string|bool $xfor * @return mixed array/false conditions */ public static function getIpConds($db, $ip, $xfor = false) { $type = $xfor ? 'xff' : 'ip'; // IPv4 CIDR, 16-32 bits $matches = array(); if (preg_match('#^(\\d+\\.\\d+\\.\\d+\\.\\d+)/(\\d+)$#', $ip, $matches)) { if ($matches[2] < 16 || $matches[2] > 32) { return false; // invalid } list($start, $end) = IP::parseRange($ip); return array('cuc_' . $type . '_hex BETWEEN ' . $db->addQuotes($start) . ' AND ' . $db->addQuotes($end)); } elseif (preg_match('#^\\w{1,4}:\\w{1,4}:\\w{1,4}:\\w{1,4}:\\w{1,4}:\\w{1,4}:\\w{1,4}:\\w{1,4}/(\\d+)$#', $ip, $matches)) { // IPv6 CIDR, 64-128 bits if ($matches[1] < 64 || $matches[1] > 128) { return false; // invalid } list($start, $end) = IP::parseRange($ip); return array('cuc_' . $type . '_hex BETWEEN ' . $db->addQuotes($start) . ' AND ' . $db->addQuotes($end)); } elseif (preg_match('#^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$#', $ip)) { // 32 bit IPv4 $ip_hex = IP::toHex($ip); return array('cuc_' . $type . '_hex' => $ip_hex); } elseif (preg_match('#^\\w{1,4}:\\w{1,4}:\\w{1,4}:\\w{1,4}:\\w{1,4}:\\w{1,4}:\\w{1,4}:\\w{1,4}$#', $ip)) { // 128 bit IPv6 $ip_hex = IP::toHex($ip); return array('cuc_' . $type . '_hex' => $ip_hex); } // throw away this query, incomplete IP, these don't get through the entry point anyway return false; // invalid }
/** * @param $user User * @param $actiontext string * @return bool */ protected static function logUserAccountCreation(User $user, $actiontext) { global $wgRequest; // Get IP $ip = $wgRequest->getIP(); // Get XFF header $xff = $wgRequest->getHeader('X-Forwarded-For'); list($xff_ip, $isSquidOnly) = self::getClientIPfromXFF($xff); // Get agent $agent = $wgRequest->getHeader('User-Agent'); $dbw = wfGetDB(DB_MASTER); $cuc_id = $dbw->nextSequenceValue('cu_changes_cu_id_seq'); $rcRow = array('cuc_id' => $cuc_id, 'cuc_page_id' => 0, 'cuc_namespace' => NS_USER, 'cuc_title' => '', 'cuc_minor' => 0, 'cuc_user' => $user->getId(), 'cuc_user_text' => $user->getName(), 'cuc_actiontext' => wfMessage($actiontext)->inContentLanguage()->text(), 'cuc_comment' => '', 'cuc_this_oldid' => 0, 'cuc_last_oldid' => 0, 'cuc_type' => RC_LOG, 'cuc_timestamp' => $dbw->timestamp(wfTimestampNow()), 'cuc_ip' => IP::sanitizeIP($ip), 'cuc_ip_hex' => $ip ? IP::toHex($ip) : null, 'cuc_xff' => !$isSquidOnly ? $xff : '', 'cuc_xff_hex' => $xff_ip && !$isSquidOnly ? IP::toHex($xff_ip) : null, 'cuc_agent' => $agent); $dbw->insert('cu_changes', $rcRow, __METHOD__); return true; }
/** * Given a string range in a number of formats, return the start and end of * the range in hexadecimal. * * Formats are: * 1.2.3.4/24 CIDR * 1.2.3.4 - 1.2.3.5 Explicit range * 1.2.3.4 Single IP */ public static function parseRange($range) { if (strpos($range, '/') !== false) { # CIDR list($network, $bits) = IP::parseCIDR($range); if ($network === false) { $start = $end = false; } else { $start = sprintf('%08X', $network); $end = sprintf('%08X', $network + pow(2, 32 - $bits) - 1); } } elseif (strpos($range, '-') !== false) { # Explicit range list($start, $end) = array_map('trim', explode('-', $range, 2)); if ($start > $end) { $start = $end = false; } else { $start = IP::toHex($start); $end = IP::toHex($end); } } else { # Single IP $start = $end = IP::toHex($range); } if ($start === false || $end === false) { return array(false, false); } else { return array($start, $end); } }
/** * This is the ajax-endpoint that the node server will connect to in order to get the currently logged-in user's info. * The node server will pass the same cookies that the client has set, and this will allow this ajax request to be * part of the same sesssion that the user already has going. By doing this, the user's existing wikia login session * can be used, so they don't need to re-login for us to know that they are legitimately authorized to use the chat or not. * * The returned info is just a custom subset of what the node server needs and does not contain an exhaustive list of rights. * * The 'isLoggedIn' field and 'canChat' field of the result should be checked by the calling code before allowing * the user to chat. This is the last line of security against any users attemptin to circumvent our protections. Otherwise, * a banned user could copy the entire client code (HTML/JS/etc.) from an unblocked user, then run that code while logged in as * under a banned account, and they would still be given access. * * The returned 'isChatMod' field is boolean based on whether the user is a chat moderator on the current wiki. * * If the user is not allowed to chat, an error message is returned (which can be shown to the user). */ public static function getUserInfo() { global $wgMemc, $wgServer, $wgArticlePath, $wgRequest, $wgCityId, $wgContLang, $wgIP; wfProfileIn(__METHOD__); $data = $wgMemc->get($wgRequest->getVal('key'), false); if (empty($data)) { return array('errorMsg' => wfMsg('chat-room-is-not-on-this-wiki')); } $user = User::newFromId($data['user_id']); if (empty($user) || !$user->isLoggedIn() || $user->getName() != $wgRequest->getVal('name', '')) { wfProfileOut(__METHOD__); return array('errorMsg' => wfMsg('chat-room-is-not-on-this-wiki')); } $isCanGiveChatMode = false; $userChangeableGroups = $user->changeableGroups(); if (in_array('chatmoderator', $userChangeableGroups['add'])) { $isCanGiveChatMode = true; } // First, check if they can chat on this wiki. $retVal = array('canChat' => Chat::canChat($user), 'isLoggedIn' => $user->isLoggedIn(), 'isChatMod' => $user->isAllowed('chatmoderator'), 'isCanGiveChatMode' => $isCanGiveChatMode, 'isStaff' => $user->isAllowed('chatstaff'), 'username' => $user->getName(), 'avatarSrc' => AvatarService::getAvatarUrl($user->getName(), self::CHAT_AVATAR_DIMENSION), 'editCount' => "", 'since' => '', 'activeBasket' => ChatHelper::getServerBasket(), 'wgCityId' => $wgCityId, 'wgServer' => $wgServer, 'wgArticlePath' => $wgArticlePath); // Figure out the error message to return (i18n is done on this side). if ($retVal['isLoggedIn'] === false) { $retVal['errorMsg'] = wfMsg('chat-no-login'); } else { if ($retVal['canChat'] === false) { $retVal['errorMsg'] = wfMsg('chat-you-are-banned-text'); } } // If the user is approved to chat, make sure the roomId provided is for this wiki. // Users may be banned on the wiki of the room, but not on this wiki for example, so this prevents cross-wiki chat hacks. if ($retVal['canChat']) { $roomId = $wgRequest->getVal('roomId'); $cityIdOfRoom = NodeApiClient::getCityIdForRoom($roomId); if ($wgCityId !== $cityIdOfRoom) { $retVal['canChat'] = false; // don't let the user chat in the room they requested. $retVal['errorMsg'] = wfMsg('chat-room-is-not-on-this-wiki'); } } // If the user can chat, dig up some other stats which are a little more expensive to compute. if ($retVal['canChat']) { $userStatsService = new UserStatsService($user->getId()); $stats = $userStatsService->getStats(); // NOTE: This is attached to the user so it will be in the wiki's content language instead of wgLang (which it normally will). $stats['edits'] = $wgContLang->formatNum($stats['edits']); if (empty($stats['date'])) { // If the user has not edited on this wiki, don't show anything $retVal['since'] = ""; } else { // this results goes to chat server, which obiously has no user lang // so we just return a short month name key - it has to be translated on client side $date = getdate(wfTimestamp(TS_UNIX, $stats['date'])); $retVal['since'] = $date; } $retVal['editCount'] = $stats['edits']; } if ($retVal['isLoggedIn'] && $retVal['canChat']) { // record the IP of the connecting user. // use memcache so we order only one (user, ip) pair each day $ip = $wgRequest->getVal('address'); $memcKey = self::getUserIPMemcKey($data['user_id'], $ip, date("Y-m-d")); $entry = $wgMemc->get($memcKey, false); if (empty($entry)) { $wgMemc->set($memcKey, true, 86400); $log = WF::build('LogPage', array('chatconnect', false, false)); $log->addEntry('chatconnect', SpecialPage::getTitleFor('Chat'), '', array($ip), $user); $dbw = wfGetDB(DB_MASTER); $cuc_id = $dbw->nextSequenceValue('cu_changes_cu_id_seq'); $rcRow = array('cuc_id' => $cuc_id, 'cuc_namespace' => NS_SPECIAL, 'cuc_title' => 'Chat', 'cuc_minor' => 0, 'cuc_user' => $user->getID(), 'cuc_user_text' => $user->getName(), 'cuc_actiontext' => wfMsgForContent('chat-checkuser-join-action'), 'cuc_comment' => '', 'cuc_this_oldid' => 0, 'cuc_last_oldid' => 0, 'cuc_type' => CUC_TYPE_CHAT, 'cuc_timestamp' => $dbw->timestamp(), 'cuc_ip' => IP::sanitizeIP($ip), 'cuc_ip_hex' => $ip ? IP::toHex($ip) : null, 'cuc_xff' => '', 'cuc_xff_hex' => null, 'cuc_agent' => null); $dbw->insert('cu_changes', $rcRow, __METHOD__); $dbw->commit(); } } wfProfileOut(__METHOD__); return $retVal; }
/** * @covers IP::toHex * @dataProvider provideToHex */ public function testToHex($expected, $input) { $result = IP::toHex($input); $this->assertTrue($result === false || is_string($result)); $this->assertEquals($expected, $result); }
/** * Search the database for any range blocks matching the given address, and * load the row if one is found. */ function loadRange($address, $killExpired = true, $user = 0) { $iaddr = IP::toHex($address); if ($iaddr === false) { # Invalid address return false; } # Only scan ranges which start in this /16, this improves search speed # Blocks should not cross a /16 boundary. $range = substr($iaddr, 0, 4); $options = array(); $db =& $this->getDBOptions($options); $conds = array("ipb_range_start LIKE '{$range}%'", "ipb_range_start <= '{$iaddr}'", "ipb_range_end >= '{$iaddr}'"); if ($user) { $conds['ipb_anon_only'] = 0; } $res = $db->resultObject($db->select('ipblocks', '*', $conds, __METHOD__, $options)); $success = $this->loadFromResult($res, $killExpired); return $success; }
/** * @param $type * @param $title Title * @return int|string */ public static function throttleIdentifier($type, $title) { global $wgUser, $wgRequest; switch ($type) { case 'ip': $identifier = $wgRequest->getIP(); break; case 'user': $identifier = $wgUser->getId(); break; case 'range': $identifier = substr(IP::toHex($wgRequest->getIP()), 0, 4); break; case 'creationdate': $reg = $wgUser->getRegistration(); $identifier = $reg - $reg % 86400; break; case 'editcount': // Hack for detecting different single-purpose accounts. $identifier = $wgUser->getEditCount(); break; case 'site': $identifier = 1; break; case 'page': $identifier = $title->getPrefixedText(); break; default: $identifier = 0; } return $identifier; }
// 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 { foreach ( $ips as $ip ) { $hex = IP::toHex( $ip ); $ranges[] = array( $lineNum, $hex, $hex ); } } showProgress( $i, count( $names ) ); // Don't DoS the recursor usleep( 10000 ); } echo "\n"; echo "Creating database...\n"; foreach ( $ranges as $i => $range ) { list( $lineNum, $start, $end ) = $range; if ( $start === $end ) { // Single host
/** * Handler for non-standard (edit/log) entries that need IP data * * @param $context IContextSource * @param $data Array * @return bool */ protected static function onLoggableUserIPData(IContextSource $context, array $data) { $user = $context->getUser(); $request = $context->getRequest(); // Get IP address $ip = $request->getIP(); // Get XFF header $xff = $request->getHeader('X-Forwarded-For'); list($xff_ip, $isSquidOnly) = IP::getClientIPfromXFF($xff); // Get agent $agent = $request->getHeader('User-Agent'); $dbw = wfGetDB(DB_MASTER); $cuc_id = $dbw->nextSequenceValue('cu_changes_cu_id_seq'); $rcRow = array('cuc_id' => $cuc_id, 'cuc_page_id' => $data['pageid'], 'cuc_namespace' => $data['namespace'], 'cuc_title' => $data['title'], 'cuc_minor' => 0, 'cuc_user' => $user->getId(), 'cuc_user_text' => $user->getName(), 'cuc_actiontext' => $data['action'], 'cuc_comment' => $data['comment'], 'cuc_this_oldid' => 0, 'cuc_last_oldid' => 0, 'cuc_type' => RC_LOG, 'cuc_timestamp' => $dbw->timestamp($data['timestamp']), 'cuc_ip' => IP::sanitizeIP($ip), 'cuc_ip_hex' => $ip ? IP::toHex($ip) : null, 'cuc_xff' => !$isSquidOnly ? $xff : '', 'cuc_xff_hex' => $xff_ip && !$isSquidOnly ? IP::toHex($xff_ip) : null, 'cuc_agent' => $agent); $dbw->insert('cu_changes', $rcRow, __METHOD__); return true; }
public static function loadHoneypotDataFromFile() { global $wgHoneypotDataFile; $fh = fopen($wgHoneypotDataFile, 'r'); $save_data = array(); $ips = array(); $count = 0; while (!feof($fh)) { $line = trim(fgets($fh)); $data = preg_split('/\\s/', $line, 3); if (IP::isIPAddress($data[0])) { $subnet = substr(IP::toHex($data[0]), 0, -6); if (!isset($ips[$subnet])) { $ips[$subnet] = array(); } if (!isset($save_data[$subnet])) { $save_data[$subnet] = array(); } $save_data[$subnet][$data[0]] = $data; $ips[$subnet][$data[0]] = true; $count++; if ($count % 100 == 0) { wfDebugLog('HoneypotDebug', "Done {$count} IPs -- {$data['0']}"); } } } fclose($fh); self::$IPs = $ips; self::$Data = $save_data; return array($save_data, $ips); }