"%{};]+'); define('WT_REGEX_PASSWORD', '.{' . WT_MINIMUM_PASSWORD_LENGTH . ',}'); // UTF8 representation of various characters define('WT_UTF8_BOM', "\xEF\xBB\xBF"); // U+FEFF // UTF8 control codes affecting the BiDirectional algorithm (see http://www.unicode.org/reports/tr9/) define('WT_UTF8_LRM', "\xE2\x80\x8E"); // U+200E (Left to Right mark: zero-width character with LTR directionality) define('WT_UTF8_RLM', "\xE2\x80\x8F"); // U+200F (Right to Left mark: zero-width character with RTL directionality) define('WT_UTF8_LRO', "\xE2\x80\xAD"); // U+202D (Left to Right override: force everything following to LTR mode) define('WT_UTF8_RLO', "\xE2\x80\xAE"); // U+202E (Right to Left override: force everything following to RTL mode) define('WT_UTF8_LRE', "\xE2\x80\xAA"); // U+202A (Left to Right embedding: treat everything following as LTR text) define('WT_UTF8_RLE', "\xE2\x80\xAB"); // U+202B (Right to Left embedding: treat everything following as RTL text) define('WT_UTF8_PDF', "\xE2\x80\xAC"); // U+202C (Pop directional formatting: restore state prior to last LRO, RLO, LRE, RLE) // Alternatives to BMD events for lists, charts, etc. define('WT_EVENTS_BIRT', 'BIRT|CHR|BAPM|_BRTM|ADOP'); define('WT_EVENTS_DEAT', 'DEAT|BURI|CREM'); define('WT_EVENTS_MARR', 'MARR|_NMR'); define('WT_EVENTS_DIV', 'DIV|ANUL|_SEPR'); // Use these line endings when writing files on the server define('WT_EOL', "\r\n"); // Gedcom specification/definitions define ('WT_GEDCOM_LINE_LENGTH', 255 - strlen(WT_EOL)); // Characters, not bytes // Used in Google charts define ('WT_GOOGLE_CHART_ENCODING', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.'); // Privacy constants define('WT_PRIV_PUBLIC', 2); // Allows visitors to view the marked information define('WT_PRIV_USER', 1); // Allows members to access the marked information define('WT_PRIV_NONE', 0); // Allows managers to access the marked information define('WT_PRIV_HIDE', -1); // Hide the item to all users // For performance, it is quicker to refer to files using absolute paths define ('WT_ROOT', realpath(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR); // Keep track of time statistics, for the summary in the footer $start_time = microtime(true); // We want to know about all PHP errors error_reporting(E_ALL | E_STRICT); // PHP5.3 may be using magic-quotes :-( if (version_compare(PHP_VERSION, '5.4', '<') && get_magic_quotes_gpc()) { // http://php.net/manual/en/security.magicquotes.disabling.php $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST); while (list($key, $val) = each($process)) { foreach ($val as $k => $v) { unset($process[$key][$k]); if (is_array($v)) { $process[$key][stripslashes($k)] = $v; $process[] = &$process[$key][stripslashes($k)]; } else { $process[$key][stripslashes($k)] = stripslashes($v); } } } unset($process); } //////////////////////////////////////////////////////////////////////////////// // The ircmaxell/password-compat library does not support unpatched versions of // PHP older than PHP5.3.6. These versions of PHP have no secure crypt library. //////////////////////////////////////////////////////////////////////////////// $hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG'; if (!defined('PASSWORD_BCRYPT') && crypt("password", $hash) !== $hash) { define('PASSWORD_BCRYPT', 1); define('PASSWORD_DEFAULT', 1); /** * @param string $password * @param integer $algo * * @return string */ function password_hash($password, $algo) { return crypt($password); } /** * @param string $hash * @param integer $algo * * @return boolean */ function password_needs_rehash($hash, $algo) { return false; } /** * @param string $password * @param integer $hash * * @return boolean */ function password_verify($password, $hash) { return crypt($password, $hash) === $hash; } } require WT_ROOT . 'library/autoload.php'; // PHP requires a time zone to be set in php.ini if (!ini_get('date.timezone')) { date_default_timezone_set(@date_default_timezone_get()); } // Use the patchwork/utf8 library to: // 1) set all PHP defaults to UTF-8 // 2) create shims for missing mb_string functions such as mb_strlen() // 3) check that requests are valid UTF-8 \Patchwork\Utf8\Bootup::initAll(); // Enables the portablity layer and configures PHP for UTF-8 \Patchwork\Utf8\Bootup::filterRequestUri(); // Redirects to an UTF-8 encoded URL if it's not already the case \Patchwork\Utf8\Bootup::filterRequestInputs(); // Normalizes HTTP inputs to UTF-8 NFC // Use the fisharebest/ext-calendar library to // 1) provide shims for the PHP ext/calendar extension, such as JewishToJD() // 2) provide calendar conversions for the Arabic and Persian calendars \Fisharebest\ExtCalendar\Shim::create(); // Split the request protocol://host:port/path/to/script.php?var=value into parts // WT_SERVER_NAME = protocol://host:port // WT_SCRIPT_PATH = /path/to/ (begins and ends with /) // WT_SCRIPT_NAME = script.php (already defined in the calling script) if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) { $protocol = $_SERVER['HTTP_X_FORWARDED_PROTO']; } elseif (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') { $protocol = 'https'; } else { $protocol = 'http'; } if (isset($_SERVER['HTTP_X_FORWARDED_PORT'])) { $port = $_SERVER['HTTP_X_FORWARDED_PORT']; } elseif (isset($_SERVER['SERVER_PORT'])) { $port = $_SERVER['SERVER_PORT']; } else { $port = '80'; } define('WT_SERVER_NAME', $protocol . '://' . (empty($_SERVER['SERVER_NAME']) ? '' : $_SERVER['SERVER_NAME']) . ($protocol === 'http' && $port === '80' || $protocol === 'https' && $port === '443' ? '' : ':' . $port) ); // REDIRECT_URL should be set in the case of Apache following a RedirectRule // SCRIPT_NAME should always be correct, but is not always present. // PHP_SELF should always be present, but may have trailing path: /path/to/script.php/FOO/BAR if (!empty($_SERVER['REDIRECT_URL'])) { define('WT_SCRIPT_PATH', substr($_SERVER['REDIRECT_URL'], 0, stripos($_SERVER['REDIRECT_URL'], WT_SCRIPT_NAME))); } elseif (!empty($_SERVER['SCRIPT_NAME'])) { define('WT_SCRIPT_PATH', substr($_SERVER['SCRIPT_NAME'], 0, stripos($_SERVER['SCRIPT_NAME'], WT_SCRIPT_NAME))); } elseif (!empty($_SERVER['PHP_SELF'])) { define('WT_SCRIPT_PATH', substr($_SERVER['PHP_SELF'], 0, stripos($_SERVER['PHP_SELF'], WT_SCRIPT_NAME))); } else { // No server settings - probably running as a command line script define('WT_SCRIPT_PATH', '/'); } // Microsoft IIS servers don’t set REQUEST_URI, so generate it for them. if (!isset($_SERVER['REQUEST_URI'])) { $_SERVER['REQUEST_URI'] = substr($_SERVER['PHP_SELF'], 1); if (isset($_SERVER['QUERY_STRING'])) { $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING']; } } // Some browsers do not send a user-agent string if (!isset($_SERVER['HTTP_USER_AGENT'])) { $_SERVER['HTTP_USER_AGENT'] = ''; } // Common functions - move these to classes so we can autoload them. require WT_ROOT . 'includes/functions/functions.php'; require WT_ROOT . 'includes/functions/functions_db.php'; require WT_ROOT . 'includes/functions/functions_print.php'; require WT_ROOT . 'includes/functions/functions_mediadb.php'; require WT_ROOT . 'includes/functions/functions_date.php'; require WT_ROOT . 'includes/functions/functions_charts.php'; require WT_ROOT . 'includes/functions/functions_import.php'; // Set a custom error handler set_error_handler(function ($errno, $errstr) { if (error_reporting() > 0 && $errno < 2048) { if (WT_ERROR_LEVEL == 0) { return false; } $fmt_msg = "
ERROR {$errno}: {$errstr}
"; $log_msg = "ERROR {$errno}: {$errstr};"; // Although debug_backtrace should always exist in PHP5, without this check, PHP sometimes crashes. // Possibly calling it generates an error, which causes infinite recursion?? if ($errno < 16 && function_exists("debug_backtrace") && strstr($errstr, "headers already sent by") === false) { $backtrace = debug_backtrace(); $num = count($backtrace); if (WT_ERROR_LEVEL == 1) { $num = 1; } for ($i = 0; $i < $num; $i++) { if ($i === 0) { $fmt_msg .= "0 Error occurred on "; $log_msg .= "\n0 Error occurred on "; } else { $fmt_msg .= "{$i} called from "; $log_msg .= "\n{$i} called from "; } if (isset($backtrace[$i]["line"]) && isset($backtrace[$i]["file"])) { $fmt_msg .= "line {$backtrace[$i]['line']} of file " . basename($backtrace[$i]['file']) . ""; $log_msg .= "line {$backtrace[$i]['line']} of file " . basename($backtrace[$i]['file']); } if ($i < $num - 1) { $fmt_msg .= " in function " . $backtrace[$i + 1]['function'] . ""; $log_msg .= " in function " . $backtrace[$i + 1]['function']; } $fmt_msg .= "
"; } } echo $fmt_msg; Log::addErrorLog($log_msg); if ($errno == 1) { die(); } } return false; }); // Load our configuration file, so we can connect to the database if (file_exists(WT_ROOT . 'data/config.ini.php')) { $dbconfig = parse_ini_file(WT_ROOT . 'data/config.ini.php'); // Invalid/unreadable config file? if (!is_array($dbconfig)) { header('Location: ' . WT_SERVER_NAME . WT_SCRIPT_PATH . 'site-unavailable.php'); exit; } // Down for maintenance? if (file_exists(WT_ROOT . 'data/offline.txt')) { header('Location: ' . WT_SERVER_NAME . WT_SCRIPT_PATH . 'site-offline.php'); exit; } } else { // No config file. Set one up. header('Location: ' . WT_SERVER_NAME . WT_SCRIPT_PATH . 'setup.php'); exit; } $WT_REQUEST = new Zend_Controller_Request_Http(); // Connect to the database try { WT_DB::createInstance($dbconfig['dbhost'], $dbconfig['dbport'], $dbconfig['dbname'], $dbconfig['dbuser'], $dbconfig['dbpass']); define('WT_TBLPREFIX', $dbconfig['tblpfx']); unset($dbconfig); // Some of the FAMILY JOIN HUSBAND JOIN WIFE queries can excede the MAX_JOIN_SIZE setting WT_DB::exec("SET NAMES 'utf8' COLLATE 'utf8_unicode_ci', SQL_BIG_SELECTS=1"); try { WT_DB::updateSchema(WT_ROOT . 'includes/db_schema/', 'WT_SCHEMA_VERSION', WT_SCHEMA_VERSION); } catch (PDOException $ex) { // The schema update scripts should never fail. If they do, there is no clean recovery. die($ex); } } catch (PDOException $ex) { header('Location: ' . WT_SERVER_NAME . WT_SCRIPT_PATH . 'site-unavailable.php'); exit; } // The config.ini.php file must always be in a fixed location. // Other user files can be stored elsewhere... define('WT_DATA_DIR', realpath(WT_Site::getPreference('INDEX_DIRECTORY') ? WT_Site::getPreference('INDEX_DIRECTORY') : 'data') . DIRECTORY_SEPARATOR); // If we have a preferred URL (e.g. www.example.com instead of www.isp.com/~example), then redirect to it. $SERVER_URL = WT_Site::getPreference('SERVER_URL'); if ($SERVER_URL && $SERVER_URL != WT_SERVER_NAME . WT_SCRIPT_PATH) { header('Location: ' . $SERVER_URL . WT_SCRIPT_NAME . (isset($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : ''), true, 301); exit; } // Request more resources - if we can/want to if (!ini_get('safe_mode')) { $memory_limit = WT_Site::getPreference('MEMORY_LIMIT'); if ($memory_limit && strpos(ini_get('disable_functions'), 'ini_set') === false) { ini_set('memory_limit', $memory_limit); } $max_execution_time = WT_Site::getPreference('MAX_EXECUTION_TIME'); if ($max_execution_time && strpos(ini_get('disable_functions'), 'set_time_limit') === false) { set_time_limit($max_execution_time); } } $rule = WT_DB::prepare( "SELECT SQL_CACHE rule FROM `##site_access_rule`" . " WHERE IFNULL(INET_ATON(?), 0) BETWEEN ip_address_start AND ip_address_end" . " AND ? LIKE user_agent_pattern" . " ORDER BY ip_address_end LIMIT 1" )->execute(array($WT_REQUEST->getClientIp(), $_SERVER['HTTP_USER_AGENT']))->fetchOne(); switch ($rule) { case 'allow': $SEARCH_SPIDER = false; break; case 'deny': header('HTTP/1.1 403 Access Denied'); exit; case 'robot': case 'unknown': // Search engines don’t send cookies, and so create a new session with every visit. // Make sure they always use the same one Zend_Session::setId('search-engine-' . str_replace('.', '-', $WT_REQUEST->getClientIp())); $SEARCH_SPIDER = true; break; case '': WT_DB::prepare( "INSERT INTO `##site_access_rule` (ip_address_start, ip_address_end, user_agent_pattern, comment) VALUES (IFNULL(INET_ATON(?), 0), IFNULL(INET_ATON(?), 4294967295), ?, '')" )->execute(array($WT_REQUEST->getClientIp(), $WT_REQUEST->getClientIp(), $_SERVER['HTTP_USER_AGENT'])); $SEARCH_SPIDER = true; break; } // Store our session data in the database. session_set_save_handler( // open function () { return true; }, // close function () { return true; }, // read function ($id) { return WT_DB::prepare("SELECT session_data FROM `##session` WHERE session_id=?")->execute(array($id))->fetchOne(); }, // write function ($id, $data) use ($WT_REQUEST) { // Only update the session table once per minute, unless the session data has actually changed. WT_DB::prepare( "INSERT INTO `##session` (session_id, user_id, ip_address, session_data, session_time)" . " VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP - SECOND(CURRENT_TIMESTAMP))" . " ON DUPLICATE KEY UPDATE" . " user_id = VALUES(user_id)," . " ip_address = VALUES(ip_address)," . " session_data = VALUES(session_data)," . " session_time = CURRENT_TIMESTAMP - SECOND(CURRENT_TIMESTAMP)" )->execute(array($id, (int)Auth::id(), $WT_REQUEST->getClientIp(), $data)); return true; }, // destroy function ($id) { WT_DB::prepare("DELETE FROM `##session` WHERE session_id=?")->execute(array($id)); return true; }, // gc function ($maxlifetime) { WT_DB::prepare("DELETE FROM `##session` WHERE session_time < DATE_SUB(NOW(), INTERVAL ? SECOND)")->execute(array($maxlifetime)); return true; } ); // Use the Zend_Session object to start the session. // This allows all the other Zend Framework components to integrate with the session define('WT_SESSION_NAME', 'WT_SESSION'); $cfg = array( 'name' => WT_SESSION_NAME, 'cookie_lifetime' => 0, 'gc_maxlifetime' => WT_Site::getPreference('SESSION_TIME'), 'gc_probability' => 1, 'gc_divisor' => 100, 'cookie_path' => WT_SCRIPT_PATH, 'cookie_httponly' => true, ); Zend_Session::start($cfg); // Register a session “namespace” to store session data. This is better than // using $_SESSION, as we can avoid clashes with other modules or applications, // and problems with servers that have enabled “register_globals”. $WT_SESSION = new Zend_Session_Namespace('WEBTREES'); if (!$SEARCH_SPIDER && !$WT_SESSION->initiated) { // A new session, so prevent session fixation attacks by choosing a new PHPSESSID. Zend_Session::regenerateId(); $WT_SESSION->initiated = true; } else { // An existing session } /** @deprecated Will be removed in 1.7.0 */ define('WT_USER_ID', Auth::id()); /** @deprecated Will be removed in 1.7.0 */ define('WT_USER_NAME', Auth::id() ? Auth::user()->getUserName() : ''); // Set the active GEDCOM if (isset($_REQUEST['ged'])) { // .... from the URL or form action $GEDCOM = $_REQUEST['ged']; } elseif ($WT_SESSION->GEDCOM) { // .... the most recently used one $GEDCOM = $WT_SESSION->GEDCOM; } else { // Try the site default $GEDCOM = WT_Site::getPreference('DEFAULT_GEDCOM'); } // Choose the selected tree (if it exists), or any valid tree otherwise $WT_TREE = null; foreach (WT_Tree::getAll() as $tree) { $WT_TREE = $tree; if ($WT_TREE->tree_name == $GEDCOM && ($WT_TREE->imported || Auth::isAdmin())) { break; } } // These attributes of the currently-selected tree are used frequently if ($WT_TREE) { define('WT_GEDCOM', $WT_TREE->tree_name); define('WT_GED_ID', $WT_TREE->tree_id); define('WT_GEDURL', $WT_TREE->tree_name_url); define('WT_TREE_TITLE', $WT_TREE->tree_title_html); define('WT_IMPORTED', $WT_TREE->imported); define('WT_USER_GEDCOM_ADMIN', Auth::isManager($WT_TREE)); define('WT_USER_CAN_ACCEPT', Auth::isModerator($WT_TREE)); define('WT_USER_CAN_EDIT', Auth::isEditor($WT_TREE)); define('WT_USER_CAN_ACCESS', Auth::isMember($WT_TREE)); define('WT_USER_GEDCOM_ID', $WT_TREE->getUserPreference(Auth::user(), 'gedcomid')); define('WT_USER_ROOT_ID', $WT_TREE->getUserPreference(Auth::user(), 'rootid') ? $WT_TREE->getUserPreference(Auth::user(), 'rootid') : WT_USER_GEDCOM_ID); define('WT_USER_PATH_LENGTH', $WT_TREE->getUserPreference(Auth::user(), 'RELATIONSHIP_PATH_LENGTH')); if (WT_USER_GEDCOM_ADMIN) { define('WT_USER_ACCESS_LEVEL', WT_PRIV_NONE); } elseif (WT_USER_CAN_ACCESS) { define('WT_USER_ACCESS_LEVEL', WT_PRIV_USER); } else { define('WT_USER_ACCESS_LEVEL', WT_PRIV_PUBLIC); } load_gedcom_settings(WT_GED_ID); } else { define('WT_GEDCOM', ''); define('WT_GED_ID', null); define('WT_GEDURL', ''); define('WT_TREE_TITLE', WT_WEBTREES); define('WT_IMPORTED', false); define('WT_USER_GEDCOM_ADMIN', false); define('WT_USER_CAN_ACCEPT', false); define('WT_USER_CAN_EDIT', false); define('WT_USER_CAN_ACCESS', false); define('WT_USER_GEDCOM_ID', ''); define('WT_USER_ROOT_ID', ''); define('WT_USER_PATH_LENGTH', 0); define('WT_USER_ACCESS_LEVEL', WT_PRIV_PUBLIC); } $GEDCOM = WT_GEDCOM; // With no parameters, init() looks to the environment to choose a language define('WT_LOCALE', WT_I18N::init()); $WT_SESSION->locale = WT_I18N::$locale; // Set our gedcom selection as a default for the next page $WT_SESSION->GEDCOM = WT_GEDCOM; if (empty($WEBTREES_EMAIL)) { $WEBTREES_EMAIL = 'webtrees-noreply@' . preg_replace('/^www\./i', '', $_SERVER['SERVER_NAME']); } // Note that the database/webservers may not be synchronised, so use DB time throughout. define('WT_TIMESTAMP', (int)WT_DB::prepare("SELECT UNIX_TIMESTAMP()")->fetchOne()); // Server timezone is defined in php.ini define('WT_SERVER_TIMESTAMP', WT_TIMESTAMP + (int)date('Z')); if (Auth::check()) { define('WT_CLIENT_TIMESTAMP', WT_TIMESTAMP - $WT_SESSION->timediff); } else { define('WT_CLIENT_TIMESTAMP', WT_SERVER_TIMESTAMP); } define('WT_CLIENT_JD', 2440588 + (int)(WT_CLIENT_TIMESTAMP / 86400)); // Application configuration data - things that aren’t (yet?) user-editable require WT_ROOT . 'includes/config_data.php'; // The login URL must be an absolute URL, and can be user-defined if (WT_Site::getPreference('LOGIN_URL')) { define('WT_LOGIN_URL', WT_Site::getPreference('LOGIN_URL')); } else { define('WT_LOGIN_URL', WT_SERVER_NAME . WT_SCRIPT_PATH . 'login.php'); } // If there is no current tree and we need one, then redirect somewhere if (WT_SCRIPT_NAME != 'admin_trees_manage.php' && WT_SCRIPT_NAME != 'admin_pgv_to_wt.php' && WT_SCRIPT_NAME != 'login.php' && WT_SCRIPT_NAME != 'logout.php' && WT_SCRIPT_NAME != 'import.php' && WT_SCRIPT_NAME != 'help_text.php' && WT_SCRIPT_NAME != 'message.php') { if (!$WT_TREE || !WT_IMPORTED) { if (Auth::isAdmin()) { header('Location: ' . WT_SERVER_NAME . WT_SCRIPT_PATH . 'admin_trees_manage.php'); } else { header('Location: ' . WT_LOGIN_URL . '?url=' . rawurlencode(WT_SCRIPT_NAME . (isset($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : '')), true, 301); } exit; } } // Update the login time every 5 minutes if (WT_TIMESTAMP - $WT_SESSION->activity_time > 300) { Auth::user()->setPreference('sessiontime', WT_TIMESTAMP); $WT_SESSION->activity_time = WT_TIMESTAMP; } // Set the theme if (substr(WT_SCRIPT_NAME, 0, 5) == 'admin' || WT_SCRIPT_NAME == 'module.php' && substr(WT_Filter::get('mod_action'), 0, 5) == 'admin') { // Administration scripts begin with “admin” and use a special administration theme define('WT_THEME_DIR', WT_THEMES_DIR . '_administration/'); } else { if (WT_Site::getPreference('ALLOW_USER_THEMES')) { // Requested change of theme? $THEME_DIR = WT_Filter::get('theme'); if (!in_array($THEME_DIR, get_theme_names())) { $THEME_DIR = ''; } // Last theme used? if (!$THEME_DIR && in_array($WT_SESSION->theme_id, get_theme_names())) { $THEME_DIR = $WT_SESSION->theme_id; } } else { $THEME_DIR = ''; } if (!$THEME_DIR) { // User cannot choose (or has not chosen) a theme. // 1) gedcom setting // 2) site setting // 3) webtrees // 4) first one found if (WT_GED_ID) { $THEME_DIR = $WT_TREE->getPreference('THEME_DIR'); } if (!in_array($THEME_DIR, get_theme_names())) { $THEME_DIR = WT_Site::getPreference('THEME_DIR'); } if (!in_array($THEME_DIR, get_theme_names())) { $THEME_DIR = 'webtrees'; } if (!in_array($THEME_DIR, get_theme_names())) { list($THEME_DIR) = get_theme_names(); } } define('WT_THEME_DIR', WT_THEMES_DIR . $THEME_DIR . '/'); // Remember this setting if (WT_THEME_DIR != WT_THEMES_DIR . '_administration/') { $WT_SESSION->theme_id = $THEME_DIR; } } // If we have specified a CDN, use it for static theme resources define('WT_THEME_URL', WT_STATIC_URL . WT_THEME_DIR); require WT_ROOT . WT_THEME_DIR . 'theme.php'; // Page hit counter - load after theme, as we need theme formatting if ($WT_TREE && $WT_TREE->getPreference('SHOW_COUNTER') && !$SEARCH_SPIDER) { require WT_ROOT . 'includes/hitcount.php'; } else { $hitCount = ''; } // Search engines are only allowed to see certain pages. if ($SEARCH_SPIDER && !in_array(WT_SCRIPT_NAME, array( 'index.php', 'indilist.php', 'module.php', 'mediafirewall.php', 'individual.php', 'family.php', 'mediaviewer.php', 'note.php', 'repo.php', 'source.php', ))) { header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden'); $controller = new WT_Controller_Page(); $controller->setPageTitle(WT_I18N::translate('Search engine')); $controller->pageHeader(); echo '

', WT_I18N::translate('You do not have permission to view this page.'), '

'; exit; }