$test[$n_components - 1]; foreach( $test as $i ) { if( count($coordinates) > $i ) { $value = 0.0 + $geo; if( $value < -180 || $value > 180 ) $result = FALSE; } } return $result; } else { // error return FALSE; } } } /** * Valid value * * Inputs: * - value value * - digitsb digits before point * - digitsa digits after point * - Empty_valid An empty number also valid? * * Return: 1(OK)/0(Error) */ function valid_value($value, $empty_valid = 1, $digitsb = 10, $digitsa = 2) { $before = ($digitsb - $digitsa); if ($empty_valid) { $result = ((preg_match("/^[0-9]{0,$before}(\.[0-9]{0,$digitsa})?$/", $value)) || (!strlen($value))); } else { $result = (preg_match("/^[0-9]{0,$before}(\.[0-9]{0,$digitsa})?$/", $value)); } return $result; } /** * Convert date * * Inputs: * - date Input date/ * - from_unix Convert from (0) or to (1) unix timestamp * * Return: unix date */ function convert_date($date, $from_unix = 0) { if (strlen($date)) { if ($from_unix) { $result = date('Y-m-d', $date); } else { $array = explode("-", $date); $result = mktime(0,0,0,$array[1],$array[2],$array[0]); } } else { $result = ""; } return $result; } /** * Convert datetime * * Inputs: * - date Input date/timestamp * - from_unix Convert from (0) or to (1) unix timestamp * * Return: unix timestamp/date */ function convert_datetime($datetime, $from_unix = 0) { // Initial values $result = ""; if (strlen($datetime)) { if ($from_unix) { // Y2K+38 BUG!! if ($datetime < 2145913200) { $result = date('Y-m-d H:i:s', $datetime); } else { DBG("Y2K+38 BUG!"); } } else { $array = explode(" ", $datetime); $date = ((count($array) > 0) && strlen($array[0])) ? explode("-", $array[0]) : array("0","0","0"); $time = ((count($array) > 1) && strlen($array[1])) ? explode(":", $array[1]) : array("0","0","0"); $result = mktime(intval($time[0]),intval($time[1]),intval($time[2]),intval($date[1]),intval($date[2]),intval($date[0])); } } return $result; } /** * Convert date/time to ISO 8601 date/time string * * Inputs: * - date Input date/timestamp * - flags ISO8601_xxx flags (orred) * * Return: ISO 8601 formatted string */ define("ISO8601_DEFAULT", 0); define("ISO8601_WITH_DATE", 0); // placeholder define("ISO8601_WITH_TIME", 0); // placeholder define("ISO8601_NO_DATE", 0x0001); define("ISO8601_NO_TIME", 0x0002); define("ISO8601_WITH_TZ", 0x0010); function iso8601($datetime, $flags = ISO8601_DEFAULT) { if( !is_numeric($datetime) ) $datetime = convert_datetime($datetime, FALSE); // Build format string $fmt = ""; if( !($flags & ISO8601_NO_DATE) ) $fmt .= "%Y%m%d"; if( !($flags & (ISO8601_NO_DATE | ISO8601_NO_TIME)) ) $fmt .= "T"; if( !($flags & ISO8601_NO_TIME) ) $fmt .= "%H%M%S"; if( ($flags & ISO8601_WITH_TZ) ) $fmt .= "%z"; return strftime($fmt, $datetime); } /** * Input is a date/time string? */ function is_date($str) { if( !is_string($str) ) return FALSE; $t = strtotime($str); return !($t === FALSE) && !($t < 0); } /** * Valid start/end date * * Inputs: * - start Start date * - end End date * * Return: 1(OK)/0(Error) */ function valid_start_end_date($start, $end) { $result = 0; if ((strlen($start)) && (strlen($end))) { $start_stamp = convert_date($start); $end_stamp = convert_date($end); // Check if end date is not before start date if ($start_stamp < $end_stamp) { $result = 1; } } else { $result = 1; } return $result; } /** * Valid gps timestamp * * Inputs: * - timestamp * * Return: 1(OK)/0(Error) */ function valid_gps_timestamp($timestamp) { // Initial values $result = 0; if (strlen($timestamp)) { $array = explode(" ", $timestamp); $date = explode("-", $array[0]); // No gps date => 1 jan 1970 $result = ($date[0] == 1970) ? 0 : 1; if ($result) { // 1 day after now? $result = (convert_datetime($timestamp) >= convert_datetime(date('Y-m-d H:i:s')) + 86400) ? 0 : $result; } } return $result; } /** * Valid start/end datetime * * Inputs: * - start_date Start date * - start_time Start time * - end_date End date * - end_time End time * * Return: 1(OK)/0(Error) */ function valid_start_end_datetime($start_date, $start_time, $end_date, $end_time) { $result = 0; if ((strlen($start_date)) && (strlen($end_date))) { $start_stamp = convert_datetime($start_date . " " . $start_time); $end_stamp = convert_datetime($end_date . " " . $end_time); // Check if end date is not before start date if ($start_stamp < $end_stamp) { $result = 1; } } else { $result = 1; } return $result; } /** * Valid timestamp * * Inputs: * - begin Begin date/datetime * - eind Eind date/datetime * - datetime (1) datetime/ (0) date * * Return: 1(OK)/0(Error) */ function valid_timestamp($begin, $eind, $datetime = 0) { $result = 1; // retrieve current timestamp $current = ($datetime) ? convert_datetime(date('Y-m-d H:i:s')) : convert_date(date('Y-m-d')); // Convert database begin/end stamp $begin = ($datetime) ? convert_datetime($begin) : convert_date($begin); $end = ($datetime) ? convert_datetime($eind) : convert_date($eind); if ((strlen($begin)) && (strlen($end))) { if (($current < $begin) || ($current > $end)) { $result = 0; } } else if (strlen($begin)) { if ($current < $begin) { $result = 0; } } else if (strlen($end)) { if ($current > $end) { $result = 0; } } return $result; } /** * convert timeperiod => valid timeperiod * * Inputs: * - begin Begin date/datetime * - eind Eind date/datetime * - begin_period Begin period * - end_period End period * * Return: array containing begin/end */ function convert_timeperiod($begin, $end, $begin_period, $end_period) { $result = ""; // Convert begin/end stamps $begin_period = (strlen($begin_period)) ? convert_datetime($begin_period) : ""; $end_period = (strlen($end_period)) ? convert_datetime($end_period) : ""; $begin = (strlen($begin)) ? convert_datetime($begin) : ""; $end = (strlen($end)) ? convert_datetime($end) : ""; // valid begin/end if ((strlen($begin)) && (strlen($end))) { if ((strlen($begin_period)) && (strlen($end_period))) { // Valid? if (($begin <= $end_period) && ($end >= $begin_period)) { // Correct start time? if ($begin < $begin_period) { $begin = $begin_period; } // Correct end time? if ($end > $end_period) { $end = $end_period; } $result = array(convert_datetime($begin,1), convert_datetime($end,1)); } } else if (strlen($begin_period)) { // Valid? if ($end >= $begin_period) { // Correct start time? if ($begin < $begin_period) { $begin = $begin_period; } $result = array(convert_datetime($begin,1), convert_datetime($end,1)); } } else if (strlen($end_period)) { // Valid? if ($begin <= $end_period) { // Correct end time? if ($end > $end_period) { $end = $end_period; } $result = array(convert_datetime($begin,1), convert_datetime($end,1)); } } else { $result = array(convert_datetime($begin,1), convert_datetime($end,1)); } } else if (strlen($begin)) { if ((strlen($begin_period)) && (strlen($end_period))) { if (($begin >= $begin_period) && ($begin <= $end_period)) { $result = array(convert_datetime($begin,1), convert_datetime($end,1)); } } else if (strlen($begin_period)) { if ($begin >= $begin_period) { $result = array(convert_datetime($begin,1), convert_datetime($end,1)); } } else if (strlen($end_period)) { if ($begin <= $end_period) { $result = array(convert_datetime($begin,1), convert_datetime($end,1)); } } else { $result = array(convert_datetime($begin,1), convert_datetime($end,1)); } } else if (strlen($end)) { if ((strlen($begin_period)) && (strlen($end_period))) { if (($end >= $begin_period) && ($end <= $end_period)) { $result = array(convert_datetime($begin,1), convert_datetime($end,1)); } } else if (strlen($begin_period)) { if ($end >= $begin_period) { $result = array(convert_datetime($begin,1), convert_datetime($end,1)); } } else if (strlen($end_period)) { if ($end >= $end_period) { $result = array(convert_datetime($begin,1), convert_datetime($end,1)); } } else { $result = array(convert_datetime($begin,1), convert_datetime($end,1)); } } return $result; } /** * Get HREF for the current page */ function get_page_href() { $href = $_GET['href']; if( is_valid_action() ) { $href .= "&action=" . current_action(); $call_actions = previous_action(); if( $call_actions ) $href .= "&call_action=" . $call_actions; } $href .= (isset($_GET['page_project'])) ? "&page_project=" . urlencode($_GET['page_project']) : ""; return $href; } /** * Get current action * * Inputs: * - full Include, separated by colons, the previous action * (as a sort of stack with previous actions) * * Returns: * - Action for this page, or FALSE on error */ function current_action($full = FALSE) { global $_PAGE_INFO; if( isset($_SESSION[$_PAGE_INFO['id']]['action']) ) { $action = $_SESSION[$_PAGE_INFO['id']]['action']; if( $full && ($previous_action = previous_action()) ) { $action .= ":" . $previous_action; } return $action; } else { return FALSE; } } /** * Get previous action ('call' action) * * Returns: * - Action for this page, or FALSE on error */ function previous_action($skip = 0, $full = TRUE) { global $_PAGE_INFO; if( isset($_SESSION[$_PAGE_INFO['id']]['call_action']) ) { $call_stack = explode(":", $_SESSION[$_PAGE_INFO['id']]['call_action']); if( $skip ) $call_stack = array_splice($call_stack, $skip); if( $full ) { return implode(":", $call_stack); } else { return $call_stack[0]; } } else { return FALSE; } } /** * Get previous action ('return' action) * * Returns: * - Action for this page, or FALSE on error */ function return_action() { global $_PAGE_INFO; if( isset($_SESSION[$_PAGE_INFO['id']]['return_action']) ) { $call_stack = explode(":", $_SESSION[$_PAGE_INFO['id']]['return_action']); // return only the top of the stack (could be the full 'current_action' on the previous page) return $call_stack[0]; } else return FALSE; } /** * Check action * * Inputs: * - actions Actions to check ("or" functionality) * * Return: Boolean */ function is_valid_action() { global $_PAGE_INFO; if( !$_SESSION[$_PAGE_INFO['id']]['action'] ) { return FALSE; } else if( func_num_args() ) { // Check arguments $index = 1; // one-based, so the caller can check "if( is_valid_action() ) ..." foreach( func_get_args() as $arg ) { if( fnmatch($arg, $_SESSION[$_PAGE_INFO['id']]['action']) ) return $index; $index++; } return FALSE; } else { // yes, return action is set return TRUE; } } /** * Check call action * * Inputs: * - actions Actions to check ("or" functionality) * * Return: FALSE if not a call action, positive integer (position in the history with '1' being * the previous page) when this is valid call action or TRUE when not searching for a * specific action */ function is_valid_call() { global $_PAGE_INFO; if( !$_SESSION[$_PAGE_INFO['id']]['call_action'] ) { return FALSE; } else if( func_num_args() ) { // Check arguments $call_actions = explode(":", $_SESSION[$_PAGE_INFO['id']]['call_action']); $index = 1; // one-based, so the caller can check "if( is_valid_call() ) ..." foreach( func_get_args() as $arg ) { foreach( $call_actions as $action ) if( fnmatch($arg, $action) ) return $index; $index++; } return FALSE; } else { // yes, call action(s) are set return TRUE; } } // As above, but for the "return_action" function is_valid_return() { global $_PAGE_INFO; if( !$_SESSION[$_PAGE_INFO['id']]['return_action'] ) { return FALSE; } else if( func_num_args() ) { // Check arguments $index = 1; // one-based, so the caller can check "if( is_valid_return() ) ..." foreach( func_get_args() as $arg ) { if( fnmatch($arg, $_SESSION[$_PAGE_INFO['id']]['return_action']) ) return $index; $index++; } return FALSE; } else { // yes, return action is set return TRUE; } } /** * Returning by pressing the back button? */ function is_valid_backbutton() { if( !$_SERVER['HTTP_REFERER'] ) { return FALSE; } else { $url = parse_url($_SERVER['HTTP_REFERER']); parse_str($url['query'], $referer_get); // Check arguments if( $referer_get['call_action'] ) { $referer_call_actions = explode(":", $referer_get['call_action']); $index = 1; // one-based, so the caller can check "if( is_valid_call() ) ..." if( func_num_args() ) { foreach( func_get_args() as $arg ) { foreach( $referer_call_actions as $action ) if( fnmatch($arg, $action) ) return $index; $index++; } return FALSE; } else return TRUE; } else return FALSE; } } /** * Call history * * Returns: * Call stack (array) in ascending order or FALSE when not available */ function call_history() { global $_PAGE_INFO; if( $_SESSION[$_PAGE_INFO['id']]['call_action'] ) { $call_actions = explode(":", $_SESSION[$_PAGE_INFO['id']]['call_action']); return array_reverse($call_actions); } else return FALSE; } /** * Get current recall */ function current_recall() { global $_PAGE_INFO; if( isset($_SESSION[$_PAGE_INFO['id']]['recall']) ) return $_SESSION[$_PAGE_INFO['id']]['recall']; else return FALSE; } /** * Check recall * * Inputs: * * Return: 1(OK)/0(Error) */ function is_valid_recall() { global $_PAGE_INFO; if( !$_SESSION[$_PAGE_INFO['id']]['recall'] ) { return FALSE; } else if( func_num_args() ) { // Check arguments $index = 1; // one-based, so the caller can check "if( is_valid_recall() ) ..." foreach( func_get_args() as $arg ) { if( fnmatch($arg, $_SESSION[$_PAGE_INFO['id']]['recall']) ) return $index; $index++; } return FALSE; } else { // yes, recall is set return TRUE; } } /** * Store recall * * Return TRUE when a recall is set, FALSE if not */ function store_recall($array) { global $_PAGE_INFO; // Clear old recall action unset($_SESSION[$_PAGE_INFO['id']]['recall']); // Find new recall action if (is_array($array)) { foreach ($array as $key => $value) { $pos = strpos($key, "recall_"); if ($pos !== FALSE) { if (isset($_SESSION[$_PAGE_INFO['id']]['recall'])) { $_SESSION[$_PAGE_INFO['id']]['recall'] = $_SESSION[$_PAGE_INFO['id']]['recall'] . "," . substr($key, ($pos + strlen("recall_"))); } else { $_SESSION[$_PAGE_INFO['id']]['recall'] = substr($key, ($pos + strlen("recall_"))); } } } } return isset($_SESSION[$_PAGE_INFO['id']]['recall']); } /** * Clear recall */ function clear_recall() { unset($_SESSION[$_PAGE_INFO['id']]['recall']); } /** * Set a (new) recall */ function set_recall($recall) { global $_PAGE_INFO; // Clear old recall action unset($_SESSION[$_PAGE_INFO['id']]['recall']); // Set the new one $_SESSION[$_PAGE_INFO['id']]['recall'] = $recall; } /** * Strip time from date_time value * * Inputs: * - date_time Date time value */ function strip_time($date_time) { $array = explode(" ", $date_time); return $array[0]; } /** * Strip date from date_time value * * Inputs: * - date_time Date time value */ function strip_date($date_time, $skip_seconds = 1) { $array = explode(" ", $date_time); if ($skip_seconds) { if (isset($array[1])) { $pos1 = strpos($array[1], ":"); $start = (is_integer($pos1)) ? ($pos1 + 1) : 0; $pos2 = strpos($array[1], ":", $start); $result = substr($array[1], 0, $pos2); } else { $result = ""; } } else { $result = $array[1]; } return $result; } /** * Is Read only? * * Inputs: * - $ro_array Read-only array (actions) _or_ boolean * * Return: Is read-only (boolean) */ function is_ro($ro_array) { if (is_array($ro_array)) { return in_array(current_action(), $ro_array); } else if( $ro_array ) { return TRUE; } return FALSE; } /** * Store href history * */ function store_history($href) { global $_PAGE_INFO; // Store new value $_SESSION[$_PAGE_INFO['id']]['href_history_prev'] = $_SESSION[$_PAGE_INFO['id']]['href_history']; $_SESSION[$_PAGE_INFO['id']]['href_history'] = $href; } /** * Detect browser * * Return: String containing browser */ function browser() { $browser_user_agent = (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''); if(strstr($browser_user_agent, "Opera")) { return "OPERA"; } else if(strstr($browser_user_agent, "SeaMonkey/")) { return "SEAMONKEY"; } else if(strstr($browser_user_agent, "Netscape/") || stristr($browser_user_agent, "Navigator/")) { return "NETSCAPE"; } else if(strstr($browser_user_agent, "Firefox/")) { return "FIREFOX"; } else if(strstr($browser_user_agent, "Chrome/") || strstr($browser_user_agent, "CriOS/")) { // Chrome (all flavours, including iOS i.e. Chrome on an iPad) return "CHROME"; } else if(strstr($browser_user_agent, "MSIE") || strstr($browser_user_agent, "Trident/")) { // f###ing morons... in IE11, IE isn't called IE anymore return "IE"; } else if(strstr($browser_user_agent, "Safari/")) { if(strstr($browser_user_agent, "Mobile/")) return "iPAD"; else return "SAFARI"; } else if(strstr($browser_user_agent, "Gecko") || strstr($browser_user_agent, "Mozilla/")) { return "MOZILLA"; } else { return "UNKNOWN"; } } /** * Detect browser version * * Return: version */ function browser_version() { $browser_user_agent = $_SERVER['HTTP_USER_AGENT']; $browser = browser(); $version = FALSE; // fall-back; shouldn't be returned if( $browser == "IE" ) { if( preg_match('/MSIE ([0-9]+\.[0-9]+)/', $browser_user_agent, $version) ) { $version = $version[1]; } else if( preg_match('/Trident\/([0-9]+\.[0-9]+)/', $browser_user_agent, $version) ) { // Microsoft _deliberatly_ fucked up the user agent string: // http://blogs.msdn.com/b/ieinternals/archive/2013/09/21/internet-explorer-11-user-agent-string-ua-string-sniffing-compatibility-with-gecko-webkit.aspx preg_match('/rv:([0-9]+\.[0-9]+)/', $browser_user_agent, $version); $version = $version[1]; } } else { preg_match('/' . $browser . '[ \/]([0-9]+\.[0-9]+)/i', $browser_user_agent, $version); $version = $version[1]; } if( $version === FALSE ) { error_log("Couldn't obtain browser version from \"" . $browser_user_agent . "\""); } return $version; } /** * Get browser CSS prefix */ function browser_css_prefix() { switch( browser() ) { case "IE": return "-ms-"; case "FIREFOX": case "SEAMONKEY": case "MOZILLA": return "-moz-"; default: return "-webkit-"; } } /** * Mobile browser? */ function is_mobile_browser() { // Device is a mobile device when the user agent string contains the word // "Mobile" (Android, Applem and perhaps others, possibly followed by a // slash and a hex-code (Apple) or somthing else return preg_match("/\bMobile(\/\w*)?\b/", $_SERVER['HTTP_USER_AGENT']) > 0; } /** * create a random code * * Return: String containing random code (number-char-number-etc.) */ function createRandomCode($nmr) { $chars = "abcdefghijkmnpqrstuvwxyz"; $nums = "023456789"; srand((double)microtime()*1000000); $i = 0; $pass = '' ; while ($i < $nmr) { if ($i % 2) { $num = rand() % 25; $tmp = substr($chars, $num, 1); } else { $num = rand() % 9; $tmp = substr($nums, $num, 1); } $pass = $pass . $tmp; $i++; } return $pass; } /** * Check device * * Return: Ok (1)/error (0) */ function is_dev() { GLOBAL $_PAGE_INFO; // Initial result value $result = 0; // Retrieve number of arguments $numargs = func_num_args(); if ($numargs) { // Retrieve arguments $arg_list = func_get_args(); // Check arguments for ($i = 0; $i < $numargs; $i++) { if (strtolower($_PAGE_INFO['MTinfo_device']) == strtolower($arg_list[$i])) { // Result OK $result = 1; } } } return $result; } /** * Get microtime */ function microtime_float() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } /** * Sort multidimesional araay */ function array_sort($array, $keyname, $type = SORT_STRING, $asc_desc = SORT_ASC) { $sort_array = array(); // Retrieve data if (is_array($array)) { foreach($array as $key => $data) { array_push($sort_array, strtolower($data[$keyname])); } array_multisort($sort_array, $type, $asc_desc, $array); } return $array; } /** * Copy an array */ function array_copy($array) { return array_slice($array, 0, count($array)); } /** * Remove duplicated keys, also for multidimesional arrays */ function arrayUnique($array, $preserveKeys = false) { // Unique Array for return $arrayRewrite = array(); // Array with the md5 hashes $arrayHashes = array(); foreach($array as $key => $item) { // Serialize the current element and create a md5 hash $hash = md5(serialize($item)); // If the md5 didn't come up yet, add the element to // to arrayRewrite, otherwise drop it if (!isset($arrayHashes[$hash])) { // Save the current element hash $arrayHashes[$hash] = $hash; // Add element to the unique Array if ($preserveKeys) { $arrayRewrite[$key] = $item; } else { $arrayRewrite[] = $item; } } } return $arrayRewrite; } /** * Remove extension */ function RemoveExtension($strName) { $ext = strrchr($strName, '.'); if($ext !== false) { $strName = substr($strName, 0, -strlen($ext)); } return $strName; } /** * Get extension */ function GetExtension($strName) { $ext = strrchr($strName, '.'); return $ext; } /** * Retrieve all timezones */ function retrieve_timezones() { // Initial value $result = ""; if (file_exists(TIME_ZONE_FILE)) { // open file which contain timezones $handle = fopen(TIME_ZONE_FILE, 'r'); while(!feof($handle)) { // Read line $line = fgets($handle); if ($line[0] != "#") { // Parse into result if (!is_array($result)) { $result = array(); } // Split by tabs $line_array = split("\t", $line); if ((strlen($line_array[2])) && (strlen($line_array[0]))) { array_push($result, array(timezone => str_replace("\n","",$line_array[2]), code => $line_array[0])); } } } // Add UTC if (is_array($result)) { array_push($result, array(timezone => "UTC")); } // Close file fclose($handle); } return array_sort($result, "timezone"); } /** * Get random image */ function get_random_image($dir, $allowed_ext = array("jpg", "png", "gif", "bmp", "ico")) { // Create file array $files = array(); // Existing dir? if (is_dir($dir)) { // Open handle if ($handle = opendir($dir)) { // Read all files from dir while($file = readdir($handle)) { // Get extension $ext = strtolower(substr(strrchr($file, "."), 1)); // Allowed extension? if ((!is_array($allowed_ext)) || (in_array($ext, $allowed_ext))) { if (($file != ".") && ($file != "..") && !is_dir($file)) { array_push($files, $dir . $file); } } } // Close handle closedir($handle); } } // Select (random) image if (empty($files)) { $result = ""; } else { srand((float) microtime() * 10000000); $result = $files[array_rand($files, 1)]; } // Return image return $result; } /** * Get all files */ function get_all_files($dir, $allowed_ext = "") { // Create file array $files = array(); // Existing dir? if (is_dir($dir)) { // Open handle if ($handle = opendir($dir)) { // Read all files from dir while($file = readdir($handle)) { // Get extension $ext = strtolower(substr(strrchr($file, "."), 1)); // Allowed extension? if ((!is_array($allowed_ext)) || (in_array($ext, $allowed_ext))) { if (($file != ".") && ($file != "..") && !is_dir($file)) { array_push($files, $dir . $file); } } } // Close handle closedir($handle); } } // Sort array sort($files); // Return files return $files; } /** * Get all directories */ function get_all_dirs($dir) { // Create dir array $dirs = array(); // Existing dir? if ($handle = opendir($dir)) { if ($handle !== FALSE) { do { $dir = readdir($handle); // Skip '.'/'..'/CVS if (($dir !== FALSE) && ($dir != ".") && ($dir != "..") && ($dir != "CVS")) { array_push($dirs, $dir); } } while($dir !== FALSE); } } // Sort array sort($dirs); // Return dir return $dirs; } /** * Define number of lines and return array containing lines */ function nmr_lines($text, $chars_on_line) { // Initial value $result = array(); $finished = 0; $index = 0; do { // Initial values $skip = 0; $length = 0; // Find carriage return $pos_cr = strpos($text, "\n"); // Found carriage return? if (($pos_cr !== FALSE) && ($pos_cr <= $chars_on_line)) { // Split up line $length = $pos_cr; // Skip cr char $skip = 1; } // EOL else if (strlen($text) <= $chars_on_line) { $length = strlen($text); } else { // Find space $pos_space = strpos($text, " "); // Found space if (($pos_space !== FALSE) && ($pos_space <= $chars_on_line)) { // Skip space char $skip = 1; // Initial counter value $counter = $pos_space; do { // Find another space $pos_space = strpos($text, " ", $counter + 1); // Find one within chars_on_line? if (($pos_space !== FALSE) && ($pos_space <= $chars_on_line)) { // increment offset $counter = $pos_space; } else { // Split up line $length = $counter; } } while (!$length); } else { // Split up line after chars_on_line $length = (strlen($text) >= $chars_on_line) ? $chars_on_line : strlen($text); } } // Parse result $result[$index++] = substr($text, 0, $length); // Adapt text $text = substr($text, ($length + $skip)); // Finished? $finished = (!strlen($text)) ? 1 : 0; } while(!$finished); return $result; } /** * Shorten text */ define("SHORTEN_NONE", 0); define("SHORTEN_CAPS", 0x01); define("SHORTEN_NARROW", 0x02); define("SHORTEN_ALL", 0x03); // flags define("SHORTEN_HTML", 0x10); define("SHORTEN_NO_SUFFIX", 0x20); // don't add an ellipsis after the string function shorten_text($value, $max_size = 25, $adjust = SHORTEN_NONE, $html = TRUE) { // Initial value $result = array(); // override 'html' flag if( ($adjust & SHORTEN_HTML) ) $html = TRUE; if( $html ) { // count html character entities as one character $value_wo_html = preg_replace("/&.+;/U", "x", $value); $max_size += strlen($value) - strlen($value_wo_html); } else $value_wo_html = $value; // Determine value length for( $i = 0, $n = 0; $i < strlen($value); $i++ ) { // copy the first 'max_size' characters, minding HTML characters like "&" if( $html && substr($value, $i, 1) == "&" ) { $char = substr($value, $i, 1); do { $char .= substr($value, ++$i, 1); } while( substr($value, $i, 1) != ";" && $i < strlen($value) ); } else { $char = substr($value, $i, 1); // Adjust for wide and narrow characters? if( $adjust && $n < $max_size ) { // Clip the name of an item in the menu structure (minding nearower letters) // Capitals and lower case 'm' and 'w' are wide if( ($adjust & SHORTEN_CAPS) ) { $max_size -= preg_match_all("/([A-Zmw])/", $char, $dummy) * 1.2; $max_size -= preg_match_all("/([MW])/", $char, $dummy) * 1.2; } // Compensate for narrow letters if( ($adjust & SHORTEN_NARROW) ) { $max_size += preg_match_all("/([.,;:il])/", $char, $dummy) / 1.2; } } } $result[$n++] = $char; } if( count($result) > $max_size ) { if( ($adjust & SHORTEN_NO_SUFFIX) ) { $result = array_splice($result, 0, $max_size); } else { $result = array_splice($result, 0, $max_size - 2); $result[] = ($html ? "…" : "..."); } } return implode("", $result); } /** * Tablet? */ function is_tablet() { return ((!isset($_COOKIE['screen_width'])) || (!strlen($_COOKIE['screen_width'])) || ($_COOKIE['screen_width'] >= 1024)) ? 0 : 1; } /** * Write cookie */ function WriteCookie($key, $value, $remove = 0, $days = 100) { if (!$remove) { $datetime = time() + $days * (24 * 60 * 60); } else { $datetime = time(); } // Set secured/http only (only for 5.2.0 or higher) cookie if (PHPValid(5,2,0)) { setcookie($key, $value, $datetime, "/", "", TRUE, TRUE); } else { setcookie($key, $value, $datetime, "/", "", TRUE); } } /** * Update globals */ function UpdateGlobals() { global $_PAGE_INFO; // First all root items $items = array("i18n","valuta","base","base_path","skin_name","skin","logged_on"); foreach($items as $item) { if (isset($_SESSION[$_PAGE_INFO['id']][$item])) { $_PAGE_INFO[$item] = $_SESSION[$_PAGE_INFO['id']][$item]; } } // Next all login items $items = array("user","customer","project"); foreach($items as $item) { if (isset($_SESSION[$_PAGE_INFO['id']]['login'][$item]['id'])) { $_PAGE_INFO['login'][$item]['id'] = $_SESSION[$_PAGE_INFO['id']]['login'][$item]['id']; } } // Cache user rights if( isset($_SESSION[$_PAGE_INFO['id']]['login']['user']['id']) ) { $user = db_fetch_user($_SESSION[$_PAGE_INFO['id']]['login']['user']['id'],"",1); $_PAGE_INFO['user']['rights'] = $user['rechten']; } } /** * Send RS3000 message */ function SendMessageRS3000($params = "") { GLOBAL $_PAGE_INFO; // Initial values $message = ""; $split_char = ","; // Send session id $message = "id='" . $_PAGE_INFO['id'] ."'"; // Send i18n if (isset($_PAGE_INFO['i18n'])) { $message .= $split_char . "i18n='" . $_PAGE_INFO['i18n'] . "'"; } // Send project id if (isset($_PAGE_INFO['login']['project']['id'])) { $message .= $split_char . "page_project='" . $_PAGE_INFO['login']['project']['id'] . "'"; } // motd? $motd = db_fetch_system_maint_mes($_PAGE_INFO['i18n']); if (is_array($motd)) { if (strlen($motd['onderhoud'])) { $message .= $split_char . "motd='" . str_replace($split_char, " ", $motd['onderhoud']) . "'"; } } // Send params if (is_array($params)) { $message .= $split_char . implode($split_char, $params); } if (strlen($message)) { if (LOG_RS) { if ((!empty($_SESSION[$_PAGE_INFO['id']]['login']['imei'])) || (!empty($_SESSION[$_PAGE_INFO['id']]['login']['user']['id']))) { $user_info = (!empty($_SESSION[$_PAGE_INFO['id']]['login']['user']['id'])) ? "user: " . $_SESSION[$_PAGE_INFO['id']]['login']['user']['id'] : ""; $imei_info = (!empty($_SESSION[$_PAGE_INFO['id']]['login']['imei'])) ? "imei: " . $_SESSION[$_PAGE_INFO['id']]['login']['imei'] : ""; $separator = ((!empty($_SESSION[$_PAGE_INFO['id']]['login']['imei'])) && (!empty($_SESSION[$_PAGE_INFO['id']]['login']['user']['id']))) ? ", " : ""; DBG("RS3000 (" . $user_info . $separator . $imei_info . "): " . $message); } else { DBG("RS3000: " . $message); } } echo $message; } } /* * Debug function */ function DBG($value, $email = "") { // Get IP $remote_addr = (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) ? " (" . $_SERVER['HTTP_X_FORWARDED_FOR'] . ")" : ((isset($_SERVER['REMOTE_ADDR'])) ? " (" . $_SERVER['REMOTE_ADDR'] . ")" : ""); if (is_array($value)) { $count = 0; foreach($value as $key => $item) { syslog(LOG_INFO, "MTinfo debug" . $remote_addr . ": " . (sprintf("%-15s",$key)) . ": " . (sprintf("%-50s",$item)) . "(" . ++$count . "/" . sizeof($value) . ")"); if (strlen($email)) { if (valid_email($email, FALSE)) { send_mail($email, "", "", "debug@dualinventive.com", "MTinfo debug", $value[$i] . "(" . $i . "/" . sizeof($value) . ")"); } } } } else if (strlen($value)) { syslog(LOG_INFO, "MTinfo debug" . $remote_addr . ": " . $value); if (strlen($email)) { if (valid_email($email, FALSE)) { send_mail($email, "", "", "debug@dualinventive.com", "MTinfo debug", $value); } } } } /** * Is this release candidate? * * Return: Release candidate (TRUE)/Release (FALSE) */ function is_ReleaseCandidate() { GLOBAL $_RELEASE; // Initial result value $result = FALSE; // Does the script name contain release candidate directory? $result = (!strlen($_RELEASE['rc']['dir']) || stristr(realpath($_SERVER['SCRIPT_FILENAME']), $_RELEASE['rc']['dir']) === FALSE) ? FALSE : TRUE; return $result; } /** * Calculate duration * * Return: String containing duration */ function CalculateDuration($start, $end) { $duration = convert_datetime($end) - convert_datetime($start); $hours = (int)($duration / 3600); $duration = (int)$duration - ($hours * 3600); $minutes = (int)($duration / 60); $duration = (int)$duration - ($minutes * 60); $seconds = (int)($duration); return sprintf("%02u:%02u:%02u", $hours, $minutes, $seconds); } /** * Format a duration in seconds to a human readable string * * Inputs: * - duration In seconds * - format For future use. Currently, it is a boolean to indicate * that the output should be in hours/minutes (when TRUE) * or minutes/seconds (when FALSE) * * Returns a formatted string */ function FormatDuration($duration, $format /* currently a very limited boolean: show seconds */ = FALSE) { if( $duration >= 60 || $format ) { if( $format ) { // hours and minutes return sprintf(_("FORMAT_ELAP_HOUR_MIN"), intval($duration / 3600), intval(($duration / 60) % 60)); } else if( $duration >= 3600 ) { // minutes and seconds return sprintf(_("FORMAT_ELAP_HOUR_MIN_SEC"), intval($duration / 3600), intval(($duration / 60) % 60), intval($duration % 60)); } else { // minutes and seconds return sprintf(_("FORMAT_ELAP_MIN_SEC"), intval($duration / 60), intval($duration % 60)); } } else { // seconds only return sprintf(_("FORMAT_ELAP_SEC"), intval($duration)); } } /** * Convert a human readable string to a duration in seconds * Returns FALSE when '$str' is invalid */ function ConvertDuration($str, $format /* as above */ = FALSE) { $pattern = _("REGEX_FORMAT_ELAP"); $pos = explode(",", _("REGEX_POS_ELAP")); $n = preg_match($pattern, $str, $duration); if( $n ) { if( is_numeric($str) ) { if( $format ) return $str * 3600; else return $str * 60; } else { // hour:minute:second $a1 = $duration[$pos[0]]; $a2 = $duration[$pos[1]]; $a3 = $duration[$pos[2]]; if( $duration[$pos[3]] == _("REGEX_TIME_SEP") ) { if( strlen($a2) == 0 ) { // hour:min or min:sec if( $format ) return ($a1 * 3600) + ($a3 * 60); else if( strlen($a3) == 0 ) return $a1; // seconds only else return ($a1 * 60) + $a3; } else { // hour:min:sec return ($a1 * 3600) + ($a2 * 60) + $a3; } } else { // human readable return ($a1 * 3600) + ($a2 * 60) + $a3; } } } else return FALSE; } /** * Next service date * * Return: String containing next service date */ function NextService($service, $sw3000) { // Get next switch memory service date $sw3000_service = strtotime(date("Y-m-d", strtotime($sw3000)) . " +4 years"); if (strlen($sw3000)) { if ((!strlen($service)) || (convert_datetime($service) > $sw3000_service)) { $service = convert_datetime($sw3000_service, TRUE); } } return $service; } /** * Hash a password * * See "CheckPassword()" below for notes and the history of this function. */ function HashPassword($input, $uid) { // Salt which will be added to password if( $uid ) { // "random" salt as recommened by security audit (v1.0 of 20131023) // the 'bcrypt' algorithm is not available, so we will resort to SHA-1 // with a "random" salt based on the user-id (which is random for any // third party, so there is no reason not to...) $uid = intval($uid); $salt_prefix = "\x50\x31"; $salt_suffix = "\x53\x84"; for( $i = 0; $i <= 30; $i += 6 ) { $salt_prefix .= chr(($uid >> $i) & 0xFF); $salt_suffix .= chr(($uid >> (30 - $i)) & 0xFF); } return sha1($salt_prefix . strtolower($input) . $salt_suffix); } else { $salt = "/$DI$/SALT&/"; return md5($salt . strtolower($input) . $salt); } } /** * Check password * * Input: * - input User input (plain text) * - password Encrypted/hashed password in the database to match * - uid User identifier * Returns: * - FALSE or one of the defines below (which will evaluate to "TRUE" where needed) * * Notes and history: * - The first version only matched MD5 hashes, but this was considered * inadequate after the first security audit. A "salt" was added. * - After the second security audit, a fixed salt was no longer adequate * so the salt is now "randomized" (i.e. the user-id is added to the * "salt" as this is hidden information and therefore sufficiently random * as the purpose of the salt is to prevent that an external party can * "guess" the passwords using a rainbow table or whichever other technique) * - The recommended "bcrypt()" function is not documented (and the site * "php.net" is down because theire HTTPS certificate has been revoked???). * The function "crypt()", which does have an implementation of the blowfish * algorithm, does not seem to return valid data on both 'arcfs12' and the * 'rootnet' servers. The output should be used as 'salt' to check the * user's password, but this does not work nor does it produce the same * output as the examples??? Moreover, when the (obviously) incorrect output * was used, it simply returned the "salt" as its output in a second run, * regardless of the data (password) to hash. * - An extra effort will be made to make sure that the encrypted passwords * are not visible, so it will be impossible to match them against a * "rainbow table". Note that the encrypted password were only "visible" in * the HTML source of the "change user" (and the similar "change password") * page and only when a user was logged in. * - The fact that MD5 or SHA1 are "too quick" is nonsense * disputable; see the comments made on the page below: * "http://us3.php.net/manual/en/faq.passwords.php#faq.passwords.fasthash" * Besides that, this only applies when an attacker gets hold of the database * data (or hashed passwords in general) and this should be avoided at all * cost as this would render any encryption void. Security starts at the * front door. */ define("PASSWD_MD5", 1); define("PASSWD_SALTED", 2); define("PASSWD_RND_SALT", 3); define("PASSWD_BCRYPT", 4); // perhaps some time in the future // the next define is used during the login process to automatically upgrade // the user's password to the recommended encryption; older encryptions // (MD5, salted MD5) may be discontinued in the future and any user that // hasn't logged on since this automatic upgrade has been effectuated, will // not be able to do so when the old encryption methods are no longer // supported // NOTE / TO DO: the automatic upgrading of passwords must be activated // when this functionality is in the live tree; NOT BEFORE! define("PASSWD_RECOMMENDED_ENCRYPTION", 0); // TO DO TO ACTIVATE AUTOMATIC UPGRADES: define("PASSWD_RECOMMENDED_ENCRYPTION", PASSWD_RND_SALT); // display text for password; control characters would have been nice (because // the user cannot enter those) but the browser (or HTTP RFC) filters those // out, so no such luck there. define("PASSWD_DISPLAY_TEXT", "sterretjes"); function CheckPassword($input, $password, $uid) { if( !$uid ) return FALSE; if( md5(strtolower($input)) == $password ) return PASSWD_MD5; else if( HashPassword($input, NULL) == $password ) return PASSWD_SALTED; else if( HashPassword($input, $uid) == $password ) return PASSWD_RND_SALT; else return FALSE; } /** * Check password complexity * * Input * - plain text password * * Returns: boolean (TRUE if the password is sufficiently complex, FALSE if not) * * Note: there are no rules at the moment, so this function only checks that * the password is not empty. */ function CheckPasswordComplexity($input) { return strlen($input) > 0; } /** * Check directory */ function CheckDirectory($allowedDir, $actualFile) { // Initial values $result = FALSE; $actualFile = realpath(dirname($actualFile)); if (is_array($allowedDir)) { foreach($allowedDir as $dir) { $dir = realpath($dir); if (($dir !== FALSE) && ($actualFile !== FALSE)) { if ($dir == $actualFile) { $result = TRUE; } } } } else { $allowedDir = realpath($allowedDir); if (($allowedDir !== FALSE) && ($actualFile !== FALSE)) { if ($allowedDir == $actualFile) { $result = TRUE; } } } return $result; } /** * Calculate Short circuit quality */ function CalcShortCircuitQuality($b_a_limit, $b_a_current) { $val = (100 * (1 - (pow(($b_a_current - 0.125),4)/pow(($b_a_limit - 0.125),4)))); return ($val < 0) ? 0 : $val; } /** * Check for active branch */ function ActiveBranch() { global $_DEFAULT, $_HOSTNAME; return in_array(file_get_contents($_DEFAULT['active_branch']), $_HOSTNAME); } /** * Load page contents in-line * (currently the same as "include") */ function PageLoadContents($php_script) { global $_PAGE_INFO; include($php_script); } /** * Build a valid URL * * - href Page to call * - action Action * - param Additional GET parameters as * - a properly encoded string * - an associated array (not encoded) */ function build_url($href, $action = FALSE, $param = FALSE) { global $_PAGE_INFO; // build the URL $url = "?id=" . $_PAGE_INFO['id']; $url .= "&href=" . $href; if( $action ) { $url .= "&action=" . $action; } if( $_GET['page_project'] ) { $url .= "&page_project=" . urlencode($_GET['page_project']); } if( $param ) { if( is_array($param) ) { foreach( $param as $key => $value ) $url .= "&" . $key . "=" . urlencode($value); } else { // URL encoded string $url .= "&" . $param; } } return $url; } /** * Redirect to a page * * Inputs: * - href Page to call * - action Action * - param Additional GET parameters as * - a properly encoded string * - an associated array (not encoded) * - target Target window (same window by default) */ function _page_redirect($href, $action = FALSE, $param = FALSE, $target = "_self") { global $_PAGE_INFO; // build the URL $url = build_url($href, $action, $param); echo "\n"; } function PageRedirect($href, $action = FALSE, $param = FALSE) { _page_redirect($href, $action, $param, "_self"); } function PageNewWindow($href, $action, $param) { _page_redirect($href, $action, $param, "_blank"); } function PageCall($href, $action = FALSE, $param = FALSE) { if( !$param ) { $param = array(); } else if( !is_array($param) ) { parse_str($param, $param_array); $param = $param_array; } $param['call_action'] = current_action(TRUE); _page_redirect($href, $action, $param); } function PageReturn($href, $param) { if( !$param ) { $param = array(); } else if( !is_array($param) ) { parse_str($param, $param_array); $param = $param_array; } $param['return_action'] = current_action(TRUE); _page_redirect($href, previous_action(), $param); } /** * Object to array conversion */ function object_to_array($data) { if(is_array($data) || is_object($data)) { $result = array(); foreach($data as $key => $value) { $result[$key] = object_to_array($value); } return $result; } return $data; } /** * Get maximum value from an array */ function array_max($array, $key = NULL, $default = NULL) { unset($max); if( is_array($array) ) { if( is_null($key) ) { foreach( $array as $item ) if( !isset($max) || $item > $max ) $max = $item; } else { foreach( $array as $item ) if( !isset($max) || $item[$key] > $max ) $max = $item[$key]; } } // return the default when the array is empty (or non-existent) if( !isset($max) && !is_null($default) ) return $default; else return $max; } /** * Extended "is_null()" */ function _is_null($value) { return is_null($value) || $value == "NULL"; } /* * Re-order an associative array */ function _array_set_keys($a, $field) { $result = array(); foreach( $a as $value ) $result[$value[$field]] = $value; return $result; } /** * Improved 'explode()'. Returns an empty array when the input is an * empty string. */ function _explode($delimiter, $string) { if( trim($string) === "" ) $a = array(); else { $a = explode($delimiter, $string); } return $a; } /** * Improved "implode()" */ function _implode($delimiter, $a, $callback = NULL) { if( !is_array($a) ) $a = array($a); if( $callback ) foreach( $a as $i => $value ) $a[$i] = call_user_func($callback, $a[$i]); return implode($delimiter, $a); } /** * Encrypt data */ function encrypt($data, $password) { return base64_encode($password . $data); } /** * Decrypt data */ function decrypt($data, $password) { return substr(base64_decode($data), strlen($password)); } /** * Check if current php version is valid (or higher of course) */ function PHPValid($major, $minor, $release) { // Initial value $result = TRUE; // Get php version $version = phpversion(); // Difference between php versions if (!is_array($version)) { $version = explode('.', $version); } if ($major > $version[0]) { $result = FALSE; } else if ($major == $version[0]) { if ($minor > $version[1]) { $result = FALSE; } else if ($minor == $version[1]) { if ($release > $version[2]) { $result = FALSE; } } } return $result; } /** * Check if a string is serialized * @param string $string */ function is_serial($string) { return (@unserialize($string) !== false || $string == 'b:0;'); } /** * Encode characters when inserting into the database */ function specialchars($str, $db_insert = TRUE) { if( $db_insert ) return addcslashes($str, "'"); else return addslashes($str); } /** * htmlspecialchars for array (recursive) * @param string $string */ function htmlspecialchars_array(&$variable) { foreach ($variable as &$value) { if (!is_array($value)) { $value = specialchars($value); } else { htmlspecialchars_array($value); } } } /** * htmlspecialchars_decode for array (recursive) * @param string $string */ function htmlspecialchars_decode_array(&$variable) { foreach ($variable as &$value) { if (!is_array($value)) { $value = htmlspecialchars_decode($value, ENT_QUOTES); } else { htmlspecialchars_decode_array($value); } } } /** * Remove spaces and other special characters for a filename */ function make_filename($text) { return preg_replace("(\s+|_+|\&[a-z0-9]+;|\&)", "_", $text); } /** * The function 'array_column()' was introduced in PHP 5.5 */ if( !function_exists("array_column") ) { function array_column($array, $key, $index_key = NULL) { $column_data = array(); if( is_null($index_key) ) { foreach( $array as $row ) { $column_data[] = $row[$key]; } } else { foreach( $array as $row ) { $column_data[$row[$index_key]] = $row[$key]; } } return $column_data; } } /** * Report a (serious) exception in MTinfo * - Log to 'syslog' * - Send e-mail (optional) * - Redirect (optional); will exit when redirected */ function report_error($msg, $redirect_url = FALSE, $send_mail = TRUE) { global $_PAGE_INFO, $_RELEASE; $release = (is_ReleaseCandidate() ? "rc" : "release"); if( !$_PAGE_INFO['mtinfo-dev'] ) { // log DBG("Error: " . $msg); // and send e-mail if( $send_mail && $_RELEASE[$release]['e-mail'] && $_RELEASE[$release]['e-mail']['error'] ) { send_mail( $_RELEASE[$release]['e-mail']['error'], "", "", "error@dualinventive.com", "MTinfo Warning (" . php_uname("n") . ")", "

Message:
" . $msg . "

Backtrace:
" . calltrace("text/html", 1) . "

", "", "", 1 ); } if( $redirect_url ) { header($redirect_url); exit(0); } } else { // development site echo "

" . $msg . "

\n"; echo "

" . calltrace("text/html") . "

\n"; } } /** * Catch illegal access * - Log to 'syslog' * - Send e-mail * - Log out the user forcefully (redirect user to the log-in page) * - Exit immediately * * Parameters: * - usermsg Message displayed to the user * - logmsg Message for the log (can/should contain more * detailed information; optional) * Returns: * Doesn't return */ function force_logout($usermsg, $logmsg = null) { global $_PAGE_INFO, $_RELEASE; $release = (is_ReleaseCandidate() ? "rc" : "release"); // is there a more detailed log message? if not, show the same message // as the user gets if( is_null($logmsg) ) $logmsg = $usermsg; // log error_log($logmsg); // do not forcefully log out the user when on the development site if( !$_PAGE_INFO['mtinfo-dev'] ) { // log DBG($logmsg); // and send e-mail if( $_RELEASE[$release]['e-mail'] && $_RELEASE[$release]['e-mail']['abuse'] ) { send_mail( $_RELEASE[$release]['e-mail']['abuse'], "", "", "abuse@dualinventive.com", "MTinfo Abuse Warning (" . php_uname("n") . ")", "

Message:
" . $logmsg . "

Backtrace:
" . calltrace("text/html", 1) . "

", "", "", 1 ); } // display logout message $_SESSION[$_PAGE_INFO['id']]['login_info']['errormsg'] = $usermsg; $_SESSION[$_PAGE_INFO['id']]['login_info']['username'] = $_SESSION[$_PAGE_INFO['id']]['login']['user']['name']; $_SESSION[$_PAGE_INFO['id']]['login_info']['customer'] = $_SESSION[$_PAGE_INFO['id']]['login']['customer']['name']; // redirect page back to login page PageRedirect(PAGE_LOGIN); } else { // debug echo "

" . $logmsg . "

\n"; echo "

" . calltrace("text/html") . "

\n"; } // do not perform any further processing (user is redirected to the login page) die($usermsg); } /** * Support for error tracing: get the call trace as a string * * Inputs: * - convert Convert output (string parameter: MIME type), currently * only "html" and anything else is plain text * - skip_frame Skip the first frames; by default only frame #0 * is skipped (the function 'backtrace()' itself) */ function calltrace($convert = FALSE, $skip_frame = 0, $print_args = TRUE) { $backtrace = ""; $frame = 0; $call_trace = debug_backtrace(); foreach( $call_trace as $call ) { if( $frame > $skip_frame ) { $backtrace .= "#" . ($frame++ - $skip_frame - 1) . " "; if( $print_args ) { if( $call['class'] ) $backtrace .= $call['class'] . " "; if( $call['object'] ) $backtrace .= serialize($call['object']); } else { if( $call['object'] ) $backtrace .= get_class($call['object']); } $backtrace .= $call['type'] . $call['function'] . "("; $sep = ""; if( $print_args && $call['args'] ) foreach( $call['args'] as $arg ) { $backtrace .= $sep; $sep = ","; if( is_null($arg) ) $backtrace .= "NULL"; else if( is_string($arg) ) $backtrace .= "\"" . $arg . "\""; else if( is_bool($arg) ) $backtrace .= ($arg ? "TRUE" : "FALSE"); else if( is_array($arg) ) $backtrace .= print_r($arg, TRUE); else $backtrace .= $arg; } $backtrace .= ") [" . $call['file'] . ":" . $call['line'] . "]\n"; } else { // no use showing the "db_report_slow_query" frame $frame++; } } // convert output? if( $convert ) switch( strtolower($convert) ) { case "html": case "text/html": // mime type :-) $backtrace = nl2br(specialchars($backtrace)); break; // default: text/plain } return $backtrace; } /** * P() * Acquire semaphore * * Inputs: * - id: Semaphore identifier * * Return: Semaphore handle */ function db_sema_acquire($id) { // Get sema id $sem = sem_get(bin2hex($id), 1, 0600); // Wait for semaphore sem_acquire($sem); // return handle return $sem; } /** * V() * Release semaphore * * Inputs: * - id: Semaphore handle * * Return: 1 (OK)/ 0(Error) */ function db_sema_release($handle) { // Release semaphore sem_release($handle); return TRUE; } ?>