|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* EGroupware API - Applications |
|
4
|
|
|
* |
|
5
|
|
|
* @link http://www.egroupware.org |
|
6
|
|
|
* This file was originaly written by Dan Kuykendall and Joseph Engo |
|
7
|
|
|
* Copyright (C) 2000, 2001 Dan Kuykendall |
|
8
|
|
|
* Parts Copyright (C) 2003 Free Software Foundation |
|
9
|
|
|
* @author [email protected] |
|
10
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License |
|
11
|
|
|
* @package api |
|
12
|
|
|
* @version $Id$ |
|
13
|
|
|
*/ |
|
14
|
|
|
|
|
15
|
|
|
namespace EGroupware\Api; |
|
16
|
|
|
|
|
17
|
|
|
// explicitly list old, non-namespaced classes |
|
18
|
|
|
// they are only used, if phpgwapi is installed |
|
19
|
|
|
use accounts as egw_accounts; |
|
20
|
|
|
use egw_session; |
|
21
|
|
|
use common; |
|
22
|
|
|
|
|
23
|
|
|
/** |
|
24
|
|
|
* New written class to create the eGW enviroment AND restore it from a php-session |
|
25
|
|
|
* |
|
26
|
|
|
* Rewritten by [email protected] to store the eGW enviroment |
|
27
|
|
|
* (egw-object and egw_info-array) in a php-session and restore it from |
|
28
|
|
|
* there instead of creating it completly new on each page-request. |
|
29
|
|
|
* The enviroment gets now created by the egw-class |
|
30
|
|
|
* |
|
31
|
|
|
* Extending Egw\Base which uses now a getter method to create the usual subobject on demand, |
|
32
|
|
|
* to allow a quicker header include on sites not using php4-restore. |
|
33
|
|
|
* This also makes a lot of application code, like the following, unnecessary: |
|
34
|
|
|
* if (!is_object($GLOBALS['egw']->ldap) |
|
35
|
|
|
* { |
|
36
|
|
|
* $GLOBALS['egw']->ldap = Api\Ldap::factory(); |
|
37
|
|
|
* } |
|
38
|
|
|
* You can now simply use $GLOBALS['egw']->ldap, and the egw class instanciates it for you on demand. |
|
39
|
|
|
*/ |
|
40
|
|
|
class Egw extends Egw\Base |
|
41
|
|
|
{ |
|
42
|
|
|
/** |
|
43
|
|
|
* Turn on debug mode. Will output additional data for debugging purposes. |
|
44
|
|
|
* @var string |
|
45
|
|
|
* @access public |
|
46
|
|
|
*/ |
|
47
|
|
|
var $debug = 0; // This will turn on debugging information. |
|
48
|
|
|
/** |
|
49
|
|
|
* Instance of the account object |
|
50
|
|
|
* |
|
51
|
|
|
* @var Accounts |
|
52
|
|
|
*/ |
|
53
|
|
|
var $accounts; |
|
54
|
|
|
|
|
55
|
|
|
/** |
|
56
|
|
|
* Constructor: Instantiates the sub-classes |
|
57
|
|
|
* |
|
58
|
|
|
* @author [email protected] |
|
59
|
|
|
* @param array $domain_names array with valid egw-domain names |
|
60
|
|
|
*/ |
|
61
|
|
|
function __construct($domain_names=null) |
|
62
|
|
|
{ |
|
63
|
|
|
$GLOBALS['egw'] =& $this; // we need to be immediately available there for the other classes we instantiate |
|
64
|
|
|
$this->setup($domain_names,True); |
|
|
|
|
|
|
65
|
|
|
} |
|
66
|
|
|
|
|
67
|
|
|
/** |
|
68
|
|
|
* Called every time the constructor is called. Also called by sessions to ensure the correct db, |
|
69
|
|
|
* in which case we do not recreate the session object. |
|
70
|
|
|
* @author [email protected] (moved to setup() by [email protected] |
|
71
|
|
|
* @param array $domain_names array with valid egw-domain names |
|
72
|
|
|
* @param boolean $createsessionobject True to create the session object (default=True) |
|
73
|
|
|
*/ |
|
74
|
|
|
function setup($domain_names,$createsessionobject=True) |
|
75
|
|
|
{ |
|
76
|
|
|
// create the DB-object |
|
77
|
|
|
// as SiteMgr, Wiki, KnowledgeBase and probably more still use eg next_record(), we stick with Db\Deprecated for now |
|
78
|
|
|
$this->db = new Db\Deprecated($GLOBALS['egw_info']['server']); |
|
|
|
|
|
|
79
|
|
|
if ($this->debug) |
|
80
|
|
|
{ |
|
81
|
|
|
$this->db->Debug = 1; |
|
|
|
|
|
|
82
|
|
|
} |
|
83
|
|
|
$this->db->set_app(Db::API_APPNAME); |
|
|
|
|
|
|
84
|
|
|
|
|
85
|
|
|
// check if eGW is already setup, if not redirect to setup/ |
|
86
|
|
|
try { |
|
87
|
|
|
$this->db->connect(); |
|
|
|
|
|
|
88
|
|
|
$num_config = $this->db->select(Config::TABLE,'COUNT(config_name)',false,__LINE__,__FILE__)->fetchColumn(); |
|
|
|
|
|
|
89
|
|
|
} |
|
90
|
|
|
catch(Db\Exception\Connection $e) { |
|
91
|
|
|
// ignore exception, get handled below |
|
92
|
|
|
} |
|
93
|
|
|
catch(Db\Exception\InvalidSql $e1) { |
|
94
|
|
|
unset($e1); // not used |
|
95
|
|
|
try { |
|
96
|
|
|
$phpgw_config = $this->db->select('phpgw_config','COUNT(config_name)',false,__LINE__,__FILE__)->fetchColumn(); |
|
|
|
|
|
|
97
|
|
|
} |
|
98
|
|
|
catch (Db\Exception\InvalidSql $e2) { |
|
99
|
|
|
unset($e2); // not used |
|
100
|
|
|
// ignor error, get handled below |
|
101
|
|
|
} |
|
102
|
|
|
} |
|
103
|
|
|
if (!$num_config) |
|
104
|
|
|
{ |
|
105
|
|
|
// we check for the old table too, to not scare updating users ;-) |
|
106
|
|
|
if ($phpgw_config) |
|
107
|
|
|
{ |
|
108
|
|
|
throw new Exception('You need to update EGroupware before you can continue using it.',999); |
|
109
|
|
|
} |
|
110
|
|
|
if ($e) |
|
111
|
|
|
{ |
|
112
|
|
|
throw new Db\Exception\Setup('Connection with '.$e->getMessage()."\n\n". |
|
113
|
|
|
'Maybe you not created a database for EGroupware yet.',999); |
|
114
|
|
|
} |
|
115
|
|
|
throw new Db\Exception\Setup('It appears that you have not created the database tables for EGroupware.',999); |
|
116
|
|
|
} |
|
117
|
|
|
// Set the DB's client charset if a system-charset is set and some other values needed by egw_cache (used in Config::read) |
|
118
|
|
|
foreach($this->db->select(Config::TABLE,'config_name,config_value',array( |
|
|
|
|
|
|
119
|
|
|
'config_app' => 'phpgwapi', |
|
120
|
|
|
'config_name' => array('system_charset','install_id','temp_dir'), |
|
121
|
|
|
),__LINE__,__FILE__) as $row) |
|
122
|
|
|
{ |
|
123
|
|
|
$GLOBALS['egw_info']['server'][$row['config_name']] = $row['config_value']; |
|
124
|
|
|
} |
|
125
|
|
|
if ($GLOBALS['egw_info']['server']['system_charset'] && $GLOBALS['egw_info']['server']['system_charset'] != 'utf-8') |
|
126
|
|
|
{ |
|
127
|
|
|
$this->db->Link_ID->SetCharSet($GLOBALS['egw_info']['server']['system_charset']); |
|
|
|
|
|
|
128
|
|
|
} |
|
129
|
|
|
// load up the $GLOBALS['egw_info']['server'] array |
|
130
|
|
|
$GLOBALS['egw_info']['server'] += Config::read('phpgwapi'); |
|
131
|
|
|
|
|
132
|
|
|
// if no server timezone set, use date_default_timezone_get() to determine it once |
|
133
|
|
|
// it fills to log with deprecated warnings under 5.3 otherwise |
|
134
|
|
|
if (empty($GLOBALS['egw_info']['server']['server_timezone']) || |
|
135
|
|
|
$GLOBALS['egw_info']['server']['server_timezone'] == 'System/Localtime') // treat invalid tz like empty! |
|
136
|
|
|
{ |
|
137
|
|
|
try |
|
138
|
|
|
{ |
|
139
|
|
|
$tz = new \DateTimeZone(date_default_timezone_get()); |
|
140
|
|
|
Config::save_value('server_timezone',$GLOBALS['egw_info']['server']['server_timezone'] = $tz->getName(),'phpgwapi'); |
|
141
|
|
|
error_log(__METHOD__."() stored server_timezone=".$GLOBALS['egw_info']['server']['server_timezone']); |
|
142
|
|
|
} |
|
143
|
|
|
catch(Exception $e) |
|
144
|
|
|
{ |
|
145
|
|
|
// do nothing if new DateTimeZone fails (eg. 'System/Localtime' returned), specially do NOT store it! |
|
146
|
|
|
error_log(__METHOD__."() NO valid 'date.timezone' set in your php.ini!"); |
|
147
|
|
|
} |
|
148
|
|
|
} |
|
149
|
|
|
date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']); |
|
150
|
|
|
|
|
151
|
|
|
// if phpgwapi exists we prefer accounts and egw_session, as they have some deprecated methods |
|
152
|
|
|
if (file_exists(EGW_SERVER_ROOT.'/phpgwapi')) |
|
153
|
|
|
{ |
|
154
|
|
|
$this->accounts = new egw_accounts(); |
|
155
|
|
|
/* Do not create the session object if called by the sessions class. This way |
|
156
|
|
|
* we ensure the correct db based on the user domain. |
|
157
|
|
|
*/ |
|
158
|
|
|
if($createsessionobject) |
|
159
|
|
|
{ |
|
160
|
|
|
$this->session = new egw_session($domain_names); |
|
161
|
|
|
} |
|
162
|
|
|
} |
|
163
|
|
|
else |
|
164
|
|
|
{ |
|
165
|
|
|
$this->accounts = new Accounts(); |
|
166
|
|
|
/* Do not create the session object if called by the sessions class. This way |
|
167
|
|
|
* we ensure the correct db based on the user domain. |
|
168
|
|
|
*/ |
|
169
|
|
|
if($createsessionobject) |
|
170
|
|
|
{ |
|
171
|
|
|
$this->session = new Session($domain_names); |
|
172
|
|
|
} |
|
173
|
|
|
} |
|
174
|
|
|
// setup the other subclasses |
|
175
|
|
|
$this->acl = new Acl(); |
|
176
|
|
|
$this->preferences = new Preferences(); |
|
177
|
|
|
$this->applications = new Egw\Applications(); |
|
178
|
|
|
|
|
179
|
|
|
if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login' && $GLOBALS['egw_info']['flags']['currentapp'] != 'logout') |
|
180
|
|
|
{ |
|
181
|
|
|
$this->verify_session(); |
|
182
|
|
|
$this->applications->read_installed_apps(); // to get translated app-titles, has to be after verify_session |
|
183
|
|
|
|
|
184
|
|
|
$this->define_egw_constants(); |
|
185
|
|
|
|
|
186
|
|
|
$this->check_app_rights(); |
|
187
|
|
|
|
|
188
|
|
|
$this->load_optional_classes(); |
|
189
|
|
|
} |
|
190
|
|
|
else // set the defines for login, in case it's more then just login |
|
191
|
|
|
{ |
|
192
|
|
|
$this->define_egw_constants(); |
|
193
|
|
|
} |
|
194
|
|
|
} |
|
195
|
|
|
|
|
196
|
|
|
/** |
|
197
|
|
|
* __wakeup function gets called by php while unserializing the egw-object, eg. reconnects to the DB |
|
198
|
|
|
* |
|
199
|
|
|
* @author [email protected] |
|
200
|
|
|
*/ |
|
201
|
|
|
function __wakeup() |
|
202
|
|
|
{ |
|
203
|
|
|
$GLOBALS['egw'] =& $this; // we need to be immediately available there for the other classes we instantiate |
|
204
|
|
|
// for the migration: reference us to the old phpgw object |
|
205
|
|
|
$GLOBALS['phpgw'] =& $this; |
|
206
|
|
|
|
|
207
|
|
|
if ($GLOBALS['egw_info']['server']['system_charset']) |
|
208
|
|
|
{ |
|
209
|
|
|
$this->db->Link_ID->SetCharSet($GLOBALS['egw_info']['server']['system_charset']); |
|
|
|
|
|
|
210
|
|
|
} |
|
211
|
|
|
// restoring server timezone, to avoid warnings under php5.3 |
|
212
|
|
View Code Duplication |
if (!empty($GLOBALS['egw_info']['server']['server_timezone'])) |
|
213
|
|
|
{ |
|
214
|
|
|
date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']); |
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
$this->define_egw_constants(); |
|
218
|
|
|
} |
|
219
|
|
|
|
|
220
|
|
|
/** |
|
221
|
|
|
* wakeup2 function needs to be called after unserializing the egw-object |
|
222
|
|
|
* |
|
223
|
|
|
* It adapts the restored object/enviroment to the changed (current) application / page-request |
|
224
|
|
|
* |
|
225
|
|
|
* @author [email protected] |
|
226
|
|
|
*/ |
|
227
|
|
|
function wakeup2() |
|
228
|
|
|
{ |
|
229
|
|
|
// do some application specific stuff, need to be done as we are different (current) app now |
|
230
|
|
|
if (isset($this->template)) |
|
231
|
|
|
{ |
|
232
|
|
|
$this->template->set_root(EGW_APP_TPL); |
|
233
|
|
|
} |
|
234
|
|
|
// init the translation class, necessary as own wakeup would run before our's |
|
235
|
|
|
Translation::init(isset($GLOBALS['egw_info']['flags']['load_translations']) ? $GLOBALS['egw_info']['flags']['load_translations'] : true); |
|
236
|
|
|
|
|
237
|
|
|
$this->unset_datetime(); |
|
238
|
|
|
|
|
239
|
|
|
// verify the session |
|
240
|
|
|
$GLOBALS['egw']->verify_session(); |
|
241
|
|
|
$GLOBALS['egw']->check_app_rights(); |
|
242
|
|
|
|
|
243
|
|
|
$this->load_optional_classes(); |
|
244
|
|
|
} |
|
245
|
|
|
|
|
246
|
|
|
/** |
|
247
|
|
|
* Unsetting datetime object, so time gets updated |
|
248
|
|
|
*/ |
|
249
|
|
|
function unset_datetime() |
|
250
|
|
|
{ |
|
251
|
|
|
unset($this->datetime); |
|
252
|
|
|
} |
|
253
|
|
|
|
|
254
|
|
|
/** |
|
255
|
|
|
* load optional classes by mentioning them in egw_info[flags][enable_CLASS_class] => true |
|
256
|
|
|
* |
|
257
|
|
|
* Also loads the template-class if not egw_info[flags][disable_Template_class] is set |
|
258
|
|
|
* |
|
259
|
|
|
* Maybe the whole thing should be depricated ;-) |
|
260
|
|
|
*/ |
|
261
|
|
|
function load_optional_classes() |
|
262
|
|
|
{ |
|
263
|
|
|
// output the header unless the developer turned it off |
|
264
|
|
|
if (!@$GLOBALS['egw_info']['flags']['noheader']) |
|
265
|
|
|
{ |
|
266
|
|
|
echo $GLOBALS['egw']->framework->header(); |
|
267
|
|
|
|
|
268
|
|
|
if (!$GLOBALS['egw_info']['flags']['nonavbar']) |
|
269
|
|
|
{ |
|
270
|
|
|
echo $GLOBALS['egw']->framework->navbar(); |
|
271
|
|
|
} |
|
272
|
|
|
} |
|
273
|
|
|
|
|
274
|
|
|
// Load the (depricated) app include files if they exists |
|
275
|
|
|
if (EGW_APP_INC != "" && ! preg_match ('/phpgwapi/i', EGW_APP_INC) && |
|
276
|
|
|
file_exists(EGW_APP_INC . '/functions.inc.php') && !isset($_GET['menuaction'])) |
|
277
|
|
|
{ |
|
278
|
|
|
include(EGW_APP_INC . '/functions.inc.php'); |
|
279
|
|
|
} |
|
280
|
|
|
if (!@$GLOBALS['egw_info']['flags']['noheader'] && !@$GLOBALS['egw_info']['flags']['noappheader'] && |
|
281
|
|
|
file_exists(EGW_APP_INC . '/header.inc.php') && !isset($_GET['menuaction'])) |
|
282
|
|
|
{ |
|
283
|
|
|
include(EGW_APP_INC . '/header.inc.php'); |
|
284
|
|
|
} |
|
285
|
|
|
} |
|
286
|
|
|
|
|
287
|
|
|
/** |
|
288
|
|
|
* Verfiy there is a valid session |
|
289
|
|
|
* |
|
290
|
|
|
* One can specify a callback, which gets called if there's no valid session. If the callback returns true, the parameter |
|
291
|
|
|
* containst account-details (in keys login, passwd and passwd_type) to automatic create an (anonymous session) |
|
292
|
|
|
* |
|
293
|
|
|
* It also checks if enforce_ssl is set in the DB and redirects to the https:// version of the site. |
|
294
|
|
|
* |
|
295
|
|
|
* If there is no valid session and none could be automatic created, the function will redirect to login and NOT return |
|
296
|
|
|
*/ |
|
297
|
|
|
function verify_session() |
|
298
|
|
|
{ |
|
299
|
|
|
if($GLOBALS['egw_info']['server']['enforce_ssl'] === 'redirect' && !$_SERVER['HTTPS']) |
|
300
|
|
|
{ |
|
301
|
|
|
Header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']); |
|
302
|
|
|
exit; |
|
303
|
|
|
} |
|
304
|
|
|
// check if we have a session, if not try to automatic create one |
|
305
|
|
|
if ($this->session->verify()) return true; |
|
306
|
|
|
|
|
307
|
|
|
$account = null; |
|
308
|
|
|
if (($account_callback = $GLOBALS['egw_info']['flags']['autocreate_session_callback']) && is_callable($account_callback) && |
|
309
|
|
|
($sessionid = call_user_func_array($account_callback,array(&$account))) === true) // $account_call_back returns true, false or a session-id |
|
310
|
|
|
{ |
|
311
|
|
|
$sessionid = $this->session->create($account); |
|
312
|
|
|
} |
|
313
|
|
|
if (!$sessionid) |
|
314
|
|
|
{ |
|
315
|
|
|
//echo "<p>account_callback='$account_callback', account=".print_r($account,true).", sessionid=$sessionid</p>\n"; exit; |
|
316
|
|
|
// we forward to the same place after the re-login |
|
317
|
|
|
if ($GLOBALS['egw_info']['server']['webserver_url'] && $GLOBALS['egw_info']['server']['webserver_url'] != '/' && |
|
318
|
|
|
($webserver_path = parse_url($GLOBALS['egw_info']['server']['webserver_url'],PHP_URL_PATH)) && $webserver_path != '/') |
|
319
|
|
|
{ |
|
320
|
|
|
// we have to use only path component, to cope with domains like http://egroupware.domain.com and /egroupware |
|
321
|
|
|
list(,$relpath) = explode($webserver_path,parse_url($_SERVER['PHP_SELF'],PHP_URL_PATH),2); |
|
322
|
|
|
} |
|
323
|
|
|
else // the webserver-url is empty or just a slash '/' (eGW is installed in the docroot and no domain given) |
|
324
|
|
|
{ |
|
325
|
|
|
$matches = null; |
|
326
|
|
|
if (preg_match('/^https?:\/\/[^\/]*\/(.*)$/',$relpath=$_SERVER['PHP_SELF'],$matches)) |
|
327
|
|
|
{ |
|
328
|
|
|
$relpath = $matches[1]; |
|
329
|
|
|
} |
|
330
|
|
|
} |
|
331
|
|
|
// this removes the sessiondata if its saved in the URL |
|
332
|
|
|
$query = preg_replace('/[&]?sessionid(=|%3D)[^&]+&kp3(=|%3D)[^&]+&domain=.*$/','',$_SERVER['QUERY_STRING']); |
|
333
|
|
|
if ($GLOBALS['egw_info']['server']['http_auth_types']) |
|
334
|
|
|
{ |
|
335
|
|
|
$redirect = '/phpgwapi/ntlm/index.php?'; |
|
336
|
|
|
} |
|
337
|
|
|
else |
|
338
|
|
|
{ |
|
339
|
|
|
$redirect = '/login.php?'; |
|
340
|
|
|
// only add "your session could not be verified", if a sessionid is given (cookie or on url) |
|
341
|
|
|
if (Session::get_sessionid()) $redirect .= 'cd=10&'; |
|
342
|
|
|
} |
|
343
|
|
|
if ($relpath) $redirect .= 'phpgw_forward='.urlencode($relpath.(!empty($query) ? '?'.$query : '')); |
|
344
|
|
|
self::redirect_link($redirect); |
|
345
|
|
|
} |
|
346
|
|
|
} |
|
347
|
|
|
|
|
348
|
|
|
/** |
|
349
|
|
|
* Verify the user has rights for the requested app |
|
350
|
|
|
* |
|
351
|
|
|
* If the user has no rights for the app (eg. called via URL) he get a permission denied page (this function does NOT return) |
|
352
|
|
|
* |
|
353
|
|
|
* @throws Exception\Redirect for anonymous user accessing something he has no rights to |
|
354
|
|
|
* @throws Exception\NoPermission\Admin |
|
355
|
|
|
* @throws Exception\NoPermission\App |
|
356
|
|
|
*/ |
|
357
|
|
|
function check_app_rights() |
|
358
|
|
|
{ |
|
359
|
|
|
$this->currentapp = $GLOBALS['egw_info']['flags']['currentapp']; // some apps change it later |
|
360
|
|
|
|
|
361
|
|
|
if (!in_array($GLOBALS['egw_info']['flags']['currentapp'], array('api','about'))) // give everyone implicit api rights |
|
362
|
|
|
{ |
|
363
|
|
|
// This will need to use ACL in the future |
|
364
|
|
|
if (!$GLOBALS['egw_info']['user']['apps'][$currentapp = $GLOBALS['egw_info']['flags']['currentapp']] || |
|
365
|
|
|
($GLOBALS['egw_info']['flags']['admin_only'] && !$GLOBALS['egw_info']['user']['apps']['admin'])) |
|
366
|
|
|
{ |
|
367
|
|
|
// present a login page, if anon user has no right for an application |
|
368
|
|
|
if ($this->session->session_flags == 'A') |
|
369
|
|
|
{ |
|
370
|
|
|
// need to destroy a basic auth session here, because it will only be available on current url |
|
371
|
|
|
if (($sessionid = Session::get_sessionid(true))) |
|
372
|
|
|
{ |
|
373
|
|
|
$GLOBALS['egw']->session->destroy($sessionid); |
|
374
|
|
|
} |
|
375
|
|
|
throw new Exception\Redirect(self::link('/logout.php')); |
|
376
|
|
|
} |
|
377
|
|
|
if ($currentapp == 'admin' || $GLOBALS['egw_info']['flags']['admin_only']) |
|
378
|
|
|
{ |
|
379
|
|
|
throw new Exception\NoPermission\Admin(); |
|
380
|
|
|
} |
|
381
|
|
|
throw new Exception\NoPermission\App($currentapp); |
|
382
|
|
|
} |
|
383
|
|
|
} |
|
384
|
|
|
} |
|
385
|
|
|
|
|
386
|
|
|
/** |
|
387
|
|
|
* create all the defines / constants of the eGW-environment (plus the deprecated phpgw ones) |
|
388
|
|
|
*/ |
|
389
|
|
|
function define_egw_constants() |
|
390
|
|
|
{ |
|
391
|
|
|
define('EGW_ACL_READ',1); |
|
392
|
|
|
define('EGW_ACL_ADD',2); |
|
393
|
|
|
define('EGW_ACL_EDIT',4); |
|
394
|
|
|
define('EGW_ACL_DELETE',8); |
|
395
|
|
|
define('EGW_ACL_PRIVATE',16); |
|
396
|
|
|
define('EGW_ACL_GROUP_MANAGERS',32); |
|
397
|
|
|
define('EGW_ACL_CUSTOM_1',64); |
|
398
|
|
|
define('EGW_ACL_CUSTOM_2',128); |
|
399
|
|
|
define('EGW_ACL_CUSTOM_3',256); |
|
400
|
|
|
// and the old ones |
|
401
|
|
|
define('PHPGW_ACL_READ',1); |
|
402
|
|
|
define('PHPGW_ACL_ADD',2); |
|
403
|
|
|
define('PHPGW_ACL_EDIT',4); |
|
404
|
|
|
define('PHPGW_ACL_DELETE',8); |
|
405
|
|
|
define('PHPGW_ACL_PRIVATE',16); |
|
406
|
|
|
define('PHPGW_ACL_GROUP_MANAGERS',32); |
|
407
|
|
|
define('PHPGW_ACL_CUSTOM_1',64); |
|
408
|
|
|
define('PHPGW_ACL_CUSTOM_2',128); |
|
409
|
|
|
define('PHPGW_ACL_CUSTOM_3',256); |
|
410
|
|
|
// A few hacker resistant constants that will be used throught the program |
|
411
|
|
|
if (file_exists(EGW_SERVER_ROOT.'/phpgwapi')) |
|
412
|
|
|
{ |
|
413
|
|
|
define('EGW_TEMPLATE_DIR', Framework\Template::get_dir('phpgwapi')); |
|
414
|
|
|
define('EGW_IMAGES_DIR', common::get_image_path('phpgwapi')); |
|
415
|
|
|
define('EGW_IMAGES_FILEDIR', common::get_image_dir('phpgwapi')); |
|
416
|
|
|
define('EGW_APP_ROOT', common::get_app_dir()); |
|
417
|
|
|
define('EGW_APP_INC', common::get_inc_dir()); |
|
418
|
|
|
try { |
|
419
|
|
|
define('EGW_APP_TPL', Framework\Template::get_dir()); |
|
420
|
|
|
} |
|
421
|
|
|
catch (Exception\WrongParameter $e) { |
|
422
|
|
|
unset($e); |
|
423
|
|
|
define('EGW_APP_TPL', null); |
|
424
|
|
|
} |
|
425
|
|
|
define('EGW_IMAGES', common::get_image_path()); |
|
426
|
|
|
define('EGW_APP_IMAGES_DIR', common::get_image_dir()); |
|
427
|
|
|
// and the old ones |
|
428
|
|
|
define('PHPGW_TEMPLATE_DIR',EGW_TEMPLATE_DIR); |
|
429
|
|
|
define('PHPGW_IMAGES_DIR',EGW_IMAGES_DIR); |
|
430
|
|
|
define('PHPGW_IMAGES_FILEDIR',EGW_IMAGES_FILEDIR); |
|
431
|
|
|
define('PHPGW_APP_ROOT',EGW_APP_ROOT); |
|
432
|
|
|
define('PHPGW_APP_INC',EGW_APP_INC); |
|
433
|
|
|
define('PHPGW_APP_TPL',EGW_APP_TPL); |
|
434
|
|
|
define('PHPGW_IMAGES',EGW_IMAGES); |
|
435
|
|
|
define('PHPGW_APP_IMAGES_DIR',EGW_APP_IMAGES_DIR); |
|
436
|
|
|
} |
|
437
|
|
|
} |
|
438
|
|
|
|
|
439
|
|
|
/** |
|
440
|
|
|
* force the session cache to be re-created, because some of it's data changed |
|
441
|
|
|
* |
|
442
|
|
|
* Needs to be called if user-preferences, system-config or enabled apps of the current user have been changed and |
|
443
|
|
|
* the change should have immediate effect |
|
444
|
|
|
*/ |
|
445
|
|
|
static function invalidate_session_cache() |
|
446
|
|
|
{ |
|
447
|
|
|
unset($_SESSION['egw_info_cache']); |
|
448
|
|
|
unset($_SESSION['egw_object_cache']); |
|
449
|
|
|
} |
|
450
|
|
|
|
|
451
|
|
|
/** |
|
452
|
|
|
* run string through htmlspecialchars and stripslashes |
|
453
|
|
|
* |
|
454
|
|
|
* @param string $s |
|
455
|
|
|
* @return string The string with html special characters replaced with entities |
|
456
|
|
|
*/ |
|
457
|
|
|
static function strip_html($s) |
|
458
|
|
|
{ |
|
459
|
|
|
return htmlspecialchars(stripslashes($s)); |
|
460
|
|
|
} |
|
461
|
|
|
|
|
462
|
|
|
/** |
|
463
|
|
|
* Link url generator |
|
464
|
|
|
* |
|
465
|
|
|
* @param string $url url link is for |
|
466
|
|
|
* @param string|array $extravars ='' extra params to be added to url |
|
467
|
|
|
* @param string $link_app =null if appname or true, some templates generate a special link-handler url |
|
468
|
|
|
* @return string The full url after processing |
|
469
|
|
|
*/ |
|
470
|
|
|
static function link($url, $extravars = '', $link_app=null) |
|
471
|
|
|
{ |
|
472
|
|
|
return $GLOBALS['egw']->framework->link($url, $extravars, $link_app); |
|
473
|
|
|
} |
|
474
|
|
|
|
|
475
|
|
|
/** |
|
476
|
|
|
* Redirects direct to a generated link |
|
477
|
|
|
* |
|
478
|
|
|
* @param string $url url link is for |
|
479
|
|
|
* @param string|array $extravars ='' extra params to be added to url |
|
480
|
|
|
* @param string $link_app =null if appname or true, some templates generate a special link-handler url |
|
481
|
|
|
* @return string The full url after processing |
|
482
|
|
|
*/ |
|
483
|
|
|
static function redirect_link($url, $extravars='', $link_app=null) |
|
484
|
|
|
{ |
|
485
|
|
|
return $GLOBALS['egw']->framework->redirect_link($url, $extravars, $link_app); |
|
486
|
|
|
} |
|
487
|
|
|
|
|
488
|
|
|
/** |
|
489
|
|
|
* Handles redirects under iis and apache, it does NOT return (calls exit) |
|
490
|
|
|
* |
|
491
|
|
|
* This function handles redirects under iis and apache it assumes that $phpgw->link() has already been called |
|
492
|
|
|
* |
|
493
|
|
|
* @param string $url url to redirect to |
|
494
|
|
|
* @param string $link_app =null appname to redirect for, default currentapp |
|
495
|
|
|
*/ |
|
496
|
|
|
static function redirect($url, $link_app=null) |
|
497
|
|
|
{ |
|
498
|
|
|
Framework::redirect($url, $link_app); |
|
499
|
|
|
} |
|
500
|
|
|
|
|
501
|
|
|
/** |
|
502
|
|
|
* Shortcut to translation class |
|
503
|
|
|
* |
|
504
|
|
|
* This function is a basic wrapper to Translation::translate() |
|
505
|
|
|
* |
|
506
|
|
|
* @deprecated only used in the old timetracker |
|
507
|
|
|
* @param string The key for the phrase |
|
508
|
|
|
* @see Translation::translate() |
|
509
|
|
|
*/ |
|
510
|
|
View Code Duplication |
static function lang($key,$args=null) |
|
511
|
|
|
{ |
|
512
|
|
|
if (!is_array($args)) |
|
513
|
|
|
{ |
|
514
|
|
|
$args = func_get_args(); |
|
515
|
|
|
array_shift($args); |
|
516
|
|
|
} |
|
517
|
|
|
return Translation::translate($key,$args); |
|
518
|
|
|
} |
|
519
|
|
|
|
|
520
|
|
|
/** |
|
521
|
|
|
* registered shutdown callbacks and optional arguments |
|
522
|
|
|
* |
|
523
|
|
|
* @var array |
|
524
|
|
|
*/ |
|
525
|
|
|
private static $shutdown_callbacks = array(); |
|
526
|
|
|
|
|
527
|
|
|
/** |
|
528
|
|
|
* Register a callback to run on shutdown AFTER output send to user |
|
529
|
|
|
* |
|
530
|
|
|
* Allows eg. static classes (no destructor) to run on shutdown AND |
|
531
|
|
|
* garanties to run AFTER output send to user. |
|
532
|
|
|
* |
|
533
|
|
|
* @param callable $callback use array($classname, $method) for static methods |
|
534
|
|
|
* @param array $args =array() |
|
535
|
|
|
*/ |
|
536
|
|
|
public static function on_shutdown($callback, array $args=array()) |
|
537
|
|
|
{ |
|
538
|
|
|
array_unshift($args, $callback); |
|
539
|
|
|
|
|
540
|
|
|
// prepend new callback, to run them in oposite order they are registered |
|
541
|
|
|
array_unshift(self::$shutdown_callbacks, $args); |
|
542
|
|
|
} |
|
543
|
|
|
|
|
544
|
|
|
/** |
|
545
|
|
|
* Shutdown handler running all registered on_shutdown callbacks and then disconnecting from db |
|
546
|
|
|
*/ |
|
547
|
|
|
function __destruct() |
|
548
|
|
|
{ |
|
549
|
|
|
if (!defined('EGW_SHUTDOWN')) |
|
550
|
|
|
{ |
|
551
|
|
|
define('EGW_SHUTDOWN',True); |
|
552
|
|
|
|
|
553
|
|
|
// send json response BEFORE flushing output |
|
554
|
|
|
if (Json\Request::isJSONRequest()) |
|
555
|
|
|
{ |
|
556
|
|
|
Json\Response::sendResult(); |
|
557
|
|
|
} |
|
558
|
|
|
|
|
559
|
|
|
// run all on_shutdown callbacks with session in their name (eg. egw_link::save_session_cache), do NOT stop on exceptions |
|
560
|
|
|
foreach(self::$shutdown_callbacks as $n => $data) |
|
561
|
|
|
{ |
|
562
|
|
|
try { |
|
563
|
|
|
//error_log(__METHOD__."() running ".array2string($data)); |
|
564
|
|
|
$callback = array_shift($data); |
|
565
|
|
|
if (!is_array($callback) || strpos($callback[1], 'session') === false) continue; |
|
566
|
|
|
call_user_func_array($callback, $data); |
|
567
|
|
|
} |
|
568
|
|
|
catch (\Exception $ex) { |
|
569
|
|
|
_egw_log_exception($ex); |
|
570
|
|
|
} |
|
571
|
|
|
unset(self::$shutdown_callbacks[$n]); |
|
572
|
|
|
} |
|
573
|
|
|
// now we can close the session |
|
574
|
|
|
// without closing the session fastcgi_finish_request() will NOT send output to user |
|
575
|
|
|
if (isset($GLOBALS['egw']->session) && is_object($GLOBALS['egw']->session)) $GLOBALS['egw']->session->commit_session(); |
|
576
|
|
|
|
|
577
|
|
|
// flush all output to user |
|
578
|
|
|
/* does NOT work on Apache :-( |
|
579
|
|
|
for($i = 0; ob_get_level() && $i < 10; ++$i) |
|
580
|
|
|
{ |
|
581
|
|
|
ob_end_flush(); |
|
582
|
|
|
} |
|
583
|
|
|
flush();*/ |
|
584
|
|
|
// working for fastCGI :-) |
|
585
|
|
|
if (function_exists('fastcgi_finish_request') && substr($_SERVER['PHP_SELF'], -32) != '/phpgwapi/cron/asyncservices.php') |
|
586
|
|
|
{ |
|
587
|
|
|
fastcgi_finish_request(); |
|
588
|
|
|
} |
|
589
|
|
|
|
|
590
|
|
|
// run all on_shutdown, do NOT stop on exceptions |
|
591
|
|
|
foreach(self::$shutdown_callbacks as $data) |
|
592
|
|
|
{ |
|
593
|
|
|
try { |
|
594
|
|
|
//error_log(__METHOD__."() running ".array2string($data)); |
|
595
|
|
|
$callback = array_shift($data); |
|
596
|
|
|
call_user_func_array($callback, $data); |
|
597
|
|
|
} |
|
598
|
|
|
catch (\Exception $ex) { |
|
599
|
|
|
_egw_log_exception($ex); |
|
600
|
|
|
} |
|
601
|
|
|
} |
|
602
|
|
|
// call the asyncservice check_run function if it is not explicitly set to cron-only |
|
603
|
|
|
if (!$GLOBALS['egw_info']['server']['asyncservice']) // is default |
|
604
|
|
|
{ |
|
605
|
|
|
$async = new Asyncservice(); |
|
606
|
|
|
$async->check_run('fallback'); |
|
607
|
|
|
} |
|
608
|
|
|
$this->db->disconnect(); |
|
|
|
|
|
|
609
|
|
|
} |
|
610
|
|
|
} |
|
611
|
|
|
} |
|
612
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.