2279 lines
92 KiB
PHP
2279 lines
92 KiB
PHP
<?php
|
|
/******************************************************************************
|
|
* Subs.php *
|
|
*******************************************************************************
|
|
* SMF: Simple Machines Forum *
|
|
* Open-Source Project Inspired by Zef Hemel (zef@zefhemel.com) *
|
|
* =========================================================================== *
|
|
* Software Version: SMF 1.0.6 *
|
|
* Software by: Simple Machines (http://www.simplemachines.org) *
|
|
* Copyright 2001-2005 by: Lewis Media (http://www.lewismedia.com) *
|
|
* Support, News, Updates at: http://www.simplemachines.org *
|
|
*******************************************************************************
|
|
* This program is free software; you may redistribute it and/or modify it *
|
|
* under the terms of the provided license as published by Lewis Media. *
|
|
* *
|
|
* This program is distributed in the hope that it is and will be useful, *
|
|
* but WITHOUT ANY WARRANTIES; without even any implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
* *
|
|
* See the "license.txt" file for details of the Simple Machines license. *
|
|
* The latest version can always be found at http://www.simplemachines.org. *
|
|
******************************************************************************/
|
|
if (!defined('SMF'))
|
|
die('Hacking attempt...');
|
|
|
|
/* This file has all the main functions in it that relate to, well,
|
|
everything. It provides all of the following functions:
|
|
|
|
resource db_query(string database_query, string __FILE__, int __LINE__)
|
|
- should always be used in place of mysql_query.
|
|
- executes a query string, and implements needed error checking.
|
|
- always use the magic constants __FILE__ and __LINE__.
|
|
- returns a MySQL result resource, to be freed with mysql_free_result.
|
|
|
|
int db_affected_rows()
|
|
- should always be used in place of db_insert_id.
|
|
- returns the number of affected rows by the most recently executed
|
|
query.
|
|
- handles the current connection so the forum with other connections
|
|
active at the same time.
|
|
|
|
int db_insert_id()
|
|
- should always be used in place of mysql_insert_id.
|
|
- returns the most recently generated auto_increment column.
|
|
- handles the current connection so the forum with other connections
|
|
active at the same time.
|
|
|
|
void updateLastMessages(array ID_BOARDs)
|
|
- takes an array of board IDs and updates their last messages.
|
|
- if the board has a parent, that parent board is also automatically
|
|
updated.
|
|
- columns updated are ID_LAST_MSG and lastUpdated.
|
|
- note that ID_LAST_MSG should always be updated using this function,
|
|
and is not automatically updated upon other changes.
|
|
|
|
void updateStats(string statistic, string condition = '1')
|
|
- statistic can be 'member', 'message', 'topic', 'calendar', or
|
|
'postgroups'.
|
|
- the condition is optional, and is only used to update post groups.
|
|
- the 'member' statistic updates the latest member, the total member
|
|
count, and the number of unapproved members.
|
|
- updating 'message' changes the total number of messages, and the
|
|
highest message id by ID_MSG.
|
|
- 'topic' updates the total number of topics.
|
|
- the 'calendar' statistic updates the cache of the calendar
|
|
information for a day before and after today.
|
|
- the 'postgroups' case updates those members who match condition's
|
|
post-based membergroups in the database.
|
|
|
|
void updateMemberData(int ID_MEMBER, array data)
|
|
- updates the columns in the members table.
|
|
- ID_MEMBER is either an int or an array of ints to be updated.
|
|
- data is an associative array of the columns to be updated and their
|
|
respective values.
|
|
- any string values updated should be quoted and slashed.
|
|
- the value of any column can be '+' or '-', which mean 'increment'
|
|
and decrement, respectively.
|
|
- if the member's post number is updated, updates their post groups.
|
|
- this function should be used whenever member data needs to be
|
|
updated in place of an UPDATE query.
|
|
|
|
void updateSettings(array changeArray)
|
|
- updates both the settings table and $modSettings array.
|
|
- all of changeArray's indexes and values are assumed to have escaped
|
|
apostrophes (')!
|
|
- if a variable is already set to what you want to change it to, that
|
|
variable will be skipped over; it would be unnecessary to reset.
|
|
|
|
string constructPageIndex(string base_url, int &start, int max_value,
|
|
int num_per_page, bool compact_start = false)
|
|
- builds the page list, e.g. 1 ... 6 7 [8] 9 10 ... 15.
|
|
- compact_start caused it to use "url.page" instead of
|
|
"url;start=page".
|
|
- handles any wireless settings (adding special things to URLs.)
|
|
- very importantly, cleans up the start value passed, and forces it to
|
|
be a multiple of num_per_page.
|
|
- also checks that start is not more than max_value.
|
|
- base_url should be the URL without any start parameter on it.
|
|
- uses the compactTopicPagesEnable and compactTopicPagesContiguous
|
|
settings to decide how to display the menu.
|
|
- an example is available near the function definition.
|
|
|
|
string comma_format(float number)
|
|
- formats a number to display in the style of the admins' choosing.
|
|
- uses the format of number_format to decide how to format the number.
|
|
- for example, it might display "1 234,50".
|
|
- caches the formatting data from the setting for optimization.
|
|
|
|
string timeformat(int time, bool show_today = true)
|
|
- returns a pretty formated version of time based on the user's format
|
|
in $user_info['time_format'].
|
|
- applies any necessary time offsets to the timestamp.
|
|
- if todayMod is set and show_today was not not specified or true, an
|
|
alternate format string is used to show the date with something to
|
|
show it is "today" or "yesterday".
|
|
- performs localization (more than just strftime would do alone.)
|
|
|
|
string un_htmlspecialchars(string text)
|
|
- removes the base entities (<, ", etc.) from text.
|
|
- should be used instead of html_entity_decode for PHP version
|
|
compatibility reasons.
|
|
- additionally converts and '.
|
|
|
|
int forum_time(bool use_user_offset = true)
|
|
- returns the current time with offsets.
|
|
- always applies the offset in the time_offset setting.
|
|
- if use_user_offset is true, applies the user's offset as well.
|
|
- returns seconds since the unix epoch.
|
|
|
|
string doUBBC(string message, bool enableSmileys = true)
|
|
- parses bbc tags in message.
|
|
- only parses smileys if enableSmileys is true.
|
|
- does nothing if the enableBBC setting is off.
|
|
- applies the fixLongWords magic if the setting is set to on.
|
|
- returns the modified message.
|
|
|
|
void parsecode(string &message)
|
|
- this very hefty function does the bulk of message parsing.
|
|
- only parses BBC tags which are not disabled in disabledBBC.
|
|
- also handles basic HTML, if enablePostHTML is on.
|
|
- caches the from/to replace regular expressions so as not to reload
|
|
them every time a string is parsed.
|
|
- returns nothing, but instead modifies message directly.
|
|
|
|
void parsesmileys(string &message)
|
|
- the smiley parsing function which makes pretty faces appear :).
|
|
- if custom smiley sets are turned off by smiley_enable, the default
|
|
set of smileys will be used.
|
|
- these are specifically not parsed in code tags [url=mailto:Dad@blah.com]
|
|
- caches the smileys from the database or array in memory.
|
|
- doesn't return anything, but rather modifies message directly.
|
|
|
|
string highlight_php_code(string code)
|
|
- Uses PHP's highlight_code() to highlight PHP syntax
|
|
- does special handling to keep the tabs in the code available.
|
|
- used to parse PHP code from inside [code] and [php] tags.
|
|
- returns the code with highlighted HTML.
|
|
|
|
void writeLog(bool force = false)
|
|
// !!!
|
|
|
|
void redirectexit(string setLocation = '', bool add = true, bool refresh = false)
|
|
// !!!
|
|
|
|
void obExit(bool do_header = true, bool do_footer = do_header)
|
|
// !!!
|
|
|
|
void adminIndex($area)
|
|
// !!!
|
|
|
|
int logAction($action, $extra = array())
|
|
// !!!
|
|
|
|
void trackStats($stats = array())
|
|
- caches statistics changes, and flushes them if you pass nothing.
|
|
- if '+' is used as a value, it will be incremented.
|
|
- does not actually commit the changes until the end of the page view.
|
|
- depends on the trackStats setting.
|
|
|
|
void spamProtection(string error_type)
|
|
- attempts to protect from spammed messages and the like.
|
|
- takes a $txt index. (not an actual string.)
|
|
- depends on the spamWaitTime setting.
|
|
|
|
array url_image_size(string url)
|
|
- uses getimagesize() to determine the size of a file.
|
|
- attempts to connect to the server first so it won't time out.
|
|
- returns false on failure, otherwise the output of getimagesize().
|
|
|
|
void determineTopicClass(array &topic_context)
|
|
// !!!
|
|
|
|
void setupThemeContext()
|
|
// !!!
|
|
|
|
void template_rawdata()
|
|
// !!!
|
|
|
|
void template_header()
|
|
// !!!
|
|
|
|
void theme_copyright(bool get_it = false)
|
|
// !!!
|
|
|
|
void template_footer()
|
|
// !!!
|
|
|
|
void db_debug_junk()
|
|
// !!!
|
|
|
|
void getAttachmentFilename(string filename, int ID_ATTACH, bool new = true)
|
|
// !!!
|
|
*/
|
|
|
|
// Do a query. Takes care of errors too.
|
|
function db_query($db_string, $file, $line)
|
|
{
|
|
global $db_cache, $db_count, $db_connection, $modSettings;
|
|
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,2);
|
|
|
|
$timer = pinba_timer_start(array("component" => 'db_query', 'file' => $trace[1]['function'], 'file' => $file));
|
|
|
|
// One more query....
|
|
$db_count = !isset($db_count) ? 1 : $db_count + 1;
|
|
|
|
// Debugging.
|
|
if (isset($GLOBALS['db_show_debug']) && $GLOBALS['db_show_debug'] === true)
|
|
{
|
|
$db_cache[$db_count]['q'] = $db_string;
|
|
$db_cache[$db_count]['f'] = $file;
|
|
$db_cache[$db_count]['l'] = $line;
|
|
$st = explode(' ', microtime());
|
|
}
|
|
|
|
// First, we clean strings out of the query, reduce whitespace, lowercase, and trim - so we can check it over.
|
|
if (empty($modSettings['disableQueryCheck']))
|
|
{
|
|
$clean = '';
|
|
$old_pos = 0;
|
|
$pos = -1;
|
|
while (true)
|
|
{
|
|
$pos = strpos($db_string, '\'', $pos + 1);
|
|
if ($pos === false)
|
|
break;
|
|
$clean .= substr($db_string, $old_pos, $pos - $old_pos);
|
|
|
|
while (true)
|
|
{
|
|
$pos1 = strpos($db_string, '\'', $pos + 1);
|
|
$pos2 = strpos($db_string, '\\', $pos + 1);
|
|
if ($pos1 === false)
|
|
break;
|
|
elseif ($pos2 == false || $pos2 > $pos1)
|
|
{
|
|
$pos = $pos1;
|
|
break;
|
|
}
|
|
|
|
$pos = $pos2 + 1;
|
|
}
|
|
$clean .= '%s';
|
|
|
|
$old_pos = $pos + 1;
|
|
}
|
|
$clean .= substr($db_string, $old_pos);
|
|
$clean = trim(strtolower(preg_replace(array('~\s+~s', '~/\*!40001 SQL_NO_CACHE \*/~', '~/\*!40000 USE INDEX \([A-Za-z\_]+?\) \*/~'), array(' ', '', ''), $clean)));
|
|
|
|
// We don't use UNION in SMF, at least so far. But it's useful for injections.
|
|
if (strpos($clean, 'union') !== false && preg_match('~(^|[^a-z])union($|[^[a-z])~s', $clean) != 0)
|
|
$fail = true;
|
|
// Comments? We don't use comments in our queries, we leave 'em outside!
|
|
elseif (strpos($clean, '/*') > 2 || strpos($clean, '--') !== false)
|
|
$fail = true;
|
|
// Trying to change passwords, slow us down, or something?
|
|
elseif (strpos($clean, 'set password') !== false && preg_match('~(^|[^a-z])set password($|[^[a-z])~s', $clean) != 0)
|
|
$fail = true;
|
|
elseif (strpos($clean, 'benchmark') !== false && preg_match('~(^|[^a-z])benchmark($|[^[a-z])~s', $clean) != 0)
|
|
$fail = true;
|
|
// Sub selects? We don't use those either.
|
|
elseif (preg_match('~\([^)]*?select~s', $clean) != 0)
|
|
$fail = true;
|
|
|
|
if (!empty($fail))
|
|
{
|
|
log_error('Hacking attempt...' . "\n" . $db_string, $file, $line);
|
|
fatal_error('Hacking attempt...', false);
|
|
}
|
|
}
|
|
|
|
$ret = mysql_query($db_string, $db_connection);
|
|
if ($ret === false)
|
|
$ret = db_error($db_string, $file, $line);
|
|
|
|
// Debugging.
|
|
if (isset($GLOBALS['db_show_debug']) && $GLOBALS['db_show_debug'] === true)
|
|
{
|
|
$end = explode(' ', microtime());
|
|
$db_cache[$db_count]['t'] = $end[0] + $end[1] - $st[0] - $st[1];
|
|
}
|
|
|
|
pinba_timer_stop($timer);
|
|
return $ret;
|
|
}
|
|
|
|
function db_affected_rows()
|
|
{
|
|
global $db_connection;
|
|
|
|
return mysql_affected_rows($db_connection);
|
|
}
|
|
|
|
function db_insert_id()
|
|
{
|
|
global $db_connection;
|
|
|
|
return mysql_insert_id($db_connection);
|
|
}
|
|
|
|
// Update the last message in a board, and its parents.
|
|
function updateLastMessages($setboards)
|
|
{
|
|
global $db_prefix, $board_info, $board;
|
|
|
|
if (!is_array($setboards))
|
|
$setboards = array($setboards);
|
|
|
|
// Find the latest message on this board. (highest ID_MSG)
|
|
$result = db_query("
|
|
SELECT ID_BOARD, MAX(ID_MSG) AS ID_MSG
|
|
FROM {$db_prefix}messages
|
|
WHERE ID_BOARD" . (count($setboards) == 1 ? " = $setboards[0]" : ' IN (' . implode(', ', $setboards) . ')') . "
|
|
GROUP BY ID_BOARD", __FILE__, __LINE__);
|
|
$setboards = array_flip($setboards);
|
|
while ($row = mysql_fetch_assoc($result))
|
|
{
|
|
// Okay, this board is done ;).
|
|
unset($setboards[$row['ID_BOARD']]);
|
|
$rPosterTime = db_query("SELECT posterTime FROM {$db_prefix}messages WHERE ID_MSG={$row['ID_MSG']}", __FILE__, __LINE__);
|
|
list($posterTime) = mysql_fetch_row($rPosterTime);
|
|
|
|
// Update the board!
|
|
db_query("
|
|
UPDATE {$db_prefix}boards
|
|
SET ID_LAST_MSG = $row[ID_MSG], lastUpdated = $posterTime
|
|
WHERE ID_BOARD = $row[ID_BOARD]
|
|
LIMIT 1", __FILE__, __LINE__);
|
|
|
|
// The loadBoard function hasn't loaded this board yet?
|
|
if (empty($board) || $board != $row['ID_BOARD'])
|
|
$the_parent_boards = getBoardParents($row['ID_BOARD']);
|
|
else
|
|
$the_parent_boards = $board_info['parent_boards'];
|
|
|
|
if (isset($the_parent_boards[$row['ID_BOARD']]))
|
|
unset($the_parent_boards[$row['ID_BOARD']]);
|
|
|
|
$the_parent_boards = array_keys($the_parent_boards);
|
|
|
|
// If the board has parents update them too.
|
|
if (!empty($the_parent_boards))
|
|
{
|
|
db_query("
|
|
UPDATE {$db_prefix}boards
|
|
SET lastUpdated = $posterTime
|
|
WHERE ID_BOARD IN (" . implode(',', $the_parent_boards) . ")
|
|
AND lastUpdated < $posterTime
|
|
AND childLevel != 0
|
|
LIMIT " . count($the_parent_boards), __FILE__, __LINE__);
|
|
|
|
// Don't do them twice.
|
|
foreach ($the_parent_boards as $ID_BOARD)
|
|
if (isset($setboards[$ID_BOARD]))
|
|
unset($setboards[$ID_BOARD]);
|
|
}
|
|
}
|
|
|
|
if (!empty($setboards))
|
|
db_query("
|
|
UPDATE {$db_prefix}boards
|
|
SET ID_LAST_MSG = 0
|
|
WHERE ID_BOARD IN (" . implode(', ', array_keys($setboards)) . ")
|
|
LIMIT 1", __FILE__, __LINE__);
|
|
}
|
|
|
|
// Update some basic statistics...
|
|
function updateStats($type, $condition = '1')
|
|
{
|
|
global $db_prefix, $sourcedir, $modSettings;
|
|
|
|
switch ($type)
|
|
{
|
|
case 'member':
|
|
// Update the latest member (highest ID_MEMBER) and count.
|
|
$result = db_query("
|
|
SELECT COUNT(ID_MEMBER), MAX(ID_MEMBER)
|
|
FROM {$db_prefix}members", __FILE__, __LINE__);
|
|
list ($memberCount, $latestmember) = mysql_fetch_row($result);
|
|
mysql_free_result($result);
|
|
|
|
// Get the latest member's display name.
|
|
$result = db_query("
|
|
SELECT IFNULL(realName, memberName) AS realName
|
|
FROM {$db_prefix}members
|
|
WHERE ID_MEMBER = " . (int) $latestmember . "
|
|
LIMIT 1", __FILE__, __LINE__);
|
|
list ($latestRealName) = mysql_fetch_row($result);
|
|
mysql_free_result($result);
|
|
|
|
// Update the amount of members awaiting approval.
|
|
if (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 2)
|
|
{
|
|
$result = db_query("
|
|
SELECT COUNT(ID_MEMBER)
|
|
FROM {$db_prefix}members
|
|
WHERE is_activated = 0
|
|
AND validation_code = ''", __FILE__, __LINE__);
|
|
list ($unapprovedCount) = mysql_fetch_row($result);
|
|
mysql_free_result($result);
|
|
}
|
|
else
|
|
$unapprovedCount = $modSettings['unapprovedMembers'];
|
|
|
|
updateSettings(array(
|
|
'latestMember' => $latestmember,
|
|
'latestRealName' => $latestRealName,
|
|
'memberCount' => $memberCount,
|
|
'unapprovedMembers' => $unapprovedCount
|
|
));
|
|
break;
|
|
case 'message':
|
|
// Get the number of messages...
|
|
$result = db_query("
|
|
SELECT COUNT(ID_MSG) AS totalMessages, MAX(ID_MSG) AS maxMsgID
|
|
FROM {$db_prefix}messages", __FILE__, __LINE__);
|
|
$row = mysql_fetch_assoc($result);
|
|
mysql_free_result($result);
|
|
|
|
updateSettings(array(
|
|
'totalMessages' => $row['totalMessages'],
|
|
'maxMsgID' => $row['maxMsgID']
|
|
));
|
|
break;
|
|
case 'topic':
|
|
// Get the number of topics.
|
|
$result = db_query("
|
|
SELECT COUNT(ID_TOPIC) AS totalTopics
|
|
FROM {$db_prefix}topics", __FILE__, __LINE__);
|
|
$row = mysql_fetch_assoc($result);
|
|
mysql_free_result($result);
|
|
|
|
updateSettings(array('totalTopics' => $row['totalTopics']));
|
|
break;
|
|
case 'calendar':
|
|
require_once($sourcedir . '/Calendar.php');
|
|
|
|
// Calculate the YYYY-MM-DD of the lowest and highest days.
|
|
$low_date = strftime('%Y-%m-%d', forum_time(false) - 24 * 3600);
|
|
$high_date = strftime('%Y-%m-%d', forum_time(false) + $modSettings['cal_days_for_index'] * 24 * 3600);
|
|
|
|
$holidays = calendarHolidayArray($low_date, $high_date);
|
|
$bday = calendarBirthdayArray($low_date, $high_date);
|
|
$events = calendarEventArray($low_date, $high_date, false);
|
|
|
|
// Cache the results in the settings.
|
|
updateSettings(array(
|
|
'cal_today_updated' => strftime('%Y%m%d', forum_time(false)),
|
|
'cal_today_holiday' => addslashes(serialize($holidays)),
|
|
'cal_today_birthday' => addslashes(serialize($bday)),
|
|
'cal_today_event' => addslashes(serialize($events))
|
|
));
|
|
break;
|
|
case 'postgroups':
|
|
// Fetch postgroups.
|
|
$request = db_query("
|
|
SELECT ID_GROUP, minPosts
|
|
FROM {$db_prefix}membergroups
|
|
WHERE minPosts != -1", __FILE__, __LINE__);
|
|
$postgroups = array();
|
|
while ($row = mysql_fetch_assoc($request))
|
|
$postgroups[$row['ID_GROUP']] = $row['minPosts'];
|
|
mysql_free_result($request);
|
|
|
|
// Oh great, they've screwed their post groups.
|
|
if (empty($postgroups))
|
|
return;
|
|
|
|
// Sort them this way because if it's done with MySQL it causes a filesort :(.
|
|
arsort($postgroups);
|
|
|
|
// Set all membergroups from most posts to least posts.
|
|
$conditions = '';
|
|
foreach ($postgroups as $id => $minPosts)
|
|
{
|
|
$conditions .= '
|
|
WHEN posts >= ' . $minPosts . (!empty($lastMin) ? ' AND posts <= ' . $lastMin : '') . ' THEN ' . $id;
|
|
$lastMin = $minPosts;
|
|
}
|
|
|
|
// A big fat CASE WHEN... END is faster than a zillion UPDATE's ;).
|
|
db_query("
|
|
UPDATE {$db_prefix}members
|
|
SET ID_POST_GROUP = CASE$conditions
|
|
ELSE 0
|
|
END" . ($condition != '1' ? "
|
|
WHERE $condition" : ''), __FILE__, __LINE__);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Assumes the data has been slashed.
|
|
function updateMemberData($members, $data)
|
|
{
|
|
global $db_prefix;
|
|
|
|
$setString = '';
|
|
foreach ($data as $var => $val)
|
|
{
|
|
if ($val === '+')
|
|
$val = $var . ' + 1';
|
|
elseif ($val === '-')
|
|
$val = $var . ' - 1';
|
|
|
|
$setString .= "
|
|
$var = $val,";
|
|
}
|
|
|
|
if (is_array($members))
|
|
$condition = 'ID_MEMBER IN (' . implode(', ', $members) . ')
|
|
LIMIT ' . count($members);
|
|
elseif ($members === null)
|
|
$condition = '1';
|
|
else
|
|
$condition = 'ID_MEMBER = ' . $members . '
|
|
LIMIT 1';
|
|
|
|
db_query("
|
|
UPDATE {$db_prefix}members
|
|
SET" . substr($setString, 0, -1) . '
|
|
WHERE ' . $condition, __FILE__, __LINE__);
|
|
|
|
if (isset($data['posts']))
|
|
updateStats('postgroups', $condition);
|
|
}
|
|
|
|
// Updates the settings table as well as $modSettings
|
|
// All input variables and values are assumed to have escaped apostrophes(')!
|
|
function updateSettings($changeArray)
|
|
{
|
|
global $db_prefix, $modSettings;
|
|
|
|
if (empty($changeArray) || !is_array($changeArray))
|
|
return;
|
|
|
|
$replaceArray = array();
|
|
foreach ($changeArray as $variable => $value)
|
|
{
|
|
// Don't bother if it's already like that ;).
|
|
if (isset($modSettings[$variable]) && $modSettings[$variable] == stripslashes($value))
|
|
continue;
|
|
|
|
$replaceArray[] = "('$variable', '$value')";
|
|
$modSettings[$variable] = stripslashes($value);
|
|
}
|
|
|
|
if (empty($replaceArray))
|
|
return;
|
|
|
|
db_query("
|
|
REPLACE INTO {$db_prefix}settings
|
|
(variable, value)
|
|
VALUES " . implode(',
|
|
', $replaceArray), __FILE__, __LINE__);
|
|
}
|
|
|
|
function constructAlphabetIndex($base_url)
|
|
{
|
|
$letters_ru = 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЫЭЮЯ';
|
|
$letters_en = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
|
|
|
|
$index = '
|
|
<table width="100%">
|
|
<tr align="center">';
|
|
|
|
for ($i=0;$i<mb_strlen($letters_en);$i++) {
|
|
$index .= '
|
|
<td>
|
|
<a href="'. $base_url. ';filter='. urlencode(mb_substr($letters_en, $i,1)). '">'. mb_substr($letters_en, $i,1). '</a>
|
|
</td>';
|
|
|
|
}
|
|
|
|
$index .= '
|
|
</tr>
|
|
</table>
|
|
<table width="100%">
|
|
<tr align="center">';
|
|
for ($i=0;$i<mb_strlen($letters_ru);$i++) {
|
|
$index .= '
|
|
<td>
|
|
<a href="'. $base_url. ';filter='. urlencode(mb_substr($letters_ru, $i,1)). '">'. mb_substr($letters_ru, $i,1). '</a>
|
|
</td>';
|
|
}
|
|
|
|
$index .= '
|
|
</tr>
|
|
</table>';
|
|
|
|
return $index;
|
|
}
|
|
|
|
/* Constructs a page list.
|
|
ie. $pageindex = constructPageIndex($scripturl . '?board=' . $board, $_REQUEST['start'], $num_messages, $maxindex, true); */
|
|
function constructPageIndex($base_url, &$start, $max_value, $num_per_page, $compact_start = false, $additional = '')
|
|
{
|
|
global $modSettings;
|
|
|
|
// Save whether $start was less than 0 or not.
|
|
$start_invalid = $start < 0;
|
|
|
|
// Make sure $start is a proper variable - not less than 0.
|
|
if ($start_invalid)
|
|
$start = 0;
|
|
// Not greater than the upper bound.
|
|
elseif ($start >= $max_value)
|
|
$start = (int) $max_value - (((int) $max_value % (int) $num_per_page) == 0 ? $num_per_page : ((int) $max_value % (int) $num_per_page));
|
|
// And it has to be a multiple of $num_per_page!
|
|
else
|
|
$start = (int) $start - ((int) $start % (int) $num_per_page);
|
|
|
|
// Somehow $start ended up zero through the subtractions... fix it.
|
|
if ($start < 0)
|
|
$start = 0;
|
|
|
|
// Wireless will need the protocol on the URL somewhere.
|
|
if (WIRELESS)
|
|
{
|
|
$base_url .= ';' . WIRELESS_PROTOCOL;
|
|
$compact_start = false;
|
|
}
|
|
|
|
$base_link = '<a class="navPages" href="' . $base_url . ($compact_start ? '.' : ';start=');
|
|
|
|
// Compact pages is off or on?
|
|
if (empty($modSettings['compactTopicPagesEnable']))
|
|
{
|
|
// Show the left arrow.
|
|
$pageindex = $start == 0 ? ' ' : $base_link . ($start - $num_per_page) . ($additional == '' ? '': ';' . $additional) . '">«</a> ';
|
|
|
|
// Show all the pages.
|
|
$display_page = 1;
|
|
for ($counter = 0; $counter < $max_value; $counter += $num_per_page)
|
|
$pageindex .= $start == $counter && !$start_invalid ? $display_page++ : $base_link . $counter . ($additional == '' ? '': ';' . $additional) . '">' . $display_page++ . '</a> ';
|
|
|
|
// Show the right arrow.
|
|
$display_page = ($start + $num_per_page) > $max_value ? $max_value : ($start + $num_per_page);
|
|
if ($start != $counter - $max_value && !$start_invalid)
|
|
$pageindex .= $display_page > $counter - $num_per_page ? ' ' : $base_link . $display_page . ($additional == '' ? '': ';' . $additional) . '">»</a> ';
|
|
}
|
|
else
|
|
{
|
|
// If they didn't enter an odd value, pretend they did.
|
|
$PageContiguous = (int) ($modSettings['compactTopicPagesContiguous'] - ($modSettings['compactTopicPagesContiguous'] % 2)) / 2;
|
|
|
|
// Show the first page. (>1< ... 6 7 [8] 9 10 ... 15)
|
|
if ($start > $num_per_page * $PageContiguous)
|
|
$pageindex = $base_link . '0">1</a> ';
|
|
else
|
|
$pageindex = '';
|
|
|
|
// Show the ... after the first page. (1 >...< 6 7 [8] 9 10 ... 15)
|
|
if ($start > $num_per_page * ($PageContiguous + 1))
|
|
$pageindex .= ' ... ';
|
|
|
|
// Show the pages before the current one. (1 ... >6 7< [8] 9 10 ... 15)
|
|
for ($nCont = $PageContiguous; $nCont >= 1; $nCont--)
|
|
if ($start >= $num_per_page * $nCont)
|
|
{
|
|
$tmpStart = $start - $num_per_page * $nCont;
|
|
$pageindex.= $base_link . $tmpStart . ($additional == '' ? '': ';' . $additional) . '">' . ($tmpStart / $num_per_page + 1) . '</a> ';
|
|
}
|
|
|
|
// Show the current page. (1 ... 6 7 >[8]< 9 10 ... 15)
|
|
if (!$start_invalid)
|
|
$pageindex .= '[' . ($start / $num_per_page + 1) . '] ';
|
|
else
|
|
$pageindex .= $base_link . $start . ($additional == '' ? '': ';' . $additional) . '">' . ($start / $num_per_page + 1) . '</a> ';
|
|
|
|
// Show the pages after the current one... (1 ... 6 7 [8] >9 10< ... 15)
|
|
$tmpMaxPages = (int) (($max_value - 1) / $num_per_page) * $num_per_page;
|
|
for ($nCont = 1; $nCont <= $PageContiguous; $nCont++)
|
|
if ($start + $num_per_page * $nCont <= $tmpMaxPages)
|
|
{
|
|
$tmpStart = $start + $num_per_page * $nCont;
|
|
$pageindex .= $base_link . $tmpStart . ($additional == '' ? '': ';' . $additional) . '">' . ($tmpStart / $num_per_page + 1) . '</a> ';
|
|
}
|
|
|
|
// Show the '...' part near the end. (1 ... 6 7 [8] 9 10 >...< 15)
|
|
if ($start + $num_per_page * ($PageContiguous + 1) < $tmpMaxPages)
|
|
$pageindex .= ' ... ';
|
|
|
|
// Show the last number in the list. (1 ... 6 7 [8] 9 10 ... >15<)
|
|
if ($start + $num_per_page * $PageContiguous < $tmpMaxPages)
|
|
$pageindex .= $base_link . $tmpMaxPages . ($additional == '' ? '': ';' . $additional) . '">' . ($tmpMaxPages / $num_per_page + 1) . '</a> ';
|
|
}
|
|
|
|
return $pageindex;
|
|
}
|
|
|
|
// Formats a number to display in the style of the admin's choosing.
|
|
function comma_format($number)
|
|
{
|
|
global $modSettings;
|
|
static $thousands_separator = null, $decimal_separator = null, $decimal_count = null;
|
|
|
|
// Cache these values...
|
|
if ($decimal_separator === null)
|
|
{
|
|
// Not set for whatever reason?
|
|
if (empty($modSettings['number_format']) || preg_match('~^1([^\d]*)?234([^\d]*)(0*?)$~', $modSettings['number_format'], $matches) != 1)
|
|
return $number;
|
|
|
|
// Cache these each load...
|
|
$thousands_separator = $matches[1];
|
|
$decimal_separator = $matches[2];
|
|
$decimal_count = strlen($matches[3]);
|
|
}
|
|
|
|
// Format the string with our friend, number_format.
|
|
return number_format($number, is_float($number) ? $decimal_count : 0, $decimal_separator, $thousands_separator);
|
|
}
|
|
|
|
// Format a time to make it look purdy.
|
|
function timeformat($logTime, $show_today = true)
|
|
{
|
|
global $user_info, $txt, $db_prefix, $modSettings;
|
|
global $days, $months, $days_short, $months_short;
|
|
|
|
// Offset the time.
|
|
$time = $logTime + ($user_info['time_offset'] + $modSettings['time_offset']) * 3600;
|
|
|
|
// We can't have a negative date!
|
|
if ($time < 0)
|
|
$time = 0;
|
|
|
|
// Today and Yesterday?
|
|
if ($modSettings['todayMod'] >= 1 && $show_today)
|
|
{
|
|
// Get the current time.
|
|
$nowtime = forum_time();
|
|
|
|
$then = @getdate($time);
|
|
$now = @getdate($nowtime);
|
|
|
|
// Try to make something of a time format string...
|
|
if (strpos($user_info['time_format'], '%H') === false && strpos($user_info['time_format'], '%T') === false)
|
|
$today_fmt = '%I:%M %p';
|
|
else
|
|
$today_fmt = '%H:%M';
|
|
|
|
// Same day of the year, same year.... Today!
|
|
if ($then['yday'] == $now['yday'] && $then['year'] == $now['year'])
|
|
return $txt['smf10'] . strftime($today_fmt, $time);
|
|
|
|
// Day-of-year is one less and same year, or it's the first of the year and that's the last of the year...
|
|
if ($modSettings['todayMod'] == '2' && (($then['yday'] == $now['yday'] - 1 && $then['year'] == $now['year']) || ($now['yday'] == 0 && $then['year'] == $now['year'] - 1) && $then['mon'] == 12 && $then['mday'] == 31))
|
|
return $txt['smf10b'] . strftime($today_fmt, $time);
|
|
}
|
|
|
|
// Strip slashes off the time format string.
|
|
$str = $user_info['time_format'];
|
|
|
|
if (setlocale(LC_TIME, @$txt['lang_locale']))
|
|
{
|
|
$str = preg_replace('#%a#', ucwords(strftime('%a', $time)), $str);
|
|
$str = preg_replace('#%A#', ucwords(strftime('%A', $time)), $str);
|
|
$str = preg_replace('#%b#', ucwords(strftime('%b', $time)), $str);
|
|
$str = preg_replace('#%B#', ucwords(strftime('%B', $time)), $str);
|
|
}
|
|
else
|
|
{
|
|
// Do-it-yourself time localization. Fun.
|
|
$str = preg_replace('#%a#', @$days_short[(int) strftime('%w', $time)], $str);
|
|
$str = preg_replace('#%A#', @$days[(int) strftime('%w', $time)], $str);
|
|
$str = preg_replace('#%b#', @$months_short[(int) strftime('%m', $time)], $str);
|
|
$str = preg_replace('#%B#', @$months[(int) strftime('%m', $time)], $str);
|
|
$str = preg_replace('#%p#', (strftime('%H', $time) < 12 ? 'am' : 'pm'), $str);
|
|
}
|
|
|
|
// Format any other characters..
|
|
return strftime($str, $time);
|
|
}
|
|
|
|
// Removes special entities from strings. Compatibility...
|
|
function un_htmlspecialchars($string)
|
|
{
|
|
return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES)) + array(''' => '\'', ' ' => ' '));
|
|
}
|
|
|
|
// The current time with offset.
|
|
function forum_time($use_user_offset = true)
|
|
{
|
|
global $user_info, $modSettings;
|
|
|
|
return time() + ($modSettings['time_offset'] + ($use_user_offset ? $user_info['time_offset'] : 0)) * 3600;
|
|
}
|
|
|
|
// Parse smileys (if $enableSmileys is true) and BBC in $message.
|
|
function doUBBC($message, $enableSmileys = true, $disabledBBC = '')
|
|
{
|
|
global $txt, $modSettings, $context;
|
|
|
|
// Item codes - for <li> types. Used with [*], [@], [o], etc.
|
|
static $itemcode = array(
|
|
'[*]' => '<li>',
|
|
'[@]' => '<li type="disc">',
|
|
'[+]' => '<li type="square">',
|
|
'[x]' => '<li type="square">',
|
|
'[#]' => '<li type="square">',
|
|
'[o]' => '<li type="circle">',
|
|
'[O]' => '<li type="circle">',
|
|
'[upload]' => '<script type="text/javascript"><!--e_bgcolor = "#000000";e_text = "#ffffff";e_type = "605x55";e_lang = "en";e_id = "u:9370";//--></script><script type="text/javascript" src="http://www.easy-share.com/upload.js"></script>'
|
|
);
|
|
|
|
if (empty($modSettings['enableBBC']))
|
|
return $message;
|
|
|
|
if (substr($message, 0, 1) == ' ')
|
|
$message = ' ' . substr($message, 1);
|
|
|
|
// Rip apart code tags.
|
|
$parts = preg_split('~\[/?code\](<br />)?~', ' ' . strtr($message, array("\n" => '<br />')));
|
|
|
|
// For each part....
|
|
for ($i = 0, $n = count($parts); $i < $n; $i++)
|
|
{
|
|
// If we're outside a block... (0: outside, 1: inside, 2: outside, 3: inside, etc.)
|
|
if ($i % 2 == 0)
|
|
{
|
|
// Close the Code block, unless this is the first block. (meaning it wasn't opened yet.)
|
|
if ($i > 0)
|
|
$parts[$i] = '</div>' . $parts[$i];
|
|
|
|
|
|
// Find any [php] code tags.... CAPTURING the delimiter.
|
|
$php_parts = preg_split('~(\[php\])(?:<br />)?|(\[/php\])~', $parts[$i], -1, PREG_SPLIT_DELIM_CAPTURE);
|
|
|
|
for ($php_i = 0, $php_n = count($php_parts); $php_i < $php_n; $php_i++)
|
|
{
|
|
// Do PHP code coloring. (this is a start tag, so everything until a [/php] should be highlighted.)
|
|
if ($php_parts[$php_i] == '[php]')
|
|
{
|
|
// Get rid of the start tag.
|
|
$php_parts[$php_i] = '';
|
|
|
|
$php_string = '';
|
|
while ($php_i < count($php_parts) && $php_parts[$php_i] != '[/php]')
|
|
{
|
|
$php_string .= $php_parts[$php_i];
|
|
|
|
// This makes it easier; jut clear it out and let the implode do all the work.
|
|
$php_parts[$php_i++] = '';
|
|
}
|
|
|
|
// Highlight the PHP code, and then remove the ?php and ? we added to do so.
|
|
$php_parts[$php_i] = highlight_php_code(substr(trim($php_string), 0, 5) != '<?' ? '<?php' . $php_string . '?>' : $php_string);
|
|
if (substr(trim($php_string), 0, 5) != '<?')
|
|
$php_parts[$php_i] = preg_replace(array('~^(.+?)<\?php~', '~\?>((?:</font>)*)$~'), '$1', $php_parts[$php_i], 1);
|
|
|
|
$did_php = true;
|
|
}
|
|
else
|
|
$did_php = false;
|
|
|
|
// Parse any URLs.... have to get rid of the @ problems some things cause... stupid email addresses.
|
|
if (!empty($modSettings['autoLinkUrls']) && (strpos($php_parts[$php_i], '://') !== false || strpos($php_parts[$php_i], 'www.') !== false))
|
|
{
|
|
// Switch out quotes really quick because they can cause problems.
|
|
$php_parts[$php_i] = strtr($php_parts[$php_i], array(''' => '\'', ' ' => '\xA0', '"' => '>">', '"' => '<"<', '<' => '<lt<'));
|
|
$php_parts[$php_i] = preg_replace(array('~(?<=[\s>\.(;\'"])((?:http|https|ftp|ftps)://[\w\-_@:|]+(?:\.[\w\-_]+)*(?::\d+)?(?:/[\w\-_\~%\.@,\?&;=#+:\']*|\([\w\-_\~%\.@,\?&;=#()+:\']*)*[/\w\-_\~%@\?;=#])~i', '~(?<=[\s>(\'])(www(?:\.[\w\-_]+)+(?::\d+)?(?:/[\w\-_\~%\.@,\?&;=#+:\']*|\([\w\-_\~%\.@,\?&;=#()+:\']*)*[/\w\-_\~%@\?;=#])~i'), array('[url]$1[/url]', '[url=http://$1]$1[/url]'), $php_parts[$php_i]);
|
|
$php_parts[$php_i] = strtr($php_parts[$php_i], array('\'' => ''', '\xA0' => ' ', '>">' => '"', '<"<' => '"', '<lt<' => '<'));
|
|
}
|
|
|
|
// Parse code.....
|
|
parsecode($php_parts[$php_i],$disabledBBC);
|
|
|
|
// Parse smileys?
|
|
if (!$enableSmileys || $did_php)
|
|
continue;
|
|
|
|
// This isn't code; change any tabs to spaces.
|
|
$php_parts[$php_i] = strtr($php_parts[$php_i], array("\t" => ' '));
|
|
|
|
// Often requested but also very kludgey; break long words.
|
|
if (!empty($modSettings['fixLongWords']))
|
|
{
|
|
// This is SADLY and INCREDIBLY browser dependent.
|
|
if ($context['browser']['is_gecko'] || strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false)
|
|
$breaker = '<span style="margin: 0 -0.5ex 0 0;"> </span>';
|
|
// Opera...
|
|
elseif ($context['browser']['is_opera'])
|
|
$breaker = '<span style="margin: 0 -0.65ex 0 -1px;"> </span>';
|
|
// Internet Explorer...
|
|
else
|
|
$breaker = '<span style="width: 0; margin: 0 -0.6ex 0 -1px;"> </span>';
|
|
|
|
// The idea is, find words xx long, and then replace them with xx + space + more.
|
|
$php_parts[$php_i] = preg_replace(
|
|
'/(?<=[>;:\?\.\! \xA0\]()])(\w{' . $modSettings['fixLongWords'] . ',})/e',
|
|
"preg_replace('/(.{" . $modSettings['fixLongWords'] . "})/', '\\\$1$breaker', '\$1')",
|
|
$php_parts[$php_i]);
|
|
}
|
|
|
|
// Figure out smileys...
|
|
parsesmileys($php_parts[$php_i]);
|
|
|
|
// List items - warning they might disrupt your code...
|
|
if (empty($modSettings['disabledBBC']) || preg_match('~[\s,](list|li)[\s,]~', $modSettings['disabledBBC']) == 0)
|
|
{
|
|
$php_parts[$php_i] = strtr($php_parts[$php_i], $itemcode);
|
|
|
|
// Now do the [0], which is special and sometimes annoying.
|
|
$php_parts[$php_i] = preg_replace('~([ \t>]| )\[0\]~', '$1<li type="circle">', $php_parts[$php_i]);
|
|
}
|
|
else
|
|
$php_parts[$php_i] = str_replace(array_keys($itemcode), '<br />', $php_parts[$php_i]);
|
|
}
|
|
|
|
$parts[$i] = implode('', $php_parts);
|
|
}
|
|
// Add the Code: part.
|
|
elseif ($i <= count($parts) - 1)
|
|
{
|
|
$php_parts = preg_split('~(<\?php|\?>)~', $parts[$i], -1, PREG_SPLIT_DELIM_CAPTURE);
|
|
|
|
for ($php_i = 0, $php_n = count($php_parts); $php_i < $php_n; $php_i++)
|
|
{
|
|
// Do PHP code coloring?
|
|
if ($php_parts[$php_i] != '<?php')
|
|
continue;
|
|
|
|
$php_string = '';
|
|
while ($php_i + 1 < count($php_parts) && $php_parts[$php_i] != '?>')
|
|
{
|
|
$php_string .= $php_parts[$php_i];
|
|
$php_parts[$php_i++] = '';
|
|
}
|
|
$php_parts[$php_i] = highlight_php_code($php_string . $php_parts[$php_i]);
|
|
}
|
|
|
|
// Fix the PHP code stuff...
|
|
$parts[$i] = str_replace("<pre style=\"display: inline;\">\t</pre>", "\t", implode('', $php_parts));
|
|
|
|
// Older browsers are annoying, aren't they?
|
|
if ($context['browser']['is_ie4'] || $context['browser']['is_ie5'] || $context['browser']['is_ie5.5'])
|
|
$parts[$i] = str_replace("\t", "<pre style=\"display: inline;\">\t</pre>", $parts[$i]);
|
|
else
|
|
$parts[$i] = str_replace("\t", "<span style=\"white-space: pre;\">\t</span>", $parts[$i]);
|
|
|
|
$parts[$i] = '<div class="codeheader">' . $txt['smf238'] . ':</div><div class="code">' . $parts[$i];
|
|
}
|
|
}
|
|
$message = substr(implode('', $parts), 1);
|
|
|
|
// Fix things.
|
|
$message = strtr($message, array(' ' => ' ', "\r" => '', "\n" => '<br />'));
|
|
|
|
$message = preg_replace('~href="(https?://)((?!([-\w]+\.)*rock\.ru).*)"~iU', 'href="http://rock.ru/go/$1$2"', $message);
|
|
return $message;
|
|
}
|
|
|
|
// Parses the code in message, using the normal syntax used by some many forums...
|
|
function parsecode(&$message, $disabledBBC = '')
|
|
{
|
|
global $modSettings, $scripturl, $txt, $settings, $context;
|
|
static $codefromcache = array(), $codetocache = array();
|
|
|
|
// If it wasn't already set, set it.
|
|
if (empty($codefromcache))
|
|
{
|
|
// If any tags are disabled then we won't add them.
|
|
if (!empty($modSettings['disabledBBC']) OR !empty($disabledBBC))
|
|
{
|
|
$disabled = array_flip(array_merge(explode(',', $modSettings['disabledBBC']),explode(',', $disabledBBC)));
|
|
|
|
foreach ($disabled as $tag => $dummy)
|
|
$disabled[trim($tag)] = true;
|
|
}
|
|
|
|
$code_to_from = array(
|
|
// A named email address. [email=me@some.place.com]me[/email] And, you can't have []s in your email, I should know.
|
|
'~\[email=([^<">]+?)\](.+?)\[/email\]~ie' => isset($disabled['email']) ? '"$2 ($1)"' : '"<a href=\"mailto:" . strtr("$1", array("\"" => """, "]" => "", "[" => "")) . "\">" . preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[iurl.*?\]|\[/iurl\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\])~i", "", strtr("$2", array("@" => "@"))) . "</a>"',
|
|
// An image. Width and height can be are optional.
|
|
'~\[img(\s+width=([\d]+))?(\s+height=([\d]+))?\s*\](?:<br />)*([^<">]+?)(?:<br />)*\[/img\]~ie' => isset($disabled['img']) ? 'preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[iurl.*?\]|\[/iurl\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", strtr("$5", array("@" => "@")))' : '"<img src=\"" . preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[iurl.*?\]|\[/iurl\]|\[flash.*?\]|\[/flash\]\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", strtr("$5", array("@" => "@", "\"" => """))) . "\" alt=\"\"" . ("$2" != "" ? " width=\"$2\"" : "") . ("$4" != "" ? " height=\"$4\"" : "") . " border=\"0\" />"',
|
|
// Find an inside link. (named?) ie. [iurl]www.simplemachines.org[/iurl]
|
|
'~\[iurl=([^<">]+?)\](.+?)\[/iurl\]~ie' => isset($disabled['iurl']) ? (!isset($disabled['url']) ? '"<a href=\"" . preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[iurl.*?\]|\[/iurl\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", strtr("$1", array("\"" => """))) . "\" target=\"_blank\">" . preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[iurl.*?\]|\[flash.*?\]|\[/flash\]|\[/iurl\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", strtr("$2", array("@" => "@"))) . "</a>"' : 'preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[iurl.*?\]|\[/iurl\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", "$2") . " ($1)"') : '"<a href=\"" . preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[iurl.*?\]|\[/iurl\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", strtr("$1", array("\"" => """))) . "\">" . preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[iurl.*?\]|\[/iurl\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", strtr("$2", array("@" => "@"))) . "</a>"',
|
|
'~\[iurl\]([^<">]+?)\[/iurl\]~ie' => isset($disabled['iurl']) ? (!isset($disabled['url']) ? '"<a href=\"" . preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[iurl.*?\]|\[/iurl\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", strtr("$1", array( "\"" => """))) . "\" target=\"_blank\">$1</a>"' : '"$1"') : '"<a href=\"" . preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[iurl.*?\]|\[/iurl\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", strtr("$1", array("\"" => """))) . "\">$1</a>"',
|
|
// FTP link. Named...? [ftp=upload.sourceforge.net]Sourceforge[/ftp]
|
|
'~\[ftp\]([^<">]+?)\[/ftp\]~ie' => isset($disabled['ftp']) ? 'preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", "$1")' : '"<a href=\"" . preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", strtr("$1", array("\"" => """))) . "\" target=\"_blank\">" . preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", strtr("$1", array("@" => "@"))) . "</a>"',
|
|
'~\[ftp=([^<">]+?)\](.+?)\[/ftp\]~ie' => isset($disabled['ftp']) ? 'preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", "$2") . " ($1)"' : '"<a href=\"" . preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", strtr("$1", array("\"" => """))) . "\" target=\"_blank\">" . preg_replace("~(\[url.*?\]|\[/url\]|\[ftp.*?\]|\[/ftp\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", strtr("$2", array("@" => "@"))) . "</a>"',
|
|
// Find a (named?) URL... [url]www.simplemachines.org[/url] or [url=www.simplemachines.org]SMF[/url]
|
|
'~\[url=([^:\]<">]+?)\]([^\]]*?\[url(?:=[^\]<">]+?)?\][^<">]+?\[/url\].*?)\[/url\]~ie' => isset($disabled['url']) ? 'preg_replace("~(\[url.*?\]|\[/url\])~i", "", "$2") . " ($1)"' : '"<a href=\"" . preg_replace("~(\[url.*?\]|\[/url\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", strtr("$1", array("\"" => """))) . "\" target=\"_blank\">" . preg_replace("~(\[url.*?\]|\[/url\])~i", "", strtr("$2", array("@" => "@"))) . "</a>"',
|
|
'~\[url=([^<">]+?)\](.+?)\[/url\]~ie' => isset($disabled['url']) ? '"$2 ($1)"' : '"<a href=\"" . preg_replace("~(\[url.*?\]|\[/url\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", strtr("$1", array("\"" => """))) . "\" target=\"_blank\">" . strtr("$2", array("@" => "@")) . "</a>"',
|
|
'~\[url\](?:<br />)*([^<">]+?)(?:<br />)*\[/url\]~ie' => isset($disabled['url']) ? '"$1"' : '"<a href=\"" . preg_replace("~(\[url.*?\]|\[/url\]|\[flash.*?\]|\[/flash\]|\[img.*?\]|\[/img\]|\[email.*?\]|\[/email\])~i", "", strtr("$1", array("\"" => """))) . "\" target=\"_blank\">$1</a>"',
|
|
// Bold, italics, underline, strikeout.
|
|
'~\[b\](.+?)\[/b\]~i' => isset($disabled['b']) ? '$1' : '<strong>$1</strong>',
|
|
'~\[i\](.+?)\[/i\]~i' => isset($disabled['i']) ? '$1' : '<em>$1</em>',
|
|
'~\[u\](.+?)\[/u\]~i' => isset($disabled['u']) ? '$1' : '<span style="text-decoration: underline;">$1</span>',
|
|
'~\[s\](.+?)\[/s\]~i' => isset($disabled['s']) ? '$1' : '<del>$1</del>',
|
|
// A quote. May or may not specify an author and/or link and date.
|
|
'~\[quote(?: author)?="(.{1,80}?)"\](?:<br />)?~i' => isset($disabled['quote']) ? '<div>' : '<div class="quoteheader">' . $txt['smf239'] . ': $1</div><blockquote class="quote">',
|
|
'~\[quote author=(.{1,80}?) link=(?:board=\d+;)?((?:topic|threadid)=[\dmsg#\./]{1,40}(?:;start=[\dmsg#\./]{1,40})?) date=(\d+)\](?:<br />)?~ei' => isset($disabled['quote']) ? '\'<div>\'' : '\'<div class="quoteheader"><a href="' . $scripturl . '?$2">' . $txt['smf239'] . '</a> <span style="font-weight:normal;">(<span class="b">$1</span> \' . timeformat(\'$3\') . \')</span></div><blockquote class="quote">\'',
|
|
'~\[quote author=(.{1,80}?)\](?:<br />)?~i' => isset($disabled['quote']) ? '<div>' : '<div class="quoteheader">' . $txt['smf239'] . ': $1</div><blockquote class="quote">',
|
|
'~\[quote\](?:<br />)?~i' => isset($disabled['quote']) ? '<div>' : '<div class="quoteheader">' . $txt['smf240'] . '</div><blockquote class="quote">',
|
|
'~\[/quote\](?:<br />)?~i' => isset($disabled['quote']) ? '</div>' : '</blockquote>',
|
|
// Size the font. [size=large]HELLO![/size]
|
|
'~\[size=([\d]{1,2}p[xt]|(?:x-)?small(?:er)?|(?:x-)?large[r]?)\](.+?)\[/size\]~i' => isset($disabled['size']) ? '$2' : '<span style="font-size: $1;">$2</span>',
|
|
'~\[size=([\d])\](.+?)\[/size\]~i' => isset($disabled['size']) ? '$2' : '<font size="$1">$2</font>',
|
|
// Performat/justify text. [center]Justifying is good.[/center]
|
|
'~\[pre\](.+?)\[/pre\]~i' => isset($disabled['pre']) ? '$1' : '<pre>$1</pre>',
|
|
'~\[left\](.+?)\[/left\]~i' => isset($disabled['left']) ? '$1' : '<div align="left">$1</div>',
|
|
'~\[right\](.+?)\[/right\]~i' => isset($disabled['right']) ? '$1' : '<div align="right">$1</div>',
|
|
'~\[center\](.+?)\[/center\]~i' => isset($disabled['center']) ? '$1' : '<span style="display: block; text-align: center;">$1</span>',
|
|
// Teletyped text. Monospace, in other words.
|
|
'~\[tt\](.+?)\[/tt\]~i' => isset($disabled['tt']) ? '$1' : '<tt>$1</tt>',
|
|
// Subscript and superscript. 6[sup]2[/sup] = 36.
|
|
'~\[sub\](.+?)\[/sub\]~i' => isset($disabled['sub']) ? '$1' : '<sub>$1</sub>',
|
|
'~\[sup\](.+?)\[/sup\]~i' => isset($disabled['sup']) ? '$1' : '<sup>$1</sup>',
|
|
// An email address. [email]me@some.place.com[/email]
|
|
'~\[email\](?:<br />)*(.+?)(?:<br />)*\[/email\]~ie' => isset($disabled['email']) ? '"$1"' : '"<a href=\"mailto:" . strtr("$1", array("\"" => """, "[" => "", "]" => "")) . "\">$1</a>"',
|
|
// Specify a specific font. [font=Comic Sans]Blah![/font]
|
|
'~\[font=([\w,\-\s]+?)\](.+?)\[/font\]~i' => isset($disabled['font']) ? '$2' : '<span style="font-family: $1;">$2</span>',
|
|
// Colors.... [red]See?[/red]
|
|
'~\[color=(#[\da-fA-F]{3}|#[\da-fA-F]{6}|[\w]{1,12})\](.*?)\[/color\]~i' => isset($disabled['color']) ? '$2' : '<span style="color: $1;">$2</span>',
|
|
'~\[(black|white|red|green|blue)\](.+?)\[/\1\]~i' => isset($disabled['color']) ? '$2' : '<span style="color: $1;">$2</span>',
|
|
'~\[(chr|k)issy\](.+?)\[/\1issy\]~i' => isset($disabled['color']) ? '$2' : '<span style="color: #CC0099;">$2 :-*</span>',
|
|
// Lists... [list][*]First, ...[o]Second![li]THIRD!!![/li][/list]
|
|
'~\[list\](?:<br />)?~i' => isset($disabled['list']) || isset($disabled['li']) ? '' : '<ul style="margin-top: 0; margin-bottom: 0;">',
|
|
'~\[/list\](?:<br />)?~i' => isset($disabled['list']) || isset($disabled['li']) ? '' : '</ul>',
|
|
'~(?:<br />| |\s)*\[li\](.+?)\[/li\](?:<br />| |\s)*~i' => isset($disabled['list']) || isset($disabled['li']) ? '<br />$1<br />' : '<li>$1</li>',
|
|
// Horizontal rule. [hr] => ------------------.
|
|
'~\[hr(?:\s*/)?\]~i' => isset($disabled['hr']) ? '' : '<hr />',
|
|
// A break. [br] or [br /]. (it makes no sense to disable this one :P.)
|
|
'~\[br(?:\s*/)?\]~i' => '<br />',
|
|
// Right-to-left and left-to-right strings.
|
|
'~\[(ltr|rtl)\](.+?)\[/\1\]~i' => isset($disabled['ltr']) || isset($disabled['rtl']) ? '$2' : '<div dir="$1">$2</div>',
|
|
// Acronyms and abbreviations... [acronym=Bulletin Board Code]BBC[/acronym]
|
|
'~\[abbr=((?:")?)(.+?)\\1\](.+?)\[/abbr\]~ie' => isset($disabled['abbr']) ? '"$3 ($2)"' : '"<abbr title=\"" . strtr("$2", array("\"" => """)) . "\">$3</abbr>"',
|
|
'~\[acronym=((?:")?)(.+?)\\1\](.+?)\[/acronym\]~ie' => isset($disabled['acronym']) ? '"$3 ($2)"' : '"<acronym title=\"" . strtr("$2", array("\"" => """)) . "\">$3</acronym>"',
|
|
// [me=Comment]does something[/me]
|
|
'~\[me=((?:")?)(.{1,80}?)\\1\](.+?)\[/me\](?:<br />)?~i' => isset($disabled['ftp']) ? '/me $3<br />' : '<div class="meaction">* $2 $3</div>',
|
|
// An email address they just typed in. Don't match if there's already a mailto: or = before it.
|
|
'~(?<=[\?\s\xA0[\]()*\\\;>]|^)([\w\-\.]{1,80}@[\w\-]+\.[\w\-\.]+[\w\-])(?=[?,\s\xA0\[\]()*\\\]|$|<br />| |>|<|"|'|\.(?:\.| |\s|$|<br />))~i' => '<a href="mailto:$1">$1</a>',
|
|
'~(?<=<br />)([\w\-\.]{1,80}@[\w\-]+\.[\w\-\.]+[\w\-])(?=[?\.,\s\xA0\[\]()*\\\]|$|<br />| |>|<|"|')~i' => '<a href="mailto:$1">$1</a>',
|
|
// This last one fixes spaces at the beginning of lines.
|
|
'~<br /> ~' => '<br /> ',
|
|
// Match a table... hopefully with everything in the right place.
|
|
'~\[table\](?:\s|\xA0|<br />| )*((?:\[tr\](?:\s|\xA0|<br />| )*\[td\]).*?(?:(?:\s|\xA0|<br />| )*\[/td\]\[/tr\])*)(?:\s|\xA0|<br />| )*\[/table\](?:\s|\xA0|<br />| )?~i' => '<table>$1</table>',
|
|
);
|
|
|
|
$codefromcache = array_keys($code_to_from);
|
|
$codetocache = array_values($code_to_from);
|
|
|
|
// GLOWING or /shadowed/ text.
|
|
$codefromcache[] = '~\[glow=([#\w]{3,12}),([012]\d{1,2}|\d{1,2})(,[^]]+)?\](.+?)\[/glow\]~i';
|
|
$codetocache[] = isset($disabled['glow']) ? '$4' : '<table border="0" cellpadding="0" cellspacing="0" style="display: inline; vertical-align: middle; font: inherit;"><tr><td style="filter: Glow(color=$1, strength=$2); font: inherit;">$4</td></tr></table> ';
|
|
$codefromcache[] = '~\[shadow=([#\w]{3,12}),(left|right|top|bottom|[0123]\d{0,2})\](.+?)\[/shadow\]~ei';
|
|
$codetocache[] = isset($disabled['shadow']) ? 'strtr(\'$3\', array(\'\\"\' => \'"\'))' : '\'<table border="0" cellpadding="0" cellspacing="0" style="display: inline; vertical-align: middle; font: inherit;"><tr><td style="filter: Shadow(color=$1, direction=\' . (isset($shadow_directions[\'$2\']) ? $shadow_directions[\'$2\'] : (int) \'$2\') . \'); font: inherit;">\' . strtr(\'$3\', array(\'\\"\' => \'"\')) . \'</td></tr></table> \'';
|
|
|
|
// Moving text... [move]stuff[/move]
|
|
$codefromcache[] = '~\[move\](.+?)\[/move\]~i';
|
|
$codetocache[] = isset($disabled['move']) ? '$1' : '<marquee>$1</marquee>';
|
|
|
|
// Handle flash.
|
|
$codefromcache[] = '~\[flash=(\d+),(\d+)\](?:<br />)*([^<>]+?)(?:<br />)*\[/flash\]~ie';
|
|
if (empty($modSettings['enableEmbeddedFlash']) || isset($disabled['flash']))
|
|
$codetocache[] = isset($disabled['url']) ? '"$3"' : '"<a href=\"" . strtr("$3", array("\"" => """)) . "\" target=\"_blank\">$3</a>"';
|
|
// Internet Explorer for Windows.
|
|
elseif ($context['browser']['is_ie'] && !$context['browser']['is_mac_ie'])
|
|
$codetocache[] = '"<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\"$1\" height=\"$2\"><param name=\"movie\" value=\"" . strtr("$3", array("\"" => """)) . "\" /><param name=\"play\" value=\"true\" /><param name=\"loop\" value=\"true\" /><param name=\"quality\" value=\"high\" /><param name=\"AllowScriptAccess\" value=\"never\" /><embed src=\"" . strtr("$3", array("\"" => """)) . "\" width=\"$1\" height=\"$2\" play=\"true\" loop=\"true\" quality=\"high\" AllowScriptAccess=\"never\" /><noembed><a href=\"" . strtr("$3", array("\"" => """)) . "\" target=\"_blank\">$3</a></noembed></object>"';
|
|
// Anything else.
|
|
else
|
|
$codetocache[] = '"<embed type=\"application/x-shockwave-flash\" src=\"" . strtr("$3", array("\"" => """)) . "\" width=\"$1\" height=\"$2\" play=\"true\" loop=\"true\" quality=\"high\" AllowScriptAccess=\"never\" /><noembed><a href=\"" . strtr("$3", array("\"" => """)) . "\" target=\"_blank\">$3</a></noembed>"';
|
|
}
|
|
|
|
// Nothing to parse... ?
|
|
if (!strstr($message, '[') && !strstr($message, '://') && !strstr($message, '@') && !strstr($message, '/me') && !strstr($message, '<'))
|
|
return;
|
|
|
|
$message = strtr($message, array('$' => '$'));
|
|
|
|
// Replace <a href="something">somewhere</a> with HTML.
|
|
if (!empty($modSettings['enablePostHTML']) && strstr($message, '<'))
|
|
{
|
|
$message = preg_replace('~<a\s+href=(?:")?(?:\[url\])?((?:http://|ftp:/\|https://|ftps://|mailto:).+?)(?:\[/url\])?(?:")?>(.+?)</a>~ie', '\'<a href="$1">\' . preg_replace(\'~(\[url.*?\]|\[/url\])~\', \'\', \'$2\') . \'</a>\'', $message);
|
|
|
|
// Do <img ... /> - with security... action= -> action-.
|
|
preg_match_all('~<img\s+src=(?:")?(?:\[url\])?((?:http://|ftp://|https://|ftps://).+?)(?:\[/url\])?(?:")?(?:\s+alt=(?:")?(.*?)(?:")?)?(?:\s?/)?>~i', $message, $matches, PREG_PATTERN_ORDER);
|
|
if (!empty($matches[0]))
|
|
{
|
|
$replaces = array();
|
|
foreach ($matches[1] as $match => $imgtag)
|
|
{
|
|
// No alt?
|
|
if (!isset($matches[2][$match]))
|
|
$matches[2][$match] = '';
|
|
|
|
// Remove action= from the URL - no funny business, now.
|
|
if ($imgtag != preg_replace('~action(=|%3d)(?!dlattach)~i', 'action-', $imgtag))
|
|
$replaces[$matches[0][$match]] = '<img src="' . preg_replace('~action(=|%3d)(?!dlattach)~i', 'action-', $imgtag) . '" alt="' . $matches[2][$match] . '" border="0" />';
|
|
|
|
// Check if the image is larger than allowed.
|
|
if (!empty($modSettings['maxwidth']) && !empty($modSettings['maxheight']))
|
|
{
|
|
list ($width, $height) = url_image_size($imgtag);
|
|
|
|
if ($width > $modSettings['maxwidth'] || $height > $modSettings['maxheight'])
|
|
{
|
|
if ($width > $modSettings['maxwidth'] && !empty($modSettings['maxwidth']))
|
|
{
|
|
$height = floor($modSettings['maxwidth'] / $width * $height);
|
|
$width = $modSettings['maxwidth'];
|
|
if ($height > $modSettings['maxheight'] && !empty($modSettings['maxheight']))
|
|
{
|
|
$width = floor($modSettings['maxheight'] / $height * $width);
|
|
$height = $modSettings['maxheight'];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ($height > $modSettings['maxheight'] && !empty($modSettings['maxheight']))
|
|
{
|
|
$width = floor($modSettings['maxheight'] / $height * $width);
|
|
$height = $modSettings['maxheight'];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set the new image tag.
|
|
$replaces[$matches[0][$match]] = '<img src="' . preg_replace('~action(=|%3d)(?!dlattach)~i', 'action-', $imgtag) . '" width="' . $width . '" height="' . $height . '" alt="' . $matches[2][$match] . '" border="0" />';
|
|
}
|
|
elseif (strpos($matches[0][$match], '[url]') !== false || substr($matches[0][$match], 0, 4) == '<')
|
|
$replaces[$matches[0][$match]] = '<img src="' . preg_replace('~action(=|%3d)(?!dlattach)~i', 'action-', $imgtag) . '" alt="' . $matches[2][$match] . '" border="0" />';
|
|
}
|
|
|
|
$message = strtr($message, $replaces);
|
|
}
|
|
}
|
|
|
|
// Do the code if necessary.
|
|
if (strstr($message, '[') || strstr($message, '://') || strstr($message, '@') || strstr($message, '/me'))
|
|
{
|
|
$shadow_directions = array('left' => '270', 'right' => '90', 'top' => '0', 'bottom' => '180');
|
|
|
|
$message = preg_replace($codefromcache, $codetocache, $message);
|
|
$message = preg_replace_callback('#\[video\](.+?)\[/video\]#', 'parseVideo', $message);
|
|
|
|
// Tables need to be done twice or they won't work properly.
|
|
if (strpos($message, '<table>') !== false)
|
|
{
|
|
for ($i = 0; $i < 2; $i++)
|
|
$message = preg_replace(
|
|
array(
|
|
'~((?:<table>|</tr>|\[/tr\])(?:\s|\xA0|<br />| )*(?:<tr>|\[tr\])|</td>|\[/td\])(?:\s|\xA0|<br />| )*\[td\](?:\s|\xA0|<br />| )*(.*?)(?:\s|\xA0|<br />| )*\[/td\](?:\s|\xA0|<br />| )*((?:</tr>|\[/tr\])(?:\s|\xA0|<br />| )*(?:<tr>|\[tr\]|</table>)|<td(?: valign="top")?>|\[td\])~i',
|
|
'~(<table>|</tr>|\[/tr\])(?:\s|\xA0|<br />| )*\[tr\](?:\s|\xA0|<br />| )*(.*?)(?:\s|\xA0|<br />| )*\[/tr\](?:\s|\xA0|<br />| )*(</table>|<tr>|\[tr\])~i'
|
|
),
|
|
array(
|
|
'$1<td valign="top">$2</td>$3',
|
|
'$1<tr>$2</tr>$3'
|
|
), $message
|
|
);
|
|
}
|
|
}
|
|
|
|
// Enable Basic HTML?
|
|
if (!empty($modSettings['enablePostHTML']) && strstr($message, '<'))
|
|
{
|
|
// b, u, i, s, pre... basic tags.
|
|
$closable_tags = array('b', 'u', 'i', 's', 'pre', 'blockquote');
|
|
foreach ($closable_tags as $tag)
|
|
{
|
|
$opens = substr_count($message, '<' . $tag . '>');
|
|
$closes = substr_count($message, '</' . $tag . '>');
|
|
$message = str_replace(array('<' . $tag . '>', '</' . $tag . '>'), array('<' . $tag . '>', '</' . $tag . '>'), $message);
|
|
|
|
if ($closes < $opens)
|
|
$message .= str_repeat('</' . $tag . '>', $opens - $closes);
|
|
}
|
|
|
|
// <br /> should be empty.
|
|
$empty_tags = array('br');
|
|
foreach ($empty_tags as $tag)
|
|
$message = str_replace(array('<' . $tag . '>', '<' . $tag . '/>', '<' . $tag . ' />'), '<' . $tag . ' />', $message);
|
|
}
|
|
}
|
|
|
|
function parseVideo($matches) {
|
|
list ($url) = explode('#', $matches[1]);
|
|
|
|
// check if it's a vimeo video
|
|
if (preg_match('~^(https?://)?(www\.)?vimeo\.com/\d+?~', $url)) {
|
|
return parseVideoVimeo($url);
|
|
} elseif (preg_match('~^(https?://)?(www\.)?youtube\.com~', $url)) {
|
|
return parseVideoYoutube($url);
|
|
} elseif (preg_match('~^(https?://)?vids.myspace.com/~', $url)) {
|
|
return parseVideoMyspace($url);
|
|
} elseif (preg_match('~^(https?://)?(www\.)?dailymotion\.com/video/~', $url)) {
|
|
return parseVideoDailymotion($url);
|
|
} else {
|
|
return $matches[1];
|
|
}
|
|
}
|
|
|
|
function parseVideoMyspace($url)
|
|
{
|
|
$ttl = 3600;
|
|
$html = eaccelerator_get($url);
|
|
if ($html !== NULL) {
|
|
return $html;
|
|
}
|
|
$page = curl_get(htmlspecialchars_decode($url));
|
|
$matches = array ();
|
|
preg_match('~link type="text/xml\+oembed" href="(.+)"~imsU', $page, $matches);
|
|
if (! empty ($matches)) {
|
|
$xml_url = $matches[1];#.'&maxheight=360';
|
|
$html = getVideoOEmbed($xml_url);
|
|
} else {
|
|
$html = false;
|
|
}
|
|
|
|
if ($html == false) {
|
|
$html = '<a href="'.$url.'">Посмотреть видео</a>';
|
|
$ttl = 60;
|
|
}
|
|
eaccelerator_put($url, $html, $ttl);
|
|
return $html;
|
|
}
|
|
|
|
function parseVideoDailymotion($url)
|
|
{
|
|
$ttl = 3600;
|
|
$html = eaccelerator_get($url);
|
|
if ($html !== NULL) {
|
|
return $html;
|
|
}
|
|
$oembed_endpoint = 'http://www.dailymotion.com/api/oembed';
|
|
// Create the URLs
|
|
$xml_url = $oembed_endpoint.'?url='.rawurlencode($url).
|
|
'&format=xml';
|
|
$html = getVideoOEmbed($xml_url);
|
|
if ($html == false) {
|
|
$html = '<a href="'.$url.'">Посмотреть видео</a>';
|
|
$ttl = 60;
|
|
}
|
|
eaccelerator_put($url, $html, $ttl);
|
|
return $html;
|
|
}
|
|
|
|
function eaccelerator_get($param) {
|
|
return NULL;
|
|
}
|
|
|
|
function eaccelerator_put($param, $value) {
|
|
return NULL;
|
|
}
|
|
function parseVideoYoutube($url)
|
|
{
|
|
$ttl = 3600;
|
|
$html = eaccelerator_get($url);
|
|
if ($html !== NULL) {
|
|
return $html;
|
|
}
|
|
$oembed_endpoint = 'http://www.youtube.com/oembed';
|
|
$_q = array ();
|
|
$q = parse_url($url, PHP_URL_QUERY);
|
|
parse_str($q, $_q);
|
|
$theURL = "http://www.youtube.com/watch?".$q; #v=".$_q['v'];
|
|
// Create the URLs
|
|
$xml_url = $oembed_endpoint.'?url='.rawurlencode($theURL).
|
|
'&format=xml';
|
|
#&maxwidth=640&maxheight=360';
|
|
$html = getVideoOEmbed($xml_url);
|
|
if ($html == false) {
|
|
$html = '<a href="'.$theURL.'">Посмотреть видео</a>';
|
|
$ttl = 60;
|
|
}
|
|
eaccelerator_put($url, $html, $ttl);
|
|
return $html;
|
|
}
|
|
|
|
function parseVideoVimeo($url)
|
|
{
|
|
$ttl = 3600;
|
|
$html = eaccelerator_get($url);
|
|
if ($html !== NULL) {
|
|
return $html;
|
|
}
|
|
$oembed_endpoint = 'http://www.vimeo.com/api/oembed';
|
|
// Create the URLs
|
|
$xml_url = $oembed_endpoint.'.xml?url='.rawurlencode($url).
|
|
'&maxwidth=640&maxheight=360';
|
|
$html = getVideoOEmbed($xml_url);
|
|
if ($html == false) {
|
|
$html = '<a href="'.$url.'">Посмотреть видео</a>';
|
|
$ttl = 60;
|
|
}
|
|
eaccelerator_put($url, $html, $ttl);
|
|
return $html;
|
|
}
|
|
|
|
function getVideoOEmbed($xml_url)
|
|
{
|
|
// Load in the oEmbed XML
|
|
$xml = curl_get($xml_url);
|
|
if ($xml !== FALSE && $oembed = @simplexml_load_string($xml)) {
|
|
return html_entity_decode($oembed->html);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Curl helper function
|
|
function curl_get($url) {
|
|
$curl = curl_init($url);
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
|
curl_setopt($curl, CURLOPT_TIMEOUT, 5);
|
|
curl_setopt($curl, CURLOPT_FAILONERROR, 1);
|
|
$return = curl_exec($curl);
|
|
curl_close($curl);
|
|
return $return;
|
|
}
|
|
|
|
|
|
// Parse smileys in the passed message.
|
|
function parsesmileys(&$message)
|
|
{
|
|
global $modSettings, $db_prefix, $txt, $user_info;
|
|
static $smileyfromcache = array(), $smileytocache = array();
|
|
|
|
// If the smiley array hasn't been set, do it now.
|
|
if (empty($smileyfromcache) && $user_info['smiley_set'] != 'none')
|
|
{
|
|
// Use the default smileys if it is disabled. (better for "portability" of smileys.)
|
|
if (empty($modSettings['smiley_enable']))
|
|
{
|
|
$smileysfrom = array('>:D', ':D', '::)', '>:(', ':)', ';)', ';D', ':(', ':o', '8)', ':P', '???', ':-[', ':-X', ':-*', ':\'(', ':-\\', '^-^', 'O0', 'C:-)', '0:)');
|
|
$smileysto = array('evil.gif', 'cheesy.gif', 'rolleyes.gif', 'angry.gif', 'smiley.gif', 'wink.gif', 'grin.gif', 'sad.gif', 'shocked.gif', 'cool.gif', 'tongue.gif', 'huh.gif', 'embarassed.gif', 'lipsrsealed.gif', 'kiss.gif', 'cry.gif', 'undecided.gif', 'azn.gif', 'afro.gif', 'police.gif', 'angel.gif');
|
|
$smileysdescs = array('', $txt[289], $txt[450], $txt[288], $txt[287], $txt[292], $txt[293], $txt[291], $txt[294], $txt[295], $txt[451], $txt[296], $txt[526], $txt[527], $txt[529], $txt[530], $txt[528], '', '', '', '');
|
|
}
|
|
else
|
|
{
|
|
// Load the smileys in reverse order by length so they don't get parsed wrong.
|
|
$result = db_query("
|
|
SELECT code, filename, description
|
|
FROM {$db_prefix}smileys
|
|
ORDER BY LENGTH(code) DESC", __FILE__, __LINE__);
|
|
$smileysfrom = array();
|
|
$smileysto = array();
|
|
$smileysdescs = array();
|
|
while ($row = mysql_fetch_assoc($result))
|
|
{
|
|
$smileysfrom[] = $row['code'];
|
|
$smileysto[] = $row['filename'];
|
|
$smileysdescs[] = $row['description'];
|
|
}
|
|
mysql_free_result($result);
|
|
}
|
|
|
|
// This smiley regex makes sure it doesn't parse smileys within code tags (so [url=mailto:David@bla.com] doesn't parse the :D smiley)
|
|
for ($i = 0, $n = count($smileysfrom); $i < $n; $i++)
|
|
{
|
|
#$smileyfromcache[] = '/(?<=[>:\?\.\s\xA0[\]()*\\\;])(' . preg_quote($smileysfrom[$i], '/') . '|' . preg_quote(htmlspecialchars($smileysfrom[$i], ENT_QUOTES), '/') . ')(?=[^[:alpha:]0-9]|$)/';
|
|
$smileyfromcache[] = '/(' . preg_quote($smileysfrom[$i], '/') . '|' . preg_quote(htmlspecialchars($smileysfrom[$i], ENT_QUOTES), '/') . ')(?=[^[:alpha:]0-9]|$)/';
|
|
$smileytocache[] = '<img src="' . $modSettings['smileys_url'] . '/' . $user_info['smiley_set'] . '/' . $smileysto[$i] . '" alt="' . htmlspecialchars($smileysdescs[$i]) . '" border="0" />';
|
|
}
|
|
}
|
|
|
|
// Replace away! (do it twice just in case.)
|
|
$message = preg_replace($smileyfromcache, $smileytocache, $message);
|
|
}
|
|
|
|
// Highlight any code...
|
|
function highlight_php_code($code)
|
|
{
|
|
global $context;
|
|
|
|
// Remove special characters.
|
|
$code = un_htmlspecialchars(strtr($code, array('<br />' => "\n", "\t" => 'SMF_TAB();')));
|
|
|
|
$oldlevel = error_reporting(0);
|
|
|
|
// It's easier in 4.2.x+.
|
|
if ((float) PHP_VERSION < 4.2)
|
|
{
|
|
ob_start();
|
|
@highlight_string($code);
|
|
$buffer = str_replace(array("\n", "\r"), '', ob_get_contents());
|
|
ob_end_clean();
|
|
}
|
|
else
|
|
$buffer = str_replace(array("\n", "\r"), '', @highlight_string($code, true));
|
|
|
|
error_reporting($oldlevel);
|
|
|
|
// Yes, I know this is kludging it, but this is the best way to preserve tabs from PHP :P.
|
|
$buffer = preg_replace('~SMF_TAB(</(font|span)><(font color|span style)="[^"]*?">)?\(\);~', "<pre style=\"display: inline;\">\t</pre>", $buffer);
|
|
|
|
return strtr($buffer, array('\'' => ''', '<code>' => '', '</code>' => ''));
|
|
}
|
|
|
|
// Put this user in the online log.
|
|
function writeLog($force = false)
|
|
{
|
|
global $db_prefix, $ID_MEMBER, $user_info, $sc, $modSettings;
|
|
|
|
// Don't mark them as online more than every so often.
|
|
if (empty($_SESSION['log_time']) || $_SESSION['log_time'] < (time() - 8) || $force)
|
|
$_SESSION['log_time'] = time();
|
|
else
|
|
return;
|
|
|
|
if (!empty($modSettings['who_enabled']))
|
|
{
|
|
$serialized = $_GET + array('USER_AGENT' => $_SERVER['HTTP_USER_AGENT']);
|
|
unset($serialized['sesc']);
|
|
$serialized = addslashes(serialize($serialized));
|
|
}
|
|
else
|
|
$serialized = '';
|
|
|
|
// Guests use 0, members use their session ID.
|
|
$session_id = $user_info['is_guest'] ? 'ip' . $user_info['ip'] : session_id();
|
|
|
|
db_query("
|
|
DELETE FROM {$db_prefix}log_online
|
|
WHERE logTime < NOW() - INTERVAL " . ($modSettings['lastActive'] * 60) . " SECOND
|
|
OR session = '$session_id'" . (empty($ID_MEMBER) ? '' : " OR ID_MEMBER = $ID_MEMBER"), __FILE__, __LINE__);
|
|
db_query("
|
|
INSERT IGNORE INTO {$db_prefix}log_online
|
|
(session, ID_MEMBER, ip, url)
|
|
VALUES ('$session_id', $ID_MEMBER, IFNULL(INET_ATON('$user_info[ip]'), 0), '$serialized')", __FILE__, __LINE__);
|
|
|
|
// Well, they are online now.
|
|
if (empty($_SESSION['timeOnlineUpdated']))
|
|
$_SESSION['timeOnlineUpdated'] = time();
|
|
|
|
// Set their login time, if not already done within the last minute.
|
|
if (!empty($user_info['last_login']) && $user_info['last_login'] < time() - 60)
|
|
{
|
|
// Don't count longer than 15 minutes.
|
|
if (time() - $_SESSION['timeOnlineUpdated'] > 60 * 15)
|
|
$_SESSION['timeOnlineUpdated'] = time();
|
|
|
|
updateMemberData($ID_MEMBER, array('lastLogin' => time(), 'memberIP' => '\'' . $user_info['ip'] . '\'', 'totalTimeLoggedIn' => 'totalTimeLoggedIn + ' . (time() - $_SESSION['timeOnlineUpdated'])));
|
|
|
|
$user_info['total_time_logged_in'] += time() - $_SESSION['timeOnlineUpdated'];
|
|
$_SESSION['timeOnlineUpdated'] = time();
|
|
}
|
|
}
|
|
|
|
/* Make sure the browser doesn't come back and repost the form data.
|
|
Should be used whenever anything is posted. */
|
|
function redirectexit($setLocation = '', $add = true, $refresh = false)
|
|
{
|
|
global $scripturl, $modSettings;
|
|
|
|
// Add the scripturl on if needed.
|
|
if (WIRELESS)
|
|
{
|
|
if ($add)
|
|
$setLocation = $scripturl . '?' . $setLocation;
|
|
|
|
$char = strpos($setLocation, '?') === false ? '?' : ';';
|
|
|
|
if (strpos($setLocation, '#') ==! false)
|
|
$setLocation = strtr($setLocation, array('#' => $char . WIRELESS_PROTOCOL . '#'));
|
|
else
|
|
$setLocation .= $char . WIRELESS_PROTOCOL;
|
|
}
|
|
elseif ($add)
|
|
$setLocation = $scripturl . ($setLocation != '' ? '?' . $setLocation : '');
|
|
|
|
// Put the session ID in.
|
|
if (defined('SID') && SID != '')
|
|
$setLocation = preg_replace('/' . preg_quote($scripturl, '/') . '(?!\?' . preg_quote(SID, '/') . ')(\?)?/', $scripturl . '?' . SID . '&', $setLocation);
|
|
|
|
// Send the header only.
|
|
if (empty($modSettings['redirectMetaRefresh']))
|
|
{
|
|
// We send a Refresh header only in special cases because Location looks better. (and is quicker...)
|
|
if ($refresh)
|
|
header('Refresh: 0; URL=' . strtr($setLocation, array(' ' => '%20', ';' => '%3b')));
|
|
else
|
|
header('Location: ' . str_replace(' ', '%20', $setLocation));
|
|
}
|
|
else
|
|
{
|
|
echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="refresh" content="0;URL=', strtr($setLocation, array(' ' => '%20', ';' => '%3b')), '" />
|
|
</head>
|
|
<body style="font-family: Georgia, serif; font-size: 1.3em; margin-top: 20%; text-align: center; background-color: white;">
|
|
<a href="', str_replace(' ', '%20', $setLocation), '" style="color: black;">', $setLocation, '</a>
|
|
</body>
|
|
</html>';
|
|
}
|
|
|
|
obExit(false);
|
|
}
|
|
|
|
// Ends execution. Takes care of template loading and remembering the previous URL.
|
|
function obExit($do_header = null, $do_footer = null, $from_index = false)
|
|
{
|
|
global $context, $modSettings;
|
|
static $header_done = false;
|
|
|
|
// Clear out the stat cache.
|
|
trackStats();
|
|
|
|
if ($do_header === null)
|
|
$do_header = !$header_done;
|
|
if ($do_footer === null)
|
|
$do_footer = $do_header;
|
|
|
|
// Has the template/header been done yet?
|
|
if ($do_header)
|
|
{
|
|
// Start up the session URL fixer.
|
|
ob_start('ob_sessrewrite');
|
|
|
|
// Display the screen in the logical order.
|
|
template_header();
|
|
$header_done = true;
|
|
}
|
|
if ($do_footer)
|
|
{
|
|
// Just show the footer, then.
|
|
loadSubTemplate(isset($context['sub_template']) ? $context['sub_template'] : 'main');
|
|
template_footer();
|
|
|
|
// (since this is just debugging... it's okay that it's after </html>.)
|
|
db_debug_junk();
|
|
}
|
|
|
|
// Remember this URL in case someone doesn't like sending HTTP_REFERER.
|
|
$_SESSION['old_url'] = $_SERVER['REQUEST_URI'];
|
|
|
|
// For session check verfication.... don't switch browsers...
|
|
$_SESSION['USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];
|
|
|
|
// Don't exit if we're coming from index.php; that will pass through normally.
|
|
if (!$from_index || WIRELESS)
|
|
exit;
|
|
}
|
|
|
|
// Set up the administration sections.
|
|
function adminIndex($area)
|
|
{
|
|
global $txt, $context, $scripturl, $sc, $modSettings, $user_info, $settings;
|
|
|
|
// Load the language and templates....
|
|
loadLanguage('Admin');
|
|
loadTemplate('Admin');
|
|
|
|
// Admin area 'Forum Controls'.
|
|
$context['admin_areas']['forum'] = array(
|
|
'title' => $txt[427],
|
|
'areas' => array(
|
|
'index' => '<a href="' . $scripturl . '?action=admin">' . $txt[208] . '</a>',
|
|
'credits' => '<a href="' . $scripturl . '?action=admin;credits">' . $txt['support_credits_title'] . '</a>',
|
|
)
|
|
);
|
|
|
|
if (allowedTo('edit_news'))
|
|
$context['admin_areas']['forum']['areas']['edit_news'] = '<a href="' . $scripturl . '?action=editnews">' . $txt[7] . '</a>';
|
|
|
|
if (allowedTo('manage_boards'))
|
|
$context['admin_areas']['forum']['areas']['manage_boards'] = '<a href="' . $scripturl . '?action=manageboards">' . $txt[4] . '</a>';
|
|
|
|
if (allowedTo('admin_forum'))
|
|
$context['admin_areas']['forum']['areas']['manage_packages'] = '<a href="' . $scripturl . '?action=packages">' . $txt['package1'] . '</a>';
|
|
|
|
if (allowedTo('manage_attachments'))
|
|
$context['admin_areas']['forum']['areas']['manage_attachments'] = '<a href="' . $scripturl . '?action=manageattachments">' . $txt['smf201'] . '</a>';
|
|
|
|
// Admin area 'Forum Configuration'.
|
|
if (allowedTo(array('manage_smileys', 'admin_forum', 'moderate_forum')))
|
|
{
|
|
$context['admin_areas']['config'] = array(
|
|
'title' => $txt[428],
|
|
'areas' => array()
|
|
);
|
|
|
|
if (allowedTo('admin_forum'))
|
|
{
|
|
$context['admin_areas']['config']['areas']['edit_mods_settings'] = '<a href="' . $scripturl . '?action=modifyModSettings">' . $txt['modSettings_title'] . '</a>';
|
|
$context['admin_areas']['config']['areas']['edit_settings'] = '<a href="' . $scripturl . '?action=modsettings;sesc=' . $sc . '">' . $txt[222] . '</a>';
|
|
$context['admin_areas']['config']['areas']['edit_theme_settings'] = '<a href="' . $scripturl . '?action=theme;sa=settings;id=' . $settings['theme_id'] . ';sesc=' . $sc . '">' . $txt['theme_current_settings'] . '</a>';
|
|
$context['admin_areas']['config']['areas']['manage_themes'] = '<a href="' . $scripturl . '?action=theme;sa=admin;sesc=' . $sc . '">' . $txt['theme_admin'] . '</a>';
|
|
}
|
|
|
|
if (allowedTo('manage_smileys'))
|
|
$context['admin_areas']['config']['areas']['manage_smileys'] = '<a href="' . $scripturl . '?action=smileys">' . $txt['smileys_manage'] . '</a>';
|
|
|
|
if (allowedTo('moderate_forum'))
|
|
{
|
|
$context['admin_areas']['config']['areas']['edit_censored'] = '<a href="' . $scripturl . '?action=setcensor">' . $txt[135] . '</a>';
|
|
$context['admin_areas']['config']['areas']['edit_agreement'] = '<a href="' . $scripturl . '?action=editagreement">' . $txt['smf11'] . '</a>';
|
|
}
|
|
}
|
|
|
|
// Admin area 'Member Controls'.
|
|
if (allowedTo(array('moderate_forum', 'manage_membergroups', 'manage_bans', 'send_mail', 'manage_permissions')))
|
|
{
|
|
$context['admin_areas']['members'] = array(
|
|
'title' => $txt[426],
|
|
'areas' => array()
|
|
);
|
|
|
|
if (allowedTo('manage_membergroups'))
|
|
$context['admin_areas']['members']['areas']['edit_groups'] = '<a href="' . $scripturl . '?action=membergroups;">' . $txt[8] . '</a>';
|
|
|
|
if (allowedTo('manage_permissions'))
|
|
$context['admin_areas']['members']['areas']['edit_permissions'] = '<a href="' . $scripturl . '?action=permissions">' . $txt['edit_permissions'] . '</a>';
|
|
|
|
if (allowedTo('moderate_forum'))
|
|
{
|
|
$context['admin_areas']['members']['areas']['registration_center'] = '<a href="' . $scripturl . '?action=regcenter">' . (!empty($modSettings['registration_method']) && $modSettings['registration_method'] != 3 ? $txt['registration_center'] : $txt['registration_member']) . '</a>';
|
|
$context['admin_areas']['members']['areas']['view_members'] = '<a href="' . $scripturl . '?action=viewmembers">' . $txt[5] . '</a>';
|
|
$context['admin_areas']['members']['areas']['edit_reserved_names'] = '<a href="' . $scripturl . '?action=setreserve">' . $txt[207] . '</a>';
|
|
$context['admin_areas']['members']['areas']['warning_manager'] = '<a href="' . $scripturl . '?action=warnlist">' . $txt['visual_warning_management'] . '</a>';
|
|
$context['admin_areas']['members']['areas']['postmod_manager'] = '<a href="' . $scripturl . '?action=warnpmman">' . $txt['visual_postmod_manager'] . '</a>';
|
|
}
|
|
|
|
if (allowedTo('send_mail'))
|
|
$context['admin_areas']['members']['areas']['email_members'] = '<a href="' . $scripturl . '?action=mailing">' . $txt[6] . '</a>';
|
|
|
|
if (allowedTo('manage_bans'))
|
|
$context['admin_areas']['members']['areas']['ban_members'] = '<a href="' . $scripturl . '?action=ban">' . $txt['ban_title'] . '</a>';
|
|
}
|
|
|
|
// Admin area 'Maintenance Controls'.
|
|
if (allowedTo('admin_forum'))
|
|
{
|
|
$context['admin_areas']['maintenance'] = array(
|
|
'title' => $txt[501],
|
|
'areas' => array(
|
|
'maintain_forum' => '<a href="' . $scripturl . '?action=maintain">' . $txt['maintain_title'] . '</a>',
|
|
'view_errors' => '<a href="' . $scripturl . '?action=viewErrorLog">' . $txt['errlog1'] . '</a>'
|
|
)
|
|
);
|
|
|
|
if (!empty($modSettings['modlog_enabled']))
|
|
$context['admin_areas']['maintenance']['areas']['view_moderation_log'] = '<a href="' . $scripturl . '?action=modlog">' . $txt['modlog_view'] . '</a>';
|
|
}
|
|
|
|
// Make sure the administrator has a valid session...
|
|
validateSession();
|
|
|
|
// Figure out which one we're in now...
|
|
foreach ($context['admin_areas'] as $id => $section)
|
|
if (isset($section[$area]))
|
|
$context['admin_section'] = $id;
|
|
$context['admin_area'] = $area;
|
|
|
|
// obExit will know what to do!
|
|
$context['template_layers'][] = 'admin';
|
|
}
|
|
|
|
// Usage: logAction('remove', array('starter' => $ID_MEMBER_STARTED));
|
|
function logAction($action, $extra = array())
|
|
{
|
|
global $db_prefix, $ID_MEMBER, $modSettings, $user_info;
|
|
|
|
if (!empty($modSettings['modlog_enabled']))
|
|
{
|
|
db_query("
|
|
INSERT INTO {$db_prefix}log_actions
|
|
(logTime, ID_MEMBER, IP, action, extra)
|
|
VALUES (" . time() . ", $ID_MEMBER, '$user_info[ip]', '$action',
|
|
'" . addslashes(serialize($extra)) . "')", __FILE__, __LINE__);
|
|
|
|
return db_insert_id();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Track Statistics.
|
|
function trackStats($stats = array())
|
|
{
|
|
global $db_prefix, $modSettings;
|
|
static $cache_stats = array();
|
|
|
|
if (empty($modSettings['trackStats']))
|
|
return false;
|
|
if (!empty($stats))
|
|
return $cache_stats = array_merge($cache_stats, $stats);
|
|
elseif (empty($cache_stats))
|
|
return false;
|
|
|
|
$setStringUpdate = '';
|
|
foreach ($cache_stats as $field => $change)
|
|
{
|
|
$setStringUpdate .= '
|
|
' . $field . ' = ' . ($change === '+' ? $field . ' + 1' : $change) . ',';
|
|
|
|
if ($change === '+')
|
|
$cache_stats[$field] = 1;
|
|
}
|
|
|
|
$date = strftime('%Y%m%d', forum_time(false));
|
|
db_query("
|
|
UPDATE {$db_prefix}log_activity
|
|
SET" . substr($setStringUpdate, 0, -1) . "
|
|
WHERE date = $date
|
|
LIMIT 1", __FILE__, __LINE__);
|
|
if (db_affected_rows() == 0)
|
|
{
|
|
db_query("
|
|
INSERT IGNORE INTO {$db_prefix}log_activity
|
|
(date, " . implode(', ', array_keys($cache_stats)) . ")
|
|
VALUES ($date, " . implode(', ', $cache_stats) . ')', __FILE__, __LINE__);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Make sure the user isn't posting over and over again.
|
|
function spamProtection($error_type)
|
|
{
|
|
global $modSettings, $txt, $db_prefix, $user_info;
|
|
|
|
// Delete old entries... if you can moderate this board or this is login, override spamWaitTime with 2.
|
|
if ($error_type == 'spam' && !allowedTo('moderate_board'))
|
|
db_query("
|
|
DELETE FROM {$db_prefix}log_floodcontrol
|
|
WHERE logTime < " . (time() - $modSettings['spamWaitTime']), __FILE__, __LINE__);
|
|
else
|
|
db_query("
|
|
DELETE FROM {$db_prefix}log_floodcontrol
|
|
WHERE (logTime < " . (time() - 2) . " AND ip = '$user_info[ip]')
|
|
OR logTime < " . (time() - $modSettings['spamWaitTime']), __FILE__, __LINE__);
|
|
|
|
// Add a new entry, deleting the old if necessary.
|
|
db_query("
|
|
REPLACE INTO {$db_prefix}log_floodcontrol
|
|
(ip, logTime)
|
|
VALUES ('$user_info[ip]', " . time() . ")", __FILE__, __LINE__);
|
|
// If affected is 0 or 2, it was there already.
|
|
if (db_affected_rows() != 1)
|
|
{
|
|
// Spammer! You only have to wait a *few* seconds!
|
|
fatal_lang_error($error_type . 'WaitTime_broken', false, array($modSettings['spamWaitTime']));
|
|
return true;
|
|
}
|
|
|
|
// They haven't posted within the limit.
|
|
return false;
|
|
}
|
|
|
|
// Get the size of a specified image with better error handling.
|
|
function url_image_size($url)
|
|
{
|
|
// Get the host to pester...
|
|
preg_match('~^\w+://(.+?)/(.*)$~', $url, $match);
|
|
|
|
// Can't figure it out, just try the image size.
|
|
if ($url == '' || $url == 'http://' || $url == 'https://')
|
|
return false;
|
|
elseif (!isset($match[1]))
|
|
return @getimagesize($url);
|
|
|
|
// Try to connect to the server... give it one full second.
|
|
$temp = 0;
|
|
$fp = @fsockopen($match[1], 80, $temp, $temp, 1);
|
|
|
|
// Successful? Continue...
|
|
if ($fp != false)
|
|
{
|
|
// Send the HEAD request.
|
|
fwrite($fp, 'HEAD /' . $match[2] . ' HTTP/1.1' . "\r\n" . 'Connection: close' . "\r\n" . 'Host: ' . $match[1] . "\r\n\r\n");
|
|
// Read in the HTTP/1.1 or whatever.
|
|
$test = substr(fgets($fp, 11), -1);
|
|
fclose($fp);
|
|
|
|
// See if it returned a 404/403 or something.
|
|
if ($test < 4)
|
|
return @getimagesize($url);
|
|
}
|
|
|
|
// Didn't work.
|
|
return false;
|
|
}
|
|
|
|
function determineTopicClass(&$topic_context)
|
|
{
|
|
// Set topic class depending on locked status and number of replies.
|
|
if ($topic_context['is_very_hot'])
|
|
$topic_context['class'] = 'veryhot';
|
|
elseif ($topic_context['is_hot'])
|
|
$topic_context['class'] = 'hot';
|
|
else
|
|
$topic_context['class'] = 'normal';
|
|
|
|
$topic_context['class'] .= $topic_context['is_poll'] ? '_poll' : '_post';
|
|
|
|
if ($topic_context['is_locked'])
|
|
$topic_context['class'] .= '_locked';
|
|
|
|
if ($topic_context['is_sticky'])
|
|
$topic_context['class'] .= '_sticky';
|
|
|
|
// This is so old themes will still work.
|
|
$topic_context['extended_class'] = &$topic_context['class'];
|
|
}
|
|
|
|
// Sets up the basic theme context stuff.
|
|
function setupThemeContext()
|
|
{
|
|
global $modSettings, $user_info, $scripturl, $context, $settings, $options, $txt, $maintenance;
|
|
global $db_prefix; // Grudge's Mod
|
|
|
|
// Get some news...
|
|
$context['news_lines'] = explode("\n", str_replace("\r", '', trim(addslashes($modSettings['news']))));
|
|
$context['fader_news_lines'] = array();
|
|
for ($i = 0, $n = count($context['news_lines']); $i < $n; $i++)
|
|
{
|
|
if (trim($context['news_lines'][$i]) == '')
|
|
continue;
|
|
|
|
// Clean it up for presentation ;).
|
|
$context['news_lines'][$i] = doUBBC(stripslashes(trim($context['news_lines'][$i])));
|
|
|
|
// Gotta be special for the javascript.
|
|
$context['fader_news_lines'][$i] = strtr(addslashes($context['news_lines'][$i]), array('/' => '\/', '<a href=' => '<a hre" + "f='));
|
|
}
|
|
$context['random_news_line'] = $context['news_lines'][rand(0, count($context['news_lines']) - 1)];
|
|
|
|
if (!$user_info['is_guest'])
|
|
{
|
|
$context['user']['messages'] = &$user_info['messages'];
|
|
$context['user']['unread_messages'] = &$user_info['unread_messages'];
|
|
if (allowedTo('visual_approve_any'))
|
|
{
|
|
$result = db_query("
|
|
SELECT COUNT(*)
|
|
FROM {$db_prefix}postmoderation", __FILE__, __LINE__);
|
|
list($modmsg) = mysql_fetch_row($result);
|
|
if ($modmsg)
|
|
$context['user']['awaiting_mod'] = $modmsg . ' ' . $txt['visual_require_mod'];
|
|
}
|
|
|
|
// Personal message popup...
|
|
if ($user_info['unread_messages'] > (isset($_SESSION['unread_messages']) ? $_SESSION['unread_messages'] : 0))
|
|
$context['user']['popup_messages'] = true;
|
|
else
|
|
$context['user']['popup_messages'] = false;
|
|
$_SESSION['unread_messages'] = $user_info['unread_messages'];
|
|
|
|
if (allowedTo('moderate_forum'))
|
|
$context['unapproved_members'] = !empty($modSettings['registration_method']) && $modSettings['registration_method'] == 2 ? $modSettings['unapprovedMembers'] : 0;
|
|
|
|
$context['user']['avatar'] = array();
|
|
|
|
// Figure out the avatar... uploaded?
|
|
if ($user_info['avatar']['url'] == '')
|
|
{
|
|
// If they are allowed to use an uploaded avatar.
|
|
if (!empty($user_info['avatar']['ID_ATTACH']) && !empty($modSettings['avatar_allow_upload']))
|
|
{
|
|
$__avatar = glob('attachments/avatar_'.$context['user']['id'].'.{jpg,png,gif}', GLOB_BRACE);
|
|
if (!empty($__avatar)) $__avatar = $__avatar[0];
|
|
$context['user']['avatar']['href'] = 'http://img.rock.ru/forum/'.$__avatar;
|
|
}
|
|
}
|
|
// Full URL?
|
|
elseif (substr($user_info['avatar']['url'], 0, 7) == 'http://' && !empty($modSettings['avatar_allow_external_url']))
|
|
{
|
|
$context['user']['avatar']['href'] = $user_info['avatar']['url'];
|
|
if ($modSettings['avatar_action_too_large'] == 'option_html_resize')
|
|
{
|
|
if (!empty($modSettings['avatar_max_width_external']))
|
|
$context['user']['avatar']['width'] = $modSettings['avatar_max_width_external'];
|
|
if (!empty($modSettings['avatar_max_height_external']))
|
|
$context['user']['avatar']['height'] = $modSettings['avatar_max_height_external'];
|
|
}
|
|
}
|
|
// Server stored?
|
|
elseif (!empty($modSettings['avatar_allow_server_stored']))
|
|
$context['user']['avatar']['href'] = $modSettings['avatar_url'] . '/' . htmlspecialchars($user_info['avatar']['url']);
|
|
|
|
if (!empty($context['user']['avatar']))
|
|
$context['user']['avatar']['image'] = '<img src="' . $context['user']['avatar']['href'] . '"' . (isset($context['user']['avatar']['width']) ? ' width="' . $context['user']['avatar']['width'] . '"' : '') . (isset($context['user']['avatar']['height']) ? ' height="' . $context['user']['avatar']['height'] . '"' : '') . ' alt="" border="0" />';
|
|
|
|
// Figure out how long they've been logged in.
|
|
$context['user']['total_time_logged_in'] = array(
|
|
'days' => floor($user_info['total_time_logged_in'] / 86400),
|
|
'hours' => floor(($user_info['total_time_logged_in'] % 86400) / 3600),
|
|
'minutes' => floor(($user_info['total_time_logged_in'] % 3600) / 60)
|
|
);
|
|
}
|
|
else
|
|
{
|
|
$context['user']['messages'] = 0;
|
|
$context['user']['unread_messages'] = 0;
|
|
$context['user']['avatar'] = array();
|
|
$context['user']['total_time_logged_in'] = array('days' => 0, 'hours' => 0, 'minutes' => 0);
|
|
$context['user']['popup_messages'] = false;
|
|
|
|
if (!empty($modSettings['registration_method']) && $modSettings['registration_method'] == 1)
|
|
$txt['welcome_guest'] .= $txt['welcome_guest_activate'];
|
|
}
|
|
|
|
// Set up the menu privileges.
|
|
$context['allow_search'] = allowedTo('search_posts');
|
|
$context['allow_admin'] = allowedTo(array('admin_forum', 'manage_boards', 'manage_permissions', 'moderate_forum', 'manage_membergroups', 'manage_bans', 'send_mail', 'edit_news', 'manage_attachments', 'manage_smileys'));
|
|
$context['allow_edit_profile'] = !$user_info['is_guest'] && allowedTo(array('profile_view_own', 'profile_view_any', 'profile_identity_own', 'profile_identity_any', 'profile_extra_own', 'profile_extra_any', 'profile_remove_own', 'profile_remove_any', 'moderate_forum', 'manage_membergroups'));
|
|
$context['allow_calendar'] = allowedTo('calendar_view') && !empty($modSettings['cal_enabled']);
|
|
|
|
$context['allow_pm'] = allowedTo('pm_read');
|
|
|
|
$context['in_maintenance'] = !empty($maintenance);
|
|
$context['current_time'] = timeformat(time(), false);
|
|
$context['show_vBlogin'] = !empty($modSettings['enableVBStyleLogin']) && $user_info['is_guest'];
|
|
|
|
// This is here because old index templates might still use it.
|
|
$context['show_news'] = !empty($settings['enable_news']);
|
|
|
|
// This is done to make it easier to add to all themes...
|
|
if ($context['user']['popup_messages'] && !empty($options['popup_messages']))
|
|
{
|
|
$context['html_headers'] .= '
|
|
<script language="JavaScript" type="text/javascript"><!--
|
|
if (confirm("' . $txt['show_personal_messages'] . '"))
|
|
window.open("' . $scripturl . '?action=pm");
|
|
// --></script>';
|
|
}
|
|
|
|
if (!isset($context['page_title']))
|
|
$context['page_title'] = '';
|
|
}
|
|
|
|
// This is the only template included in the sources...
|
|
function template_rawdata()
|
|
{
|
|
global $context;
|
|
|
|
echo $context['raw_data'];
|
|
}
|
|
|
|
function template_header()
|
|
{
|
|
global $txt, $modSettings, $context, $settings, $user_info;
|
|
|
|
setupThemeContext();
|
|
|
|
// Print stuff to prevent caching of pages.
|
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
|
|
|
foreach ($context['template_layers'] as $layer)
|
|
{
|
|
loadSubTemplate($layer . '_above', true);
|
|
|
|
// May seem contrived, but this is done in case the main layer isn't there...
|
|
if ($layer == 'main' && allowedTo('admin_forum'))
|
|
{
|
|
$securityFiles = array('install.php', 'upgrade.php', 'repair_paths.php', 'repair_settings.php');
|
|
foreach ($securityFiles as $i => $securityFile)
|
|
{
|
|
if (!file_exists($securityFile))
|
|
unset($securityFiles[$i]);
|
|
}
|
|
|
|
if (!empty($securityFiles))
|
|
{
|
|
echo '
|
|
<div class="windowbg" style="margin: 2ex; padding: 2ex; border: 2px dashed red; color: red;">
|
|
<span style="text-decoration: underline;">', $txt['smf299'], '</span>
|
|
<div style="padding-left: 4ex;">';
|
|
|
|
foreach ($securityFiles as $securityFile)
|
|
echo '
|
|
', $txt['smf300'], $securityFile, '!<br />';
|
|
|
|
echo '
|
|
</div>
|
|
</div>';
|
|
}
|
|
}
|
|
// If the user is banned from posting inform them of it.
|
|
elseif ($layer == 'main' && !empty($_SESSION['ban']['cannot_post']['is_banned']))
|
|
{
|
|
echo '
|
|
<div class="windowbg" style="margin: 2ex; padding: 2ex; border: 2px dashed red; color: red;">
|
|
', sprintf($txt['you_are_post_banned'], $user_info['is_guest'] ? $txt[28] : $user_info['name']);
|
|
|
|
// The substr here is used to get rid of the first of two <br />s.
|
|
if (isset($_SESSION['ban']['cannot_post']['reason']))
|
|
echo '
|
|
<div style="padding-left: 4ex;">', substr($_SESSION['ban']['cannot_post']['reason'], 6), '</div>';
|
|
|
|
echo '
|
|
</div>';
|
|
}
|
|
}
|
|
|
|
if (isset($settings['use_default_images']) && $settings['use_default_images'] == 'defaults' && isset($settings['default_template']))
|
|
{
|
|
$settings['theme_url'] = $settings['default_theme_url'];
|
|
$settings['images_url'] = $settings['default_images_url'];
|
|
$settings['theme_dir'] = $settings['default_theme_dir'];
|
|
}
|
|
}
|
|
|
|
// Show the copyright...
|
|
function theme_copyright($get_it = false)
|
|
{
|
|
global $forum_copyright, $context, $boardurl, $forum_version, $txt;
|
|
static $found = false;
|
|
|
|
// Meaning, this is the footer checking in..
|
|
if ($get_it === true)
|
|
return $found;
|
|
|
|
echo '
|
|
<span class="smalltext" style="display: inline; visibility: visible; font-family: Verdana, Arial, sans-serif;">';
|
|
|
|
if ($get_it == 'none')
|
|
{
|
|
$found = true;
|
|
echo '
|
|
The administrator doesn\'t want a copyright notice saying this is copyright 2001-2005 by <a href="http://www.lewismedia.com/" target="_blank">Lewis Media</a>, and named <a href="http://www.simplemachines.org/">SMF</a>, so the forum will honor this request.';
|
|
}
|
|
// If it's in the copyright, and we are outputting it... it's been found.
|
|
elseif ((strpos($forum_copyright, '<a href="http://www.simplemachines.org/" onclick="this.href += \'referer.php?forum=' . urlencode($context['forum_name'] . '|' . $boardurl . '|' . $forum_version) . '\';" target="_blank">SMF') !== false || strpos($forum_copyright, '<a href="http://www.simplemachines.org/" target="_blank">SMF') !== false || strpos($forum_copyright, '<a href="http://www.simplemachines.org/" title="Simple Machines Forum" target="_blank">SMF') !== false) && (strpos($forum_copyright, '<a href="http://www.lewismedia.com/">Lewis Media</a>') !== false || strpos($forum_copyright, '<a href="http://www.lewismedia.com/" target="_blank">Lewis Media</a>') !== false))
|
|
{
|
|
$found = true;
|
|
echo $forum_copyright;
|
|
}
|
|
|
|
echo '
|
|
</span>';
|
|
}
|
|
|
|
function template_footer()
|
|
{
|
|
global $context, $settings, $modSettings, $time_start, $db_count;
|
|
|
|
// Show the load time? (only makes sense for the footer.)
|
|
$context['show_load_time'] = $modSettings['timeLoadPageEnable'] == 1;
|
|
$time_start = explode(' ', $time_start);
|
|
$time_end = explode(' ', microtime());
|
|
$context['load_time'] = round($time_end[0] + $time_end[1] - $time_start[0] - $time_start[1], 3);
|
|
$context['load_queries'] = $db_count;
|
|
|
|
if (isset($settings['use_default_images']) && $settings['use_default_images'] == 'defaults' && isset($settings['default_template']))
|
|
{
|
|
$settings['theme_url'] = $settings['actual_theme_url'];
|
|
$settings['images_url'] = $settings['actual_images_url'];
|
|
$settings['theme_dir'] = $settings['actual_theme_dir'];
|
|
}
|
|
|
|
foreach (array_reverse($context['template_layers']) as $layer)
|
|
loadSubTemplate($layer . '_below', true);
|
|
|
|
// Do not remove hard-coded text - it's in here so users cannot change the text easily. (as if it were in language file)
|
|
if (!theme_copyright(true) && !empty($context['template_layers']) && SMF !== 'SSI' && !WIRELESS)
|
|
{
|
|
echo '
|
|
<div align="center" style="display: block !important; visibility: visible !important; font-size: xx-large !important; font-weight: bold; color: black !important; background-color: white !important;">
|
|
Sorry, the copyright must be in the template.<br />
|
|
Please notify this ' . "forum's" . ' administrator that this site is using an <span style="color: #FF0000;">ILLEGAL</span> copy of <a href="http://www.simplemachines.org/" style="color: black !important; font-size: xx-large !important;">SMF</a>!
|
|
</div>';
|
|
|
|
log_error('Copyright removed!!');
|
|
}
|
|
}
|
|
|
|
// Debugging.
|
|
function db_debug_junk()
|
|
{
|
|
global $db_cache, $db_count, $context, $scripturl;
|
|
|
|
// Add to Settings.php if you want to show the debugging information.
|
|
if (!isset($GLOBALS['db_show_debug']) || $GLOBALS['db_show_debug'] !== true || (isset($_GET['action']) && $_GET['action'] == 'viewquery'))
|
|
return;
|
|
|
|
if (empty($_SESSION['view_queries']))
|
|
$_SESSION['view_queries'] = 0;
|
|
|
|
$_SESSION['debug'] = $db_cache;
|
|
echo '
|
|
<div align="left" class="smalltext">', (isset($context['template']) ? '
|
|
Template: <i>' . $context['template'] . '</i>' . (isset($context['sub_template']) ? ' (<i>' . $context['sub_template'] . '</i>)' : '') . '.<br />' : ''), '
|
|
<a href="', $scripturl, '?action=viewquery" target="_blank">Queries used: ', $db_count, '</a>.<br />
|
|
<br />';
|
|
|
|
if ($_SESSION['view_queries'] == 1)
|
|
foreach ($db_cache as $q => $qq)
|
|
echo '
|
|
', substr(trim($qq['q']), 0, 6) == 'SELECT' ? '<a class="b" href="' . $scripturl . '?action=viewquery;qq=' . ($q + 1) . '#qq' . $q . '" target="_blank">' : '', nl2br(str_replace("\t", ' ', ltrim($qq['q'], "\n\r"))) . '</a> in <em>' . $qq['f'] . '</em> line <em>' . $qq['l'] . '</em>, which took ' . $qq['t'] . ' seconds.<br />
|
|
<br />';
|
|
|
|
echo '
|
|
<a href="' . $scripturl . '?action=viewquery;sa=hide">[' . (empty($_SESSION['view_queries']) ? 'show' : 'hide') . ' queries]</a>
|
|
</div>';
|
|
}
|
|
|
|
// Get an attachment's encrypted filename. If $new is true, won't check for file existence.
|
|
function getAttachmentFilename($filename, $attachment_id, $new = false)
|
|
{
|
|
global $modSettings;
|
|
|
|
// Remove special accented characters - ie. s?.
|
|
$clean_name = strtr($filename, '????????????????????????????????????????????????????????????', 'SZszYAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy');
|
|
$clean_name = strtr($clean_name, array('?' => 'TH', '?' => 'th', '?' => 'DH', '?' => 'dh', '?' => 'ss', '?' => 'OE', '?' => 'oe', '?' => 'AE', '?' => 'ae', '?' => 'u'));
|
|
|
|
// Sorry, no spaces, dots, or anything else but letters allowed.
|
|
$clean_name = preg_replace(array('/\s/', '/[^\w_\.\-]/'), array('_', ''), $clean_name);
|
|
|
|
$enc_name = $attachment_id . '_' . str_replace('.', '_', $clean_name) . md5($clean_name);
|
|
$clean_name = preg_replace('~\.[\.]+~', '.', $clean_name);
|
|
|
|
if ($attachment_id == false || ($new && empty($modSettings['attachmentEncryptFilenames'])))
|
|
return $clean_name;
|
|
elseif ($new)
|
|
return $enc_name;
|
|
|
|
if (file_exists($modSettings['attachmentUploadDir'] . '/' . $enc_name))
|
|
$filename = $modSettings['attachmentUploadDir'] . '/' . $enc_name;
|
|
else
|
|
$filename = $modSettings['attachmentUploadDir'] . '/' . $clean_name;
|
|
|
|
return $filename;
|
|
}
|
|
|
|
function getThumbnailFilename($filename, $attachment_id, $new = false)
|
|
{
|
|
global $modSettings;
|
|
/*
|
|
// Remove special accented characters - ie. s?.
|
|
$clean_name = strtr($filename, '????????????????????????????????????????????????????????????', 'SZszYAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy');
|
|
$clean_name = strtr($clean_name, array('?' => 'TH', '?' => 'th', '?' => 'DH', '?' => 'dh', '?' => 'ss', '?' => 'OE', '?' => 'oe', '?' => 'AE', '?' => 'ae', '?' => 'u'));
|
|
|
|
// Sorry, no spaces, dots, or anything else but letters allowed.
|
|
$clean_name = preg_replace(array('/\s/', '/[^\w_\.\-]/'), array('_', ''), $clean_name);
|
|
|
|
$enc_name = $attachment_id . '_' . str_replace('.', '_', $clean_name) . md5($clean_name);
|
|
$clean_name = preg_replace('~\.[\.]+~', '.', $clean_name);
|
|
|
|
if ($attachment_id == false || ($new && empty($modSettings['attachmentEncryptFilenames'])))
|
|
return $clean_name;
|
|
elseif ($new)
|
|
return $enc_name;
|
|
|
|
if (file_exists($modSettings['attachmentUploadDir'] . '/thumbs/' . $enc_name))
|
|
$filename = $modSettings['attachmentUploadDir'] . '/thumbs/' . $enc_name;
|
|
else
|
|
$filename = $modSettings['attachmentUploadDir'] . '/thumbs/' . $clean_name;
|
|
|
|
return $filename;*/
|
|
return $modSettings['attachmentUploadDir']."/thumbs/".$attachment_id.md5($filename);
|
|
}
|
|
|
|
function ob_googlebot_getAgent( &$user_agent, &$user_name, &$result, $guest )
|
|
{
|
|
//Search Spiders
|
|
$spider_agents = array (
|
|
array (
|
|
'agent' => 'WISENutbot',
|
|
'spidername' => 'Looksmart spider',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'MSNBot',
|
|
'spidername' => 'MSN spider',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'W3C_Validator',
|
|
'spidername' => 'W3C Validator',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'Googlebot-Image',
|
|
'spidername' => 'Google-Image Spider',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'Googlebot',
|
|
'spidername' => 'Google spider',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'Mediapartners-Google',
|
|
'spidername' => 'Google AdSense spider',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'Scooter',
|
|
'spidername' => 'Altavista spider',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'Yahoo! Slurp',
|
|
'spidername' => 'Yahoo spider',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'Yandex',
|
|
'spidername' => 'YandexBot',
|
|
'spider' => true
|
|
),
|
|
array (
|
|
'agent' => 'Rambler',
|
|
'spidername' => 'RamblerBot',
|
|
'spider' => true
|
|
),
|
|
array (
|
|
'agent' => 'FAST-WebCrawler',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'Wget',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'Ask Jeeves',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'Speedy Spider',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'SurveyBot',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'IBM_Planetwide',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'GigaBot',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'ia_archiver',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'FAST-WebCrawler',
|
|
'spider' => true,
|
|
),
|
|
array (
|
|
'agent' => 'Inktomi Slurp',
|
|
'spider' => true,
|
|
),
|
|
);
|
|
|
|
foreach( $spider_agents as $poss )
|
|
if (strpos(strtolower($user_agent), strtolower($poss['agent'])) !== false)
|
|
{
|
|
if ( $guest && isset($poss['spider']) && $poss['spider'] )
|
|
$user_name = isset($poss['spidername']) ? $poss['spidername'] : (isset($poss['name']) ? $poss['name'] : $poss['agent']);
|
|
|
|
$result = isset($poss['name']) ? $poss['name'] : $poss['agent'];
|
|
return isset($poss['spider']) && $poss['spider'];
|
|
}
|
|
|
|
$result = $user_agent;
|
|
return false;
|
|
};
|
|
|
|
?>
|