public function pushApp($app, array $options = array())
{
global $injector, $notification, $language, $session;
if ($app == $this->getApp()) {
return false;
}
/* Bail out if application is not present or inactive. */
if ($this->isInactive($app)) {
throw new Horde_Exception_PushApp(sprintf(Horde_Core_Translation::t("%s is not activated."), $this->applications[$app]['name']), self::NOT_ACTIVE, $app);
}
$checkPerms = (!isset($options['check_perms']) || !empty($options['check_perms'])) && $this->currentProcessAuth();
/* If permissions checking is requested, return an error if the
* current user does not have read perms to the application being
* loaded. We allow access:
* - To all admins.
* - To all authenticated users if no permission is set on $app.
* - To anyone who is allowed by an explicit ACL on $app. */
if ($checkPerms) {
$error = $error_log = null;
$error_app = $this->applications[$app]['name'];
$error_type = self::AUTH_FAILURE;
if (($auth = $this->getAuth()) && !$this->checkExistingAuth()) {
$error = '%s is not authorized %s(Remote host: %s)';
$error_app = '';
}
if (!$error && !$this->hasPermission($app, Horde_Perms::READ, array('notransparent' => !empty($options['notransparent'])))) {
$error = '%s is not authorized for %s (Host: %s).';
if ($this->isAuthenticated(array('app' => $app))) {
$error_log = '%s does not have READ permission for %s (Host: %s)';
$error_type = self::PERMISSION_DENIED;
}
}
if ($error) {
$auth = $auth ? 'User ' . $auth : 'Guest user';
$remote = $this->remoteHost();
if ($error_log) {
Horde::log(sprintf($error_log, $auth, $error_app, $remote->host), 'DEBUG');
}
throw new Horde_Exception_PushApp(sprintf($error, $auth, $error_app, $remote->host), $error_type, $app);
}
}
/* Push application on the stack. */
$this->_appStack[] = $app;
/* Chicken and egg problem: the language environment has to be loaded
* before loading the configuration file, because it might contain
* gettext strings. Though the preferences can specify a different
* language for this app, they have to be loaded after the
* configuration, because they rely on configuration settings. So try
* with the current language, and reset the language later. */
$this->setLanguageEnvironment($language, $app);
/* Load config and prefs. */
$this->importConfig('horde');
$this->importConfig($app);
$this->loadPrefs($app);
/* Reset language, since now we can grab language from prefs. */
if (!$checkPerms && count($this->_appStack) == 1) {
$this->setLanguageEnvironment(null, $app);
}
/* Run authenticated hooks, if necessary. */
$hooks = $injector->getInstance('Horde_Core_Hooks');
if ($session->get('horde', 'auth_app_init/' . $app)) {
try {
$error = self::INITCALLBACK_FATAL;
$this->callAppMethod($app, 'authenticated');
$error = self::HOOK_FATAL;
$hooks->callHook('appauthenticated', $app);
} catch (Exception $e) {
$this->_pushAppError($e, $error);
}
$session->remove('horde', 'auth_app_init/' . $app);
unset($this->_appsInit[$app]);
}
/* Initialize application. */
if (!isset($this->_appsInit[$app])) {
$notification->addAppHandler($app);
try {
$error = self::INITCALLBACK_FATAL;
$this->callAppMethod($app, 'init');
$error = self::HOOK_FATAL;
$hooks->callHook('pushapp', $app);
} catch (Exception $e) {
$this->_pushAppError($e, $error);
}
$this->_appsInit[$app] = true;
}
/* Do login tasks. */
if ($checkPerms && !empty($options['logintasks']) && ($tasks = $injector->getInstance('Horde_Core_Factory_LoginTasks')->create($app))) {
$tasks->runTasks();
}
return true;
}