. 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();
}
}
}
}
{ Ë 8 ffffXÎ xE irst) {
$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;
}
}