$type, 'message' => $message, 'file' => $file, 'line' => $line ); switch ($type) { case MSG_NOTICE : break; case MSG_SUCCESS : break; case MSG_WARNING : break; case MSG_ERROR : case MSG_ERR : default : break; } } /** * Logs a message to a user defined log file. Additional actions to take for * different types of message types can be specified (ERROR, NOTICE, etc). * * @access public * * @param string $message The text description of the message. * @param int $priority The type of message priority (in descending order): * LOG_EMERG system is unusable * LOG_ALERT action must be taken immediately * LOG_CRIT critical conditions * LOG_ERR error conditions * LOG_WARNING warning conditions * LOG_NOTICE normal, but significant, condition * LOG_INFO informational message * LOG_DEBUG debug-level message * @param string $file The file where the log event occurs. * @param string $line The line of the file where the log event occurs. */ function logMsg($message, $priority=LOG_INFO, $file=null, $line=null) { global $CFG; // If priority is not specified, assume the worst. if (!priorityToString($priority)) { logMsg(sprintf('Log priority %s not defined. (Message: %s)', $priority, $message), LOG_EMERG, $file, $line); $priority = LOG_EMERG; } // If log file is not specified, create one in the codebase root. if (!is_dir($CFG->log_directory) || !is_writable($CFG->log_directory)) { // We must use trigger_error rather than calling logMsg, which might lead to an infinite loop. trigger_error(sprintf('Codebase error: log directory (%s) not found or writable.', $CFG->log_directory), E_USER_ERROR); } // Data to be stored for a log event. $event = array(); $event['date'] = date('Y-m-d H:i:s'); $event['remote ip'] = getRemoteAddr(); $event['type'] = priorityToString($priority); $event['file:line'] = $file . " : $line"; $event['pid'] = posix_getpid(); $event['message'] = "$message"; $event_str = strip_tags('[' . preg_replace('/\s{2,}/', ' ', join('] [', $event)) . ']'); // FILE ACTION if ($priority <= $CFG->log_file_priority && $CFG->log_file_priority) { error_log($event_str . "\n", 3, $CFG->log_directory . '/' . $CFG->log_filename); } // EMAIL ACTION if ($priority <= $CFG->log_email_priority && $CFG->log_email_priority) { if (empty($CFG->log_to_email)) { $CFG->log_to_email = 'bug@strangecode.com'; } $subject = sprintf('[%s %s] %s', getenv('HTTP_HOST'), $event['type'], $message); $email_msg = sprintf("A %s log event occured on %s\n\n", $event['type'], getenv('HTTP_HOST')); $headers = "From: codebase@strangecode.com\r\n"; foreach ($event as $k=>$v) { $email_msg .= sprintf("%-11s%s\n", $k, $v); } mail($CFG->log_to_email, $subject, $email_msg, $headers, '-f codebase@strangecode.com'); } // SMS ACTION if ($priority <= $CFG->log_sms_priority && $CFG->log_sms_priority) { if (empty($CFG->log_to_email)) { $CFG->log_to_sms = 'bug@strangecode.com'; } $subject = '[' . getenv('HTTP_HOST') . ' log event]'; $headers = "From: codebase@strangecode.com\r\n"; mail($CFG->log_to_sms, $subject, $event_str, $headers, '-f codebase@strangecode.com'); } // SCREEN ACTION if ($priority <= $CFG->log_screen_priority && $CFG->log_screen_priority) { echo "[{$event['date']}] [{$event['type']}] [{$event['file:line']}] [{$event['message']}]\n"; } } /** * Returns the string representation of a LOG_* integer constant. * * @param int $priority The LOG_* integer constant. * * @return The string representation of $priority. */ function priorityToString ($priority) { $priorities = array( LOG_EMERG => 'emergency', LOG_ALERT => 'alert', LOG_CRIT => 'critical', LOG_ERR => 'error', LOG_WARNING => 'warning', LOG_NOTICE => 'notice', LOG_INFO => 'info', LOG_DEBUG => 'debug' ); if (isset($priorities[$priority])) { return $priorities[$priority]; } else { return false; } } /** * Set the URL to return to when dieBoomerangURL() is called. * * @param string $url A fully validated URL. * @param bool $id An identification tag for this url. * FIXME: url garbage collection? */ function setBoomerangURL($url=null, $id=null) { // A redirection will never happen immediatly after setting the boomerangURL. // Set the time so ensure this doesn't happen. See validBoomerangURL for more. if (isset($url) && is_string($url)) { // Delete any boomerang request keys in the query string. $url = preg_replace('/boomerang=[\w]+/', '', $url); if (is_array($_SESSION['_boomerang']['url']) && !empty($_SESSION['_boomerang']['url'])) { // If the URL currently exists in the boomerang array, delete. while ($existing_key = array_search($url, $_SESSION['_boomerang']['url'])) { unset($_SESSION['_boomerang']['url'][$existing_key]); } } if (isset($id)) { $_SESSION['_boomerang']['url'][$id] = $url; } else { $_SESSION['_boomerang']['url'][] = $url; } logMsg(sprintf('setBoomerangURL added URL %s to session %s=%s', $url, session_name(), session_id()), LOG_DEBUG, __FILE__, __LINE__); return true; } else { return false; } } /** * Return the URL set for the specified $id. * * @param string $id An identification tag for this url. */ function getBoomerangURL($id=null) { if (isset($id)) { if (isset($_SESSION['_boomerang']['url'][$id])) { return $_SESSION['_boomerang']['url'][$id]; } else { return ''; } } else if (is_array($_SESSION['_boomerang']['url'])) { return end($_SESSION['_boomerang']['url']); } else { return false; } } /** * Delete the URL set for the specified $id. * * @param string $id An identification tag for this url. */ function deleteBoomerangURL($id=null) { if (isset($id) && isset($_SESSION['_boomerang']['url'][$id])) { unset($_SESSION['_boomerang']['url'][$id]); } else if (is_array($_SESSION['_boomerang']['url'])) { array_pop($_SESSION['_boomerang']['url']); } } /** * Check if a valid boomerang URL value has been set. * if it is not the current url, and has not been accessed within n seconds. * * @return bool True if it is set and not the current URL. */ function validBoomerangURL($id=null, $use_nonspecific_boomerang=false) { if (!isset($_SESSION['_boomerang']['url'])) { logMsg(sprintf('validBoomerangURL no URL set in session %s=%s %s', session_name(), session_id(), getDump($_SESSION)), LOG_DEBUG, __FILE__, __LINE__); return false; } // Time is the timestamp of a boomerangURL redirection, or setting of a boomerangURL. // a boomerang redirection will always occur at least several seconds after the last boomerang redirect // or a boomerang being set. $boomerang_time = isset($_SESSION['_boomerang']['time']) ? $_SESSION['_boomerang']['time'] : 0; if (isset($id) && isset($_SESSION['_boomerang']['url'][$id])) { $url = $_SESSION['_boomerang']['url'][$id]; } else if (!isset($id) || $use_nonspecific_boomerang) { // Use non specific boomerang if available. $url = end($_SESSION['_boomerang']['url']); } logMsg(sprintf('validBoomerangURL testing url: %s', $url), LOG_DEBUG, __FILE__, __LINE__); if (empty($url)) { return false; } if ($url == absoluteMe()) { // The URL we are directing to is not the current page. logMsg(sprintf('Boomerang URL not valid, same as absoluteMe: %s', $url), LOG_WARNING, __FILE__, __LINE__); return false; } if ($boomerang_time >= (time() - 2)) { // Last boomerang direction was more than 2 seconds ago. logMsg(sprintf('Boomerang URL not valid, boomerang_time too short: %s', time() - $boomerang_time), LOG_WARNING, __FILE__, __LINE__); return false; } return true; } /** * Redirects a user by calling the dieURL(). It will use: * 1. the stored boomerang URL, it it exists * 2. the referring URL, it it exists. * 3. an empty string, which will force dieURL to use the default URL. */ function dieBoomerangURL($id=null, $carry_args=null) { // Get URL from stored boomerang. Allow non specific URL if ID not valid. if (validBoomerangURL($id, true)) { if (isset($id) && isset($_SESSION['_boomerang']['url'][$id])) { $url = $_SESSION['_boomerang']['url'][$id]; } else { $url = end($_SESSION['_boomerang']['url']); } } else if (!refererIsMe() && !preg_match('/admin_common/', getenv('SCRIPT_NAME'))) { // Ensure that the redirecting page is not also the referrer. // admin_common is an alias of 'admin', which confuses this function. Just here for local testing. $url = getenv('HTTP_REFERER'); } else { $url = ''; } logMsg(sprintf('dieBoomerangURL found URL: %s', $url), LOG_DEBUG, __FILE__, __LINE__); // Delete stored boomerang. deleteBoomerangURL($id); // A redirection will never happen immediatly twice. // Set the time so ensure this doesn't happen. $_SESSION['_boomerang']['time'] = time(); dieURL($url, $carry_args); } /** * Uses an http header to redirect the client to the given $url. If sessions are not used * and the session is not already defined in the given $url, the SID is appended as a URI query. * As with all header generating functions, make sure this is called before any other output. * * @param string $url The URL the client will be redirected to. * @param mixed $carry_args Additional url arguments to carry in the query, * or FALSE to prevent carrying queries. Can be any of the following formats: * -array('key1', key2', key3') <-- to save these keys if in the form data. * -array('key1'=>'value', key2'='value') <-- to set keys to default values if not present in form data. * -false <-- To not carry any queries. If URL already has queries those will be retained. * @param bool $always_include_sid Force session id to be added to Location header. */ function dieURL($url, $carry_args=null, $always_include_sid=false) { global $CFG; if ('' == $url) { // If URL is not specified, use the redirect_home. $url = $CFG->redirect_home; } if (preg_match('!^/!', $url)) { // If relative URL is given, prepend correct local hostname. $hostname = ('on' == getenv('HTTPS')) ? 'https://' . getenv('HTTP_HOST') : 'http://' . getenv('HTTP_HOST'); $url = $hostname . $url; } $url = url($url, $carry_args, $always_include_sid); header(sprintf('Location: %s', $url)); logMsg(sprintf('dieURL dying to URL: %s', $url), LOG_DEBUG, __FILE__, __LINE__); die; } /** * Prints a hidden form element with the PHPSESSID when cookies are not used, as well * as hidden form elements for GET_VARS that might be in use. * * @global string $carry_queries An array of keys to define which values to * carry through from the POST or GET. * $carry_queries = array('qry'); for example * * @param mixed $carry_args Additional url arguments to carry in the query, * or FALSE to prevent carrying queries. Can be any of the following formats: * -array('key1', key2', key3') <-- to save these keys if in the form data. * -array('key1'=>'value', key2'='value') <-- to set keys to default values if not present in form data. * -false <-- To not carry any queries. If URL already has queries those will be retained. */ function printHiddenSession($carry_args=null) { static $_using_trans_sid; global $carry_queries; // Save the trans_sid setting. if (!isset($_using_trans_sid)) { $_using_trans_sid = ini_get('session.use_trans_sid'); } // Initialize the carried queries. if (!isset($carry_queries['_carry_queries_init'])) { if (!is_array($carry_queries)) { $carry_queries = array($carry_queries); } $tmp = $carry_queries; $carry_queries = array(); foreach ($tmp as $key) { if (!empty($key) && getFormData($key, false)) { $carry_queries[$key] = getFormData($key); } } $carry_queries['_carry_queries_init'] = true; } // Get any additional query names to add to the $carry_queries array // that are found as function arguments. // If FALSE is a function argument, DO NOT carry the queries. $do_carry_queries = true; if (!is_null($carry_args)) { if (is_array($carry_args) && !empty($carry_args)) { foreach ($carry_args as $key=>$arg) { // Get query from appropriate source. if (false === $arg) { $do_carry_queries = false; } else if (false !== getFormData($arg, false)) { $one_time_carry_queries[$arg] = getFormData($arg); // Set arg to form data if available. } else if (!is_numeric($key) && '' != $arg) { $one_time_carry_queries[$key] = getFormData($key, $arg); // Set to arg to default if specified (overwritten by form data). } } } else if (false !== getFormData($carry_args, false)) { $one_time_carry_queries[$carry_args] = getFormData($carry_args); } else if (false === $carry_args) { $do_carry_queries = false; } } // For each existing POST value, we create a hidden input to carry it through a form. if ($do_carry_queries) { // Join the perm and temp carry_queries and filter out the _carry_queries_init element for the final query args. $query_args = array_diff_assoc(urlEncodeArray(array_merge($carry_queries, $one_time_carry_queries)), array('_carry_queries_init' => true)); foreach ($query_args as $key=>$val) { echo ''; } } // Include the SID if cookies are disabled. if (!isset($_COOKIE[session_name()]) && !$_using_trans_sid) { echo ''; } } /** * Outputs a fully qualified URL with a query of all the used (ie: not empty) * keys and values, including optional queries. This allows simple printing of * links without needing to know which queries to add to it. If cookies are not * used, the session id will be propogated in the URL. * * @global string $carry_queries An array of keys to define which values to * carry through from the POST or GET. * $carry_queries = array('qry'); for example. * * @param string $url The initial url * @param mixed $carry_args Additional url arguments to carry in the query, * or FALSE to prevent carrying queries. Can be any of the following formats: * -array('key1', key2', key3') <-- to save these keys if in the form data. * -array('key1'=>'value', key2'='value') <-- to set keys to default values if not present in form data. * -false <-- To not carry any queries. If URL already has queries those will be retained. * * @param mixed $always_include_sid Always add the session id, even if using_trans_sid = true. This is required when * URL starts with http, since PHP using_trans_sid doesn't do those and also for * header('Location...') redirections. * * @return string url with attached queries and, if not using cookies, the session id */ function url($url='', $carry_args=null, $always_include_sid=false) { static $_using_trans_sid; global $carry_queries; global $CFG; // Save the trans_sid setting. if (!isset($_using_trans_sid)) { $_using_trans_sid = ini_get('session.use_trans_sid'); } // Initialize the carried queries. if (!isset($carry_queries['_carry_queries_init'])) { if (!is_array($carry_queries)) { $carry_queries = array($carry_queries); } $tmp = $carry_queries; $carry_queries = array(); foreach ($tmp as $key) { if (!empty($key) && getFormData($key, false)) { $carry_queries[$key] = getFormData($key); } } $carry_queries['_carry_queries_init'] = true; } // Get any additional query arguments to add to the $carry_queries array. // If FALSE is a function argument, DO NOT carry the queries. $do_carry_queries = true; if (!is_null($carry_args)) { if (is_array($carry_args) && !empty($carry_args)) { foreach ($carry_args as $key=>$arg) { // Get query from appropriate source. if (false === $arg) { $do_carry_queries = false; } else if (false !== getFormData($arg, false)) { $one_time_carry_queries[$arg] = getFormData($arg); // Set arg to form data if available. } else if (!is_numeric($key) && '' != $arg) { $one_time_carry_queries[$key] = getFormData($key, $arg); // Set to arg to default if specified (overwritten by form data). } } } else if (false !== getFormData($carry_args, false)) { $one_time_carry_queries[$carry_args] = getFormData($carry_args); } else if (false === $carry_args) { $do_carry_queries = false; } } // Get the first delimiter that is needed in the url. $delim = preg_match('/\?/', $url) ? ini_get('arg_separator.output') : '?'; $q = ''; if ($do_carry_queries) { // Join the perm and temp carry_queries and filter out the _carry_queries_init element for the final query args. $query_args = array_diff_assoc(urlEncodeArray(array_merge($carry_queries, $one_time_carry_queries)), array('_carry_queries_init' => true)); foreach ($query_args as $key=>$val) { // Check value is set and value does not already exist in the url. if (!preg_match('/[?&]' . preg_quote($key) . '=/', $url)) { $q .= $delim . $key . '=' . $val; $delim = ini_get('arg_separator.output'); } } } // Include the necessary SID if the following is true: // - no cookie in http request OR cookies disabled in config // - sessions are enabled // - the link stays on our site // - transparent SID propogation with session.use_trans_sid is not being used OR url begins with protocol (using_trans_sid has no effect here) // OR // - we must include the SID because we say so (it's used in a context where cookies will not be effective, ie. moving from http to https) // AND // - the SID is not already in the query. if ( ( ( ( !isset($_COOKIE[session_name()]) || !$CFG->session_use_cookies ) && $CFG->enable_session && isMyDomain($url) && ( !$_using_trans_sid || preg_match('!^(http|https)://!i', $url) ) ) || $always_include_sid ) && !preg_match('/[?&]' . preg_quote(session_name()) . '=/', $url) ) { $url .= $q . $delim . session_name() . '=' . session_id(); // logMsg(sprintf('oHREF appending session id to URL: %s', $url), LOG_DEBUG, __FILE__, __LINE__); } else { $url .= $q; } return $url; } /** * Returns a URL processed with App::url and htmlentities for printing in html. * * @access public * @param string $url Input URL to parse. * @return string URL with App::url() and htmlentities() applied. * @author Quinn Comendant * @since 09 Dec 2005 17:58:45 */ function oHREF($url, $carry_args=null, $always_include_sid=false) { $url = url($url, $carry_args, $always_include_sid); // Replace any & not followed by an html or unicode entity with it's & equivalent. $url = preg_replace('/&(?![\w\d#]{1,10};)/', '&', $url); return $url; } /** * Force the user to connect via https (port 443) by redirecting them to * the same page but with https. */ function sslOn() { global $CFG; if (function_exists('apache_get_modules')) { $modules = apache_get_modules(); } else { // It's safe to assume we have mod_ssl if we can't determine otherwise. $modules = array('mod_ssl'); } if ('on' != getenv('HTTPS') && $CFG->ssl_enabled && in_array('mod_ssl', $modules)) { raiseMsg(sprintf(_("Secure SSL connection made to %s"), $CFG->ssl_domain), MSG_NOTICE, __FILE__, __LINE__); // Always append session because some browsers do not send cookie when crossing to SSL URL. dieURL('https://' . $CFG->ssl_domain . getenv('REQUEST_URI'), null, true); } } /** * to enforce the user to connect via http (port 80) by redirecting them to * a http version of the current url. */ function sslOff() { if ('on' == getenv('HTTPS')) { dieURL('http://' . getenv('HTTP_HOST') . getenv('REQUEST_URI'), null, true); } } /** * If the given $url is on the same web site, return true. This can be used to * prevent from sending sensitive info in a get query (like the SID) to another * domain. $method can be "ip" or "domain". The domain method might be preferred * if your domain spans mutiple IP's (load sharing servers) * * @param string $url the URI to test. * @param mixed $method the method to use. Either 'domain' or 'ip'. * * @return bool true if given $url is this domain or has no domain (is a * relative url), false if it's another */ function isMyDomain($url) { if (!preg_match('|\w{1,}\.\w{2,5}/|', $url)) { // If we can't find a domain we assume the URL is relative. return true; } else { return preg_match('/' . preg_quote(getenv('HTTP_HOST')) . '/', $url); } } /** * Loads a list of tables in the current database into an array, and returns * true if the requested table is found. Use this function to enable/disable * funtionality based upon the current available db tables. * * @param string $table The name of the table to search. * * @return bool true if given $table exists. */ function dbTableExists($table) { static $existing_tables; // Save the trans_sid setting. if (!isset($existing_tables)) { // Get DB tables. $existing_tables = array(); $qid = dbQuery("SHOW TABLES"); while (list($row) = mysql_fetch_row($qid)) { $existing_tables[] = $row; } } // Test if requested table is in database. return in_array($table, $existing_tables); } /** * Takes a URL and returns it without the query or anchor portion * * @param string $url any kind of URI * * @return string the URI with ? or # and everything after removed */ function stripQuery($url) { return preg_replace('![?#].*!', '', $url); } /** * Returns the remote IP address, taking into consideration proxy servers. * * @param bool $dolookup If true we resolve to IP to a host name, * if false we don't. * * @return string IP address if $dolookup is false or no arg * Hostname if $dolookup is true */ function getRemoteAddr($dolookup=false) { $ip = getenv('HTTP_CLIENT_IP'); if (empty($ip) || $ip == 'unknown' || $ip == 'localhost' || $ip == '127.0.0.1') { $ip = getenv('HTTP_X_FORWARDED_FOR'); if (empty($ip) || $ip == 'unknown' || $ip == 'localhost' || $ip == '127.0.0.1') { $ip = getenv('REMOTE_ADDR'); } } return $dolookup ? gethostbyaddr($ip) : $ip; } /** * Tests whether a given iP address can be found in an array of IP address networks. * Elements of networks array can be single IP addresses or an IP address range in CIDR notation * See: http://en.wikipedia.org/wiki/Classless_inter-domain_routing * * @access public * * @param string IP address to search for. * @param array Array of networks to search within. * * @return mixed Returns the network that matched on success, false on failure. */ function ipInRange($my_ip, $ip_pool) { if (!is_array($ip_pool)) { $ip_pool = array($ip_pool); } $my_ip_binary = sprintf('%032b', ip2long($my_ip)); foreach ($ip_pool as $ip) { if (preg_match('![\d\.]{7,15}/\d{1,2}!', $ip)) { // IP is in CIDR notation. list($cidr_ip, $cidr_bitmask) = split('/', $ip); $cidr_ip_binary = sprintf('%032b', ip2long($cidr_ip)); if (substr($my_ip_binary, 0, $cidr_bitmask) === substr($cidr_ip_binary, 0, $cidr_bitmask)) { // IP address is within the specified IP range. return $ip; } } else { if ($my_ip === $ip) { // IP address exactly matches. return $ip; } } } return false; } /** * Returns a fully qualified URL to the current script, including the query. * * @return string a full url to the current script */ function absoluteMe() { $protocol = ('on' == getenv('HTTPS')) ? 'https://' : 'http://'; return $protocol . getenv('HTTP_HOST') . getenv('REQUEST_URI'); } /** * Compares the current url with the referring url. * * @param string $compary_query Include the query string in the comparison. * * @return bool true if the current script (or specified valid_referer) * is the referrer. false otherwise. */ function refererIsMe($exclude_query=false) { if ($exclude_query) { return (stripQuery(absoluteMe()) == stripQuery(getenv('HTTP_REFERER'))); } else { return (absoluteMe() == getenv('HTTP_REFERER')); } } ?>