. sprintf($this->lang['BOARD_BAN_REASON'], $ban_row['ban_give_reason']) : ''; $message .= '

' . $this->lang['BAN_TRIGGERED_BY_' . strtoupper($ban_triggered_by)] . ''; // To circumvent session_begin returning a valid value and the check_ban() not called on second page view, we kill the session again $this->session_kill(false); // A very special case... we are within the cron script which is not supposed to print out the ban message... show blank page if (defined('IN_CRON')) { garbage_collection(); exit_handler(); exit; } trigger_error($message); } return ($banned && $ban_row['ban_give_reason']) ? $ban_row['ban_give_reason'] : $banned; } /** * Check if ip is blacklisted * This should be called only where absolutely necessary * * Only IPv4 (rbldns does not support AAAA records/IPv6 lookups) * * @author satmd (from the php manual) * @param string $mode register/post - spamcop for example is ommitted for posting * @param string|false $ip the IPv4 address to check * * @return false if ip is not blacklisted, else an array([checked server], [lookup]) */ function check_dnsbl($mode, $ip = false) { if ($ip === false) { $ip = $this->ip; } // Neither Spamhaus nor Spamcop supports IPv6 addresses. if (strpos($ip, ':') !== false) { return false; } $dnsbl_check = array( 'sbl.spamhaus.org' => 'http://www.spamhaus.org/query/bl?ip=', ); if ($mode == 'register') { $dnsbl_check['bl.spamcop.net'] = 'http://spamcop.net/bl.shtml?'; } if ($ip) { $quads = explode('.', $ip); $reverse_ip = $quads[3] . '.' . $quads[2] . '.' . $quads[1] . '.' . $quads[0]; // Need to be listed on all servers... $listed = true; $info = array(); foreach ($dnsbl_check as $dnsbl => $lookup) { if (phpbb_checkdnsrr($reverse_ip . '.' . $dnsbl . '.', 'A') === true) { $info = array($dnsbl, $lookup . $ip); } else { $listed = false; } } if ($listed) { return $info; } } return false; } /** * Check if URI is blacklisted * This should be called only where absolutly necessary, for example on the submitted website field * This function is not in use at the moment and is only included for testing purposes, it may not work at all! * This means it is untested at the moment and therefore commented out * * @param string $uri URI to check * @return true if uri is on blacklist, else false. Only blacklist is checked (~zero FP), no grey lists function check_uribl($uri) { // Normally parse_url() is not intended to parse uris // We need to get the top-level domain name anyway... change. $uri = parse_url($uri); if ($uri === false || empty($uri['host'])) { return false; } $uri = trim($uri['host']); if ($uri) { // One problem here... the return parameter for the "windows" method is different from what // we expect... this may render this check useless... if (phpbb_checkdnsrr($uri . '.multi.uribl.com.', 'A') === true) { return true; } } return false; } */ /** * Set/Update a persistent login key * * This method creates or updates a persistent session key. When a user makes * use of persistent (formerly auto-) logins a key is generated and stored in the * DB. When they revisit with the same key it's automatically updated in both the * DB and cookie. Multiple keys may exist for each user representing different * browsers or locations. As with _any_ non-secure-socket no passphrase login this * remains vulnerable to exploit. */ function set_login_key($user_id = false, $key = false, $user_ip = false) { global $config, $db; $user_id = ($user_id === false) ? $this->data['user_id'] : $user_id; $user_ip = ($user_ip === false) ? $this->ip : $user_ip; $key = ($key === false) ? (($this->cookie_data['k']) ? $this->cookie_data['k'] : false) : $key; $key_id = unique_id(hexdec(substr($this->session_id, 0, 8))); $sql_ary = array( 'key_id' => (string) md5($key_id), 'last_ip' => (string) $this->ip, 'last_login' => (int) time() ); if (!$key) { $sql_ary += array( 'user_id' => (int) $user_id ); } if ($key) { $sql = 'UPDATE ' . SESSIONS_KEYS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE user_id = ' . (int) $user_id . " AND key_id = '" . $db->sql_escape(md5($key)) . "'"; } else { $sql = 'INSERT INTO ' . SESSIONS_KEYS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); } $db->sql_query($sql); $this->cookie_data['k'] = $key_id; return false; } /** * Reset all login keys for the specified user * * This method removes all current login keys for a specified (or the current) * user. It will be called on password change to render old keys unusable */ function reset_login_keys($user_id = false) { global $config, $db; $user_id = ($user_id === false) ? (int) $this->data['user_id'] : (int) $user_id; $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' WHERE user_id = ' . (int) $user_id; $db->sql_query($sql); // If the user is logged in, update last visit info first before deleting sessions $sql = 'SELECT session_time, session_page FROM ' . SESSIONS_TABLE . ' WHERE session_user_id = ' . (int) $user_id . ' ORDER BY session_time DESC'; $result = $db->sql_query_limit($sql, 1); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); if ($row) { $sql = 'UPDATE ' . USERS_TABLE . ' SET user_lastvisit = ' . (int) $row['session_time'] . ", user_lastpage = '" . $db->sql_escape($row['session_page']) . "' WHERE user_id = " . (int) $user_id; $db->sql_query($sql); } // Let's also clear any current sessions for the specified user_id // If it's the current user then we'll leave this session intact $sql_where = 'session_user_id = ' . (int) $user_id; $sql_where .= ($user_id === (int) $this->data['user_id']) ? " AND session_id <> '" . $db->sql_escape($this->session_id) . "'" : ''; $sql = 'DELETE FROM ' . SESSIONS_TABLE . " WHERE $sql_where"; $db->sql_query($sql); // We're changing the password of the current user and they have a key // Lets regenerate it to be safe if ($user_id === (int) $this->data['user_id'] && $this->cookie_data['k']) { $this->set_login_key($user_id); } } /** * Check if the request originated from the same page. * @param bool $check_script_path If true, the path will be checked as well */ function validate_referer($check_script_path = false) { global $config, $request; // no referer - nothing to validate, user's fault for turning it off (we only check on POST; so meta can't be the reason) if (empty($this->referer) || empty($this->host)) { return true; } $host = htmlspecialchars($this->host); $ref = substr($this->referer, strpos($this->referer, '://') + 3); if (!(stripos($ref, $host) === 0) && (!$config['force_server_vars'] || !(stripos($ref, $config['server_name']) === 0))) { return false; } else if ($check_script_path && rtrim($this->page['root_script_path'], '/') !== '') { $ref = substr($ref, strlen($host)); $server_port = $request->server('SERVER_PORT', 0); if ($server_port !== 80 && $server_port !== 443 && stripos($ref, ":$server_port") === 0) { $ref = substr($ref, strlen(":$server_port")); } if (!(stripos(rtrim($ref, '/'), rtrim($this->page['root_script_path'], '/')) === 0)) { return false; } } return true; } function unset_admin() { global $db; $sql = 'UPDATE ' . SESSIONS_TABLE . ' SET session_admin = 0 WHERE session_id = \'' . $db->sql_escape($this->session_id) . '\''; $db->sql_query($sql); } /** * Update the session data * * @param array $session_data associative array of session keys to be updated * @param string $session_id optional session_id, defaults to current user's session_id */ public function update_session($session_data, $session_id = null) { global $db, $phpbb_dispatcher; $session_id = ($session_id) ? $session_id : $this->session_id; $sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $session_data) . " WHERE session_id = '" . $db->sql_escape($session_id) . "'"; $db->sql_query($sql); /** * Event to send update session information to extension * Read-only event * * @event core.update_session_after * @var array session_data Associative array of session keys to be updated * @var string session_id current user's session_id * @since 3.1.6-RC1 */ $vars = array('session_data', 'session_id'); extract($phpbb_dispatcher->trigger_event('core.update_session_after', compact($vars))); } public function update_session_infos() { global $config, $db, $request; // No need to update if it's a new session. Informations are already inserted by session_create() if (isset($this->data['session_created']) && $this->data['session_created']) { return; } // Only update session DB a minute or so after last update or if page changes if ($this->time_now - $this->data['session_time'] > 60 || ($this->update_session_page && $this->data['session_page'] != $this->page['page'])) { $sql_ary = array('session_time' => $this->time_now); // Do not update the session page for ajax requests, so the view online still works as intended if ($this->update_session_page && !$request->is_ajax()) { $sql_ary['session_page'] = substr($this->page['page'], 0, 199); $sql_ary['session_forum_id'] = $this->page['forum']; } $db->sql_return_on_error(true); $this->update_session($sql_ary); $db->sql_return_on_error(false); $this->data = array_merge($this->data, $sql_ary); if ($this->data['user_id'] != ANONYMOUS && !empty($config['new_member_post_limit']) && $this->data['user_new'] && $config['new_member_post_limit'] <= $this->data['user_posts']) { $this->leave_newly_registered(); } } } } { Ë8ffffXÎxEirst) { $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma'); // trailing ,? if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) { break; } } $first = false; // a hash key can be: // // * a number -- 12 // * a string -- 'a' // * a name, which is equivalent to a string -- a // * an expression, which must be enclosed in parentheses -- (1 + 2) if (($token = $stream->nextIf(Twig_Token::STRING_TYPE)) || ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) || $token = $stream->nextIf(Twig_Token::NUMBER_TYPE)) { $key = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); } elseif ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { $key = $this->parseExpression(); } else { $current = $stream->getCurrent(); throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($current->getType()), $current->getValue()), $current->getLine(), $this->parser->getFilename()); } $stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)'); $value = $this->parseExpression(); $node->addElement($value, $key); } $stream->expect(Twig_Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed'); return $node; } public function parsePostfixExpression($node) { while (true) { $token = $this->parser->getCurrentToken(); if ($token->getType() == Twig_Token::PUNCTUATION_TYPE) { if ('.' == $token->getValue() || '[' == $token->getValue()) { $node = $this->parseSubscriptExpression($node); } elseif ('|' == $token->getValue()) { $node = $this->parseFilterExpression($node); } else { break; } } else { break; } } return $node; } public function getFunctionNode($name, $line) { switch ($name) { case 'parent': $this->parseArguments(); if (!count($this->parser->getBlockStack())) { throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line, $this->parser->getFilename()); } if (!$this->parser->getParent() && !$this->parser->hasTraits()) { throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden', $line, $this->parser->getFilename()); } return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line); case 'block': return new Twig_Node_Expression_BlockReference($this->parseArguments()->getNode(0), false, $line); case 'attribute': $args = $this->parseArguments(); if (count($args) < 2) { throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes)', $line, $this->parser->getFilename()); } return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : null, Twig_Template::ANY_CALL, $line); default: if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) { $arguments = new Twig_Node_Expression_Array(array(), $line); foreach ($this->parseArguments() as $n) { $arguments->addElement($n); } $node = new Twig_Node_Expression_MethodCall($alias['node'], $alias['name'], $arguments, $line); $node->setAttribute('safe', true); return $node; } $args = $this->parseArguments(true); $class = $this->getFunctionNodeClass($name, $line); return new $class($name, $args, $line); } } public function parseSubscriptExpression($node) { $stream = $this->parser->getStream(); $token = $stream->next(); $lineno = $token->getLine(); $arguments = new Twig_Node_Expression_Array(array(), $lineno); $type = Twig_Template::ANY_CALL; if ($token->getValue() == '.') { $token = $stream->next(); if ( $token->getType() == Twig_Token::NAME_TYPE || $token->getType() == Twig_Token::NUMBER_TYPE || ($token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue())) ) { $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno); if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { $type = Twig_TemplateInterface::METHOD_CALL; foreach ($this->parseArguments() as $n) { $arguments->addElement($n); } } } else { throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename()); } if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) { if (!$arg instanceof Twig_Node_Expression_Constant) { throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s")', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename()); } $name = $arg->getAttribute('value'); if ($this->parser->isReservedMacroName($name)) { throw new Twig_Error_Syntax(sprintf('"%s" cannot be called as macro as it is a reserved keyword', $name), $token->getLine(), $this->parser->getFilename()); } $node = new Twig_Node_Expression_MethodCall($node, 'get'.$name, $arguments, $lineno); $node->setAttribute('safe', true); return $node; } } else { $type = Twig_Template::ARRAY_CALL; // slice? $slice = false; if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) { $slice = true; $arg = new Twig_Node_Expression_Constant(0, $token->getLine()); } else { $arg = $this->parseExpression(); } if ($stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { $slice = true; } if ($slice) { if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { $length = new Twig_Node_Expression_Constant(null, $token->getLine()); } else { $length = $this->parseExpression(); } $class = $this->getFilterNodeClass('slice', $token->getLine()); $arguments = new Twig_Node(array($arg, $length)); $filter = new $class($node, new Twig_Node_Expression_Constant('slice', $token->getLine()), $arguments, $token->getLine()); $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); return $filter; } $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); } return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno); } public func8 parseFilterExpression($node) { $this->parser->getStream()->next(); return $this->parseFilterExpressionRaw($node); } public function parseFilterExpressionRaw($node, $tag = null) { while (true) { $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE); $name = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '(')) { $arguments = new Twig_Node(); } else { $arguments = $this->parseArguments(true); } $class = $this->getFilterNodeClass($name->getAttribute('value'), $token->getLine()); $node = new $class($node, $name, $arguments, $token->getLine(), $tag); if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '|')) { break; } $this->parser->getStream()->next(); } return $node; } /** * Parses arguments. * * @param bool $namedArguments Whether to allow named arguments or not * @param bool $definition Whether we are parsing arguments for a function definition * * @return Twig_Node * * @throws Twig_Error_Syntax */ public function parseArguments($namedArguments = false, $definition = false) { $args = array(); $stream = $this->parser->getStream(); $stream->expect(Twig_Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis'); while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ')')) { if (!empty($args)) { $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma'); } if ($definition) { $token = $stream->expect(Twig_Token::NAME_TYPE, null, 'An argument must be a name'); $value = new Twig_Node_Expression_Name($token->getValue(), $this->parser->getCurrentToken()->getLine()); } else { $value = $this->parseExpression(); } $name = null; if ($namedArguments && $token = $stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) { if (!$value instanceof Twig_Node_Expression_Name) { throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given', get_class($value)), $token->getLine(), $this->parser->getFilename()); } $name = $value->getAttribute('name'); if ($definition) { $value = $this->parsePrimaryExpression(); if (!$this->checkConstantExpression($value)) { throw new Twig_Error_Syntax(sprintf('A default value for an argument must be a constant (a boolean, a string, a number, or an array).'), $token->getLine(), $this->parser->getFilename()); } } else { $value = $this->parseExpression(); } } if ($definition) { if (null === $name) { $name = $value->getAttribute('name'); $value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine()); } $args[$name] = $value; } else { if (null === $name) { $args[] = $value; } else { $args[$name] = $value; } } } $stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis'); return new Twig_Node($args); } public function parseAssignmentExpression() { $targets = array(); while (true) { $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to'); if (in_array($token->getValue(), array('true', 'false', 'none'))) { throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s"', $token->getValue()), $token->getLine(), $this->parser->getFilename()); } $targets[] = new Twig_Node_Expression_AssignName($token->getValue(), $token->getLine()); if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { break; } } return new Twig_Node($targets); } public function parseMultitargetExpression() { $targets = array(); while (true) { $targets[] = $this->parseExpression(); if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { break; } } return new Twig_Node($targets); } protected function getFunctionNodeClass($name, $line) { $env = $this->parser->getEnvironment(); if (false === $function = $env->getFunction($name)) { $message = sprintf('The function "%s" does not exist', $name); if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFunctions()))) { $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives)); } throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename()); } if ($function instanceof Twig_SimpleFunction) { return $function->getNodeClass(); } return $function instanceof Twig_Function_Node ? $function->getClass() : 'Twig_Node_Expression_Function'; } protected function getFilterNodeClass($name, $line) { $env = $this->parser->getEnvironment(); if (false === $filter = $env->getFilter($name)) { $message = sprintf('The filter "%s" does not exist', $name); if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFilters()))) { $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives)); } throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename()); } if ($filter instanceof Twig_SimpleFilter) { return $filter->getNodeClass(); } return $filter instanceof Twig_Filter_Node ? $filter->getClass() : 'Twig_Node_Expression_Filter'; } // checks that the node only contains "constant" elements protected function checkConstantExpression(Twig_NodeInterface $node) { if (!($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array || $node instanceof Twig_Node_Expression_Unary_Neg || $node instanceof Twig_Node_Expression_Unary_Pos )) { return false; } foreach ($node as $n) { if (!$this->checkConstantExpression($n)) { return false; } } return true; } }