Author: ralfbecker
Date: Tue Apr 26 16:38:08 2016
New Revision: 55853
URL: http://svn.stylite.de/viewvc/egroupware?rev=55853&view=rev
Log:
move egw and applications class to api including (common_)functions.inc.php
Added:
trunk/egroupware/api/src/Egw/
trunk/egroupware/api/src/Egw.php
- copied, changed from r55817, trunk/phpgwapi/inc/class.egw.inc.php
trunk/egroupware/api/src/Egw/Applications.php
- copied, changed from r55840, trunk/phpgwapi/inc/class.applications.inc.php
trunk/egroupware/api/src/Egw/Base.php
- copied, changed from r55817, trunk/phpgwapi/inc/class.egw.inc.php
trunk/egroupware/api/src/autoload.php
- copied, changed from r55840, trunk/phpgwapi/inc/common_functions.inc.php
trunk/egroupware/api/src/loader/
trunk/egroupware/api/src/loader.php
- copied, changed from r55817, trunk/phpgwapi/inc/functions.inc.php
trunk/egroupware/api/src/loader/common.php
- copied, changed from r55840, trunk/phpgwapi/inc/common_functions.inc.php
trunk/egroupware/api/src/loader/exception.php
- copied, changed from r55840, trunk/phpgwapi/inc/common_functions.inc.php
trunk/egroupware/api/src/loader/security.php
- copied, changed from r55840, trunk/phpgwapi/inc/common_functions.inc.php
trunk/phpgwapi/inc/deprecated_functions.inc.php
- copied, changed from r55840, trunk/phpgwapi/inc/common_functions.inc.php
Modified:
trunk/egroupware/header.inc.php.template
trunk/phpgwapi/inc/class.applications.inc.php
trunk/phpgwapi/inc/class.egw.inc.php
trunk/phpgwapi/inc/common_functions.inc.php
trunk/phpgwapi/inc/functions.inc.php
Copied: trunk/egroupware/api/src/Egw.php (from r55817, trunk/phpgwapi/inc/class.egw.inc.php)
URL: http://svn.stylite.de/viewvc/egroupware/trunk/egroupware/api/src/Egw.php?p2=trunk/egroupware/api/src/Egw.php&p1=trunk/phpgwapi/inc/class.egw.inc.php&r1=55817&r2=55853&rev=55853&view=diff
==============================================================================
--- trunk/phpgwapi/inc/class.egw.inc.php (original)
+++ trunk/egroupware/api/src/Egw.php Tue Apr 26 16:38:08 2016
@@ -1,6 +1,6 @@
<?php
/**
- * eGroupWare API - Applications
+ * EGroupware API - Applications
*
* @link http://www.egroupware.org
* This file was originaly written by Dan Kuykendall and Joseph Engo
@@ -12,7 +12,12 @@
* @version $Id$
*/
-use EGroupware\Api;
+namespace EGroupware\Api;
+
+// explicitly list old, non-namespaced classes
+// they are only used, if phpgwapi is installed
+use accounts;
+use egw_session;
/**
* New written class to create the eGW enviroment AND restore it from a php-session
@@ -22,16 +27,16 @@
* there instead of creating it completly new on each page-request.
* The enviroment gets now created by the egw-class
*
- * Use now a php5 getter method to create the usuall subobject on demand, to allow a quicker
- * header include on sites not useing php4-restore.
+ * Extending Egw\Base which uses now a getter method to create the usual subobject on demand,
+ * to allow a quicker header include on sites not using php4-restore.
* This also makes a lot of application code, like the following, unnecessary:
- * if (!is_object($GLOBALS['egw']->datetime)
+ * if (!is_object($GLOBALS['egw']->ldap)
* {
- * $GLOBALS['egw']->datetime = CreateObject('phpgwapi.datetime');
+ * $GLOBALS['egw']->ldap = Api\Ldap::factory();
* }
- * You can now simply use $GLOBALS['egw']->datetime, and the egw class instanciates it for you on demand.
+ * You can now simply use $GLOBALS['egw']->ldap, and the egw class instanciates it for you on demand.
*/
-class egw extends egw_minimal
+class Egw extends Egw\Base
{
/**
* Turn on debug mode. Will output additional data for debugging purposes.
@@ -42,21 +47,9 @@
/**
* Instance of the account object
*
- * @var accounts
+ * @var Accounts
*/
var $accounts;
- /**
- * Instace of the common object
- *
- * @var common
- */
- var $common;
- /**
- * Instace of the hooks object
- *
- * @var hooks
- */
- var $hooks;
/**
* Constructor: Instantiates the sub-classes
@@ -67,8 +60,6 @@
function __construct($domain_names=null)
{
$GLOBALS['egw'] =& $this; // we need to be immediately available there for the other classes we instantiate
- // for the migration: reference us to the old phpgw object
- $GLOBALS['phpgw'] =& $this;
$this->setup($domain_names,True);
}
@@ -83,27 +74,27 @@
{
// create the DB-object
// as SiteMgr, Wiki, KnowledgeBase and probably more still use eg next_record(), we stick with Db\Deprecated for now
- $this->db = new Api\Db\Deprecated($GLOBALS['egw_info']['server']);
+ $this->db = new Db\Deprecated($GLOBALS['egw_info']['server']);
if ($this->debug)
{
$this->db->Debug = 1;
}
- $this->db->set_app(Api\Db::API_APPNAME);
+ $this->db->set_app(Db::API_APPNAME);
// check if eGW is already setup, if not redirect to setup/
try {
$this->db->connect();
- $num_config = $this->db->select(config::TABLE,'COUNT(config_name)',false,__LINE__,__FILE__)->fetchColumn();
- }
- catch(Api\Db\Exception\Connection $e) {
+ $num_config = $this->db->select(Config::TABLE,'COUNT(config_name)',false,__LINE__,__FILE__)->fetchColumn();
+ }
+ catch(Db\Exception\Connection $e) {
// ignore exception, get handled below
}
- catch(Api\Db\Exception\InvalidSql $e1) {
+ catch(Db\Exception\InvalidSql $e1) {
unset($e1); // not used
try {
$phpgw_config = $this->db->select('phpgw_config','COUNT(config_name)',false,__LINE__,__FILE__)->fetchColumn();
}
- catch (Api\Db\Exception\InvalidSql $e2) {
+ catch (Db\Exception\InvalidSql $e2) {
unset($e2); // not used
// ignor error, get handled below
}
@@ -117,13 +108,13 @@
}
if ($e)
{
- throw new Api\Db\Exception\Setup('Connection with '.$e->getMessage()."\n\n".
+ throw new Db\Exception\Setup('Connection with '.$e->getMessage()."\n\n".
'Maybe you not created a database for EGroupware yet.',999);
}
- throw new Api\Db\Exception\Setup('It appears that you have not created the database tables for EGroupware.',999);
- }
- // Set the DB's client charset if a system-charset is set and some other values needed by egw_cache (used in config::read)
- foreach($this->db->select(config::TABLE,'config_name,config_value',array(
+ throw new Db\Exception\Setup('It appears that you have not created the database tables for EGroupware.',999);
+ }
+ // Set the DB's client charset if a system-charset is set and some other values needed by egw_cache (used in Config::read)
+ foreach($this->db->select(Config::TABLE,'config_name,config_value',array(
'config_app' => 'phpgwapi',
'config_name' => array('system_charset','install_id','temp_dir'),
),__LINE__,__FILE__) as $row)
@@ -135,7 +126,7 @@
$this->db->Link_ID->SetCharSet($GLOBALS['egw_info']['server']['system_charset']);
}
// load up the $GLOBALS['egw_info']['server'] array
- $GLOBALS['egw_info']['server'] += config::read('phpgwapi');
+ $GLOBALS['egw_info']['server'] += Config::read('phpgwapi');
// if no server timezone set, use date_default_timezone_get() to determine it once
// it fills to log with deprecated warnings under 5.3 otherwise
@@ -145,7 +136,7 @@
try
{
$tz = new DateTimeZone(date_default_timezone_get());
- config::save_value('server_timezone',$GLOBALS['egw_info']['server']['server_timezone'] = $tz->getName(),'phpgwapi');
+ Config::save_value('server_timezone',$GLOBALS['egw_info']['server']['server_timezone'] = $tz->getName(),'phpgwapi');
error_log(__METHOD__."() stored server_timezone=".$GLOBALS['egw_info']['server']['server_timezone']);
}
catch(Exception $e)
@@ -156,23 +147,33 @@
}
date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
+ // if phpgwapi exists we prefer accounts and egw_session, as they have some deprecated methods
+ if (file_exists(EGW_SERVER_ROOT.'/phpgwapi'))
+ {
+ $this->accounts = new accounts();
+ /* Do not create the session object if called by the sessions class. This way
+ * we ensure the correct db based on the user domain.
+ */
+ if($createsessionobject)
+ {
+ $this->session = new egw_session($domain_names);
+ }
+ }
+ else
+ {
+ $this->accounts = new Accounts();
+ /* Do not create the session object if called by the sessions class. This way
+ * we ensure the correct db based on the user domain.
+ */
+ if($createsessionobject)
+ {
+ $this->session = new Session($domain_names);
+ }
+ }
// setup the other subclasses
- // translation class is here only for backward compatibility, as all it's methods can be called static now
- $this->translation = new translation();
- $this->common = new common();
- $this->accounts = new accounts();
- $this->acl = new acl();
- // we instanciate the hooks object here manually, to cache it's hooks in the session
- $this->hooks = new hooks();
- /* Do not create the session object if called by the sessions class. This way
- * we ensure the correct db based on the user domain.
- */
- if($createsessionobject)
- {
- $this->session = new egw_session($domain_names);
- }
- $this->preferences = new preferences();
- $this->applications = new applications();
+ $this->acl = new Acl();
+ $this->preferences = new Preferences();
+ $this->applications = new Egw\Applications();
if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login' && $GLOBALS['egw_info']['flags']['currentapp'] != 'logout')
{
@@ -230,7 +231,7 @@
$this->template->set_root(EGW_APP_TPL);
}
// init the translation class, necessary as own wakeup would run before our's
- translation::init(isset($GLOBALS['egw_info']['flags']['load_translations']) ? $GLOBALS['egw_info']['flags']['load_translations'] : true);
+ Translation::init(isset($GLOBALS['egw_info']['flags']['load_translations']) ? $GLOBALS['egw_info']['flags']['load_translations'] : true);
$this->unset_datetime();
@@ -261,17 +262,22 @@
// output the header unless the developer turned it off
if (!@$GLOBALS['egw_info']['flags']['noheader'])
{
- common::egw_header();
+ echo $GLOBALS['egw']->framework->header();
+
+ if (!$GLOBALS['egw_info']['flags']['nonavbar'])
+ {
+ echo $GLOBALS['egw']->framework->navbar();
+ }
}
// Load the (depricated) app include files if they exists
if (EGW_APP_INC != "" && ! preg_match ('/phpgwapi/i', EGW_APP_INC) &&
- file_exists(EGW_APP_INC . '/functions.inc.php') && !isset($_GET['menuaction']))
+ file_exists(EGW_APP_INC . '/functions.inc.php') && !isset($_GET['menuaction']))
{
include(EGW_APP_INC . '/functions.inc.php');
}
if (!@$GLOBALS['egw_info']['flags']['noheader'] && !@$GLOBALS['egw_info']['flags']['noappheader'] &&
- file_exists(EGW_APP_INC . '/header.inc.php') && !isset($_GET['menuaction']))
+ file_exists(EGW_APP_INC . '/header.inc.php') && !isset($_GET['menuaction']))
{
include(EGW_APP_INC . '/header.inc.php');
}
@@ -331,7 +337,7 @@
{
$redirect = '/login.php?';
// only add "your session could not be verified", if a sessionid is given (cookie or on url)
- if (egw_session::get_sessionid()) $redirect .= 'cd=10&';
+ if (Session::get_sessionid()) $redirect .= 'cd=10&';
}
if ($relpath) $redirect .= 'phpgw_forward='.urlencode($relpath.(!empty($query) ? '?'.$query : ''));
self::redirect_link($redirect);
@@ -343,9 +349,9 @@
*
* If the user has no rights for the app (eg. called via URL) he get a permission denied page (this function does NOT return)
*
- * @throws Api\Exception\Redirect for anonymous user accessing something he has no rights to
- * @throws Api\Exception\NoPermission\Admin
- * @throws Api\Exception\NoPermission\App
+ * @throws Exception\Redirect for anonymous user accessing something he has no rights to
+ * @throws Exception\NoPermission\Admin
+ * @throws Exception\NoPermission\App
*/
function check_app_rights()
{
@@ -361,17 +367,17 @@
if ($this->session->session_flags == 'A')
{
// need to destroy a basic auth session here, because it will only be available on current url
- if (($sessionid = egw_session::get_sessionid(true)))
+ if (($sessionid = Session::get_sessionid(true)))
{
$GLOBALS['egw']->session->destroy($sessionid);
}
- throw new Api\Exception\Redirect(egw::link('/logout.php'));
+ throw new Exception\Redirect(egw::link('/logout.php'));
}
if ($currentapp == 'admin' || $GLOBALS['egw_info']['flags']['admin_only'])
{
- throw new Api\Exception\NoPermission\Admin();
+ throw new Exception\NoPermission\Admin();
}
- throw new Api\Exception\NoPermission\App($currentapp);
+ throw new Exception\NoPermission\App($currentapp);
}
}
}
@@ -479,17 +485,17 @@
*/
static function redirect($url, $link_app=null)
{
- Api\Framework::redirect($url, $link_app);
+ Framework::redirect($url, $link_app);
}
/**
* Shortcut to translation class
*
- * This function is a basic wrapper to translation::translate()
+ * This function is a basic wrapper to Translation::translate()
*
* @deprecated only used in the old timetracker
* @param string The key for the phrase
- * @see translation::translate()
+ * @see Translation::translate()
*/
static function lang($key,$args=null)
{
@@ -498,7 +504,7 @@
$args = func_get_args();
array_shift($args);
}
- return translation::translate($key,$args);
+ return Translation::translate($key,$args);
}
/**
@@ -535,9 +541,9 @@
define('EGW_SHUTDOWN',True);
// send json response BEFORE flushing output
- if (egw_json_request::isJSONRequest())
- {
- egw_json_response::sendResult();
+ if (Json\Request::isJSONRequest())
+ {
+ Json\Response::sendResult();
}
// run all on_shutdown callbacks with session in their name (eg. egw_link::save_session_cache), do NOT stop on exceptions
@@ -549,7 +555,7 @@
if (!is_array($callback) || strpos($callback[1], 'session') === false) continue;
call_user_func_array($callback, $data);
}
- catch (Exception $ex) {
+ catch (\Exception $ex) {
_egw_log_exception($ex);
}
unset(self::$shutdown_callbacks[$n]);
@@ -579,113 +585,17 @@
$callback = array_shift($data);
call_user_func_array($callback, $data);
}
- catch (Exception $ex) {
+ catch (\Exception $ex) {
_egw_log_exception($ex);
}
}
// call the asyncservice check_run function if it is not explicitly set to cron-only
if (!$GLOBALS['egw_info']['server']['asyncservice']) // is default
{
- ExecMethod('phpgwapi.asyncservice.check_run','fallback');
+ $async = new Asyncservice();
+ $async->fallback();
}
$this->db->disconnect();
}
}
}
-
-/**
- * Minimal eGW object used in setup, does not instanciate anything by default
- *
- */
-class egw_minimal
-{
- /**
- * Instance of the db-object
- *
- * @var egw_db
- */
- var $db;
- /**
- * Current app at the instancation of the class
- *
- * @var string
- */
- var $currentapp;
- /**
- * Global ADOdb object, need to be defined here, to not call magic __get method
- *
- * @var ADOConnection
- */
- var $ADOdb;
-
- /**
- * Classes which get instanciated in a different name
- *
- * @var array
- */
- static $sub_objects = array(
- 'log' => 'errorlog',
-// 'js' => 'javascript',
- 'link' => 'bolink', // depricated use static egw_link methods
- 'datetime' => 'egw_datetime',
- 'framework' => true, // special handling in __get()
- 'template' => 'Template',
- 'session' => 'egw_session', // otherwise $GLOBALS['egw']->session->appsession() fails
- // classes moved to new api dir
- 'ldap' => true,
- 'auth' => 'EGroupware\\Api\\Auth',
- );
-
- /**
- * Magic function to check if a sub-object is set
- *
- * @param string $name
- * @return boolean
- */
- function __isset($name)
- {
- //error_log(__METHOD__."($name)");
- return isset($this->$name);
- }
-
- /**
- * Magic function to return a sub-object
- *
- * @param string $name
- * @return mixed
- */
- function __get($name)
- {
- //error_log(__METHOD__."($name)".function_backtrace());
-
- if ($name == 'js') $name = 'framework'; // javascript class is integrated now into framework
-
- if (isset($this->$name))
- {
- return $this->$name;
- }
-
- if (!isset(self::$sub_objects[$name]) && !class_exists($name))
- {
- if ($name != 'ADOdb') error_log(__METHOD__.": There's NO $name object! ".function_backtrace());
- return null;
- }
- switch($name)
- {
- case 'framework':
- return $this->framework = egw_framework::factory();
- case 'template': // need to be instancated for the current app
- if (!($tpl_dir = common::get_tpl_dir($this->currentapp)))
- {
- return null;
- }
- return $this->template = new Template($tpl_dir);
- case 'ldap':
- return $this->ldap = Api\Ldap::factory(false);
- default:
- $class = isset(self::$sub_objects[$name]) ? self::$sub_objects[$name] : $name;
- break;
- }
- return $this->$name = new $class();
- }
-}
Copied: trunk/egroupware/api/src/Egw/Applications.php (from r55840, trunk/phpgwapi/inc/class.applications.inc.php)
URL: http://svn.stylite.de/viewvc/egroupware/trunk/egroupware/api/src/Egw/Applications.php?p2=trunk/egroupware/api/src/Egw/Applications.php&p1=trunk/phpgwapi/inc/class.applications.inc.php&r1=55840&r2=55853&rev=55853&view=diff
==============================================================================
--- trunk/phpgwapi/inc/class.applications.inc.php (original)
+++ trunk/egroupware/api/src/Egw/Applications.php Tue Apr 26 16:38:08 2016
@@ -1,21 +1,22 @@
<?php
/**
- * eGroupWare API - Applications
+ * EGroupware API - Applications
*
* @link http://www.egroupware.org
* @author Mark Peters <[email protected]>
* Copyright (C) 2001 Mark Peters
* @license http://opensource.org/licenses/lgpl-license.php LGPL - GNU Lesser General Public License
* @package api
+ * @subpackage egw
* @version $Id$
*/
+namespace EGroupware\Api\Egw;
+
/**
- * functions for managing and installing apps
- *
- * Author: skeeter
+ * Application (sub-)object of Egw-object used to load $GLOBALS['egw_info'](['user'])['apps']
*/
-class applications
+class Applications
{
var $account_id;
var $data = Array();
@@ -50,14 +51,10 @@
$this->account_id = get_account_id($account_id);
}
- /**************************************************************************\
- * These are the standard $this->account_id specific functions *
- \**************************************************************************/
-
/**
- * read from repository
+ * Get applications of user
*
- * private should only be called from withing this class
+ * Used to populate $GLOBALS['egw_info']['user']['apps'] in Api\Session
*/
function read_repository()
{
@@ -71,7 +68,7 @@
return False;
}
$apps = $GLOBALS['egw']->acl->get_user_applications($this->account_id);
- foreach($GLOBALS['egw_info']['apps'] as $app => $data)
+ foreach(array_keys($GLOBALS['egw_info']['apps']) as $app)
{
if (isset($apps[$app]) && $apps[$app])
{
@@ -80,124 +77,6 @@
}
return $this->data;
}
-
- /**
- * read from the repository
- *
- * pubic function that is used to determine what apps a user has rights to
- */
- function read()
- {
- if (!count($this->data))
- {
- $this->read_repository();
- }
- return $this->data;
- }
- /**
- * add an app to a user profile
- *
- * @discussion
- * @param $apps array containing apps to add for a user
- */
- function add($apps)
- {
- if(is_array($apps))
- {
- foreach($apps as $app)
- {
- $this->data[$app] =& $GLOBALS['egw_info']['apps'][$app];
- }
- }
- elseif(gettype($apps))
- {
- $this->data[$apps] =& $GLOBALS['egw_info']['apps'][$apps];
- }
- return $this->data;
- }
- /**
- * delete an app from a user profile
- *
- * @discussion
- * @param $appname appname to remove
- */
- function delete($appname)
- {
- if($this->data[$appname])
- {
- unset($this->data[$appname]);
- }
- return $this->data;
- }
- /**
- * update the array(?)
- *
- * @discussion
- * @param $data update the repository array(?)
- */
- function update_data($data)
- {
- $this->data = $data;
- return $this->data;
- }
- /**
- * save the repository
- *
- * @discussion
- */
- function save_repository()
- {
- $GLOBALS['egw']->acl->delete_repository("%%", 'run', $this->account_id);
- foreach($this->data as $app => $data)
- {
- if(!$this->is_system_enabled($app))
- {
- continue;
- }
- $GLOBALS['egw']->acl->add_repository($app,'run',$this->account_id,1);
- }
- return $this->data;
- }
-
- /**************************************************************************\
- * These are the non-standard $this->account_id specific functions *
- \**************************************************************************/
-
- function app_perms()
- {
- if (!count($this->data))
- {
- $this->read_repository();
- }
- foreach ($this->data as $app => $data)
- {
- $apps[] = $this->data[$app]['name'];
- }
- return $apps;
- }
-
- function read_account_specific()
- {
- if (!is_array($GLOBALS['egw_info']['apps']))
- {
- $this->read_installed_apps();
- }
- if (($app_list = $GLOBALS['egw']->acl->get_app_list_for_id('run',1,$this->account_id)))
- {
- foreach($app_list as $app)
- {
- if ($this->is_system_enabled($app))
- {
- $this->data[$app] =& $GLOBALS['egw_info']['apps'][$app];
- }
- }
- }
- return $this->data;
- }
-
- /**************************************************************************\
- * These are the generic functions. Not specific to $this->account_id *
- \**************************************************************************/
/**
* populate array with a list of installed apps
@@ -227,46 +106,4 @@
);
}
}
-
- /**
- * check if an app is enabled
- *
- * @param $appname name of the app to check for
- */
- function is_system_enabled($appname)
- {
- if(!is_array($GLOBALS['egw_info']['apps']))
- {
- $this->read_installed_apps();
- }
- if ($GLOBALS['egw_info']['apps'][$appname]['enabled'])
- {
- return True;
- }
- else
- {
- return False;
- }
- }
-
- function id2name($id)
- {
- foreach($GLOBALS['egw_info']['apps'] as $appname => $app)
- {
- if((int)$app['id'] == (int)$id)
- {
- return $appname;
- }
- }
- return '';
- }
-
- function name2id($appname)
- {
- if(is_array($GLOBALS['egw_info']['apps'][$appname]))
- {
- return $GLOBALS['egw_info']['apps'][$appname]['id'];
- }
- return 0;
- }
}
Copied: trunk/egroupware/api/src/Egw/Base.php (from r55817, trunk/phpgwapi/inc/class.egw.inc.php)
URL: http://svn.stylite.de/viewvc/egroupware/trunk/egroupware/api/src/Egw/Base.php?p2=trunk/egroupware/api/src/Egw/Base.php&p1=trunk/phpgwapi/inc/class.egw.inc.php&r1=55817&r2=55853&rev=55853&view=diff
==============================================================================
--- trunk/phpgwapi/inc/class.egw.inc.php (original)
+++ trunk/egroupware/api/src/Egw/Base.php Tue Apr 26 16:38:08 2016
@@ -1,6 +1,6 @@
<?php
/**
- * eGroupWare API - Applications
+ * EGroupware API - Applications
*
* @link http://www.egroupware.org
* This file was originaly written by Dan Kuykendall and Joseph Engo
@@ -9,600 +9,35 @@
* @author [email protected]
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
+ * @subpackage egw
* @version $Id$
*/
+namespace EGroupware\Api\Egw;
+
use EGroupware\Api;
-/**
- * New written class to create the eGW enviroment AND restore it from a php-session
- *
- * Rewritten by [email protected] to store the eGW enviroment
- * (egw-object and egw_info-array) in a php-session and restore it from
- * there instead of creating it completly new on each page-request.
- * The enviroment gets now created by the egw-class
- *
- * Use now a php5 getter method to create the usuall subobject on demand, to allow a quicker
- * header include on sites not useing php4-restore.
- * This also makes a lot of application code, like the following, unnecessary:
- * if (!is_object($GLOBALS['egw']->datetime)
- * {
- * $GLOBALS['egw']->datetime = CreateObject('phpgwapi.datetime');
- * }
- * You can now simply use $GLOBALS['egw']->datetime, and the egw class instanciates it for you on demand.
- */
-class egw extends egw_minimal
-{
- /**
- * Turn on debug mode. Will output additional data for debugging purposes.
- * @var string
- * @access public
- */
- var $debug = 0; // This will turn on debugging information.
- /**
- * Instance of the account object
- *
- * @var accounts
- */
- var $accounts;
- /**
- * Instace of the common object
- *
- * @var common
- */
- var $common;
- /**
- * Instace of the hooks object
- *
- * @var hooks
- */
- var $hooks;
-
- /**
- * Constructor: Instantiates the sub-classes
- *
- * @author [email protected]
- * @param array $domain_names array with valid egw-domain names
- */
- function __construct($domain_names=null)
- {
- $GLOBALS['egw'] =& $this; // we need to be immediately available there for the other classes we instantiate
- // for the migration: reference us to the old phpgw object
- $GLOBALS['phpgw'] =& $this;
- $this->setup($domain_names,True);
- }
-
- /**
- * Called every time the constructor is called. Also called by sessions to ensure the correct db,
- * in which case we do not recreate the session object.
- * @author [email protected] (moved to setup() by [email protected]
- * @param array $domain_names array with valid egw-domain names
- * @param boolean $createsessionobject True to create the session object (default=True)
- */
- function setup($domain_names,$createsessionobject=True)
- {
- // create the DB-object
- // as SiteMgr, Wiki, KnowledgeBase and probably more still use eg next_record(), we stick with Db\Deprecated for now
- $this->db = new Api\Db\Deprecated($GLOBALS['egw_info']['server']);
- if ($this->debug)
- {
- $this->db->Debug = 1;
- }
- $this->db->set_app(Api\Db::API_APPNAME);
-
- // check if eGW is already setup, if not redirect to setup/
- try {
- $this->db->connect();
- $num_config = $this->db->select(config::TABLE,'COUNT(config_name)',false,__LINE__,__FILE__)->fetchColumn();
- }
- catch(Api\Db\Exception\Connection $e) {
- // ignore exception, get handled below
- }
- catch(Api\Db\Exception\InvalidSql $e1) {
- unset($e1); // not used
- try {
- $phpgw_config = $this->db->select('phpgw_config','COUNT(config_name)',false,__LINE__,__FILE__)->fetchColumn();
- }
- catch (Api\Db\Exception\InvalidSql $e2) {
- unset($e2); // not used
- // ignor error, get handled below
- }
- }
- if (!$num_config)
- {
- // we check for the old table too, to not scare updating users ;-)
- if ($phpgw_config)
- {
- throw new Exception('You need to update EGroupware before you can continue using it.',999);
- }
- if ($e)
- {
- throw new Api\Db\Exception\Setup('Connection with '.$e->getMessage()."\n\n".
- 'Maybe you not created a database for EGroupware yet.',999);
- }
- throw new Api\Db\Exception\Setup('It appears that you have not created the database tables for EGroupware.',999);
- }
- // Set the DB's client charset if a system-charset is set and some other values needed by egw_cache (used in config::read)
- foreach($this->db->select(config::TABLE,'config_name,config_value',array(
- 'config_app' => 'phpgwapi',
- 'config_name' => array('system_charset','install_id','temp_dir'),
- ),__LINE__,__FILE__) as $row)
- {
- $GLOBALS['egw_info']['server'][$row['config_name']] = $row['config_value'];
- }
- if ($GLOBALS['egw_info']['server']['system_charset'] && $GLOBALS['egw_info']['server']['system_charset'] != 'utf-8')
- {
- $this->db->Link_ID->SetCharSet($GLOBALS['egw_info']['server']['system_charset']);
- }
- // load up the $GLOBALS['egw_info']['server'] array
- $GLOBALS['egw_info']['server'] += config::read('phpgwapi');
-
- // if no server timezone set, use date_default_timezone_get() to determine it once
- // it fills to log with deprecated warnings under 5.3 otherwise
- if (empty($GLOBALS['egw_info']['server']['server_timezone']) ||
- $GLOBALS['egw_info']['server']['server_timezone'] == 'System/Localtime') // treat invalid tz like empty!
- {
- try
- {
- $tz = new DateTimeZone(date_default_timezone_get());
- config::save_value('server_timezone',$GLOBALS['egw_info']['server']['server_timezone'] = $tz->getName(),'phpgwapi');
- error_log(__METHOD__."() stored server_timezone=".$GLOBALS['egw_info']['server']['server_timezone']);
- }
- catch(Exception $e)
- {
- // do nothing if new DateTimeZone fails (eg. 'System/Localtime' returned), specially do NOT store it!
- error_log(__METHOD__."() NO valid 'date.timezone' set in your php.ini!");
- }
- }
- date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
-
- // setup the other subclasses
- // translation class is here only for backward compatibility, as all it's methods can be called static now
- $this->translation = new translation();
- $this->common = new common();
- $this->accounts = new accounts();
- $this->acl = new acl();
- // we instanciate the hooks object here manually, to cache it's hooks in the session
- $this->hooks = new hooks();
- /* Do not create the session object if called by the sessions class. This way
- * we ensure the correct db based on the user domain.
- */
- if($createsessionobject)
- {
- $this->session = new egw_session($domain_names);
- }
- $this->preferences = new preferences();
- $this->applications = new applications();
-
- if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login' && $GLOBALS['egw_info']['flags']['currentapp'] != 'logout')
- {
- $this->verify_session();
- $this->applications->read_installed_apps(); // to get translated app-titles, has to be after verify_session
-
- $this->define_egw_constants();
-
- $this->check_app_rights();
-
- $this->load_optional_classes();
- }
- else // set the defines for login, in case it's more then just login
- {
- $this->define_egw_constants();
- }
- }
-
- /**
- * __wakeup function gets called by php while unserializing the egw-object, eg. reconnects to the DB
- *
- * @author [email protected]
- */
- function __wakeup()
- {
- $GLOBALS['egw'] =& $this; // we need to be immediately available there for the other classes we instantiate
- // for the migration: reference us to the old phpgw object
- $GLOBALS['phpgw'] =& $this;
-
- if ($GLOBALS['egw_info']['server']['system_charset'])
- {
- $this->db->Link_ID->SetCharSet($GLOBALS['egw_info']['server']['system_charset']);
- }
- // restoring server timezone, to avoid warnings under php5.3
- if (!empty($GLOBALS['egw_info']['server']['server_timezone']))
- {
- date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
- }
-
- $this->define_egw_constants();
- }
-
- /**
- * wakeup2 function needs to be called after unserializing the egw-object
- *
- * It adapts the restored object/enviroment to the changed (current) application / page-request
- *
- * @author [email protected]
- */
- function wakeup2()
- {
- // do some application specific stuff, need to be done as we are different (current) app now
- if (isset($this->template))
- {
- $this->template->set_root(EGW_APP_TPL);
- }
- // init the translation class, necessary as own wakeup would run before our's
- translation::init(isset($GLOBALS['egw_info']['flags']['load_translations']) ? $GLOBALS['egw_info']['flags']['load_translations'] : true);
-
- $this->unset_datetime();
-
- // verify the session
- $GLOBALS['egw']->verify_session();
- $GLOBALS['egw']->check_app_rights();
-
- $this->load_optional_classes();
- }
-
- /**
- * Unsetting datetime object, so time gets updated
- */
- function unset_datetime()
- {
- unset($this->datetime);
- }
-
- /**
- * load optional classes by mentioning them in egw_info[flags][enable_CLASS_class] => true
- *
- * Also loads the template-class if not egw_info[flags][disable_Template_class] is set
- *
- * Maybe the whole thing should be depricated ;-)
- */
- function load_optional_classes()
- {
- // output the header unless the developer turned it off
- if (!@$GLOBALS['egw_info']['flags']['noheader'])
- {
- common::egw_header();
- }
-
- // Load the (depricated) app include files if they exists
- if (EGW_APP_INC != "" && ! preg_match ('/phpgwapi/i', EGW_APP_INC) &&
- file_exists(EGW_APP_INC . '/functions.inc.php') && !isset($_GET['menuaction']))
- {
- include(EGW_APP_INC . '/functions.inc.php');
- }
- if (!@$GLOBALS['egw_info']['flags']['noheader'] && !@$GLOBALS['egw_info']['flags']['noappheader'] &&
- file_exists(EGW_APP_INC . '/header.inc.php') && !isset($_GET['menuaction']))
- {
- include(EGW_APP_INC . '/header.inc.php');
- }
- }
-
- /**
- * Verfiy there is a valid session
- *
- * One can specify a callback, which gets called if there's no valid session. If the callback returns true, the parameter
- * containst account-details (in keys login, passwd and passwd_type) to automatic create an (anonymous session)
- *
- * It also checks if enforce_ssl is set in the DB and redirects to the https:// version of the site.
- *
- * If there is no valid session and none could be automatic created, the function will redirect to login and NOT return
- */
- function verify_session()
- {
- if($GLOBALS['egw_info']['server']['enforce_ssl'] === 'redirect' && !$_SERVER['HTTPS'])
- {
- Header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
- exit;
- }
- // check if we have a session, if not try to automatic create one
- if ($this->session->verify()) return true;
-
- $account = null;
- if (($account_callback = $GLOBALS['egw_info']['flags']['autocreate_session_callback']) && is_callable($account_callback) &&
- ($sessionid = call_user_func_array($account_callback,array(&$account))) === true) // $account_call_back returns true, false or a session-id
- {
- $sessionid = $this->session->create($account);
- }
- if (!$sessionid)
- {
- //echo "<p>account_callback='$account_callback', account=".print_r($account,true).", sessionid=$sessionid</p>\n"; exit;
- // we forward to the same place after the re-login
- if ($GLOBALS['egw_info']['server']['webserver_url'] && $GLOBALS['egw_info']['server']['webserver_url'] != '/' &&
- ($webserver_path = parse_url($GLOBALS['egw_info']['server']['webserver_url'],PHP_URL_PATH)) && $webserver_path != '/')
- {
- // we have to use only path component, to cope with domains like http://egroupware.domain.com and /egroupware
- list(,$relpath) = explode($webserver_path,parse_url($_SERVER['PHP_SELF'],PHP_URL_PATH),2);
- }
- else // the webserver-url is empty or just a slash '/' (eGW is installed in the docroot and no domain given)
- {
- $matches = null;
- if (preg_match('/^https?:\/\/[^\/]*\/(.*)$/',$relpath=$_SERVER['PHP_SELF'],$matches))
- {
- $relpath = $matches[1];
- }
- }
- // this removes the sessiondata if its saved in the URL
- $query = preg_replace('/[&]?sessionid(=|%3D)[^&]+&kp3(=|%3D)[^&]+&domain=.*$/','',$_SERVER['QUERY_STRING']);
- if ($GLOBALS['egw_info']['server']['http_auth_types'])
- {
- $redirect = '/phpgwapi/ntlm/index.php?';
- }
- else
- {
- $redirect = '/login.php?';
- // only add "your session could not be verified", if a sessionid is given (cookie or on url)
- if (egw_session::get_sessionid()) $redirect .= 'cd=10&';
- }
- if ($relpath) $redirect .= 'phpgw_forward='.urlencode($relpath.(!empty($query) ? '?'.$query : ''));
- self::redirect_link($redirect);
- }
- }
-
- /**
- * Verify the user has rights for the requested app
- *
- * If the user has no rights for the app (eg. called via URL) he get a permission denied page (this function does NOT return)
- *
- * @throws Api\Exception\Redirect for anonymous user accessing something he has no rights to
- * @throws Api\Exception\NoPermission\Admin
- * @throws Api\Exception\NoPermission\App
- */
- function check_app_rights()
- {
- $this->currentapp = $GLOBALS['egw_info']['flags']['currentapp']; // some apps change it later
-
- if (!in_array($GLOBALS['egw_info']['flags']['currentapp'], array('api', 'home'))) // give everyone implicit home rights
- {
- // This will need to use ACL in the future
- if (!$GLOBALS['egw_info']['user']['apps'][$currentapp = $GLOBALS['egw_info']['flags']['currentapp']] ||
- ($GLOBALS['egw_info']['flags']['admin_only'] && !$GLOBALS['egw_info']['user']['apps']['admin']))
- {
- // present a login page, if anon user has no right for an application
- if ($this->session->session_flags == 'A')
- {
- // need to destroy a basic auth session here, because it will only be available on current url
- if (($sessionid = egw_session::get_sessionid(true)))
- {
- $GLOBALS['egw']->session->destroy($sessionid);
- }
- throw new Api\Exception\Redirect(egw::link('/logout.php'));
- }
- if ($currentapp == 'admin' || $GLOBALS['egw_info']['flags']['admin_only'])
- {
- throw new Api\Exception\NoPermission\Admin();
- }
- throw new Api\Exception\NoPermission\App($currentapp);
- }
- }
- }
-
- /**
- * create all the defines / constants of the eGW-environment (plus the deprecated phpgw ones)
- */
- function define_egw_constants()
- {
- define('EGW_ACL_READ',1);
- define('EGW_ACL_ADD',2);
- define('EGW_ACL_EDIT',4);
- define('EGW_ACL_DELETE',8);
- define('EGW_ACL_PRIVATE',16);
- define('EGW_ACL_GROUP_MANAGERS',32);
- define('EGW_ACL_CUSTOM_1',64);
- define('EGW_ACL_CUSTOM_2',128);
- define('EGW_ACL_CUSTOM_3',256);
- // and the old ones
- define('PHPGW_ACL_READ',1);
- define('PHPGW_ACL_ADD',2);
- define('PHPGW_ACL_EDIT',4);
- define('PHPGW_ACL_DELETE',8);
- define('PHPGW_ACL_PRIVATE',16);
- define('PHPGW_ACL_GROUP_MANAGERS',32);
- define('PHPGW_ACL_CUSTOM_1',64);
- define('PHPGW_ACL_CUSTOM_2',128);
- define('PHPGW_ACL_CUSTOM_3',256);
- // A few hacker resistant constants that will be used throught the program
- define('EGW_TEMPLATE_DIR', $this->common->get_tpl_dir('phpgwapi'));
- define('EGW_IMAGES_DIR', $this->common->get_image_path('phpgwapi'));
- define('EGW_IMAGES_FILEDIR', $this->common->get_image_dir('phpgwapi'));
- define('EGW_APP_ROOT', $this->common->get_app_dir());
- define('EGW_APP_INC', $this->common->get_inc_dir());
- define('EGW_APP_TPL', $this->common->get_tpl_dir());
- define('EGW_IMAGES', $this->common->get_image_path());
- define('EGW_APP_IMAGES_DIR', $this->common->get_image_dir());
- // and the old ones
- define('PHPGW_TEMPLATE_DIR',EGW_TEMPLATE_DIR);
- define('PHPGW_IMAGES_DIR',EGW_IMAGES_DIR);
- define('PHPGW_IMAGES_FILEDIR',EGW_IMAGES_FILEDIR);
- define('PHPGW_APP_ROOT',EGW_APP_ROOT);
- define('PHPGW_APP_INC',EGW_APP_INC);
- define('PHPGW_APP_TPL',EGW_APP_TPL);
- define('PHPGW_IMAGES',EGW_IMAGES);
- define('PHPGW_APP_IMAGES_DIR',EGW_APP_IMAGES_DIR);
- }
-
- /**
- * force the session cache to be re-created, because some of it's data changed
- *
- * Needs to be called if user-preferences, system-config or enabled apps of the current user have been changed and
- * the change should have immediate effect
- */
- static function invalidate_session_cache()
- {
- unset($_SESSION['egw_info_cache']);
- unset($_SESSION['egw_object_cache']);
- }
-
- /**
- * run string through htmlspecialchars and stripslashes
- *
- * @param string $s
- * @return string The string with html special characters replaced with entities
- */
- static function strip_html($s)
- {
- return htmlspecialchars(stripslashes($s));
- }
-
- /**
- * Link url generator
- *
- * @param string $url url link is for
- * @param string|array $extravars ='' extra params to be added to url
- * @param string $link_app =null if appname or true, some templates generate a special link-handler url
- * @return string The full url after processing
- */
- static function link($url, $extravars = '', $link_app=null)
- {
- return $GLOBALS['egw']->framework->link($url, $extravars, $link_app);
- }
-
- /**
- * Redirects direct to a generated link
- *
- * @param string $url url link is for
- * @param string|array $extravars ='' extra params to be added to url
- * @param string $link_app =null if appname or true, some templates generate a special link-handler url
- * @return string The full url after processing
- */
- static function redirect_link($url, $extravars='', $link_app=null)
- {
- return $GLOBALS['egw']->framework->redirect_link($url, $extravars, $link_app);
- }
-
- /**
- * Handles redirects under iis and apache, it does NOT return (calls exit)
- *
- * This function handles redirects under iis and apache it assumes that $phpgw->link() has already been called
- *
- * @param string $url url to redirect to
- * @param string $link_app =null appname to redirect for, default currentapp
- */
- static function redirect($url, $link_app=null)
- {
- Api\Framework::redirect($url, $link_app);
- }
-
- /**
- * Shortcut to translation class
- *
- * This function is a basic wrapper to translation::translate()
- *
- * @deprecated only used in the old timetracker
- * @param string The key for the phrase
- * @see translation::translate()
- */
- static function lang($key,$args=null)
- {
- if (!is_array($args))
- {
- $args = func_get_args();
- array_shift($args);
- }
- return translation::translate($key,$args);
- }
-
- /**
- * registered shutdown callbacks and optional arguments
- *
- * @var array
- */
- private static $shutdown_callbacks = array();
-
- /**
- * Register a callback to run on shutdown AFTER output send to user
- *
- * Allows eg. static classes (no destructor) to run on shutdown AND
- * garanties to run AFTER output send to user.
- *
- * @param callable $callback use array($classname, $method) for static methods
- * @param array $args =array()
- */
- public static function on_shutdown($callback, array $args=array())
- {
- array_unshift($args, $callback);
-
- // prepend new callback, to run them in oposite order they are registered
- array_unshift(self::$shutdown_callbacks, $args);
- }
-
- /**
- * Shutdown handler running all registered on_shutdown callbacks and then disconnecting from db
- */
- function __destruct()
- {
- if (!defined('EGW_SHUTDOWN'))
- {
- define('EGW_SHUTDOWN',True);
-
- // send json response BEFORE flushing output
- if (egw_json_request::isJSONRequest())
- {
- egw_json_response::sendResult();
- }
-
- // run all on_shutdown callbacks with session in their name (eg. egw_link::save_session_cache), do NOT stop on exceptions
- foreach(self::$shutdown_callbacks as $n => $data)
- {
- try {
- //error_log(__METHOD__."() running ".array2string($data));
- $callback = array_shift($data);
- if (!is_array($callback) || strpos($callback[1], 'session') === false) continue;
- call_user_func_array($callback, $data);
- }
- catch (Exception $ex) {
- _egw_log_exception($ex);
- }
- unset(self::$shutdown_callbacks[$n]);
- }
- // now we can close the session
- // without closing the session fastcgi_finish_request() will NOT send output to user
- if (isset($GLOBALS['egw']->session) && is_object($GLOBALS['egw']->session)) $GLOBALS['egw']->session->commit_session();
-
- // flush all output to user
- /* does NOT work on Apache :-(
- for($i = 0; ob_get_level() && $i < 10; ++$i)
- {
- ob_end_flush();
- }
- flush();*/
- // working for fastCGI :-)
- if (function_exists('fastcgi_finish_request') && substr($_SERVER['PHP_SELF'], -32) != '/phpgwapi/cron/asyncservices.php')
- {
- fastcgi_finish_request();
- }
-
- // run all on_shutdown, do NOT stop on exceptions
- foreach(self::$shutdown_callbacks as $data)
- {
- try {
- //error_log(__METHOD__."() running ".array2string($data));
- $callback = array_shift($data);
- call_user_func_array($callback, $data);
- }
- catch (Exception $ex) {
- _egw_log_exception($ex);
- }
- }
- // call the asyncservice check_run function if it is not explicitly set to cron-only
- if (!$GLOBALS['egw_info']['server']['asyncservice']) // is default
- {
- ExecMethod('phpgwapi.asyncservice.check_run','fallback');
- }
- $this->db->disconnect();
- }
- }
-}
+// explicitly list old, non-namespaced classes
+use common; // get_tpl_dir
/**
- * Minimal eGW object used in setup, does not instanciate anything by default
+ * Egw\Base object used in setup, does not instanciate anything by default
*
+ * Extending Egw\Base which uses now a getter method to create the usual subobject on demand,
+ * to allow a quicker header include on sites not using php4-restore.
+ * This also makes a lot of application code, like the following, unnecessary:
+ * if (!is_object($GLOBALS['egw']->ldap)
+ * {
+ * $GLOBALS['egw']->ldap = Api\Ldap::factory();
+ * }
+ * You can now simply use $GLOBALS['egw']->ldap, and the egw class instanciates it for you on demand.
*/
-class egw_minimal
+class Base
{
/**
* Instance of the db-object
*
- * @var egw_db
+ * @var Api\Db
*/
var $db;
/**
@@ -625,13 +60,12 @@
*/
static $sub_objects = array(
'log' => 'errorlog',
-// 'js' => 'javascript',
'link' => 'bolink', // depricated use static egw_link methods
'datetime' => 'egw_datetime',
- 'framework' => true, // special handling in __get()
'template' => 'Template',
'session' => 'egw_session', // otherwise $GLOBALS['egw']->session->appsession() fails
// classes moved to new api dir
+ 'framework' => true, // special handling in __get()
'ldap' => true,
'auth' => 'EGroupware\\Api\\Auth',
);
@@ -673,13 +107,13 @@
switch($name)
{
case 'framework':
- return $this->framework = egw_framework::factory();
+ return $this->framework = Api\Framework::factory();
case 'template': // need to be instancated for the current app
if (!($tpl_dir = common::get_tpl_dir($this->currentapp)))
{
return null;
}
- return $this->template = new Template($tpl_dir);
+ return $this->template = new Api\Framework\Template($tpl_dir);
case 'ldap':
return $this->ldap = Api\Ldap::factory(false);
default:
Copied: trunk/egroupware/api/src/autoload.php (from r55840, trunk/phpgwapi/inc/common_functions.inc.php)
URL: http://svn.stylite.de/viewvc/egroupware/trunk/egroupware/api/src/autoload.php?p2=trunk/egroupware/api/src/autoload.php&p1=trunk/phpgwapi/inc/common_functions.inc.php&r1=55840&r2=55853&rev=55853&view=diff
==============================================================================
--- trunk/phpgwapi/inc/common_functions.inc.php (original)
+++ trunk/egroupware/api/src/autoload.php Tue Apr 26 16:38:08 2016
@@ -1,11 +1,11 @@
<?php
/**
- * EGroupware commonly used functions
+ * EGroupware autloader
*
- * This file was originaly written by Dan Kuykendall and Joseph Engo
- * Copyright (C) 2000, 2001 Dan Kuykendall
- *
- * All newer parts (XSS checks, autoloading, exception handler, ...) are written by Ralf Becker.
+ * Normally included by either:
+ * - header.inc.php
+ * - api/src/loader.php
+ * - api/src/loader/common.php
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
@@ -14,9 +14,7 @@
* @version $Id$
*/
-use EGroupware\Api;
-
-// this is only neccessary, if header.inc.php is not included, but common_functions.inc.php directly
+// this is only neccessary, if header.inc.php is not included, but api/src/autoload.php directly
if (!defined('EGW_SERVER_ROOT'))
{
define('EGW_SERVER_ROOT', dirname(dirname(__DIR__)));
@@ -104,1890 +102,3 @@
{
require_once EGW_SERVER_ROOT.'/vendor/autoload.php';
}
-
-/**
-* applies stripslashes recursivly on each element of an array
-*
-* @param array &$var
-* @return array
-*/
-function array_stripslashes($var)
-{
- if (!is_array($var))
- {
- return stripslashes($var);
- }
- foreach($var as $key => $val)
- {
- $var[$key] = is_array($val) ? array_stripslashes($val) : stripslashes($val);
- }
- return $var;
-}
-
-/**
- * Return the number of bytes of a string, independent of mbstring.func_overload
- * AND the availability of mbstring
- *
- * @param string $str
- * @return int
- */
-function bytes($str)
-{
- static $func_overload = null;
-
- if (is_null($func_overload)) $func_overload = extension_loaded('mbstring') ? ini_get('mbstring.func_overload') : 0;
-
- return $func_overload & 2 ? mb_strlen($str,'ascii') : strlen($str);
-}
-
-/**
- * mbstring.func_overload safe substr
- *
- * @param string $data
- * @param int $offset
- * @param int $len
- * @return string
- */
-function cut_bytes(&$data,$offset,$len=null)
-{
- static $func_overload = null;
-
- if (is_null($func_overload)) $func_overload = extension_loaded('mbstring') ? ini_get('mbstring.func_overload') : 0;
-
- if (is_null($len))
- {
- return $func_overload & 2 ? mb_substr($data,$offset,bytes($data),'ascii') : substr($data,$offset);
- }
- return $func_overload & 2 ? mb_substr($data,$offset,$len,'ascii') : substr($data,$offset,$len);
-}
-
-if (!function_exists('imap_rfc822_parse_adrlist'))
-{
- /**
- * parses a (comma-separated) address string
- *
- * Examples:
- * - Joe Doe <[email protected]>
- * - "Doe, Joe" <[email protected]>
- * - "\'Joe Doe\'" <[email protected]> // actually not necessary to quote
- * - [email protected]
- * - root
- * - "Joe on its way Down Under :-\)" <[email protected]>
- * - "Giant; \"Big\" Box" <[email protected]>
- * - [email protected] <[email protected]> // this is wrong, because @ need to be quoted
- *
- * Invalid addresses, if detected, set host to '.SYNTAX-ERROR.'
- *
- * @param string $address - A string containing addresses
- * @param string $default_host - The default host name
- * @return array of objects. The objects properties are:
- * mailbox - the mailbox name (username)
- * host - the host name
- * personal - the personal name
- * adl - at domain source route
- */
- function imap_rfc822_parse_adrlist($address, $default_host)
- {
- $addresses = array();
- $pending = '';
- foreach(explode(',', $address) as $part)
- {
- $trimmed = trim(($pending ? $pending.',' : '').$part);
- if (($trimmed[0] == '"' && substr($trimmed, -1) != '>')||strpos($part, '@')===false)
- {
- $pending .= ($pending ? $pending.',' : '').$part;
- continue;
- }
- $pending = '';
- $matches = $personal = $mailbox = $host = null;
- if (preg_match('/^(.*)<([^>@]+)(@([^>]+))?>$/', $trimmed, $matches))
- {
- $personal = trim($matches[1]);
- $mailbox = $matches[2];
- $host = $matches[4];
- }
- elseif (strpos($trimmed, '@') !== false)
- {
- list($mailbox, $host) = explode('@', $trimmed);
- }
- else
- {
- $mailbox = $trimmed;
- }
- if ($personal[0] == '"' && substr($personal, -1) == '"')
- {
- $personal = str_replace('\\', '', substr($personal, 1, -1));
- }
- if (empty($host)) $host = $default_host;
-
- $addresses[] = (object)array_diff(array(
- 'mailbox' => $mailbox,
- 'host' => $host,
- 'personal' => $personal,
- ), array(null, ''));
- }
- return $addresses;
- }
-}
-
-if (!function_exists('imap_rfc822_write_address'))
-{
- /**
- * Returns a properly formatted email address given the mailbox, host, and personal info
- * @param string $mailbox - The mailbox name, see imap_open() for more information
- * @param string $host - The email host part
- * @param string $personal - The name of the account owner
- * @return string properly formatted email address as defined in » RFC2822.
- */
- function imap_rfc822_write_address($mailbox, $host, $personal)
- {
- if (is_array($personal)) $personal = implode(' ', $personal);
-
- //if (!preg_match('/^[!#$%&\'*+/0-9=?A-Z^_`a-z{|}~-]+$/u', $personal)) // that's how I read the rfc(2)822
- if ($personal && !preg_match('/^[0-9A-Z -]*$/iu', $personal)) // but quoting is never wrong, so quote more then necessary
- {
- $personal = '"'.str_replace(array('\\', '"'),array('\\\\', '\\"'), $personal).'"';
- }
- return ($personal ? $personal.' <' : '').$mailbox.($host ? '@'.$host : '').($personal ? '>' : '');
- }
-}
-
-if (!function_exists('imap_mime_header_decode'))
-{
- /**
- * Decodes MIME message header extensions that are non ASCII text (RFC2047)
- *
- * Uses Horde_Mime::decode() and therefore always returns only a single array element!
- *
- * @param string $text
- * @return array with single object with attribute text already in our internal encoding and charset
- * @deprecated use Horde_Mime::decode()
- */
- function imap_mime_header_decode($text)
- {
- return array((object)array(
- 'text' => Horde_Mime::decode($text),
- 'charset' => translation::charset(), // is already in our internal encoding!
- ));
- }
-}
-
-if (!function_exists('mb_strlen'))
-{
- /**
- * Number of characters in a string
- *
- * @param string $str
- * @return int
- */
- function mb_strlen($str)
- {
- return strlen($str);
- }
-}
-
-if (!function_exists('mb_substr'))
-{
- /**
- * Return part of a string
- *
- * @param string $data
- * @param int $offset
- * @param int $len
- * @return string
- */
- function mb_substr(&$data, $offset, $len=null)
- {
- return is_null($len) ? substr($data, $offset) : substr($data, $offset, $len);
- }
-}
-
-/**
- * Format array or other types as (one-line) string, eg. for error_log statements
- *
- * @param mixed $var variable to dump
- * @return string
- */
-function array2string($var)
-{
- switch (($type = gettype($var)))
- {
- case 'boolean':
- return $var ? 'TRUE' : 'FALSE';
- case 'string':
- return "'$var'";
- case 'integer':
- case 'double':
- case 'resource':
- return $var;
- case 'NULL':
- return 'NULL';
- case 'object':
- case 'array':
- return str_replace(array("\n",' '/*,'Array'*/),'',print_r($var,true));
- }
- return 'UNKNOWN TYPE!';
-}
-
-/**
- * Check if a given extension is loaded or load it if possible (requires sometimes disabled or unavailable dl function)
- *
- * @param string $extension
- * @param boolean $throw =false should we throw an exception, if $extension could not be loaded, default false = no
- * @return boolean true if loaded now, false otherwise
- */
-function check_load_extension($extension,$throw=false)
-{
- if (!defined('PHP_SHLIB_PREFIX'))
- {
- define('PHP_SHLIB_PREFIX',PHP_SHLIB_SUFFIX == 'dll' ? 'php_' : '');
- }
- // we check for the existens of 'dl', as multithreaded webservers dont have it and some hosters disable it !!!
- $loaded = extension_loaded($extension) || function_exists('dl') && @dl($dl=PHP_SHLIB_PREFIX.$extension.'.'.PHP_SHLIB_SUFFIX);
-
- if (!$loaded && $throw)
- {
- throw new Exception ("PHP extension '$extension' not loaded AND can NOT be loaded via dl('$dl')!");
- }
- return $loaded;
-}
-
-/**
- * @internal Not to be used directly. Should only be used by print_debug()
- */
-function print_debug_subarray($array)
-{
- foreach($array as $key => $value)
- {
- if (is_array($value))
- {
- $vartypes[$key] = print_debug_subarray($value);
- }
- else
- {
- $vartypes[$key] = gettype($value);
- }
- }
- return $vartypes;
-}
-
-/**
- * print debug data only when debugging mode is turned on.
- *
- * @author seek3r
- * This function is used to debugging data.
- * print_debug('this is some debugging data',$somevar);
- */
-function print_debug($message,$var = 'messageonly',$part = 'app', $level = 3)
-{
- if (($part == 'app' && DEBUG_APP == True) || ($part == 'api' && DEBUG_API == True))
- {
- if (!defined('DEBUG_OUTPUT'))
- {
- define('DEBUG_OUTPUT', 1);
- }
- if ($level >= DEBUG_LEVEL)
- {
- if (!is_array($var))
- {
- if ($var != 'messageonly')
- {
- if (!DEBUG_DATATYPES)
- {
- $output = "$message\n$var";
- }
- else
- {
- $output = "$message\n$var is a ".gettype($var);
- }
- }
- else
- {
- $output = $message;
- }
-
- /* Bit 1 means to output to screen */
- if (!!(DEBUG_OUTPUT & 1))
- {
- echo "$output<br>\n";
- }
- /* Bit 2 means to output to sql */
- if (!!(DEBUG_OUTPUT & 2))
- {
- /* Need to flesh this out still. I dont have a table to dump this in yet.*/
- /* So the SQL statement will go here*/
- }
-
- /* Example of how this can be extended to output to other locations as well. This example uses a COM object */
- /*
- if (!!(DEBUG_OUTPUT & 32))
- {
- $obj_debug = new COM('Some_COM_App.Class','localhost');
- if (is_object($obj_debug))
- {
- $DebugMessage_return = $obj_debug->DebugMessage($output);
- }
- }
- */
- }
- else
- {
- if (floor(phpversion()) > 3 && !!(DEBUG_OUTPUT & 2))
- {
- ob_start();
- }
- echo "<pre>\n$message\n";
- print_r($var);
- if (DEBUG_DATATYPES)
- {
- foreach($var as $key => $value)
- {
- if (is_array($value))
- {
- $vartypes[$key] = print_debug_subarray($value);
- }
- else
- {
- $vartypes[$key] = gettype($value);
- }
- }
- echo "Data Types:\n";
- print_r($vartypes);
- }
- echo "\n<pre>\n";
- if (floor(phpversion()) > 3 && !!(DEBUG_OUTPUT & 2))
- {
- $output .= ob_get_contents();
- ob_end_clean();
- /* Need to flesh this out still. I dont have a table to dump this in yet.*/
- /* So the SQL statement will go here*/
- if (!!(DEBUG_OUTPUT & 1))
- {
- echo "$output<br>\n";
- }
- }
- }
- }
- }
-}
-
-/**
- * Allows for array and direct function params as well as sanatization.
- *
- * @author seek3r
- * This function is used to validate param data as well as offer flexible function usage.
- *
- function somefunc()
- {
- $expected_args[0] = Array('name'=>'fname','default'=>'joe', 'type'=>'string');
- $expected_args[1] = Array('name'=>'mname','default'=>'hick', 'type'=>'string');
- $expected_args[2] = Array('name'=>'lname','default'=>'bob', 'type'=>'string');
- $recieved_args = func_get_args();
- $args = safe_args($expected_args, $recieved_args,__LINE__,__FILE__);
- echo 'Full name: '.$args['fname'].' '.$args['fname'].' '.$args['lname'].'<br>';
- //default result would be:
- // Full name: joe hick bob<br>
- }
-
- Using this it is possible to use the function in any of the following ways
- somefunc('jack','city','brown');
- or
- somefunc(array('fname'=>'jack','mname'=>'city','lname'=>'brown'));
- or
- somefunc(array('lname'=>'brown','fname'=>'jack','mname'=>'city'));
-
- For the last one, when using named params in an array you dont have to follow any order
- All three would result in - Full name: jack city brown<br>
-
- When you use this method of handling params you can secure your functions as well offer
- flexibility needed for both normal use and web services use.
- If you have params that are required just set the default as ##REQUIRED##
- Users of your functions can also use ##DEFAULT## to use your default value for a param
- when using the standard format like this:
- somefunc('jack','##DEFAULT##','brown');
- This would result in - Full name: jack hick brown<br>
- Its using the default value for the second param.
- Of course if you have the second param as a required field it will fail to work.
- */
-function safe_args($expected, $recieved, $line='??', $file='??')
-{
- /* This array will contain all the required fields */
- $required = Array();
-
- /* This array will contain all types for sanatization checking */
- /* only used when an array is passed as the first arg */
- $types = Array();
-
- /* start by looping thru the expected list and set params with */
- /* the default values */
- $num = count($expected);
- for ($i = 0; $i < $num; $i++)
- {
- $args[$expected[$i]['name']] = $expected[$i]['default'];
- if ($expected[$i]['default'] === '##REQUIRED##')
- {
- $required[$expected[$i]['name']] = True;
- }
- $types[$expected[$i]['name']] = $expected[$i]['type'];
- }
-
- /* Make sure they passed at least one param */
- if(count($recieved) != 0)
- {
- /* if used as standard function we loop thru and set by position */
- if(!is_array($recieved[0]))
- {
- for ($i = 0; $i < $num; $i++)
- {
- if(isset($recieved[$i]) && $recieved[$i] !== '##DEFAULT##')
- {
- if(sanitize($recieved[$i],$expected[$i]['type']))
- {
- $args[$expected[$i]['name']] = $recieved[$i];
- unset($required[$expected[$i]['name']]);
- }
- else
- {
- echo 'Fatal Error: Invalid paramater type for '.$expected[$i]['name'].' on line '.$line.' of '.$file.'<br>';
- exit;
- }
- }
- }
- }
- /* if used as standard function we loop thru and set by position */
- else
- {
- for ($i = 0; $i < $num; $i++)
- {
- $types[$expected[$i]['name']] = $expected[$i]['type'];
- }
- while(list($key,$val) = each($recieved[0]))
- {
- if($val !== '##DEFAULT##')
- {
- if(sanitize($val,$types[$key]) == True)
- {
- $args[$key] = $val;
- unset($required[$key]);
- }
- else
- {
- echo 'Fatal Error: Invalid paramater type for '.$key.' on line '.$line.' of '.$file.'<br>';
- exit;
- }
- }
- }
- }
- }
- if(count($required) != 0)
- {
- while (list($key) = each($required))
- {
- echo 'Fatal Error: Missing required paramater '.$key.' on line '.$line.' of '.$file.'<br>';
- }
- exit;
- }
- return $args;
-}
-
-/**
- * Validate data.
- *
- * @author seek3r
- * This function is used to validate input data.
- * sanitize('number',$somestring);
- */
-function sanitize($string,$type)
-{
- switch ($type)
- {
- case 'bool':
- if ($string == 1 || $string == 0)
- {
- return True;
- }
- break;
-
- case 'isprint':
- $length = strlen($string);
- $position = 0;
- while ($length > $position)
- {
- $char = substr($string, $position, 1);
- if ($char < ' ' || $char > '~')
- {
- return False;
- }
- $position = $position + 1;
- }
- return True;
-
- case 'alpha':
- if (preg_match("/^[a-z]+$/i", $string))
- {
- return True;
- }
- break;
-
- case 'number':
- if (preg_match("/^[0-9]+$/i", $string))
- {
- return True;
- }
- break;
-
- case 'alphanumeric':
- if (preg_match("/^[a-z0-9 -._]+$/i", $string))
- {
- return True;
- }
- break;
- case 'string':
- if (preg_match("/^[a-z]+$/i", $string))
- {
- return True;
- }
- break;
- case 'ip':
- if (preg_match('/'."^[0-9]{1,3}(\.[0-9]{1,3}){3}$".'/i',$string))
- {
- $octets = preg_split('/\./',$string);
- for ($i=0; $i != count($octets); $i++)
- {
- if ($octets[$i] < 0 || $octets[$i] > 255)
- {
- return False;
- }
- }
- return True;
- }
- return False;
-
- case 'file':
- if (preg_match("/^[a-z0-9_]+\.+[a-z]+$/i", $string))
- {
- return True;
- }
- break;
- case 'email':
- if (preg_match('/'."^([[:alnum:]_%+=.-]+)@([[:alnum:]_.-]+)\.([a-z]{2,3}|[0-9]{1,3})$".'/i',$string))
- {
- return True;
- }
- break;
- case 'password':
- $password_length = strlen($string);
- $password_numbers = Array('0','1','2','3','4','5','6','7','8','9');
- $password_special_chars = Array(' ','~','`','!','@','#','$','%','^','&','*','(',')','_','+','-','=','{','}','|','[',']',"\\",':','"',';',"'",'<','>','?',',','.','/');
-
- if(@isset($GLOBALS['egw_info']['server']['pass_min_length']) && is_int($GLOBALS['egw_info']['server']['pass_min_length']) && $GLOBALS['egw_info']['server']['pass_min_length'] > 1)
- {
- $min_length = $GLOBALS['egw_info']['server']['pass_min_length'];
- }
- else
- {
- $min_length = 1;
- }
-
- if(@isset($GLOBALS['egw_info']['server']['pass_require_non_alpha']) && $GLOBALS['egw_info']['server']['pass_require_non_alpha'] == True)
- {
- $pass_verify_non_alpha = False;
- }
- else
- {
- $pass_verify_non_alpha = True;
- }
-
- if(@isset($GLOBALS['egw_info']['server']['pass_require_numbers']) && $GLOBALS['egw_info']['server']['pass_require_numbers'] == True)
- {
- $pass_verify_num = False;
- }
- else
- {
- $pass_verify_num = True;
- }
-
- if(@isset($GLOBALS['egw_info']['server']['pass_require_special_char']) && $GLOBALS['egw_info']['server']['pass_require_special_char'] == True)
- {
- $pass_verify_special_char = False;
- }
- else
- {
- $pass_verify_special_char = True;
- }
-
- if ($password_length >= $min_length)
- {
- for ($i=0; $i != $password_length; $i++)
- {
- $cur_test_string = substr($string, $i, 1);
- if (in_array($cur_test_string, $password_numbers) || in_array($cur_test_string, $password_special_chars))
- {
- $pass_verify_non_alpha = True;
- if (in_array($cur_test_string, $password_numbers))
- {
- $pass_verify_num = True;
- }
- elseif (in_array($cur_test_string, $password_special_chars))
- {
- $pass_verify_special_char = True;
- }
- }
- }
-
- if ($pass_verify_num == False)
- {
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password requires at least one non-alpha character']=False;
- }
-
- if ($pass_verify_num == False)
- {
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password requires at least one numeric character']=False;
- }
-
- if ($pass_verify_special_char == False)
- {
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password requires at least one special character (non-letter and non-number)']=False;
- }
-
- if ($pass_verify_num == True && $pass_verify_special_char == True)
- {
- return True;
- }
- return False;
- }
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password must be at least '.$min_length.' characters']=False;
- return False;
-
- case 'any':
- return True;
-
- default :
- if (isset($GLOBALS['egw_info']['server']['sanitize_types'][$type]['type']))
- {
- if ($GLOBALS['egw_info']['server']['sanitize_types'][$type]['type']($GLOBALS['egw_info']['server']['sanitize_types'][$type]['string'], $string))
- {
- return True;
- }
- }
- return False;
- }
-}
-
-function reg_var($varname, $method='any', $valuetype='alphanumeric',$default_value='',$register=True)
-{
- if($method == 'any' || $method == array('any'))
- {
- $method = Array('POST','GET','COOKIE','SERVER','FILES','GLOBAL','DEFAULT');
- }
- elseif(!is_array($method))
- {
- $method = Array($method);
- }
- $cnt = count($method);
- for($i=0;$i<$cnt;$i++)
- {
- switch(strtoupper($method[$i]))
- {
- case 'DEFAULT':
- if($default_value)
- {
- $value = $default_value;
- $i = $cnt+1; /* Found what we were looking for, now we end the loop */
- }
- break;
- case 'GLOBAL':
- if(@isset($GLOBALS[$varname]))
- {
- $value = $GLOBALS[$varname];
- $i = $cnt+1;
- }
- break;
- case 'POST':
- case 'GET':
- case 'COOKIE':
- case 'SERVER':
- if(phpversion() >= '4.1.0')
- {
- $meth = '_'.strtoupper($method[$i]);
- }
- else
- {
- $meth = 'HTTP_'.strtoupper($method[$i]).'_VARS';
- }
- if(@isset($GLOBALS[$meth][$varname]))
- {
- $value = $GLOBALS[$meth][$varname];
- $i = $cnt+1;
- }
- if(get_magic_quotes_gpc() && isset($value))
- {
- // we need to stripslash 3 levels of arrays
- // because of the password function in preferences
- // it's named ['user']['variablename']['pw']
- // or something like this in projects
- // $values['budgetBegin']['1']['year']
- if(@is_array($value))
- {
- /* stripslashes on the first level of array values */
- foreach($value as $name => $val)
- {
- if(@is_array($val))
- {
- foreach($val as $name2 => $val2)
- {
- if(@is_array($val2))
- {
- foreach($val2 as $name3 => $val3)
- {
- $value[$name][$name2][$name3] = stripslashes($val3);
- }
- }
- else
- {
- $value[$name][$name2] = stripslashes($val2);
- }
- }
- }
- else
- {
- $value[$name] = stripslashes($val);
- }
- }
- }
- else
- {
- /* stripslashes on this (string) */
- $value = stripslashes($value);
- }
- }
- break;
- case 'FILES':
- if(phpversion() >= '4.1.0')
- {
- $meth = '_FILES';
- }
- else
- {
- $meth = 'HTTP_POST_FILES';
- }
- if(@isset($GLOBALS[$meth][$varname]))
- {
- $value = $GLOBALS[$meth][$varname];
- $i = $cnt+1;
- }
- break;
- default:
- if(@isset($GLOBALS[strtoupper($method[$i])][$varname]))
- {
- $value = $GLOBALS[strtoupper($method[$i])][$varname];
- $i = $cnt+1;
- }
- break;
- }
- }
-
- if (@!isset($value))
- {
- $value = $default_value;
- }
-
- if (@!is_array($value))
- {
- if ($value == '')
- {
- $result = $value;
- }
- else
- {
- if (sanitize($value,$valuetype) == 1)
- {
- $result = $value;
- }
- else
- {
- $result = $default_value;
- }
- }
- }
- else
- {
- reset($value);
- while(list($k, $v) = each($value))
- {
- if ($v == '')
- {
- $result[$k] = $v;
- }
- else
- {
- if (is_array($valuetype))
- {
- $vt = $valuetype[$k];
- }
- else
- {
- $vt = $valuetype;
- }
-
- if (sanitize($v,$vt) == 1)
- {
- $result[$k] = $v;
- }
- else
- {
- if (is_array($default_value))
- {
- $result[$k] = $default_value[$k];
- }
- else
- {
- $result[$k] = $default_value;
- }
- }
- }
- }
- }
- if($register)
- {
- $GLOBALS['egw_info'][$GLOBALS['egw_info']['flags']['currentapp']][$varname] = $result;
- }
- return $result;
-}
-
-/**
- * retrieve a value from either a POST, GET, COOKIE, SERVER or from a class variable.
- *
- * @author skeeter
- * This function is used to retrieve a value from a user defined order of methods.
- * $this->id = get_var('id',array('HTTP_POST_VARS'||'POST','HTTP_GET_VARS'||'GET','HTTP_COOKIE_VARS'||'COOKIE','GLOBAL','DEFAULT'));
- * @param $variable name
- * @param $method ordered array of methods to search for supplied variable
- * @param $default_value (optional)
- */
-function get_var($variable,$method='any',$default_value='')
-{
- if(!@is_array($method))
- {
- $method = array($method);
- }
- return reg_var($variable,$method,'any',$default_value,False);
-}
-
-/**
- * Load a class and include the class file if not done so already.
- *
- * This function is used to create an instance of a class, and if the class file has not been included it will do so.
- * $GLOBALS['egw']->acl =& CreateObject('phpgwapi.acl');
- *
- * @author [email protected]
- * @param $classname name of class
- * @param $p1,$p2,... class parameters (all optional)
- * @return object reference to an object
- */
-function CreateObject($class)
-{
- list($appname,$classname) = explode('.',$class);
-
- if (!class_exists($classname))
- {
- static $replace = array(
- 'datetime' => 'egw_datetime',
- 'uitimesheet' => 'timesheet_ui',
- 'uiinfolog' => 'infolog_ui',
- 'uiprojectmanager' => 'projectmanager_ui',
- 'uiprojectelements' => 'projectmanager_elements_ui',
- 'uiroles' => 'projectmanager_roles_ui',
- 'uimilestones' => 'projectmanager_milestones_ui',
- 'uipricelist' => 'projectmanager_pricelist_ui',
- 'bowiki' => 'wiki_bo',
- 'uicategories' => 'admin_categories',
- 'defaultimap' => 'emailadmin_oldimap',
- );
- if (!file_exists(EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php') || isset($replace[$classname]))
- {
- if (isset($replace[$classname]))
- {
- //throw new Exception(__METHOD__."('$class') old classname '$classname' used in menuaction=$_GET[menuaction]!");
- error_log(__METHOD__."('$class') old classname '$classname' used in menuaction=$_GET[menuaction]!");
- $classname = $replace[$classname];
- }
- }
- if (!file_exists($f=EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php'))
- {
- throw new Api\Exception\AssertionFailed(__FUNCTION__."($classname) file $f not found!");
- }
- // this will stop php with a 500, if the class does not exist or there are errors in it (syntax error go into the error_log)
- require_once(EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php');
- }
- $args = func_get_args();
- switch(count($args))
- {
- case 1:
- $obj = new $classname;
- break;
- case 2:
- $obj = new $classname($args[1]);
- break;
- case 3:
- $obj = new $classname($args[1],$args[2]);
- break;
- case 4:
- $obj = new $classname($args[1],$args[2],$args[3]);
- break;
- default:
- $code = '$obj = new ' . $classname . '(';
- foreach(array_keys($args) as $n)
- {
- if ($n)
- {
- $code .= ($n > 1 ? ',' : '') . '$args[' . $n . ']';
- }
- }
- $code .= ');';
- eval($code);
- break;
- }
- if (!is_object($obj))
- {
- echo "<p>CreateObject('$class'): Cant instanciate class!!!<br />\n".function_backtrace(1)."</p>\n";
- }
- return $obj;
-}
-
-/**
- * Execute a function with multiple arguments
- * We take object $GLOBALS[classname] from class if exists
- *
- * @param string app.class.method method to execute
- * @example ExecObject('etemplates.so_sql.search',$criteria,$key_only,...);
- * @return mixed reference to returnvalue of the method
- */
-function &ExecMethod2($acm)
-{
- // class::method is php5.2.3+
- if (strpos($acm,'::') !== false && version_compare(PHP_VERSION,'5.2.3','<'))
- {
- list($class,$method) = explode('::',$acm);
- $acm = array($class,$method);
- }
- if (!is_callable($acm))
- {
- list(,$class,$method) = explode('.',$acm);
- if (!is_object($obj =& $GLOBALS[$class]))
- {
- if (class_exists($class))
- {
- $obj = new $class;
- }
- else
- {
- $obj = CreateObject($acm);
- }
- }
-
- if (!method_exists($obj,$method))
- {
- echo "<p><b>".function_backtrace()."</b>: no methode '$method' in class '$class'</p>\n";
- return False;
- }
- $acm = array($obj,$method);
- }
- $args = func_get_args();
- unset($args[0]);
-
- return call_user_func_array($acm,$args);
-}
-
-/**
- * Execute a function, and load a class and include the class file if not done so already.
- *
- * This function is used to create an instance of a class, and if the class file has not been included it will do so.
- *
- * @author seek3r
- * @param $method to execute
- * @param $functionparam function param should be an array
- * @param $loglevel developers choice of logging level
- * @param $classparams params to be sent to the contructor
- * @return mixed returnvalue of method
- */
-function ExecMethod($method, $functionparam = '_UNDEF_', $loglevel = 3, $classparams = '_UNDEF_')
-{
- unset($loglevel); // not used
- /* Need to make sure this is working against a single dimensional object */
- $partscount = count(explode('.',$method)) - 1;
-
- if (!is_callable($method) && $partscount == 2)
- {
- list($appname,$classname,$functionname) = explode(".", $method);
- if (!is_object($GLOBALS[$classname]))
- {
- // please note: no reference assignment (=&) here, as $GLOBALS is a reference itself!!!
- if ($classparams != '_UNDEF_' && ($classparams || $classparams != 'True'))
- {
- $GLOBALS[$classname] = CreateObject($appname.'.'.$classname, $classparams);
- }
- elseif (class_exists($classname))
- {
- $GLOBALS[$classname] = new $classname;
- }
- else
- {
- $GLOBALS[$classname] = CreateObject($appname.'.'.$classname);
- }
- }
-
- if (!method_exists($GLOBALS[$classname],$functionname))
- {
- error_log("ExecMethod('$method', ...) No methode '$functionname' in class '$classname'! ".function_backtrace());
- return false;
- }
- $method = array($GLOBALS[$classname],$functionname);
- }
- if (is_callable($method))
- {
- return $functionparam != '_UNDEF_' ? call_user_func($method,$functionparam) : call_user_func($method);
- }
- error_log("ExecMethod('$method', ...) Error in parts! ".function_backtrace());
- return false;
-}
-
-/**
- * Return a properly formatted account_id.
- *
- * @author skeeter
- * This function will return a properly formatted account_id. This can take either a name or an account_id as paramters. If a name is provided it will return the associated id.
- * $account_id = get_account_id($accountid);
- * @param int/string $account_id either a name or an id
- * @param int/string $default_id either a name or an id
- * @return int account_id
- */
-function get_account_id($account_id = '',$default_id = '')
-{
- if (gettype($account_id) == 'integer')
- {
- return $account_id;
- }
- elseif ($account_id == '')
- {
- if ($default_id == '')
- {
- return (isset($GLOBALS['egw_info']['user']['account_id'])?$GLOBALS['egw_info']['user']['account_id']:0);
- }
- elseif (is_string($default_id))
- {
- return $GLOBALS['egw']->accounts->name2id($default_id);
- }
- return (int)$default_id;
- }
- elseif (is_string($account_id))
- {
- if($GLOBALS['egw']->accounts->exists((int)$account_id) == True)
- {
- return (int)$account_id;
- }
- else
- {
- return $GLOBALS['egw']->accounts->name2id($account_id);
- }
- }
-}
-
-/**
- * sets the file system seperator depending on OS
- *
- * This is completely unnecessary, as you can use forward slashes in php under every OS -- RalfBecker 2005/11/09
- *
- * @deprecated just use forward slashes supported by PHP on all OS
- * @return file system separator
- */
-function filesystem_separator()
-{
- if(PHP_OS == 'Windows' || PHP_OS == 'OS/2' || PHP_OS == 'WINNT')
- {
- return '\\';
- }
- else
- {
- return '/';
- }
-}
-
-/**
- * @deprecated just use forward slashes supported by PHP on all OS
- */
-define('SEP', filesystem_separator());
-
-/**
- * print an array or object as pre-formatted html
- *
- * @param mixed $array
- * @param boolean $print =true print or return the content
- * @return string if !$print
- */
-function _debug_array($array,$print=True)
-{
- $output = '<pre>'.print_r($array,true)."</pre>\n";
-
- if ($print)
- {
- echo $output;
- }
- else
- {
- return $output;
- }
-}
-
-/**
- * eGW version checking, is eGW version in $a < $b
- *
- * @param string $a egw version number to check if less than $b
- * @param string $b egw version number to check $a against
- * @return boolean True if $a < $b
- */
-function alessthanb($a,$b,$DEBUG=False)
-{
- $num = array('1st','2nd','3rd','4th');
-
- if ($DEBUG)
- {
- echo'<br>Input values: ' . 'A="'.$a.'", B="'.$b.'"';
- }
- $newa = str_replace('pre','.',$a);
- $newb = str_replace('pre','.',$b);
- $testa = explode('.',$newa);
- if(@$testa[1] == '')
- {
- $testa[1] = 0;
- }
- if(@$testa[3] == '')
- {
- $testa[3] = 0;
- }
- $testb = explode('.',$newb);
- if(@$testb[1] == '')
- {
- $testb[1] = 0;
- }
- if(@$testb[3] == '')
- {
- $testb[3] = 0;
- }
- $less = 0;
-
- for ($i=0;$i<count($testa);$i++)
- {
- if ($DEBUG) { echo'<br>Checking if '. (int)$testa[$i] . ' is less than ' . (int)$testb[$i] . ' ...'; }
- if ((int)$testa[$i] < (int)$testb[$i])
- {
- if ($DEBUG) { echo ' yes.'; }
- $less++;
- if ($i<3)
- {
- /* Ensure that this is definitely smaller */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely less than B."; }
- $less = 5;
- break;
- }
- }
- elseif((int)$testa[$i] > (int)$testb[$i])
- {
- if ($DEBUG) { echo ' no.'; }
- $less--;
- if ($i<2)
- {
- /* Ensure that this is definitely greater */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely greater than B."; }
- $less = -5;
- break;
- }
- }
- else
- {
- if ($DEBUG) { echo ' no, they are equal.'; }
- $less = 0;
- }
- }
- if ($DEBUG) { echo '<br>Check value is: "'.$less.'"'; }
- if ($less>0)
- {
- if ($DEBUG) { echo '<br>A is less than B'; }
- return True;
- }
- elseif($less<0)
- {
- if ($DEBUG) { echo '<br>A is greater than B'; }
- return False;
- }
- else
- {
- if ($DEBUG) { echo '<br>A is equal to B'; }
- return False;
- }
-}
-
-/**
- * eGW version checking, is eGW version in $a > $b
- *
- * @param string $a eGW version number to check if more than $b
- * @param string $b eGW version number to check check $a against
- * @return boolean True if $a > $b
- */
-function amorethanb($a,$b,$DEBUG=False)
-{
- $num = array('1st','2nd','3rd','4th');
-
- if ($DEBUG)
- {
- echo'<br>Input values: ' . 'A="'.$a.'", B="'.$b.'"';
- }
- $newa = str_replace('pre','.',$a);
- $newb = str_replace('pre','.',$b);
- $testa = explode('.',$newa);
- if($testa[3] == '')
- {
- $testa[3] = 0;
- }
- $testb = explode('.',$newb);
- if($testb[3] == '')
- {
- $testb[3] = 0;
- }
- $less = 0;
-
- for ($i=0;$i<count($testa);$i++)
- {
- if ($DEBUG) { echo'<br>Checking if '. (int)$testa[$i] . ' is more than ' . (int)$testb[$i] . ' ...'; }
- if ((int)$testa[$i] > (int)$testb[$i])
- {
- if ($DEBUG) { echo ' yes.'; }
- $less++;
- if ($i<3)
- {
- /* Ensure that this is definitely greater */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely greater than B."; }
- $less = 5;
- break;
- }
- }
- elseif((int)$testa[$i] < (int)$testb[$i])
- {
- if ($DEBUG) { echo ' no.'; }
- $less--;
- if ($i<2)
- {
- /* Ensure that this is definitely smaller */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely less than B."; }
- $less = -5;
- break;
- }
- }
- else
- {
- if ($DEBUG) { echo ' no, they are equal.'; }
- $less = 0;
- }
- }
- if ($DEBUG) { echo '<br>Check value is: "'.$less.'"'; }
- if ($less>0)
- {
- if ($DEBUG) { echo '<br>A is greater than B'; }
- return True;
- }
- elseif($less<0)
- {
- if ($DEBUG) { echo '<br>A is less than B'; }
- return False;
- }
- else
- {
- if ($DEBUG) { echo '<br>A is equal to B'; }
- return False;
- }
-}
-
-/**
- * prepend a prefix to an array of table names
- *
- * @author Adam Hull (aka fixe) - No copyright claim
- * @param $prefix the string to be prepended
- * @param $tables and array of tables to have the prefix prepended to
- * @return array of table names with the prefix prepended
- */
-function prepend_tables_prefix($prefix,$tables)
-{
- foreach($tables as $key => $value)
- {
- $tables[$key] = $prefix.$value;
- }
- return $tables;
-}
-
-/**
- * backtrace of the calling functions for php4.3+ else menuaction/scriptname
- *
- * @author RalfBecker-AT-outdoor-training.de
- * @param int $remove =0 number of levels to remove
- * @return string function-names separated by slashes (beginning with the calling function not this one)
- */
-function function_backtrace($remove=0)
-{
- if (function_exists('debug_backtrace'))
- {
- $backtrace = debug_backtrace();
- //echo "function_backtrace($remove)<pre>".print_r($backtrace,True)."</pre>\n";
- foreach($backtrace as $n => $level)
- {
- if ($remove-- < 0)
- {
- $ret[] = (isset($level['class'])?$level['class'].$level['type']:'').$level['function'].
- ($n > 0 && isset($backtrace[$n-1]['line']) ? ':'.$backtrace[$n-1]['line'] : ''). // add line number of call
- (!$level['class'] && !is_object($level['args'][0]) && $level['function'] != 'unserialize' ?
- '('.substr(str_replace(EGW_SERVER_ROOT,'',(string)$level['args'][0]),0,64).')' : '');
- }
- }
- if (is_array($ret))
- {
- return implode(' / ',$ret);
- }
- }
- return $_GET['menuaction'] ? $_GET['menuaction'] : str_replace(EGW_SERVER_ROOT,'',$_SERVER['SCRIPT_FILENAME']);
-}
-
-/**
- * check $_REQUEST data for XSS, vars containing script tags are moved to $GLOBALS['egw_unset_vars']
- *
- * @internal
- * @param array &$var reference of array to check
- * @param string $name ='' name of the array
- */
-function _check_script_tag(&$var,$name='')
-{
- static $preg=null;
- //old: '/<\/?[^>]*\b(iframe|script|javascript|on(before)?(abort|blur|change|click|dblclick|error|focus|keydown|keypress|keyup|load|mousedown|mousemove|mouseout|mouseover|mouseup|reset|select|submit|unload))\b[^>]*>/i';
- if (!isset($preg)) $preg =
- // forbidden tags like iframe or script
- '/(<(\s*\/)?\s*(iframe|script|object|embed|math|meta)[^a-z0-9]|'.
- // on* attributes
- '<[^>]*on(before)?(abort|blur|change|click|dblclick|error|focus|keydown|keypress|keyup|load|mouse[^=]+|reset|select|submit|unload|resize|propertychange|page[^=]*|scroll|readystatechange|start|popstate|form[^=]+|input)\s*=|'.
- // ="javascript:*" diverse javascript attribute value
- '<[^>]+(href|src|dynsrc|lowsrc|background|style|poster|action)\s*=\s*("|\')?[^"\']*javascript|'.
- // benavior:url and expression in style attribute
- '<[^>]+style\s*=\s*("|\')[^>]*(behavior\s*:\s*url|expression)\s*\()/i';
- if (is_array($var))
- {
- foreach($var as $key => $val)
- {
- if (is_array($val))
- {
- _check_script_tag($var[$key],$name.'['.$key.']');
- }
- elseif(strpos($val, '<') !== false) // speedup: ignore everything without <
- {
- if (preg_match($preg,$val))
- {
- // special handling for $_POST[json_data], to decend into it's decoded content, fixing json direct might break json syntax
- if ($name == '_POST' && $key == 'json_data' && ($json_data = json_decode($val, true)))
- {
- _check_script_tag($json_data, $name.'[json_data]');
- $_REQUEST[$key] = $var[$key] = json_encode($json_data);
- continue;
- }
- error_log(__FUNCTION__."(,$name) ${name}[$key] = ".$var[$key]);
- $GLOBALS['egw_unset_vars'][$name.'['.$key.']'] = $var[$key];
- // attempt to clean the thing
- $var[$key] = $val = html::purify($val);
- // check if we succeeded, if not drop the var anyway, keep the egw_unset_var in any case
- if (preg_match($preg,$val))
- {
- error_log("*** _check_script_tag($name): unset(${name}[$key]) with value $val***");
- unset($var[$key]);
- }
- }
- }
- }
- // in case some stupid old code expects the array-pointer to be at the start of the array
- reset($var);
- }
-}
-
-/* some _check_script_tag tests, should be commented out by default
-if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__) // some tests
-{
- if (!defined('EGW_INCLUDE_ROOT'))
- {
- define(EGW_INCLUDE_ROOT, realpath(dirname(__FILE__).'/../..'));
- define(EGW_API_INC, realpath(dirname(__FILE__)));
- }
-
- $total = $num_failed = 0;
- $patterns = array(
- // pattern => true: should fail, false: should not fail
- '< script >alert(1)< / script >' => true,
- '<span onMouseOver ="alert(1)">blah</span>' => true,
- '<a href= "JaVascript: alert(1)">Click Me</a>' => true,
- // from https://www.acunetix.com/websitesecurity/cross-site-scripting/
- '<body onload=alert("XSS")>' => true,
- '<body background="javascript:alert("XSS")">' => true,
- '<iframe src=âhttp://evil.com/xss.htmlâ>' => true,
- '<input type="image" src="javascript:alert(\'XSS\');">' => true,
- '<link rel="stylesheet" href="javascript:alert(\'XSS\');">' => true,
- '<table background="javascript:alert(\'XSS\')">' => true,
- '<td background="javascript:alert(\'XSS\')">' => true,
- '<div style="background-image: url(javascript:alert(\'XSS\'))">' => true,
- '<div style="width: expression(alert(\'XSS\'));">' => true,
- '<object type="text/x-scriptlet" data="http://hacker.com/xss.html">' => true,
- // false positiv tests
- 'If 1 < 2, what does that mean for description, if 2 > 1.' => false,
- 'If 1 < 2, what does that mean for a script, if 2 > 1.' => false,
- '<div>Script and Javascript: not evil ;-)' => false,
- '<span>style=background-color' => false,
- '<font face="Script MT Bold" size="4"><span style="font-size:16pt;">Hugo Sonstwas</span></font>' => false,
- '<[email protected]>' => false,
- );
- foreach($patterns as $pattern => $should_fail)
- {
- $test = array($pattern);
- unset($GLOBALS['egw_unset_vars']);
- _check_script_tag($test,'test');
- $failed = isset($GLOBALS['egw_unset_vars']) !== $should_fail;
- ++$total;
- if ($failed) $num_failed++;
- echo "<p style='color: ".($failed?'red':'black')."'> ".html::htmlspecialchars($pattern).' '.
- (isset($GLOBALS['egw_unset_vars'])?'removed':'passed')."</p>";
- }
- $x = 1;
- // urls with attack vectors
- $urls = array(
- // we currently fail 76 of 666 test, thought they seem not to apply to our use case, as we check request data
- 'https://gist.github.com/JohannesHoppe/5612274' => file(
- 'https://gist.githubusercontent.com/JohannesHoppe/5612274/raw/60016bccbfe894dcd61a6be658a4469e403527de/666_lines_of_XSS_vectors.html'),
- // we currently fail 44 of 140 tests, thought they seem not to apply to our use case, as we check request data
- 'https://html5sec.org/' => call_user_func(function() {
- $payloads = $items = null;
- if (!($items_js = file_get_contents('https://html5sec.org/items.js')) ||
- !preg_match_all("|^\s+'data'\s+:\s+'(.*)',$|m", $items_js, $items, PREG_PATTERN_ORDER) ||
- !($payload_js = file_get_contents('https://html5sec.org/payloads.js')) ||
- !preg_match_all("|^\s+'([^']+)'\s+:\s+'(.*)',$|m", $payload_js, $payloads, PREG_PATTERN_ORDER))
- {
- return false;
- }
- $replace = array(
- "\\'" => "'",
- '\\\\'=> '\\,',
- '\r' => "\r",
- '\n' => "\n",
- );
- foreach($payloads[1] as $n => $from) {
- $replace['%'.$from.'%'] = $payloads[2][$n];
- }
- return array_map(function($item) use ($replace) {
- return strtr($item, $replace);
- }, $items[1]);
- }),
- );
- foreach($urls as $url => $vectors)
- {
- // no all xss attack vectors from http://ha.ckers.org/xssAttacks.xml are relevant here! (needs interpretation)
- if (!$vectors)
- {
- echo "<p style='color:red'>Could NOT download or parse $url with attack vectors!</p>\n";
- continue;
- }
- echo "<p><b>Attacks from <a href='$url' target='_blank'>$url</a> with ".count($vectors)." tests:</b></p>";
- foreach($vectors as $line => $pattern)
- {
- $test = array($pattern);
- unset($GLOBALS['egw_unset_vars']);
- _check_script_tag($test, 'line '.(1+$line));
- $failed = !isset($GLOBALS['egw_unset_vars']);
- ++$total;
- if ($failed) $num_failed++;
- echo "<p style='color: ".($failed?'red':'black')."'>".(1+$line).": ".html::htmlspecialchars($pattern).' '.
- (isset($GLOBALS['egw_unset_vars'])?'removed':'passed')."</p>";
- }
- }
- die("<p style='color: ".($num_failed?'red':'black')."'>Tests finished: $num_failed / $total failed</p>");
-}*/
-
-foreach(array('_GET','_POST','_REQUEST','HTTP_GET_VARS','HTTP_POST_VARS') as $n => $where)
-{
- $pregs = array(
- 'order' => '/^[a-zA-Z0-9_,]*$/',
- 'sort' => '/^(ASC|DESC|asc|desc|0|1|2|3|4|5|6|7){0,1}$/',
- );
- foreach(array('order','sort') as $name)
- {
- if (isset($GLOBALS[$where][$name]) && !is_array($GLOBALS[$where][$name]) && !preg_match($pregs[$name],$GLOBALS[$where][$name]))
- {
- $GLOBALS[$where][$name] = '';
- }
- }
- // do the check for script-tags only for _GET and _POST or if we found something in _GET and _POST
- // speeds up the execusion a bit
- if (isset($GLOBALS[$where]) && is_array($GLOBALS[$where]) && ($n < 2 || isset($GLOBALS['egw_unset_vars'])))
- {
- _check_script_tag($GLOBALS[$where],$where);
- }
-}
-//if (is_array($GLOBALS['egw_unset_vars'])) { echo "egw_unset_vars=<pre>".htmlspecialchars(print_r($GLOBALS['egw_unset_vars'],true))."</pre>"; exit; }
-
-// $GLOBALS[egw_info][flags][currentapp] and die if it contains something nasty or unexpected
-if (isset($GLOBALS['egw_info']) && isset($GLOBALS['egw_info']['flags']) &&
- isset($GLOBALS['egw_info']['flags']['currentapp']) && !preg_match('/^[A-Za-z0-9_-]+$/',$GLOBALS['egw_info']['flags']['currentapp']))
-{
- error_log(__FILE__.': '.__LINE__.' Invalid $GLOBALS[egw_info][flags][currentapp]='.array2string($GLOBALS['egw_info']['flags']['currentapp']).', $_SERVER[REQUEST_URI]='.array2string($_SERVER[REQUEST_URI]));
- die('Invalid $GLOBALS[egw_info][flags][currentapp]!');
-}
-
-// neutralises register_globals On, which is not used by eGW
-// some code from the hardend php project: http://www.hardened-php.net/articles/PHPUG-PHP-Sicherheit-Parametermanipulationen.pdf
-if (ini_get('register_globals'))
-{
- function unregister_globals()
- {
- // protect against GLOBALS overwrite or setting egw_info
- if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS']) || isset($_REQUEST['egw_info']) || isset($_FILES['egw_info']))
- {
- die('GLOBALS overwrite detected!!!');
- }
- // unregister all globals
- $noUnset = array('GLOBALS','_GET','_POST','_COOKIE','_SERVER','_ENV','_FILES','xajax');
- foreach(array_unique(array_merge(
- array_keys($_GET),array_keys($_POST),array_keys($_COOKIE),array_keys($_SERVER),array_keys($_ENV),array_keys($_FILES),
- isset($_SESSION) && is_array($_SESSION) ? array_keys($_SESSION) : array())) as $k)
- {
- if (!in_array($k,$noUnset) && isset($GLOBALS[$k]))
- {
- unset($GLOBALS[$k]);
- }
- }
- }
- unregister_globals();
-}
-
-if (!function_exists('lang') || defined('NO_LANG')) // setup declares an own version
-{
- /**
- * function to handle multilanguage support
- *
- * @param string $key message in englich with %1, %2, ... placeholders
- * @param string $vars =null multiple values to replace the placeholders
- * @return string translated message with placeholders replaced
- */
- function lang($key,$vars=null)
- {
- if(!is_array($vars))
- {
- $vars = func_get_args();
- array_shift($vars); // remove $key
- }
- return translation::translate($key,$vars);
- }
-}
-
-/**
- * Translate message only if translation object is already loaded
- *
- * This function is usefull for exception handlers or early stages of the initialisation of the egw object,
- * as calling lang would try to load the translations, evtl. cause more errors, eg. because there's no db-connection.
- *
- * @param string $key message in englich with %1, %2, ... placeholders
- * @param string $vars =null multiple values to replace the placeholders
- * @return string translated message with placeholders replaced
- */
-function try_lang($key,$vars=null)
-{
- static $varnames = array('%1','%2','%3','%4');
-
- if(!is_array($vars))
- {
- $vars = func_get_args();
- array_shift($vars); // remove $key
- }
- return class_exists(translations,false) ? translation::translate($key,$vars) : str_replace($varnames,$vars,$key);
-}
-
-/**
- * Unserialize a php serialized string, but only if it contains NO objects 'O:\d:"' or 'C:\d:"' pattern
- *
- * Should be used for all external content, to guard against exploidts.
- *
- * PHP 7.0+ can be told not to instanciate any classes (and calling eg. it's destructor).
- * In fact it instanciates it as __PHP_Incomplete_Class without any methods and therefore disarming threads.
- *
- * @param string $str
- * @return mixed
- */
-function php_safe_unserialize($str)
-{
- if (PHP_VERSION >= 7)
- {
- return unserialize($str, array('allowed_classes' => false));
- }
- if ((strpos($str, 'O:') !== false || strpos($str, 'C:') !== false) &&
- preg_match('/(^|;|{)[OC]:\d+:"/', $str))
- {
- error_log(__METHOD__."('$str') contains objects --> return NULL");
- return null; // null, not false, to not trigger behavior of returning string itself to app code
- }
- return unserialize($str);
-}
-
-/* some test for object safe unserialisation
-if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__) // some tests
-{
- if (php_sapi_name() !== 'cli') echo "<pre>\n";
- foreach(array(
- // things unsafe to unserialize
- "O:34:\"Horde_Kolab_Server_Decorator_Clean\":2:{s:43:\"\x00Horde_Kolab_Server_Decorator_Clean\x00_server\";" => false,
- "O:20:\"Horde_Prefs_Identity\":2:{s:9:\"\x00*\x00_prefs\";O:11:\"Horde_Prefs\":2:{s:8:\"\x00*\x00_opts\";a:1:{s:12:\"sizecallback\";" => false,
- "a:2:{i:0;O:12:\"Horde_Config\":1:{s:13:\"\x00*\x00_oldConfig\";s:#{php_injection.length}:\"#{php_injection}\";}i:1;s:13:\"readXMLConfig\";}}" => false,
- 'a:6:{i:0;i:0;i:1;d:2;i:2;s:4:"ABCD";i:3;r:3;i:4;O:8:"my_Class":2:{s:1:"a";r:6;s:1:"b";N;};i:5;C:16:"SplObjectStorage":14:{x:i:0;m:a:0:{}}' => false,
- serialize(new stdClass()) => false,
- serialize(array(new stdClass(), new SplObjectStorage())) => false,
- // string content, safe to unserialize
- serialize('O:8:"stdClass"') => true,
- serialize('C:16:"SplObjectStorage"') => true,
- serialize(array('a' => 'O:8:"stdClass"', 'b' => 'C:16:"SplObjectStorage"')) => true,
- // false positive: failing our php<7 regular expression, because it has correct delimiter (^|;|{) in front of pattern :-(
- serialize('O:8:"stdClass";C:16:"SplObjectStorage"') => true,
- ) as $str => $result)
- {
- if ((bool)($r=php_safe_unserialize($str)) !== $result)
- {
- if (!$result)
- {
- if (PHP_VERSION >= 7)
- {
- if (preg_match_all('/([^ ]+) Object\(/', array2string($r), $matches))
- {
- foreach($matches[1] as $class)
- {
- if (!preg_match('/^__PHP_Incomplete_Class(#\d+)?$/', $class))
- {
- echo "FAILED: $str\n";
- continue 2;
- }
- }
- }
- echo "passed: ".array2string($str)." = ".array2string($r)."\n";
- }
- else
- {
- echo "FAILED: $str\n";
- }
- }
- else
- {
- echo "false positive: $str\n";
- }
- }
- else
- {
- echo "passed: $str\n";
- }
- //echo "result=".array2string($result).", php_save_unserialize('".htmlspecialchars($str)."') = ".array2string(php_safe_unserialize($str))." --> ".array2string((bool)php_safe_unserialize($str))."\n";
- }
-}*/
-
-/**
- * Unserialize a json or php serialized array
- *
- * Used to migrate from PHP serialized database values to json-encoded ones.
- *
- * @param string $str string with serialized array
- * @param boolean $allow_not_serialized =false true: return $str as is, if it is no serialized array
- * @return array|str|false
- */
-function json_php_unserialize($str, $allow_not_serialized=false)
-{
- if ((in_array($str[0], array('a', 'i', 's', 'b', 'O', 'C')) && $str[1] == ':' || $str === 'N;') &&
- ($arr = php_safe_unserialize($str)) !== false || $str === 'b:0;')
- {
- return $arr;
- }
- if (!$allow_not_serialized || $str[0] == '[' || $str[0] == '{' || $str[0] == '"' || $str === 'null' || ($val = json_decode($str)) !== null)
- {
- return isset($val) ? $val : json_decode($str, true);
- }
- return $str;
-}
-
-/**
- * Clasify exception for a headline and log it to error_log, if not running as cli
- *
- * @param Exception|Error $e
- * @param string &$headline
- */
-function _egw_log_exception($e,&$headline=null)
-{
- $trace = explode("\n", $e->getTraceAsString());
- if ($e instanceof Api\Exception\NoPermission)
- {
- $headline = try_lang('Permission denied!');
- }
- elseif ($e instanceof Api\Db\Exception)
- {
- $headline = try_lang('Database error');
- }
- elseif ($e instanceof Api\Exception\WrongUserinput)
- {
- $headline = ''; // message contains the whole message, it's usually no real error but some input validation
- }
- elseif ($e instanceof egw_exception_warning)
- {
- $headline = 'PHP Warning';
- array_shift($trace);
- }
- else
- {
- $headline = try_lang('An error happened');
- }
- // log exception to error log, if not running as cli,
- // which outputs the error_log to stderr and therefore output it twice to the user
- if(isset($_SERVER['HTTP_HOST']) || $GLOBALS['egw_info']['flags']['no_exception_handler'] !== 'cli')
- {
- error_log($headline.($e instanceof egw_exception_warning ? ': ' : ' ('.get_class($e).'): ').$e->getMessage());
- foreach($trace as $line)
- {
- error_log($line);
- }
- error_log('# Instance='.$GLOBALS['egw_info']['user']['domain'].', User='.$GLOBALS['egw_info']['user']['account_lid'].
- ', Request='.$_SERVER['REQUEST_METHOD'].' '.($_SERVER['HTTPS']?'https://':'http://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].
- ', User-agent='.$_SERVER['HTTP_USER_AGENT']);
- }
-}
-
-/**
- * Fail a little bit more gracefully then an uncought exception
- *
- * Does NOT return
- *
- * @param Exception|Error $e
- */
-function egw_exception_handler($e)
-{
- // handle redirects without logging
- if (is_a($e, 'egw_exception_redirect'))
- {
- egw::redirect($e->url, $e->app);
- }
- // logging all exceptions to the error_log (if not cli) and get headline
- $headline = null;
- _egw_log_exception($e,$headline);
-
- // exception handler for cli (command line interface) clients, no html, no logging
- if(!isset($_SERVER['HTTP_HOST']) || $GLOBALS['egw_info']['flags']['no_exception_handler'] == 'cli')
- {
- echo ($headline ? $headline.': ' : '').$e->getMessage()."\n";
- if ($GLOBALS['egw_info']['server']['exception_show_trace'])
- {
- echo $e->getTraceAsString()."\n";
- }
- exit($e->getCode() ? $e->getCode() : 9999); // allways give a non-zero exit code
- }
- // regular GUI exception
- if (!isset($GLOBALS['egw_info']['flags']['no_exception_handler']))
- {
- header('HTTP/1.1 500 '.$headline);
- $message = '<h3>'.html::htmlspecialchars($headline)."</h3>\n".
- '<pre><b>'.html::htmlspecialchars($e->getMessage())."</b>\n\n";
-
- // only show trace (incl. function arguments) if explicitly enabled, eg. on a development system
- if ($GLOBALS['egw_info']['server']['exception_show_trace'])
- {
- $message .= html::htmlspecialchars($e->getTraceAsString());
- }
- $message .= "</pre>\n";
- if (is_a($e, 'EGroupware\Api\Db\Exception\Setup'))
- {
- $setup_dir = str_replace(array('home/index.php','index.php'),'setup/',$_SERVER['PHP_SELF']);
- $message .= '<a href="'.$setup_dir.'">Run setup to install or configure EGroupware.</a>';
- }
- elseif (is_object($GLOBALS['egw']) && isset($GLOBALS['egw']->session) && method_exists($GLOBALS['egw'],'link'))
- {
- $message .= '<p><a href="'.$GLOBALS['egw']->link('/index.php').'">'.try_lang('Click here to resume your eGroupWare Session.').'</a></p>';
- }
- if (is_object($GLOBALS['egw']) && isset($GLOBALS['egw']->framework))
- {
- $GLOBALS['egw']->framework->render($message,$headline);
- }
- else
- {
- echo "<html>\n<head>\n<title>".html::htmlspecialchars($headline)."</title>\n</head>\n<body>\n$message\n</body>\n</html>\n";
- }
- }
- // exception handler sending message back to the client as basic auth message
- elseif($GLOBALS['egw_info']['flags']['no_exception_handler'] == 'basic_auth')
- {
- $error = str_replace(array("\r", "\n"), array('', ' | '), $e->getMessage());
- header('WWW-Authenticate: Basic realm="'.$headline.' '.$error.'"');
- header('HTTP/1.1 401 Unauthorized');
- header('X-WebDAV-Status: 401 Unauthorized', true);
- }
- if (is_object($GLOBALS['egw']))
- {
- common::egw_exit();
- }
- exit;
-}
-
-if (!isset($GLOBALS['egw_info']['flags']['no_exception_handler']) || $GLOBALS['egw_info']['flags']['no_exception_handler'] !== true)
-{
- set_exception_handler('egw_exception_handler');
-}
-
-/**
- * Fail a little bit more gracefully then a catchable fatal error, by throwing an exception
- *
- * @param int $errno level of the error raised: E_* constants
- * @param string $errstr error message
- * @param string $errfile filename that the error was raised in
- * @param int $errline line number the error was raised at
- * @link http://www.php.net/manual/en/function.set-error-handler.php
- * @throws ErrorException
- */
-function egw_error_handler ($errno, $errstr, $errfile, $errline)
-{
- switch ($errno)
- {
- case E_RECOVERABLE_ERROR:
- case E_USER_ERROR:
- throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
-
- case E_WARNING:
- case E_USER_WARNING:
- // skip message for warnings supressed via @-error-control-operator (eg. @is_dir($path))
- // can be commented out to get suppressed warnings too!
- if (error_reporting())
- {
- _egw_log_exception(new egw_exception_warning($errstr.' in '.$errfile.' on line '.$errline));
- }
- break;
- }
-}
-
-/**
- * Used internally to trace warnings
- */
-class egw_exception_warning extends Exception {}
-
-// install our error-handler only for catchable fatal errors and warnings
-// following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING
-set_error_handler('egw_error_handler', E_RECOVERABLE_ERROR|E_USER_ERROR|E_WARNING|E_USER_WARNING);
-
-// some not longer necessary defines
-if (isset($GLOBALS['egw_info']['flags']['phpgw_compatibility']) && $GLOBALS['egw_info']['flags']['phpgw_compatibility'])
-{
- define('PHPGW_API_INC',EGW_API_INC);
- define('PHPGW_SERVER_ROOT',EGW_SERVER_ROOT);
- define('PHPGW_INCLUDE_ROOT',EGW_INCLUDE_ROOT);
-
- /* debugging settings */
- define('DEBUG_DATATYPES', True);
- define('DEBUG_LEVEL', 3);
- define('DEBUG_OUTPUT', 2); /* 1 = screen, 2 = DB. For both use 3. */
- define('DEBUG_TIMER', False);
-}
Copied: trunk/egroupware/api/src/loader.php (from r55817, trunk/phpgwapi/inc/functions.inc.php)
URL: http://svn.stylite.de/viewvc/egroupware/trunk/egroupware/api/src/loader.php?p2=trunk/egroupware/api/src/loader.php&p1=trunk/phpgwapi/inc/functions.inc.php&r1=55817&r2=55853&rev=55853&view=diff
==============================================================================
--- trunk/phpgwapi/inc/functions.inc.php (original)
+++ trunk/egroupware/api/src/loader.php Tue Apr 26 16:38:08 2016
@@ -1,6 +1,6 @@
<?php
/**
- * eGroupWare API loader
+ * EGroupware API loader
*
* Rewritten by [email protected] to store the eGW enviroment
* (egw-object and egw_info-array) in a php-session and restore it from
@@ -17,6 +17,9 @@
* @version $Id$
*/
+use EGroupware\Api\Session;
+use EGroupware\Api\Egw;
+
// E_STRICT in PHP 5.4 gives various strict warnings in working code, which can NOT be easy fixed in all use-cases :-(
// Only variables should be assigned by reference, eg. soetemplate::tree_walk()
// Declaration of <extended method> should be compatible with <parent method>, varios places where method parameters change
@@ -30,7 +33,7 @@
$egw_min_php_version = '5.4';
if (!function_exists('version_compare') || version_compare(PHP_VERSION,$egw_min_php_version) < 0)
{
- die("eGroupWare requires PHP $egw_min_php_version or greater.<br />Please contact your System Administrator to upgrade PHP!");
+ die("EGroupware requires PHP $egw_min_php_version or greater.<br />Please contact your System Administrator to upgrade PHP!");
}
if (!defined('EGW_API_INC')) define('EGW_API_INC',PHPGW_API_INC); // this is to support the header upgrade
@@ -51,36 +54,35 @@
echo '!!! PLEASE CORRECT THIS SITUATION !!!</b></p>';
}
-require_once(EGW_API_INC.'/common_functions.inc.php');
+require_once(__DIR__.'/loader/common.php');
// init eGW's sessions-handler and check if we can restore the eGW enviroment from the php-session
-if (egw_session::init_handler())
+if (Session::init_handler())
{
if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login' && $GLOBALS['egw_info']['flags']['currentapp'] != 'logout')
{
- if (is_array($_SESSION[egw_session::EGW_INFO_CACHE]) && $_SESSION[egw_session::EGW_OBJECT_CACHE] && $_SESSION[egw_session::EGW_REQUIRED_FILES])
+ if (is_array($_SESSION[Session::EGW_INFO_CACHE]) && $_SESSION[Session::EGW_OBJECT_CACHE] && $_SESSION[Session::EGW_REQUIRED_FILES])
{
// marking the context as restored from the session, used by session->verify to not read the data from the db again
$GLOBALS['egw_info']['flags']['restored_from_session'] = true;
// restoring the egw_info-array
- $GLOBALS['egw_info'] = array_merge($_SESSION[egw_session::EGW_INFO_CACHE],array('flags' => $GLOBALS['egw_info']['flags']));
+ $GLOBALS['egw_info'] = array_merge($_SESSION[Session::EGW_INFO_CACHE],array('flags' => $GLOBALS['egw_info']['flags']));
// include required class-definitions
- if (is_array($_SESSION[egw_session::EGW_REQUIRED_FILES])) // all classes, which can not be autoloaded
+ if (is_array($_SESSION[Session::EGW_REQUIRED_FILES])) // all classes, which can not be autoloaded
{
- foreach($_SESSION[egw_session::EGW_REQUIRED_FILES] as $file)
+ foreach($_SESSION[Session::EGW_REQUIRED_FILES] as $file)
{
require_once($file);
}
}
- $GLOBALS['egw'] = unserialize($_SESSION[egw_session::EGW_OBJECT_CACHE]);
+ $GLOBALS['egw'] = unserialize($_SESSION[Session::EGW_OBJECT_CACHE]);
- if (is_object($GLOBALS['egw']) && ($GLOBALS['egw'] instanceof egw)) // only egw object has wakeup2, setups egw_minimal eg. has not!
+ if (is_object($GLOBALS['egw']) && ($GLOBALS['egw'] instanceof Egw)) // only egw object has wakeup2, setups egw_minimal eg. has not!
{
$GLOBALS['egw']->wakeup2(); // adapt the restored egw-object/enviroment to this request (eg. changed current app)
- //printf("<p style=\"position: absolute; right: 0px; top: 0px;\">egw-enviroment restored in %d ms</p>\n",1000*(perfgetmicrotime()-$GLOBALS['egw_info']['flags']['page_start_time']));
$GLOBALS['egw_info']['flags']['session_restore_time'] = microtime(true) - $GLOBALS['egw_info']['flags']['page_start_time'];
if (is_object($GLOBALS['egw']->translation)) return; // exit this file, as the rest of the file creates a new egw-object and -enviroment
}
@@ -88,28 +90,26 @@
unset($GLOBALS['egw']);
$GLOBALS['egw_info'] = array('flags'=>$GLOBALS['egw_info']['flags']);
unset($GLOBALS['egw_info']['flags']['restored_from_session']);
- unset($_SESSION[egw_session::EGW_INFO_CACHE]);
- unset($_SESSION[egw_session::EGW_REQUIRED_FILES]);
- unset($_SESSION[egw_session::EGW_OBJECT_CACHE]);
+ unset($_SESSION[Session::EGW_INFO_CACHE]);
+ unset($_SESSION[Session::EGW_REQUIRED_FILES]);
+ unset($_SESSION[Session::EGW_OBJECT_CACHE]);
}
- //echo "<p>could not restore egw_info and the egw-object!!!</p>\n";
}
else // destroy the session-cache if called by login or logout
{
- unset($_SESSION[egw_session::EGW_INFO_CACHE]);
- unset($_SESSION[egw_session::EGW_REQUIRED_FILES]);
- unset($_SESSION[egw_session::EGW_OBJECT_CACHE]);
+ unset($_SESSION[Session::EGW_INFO_CACHE]);
+ unset($_SESSION[Session::EGW_REQUIRED_FILES]);
+ unset($_SESSION[Session::EGW_OBJECT_CACHE]);
}
}
-print_debug('sane environment','messageonly','api');
/****************************************************************************\
* Multi-Domain support *
\****************************************************************************/
-$GLOBALS['egw_info']['user']['domain'] = egw_session::search_instance(
+$GLOBALS['egw_info']['user']['domain'] = Session::search_instance(
isset($_POST['login']) ? $_POST['login'] : (isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : $_SERVER['REMOTE_USER']),
- egw_session::get_request('domain'),$GLOBALS['egw_info']['server']['default_domain'],
+ Session::get_request('domain'),$GLOBALS['egw_info']['server']['default_domain'],
array($_SERVER['HTTP_HOST'], $_SERVER['SERVER_NAME']),$GLOBALS['egw_domain']);
$GLOBALS['egw_info']['server']['db_host'] = $GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]['db_host'];
@@ -118,13 +118,12 @@
$GLOBALS['egw_info']['server']['db_user'] = $GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]['db_user'];
$GLOBALS['egw_info']['server']['db_pass'] = $GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]['db_pass'];
$GLOBALS['egw_info']['server']['db_type'] = $GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]['db_type'];
-print_debug('domain',@$GLOBALS['egw_info']['user']['domain'],'api');
// the egw-object instanciates all sub-classes (eg. $GLOBALS['egw']->db) and the egw_info array
-$GLOBALS['egw'] = new egw(array_keys($GLOBALS['egw_domain']));
+$GLOBALS['egw'] = new Egw(array_keys($GLOBALS['egw_domain']));
// store domain config user&pw as a hash (originals get unset)
-$GLOBALS['egw_info']['server']['config_hash'] = egw_session::user_pw_hash($GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]['config_user'],
+$GLOBALS['egw_info']['server']['config_hash'] = Session::user_pw_hash($GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]['config_user'],
$GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]['config_passwd'],true);
if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login' && !$GLOBALS['egw_info']['server']['show_domain_selectbox'])
@@ -137,8 +136,8 @@
// saving the the egw_info array and the egw-object in the session
if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login')
{
- $_SESSION[egw_session::EGW_INFO_CACHE] = $GLOBALS['egw_info'];
- unset($_SESSION[egw_session::EGW_INFO_CACHE]['flags']); // dont save the flags, they change on each request
+ $_SESSION[Session::EGW_INFO_CACHE] = $GLOBALS['egw_info'];
+ unset($_SESSION[Session::EGW_INFO_CACHE]['flags']); // dont save the flags, they change on each request
- $_SESSION[egw_session::EGW_OBJECT_CACHE] = serialize($GLOBALS['egw']);
+ $_SESSION[Session::EGW_OBJECT_CACHE] = serialize($GLOBALS['egw']);
}
Copied: trunk/egroupware/api/src/loader/common.php (from r55840, trunk/phpgwapi/inc/common_functions.inc.php)
URL: http://svn.stylite.de/viewvc/egroupware/trunk/egroupware/api/src/loader/common.php?p2=trunk/egroupware/api/src/loader/common.php&p1=trunk/phpgwapi/inc/common_functions.inc.php&r1=55840&r2=55853&rev=55853&view=diff
==============================================================================
--- trunk/phpgwapi/inc/common_functions.inc.php (original)
+++ trunk/egroupware/api/src/loader/common.php Tue Apr 26 16:38:08 2016
@@ -1,11 +1,10 @@
<?php
/**
- * EGroupware commonly used functions
- *
- * This file was originaly written by Dan Kuykendall and Joseph Engo
- * Copyright (C) 2000, 2001 Dan Kuykendall
- *
- * All newer parts (XSS checks, autoloading, exception handler, ...) are written by Ralf Becker.
+ * EGroupware create enviroment:
+ * - autoloader
+ * - exception handler
+ * - XSS and other security stuff
+ * - global functions (incl. deprecated ones, if /phpgwapi dir is there)
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
@@ -16,94 +15,7 @@
use EGroupware\Api;
-// this is only neccessary, if header.inc.php is not included, but common_functions.inc.php directly
-if (!defined('EGW_SERVER_ROOT'))
-{
- define('EGW_SERVER_ROOT', dirname(dirname(__DIR__)));
- define('EGW_INCLUDE_ROOT', EGW_SERVER_ROOT);
- define('EGW_API_INC', __DIR__);
-}
-
-/**
- * New PSR-4 autoloader for EGroupware
- *
- * class_exists('\\EGroupware\\Api\\Vfs'); // /api/src/Vfs.php
- * class_exists('\\EGroupware\\Api\\Vfs\\Dav\\Directory'); // /api/src/Vfs/Dav/Directory.php
- * class_exists('\\EGroupware\\Api\\Vfs\\Sqlfs\\StreamWrapper'); // /api/src/Vfs/Sqlfs/StreamWrapper.php
- * class_exists('\\EGroupware\\Api\\Vfs\\Sqlfs\\Utils'); // /api/src/Vfs/Sqlfs/Utils.php
- * class_exists('\\EGroupware\\Stylite\\Versioning\\StreamWrapper'); // /stylite/src/Versioning/StreamWrapper.php
- * class_exists('\\EGroupware\\Calendar\\Ui'); // /calendar/src/Ui.php
- * class_exists('\\EGroupware\\Calendar\\Ui\\Lists'); // /calendar/src/Ui/Lists.php
- * class_exists('\\EGroupware\\Calendar\\Ui\\Views'); // /calendar/src/Ui/Views.php
- */
-spl_autoload_register(function($class)
-{
- $parts = explode('\\', $class);
- if (array_shift($parts) != 'EGroupware') return; // not our prefix
-
- $app = lcfirst(array_shift($parts));
- $base = EGW_INCLUDE_ROOT.'/'.$app.'/src/';
- $path = $base.implode('/', $parts).'.php';
-
- if (file_exists($path))
- {
- require_once $path;
- //error_log("PSR4_autoload('$class') --> require_once($path) --> class_exists('$class')=".array2string(class_exists($class,false)));
- }
-});
-
-/**
- * Old autoloader for EGroupware understanding the following naming schema:
- *
- * 1. new (prefered) nameing schema: app_class_something loading app/inc/class.class_something.inc.php
- * 2. API classes: classname loading phpgwapi/inc/class.classname.inc.php
- * 2a.API classes containing multiple classes per file eg. egw_exception* in class.egw_exception.inc.php
- * 3. eTemplate classes: classname loading etemplate/inc/class.classname.inc.php
- *
- * @param string $class name of class to load
- */
-spl_autoload_register(function($class)
-{
- // fixing warnings generated by php 5.3.8 is_a($obj) trying to autoload huge strings
- if (strlen($class) > 64 || strpos($class, '.') !== false) return;
-
- $components = explode('_',$class);
- $app = array_shift($components);
- // classes using the new naming schema app_class_name, eg. admin_cmd
- if (file_exists($file = EGW_INCLUDE_ROOT.'/'.$app.'/inc/class.'.$class.'.inc.php') ||
- // classes using the new naming schema app_class_name, eg. admin_cmd
- isset($components[0]) && file_exists($file = EGW_INCLUDE_ROOT.'/'.$app.'/inc/class.'.$app.'_'.$components[0].'.inc.php') ||
- // classes with an underscore in their name
- !isset($GLOBALS['egw_info']['apps'][$app]) && isset($GLOBALS['egw_info']['apps'][$app . '_' . $components[0]]) &&
- file_exists($file = EGW_INCLUDE_ROOT.'/'.$app.'_'.$components[0].'/inc/class.'.$class.'.inc.php') ||
- // eGW api classes using the old naming schema, eg. html
- file_exists($file = EGW_API_INC.'/class.'.$class.'.inc.php') ||
- // eGW api classes containing multiple classes in on file, eg. egw_exception
- isset($components[0]) && file_exists($file = EGW_API_INC.'/class.'.$app.'_'.$components[0].'.inc.php') ||
- // eGW eTemplate classes using the old naming schema, eg. etemplate
- file_exists($file = EGW_INCLUDE_ROOT.'/etemplate/inc/class.'.$class.'.inc.php') ||
- // include PEAR and PSR0 classes from include_path
- // need to use include (not include_once) as eg. a previous included EGW_API_INC/horde/Horde/String.php causes
- // include_once('Horde/String.php') to return true, even if the former was included with an absolute path
- // only use include_path, if no Composer vendor directory exists
- !isset($GLOBALS['egw_info']['apps'][$app]) && !file_exists(EGW_SERVER_ROOT.'/vendor') &&
- @include($file = strtr($class, array('_'=>'/','\\'=>'/')).'.php'))
- {
- include_once($file);
- //if (!class_exists($class, false) && !interface_exists($class, false)) error_log("autoloading class $class by include_once($file) failed!");
- }
- // allow apps to define an own autoload method
- elseif (isset($GLOBALS['egw_info']['flags']['autoload']) && is_callable($GLOBALS['egw_info']['flags']['autoload']))
- {
- call_user_func($GLOBALS['egw_info']['flags']['autoload'],$class);
- }
-});
-
-// if we have a Composer vendor directory, also load it's autoloader, to allow manage our requirements with Composer
-if (file_exists(EGW_SERVER_ROOT.'/vendor'))
-{
- require_once EGW_SERVER_ROOT.'/vendor/autoload.php';
-}
+require_once dirname(__DIR__).'/autoload.php';
/**
* applies stripslashes recursivly on each element of an array
@@ -267,7 +179,7 @@
{
return array((object)array(
'text' => Horde_Mime::decode($text),
- 'charset' => translation::charset(), // is already in our internal encoding!
+ 'charset' => Api\Translation::charset(), // is already in our internal encoding!
));
}
}
@@ -352,804 +264,10 @@
return $loaded;
}
-/**
- * @internal Not to be used directly. Should only be used by print_debug()
- */
-function print_debug_subarray($array)
-{
- foreach($array as $key => $value)
- {
- if (is_array($value))
- {
- $vartypes[$key] = print_debug_subarray($value);
- }
- else
- {
- $vartypes[$key] = gettype($value);
- }
- }
- return $vartypes;
-}
-
-/**
- * print debug data only when debugging mode is turned on.
- *
- * @author seek3r
- * This function is used to debugging data.
- * print_debug('this is some debugging data',$somevar);
- */
-function print_debug($message,$var = 'messageonly',$part = 'app', $level = 3)
-{
- if (($part == 'app' && DEBUG_APP == True) || ($part == 'api' && DEBUG_API == True))
- {
- if (!defined('DEBUG_OUTPUT'))
- {
- define('DEBUG_OUTPUT', 1);
- }
- if ($level >= DEBUG_LEVEL)
- {
- if (!is_array($var))
- {
- if ($var != 'messageonly')
- {
- if (!DEBUG_DATATYPES)
- {
- $output = "$message\n$var";
- }
- else
- {
- $output = "$message\n$var is a ".gettype($var);
- }
- }
- else
- {
- $output = $message;
- }
-
- /* Bit 1 means to output to screen */
- if (!!(DEBUG_OUTPUT & 1))
- {
- echo "$output<br>\n";
- }
- /* Bit 2 means to output to sql */
- if (!!(DEBUG_OUTPUT & 2))
- {
- /* Need to flesh this out still. I dont have a table to dump this in yet.*/
- /* So the SQL statement will go here*/
- }
-
- /* Example of how this can be extended to output to other locations as well. This example uses a COM object */
- /*
- if (!!(DEBUG_OUTPUT & 32))
- {
- $obj_debug = new COM('Some_COM_App.Class','localhost');
- if (is_object($obj_debug))
- {
- $DebugMessage_return = $obj_debug->DebugMessage($output);
- }
- }
- */
- }
- else
- {
- if (floor(phpversion()) > 3 && !!(DEBUG_OUTPUT & 2))
- {
- ob_start();
- }
- echo "<pre>\n$message\n";
- print_r($var);
- if (DEBUG_DATATYPES)
- {
- foreach($var as $key => $value)
- {
- if (is_array($value))
- {
- $vartypes[$key] = print_debug_subarray($value);
- }
- else
- {
- $vartypes[$key] = gettype($value);
- }
- }
- echo "Data Types:\n";
- print_r($vartypes);
- }
- echo "\n<pre>\n";
- if (floor(phpversion()) > 3 && !!(DEBUG_OUTPUT & 2))
- {
- $output .= ob_get_contents();
- ob_end_clean();
- /* Need to flesh this out still. I dont have a table to dump this in yet.*/
- /* So the SQL statement will go here*/
- if (!!(DEBUG_OUTPUT & 1))
- {
- echo "$output<br>\n";
- }
- }
- }
- }
- }
-}
-
-/**
- * Allows for array and direct function params as well as sanatization.
- *
- * @author seek3r
- * This function is used to validate param data as well as offer flexible function usage.
- *
- function somefunc()
- {
- $expected_args[0] = Array('name'=>'fname','default'=>'joe', 'type'=>'string');
- $expected_args[1] = Array('name'=>'mname','default'=>'hick', 'type'=>'string');
- $expected_args[2] = Array('name'=>'lname','default'=>'bob', 'type'=>'string');
- $recieved_args = func_get_args();
- $args = safe_args($expected_args, $recieved_args,__LINE__,__FILE__);
- echo 'Full name: '.$args['fname'].' '.$args['fname'].' '.$args['lname'].'<br>';
- //default result would be:
- // Full name: joe hick bob<br>
- }
-
- Using this it is possible to use the function in any of the following ways
- somefunc('jack','city','brown');
- or
- somefunc(array('fname'=>'jack','mname'=>'city','lname'=>'brown'));
- or
- somefunc(array('lname'=>'brown','fname'=>'jack','mname'=>'city'));
-
- For the last one, when using named params in an array you dont have to follow any order
- All three would result in - Full name: jack city brown<br>
-
- When you use this method of handling params you can secure your functions as well offer
- flexibility needed for both normal use and web services use.
- If you have params that are required just set the default as ##REQUIRED##
- Users of your functions can also use ##DEFAULT## to use your default value for a param
- when using the standard format like this:
- somefunc('jack','##DEFAULT##','brown');
- This would result in - Full name: jack hick brown<br>
- Its using the default value for the second param.
- Of course if you have the second param as a required field it will fail to work.
- */
-function safe_args($expected, $recieved, $line='??', $file='??')
-{
- /* This array will contain all the required fields */
- $required = Array();
-
- /* This array will contain all types for sanatization checking */
- /* only used when an array is passed as the first arg */
- $types = Array();
-
- /* start by looping thru the expected list and set params with */
- /* the default values */
- $num = count($expected);
- for ($i = 0; $i < $num; $i++)
- {
- $args[$expected[$i]['name']] = $expected[$i]['default'];
- if ($expected[$i]['default'] === '##REQUIRED##')
- {
- $required[$expected[$i]['name']] = True;
- }
- $types[$expected[$i]['name']] = $expected[$i]['type'];
- }
-
- /* Make sure they passed at least one param */
- if(count($recieved) != 0)
- {
- /* if used as standard function we loop thru and set by position */
- if(!is_array($recieved[0]))
- {
- for ($i = 0; $i < $num; $i++)
- {
- if(isset($recieved[$i]) && $recieved[$i] !== '##DEFAULT##')
- {
- if(sanitize($recieved[$i],$expected[$i]['type']))
- {
- $args[$expected[$i]['name']] = $recieved[$i];
- unset($required[$expected[$i]['name']]);
- }
- else
- {
- echo 'Fatal Error: Invalid paramater type for '.$expected[$i]['name'].' on line '.$line.' of '.$file.'<br>';
- exit;
- }
- }
- }
- }
- /* if used as standard function we loop thru and set by position */
- else
- {
- for ($i = 0; $i < $num; $i++)
- {
- $types[$expected[$i]['name']] = $expected[$i]['type'];
- }
- while(list($key,$val) = each($recieved[0]))
- {
- if($val !== '##DEFAULT##')
- {
- if(sanitize($val,$types[$key]) == True)
- {
- $args[$key] = $val;
- unset($required[$key]);
- }
- else
- {
- echo 'Fatal Error: Invalid paramater type for '.$key.' on line '.$line.' of '.$file.'<br>';
- exit;
- }
- }
- }
- }
- }
- if(count($required) != 0)
- {
- while (list($key) = each($required))
- {
- echo 'Fatal Error: Missing required paramater '.$key.' on line '.$line.' of '.$file.'<br>';
- }
- exit;
- }
- return $args;
-}
-
-/**
- * Validate data.
- *
- * @author seek3r
- * This function is used to validate input data.
- * sanitize('number',$somestring);
- */
-function sanitize($string,$type)
-{
- switch ($type)
- {
- case 'bool':
- if ($string == 1 || $string == 0)
- {
- return True;
- }
- break;
-
- case 'isprint':
- $length = strlen($string);
- $position = 0;
- while ($length > $position)
- {
- $char = substr($string, $position, 1);
- if ($char < ' ' || $char > '~')
- {
- return False;
- }
- $position = $position + 1;
- }
- return True;
-
- case 'alpha':
- if (preg_match("/^[a-z]+$/i", $string))
- {
- return True;
- }
- break;
-
- case 'number':
- if (preg_match("/^[0-9]+$/i", $string))
- {
- return True;
- }
- break;
-
- case 'alphanumeric':
- if (preg_match("/^[a-z0-9 -._]+$/i", $string))
- {
- return True;
- }
- break;
- case 'string':
- if (preg_match("/^[a-z]+$/i", $string))
- {
- return True;
- }
- break;
- case 'ip':
- if (preg_match('/'."^[0-9]{1,3}(\.[0-9]{1,3}){3}$".'/i',$string))
- {
- $octets = preg_split('/\./',$string);
- for ($i=0; $i != count($octets); $i++)
- {
- if ($octets[$i] < 0 || $octets[$i] > 255)
- {
- return False;
- }
- }
- return True;
- }
- return False;
-
- case 'file':
- if (preg_match("/^[a-z0-9_]+\.+[a-z]+$/i", $string))
- {
- return True;
- }
- break;
- case 'email':
- if (preg_match('/'."^([[:alnum:]_%+=.-]+)@([[:alnum:]_.-]+)\.([a-z]{2,3}|[0-9]{1,3})$".'/i',$string))
- {
- return True;
- }
- break;
- case 'password':
- $password_length = strlen($string);
- $password_numbers = Array('0','1','2','3','4','5','6','7','8','9');
- $password_special_chars = Array(' ','~','`','!','@','#','$','%','^','&','*','(',')','_','+','-','=','{','}','|','[',']',"\\",':','"',';',"'",'<','>','?',',','.','/');
-
- if(@isset($GLOBALS['egw_info']['server']['pass_min_length']) && is_int($GLOBALS['egw_info']['server']['pass_min_length']) && $GLOBALS['egw_info']['server']['pass_min_length'] > 1)
- {
- $min_length = $GLOBALS['egw_info']['server']['pass_min_length'];
- }
- else
- {
- $min_length = 1;
- }
-
- if(@isset($GLOBALS['egw_info']['server']['pass_require_non_alpha']) && $GLOBALS['egw_info']['server']['pass_require_non_alpha'] == True)
- {
- $pass_verify_non_alpha = False;
- }
- else
- {
- $pass_verify_non_alpha = True;
- }
-
- if(@isset($GLOBALS['egw_info']['server']['pass_require_numbers']) && $GLOBALS['egw_info']['server']['pass_require_numbers'] == True)
- {
- $pass_verify_num = False;
- }
- else
- {
- $pass_verify_num = True;
- }
-
- if(@isset($GLOBALS['egw_info']['server']['pass_require_special_char']) && $GLOBALS['egw_info']['server']['pass_require_special_char'] == True)
- {
- $pass_verify_special_char = False;
- }
- else
- {
- $pass_verify_special_char = True;
- }
-
- if ($password_length >= $min_length)
- {
- for ($i=0; $i != $password_length; $i++)
- {
- $cur_test_string = substr($string, $i, 1);
- if (in_array($cur_test_string, $password_numbers) || in_array($cur_test_string, $password_special_chars))
- {
- $pass_verify_non_alpha = True;
- if (in_array($cur_test_string, $password_numbers))
- {
- $pass_verify_num = True;
- }
- elseif (in_array($cur_test_string, $password_special_chars))
- {
- $pass_verify_special_char = True;
- }
- }
- }
-
- if ($pass_verify_num == False)
- {
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password requires at least one non-alpha character']=False;
- }
-
- if ($pass_verify_num == False)
- {
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password requires at least one numeric character']=False;
- }
-
- if ($pass_verify_special_char == False)
- {
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password requires at least one special character (non-letter and non-number)']=False;
- }
-
- if ($pass_verify_num == True && $pass_verify_special_char == True)
- {
- return True;
- }
- return False;
- }
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password must be at least '.$min_length.' characters']=False;
- return False;
-
- case 'any':
- return True;
-
- default :
- if (isset($GLOBALS['egw_info']['server']['sanitize_types'][$type]['type']))
- {
- if ($GLOBALS['egw_info']['server']['sanitize_types'][$type]['type']($GLOBALS['egw_info']['server']['sanitize_types'][$type]['string'], $string))
- {
- return True;
- }
- }
- return False;
- }
-}
-
-function reg_var($varname, $method='any', $valuetype='alphanumeric',$default_value='',$register=True)
-{
- if($method == 'any' || $method == array('any'))
- {
- $method = Array('POST','GET','COOKIE','SERVER','FILES','GLOBAL','DEFAULT');
- }
- elseif(!is_array($method))
- {
- $method = Array($method);
- }
- $cnt = count($method);
- for($i=0;$i<$cnt;$i++)
- {
- switch(strtoupper($method[$i]))
- {
- case 'DEFAULT':
- if($default_value)
- {
- $value = $default_value;
- $i = $cnt+1; /* Found what we were looking for, now we end the loop */
- }
- break;
- case 'GLOBAL':
- if(@isset($GLOBALS[$varname]))
- {
- $value = $GLOBALS[$varname];
- $i = $cnt+1;
- }
- break;
- case 'POST':
- case 'GET':
- case 'COOKIE':
- case 'SERVER':
- if(phpversion() >= '4.1.0')
- {
- $meth = '_'.strtoupper($method[$i]);
- }
- else
- {
- $meth = 'HTTP_'.strtoupper($method[$i]).'_VARS';
- }
- if(@isset($GLOBALS[$meth][$varname]))
- {
- $value = $GLOBALS[$meth][$varname];
- $i = $cnt+1;
- }
- if(get_magic_quotes_gpc() && isset($value))
- {
- // we need to stripslash 3 levels of arrays
- // because of the password function in preferences
- // it's named ['user']['variablename']['pw']
- // or something like this in projects
- // $values['budgetBegin']['1']['year']
- if(@is_array($value))
- {
- /* stripslashes on the first level of array values */
- foreach($value as $name => $val)
- {
- if(@is_array($val))
- {
- foreach($val as $name2 => $val2)
- {
- if(@is_array($val2))
- {
- foreach($val2 as $name3 => $val3)
- {
- $value[$name][$name2][$name3] = stripslashes($val3);
- }
- }
- else
- {
- $value[$name][$name2] = stripslashes($val2);
- }
- }
- }
- else
- {
- $value[$name] = stripslashes($val);
- }
- }
- }
- else
- {
- /* stripslashes on this (string) */
- $value = stripslashes($value);
- }
- }
- break;
- case 'FILES':
- if(phpversion() >= '4.1.0')
- {
- $meth = '_FILES';
- }
- else
- {
- $meth = 'HTTP_POST_FILES';
- }
- if(@isset($GLOBALS[$meth][$varname]))
- {
- $value = $GLOBALS[$meth][$varname];
- $i = $cnt+1;
- }
- break;
- default:
- if(@isset($GLOBALS[strtoupper($method[$i])][$varname]))
- {
- $value = $GLOBALS[strtoupper($method[$i])][$varname];
- $i = $cnt+1;
- }
- break;
- }
- }
-
- if (@!isset($value))
- {
- $value = $default_value;
- }
-
- if (@!is_array($value))
- {
- if ($value == '')
- {
- $result = $value;
- }
- else
- {
- if (sanitize($value,$valuetype) == 1)
- {
- $result = $value;
- }
- else
- {
- $result = $default_value;
- }
- }
- }
- else
- {
- reset($value);
- while(list($k, $v) = each($value))
- {
- if ($v == '')
- {
- $result[$k] = $v;
- }
- else
- {
- if (is_array($valuetype))
- {
- $vt = $valuetype[$k];
- }
- else
- {
- $vt = $valuetype;
- }
-
- if (sanitize($v,$vt) == 1)
- {
- $result[$k] = $v;
- }
- else
- {
- if (is_array($default_value))
- {
- $result[$k] = $default_value[$k];
- }
- else
- {
- $result[$k] = $default_value;
- }
- }
- }
- }
- }
- if($register)
- {
- $GLOBALS['egw_info'][$GLOBALS['egw_info']['flags']['currentapp']][$varname] = $result;
- }
- return $result;
-}
-
-/**
- * retrieve a value from either a POST, GET, COOKIE, SERVER or from a class variable.
- *
- * @author skeeter
- * This function is used to retrieve a value from a user defined order of methods.
- * $this->id = get_var('id',array('HTTP_POST_VARS'||'POST','HTTP_GET_VARS'||'GET','HTTP_COOKIE_VARS'||'COOKIE','GLOBAL','DEFAULT'));
- * @param $variable name
- * @param $method ordered array of methods to search for supplied variable
- * @param $default_value (optional)
- */
-function get_var($variable,$method='any',$default_value='')
-{
- if(!@is_array($method))
- {
- $method = array($method);
- }
- return reg_var($variable,$method,'any',$default_value,False);
-}
-
-/**
- * Load a class and include the class file if not done so already.
- *
- * This function is used to create an instance of a class, and if the class file has not been included it will do so.
- * $GLOBALS['egw']->acl =& CreateObject('phpgwapi.acl');
- *
- * @author [email protected]
- * @param $classname name of class
- * @param $p1,$p2,... class parameters (all optional)
- * @return object reference to an object
- */
-function CreateObject($class)
-{
- list($appname,$classname) = explode('.',$class);
-
- if (!class_exists($classname))
- {
- static $replace = array(
- 'datetime' => 'egw_datetime',
- 'uitimesheet' => 'timesheet_ui',
- 'uiinfolog' => 'infolog_ui',
- 'uiprojectmanager' => 'projectmanager_ui',
- 'uiprojectelements' => 'projectmanager_elements_ui',
- 'uiroles' => 'projectmanager_roles_ui',
- 'uimilestones' => 'projectmanager_milestones_ui',
- 'uipricelist' => 'projectmanager_pricelist_ui',
- 'bowiki' => 'wiki_bo',
- 'uicategories' => 'admin_categories',
- 'defaultimap' => 'emailadmin_oldimap',
- );
- if (!file_exists(EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php') || isset($replace[$classname]))
- {
- if (isset($replace[$classname]))
- {
- //throw new Exception(__METHOD__."('$class') old classname '$classname' used in menuaction=$_GET[menuaction]!");
- error_log(__METHOD__."('$class') old classname '$classname' used in menuaction=$_GET[menuaction]!");
- $classname = $replace[$classname];
- }
- }
- if (!file_exists($f=EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php'))
- {
- throw new Api\Exception\AssertionFailed(__FUNCTION__."($classname) file $f not found!");
- }
- // this will stop php with a 500, if the class does not exist or there are errors in it (syntax error go into the error_log)
- require_once(EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php');
- }
- $args = func_get_args();
- switch(count($args))
- {
- case 1:
- $obj = new $classname;
- break;
- case 2:
- $obj = new $classname($args[1]);
- break;
- case 3:
- $obj = new $classname($args[1],$args[2]);
- break;
- case 4:
- $obj = new $classname($args[1],$args[2],$args[3]);
- break;
- default:
- $code = '$obj = new ' . $classname . '(';
- foreach(array_keys($args) as $n)
- {
- if ($n)
- {
- $code .= ($n > 1 ? ',' : '') . '$args[' . $n . ']';
- }
- }
- $code .= ');';
- eval($code);
- break;
- }
- if (!is_object($obj))
- {
- echo "<p>CreateObject('$class'): Cant instanciate class!!!<br />\n".function_backtrace(1)."</p>\n";
- }
- return $obj;
-}
-
-/**
- * Execute a function with multiple arguments
- * We take object $GLOBALS[classname] from class if exists
- *
- * @param string app.class.method method to execute
- * @example ExecObject('etemplates.so_sql.search',$criteria,$key_only,...);
- * @return mixed reference to returnvalue of the method
- */
-function &ExecMethod2($acm)
-{
- // class::method is php5.2.3+
- if (strpos($acm,'::') !== false && version_compare(PHP_VERSION,'5.2.3','<'))
- {
- list($class,$method) = explode('::',$acm);
- $acm = array($class,$method);
- }
- if (!is_callable($acm))
- {
- list(,$class,$method) = explode('.',$acm);
- if (!is_object($obj =& $GLOBALS[$class]))
- {
- if (class_exists($class))
- {
- $obj = new $class;
- }
- else
- {
- $obj = CreateObject($acm);
- }
- }
-
- if (!method_exists($obj,$method))
- {
- echo "<p><b>".function_backtrace()."</b>: no methode '$method' in class '$class'</p>\n";
- return False;
- }
- $acm = array($obj,$method);
- }
- $args = func_get_args();
- unset($args[0]);
-
- return call_user_func_array($acm,$args);
-}
-
-/**
- * Execute a function, and load a class and include the class file if not done so already.
- *
- * This function is used to create an instance of a class, and if the class file has not been included it will do so.
- *
- * @author seek3r
- * @param $method to execute
- * @param $functionparam function param should be an array
- * @param $loglevel developers choice of logging level
- * @param $classparams params to be sent to the contructor
- * @return mixed returnvalue of method
- */
-function ExecMethod($method, $functionparam = '_UNDEF_', $loglevel = 3, $classparams = '_UNDEF_')
-{
- unset($loglevel); // not used
- /* Need to make sure this is working against a single dimensional object */
- $partscount = count(explode('.',$method)) - 1;
-
- if (!is_callable($method) && $partscount == 2)
- {
- list($appname,$classname,$functionname) = explode(".", $method);
- if (!is_object($GLOBALS[$classname]))
- {
- // please note: no reference assignment (=&) here, as $GLOBALS is a reference itself!!!
- if ($classparams != '_UNDEF_' && ($classparams || $classparams != 'True'))
- {
- $GLOBALS[$classname] = CreateObject($appname.'.'.$classname, $classparams);
- }
- elseif (class_exists($classname))
- {
- $GLOBALS[$classname] = new $classname;
- }
- else
- {
- $GLOBALS[$classname] = CreateObject($appname.'.'.$classname);
- }
- }
-
- if (!method_exists($GLOBALS[$classname],$functionname))
- {
- error_log("ExecMethod('$method', ...) No methode '$functionname' in class '$classname'! ".function_backtrace());
- return false;
- }
- $method = array($GLOBALS[$classname],$functionname);
- }
- if (is_callable($method))
- {
- return $functionparam != '_UNDEF_' ? call_user_func($method,$functionparam) : call_user_func($method);
- }
- error_log("ExecMethod('$method', ...) Error in parts! ".function_backtrace());
- return false;
+// include deprecated global functions, if phpgwapi is installed
+if (file_exists(EGW_SERVER_ROOT.'/phpgwapi'))
+{
+ include_once EGW_SERVER_ROOT.'/phpgwapi/inc/deprecated_functions.inc.php';
}
/**
@@ -1194,31 +312,6 @@
}
/**
- * sets the file system seperator depending on OS
- *
- * This is completely unnecessary, as you can use forward slashes in php under every OS -- RalfBecker 2005/11/09
- *
- * @deprecated just use forward slashes supported by PHP on all OS
- * @return file system separator
- */
-function filesystem_separator()
-{
- if(PHP_OS == 'Windows' || PHP_OS == 'OS/2' || PHP_OS == 'WINNT')
- {
- return '\\';
- }
- else
- {
- return '/';
- }
-}
-
-/**
- * @deprecated just use forward slashes supported by PHP on all OS
- */
-define('SEP', filesystem_separator());
-
-/**
* print an array or object as pre-formatted html
*
* @param mixed $array
@@ -1237,191 +330,6 @@
{
return $output;
}
-}
-
-/**
- * eGW version checking, is eGW version in $a < $b
- *
- * @param string $a egw version number to check if less than $b
- * @param string $b egw version number to check $a against
- * @return boolean True if $a < $b
- */
-function alessthanb($a,$b,$DEBUG=False)
-{
- $num = array('1st','2nd','3rd','4th');
-
- if ($DEBUG)
- {
- echo'<br>Input values: ' . 'A="'.$a.'", B="'.$b.'"';
- }
- $newa = str_replace('pre','.',$a);
- $newb = str_replace('pre','.',$b);
- $testa = explode('.',$newa);
- if(@$testa[1] == '')
- {
- $testa[1] = 0;
- }
- if(@$testa[3] == '')
- {
- $testa[3] = 0;
- }
- $testb = explode('.',$newb);
- if(@$testb[1] == '')
- {
- $testb[1] = 0;
- }
- if(@$testb[3] == '')
- {
- $testb[3] = 0;
- }
- $less = 0;
-
- for ($i=0;$i<count($testa);$i++)
- {
- if ($DEBUG) { echo'<br>Checking if '. (int)$testa[$i] . ' is less than ' . (int)$testb[$i] . ' ...'; }
- if ((int)$testa[$i] < (int)$testb[$i])
- {
- if ($DEBUG) { echo ' yes.'; }
- $less++;
- if ($i<3)
- {
- /* Ensure that this is definitely smaller */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely less than B."; }
- $less = 5;
- break;
- }
- }
- elseif((int)$testa[$i] > (int)$testb[$i])
- {
- if ($DEBUG) { echo ' no.'; }
- $less--;
- if ($i<2)
- {
- /* Ensure that this is definitely greater */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely greater than B."; }
- $less = -5;
- break;
- }
- }
- else
- {
- if ($DEBUG) { echo ' no, they are equal.'; }
- $less = 0;
- }
- }
- if ($DEBUG) { echo '<br>Check value is: "'.$less.'"'; }
- if ($less>0)
- {
- if ($DEBUG) { echo '<br>A is less than B'; }
- return True;
- }
- elseif($less<0)
- {
- if ($DEBUG) { echo '<br>A is greater than B'; }
- return False;
- }
- else
- {
- if ($DEBUG) { echo '<br>A is equal to B'; }
- return False;
- }
-}
-
-/**
- * eGW version checking, is eGW version in $a > $b
- *
- * @param string $a eGW version number to check if more than $b
- * @param string $b eGW version number to check check $a against
- * @return boolean True if $a > $b
- */
-function amorethanb($a,$b,$DEBUG=False)
-{
- $num = array('1st','2nd','3rd','4th');
-
- if ($DEBUG)
- {
- echo'<br>Input values: ' . 'A="'.$a.'", B="'.$b.'"';
- }
- $newa = str_replace('pre','.',$a);
- $newb = str_replace('pre','.',$b);
- $testa = explode('.',$newa);
- if($testa[3] == '')
- {
- $testa[3] = 0;
- }
- $testb = explode('.',$newb);
- if($testb[3] == '')
- {
- $testb[3] = 0;
- }
- $less = 0;
-
- for ($i=0;$i<count($testa);$i++)
- {
- if ($DEBUG) { echo'<br>Checking if '. (int)$testa[$i] . ' is more than ' . (int)$testb[$i] . ' ...'; }
- if ((int)$testa[$i] > (int)$testb[$i])
- {
- if ($DEBUG) { echo ' yes.'; }
- $less++;
- if ($i<3)
- {
- /* Ensure that this is definitely greater */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely greater than B."; }
- $less = 5;
- break;
- }
- }
- elseif((int)$testa[$i] < (int)$testb[$i])
- {
- if ($DEBUG) { echo ' no.'; }
- $less--;
- if ($i<2)
- {
- /* Ensure that this is definitely smaller */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely less than B."; }
- $less = -5;
- break;
- }
- }
- else
- {
- if ($DEBUG) { echo ' no, they are equal.'; }
- $less = 0;
- }
- }
- if ($DEBUG) { echo '<br>Check value is: "'.$less.'"'; }
- if ($less>0)
- {
- if ($DEBUG) { echo '<br>A is greater than B'; }
- return True;
- }
- elseif($less<0)
- {
- if ($DEBUG) { echo '<br>A is less than B'; }
- return False;
- }
- else
- {
- if ($DEBUG) { echo '<br>A is equal to B'; }
- return False;
- }
-}
-
-/**
- * prepend a prefix to an array of table names
- *
- * @author Adam Hull (aka fixe) - No copyright claim
- * @param $prefix the string to be prepended
- * @param $tables and array of tables to have the prefix prepended to
- * @return array of table names with the prefix prepended
- */
-function prepend_tables_prefix($prefix,$tables)
-{
- foreach($tables as $key => $value)
- {
- $tables[$key] = $prefix.$value;
- }
- return $tables;
}
/**
@@ -1455,218 +363,6 @@
return $_GET['menuaction'] ? $_GET['menuaction'] : str_replace(EGW_SERVER_ROOT,'',$_SERVER['SCRIPT_FILENAME']);
}
-/**
- * check $_REQUEST data for XSS, vars containing script tags are moved to $GLOBALS['egw_unset_vars']
- *
- * @internal
- * @param array &$var reference of array to check
- * @param string $name ='' name of the array
- */
-function _check_script_tag(&$var,$name='')
-{
- static $preg=null;
- //old: '/<\/?[^>]*\b(iframe|script|javascript|on(before)?(abort|blur|change|click|dblclick|error|focus|keydown|keypress|keyup|load|mousedown|mousemove|mouseout|mouseover|mouseup|reset|select|submit|unload))\b[^>]*>/i';
- if (!isset($preg)) $preg =
- // forbidden tags like iframe or script
- '/(<(\s*\/)?\s*(iframe|script|object|embed|math|meta)[^a-z0-9]|'.
- // on* attributes
- '<[^>]*on(before)?(abort|blur|change|click|dblclick|error|focus|keydown|keypress|keyup|load|mouse[^=]+|reset|select|submit|unload|resize|propertychange|page[^=]*|scroll|readystatechange|start|popstate|form[^=]+|input)\s*=|'.
- // ="javascript:*" diverse javascript attribute value
- '<[^>]+(href|src|dynsrc|lowsrc|background|style|poster|action)\s*=\s*("|\')?[^"\']*javascript|'.
- // benavior:url and expression in style attribute
- '<[^>]+style\s*=\s*("|\')[^>]*(behavior\s*:\s*url|expression)\s*\()/i';
- if (is_array($var))
- {
- foreach($var as $key => $val)
- {
- if (is_array($val))
- {
- _check_script_tag($var[$key],$name.'['.$key.']');
- }
- elseif(strpos($val, '<') !== false) // speedup: ignore everything without <
- {
- if (preg_match($preg,$val))
- {
- // special handling for $_POST[json_data], to decend into it's decoded content, fixing json direct might break json syntax
- if ($name == '_POST' && $key == 'json_data' && ($json_data = json_decode($val, true)))
- {
- _check_script_tag($json_data, $name.'[json_data]');
- $_REQUEST[$key] = $var[$key] = json_encode($json_data);
- continue;
- }
- error_log(__FUNCTION__."(,$name) ${name}[$key] = ".$var[$key]);
- $GLOBALS['egw_unset_vars'][$name.'['.$key.']'] = $var[$key];
- // attempt to clean the thing
- $var[$key] = $val = html::purify($val);
- // check if we succeeded, if not drop the var anyway, keep the egw_unset_var in any case
- if (preg_match($preg,$val))
- {
- error_log("*** _check_script_tag($name): unset(${name}[$key]) with value $val***");
- unset($var[$key]);
- }
- }
- }
- }
- // in case some stupid old code expects the array-pointer to be at the start of the array
- reset($var);
- }
-}
-
-/* some _check_script_tag tests, should be commented out by default
-if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__) // some tests
-{
- if (!defined('EGW_INCLUDE_ROOT'))
- {
- define(EGW_INCLUDE_ROOT, realpath(dirname(__FILE__).'/../..'));
- define(EGW_API_INC, realpath(dirname(__FILE__)));
- }
-
- $total = $num_failed = 0;
- $patterns = array(
- // pattern => true: should fail, false: should not fail
- '< script >alert(1)< / script >' => true,
- '<span onMouseOver ="alert(1)">blah</span>' => true,
- '<a href= "JaVascript: alert(1)">Click Me</a>' => true,
- // from https://www.acunetix.com/websitesecurity/cross-site-scripting/
- '<body onload=alert("XSS")>' => true,
- '<body background="javascript:alert("XSS")">' => true,
- '<iframe src=âhttp://evil.com/xss.htmlâ>' => true,
- '<input type="image" src="javascript:alert(\'XSS\');">' => true,
- '<link rel="stylesheet" href="javascript:alert(\'XSS\');">' => true,
- '<table background="javascript:alert(\'XSS\')">' => true,
- '<td background="javascript:alert(\'XSS\')">' => true,
- '<div style="background-image: url(javascript:alert(\'XSS\'))">' => true,
- '<div style="width: expression(alert(\'XSS\'));">' => true,
- '<object type="text/x-scriptlet" data="http://hacker.com/xss.html">' => true,
- // false positiv tests
- 'If 1 < 2, what does that mean for description, if 2 > 1.' => false,
- 'If 1 < 2, what does that mean for a script, if 2 > 1.' => false,
- '<div>Script and Javascript: not evil ;-)' => false,
- '<span>style=background-color' => false,
- '<font face="Script MT Bold" size="4"><span style="font-size:16pt;">Hugo Sonstwas</span></font>' => false,
- '<[email protected]>' => false,
- );
- foreach($patterns as $pattern => $should_fail)
- {
- $test = array($pattern);
- unset($GLOBALS['egw_unset_vars']);
- _check_script_tag($test,'test');
- $failed = isset($GLOBALS['egw_unset_vars']) !== $should_fail;
- ++$total;
- if ($failed) $num_failed++;
- echo "<p style='color: ".($failed?'red':'black')."'> ".html::htmlspecialchars($pattern).' '.
- (isset($GLOBALS['egw_unset_vars'])?'removed':'passed')."</p>";
- }
- $x = 1;
- // urls with attack vectors
- $urls = array(
- // we currently fail 76 of 666 test, thought they seem not to apply to our use case, as we check request data
- 'https://gist.github.com/JohannesHoppe/5612274' => file(
- 'https://gist.githubusercontent.com/JohannesHoppe/5612274/raw/60016bccbfe894dcd61a6be658a4469e403527de/666_lines_of_XSS_vectors.html'),
- // we currently fail 44 of 140 tests, thought they seem not to apply to our use case, as we check request data
- 'https://html5sec.org/' => call_user_func(function() {
- $payloads = $items = null;
- if (!($items_js = file_get_contents('https://html5sec.org/items.js')) ||
- !preg_match_all("|^\s+'data'\s+:\s+'(.*)',$|m", $items_js, $items, PREG_PATTERN_ORDER) ||
- !($payload_js = file_get_contents('https://html5sec.org/payloads.js')) ||
- !preg_match_all("|^\s+'([^']+)'\s+:\s+'(.*)',$|m", $payload_js, $payloads, PREG_PATTERN_ORDER))
- {
- return false;
- }
- $replace = array(
- "\\'" => "'",
- '\\\\'=> '\\,',
- '\r' => "\r",
- '\n' => "\n",
- );
- foreach($payloads[1] as $n => $from) {
- $replace['%'.$from.'%'] = $payloads[2][$n];
- }
- return array_map(function($item) use ($replace) {
- return strtr($item, $replace);
- }, $items[1]);
- }),
- );
- foreach($urls as $url => $vectors)
- {
- // no all xss attack vectors from http://ha.ckers.org/xssAttacks.xml are relevant here! (needs interpretation)
- if (!$vectors)
- {
- echo "<p style='color:red'>Could NOT download or parse $url with attack vectors!</p>\n";
- continue;
- }
- echo "<p><b>Attacks from <a href='$url' target='_blank'>$url</a> with ".count($vectors)." tests:</b></p>";
- foreach($vectors as $line => $pattern)
- {
- $test = array($pattern);
- unset($GLOBALS['egw_unset_vars']);
- _check_script_tag($test, 'line '.(1+$line));
- $failed = !isset($GLOBALS['egw_unset_vars']);
- ++$total;
- if ($failed) $num_failed++;
- echo "<p style='color: ".($failed?'red':'black')."'>".(1+$line).": ".html::htmlspecialchars($pattern).' '.
- (isset($GLOBALS['egw_unset_vars'])?'removed':'passed')."</p>";
- }
- }
- die("<p style='color: ".($num_failed?'red':'black')."'>Tests finished: $num_failed / $total failed</p>");
-}*/
-
-foreach(array('_GET','_POST','_REQUEST','HTTP_GET_VARS','HTTP_POST_VARS') as $n => $where)
-{
- $pregs = array(
- 'order' => '/^[a-zA-Z0-9_,]*$/',
- 'sort' => '/^(ASC|DESC|asc|desc|0|1|2|3|4|5|6|7){0,1}$/',
- );
- foreach(array('order','sort') as $name)
- {
- if (isset($GLOBALS[$where][$name]) && !is_array($GLOBALS[$where][$name]) && !preg_match($pregs[$name],$GLOBALS[$where][$name]))
- {
- $GLOBALS[$where][$name] = '';
- }
- }
- // do the check for script-tags only for _GET and _POST or if we found something in _GET and _POST
- // speeds up the execusion a bit
- if (isset($GLOBALS[$where]) && is_array($GLOBALS[$where]) && ($n < 2 || isset($GLOBALS['egw_unset_vars'])))
- {
- _check_script_tag($GLOBALS[$where],$where);
- }
-}
-//if (is_array($GLOBALS['egw_unset_vars'])) { echo "egw_unset_vars=<pre>".htmlspecialchars(print_r($GLOBALS['egw_unset_vars'],true))."</pre>"; exit; }
-
-// $GLOBALS[egw_info][flags][currentapp] and die if it contains something nasty or unexpected
-if (isset($GLOBALS['egw_info']) && isset($GLOBALS['egw_info']['flags']) &&
- isset($GLOBALS['egw_info']['flags']['currentapp']) && !preg_match('/^[A-Za-z0-9_-]+$/',$GLOBALS['egw_info']['flags']['currentapp']))
-{
- error_log(__FILE__.': '.__LINE__.' Invalid $GLOBALS[egw_info][flags][currentapp]='.array2string($GLOBALS['egw_info']['flags']['currentapp']).', $_SERVER[REQUEST_URI]='.array2string($_SERVER[REQUEST_URI]));
- die('Invalid $GLOBALS[egw_info][flags][currentapp]!');
-}
-
-// neutralises register_globals On, which is not used by eGW
-// some code from the hardend php project: http://www.hardened-php.net/articles/PHPUG-PHP-Sicherheit-Parametermanipulationen.pdf
-if (ini_get('register_globals'))
-{
- function unregister_globals()
- {
- // protect against GLOBALS overwrite or setting egw_info
- if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS']) || isset($_REQUEST['egw_info']) || isset($_FILES['egw_info']))
- {
- die('GLOBALS overwrite detected!!!');
- }
- // unregister all globals
- $noUnset = array('GLOBALS','_GET','_POST','_COOKIE','_SERVER','_ENV','_FILES','xajax');
- foreach(array_unique(array_merge(
- array_keys($_GET),array_keys($_POST),array_keys($_COOKIE),array_keys($_SERVER),array_keys($_ENV),array_keys($_FILES),
- isset($_SESSION) && is_array($_SESSION) ? array_keys($_SESSION) : array())) as $k)
- {
- if (!in_array($k,$noUnset) && isset($GLOBALS[$k]))
- {
- unset($GLOBALS[$k]);
- }
- }
- }
- unregister_globals();
-}
-
if (!function_exists('lang') || defined('NO_LANG')) // setup declares an own version
{
/**
@@ -1683,311 +379,39 @@
$vars = func_get_args();
array_shift($vars); // remove $key
}
- return translation::translate($key,$vars);
- }
-}
-
-/**
- * Translate message only if translation object is already loaded
- *
- * This function is usefull for exception handlers or early stages of the initialisation of the egw object,
- * as calling lang would try to load the translations, evtl. cause more errors, eg. because there's no db-connection.
- *
- * @param string $key message in englich with %1, %2, ... placeholders
- * @param string $vars =null multiple values to replace the placeholders
- * @return string translated message with placeholders replaced
- */
-function try_lang($key,$vars=null)
-{
- static $varnames = array('%1','%2','%3','%4');
-
- if(!is_array($vars))
- {
- $vars = func_get_args();
- array_shift($vars); // remove $key
- }
- return class_exists(translations,false) ? translation::translate($key,$vars) : str_replace($varnames,$vars,$key);
-}
-
-/**
- * Unserialize a php serialized string, but only if it contains NO objects 'O:\d:"' or 'C:\d:"' pattern
- *
- * Should be used for all external content, to guard against exploidts.
- *
- * PHP 7.0+ can be told not to instanciate any classes (and calling eg. it's destructor).
- * In fact it instanciates it as __PHP_Incomplete_Class without any methods and therefore disarming threads.
- *
- * @param string $str
- * @return mixed
- */
-function php_safe_unserialize($str)
-{
- if (PHP_VERSION >= 7)
- {
- return unserialize($str, array('allowed_classes' => false));
- }
- if ((strpos($str, 'O:') !== false || strpos($str, 'C:') !== false) &&
- preg_match('/(^|;|{)[OC]:\d+:"/', $str))
- {
- error_log(__METHOD__."('$str') contains objects --> return NULL");
- return null; // null, not false, to not trigger behavior of returning string itself to app code
- }
- return unserialize($str);
-}
-
-/* some test for object safe unserialisation
-if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__) // some tests
-{
- if (php_sapi_name() !== 'cli') echo "<pre>\n";
- foreach(array(
- // things unsafe to unserialize
- "O:34:\"Horde_Kolab_Server_Decorator_Clean\":2:{s:43:\"\x00Horde_Kolab_Server_Decorator_Clean\x00_server\";" => false,
- "O:20:\"Horde_Prefs_Identity\":2:{s:9:\"\x00*\x00_prefs\";O:11:\"Horde_Prefs\":2:{s:8:\"\x00*\x00_opts\";a:1:{s:12:\"sizecallback\";" => false,
- "a:2:{i:0;O:12:\"Horde_Config\":1:{s:13:\"\x00*\x00_oldConfig\";s:#{php_injection.length}:\"#{php_injection}\";}i:1;s:13:\"readXMLConfig\";}}" => false,
- 'a:6:{i:0;i:0;i:1;d:2;i:2;s:4:"ABCD";i:3;r:3;i:4;O:8:"my_Class":2:{s:1:"a";r:6;s:1:"b";N;};i:5;C:16:"SplObjectStorage":14:{x:i:0;m:a:0:{}}' => false,
- serialize(new stdClass()) => false,
- serialize(array(new stdClass(), new SplObjectStorage())) => false,
- // string content, safe to unserialize
- serialize('O:8:"stdClass"') => true,
- serialize('C:16:"SplObjectStorage"') => true,
- serialize(array('a' => 'O:8:"stdClass"', 'b' => 'C:16:"SplObjectStorage"')) => true,
- // false positive: failing our php<7 regular expression, because it has correct delimiter (^|;|{) in front of pattern :-(
- serialize('O:8:"stdClass";C:16:"SplObjectStorage"') => true,
- ) as $str => $result)
- {
- if ((bool)($r=php_safe_unserialize($str)) !== $result)
- {
- if (!$result)
- {
- if (PHP_VERSION >= 7)
- {
- if (preg_match_all('/([^ ]+) Object\(/', array2string($r), $matches))
- {
- foreach($matches[1] as $class)
- {
- if (!preg_match('/^__PHP_Incomplete_Class(#\d+)?$/', $class))
- {
- echo "FAILED: $str\n";
- continue 2;
- }
- }
- }
- echo "passed: ".array2string($str)." = ".array2string($r)."\n";
- }
- else
- {
- echo "FAILED: $str\n";
- }
- }
- else
- {
- echo "false positive: $str\n";
- }
- }
- else
- {
- echo "passed: $str\n";
- }
- //echo "result=".array2string($result).", php_save_unserialize('".htmlspecialchars($str)."') = ".array2string(php_safe_unserialize($str))." --> ".array2string((bool)php_safe_unserialize($str))."\n";
- }
-}*/
-
-/**
- * Unserialize a json or php serialized array
- *
- * Used to migrate from PHP serialized database values to json-encoded ones.
- *
- * @param string $str string with serialized array
- * @param boolean $allow_not_serialized =false true: return $str as is, if it is no serialized array
- * @return array|str|false
- */
-function json_php_unserialize($str, $allow_not_serialized=false)
-{
- if ((in_array($str[0], array('a', 'i', 's', 'b', 'O', 'C')) && $str[1] == ':' || $str === 'N;') &&
- ($arr = php_safe_unserialize($str)) !== false || $str === 'b:0;')
- {
- return $arr;
- }
- if (!$allow_not_serialized || $str[0] == '[' || $str[0] == '{' || $str[0] == '"' || $str === 'null' || ($val = json_decode($str)) !== null)
- {
- return isset($val) ? $val : json_decode($str, true);
- }
- return $str;
-}
-
-/**
- * Clasify exception for a headline and log it to error_log, if not running as cli
- *
- * @param Exception|Error $e
- * @param string &$headline
- */
-function _egw_log_exception($e,&$headline=null)
-{
- $trace = explode("\n", $e->getTraceAsString());
- if ($e instanceof Api\Exception\NoPermission)
- {
- $headline = try_lang('Permission denied!');
- }
- elseif ($e instanceof Api\Db\Exception)
- {
- $headline = try_lang('Database error');
- }
- elseif ($e instanceof Api\Exception\WrongUserinput)
- {
- $headline = ''; // message contains the whole message, it's usually no real error but some input validation
- }
- elseif ($e instanceof egw_exception_warning)
- {
- $headline = 'PHP Warning';
- array_shift($trace);
- }
- else
- {
- $headline = try_lang('An error happened');
- }
- // log exception to error log, if not running as cli,
- // which outputs the error_log to stderr and therefore output it twice to the user
- if(isset($_SERVER['HTTP_HOST']) || $GLOBALS['egw_info']['flags']['no_exception_handler'] !== 'cli')
- {
- error_log($headline.($e instanceof egw_exception_warning ? ': ' : ' ('.get_class($e).'): ').$e->getMessage());
- foreach($trace as $line)
- {
- error_log($line);
- }
- error_log('# Instance='.$GLOBALS['egw_info']['user']['domain'].', User='.$GLOBALS['egw_info']['user']['account_lid'].
- ', Request='.$_SERVER['REQUEST_METHOD'].' '.($_SERVER['HTTPS']?'https://':'http://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].
- ', User-agent='.$_SERVER['HTTP_USER_AGENT']);
- }
-}
-
-/**
- * Fail a little bit more gracefully then an uncought exception
- *
- * Does NOT return
- *
- * @param Exception|Error $e
- */
-function egw_exception_handler($e)
-{
- // handle redirects without logging
- if (is_a($e, 'egw_exception_redirect'))
- {
- egw::redirect($e->url, $e->app);
- }
- // logging all exceptions to the error_log (if not cli) and get headline
- $headline = null;
- _egw_log_exception($e,$headline);
-
- // exception handler for cli (command line interface) clients, no html, no logging
- if(!isset($_SERVER['HTTP_HOST']) || $GLOBALS['egw_info']['flags']['no_exception_handler'] == 'cli')
- {
- echo ($headline ? $headline.': ' : '').$e->getMessage()."\n";
- if ($GLOBALS['egw_info']['server']['exception_show_trace'])
- {
- echo $e->getTraceAsString()."\n";
- }
- exit($e->getCode() ? $e->getCode() : 9999); // allways give a non-zero exit code
- }
- // regular GUI exception
- if (!isset($GLOBALS['egw_info']['flags']['no_exception_handler']))
- {
- header('HTTP/1.1 500 '.$headline);
- $message = '<h3>'.html::htmlspecialchars($headline)."</h3>\n".
- '<pre><b>'.html::htmlspecialchars($e->getMessage())."</b>\n\n";
-
- // only show trace (incl. function arguments) if explicitly enabled, eg. on a development system
- if ($GLOBALS['egw_info']['server']['exception_show_trace'])
- {
- $message .= html::htmlspecialchars($e->getTraceAsString());
- }
- $message .= "</pre>\n";
- if (is_a($e, 'EGroupware\Api\Db\Exception\Setup'))
- {
- $setup_dir = str_replace(array('home/index.php','index.php'),'setup/',$_SERVER['PHP_SELF']);
- $message .= '<a href="'.$setup_dir.'">Run setup to install or configure EGroupware.</a>';
- }
- elseif (is_object($GLOBALS['egw']) && isset($GLOBALS['egw']->session) && method_exists($GLOBALS['egw'],'link'))
- {
- $message .= '<p><a href="'.$GLOBALS['egw']->link('/index.php').'">'.try_lang('Click here to resume your eGroupWare Session.').'</a></p>';
- }
- if (is_object($GLOBALS['egw']) && isset($GLOBALS['egw']->framework))
- {
- $GLOBALS['egw']->framework->render($message,$headline);
- }
- else
- {
- echo "<html>\n<head>\n<title>".html::htmlspecialchars($headline)."</title>\n</head>\n<body>\n$message\n</body>\n</html>\n";
- }
- }
- // exception handler sending message back to the client as basic auth message
- elseif($GLOBALS['egw_info']['flags']['no_exception_handler'] == 'basic_auth')
- {
- $error = str_replace(array("\r", "\n"), array('', ' | '), $e->getMessage());
- header('WWW-Authenticate: Basic realm="'.$headline.' '.$error.'"');
- header('HTTP/1.1 401 Unauthorized');
- header('X-WebDAV-Status: 401 Unauthorized', true);
- }
- if (is_object($GLOBALS['egw']))
- {
- common::egw_exit();
- }
- exit;
-}
-
-if (!isset($GLOBALS['egw_info']['flags']['no_exception_handler']) || $GLOBALS['egw_info']['flags']['no_exception_handler'] !== true)
-{
- set_exception_handler('egw_exception_handler');
-}
-
-/**
- * Fail a little bit more gracefully then a catchable fatal error, by throwing an exception
- *
- * @param int $errno level of the error raised: E_* constants
- * @param string $errstr error message
- * @param string $errfile filename that the error was raised in
- * @param int $errline line number the error was raised at
- * @link http://www.php.net/manual/en/function.set-error-handler.php
- * @throws ErrorException
- */
-function egw_error_handler ($errno, $errstr, $errfile, $errline)
-{
- switch ($errno)
- {
- case E_RECOVERABLE_ERROR:
- case E_USER_ERROR:
- throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
-
- case E_WARNING:
- case E_USER_WARNING:
- // skip message for warnings supressed via @-error-control-operator (eg. @is_dir($path))
- // can be commented out to get suppressed warnings too!
- if (error_reporting())
- {
- _egw_log_exception(new egw_exception_warning($errstr.' in '.$errfile.' on line '.$errline));
- }
- break;
- }
-}
-
-/**
- * Used internally to trace warnings
- */
-class egw_exception_warning extends Exception {}
-
-// install our error-handler only for catchable fatal errors and warnings
-// following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING
-set_error_handler('egw_error_handler', E_RECOVERABLE_ERROR|E_USER_ERROR|E_WARNING|E_USER_WARNING);
-
-// some not longer necessary defines
-if (isset($GLOBALS['egw_info']['flags']['phpgw_compatibility']) && $GLOBALS['egw_info']['flags']['phpgw_compatibility'])
-{
- define('PHPGW_API_INC',EGW_API_INC);
- define('PHPGW_SERVER_ROOT',EGW_SERVER_ROOT);
- define('PHPGW_INCLUDE_ROOT',EGW_INCLUDE_ROOT);
-
- /* debugging settings */
- define('DEBUG_DATATYPES', True);
- define('DEBUG_LEVEL', 3);
- define('DEBUG_OUTPUT', 2); /* 1 = screen, 2 = DB. For both use 3. */
- define('DEBUG_TIMER', False);
-}
+ return Api\Translation::translate($key,$vars);
+ }
+}
+
+require_once __DIR__.'/security.php';
+require_once __DIR__.'/exception.php';
+
+/**
+ * Public functions to be compatible with the exiting eGW framework
+ */
+if (!function_exists('parse_navbar'))
+{
+ /**
+ * echo's out the navbar
+ *
+ * @deprecated use $GLOBALS['egw']->framework->navbar() or $GLOBALS['egw']->framework::render()
+ */
+ function parse_navbar()
+ {
+ echo $GLOBALS['egw']->framework->navbar();
+ }
+}
+
+if (!function_exists('display_sidebox'))
+{
+ /**
+ * echo's out a sidebox menu
+ *
+ * @deprecated use $GLOBALS['egw']->framework->sidebox()
+ */
+ function display_sidebox($appname,$menu_title,$_file)
+ {
+ $file = str_replace('preferences.uisettings.index', 'preferences.preferences_settings.index', $_file);
+ $GLOBALS['egw']->framework->sidebox($appname,$menu_title,$file);
+ }
+}
Copied: trunk/egroupware/api/src/loader/exception.php (from r55840, trunk/phpgwapi/inc/common_functions.inc.php)
URL: http://svn.stylite.de/viewvc/egroupware/trunk/egroupware/api/src/loader/exception.php?p2=trunk/egroupware/api/src/loader/exception.php&p1=trunk/phpgwapi/inc/common_functions.inc.php&r1=55840&r2=55853&rev=55853&view=diff
==============================================================================
--- trunk/phpgwapi/inc/common_functions.inc.php (original)
+++ trunk/egroupware/api/src/loader/exception.php Tue Apr 26 16:38:08 2016
@@ -1,11 +1,8 @@
<?php
/**
- * EGroupware commonly used functions
+ * EGroupware exception handler and friends
*
- * This file was originaly written by Dan Kuykendall and Joseph Engo
- * Copyright (C) 2000, 2001 Dan Kuykendall
- *
- * All newer parts (XSS checks, autoloading, exception handler, ...) are written by Ralf Becker.
+ * Usually loaded via header.inc.php or api/src/loader/common.php
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
@@ -15,1677 +12,6 @@
*/
use EGroupware\Api;
-
-// this is only neccessary, if header.inc.php is not included, but common_functions.inc.php directly
-if (!defined('EGW_SERVER_ROOT'))
-{
- define('EGW_SERVER_ROOT', dirname(dirname(__DIR__)));
- define('EGW_INCLUDE_ROOT', EGW_SERVER_ROOT);
- define('EGW_API_INC', __DIR__);
-}
-
-/**
- * New PSR-4 autoloader for EGroupware
- *
- * class_exists('\\EGroupware\\Api\\Vfs'); // /api/src/Vfs.php
- * class_exists('\\EGroupware\\Api\\Vfs\\Dav\\Directory'); // /api/src/Vfs/Dav/Directory.php
- * class_exists('\\EGroupware\\Api\\Vfs\\Sqlfs\\StreamWrapper'); // /api/src/Vfs/Sqlfs/StreamWrapper.php
- * class_exists('\\EGroupware\\Api\\Vfs\\Sqlfs\\Utils'); // /api/src/Vfs/Sqlfs/Utils.php
- * class_exists('\\EGroupware\\Stylite\\Versioning\\StreamWrapper'); // /stylite/src/Versioning/StreamWrapper.php
- * class_exists('\\EGroupware\\Calendar\\Ui'); // /calendar/src/Ui.php
- * class_exists('\\EGroupware\\Calendar\\Ui\\Lists'); // /calendar/src/Ui/Lists.php
- * class_exists('\\EGroupware\\Calendar\\Ui\\Views'); // /calendar/src/Ui/Views.php
- */
-spl_autoload_register(function($class)
-{
- $parts = explode('\\', $class);
- if (array_shift($parts) != 'EGroupware') return; // not our prefix
-
- $app = lcfirst(array_shift($parts));
- $base = EGW_INCLUDE_ROOT.'/'.$app.'/src/';
- $path = $base.implode('/', $parts).'.php';
-
- if (file_exists($path))
- {
- require_once $path;
- //error_log("PSR4_autoload('$class') --> require_once($path) --> class_exists('$class')=".array2string(class_exists($class,false)));
- }
-});
-
-/**
- * Old autoloader for EGroupware understanding the following naming schema:
- *
- * 1. new (prefered) nameing schema: app_class_something loading app/inc/class.class_something.inc.php
- * 2. API classes: classname loading phpgwapi/inc/class.classname.inc.php
- * 2a.API classes containing multiple classes per file eg. egw_exception* in class.egw_exception.inc.php
- * 3. eTemplate classes: classname loading etemplate/inc/class.classname.inc.php
- *
- * @param string $class name of class to load
- */
-spl_autoload_register(function($class)
-{
- // fixing warnings generated by php 5.3.8 is_a($obj) trying to autoload huge strings
- if (strlen($class) > 64 || strpos($class, '.') !== false) return;
-
- $components = explode('_',$class);
- $app = array_shift($components);
- // classes using the new naming schema app_class_name, eg. admin_cmd
- if (file_exists($file = EGW_INCLUDE_ROOT.'/'.$app.'/inc/class.'.$class.'.inc.php') ||
- // classes using the new naming schema app_class_name, eg. admin_cmd
- isset($components[0]) && file_exists($file = EGW_INCLUDE_ROOT.'/'.$app.'/inc/class.'.$app.'_'.$components[0].'.inc.php') ||
- // classes with an underscore in their name
- !isset($GLOBALS['egw_info']['apps'][$app]) && isset($GLOBALS['egw_info']['apps'][$app . '_' . $components[0]]) &&
- file_exists($file = EGW_INCLUDE_ROOT.'/'.$app.'_'.$components[0].'/inc/class.'.$class.'.inc.php') ||
- // eGW api classes using the old naming schema, eg. html
- file_exists($file = EGW_API_INC.'/class.'.$class.'.inc.php') ||
- // eGW api classes containing multiple classes in on file, eg. egw_exception
- isset($components[0]) && file_exists($file = EGW_API_INC.'/class.'.$app.'_'.$components[0].'.inc.php') ||
- // eGW eTemplate classes using the old naming schema, eg. etemplate
- file_exists($file = EGW_INCLUDE_ROOT.'/etemplate/inc/class.'.$class.'.inc.php') ||
- // include PEAR and PSR0 classes from include_path
- // need to use include (not include_once) as eg. a previous included EGW_API_INC/horde/Horde/String.php causes
- // include_once('Horde/String.php') to return true, even if the former was included with an absolute path
- // only use include_path, if no Composer vendor directory exists
- !isset($GLOBALS['egw_info']['apps'][$app]) && !file_exists(EGW_SERVER_ROOT.'/vendor') &&
- @include($file = strtr($class, array('_'=>'/','\\'=>'/')).'.php'))
- {
- include_once($file);
- //if (!class_exists($class, false) && !interface_exists($class, false)) error_log("autoloading class $class by include_once($file) failed!");
- }
- // allow apps to define an own autoload method
- elseif (isset($GLOBALS['egw_info']['flags']['autoload']) && is_callable($GLOBALS['egw_info']['flags']['autoload']))
- {
- call_user_func($GLOBALS['egw_info']['flags']['autoload'],$class);
- }
-});
-
-// if we have a Composer vendor directory, also load it's autoloader, to allow manage our requirements with Composer
-if (file_exists(EGW_SERVER_ROOT.'/vendor'))
-{
- require_once EGW_SERVER_ROOT.'/vendor/autoload.php';
-}
-
-/**
-* applies stripslashes recursivly on each element of an array
-*
-* @param array &$var
-* @return array
-*/
-function array_stripslashes($var)
-{
- if (!is_array($var))
- {
- return stripslashes($var);
- }
- foreach($var as $key => $val)
- {
- $var[$key] = is_array($val) ? array_stripslashes($val) : stripslashes($val);
- }
- return $var;
-}
-
-/**
- * Return the number of bytes of a string, independent of mbstring.func_overload
- * AND the availability of mbstring
- *
- * @param string $str
- * @return int
- */
-function bytes($str)
-{
- static $func_overload = null;
-
- if (is_null($func_overload)) $func_overload = extension_loaded('mbstring') ? ini_get('mbstring.func_overload') : 0;
-
- return $func_overload & 2 ? mb_strlen($str,'ascii') : strlen($str);
-}
-
-/**
- * mbstring.func_overload safe substr
- *
- * @param string $data
- * @param int $offset
- * @param int $len
- * @return string
- */
-function cut_bytes(&$data,$offset,$len=null)
-{
- static $func_overload = null;
-
- if (is_null($func_overload)) $func_overload = extension_loaded('mbstring') ? ini_get('mbstring.func_overload') : 0;
-
- if (is_null($len))
- {
- return $func_overload & 2 ? mb_substr($data,$offset,bytes($data),'ascii') : substr($data,$offset);
- }
- return $func_overload & 2 ? mb_substr($data,$offset,$len,'ascii') : substr($data,$offset,$len);
-}
-
-if (!function_exists('imap_rfc822_parse_adrlist'))
-{
- /**
- * parses a (comma-separated) address string
- *
- * Examples:
- * - Joe Doe <[email protected]>
- * - "Doe, Joe" <[email protected]>
- * - "\'Joe Doe\'" <[email protected]> // actually not necessary to quote
- * - [email protected]
- * - root
- * - "Joe on its way Down Under :-\)" <[email protected]>
- * - "Giant; \"Big\" Box" <[email protected]>
- * - [email protected] <[email protected]> // this is wrong, because @ need to be quoted
- *
- * Invalid addresses, if detected, set host to '.SYNTAX-ERROR.'
- *
- * @param string $address - A string containing addresses
- * @param string $default_host - The default host name
- * @return array of objects. The objects properties are:
- * mailbox - the mailbox name (username)
- * host - the host name
- * personal - the personal name
- * adl - at domain source route
- */
- function imap_rfc822_parse_adrlist($address, $default_host)
- {
- $addresses = array();
- $pending = '';
- foreach(explode(',', $address) as $part)
- {
- $trimmed = trim(($pending ? $pending.',' : '').$part);
- if (($trimmed[0] == '"' && substr($trimmed, -1) != '>')||strpos($part, '@')===false)
- {
- $pending .= ($pending ? $pending.',' : '').$part;
- continue;
- }
- $pending = '';
- $matches = $personal = $mailbox = $host = null;
- if (preg_match('/^(.*)<([^>@]+)(@([^>]+))?>$/', $trimmed, $matches))
- {
- $personal = trim($matches[1]);
- $mailbox = $matches[2];
- $host = $matches[4];
- }
- elseif (strpos($trimmed, '@') !== false)
- {
- list($mailbox, $host) = explode('@', $trimmed);
- }
- else
- {
- $mailbox = $trimmed;
- }
- if ($personal[0] == '"' && substr($personal, -1) == '"')
- {
- $personal = str_replace('\\', '', substr($personal, 1, -1));
- }
- if (empty($host)) $host = $default_host;
-
- $addresses[] = (object)array_diff(array(
- 'mailbox' => $mailbox,
- 'host' => $host,
- 'personal' => $personal,
- ), array(null, ''));
- }
- return $addresses;
- }
-}
-
-if (!function_exists('imap_rfc822_write_address'))
-{
- /**
- * Returns a properly formatted email address given the mailbox, host, and personal info
- * @param string $mailbox - The mailbox name, see imap_open() for more information
- * @param string $host - The email host part
- * @param string $personal - The name of the account owner
- * @return string properly formatted email address as defined in » RFC2822.
- */
- function imap_rfc822_write_address($mailbox, $host, $personal)
- {
- if (is_array($personal)) $personal = implode(' ', $personal);
-
- //if (!preg_match('/^[!#$%&\'*+/0-9=?A-Z^_`a-z{|}~-]+$/u', $personal)) // that's how I read the rfc(2)822
- if ($personal && !preg_match('/^[0-9A-Z -]*$/iu', $personal)) // but quoting is never wrong, so quote more then necessary
- {
- $personal = '"'.str_replace(array('\\', '"'),array('\\\\', '\\"'), $personal).'"';
- }
- return ($personal ? $personal.' <' : '').$mailbox.($host ? '@'.$host : '').($personal ? '>' : '');
- }
-}
-
-if (!function_exists('imap_mime_header_decode'))
-{
- /**
- * Decodes MIME message header extensions that are non ASCII text (RFC2047)
- *
- * Uses Horde_Mime::decode() and therefore always returns only a single array element!
- *
- * @param string $text
- * @return array with single object with attribute text already in our internal encoding and charset
- * @deprecated use Horde_Mime::decode()
- */
- function imap_mime_header_decode($text)
- {
- return array((object)array(
- 'text' => Horde_Mime::decode($text),
- 'charset' => translation::charset(), // is already in our internal encoding!
- ));
- }
-}
-
-if (!function_exists('mb_strlen'))
-{
- /**
- * Number of characters in a string
- *
- * @param string $str
- * @return int
- */
- function mb_strlen($str)
- {
- return strlen($str);
- }
-}
-
-if (!function_exists('mb_substr'))
-{
- /**
- * Return part of a string
- *
- * @param string $data
- * @param int $offset
- * @param int $len
- * @return string
- */
- function mb_substr(&$data, $offset, $len=null)
- {
- return is_null($len) ? substr($data, $offset) : substr($data, $offset, $len);
- }
-}
-
-/**
- * Format array or other types as (one-line) string, eg. for error_log statements
- *
- * @param mixed $var variable to dump
- * @return string
- */
-function array2string($var)
-{
- switch (($type = gettype($var)))
- {
- case 'boolean':
- return $var ? 'TRUE' : 'FALSE';
- case 'string':
- return "'$var'";
- case 'integer':
- case 'double':
- case 'resource':
- return $var;
- case 'NULL':
- return 'NULL';
- case 'object':
- case 'array':
- return str_replace(array("\n",' '/*,'Array'*/),'',print_r($var,true));
- }
- return 'UNKNOWN TYPE!';
-}
-
-/**
- * Check if a given extension is loaded or load it if possible (requires sometimes disabled or unavailable dl function)
- *
- * @param string $extension
- * @param boolean $throw =false should we throw an exception, if $extension could not be loaded, default false = no
- * @return boolean true if loaded now, false otherwise
- */
-function check_load_extension($extension,$throw=false)
-{
- if (!defined('PHP_SHLIB_PREFIX'))
- {
- define('PHP_SHLIB_PREFIX',PHP_SHLIB_SUFFIX == 'dll' ? 'php_' : '');
- }
- // we check for the existens of 'dl', as multithreaded webservers dont have it and some hosters disable it !!!
- $loaded = extension_loaded($extension) || function_exists('dl') && @dl($dl=PHP_SHLIB_PREFIX.$extension.'.'.PHP_SHLIB_SUFFIX);
-
- if (!$loaded && $throw)
- {
- throw new Exception ("PHP extension '$extension' not loaded AND can NOT be loaded via dl('$dl')!");
- }
- return $loaded;
-}
-
-/**
- * @internal Not to be used directly. Should only be used by print_debug()
- */
-function print_debug_subarray($array)
-{
- foreach($array as $key => $value)
- {
- if (is_array($value))
- {
- $vartypes[$key] = print_debug_subarray($value);
- }
- else
- {
- $vartypes[$key] = gettype($value);
- }
- }
- return $vartypes;
-}
-
-/**
- * print debug data only when debugging mode is turned on.
- *
- * @author seek3r
- * This function is used to debugging data.
- * print_debug('this is some debugging data',$somevar);
- */
-function print_debug($message,$var = 'messageonly',$part = 'app', $level = 3)
-{
- if (($part == 'app' && DEBUG_APP == True) || ($part == 'api' && DEBUG_API == True))
- {
- if (!defined('DEBUG_OUTPUT'))
- {
- define('DEBUG_OUTPUT', 1);
- }
- if ($level >= DEBUG_LEVEL)
- {
- if (!is_array($var))
- {
- if ($var != 'messageonly')
- {
- if (!DEBUG_DATATYPES)
- {
- $output = "$message\n$var";
- }
- else
- {
- $output = "$message\n$var is a ".gettype($var);
- }
- }
- else
- {
- $output = $message;
- }
-
- /* Bit 1 means to output to screen */
- if (!!(DEBUG_OUTPUT & 1))
- {
- echo "$output<br>\n";
- }
- /* Bit 2 means to output to sql */
- if (!!(DEBUG_OUTPUT & 2))
- {
- /* Need to flesh this out still. I dont have a table to dump this in yet.*/
- /* So the SQL statement will go here*/
- }
-
- /* Example of how this can be extended to output to other locations as well. This example uses a COM object */
- /*
- if (!!(DEBUG_OUTPUT & 32))
- {
- $obj_debug = new COM('Some_COM_App.Class','localhost');
- if (is_object($obj_debug))
- {
- $DebugMessage_return = $obj_debug->DebugMessage($output);
- }
- }
- */
- }
- else
- {
- if (floor(phpversion()) > 3 && !!(DEBUG_OUTPUT & 2))
- {
- ob_start();
- }
- echo "<pre>\n$message\n";
- print_r($var);
- if (DEBUG_DATATYPES)
- {
- foreach($var as $key => $value)
- {
- if (is_array($value))
- {
- $vartypes[$key] = print_debug_subarray($value);
- }
- else
- {
- $vartypes[$key] = gettype($value);
- }
- }
- echo "Data Types:\n";
- print_r($vartypes);
- }
- echo "\n<pre>\n";
- if (floor(phpversion()) > 3 && !!(DEBUG_OUTPUT & 2))
- {
- $output .= ob_get_contents();
- ob_end_clean();
- /* Need to flesh this out still. I dont have a table to dump this in yet.*/
- /* So the SQL statement will go here*/
- if (!!(DEBUG_OUTPUT & 1))
- {
- echo "$output<br>\n";
- }
- }
- }
- }
- }
-}
-
-/**
- * Allows for array and direct function params as well as sanatization.
- *
- * @author seek3r
- * This function is used to validate param data as well as offer flexible function usage.
- *
- function somefunc()
- {
- $expected_args[0] = Array('name'=>'fname','default'=>'joe', 'type'=>'string');
- $expected_args[1] = Array('name'=>'mname','default'=>'hick', 'type'=>'string');
- $expected_args[2] = Array('name'=>'lname','default'=>'bob', 'type'=>'string');
- $recieved_args = func_get_args();
- $args = safe_args($expected_args, $recieved_args,__LINE__,__FILE__);
- echo 'Full name: '.$args['fname'].' '.$args['fname'].' '.$args['lname'].'<br>';
- //default result would be:
- // Full name: joe hick bob<br>
- }
-
- Using this it is possible to use the function in any of the following ways
- somefunc('jack','city','brown');
- or
- somefunc(array('fname'=>'jack','mname'=>'city','lname'=>'brown'));
- or
- somefunc(array('lname'=>'brown','fname'=>'jack','mname'=>'city'));
-
- For the last one, when using named params in an array you dont have to follow any order
- All three would result in - Full name: jack city brown<br>
-
- When you use this method of handling params you can secure your functions as well offer
- flexibility needed for both normal use and web services use.
- If you have params that are required just set the default as ##REQUIRED##
- Users of your functions can also use ##DEFAULT## to use your default value for a param
- when using the standard format like this:
- somefunc('jack','##DEFAULT##','brown');
- This would result in - Full name: jack hick brown<br>
- Its using the default value for the second param.
- Of course if you have the second param as a required field it will fail to work.
- */
-function safe_args($expected, $recieved, $line='??', $file='??')
-{
- /* This array will contain all the required fields */
- $required = Array();
-
- /* This array will contain all types for sanatization checking */
- /* only used when an array is passed as the first arg */
- $types = Array();
-
- /* start by looping thru the expected list and set params with */
- /* the default values */
- $num = count($expected);
- for ($i = 0; $i < $num; $i++)
- {
- $args[$expected[$i]['name']] = $expected[$i]['default'];
- if ($expected[$i]['default'] === '##REQUIRED##')
- {
- $required[$expected[$i]['name']] = True;
- }
- $types[$expected[$i]['name']] = $expected[$i]['type'];
- }
-
- /* Make sure they passed at least one param */
- if(count($recieved) != 0)
- {
- /* if used as standard function we loop thru and set by position */
- if(!is_array($recieved[0]))
- {
- for ($i = 0; $i < $num; $i++)
- {
- if(isset($recieved[$i]) && $recieved[$i] !== '##DEFAULT##')
- {
- if(sanitize($recieved[$i],$expected[$i]['type']))
- {
- $args[$expected[$i]['name']] = $recieved[$i];
- unset($required[$expected[$i]['name']]);
- }
- else
- {
- echo 'Fatal Error: Invalid paramater type for '.$expected[$i]['name'].' on line '.$line.' of '.$file.'<br>';
- exit;
- }
- }
- }
- }
- /* if used as standard function we loop thru and set by position */
- else
- {
- for ($i = 0; $i < $num; $i++)
- {
- $types[$expected[$i]['name']] = $expected[$i]['type'];
- }
- while(list($key,$val) = each($recieved[0]))
- {
- if($val !== '##DEFAULT##')
- {
- if(sanitize($val,$types[$key]) == True)
- {
- $args[$key] = $val;
- unset($required[$key]);
- }
- else
- {
- echo 'Fatal Error: Invalid paramater type for '.$key.' on line '.$line.' of '.$file.'<br>';
- exit;
- }
- }
- }
- }
- }
- if(count($required) != 0)
- {
- while (list($key) = each($required))
- {
- echo 'Fatal Error: Missing required paramater '.$key.' on line '.$line.' of '.$file.'<br>';
- }
- exit;
- }
- return $args;
-}
-
-/**
- * Validate data.
- *
- * @author seek3r
- * This function is used to validate input data.
- * sanitize('number',$somestring);
- */
-function sanitize($string,$type)
-{
- switch ($type)
- {
- case 'bool':
- if ($string == 1 || $string == 0)
- {
- return True;
- }
- break;
-
- case 'isprint':
- $length = strlen($string);
- $position = 0;
- while ($length > $position)
- {
- $char = substr($string, $position, 1);
- if ($char < ' ' || $char > '~')
- {
- return False;
- }
- $position = $position + 1;
- }
- return True;
-
- case 'alpha':
- if (preg_match("/^[a-z]+$/i", $string))
- {
- return True;
- }
- break;
-
- case 'number':
- if (preg_match("/^[0-9]+$/i", $string))
- {
- return True;
- }
- break;
-
- case 'alphanumeric':
- if (preg_match("/^[a-z0-9 -._]+$/i", $string))
- {
- return True;
- }
- break;
- case 'string':
- if (preg_match("/^[a-z]+$/i", $string))
- {
- return True;
- }
- break;
- case 'ip':
- if (preg_match('/'."^[0-9]{1,3}(\.[0-9]{1,3}){3}$".'/i',$string))
- {
- $octets = preg_split('/\./',$string);
- for ($i=0; $i != count($octets); $i++)
- {
- if ($octets[$i] < 0 || $octets[$i] > 255)
- {
- return False;
- }
- }
- return True;
- }
- return False;
-
- case 'file':
- if (preg_match("/^[a-z0-9_]+\.+[a-z]+$/i", $string))
- {
- return True;
- }
- break;
- case 'email':
- if (preg_match('/'."^([[:alnum:]_%+=.-]+)@([[:alnum:]_.-]+)\.([a-z]{2,3}|[0-9]{1,3})$".'/i',$string))
- {
- return True;
- }
- break;
- case 'password':
- $password_length = strlen($string);
- $password_numbers = Array('0','1','2','3','4','5','6','7','8','9');
- $password_special_chars = Array(' ','~','`','!','@','#','$','%','^','&','*','(',')','_','+','-','=','{','}','|','[',']',"\\",':','"',';',"'",'<','>','?',',','.','/');
-
- if(@isset($GLOBALS['egw_info']['server']['pass_min_length']) && is_int($GLOBALS['egw_info']['server']['pass_min_length']) && $GLOBALS['egw_info']['server']['pass_min_length'] > 1)
- {
- $min_length = $GLOBALS['egw_info']['server']['pass_min_length'];
- }
- else
- {
- $min_length = 1;
- }
-
- if(@isset($GLOBALS['egw_info']['server']['pass_require_non_alpha']) && $GLOBALS['egw_info']['server']['pass_require_non_alpha'] == True)
- {
- $pass_verify_non_alpha = False;
- }
- else
- {
- $pass_verify_non_alpha = True;
- }
-
- if(@isset($GLOBALS['egw_info']['server']['pass_require_numbers']) && $GLOBALS['egw_info']['server']['pass_require_numbers'] == True)
- {
- $pass_verify_num = False;
- }
- else
- {
- $pass_verify_num = True;
- }
-
- if(@isset($GLOBALS['egw_info']['server']['pass_require_special_char']) && $GLOBALS['egw_info']['server']['pass_require_special_char'] == True)
- {
- $pass_verify_special_char = False;
- }
- else
- {
- $pass_verify_special_char = True;
- }
-
- if ($password_length >= $min_length)
- {
- for ($i=0; $i != $password_length; $i++)
- {
- $cur_test_string = substr($string, $i, 1);
- if (in_array($cur_test_string, $password_numbers) || in_array($cur_test_string, $password_special_chars))
- {
- $pass_verify_non_alpha = True;
- if (in_array($cur_test_string, $password_numbers))
- {
- $pass_verify_num = True;
- }
- elseif (in_array($cur_test_string, $password_special_chars))
- {
- $pass_verify_special_char = True;
- }
- }
- }
-
- if ($pass_verify_num == False)
- {
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password requires at least one non-alpha character']=False;
- }
-
- if ($pass_verify_num == False)
- {
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password requires at least one numeric character']=False;
- }
-
- if ($pass_verify_special_char == False)
- {
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password requires at least one special character (non-letter and non-number)']=False;
- }
-
- if ($pass_verify_num == True && $pass_verify_special_char == True)
- {
- return True;
- }
- return False;
- }
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password must be at least '.$min_length.' characters']=False;
- return False;
-
- case 'any':
- return True;
-
- default :
- if (isset($GLOBALS['egw_info']['server']['sanitize_types'][$type]['type']))
- {
- if ($GLOBALS['egw_info']['server']['sanitize_types'][$type]['type']($GLOBALS['egw_info']['server']['sanitize_types'][$type]['string'], $string))
- {
- return True;
- }
- }
- return False;
- }
-}
-
-function reg_var($varname, $method='any', $valuetype='alphanumeric',$default_value='',$register=True)
-{
- if($method == 'any' || $method == array('any'))
- {
- $method = Array('POST','GET','COOKIE','SERVER','FILES','GLOBAL','DEFAULT');
- }
- elseif(!is_array($method))
- {
- $method = Array($method);
- }
- $cnt = count($method);
- for($i=0;$i<$cnt;$i++)
- {
- switch(strtoupper($method[$i]))
- {
- case 'DEFAULT':
- if($default_value)
- {
- $value = $default_value;
- $i = $cnt+1; /* Found what we were looking for, now we end the loop */
- }
- break;
- case 'GLOBAL':
- if(@isset($GLOBALS[$varname]))
- {
- $value = $GLOBALS[$varname];
- $i = $cnt+1;
- }
- break;
- case 'POST':
- case 'GET':
- case 'COOKIE':
- case 'SERVER':
- if(phpversion() >= '4.1.0')
- {
- $meth = '_'.strtoupper($method[$i]);
- }
- else
- {
- $meth = 'HTTP_'.strtoupper($method[$i]).'_VARS';
- }
- if(@isset($GLOBALS[$meth][$varname]))
- {
- $value = $GLOBALS[$meth][$varname];
- $i = $cnt+1;
- }
- if(get_magic_quotes_gpc() && isset($value))
- {
- // we need to stripslash 3 levels of arrays
- // because of the password function in preferences
- // it's named ['user']['variablename']['pw']
- // or something like this in projects
- // $values['budgetBegin']['1']['year']
- if(@is_array($value))
- {
- /* stripslashes on the first level of array values */
- foreach($value as $name => $val)
- {
- if(@is_array($val))
- {
- foreach($val as $name2 => $val2)
- {
- if(@is_array($val2))
- {
- foreach($val2 as $name3 => $val3)
- {
- $value[$name][$name2][$name3] = stripslashes($val3);
- }
- }
- else
- {
- $value[$name][$name2] = stripslashes($val2);
- }
- }
- }
- else
- {
- $value[$name] = stripslashes($val);
- }
- }
- }
- else
- {
- /* stripslashes on this (string) */
- $value = stripslashes($value);
- }
- }
- break;
- case 'FILES':
- if(phpversion() >= '4.1.0')
- {
- $meth = '_FILES';
- }
- else
- {
- $meth = 'HTTP_POST_FILES';
- }
- if(@isset($GLOBALS[$meth][$varname]))
- {
- $value = $GLOBALS[$meth][$varname];
- $i = $cnt+1;
- }
- break;
- default:
- if(@isset($GLOBALS[strtoupper($method[$i])][$varname]))
- {
- $value = $GLOBALS[strtoupper($method[$i])][$varname];
- $i = $cnt+1;
- }
- break;
- }
- }
-
- if (@!isset($value))
- {
- $value = $default_value;
- }
-
- if (@!is_array($value))
- {
- if ($value == '')
- {
- $result = $value;
- }
- else
- {
- if (sanitize($value,$valuetype) == 1)
- {
- $result = $value;
- }
- else
- {
- $result = $default_value;
- }
- }
- }
- else
- {
- reset($value);
- while(list($k, $v) = each($value))
- {
- if ($v == '')
- {
- $result[$k] = $v;
- }
- else
- {
- if (is_array($valuetype))
- {
- $vt = $valuetype[$k];
- }
- else
- {
- $vt = $valuetype;
- }
-
- if (sanitize($v,$vt) == 1)
- {
- $result[$k] = $v;
- }
- else
- {
- if (is_array($default_value))
- {
- $result[$k] = $default_value[$k];
- }
- else
- {
- $result[$k] = $default_value;
- }
- }
- }
- }
- }
- if($register)
- {
- $GLOBALS['egw_info'][$GLOBALS['egw_info']['flags']['currentapp']][$varname] = $result;
- }
- return $result;
-}
-
-/**
- * retrieve a value from either a POST, GET, COOKIE, SERVER or from a class variable.
- *
- * @author skeeter
- * This function is used to retrieve a value from a user defined order of methods.
- * $this->id = get_var('id',array('HTTP_POST_VARS'||'POST','HTTP_GET_VARS'||'GET','HTTP_COOKIE_VARS'||'COOKIE','GLOBAL','DEFAULT'));
- * @param $variable name
- * @param $method ordered array of methods to search for supplied variable
- * @param $default_value (optional)
- */
-function get_var($variable,$method='any',$default_value='')
-{
- if(!@is_array($method))
- {
- $method = array($method);
- }
- return reg_var($variable,$method,'any',$default_value,False);
-}
-
-/**
- * Load a class and include the class file if not done so already.
- *
- * This function is used to create an instance of a class, and if the class file has not been included it will do so.
- * $GLOBALS['egw']->acl =& CreateObject('phpgwapi.acl');
- *
- * @author [email protected]
- * @param $classname name of class
- * @param $p1,$p2,... class parameters (all optional)
- * @return object reference to an object
- */
-function CreateObject($class)
-{
- list($appname,$classname) = explode('.',$class);
-
- if (!class_exists($classname))
- {
- static $replace = array(
- 'datetime' => 'egw_datetime',
- 'uitimesheet' => 'timesheet_ui',
- 'uiinfolog' => 'infolog_ui',
- 'uiprojectmanager' => 'projectmanager_ui',
- 'uiprojectelements' => 'projectmanager_elements_ui',
- 'uiroles' => 'projectmanager_roles_ui',
- 'uimilestones' => 'projectmanager_milestones_ui',
- 'uipricelist' => 'projectmanager_pricelist_ui',
- 'bowiki' => 'wiki_bo',
- 'uicategories' => 'admin_categories',
- 'defaultimap' => 'emailadmin_oldimap',
- );
- if (!file_exists(EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php') || isset($replace[$classname]))
- {
- if (isset($replace[$classname]))
- {
- //throw new Exception(__METHOD__."('$class') old classname '$classname' used in menuaction=$_GET[menuaction]!");
- error_log(__METHOD__."('$class') old classname '$classname' used in menuaction=$_GET[menuaction]!");
- $classname = $replace[$classname];
- }
- }
- if (!file_exists($f=EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php'))
- {
- throw new Api\Exception\AssertionFailed(__FUNCTION__."($classname) file $f not found!");
- }
- // this will stop php with a 500, if the class does not exist or there are errors in it (syntax error go into the error_log)
- require_once(EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php');
- }
- $args = func_get_args();
- switch(count($args))
- {
- case 1:
- $obj = new $classname;
- break;
- case 2:
- $obj = new $classname($args[1]);
- break;
- case 3:
- $obj = new $classname($args[1],$args[2]);
- break;
- case 4:
- $obj = new $classname($args[1],$args[2],$args[3]);
- break;
- default:
- $code = '$obj = new ' . $classname . '(';
- foreach(array_keys($args) as $n)
- {
- if ($n)
- {
- $code .= ($n > 1 ? ',' : '') . '$args[' . $n . ']';
- }
- }
- $code .= ');';
- eval($code);
- break;
- }
- if (!is_object($obj))
- {
- echo "<p>CreateObject('$class'): Cant instanciate class!!!<br />\n".function_backtrace(1)."</p>\n";
- }
- return $obj;
-}
-
-/**
- * Execute a function with multiple arguments
- * We take object $GLOBALS[classname] from class if exists
- *
- * @param string app.class.method method to execute
- * @example ExecObject('etemplates.so_sql.search',$criteria,$key_only,...);
- * @return mixed reference to returnvalue of the method
- */
-function &ExecMethod2($acm)
-{
- // class::method is php5.2.3+
- if (strpos($acm,'::') !== false && version_compare(PHP_VERSION,'5.2.3','<'))
- {
- list($class,$method) = explode('::',$acm);
- $acm = array($class,$method);
- }
- if (!is_callable($acm))
- {
- list(,$class,$method) = explode('.',$acm);
- if (!is_object($obj =& $GLOBALS[$class]))
- {
- if (class_exists($class))
- {
- $obj = new $class;
- }
- else
- {
- $obj = CreateObject($acm);
- }
- }
-
- if (!method_exists($obj,$method))
- {
- echo "<p><b>".function_backtrace()."</b>: no methode '$method' in class '$class'</p>\n";
- return False;
- }
- $acm = array($obj,$method);
- }
- $args = func_get_args();
- unset($args[0]);
-
- return call_user_func_array($acm,$args);
-}
-
-/**
- * Execute a function, and load a class and include the class file if not done so already.
- *
- * This function is used to create an instance of a class, and if the class file has not been included it will do so.
- *
- * @author seek3r
- * @param $method to execute
- * @param $functionparam function param should be an array
- * @param $loglevel developers choice of logging level
- * @param $classparams params to be sent to the contructor
- * @return mixed returnvalue of method
- */
-function ExecMethod($method, $functionparam = '_UNDEF_', $loglevel = 3, $classparams = '_UNDEF_')
-{
- unset($loglevel); // not used
- /* Need to make sure this is working against a single dimensional object */
- $partscount = count(explode('.',$method)) - 1;
-
- if (!is_callable($method) && $partscount == 2)
- {
- list($appname,$classname,$functionname) = explode(".", $method);
- if (!is_object($GLOBALS[$classname]))
- {
- // please note: no reference assignment (=&) here, as $GLOBALS is a reference itself!!!
- if ($classparams != '_UNDEF_' && ($classparams || $classparams != 'True'))
- {
- $GLOBALS[$classname] = CreateObject($appname.'.'.$classname, $classparams);
- }
- elseif (class_exists($classname))
- {
- $GLOBALS[$classname] = new $classname;
- }
- else
- {
- $GLOBALS[$classname] = CreateObject($appname.'.'.$classname);
- }
- }
-
- if (!method_exists($GLOBALS[$classname],$functionname))
- {
- error_log("ExecMethod('$method', ...) No methode '$functionname' in class '$classname'! ".function_backtrace());
- return false;
- }
- $method = array($GLOBALS[$classname],$functionname);
- }
- if (is_callable($method))
- {
- return $functionparam != '_UNDEF_' ? call_user_func($method,$functionparam) : call_user_func($method);
- }
- error_log("ExecMethod('$method', ...) Error in parts! ".function_backtrace());
- return false;
-}
-
-/**
- * Return a properly formatted account_id.
- *
- * @author skeeter
- * This function will return a properly formatted account_id. This can take either a name or an account_id as paramters. If a name is provided it will return the associated id.
- * $account_id = get_account_id($accountid);
- * @param int/string $account_id either a name or an id
- * @param int/string $default_id either a name or an id
- * @return int account_id
- */
-function get_account_id($account_id = '',$default_id = '')
-{
- if (gettype($account_id) == 'integer')
- {
- return $account_id;
- }
- elseif ($account_id == '')
- {
- if ($default_id == '')
- {
- return (isset($GLOBALS['egw_info']['user']['account_id'])?$GLOBALS['egw_info']['user']['account_id']:0);
- }
- elseif (is_string($default_id))
- {
- return $GLOBALS['egw']->accounts->name2id($default_id);
- }
- return (int)$default_id;
- }
- elseif (is_string($account_id))
- {
- if($GLOBALS['egw']->accounts->exists((int)$account_id) == True)
- {
- return (int)$account_id;
- }
- else
- {
- return $GLOBALS['egw']->accounts->name2id($account_id);
- }
- }
-}
-
-/**
- * sets the file system seperator depending on OS
- *
- * This is completely unnecessary, as you can use forward slashes in php under every OS -- RalfBecker 2005/11/09
- *
- * @deprecated just use forward slashes supported by PHP on all OS
- * @return file system separator
- */
-function filesystem_separator()
-{
- if(PHP_OS == 'Windows' || PHP_OS == 'OS/2' || PHP_OS == 'WINNT')
- {
- return '\\';
- }
- else
- {
- return '/';
- }
-}
-
-/**
- * @deprecated just use forward slashes supported by PHP on all OS
- */
-define('SEP', filesystem_separator());
-
-/**
- * print an array or object as pre-formatted html
- *
- * @param mixed $array
- * @param boolean $print =true print or return the content
- * @return string if !$print
- */
-function _debug_array($array,$print=True)
-{
- $output = '<pre>'.print_r($array,true)."</pre>\n";
-
- if ($print)
- {
- echo $output;
- }
- else
- {
- return $output;
- }
-}
-
-/**
- * eGW version checking, is eGW version in $a < $b
- *
- * @param string $a egw version number to check if less than $b
- * @param string $b egw version number to check $a against
- * @return boolean True if $a < $b
- */
-function alessthanb($a,$b,$DEBUG=False)
-{
- $num = array('1st','2nd','3rd','4th');
-
- if ($DEBUG)
- {
- echo'<br>Input values: ' . 'A="'.$a.'", B="'.$b.'"';
- }
- $newa = str_replace('pre','.',$a);
- $newb = str_replace('pre','.',$b);
- $testa = explode('.',$newa);
- if(@$testa[1] == '')
- {
- $testa[1] = 0;
- }
- if(@$testa[3] == '')
- {
- $testa[3] = 0;
- }
- $testb = explode('.',$newb);
- if(@$testb[1] == '')
- {
- $testb[1] = 0;
- }
- if(@$testb[3] == '')
- {
- $testb[3] = 0;
- }
- $less = 0;
-
- for ($i=0;$i<count($testa);$i++)
- {
- if ($DEBUG) { echo'<br>Checking if '. (int)$testa[$i] . ' is less than ' . (int)$testb[$i] . ' ...'; }
- if ((int)$testa[$i] < (int)$testb[$i])
- {
- if ($DEBUG) { echo ' yes.'; }
- $less++;
- if ($i<3)
- {
- /* Ensure that this is definitely smaller */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely less than B."; }
- $less = 5;
- break;
- }
- }
- elseif((int)$testa[$i] > (int)$testb[$i])
- {
- if ($DEBUG) { echo ' no.'; }
- $less--;
- if ($i<2)
- {
- /* Ensure that this is definitely greater */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely greater than B."; }
- $less = -5;
- break;
- }
- }
- else
- {
- if ($DEBUG) { echo ' no, they are equal.'; }
- $less = 0;
- }
- }
- if ($DEBUG) { echo '<br>Check value is: "'.$less.'"'; }
- if ($less>0)
- {
- if ($DEBUG) { echo '<br>A is less than B'; }
- return True;
- }
- elseif($less<0)
- {
- if ($DEBUG) { echo '<br>A is greater than B'; }
- return False;
- }
- else
- {
- if ($DEBUG) { echo '<br>A is equal to B'; }
- return False;
- }
-}
-
-/**
- * eGW version checking, is eGW version in $a > $b
- *
- * @param string $a eGW version number to check if more than $b
- * @param string $b eGW version number to check check $a against
- * @return boolean True if $a > $b
- */
-function amorethanb($a,$b,$DEBUG=False)
-{
- $num = array('1st','2nd','3rd','4th');
-
- if ($DEBUG)
- {
- echo'<br>Input values: ' . 'A="'.$a.'", B="'.$b.'"';
- }
- $newa = str_replace('pre','.',$a);
- $newb = str_replace('pre','.',$b);
- $testa = explode('.',$newa);
- if($testa[3] == '')
- {
- $testa[3] = 0;
- }
- $testb = explode('.',$newb);
- if($testb[3] == '')
- {
- $testb[3] = 0;
- }
- $less = 0;
-
- for ($i=0;$i<count($testa);$i++)
- {
- if ($DEBUG) { echo'<br>Checking if '. (int)$testa[$i] . ' is more than ' . (int)$testb[$i] . ' ...'; }
- if ((int)$testa[$i] > (int)$testb[$i])
- {
- if ($DEBUG) { echo ' yes.'; }
- $less++;
- if ($i<3)
- {
- /* Ensure that this is definitely greater */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely greater than B."; }
- $less = 5;
- break;
- }
- }
- elseif((int)$testa[$i] < (int)$testb[$i])
- {
- if ($DEBUG) { echo ' no.'; }
- $less--;
- if ($i<2)
- {
- /* Ensure that this is definitely smaller */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely less than B."; }
- $less = -5;
- break;
- }
- }
- else
- {
- if ($DEBUG) { echo ' no, they are equal.'; }
- $less = 0;
- }
- }
- if ($DEBUG) { echo '<br>Check value is: "'.$less.'"'; }
- if ($less>0)
- {
- if ($DEBUG) { echo '<br>A is greater than B'; }
- return True;
- }
- elseif($less<0)
- {
- if ($DEBUG) { echo '<br>A is less than B'; }
- return False;
- }
- else
- {
- if ($DEBUG) { echo '<br>A is equal to B'; }
- return False;
- }
-}
-
-/**
- * prepend a prefix to an array of table names
- *
- * @author Adam Hull (aka fixe) - No copyright claim
- * @param $prefix the string to be prepended
- * @param $tables and array of tables to have the prefix prepended to
- * @return array of table names with the prefix prepended
- */
-function prepend_tables_prefix($prefix,$tables)
-{
- foreach($tables as $key => $value)
- {
- $tables[$key] = $prefix.$value;
- }
- return $tables;
-}
-
-/**
- * backtrace of the calling functions for php4.3+ else menuaction/scriptname
- *
- * @author RalfBecker-AT-outdoor-training.de
- * @param int $remove =0 number of levels to remove
- * @return string function-names separated by slashes (beginning with the calling function not this one)
- */
-function function_backtrace($remove=0)
-{
- if (function_exists('debug_backtrace'))
- {
- $backtrace = debug_backtrace();
- //echo "function_backtrace($remove)<pre>".print_r($backtrace,True)."</pre>\n";
- foreach($backtrace as $n => $level)
- {
- if ($remove-- < 0)
- {
- $ret[] = (isset($level['class'])?$level['class'].$level['type']:'').$level['function'].
- ($n > 0 && isset($backtrace[$n-1]['line']) ? ':'.$backtrace[$n-1]['line'] : ''). // add line number of call
- (!$level['class'] && !is_object($level['args'][0]) && $level['function'] != 'unserialize' ?
- '('.substr(str_replace(EGW_SERVER_ROOT,'',(string)$level['args'][0]),0,64).')' : '');
- }
- }
- if (is_array($ret))
- {
- return implode(' / ',$ret);
- }
- }
- return $_GET['menuaction'] ? $_GET['menuaction'] : str_replace(EGW_SERVER_ROOT,'',$_SERVER['SCRIPT_FILENAME']);
-}
-
-/**
- * check $_REQUEST data for XSS, vars containing script tags are moved to $GLOBALS['egw_unset_vars']
- *
- * @internal
- * @param array &$var reference of array to check
- * @param string $name ='' name of the array
- */
-function _check_script_tag(&$var,$name='')
-{
- static $preg=null;
- //old: '/<\/?[^>]*\b(iframe|script|javascript|on(before)?(abort|blur|change|click|dblclick|error|focus|keydown|keypress|keyup|load|mousedown|mousemove|mouseout|mouseover|mouseup|reset|select|submit|unload))\b[^>]*>/i';
- if (!isset($preg)) $preg =
- // forbidden tags like iframe or script
- '/(<(\s*\/)?\s*(iframe|script|object|embed|math|meta)[^a-z0-9]|'.
- // on* attributes
- '<[^>]*on(before)?(abort|blur|change|click|dblclick|error|focus|keydown|keypress|keyup|load|mouse[^=]+|reset|select|submit|unload|resize|propertychange|page[^=]*|scroll|readystatechange|start|popstate|form[^=]+|input)\s*=|'.
- // ="javascript:*" diverse javascript attribute value
- '<[^>]+(href|src|dynsrc|lowsrc|background|style|poster|action)\s*=\s*("|\')?[^"\']*javascript|'.
- // benavior:url and expression in style attribute
- '<[^>]+style\s*=\s*("|\')[^>]*(behavior\s*:\s*url|expression)\s*\()/i';
- if (is_array($var))
- {
- foreach($var as $key => $val)
- {
- if (is_array($val))
- {
- _check_script_tag($var[$key],$name.'['.$key.']');
- }
- elseif(strpos($val, '<') !== false) // speedup: ignore everything without <
- {
- if (preg_match($preg,$val))
- {
- // special handling for $_POST[json_data], to decend into it's decoded content, fixing json direct might break json syntax
- if ($name == '_POST' && $key == 'json_data' && ($json_data = json_decode($val, true)))
- {
- _check_script_tag($json_data, $name.'[json_data]');
- $_REQUEST[$key] = $var[$key] = json_encode($json_data);
- continue;
- }
- error_log(__FUNCTION__."(,$name) ${name}[$key] = ".$var[$key]);
- $GLOBALS['egw_unset_vars'][$name.'['.$key.']'] = $var[$key];
- // attempt to clean the thing
- $var[$key] = $val = html::purify($val);
- // check if we succeeded, if not drop the var anyway, keep the egw_unset_var in any case
- if (preg_match($preg,$val))
- {
- error_log("*** _check_script_tag($name): unset(${name}[$key]) with value $val***");
- unset($var[$key]);
- }
- }
- }
- }
- // in case some stupid old code expects the array-pointer to be at the start of the array
- reset($var);
- }
-}
-
-/* some _check_script_tag tests, should be commented out by default
-if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__) // some tests
-{
- if (!defined('EGW_INCLUDE_ROOT'))
- {
- define(EGW_INCLUDE_ROOT, realpath(dirname(__FILE__).'/../..'));
- define(EGW_API_INC, realpath(dirname(__FILE__)));
- }
-
- $total = $num_failed = 0;
- $patterns = array(
- // pattern => true: should fail, false: should not fail
- '< script >alert(1)< / script >' => true,
- '<span onMouseOver ="alert(1)">blah</span>' => true,
- '<a href= "JaVascript: alert(1)">Click Me</a>' => true,
- // from https://www.acunetix.com/websitesecurity/cross-site-scripting/
- '<body onload=alert("XSS")>' => true,
- '<body background="javascript:alert("XSS")">' => true,
- '<iframe src=âhttp://evil.com/xss.htmlâ>' => true,
- '<input type="image" src="javascript:alert(\'XSS\');">' => true,
- '<link rel="stylesheet" href="javascript:alert(\'XSS\');">' => true,
- '<table background="javascript:alert(\'XSS\')">' => true,
- '<td background="javascript:alert(\'XSS\')">' => true,
- '<div style="background-image: url(javascript:alert(\'XSS\'))">' => true,
- '<div style="width: expression(alert(\'XSS\'));">' => true,
- '<object type="text/x-scriptlet" data="http://hacker.com/xss.html">' => true,
- // false positiv tests
- 'If 1 < 2, what does that mean for description, if 2 > 1.' => false,
- 'If 1 < 2, what does that mean for a script, if 2 > 1.' => false,
- '<div>Script and Javascript: not evil ;-)' => false,
- '<span>style=background-color' => false,
- '<font face="Script MT Bold" size="4"><span style="font-size:16pt;">Hugo Sonstwas</span></font>' => false,
- '<[email protected]>' => false,
- );
- foreach($patterns as $pattern => $should_fail)
- {
- $test = array($pattern);
- unset($GLOBALS['egw_unset_vars']);
- _check_script_tag($test,'test');
- $failed = isset($GLOBALS['egw_unset_vars']) !== $should_fail;
- ++$total;
- if ($failed) $num_failed++;
- echo "<p style='color: ".($failed?'red':'black')."'> ".html::htmlspecialchars($pattern).' '.
- (isset($GLOBALS['egw_unset_vars'])?'removed':'passed')."</p>";
- }
- $x = 1;
- // urls with attack vectors
- $urls = array(
- // we currently fail 76 of 666 test, thought they seem not to apply to our use case, as we check request data
- 'https://gist.github.com/JohannesHoppe/5612274' => file(
- 'https://gist.githubusercontent.com/JohannesHoppe/5612274/raw/60016bccbfe894dcd61a6be658a4469e403527de/666_lines_of_XSS_vectors.html'),
- // we currently fail 44 of 140 tests, thought they seem not to apply to our use case, as we check request data
- 'https://html5sec.org/' => call_user_func(function() {
- $payloads = $items = null;
- if (!($items_js = file_get_contents('https://html5sec.org/items.js')) ||
- !preg_match_all("|^\s+'data'\s+:\s+'(.*)',$|m", $items_js, $items, PREG_PATTERN_ORDER) ||
- !($payload_js = file_get_contents('https://html5sec.org/payloads.js')) ||
- !preg_match_all("|^\s+'([^']+)'\s+:\s+'(.*)',$|m", $payload_js, $payloads, PREG_PATTERN_ORDER))
- {
- return false;
- }
- $replace = array(
- "\\'" => "'",
- '\\\\'=> '\\,',
- '\r' => "\r",
- '\n' => "\n",
- );
- foreach($payloads[1] as $n => $from) {
- $replace['%'.$from.'%'] = $payloads[2][$n];
- }
- return array_map(function($item) use ($replace) {
- return strtr($item, $replace);
- }, $items[1]);
- }),
- );
- foreach($urls as $url => $vectors)
- {
- // no all xss attack vectors from http://ha.ckers.org/xssAttacks.xml are relevant here! (needs interpretation)
- if (!$vectors)
- {
- echo "<p style='color:red'>Could NOT download or parse $url with attack vectors!</p>\n";
- continue;
- }
- echo "<p><b>Attacks from <a href='$url' target='_blank'>$url</a> with ".count($vectors)." tests:</b></p>";
- foreach($vectors as $line => $pattern)
- {
- $test = array($pattern);
- unset($GLOBALS['egw_unset_vars']);
- _check_script_tag($test, 'line '.(1+$line));
- $failed = !isset($GLOBALS['egw_unset_vars']);
- ++$total;
- if ($failed) $num_failed++;
- echo "<p style='color: ".($failed?'red':'black')."'>".(1+$line).": ".html::htmlspecialchars($pattern).' '.
- (isset($GLOBALS['egw_unset_vars'])?'removed':'passed')."</p>";
- }
- }
- die("<p style='color: ".($num_failed?'red':'black')."'>Tests finished: $num_failed / $total failed</p>");
-}*/
-
-foreach(array('_GET','_POST','_REQUEST','HTTP_GET_VARS','HTTP_POST_VARS') as $n => $where)
-{
- $pregs = array(
- 'order' => '/^[a-zA-Z0-9_,]*$/',
- 'sort' => '/^(ASC|DESC|asc|desc|0|1|2|3|4|5|6|7){0,1}$/',
- );
- foreach(array('order','sort') as $name)
- {
- if (isset($GLOBALS[$where][$name]) && !is_array($GLOBALS[$where][$name]) && !preg_match($pregs[$name],$GLOBALS[$where][$name]))
- {
- $GLOBALS[$where][$name] = '';
- }
- }
- // do the check for script-tags only for _GET and _POST or if we found something in _GET and _POST
- // speeds up the execusion a bit
- if (isset($GLOBALS[$where]) && is_array($GLOBALS[$where]) && ($n < 2 || isset($GLOBALS['egw_unset_vars'])))
- {
- _check_script_tag($GLOBALS[$where],$where);
- }
-}
-//if (is_array($GLOBALS['egw_unset_vars'])) { echo "egw_unset_vars=<pre>".htmlspecialchars(print_r($GLOBALS['egw_unset_vars'],true))."</pre>"; exit; }
-
-// $GLOBALS[egw_info][flags][currentapp] and die if it contains something nasty or unexpected
-if (isset($GLOBALS['egw_info']) && isset($GLOBALS['egw_info']['flags']) &&
- isset($GLOBALS['egw_info']['flags']['currentapp']) && !preg_match('/^[A-Za-z0-9_-]+$/',$GLOBALS['egw_info']['flags']['currentapp']))
-{
- error_log(__FILE__.': '.__LINE__.' Invalid $GLOBALS[egw_info][flags][currentapp]='.array2string($GLOBALS['egw_info']['flags']['currentapp']).', $_SERVER[REQUEST_URI]='.array2string($_SERVER[REQUEST_URI]));
- die('Invalid $GLOBALS[egw_info][flags][currentapp]!');
-}
-
-// neutralises register_globals On, which is not used by eGW
-// some code from the hardend php project: http://www.hardened-php.net/articles/PHPUG-PHP-Sicherheit-Parametermanipulationen.pdf
-if (ini_get('register_globals'))
-{
- function unregister_globals()
- {
- // protect against GLOBALS overwrite or setting egw_info
- if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS']) || isset($_REQUEST['egw_info']) || isset($_FILES['egw_info']))
- {
- die('GLOBALS overwrite detected!!!');
- }
- // unregister all globals
- $noUnset = array('GLOBALS','_GET','_POST','_COOKIE','_SERVER','_ENV','_FILES','xajax');
- foreach(array_unique(array_merge(
- array_keys($_GET),array_keys($_POST),array_keys($_COOKIE),array_keys($_SERVER),array_keys($_ENV),array_keys($_FILES),
- isset($_SESSION) && is_array($_SESSION) ? array_keys($_SESSION) : array())) as $k)
- {
- if (!in_array($k,$noUnset) && isset($GLOBALS[$k]))
- {
- unset($GLOBALS[$k]);
- }
- }
- }
- unregister_globals();
-}
-
-if (!function_exists('lang') || defined('NO_LANG')) // setup declares an own version
-{
- /**
- * function to handle multilanguage support
- *
- * @param string $key message in englich with %1, %2, ... placeholders
- * @param string $vars =null multiple values to replace the placeholders
- * @return string translated message with placeholders replaced
- */
- function lang($key,$vars=null)
- {
- if(!is_array($vars))
- {
- $vars = func_get_args();
- array_shift($vars); // remove $key
- }
- return translation::translate($key,$vars);
- }
-}
/**
* Translate message only if translation object is already loaded
@@ -1706,113 +32,7 @@
$vars = func_get_args();
array_shift($vars); // remove $key
}
- return class_exists(translations,false) ? translation::translate($key,$vars) : str_replace($varnames,$vars,$key);
-}
-
-/**
- * Unserialize a php serialized string, but only if it contains NO objects 'O:\d:"' or 'C:\d:"' pattern
- *
- * Should be used for all external content, to guard against exploidts.
- *
- * PHP 7.0+ can be told not to instanciate any classes (and calling eg. it's destructor).
- * In fact it instanciates it as __PHP_Incomplete_Class without any methods and therefore disarming threads.
- *
- * @param string $str
- * @return mixed
- */
-function php_safe_unserialize($str)
-{
- if (PHP_VERSION >= 7)
- {
- return unserialize($str, array('allowed_classes' => false));
- }
- if ((strpos($str, 'O:') !== false || strpos($str, 'C:') !== false) &&
- preg_match('/(^|;|{)[OC]:\d+:"/', $str))
- {
- error_log(__METHOD__."('$str') contains objects --> return NULL");
- return null; // null, not false, to not trigger behavior of returning string itself to app code
- }
- return unserialize($str);
-}
-
-/* some test for object safe unserialisation
-if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__) // some tests
-{
- if (php_sapi_name() !== 'cli') echo "<pre>\n";
- foreach(array(
- // things unsafe to unserialize
- "O:34:\"Horde_Kolab_Server_Decorator_Clean\":2:{s:43:\"\x00Horde_Kolab_Server_Decorator_Clean\x00_server\";" => false,
- "O:20:\"Horde_Prefs_Identity\":2:{s:9:\"\x00*\x00_prefs\";O:11:\"Horde_Prefs\":2:{s:8:\"\x00*\x00_opts\";a:1:{s:12:\"sizecallback\";" => false,
- "a:2:{i:0;O:12:\"Horde_Config\":1:{s:13:\"\x00*\x00_oldConfig\";s:#{php_injection.length}:\"#{php_injection}\";}i:1;s:13:\"readXMLConfig\";}}" => false,
- 'a:6:{i:0;i:0;i:1;d:2;i:2;s:4:"ABCD";i:3;r:3;i:4;O:8:"my_Class":2:{s:1:"a";r:6;s:1:"b";N;};i:5;C:16:"SplObjectStorage":14:{x:i:0;m:a:0:{}}' => false,
- serialize(new stdClass()) => false,
- serialize(array(new stdClass(), new SplObjectStorage())) => false,
- // string content, safe to unserialize
- serialize('O:8:"stdClass"') => true,
- serialize('C:16:"SplObjectStorage"') => true,
- serialize(array('a' => 'O:8:"stdClass"', 'b' => 'C:16:"SplObjectStorage"')) => true,
- // false positive: failing our php<7 regular expression, because it has correct delimiter (^|;|{) in front of pattern :-(
- serialize('O:8:"stdClass";C:16:"SplObjectStorage"') => true,
- ) as $str => $result)
- {
- if ((bool)($r=php_safe_unserialize($str)) !== $result)
- {
- if (!$result)
- {
- if (PHP_VERSION >= 7)
- {
- if (preg_match_all('/([^ ]+) Object\(/', array2string($r), $matches))
- {
- foreach($matches[1] as $class)
- {
- if (!preg_match('/^__PHP_Incomplete_Class(#\d+)?$/', $class))
- {
- echo "FAILED: $str\n";
- continue 2;
- }
- }
- }
- echo "passed: ".array2string($str)." = ".array2string($r)."\n";
- }
- else
- {
- echo "FAILED: $str\n";
- }
- }
- else
- {
- echo "false positive: $str\n";
- }
- }
- else
- {
- echo "passed: $str\n";
- }
- //echo "result=".array2string($result).", php_save_unserialize('".htmlspecialchars($str)."') = ".array2string(php_safe_unserialize($str))." --> ".array2string((bool)php_safe_unserialize($str))."\n";
- }
-}*/
-
-/**
- * Unserialize a json or php serialized array
- *
- * Used to migrate from PHP serialized database values to json-encoded ones.
- *
- * @param string $str string with serialized array
- * @param boolean $allow_not_serialized =false true: return $str as is, if it is no serialized array
- * @return array|str|false
- */
-function json_php_unserialize($str, $allow_not_serialized=false)
-{
- if ((in_array($str[0], array('a', 'i', 's', 'b', 'O', 'C')) && $str[1] == ':' || $str === 'N;') &&
- ($arr = php_safe_unserialize($str)) !== false || $str === 'b:0;')
- {
- return $arr;
- }
- if (!$allow_not_serialized || $str[0] == '[' || $str[0] == '{' || $str[0] == '"' || $str === 'null' || ($val = json_decode($str)) !== null)
- {
- return isset($val) ? $val : json_decode($str, true);
- }
- return $str;
+ return class_exists('EGroupware\Api\Translations',false) ? Api\Translation::translate($key,$vars) : str_replace($varnames,$vars,$key);
}
/**
@@ -1892,13 +112,13 @@
if (!isset($GLOBALS['egw_info']['flags']['no_exception_handler']))
{
header('HTTP/1.1 500 '.$headline);
- $message = '<h3>'.html::htmlspecialchars($headline)."</h3>\n".
- '<pre><b>'.html::htmlspecialchars($e->getMessage())."</b>\n\n";
+ $message = '<h3>'.Api\Html::htmlspecialchars($headline)."</h3>\n".
+ '<pre><b>'.Api\Html::htmlspecialchars($e->getMessage())."</b>\n\n";
// only show trace (incl. function arguments) if explicitly enabled, eg. on a development system
if ($GLOBALS['egw_info']['server']['exception_show_trace'])
{
- $message .= html::htmlspecialchars($e->getTraceAsString());
+ $message .= Api\Html::htmlspecialchars($e->getTraceAsString());
}
$message .= "</pre>\n";
if (is_a($e, 'EGroupware\Api\Db\Exception\Setup'))
@@ -1916,7 +136,7 @@
}
else
{
- echo "<html>\n<head>\n<title>".html::htmlspecialchars($headline)."</title>\n</head>\n<body>\n$message\n</body>\n</html>\n";
+ echo "<html>\n<head>\n<title>".Api\Html::htmlspecialchars($headline)."</title>\n</head>\n<body>\n$message\n</body>\n</html>\n";
}
}
// exception handler sending message back to the client as basic auth message
@@ -1926,10 +146,6 @@
header('WWW-Authenticate: Basic realm="'.$headline.' '.$error.'"');
header('HTTP/1.1 401 Unauthorized');
header('X-WebDAV-Status: 401 Unauthorized', true);
- }
- if (is_object($GLOBALS['egw']))
- {
- common::egw_exit();
}
exit;
}
@@ -1977,17 +193,3 @@
// install our error-handler only for catchable fatal errors and warnings
// following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING
set_error_handler('egw_error_handler', E_RECOVERABLE_ERROR|E_USER_ERROR|E_WARNING|E_USER_WARNING);
-
-// some not longer necessary defines
-if (isset($GLOBALS['egw_info']['flags']['phpgw_compatibility']) && $GLOBALS['egw_info']['flags']['phpgw_compatibility'])
-{
- define('PHPGW_API_INC',EGW_API_INC);
- define('PHPGW_SERVER_ROOT',EGW_SERVER_ROOT);
- define('PHPGW_INCLUDE_ROOT',EGW_INCLUDE_ROOT);
-
- /* debugging settings */
- define('DEBUG_DATATYPES', True);
- define('DEBUG_LEVEL', 3);
- define('DEBUG_OUTPUT', 2); /* 1 = screen, 2 = DB. For both use 3. */
- define('DEBUG_TIMER', False);
-}
Copied: trunk/egroupware/api/src/loader/security.php (from r55840, trunk/phpgwapi/inc/common_functions.inc.php)
URL: http://svn.stylite.de/viewvc/egroupware/trunk/egroupware/api/src/loader/security.php?p2=trunk/egroupware/api/src/loader/security.php&p1=trunk/phpgwapi/inc/common_functions.inc.php&r1=55840&r2=55853&rev=55853&view=diff
==============================================================================
--- trunk/phpgwapi/inc/common_functions.inc.php (original)
+++ trunk/egroupware/api/src/loader/security.php Tue Apr 26 16:38:08 2016
@@ -1,11 +1,8 @@
<?php
/**
- * EGroupware commonly used functions
- *
- * This file was originaly written by Dan Kuykendall and Joseph Engo
- * Copyright (C) 2000, 2001 Dan Kuykendall
- *
- * All newer parts (XSS checks, autoloading, exception handler, ...) are written by Ralf Becker.
+ * EGroupware XSS protection and other security relevant functions
+ *
+ * Usually loaded via header.inc.php or api/src/loader/common.php
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
@@ -15,1445 +12,6 @@
*/
use EGroupware\Api;
-
-// this is only neccessary, if header.inc.php is not included, but common_functions.inc.php directly
-if (!defined('EGW_SERVER_ROOT'))
-{
- define('EGW_SERVER_ROOT', dirname(dirname(__DIR__)));
- define('EGW_INCLUDE_ROOT', EGW_SERVER_ROOT);
- define('EGW_API_INC', __DIR__);
-}
-
-/**
- * New PSR-4 autoloader for EGroupware
- *
- * class_exists('\\EGroupware\\Api\\Vfs'); // /api/src/Vfs.php
- * class_exists('\\EGroupware\\Api\\Vfs\\Dav\\Directory'); // /api/src/Vfs/Dav/Directory.php
- * class_exists('\\EGroupware\\Api\\Vfs\\Sqlfs\\StreamWrapper'); // /api/src/Vfs/Sqlfs/StreamWrapper.php
- * class_exists('\\EGroupware\\Api\\Vfs\\Sqlfs\\Utils'); // /api/src/Vfs/Sqlfs/Utils.php
- * class_exists('\\EGroupware\\Stylite\\Versioning\\StreamWrapper'); // /stylite/src/Versioning/StreamWrapper.php
- * class_exists('\\EGroupware\\Calendar\\Ui'); // /calendar/src/Ui.php
- * class_exists('\\EGroupware\\Calendar\\Ui\\Lists'); // /calendar/src/Ui/Lists.php
- * class_exists('\\EGroupware\\Calendar\\Ui\\Views'); // /calendar/src/Ui/Views.php
- */
-spl_autoload_register(function($class)
-{
- $parts = explode('\\', $class);
- if (array_shift($parts) != 'EGroupware') return; // not our prefix
-
- $app = lcfirst(array_shift($parts));
- $base = EGW_INCLUDE_ROOT.'/'.$app.'/src/';
- $path = $base.implode('/', $parts).'.php';
-
- if (file_exists($path))
- {
- require_once $path;
- //error_log("PSR4_autoload('$class') --> require_once($path) --> class_exists('$class')=".array2string(class_exists($class,false)));
- }
-});
-
-/**
- * Old autoloader for EGroupware understanding the following naming schema:
- *
- * 1. new (prefered) nameing schema: app_class_something loading app/inc/class.class_something.inc.php
- * 2. API classes: classname loading phpgwapi/inc/class.classname.inc.php
- * 2a.API classes containing multiple classes per file eg. egw_exception* in class.egw_exception.inc.php
- * 3. eTemplate classes: classname loading etemplate/inc/class.classname.inc.php
- *
- * @param string $class name of class to load
- */
-spl_autoload_register(function($class)
-{
- // fixing warnings generated by php 5.3.8 is_a($obj) trying to autoload huge strings
- if (strlen($class) > 64 || strpos($class, '.') !== false) return;
-
- $components = explode('_',$class);
- $app = array_shift($components);
- // classes using the new naming schema app_class_name, eg. admin_cmd
- if (file_exists($file = EGW_INCLUDE_ROOT.'/'.$app.'/inc/class.'.$class.'.inc.php') ||
- // classes using the new naming schema app_class_name, eg. admin_cmd
- isset($components[0]) && file_exists($file = EGW_INCLUDE_ROOT.'/'.$app.'/inc/class.'.$app.'_'.$components[0].'.inc.php') ||
- // classes with an underscore in their name
- !isset($GLOBALS['egw_info']['apps'][$app]) && isset($GLOBALS['egw_info']['apps'][$app . '_' . $components[0]]) &&
- file_exists($file = EGW_INCLUDE_ROOT.'/'.$app.'_'.$components[0].'/inc/class.'.$class.'.inc.php') ||
- // eGW api classes using the old naming schema, eg. html
- file_exists($file = EGW_API_INC.'/class.'.$class.'.inc.php') ||
- // eGW api classes containing multiple classes in on file, eg. egw_exception
- isset($components[0]) && file_exists($file = EGW_API_INC.'/class.'.$app.'_'.$components[0].'.inc.php') ||
- // eGW eTemplate classes using the old naming schema, eg. etemplate
- file_exists($file = EGW_INCLUDE_ROOT.'/etemplate/inc/class.'.$class.'.inc.php') ||
- // include PEAR and PSR0 classes from include_path
- // need to use include (not include_once) as eg. a previous included EGW_API_INC/horde/Horde/String.php causes
- // include_once('Horde/String.php') to return true, even if the former was included with an absolute path
- // only use include_path, if no Composer vendor directory exists
- !isset($GLOBALS['egw_info']['apps'][$app]) && !file_exists(EGW_SERVER_ROOT.'/vendor') &&
- @include($file = strtr($class, array('_'=>'/','\\'=>'/')).'.php'))
- {
- include_once($file);
- //if (!class_exists($class, false) && !interface_exists($class, false)) error_log("autoloading class $class by include_once($file) failed!");
- }
- // allow apps to define an own autoload method
- elseif (isset($GLOBALS['egw_info']['flags']['autoload']) && is_callable($GLOBALS['egw_info']['flags']['autoload']))
- {
- call_user_func($GLOBALS['egw_info']['flags']['autoload'],$class);
- }
-});
-
-// if we have a Composer vendor directory, also load it's autoloader, to allow manage our requirements with Composer
-if (file_exists(EGW_SERVER_ROOT.'/vendor'))
-{
- require_once EGW_SERVER_ROOT.'/vendor/autoload.php';
-}
-
-/**
-* applies stripslashes recursivly on each element of an array
-*
-* @param array &$var
-* @return array
-*/
-function array_stripslashes($var)
-{
- if (!is_array($var))
- {
- return stripslashes($var);
- }
- foreach($var as $key => $val)
- {
- $var[$key] = is_array($val) ? array_stripslashes($val) : stripslashes($val);
- }
- return $var;
-}
-
-/**
- * Return the number of bytes of a string, independent of mbstring.func_overload
- * AND the availability of mbstring
- *
- * @param string $str
- * @return int
- */
-function bytes($str)
-{
- static $func_overload = null;
-
- if (is_null($func_overload)) $func_overload = extension_loaded('mbstring') ? ini_get('mbstring.func_overload') : 0;
-
- return $func_overload & 2 ? mb_strlen($str,'ascii') : strlen($str);
-}
-
-/**
- * mbstring.func_overload safe substr
- *
- * @param string $data
- * @param int $offset
- * @param int $len
- * @return string
- */
-function cut_bytes(&$data,$offset,$len=null)
-{
- static $func_overload = null;
-
- if (is_null($func_overload)) $func_overload = extension_loaded('mbstring') ? ini_get('mbstring.func_overload') : 0;
-
- if (is_null($len))
- {
- return $func_overload & 2 ? mb_substr($data,$offset,bytes($data),'ascii') : substr($data,$offset);
- }
- return $func_overload & 2 ? mb_substr($data,$offset,$len,'ascii') : substr($data,$offset,$len);
-}
-
-if (!function_exists('imap_rfc822_parse_adrlist'))
-{
- /**
- * parses a (comma-separated) address string
- *
- * Examples:
- * - Joe Doe <[email protected]>
- * - "Doe, Joe" <[email protected]>
- * - "\'Joe Doe\'" <[email protected]> // actually not necessary to quote
- * - [email protected]
- * - root
- * - "Joe on its way Down Under :-\)" <[email protected]>
- * - "Giant; \"Big\" Box" <[email protected]>
- * - [email protected] <[email protected]> // this is wrong, because @ need to be quoted
- *
- * Invalid addresses, if detected, set host to '.SYNTAX-ERROR.'
- *
- * @param string $address - A string containing addresses
- * @param string $default_host - The default host name
- * @return array of objects. The objects properties are:
- * mailbox - the mailbox name (username)
- * host - the host name
- * personal - the personal name
- * adl - at domain source route
- */
- function imap_rfc822_parse_adrlist($address, $default_host)
- {
- $addresses = array();
- $pending = '';
- foreach(explode(',', $address) as $part)
- {
- $trimmed = trim(($pending ? $pending.',' : '').$part);
- if (($trimmed[0] == '"' && substr($trimmed, -1) != '>')||strpos($part, '@')===false)
- {
- $pending .= ($pending ? $pending.',' : '').$part;
- continue;
- }
- $pending = '';
- $matches = $personal = $mailbox = $host = null;
- if (preg_match('/^(.*)<([^>@]+)(@([^>]+))?>$/', $trimmed, $matches))
- {
- $personal = trim($matches[1]);
- $mailbox = $matches[2];
- $host = $matches[4];
- }
- elseif (strpos($trimmed, '@') !== false)
- {
- list($mailbox, $host) = explode('@', $trimmed);
- }
- else
- {
- $mailbox = $trimmed;
- }
- if ($personal[0] == '"' && substr($personal, -1) == '"')
- {
- $personal = str_replace('\\', '', substr($personal, 1, -1));
- }
- if (empty($host)) $host = $default_host;
-
- $addresses[] = (object)array_diff(array(
- 'mailbox' => $mailbox,
- 'host' => $host,
- 'personal' => $personal,
- ), array(null, ''));
- }
- return $addresses;
- }
-}
-
-if (!function_exists('imap_rfc822_write_address'))
-{
- /**
- * Returns a properly formatted email address given the mailbox, host, and personal info
- * @param string $mailbox - The mailbox name, see imap_open() for more information
- * @param string $host - The email host part
- * @param string $personal - The name of the account owner
- * @return string properly formatted email address as defined in » RFC2822.
- */
- function imap_rfc822_write_address($mailbox, $host, $personal)
- {
- if (is_array($personal)) $personal = implode(' ', $personal);
-
- //if (!preg_match('/^[!#$%&\'*+/0-9=?A-Z^_`a-z{|}~-]+$/u', $personal)) // that's how I read the rfc(2)822
- if ($personal && !preg_match('/^[0-9A-Z -]*$/iu', $personal)) // but quoting is never wrong, so quote more then necessary
- {
- $personal = '"'.str_replace(array('\\', '"'),array('\\\\', '\\"'), $personal).'"';
- }
- return ($personal ? $personal.' <' : '').$mailbox.($host ? '@'.$host : '').($personal ? '>' : '');
- }
-}
-
-if (!function_exists('imap_mime_header_decode'))
-{
- /**
- * Decodes MIME message header extensions that are non ASCII text (RFC2047)
- *
- * Uses Horde_Mime::decode() and therefore always returns only a single array element!
- *
- * @param string $text
- * @return array with single object with attribute text already in our internal encoding and charset
- * @deprecated use Horde_Mime::decode()
- */
- function imap_mime_header_decode($text)
- {
- return array((object)array(
- 'text' => Horde_Mime::decode($text),
- 'charset' => translation::charset(), // is already in our internal encoding!
- ));
- }
-}
-
-if (!function_exists('mb_strlen'))
-{
- /**
- * Number of characters in a string
- *
- * @param string $str
- * @return int
- */
- function mb_strlen($str)
- {
- return strlen($str);
- }
-}
-
-if (!function_exists('mb_substr'))
-{
- /**
- * Return part of a string
- *
- * @param string $data
- * @param int $offset
- * @param int $len
- * @return string
- */
- function mb_substr(&$data, $offset, $len=null)
- {
- return is_null($len) ? substr($data, $offset) : substr($data, $offset, $len);
- }
-}
-
-/**
- * Format array or other types as (one-line) string, eg. for error_log statements
- *
- * @param mixed $var variable to dump
- * @return string
- */
-function array2string($var)
-{
- switch (($type = gettype($var)))
- {
- case 'boolean':
- return $var ? 'TRUE' : 'FALSE';
- case 'string':
- return "'$var'";
- case 'integer':
- case 'double':
- case 'resource':
- return $var;
- case 'NULL':
- return 'NULL';
- case 'object':
- case 'array':
- return str_replace(array("\n",' '/*,'Array'*/),'',print_r($var,true));
- }
- return 'UNKNOWN TYPE!';
-}
-
-/**
- * Check if a given extension is loaded or load it if possible (requires sometimes disabled or unavailable dl function)
- *
- * @param string $extension
- * @param boolean $throw =false should we throw an exception, if $extension could not be loaded, default false = no
- * @return boolean true if loaded now, false otherwise
- */
-function check_load_extension($extension,$throw=false)
-{
- if (!defined('PHP_SHLIB_PREFIX'))
- {
- define('PHP_SHLIB_PREFIX',PHP_SHLIB_SUFFIX == 'dll' ? 'php_' : '');
- }
- // we check for the existens of 'dl', as multithreaded webservers dont have it and some hosters disable it !!!
- $loaded = extension_loaded($extension) || function_exists('dl') && @dl($dl=PHP_SHLIB_PREFIX.$extension.'.'.PHP_SHLIB_SUFFIX);
-
- if (!$loaded && $throw)
- {
- throw new Exception ("PHP extension '$extension' not loaded AND can NOT be loaded via dl('$dl')!");
- }
- return $loaded;
-}
-
-/**
- * @internal Not to be used directly. Should only be used by print_debug()
- */
-function print_debug_subarray($array)
-{
- foreach($array as $key => $value)
- {
- if (is_array($value))
- {
- $vartypes[$key] = print_debug_subarray($value);
- }
- else
- {
- $vartypes[$key] = gettype($value);
- }
- }
- return $vartypes;
-}
-
-/**
- * print debug data only when debugging mode is turned on.
- *
- * @author seek3r
- * This function is used to debugging data.
- * print_debug('this is some debugging data',$somevar);
- */
-function print_debug($message,$var = 'messageonly',$part = 'app', $level = 3)
-{
- if (($part == 'app' && DEBUG_APP == True) || ($part == 'api' && DEBUG_API == True))
- {
- if (!defined('DEBUG_OUTPUT'))
- {
- define('DEBUG_OUTPUT', 1);
- }
- if ($level >= DEBUG_LEVEL)
- {
- if (!is_array($var))
- {
- if ($var != 'messageonly')
- {
- if (!DEBUG_DATATYPES)
- {
- $output = "$message\n$var";
- }
- else
- {
- $output = "$message\n$var is a ".gettype($var);
- }
- }
- else
- {
- $output = $message;
- }
-
- /* Bit 1 means to output to screen */
- if (!!(DEBUG_OUTPUT & 1))
- {
- echo "$output<br>\n";
- }
- /* Bit 2 means to output to sql */
- if (!!(DEBUG_OUTPUT & 2))
- {
- /* Need to flesh this out still. I dont have a table to dump this in yet.*/
- /* So the SQL statement will go here*/
- }
-
- /* Example of how this can be extended to output to other locations as well. This example uses a COM object */
- /*
- if (!!(DEBUG_OUTPUT & 32))
- {
- $obj_debug = new COM('Some_COM_App.Class','localhost');
- if (is_object($obj_debug))
- {
- $DebugMessage_return = $obj_debug->DebugMessage($output);
- }
- }
- */
- }
- else
- {
- if (floor(phpversion()) > 3 && !!(DEBUG_OUTPUT & 2))
- {
- ob_start();
- }
- echo "<pre>\n$message\n";
- print_r($var);
- if (DEBUG_DATATYPES)
- {
- foreach($var as $key => $value)
- {
- if (is_array($value))
- {
- $vartypes[$key] = print_debug_subarray($value);
- }
- else
- {
- $vartypes[$key] = gettype($value);
- }
- }
- echo "Data Types:\n";
- print_r($vartypes);
- }
- echo "\n<pre>\n";
- if (floor(phpversion()) > 3 && !!(DEBUG_OUTPUT & 2))
- {
- $output .= ob_get_contents();
- ob_end_clean();
- /* Need to flesh this out still. I dont have a table to dump this in yet.*/
- /* So the SQL statement will go here*/
- if (!!(DEBUG_OUTPUT & 1))
- {
- echo "$output<br>\n";
- }
- }
- }
- }
- }
-}
-
-/**
- * Allows for array and direct function params as well as sanatization.
- *
- * @author seek3r
- * This function is used to validate param data as well as offer flexible function usage.
- *
- function somefunc()
- {
- $expected_args[0] = Array('name'=>'fname','default'=>'joe', 'type'=>'string');
- $expected_args[1] = Array('name'=>'mname','default'=>'hick', 'type'=>'string');
- $expected_args[2] = Array('name'=>'lname','default'=>'bob', 'type'=>'string');
- $recieved_args = func_get_args();
- $args = safe_args($expected_args, $recieved_args,__LINE__,__FILE__);
- echo 'Full name: '.$args['fname'].' '.$args['fname'].' '.$args['lname'].'<br>';
- //default result would be:
- // Full name: joe hick bob<br>
- }
-
- Using this it is possible to use the function in any of the following ways
- somefunc('jack','city','brown');
- or
- somefunc(array('fname'=>'jack','mname'=>'city','lname'=>'brown'));
- or
- somefunc(array('lname'=>'brown','fname'=>'jack','mname'=>'city'));
-
- For the last one, when using named params in an array you dont have to follow any order
- All three would result in - Full name: jack city brown<br>
-
- When you use this method of handling params you can secure your functions as well offer
- flexibility needed for both normal use and web services use.
- If you have params that are required just set the default as ##REQUIRED##
- Users of your functions can also use ##DEFAULT## to use your default value for a param
- when using the standard format like this:
- somefunc('jack','##DEFAULT##','brown');
- This would result in - Full name: jack hick brown<br>
- Its using the default value for the second param.
- Of course if you have the second param as a required field it will fail to work.
- */
-function safe_args($expected, $recieved, $line='??', $file='??')
-{
- /* This array will contain all the required fields */
- $required = Array();
-
- /* This array will contain all types for sanatization checking */
- /* only used when an array is passed as the first arg */
- $types = Array();
-
- /* start by looping thru the expected list and set params with */
- /* the default values */
- $num = count($expected);
- for ($i = 0; $i < $num; $i++)
- {
- $args[$expected[$i]['name']] = $expected[$i]['default'];
- if ($expected[$i]['default'] === '##REQUIRED##')
- {
- $required[$expected[$i]['name']] = True;
- }
- $types[$expected[$i]['name']] = $expected[$i]['type'];
- }
-
- /* Make sure they passed at least one param */
- if(count($recieved) != 0)
- {
- /* if used as standard function we loop thru and set by position */
- if(!is_array($recieved[0]))
- {
- for ($i = 0; $i < $num; $i++)
- {
- if(isset($recieved[$i]) && $recieved[$i] !== '##DEFAULT##')
- {
- if(sanitize($recieved[$i],$expected[$i]['type']))
- {
- $args[$expected[$i]['name']] = $recieved[$i];
- unset($required[$expected[$i]['name']]);
- }
- else
- {
- echo 'Fatal Error: Invalid paramater type for '.$expected[$i]['name'].' on line '.$line.' of '.$file.'<br>';
- exit;
- }
- }
- }
- }
- /* if used as standard function we loop thru and set by position */
- else
- {
- for ($i = 0; $i < $num; $i++)
- {
- $types[$expected[$i]['name']] = $expected[$i]['type'];
- }
- while(list($key,$val) = each($recieved[0]))
- {
- if($val !== '##DEFAULT##')
- {
- if(sanitize($val,$types[$key]) == True)
- {
- $args[$key] = $val;
- unset($required[$key]);
- }
- else
- {
- echo 'Fatal Error: Invalid paramater type for '.$key.' on line '.$line.' of '.$file.'<br>';
- exit;
- }
- }
- }
- }
- }
- if(count($required) != 0)
- {
- while (list($key) = each($required))
- {
- echo 'Fatal Error: Missing required paramater '.$key.' on line '.$line.' of '.$file.'<br>';
- }
- exit;
- }
- return $args;
-}
-
-/**
- * Validate data.
- *
- * @author seek3r
- * This function is used to validate input data.
- * sanitize('number',$somestring);
- */
-function sanitize($string,$type)
-{
- switch ($type)
- {
- case 'bool':
- if ($string == 1 || $string == 0)
- {
- return True;
- }
- break;
-
- case 'isprint':
- $length = strlen($string);
- $position = 0;
- while ($length > $position)
- {
- $char = substr($string, $position, 1);
- if ($char < ' ' || $char > '~')
- {
- return False;
- }
- $position = $position + 1;
- }
- return True;
-
- case 'alpha':
- if (preg_match("/^[a-z]+$/i", $string))
- {
- return True;
- }
- break;
-
- case 'number':
- if (preg_match("/^[0-9]+$/i", $string))
- {
- return True;
- }
- break;
-
- case 'alphanumeric':
- if (preg_match("/^[a-z0-9 -._]+$/i", $string))
- {
- return True;
- }
- break;
- case 'string':
- if (preg_match("/^[a-z]+$/i", $string))
- {
- return True;
- }
- break;
- case 'ip':
- if (preg_match('/'."^[0-9]{1,3}(\.[0-9]{1,3}){3}$".'/i',$string))
- {
- $octets = preg_split('/\./',$string);
- for ($i=0; $i != count($octets); $i++)
- {
- if ($octets[$i] < 0 || $octets[$i] > 255)
- {
- return False;
- }
- }
- return True;
- }
- return False;
-
- case 'file':
- if (preg_match("/^[a-z0-9_]+\.+[a-z]+$/i", $string))
- {
- return True;
- }
- break;
- case 'email':
- if (preg_match('/'."^([[:alnum:]_%+=.-]+)@([[:alnum:]_.-]+)\.([a-z]{2,3}|[0-9]{1,3})$".'/i',$string))
- {
- return True;
- }
- break;
- case 'password':
- $password_length = strlen($string);
- $password_numbers = Array('0','1','2','3','4','5','6','7','8','9');
- $password_special_chars = Array(' ','~','`','!','@','#','$','%','^','&','*','(',')','_','+','-','=','{','}','|','[',']',"\\",':','"',';',"'",'<','>','?',',','.','/');
-
- if(@isset($GLOBALS['egw_info']['server']['pass_min_length']) && is_int($GLOBALS['egw_info']['server']['pass_min_length']) && $GLOBALS['egw_info']['server']['pass_min_length'] > 1)
- {
- $min_length = $GLOBALS['egw_info']['server']['pass_min_length'];
- }
- else
- {
- $min_length = 1;
- }
-
- if(@isset($GLOBALS['egw_info']['server']['pass_require_non_alpha']) && $GLOBALS['egw_info']['server']['pass_require_non_alpha'] == True)
- {
- $pass_verify_non_alpha = False;
- }
- else
- {
- $pass_verify_non_alpha = True;
- }
-
- if(@isset($GLOBALS['egw_info']['server']['pass_require_numbers']) && $GLOBALS['egw_info']['server']['pass_require_numbers'] == True)
- {
- $pass_verify_num = False;
- }
- else
- {
- $pass_verify_num = True;
- }
-
- if(@isset($GLOBALS['egw_info']['server']['pass_require_special_char']) && $GLOBALS['egw_info']['server']['pass_require_special_char'] == True)
- {
- $pass_verify_special_char = False;
- }
- else
- {
- $pass_verify_special_char = True;
- }
-
- if ($password_length >= $min_length)
- {
- for ($i=0; $i != $password_length; $i++)
- {
- $cur_test_string = substr($string, $i, 1);
- if (in_array($cur_test_string, $password_numbers) || in_array($cur_test_string, $password_special_chars))
- {
- $pass_verify_non_alpha = True;
- if (in_array($cur_test_string, $password_numbers))
- {
- $pass_verify_num = True;
- }
- elseif (in_array($cur_test_string, $password_special_chars))
- {
- $pass_verify_special_char = True;
- }
- }
- }
-
- if ($pass_verify_num == False)
- {
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password requires at least one non-alpha character']=False;
- }
-
- if ($pass_verify_num == False)
- {
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password requires at least one numeric character']=False;
- }
-
- if ($pass_verify_special_char == False)
- {
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password requires at least one special character (non-letter and non-number)']=False;
- }
-
- if ($pass_verify_num == True && $pass_verify_special_char == True)
- {
- return True;
- }
- return False;
- }
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password must be at least '.$min_length.' characters']=False;
- return False;
-
- case 'any':
- return True;
-
- default :
- if (isset($GLOBALS['egw_info']['server']['sanitize_types'][$type]['type']))
- {
- if ($GLOBALS['egw_info']['server']['sanitize_types'][$type]['type']($GLOBALS['egw_info']['server']['sanitize_types'][$type]['string'], $string))
- {
- return True;
- }
- }
- return False;
- }
-}
-
-function reg_var($varname, $method='any', $valuetype='alphanumeric',$default_value='',$register=True)
-{
- if($method == 'any' || $method == array('any'))
- {
- $method = Array('POST','GET','COOKIE','SERVER','FILES','GLOBAL','DEFAULT');
- }
- elseif(!is_array($method))
- {
- $method = Array($method);
- }
- $cnt = count($method);
- for($i=0;$i<$cnt;$i++)
- {
- switch(strtoupper($method[$i]))
- {
- case 'DEFAULT':
- if($default_value)
- {
- $value = $default_value;
- $i = $cnt+1; /* Found what we were looking for, now we end the loop */
- }
- break;
- case 'GLOBAL':
- if(@isset($GLOBALS[$varname]))
- {
- $value = $GLOBALS[$varname];
- $i = $cnt+1;
- }
- break;
- case 'POST':
- case 'GET':
- case 'COOKIE':
- case 'SERVER':
- if(phpversion() >= '4.1.0')
- {
- $meth = '_'.strtoupper($method[$i]);
- }
- else
- {
- $meth = 'HTTP_'.strtoupper($method[$i]).'_VARS';
- }
- if(@isset($GLOBALS[$meth][$varname]))
- {
- $value = $GLOBALS[$meth][$varname];
- $i = $cnt+1;
- }
- if(get_magic_quotes_gpc() && isset($value))
- {
- // we need to stripslash 3 levels of arrays
- // because of the password function in preferences
- // it's named ['user']['variablename']['pw']
- // or something like this in projects
- // $values['budgetBegin']['1']['year']
- if(@is_array($value))
- {
- /* stripslashes on the first level of array values */
- foreach($value as $name => $val)
- {
- if(@is_array($val))
- {
- foreach($val as $name2 => $val2)
- {
- if(@is_array($val2))
- {
- foreach($val2 as $name3 => $val3)
- {
- $value[$name][$name2][$name3] = stripslashes($val3);
- }
- }
- else
- {
- $value[$name][$name2] = stripslashes($val2);
- }
- }
- }
- else
- {
- $value[$name] = stripslashes($val);
- }
- }
- }
- else
- {
- /* stripslashes on this (string) */
- $value = stripslashes($value);
- }
- }
- break;
- case 'FILES':
- if(phpversion() >= '4.1.0')
- {
- $meth = '_FILES';
- }
- else
- {
- $meth = 'HTTP_POST_FILES';
- }
- if(@isset($GLOBALS[$meth][$varname]))
- {
- $value = $GLOBALS[$meth][$varname];
- $i = $cnt+1;
- }
- break;
- default:
- if(@isset($GLOBALS[strtoupper($method[$i])][$varname]))
- {
- $value = $GLOBALS[strtoupper($method[$i])][$varname];
- $i = $cnt+1;
- }
- break;
- }
- }
-
- if (@!isset($value))
- {
- $value = $default_value;
- }
-
- if (@!is_array($value))
- {
- if ($value == '')
- {
- $result = $value;
- }
- else
- {
- if (sanitize($value,$valuetype) == 1)
- {
- $result = $value;
- }
- else
- {
- $result = $default_value;
- }
- }
- }
- else
- {
- reset($value);
- while(list($k, $v) = each($value))
- {
- if ($v == '')
- {
- $result[$k] = $v;
- }
- else
- {
- if (is_array($valuetype))
- {
- $vt = $valuetype[$k];
- }
- else
- {
- $vt = $valuetype;
- }
-
- if (sanitize($v,$vt) == 1)
- {
- $result[$k] = $v;
- }
- else
- {
- if (is_array($default_value))
- {
- $result[$k] = $default_value[$k];
- }
- else
- {
- $result[$k] = $default_value;
- }
- }
- }
- }
- }
- if($register)
- {
- $GLOBALS['egw_info'][$GLOBALS['egw_info']['flags']['currentapp']][$varname] = $result;
- }
- return $result;
-}
-
-/**
- * retrieve a value from either a POST, GET, COOKIE, SERVER or from a class variable.
- *
- * @author skeeter
- * This function is used to retrieve a value from a user defined order of methods.
- * $this->id = get_var('id',array('HTTP_POST_VARS'||'POST','HTTP_GET_VARS'||'GET','HTTP_COOKIE_VARS'||'COOKIE','GLOBAL','DEFAULT'));
- * @param $variable name
- * @param $method ordered array of methods to search for supplied variable
- * @param $default_value (optional)
- */
-function get_var($variable,$method='any',$default_value='')
-{
- if(!@is_array($method))
- {
- $method = array($method);
- }
- return reg_var($variable,$method,'any',$default_value,False);
-}
-
-/**
- * Load a class and include the class file if not done so already.
- *
- * This function is used to create an instance of a class, and if the class file has not been included it will do so.
- * $GLOBALS['egw']->acl =& CreateObject('phpgwapi.acl');
- *
- * @author [email protected]
- * @param $classname name of class
- * @param $p1,$p2,... class parameters (all optional)
- * @return object reference to an object
- */
-function CreateObject($class)
-{
- list($appname,$classname) = explode('.',$class);
-
- if (!class_exists($classname))
- {
- static $replace = array(
- 'datetime' => 'egw_datetime',
- 'uitimesheet' => 'timesheet_ui',
- 'uiinfolog' => 'infolog_ui',
- 'uiprojectmanager' => 'projectmanager_ui',
- 'uiprojectelements' => 'projectmanager_elements_ui',
- 'uiroles' => 'projectmanager_roles_ui',
- 'uimilestones' => 'projectmanager_milestones_ui',
- 'uipricelist' => 'projectmanager_pricelist_ui',
- 'bowiki' => 'wiki_bo',
- 'uicategories' => 'admin_categories',
- 'defaultimap' => 'emailadmin_oldimap',
- );
- if (!file_exists(EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php') || isset($replace[$classname]))
- {
- if (isset($replace[$classname]))
- {
- //throw new Exception(__METHOD__."('$class') old classname '$classname' used in menuaction=$_GET[menuaction]!");
- error_log(__METHOD__."('$class') old classname '$classname' used in menuaction=$_GET[menuaction]!");
- $classname = $replace[$classname];
- }
- }
- if (!file_exists($f=EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php'))
- {
- throw new Api\Exception\AssertionFailed(__FUNCTION__."($classname) file $f not found!");
- }
- // this will stop php with a 500, if the class does not exist or there are errors in it (syntax error go into the error_log)
- require_once(EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php');
- }
- $args = func_get_args();
- switch(count($args))
- {
- case 1:
- $obj = new $classname;
- break;
- case 2:
- $obj = new $classname($args[1]);
- break;
- case 3:
- $obj = new $classname($args[1],$args[2]);
- break;
- case 4:
- $obj = new $classname($args[1],$args[2],$args[3]);
- break;
- default:
- $code = '$obj = new ' . $classname . '(';
- foreach(array_keys($args) as $n)
- {
- if ($n)
- {
- $code .= ($n > 1 ? ',' : '') . '$args[' . $n . ']';
- }
- }
- $code .= ');';
- eval($code);
- break;
- }
- if (!is_object($obj))
- {
- echo "<p>CreateObject('$class'): Cant instanciate class!!!<br />\n".function_backtrace(1)."</p>\n";
- }
- return $obj;
-}
-
-/**
- * Execute a function with multiple arguments
- * We take object $GLOBALS[classname] from class if exists
- *
- * @param string app.class.method method to execute
- * @example ExecObject('etemplates.so_sql.search',$criteria,$key_only,...);
- * @return mixed reference to returnvalue of the method
- */
-function &ExecMethod2($acm)
-{
- // class::method is php5.2.3+
- if (strpos($acm,'::') !== false && version_compare(PHP_VERSION,'5.2.3','<'))
- {
- list($class,$method) = explode('::',$acm);
- $acm = array($class,$method);
- }
- if (!is_callable($acm))
- {
- list(,$class,$method) = explode('.',$acm);
- if (!is_object($obj =& $GLOBALS[$class]))
- {
- if (class_exists($class))
- {
- $obj = new $class;
- }
- else
- {
- $obj = CreateObject($acm);
- }
- }
-
- if (!method_exists($obj,$method))
- {
- echo "<p><b>".function_backtrace()."</b>: no methode '$method' in class '$class'</p>\n";
- return False;
- }
- $acm = array($obj,$method);
- }
- $args = func_get_args();
- unset($args[0]);
-
- return call_user_func_array($acm,$args);
-}
-
-/**
- * Execute a function, and load a class and include the class file if not done so already.
- *
- * This function is used to create an instance of a class, and if the class file has not been included it will do so.
- *
- * @author seek3r
- * @param $method to execute
- * @param $functionparam function param should be an array
- * @param $loglevel developers choice of logging level
- * @param $classparams params to be sent to the contructor
- * @return mixed returnvalue of method
- */
-function ExecMethod($method, $functionparam = '_UNDEF_', $loglevel = 3, $classparams = '_UNDEF_')
-{
- unset($loglevel); // not used
- /* Need to make sure this is working against a single dimensional object */
- $partscount = count(explode('.',$method)) - 1;
-
- if (!is_callable($method) && $partscount == 2)
- {
- list($appname,$classname,$functionname) = explode(".", $method);
- if (!is_object($GLOBALS[$classname]))
- {
- // please note: no reference assignment (=&) here, as $GLOBALS is a reference itself!!!
- if ($classparams != '_UNDEF_' && ($classparams || $classparams != 'True'))
- {
- $GLOBALS[$classname] = CreateObject($appname.'.'.$classname, $classparams);
- }
- elseif (class_exists($classname))
- {
- $GLOBALS[$classname] = new $classname;
- }
- else
- {
- $GLOBALS[$classname] = CreateObject($appname.'.'.$classname);
- }
- }
-
- if (!method_exists($GLOBALS[$classname],$functionname))
- {
- error_log("ExecMethod('$method', ...) No methode '$functionname' in class '$classname'! ".function_backtrace());
- return false;
- }
- $method = array($GLOBALS[$classname],$functionname);
- }
- if (is_callable($method))
- {
- return $functionparam != '_UNDEF_' ? call_user_func($method,$functionparam) : call_user_func($method);
- }
- error_log("ExecMethod('$method', ...) Error in parts! ".function_backtrace());
- return false;
-}
-
-/**
- * Return a properly formatted account_id.
- *
- * @author skeeter
- * This function will return a properly formatted account_id. This can take either a name or an account_id as paramters. If a name is provided it will return the associated id.
- * $account_id = get_account_id($accountid);
- * @param int/string $account_id either a name or an id
- * @param int/string $default_id either a name or an id
- * @return int account_id
- */
-function get_account_id($account_id = '',$default_id = '')
-{
- if (gettype($account_id) == 'integer')
- {
- return $account_id;
- }
- elseif ($account_id == '')
- {
- if ($default_id == '')
- {
- return (isset($GLOBALS['egw_info']['user']['account_id'])?$GLOBALS['egw_info']['user']['account_id']:0);
- }
- elseif (is_string($default_id))
- {
- return $GLOBALS['egw']->accounts->name2id($default_id);
- }
- return (int)$default_id;
- }
- elseif (is_string($account_id))
- {
- if($GLOBALS['egw']->accounts->exists((int)$account_id) == True)
- {
- return (int)$account_id;
- }
- else
- {
- return $GLOBALS['egw']->accounts->name2id($account_id);
- }
- }
-}
-
-/**
- * sets the file system seperator depending on OS
- *
- * This is completely unnecessary, as you can use forward slashes in php under every OS -- RalfBecker 2005/11/09
- *
- * @deprecated just use forward slashes supported by PHP on all OS
- * @return file system separator
- */
-function filesystem_separator()
-{
- if(PHP_OS == 'Windows' || PHP_OS == 'OS/2' || PHP_OS == 'WINNT')
- {
- return '\\';
- }
- else
- {
- return '/';
- }
-}
-
-/**
- * @deprecated just use forward slashes supported by PHP on all OS
- */
-define('SEP', filesystem_separator());
-
-/**
- * print an array or object as pre-formatted html
- *
- * @param mixed $array
- * @param boolean $print =true print or return the content
- * @return string if !$print
- */
-function _debug_array($array,$print=True)
-{
- $output = '<pre>'.print_r($array,true)."</pre>\n";
-
- if ($print)
- {
- echo $output;
- }
- else
- {
- return $output;
- }
-}
-
-/**
- * eGW version checking, is eGW version in $a < $b
- *
- * @param string $a egw version number to check if less than $b
- * @param string $b egw version number to check $a against
- * @return boolean True if $a < $b
- */
-function alessthanb($a,$b,$DEBUG=False)
-{
- $num = array('1st','2nd','3rd','4th');
-
- if ($DEBUG)
- {
- echo'<br>Input values: ' . 'A="'.$a.'", B="'.$b.'"';
- }
- $newa = str_replace('pre','.',$a);
- $newb = str_replace('pre','.',$b);
- $testa = explode('.',$newa);
- if(@$testa[1] == '')
- {
- $testa[1] = 0;
- }
- if(@$testa[3] == '')
- {
- $testa[3] = 0;
- }
- $testb = explode('.',$newb);
- if(@$testb[1] == '')
- {
- $testb[1] = 0;
- }
- if(@$testb[3] == '')
- {
- $testb[3] = 0;
- }
- $less = 0;
-
- for ($i=0;$i<count($testa);$i++)
- {
- if ($DEBUG) { echo'<br>Checking if '. (int)$testa[$i] . ' is less than ' . (int)$testb[$i] . ' ...'; }
- if ((int)$testa[$i] < (int)$testb[$i])
- {
- if ($DEBUG) { echo ' yes.'; }
- $less++;
- if ($i<3)
- {
- /* Ensure that this is definitely smaller */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely less than B."; }
- $less = 5;
- break;
- }
- }
- elseif((int)$testa[$i] > (int)$testb[$i])
- {
- if ($DEBUG) { echo ' no.'; }
- $less--;
- if ($i<2)
- {
- /* Ensure that this is definitely greater */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely greater than B."; }
- $less = -5;
- break;
- }
- }
- else
- {
- if ($DEBUG) { echo ' no, they are equal.'; }
- $less = 0;
- }
- }
- if ($DEBUG) { echo '<br>Check value is: "'.$less.'"'; }
- if ($less>0)
- {
- if ($DEBUG) { echo '<br>A is less than B'; }
- return True;
- }
- elseif($less<0)
- {
- if ($DEBUG) { echo '<br>A is greater than B'; }
- return False;
- }
- else
- {
- if ($DEBUG) { echo '<br>A is equal to B'; }
- return False;
- }
-}
-
-/**
- * eGW version checking, is eGW version in $a > $b
- *
- * @param string $a eGW version number to check if more than $b
- * @param string $b eGW version number to check check $a against
- * @return boolean True if $a > $b
- */
-function amorethanb($a,$b,$DEBUG=False)
-{
- $num = array('1st','2nd','3rd','4th');
-
- if ($DEBUG)
- {
- echo'<br>Input values: ' . 'A="'.$a.'", B="'.$b.'"';
- }
- $newa = str_replace('pre','.',$a);
- $newb = str_replace('pre','.',$b);
- $testa = explode('.',$newa);
- if($testa[3] == '')
- {
- $testa[3] = 0;
- }
- $testb = explode('.',$newb);
- if($testb[3] == '')
- {
- $testb[3] = 0;
- }
- $less = 0;
-
- for ($i=0;$i<count($testa);$i++)
- {
- if ($DEBUG) { echo'<br>Checking if '. (int)$testa[$i] . ' is more than ' . (int)$testb[$i] . ' ...'; }
- if ((int)$testa[$i] > (int)$testb[$i])
- {
- if ($DEBUG) { echo ' yes.'; }
- $less++;
- if ($i<3)
- {
- /* Ensure that this is definitely greater */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely greater than B."; }
- $less = 5;
- break;
- }
- }
- elseif((int)$testa[$i] < (int)$testb[$i])
- {
- if ($DEBUG) { echo ' no.'; }
- $less--;
- if ($i<2)
- {
- /* Ensure that this is definitely smaller */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely less than B."; }
- $less = -5;
- break;
- }
- }
- else
- {
- if ($DEBUG) { echo ' no, they are equal.'; }
- $less = 0;
- }
- }
- if ($DEBUG) { echo '<br>Check value is: "'.$less.'"'; }
- if ($less>0)
- {
- if ($DEBUG) { echo '<br>A is greater than B'; }
- return True;
- }
- elseif($less<0)
- {
- if ($DEBUG) { echo '<br>A is less than B'; }
- return False;
- }
- else
- {
- if ($DEBUG) { echo '<br>A is equal to B'; }
- return False;
- }
-}
-
-/**
- * prepend a prefix to an array of table names
- *
- * @author Adam Hull (aka fixe) - No copyright claim
- * @param $prefix the string to be prepended
- * @param $tables and array of tables to have the prefix prepended to
- * @return array of table names with the prefix prepended
- */
-function prepend_tables_prefix($prefix,$tables)
-{
- foreach($tables as $key => $value)
- {
- $tables[$key] = $prefix.$value;
- }
- return $tables;
-}
-
-/**
- * backtrace of the calling functions for php4.3+ else menuaction/scriptname
- *
- * @author RalfBecker-AT-outdoor-training.de
- * @param int $remove =0 number of levels to remove
- * @return string function-names separated by slashes (beginning with the calling function not this one)
- */
-function function_backtrace($remove=0)
-{
- if (function_exists('debug_backtrace'))
- {
- $backtrace = debug_backtrace();
- //echo "function_backtrace($remove)<pre>".print_r($backtrace,True)."</pre>\n";
- foreach($backtrace as $n => $level)
- {
- if ($remove-- < 0)
- {
- $ret[] = (isset($level['class'])?$level['class'].$level['type']:'').$level['function'].
- ($n > 0 && isset($backtrace[$n-1]['line']) ? ':'.$backtrace[$n-1]['line'] : ''). // add line number of call
- (!$level['class'] && !is_object($level['args'][0]) && $level['function'] != 'unserialize' ?
- '('.substr(str_replace(EGW_SERVER_ROOT,'',(string)$level['args'][0]),0,64).')' : '');
- }
- }
- if (is_array($ret))
- {
- return implode(' / ',$ret);
- }
- }
- return $_GET['menuaction'] ? $_GET['menuaction'] : str_replace(EGW_SERVER_ROOT,'',$_SERVER['SCRIPT_FILENAME']);
-}
/**
* check $_REQUEST data for XSS, vars containing script tags are moved to $GLOBALS['egw_unset_vars']
@@ -1497,7 +55,7 @@
error_log(__FUNCTION__."(,$name) ${name}[$key] = ".$var[$key]);
$GLOBALS['egw_unset_vars'][$name.'['.$key.']'] = $var[$key];
// attempt to clean the thing
- $var[$key] = $val = html::purify($val);
+ $var[$key] = $val = Api\Html\HtmLawed::purify($val);
// check if we succeeded, if not drop the var anyway, keep the egw_unset_var in any case
if (preg_match($preg,$val))
{
@@ -1554,7 +112,7 @@
$failed = isset($GLOBALS['egw_unset_vars']) !== $should_fail;
++$total;
if ($failed) $num_failed++;
- echo "<p style='color: ".($failed?'red':'black')."'> ".html::htmlspecialchars($pattern).' '.
+ echo "<p style='color: ".($failed?'red':'black')."'> ".Api\Html::htmlspecialchars($pattern).' '.
(isset($GLOBALS['egw_unset_vars'])?'removed':'passed')."</p>";
}
$x = 1;
@@ -1604,7 +162,7 @@
$failed = !isset($GLOBALS['egw_unset_vars']);
++$total;
if ($failed) $num_failed++;
- echo "<p style='color: ".($failed?'red':'black')."'>".(1+$line).": ".html::htmlspecialchars($pattern).' '.
+ echo "<p style='color: ".($failed?'red':'black')."'>".(1+$line).": ".Api\Html::htmlspecialchars($pattern).' '.
(isset($GLOBALS['egw_unset_vars'])?'removed':'passed')."</p>";
}
}
@@ -1665,48 +223,6 @@
}
}
unregister_globals();
-}
-
-if (!function_exists('lang') || defined('NO_LANG')) // setup declares an own version
-{
- /**
- * function to handle multilanguage support
- *
- * @param string $key message in englich with %1, %2, ... placeholders
- * @param string $vars =null multiple values to replace the placeholders
- * @return string translated message with placeholders replaced
- */
- function lang($key,$vars=null)
- {
- if(!is_array($vars))
- {
- $vars = func_get_args();
- array_shift($vars); // remove $key
- }
- return translation::translate($key,$vars);
- }
-}
-
-/**
- * Translate message only if translation object is already loaded
- *
- * This function is usefull for exception handlers or early stages of the initialisation of the egw object,
- * as calling lang would try to load the translations, evtl. cause more errors, eg. because there's no db-connection.
- *
- * @param string $key message in englich with %1, %2, ... placeholders
- * @param string $vars =null multiple values to replace the placeholders
- * @return string translated message with placeholders replaced
- */
-function try_lang($key,$vars=null)
-{
- static $varnames = array('%1','%2','%3','%4');
-
- if(!is_array($vars))
- {
- $vars = func_get_args();
- array_shift($vars); // remove $key
- }
- return class_exists(translations,false) ? translation::translate($key,$vars) : str_replace($varnames,$vars,$key);
}
/**
@@ -1814,180 +330,3 @@
}
return $str;
}
-
-/**
- * Clasify exception for a headline and log it to error_log, if not running as cli
- *
- * @param Exception|Error $e
- * @param string &$headline
- */
-function _egw_log_exception($e,&$headline=null)
-{
- $trace = explode("\n", $e->getTraceAsString());
- if ($e instanceof Api\Exception\NoPermission)
- {
- $headline = try_lang('Permission denied!');
- }
- elseif ($e instanceof Api\Db\Exception)
- {
- $headline = try_lang('Database error');
- }
- elseif ($e instanceof Api\Exception\WrongUserinput)
- {
- $headline = ''; // message contains the whole message, it's usually no real error but some input validation
- }
- elseif ($e instanceof egw_exception_warning)
- {
- $headline = 'PHP Warning';
- array_shift($trace);
- }
- else
- {
- $headline = try_lang('An error happened');
- }
- // log exception to error log, if not running as cli,
- // which outputs the error_log to stderr and therefore output it twice to the user
- if(isset($_SERVER['HTTP_HOST']) || $GLOBALS['egw_info']['flags']['no_exception_handler'] !== 'cli')
- {
- error_log($headline.($e instanceof egw_exception_warning ? ': ' : ' ('.get_class($e).'): ').$e->getMessage());
- foreach($trace as $line)
- {
- error_log($line);
- }
- error_log('# Instance='.$GLOBALS['egw_info']['user']['domain'].', User='.$GLOBALS['egw_info']['user']['account_lid'].
- ', Request='.$_SERVER['REQUEST_METHOD'].' '.($_SERVER['HTTPS']?'https://':'http://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].
- ', User-agent='.$_SERVER['HTTP_USER_AGENT']);
- }
-}
-
-/**
- * Fail a little bit more gracefully then an uncought exception
- *
- * Does NOT return
- *
- * @param Exception|Error $e
- */
-function egw_exception_handler($e)
-{
- // handle redirects without logging
- if (is_a($e, 'egw_exception_redirect'))
- {
- egw::redirect($e->url, $e->app);
- }
- // logging all exceptions to the error_log (if not cli) and get headline
- $headline = null;
- _egw_log_exception($e,$headline);
-
- // exception handler for cli (command line interface) clients, no html, no logging
- if(!isset($_SERVER['HTTP_HOST']) || $GLOBALS['egw_info']['flags']['no_exception_handler'] == 'cli')
- {
- echo ($headline ? $headline.': ' : '').$e->getMessage()."\n";
- if ($GLOBALS['egw_info']['server']['exception_show_trace'])
- {
- echo $e->getTraceAsString()."\n";
- }
- exit($e->getCode() ? $e->getCode() : 9999); // allways give a non-zero exit code
- }
- // regular GUI exception
- if (!isset($GLOBALS['egw_info']['flags']['no_exception_handler']))
- {
- header('HTTP/1.1 500 '.$headline);
- $message = '<h3>'.html::htmlspecialchars($headline)."</h3>\n".
- '<pre><b>'.html::htmlspecialchars($e->getMessage())."</b>\n\n";
-
- // only show trace (incl. function arguments) if explicitly enabled, eg. on a development system
- if ($GLOBALS['egw_info']['server']['exception_show_trace'])
- {
- $message .= html::htmlspecialchars($e->getTraceAsString());
- }
- $message .= "</pre>\n";
- if (is_a($e, 'EGroupware\Api\Db\Exception\Setup'))
- {
- $setup_dir = str_replace(array('home/index.php','index.php'),'setup/',$_SERVER['PHP_SELF']);
- $message .= '<a href="'.$setup_dir.'">Run setup to install or configure EGroupware.</a>';
- }
- elseif (is_object($GLOBALS['egw']) && isset($GLOBALS['egw']->session) && method_exists($GLOBALS['egw'],'link'))
- {
- $message .= '<p><a href="'.$GLOBALS['egw']->link('/index.php').'">'.try_lang('Click here to resume your eGroupWare Session.').'</a></p>';
- }
- if (is_object($GLOBALS['egw']) && isset($GLOBALS['egw']->framework))
- {
- $GLOBALS['egw']->framework->render($message,$headline);
- }
- else
- {
- echo "<html>\n<head>\n<title>".html::htmlspecialchars($headline)."</title>\n</head>\n<body>\n$message\n</body>\n</html>\n";
- }
- }
- // exception handler sending message back to the client as basic auth message
- elseif($GLOBALS['egw_info']['flags']['no_exception_handler'] == 'basic_auth')
- {
- $error = str_replace(array("\r", "\n"), array('', ' | '), $e->getMessage());
- header('WWW-Authenticate: Basic realm="'.$headline.' '.$error.'"');
- header('HTTP/1.1 401 Unauthorized');
- header('X-WebDAV-Status: 401 Unauthorized', true);
- }
- if (is_object($GLOBALS['egw']))
- {
- common::egw_exit();
- }
- exit;
-}
-
-if (!isset($GLOBALS['egw_info']['flags']['no_exception_handler']) || $GLOBALS['egw_info']['flags']['no_exception_handler'] !== true)
-{
- set_exception_handler('egw_exception_handler');
-}
-
-/**
- * Fail a little bit more gracefully then a catchable fatal error, by throwing an exception
- *
- * @param int $errno level of the error raised: E_* constants
- * @param string $errstr error message
- * @param string $errfile filename that the error was raised in
- * @param int $errline line number the error was raised at
- * @link http://www.php.net/manual/en/function.set-error-handler.php
- * @throws ErrorException
- */
-function egw_error_handler ($errno, $errstr, $errfile, $errline)
-{
- switch ($errno)
- {
- case E_RECOVERABLE_ERROR:
- case E_USER_ERROR:
- throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
-
- case E_WARNING:
- case E_USER_WARNING:
- // skip message for warnings supressed via @-error-control-operator (eg. @is_dir($path))
- // can be commented out to get suppressed warnings too!
- if (error_reporting())
- {
- _egw_log_exception(new egw_exception_warning($errstr.' in '.$errfile.' on line '.$errline));
- }
- break;
- }
-}
-
-/**
- * Used internally to trace warnings
- */
-class egw_exception_warning extends Exception {}
-
-// install our error-handler only for catchable fatal errors and warnings
-// following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING
-set_error_handler('egw_error_handler', E_RECOVERABLE_ERROR|E_USER_ERROR|E_WARNING|E_USER_WARNING);
-
-// some not longer necessary defines
-if (isset($GLOBALS['egw_info']['flags']['phpgw_compatibility']) && $GLOBALS['egw_info']['flags']['phpgw_compatibility'])
-{
- define('PHPGW_API_INC',EGW_API_INC);
- define('PHPGW_SERVER_ROOT',EGW_SERVER_ROOT);
- define('PHPGW_INCLUDE_ROOT',EGW_INCLUDE_ROOT);
-
- /* debugging settings */
- define('DEBUG_DATATYPES', True);
- define('DEBUG_LEVEL', 3);
- define('DEBUG_OUTPUT', 2); /* 1 = screen, 2 = DB. For both use 3. */
- define('DEBUG_TIMER', False);
-}
Modified: trunk/egroupware/header.inc.php.template
URL: http://svn.stylite.de/viewvc/egroupware/trunk/egroupware/header.inc.php.template?rev=55853&r1=55852&r2=55853&view=diff
==============================================================================
--- trunk/egroupware/header.inc.php.template (original)
+++ trunk/egroupware/header.inc.php.template Tue Apr 26 16:38:08 2016
@@ -1,8 +1,8 @@
<?php
/**
- * eGroupWare - configuration file
+ * EGroupware - configuration file
*
- * Use eGroupWare's setup to create or edit this configuration file.
+ * Use EGroupware's setup to create or edit this configuration file.
* You do NOT need to copy and edit this file manually!
*
* @link http://www.egroupware.org
@@ -11,20 +11,6 @@
* (This file was originaly written by Dan Kuykendall)
* @version $Id$
*/
-
-// allow to migrate from phpgw_info to egw_info
-if (!isset($GLOBALS['egw_info']) || in_array($GLOBALS['egw_info']['flags']['currentapp'],array('jinn','mydms','tts')))
-{
- if (!isset($GLOBALS['egw_info']))
- {
- $GLOBALS['egw_info'] =& $GLOBALS['phpgw_info'];
- }
- else
- {
- $GLOBALS['phpgw_info'] =& $GLOBALS['egw_info'];
- }
- $GLOBALS['egw_info']['flags']['phpgw_compatibility'] = true;
-}
// eGW install dir, need to be changed if you copy the server to an other directory
define('EGW_SERVER_ROOT','{SERVER_ROOT}');
@@ -52,12 +38,6 @@
$GLOBALS['egw_info']['server']['db_persistent'] = {DB_PERSISTENT};
-/*
-** used session handler: egw_session_files works for all build in php session handlers
-** other handlers (like egw_session_memcache) can be enabled here
-*/
-$GLOBALS['egw_info']['server']['session_handler'] = '{SESSION_HANDLER}';
-
/* This is used to control mcrypt's use */
$GLOBALS['egw_info']['server']['mcrypt_enabled'] = {ENABLE_MCRYPT};
@@ -71,11 +51,8 @@
$GLOBALS['egw_info']['flags']['page_start_time'] = microtime(true);
-define('DEBUG_API', False);
-define('DEBUG_APP', False);
-
-include(EGW_SERVER_ROOT.'/phpgwapi/setup/setup.inc.php');
-$GLOBALS['egw_info']['server']['versions']['phpgwapi'] = $setup_info['phpgwapi']['version'];
+include(EGW_SERVER_ROOT.'/api/setup/setup.inc.php');
+$GLOBALS['egw_info']['server']['versions']['phpgwapi'] = $GLOBALS['egw_info']['server']['versions']['api'] = $setup_info['api']['version'];
$GLOBALS['egw_info']['server']['versions']['current_header'] = $setup_info['phpgwapi']['versions']['current_header'];
unset($setup_info);
$GLOBALS['egw_info']['server']['versions']['header'] = '1.29';
@@ -88,11 +65,11 @@
{
ob_start(); // to prevent error messages to be send before our headers
}
- require_once(EGW_API_INC . '/functions.inc.php');
+ require_once(EGW_SERVER_ROOT.'/api/src/loader.php');
}
else
{
- require_once(EGW_API_INC . '/common_functions.inc.php');
+ require_once(EGW_SERVER_ROOT.'/api/src/loader/common.php');
}
/*
Modified: trunk/phpgwapi/inc/class.applications.inc.php
URL: http://svn.stylite.de/viewvc/egroupware/trunk/phpgwapi/inc/class.applications.inc.php?rev=55853&r1=55852&r2=55853&view=diff
==============================================================================
--- trunk/phpgwapi/inc/class.applications.inc.php (original)
+++ trunk/phpgwapi/inc/class.applications.inc.php Tue Apr 26 16:38:08 2016
@@ -1,6 +1,6 @@
<?php
/**
- * eGroupWare API - Applications
+ * EGroupware API - Applications
*
* @link http://www.egroupware.org
* @author Mark Peters <[email protected]>
@@ -10,77 +10,17 @@
* @version $Id$
*/
+use EGroupware\Api;
+
/**
* functions for managing and installing apps
*
* Author: skeeter
+ *
+ * @deprecated use just methods from Api\Egw\Applications
*/
-class applications
+class applications extends Api\Egw\Applications
{
- var $account_id;
- var $data = Array();
- /**
- * Reference to the global db class
- *
- * @var egw_db
- */
- var $db;
- var $table_name = 'egw_applications';
-
- /**************************************************************************\
- * Standard constructor for setting $this->account_id *
- \**************************************************************************/
-
- /**
- * standard constructor for setting $this->account_id
- *
- * @param $account_id account id
- */
- function __construct($account_id = '')
- {
- if (is_object($GLOBALS['egw_setup']) && is_object($GLOBALS['egw_setup']->db))
- {
- $this->db = $GLOBALS['egw_setup']->db;
- }
- else
- {
- $this->db = $GLOBALS['egw']->db;
- }
-
- $this->account_id = get_account_id($account_id);
- }
-
- /**************************************************************************\
- * These are the standard $this->account_id specific functions *
- \**************************************************************************/
-
- /**
- * read from repository
- *
- * private should only be called from withing this class
- */
- function read_repository()
- {
- if (!isset($GLOBALS['egw_info']['apps']) || !is_array($GLOBALS['egw_info']['apps']))
- {
- $this->read_installed_apps();
- }
- $this->data = Array();
- if(!$this->account_id)
- {
- return False;
- }
- $apps = $GLOBALS['egw']->acl->get_user_applications($this->account_id);
- foreach($GLOBALS['egw_info']['apps'] as $app => $data)
- {
- if (isset($apps[$app]) && $apps[$app])
- {
- $this->data[$app] =& $GLOBALS['egw_info']['apps'][$app];
- }
- }
- return $this->data;
- }
-
/**
* read from the repository
*
@@ -148,7 +88,7 @@
function save_repository()
{
$GLOBALS['egw']->acl->delete_repository("%%", 'run', $this->account_id);
- foreach($this->data as $app => $data)
+ foreach(array_keys($this->data) as $app)
{
if(!$this->is_system_enabled($app))
{
@@ -169,7 +109,7 @@
{
$this->read_repository();
}
- foreach ($this->data as $app => $data)
+ foreach (array_keys($this->data) as $app)
{
$apps[] = $this->data[$app]['name'];
}
@@ -193,39 +133,6 @@
}
}
return $this->data;
- }
-
- /**************************************************************************\
- * These are the generic functions. Not specific to $this->account_id *
- \**************************************************************************/
-
- /**
- * populate array with a list of installed apps
- *
- */
- function read_installed_apps()
- {
- foreach($this->db->select($this->table_name,'*',false,__LINE__,__FILE__,false,'ORDER BY app_order ASC') as $row)
- {
- $title = $app_name = $row['app_name'];
-
- if (@is_array($GLOBALS['egw_info']['user']['preferences']) && ($t = lang($app_name)) != $app_name.'*')
- {
- $title = $t;
- }
- $GLOBALS['egw_info']['apps'][$app_name] = Array(
- 'title' => $title,
- 'name' => $app_name,
- 'enabled' => True,
- 'status' => $row['app_enabled'],
- 'id' => (int)$row['app_id'],
- 'order' => (int)$row['app_order'],
- 'version' => $row['app_version'],
- 'index' => $row['app_index'],
- 'icon' => $row['app_icon'],
- 'icon_app'=> $row['app_icon_app'],
- );
- }
}
/**
Modified: trunk/phpgwapi/inc/class.egw.inc.php
URL: http://svn.stylite.de/viewvc/egroupware/trunk/phpgwapi/inc/class.egw.inc.php?rev=55853&r1=55852&r2=55853&view=diff
==============================================================================
--- trunk/phpgwapi/inc/class.egw.inc.php (original)
+++ trunk/phpgwapi/inc/class.egw.inc.php Tue Apr 26 16:38:08 2016
@@ -1,11 +1,8 @@
<?php
/**
- * eGroupWare API - Applications
+ * EGroupware API - Applications
*
* @link http://www.egroupware.org
- * This file was originaly written by Dan Kuykendall and Joseph Engo
- * Copyright (C) 2000, 2001 Dan Kuykendall
- * Parts Copyright (C) 2003 Free Software Foundation
* @author [email protected]
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
@@ -15,677 +12,11 @@
use EGroupware\Api;
/**
- * New written class to create the eGW enviroment AND restore it from a php-session
- *
- * Rewritten by [email protected] to store the eGW enviroment
- * (egw-object and egw_info-array) in a php-session and restore it from
- * there instead of creating it completly new on each page-request.
- * The enviroment gets now created by the egw-class
- *
- * Use now a php5 getter method to create the usuall subobject on demand, to allow a quicker
- * header include on sites not useing php4-restore.
- * This also makes a lot of application code, like the following, unnecessary:
- * if (!is_object($GLOBALS['egw']->datetime)
- * {
- * $GLOBALS['egw']->datetime = CreateObject('phpgwapi.datetime');
- * }
- * You can now simply use $GLOBALS['egw']->datetime, and the egw class instanciates it for you on demand.
+ * @deprecated use Api\Egw
*/
-class egw extends egw_minimal
-{
- /**
- * Turn on debug mode. Will output additional data for debugging purposes.
- * @var string
- * @access public
- */
- var $debug = 0; // This will turn on debugging information.
- /**
- * Instance of the account object
- *
- * @var accounts
- */
- var $accounts;
- /**
- * Instace of the common object
- *
- * @var common
- */
- var $common;
- /**
- * Instace of the hooks object
- *
- * @var hooks
- */
- var $hooks;
-
- /**
- * Constructor: Instantiates the sub-classes
- *
- * @author [email protected]
- * @param array $domain_names array with valid egw-domain names
- */
- function __construct($domain_names=null)
- {
- $GLOBALS['egw'] =& $this; // we need to be immediately available there for the other classes we instantiate
- // for the migration: reference us to the old phpgw object
- $GLOBALS['phpgw'] =& $this;
- $this->setup($domain_names,True);
- }
-
- /**
- * Called every time the constructor is called. Also called by sessions to ensure the correct db,
- * in which case we do not recreate the session object.
- * @author [email protected] (moved to setup() by [email protected]
- * @param array $domain_names array with valid egw-domain names
- * @param boolean $createsessionobject True to create the session object (default=True)
- */
- function setup($domain_names,$createsessionobject=True)
- {
- // create the DB-object
- // as SiteMgr, Wiki, KnowledgeBase and probably more still use eg next_record(), we stick with Db\Deprecated for now
- $this->db = new Api\Db\Deprecated($GLOBALS['egw_info']['server']);
- if ($this->debug)
- {
- $this->db->Debug = 1;
- }
- $this->db->set_app(Api\Db::API_APPNAME);
-
- // check if eGW is already setup, if not redirect to setup/
- try {
- $this->db->connect();
- $num_config = $this->db->select(config::TABLE,'COUNT(config_name)',false,__LINE__,__FILE__)->fetchColumn();
- }
- catch(Api\Db\Exception\Connection $e) {
- // ignore exception, get handled below
- }
- catch(Api\Db\Exception\InvalidSql $e1) {
- unset($e1); // not used
- try {
- $phpgw_config = $this->db->select('phpgw_config','COUNT(config_name)',false,__LINE__,__FILE__)->fetchColumn();
- }
- catch (Api\Db\Exception\InvalidSql $e2) {
- unset($e2); // not used
- // ignor error, get handled below
- }
- }
- if (!$num_config)
- {
- // we check for the old table too, to not scare updating users ;-)
- if ($phpgw_config)
- {
- throw new Exception('You need to update EGroupware before you can continue using it.',999);
- }
- if ($e)
- {
- throw new Api\Db\Exception\Setup('Connection with '.$e->getMessage()."\n\n".
- 'Maybe you not created a database for EGroupware yet.',999);
- }
- throw new Api\Db\Exception\Setup('It appears that you have not created the database tables for EGroupware.',999);
- }
- // Set the DB's client charset if a system-charset is set and some other values needed by egw_cache (used in config::read)
- foreach($this->db->select(config::TABLE,'config_name,config_value',array(
- 'config_app' => 'phpgwapi',
- 'config_name' => array('system_charset','install_id','temp_dir'),
- ),__LINE__,__FILE__) as $row)
- {
- $GLOBALS['egw_info']['server'][$row['config_name']] = $row['config_value'];
- }
- if ($GLOBALS['egw_info']['server']['system_charset'] && $GLOBALS['egw_info']['server']['system_charset'] != 'utf-8')
- {
- $this->db->Link_ID->SetCharSet($GLOBALS['egw_info']['server']['system_charset']);
- }
- // load up the $GLOBALS['egw_info']['server'] array
- $GLOBALS['egw_info']['server'] += config::read('phpgwapi');
-
- // if no server timezone set, use date_default_timezone_get() to determine it once
- // it fills to log with deprecated warnings under 5.3 otherwise
- if (empty($GLOBALS['egw_info']['server']['server_timezone']) ||
- $GLOBALS['egw_info']['server']['server_timezone'] == 'System/Localtime') // treat invalid tz like empty!
- {
- try
- {
- $tz = new DateTimeZone(date_default_timezone_get());
- config::save_value('server_timezone',$GLOBALS['egw_info']['server']['server_timezone'] = $tz->getName(),'phpgwapi');
- error_log(__METHOD__."() stored server_timezone=".$GLOBALS['egw_info']['server']['server_timezone']);
- }
- catch(Exception $e)
- {
- // do nothing if new DateTimeZone fails (eg. 'System/Localtime' returned), specially do NOT store it!
- error_log(__METHOD__."() NO valid 'date.timezone' set in your php.ini!");
- }
- }
- date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
-
- // setup the other subclasses
- // translation class is here only for backward compatibility, as all it's methods can be called static now
- $this->translation = new translation();
- $this->common = new common();
- $this->accounts = new accounts();
- $this->acl = new acl();
- // we instanciate the hooks object here manually, to cache it's hooks in the session
- $this->hooks = new hooks();
- /* Do not create the session object if called by the sessions class. This way
- * we ensure the correct db based on the user domain.
- */
- if($createsessionobject)
- {
- $this->session = new egw_session($domain_names);
- }
- $this->preferences = new preferences();
- $this->applications = new applications();
-
- if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login' && $GLOBALS['egw_info']['flags']['currentapp'] != 'logout')
- {
- $this->verify_session();
- $this->applications->read_installed_apps(); // to get translated app-titles, has to be after verify_session
-
- $this->define_egw_constants();
-
- $this->check_app_rights();
-
- $this->load_optional_classes();
- }
- else // set the defines for login, in case it's more then just login
- {
- $this->define_egw_constants();
- }
- }
-
- /**
- * __wakeup function gets called by php while unserializing the egw-object, eg. reconnects to the DB
- *
- * @author [email protected]
- */
- function __wakeup()
- {
- $GLOBALS['egw'] =& $this; // we need to be immediately available there for the other classes we instantiate
- // for the migration: reference us to the old phpgw object
- $GLOBALS['phpgw'] =& $this;
-
- if ($GLOBALS['egw_info']['server']['system_charset'])
- {
- $this->db->Link_ID->SetCharSet($GLOBALS['egw_info']['server']['system_charset']);
- }
- // restoring server timezone, to avoid warnings under php5.3
- if (!empty($GLOBALS['egw_info']['server']['server_timezone']))
- {
- date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
- }
-
- $this->define_egw_constants();
- }
-
- /**
- * wakeup2 function needs to be called after unserializing the egw-object
- *
- * It adapts the restored object/enviroment to the changed (current) application / page-request
- *
- * @author [email protected]
- */
- function wakeup2()
- {
- // do some application specific stuff, need to be done as we are different (current) app now
- if (isset($this->template))
- {
- $this->template->set_root(EGW_APP_TPL);
- }
- // init the translation class, necessary as own wakeup would run before our's
- translation::init(isset($GLOBALS['egw_info']['flags']['load_translations']) ? $GLOBALS['egw_info']['flags']['load_translations'] : true);
-
- $this->unset_datetime();
-
- // verify the session
- $GLOBALS['egw']->verify_session();
- $GLOBALS['egw']->check_app_rights();
-
- $this->load_optional_classes();
- }
-
- /**
- * Unsetting datetime object, so time gets updated
- */
- function unset_datetime()
- {
- unset($this->datetime);
- }
-
- /**
- * load optional classes by mentioning them in egw_info[flags][enable_CLASS_class] => true
- *
- * Also loads the template-class if not egw_info[flags][disable_Template_class] is set
- *
- * Maybe the whole thing should be depricated ;-)
- */
- function load_optional_classes()
- {
- // output the header unless the developer turned it off
- if (!@$GLOBALS['egw_info']['flags']['noheader'])
- {
- common::egw_header();
- }
-
- // Load the (depricated) app include files if they exists
- if (EGW_APP_INC != "" && ! preg_match ('/phpgwapi/i', EGW_APP_INC) &&
- file_exists(EGW_APP_INC . '/functions.inc.php') && !isset($_GET['menuaction']))
- {
- include(EGW_APP_INC . '/functions.inc.php');
- }
- if (!@$GLOBALS['egw_info']['flags']['noheader'] && !@$GLOBALS['egw_info']['flags']['noappheader'] &&
- file_exists(EGW_APP_INC . '/header.inc.php') && !isset($_GET['menuaction']))
- {
- include(EGW_APP_INC . '/header.inc.php');
- }
- }
-
- /**
- * Verfiy there is a valid session
- *
- * One can specify a callback, which gets called if there's no valid session. If the callback returns true, the parameter
- * containst account-details (in keys login, passwd and passwd_type) to automatic create an (anonymous session)
- *
- * It also checks if enforce_ssl is set in the DB and redirects to the https:// version of the site.
- *
- * If there is no valid session and none could be automatic created, the function will redirect to login and NOT return
- */
- function verify_session()
- {
- if($GLOBALS['egw_info']['server']['enforce_ssl'] === 'redirect' && !$_SERVER['HTTPS'])
- {
- Header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
- exit;
- }
- // check if we have a session, if not try to automatic create one
- if ($this->session->verify()) return true;
-
- $account = null;
- if (($account_callback = $GLOBALS['egw_info']['flags']['autocreate_session_callback']) && is_callable($account_callback) &&
- ($sessionid = call_user_func_array($account_callback,array(&$account))) === true) // $account_call_back returns true, false or a session-id
- {
- $sessionid = $this->session->create($account);
- }
- if (!$sessionid)
- {
- //echo "<p>account_callback='$account_callback', account=".print_r($account,true).", sessionid=$sessionid</p>\n"; exit;
- // we forward to the same place after the re-login
- if ($GLOBALS['egw_info']['server']['webserver_url'] && $GLOBALS['egw_info']['server']['webserver_url'] != '/' &&
- ($webserver_path = parse_url($GLOBALS['egw_info']['server']['webserver_url'],PHP_URL_PATH)) && $webserver_path != '/')
- {
- // we have to use only path component, to cope with domains like http://egroupware.domain.com and /egroupware
- list(,$relpath) = explode($webserver_path,parse_url($_SERVER['PHP_SELF'],PHP_URL_PATH),2);
- }
- else // the webserver-url is empty or just a slash '/' (eGW is installed in the docroot and no domain given)
- {
- $matches = null;
- if (preg_match('/^https?:\/\/[^\/]*\/(.*)$/',$relpath=$_SERVER['PHP_SELF'],$matches))
- {
- $relpath = $matches[1];
- }
- }
- // this removes the sessiondata if its saved in the URL
- $query = preg_replace('/[&]?sessionid(=|%3D)[^&]+&kp3(=|%3D)[^&]+&domain=.*$/','',$_SERVER['QUERY_STRING']);
- if ($GLOBALS['egw_info']['server']['http_auth_types'])
- {
- $redirect = '/phpgwapi/ntlm/index.php?';
- }
- else
- {
- $redirect = '/login.php?';
- // only add "your session could not be verified", if a sessionid is given (cookie or on url)
- if (egw_session::get_sessionid()) $redirect .= 'cd=10&';
- }
- if ($relpath) $redirect .= 'phpgw_forward='.urlencode($relpath.(!empty($query) ? '?'.$query : ''));
- self::redirect_link($redirect);
- }
- }
-
- /**
- * Verify the user has rights for the requested app
- *
- * If the user has no rights for the app (eg. called via URL) he get a permission denied page (this function does NOT return)
- *
- * @throws Api\Exception\Redirect for anonymous user accessing something he has no rights to
- * @throws Api\Exception\NoPermission\Admin
- * @throws Api\Exception\NoPermission\App
- */
- function check_app_rights()
- {
- $this->currentapp = $GLOBALS['egw_info']['flags']['currentapp']; // some apps change it later
-
- if (!in_array($GLOBALS['egw_info']['flags']['currentapp'], array('api', 'home'))) // give everyone implicit home rights
- {
- // This will need to use ACL in the future
- if (!$GLOBALS['egw_info']['user']['apps'][$currentapp = $GLOBALS['egw_info']['flags']['currentapp']] ||
- ($GLOBALS['egw_info']['flags']['admin_only'] && !$GLOBALS['egw_info']['user']['apps']['admin']))
- {
- // present a login page, if anon user has no right for an application
- if ($this->session->session_flags == 'A')
- {
- // need to destroy a basic auth session here, because it will only be available on current url
- if (($sessionid = egw_session::get_sessionid(true)))
- {
- $GLOBALS['egw']->session->destroy($sessionid);
- }
- throw new Api\Exception\Redirect(egw::link('/logout.php'));
- }
- if ($currentapp == 'admin' || $GLOBALS['egw_info']['flags']['admin_only'])
- {
- throw new Api\Exception\NoPermission\Admin();
- }
- throw new Api\Exception\NoPermission\App($currentapp);
- }
- }
- }
-
- /**
- * create all the defines / constants of the eGW-environment (plus the deprecated phpgw ones)
- */
- function define_egw_constants()
- {
- define('EGW_ACL_READ',1);
- define('EGW_ACL_ADD',2);
- define('EGW_ACL_EDIT',4);
- define('EGW_ACL_DELETE',8);
- define('EGW_ACL_PRIVATE',16);
- define('EGW_ACL_GROUP_MANAGERS',32);
- define('EGW_ACL_CUSTOM_1',64);
- define('EGW_ACL_CUSTOM_2',128);
- define('EGW_ACL_CUSTOM_3',256);
- // and the old ones
- define('PHPGW_ACL_READ',1);
- define('PHPGW_ACL_ADD',2);
- define('PHPGW_ACL_EDIT',4);
- define('PHPGW_ACL_DELETE',8);
- define('PHPGW_ACL_PRIVATE',16);
- define('PHPGW_ACL_GROUP_MANAGERS',32);
- define('PHPGW_ACL_CUSTOM_1',64);
- define('PHPGW_ACL_CUSTOM_2',128);
- define('PHPGW_ACL_CUSTOM_3',256);
- // A few hacker resistant constants that will be used throught the program
- define('EGW_TEMPLATE_DIR', $this->common->get_tpl_dir('phpgwapi'));
- define('EGW_IMAGES_DIR', $this->common->get_image_path('phpgwapi'));
- define('EGW_IMAGES_FILEDIR', $this->common->get_image_dir('phpgwapi'));
- define('EGW_APP_ROOT', $this->common->get_app_dir());
- define('EGW_APP_INC', $this->common->get_inc_dir());
- define('EGW_APP_TPL', $this->common->get_tpl_dir());
- define('EGW_IMAGES', $this->common->get_image_path());
- define('EGW_APP_IMAGES_DIR', $this->common->get_image_dir());
- // and the old ones
- define('PHPGW_TEMPLATE_DIR',EGW_TEMPLATE_DIR);
- define('PHPGW_IMAGES_DIR',EGW_IMAGES_DIR);
- define('PHPGW_IMAGES_FILEDIR',EGW_IMAGES_FILEDIR);
- define('PHPGW_APP_ROOT',EGW_APP_ROOT);
- define('PHPGW_APP_INC',EGW_APP_INC);
- define('PHPGW_APP_TPL',EGW_APP_TPL);
- define('PHPGW_IMAGES',EGW_IMAGES);
- define('PHPGW_APP_IMAGES_DIR',EGW_APP_IMAGES_DIR);
- }
-
- /**
- * force the session cache to be re-created, because some of it's data changed
- *
- * Needs to be called if user-preferences, system-config or enabled apps of the current user have been changed and
- * the change should have immediate effect
- */
- static function invalidate_session_cache()
- {
- unset($_SESSION['egw_info_cache']);
- unset($_SESSION['egw_object_cache']);
- }
-
- /**
- * run string through htmlspecialchars and stripslashes
- *
- * @param string $s
- * @return string The string with html special characters replaced with entities
- */
- static function strip_html($s)
- {
- return htmlspecialchars(stripslashes($s));
- }
-
- /**
- * Link url generator
- *
- * @param string $url url link is for
- * @param string|array $extravars ='' extra params to be added to url
- * @param string $link_app =null if appname or true, some templates generate a special link-handler url
- * @return string The full url after processing
- */
- static function link($url, $extravars = '', $link_app=null)
- {
- return $GLOBALS['egw']->framework->link($url, $extravars, $link_app);
- }
-
- /**
- * Redirects direct to a generated link
- *
- * @param string $url url link is for
- * @param string|array $extravars ='' extra params to be added to url
- * @param string $link_app =null if appname or true, some templates generate a special link-handler url
- * @return string The full url after processing
- */
- static function redirect_link($url, $extravars='', $link_app=null)
- {
- return $GLOBALS['egw']->framework->redirect_link($url, $extravars, $link_app);
- }
-
- /**
- * Handles redirects under iis and apache, it does NOT return (calls exit)
- *
- * This function handles redirects under iis and apache it assumes that $phpgw->link() has already been called
- *
- * @param string $url url to redirect to
- * @param string $link_app =null appname to redirect for, default currentapp
- */
- static function redirect($url, $link_app=null)
- {
- Api\Framework::redirect($url, $link_app);
- }
-
- /**
- * Shortcut to translation class
- *
- * This function is a basic wrapper to translation::translate()
- *
- * @deprecated only used in the old timetracker
- * @param string The key for the phrase
- * @see translation::translate()
- */
- static function lang($key,$args=null)
- {
- if (!is_array($args))
- {
- $args = func_get_args();
- array_shift($args);
- }
- return translation::translate($key,$args);
- }
-
- /**
- * registered shutdown callbacks and optional arguments
- *
- * @var array
- */
- private static $shutdown_callbacks = array();
-
- /**
- * Register a callback to run on shutdown AFTER output send to user
- *
- * Allows eg. static classes (no destructor) to run on shutdown AND
- * garanties to run AFTER output send to user.
- *
- * @param callable $callback use array($classname, $method) for static methods
- * @param array $args =array()
- */
- public static function on_shutdown($callback, array $args=array())
- {
- array_unshift($args, $callback);
-
- // prepend new callback, to run them in oposite order they are registered
- array_unshift(self::$shutdown_callbacks, $args);
- }
-
- /**
- * Shutdown handler running all registered on_shutdown callbacks and then disconnecting from db
- */
- function __destruct()
- {
- if (!defined('EGW_SHUTDOWN'))
- {
- define('EGW_SHUTDOWN',True);
-
- // send json response BEFORE flushing output
- if (egw_json_request::isJSONRequest())
- {
- egw_json_response::sendResult();
- }
-
- // run all on_shutdown callbacks with session in their name (eg. egw_link::save_session_cache), do NOT stop on exceptions
- foreach(self::$shutdown_callbacks as $n => $data)
- {
- try {
- //error_log(__METHOD__."() running ".array2string($data));
- $callback = array_shift($data);
- if (!is_array($callback) || strpos($callback[1], 'session') === false) continue;
- call_user_func_array($callback, $data);
- }
- catch (Exception $ex) {
- _egw_log_exception($ex);
- }
- unset(self::$shutdown_callbacks[$n]);
- }
- // now we can close the session
- // without closing the session fastcgi_finish_request() will NOT send output to user
- if (isset($GLOBALS['egw']->session) && is_object($GLOBALS['egw']->session)) $GLOBALS['egw']->session->commit_session();
-
- // flush all output to user
- /* does NOT work on Apache :-(
- for($i = 0; ob_get_level() && $i < 10; ++$i)
- {
- ob_end_flush();
- }
- flush();*/
- // working for fastCGI :-)
- if (function_exists('fastcgi_finish_request') && substr($_SERVER['PHP_SELF'], -32) != '/phpgwapi/cron/asyncservices.php')
- {
- fastcgi_finish_request();
- }
-
- // run all on_shutdown, do NOT stop on exceptions
- foreach(self::$shutdown_callbacks as $data)
- {
- try {
- //error_log(__METHOD__."() running ".array2string($data));
- $callback = array_shift($data);
- call_user_func_array($callback, $data);
- }
- catch (Exception $ex) {
- _egw_log_exception($ex);
- }
- }
- // call the asyncservice check_run function if it is not explicitly set to cron-only
- if (!$GLOBALS['egw_info']['server']['asyncservice']) // is default
- {
- ExecMethod('phpgwapi.asyncservice.check_run','fallback');
- }
- $this->db->disconnect();
- }
- }
-}
+class egw extends Api\Egw{}
/**
- * Minimal eGW object used in setup, does not instanciate anything by default
- *
+ * @deprecated use Api\Egw\Base
*/
-class egw_minimal
-{
- /**
- * Instance of the db-object
- *
- * @var egw_db
- */
- var $db;
- /**
- * Current app at the instancation of the class
- *
- * @var string
- */
- var $currentapp;
- /**
- * Global ADOdb object, need to be defined here, to not call magic __get method
- *
- * @var ADOConnection
- */
- var $ADOdb;
-
- /**
- * Classes which get instanciated in a different name
- *
- * @var array
- */
- static $sub_objects = array(
- 'log' => 'errorlog',
-// 'js' => 'javascript',
- 'link' => 'bolink', // depricated use static egw_link methods
- 'datetime' => 'egw_datetime',
- 'framework' => true, // special handling in __get()
- 'template' => 'Template',
- 'session' => 'egw_session', // otherwise $GLOBALS['egw']->session->appsession() fails
- // classes moved to new api dir
- 'ldap' => true,
- 'auth' => 'EGroupware\\Api\\Auth',
- );
-
- /**
- * Magic function to check if a sub-object is set
- *
- * @param string $name
- * @return boolean
- */
- function __isset($name)
- {
- //error_log(__METHOD__."($name)");
- return isset($this->$name);
- }
-
- /**
- * Magic function to return a sub-object
- *
- * @param string $name
- * @return mixed
- */
- function __get($name)
- {
- //error_log(__METHOD__."($name)".function_backtrace());
-
- if ($name == 'js') $name = 'framework'; // javascript class is integrated now into framework
-
- if (isset($this->$name))
- {
- return $this->$name;
- }
-
- if (!isset(self::$sub_objects[$name]) && !class_exists($name))
- {
- if ($name != 'ADOdb') error_log(__METHOD__.": There's NO $name object! ".function_backtrace());
- return null;
- }
- switch($name)
- {
- case 'framework':
- return $this->framework = egw_framework::factory();
- case 'template': // need to be instancated for the current app
- if (!($tpl_dir = common::get_tpl_dir($this->currentapp)))
- {
- return null;
- }
- return $this->template = new Template($tpl_dir);
- case 'ldap':
- return $this->ldap = Api\Ldap::factory(false);
- default:
- $class = isset(self::$sub_objects[$name]) ? self::$sub_objects[$name] : $name;
- break;
- }
- return $this->$name = new $class();
- }
-}
+class egw_minimal extends Api\Egw\Base{}
Modified: trunk/phpgwapi/inc/common_functions.inc.php
URL: http://svn.stylite.de/viewvc/egroupware/trunk/phpgwapi/inc/common_functions.inc.php?rev=55853&r1=55852&r2=55853&view=diff
==============================================================================
--- trunk/phpgwapi/inc/common_functions.inc.php (original)
+++ trunk/phpgwapi/inc/common_functions.inc.php Tue Apr 26 16:38:08 2016
@@ -1,1993 +1,13 @@
<?php
/**
- * EGroupware commonly used functions
- *
- * This file was originaly written by Dan Kuykendall and Joseph Engo
- * Copyright (C) 2000, 2001 Dan Kuykendall
- *
- * All newer parts (XSS checks, autoloading, exception handler, ...) are written by Ralf Becker.
+ * EGroupware commonly used functions incl. autoloader
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @package api
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
+ * @deprecated use api/src/common.php
* @version $Id$
*/
-use EGroupware\Api;
-
-// this is only neccessary, if header.inc.php is not included, but common_functions.inc.php directly
-if (!defined('EGW_SERVER_ROOT'))
-{
- define('EGW_SERVER_ROOT', dirname(dirname(__DIR__)));
- define('EGW_INCLUDE_ROOT', EGW_SERVER_ROOT);
- define('EGW_API_INC', __DIR__);
-}
-
-/**
- * New PSR-4 autoloader for EGroupware
- *
- * class_exists('\\EGroupware\\Api\\Vfs'); // /api/src/Vfs.php
- * class_exists('\\EGroupware\\Api\\Vfs\\Dav\\Directory'); // /api/src/Vfs/Dav/Directory.php
- * class_exists('\\EGroupware\\Api\\Vfs\\Sqlfs\\StreamWrapper'); // /api/src/Vfs/Sqlfs/StreamWrapper.php
- * class_exists('\\EGroupware\\Api\\Vfs\\Sqlfs\\Utils'); // /api/src/Vfs/Sqlfs/Utils.php
- * class_exists('\\EGroupware\\Stylite\\Versioning\\StreamWrapper'); // /stylite/src/Versioning/StreamWrapper.php
- * class_exists('\\EGroupware\\Calendar\\Ui'); // /calendar/src/Ui.php
- * class_exists('\\EGroupware\\Calendar\\Ui\\Lists'); // /calendar/src/Ui/Lists.php
- * class_exists('\\EGroupware\\Calendar\\Ui\\Views'); // /calendar/src/Ui/Views.php
- */
-spl_autoload_register(function($class)
-{
- $parts = explode('\\', $class);
- if (array_shift($parts) != 'EGroupware') return; // not our prefix
-
- $app = lcfirst(array_shift($parts));
- $base = EGW_INCLUDE_ROOT.'/'.$app.'/src/';
- $path = $base.implode('/', $parts).'.php';
-
- if (file_exists($path))
- {
- require_once $path;
- //error_log("PSR4_autoload('$class') --> require_once($path) --> class_exists('$class')=".array2string(class_exists($class,false)));
- }
-});
-
-/**
- * Old autoloader for EGroupware understanding the following naming schema:
- *
- * 1. new (prefered) nameing schema: app_class_something loading app/inc/class.class_something.inc.php
- * 2. API classes: classname loading phpgwapi/inc/class.classname.inc.php
- * 2a.API classes containing multiple classes per file eg. egw_exception* in class.egw_exception.inc.php
- * 3. eTemplate classes: classname loading etemplate/inc/class.classname.inc.php
- *
- * @param string $class name of class to load
- */
-spl_autoload_register(function($class)
-{
- // fixing warnings generated by php 5.3.8 is_a($obj) trying to autoload huge strings
- if (strlen($class) > 64 || strpos($class, '.') !== false) return;
-
- $components = explode('_',$class);
- $app = array_shift($components);
- // classes using the new naming schema app_class_name, eg. admin_cmd
- if (file_exists($file = EGW_INCLUDE_ROOT.'/'.$app.'/inc/class.'.$class.'.inc.php') ||
- // classes using the new naming schema app_class_name, eg. admin_cmd
- isset($components[0]) && file_exists($file = EGW_INCLUDE_ROOT.'/'.$app.'/inc/class.'.$app.'_'.$components[0].'.inc.php') ||
- // classes with an underscore in their name
- !isset($GLOBALS['egw_info']['apps'][$app]) && isset($GLOBALS['egw_info']['apps'][$app . '_' . $components[0]]) &&
- file_exists($file = EGW_INCLUDE_ROOT.'/'.$app.'_'.$components[0].'/inc/class.'.$class.'.inc.php') ||
- // eGW api classes using the old naming schema, eg. html
- file_exists($file = EGW_API_INC.'/class.'.$class.'.inc.php') ||
- // eGW api classes containing multiple classes in on file, eg. egw_exception
- isset($components[0]) && file_exists($file = EGW_API_INC.'/class.'.$app.'_'.$components[0].'.inc.php') ||
- // eGW eTemplate classes using the old naming schema, eg. etemplate
- file_exists($file = EGW_INCLUDE_ROOT.'/etemplate/inc/class.'.$class.'.inc.php') ||
- // include PEAR and PSR0 classes from include_path
- // need to use include (not include_once) as eg. a previous included EGW_API_INC/horde/Horde/String.php causes
- // include_once('Horde/String.php') to return true, even if the former was included with an absolute path
- // only use include_path, if no Composer vendor directory exists
- !isset($GLOBALS['egw_info']['apps'][$app]) && !file_exists(EGW_SERVER_ROOT.'/vendor') &&
- @include($file = strtr($class, array('_'=>'/','\\'=>'/')).'.php'))
- {
- include_once($file);
- //if (!class_exists($class, false) && !interface_exists($class, false)) error_log("autoloading class $class by include_once($file) failed!");
- }
- // allow apps to define an own autoload method
- elseif (isset($GLOBALS['egw_info']['flags']['autoload']) && is_callable($GLOBALS['egw_info']['flags']['autoload']))
- {
- call_user_func($GLOBALS['egw_info']['flags']['autoload'],$class);
- }
-});
-
-// if we have a Composer vendor directory, also load it's autoloader, to allow manage our requirements with Composer
-if (file_exists(EGW_SERVER_ROOT.'/vendor'))
-{
- require_once EGW_SERVER_ROOT.'/vendor/autoload.php';
-}
-
-/**
-* applies stripslashes recursivly on each element of an array
-*
-* @param array &$var
-* @return array
-*/
-function array_stripslashes($var)
-{
- if (!is_array($var))
- {
- return stripslashes($var);
- }
- foreach($var as $key => $val)
- {
- $var[$key] = is_array($val) ? array_stripslashes($val) : stripslashes($val);
- }
- return $var;
-}
-
-/**
- * Return the number of bytes of a string, independent of mbstring.func_overload
- * AND the availability of mbstring
- *
- * @param string $str
- * @return int
- */
-function bytes($str)
-{
- static $func_overload = null;
-
- if (is_null($func_overload)) $func_overload = extension_loaded('mbstring') ? ini_get('mbstring.func_overload') : 0;
-
- return $func_overload & 2 ? mb_strlen($str,'ascii') : strlen($str);
-}
-
-/**
- * mbstring.func_overload safe substr
- *
- * @param string $data
- * @param int $offset
- * @param int $len
- * @return string
- */
-function cut_bytes(&$data,$offset,$len=null)
-{
- static $func_overload = null;
-
- if (is_null($func_overload)) $func_overload = extension_loaded('mbstring') ? ini_get('mbstring.func_overload') : 0;
-
- if (is_null($len))
- {
- return $func_overload & 2 ? mb_substr($data,$offset,bytes($data),'ascii') : substr($data,$offset);
- }
- return $func_overload & 2 ? mb_substr($data,$offset,$len,'ascii') : substr($data,$offset,$len);
-}
-
-if (!function_exists('imap_rfc822_parse_adrlist'))
-{
- /**
- * parses a (comma-separated) address string
- *
- * Examples:
- * - Joe Doe <[email protected]>
- * - "Doe, Joe" <[email protected]>
- * - "\'Joe Doe\'" <[email protected]> // actually not necessary to quote
- * - [email protected]
- * - root
- * - "Joe on its way Down Under :-\)" <[email protected]>
- * - "Giant; \"Big\" Box" <[email protected]>
- * - [email protected] <[email protected]> // this is wrong, because @ need to be quoted
- *
- * Invalid addresses, if detected, set host to '.SYNTAX-ERROR.'
- *
- * @param string $address - A string containing addresses
- * @param string $default_host - The default host name
- * @return array of objects. The objects properties are:
- * mailbox - the mailbox name (username)
- * host - the host name
- * personal - the personal name
- * adl - at domain source route
- */
- function imap_rfc822_parse_adrlist($address, $default_host)
- {
- $addresses = array();
- $pending = '';
- foreach(explode(',', $address) as $part)
- {
- $trimmed = trim(($pending ? $pending.',' : '').$part);
- if (($trimmed[0] == '"' && substr($trimmed, -1) != '>')||strpos($part, '@')===false)
- {
- $pending .= ($pending ? $pending.',' : '').$part;
- continue;
- }
- $pending = '';
- $matches = $personal = $mailbox = $host = null;
- if (preg_match('/^(.*)<([^>@]+)(@([^>]+))?>$/', $trimmed, $matches))
- {
- $personal = trim($matches[1]);
- $mailbox = $matches[2];
- $host = $matches[4];
- }
- elseif (strpos($trimmed, '@') !== false)
- {
- list($mailbox, $host) = explode('@', $trimmed);
- }
- else
- {
- $mailbox = $trimmed;
- }
- if ($personal[0] == '"' && substr($personal, -1) == '"')
- {
- $personal = str_replace('\\', '', substr($personal, 1, -1));
- }
- if (empty($host)) $host = $default_host;
-
- $addresses[] = (object)array_diff(array(
- 'mailbox' => $mailbox,
- 'host' => $host,
- 'personal' => $personal,
- ), array(null, ''));
- }
- return $addresses;
- }
-}
-
-if (!function_exists('imap_rfc822_write_address'))
-{
- /**
- * Returns a properly formatted email address given the mailbox, host, and personal info
- * @param string $mailbox - The mailbox name, see imap_open() for more information
- * @param string $host - The email host part
- * @param string $personal - The name of the account owner
- * @return string properly formatted email address as defined in » RFC2822.
- */
- function imap_rfc822_write_address($mailbox, $host, $personal)
- {
- if (is_array($personal)) $personal = implode(' ', $personal);
-
- //if (!preg_match('/^[!#$%&\'*+/0-9=?A-Z^_`a-z{|}~-]+$/u', $personal)) // that's how I read the rfc(2)822
- if ($personal && !preg_match('/^[0-9A-Z -]*$/iu', $personal)) // but quoting is never wrong, so quote more then necessary
- {
- $personal = '"'.str_replace(array('\\', '"'),array('\\\\', '\\"'), $personal).'"';
- }
- return ($personal ? $personal.' <' : '').$mailbox.($host ? '@'.$host : '').($personal ? '>' : '');
- }
-}
-
-if (!function_exists('imap_mime_header_decode'))
-{
- /**
- * Decodes MIME message header extensions that are non ASCII text (RFC2047)
- *
- * Uses Horde_Mime::decode() and therefore always returns only a single array element!
- *
- * @param string $text
- * @return array with single object with attribute text already in our internal encoding and charset
- * @deprecated use Horde_Mime::decode()
- */
- function imap_mime_header_decode($text)
- {
- return array((object)array(
- 'text' => Horde_Mime::decode($text),
- 'charset' => translation::charset(), // is already in our internal encoding!
- ));
- }
-}
-
-if (!function_exists('mb_strlen'))
-{
- /**
- * Number of characters in a string
- *
- * @param string $str
- * @return int
- */
- function mb_strlen($str)
- {
- return strlen($str);
- }
-}
-
-if (!function_exists('mb_substr'))
-{
- /**
- * Return part of a string
- *
- * @param string $data
- * @param int $offset
- * @param int $len
- * @return string
- */
- function mb_substr(&$data, $offset, $len=null)
- {
- return is_null($len) ? substr($data, $offset) : substr($data, $offset, $len);
- }
-}
-
-/**
- * Format array or other types as (one-line) string, eg. for error_log statements
- *
- * @param mixed $var variable to dump
- * @return string
- */
-function array2string($var)
-{
- switch (($type = gettype($var)))
- {
- case 'boolean':
- return $var ? 'TRUE' : 'FALSE';
- case 'string':
- return "'$var'";
- case 'integer':
- case 'double':
- case 'resource':
- return $var;
- case 'NULL':
- return 'NULL';
- case 'object':
- case 'array':
- return str_replace(array("\n",' '/*,'Array'*/),'',print_r($var,true));
- }
- return 'UNKNOWN TYPE!';
-}
-
-/**
- * Check if a given extension is loaded or load it if possible (requires sometimes disabled or unavailable dl function)
- *
- * @param string $extension
- * @param boolean $throw =false should we throw an exception, if $extension could not be loaded, default false = no
- * @return boolean true if loaded now, false otherwise
- */
-function check_load_extension($extension,$throw=false)
-{
- if (!defined('PHP_SHLIB_PREFIX'))
- {
- define('PHP_SHLIB_PREFIX',PHP_SHLIB_SUFFIX == 'dll' ? 'php_' : '');
- }
- // we check for the existens of 'dl', as multithreaded webservers dont have it and some hosters disable it !!!
- $loaded = extension_loaded($extension) || function_exists('dl') && @dl($dl=PHP_SHLIB_PREFIX.$extension.'.'.PHP_SHLIB_SUFFIX);
-
- if (!$loaded && $throw)
- {
- throw new Exception ("PHP extension '$extension' not loaded AND can NOT be loaded via dl('$dl')!");
- }
- return $loaded;
-}
-
-/**
- * @internal Not to be used directly. Should only be used by print_debug()
- */
-function print_debug_subarray($array)
-{
- foreach($array as $key => $value)
- {
- if (is_array($value))
- {
- $vartypes[$key] = print_debug_subarray($value);
- }
- else
- {
- $vartypes[$key] = gettype($value);
- }
- }
- return $vartypes;
-}
-
-/**
- * print debug data only when debugging mode is turned on.
- *
- * @author seek3r
- * This function is used to debugging data.
- * print_debug('this is some debugging data',$somevar);
- */
-function print_debug($message,$var = 'messageonly',$part = 'app', $level = 3)
-{
- if (($part == 'app' && DEBUG_APP == True) || ($part == 'api' && DEBUG_API == True))
- {
- if (!defined('DEBUG_OUTPUT'))
- {
- define('DEBUG_OUTPUT', 1);
- }
- if ($level >= DEBUG_LEVEL)
- {
- if (!is_array($var))
- {
- if ($var != 'messageonly')
- {
- if (!DEBUG_DATATYPES)
- {
- $output = "$message\n$var";
- }
- else
- {
- $output = "$message\n$var is a ".gettype($var);
- }
- }
- else
- {
- $output = $message;
- }
-
- /* Bit 1 means to output to screen */
- if (!!(DEBUG_OUTPUT & 1))
- {
- echo "$output<br>\n";
- }
- /* Bit 2 means to output to sql */
- if (!!(DEBUG_OUTPUT & 2))
- {
- /* Need to flesh this out still. I dont have a table to dump this in yet.*/
- /* So the SQL statement will go here*/
- }
-
- /* Example of how this can be extended to output to other locations as well. This example uses a COM object */
- /*
- if (!!(DEBUG_OUTPUT & 32))
- {
- $obj_debug = new COM('Some_COM_App.Class','localhost');
- if (is_object($obj_debug))
- {
- $DebugMessage_return = $obj_debug->DebugMessage($output);
- }
- }
- */
- }
- else
- {
- if (floor(phpversion()) > 3 && !!(DEBUG_OUTPUT & 2))
- {
- ob_start();
- }
- echo "<pre>\n$message\n";
- print_r($var);
- if (DEBUG_DATATYPES)
- {
- foreach($var as $key => $value)
- {
- if (is_array($value))
- {
- $vartypes[$key] = print_debug_subarray($value);
- }
- else
- {
- $vartypes[$key] = gettype($value);
- }
- }
- echo "Data Types:\n";
- print_r($vartypes);
- }
- echo "\n<pre>\n";
- if (floor(phpversion()) > 3 && !!(DEBUG_OUTPUT & 2))
- {
- $output .= ob_get_contents();
- ob_end_clean();
- /* Need to flesh this out still. I dont have a table to dump this in yet.*/
- /* So the SQL statement will go here*/
- if (!!(DEBUG_OUTPUT & 1))
- {
- echo "$output<br>\n";
- }
- }
- }
- }
- }
-}
-
-/**
- * Allows for array and direct function params as well as sanatization.
- *
- * @author seek3r
- * This function is used to validate param data as well as offer flexible function usage.
- *
- function somefunc()
- {
- $expected_args[0] = Array('name'=>'fname','default'=>'joe', 'type'=>'string');
- $expected_args[1] = Array('name'=>'mname','default'=>'hick', 'type'=>'string');
- $expected_args[2] = Array('name'=>'lname','default'=>'bob', 'type'=>'string');
- $recieved_args = func_get_args();
- $args = safe_args($expected_args, $recieved_args,__LINE__,__FILE__);
- echo 'Full name: '.$args['fname'].' '.$args['fname'].' '.$args['lname'].'<br>';
- //default result would be:
- // Full name: joe hick bob<br>
- }
-
- Using this it is possible to use the function in any of the following ways
- somefunc('jack','city','brown');
- or
- somefunc(array('fname'=>'jack','mname'=>'city','lname'=>'brown'));
- or
- somefunc(array('lname'=>'brown','fname'=>'jack','mname'=>'city'));
-
- For the last one, when using named params in an array you dont have to follow any order
- All three would result in - Full name: jack city brown<br>
-
- When you use this method of handling params you can secure your functions as well offer
- flexibility needed for both normal use and web services use.
- If you have params that are required just set the default as ##REQUIRED##
- Users of your functions can also use ##DEFAULT## to use your default value for a param
- when using the standard format like this:
- somefunc('jack','##DEFAULT##','brown');
- This would result in - Full name: jack hick brown<br>
- Its using the default value for the second param.
- Of course if you have the second param as a required field it will fail to work.
- */
-function safe_args($expected, $recieved, $line='??', $file='??')
-{
- /* This array will contain all the required fields */
- $required = Array();
-
- /* This array will contain all types for sanatization checking */
- /* only used when an array is passed as the first arg */
- $types = Array();
-
- /* start by looping thru the expected list and set params with */
- /* the default values */
- $num = count($expected);
- for ($i = 0; $i < $num; $i++)
- {
- $args[$expected[$i]['name']] = $expected[$i]['default'];
- if ($expected[$i]['default'] === '##REQUIRED##')
- {
- $required[$expected[$i]['name']] = True;
- }
- $types[$expected[$i]['name']] = $expected[$i]['type'];
- }
-
- /* Make sure they passed at least one param */
- if(count($recieved) != 0)
- {
- /* if used as standard function we loop thru and set by position */
- if(!is_array($recieved[0]))
- {
- for ($i = 0; $i < $num; $i++)
- {
- if(isset($recieved[$i]) && $recieved[$i] !== '##DEFAULT##')
- {
- if(sanitize($recieved[$i],$expected[$i]['type']))
- {
- $args[$expected[$i]['name']] = $recieved[$i];
- unset($required[$expected[$i]['name']]);
- }
- else
- {
- echo 'Fatal Error: Invalid paramater type for '.$expected[$i]['name'].' on line '.$line.' of '.$file.'<br>';
- exit;
- }
- }
- }
- }
- /* if used as standard function we loop thru and set by position */
- else
- {
- for ($i = 0; $i < $num; $i++)
- {
- $types[$expected[$i]['name']] = $expected[$i]['type'];
- }
- while(list($key,$val) = each($recieved[0]))
- {
- if($val !== '##DEFAULT##')
- {
- if(sanitize($val,$types[$key]) == True)
- {
- $args[$key] = $val;
- unset($required[$key]);
- }
- else
- {
- echo 'Fatal Error: Invalid paramater type for '.$key.' on line '.$line.' of '.$file.'<br>';
- exit;
- }
- }
- }
- }
- }
- if(count($required) != 0)
- {
- while (list($key) = each($required))
- {
- echo 'Fatal Error: Missing required paramater '.$key.' on line '.$line.' of '.$file.'<br>';
- }
- exit;
- }
- return $args;
-}
-
-/**
- * Validate data.
- *
- * @author seek3r
- * This function is used to validate input data.
- * sanitize('number',$somestring);
- */
-function sanitize($string,$type)
-{
- switch ($type)
- {
- case 'bool':
- if ($string == 1 || $string == 0)
- {
- return True;
- }
- break;
-
- case 'isprint':
- $length = strlen($string);
- $position = 0;
- while ($length > $position)
- {
- $char = substr($string, $position, 1);
- if ($char < ' ' || $char > '~')
- {
- return False;
- }
- $position = $position + 1;
- }
- return True;
-
- case 'alpha':
- if (preg_match("/^[a-z]+$/i", $string))
- {
- return True;
- }
- break;
-
- case 'number':
- if (preg_match("/^[0-9]+$/i", $string))
- {
- return True;
- }
- break;
-
- case 'alphanumeric':
- if (preg_match("/^[a-z0-9 -._]+$/i", $string))
- {
- return True;
- }
- break;
- case 'string':
- if (preg_match("/^[a-z]+$/i", $string))
- {
- return True;
- }
- break;
- case 'ip':
- if (preg_match('/'."^[0-9]{1,3}(\.[0-9]{1,3}){3}$".'/i',$string))
- {
- $octets = preg_split('/\./',$string);
- for ($i=0; $i != count($octets); $i++)
- {
- if ($octets[$i] < 0 || $octets[$i] > 255)
- {
- return False;
- }
- }
- return True;
- }
- return False;
-
- case 'file':
- if (preg_match("/^[a-z0-9_]+\.+[a-z]+$/i", $string))
- {
- return True;
- }
- break;
- case 'email':
- if (preg_match('/'."^([[:alnum:]_%+=.-]+)@([[:alnum:]_.-]+)\.([a-z]{2,3}|[0-9]{1,3})$".'/i',$string))
- {
- return True;
- }
- break;
- case 'password':
- $password_length = strlen($string);
- $password_numbers = Array('0','1','2','3','4','5','6','7','8','9');
- $password_special_chars = Array(' ','~','`','!','@','#','$','%','^','&','*','(',')','_','+','-','=','{','}','|','[',']',"\\",':','"',';',"'",'<','>','?',',','.','/');
-
- if(@isset($GLOBALS['egw_info']['server']['pass_min_length']) && is_int($GLOBALS['egw_info']['server']['pass_min_length']) && $GLOBALS['egw_info']['server']['pass_min_length'] > 1)
- {
- $min_length = $GLOBALS['egw_info']['server']['pass_min_length'];
- }
- else
- {
- $min_length = 1;
- }
-
- if(@isset($GLOBALS['egw_info']['server']['pass_require_non_alpha']) && $GLOBALS['egw_info']['server']['pass_require_non_alpha'] == True)
- {
- $pass_verify_non_alpha = False;
- }
- else
- {
- $pass_verify_non_alpha = True;
- }
-
- if(@isset($GLOBALS['egw_info']['server']['pass_require_numbers']) && $GLOBALS['egw_info']['server']['pass_require_numbers'] == True)
- {
- $pass_verify_num = False;
- }
- else
- {
- $pass_verify_num = True;
- }
-
- if(@isset($GLOBALS['egw_info']['server']['pass_require_special_char']) && $GLOBALS['egw_info']['server']['pass_require_special_char'] == True)
- {
- $pass_verify_special_char = False;
- }
- else
- {
- $pass_verify_special_char = True;
- }
-
- if ($password_length >= $min_length)
- {
- for ($i=0; $i != $password_length; $i++)
- {
- $cur_test_string = substr($string, $i, 1);
- if (in_array($cur_test_string, $password_numbers) || in_array($cur_test_string, $password_special_chars))
- {
- $pass_verify_non_alpha = True;
- if (in_array($cur_test_string, $password_numbers))
- {
- $pass_verify_num = True;
- }
- elseif (in_array($cur_test_string, $password_special_chars))
- {
- $pass_verify_special_char = True;
- }
- }
- }
-
- if ($pass_verify_num == False)
- {
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password requires at least one non-alpha character']=False;
- }
-
- if ($pass_verify_num == False)
- {
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password requires at least one numeric character']=False;
- }
-
- if ($pass_verify_special_char == False)
- {
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password requires at least one special character (non-letter and non-number)']=False;
- }
-
- if ($pass_verify_num == True && $pass_verify_special_char == True)
- {
- return True;
- }
- return False;
- }
- $GLOBALS['egw_info']['flags']['msgbox_data']['Password must be at least '.$min_length.' characters']=False;
- return False;
-
- case 'any':
- return True;
-
- default :
- if (isset($GLOBALS['egw_info']['server']['sanitize_types'][$type]['type']))
- {
- if ($GLOBALS['egw_info']['server']['sanitize_types'][$type]['type']($GLOBALS['egw_info']['server']['sanitize_types'][$type]['string'], $string))
- {
- return True;
- }
- }
- return False;
- }
-}
-
-function reg_var($varname, $method='any', $valuetype='alphanumeric',$default_value='',$register=True)
-{
- if($method == 'any' || $method == array('any'))
- {
- $method = Array('POST','GET','COOKIE','SERVER','FILES','GLOBAL','DEFAULT');
- }
- elseif(!is_array($method))
- {
- $method = Array($method);
- }
- $cnt = count($method);
- for($i=0;$i<$cnt;$i++)
- {
- switch(strtoupper($method[$i]))
- {
- case 'DEFAULT':
- if($default_value)
- {
- $value = $default_value;
- $i = $cnt+1; /* Found what we were looking for, now we end the loop */
- }
- break;
- case 'GLOBAL':
- if(@isset($GLOBALS[$varname]))
- {
- $value = $GLOBALS[$varname];
- $i = $cnt+1;
- }
- break;
- case 'POST':
- case 'GET':
- case 'COOKIE':
- case 'SERVER':
- if(phpversion() >= '4.1.0')
- {
- $meth = '_'.strtoupper($method[$i]);
- }
- else
- {
- $meth = 'HTTP_'.strtoupper($method[$i]).'_VARS';
- }
- if(@isset($GLOBALS[$meth][$varname]))
- {
- $value = $GLOBALS[$meth][$varname];
- $i = $cnt+1;
- }
- if(get_magic_quotes_gpc() && isset($value))
- {
- // we need to stripslash 3 levels of arrays
- // because of the password function in preferences
- // it's named ['user']['variablename']['pw']
- // or something like this in projects
- // $values['budgetBegin']['1']['year']
- if(@is_array($value))
- {
- /* stripslashes on the first level of array values */
- foreach($value as $name => $val)
- {
- if(@is_array($val))
- {
- foreach($val as $name2 => $val2)
- {
- if(@is_array($val2))
- {
- foreach($val2 as $name3 => $val3)
- {
- $value[$name][$name2][$name3] = stripslashes($val3);
- }
- }
- else
- {
- $value[$name][$name2] = stripslashes($val2);
- }
- }
- }
- else
- {
- $value[$name] = stripslashes($val);
- }
- }
- }
- else
- {
- /* stripslashes on this (string) */
- $value = stripslashes($value);
- }
- }
- break;
- case 'FILES':
- if(phpversion() >= '4.1.0')
- {
- $meth = '_FILES';
- }
- else
- {
- $meth = 'HTTP_POST_FILES';
- }
- if(@isset($GLOBALS[$meth][$varname]))
- {
- $value = $GLOBALS[$meth][$varname];
- $i = $cnt+1;
- }
- break;
- default:
- if(@isset($GLOBALS[strtoupper($method[$i])][$varname]))
- {
- $value = $GLOBALS[strtoupper($method[$i])][$varname];
- $i = $cnt+1;
- }
- break;
- }
- }
-
- if (@!isset($value))
- {
- $value = $default_value;
- }
-
- if (@!is_array($value))
- {
- if ($value == '')
- {
- $result = $value;
- }
- else
- {
- if (sanitize($value,$valuetype) == 1)
- {
- $result = $value;
- }
- else
- {
- $result = $default_value;
- }
- }
- }
- else
- {
- reset($value);
- while(list($k, $v) = each($value))
- {
- if ($v == '')
- {
- $result[$k] = $v;
- }
- else
- {
- if (is_array($valuetype))
- {
- $vt = $valuetype[$k];
- }
- else
- {
- $vt = $valuetype;
- }
-
- if (sanitize($v,$vt) == 1)
- {
- $result[$k] = $v;
- }
- else
- {
- if (is_array($default_value))
- {
- $result[$k] = $default_value[$k];
- }
- else
- {
- $result[$k] = $default_value;
- }
- }
- }
- }
- }
- if($register)
- {
- $GLOBALS['egw_info'][$GLOBALS['egw_info']['flags']['currentapp']][$varname] = $result;
- }
- return $result;
-}
-
-/**
- * retrieve a value from either a POST, GET, COOKIE, SERVER or from a class variable.
- *
- * @author skeeter
- * This function is used to retrieve a value from a user defined order of methods.
- * $this->id = get_var('id',array('HTTP_POST_VARS'||'POST','HTTP_GET_VARS'||'GET','HTTP_COOKIE_VARS'||'COOKIE','GLOBAL','DEFAULT'));
- * @param $variable name
- * @param $method ordered array of methods to search for supplied variable
- * @param $default_value (optional)
- */
-function get_var($variable,$method='any',$default_value='')
-{
- if(!@is_array($method))
- {
- $method = array($method);
- }
- return reg_var($variable,$method,'any',$default_value,False);
-}
-
-/**
- * Load a class and include the class file if not done so already.
- *
- * This function is used to create an instance of a class, and if the class file has not been included it will do so.
- * $GLOBALS['egw']->acl =& CreateObject('phpgwapi.acl');
- *
- * @author [email protected]
- * @param $classname name of class
- * @param $p1,$p2,... class parameters (all optional)
- * @return object reference to an object
- */
-function CreateObject($class)
-{
- list($appname,$classname) = explode('.',$class);
-
- if (!class_exists($classname))
- {
- static $replace = array(
- 'datetime' => 'egw_datetime',
- 'uitimesheet' => 'timesheet_ui',
- 'uiinfolog' => 'infolog_ui',
- 'uiprojectmanager' => 'projectmanager_ui',
- 'uiprojectelements' => 'projectmanager_elements_ui',
- 'uiroles' => 'projectmanager_roles_ui',
- 'uimilestones' => 'projectmanager_milestones_ui',
- 'uipricelist' => 'projectmanager_pricelist_ui',
- 'bowiki' => 'wiki_bo',
- 'uicategories' => 'admin_categories',
- 'defaultimap' => 'emailadmin_oldimap',
- );
- if (!file_exists(EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php') || isset($replace[$classname]))
- {
- if (isset($replace[$classname]))
- {
- //throw new Exception(__METHOD__."('$class') old classname '$classname' used in menuaction=$_GET[menuaction]!");
- error_log(__METHOD__."('$class') old classname '$classname' used in menuaction=$_GET[menuaction]!");
- $classname = $replace[$classname];
- }
- }
- if (!file_exists($f=EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php'))
- {
- throw new Api\Exception\AssertionFailed(__FUNCTION__."($classname) file $f not found!");
- }
- // this will stop php with a 500, if the class does not exist or there are errors in it (syntax error go into the error_log)
- require_once(EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php');
- }
- $args = func_get_args();
- switch(count($args))
- {
- case 1:
- $obj = new $classname;
- break;
- case 2:
- $obj = new $classname($args[1]);
- break;
- case 3:
- $obj = new $classname($args[1],$args[2]);
- break;
- case 4:
- $obj = new $classname($args[1],$args[2],$args[3]);
- break;
- default:
- $code = '$obj = new ' . $classname . '(';
- foreach(array_keys($args) as $n)
- {
- if ($n)
- {
- $code .= ($n > 1 ? ',' : '') . '$args[' . $n . ']';
- }
- }
- $code .= ');';
- eval($code);
- break;
- }
- if (!is_object($obj))
- {
- echo "<p>CreateObject('$class'): Cant instanciate class!!!<br />\n".function_backtrace(1)."</p>\n";
- }
- return $obj;
-}
-
-/**
- * Execute a function with multiple arguments
- * We take object $GLOBALS[classname] from class if exists
- *
- * @param string app.class.method method to execute
- * @example ExecObject('etemplates.so_sql.search',$criteria,$key_only,...);
- * @return mixed reference to returnvalue of the method
- */
-function &ExecMethod2($acm)
-{
- // class::method is php5.2.3+
- if (strpos($acm,'::') !== false && version_compare(PHP_VERSION,'5.2.3','<'))
- {
- list($class,$method) = explode('::',$acm);
- $acm = array($class,$method);
- }
- if (!is_callable($acm))
- {
- list(,$class,$method) = explode('.',$acm);
- if (!is_object($obj =& $GLOBALS[$class]))
- {
- if (class_exists($class))
- {
- $obj = new $class;
- }
- else
- {
- $obj = CreateObject($acm);
- }
- }
-
- if (!method_exists($obj,$method))
- {
- echo "<p><b>".function_backtrace()."</b>: no methode '$method' in class '$class'</p>\n";
- return False;
- }
- $acm = array($obj,$method);
- }
- $args = func_get_args();
- unset($args[0]);
-
- return call_user_func_array($acm,$args);
-}
-
-/**
- * Execute a function, and load a class and include the class file if not done so already.
- *
- * This function is used to create an instance of a class, and if the class file has not been included it will do so.
- *
- * @author seek3r
- * @param $method to execute
- * @param $functionparam function param should be an array
- * @param $loglevel developers choice of logging level
- * @param $classparams params to be sent to the contructor
- * @return mixed returnvalue of method
- */
-function ExecMethod($method, $functionparam = '_UNDEF_', $loglevel = 3, $classparams = '_UNDEF_')
-{
- unset($loglevel); // not used
- /* Need to make sure this is working against a single dimensional object */
- $partscount = count(explode('.',$method)) - 1;
-
- if (!is_callable($method) && $partscount == 2)
- {
- list($appname,$classname,$functionname) = explode(".", $method);
- if (!is_object($GLOBALS[$classname]))
- {
- // please note: no reference assignment (=&) here, as $GLOBALS is a reference itself!!!
- if ($classparams != '_UNDEF_' && ($classparams || $classparams != 'True'))
- {
- $GLOBALS[$classname] = CreateObject($appname.'.'.$classname, $classparams);
- }
- elseif (class_exists($classname))
- {
- $GLOBALS[$classname] = new $classname;
- }
- else
- {
- $GLOBALS[$classname] = CreateObject($appname.'.'.$classname);
- }
- }
-
- if (!method_exists($GLOBALS[$classname],$functionname))
- {
- error_log("ExecMethod('$method', ...) No methode '$functionname' in class '$classname'! ".function_backtrace());
- return false;
- }
- $method = array($GLOBALS[$classname],$functionname);
- }
- if (is_callable($method))
- {
- return $functionparam != '_UNDEF_' ? call_user_func($method,$functionparam) : call_user_func($method);
- }
- error_log("ExecMethod('$method', ...) Error in parts! ".function_backtrace());
- return false;
-}
-
-/**
- * Return a properly formatted account_id.
- *
- * @author skeeter
- * This function will return a properly formatted account_id. This can take either a name or an account_id as paramters. If a name is provided it will return the associated id.
- * $account_id = get_account_id($accountid);
- * @param int/string $account_id either a name or an id
- * @param int/string $default_id either a name or an id
- * @return int account_id
- */
-function get_account_id($account_id = '',$default_id = '')
-{
- if (gettype($account_id) == 'integer')
- {
- return $account_id;
- }
- elseif ($account_id == '')
- {
- if ($default_id == '')
- {
- return (isset($GLOBALS['egw_info']['user']['account_id'])?$GLOBALS['egw_info']['user']['account_id']:0);
- }
- elseif (is_string($default_id))
- {
- return $GLOBALS['egw']->accounts->name2id($default_id);
- }
- return (int)$default_id;
- }
- elseif (is_string($account_id))
- {
- if($GLOBALS['egw']->accounts->exists((int)$account_id) == True)
- {
- return (int)$account_id;
- }
- else
- {
- return $GLOBALS['egw']->accounts->name2id($account_id);
- }
- }
-}
-
-/**
- * sets the file system seperator depending on OS
- *
- * This is completely unnecessary, as you can use forward slashes in php under every OS -- RalfBecker 2005/11/09
- *
- * @deprecated just use forward slashes supported by PHP on all OS
- * @return file system separator
- */
-function filesystem_separator()
-{
- if(PHP_OS == 'Windows' || PHP_OS == 'OS/2' || PHP_OS == 'WINNT')
- {
- return '\\';
- }
- else
- {
- return '/';
- }
-}
-
-/**
- * @deprecated just use forward slashes supported by PHP on all OS
- */
-define('SEP', filesystem_separator());
-
-/**
- * print an array or object as pre-formatted html
- *
- * @param mixed $array
- * @param boolean $print =true print or return the content
- * @return string if !$print
- */
-function _debug_array($array,$print=True)
-{
- $output = '<pre>'.print_r($array,true)."</pre>\n";
-
- if ($print)
- {
- echo $output;
- }
- else
- {
- return $output;
- }
-}
-
-/**
- * eGW version checking, is eGW version in $a < $b
- *
- * @param string $a egw version number to check if less than $b
- * @param string $b egw version number to check $a against
- * @return boolean True if $a < $b
- */
-function alessthanb($a,$b,$DEBUG=False)
-{
- $num = array('1st','2nd','3rd','4th');
-
- if ($DEBUG)
- {
- echo'<br>Input values: ' . 'A="'.$a.'", B="'.$b.'"';
- }
- $newa = str_replace('pre','.',$a);
- $newb = str_replace('pre','.',$b);
- $testa = explode('.',$newa);
- if(@$testa[1] == '')
- {
- $testa[1] = 0;
- }
- if(@$testa[3] == '')
- {
- $testa[3] = 0;
- }
- $testb = explode('.',$newb);
- if(@$testb[1] == '')
- {
- $testb[1] = 0;
- }
- if(@$testb[3] == '')
- {
- $testb[3] = 0;
- }
- $less = 0;
-
- for ($i=0;$i<count($testa);$i++)
- {
- if ($DEBUG) { echo'<br>Checking if '. (int)$testa[$i] . ' is less than ' . (int)$testb[$i] . ' ...'; }
- if ((int)$testa[$i] < (int)$testb[$i])
- {
- if ($DEBUG) { echo ' yes.'; }
- $less++;
- if ($i<3)
- {
- /* Ensure that this is definitely smaller */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely less than B."; }
- $less = 5;
- break;
- }
- }
- elseif((int)$testa[$i] > (int)$testb[$i])
- {
- if ($DEBUG) { echo ' no.'; }
- $less--;
- if ($i<2)
- {
- /* Ensure that this is definitely greater */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely greater than B."; }
- $less = -5;
- break;
- }
- }
- else
- {
- if ($DEBUG) { echo ' no, they are equal.'; }
- $less = 0;
- }
- }
- if ($DEBUG) { echo '<br>Check value is: "'.$less.'"'; }
- if ($less>0)
- {
- if ($DEBUG) { echo '<br>A is less than B'; }
- return True;
- }
- elseif($less<0)
- {
- if ($DEBUG) { echo '<br>A is greater than B'; }
- return False;
- }
- else
- {
- if ($DEBUG) { echo '<br>A is equal to B'; }
- return False;
- }
-}
-
-/**
- * eGW version checking, is eGW version in $a > $b
- *
- * @param string $a eGW version number to check if more than $b
- * @param string $b eGW version number to check check $a against
- * @return boolean True if $a > $b
- */
-function amorethanb($a,$b,$DEBUG=False)
-{
- $num = array('1st','2nd','3rd','4th');
-
- if ($DEBUG)
- {
- echo'<br>Input values: ' . 'A="'.$a.'", B="'.$b.'"';
- }
- $newa = str_replace('pre','.',$a);
- $newb = str_replace('pre','.',$b);
- $testa = explode('.',$newa);
- if($testa[3] == '')
- {
- $testa[3] = 0;
- }
- $testb = explode('.',$newb);
- if($testb[3] == '')
- {
- $testb[3] = 0;
- }
- $less = 0;
-
- for ($i=0;$i<count($testa);$i++)
- {
- if ($DEBUG) { echo'<br>Checking if '. (int)$testa[$i] . ' is more than ' . (int)$testb[$i] . ' ...'; }
- if ((int)$testa[$i] > (int)$testb[$i])
- {
- if ($DEBUG) { echo ' yes.'; }
- $less++;
- if ($i<3)
- {
- /* Ensure that this is definitely greater */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely greater than B."; }
- $less = 5;
- break;
- }
- }
- elseif((int)$testa[$i] < (int)$testb[$i])
- {
- if ($DEBUG) { echo ' no.'; }
- $less--;
- if ($i<2)
- {
- /* Ensure that this is definitely smaller */
- if ($DEBUG) { echo" This is the $num[$i] octet, so A is definitely less than B."; }
- $less = -5;
- break;
- }
- }
- else
- {
- if ($DEBUG) { echo ' no, they are equal.'; }
- $less = 0;
- }
- }
- if ($DEBUG) { echo '<br>Check value is: "'.$less.'"'; }
- if ($less>0)
- {
- if ($DEBUG) { echo '<br>A is greater than B'; }
- return True;
- }
- elseif($less<0)
- {
- if ($DEBUG) { echo '<br>A is less than B'; }
- return False;
- }
- else
- {
- if ($DEBUG) { echo '<br>A is equal to B'; }
- return False;
- }
-}
-
-/**
- * prepend a prefix to an array of table names
- *
- * @author Adam Hull (aka fixe) - No copyright claim
- * @param $prefix the string to be prepended
- * @param $tables and array of tables to have the prefix prepended to
- * @return array of table names with the prefix prepended
- */
-function prepend_tables_prefix($prefix,$tables)
-{
- foreach($tables as $key => $value)
- {
- $tables[$key] = $prefix.$value;
- }
- return $tables;
-}
-
-/**
- * backtrace of the calling functions for php4.3+ else menuaction/scriptname
- *
- * @author RalfBecker-AT-outdoor-training.de
- * @param int $remove =0 number of levels to remove
- * @return string function-names separated by slashes (beginning with the calling function not this one)
- */
-function function_backtrace($remove=0)
-{
- if (function_exists('debug_backtrace'))
- {
- $backtrace = debug_backtrace();
- //echo "function_backtrace($remove)<pre>".print_r($backtrace,True)."</pre>\n";
- foreach($backtrace as $n => $level)
- {
- if ($remove-- < 0)
- {
- $ret[] = (isset($level['class'])?$level['class'].$level['type']:'').$level['function'].
- ($n > 0 && isset($backtrace[$n-1]['line']) ? ':'.$backtrace[$n-1]['line'] : ''). // add line number of call
- (!$level['class'] && !is_object($level['args'][0]) && $level['function'] != 'unserialize' ?
- '('.substr(str_replace(EGW_SERVER_ROOT,'',(string)$level['args'][0]),0,64).')' : '');
- }
- }
- if (is_array($ret))
- {
- return implode(' / ',$ret);
- }
- }
- return $_GET['menuaction'] ? $_GET['menuaction'] : str_replace(EGW_SERVER_ROOT,'',$_SERVER['SCRIPT_FILENAME']);
-}
-
-/**
- * check $_REQUEST data for XSS, vars containing script tags are moved to $GLOBALS['egw_unset_vars']
- *
- * @internal
- * @param array &$var reference of array to check
- * @param string $name ='' name of the array
- */
-function _check_script_tag(&$var,$name='')
-{
- static $preg=null;
- //old: '/<\/?[^>]*\b(iframe|script|javascript|on(before)?(abort|blur|change|click|dblclick|error|focus|keydown|keypress|keyup|load|mousedown|mousemove|mouseout|mouseover|mouseup|reset|select|submit|unload))\b[^>]*>/i';
- if (!isset($preg)) $preg =
- // forbidden tags like iframe or script
- '/(<(\s*\/)?\s*(iframe|script|object|embed|math|meta)[^a-z0-9]|'.
- // on* attributes
- '<[^>]*on(before)?(abort|blur|change|click|dblclick|error|focus|keydown|keypress|keyup|load|mouse[^=]+|reset|select|submit|unload|resize|propertychange|page[^=]*|scroll|readystatechange|start|popstate|form[^=]+|input)\s*=|'.
- // ="javascript:*" diverse javascript attribute value
- '<[^>]+(href|src|dynsrc|lowsrc|background|style|poster|action)\s*=\s*("|\')?[^"\']*javascript|'.
- // benavior:url and expression in style attribute
- '<[^>]+style\s*=\s*("|\')[^>]*(behavior\s*:\s*url|expression)\s*\()/i';
- if (is_array($var))
- {
- foreach($var as $key => $val)
- {
- if (is_array($val))
- {
- _check_script_tag($var[$key],$name.'['.$key.']');
- }
- elseif(strpos($val, '<') !== false) // speedup: ignore everything without <
- {
- if (preg_match($preg,$val))
- {
- // special handling for $_POST[json_data], to decend into it's decoded content, fixing json direct might break json syntax
- if ($name == '_POST' && $key == 'json_data' && ($json_data = json_decode($val, true)))
- {
- _check_script_tag($json_data, $name.'[json_data]');
- $_REQUEST[$key] = $var[$key] = json_encode($json_data);
- continue;
- }
- error_log(__FUNCTION__."(,$name) ${name}[$key] = ".$var[$key]);
- $GLOBALS['egw_unset_vars'][$name.'['.$key.']'] = $var[$key];
- // attempt to clean the thing
- $var[$key] = $val = html::purify($val);
- // check if we succeeded, if not drop the var anyway, keep the egw_unset_var in any case
- if (preg_match($preg,$val))
- {
- error_log("*** _check_script_tag($name): unset(${name}[$key]) with value $val***");
- unset($var[$key]);
- }
- }
- }
- }
- // in case some stupid old code expects the array-pointer to be at the start of the array
- reset($var);
- }
-}
-
-/* some _check_script_tag tests, should be commented out by default
-if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__) // some tests
-{
- if (!defined('EGW_INCLUDE_ROOT'))
- {
- define(EGW_INCLUDE_ROOT, realpath(dirname(__FILE__).'/../..'));
- define(EGW_API_INC, realpath(dirname(__FILE__)));
- }
-
- $total = $num_failed = 0;
- $patterns = array(
- // pattern => true: should fail, false: should not fail
- '< script >alert(1)< / script >' => true,
- '<span onMouseOver ="alert(1)">blah</span>' => true,
- '<a href= "JaVascript: alert(1)">Click Me</a>' => true,
- // from https://www.acunetix.com/websitesecurity/cross-site-scripting/
- '<body onload=alert("XSS")>' => true,
- '<body background="javascript:alert("XSS")">' => true,
- '<iframe src=âhttp://evil.com/xss.htmlâ>' => true,
- '<input type="image" src="javascript:alert(\'XSS\');">' => true,
- '<link rel="stylesheet" href="javascript:alert(\'XSS\');">' => true,
- '<table background="javascript:alert(\'XSS\')">' => true,
- '<td background="javascript:alert(\'XSS\')">' => true,
- '<div style="background-image: url(javascript:alert(\'XSS\'))">' => true,
- '<div style="width: expression(alert(\'XSS\'));">' => true,
- '<object type="text/x-scriptlet" data="http://hacker.com/xss.html">' => true,
- // false positiv tests
- 'If 1 < 2, what does that mean for description, if 2 > 1.' => false,
- 'If 1 < 2, what does that mean for a script, if 2 > 1.' => false,
- '<div>Script and Javascript: not evil ;-)' => false,
- '<span>style=background-color' => false,
- '<font face="Script MT Bold" size="4"><span style="font-size:16pt;">Hugo Sonstwas</span></font>' => false,
- '<[email protected]>' => false,
- );
- foreach($patterns as $pattern => $should_fail)
- {
- $test = array($pattern);
- unset($GLOBALS['egw_unset_vars']);
- _check_script_tag($test,'test');
- $failed = isset($GLOBALS['egw_unset_vars']) !== $should_fail;
- ++$total;
- if ($failed) $num_failed++;
- echo "<p style='color: ".($failed?'red':'black')."'> ".html::htmlspecialchars($pattern).' '.
- (isset($GLOBALS['egw_unset_vars'])?'removed':'passed')."</p>";
- }
- $x = 1;
- // urls with attack vectors
- $urls = array(
- // we currently fail 76 of 666 test, thought they seem not to apply to our use case, as we check request data
- 'https://gist.github.com/JohannesHoppe/5612274' => file(
- 'https://gist.githubusercontent.com/JohannesHoppe/5612274/raw/60016bccbfe894dcd61a6be658a4469e403527de/666_lines_of_XSS_vectors.html'),
- // we currently fail 44 of 140 tests, thought they seem not to apply to our use case, as we check request data
- 'https://html5sec.org/' => call_user_func(function() {
- $payloads = $items = null;
- if (!($items_js = file_get_contents('https://html5sec.org/items.js')) ||
- !preg_match_all("|^\s+'data'\s+:\s+'(.*)',$|m", $items_js, $items, PREG_PATTERN_ORDER) ||
- !($payload_js = file_get_contents('https://html5sec.org/payloads.js')) ||
- !preg_match_all("|^\s+'([^']+)'\s+:\s+'(.*)',$|m", $payload_js, $payloads, PREG_PATTERN_ORDER))
- {
- return false;
- }
- $replace = array(
- "\\'" => "'",
- '\\\\'=> '\\,',
- '\r' => "\r",
- '\n' => "\n",
- );
- foreach($payloads[1] as $n => $from) {
- $replace['%'.$from.'%'] = $payloads[2][$n];
- }
- return array_map(function($item) use ($replace) {
- return strtr($item, $replace);
- }, $items[1]);
- }),
- );
- foreach($urls as $url => $vectors)
- {
- // no all xss attack vectors from http://ha.ckers.org/xssAttacks.xml are relevant here! (needs interpretation)
- if (!$vectors)
- {
- echo "<p style='color:red'>Could NOT download or parse $url with attack vectors!</p>\n";
- continue;
- }
- echo "<p><b>Attacks from <a href='$url' target='_blank'>$url</a> with ".count($vectors)." tests:</b></p>";
- foreach($vectors as $line => $pattern)
- {
- $test = array($pattern);
- unset($GLOBALS['egw_unset_vars']);
- _check_script_tag($test, 'line '.(1+$line));
- $failed = !isset($GLOBALS['egw_unset_vars']);
- ++$total;
- if ($failed) $num_failed++;
- echo "<p style='color: ".($failed?'red':'black')."'>".(1+$line).": ".html::htmlspecialchars($pattern).' '.
- (isset($GLOBALS['egw_unset_vars'])?'removed':'passed')."</p>";
- }
- }
- die("<p style='color: ".($num_failed?'red':'black')."'>Tests finished: $num_failed / $total failed</p>");
-}*/
-
-foreach(array('_GET','_POST','_REQUEST','HTTP_GET_VARS','HTTP_POST_VARS') as $n => $where)
-{
- $pregs = array(
- 'order' => '/^[a-zA-Z0-9_,]*$/',
- 'sort' => '/^(ASC|DESC|asc|desc|0|1|2|3|4|5|6|7){0,1}$/',
- );
- foreach(array('order','sort') as $name)
- {
- if (isset($GLOBALS[$where][$name]) && !is_array($GLOBALS[$where][$name]) && !preg_match($pregs[$name],$GLOBALS[$where][$name]))
- {
- $GLOBALS[$where][$name] = '';
- }
- }
- // do the check for script-tags only for _GET and _POST or if we found something in _GET and _POST
- // speeds up the execusion a bit
- if (isset($GLOBALS[$where]) && is_array($GLOBALS[$where]) && ($n < 2 || isset($GLOBALS['egw_unset_vars'])))
- {
- _check_script_tag($GLOBALS[$where],$where);
- }
-}
-//if (is_array($GLOBALS['egw_unset_vars'])) { echo "egw_unset_vars=<pre>".htmlspecialchars(print_r($GLOBALS['egw_unset_vars'],true))."</pre>"; exit; }
-
-// $GLOBALS[egw_info][flags][currentapp] and die if it contains something nasty or unexpected
-if (isset($GLOBALS['egw_info']) && isset($GLOBALS['egw_info']['flags']) &&
- isset($GLOBALS['egw_info']['flags']['currentapp']) && !preg_match('/^[A-Za-z0-9_-]+$/',$GLOBALS['egw_info']['flags']['currentapp']))
-{
- error_log(__FILE__.': '.__LINE__.' Invalid $GLOBALS[egw_info][flags][currentapp]='.array2string($GLOBALS['egw_info']['flags']['currentapp']).', $_SERVER[REQUEST_URI]='.array2string($_SERVER[REQUEST_URI]));
- die('Invalid $GLOBALS[egw_info][flags][currentapp]!');
-}
-
-// neutralises register_globals On, which is not used by eGW
-// some code from the hardend php project: http://www.hardened-php.net/articles/PHPUG-PHP-Sicherheit-Parametermanipulationen.pdf
-if (ini_get('register_globals'))
-{
- function unregister_globals()
- {
- // protect against GLOBALS overwrite or setting egw_info
- if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS']) || isset($_REQUEST['egw_info']) || isset($_FILES['egw_info']))
- {
- die('GLOBALS overwrite detected!!!');
- }
- // unregister all globals
- $noUnset = array('GLOBALS','_GET','_POST','_COOKIE','_SERVER','_ENV','_FILES','xajax');
- foreach(array_unique(array_merge(
- array_keys($_GET),array_keys($_POST),array_keys($_COOKIE),array_keys($_SERVER),array_keys($_ENV),array_keys($_FILES),
- isset($_SESSION) && is_array($_SESSION) ? array_keys($_SESSION) : array())) as $k)
- {
- if (!in_array($k,$noUnset) && isset($GLOBALS[$k]))
- {
- unset($GLOBALS[$k]);
- }
- }
- }
- unregister_globals();
-}
-
-if (!function_exists('lang') || defined('NO_LANG')) // setup declares an own version
-{
- /**
- * function to handle multilanguage support
- *
- * @param string $key message in englich with %1, %2, ... placeholders
- * @param string $vars =null multiple values to replace the placeholders
- * @return string translated message with placeholders replaced
- */
- function lang($key,$vars=null)
- {
- if(!is_array($vars))
- {
- $vars = func_get_args();
- array_shift($vars); // remove $key
- }
- return translation::translate($key,$vars);
- }
-}
-
-/**
- * Translate message only if translation object is already loaded
- *
- * This function is usefull for exception handlers or early stages of the initialisation of the egw object,
- * as calling lang would try to load the translations, evtl. cause more errors, eg. because there's no db-connection.
- *
- * @param string $key message in englich with %1, %2, ... placeholders
- * @param string $vars =null multiple values to replace the placeholders
- * @return string translated message with placeholders replaced
- */
-function try_lang($key,$vars=null)
-{
- static $varnames = array('%1','%2','%3','%4');
-
- if(!is_array($vars))
- {
- $vars = func_get_args();
- array_shift($vars); // remove $key
- }
- return class_exists(translations,false) ? translation::translate($key,$vars) : str_replace($varnames,$vars,$key);
-}
-
-/**
- * Unserialize a php serialized string, but only if it contains NO objects 'O:\d:"' or 'C:\d:"' pattern
- *
- * Should be used for all external content, to guard against exploidts.
- *
- * PHP 7.0+ can be told not to instanciate any classes (and calling eg. it's destructor).
- * In fact it instanciates it as __PHP_Incomplete_Class without any methods and therefore disarming threads.
- *
- * @param string $str
- * @return mixed
- */
-function php_safe_unserialize($str)
-{
- if (PHP_VERSION >= 7)
- {
- return unserialize($str, array('allowed_classes' => false));
- }
- if ((strpos($str, 'O:') !== false || strpos($str, 'C:') !== false) &&
- preg_match('/(^|;|{)[OC]:\d+:"/', $str))
- {
- error_log(__METHOD__."('$str') contains objects --> return NULL");
- return null; // null, not false, to not trigger behavior of returning string itself to app code
- }
- return unserialize($str);
-}
-
-/* some test for object safe unserialisation
-if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__) // some tests
-{
- if (php_sapi_name() !== 'cli') echo "<pre>\n";
- foreach(array(
- // things unsafe to unserialize
- "O:34:\"Horde_Kolab_Server_Decorator_Clean\":2:{s:43:\"\x00Horde_Kolab_Server_Decorator_Clean\x00_server\";" => false,
- "O:20:\"Horde_Prefs_Identity\":2:{s:9:\"\x00*\x00_prefs\";O:11:\"Horde_Prefs\":2:{s:8:\"\x00*\x00_opts\";a:1:{s:12:\"sizecallback\";" => false,
- "a:2:{i:0;O:12:\"Horde_Config\":1:{s:13:\"\x00*\x00_oldConfig\";s:#{php_injection.length}:\"#{php_injection}\";}i:1;s:13:\"readXMLConfig\";}}" => false,
- 'a:6:{i:0;i:0;i:1;d:2;i:2;s:4:"ABCD";i:3;r:3;i:4;O:8:"my_Class":2:{s:1:"a";r:6;s:1:"b";N;};i:5;C:16:"SplObjectStorage":14:{x:i:0;m:a:0:{}}' => false,
- serialize(new stdClass()) => false,
- serialize(array(new stdClass(), new SplObjectStorage())) => false,
- // string content, safe to unserialize
- serialize('O:8:"stdClass"') => true,
- serialize('C:16:"SplObjectStorage"') => true,
- serialize(array('a' => 'O:8:"stdClass"', 'b' => 'C:16:"SplObjectStorage"')) => true,
- // false positive: failing our php<7 regular expression, because it has correct delimiter (^|;|{) in front of pattern :-(
- serialize('O:8:"stdClass";C:16:"SplObjectStorage"') => true,
- ) as $str => $result)
- {
- if ((bool)($r=php_safe_unserialize($str)) !== $result)
- {
- if (!$result)
- {
- if (PHP_VERSION >= 7)
- {
- if (preg_match_all('/([^ ]+) Object\(/', array2string($r), $matches))
- {
- foreach($matches[1] as $class)
- {
- if (!preg_match('/^__PHP_Incomplete_Class(#\d+)?$/', $class))
- {
- echo "FAILED: $str\n";
- continue 2;
- }
- }
- }
- echo "passed: ".array2string($str)." = ".array2string($r)."\n";
- }
- else
- {
- echo "FAILED: $str\n";
- }
- }
- else
- {
- echo "false positive: $str\n";
- }
- }
- else
- {
- echo "passed: $str\n";
- }
- //echo "result=".array2string($result).", php_save_unserialize('".htmlspecialchars($str)."') = ".array2string(php_safe_unserialize($str))." --> ".array2string((bool)php_safe_unserialize($str))."\n";
- }
-}*/
-
-/**
- * Unserialize a json or php serialized array
- *
- * Used to migrate from PHP serialized database values to json-encoded ones.
- *
- * @param string $str string with serialized array
- * @param boolean $allow_not_serialized =false true: return $str as is, if it is no serialized array
- * @return array|str|false
- */
-function json_php_unserialize($str, $allow_not_serialized=false)
-{
- if ((in_array($str[0], array('a', 'i', 's', 'b', 'O', 'C')) && $str[1] == ':' || $str === 'N;') &&
- ($arr = php_safe_unserialize($str)) !== false || $str === 'b:0;')
- {
- return $arr;
- }
- if (!$allow_not_serialized || $str[0] == '[' || $str[0] == '{' || $str[0] == '"' || $str === 'null' || ($val = json_decode($str)) !== null)
- {
- return isset($val) ? $val : json_decode($str, true);
- }
- return $str;
-}
-
-/**
- * Clasify exception for a headline and log it to error_log, if not running as cli
- *
- * @param Exception|Error $e
- * @param string &$headline
- */
-function _egw_log_exception($e,&$headline=null)
-{
- $trace = explode("\n", $e->getTraceAsString());
- if ($e instanceof Api\Exception\NoPermission)
- {
- $headline = try_lang('Permission denied!');
- }
- elseif ($e instanceof Api\Db\Exception)
- {
- $headline = try_lang('Database error');
- }
- elseif ($e instanceof Api\Exception\WrongUserinput)
- {
- $headline = ''; // message contains the whole message, it's usually no real error but some input validation
- }
- elseif ($e instanceof egw_exception_warning)
- {
- $headline = 'PHP Warning';
- array_shift($trace);
- }
- else
- {
- $headline = try_lang('An error happened');
- }
- // log exception to error log, if not running as cli,
- // which outputs the error_log to stderr and therefore output it twice to the user
- if(isset($_SERVER['HTTP_HOST']) || $GLOBALS['egw_info']['flags']['no_exception_handler'] !== 'cli')
- {
- error_log($headline.($e instanceof egw_exception_warning ? ': ' : ' ('.get_class($e).'): ').$e->getMessage());
- foreach($trace as $line)
- {
- error_log($line);
- }
- error_log('# Instance='.$GLOBALS['egw_info']['user']['domain'].', User='.$GLOBALS['egw_info']['user']['account_lid'].
- ', Request='.$_SERVER['REQUEST_METHOD'].' '.($_SERVER['HTTPS']?'https://':'http://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].
- ', User-agent='.$_SERVER['HTTP_USER_AGENT']);
- }
-}
-
-/**
- * Fail a little bit more gracefully then an uncought exception
- *
- * Does NOT return
- *
- * @param Exception|Error $e
- */
-function egw_exception_handler($e)
-{
- // handle redirects without logging
- if (is_a($e, 'egw_exception_redirect'))
- {
- egw::redirect($e->url, $e->app);
- }
- // logging all exceptions to the error_log (if not cli) and get headline
- $headline = null;
- _egw_log_exception($e,$headline);
-
- // exception handler for cli (command line interface) clients, no html, no logging
- if(!isset($_SERVER['HTTP_HOST']) || $GLOBALS['egw_info']['flags']['no_exception_handler'] == 'cli')
- {
- echo ($headline ? $headline.': ' : '').$e->getMessage()."\n";
- if ($GLOBALS['egw_info']['server']['exception_show_trace'])
- {
- echo $e->getTraceAsString()."\n";
- }
- exit($e->getCode() ? $e->getCode() : 9999); // allways give a non-zero exit code
- }
- // regular GUI exception
- if (!isset($GLOBALS['egw_info']['flags']['no_exception_handler']))
- {
- header('HTTP/1.1 500 '.$headline);
- $message = '<h3>'.html::htmlspecialchars($headline)."</h3>\n".
- '<pre><b>'.html::htmlspecialchars($e->getMessage())."</b>\n\n";
-
- // only show trace (incl. function arguments) if explicitly enabled, eg. on a development system
- if ($GLOBALS['egw_info']['server']['exception_show_trace'])
- {
- $message .= html::htmlspecialchars($e->getTraceAsString());
- }
- $message .= "</pre>\n";
- if (is_a($e, 'EGroupware\Api\Db\Exception\Setup'))
- {
- $setup_dir = str_replace(array('home/index.php','index.php'),'setup/',$_SERVER['PHP_SELF']);
- $message .= '<a href="'.$setup_dir.'">Run setup to install or configure EGroupware.</a>';
- }
- elseif (is_object($GLOBALS['egw']) && isset($GLOBALS['egw']->session) && method_exists($GLOBALS['egw'],'link'))
- {
- $message .= '<p><a href="'.$GLOBALS['egw']->link('/index.php').'">'.try_lang('Click here to resume your eGroupWare Session.').'</a></p>';
- }
- if (is_object($GLOBALS['egw']) && isset($GLOBALS['egw']->framework))
- {
- $GLOBALS['egw']->framework->render($message,$headline);
- }
- else
- {
- echo "<html>\n<head>\n<title>".html::htmlspecialchars($headline)."</title>\n</head>\n<body>\n$message\n</body>\n</html>\n";
- }
- }
- // exception handler sending message back to the client as basic auth message
- elseif($GLOBALS['egw_info']['flags']['no_exception_handler'] == 'basic_auth')
- {
- $error = str_replace(array("\r", "\n"), array('', ' | '), $e->getMessage());
- header('WWW-Authenticate: Basic realm="'.$headline.' '.$error.'"');
- header('HTTP/1.1 401 Unauthorized');
- header('X-WebDAV-Status: 401 Unauthorized', true);
- }
- if (is_object($GLOBALS['egw']))
- {
- common::egw_exit();
- }
- exit;
-}
-
-if (!isset($GLOBALS['egw_info']['flags']['no_exception_handler']) || $GLOBALS['egw_info']['flags']['no_exception_handler'] !== true)
-{
- set_exception_handler('egw_exception_handler');
-}
-
-/**
- * Fail a little bit more gracefully then a catchable fatal error, by throwing an exception
- *
- * @param int $errno level of the error raised: E_* constants
- * @param string $errstr error message
- * @param string $errfile filename that the error was raised in
- * @param int $errline line number the error was raised at
- * @link http://www.php.net/manual/en/function.set-error-handler.php
- * @throws ErrorException
- */
-function egw_error_handler ($errno, $errstr, $errfile, $errline)
-{
- switch ($errno)
- {
- case E_RECOVERABLE_ERROR:
- case E_USER_ERROR:
- throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
-
- case E_WARNING:
- case E_USER_WARNING:
- // skip message for warnings supressed via @-error-control-operator (eg. @is_dir($path))
- // can be commented out to get suppressed warnings too!
- if (error_reporting())
- {
- _egw_log_exception(new egw_exception_warning($errstr.' in '.$errfile.' on line '.$errline));
- }
- break;
- }
-}
-
-/**
- * Used internally to trace warnings
- */
-class egw_exception_warning extends Exception {}
-
-// install our error-handler only for catchable fatal errors and warnings
-// following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING
-set_error_handler('egw_error_handler', E_RECOVERABLE_ERROR|E_USER_ERROR|E_WARNING|E_USER_WARNING);
-
-// some not longer necessary defines
-if (isset($GLOBALS['egw_info']['flags']['phpgw_compatibility']) && $GLOBALS['egw_info']['flags']['phpgw_compatibility'])
-{
- define('PHPGW_API_INC',EGW_API_INC);
- define('PHPGW_SERVER_ROOT',EGW_SERVER_ROOT);
- define('PHPGW_INCLUDE_ROOT',EGW_INCLUDE_ROOT);
-
- /* debugging settings */
- define('DEBUG_DATATYPES', True);
- define('DEBUG_LEVEL', 3);
- define('DEBUG_OUTPUT', 2); /* 1 = screen, 2 = DB. For both use 3. */
- define('DEBUG_TIMER', False);
-}
+require_once dirname(dirname(__DIR__)).'/api/src/loader/common.php';
Copied: trunk/phpgwapi/inc/deprecated_functions.inc.php (from r55840, trunk/phpgwapi/inc/common_functions.inc.php)
URL: http://svn.stylite.de/viewvc/egroupware/trunk/phpgwapi/inc/deprecated_functions.inc.php?p2=trunk/phpgwapi/inc/deprecated_functions.inc.php&p1=trunk/phpgwapi/inc/common_functions.inc.php&r1=55840&r2=55853&rev=55853&view=diff
==============================================================================
--- trunk/phpgwapi/inc/common_functions.inc.php (original)
+++ trunk/phpgwapi/inc/deprecated_functions.inc.php Tue Apr 26 16:38:08 2016
@@ -1,14 +1,11 @@
<?php
/**
- * EGroupware commonly used functions
+ * EGroupware deprecated global functions
*
* This file was originaly written by Dan Kuykendall and Joseph Engo
* Copyright (C) 2000, 2001 Dan Kuykendall
*
- * All newer parts (XSS checks, autoloading, exception handler, ...) are written by Ralf Becker.
- *
* @link http://www.egroupware.org
- * @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @package api
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
@@ -16,359 +13,199 @@
use EGroupware\Api;
-// this is only neccessary, if header.inc.php is not included, but common_functions.inc.php directly
-if (!defined('EGW_SERVER_ROOT'))
-{
- define('EGW_SERVER_ROOT', dirname(dirname(__DIR__)));
- define('EGW_INCLUDE_ROOT', EGW_SERVER_ROOT);
- define('EGW_API_INC', __DIR__);
-}
-
-/**
- * New PSR-4 autoloader for EGroupware
- *
- * class_exists('\\EGroupware\\Api\\Vfs'); // /api/src/Vfs.php
- * class_exists('\\EGroupware\\Api\\Vfs\\Dav\\Directory'); // /api/src/Vfs/Dav/Directory.php
- * class_exists('\\EGroupware\\Api\\Vfs\\Sqlfs\\StreamWrapper'); // /api/src/Vfs/Sqlfs/StreamWrapper.php
- * class_exists('\\EGroupware\\Api\\Vfs\\Sqlfs\\Utils'); // /api/src/Vfs/Sqlfs/Utils.php
- * class_exists('\\EGroupware\\Stylite\\Versioning\\StreamWrapper'); // /stylite/src/Versioning/StreamWrapper.php
- * class_exists('\\EGroupware\\Calendar\\Ui'); // /calendar/src/Ui.php
- * class_exists('\\EGroupware\\Calendar\\Ui\\Lists'); // /calendar/src/Ui/Lists.php
- * class_exists('\\EGroupware\\Calendar\\Ui\\Views'); // /calendar/src/Ui/Views.php
- */
-spl_autoload_register(function($class)
-{
- $parts = explode('\\', $class);
- if (array_shift($parts) != 'EGroupware') return; // not our prefix
-
- $app = lcfirst(array_shift($parts));
- $base = EGW_INCLUDE_ROOT.'/'.$app.'/src/';
- $path = $base.implode('/', $parts).'.php';
-
- if (file_exists($path))
- {
- require_once $path;
- //error_log("PSR4_autoload('$class') --> require_once($path) --> class_exists('$class')=".array2string(class_exists($class,false)));
- }
-});
-
-/**
- * Old autoloader for EGroupware understanding the following naming schema:
- *
- * 1. new (prefered) nameing schema: app_class_something loading app/inc/class.class_something.inc.php
- * 2. API classes: classname loading phpgwapi/inc/class.classname.inc.php
- * 2a.API classes containing multiple classes per file eg. egw_exception* in class.egw_exception.inc.php
- * 3. eTemplate classes: classname loading etemplate/inc/class.classname.inc.php
- *
- * @param string $class name of class to load
- */
-spl_autoload_register(function($class)
-{
- // fixing warnings generated by php 5.3.8 is_a($obj) trying to autoload huge strings
- if (strlen($class) > 64 || strpos($class, '.') !== false) return;
-
- $components = explode('_',$class);
- $app = array_shift($components);
- // classes using the new naming schema app_class_name, eg. admin_cmd
- if (file_exists($file = EGW_INCLUDE_ROOT.'/'.$app.'/inc/class.'.$class.'.inc.php') ||
- // classes using the new naming schema app_class_name, eg. admin_cmd
- isset($components[0]) && file_exists($file = EGW_INCLUDE_ROOT.'/'.$app.'/inc/class.'.$app.'_'.$components[0].'.inc.php') ||
- // classes with an underscore in their name
- !isset($GLOBALS['egw_info']['apps'][$app]) && isset($GLOBALS['egw_info']['apps'][$app . '_' . $components[0]]) &&
- file_exists($file = EGW_INCLUDE_ROOT.'/'.$app.'_'.$components[0].'/inc/class.'.$class.'.inc.php') ||
- // eGW api classes using the old naming schema, eg. html
- file_exists($file = EGW_API_INC.'/class.'.$class.'.inc.php') ||
- // eGW api classes containing multiple classes in on file, eg. egw_exception
- isset($components[0]) && file_exists($file = EGW_API_INC.'/class.'.$app.'_'.$components[0].'.inc.php') ||
- // eGW eTemplate classes using the old naming schema, eg. etemplate
- file_exists($file = EGW_INCLUDE_ROOT.'/etemplate/inc/class.'.$class.'.inc.php') ||
- // include PEAR and PSR0 classes from include_path
- // need to use include (not include_once) as eg. a previous included EGW_API_INC/horde/Horde/String.php causes
- // include_once('Horde/String.php') to return true, even if the former was included with an absolute path
- // only use include_path, if no Composer vendor directory exists
- !isset($GLOBALS['egw_info']['apps'][$app]) && !file_exists(EGW_SERVER_ROOT.'/vendor') &&
- @include($file = strtr($class, array('_'=>'/','\\'=>'/')).'.php'))
- {
- include_once($file);
- //if (!class_exists($class, false) && !interface_exists($class, false)) error_log("autoloading class $class by include_once($file) failed!");
- }
- // allow apps to define an own autoload method
- elseif (isset($GLOBALS['egw_info']['flags']['autoload']) && is_callable($GLOBALS['egw_info']['flags']['autoload']))
- {
- call_user_func($GLOBALS['egw_info']['flags']['autoload'],$class);
- }
-});
-
-// if we have a Composer vendor directory, also load it's autoloader, to allow manage our requirements with Composer
-if (file_exists(EGW_SERVER_ROOT.'/vendor'))
-{
- require_once EGW_SERVER_ROOT.'/vendor/autoload.php';
-}
-
-/**
-* applies stripslashes recursivly on each element of an array
-*
-* @param array &$var
-* @return array
-*/
-function array_stripslashes($var)
-{
- if (!is_array($var))
- {
- return stripslashes($var);
- }
- foreach($var as $key => $val)
- {
- $var[$key] = is_array($val) ? array_stripslashes($val) : stripslashes($val);
- }
- return $var;
-}
-
-/**
- * Return the number of bytes of a string, independent of mbstring.func_overload
- * AND the availability of mbstring
- *
- * @param string $str
- * @return int
- */
-function bytes($str)
-{
- static $func_overload = null;
-
- if (is_null($func_overload)) $func_overload = extension_loaded('mbstring') ? ini_get('mbstring.func_overload') : 0;
-
- return $func_overload & 2 ? mb_strlen($str,'ascii') : strlen($str);
-}
-
-/**
- * mbstring.func_overload safe substr
- *
- * @param string $data
- * @param int $offset
- * @param int $len
- * @return string
- */
-function cut_bytes(&$data,$offset,$len=null)
-{
- static $func_overload = null;
-
- if (is_null($func_overload)) $func_overload = extension_loaded('mbstring') ? ini_get('mbstring.func_overload') : 0;
-
- if (is_null($len))
- {
- return $func_overload & 2 ? mb_substr($data,$offset,bytes($data),'ascii') : substr($data,$offset);
- }
- return $func_overload & 2 ? mb_substr($data,$offset,$len,'ascii') : substr($data,$offset,$len);
-}
-
-if (!function_exists('imap_rfc822_parse_adrlist'))
-{
- /**
- * parses a (comma-separated) address string
- *
- * Examples:
- * - Joe Doe <[email protected]>
- * - "Doe, Joe" <[email protected]>
- * - "\'Joe Doe\'" <[email protected]> // actually not necessary to quote
- * - [email protected]
- * - root
- * - "Joe on its way Down Under :-\)" <[email protected]>
- * - "Giant; \"Big\" Box" <[email protected]>
- * - [email protected] <[email protected]> // this is wrong, because @ need to be quoted
- *
- * Invalid addresses, if detected, set host to '.SYNTAX-ERROR.'
- *
- * @param string $address - A string containing addresses
- * @param string $default_host - The default host name
- * @return array of objects. The objects properties are:
- * mailbox - the mailbox name (username)
- * host - the host name
- * personal - the personal name
- * adl - at domain source route
- */
- function imap_rfc822_parse_adrlist($address, $default_host)
- {
- $addresses = array();
- $pending = '';
- foreach(explode(',', $address) as $part)
- {
- $trimmed = trim(($pending ? $pending.',' : '').$part);
- if (($trimmed[0] == '"' && substr($trimmed, -1) != '>')||strpos($part, '@')===false)
- {
- $pending .= ($pending ? $pending.',' : '').$part;
- continue;
- }
- $pending = '';
- $matches = $personal = $mailbox = $host = null;
- if (preg_match('/^(.*)<([^>@]+)(@([^>]+))?>$/', $trimmed, $matches))
- {
- $personal = trim($matches[1]);
- $mailbox = $matches[2];
- $host = $matches[4];
- }
- elseif (strpos($trimmed, '@') !== false)
- {
- list($mailbox, $host) = explode('@', $trimmed);
+/**
+ * Load a class and include the class file if not done so already.
+ *
+ * This function is used to create an instance of a class, and if the class file has not been included it will do so.
+ * $GLOBALS['egw']->acl =& CreateObject('phpgwapi.acl');
+ *
+ * @author [email protected]
+ * @param $classname name of class
+ * @param $p1,$p2,... class parameters (all optional)
+ * @return object reference to an object
+ */
+function CreateObject($class)
+{
+ list($appname,$classname) = explode('.',$class);
+
+ if (!class_exists($classname))
+ {
+ static $replace = array(
+ 'datetime' => 'egw_datetime',
+ 'uitimesheet' => 'timesheet_ui',
+ 'uiinfolog' => 'infolog_ui',
+ 'uiprojectmanager' => 'projectmanager_ui',
+ 'uiprojectelements' => 'projectmanager_elements_ui',
+ 'uiroles' => 'projectmanager_roles_ui',
+ 'uimilestones' => 'projectmanager_milestones_ui',
+ 'uipricelist' => 'projectmanager_pricelist_ui',
+ 'bowiki' => 'wiki_bo',
+ 'uicategories' => 'admin_categories',
+ 'defaultimap' => 'emailadmin_oldimap',
+ );
+ if (!file_exists(EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php') || isset($replace[$classname]))
+ {
+ if (isset($replace[$classname]))
+ {
+ //throw new Exception(__METHOD__."('$class') old classname '$classname' used in menuaction=$_GET[menuaction]!");
+ error_log(__METHOD__."('$class') old classname '$classname' used in menuaction=$_GET[menuaction]!");
+ $classname = $replace[$classname];
+ }
+ }
+ if (!file_exists($f=EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php'))
+ {
+ throw new Api\Exception\AssertionFailed(__FUNCTION__."($classname) file $f not found!");
+ }
+ // this will stop php with a 500, if the class does not exist or there are errors in it (syntax error go into the error_log)
+ require_once(EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php');
+ }
+ $args = func_get_args();
+ switch(count($args))
+ {
+ case 1:
+ $obj = new $classname;
+ break;
+ case 2:
+ $obj = new $classname($args[1]);
+ break;
+ case 3:
+ $obj = new $classname($args[1],$args[2]);
+ break;
+ case 4:
+ $obj = new $classname($args[1],$args[2],$args[3]);
+ break;
+ default:
+ $code = '$obj = new ' . $classname . '(';
+ foreach(array_keys($args) as $n)
+ {
+ if ($n)
+ {
+ $code .= ($n > 1 ? ',' : '') . '$args[' . $n . ']';
+ }
+ }
+ $code .= ');';
+ eval($code);
+ break;
+ }
+ if (!is_object($obj))
+ {
+ echo "<p>CreateObject('$class'): Cant instanciate class!!!<br />\n".function_backtrace(1)."</p>\n";
+ }
+ return $obj;
+}
+
+/**
+ * Execute a function with multiple arguments
+ * We take object $GLOBALS[classname] from class if exists
+ *
+ * @param string app.class.method method to execute
+ * @example ExecObject('etemplates.so_sql.search',$criteria,$key_only,...);
+ * @return mixed reference to returnvalue of the method
+ */
+function &ExecMethod2($acm)
+{
+ // class::method is php5.2.3+
+ if (strpos($acm,'::') !== false && version_compare(PHP_VERSION,'5.2.3','<'))
+ {
+ list($class,$method) = explode('::',$acm);
+ $acm = array($class,$method);
+ }
+ if (!is_callable($acm))
+ {
+ list(,$class,$method) = explode('.',$acm);
+ if (!is_object($obj =& $GLOBALS[$class]))
+ {
+ if (class_exists($class))
+ {
+ $obj = new $class;
}
else
{
- $mailbox = $trimmed;
- }
- if ($personal[0] == '"' && substr($personal, -1) == '"')
- {
- $personal = str_replace('\\', '', substr($personal, 1, -1));
- }
- if (empty($host)) $host = $default_host;
-
- $addresses[] = (object)array_diff(array(
- 'mailbox' => $mailbox,
- 'host' => $host,
- 'personal' => $personal,
- ), array(null, ''));
- }
- return $addresses;
- }
-}
-
-if (!function_exists('imap_rfc822_write_address'))
-{
- /**
- * Returns a properly formatted email address given the mailbox, host, and personal info
- * @param string $mailbox - The mailbox name, see imap_open() for more information
- * @param string $host - The email host part
- * @param string $personal - The name of the account owner
- * @return string properly formatted email address as defined in » RFC2822.
- */
- function imap_rfc822_write_address($mailbox, $host, $personal)
- {
- if (is_array($personal)) $personal = implode(' ', $personal);
-
- //if (!preg_match('/^[!#$%&\'*+/0-9=?A-Z^_`a-z{|}~-]+$/u', $personal)) // that's how I read the rfc(2)822
- if ($personal && !preg_match('/^[0-9A-Z -]*$/iu', $personal)) // but quoting is never wrong, so quote more then necessary
- {
- $personal = '"'.str_replace(array('\\', '"'),array('\\\\', '\\"'), $personal).'"';
- }
- return ($personal ? $personal.' <' : '').$mailbox.($host ? '@'.$host : '').($personal ? '>' : '');
- }
-}
-
-if (!function_exists('imap_mime_header_decode'))
-{
- /**
- * Decodes MIME message header extensions that are non ASCII text (RFC2047)
- *
- * Uses Horde_Mime::decode() and therefore always returns only a single array element!
- *
- * @param string $text
- * @return array with single object with attribute text already in our internal encoding and charset
- * @deprecated use Horde_Mime::decode()
- */
- function imap_mime_header_decode($text)
- {
- return array((object)array(
- 'text' => Horde_Mime::decode($text),
- 'charset' => translation::charset(), // is already in our internal encoding!
- ));
- }
-}
-
-if (!function_exists('mb_strlen'))
-{
- /**
- * Number of characters in a string
- *
- * @param string $str
- * @return int
- */
- function mb_strlen($str)
- {
- return strlen($str);
- }
-}
-
-if (!function_exists('mb_substr'))
-{
- /**
- * Return part of a string
- *
- * @param string $data
- * @param int $offset
- * @param int $len
- * @return string
- */
- function mb_substr(&$data, $offset, $len=null)
- {
- return is_null($len) ? substr($data, $offset) : substr($data, $offset, $len);
- }
-}
-
-/**
- * Format array or other types as (one-line) string, eg. for error_log statements
- *
- * @param mixed $var variable to dump
- * @return string
- */
-function array2string($var)
-{
- switch (($type = gettype($var)))
- {
- case 'boolean':
- return $var ? 'TRUE' : 'FALSE';
- case 'string':
- return "'$var'";
- case 'integer':
- case 'double':
- case 'resource':
- return $var;
- case 'NULL':
- return 'NULL';
- case 'object':
- case 'array':
- return str_replace(array("\n",' '/*,'Array'*/),'',print_r($var,true));
- }
- return 'UNKNOWN TYPE!';
-}
-
-/**
- * Check if a given extension is loaded or load it if possible (requires sometimes disabled or unavailable dl function)
- *
- * @param string $extension
- * @param boolean $throw =false should we throw an exception, if $extension could not be loaded, default false = no
- * @return boolean true if loaded now, false otherwise
- */
-function check_load_extension($extension,$throw=false)
-{
- if (!defined('PHP_SHLIB_PREFIX'))
- {
- define('PHP_SHLIB_PREFIX',PHP_SHLIB_SUFFIX == 'dll' ? 'php_' : '');
- }
- // we check for the existens of 'dl', as multithreaded webservers dont have it and some hosters disable it !!!
- $loaded = extension_loaded($extension) || function_exists('dl') && @dl($dl=PHP_SHLIB_PREFIX.$extension.'.'.PHP_SHLIB_SUFFIX);
-
- if (!$loaded && $throw)
- {
- throw new Exception ("PHP extension '$extension' not loaded AND can NOT be loaded via dl('$dl')!");
- }
- return $loaded;
-}
-
-/**
- * @internal Not to be used directly. Should only be used by print_debug()
- */
-function print_debug_subarray($array)
-{
- foreach($array as $key => $value)
- {
- if (is_array($value))
- {
- $vartypes[$key] = print_debug_subarray($value);
- }
- else
- {
- $vartypes[$key] = gettype($value);
- }
- }
- return $vartypes;
+ $obj = CreateObject($acm);
+ }
+ }
+
+ if (!method_exists($obj,$method))
+ {
+ echo "<p><b>".function_backtrace()."</b>: no methode '$method' in class '$class'</p>\n";
+ return False;
+ }
+ $acm = array($obj,$method);
+ }
+ $args = func_get_args();
+ unset($args[0]);
+
+ return call_user_func_array($acm,$args);
+}
+
+/**
+ * Execute a function, and load a class and include the class file if not done so already.
+ *
+ * This function is used to create an instance of a class, and if the class file has not been included it will do so.
+ *
+ * @author seek3r
+ * @param $method to execute
+ * @param $functionparam function param should be an array
+ * @param $loglevel developers choice of logging level
+ * @param $classparams params to be sent to the contructor
+ * @return mixed returnvalue of method
+ */
+function ExecMethod($method, $functionparam = '_UNDEF_', $loglevel = 3, $classparams = '_UNDEF_')
+{
+ unset($loglevel); // not used
+ /* Need to make sure this is working against a single dimensional object */
+ $partscount = count(explode('.',$method)) - 1;
+
+ if (!is_callable($method) && $partscount == 2)
+ {
+ list($appname,$classname,$functionname) = explode(".", $method);
+ if (!is_object($GLOBALS[$classname]))
+ {
+ // please note: no reference assignment (=&) here, as $GLOBALS is a reference itself!!!
+ if ($classparams != '_UNDEF_' && ($classparams || $classparams != 'True'))
+ {
+ $GLOBALS[$classname] = CreateObject($appname.'.'.$classname, $classparams);
+ }
+ elseif (class_exists($classname))
+ {
+ $GLOBALS[$classname] = new $classname;
+ }
+ else
+ {
+ $GLOBALS[$classname] = CreateObject($appname.'.'.$classname);
+ }
+ }
+
+ if (!method_exists($GLOBALS[$classname],$functionname))
+ {
+ error_log("ExecMethod('$method', ...) No methode '$functionname' in class '$classname'! ".function_backtrace());
+ return false;
+ }
+ $method = array($GLOBALS[$classname],$functionname);
+ }
+ if (is_callable($method))
+ {
+ return $functionparam != '_UNDEF_' ? call_user_func($method,$functionparam) : call_user_func($method);
+ }
+ error_log("ExecMethod('$method', ...) Error in parts! ".function_backtrace());
+ return false;
+}
+
+/**
+ * prepend a prefix to an array of table names
+ *
+ * @author Adam Hull (aka fixe) - No copyright claim
+ * @param $prefix the string to be prepended
+ * @param $tables and array of tables to have the prefix prepended to
+ * @return array of table names with the prefix prepended
+ */
+function prepend_tables_prefix($prefix,$tables)
+{
+ foreach($tables as $key => $value)
+ {
+ $tables[$key] = $prefix.$value;
+ }
+ return $tables;
}
/**
@@ -380,95 +217,7 @@
*/
function print_debug($message,$var = 'messageonly',$part = 'app', $level = 3)
{
- if (($part == 'app' && DEBUG_APP == True) || ($part == 'api' && DEBUG_API == True))
- {
- if (!defined('DEBUG_OUTPUT'))
- {
- define('DEBUG_OUTPUT', 1);
- }
- if ($level >= DEBUG_LEVEL)
- {
- if (!is_array($var))
- {
- if ($var != 'messageonly')
- {
- if (!DEBUG_DATATYPES)
- {
- $output = "$message\n$var";
- }
- else
- {
- $output = "$message\n$var is a ".gettype($var);
- }
- }
- else
- {
- $output = $message;
- }
-
- /* Bit 1 means to output to screen */
- if (!!(DEBUG_OUTPUT & 1))
- {
- echo "$output<br>\n";
- }
- /* Bit 2 means to output to sql */
- if (!!(DEBUG_OUTPUT & 2))
- {
- /* Need to flesh this out still. I dont have a table to dump this in yet.*/
- /* So the SQL statement will go here*/
- }
-
- /* Example of how this can be extended to output to other locations as well. This example uses a COM object */
- /*
- if (!!(DEBUG_OUTPUT & 32))
- {
- $obj_debug = new COM('Some_COM_App.Class','localhost');
- if (is_object($obj_debug))
- {
- $DebugMessage_return = $obj_debug->DebugMessage($output);
- }
- }
- */
- }
- else
- {
- if (floor(phpversion()) > 3 && !!(DEBUG_OUTPUT & 2))
- {
- ob_start();
- }
- echo "<pre>\n$message\n";
- print_r($var);
- if (DEBUG_DATATYPES)
- {
- foreach($var as $key => $value)
- {
- if (is_array($value))
- {
- $vartypes[$key] = print_debug_subarray($value);
- }
- else
- {
- $vartypes[$key] = gettype($value);
- }
- }
- echo "Data Types:\n";
- print_r($vartypes);
- }
- echo "\n<pre>\n";
- if (floor(phpversion()) > 3 && !!(DEBUG_OUTPUT & 2))
- {
- $output .= ob_get_contents();
- ob_end_clean();
- /* Need to flesh this out still. I dont have a table to dump this in yet.*/
- /* So the SQL statement will go here*/
- if (!!(DEBUG_OUTPUT & 1))
- {
- echo "$output<br>\n";
- }
- }
- }
- }
- }
+ unset($message, $var, $part, $level);
}
/**
@@ -975,225 +724,6 @@
}
/**
- * Load a class and include the class file if not done so already.
- *
- * This function is used to create an instance of a class, and if the class file has not been included it will do so.
- * $GLOBALS['egw']->acl =& CreateObject('phpgwapi.acl');
- *
- * @author [email protected]
- * @param $classname name of class
- * @param $p1,$p2,... class parameters (all optional)
- * @return object reference to an object
- */
-function CreateObject($class)
-{
- list($appname,$classname) = explode('.',$class);
-
- if (!class_exists($classname))
- {
- static $replace = array(
- 'datetime' => 'egw_datetime',
- 'uitimesheet' => 'timesheet_ui',
- 'uiinfolog' => 'infolog_ui',
- 'uiprojectmanager' => 'projectmanager_ui',
- 'uiprojectelements' => 'projectmanager_elements_ui',
- 'uiroles' => 'projectmanager_roles_ui',
- 'uimilestones' => 'projectmanager_milestones_ui',
- 'uipricelist' => 'projectmanager_pricelist_ui',
- 'bowiki' => 'wiki_bo',
- 'uicategories' => 'admin_categories',
- 'defaultimap' => 'emailadmin_oldimap',
- );
- if (!file_exists(EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php') || isset($replace[$classname]))
- {
- if (isset($replace[$classname]))
- {
- //throw new Exception(__METHOD__."('$class') old classname '$classname' used in menuaction=$_GET[menuaction]!");
- error_log(__METHOD__."('$class') old classname '$classname' used in menuaction=$_GET[menuaction]!");
- $classname = $replace[$classname];
- }
- }
- if (!file_exists($f=EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php'))
- {
- throw new Api\Exception\AssertionFailed(__FUNCTION__."($classname) file $f not found!");
- }
- // this will stop php with a 500, if the class does not exist or there are errors in it (syntax error go into the error_log)
- require_once(EGW_INCLUDE_ROOT.'/'.$appname.'/inc/class.'.$classname.'.inc.php');
- }
- $args = func_get_args();
- switch(count($args))
- {
- case 1:
- $obj = new $classname;
- break;
- case 2:
- $obj = new $classname($args[1]);
- break;
- case 3:
- $obj = new $classname($args[1],$args[2]);
- break;
- case 4:
- $obj = new $classname($args[1],$args[2],$args[3]);
- break;
- default:
- $code = '$obj = new ' . $classname . '(';
- foreach(array_keys($args) as $n)
- {
- if ($n)
- {
- $code .= ($n > 1 ? ',' : '') . '$args[' . $n . ']';
- }
- }
- $code .= ');';
- eval($code);
- break;
- }
- if (!is_object($obj))
- {
- echo "<p>CreateObject('$class'): Cant instanciate class!!!<br />\n".function_backtrace(1)."</p>\n";
- }
- return $obj;
-}
-
-/**
- * Execute a function with multiple arguments
- * We take object $GLOBALS[classname] from class if exists
- *
- * @param string app.class.method method to execute
- * @example ExecObject('etemplates.so_sql.search',$criteria,$key_only,...);
- * @return mixed reference to returnvalue of the method
- */
-function &ExecMethod2($acm)
-{
- // class::method is php5.2.3+
- if (strpos($acm,'::') !== false && version_compare(PHP_VERSION,'5.2.3','<'))
- {
- list($class,$method) = explode('::',$acm);
- $acm = array($class,$method);
- }
- if (!is_callable($acm))
- {
- list(,$class,$method) = explode('.',$acm);
- if (!is_object($obj =& $GLOBALS[$class]))
- {
- if (class_exists($class))
- {
- $obj = new $class;
- }
- else
- {
- $obj = CreateObject($acm);
- }
- }
-
- if (!method_exists($obj,$method))
- {
- echo "<p><b>".function_backtrace()."</b>: no methode '$method' in class '$class'</p>\n";
- return False;
- }
- $acm = array($obj,$method);
- }
- $args = func_get_args();
- unset($args[0]);
-
- return call_user_func_array($acm,$args);
-}
-
-/**
- * Execute a function, and load a class and include the class file if not done so already.
- *
- * This function is used to create an instance of a class, and if the class file has not been included it will do so.
- *
- * @author seek3r
- * @param $method to execute
- * @param $functionparam function param should be an array
- * @param $loglevel developers choice of logging level
- * @param $classparams params to be sent to the contructor
- * @return mixed returnvalue of method
- */
-function ExecMethod($method, $functionparam = '_UNDEF_', $loglevel = 3, $classparams = '_UNDEF_')
-{
- unset($loglevel); // not used
- /* Need to make sure this is working against a single dimensional object */
- $partscount = count(explode('.',$method)) - 1;
-
- if (!is_callable($method) && $partscount == 2)
- {
- list($appname,$classname,$functionname) = explode(".", $method);
- if (!is_object($GLOBALS[$classname]))
- {
- // please note: no reference assignment (=&) here, as $GLOBALS is a reference itself!!!
- if ($classparams != '_UNDEF_' && ($classparams || $classparams != 'True'))
- {
- $GLOBALS[$classname] = CreateObject($appname.'.'.$classname, $classparams);
- }
- elseif (class_exists($classname))
- {
- $GLOBALS[$classname] = new $classname;
- }
- else
- {
- $GLOBALS[$classname] = CreateObject($appname.'.'.$classname);
- }
- }
-
- if (!method_exists($GLOBALS[$classname],$functionname))
- {
- error_log("ExecMethod('$method', ...) No methode '$functionname' in class '$classname'! ".function_backtrace());
- return false;
- }
- $method = array($GLOBALS[$classname],$functionname);
- }
- if (is_callable($method))
- {
- return $functionparam != '_UNDEF_' ? call_user_func($method,$functionparam) : call_user_func($method);
- }
- error_log("ExecMethod('$method', ...) Error in parts! ".function_backtrace());
- return false;
-}
-
-/**
- * Return a properly formatted account_id.
- *
- * @author skeeter
- * This function will return a properly formatted account_id. This can take either a name or an account_id as paramters. If a name is provided it will return the associated id.
- * $account_id = get_account_id($accountid);
- * @param int/string $account_id either a name or an id
- * @param int/string $default_id either a name or an id
- * @return int account_id
- */
-function get_account_id($account_id = '',$default_id = '')
-{
- if (gettype($account_id) == 'integer')
- {
- return $account_id;
- }
- elseif ($account_id == '')
- {
- if ($default_id == '')
- {
- return (isset($GLOBALS['egw_info']['user']['account_id'])?$GLOBALS['egw_info']['user']['account_id']:0);
- }
- elseif (is_string($default_id))
- {
- return $GLOBALS['egw']->accounts->name2id($default_id);
- }
- return (int)$default_id;
- }
- elseif (is_string($account_id))
- {
- if($GLOBALS['egw']->accounts->exists((int)$account_id) == True)
- {
- return (int)$account_id;
- }
- else
- {
- return $GLOBALS['egw']->accounts->name2id($account_id);
- }
- }
-}
-
-/**
* sets the file system seperator depending on OS
*
* This is completely unnecessary, as you can use forward slashes in php under every OS -- RalfBecker 2005/11/09
@@ -1217,27 +747,6 @@
* @deprecated just use forward slashes supported by PHP on all OS
*/
define('SEP', filesystem_separator());
-
-/**
- * print an array or object as pre-formatted html
- *
- * @param mixed $array
- * @param boolean $print =true print or return the content
- * @return string if !$print
- */
-function _debug_array($array,$print=True)
-{
- $output = '<pre>'.print_r($array,true)."</pre>\n";
-
- if ($print)
- {
- echo $output;
- }
- else
- {
- return $output;
- }
-}
/**
* eGW version checking, is eGW version in $a < $b
@@ -1406,577 +915,6 @@
return False;
}
}
-
-/**
- * prepend a prefix to an array of table names
- *
- * @author Adam Hull (aka fixe) - No copyright claim
- * @param $prefix the string to be prepended
- * @param $tables and array of tables to have the prefix prepended to
- * @return array of table names with the prefix prepended
- */
-function prepend_tables_prefix($prefix,$tables)
-{
- foreach($tables as $key => $value)
- {
- $tables[$key] = $prefix.$value;
- }
- return $tables;
-}
-
-/**
- * backtrace of the calling functions for php4.3+ else menuaction/scriptname
- *
- * @author RalfBecker-AT-outdoor-training.de
- * @param int $remove =0 number of levels to remove
- * @return string function-names separated by slashes (beginning with the calling function not this one)
- */
-function function_backtrace($remove=0)
-{
- if (function_exists('debug_backtrace'))
- {
- $backtrace = debug_backtrace();
- //echo "function_backtrace($remove)<pre>".print_r($backtrace,True)."</pre>\n";
- foreach($backtrace as $n => $level)
- {
- if ($remove-- < 0)
- {
- $ret[] = (isset($level['class'])?$level['class'].$level['type']:'').$level['function'].
- ($n > 0 && isset($backtrace[$n-1]['line']) ? ':'.$backtrace[$n-1]['line'] : ''). // add line number of call
- (!$level['class'] && !is_object($level['args'][0]) && $level['function'] != 'unserialize' ?
- '('.substr(str_replace(EGW_SERVER_ROOT,'',(string)$level['args'][0]),0,64).')' : '');
- }
- }
- if (is_array($ret))
- {
- return implode(' / ',$ret);
- }
- }
- return $_GET['menuaction'] ? $_GET['menuaction'] : str_replace(EGW_SERVER_ROOT,'',$_SERVER['SCRIPT_FILENAME']);
-}
-
-/**
- * check $_REQUEST data for XSS, vars containing script tags are moved to $GLOBALS['egw_unset_vars']
- *
- * @internal
- * @param array &$var reference of array to check
- * @param string $name ='' name of the array
- */
-function _check_script_tag(&$var,$name='')
-{
- static $preg=null;
- //old: '/<\/?[^>]*\b(iframe|script|javascript|on(before)?(abort|blur|change|click|dblclick|error|focus|keydown|keypress|keyup|load|mousedown|mousemove|mouseout|mouseover|mouseup|reset|select|submit|unload))\b[^>]*>/i';
- if (!isset($preg)) $preg =
- // forbidden tags like iframe or script
- '/(<(\s*\/)?\s*(iframe|script|object|embed|math|meta)[^a-z0-9]|'.
- // on* attributes
- '<[^>]*on(before)?(abort|blur|change|click|dblclick|error|focus|keydown|keypress|keyup|load|mouse[^=]+|reset|select|submit|unload|resize|propertychange|page[^=]*|scroll|readystatechange|start|popstate|form[^=]+|input)\s*=|'.
- // ="javascript:*" diverse javascript attribute value
- '<[^>]+(href|src|dynsrc|lowsrc|background|style|poster|action)\s*=\s*("|\')?[^"\']*javascript|'.
- // benavior:url and expression in style attribute
- '<[^>]+style\s*=\s*("|\')[^>]*(behavior\s*:\s*url|expression)\s*\()/i';
- if (is_array($var))
- {
- foreach($var as $key => $val)
- {
- if (is_array($val))
- {
- _check_script_tag($var[$key],$name.'['.$key.']');
- }
- elseif(strpos($val, '<') !== false) // speedup: ignore everything without <
- {
- if (preg_match($preg,$val))
- {
- // special handling for $_POST[json_data], to decend into it's decoded content, fixing json direct might break json syntax
- if ($name == '_POST' && $key == 'json_data' && ($json_data = json_decode($val, true)))
- {
- _check_script_tag($json_data, $name.'[json_data]');
- $_REQUEST[$key] = $var[$key] = json_encode($json_data);
- continue;
- }
- error_log(__FUNCTION__."(,$name) ${name}[$key] = ".$var[$key]);
- $GLOBALS['egw_unset_vars'][$name.'['.$key.']'] = $var[$key];
- // attempt to clean the thing
- $var[$key] = $val = html::purify($val);
- // check if we succeeded, if not drop the var anyway, keep the egw_unset_var in any case
- if (preg_match($preg,$val))
- {
- error_log("*** _check_script_tag($name): unset(${name}[$key]) with value $val***");
- unset($var[$key]);
- }
- }
- }
- }
- // in case some stupid old code expects the array-pointer to be at the start of the array
- reset($var);
- }
-}
-
-/* some _check_script_tag tests, should be commented out by default
-if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__) // some tests
-{
- if (!defined('EGW_INCLUDE_ROOT'))
- {
- define(EGW_INCLUDE_ROOT, realpath(dirname(__FILE__).'/../..'));
- define(EGW_API_INC, realpath(dirname(__FILE__)));
- }
-
- $total = $num_failed = 0;
- $patterns = array(
- // pattern => true: should fail, false: should not fail
- '< script >alert(1)< / script >' => true,
- '<span onMouseOver ="alert(1)">blah</span>' => true,
- '<a href= "JaVascript: alert(1)">Click Me</a>' => true,
- // from https://www.acunetix.com/websitesecurity/cross-site-scripting/
- '<body onload=alert("XSS")>' => true,
- '<body background="javascript:alert("XSS")">' => true,
- '<iframe src=âhttp://evil.com/xss.htmlâ>' => true,
- '<input type="image" src="javascript:alert(\'XSS\');">' => true,
- '<link rel="stylesheet" href="javascript:alert(\'XSS\');">' => true,
- '<table background="javascript:alert(\'XSS\')">' => true,
- '<td background="javascript:alert(\'XSS\')">' => true,
- '<div style="background-image: url(javascript:alert(\'XSS\'))">' => true,
- '<div style="width: expression(alert(\'XSS\'));">' => true,
- '<object type="text/x-scriptlet" data="http://hacker.com/xss.html">' => true,
- // false positiv tests
- 'If 1 < 2, what does that mean for description, if 2 > 1.' => false,
- 'If 1 < 2, what does that mean for a script, if 2 > 1.' => false,
- '<div>Script and Javascript: not evil ;-)' => false,
- '<span>style=background-color' => false,
- '<font face="Script MT Bold" size="4"><span style="font-size:16pt;">Hugo Sonstwas</span></font>' => false,
- '<[email protected]>' => false,
- );
- foreach($patterns as $pattern => $should_fail)
- {
- $test = array($pattern);
- unset($GLOBALS['egw_unset_vars']);
- _check_script_tag($test,'test');
- $failed = isset($GLOBALS['egw_unset_vars']) !== $should_fail;
- ++$total;
- if ($failed) $num_failed++;
- echo "<p style='color: ".($failed?'red':'black')."'> ".html::htmlspecialchars($pattern).' '.
- (isset($GLOBALS['egw_unset_vars'])?'removed':'passed')."</p>";
- }
- $x = 1;
- // urls with attack vectors
- $urls = array(
- // we currently fail 76 of 666 test, thought they seem not to apply to our use case, as we check request data
- 'https://gist.github.com/JohannesHoppe/5612274' => file(
- 'https://gist.githubusercontent.com/JohannesHoppe/5612274/raw/60016bccbfe894dcd61a6be658a4469e403527de/666_lines_of_XSS_vectors.html'),
- // we currently fail 44 of 140 tests, thought they seem not to apply to our use case, as we check request data
- 'https://html5sec.org/' => call_user_func(function() {
- $payloads = $items = null;
- if (!($items_js = file_get_contents('https://html5sec.org/items.js')) ||
- !preg_match_all("|^\s+'data'\s+:\s+'(.*)',$|m", $items_js, $items, PREG_PATTERN_ORDER) ||
- !($payload_js = file_get_contents('https://html5sec.org/payloads.js')) ||
- !preg_match_all("|^\s+'([^']+)'\s+:\s+'(.*)',$|m", $payload_js, $payloads, PREG_PATTERN_ORDER))
- {
- return false;
- }
- $replace = array(
- "\\'" => "'",
- '\\\\'=> '\\,',
- '\r' => "\r",
- '\n' => "\n",
- );
- foreach($payloads[1] as $n => $from) {
- $replace['%'.$from.'%'] = $payloads[2][$n];
- }
- return array_map(function($item) use ($replace) {
- return strtr($item, $replace);
- }, $items[1]);
- }),
- );
- foreach($urls as $url => $vectors)
- {
- // no all xss attack vectors from http://ha.ckers.org/xssAttacks.xml are relevant here! (needs interpretation)
- if (!$vectors)
- {
- echo "<p style='color:red'>Could NOT download or parse $url with attack vectors!</p>\n";
- continue;
- }
- echo "<p><b>Attacks from <a href='$url' target='_blank'>$url</a> with ".count($vectors)." tests:</b></p>";
- foreach($vectors as $line => $pattern)
- {
- $test = array($pattern);
- unset($GLOBALS['egw_unset_vars']);
- _check_script_tag($test, 'line '.(1+$line));
- $failed = !isset($GLOBALS['egw_unset_vars']);
- ++$total;
- if ($failed) $num_failed++;
- echo "<p style='color: ".($failed?'red':'black')."'>".(1+$line).": ".html::htmlspecialchars($pattern).' '.
- (isset($GLOBALS['egw_unset_vars'])?'removed':'passed')."</p>";
- }
- }
- die("<p style='color: ".($num_failed?'red':'black')."'>Tests finished: $num_failed / $total failed</p>");
-}*/
-
-foreach(array('_GET','_POST','_REQUEST','HTTP_GET_VARS','HTTP_POST_VARS') as $n => $where)
-{
- $pregs = array(
- 'order' => '/^[a-zA-Z0-9_,]*$/',
- 'sort' => '/^(ASC|DESC|asc|desc|0|1|2|3|4|5|6|7){0,1}$/',
- );
- foreach(array('order','sort') as $name)
- {
- if (isset($GLOBALS[$where][$name]) && !is_array($GLOBALS[$where][$name]) && !preg_match($pregs[$name],$GLOBALS[$where][$name]))
- {
- $GLOBALS[$where][$name] = '';
- }
- }
- // do the check for script-tags only for _GET and _POST or if we found something in _GET and _POST
- // speeds up the execusion a bit
- if (isset($GLOBALS[$where]) && is_array($GLOBALS[$where]) && ($n < 2 || isset($GLOBALS['egw_unset_vars'])))
- {
- _check_script_tag($GLOBALS[$where],$where);
- }
-}
-//if (is_array($GLOBALS['egw_unset_vars'])) { echo "egw_unset_vars=<pre>".htmlspecialchars(print_r($GLOBALS['egw_unset_vars'],true))."</pre>"; exit; }
-
-// $GLOBALS[egw_info][flags][currentapp] and die if it contains something nasty or unexpected
-if (isset($GLOBALS['egw_info']) && isset($GLOBALS['egw_info']['flags']) &&
- isset($GLOBALS['egw_info']['flags']['currentapp']) && !preg_match('/^[A-Za-z0-9_-]+$/',$GLOBALS['egw_info']['flags']['currentapp']))
-{
- error_log(__FILE__.': '.__LINE__.' Invalid $GLOBALS[egw_info][flags][currentapp]='.array2string($GLOBALS['egw_info']['flags']['currentapp']).', $_SERVER[REQUEST_URI]='.array2string($_SERVER[REQUEST_URI]));
- die('Invalid $GLOBALS[egw_info][flags][currentapp]!');
-}
-
-// neutralises register_globals On, which is not used by eGW
-// some code from the hardend php project: http://www.hardened-php.net/articles/PHPUG-PHP-Sicherheit-Parametermanipulationen.pdf
-if (ini_get('register_globals'))
-{
- function unregister_globals()
- {
- // protect against GLOBALS overwrite or setting egw_info
- if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS']) || isset($_REQUEST['egw_info']) || isset($_FILES['egw_info']))
- {
- die('GLOBALS overwrite detected!!!');
- }
- // unregister all globals
- $noUnset = array('GLOBALS','_GET','_POST','_COOKIE','_SERVER','_ENV','_FILES','xajax');
- foreach(array_unique(array_merge(
- array_keys($_GET),array_keys($_POST),array_keys($_COOKIE),array_keys($_SERVER),array_keys($_ENV),array_keys($_FILES),
- isset($_SESSION) && is_array($_SESSION) ? array_keys($_SESSION) : array())) as $k)
- {
- if (!in_array($k,$noUnset) && isset($GLOBALS[$k]))
- {
- unset($GLOBALS[$k]);
- }
- }
- }
- unregister_globals();
-}
-
-if (!function_exists('lang') || defined('NO_LANG')) // setup declares an own version
-{
- /**
- * function to handle multilanguage support
- *
- * @param string $key message in englich with %1, %2, ... placeholders
- * @param string $vars =null multiple values to replace the placeholders
- * @return string translated message with placeholders replaced
- */
- function lang($key,$vars=null)
- {
- if(!is_array($vars))
- {
- $vars = func_get_args();
- array_shift($vars); // remove $key
- }
- return translation::translate($key,$vars);
- }
-}
-
-/**
- * Translate message only if translation object is already loaded
- *
- * This function is usefull for exception handlers or early stages of the initialisation of the egw object,
- * as calling lang would try to load the translations, evtl. cause more errors, eg. because there's no db-connection.
- *
- * @param string $key message in englich with %1, %2, ... placeholders
- * @param string $vars =null multiple values to replace the placeholders
- * @return string translated message with placeholders replaced
- */
-function try_lang($key,$vars=null)
-{
- static $varnames = array('%1','%2','%3','%4');
-
- if(!is_array($vars))
- {
- $vars = func_get_args();
- array_shift($vars); // remove $key
- }
- return class_exists(translations,false) ? translation::translate($key,$vars) : str_replace($varnames,$vars,$key);
-}
-
-/**
- * Unserialize a php serialized string, but only if it contains NO objects 'O:\d:"' or 'C:\d:"' pattern
- *
- * Should be used for all external content, to guard against exploidts.
- *
- * PHP 7.0+ can be told not to instanciate any classes (and calling eg. it's destructor).
- * In fact it instanciates it as __PHP_Incomplete_Class without any methods and therefore disarming threads.
- *
- * @param string $str
- * @return mixed
- */
-function php_safe_unserialize($str)
-{
- if (PHP_VERSION >= 7)
- {
- return unserialize($str, array('allowed_classes' => false));
- }
- if ((strpos($str, 'O:') !== false || strpos($str, 'C:') !== false) &&
- preg_match('/(^|;|{)[OC]:\d+:"/', $str))
- {
- error_log(__METHOD__."('$str') contains objects --> return NULL");
- return null; // null, not false, to not trigger behavior of returning string itself to app code
- }
- return unserialize($str);
-}
-
-/* some test for object safe unserialisation
-if (isset($_SERVER['SCRIPT_FILENAME']) && $_SERVER['SCRIPT_FILENAME'] == __FILE__) // some tests
-{
- if (php_sapi_name() !== 'cli') echo "<pre>\n";
- foreach(array(
- // things unsafe to unserialize
- "O:34:\"Horde_Kolab_Server_Decorator_Clean\":2:{s:43:\"\x00Horde_Kolab_Server_Decorator_Clean\x00_server\";" => false,
- "O:20:\"Horde_Prefs_Identity\":2:{s:9:\"\x00*\x00_prefs\";O:11:\"Horde_Prefs\":2:{s:8:\"\x00*\x00_opts\";a:1:{s:12:\"sizecallback\";" => false,
- "a:2:{i:0;O:12:\"Horde_Config\":1:{s:13:\"\x00*\x00_oldConfig\";s:#{php_injection.length}:\"#{php_injection}\";}i:1;s:13:\"readXMLConfig\";}}" => false,
- 'a:6:{i:0;i:0;i:1;d:2;i:2;s:4:"ABCD";i:3;r:3;i:4;O:8:"my_Class":2:{s:1:"a";r:6;s:1:"b";N;};i:5;C:16:"SplObjectStorage":14:{x:i:0;m:a:0:{}}' => false,
- serialize(new stdClass()) => false,
- serialize(array(new stdClass(), new SplObjectStorage())) => false,
- // string content, safe to unserialize
- serialize('O:8:"stdClass"') => true,
- serialize('C:16:"SplObjectStorage"') => true,
- serialize(array('a' => 'O:8:"stdClass"', 'b' => 'C:16:"SplObjectStorage"')) => true,
- // false positive: failing our php<7 regular expression, because it has correct delimiter (^|;|{) in front of pattern :-(
- serialize('O:8:"stdClass";C:16:"SplObjectStorage"') => true,
- ) as $str => $result)
- {
- if ((bool)($r=php_safe_unserialize($str)) !== $result)
- {
- if (!$result)
- {
- if (PHP_VERSION >= 7)
- {
- if (preg_match_all('/([^ ]+) Object\(/', array2string($r), $matches))
- {
- foreach($matches[1] as $class)
- {
- if (!preg_match('/^__PHP_Incomplete_Class(#\d+)?$/', $class))
- {
- echo "FAILED: $str\n";
- continue 2;
- }
- }
- }
- echo "passed: ".array2string($str)." = ".array2string($r)."\n";
- }
- else
- {
- echo "FAILED: $str\n";
- }
- }
- else
- {
- echo "false positive: $str\n";
- }
- }
- else
- {
- echo "passed: $str\n";
- }
- //echo "result=".array2string($result).", php_save_unserialize('".htmlspecialchars($str)."') = ".array2string(php_safe_unserialize($str))." --> ".array2string((bool)php_safe_unserialize($str))."\n";
- }
-}*/
-
-/**
- * Unserialize a json or php serialized array
- *
- * Used to migrate from PHP serialized database values to json-encoded ones.
- *
- * @param string $str string with serialized array
- * @param boolean $allow_not_serialized =false true: return $str as is, if it is no serialized array
- * @return array|str|false
- */
-function json_php_unserialize($str, $allow_not_serialized=false)
-{
- if ((in_array($str[0], array('a', 'i', 's', 'b', 'O', 'C')) && $str[1] == ':' || $str === 'N;') &&
- ($arr = php_safe_unserialize($str)) !== false || $str === 'b:0;')
- {
- return $arr;
- }
- if (!$allow_not_serialized || $str[0] == '[' || $str[0] == '{' || $str[0] == '"' || $str === 'null' || ($val = json_decode($str)) !== null)
- {
- return isset($val) ? $val : json_decode($str, true);
- }
- return $str;
-}
-
-/**
- * Clasify exception for a headline and log it to error_log, if not running as cli
- *
- * @param Exception|Error $e
- * @param string &$headline
- */
-function _egw_log_exception($e,&$headline=null)
-{
- $trace = explode("\n", $e->getTraceAsString());
- if ($e instanceof Api\Exception\NoPermission)
- {
- $headline = try_lang('Permission denied!');
- }
- elseif ($e instanceof Api\Db\Exception)
- {
- $headline = try_lang('Database error');
- }
- elseif ($e instanceof Api\Exception\WrongUserinput)
- {
- $headline = ''; // message contains the whole message, it's usually no real error but some input validation
- }
- elseif ($e instanceof egw_exception_warning)
- {
- $headline = 'PHP Warning';
- array_shift($trace);
- }
- else
- {
- $headline = try_lang('An error happened');
- }
- // log exception to error log, if not running as cli,
- // which outputs the error_log to stderr and therefore output it twice to the user
- if(isset($_SERVER['HTTP_HOST']) || $GLOBALS['egw_info']['flags']['no_exception_handler'] !== 'cli')
- {
- error_log($headline.($e instanceof egw_exception_warning ? ': ' : ' ('.get_class($e).'): ').$e->getMessage());
- foreach($trace as $line)
- {
- error_log($line);
- }
- error_log('# Instance='.$GLOBALS['egw_info']['user']['domain'].', User='.$GLOBALS['egw_info']['user']['account_lid'].
- ', Request='.$_SERVER['REQUEST_METHOD'].' '.($_SERVER['HTTPS']?'https://':'http://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].
- ', User-agent='.$_SERVER['HTTP_USER_AGENT']);
- }
-}
-
-/**
- * Fail a little bit more gracefully then an uncought exception
- *
- * Does NOT return
- *
- * @param Exception|Error $e
- */
-function egw_exception_handler($e)
-{
- // handle redirects without logging
- if (is_a($e, 'egw_exception_redirect'))
- {
- egw::redirect($e->url, $e->app);
- }
- // logging all exceptions to the error_log (if not cli) and get headline
- $headline = null;
- _egw_log_exception($e,$headline);
-
- // exception handler for cli (command line interface) clients, no html, no logging
- if(!isset($_SERVER['HTTP_HOST']) || $GLOBALS['egw_info']['flags']['no_exception_handler'] == 'cli')
- {
- echo ($headline ? $headline.': ' : '').$e->getMessage()."\n";
- if ($GLOBALS['egw_info']['server']['exception_show_trace'])
- {
- echo $e->getTraceAsString()."\n";
- }
- exit($e->getCode() ? $e->getCode() : 9999); // allways give a non-zero exit code
- }
- // regular GUI exception
- if (!isset($GLOBALS['egw_info']['flags']['no_exception_handler']))
- {
- header('HTTP/1.1 500 '.$headline);
- $message = '<h3>'.html::htmlspecialchars($headline)."</h3>\n".
- '<pre><b>'.html::htmlspecialchars($e->getMessage())."</b>\n\n";
-
- // only show trace (incl. function arguments) if explicitly enabled, eg. on a development system
- if ($GLOBALS['egw_info']['server']['exception_show_trace'])
- {
- $message .= html::htmlspecialchars($e->getTraceAsString());
- }
- $message .= "</pre>\n";
- if (is_a($e, 'EGroupware\Api\Db\Exception\Setup'))
- {
- $setup_dir = str_replace(array('home/index.php','index.php'),'setup/',$_SERVER['PHP_SELF']);
- $message .= '<a href="'.$setup_dir.'">Run setup to install or configure EGroupware.</a>';
- }
- elseif (is_object($GLOBALS['egw']) && isset($GLOBALS['egw']->session) && method_exists($GLOBALS['egw'],'link'))
- {
- $message .= '<p><a href="'.$GLOBALS['egw']->link('/index.php').'">'.try_lang('Click here to resume your eGroupWare Session.').'</a></p>';
- }
- if (is_object($GLOBALS['egw']) && isset($GLOBALS['egw']->framework))
- {
- $GLOBALS['egw']->framework->render($message,$headline);
- }
- else
- {
- echo "<html>\n<head>\n<title>".html::htmlspecialchars($headline)."</title>\n</head>\n<body>\n$message\n</body>\n</html>\n";
- }
- }
- // exception handler sending message back to the client as basic auth message
- elseif($GLOBALS['egw_info']['flags']['no_exception_handler'] == 'basic_auth')
- {
- $error = str_replace(array("\r", "\n"), array('', ' | '), $e->getMessage());
- header('WWW-Authenticate: Basic realm="'.$headline.' '.$error.'"');
- header('HTTP/1.1 401 Unauthorized');
- header('X-WebDAV-Status: 401 Unauthorized', true);
- }
- if (is_object($GLOBALS['egw']))
- {
- common::egw_exit();
- }
- exit;
-}
-
-if (!isset($GLOBALS['egw_info']['flags']['no_exception_handler']) || $GLOBALS['egw_info']['flags']['no_exception_handler'] !== true)
-{
- set_exception_handler('egw_exception_handler');
-}
-
-/**
- * Fail a little bit more gracefully then a catchable fatal error, by throwing an exception
- *
- * @param int $errno level of the error raised: E_* constants
- * @param string $errstr error message
- * @param string $errfile filename that the error was raised in
- * @param int $errline line number the error was raised at
- * @link http://www.php.net/manual/en/function.set-error-handler.php
- * @throws ErrorException
- */
-function egw_error_handler ($errno, $errstr, $errfile, $errline)
-{
- switch ($errno)
- {
- case E_RECOVERABLE_ERROR:
- case E_USER_ERROR:
- throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
-
- case E_WARNING:
- case E_USER_WARNING:
- // skip message for warnings supressed via @-error-control-operator (eg. @is_dir($path))
- // can be commented out to get suppressed warnings too!
- if (error_reporting())
- {
- _egw_log_exception(new egw_exception_warning($errstr.' in '.$errfile.' on line '.$errline));
- }
- break;
- }
-}
-
-/**
- * Used internally to trace warnings
- */
-class egw_exception_warning extends Exception {}
-
-// install our error-handler only for catchable fatal errors and warnings
-// following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING
-set_error_handler('egw_error_handler', E_RECOVERABLE_ERROR|E_USER_ERROR|E_WARNING|E_USER_WARNING);
// some not longer necessary defines
if (isset($GLOBALS['egw_info']['flags']['phpgw_compatibility']) && $GLOBALS['egw_info']['flags']['phpgw_compatibility'])
Modified: trunk/phpgwapi/inc/functions.inc.php
URL: http://svn.stylite.de/viewvc/egroupware/trunk/phpgwapi/inc/functions.inc.php?rev=55853&r1=55852&r2=55853&view=diff
==============================================================================
--- trunk/phpgwapi/inc/functions.inc.php (original)
+++ trunk/phpgwapi/inc/functions.inc.php Tue Apr 26 16:38:08 2016
@@ -1,144 +1,13 @@
<?php
/**
- * eGroupWare API loader
- *
- * Rewritten by [email protected] to store the eGW enviroment
- * (egw-object and egw_info-array) in a php-session and restore it from
- * there instead of creating it completly new on each page-request.
- * The enviroment gets now created by the egw-class
- *
- * This file was originaly written by Dan Kuykendall and Joseph Engo
- * Copyright (C) 2000, 2001 Dan Kuykendall
+ * EGroupware API loader
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @package api
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
+ * @deprecated use api/src/loader.php
* @version $Id$
*/
-// E_STRICT in PHP 5.4 gives various strict warnings in working code, which can NOT be easy fixed in all use-cases :-(
-// Only variables should be assigned by reference, eg. soetemplate::tree_walk()
-// Declaration of <extended method> should be compatible with <parent method>, varios places where method parameters change
-// --> switching it off for now, as it makes error-log unusable
-error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT);
-if (function_exists('get_magic_quotes_runtime') && get_magic_quotes_runtime())
-{
- set_magic_quotes_runtime(false);
-}
-
-$egw_min_php_version = '5.4';
-if (!function_exists('version_compare') || version_compare(PHP_VERSION,$egw_min_php_version) < 0)
-{
- die("eGroupWare requires PHP $egw_min_php_version or greater.<br />Please contact your System Administrator to upgrade PHP!");
-}
-
-if (!defined('EGW_API_INC')) define('EGW_API_INC',PHPGW_API_INC); // this is to support the header upgrade
-
-/* Make sure the header.inc.php is current. */
-if (!isset($GLOBALS['egw_domain']) || $GLOBALS['egw_info']['server']['versions']['header'] < $GLOBALS['egw_info']['server']['versions']['current_header'])
-{
- echo '<center><b>You need to update your header.inc.php file to version '.
- $GLOBALS['egw_info']['server']['versions']['current_header'].
- ' by running <a href="setup/manageheader.php">setup/headeradmin</a>.</b></center>';
- exit;
-}
-
-/* Make sure the developer is following the rules. */
-if (!isset($GLOBALS['egw_info']['flags']['currentapp']))
-{
- echo "<p><b>!!! YOU DO NOT HAVE YOUR \$GLOBALS['egw_info']['flags']['currentapp'] SET !!!<br>\n";
- echo '!!! PLEASE CORRECT THIS SITUATION !!!</b></p>';
-}
-
-require_once(EGW_API_INC.'/common_functions.inc.php');
-
-// init eGW's sessions-handler and check if we can restore the eGW enviroment from the php-session
-if (egw_session::init_handler())
-{
- if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login' && $GLOBALS['egw_info']['flags']['currentapp'] != 'logout')
- {
- if (is_array($_SESSION[egw_session::EGW_INFO_CACHE]) && $_SESSION[egw_session::EGW_OBJECT_CACHE] && $_SESSION[egw_session::EGW_REQUIRED_FILES])
- {
- // marking the context as restored from the session, used by session->verify to not read the data from the db again
- $GLOBALS['egw_info']['flags']['restored_from_session'] = true;
-
- // restoring the egw_info-array
- $GLOBALS['egw_info'] = array_merge($_SESSION[egw_session::EGW_INFO_CACHE],array('flags' => $GLOBALS['egw_info']['flags']));
-
- // include required class-definitions
- if (is_array($_SESSION[egw_session::EGW_REQUIRED_FILES])) // all classes, which can not be autoloaded
- {
- foreach($_SESSION[egw_session::EGW_REQUIRED_FILES] as $file)
- {
- require_once($file);
- }
- }
- $GLOBALS['egw'] = unserialize($_SESSION[egw_session::EGW_OBJECT_CACHE]);
-
- if (is_object($GLOBALS['egw']) && ($GLOBALS['egw'] instanceof egw)) // only egw object has wakeup2, setups egw_minimal eg. has not!
- {
- $GLOBALS['egw']->wakeup2(); // adapt the restored egw-object/enviroment to this request (eg. changed current app)
-
- //printf("<p style=\"position: absolute; right: 0px; top: 0px;\">egw-enviroment restored in %d ms</p>\n",1000*(perfgetmicrotime()-$GLOBALS['egw_info']['flags']['page_start_time']));
- $GLOBALS['egw_info']['flags']['session_restore_time'] = microtime(true) - $GLOBALS['egw_info']['flags']['page_start_time'];
- if (is_object($GLOBALS['egw']->translation)) return; // exit this file, as the rest of the file creates a new egw-object and -enviroment
- }
- // egw object could NOT be restored from the session, create a new one
- unset($GLOBALS['egw']);
- $GLOBALS['egw_info'] = array('flags'=>$GLOBALS['egw_info']['flags']);
- unset($GLOBALS['egw_info']['flags']['restored_from_session']);
- unset($_SESSION[egw_session::EGW_INFO_CACHE]);
- unset($_SESSION[egw_session::EGW_REQUIRED_FILES]);
- unset($_SESSION[egw_session::EGW_OBJECT_CACHE]);
- }
- //echo "<p>could not restore egw_info and the egw-object!!!</p>\n";
- }
- else // destroy the session-cache if called by login or logout
- {
- unset($_SESSION[egw_session::EGW_INFO_CACHE]);
- unset($_SESSION[egw_session::EGW_REQUIRED_FILES]);
- unset($_SESSION[egw_session::EGW_OBJECT_CACHE]);
- }
-}
-print_debug('sane environment','messageonly','api');
-
-/****************************************************************************\
-* Multi-Domain support *
-\****************************************************************************/
-
-$GLOBALS['egw_info']['user']['domain'] = egw_session::search_instance(
- isset($_POST['login']) ? $_POST['login'] : (isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : $_SERVER['REMOTE_USER']),
- egw_session::get_request('domain'),$GLOBALS['egw_info']['server']['default_domain'],
- array($_SERVER['HTTP_HOST'], $_SERVER['SERVER_NAME']),$GLOBALS['egw_domain']);
-
-$GLOBALS['egw_info']['server']['db_host'] = $GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]['db_host'];
-$GLOBALS['egw_info']['server']['db_port'] = $GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]['db_port'];
-$GLOBALS['egw_info']['server']['db_name'] = $GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]['db_name'];
-$GLOBALS['egw_info']['server']['db_user'] = $GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]['db_user'];
-$GLOBALS['egw_info']['server']['db_pass'] = $GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]['db_pass'];
-$GLOBALS['egw_info']['server']['db_type'] = $GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]['db_type'];
-print_debug('domain',@$GLOBALS['egw_info']['user']['domain'],'api');
-
-// the egw-object instanciates all sub-classes (eg. $GLOBALS['egw']->db) and the egw_info array
-$GLOBALS['egw'] = new egw(array_keys($GLOBALS['egw_domain']));
-
-// store domain config user&pw as a hash (originals get unset)
-$GLOBALS['egw_info']['server']['config_hash'] = egw_session::user_pw_hash($GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]['config_user'],
- $GLOBALS['egw_domain'][$GLOBALS['egw_info']['user']['domain']]['config_passwd'],true);
-
-if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login' && !$GLOBALS['egw_info']['server']['show_domain_selectbox'])
-{
- unset($GLOBALS['egw_domain']); // we kill this for security reasons
- unset($GLOBALS['egw_info']['server']['header_admin_user']);
- unset($GLOBALS['egw_info']['server']['header_admin_password']);
-}
-
-// saving the the egw_info array and the egw-object in the session
-if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login')
-{
- $_SESSION[egw_session::EGW_INFO_CACHE] = $GLOBALS['egw_info'];
- unset($_SESSION[egw_session::EGW_INFO_CACHE]['flags']); // dont save the flags, they change on each request
-
- $_SESSION[egw_session::EGW_OBJECT_CACHE] = serialize($GLOBALS['egw']);
-}
+require_once dirname(dirname(__DIR__)).'/api/src/loader.php';
------------------------------------------------------------------------------
Find and fix application performance issues faster with Applications Manager
Applications Manager provides deep performance insights into multiple tiers of
your business applications. It resolves application problems quickly and
reduces your MTTR. Get your free trial!
https://ad.doubleclick.net/ddm/clk/302982198;130105516;z
_______________________________________________
eGroupWare-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/egroupware-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.