$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(
'date' => date('Y-m-d H:i:s'),
'remote ip' => getRemoteAddr(),
'pid' => (substr(PHP_OS, 0, 3) != 'WIN' ? posix_getpid() : ''),
'type' => priorityToString($priority),
'file:line' => "$file : $line",
'url' => (isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''),
'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'));
}
}
?>