mage_size($imgtag); if (!empty($modSettings['max_image_width']) && $width > $modSettings['max_image_width']) { $height = (int) (($modSettings['max_image_width'] * $height) / $width); $width = $modSettings['max_image_width']; } if (!empty($modSettings['max_image_height']) && $height > $modSettings['max_image_height']) { $width = (int) (($modSettings['max_image_height'] * $width) / $height); $height = $modSettings['max_image_height']; } // Set the new image tag. $replaces[$matches[0][$match]] = '' . $matches[2][$match] . ''; } else $replaces[$matches[0][$match]] = '' . $matches[2][$match] . ''; } $data = strtr($data, $replaces); } } if (!empty($modSettings['autoLinkUrls'])) { // Are we inside tags that should be auto linked? $no_autolink_area = false; if (!empty($open_tags)) { foreach ($open_tags as $open_tag) if (in_array($open_tag['tag'], $no_autolink_tags)) $no_autolink_area = true; } // Don't go backwards. //!!! Don't think is the real solution.... $lastAutoPos = isset($lastAutoPos) ? $lastAutoPos : 0; if ($pos < $lastAutoPos) $no_autolink_area = true; $lastAutoPos = $pos; if (!$no_autolink_area) { // Parse any URLs.... have to get rid of the @ problems some things cause... stupid email addresses. if (!isset($disabled['url']) && (strpos($data, '://') !== false || strpos($data, 'www.') !== false)) { // Switch out quotes really quick because they can cause problems. $data = strtr($data, array(''' => '\'', ' ' => $context['utf8'] ? "\xC2\xA0" : "\xA0", '"' => '>">', '"' => '<"<', '<' => '\.(;\'"]|^)((?: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]'), $data); $data = strtr($data, array('\'' => ''', $context['utf8'] ? "\xC2\xA0" : "\xA0" => ' ', '>">' => '"', '<"<' => '"', ' '<')); } // Next, emails... if (!isset($disabled['email']) && strpos($data, '@') !== false) { $data = preg_replace('~(?<=[\?\s' . $non_breaking_space . '\[\]()*\\\;>]|^)([\w\-\.]{1,80}@[\w\-]+\.[\w\-\.]+[\w\-])(?=[?,\s' . $non_breaking_space . '\[\]()*\\\]|$|
| |>|<|"|'|\.(?:\.|;| |\s|$|
))~' . ($context['utf8'] ? 'u' : ''), '[email]$1[/email]', $data); $data = preg_replace('~(?<=
)([\w\-\.]{1,80}@[\w\-]+\.[\w\-\.]+[\w\-])(?=[?\.,;\s' . $non_breaking_space . '\[\]()*\\\]|$|
| |>|<|"|')~' . ($context['utf8'] ? 'u' : ''), '[email]$1[/email]', $data); } } } $data = strtr($data, array("\t" => '   ')); if (!empty($modSettings['fixLongWords']) && $modSettings['fixLongWords'] > 5) { // This is SADLY and INCREDIBLY browser dependent. if ($context['browser']['is_gecko'] || $context['browser']['is_konqueror']) $breaker = ' '; // Opera... elseif ($context['browser']['is_opera']) $breaker = ' '; // Internet Explorer... else $breaker = ' '; // PCRE will not be happy if we don't give it a short. $modSettings['fixLongWords'] = (int) min(65535, $modSettings['fixLongWords']); // The idea is, find words xx long, and then replace them with xx + space + more. if (strlen($data) > $modSettings['fixLongWords']) { // This is done in a roundabout way because $breaker has "long words" :P. $data = strtr($data, array($breaker => '< >', ' ' => $context['utf8'] ? "\xC2\xA0" : "\xA0")); $data = preg_replace( '~(?<=[>;:!? ' . $non_breaking_space . '\]()]|^)([\w\.]{' . $modSettings['fixLongWords'] . ',})~e' . ($context['utf8'] ? 'u' : ''), "preg_replace('/(.{" . ($modSettings['fixLongWords'] - 1) . '})/' . ($context['utf8'] ? 'u' : '') . "', '\\\$1< >', '\$1')", $data); $data = strtr($data, array('< >' => $breaker, $context['utf8'] ? "\xC2\xA0" : "\xA0" => ' ')); } } // Do any smileys! if ($smileys === true) parsesmileys($data); // If it wasn't changed, no copying or other boring stuff has to happen! if ($data != substr($message, $last_pos, $pos - $last_pos + 1)) { $message = substr($message, 0, $last_pos) . $data . substr($message, $pos + 1); // Since we changed it, look again incase we added or removed a tag. But we don't want to skip any. $old_pos = strlen($data) + $last_pos - 1; $pos = strpos($message, '[', $last_pos); $pos = $pos === false ? $old_pos : min($pos, $old_pos); } } // Are we there yet? Are we there yet? if ($pos >= strlen($message) - 1) break; $tags = strtolower(substr($message, $pos + 1, 1)); if ($tags == '/' && !empty($open_tags)) { $pos2 = strpos($message, ']', $pos + 1); if ($pos2 == $pos + 2) continue; $look_for = strtolower(substr($message, $pos + 2, $pos2 - $pos - 2)); $to_close = array(); $block_level = null; do { $tag = array_pop($open_tags); if (!$tag) break; if (!empty($tag['block_level'])) { // Only find out if we need to. if ($block_level === false) { array_push($open_tags, $tag); break; } // The idea is, if we are LOOKING for a block level tag, we can close them on the way. if (strlen($look_for) > 0 && isset($bbc_codes[$look_for{0}])) { foreach ($bbc_codes[$look_for{0}] as $temp) if ($temp['tag'] == $look_for) { $block_level = !empty($temp['block_level']); break; } } if ($block_level !== true) { $block_level = false; array_push($open_tags, $tag); break; } } $to_close[] = $tag; } while ($tag['tag'] != $look_for); // Did we just eat through everything and not find it? if ((empty($open_tags) && (empty($tag) || $tag['tag'] != $look_for))) { $open_tags = $to_close; continue; } elseif (!empty($to_close) && $tag['tag'] != $look_for) { if ($block_level === null && isset($look_for{0}, $bbc_codes[$look_for{0}])) { foreach ($bbc_codes[$look_for{0}] as $temp) if ($temp['tag'] == $look_for) { $block_level = !empty($temp['block_level']); break; } } // We're not looking for a block level tag (or maybe even a tag that exists...) if (!$block_level) { foreach ($to_close as $tag) array_push($open_tags, $tag); continue; } } foreach ($to_close as $tag) { $message = substr($message, 0, $pos) . $tag['after'] . substr($message, $pos2 + 1); $pos += strlen($tag['after']); $pos2 = $pos - 1; // See the comment at the end of the big loop - just eating whitespace ;). if (!empty($tag['block_level']) && substr($message, $pos, 6) == '
') $message = substr($message, 0, $pos) . substr($message, $pos + 6); if (!empty($tag['trim']) && $tag['trim'] != 'inside' && preg_match('~(
| |\s)*~', substr($message, $pos), $matches) != 0) $message = substr($message, 0, $pos) . substr($message, $pos + strlen($matches[0])); } if (!empty($to_close)) { $to_close = array(); $pos--; } continue; } // No tags for this character, so just keep going (fastest possible course.) if (!isset($bbc_codes[$tags])) continue; $inside = empty($open_tags) ? null : $open_tags[count($open_tags) - 1]; $tag = null; foreach ($bbc_codes[$tags] as $possible) { // Not a match? if (strtolower(substr($message, $pos + 1, strlen($possible['tag']))) != $possible['tag']) continue; $next_c = substr($message, $pos + 1 + strlen($possible['tag']), 1); // A test validation? if (isset($possible['test']) && preg_match('~^' . $possible['test'] . '~', substr($message, $pos + 1 + strlen($possible['tag']) + 1)) == 0) continue; // Do we want parameters? elseif (!empty($possible['parameters'])) { if ($next_c != ' ') continue; } elseif (isset($possible['type'])) { // Do we need an equal sign? if (in_array($possible['type'], array('unparsed_equals', 'unparsed_commas', 'unparsed_commas_content', 'unparsed_equals_content', 'parsed_equals')) && $next_c != '=') continue; // Maybe we just want a /... if ($possible['type'] == 'closed' && $next_c != ']' && substr($message, $pos + 1 + strlen($possible['tag']), 2) != '/]' && substr($message, $pos + 1 + strlen($possible['tag']), 3) != ' /]') continue; // An immediate ]? if ($possible['type'] == 'unparsed_content' && $next_c != ']') continue; } // No type means 'parsed_content', which demands an immediate ] without parameters! elseif ($next_c != ']') continue; // Check allowed tree? if (isset($possible['require_parents']) && ($inside === null || !in_array($inside['tag'], $possible['require_parents']))) continue; elseif (isset($inside['require_children']) && !in_array($possible['tag'], $inside['require_children'])) continue; // If this is in the list of disallowed child tags, don't parse it. elseif (isset($inside['disallow_children']) && in_array($possible['tag'], $inside['disallow_children'])) continue; $pos1 = $pos + 1 + strlen($possible['tag']) + 1; // This is long, but it makes things much easier and cleaner. if (!empty($possible['parameters'])) { $preg = array(); foreach ($possible['parameters'] as $p => $info) $preg[] = '(\s+' . $p . '=' . (empty($info['quoted']) ? '' : '"') . (isset($info['match']) ? $info['match'] : '(.+?)') . (empty($info['quoted']) ? '' : '"') . ')' . (empty($info['optional']) ? '' : '?'); // Okay, this may look ugly and it is, but it's not going to happen much and it is the best way of allowing any order of parameters but still parsing them right. $match = false; $orders = permute($preg); foreach ($orders as $p) if (preg_match('~^' . implode('', $p) . '\]~i', substr($message, $pos1 - 1), $matches) != 0) { $match = true; break; } // Didn't match our parameter list, try the next possible. if (!$match) continue; $params = array(); for ($i = 1, $n = count($matches); $i < $n; $i += 2) { $key = strtok(ltrim($matches[$i]), '='); if (isset($possible['parameters'][$key]['value'])) $params['{' . $key . '}'] = strtr($possible['parameters'][$key]['value'], array('$1' => $matches[$i + 1])); elseif (isset($possible['parameters'][$key]['validate'])) $params['{' . $key . '}'] = $possible['parameters'][$key]['validate']($matches[$i + 1]); else $params['{' . $key . '}'] = $matches[$i + 1]; // Just to make sure: replace any $ or { so they can't interpolate wrongly. $params['{' . $key . '}'] = strtr($params['{' . $key . '}'], array('$' => '$', '{' => '{')); } foreach ($possible['parameters'] as $p => $info) { if (!isset($params['{' . $p . '}'])) $params['{' . $p . '}'] = ''; } $tag = $possible; // Put the parameters into the string. if (isset($tag['before'])) $tag['before'] = strtr($tag['before'], $params); if (isset($tag['after'])) $tag['after'] = strtr($tag['after'], $params); if (isset($tag['content'])) $tag['content'] = strtr($tag['content'], $params); $pos1 += strlen($matches[0]) - 1; } else $tag = $possible; break; } // Item codes are complicated buggers... they are implicit [li]s and can make [list]s! if ($smileys !== false && $tag === null && isset($itemcodes[substr($message, $pos + 1, 1)]) && substr($message, $pos + 2, 1) == ']' && !isset($disabled['list']) && !isset($disabled['li'])) { if (substr($message, $pos + 1, 1) == '0' && !in_array(substr($message, $pos - 1, 1), array(';', ' ', "\t", '>'))) continue; $tag = $itemcodes[substr($message, $pos + 1, 1)]; // First let's set up the tree: it needs to be in a list, or after an li. if ($inside === null || ($inside['tag'] != 'list' && $inside['tag'] != 'li')) { $open_tags[] = array( 'tag' => 'list', 'after' => '', 'block_level' => true, 'require_children' => array('li'), 'disallow_children' => isset($inside['disallow_children']) ? $inside['disallow_children'] : null, ); $code = ''; } // Tell the [list] that it needs to close specially. else { // Move the li over, because we're not sure what we'll hit. $open_tags[count($open_tags) - 1]['after'] = ''; $open_tags[count($open_tags) - 2]['after'] = ''; } continue; } // Implicitly close lists and tables if something other than what's required is in them. This is needed for itemcode. if ($tag === null && $inside !== null && !empty($inside['require_children'])) { array_pop($open_tags); $message = substr($message, 0, $pos) . $inside['after'] . substr($message, $pos); $pos += strlen($inside['after']) - 1; } // No tag? Keep looking, then. Silly people using brackets without actual tags. if ($tag === null) continue; // Propagate the list to the child (so wrapping the disallowed tag won't work either.) if (isset($inside['disallow_children'])) $tag['disallow_children'] = isset($tag['disallow_children']) ? array_unique(array_merge($tag['disallow_children'], $inside['disallow_children'])) : $inside['disallow_children']; // Is this tag disabled? if (isset($disabled[$tag['tag']])) { if (!isset($tag['disabled_before']) && !isset($tag['disabled_after']) && !isset($tag['disabled_content'])) { $tag['before'] = !empty($tag['block_level']) ? '
' : ''; $tag['after'] = !empty($tag['block_level']) ? '
' : ''; $tag['content'] = isset($tag['type']) && $tag['type'] == 'closed' ? '' : (!empty($tag['block_level']) ? '
$1
' : '$1'); } elseif (isset($tag['disabled_before']) || isset($tag['disabled_after'])) { $tag['before'] = isset($tag['disabled_before']) ? $tag['disabled_before'] : (!empty($tag['block_level']) ? '
' : ''); $tag['after'] = isset($tag['disabled_after']) ? $tag['disabled_after'] : (!empty($tag['block_level']) ? '
' : ''); } else $tag['content'] = $tag['disabled_content']; } // The only special case is 'html', which doesn't need to close things. if (!empty($tag['block_level']) && $tag['tag'] != 'html' && empty($inside['block_level'])) { $n = count($open_tags) - 1; while (empty($open_tags[$n]['block_level']) && $n >= 0) $n--; // Close all the non block level tags so this tag isn't surrounded by them. for ($i = count($open_tags) - 1; $i > $n; $i--) { $message = substr($message, 0, $pos) . $open_tags[$i]['after'] . substr($message, $pos); $pos += strlen($open_tags[$i]['after']); $pos1 += strlen($open_tags[$i]['after']); // Trim or eat trailing stuff... see comment at the end of the big loop. if (!empty($open_tags[$i]['block_level']) && substr($message, $pos, 6) == '
') $message = substr($message, 0, $pos) . substr($message, $pos + 6); if (!empty($open_tags[$i]['trim']) && $tag['trim'] != 'inside' && preg_match('~(
| |\s)*~', substr($message, $pos), $matches) != 0) $message = substr($message, 0, $pos) . substr($message, $pos + strlen($matches[0])); array_pop($open_tags); } } // No type means 'parsed_content'. if (!isset($tag['type'])) { // !!! Check for end tag first, so people can say "I like that [i] tag"? $open_tags[] = $tag; $message = substr($message, 0, $pos) . $tag['before'] . substr($message, $pos1); $pos += strlen($tag['before']) - 1; } // Don't parse the content, just skip it. elseif ($tag['type'] == 'unparsed_content') { $pos2 = stripos($message, '[/' . substr($message, $pos + 1, strlen($tag['tag'])) . ']', $pos1); if ($pos2 === false) continue; $data = substr($message, $pos1, $pos2 - $pos1); if (!empty($tag['block_level']) && substr($data, 0, 6) == '
') $data = substr($data, 6); if (isset($tag['validate'])) $tag['validate']($tag, $data, $disabled); $code = strtr($tag['content'], array('$1' => $data)); $message = substr($message, 0, $pos) . $code . substr($message, $pos2 + 3 + strlen($tag['tag'])); $pos += strlen($code) - 1; } // Don't parse the content, just skip it. elseif ($tag['type'] == 'unparsed_equals_content') { // The value may be quoted for some tags - check. if (isset($tag['quoted'])) { $quoted = substr($message, $pos1, 6) == '"'; if ($tag['quoted'] != 'optional' && !$quoted) continue; if ($quoted) $pos1 += 6; } else $quoted = false; $pos2 = strpos($message, $quoted == false ? ']' : '"]', $pos1); if ($pos2 === false) continue; $pos3 = stripos($message, '[/' . substr($message, $pos + 1, strlen($tag['tag'])) . ']', $pos2); if ($pos3 === false) continue; $data = array( substr($message, $pos2 + ($quoted == false ? 1 : 7), $pos3 - ($pos2 + ($quoted == false ? 1 : 7))), substr($message, $pos1, $pos2 - $pos1) ); if (!empty($tag['block_level']) && substr($data[0], 0, 6) == '
') $data[0] = substr($data[0], 6); // Validation for my parking, please! if (isset($tag['validate'])) $tag['validate']($tag, $data, $disabled); $code = strtr($tag['content'], array('$1' => $data[0], '$2' => $data[1])); $message = substr($message, 0, $pos) . $code . substr($message, $pos3 + 3 + strlen($tag['tag'])); $pos += strlen($code) - 1; } // A closed tag, with no content or value. elseif ($tag['type'] == 'closed') { $pos2 = strpos($message, ']', $pos); $message = substr($message, 0, $pos) . $tag['content'] . substr($message, $pos2 + 1); $pos += strlen($tag['content']) - 1; } // This one is sorta ugly... :/. Unforunately, it's needed for flash. elseif ($tag['type'] == 'unparsed_commas_content') { $pos2 = strpos($message, ']', $pos1); if ($pos2 === false) continue; $pos3 = stripos($message, '[/' . substr($message, $pos + 1, strlen($tag['tag'])) . ']', $pos2); if ($pos3 === false) continue; // We want $1 to be the content, and the rest to be csv. $data = explode(',', ',' . substr($message, $pos1, $pos2 - $pos1)); $data[0] = substr($message, $pos2 + 1, $pos3 - $pos2 - 1); if (isset($tag['validate'])) $tag['validate']($tag, $data, $disabled); $code = $tag['content']; foreach ($data as $k => $d) $code = strtr($code, array('$' . ($k + 1) => trim($d))); $message = substr($message, 0, $pos) . $code . substr($message, $pos3 + 3 + strlen($tag['tag'])); $pos += strlen($code) - 1; } // This has parsed content, and a csv value which is unparsed. elseif ($tag['type'] == 'unparsed_commas') { $pos2 = strpos($message, ']', $pos1); if ($pos2 === false) continue; $data = explode(',', substr($message, $pos1, $pos2 - $pos1)); if (isset($tag['validate'])) $tag['validate']($tag, $data, $disabled); // Fix after, for disabled code mainly. foreach ($data as $k => $d) $tag['after'] = strtr($tag['after'], array('$' . ($k + 1) => trim($d))); $open_tags[] = $tag; // Replace them out, $1, $2, $3, $4, etc. $code = $tag['before']; foreach ($data as $k => $d) $code = strtr($code, array('$' . ($k + 1) => trim($d))); $message = substr($message, 0, $pos) . $code . substr($message, $pos2 + 1); $pos += strlen($code) - 1; } // A tag set to a value, parsed or not. elseif ($tag['type'] == 'unparsed_equals' || $tag['type'] == 'parsed_equals') { // The value may be quoted for some tags - check. if (isset($tag['quoted'])) { $quoted = substr($message, $pos1, 6) == '"'; if ($tag['quoted'] != 'optional' && !$quoted) continue; if ($quoted) $pos1 += 6; } else $quoted = false; $pos2 = strpos($message, $quoted == false ? ']' : '"]', $pos1); if ($pos2 === false) continue; $data = substr($message, $pos1, $pos2 - $pos1); // Validation for my parking, please! if (isset($tag['validate'])) $tag['validate']($tag, $data, $disabled); // For parsed content, we must recurse to avoid security problems. if ($tag['type'] != 'unparsed_equals') $data = parse_bbc($data); $tag['after'] = strtr($tag['after'], array('$1' => $data)); $open_tags[] = $tag; $code = strtr($tag['before'], array('$1' => $data)); $message = substr($message, 0, $pos) . $code . substr($message, $pos2 + ($quoted == false ? 1 : 7)); $pos += strlen($code) - 1; } // If this is block level, eat any breaks after it. if (!empty($tag['block_level']) && substr($message, $pos + 1, 6) == '
') $message = substr($message, 0, $pos + 1) . substr($message, $pos + 7); // Are we trimming outside this tag? if (!empty($tag['trim']) && $tag['trim'] != 'outside' && preg_match('~(
| |\s)*~', substr($message, $pos + 1), $matches) != 0) $message = substr($message, 0, $pos + 1) . substr($message, $pos + 1 + strlen($matches[0])); } // Close any remaining tags. while ($tag = array_pop($open_tags)) $message .= $tag['after']; if (substr($message, 0, 1) == ' ') $message = ' ' . substr($message, 1); // Cleanup whitespace. $message = strtr($message, array(' ' => '  ', "\r" => '', "\n" => '
', '
' => '
 ', ' ' => "\n")); // Cache the output if it took some time... if (isset($cache_key, $cache_t) && array_sum(explode(' ', microtime())) - array_sum(explode(' ', $cache_t)) > 0.05) cache_put_data($cache_key, $message, 240); return $message; } // Parse smileys in the passed message. function parsesmileys(&$message) { global $modSettings, $db_prefix, $txt, $user_info, $context; static $smileyfromcache = array(), $smileytocache = array(); // No smiley set at all?! if ($user_info['smiley_set'] == 'none') return; // If the smiley array hasn't been set, do it now. if (empty($smileyfromcache)) { // 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', 'embarrassed.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. if (($temp = cache_get_data('parsing_smileys', 480)) == null) { $result = db_query(" SELECT code, filename, description FROM {$db_prefix}smileys", __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); cache_put_data('parsing_smileys', array($smileysfrom, $smileysto, $smileysdescs), 480); } else list ($smileysfrom, $smileysto, $smileysdescs) = $temp; } // The non-breaking-space is a complex thing... $non_breaking_space = $context['utf8'] ? ($context['server']['complex_preg_chars'] ? '\x{A0}' : pack('C*', 0xC2, 0xA0)) : '\xA0'; // 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' . $non_breaking_space . '[\]()*\\\;]|^)(' . preg_quote($smileysfrom[$i], '/') . '|' . preg_quote(htmlspecialchars($smileysfrom[$i], ENT_QUOTES), '/') . ')(?=[^[:alpha:]0-9]|$)/' . ($context['utf8'] ? 'u' : ''); // Escape a bunch of smiley-related characters in the description so it doesn't get a double dose :P. $smileytocache[] = '' . strtr(htmlspecialchars($smileysdescs[$i]), array(':' => ':', '(' => '(', ')' => ')', '$' => '$', '[' => '[')) . ''; } } // Replace away! // !!! There must be a way to speed this up. $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('
' => "\n", "\t" => 'SMF_TAB();', '[' => '['))); $oldlevel = error_reporting(0); // It's easier in 4.2.x+. if (@version_compare(PHP_VERSION, '4.2.0') == -1) { 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 color|span style)="[^"]*?">)?\(\);~', "
\t
", $buffer); return strtr($buffer, array('\'' => ''', '' => '', '' => '')); } // Put this user in the online log. function writeLog($force = false) { global $db_prefix, $ID_MEMBER, $user_info, $user_settings, $sc, $modSettings, $settings, $topic, $board; // If we are showing who is viewing a topic, let's see if we are, and force an update if so - to make it accurate. if (!empty($settings['display_who_viewing']) && ($topic || $board)) { // Take the opposite approach! $force = true; // Don't update for every page - this isn't wholly accurate but who cares. if ($topic) { if (isset($_SESSION['last_topic_id']) && $_SESSION['last_topic_id'] == $topic) $force = false; $_SESSION['last_topic_id'] = $topic; } } // Don't mark them as online more than every so often. if (!empty($_SESSION['log_time']) && $_SESSION['log_time'] >= (time() - 8) && !$force) 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(); // Grab the last all-of-SMF-specific log_online deletion time. $do_delete = cache_get_data('log_online-update', 10) < time() - 10; // If the last click wasn't a long time ago, and there was a last click... if (!empty($_SESSION['log_time']) && $_SESSION['log_time'] >= time() - $modSettings['lastActive'] * 20) { if ($do_delete) { db_query(" DELETE FROM {$db_prefix}log_online WHERE logTime < NOW() - INTERVAL " . ($modSettings['lastActive'] * 60) . " SECOND AND session != '$session_id'", __FILE__, __LINE__); cache_put_data('log_online-update', time(), 10); } db_query(" UPDATE {$db_prefix}log_online SET logTime = NOW(), ip = IFNULL(INET_ATON('$user_info[ip]'), 0), url = '$serialized' WHERE session = '$session_id' LIMIT 1", __FILE__, __LINE__); // Guess it got deleted. if (db_affected_rows() == 0) $_SESSION['log_time'] = 0; } else $_SESSION['log_time'] = 0; // Otherwise, we have to delete and insert. if (empty($_SESSION['log_time'])) { if ($do_delete || !empty($ID_MEMBER)) db_query(" DELETE FROM {$db_prefix}log_online WHERE " . ($do_delete ? "logTime < NOW() - INTERVAL " . ($modSettings['lastActive'] * 60) . ' SECOND' : '') . ($do_delete && !empty($ID_MEMBER) ? ' OR ' : '') . (empty($ID_MEMBER) ? '' : "ID_MEMBER = $ID_MEMBER"), __FILE__, __LINE__); db_query(" " . ($do_delete ? 'INSERT IGNORE' : 'REPLACE') . " INTO {$db_prefix}log_online (session, ID_MEMBER, logTime, ip, url) VALUES ('$session_id', $ID_MEMBER, NOW(), IFNULL(INET_ATON('$user_info[ip]'), 0), '$serialized')", __FILE__, __LINE__); } // Mark your session as being logged. $_SESSION['log_time'] = time(); // 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 (SMF != 'SSI' && !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(); $user_settings['totalTimeLoggedIn'] += time() - $_SESSION['timeOnlineUpdated']; updateMemberData($ID_MEMBER, array('lastLogin' => time(), 'memberIP' => '\'' . $user_info['ip'] . '\'', 'memberIP2' => '\'' . $_SERVER['BAN_CHECK_IP'] . '\'', 'totalTimeLoggedIn' => $user_settings['totalTimeLoggedIn'])); if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2) cache_put_data('user_settings-' . $ID_MEMBER, $user_settings, 60); $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 = '', $refresh = false) { global $scripturl, $context, $modSettings, $db_show_debug; $add = preg_match('~^(ftp|http)[s]?://~', $setLocation) == 0 && substr($setLocation, 0, 6) != 'about:'; if (WIRELESS) { // Add the scripturl on if needed. 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); // Keep that debug in their for template debugging! elseif (isset($_GET['debug'])) $setLocation = preg_replace('/^' . preg_quote($scripturl, '/') . '(\?)?/', $scripturl . '?debug;', $setLocation); if (!empty($modSettings['queryless_urls']) && (empty($context['server']['is_cgi']) || @ini_get('cgi.fix_pathinfo') == 1) && !empty($context['server']['is_apache'])) { if (defined('SID') && SID != '') $setLocation = preg_replace('/^' . preg_quote($scripturl, '/') . '\?(?:' . SID . ';)((?:board|topic)=[^#]+?)(#[^"]*?)?$/e', "\$scripturl . '/' . strtr('\$1', '&;=', '//,') . '.html\$2?' . SID", $setLocation); else $setLocation = preg_replace('/^' . preg_quote($scripturl, '/') . '\?((?:board|topic)=[^#"]+?)(#[^"]*?)?$/e', "\$scripturl . '/' . strtr('\$1', '&;=', '//,') . '.html\$2'", $setLocation); } if (isset($modSettings['integrate_redirect']) && function_exists($modSettings['integrate_redirect'])) $modSettings['integrate_redirect']($setLocation, $refresh); // We send a Refresh header only in special cases because Location looks better. (and is quicker...) if ($refresh && !WIRELESS) header('Refresh: 0; URL=' . strtr($setLocation, array(' ' => '%20', ';' => '%3b'))); else header('Location: ' . str_replace(' ', '%20', $setLocation)); // Debugging. if (isset($db_show_debug) && $db_show_debug === true) $_SESSION['debug_redirect'] = &$GLOBALS['db_cache']; obExit(false); } // Ends execution. Takes care of template loading and remembering the previous URL. function obExit($header = null, $do_footer = null, $from_index = false) { global $context, $settings, $modSettings, $txt; static $header_done = false, $footer_done = false; // Clear out the stat cache. trackStats(); $do_header = $header === null ? !$header_done : $header; 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'); // Just in case we have anything bad already in there... if ((isset($_REQUEST['debug']) || isset($_REQUEST['xml']) || (WIRELESS && WIRELESS_PROTOCOL == 'wap')) && in_array($txt['lang_locale'], array('UTF-8', 'ISO-8859-1'))) ob_start('validate_unicode__recursive'); if (!empty($settings['output_buffers']) && is_string($settings['output_buffers'])) $buffers = explode(',', $settings['output_buffers']); elseif (!empty($settings['output_buffers'])) $buffers = $settings['output_buffers']; else $buffers = array(); if (isset($modSettings['integrate_buffer'])) $buffers = array_merge(explode(',', $modSettings['integrate_buffer']), $buffers); if (!empty($buffers)) foreach ($buffers as $buffer_function) { if (function_exists(trim($buffer_function))) ob_start(trim($buffer_function)); } // Display the screen in the logical order. template_header(); $header_done = true; } if ($do_footer) { if (WIRELESS && !isset($context['sub_template'])) fatal_lang_error('wireless_error_notyet', false); // Just show the footer, then. loadSubTemplate(isset($context['sub_template']) ? $context['sub_template'] : 'main'); // Just so we don't get caught in an endless loop of errors from the footer... if (!$footer_done) { $footer_done = true; template_footer(); // (since this is just debugging... it's okay that it's after .) if (!isset($_REQUEST['xml'])) db_debug_junk(); } } // Remember this URL in case someone doesn't like sending HTTP_REFERER. if (strpos($_SERVER['REQUEST_URL'], 'action=dlattach') === false) $_SESSION['old_url'] = $_SERVER['REQUEST_URL']; // For session check verfication.... don't switch browsers... $_SESSION['USER_AGENT'] = $_SERVER['HTTP_USER_AGENT']; // Hand off the output to the portal, etc. we're integrated with. if (isset($modSettings['integrate_exit'], $context['template_layers']) && in_array('main', $context['template_layers']) && function_exists($modSettings['integrate_exit'])) call_user_func($modSettings['integrate_exit'], $do_footer && !WIRELESS); // 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 'Main'. $context['admin_areas']['forum'] = array( 'title' => $txt[427], 'areas' => array( 'index' => '' . $txt[208] . '', 'credits' => '' . $txt['support_credits_title'] . '', ) ); if (allowedTo(array('edit_news', 'send_mail', 'admin_forum'))) $context['admin_areas']['forum']['areas']['news'] = '' . $txt['news_title'] . ''; if (allowedTo('admin_forum')) $context['admin_areas']['forum']['areas']['manage_packages'] = '' . $txt['package1'] . ''; // Admin area 'Configuration'. if (allowedTo('admin_forum')) { $context['admin_areas']['config'] = array( 'title' => $txt[428], 'areas' => array( 'edit_mods_settings' => '' . $txt['modSettings_title'] . '', 'edit_settings' => '' . $txt[222] . '', 'edit_theme_settings' => '' . $txt['theme_current_settings'] . '', 'manage_themes' => '' . $txt['theme_admin'] . '', ) ); } // Admin area 'Forum'. if (allowedTo(array('manage_boards', 'admin_forum', 'manage_smileys', 'manage_attachments', 'moderate_forum'))) { $context['admin_areas']['layout'] = array( 'title' => $txt['layout_controls'], 'areas' => array() ); if (allowedTo('manage_boards')) $context['admin_areas']['layout']['areas']['manage_boards'] = '' . $txt[4] . ''; if (allowedTo(array('admin_forum', 'moderate_forum'))) $context['admin_areas']['layout']['areas']['posts_and_topics'] = '' . $txt['manageposts'] . ''; if (allowedTo('admin_forum')) { $context['admin_areas']['layout']['areas']['manage_calendar'] = '' . $txt['manage_calendar'] . ''; $context['admin_areas']['layout']['areas']['manage_search'] = '' . $txt['manage_search'] . ''; } if (allowedTo('manage_smileys')) $context['admin_areas']['layout']['areas']['manage_smileys'] = '' . $txt['smileys_manage'] . ''; if (allowedTo('manage_attachments')) $context['admin_areas']['layout']['areas']['manage_attachments'] = '' . $txt['smf201'] . ''; } // Admin area 'Members'. if (allowedTo(array('moderate_forum', 'manage_membergroups', 'manage_bans', 'manage_permissions', 'admin_forum'))) { $context['admin_areas']['members'] = array( 'title' => $txt[426], 'areas' => array() ); if (allowedTo('moderate_forum')) $context['admin_areas']['members']['areas']['view_members'] = '' . $txt[5] . ''; if (allowedTo('manage_membergroups')) $context['admin_areas']['members']['areas']['edit_groups'] = '' . $txt[8] . ''; if (allowedTo('manage_permissions')) $context['admin_areas']['members']['areas']['edit_permissions'] = '' . $txt['edit_permissions'] . ''; if (allowedTo(array('admin_forum', 'moderate_forum'))) $context['admin_areas']['members']['areas']['registration_center'] = '' . $txt['registration_center'] . ''; if (allowedTo('manage_bans')) $context['admin_areas']['members']['areas']['ban_members'] = '' . $txt['ban_title'] . ''; } // Admin area 'Maintenance Controls'. if (allowedTo('admin_forum')) { $context['admin_areas']['maintenance'] = array( 'title' => $txt[501], 'areas' => array( 'maintain_forum' => '' . $txt['maintain_title'] . '', 'generate_reports' => '' . $txt['generate_reports'] . '', // !!! Why? Don't you want to take care of errors in the order they happened, like normal people and programmers? Seeing them backwards helps no one, and only increases confusion. // !!! You know I've argued this before. 'view_errors' => '' . $txt['errlog1'] . '' ) ); if (!empty($modSettings['modlog_enabled'])) $context['admin_areas']['maintenance']['areas']['view_moderation_log'] = '' . $txt['modlog_view'] . ''; } // 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 (!is_array($extra)) trigger_error('logAction(): data is not an array with action \'' . $action . '\'', E_USER_NOTICE); if (isset($extra['topic']) && !is_numeric($extra['topic'])) trigger_error('logAction(): data\'s topic is not an number', E_USER_NOTICE); if (isset($extra['member']) && !is_numeric($extra['member'])) trigger_error('logAction(): data\'s member is not an number', E_USER_NOTICE); if (!empty($modSettings['modlog_enabled'])) { db_query(" INSERT INTO {$db_prefix}log_actions (logTime, ID_MEMBER, ip, action, extra) VALUES (" . time() . ", $ID_MEMBER, SUBSTRING('$user_info[ip]', 1, 16), SUBSTRING('$action', 1, 30), SUBSTRING('" . addslashes(serialize($extra)) . "', 1, 65534))", __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__); } // Don't do this again. $cache_stats = array(); 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 (SUBSTRING('$user_info[ip]', 1, 16), " . 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) { global $sourcedir; // Can we pull this from the cache... please please? if (($temp = cache_get_data('url_image_size-' . md5($url), 240)) !== null) return $temp; $t = microtime(); // 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])) $size = @getimagesize($url); else { // Try to connect to the server... give it half a second. $temp = 0; $fp = @fsockopen($match[1], 80, $temp, $temp, 0.5); // Successful? Continue... if ($fp != false) { // Send the HEAD request (since we don't have to worry about chunked, HTTP/1.1 is fine here.) fwrite($fp, 'HEAD /' . $match[2] . ' HTTP/1.1' . "\r\n" . 'Host: ' . $match[1] . "\r\n" . 'User-Agent: PHP/SMF' . "\r\n" . 'Connection: close' . "\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) { $size = @getimagesize($url); // This probably means allow_url_fopen is off, let's try GD. if ($size === false && function_exists('imagecreatefromstring')) { include_once($sourcedir . '/Subs-Package.php'); // It's going to hate us for doing this, but another request... $image = @imagecreatefromstring(fetch_web_data($url)); if ($image !== false) { $size = array(imagesx($image), imagesy($image)); imagedestroy($image); } } } } } // If we didn't get it, we failed. if (!isset($size)) $size = false; // If this took a long time, we may never have to do it again, but then again we might... if (array_sum(explode(' ', microtime())) - array_sum(explode(' ', $t)) > 0.8) cache_put_data('url_image_size-' . md5($url), $size, 240); // Didn't work. return $size; } 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; // 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] = parse_bbc(stripslashes(trim($context['news_lines'][$i])), true, 'news' . $i); // Gotta be special for the javascript. $context['fader_news_lines'][$i] = strtr(addslashes($context['news_lines'][$i]), array('/' => '\/', ' (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'] == '' && !empty($user_info['avatar']['ID_ATTACH'])) $context['user']['avatar']['href'] = $user_info['avatar']['custom_dir'] ? $modSettings['custom_avatar_url'] . '/' . $user_info['avatar']['filename'] : $scripturl . '?action=dlattach;attach=' . $user_info['avatar']['ID_ATTACH'] . ';type=avatar'; // Full URL? elseif (substr($user_info['avatar']['url'], 0, 7) == 'http://') { $context['user']['avatar']['href'] = $user_info['avatar']['url']; if ($modSettings['avatar_action_too_large'] == 'option_html_resize' || $modSettings['avatar_action_too_large'] == 'option_js_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']; } } // Otherwise we assume it's server stored? elseif ($user_info['avatar']['url'] != '') $context['user']['avatar']['href'] = $modSettings['avatar_url'] . '/' . htmlspecialchars($user_info['avatar']['url']); if (!empty($context['user']['avatar'])) $context['user']['avatar']['image'] = ''; // 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']; // If we've upgraded recently, go easy on the passwords. if (!empty($modSettings['disableHashTime']) && ($modSettings['disableHashTime'] == 1 || time() < $modSettings['disableHashTime'])) $context['disable_login_hashing'] = true; elseif ($context['browser']['is_ie5'] || $context['browser']['is_ie5.5']) $context['disable_login_hashing'] = true; } // 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_memberlist'] = allowedTo('view_mlist'); $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['current_action'] = isset($_GET['action']) ? $_GET['action'] : ''; $context['show_quick_login'] = !empty($modSettings['enableVBStyleLogin']) && $user_info['is_guest']; if (empty($settings['theme_version'])) $context['show_vBlogin'] = $context['show_quick_login']; // 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']) && (!isset($_REQUEST['action']) || $_REQUEST['action'] != 'pm')) { $context['html_headers'] .= ' '; } // Resize avatars the fancy, but non-GD requiring way. if ($modSettings['avatar_action_too_large'] == 'option_js_resize' && (!empty($modSettings['avatar_max_width_external']) || !empty($modSettings['avatar_max_height_external']))) { $context['html_headers'] .= ' '; } // This looks weird, but it's because BoardIndex.php references the variable. $context['common_stats']['latest_member'] = array( 'id' => $modSettings['latestMember'], 'name' => $modSettings['latestRealName'], 'href' => $scripturl . '?action=profile;u=' . $modSettings['latestMember'], 'link' => '' . $modSettings['latestRealName'] . '', ); $context['common_stats'] = array( 'total_posts' => comma_format($modSettings['totalMessages']), 'total_topics' => comma_format($modSettings['totalTopics']), 'total_members' => comma_format($modSettings['totalMembers']), 'latest_member' => $context['common_stats']['latest_member'], ); if (empty($settings['theme_version'])) $context['html_headers'] .= ' '; 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, $boarddir; setupThemeContext(); // Print stuff to prevent caching of pages (except on attachment errors, etc.) if (empty($context['no_last_modified'])) { header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // Are we debugging the template/html content? if (!isset($_REQUEST['xml']) && isset($_GET['debug']) && !$context['browser']['is_ie'] && !WIRELESS) header('Content-Type: application/xhtml+xml'); elseif (!isset($_REQUEST['xml']) && !WIRELESS) header('Content-Type: text/html; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set'])); } header('Content-Type: text/' . (isset($_REQUEST['xml']) ? 'xml' : 'html') . '; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set'])); 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') && !$user_info['is_guest']) { $securityFiles = array('install.php', 'webinstall.php', 'upgrade.php', 'convert.php', 'repair_paths.php', 'repair_settings.php'); foreach ($securityFiles as $i => $securityFile) { if (!file_exists($boarddir . '/' . $securityFile)) unset($securityFiles[$i]); } if (!empty($securityFiles)) { echo '
!!
', $txt['smf299'], '
'; foreach ($securityFiles as $securityFile) echo ' ', $txt['smf300'], '', $securityFile, '!
'; echo '
'; } } // If the user is banned from posting inform them of it. elseif ($layer == 'main' && isset($_SESSION['ban']['cannot_post'])) { echo '
', sprintf($txt['you_are_post_banned'], $user_info['is_guest'] ? $txt[28] : $user_info['name']); if (!empty($_SESSION['ban']['cannot_post']['reason'])) echo '
', $_SESSION['ban']['cannot_post']['reason'], '
'; echo '
'; } } 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, $modSettings; static $found = false; // DO NOT MODIFY THIS FUNCTION. DO NOT REMOVE YOUR COPYRIGHT. // DOING SO VOIDS YOUR LICENSE AND IS ILLEGAL. // Meaning, this is the footer checking in.. if ($get_it === true) return $found; // Naughty, naughty. if (mt_rand(0, 2) == 1) { $temporary = preg_replace('~~s', '', ob_get_contents()); if (strpos($temporary, ''; } // For SSI and other things, detect the version. if (!isset($forum_version) || strpos($forum_version, 'SMF') === false || isset($_GET['checkcopyright'])) { $data = substr(file_get_contents(__FILE__), 0, 4096); if (preg_match('~\*\s*Software\s+Version:\s+(SMF\s+.+?)[\s]{2}~i', $data, $match) == 0) $match = array('', 'SMF'); $forum_copyright = preg_replace('~(]+>)~', '$1' . $match[1] . '', $forum_copyright); } // Lewis Media no longer holds the copyright. $forum_copyright = str_replace(array('Lewis Media', 'href="http://www.lewismedia.com/"', '2001-'), array('Simple Machines LLC', 'href="http://www.simplemachines.org/about/copyright.php" title="Free Forum Software"', ''), $forum_copyright); echo ' '; if ($get_it == 'none') { $found = true; echo '
The administrator doesn\'t want a copyright notice saying this is copyright 2006 - 2009 by Simple Machines LLC, and named SMF, so the forum will honor this request and be quiet.
'; } // If it's in the copyright, and we are outputting it... it's been found. elseif (isset($modSettings['copyright_key']) && sha1($modSettings['copyright_key'] . 'banjo') == '1d01885ece7a9355bdeb22ed107f0ffa8c323026'){$found = true; return;}elseif ((strpos($forum_copyright, 'Powered by SMF') !== false || strpos($forum_copyright, 'SMF') !== false || strpos($forum_copyright, 'SMF') !== false || strpos($forum_copyright, 'SMF') !== false)&&((strpos($forum_copyright, 'SMF ©') !== false && (strpos($forum_copyright, 'Lewis Media') !== false || strpos($forum_copyright, 'Simple Machines LLC') !== false)) || strpos($forum_copyright, 'Lewis Media') !== false || strpos($forum_copyright, 'Lewis Media') !== false || (strpos($forum_copyright, ''; } 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'] = !empty($modSettings['timeLoadPageEnable']); $context['load_time'] = round(array_sum(explode(' ', microtime())) - array_sum(explode(' ', $time_start)), 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) { // DO NOT MODIFY THIS SECTION. DO NOT REMOVE YOUR COPYRIGHT. // DOING SO VOIDS YOUR LICENSE AND IS ILLEGAL. echo '
Sorry, the copyright must be in the template.
Please notify this forum\'s administrator that this site is missing the copyright message for
SMF so they can rectify the situation. Display of copyright is a legal requirement. For more information on this please visit the Simple Machines website.', empty($context['user']['is_admin']) ? '' : '
Not sure why this message is appearing? Take a look at some common causes.', '
'; log_error('Copyright removed!!'); } } // Debugging. function db_debug_junk() { global $context, $scripturl, $boarddir, $modSettings; global $db_cache, $db_count, $db_show_debug, $cache_count, $cache_hits; // Add to Settings.php if you want to show the debugging information. if (!isset($db_show_debug) || $db_show_debug !== true || (isset($_GET['action']) && $_GET['action'] == 'viewquery') || WIRELESS) return; if (empty($_SESSION['view_queries'])) $_SESSION['view_queries'] = 0; if (empty($context['debug']['language_files'])) $context['debug']['language_files'] = array(); $files = get_included_files(); $total_size = 0; for ($i = 0, $n = count($files); $i < $n; $i++) { $total_size += filesize($files[$i]); $files[$i] = strtr($files[$i], array($boarddir => '.')); } $warnings = 0; foreach ($db_cache as $q => $qq) { if (!empty($qq['w'])) $warnings += count($qq['w']); } $_SESSION['debug'] = &$db_cache; // Gotta have valid HTML ;). $temp = ob_get_contents(); if (function_exists('ob_clean')) ob_clean(); else { ob_end_clean(); ob_start('ob_sessrewrite'); } echo preg_replace('~\s*~', '', $temp), '
Templates: ', count($context['debug']['templates']), ': ', implode(', ', $context['debug']['templates']), '.
Sub templates: ', count($context['debug']['sub_templates']), ': ', implode(', ', $context['debug']['sub_templates']), '.
Language files: ', count($context['debug']['language_files']), ': ', implode(', ', $context['debug']['language_files']), '.
Files included: ', count($files), ' - ', round($total_size / 1024), 'KB. (show)
'; if (!empty($modSettings['cache_enable']) && !empty($cache_hits)) { $entries = array(); $total_t = 0; $total_s = 0; foreach ($cache_hits as $h) { $entries[] = $h['d'] . ' ' . $h['k'] . ': ' . comma_format($h['t'], 5) . ' - ' . $h['s'] . ' bytes'; $total_t += $h['t']; $total_s += $h['s']; } echo ' Cache hits: ', $cache_count, ': ', comma_format($total_t, 5), 's for ', comma_format($total_s), ' bytes (show)
'; } echo ' Queries used: ', $db_count, $warnings == 0 ? '' : ', ' . $warnings . ' warning(s)', '.

'; if ($_SESSION['view_queries'] == 1) foreach ($db_cache as $q => $qq) { $is_select = substr(trim($qq['q']), 0, 6) == 'SELECT' || preg_match('~^INSERT(?: IGNORE)? INTO \w+(?:\s+\([^)]+\))?\s+SELECT .+$~s', trim($qq['q'])) != 0; echo ' ', $is_select ? '' : '', nl2br(str_replace("\t", '   ', htmlspecialchars(ltrim($qq['q'], "\n\r")))) . ($is_select ? '' : '') . '
   '; if (!empty($qq['f']) && !empty($qq['l'])) echo 'in ' . $qq['f'] . ' line ' . $qq['l'] . ', '; echo 'which took ' . round($qq['t'], 8) . ' seconds.

'; } echo ' [' . (empty($_SESSION['view_queries']) ? 'show' : 'hide') . ' queries]
'; } // Get an attachment's encrypted filename. If $new is true, won't check for file existence. function getAttachmentFilename($filename, $attachment_id, $new = false, $file_hash = '') { global $modSettings, $db_prefix; // Just make up a nice hash... if ($new) return sha1(md5($filename . time()) . mt_rand()); // Grab the file hash if it wasn't added. if ($file_hash === '') { $request = db_query(" SELECT file_hash FROM {$db_prefix}attachments WHERE ID_ATTACH = " . (int) $attachment_id, __FILE__, __LINE__); if (mysql_num_rows($request) === 0) return false; list ($file_hash) = mysql_fetch_row($request); mysql_free_result($request); } // In case of files from the old system, do a legacy call. if (empty($file_hash)) return getLegacyAttachmentFilename($filename, $attachment_id, $new); return $modSettings['attachmentUploadDir'] . '/' . $attachment_id . '_' . $file_hash; } function getLegacyAttachmentFilename($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 . '_' . strtr($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; } // Lookup an IP; try shell_exec first because we can do a timeout on it. function host_from_ip($ip) { global $modSettings; if (($host = cache_get_data('hostlookup-' . $ip, 600)) !== null) return $host; $t = microtime(); // If we can't access nslookup/host, PHP 4.1.x might just crash. if (@version_compare(PHP_VERSION, '4.2.0') == -1) $host = false; // Try the Linux host command, perhaps? if (!isset($host) && (strpos(strtolower(PHP_OS), 'win') === false || strpos(strtolower(PHP_OS), 'darwin') !== false) && mt_rand(0, 1) == 1) { if (!isset($modSettings['host_to_dis'])) $test = @shell_exec('host -W 1 ' . @escapeshellarg($ip)); else $test = @shell_exec('host ' . @escapeshellarg($ip)); // Did host say it didn't find anything? if (strpos($test, 'not found') !== false) $host = ''; // Invalid server option? elseif ((strpos($test, 'invalid option') || strpos($test, 'Invalid query name 1')) && !isset($modSettings['host_to_dis'])) updateSettings(array('host_to_dis' => 1)); // Maybe it found something, after all? elseif (preg_match('~\s([^\s]+?)\.\s~', $test, $match) == 1) $host = $match[1]; } // This is nslookup; usually only Windows, but possibly some Unix? if (!isset($host) && strpos(strtolower(PHP_OS), 'win') !== false && strpos(strtolower(PHP_OS), 'darwin') === false && mt_rand(0, 1) == 1) { $test = @shell_exec('nslookup -timeout=1 ' . @escapeshellarg($ip)); if (strpos($test, 'Non-existent domain') !== false) $host = ''; elseif (preg_match('~Name:\s+([^\s]+)~', $test, $match) == 1) $host = $match[1]; } // This is the last try :/. if (!isset($host) || $host === false) $host = @gethostbyaddr($ip); // It took a long time, so let's cache it! if (array_sum(explode(' ', microtime())) - array_sum(explode(' ', $t)) > 0.5) cache_put_data('hostlookup-' . $ip, $host, 600); return $host; } // Chops a string into words and prepares them to be inserted into (or searched from) the database. function text2words($text, $max_chars = 20, $encrypt = false) { global $func, $context; // Step 1: Remove entities/things we don't consider words: $words = preg_replace('~([\x0B\0' . ($context['utf8'] ? ($context['server']['complex_preg_chars'] ? '\x{A0}' : pack('C*', 0xC2, 0xA0)) : '\xA0') . '\t\r\s\n(){}\\[\\]<>!@$%^*.,:+=`\~\?/\\\\]|&(amp|lt|gt|quot);)+~' . ($context['utf8'] ? 'u' : ''), ' ', strtr($text, array('
' => ' '))); // Step 2: Entities we left to letters, where applicable, lowercase. $words = un_htmlspecialchars($func['strtolower']($words)); // Step 3: Ready to split apart and index! $words = explode(' ', $words); if ($encrypt) { $possible_chars = array_flip(array_merge(range(46, 57), range(65, 90), range(97, 122))); $returned_ints = array(); foreach ($words as $word) { if (($word = trim($word, '-_\'')) !== '') { $encrypted = substr(crypt($word, 'uk'), 2, $max_chars); $total = 0; for ($i = 0; $i < $max_chars; $i++) $total += $possible_chars[ord($encrypted{$i})] * pow(63, $i); $returned_ints[] = $max_chars == 4 ? min($total, 16777215) : $total; } } return array_unique($returned_ints); } else { // Trim characters before and after and add slashes for database insertion. $returned_words = array(); foreach ($words as $word) if (($word = trim($word, '-_\'')) !== '') $returned_words[] = addslashes($max_chars === null ? $word : substr($word, 0, $max_chars)); // Filter out all words that occur more than once. return array_unique($returned_words); } } // Creates an image/text button function create_button($name, $alt, $label = '', $custom = '') { global $settings, $txt, $context; if (!$settings['use_image_buttons']) return $txt[$alt]; elseif (!empty($settings['use_buttons'])) return '' . $txt[$alt] . '' . ($label != '' ? '' . $txt[$label] . '' : ''); else return '' . $txt[$alt] . ''; } // Generate a random seed and ensure it's stored in settings. function smf_seed_generator() { global $modSettings; // Never existed? if (empty($modSettings['rand_seed'])) { $modSettings['rand_seed'] = microtime() * 1000000; updateSettings(array('rand_seed' => $modSettings['rand_seed'])); } if (@version_compare(PHP_VERSION, '4.2.0') == -1) { $seed = ($modSettings['rand_seed'] + ((double) microtime() * 1000003)) & 0x7fffffff; mt_srand($seed); } // Change the seed. updateSettings(array('rand_seed' => mt_rand())); } ?>
Warning: Cannot modify header information - headers already sent by (output started at D:\Nationalpark\TAK\board_paro14\Sources\Subs.php:1) in D:\Nationalpark\TAK\board_paro14\Sources\Subs-Auth.php on line 346

Warning: Cannot modify header information - headers already sent by (output started at D:\Nationalpark\TAK\board_paro14\Sources\Subs.php:1) in D:\Nationalpark\TAK\board_paro14\Sources\Subs-Auth.php on line 347

Warning: Cannot modify header information - headers already sent by (output started at D:\Nationalpark\TAK\board_paro14\Sources\Subs.php:1) in D:\Nationalpark\TAK\board_paro14\Sources\Subs-Auth.php on line 348
Connection Problems

Connection Problems

Sorry, SMF was unable to connect to the database. This may be caused by the server being busy. Please try again later.