<?php /** * eGroupWare API: Commononly used (static) functions * * This file written by Dan Kuykendall <seek3r@phpgroupware.org> * and Joseph Engo <jengo@phpgroupware.org> * and Mark Peters <skeeter@phpgroupware.org> * and Lars Kneschke <lkneschke@linux-at-work.de> * Functions commonly used by eGroupWare developers * Copyright (C) 2000, 2001 Dan Kuykendall * Copyright (C) 2003 Lars Kneschke * * @link http://www.egroupware.org * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @package api * @version $Id$ */ /** * common class containing commonly used static functions */ class common { static $debug_info; // An array with debugging info from the API static $found_files; /** * Try to guess and set a locale supported by the server, with fallback to 'en_EN' and 'C' * * This method uses the language and nationalty set in the users common prefs. * * @param $category=LC_ALL category to set, see setlocal function * @param $charset=null default system charset * @return string the local (or best estimate) set */ static function setlocale($category=LC_ALL,$charset=null) { $lang = $GLOBALS['egw_info']['user']['preferences']['common']['lang']; $country = $GLOBALS['egw_info']['user']['preferences']['common']['country']; if (strlen($lang) == 2) { $country_from_lang = strtoupper($lang); } else { list($lang,$lang2) = explode('-',$lang); $country_from_lang = strtoupper($lang2); } if (is_null($charset)) $charset = translation::charset(); foreach(array( $lang.'_'.$country, $lang.'_'.$country_from_lang, $lang, 'en_US', 'C', ) as $local) { if (($ret = setlocale($category,$local.'@'.$charset)) || ($ret = setlocale($category,$local))) { //error_log(__METHOD__."($category,$charset) lang=$lang, country=$country, country_from_lang=$country_from_lang: returning '$ret'"); return $ret; } } error_log(__METHOD__."($category,$charset) lang=$lang, country=$country, country_from_lang=$country_from_lang: Could not set local!"); return false; // should not happen, as the 'C' local should at least be available everywhere } /** * Compares two Version strings and return 1 if str2 is newest (bigger version number) than str1 * * This function checks for major version only. * @param $str1 * @param $str2 */ static function cmp_version($str1,$str2,$debug=False) { $regs = $regs2 = null; preg_match("/([0-9]+)\.([0-9]+)\.([0-9]+)[a-zA-Z]*([0-9]*)/",$str1,$regs); preg_match("/([0-9]+)\.([0-9]+)\.([0-9]+)[a-zA-Z]*([0-9]*)/",$str2,$regs2); if($debug) { echo "<br>$regs[0] - $regs2[0]"; } for($i=1;$i<5;$i++) { if($debug) { echo "<br>$i: $regs[$i] - $regs2[$i]"; } if($regs2[$i] == $regs[$i]) { continue; } if($regs2[$i] > $regs[$i]) { return 1; } elseif($regs2[$i] < $regs[$i]) { return 0; } } } /** * Compares two Version strings and return 1 if str2 is newest (bigger version number) than str1 * * This function checks all fields. cmp_version() checks release version only. * @param $str1 * @param $str2 */ static function cmp_version_long($str1,$str2,$debug=False) { $regs = $regs2 = null; preg_match("/([0-9]+)\.([0-9]+)\.([0-9]+)[a-zA-Z]*([0-9]*)\.([0-9]*)/",$str1,$regs); preg_match("/([0-9]+)\.([0-9]+)\.([0-9]+)[a-zA-Z]*([0-9]*)\.([0-9]*)/",$str2,$regs2); if($debug) { echo "<br>$regs[0] - $regs2[0]"; } for($i=1;$i<6;$i++) { if($debug) { echo "<br>$i: $regs[$i] - $regs2[$i]"; } if($regs2[$i] == $regs[$i]) { if($debug) { echo ' are equal...'; } continue; } if($regs2[$i] > $regs[$i]) { if($debug) { echo ', and a > b'; } return 1; } elseif($regs2[$i] < $regs[$i]) { if($debug) { echo ', and a < b'; } return 0; } } if($debug) { echo ' - all equal.'; } } /** * generate a unique id, which can be used for syncronisation * * @param string $_appName the appname * @param string $_eventID the id of the content * @return string the unique id */ static function generate_uid($_appName, $_eventID) { if(empty($_appName) || empty($_eventID)) return false; // not used: $suffix = $GLOBALS['egw_info']['server']['hostname'] ? $GLOBALS['egw_info']['server']['hostname'] : 'local'; $prefix = $_appName.'-'.$_eventID.'-'.$GLOBALS['egw_info']['server']['install_id']; return $prefix; } /** * get the local content id from a global UID * * @param sting $_globalUid the global UID * @return int local egw content id */ static function get_egwId($_globalUid) { if(empty($_globalUid)) return false; $globalUidParts = explode('-',$_globalUid); array_shift($globalUidParts); // remove the app name array_pop($globalUidParts); // remove the install_id return implode('-',$globalUidParts); // return the rest, allowing to have dashs in the id, can happen with LDAP! } /** * return an array of installed languages * * @return $installedLanguages; an array containing the installed languages */ static function getInstalledLanguages() { $GLOBALS['egw']->db->query('SELECT DISTINCT lang FROM egw_lang'); while (@$GLOBALS['egw']->db->next_record()) { $installedLanguages[$GLOBALS['egw']->db->f('lang')] = $GLOBALS['egw']->db->f('lang'); } return $installedLanguages; } /** * get preferred language of the users * * Uses HTTP_ACCEPT_LANGUAGE (from the browser) and getInstalledLanguages to find out which languages are installed * * @return string */ static function getPreferredLanguage() { // create a array of languages the user is accepting $userLanguages = explode(',',$_SERVER['HTTP_ACCEPT_LANGUAGE']); $supportedLanguages = self::getInstalledLanguages(); // find usersupported language foreach($userLanguages as $lang) { // remove everything behind '-' example: de-de $pieces = explode('-', trim($lang)); $value = $pieces[0]; # print 'current lang $value<br>'; if ($supportedLanguages[$value]) { $retValue=$value; break; } } // no usersupported language found -> return english if (empty($retValue)) { $retValue='en'; } return $retValue; } /** * escapes a string for use in searchfilters meant for ldap_search. * * Escaped Characters are: '*', '(', ')', ' ', '\', NUL * It's actually a PHP-Bug, that we have to escape space. * For all other Characters, refer to RFC2254. * * @deprecated use ldap::quote() * @param $string either a string to be escaped, or an array of values to be escaped * @return string */ static function ldap_addslashes($string='') { return ldap::quote($string); } /** * connect to the ldap server and return a handle * * @deprecated use ldap::ldapConnect() * @param $host ldap host * @param $dn ldap_root_dn * @param $passwd ldap_root_pw * @return resource */ static function ldapConnect($host='', $dn='', $passwd='') { // use Lars new ldap class return $GLOBALS['egw']->ldap->ldapConnect($host,$dn,$passwd); } /** * function to stop running an app * * used to stop running an app in the middle of execution <br> * There may need to be some cleanup before hand * @param $call_footer boolean value to if true then call footer else exit */ static function egw_exit($call_footer = False) { if (!defined('EGW_EXIT')) { define('EGW_EXIT',True); if ($call_footer) { self::egw_footer(); } } exit; } /** * return a random string of size $size * * @param $size int-size of random string to return */ static function randomstring($size) { static $random_char = array( '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f', 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', 'w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L', 'M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' ); $s = ''; for ($i=0; $i < $size; $i++) { $s .= $random_char[mt_rand(0,count($random_char)-1)]; } return $s; } // Look at the note towards the top of this file (jengo) static function filesystem_separator() { return filesystem_separator(); } /** * This is used for reporting errors in a nice format. * * @param $error - array of errors */ static function error_list($errors,$text='Error') { if (!is_array($errors)) { return False; } $html_error = '<table border="0" width="100%"><tr><td align="right"><b>' . lang($text) . '</b>: </td><td align="left">' . $errors[0] . '</td></tr>'; for ($i=1; $i<count($errors); $i++) { $html_error .= '<tr><td> </td><td align="left">' . $errors[$i] . '</td></tr>'; } return $html_error . '</table>'; } /** * return the fullname of a user * * @param $lid='' account loginid * @param $firstname='' firstname * @param $lastname='' lastname * @param $accountid=0 id, to check if it's a user or group, otherwise the lid will be used */ static function display_fullname($lid = '', $firstname = '', $lastname = '',$accountid=0) { if (! $lid && ! $firstname && ! $lastname) { $lid = $GLOBALS['egw_info']['user']['account_lid']; $firstname = $GLOBALS['egw_info']['user']['account_firstname']; $lastname = $GLOBALS['egw_info']['user']['account_lastname']; } $is_group = $GLOBALS['egw']->accounts->get_type($accountid ? $accountid : $lid) == 'g'; if (empty($firstname)) $firstname = $lid; if (empty($lastname) || $is_group) { $lastname = $is_group ? lang('Group') : lang('User'); } $display = $GLOBALS['egw_info']['user']['preferences']['common']['account_display']; if ($firstname && $lastname) { $delimiter = $is_group ? ' ' : ', '; } else { $delimiter = ''; } $name = ''; switch($display) { case 'firstname': $name = $firstname . ' ' . $lastname; break; case 'lastname': $name = $lastname . $delimiter . $firstname; break; case 'username': $name = $lid; break; case 'firstall': $name = $firstname . ' ' . $lastname . ' ['.$lid.']'; break; case 'lastall': $name = $lastname . $delimiter . $firstname . ' ['.$lid.']'; break; case 'allfirst': $name = '['.$lid.'] ' . $firstname . ' ' . $lastname; break; case 'all': /* fall through */ default: $name = '['.$lid.'] ' . $lastname . $delimiter . $firstname; } return $name; } /** * grab the owner name * * @param $id account id * @return string full name of user or "#$accountid" if user not found */ static function grab_owner_name($accountid = '') { $lid = $fname = $lname = null; if (!$GLOBALS['egw']->accounts->get_account_name($accountid,$lid,$fname,$lname)) { return '#'.$accountid; } return self::display_fullname($lid,$fname,$lname,$accountid); } /** * create tabs * * @param array $tabs an array repersenting the tabs you wish to display, each element * * * in the array is an array of 3 elements, 'label' which is the * * * text displaed on the tab (you should pass translated string, * * * create_tabs will not do <code>lang()</code> for you), 'link' * * * which is the uri, 'target', the frame name or '_blank' to show * * * page in a new browser window. * @param mixed $selected the tab whos key is $selected will be displayed as current tab * @param $fontsize optional * @return string return html that displays the tabs */ static function create_tabs($tabs, $selected, $fontsize = '') { $output_text = '<table border="0" cellspacing="0" cellpadding="0"><tr>'; /* This is a php3 workaround */ if(EGW_IMAGES_DIR == 'EGW_IMAGES_DIR') { $ir = ExecMethod('phpgwapi.phpgw.common.get_image_path', 'phpgwapi'); } else { $ir = EGW_IMAGES_DIR; } if ($fontsize) { $fs = '<font size="' . $fontsize . '">'; $fse = '</font>'; } $i = 1; while ($tab = each($tabs)) { if ($tab[0] == $selected) { if ($i == 1) { $output_text .= '<td align="right"><img src="' . $ir . '/tabs-start1.gif"></td>'; } $output_text .= '<td align="left" style="background: url(' . $ir . '/tabs-bg1.gif) repeat-x;"> <b><a href="' . $tab[1]['link'] . '" class="tablink" '.$tab[1]['target'].'>' . $fs . $tab[1]['label'] . $fse . '</a></b> </td>'; if ($i == count($tabs)) { $output_text .= '<td align="left"><img src="' . $ir . '/tabs-end1.gif"></td>'; } else { $output_text .= '<td align="left"><img src="' . $ir . '/tabs-sepr.gif"></td>'; } } else { if ($i == 1) { $output_text .= '<td align="right"><img src="' . $ir . '/tabs-start0.gif"></td>'; } $output_text .= '<td align="left" style="background: url(' . $ir . '/tabs-bg0.gif) repeat-x;"> <b><a href="' . $tab[1]['link'] . '" class="tablink" '.$tab[1]['target'].'>' . $fs . $tab[1]['label'] . $fse . '</a></b> </td>'; if (($i + 1) == $selected) { $output_text .= '<td align="left"><img src="' . $ir . '/tabs-sepl.gif"></td>'; } elseif ($i == $selected || $i != count($tabs)) { $output_text .= '<td align="left"><img src="' . $ir . '/tabs-sepm.gif"></td>'; } elseif ($i == count($tabs)) { if ($i == $selected) { $output_text .= '<td align="left"><img src="' . $ir . '/tabs-end1.gif"></td>'; } else { $output_text .= '<td align="left"><img src="' . $ir . '/tabs-end0.gif"></td>'; } } else { if ($i != count($tabs)) { $output_text .= '<td align="left"><img src="' . $ir . '/tabs-sepr.gif"></td>'; } } } $i++; $output_text .= "\n"; } $output_text .= "</table>\n"; return $output_text; } /** * get directory of application * * $appname can either be passed or derived from $GLOBALS['egw_info']['flags']['currentapp']; * @param $appname name of application */ static function get_app_dir($appname = '') { if ($appname == '') { $appname = $GLOBALS['egw_info']['flags']['currentapp']; } if ($appname == 'logout' || $appname == 'login') { $appname = 'phpgwapi'; } $appdir = EGW_INCLUDE_ROOT . '/'.$appname; $appdir_default = EGW_SERVER_ROOT . '/'.$appname; if (@is_dir($appdir)) { return $appdir; } elseif (@is_dir($appdir_default)) { return $appdir_default; } else { return False; } } /** * get inc (include dir) of application * * $appname can either be passed or derived from $GLOBALS['egw_info']['flags']['currentapp']; * @param $appname name of application */ static function get_inc_dir($appname = '') { if (!$appname) { $appname = $GLOBALS['egw_info']['flags']['currentapp']; } if ($appname == 'logout' || $appname == 'login' || $appname == 'about') { $appname = 'phpgwapi'; } $incdir = EGW_INCLUDE_ROOT . '/' . $appname . '/inc'; $incdir_default = EGW_SERVER_ROOT . '/' . $appname . '/inc'; if (@is_dir ($incdir)) { return $incdir; } elseif (@is_dir ($incdir_default)) { return $incdir_default; } else { return False; } } /** * get template dir of an application * * @param $appname appication name optional can be derived from $GLOBALS['egw_info']['flags']['currentapp']; * @return string|boolean dir or false if no dir is found */ static function get_tpl_dir($appname = '') { if (!$appname) { $appname = $GLOBALS['egw_info']['flags']['currentapp']; } if ($appname == 'logout' || $appname == 'login') { $appname = 'phpgwapi'; } if (!isset($GLOBALS['egw_info']['server']['template_set']) && isset($GLOBALS['egw_info']['user']['preferences']['common']['template_set'])) { $GLOBALS['egw_info']['server']['template_set'] = $GLOBALS['egw_info']['user']['preferences']['common']['template_set']; } // Setting this for display of template choices in user preferences if ($GLOBALS['egw_info']['server']['template_set'] == 'user_choice') { $GLOBALS['egw_info']['server']['usrtplchoice'] = 'user_choice'; } if (($GLOBALS['egw_info']['server']['template_set'] == 'user_choice' || !isset($GLOBALS['egw_info']['server']['template_set'])) && isset($GLOBALS['egw_info']['user']['preferences']['common']['template_set'])) { $GLOBALS['egw_info']['server']['template_set'] = $GLOBALS['egw_info']['user']['preferences']['common']['template_set']; } if (!file_exists(EGW_SERVER_ROOT.'/phpgwapi/templates/'.basename($GLOBALS['egw_info']['server']['template_set']).'/class.'. $GLOBALS['egw_info']['server']['template_set'].'_framework.inc.php') && !file_exists(EGW_SERVER_ROOT.'/'.basename($GLOBALS['egw_info']['server']['template_set']).'/inc/class.'. $GLOBALS['egw_info']['server']['template_set'].'_framework.inc.php')) { $GLOBALS['egw_info']['server']['template_set'] = 'idots'; } $tpldir = EGW_SERVER_ROOT . '/' . $appname . '/templates/' . $GLOBALS['egw_info']['server']['template_set']; $tpldir_default = EGW_SERVER_ROOT . '/' . $appname . '/templates/default'; if (@is_dir($tpldir)) { return $tpldir; } elseif (@is_dir($tpldir_default)) { return $tpldir_default; } return False; } /** * checks if image_dir exists and has more than just a navbar-icon * * this is just a workaround for idots, better to use find_image, which has a fallback \ * on a per image basis to the default dir * * @deprecated */ static function is_image_dir($dir) { if (!@is_dir($dir)) { return False; } if (($d = opendir($dir))) { while ($f = readdir($d)) { $ext = strtolower(strrchr($f,'.')); if (($ext == '.gif' || $ext == '.png') && strpos($f,'navbar') === False) { closedir($d); return True; } } closedir($d); } return False; } /** * get image dir of an application * * @param $appname application name optional can be derived from $GLOBALS['egw_info']['flags']['currentapp']; * @deprecated */ static function get_image_dir($appname = '') { if ($appname == '') { $appname = $GLOBALS['egw_info']['flags']['currentapp']; } if (empty($GLOBALS['egw_info']['server']['template_set'])) { $GLOBALS['egw_info']['server']['template_set'] = 'idots'; } $imagedir = EGW_SERVER_ROOT . '/' . $appname . '/templates/' . $GLOBALS['egw_info']['server']['template_set'] . '/images'; $imagedir_default = EGW_SERVER_ROOT . '/' . $appname . '/templates/idots/images'; $imagedir_olddefault = EGW_SERVER_ROOT . '/' . $appname . '/images'; if (self::is_image_dir ($imagedir)) { return $imagedir; } elseif (self::is_image_dir ($imagedir_default)) { return $imagedir_default; } elseif (self::is_image_dir ($imagedir_olddefault)) { return $imagedir_olddefault; } else { return False; } } /** * get image path of an application * * @param $appname appication name optional can be derived from $GLOBALS['egw_info']['flags']['currentapp']; * @deprecated */ static function get_image_path($appname = '') { if ($appname == '') { $appname = $GLOBALS['egw_info']['flags']['currentapp']; } if (empty($GLOBALS['egw_info']['server']['template_set'])) { $GLOBALS['egw_info']['server']['template_set'] = 'idots'; } $imagedir = EGW_SERVER_ROOT . '/'.$appname.'/templates/'.$GLOBALS['egw_info']['server']['template_set'].'/images'; $imagedir_default = EGW_SERVER_ROOT . '/'.$appname.'/templates/idots/images'; $imagedir_olddefault = EGW_SERVER_ROOT . '/'.$appname.'/templates/default/images'; if (self::is_image_dir($imagedir)) { return $GLOBALS['egw_info']['server']['webserver_url'].'/'.$appname.'/templates/'.$GLOBALS['egw_info']['server']['template_set'].'/images'; } elseif (self::is_image_dir($imagedir_default)) { return $GLOBALS['egw_info']['server']['webserver_url'].'/'.$appname.'/templates/idots/images'; } elseif (self::is_image_dir($imagedir_olddefault)) { return $GLOBALS['egw_info']['server']['webserver_url'].'/'.$appname.'/templates/default/images'; } return False; } /** * @deprecated use image($app,$image) they are identical now */ static function find_image($app,$image) { return self::image($app,$image); } /** * Searches an image of a given type, if not found also without extension * * @param string $appname * @param string|array $image one or more image-name in order of precedence * @param string $extension='' extension to $image, makes sense only with an array * @param boolean $svg=false should svg images be returned or not: * true: always return svg, false: never return svg (current default), null: browser dependent, see svg_usable() * @return string url of image or null if not found */ static function image_on($app,$image,$extension='_on',$svg=false) { return ($img = self::image($app,$image,$extension,$svg)) ? $img : self::image($app,$image,'',$svg); } /** * Searches a appname, template and maybe language and type-specific image * * @param string $appname * @param string|array $image one or more image-name in order of precedence * @param string $extension='' extension to $image, makes sense only with an array * @param boolean $svg=false should svg images be returned or not: * true: always return svg, false: never return svg (current default), null: browser dependent, see svg_usable() * @return string url of image or null if not found */ static function image($app,$image,$extension='',$svg=false) { static $image_map_no_svg = null, $image_map_svg = null; if (is_null($svg)) $svg = self::svg_usable (); if ($svg) { $image_map =& $image_map_svg; } else { $image_map =& $image_map_no_svg; } if (is_null($image_map)) $image_map = self::image_map(null, $svg); // array of images in descending precedence if (is_array($image)) { foreach($image as $img) { if (($url = self::image($app, $img, $extension))) { return $url; } } //error_log(__METHOD__."('$app', ".array2string($image).", '$extension') NONE found!"); return null; } $webserver_url = $GLOBALS['egw_info']['server']['webserver_url']; // instance specific images have highest precedence if (isset($image_map['vfs'][$image.$extension])) { return $webserver_url.$image_map['vfs'][$image.$extension]; } // then app specific ones if(isset($image_map[$app][$image.$extension])) { return $webserver_url.$image_map[$app][$image.$extension]; } // then api if(isset($image_map['phpgwapi'][$image.$extension])) { return $webserver_url.$image_map['phpgwapi'][$image.$extension]; } // if image not found, check if it has an extension and try withoug if (strpos($image, '.') !== false) { $name = null; self::get_extension($image, $name); return self::image($app, $name, $extension); } //error_log(__METHOD__."('$app', '$image', '$extension') image NOT found!"); return null; } /** * Does browser support svg * * All non IE and IE 9+ * * @return boolean */ static function svg_usable() { return html::$user_agent !== 'msie' || html::$ua_version >= 9; } /** * Scan filesystem for images of all apps * * For each application and image-name (without extension) one full path is returned. * The path takes template-set and image-type-priority (now fixed to: png, jpg, gif, ico) into account. * * VFS image directory is treated like an application named 'vfs'. * * @param string $template_set=null 'default', 'idots', 'jerryr', default is template-set from user prefs * @param boolean $svg=null prefer svg images, default for all browsers but IE<9 * @return array of application => image-name => full path */ static function image_map($template_set=null, $svg=null) { if (is_null($template_set)) { $template_set = $GLOBALS['egw_info']['server']['template_set']; } if (is_null($svg)) { $svg = self::svg_usable(); } $cache_name = 'image_map_'.$template_set.($svg ? '_svg' : ''); if (($map = egw_cache::getInstance(__CLASS__, $cache_name))) { return $map; } //$starttime = microtime(true); // priority: : PNG->JPG->GIF $img_types = array('png','jpg','gif','ico'); // if we want svg, prepend it to img-types if ($svg) array_unshift ($img_types, 'svg'); $map = array(); foreach(scandir(EGW_SERVER_ROOT) as $app) { if ($app[0] == '.' || !is_dir(EGW_SERVER_ROOT.'/'.$app) || !file_exists(EGW_SERVER_ROOT.'/'.$app.'/templates')) continue; $app_map =& $map[$app]; if (true) $app_map = array(); $imagedirs = array(); if ($app == 'phpgwapi') { $imagedirs[] = $GLOBALS['egw']->framework->template_dir.'/images'; } else { $imagedirs[] = '/'.$app.'/templates/'.$template_set.'/images'; } if ($template_set != 'idots') $imagedirs[] = '/'.$app.'/templates/idots/images'; $imagedirs[] = '/'.$app.'/templates/default/images'; foreach($imagedirs as $imagedir) { if (!file_exists($dir = EGW_SERVER_ROOT.$imagedir) || !is_readable($dir)) continue; foreach(scandir($dir) as $img) { if ($img[0] == '.') continue; $subdir = null; foreach(is_dir($dir.'/'.$img) ? scandir($dir.'/'.($subdir=$img)) : (array) $img as $img) { $name = null; if (!in_array($ext = self::get_extension($img, $name), $img_types) || empty($name)) continue; if (isset($subdir)) $name = $subdir.'/'.$name; if (!isset($app_map[$name]) || array_search($ext, $img_types) < array_search(self::get_extension($app_map[$name]), $img_types)) { $app_map[$name] = $imagedir.'/'.$name.'.'.$ext; } } } } } $app_map =& $map['vfs']; if (true) $app_map = array(); if (($dir = $GLOBALS['egw_info']['server']['vfs_image_dir']) && egw_vfs::file_exists($dir) && egw_vfs::is_readable($dir)) { foreach(egw_vfs::find($dir) as $img) { if (!in_array($ext = self::get_extension($img, $name), $img_types) || empty($name)) continue; if (!isset($app_map[$name]) || array_search($ext, $img_types) < array_search(self::get_extension($app_map[$name]), $img_types)) { $app_map[$name] = egw_vfs::download_url($img); } } } else if ($dir) { return $map; } //error_log(__METHOD__."('$template_set') took ".(microtime(true)-$starttime).' secs'); egw_cache::setInstance(__CLASS__, $cache_name, $map, 86400); // cache for one day //echo "<p>template_set=".array2string($template_set)."</p>\n"; _debug_array($map); return $map; } /** * Delete image map cache for ALL template sets */ public static function delete_image_map() { $templates = array('idots', 'jerryr', 'jdots', 'pixelegg'); if (($template_set = $GLOBALS['egw_info']['user']['preferences']['common']['template_set']) && !in_array($template_set, $templates)) { $templates[] = $template_set; } //error_log(__METHOD__."() for templates ".array2string($templates)); foreach($templates as $template_set) { egw_cache::unsetInstance(__CLASS__, 'image_map_'.$template_set); egw_cache::unsetInstance(__CLASS__, 'image_map_'.$template_set.'_svg'); } } /** * Get extension (and optional basename without extension) of a given path * * @param string $path * @param string &$name on return basename without extension * @return string extension without dot, eg. 'php' */ public static function get_extension($path, &$name=null) { $parts = explode('.', basename($path)); $ext = array_pop($parts); $name = implode('.', $parts); return $ext; } /** * prepare an array with variables used to render the navbar * * @deprecated inherit from egw_framework class in your template and use egw_framework::_navbar_vars() */ static function navbar() { $GLOBALS['egw_info']['navbar'] = $GLOBALS['egw']->framework->_get_navbar_vars(); } /** * load header.inc.php for an application * * @deprecated */ static function app_header() { if (file_exists(EGW_APP_INC . '/header.inc.php')) { include(EGW_APP_INC . '/header.inc.php'); } } /** * load the eGW header * * @deprecated use egw_framework::header(), $GLOBALS['egw']->framework->navbar() or better egw_framework::render($content) */ static function egw_header() { echo $GLOBALS['egw']->framework->header(); if (!$GLOBALS['egw_info']['flags']['nonavbar']) { echo $GLOBALS['egw']->framework->navbar(); } } /** * load the eGW footer * * @deprecated use echo $GLOBALS['egw']->framework->footer() or egw_framework::render($content) */ static function egw_footer() { if(is_object($GLOBALS['egw']->framework)) { echo $GLOBALS['egw']->framework->footer(); } } /** * Used by template headers for including CSS in the header * * @deprecated use $GLOBALS['egw']->framework->_get_css() * @return string */ static function get_css() { return $GLOBALS['egw']->framework->_get_css(); } /** * Used by the template headers for including javascript in the header * * @deprecated use egw_framework::_get_js() * @return string the javascript to be included */ static function get_java_script() { return egw_framework::_get_js(); } /** * Returns on(Un)Load attributes from js class * * @deprecated use egw_framework::_get_js() * @returns string body attributes */ static function get_body_attribs() { return egw_framework::_get_body_attribs(); } static function hex2bin($data) { $len = strlen($data); return @pack('H' . $len, $data); } /** * encrypt data passed to the function * * @param $data data (string?) to be encrypted */ static function encrypt($data) { return $GLOBALS['egw']->crypto->encrypt($data); } /** * decrypt $data * * @param $data data to be decrypted */ static function decrypt($data) { return $GLOBALS['egw']->crypto->decrypt($data); } /** * legacy wrapper for newer auth class function, encrypt_password * * uses the encryption type set in setup and calls the appropriate encryption functions * * @deprecated use auth::encrypt_password() * @param $password password to encrypt */ static function encrypt_password($password,$sql=False) { return auth::encrypt_password($password,$sql); } /** * find the current position of the app is the users portal_order preference * * @param $app application id to find current position - required * No discussion */ function find_portal_order($app) { if(!is_array($GLOBALS['egw_info']['user']['preferences']['portal_order'])) { return -1; } @reset($GLOBALS['egw_info']['user']['preferences']['portal_order']); while(list($seq,$appid) = each($GLOBALS['egw_info']['user']['preferences']['portal_order'])) { if($appid == $app) { @reset($GLOBALS['egw_info']['user']['preferences']['portal_order']); return $seq; } } @reset($GLOBALS['egw_info']['user']['preferences']['portal_order']); return -1; } /** * return a formatted timestamp or current time * * @param int $t=0 timestamp, default current time * @param string $format='' timeformat, default '' = read from the user prefernces * @param boolean $adjust_to_usertime=true should datetime::tz_offset be added to $t or not, default true * @deprecated use egw_time::to($time, $format) egw_time::server2user($time, $format) * @return string the formated date/time */ static function show_date($t = 0, $format = '', $adjust_to_usertime=true) { if (!$t) $t = 'now'; $ret = $adjust_to_usertime ? egw_time::server2user($t, $format) : egw_time::to($t, $format); //error_log(__METHOD__.'('.array2string($t).", '$format', ".array2string($adjust_to_usertime).') returning '.array2string($ret)); return $ret; } /** * Format a date according to the user preferences * * @param string $yearstr year * @param string $monthstr month * @param string $day day * @param boolean $add_seperator=false add the separator specifed in the prefs or not, default no * @return string */ static function dateformatorder($yearstr,$monthstr,$daystr,$add_seperator = False) { $dateformat = strtolower($GLOBALS['egw_info']['user']['preferences']['common']['dateformat']); $sep = substr($GLOBALS['egw_info']['user']['preferences']['common']['dateformat'],1,1); $dlarr[strpos($dateformat,'y')] = $yearstr; $dlarr[strpos($dateformat,'m')] = $monthstr; $dlarr[strpos($dateformat,'d')] = $daystr; ksort($dlarr); if ($add_seperator) { return implode($sep,$dlarr); } return implode(' ',$dlarr); } /** * format the time takes settings from user preferences * * @param int $hour hour * @param int $min minutes * @param int/string $sec='' defaults to '' * @return string formated time */ static function formattime($hour,$min,$sec='') { $h12 = $hour; if ($GLOBALS['egw_info']['user']['preferences']['common']['timeformat'] == '12') { if ($hour >= 12) { $ampm = ' pm'; } else { $ampm = ' am'; } $h12 %= 12; if ($h12 == 0 && $hour) { $h12 = 12; } if ($h12 == 0 && !$hour) { $h12 = 0; } } else { $h12 = $hour; } if ($sec !== '') { $sec = ':'.$sec; } return $h12.':'.$min.$sec.$ampm; } /** * convert all european special chars to ascii * * @param string $str * @return string */ public static function transliterate($str) { static $extra = array( 'ß' => 'ss', ' ' => '', ); $entities = htmlentities($str, ENT_QUOTES,translation::charset()); $extra_replaced = str_replace(array_keys($extra),array_values($extra),$entities); $umlauts = preg_replace('/&([aAuUoO])uml;/','\\1e',$extra_replaced); // replace german umlauts with the letter plus one 'e' $accents = preg_replace('/&([a-zA-Z])(grave|acute|circ|ring|cedil|tilde|slash|uml);/','\\1',$umlauts); // remove all types of acents return preg_replace('/&([a-zA-Z]+|#[0-9]+|);/','',$accents); // remove all other entities } /** * Format an email address according to the system standard * * Convert all european special chars to ascii and fallback to the accountname, if nothing left eg. chiniese * * @param string $first firstname * @param string $last lastname * @param string $account account-name (lid) * @param string $domain =null domain-name or null to use eGW's default domain $GLOBALS['egw_info']['server']['mail_suffix] * @return string with email address */ static function email_address($first,$last,$account,$domain=null) { //echo "<p align=right>common::email_address('$first','$last','$account')"; foreach (array('first','last','account') as $name) { $$name = self::transliterate($$name); } //echo " --> ('$first', '$last', '$account')"; if (!$first && !$last) // fallback to the account-name, if real names contain only special chars { $first = ''; $last = $account; } if (!$first || !$last) { $dot = $underscore = ''; } else { $dot = '.'; $underscore = '_'; } if (!$domain) $domain = $GLOBALS['egw_info']['server']['mail_suffix']; $email = str_replace(array('first','last','initial','account','dot','underscore','-'), array($first,$last,substr($first,0,1),$account,$dot,$underscore,''), $GLOBALS['egw_info']['server']['email_address_format'] ? $GLOBALS['egw_info']['server']['email_address_format'] : 'first-dot-last'). ($domain ? '@'.$domain : ''); //echo " = '$email'</p>\n"; return $email; } /** * ? * * This will be moved into the applications area */ static function check_code($code) { $s = '<br>'; switch ($code) { case 13: $s .= lang('Your message has been sent');break; case 14: $s .= lang('New entry added sucessfully');break; case 15: $s .= lang('Entry updated sucessfully'); break; case 16: $s .= lang('Entry has been deleted sucessfully'); break; case 18: $s .= lang('Password has been updated'); break; case 38: $s .= lang('Password could not be changed'); break; case 19: $s .= lang('Session has been killed'); break; case 27: $s .= lang('Account has been updated'); break; case 28: $s .= lang('Account has been created'); break; case 29: $s .= lang('Account has been deleted'); break; case 30: $s .= lang('Your settings have been updated'); break; case 31: $s .= lang('Group has been added'); break; case 32: $s .= lang('Group has been deleted'); break; case 33: $s .= lang('Group has been updated'); break; case 34: $s .= lang('Account has been deleted') . '<p>' . lang('Error deleting %1 %2 directory',lang('users'),' '.lang('private').' ') . ',<br>' . lang('Please %1 by hand',lang('delete')) . '<br><br>' . lang('To correct this error for the future you will need to properly set the') . '<br>' . lang('permissions to the files/users directory') . '<br>' . lang('On *nix systems please type: %1','chmod 770 ' . $GLOBALS['egw_info']['server']['files_dir'] . '/users/'); break; case 35: $s .= lang('Account has been updated') . '<p>' . lang('Error renaming %1 %2 directory',lang('users'), ' '.lang('private').' ') . ',<br>' . lang('Please %1 by hand', lang('rename')) . '<br><br>' . lang('To correct this error for the future you will need to properly set the') . '<br>' . lang('permissions to the files/users directory') . '<br>' . lang('On *nix systems please type: %1','chmod 770 ' . $GLOBALS['egw_info']['server']['files_dir'] . '/users/'); break; case 36: $s .= lang('Account has been created') . '<p>' . lang('Error creating %1 %2 directory',lang('users'), ' '.lang('private').' ') . ',<br>' . lang('Please %1 by hand', lang('create')) . '<br><br>' . lang('To correct this error for the future you will need to properly set the') . '<br>' . lang('permissions to the files/users directory') . '<br>' . lang('On *nix systems please type: %1','chmod 770 ' . $GLOBALS['egw_info']['server']['files_dir'] . '/users/'); break; case 37: $s .= lang('Group has been added') . '<p>' . lang('Error creating %1 %2 directory',lang('groups'),' ') . ',<br>' . lang('Please %1 by hand', lang('create')) . '<br><br>' . lang('To correct this error for the future you will need to properly set the') . '<br>' . lang('permissions to the files/users directory') . '<br>' . lang('On *nix systems please type: %1','chmod 770 ' . $GLOBALS['egw_info']['server']['files_dir'] . '/groups/'); break; case 38: $s .= lang('Group has been deleted') . '<p>' . lang('Error deleting %1 %2 directory',lang('groups'),' ') . ',<br>' . lang('Please %1 by hand', lang('delete')) . '<br><br>' . lang('To correct this error for the future you will need to properly set the') . '<br>' . lang('permissions to the files/users directory') . '<br>' . lang('On *nix systems please type: %1','chmod 770 ' . $GLOBALS['egw_info']['server']['files_dir'] . '/groups/'); break; case 39: $s .= lang('Group has been updated') . '<p>' . lang('Error renaming %1 %2 directory',lang('groups'),' ') . ',<br>' . lang('Please %1 by hand', lang('rename')) . '<br><br>' . lang('To correct this error for the future you will need to properly set the') . '<br>' . lang('permissions to the files/users directory') . '<br>' . lang('On *nix systems please type: %1','chmod 770 ' . $GLOBALS['egw_info']['server']['files_dir'] . '/groups/'); break; case 40: $s .= lang('You have not entered a title').'.'; break; case 41: $s .= lang('You have not entered a valid time of day').'.'; break; case 42: $s .= lang('You have not entered a valid date').'.'; break; case 43: $s .= lang('You have not entered participants').'.'; break; default: return ''; } return $s; } /** * process error message * * @param $error error * @param $line line * @param $file file */ static function phpgw_error($error,$line = '', $file = '') { echo '<p><b>eGroupWare internal error:</b><p>'.$error; if ($line) { echo 'Line: '.$line; } if ($file) { echo 'File: '.$file; } echo '<p>Your session has been halted.'; exit; } /** * create phpcode from array * * @param $array - array */ static function create_phpcode_from_array($array) { while (list($key, $val) = each($array)) { if (is_array($val)) { while (list($key2, $val2) = each($val)) { if (is_array($val2)) { while (list($key3, $val3) = each ($val2)) { if (is_array($val3)) { while (list($key4, $val4) = each ($val3)) { $s .= "\$GLOBALS['egw_info']['" . $key . "']['" . $key2 . "']['" . $key3 . "']['" .$key4 . "']='" . $val4 . "';"; $s .= "\n"; } } else { $s .= "\$GLOBALS['egw_info']['" . $key . "']['" . $key2 . "']['" . $key3 . "']='" . $val3 . "';"; $s .= "\n"; } } } else { $s .= "\$GLOBALS['egw_info']['" . $key ."']['" . $key2 . "']='" . $val2 . "';"; $s .= "\n"; } } } else { $s .= "\$GLOBALS['egw_info']['" . $key . "']='" . $val . "';"; $s .= "\n"; } } return $s; } // This will return the full phpgw_info array, used for debugging /** * return the full phpgw_info array for debugging * * @param array - array */ static function debug_list_array_contents($array) { while (list($key, $val) = each($array)) { if (is_array($val)) { while (list($key2, $val2) = each($val)) { if (is_array($val2)) { while (list($key3, $val3) = each ($val2)) { if (is_array($val3)) { while (list($key4, $val4) = each ($val3)) { echo $$array . "[$key][$key2][$key3][$key4]=$val4<br>"; } } else { echo $$array . "[$key][$key2][$key3]=$val3<br>"; } } } else { echo $$array . "[$key][$key2]=$val2<br>"; } } } else { echo $$array . "[$key]=$val<br>"; } } } // This will return a list of functions in the API /** * return a list of functionsin the API * */ static function debug_list_core_functions() { echo '<br><b>core functions</b><br>'; echo '<pre>'; chdir(EGW_INCLUDE_ROOT . '/phpgwapi'); system("grep -r '^[ \t]*function' *"); echo '</pre>'; } const NEXTID_TABLE = 'egw_nextid'; /** * Return a value for the next id an app/class may need to insert values into LDAP * * @param string $appname app-name * @param int $min=0 if != 0 minimum id * @param int $max=0 if != 0 maximum id allowed, if it would be exceeded we return false * @return int/boolean the next id or false if $max given and exceeded */ static function next_id($appname,$min=0,$max=0) { if (!$appname) { return -1; } $id = (int) $GLOBALS['egw']->db->select(self::NEXTID_TABLE,'id',array('appname' => $appname),__LINE__,__FILE__)->fetchColumn(); if ($max && $id >= $max) { return False; } ++$id; if($id < $min) $id = $min; $GLOBALS['egw']->db->insert(self::NEXTID_TABLE,array('id' => $id),array('appname' => $appname),__LINE__,__FILE__); return (int)$id; } /** * Return a value for the last id entered, which an app may need to check values for LDAP * * @param string $appname app-name * @param int $min=0 if != 0 minimum id * @param int $max=0 if != 0 maximum id allowed, if it would be exceeded we return false * @return int current id in the next_id table for a particular app/class or -1 for no app and false if $max is exceeded. */ static function last_id($appname,$min=0,$max=0) { if (!$appname) { return -1; } $id = (int)$GLOBALS['egw']->db->select(self::NEXTID_TABLE,'id',array('appname' => $appname),__LINE__,__FILE__)->fetchColumn(); if (!$id || $id < $min) { return self::next_id($appname,$min,$max); } if ($max && $id > $max) { return False; } return $id; } /** * gets an eGW conformat referer from $_SERVER['HTTP_REFERER'], suitable for direct use in the link function * * @param string $default='' default to use if referer is not set by webserver or not determinable * @param string $referer='' referer string to use, default ('') use $_SERVER['HTTP_REFERER'] * @return string * @todo get "real" referer for jDots template */ static function get_referer($default='',$referer='') { // HTTP_REFERER seems NOT to get urldecoded if (!$referer) $referer = urldecode($_SERVER['HTTP_REFERER']); $webserver_url = $GLOBALS['egw_info']['server']['webserver_url']; if (empty($webserver_url) || $webserver_url{0} == '/') // url is just a path { $referer = preg_replace('/^https?:\/\/[^\/]+/','',$referer); // removing the domain part } if (strlen($webserver_url) > 1) { list(,$referer) = explode($webserver_url,$referer,2); } $referer = str_replace('/etemplate/process_exec.php','/index.php',$referer); if (empty($referer) || strpos($referer,'cd=yes') !== false) $referer = $default; return $referer; } // some depricated functions for the migration static function phpgw_exit($call_footer = False) { self::egw_exit($call_footer); } static function phpgw_final() { self::egw_final(); } static function phpgw_header() { self::egw_header(); } static function phpgw_footer() { self::egw_footer(); } }