Files
server/usr/share/psa-horde/lib/Api.php
2026-01-07 20:52:11 +01:00

795 lines
27 KiB
PHP

<?php
/**
* Copyright 2010-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL-2). If you
* did not receive this file, see http://www.horde.org/licenses/lgpl.
*
* @category Horde
* @copyright 2010-2017 Horde LLC
* @license http://www.horde.org/licenses/lgpl LGPL-2
* @package Horde
*/
/**
* Horde external API interface.
*
* This file defines Horde's external API interface. Other
* applications can interact with Horde through this API.
*
* @category Horde
* @copyright 2010-2017 Horde LLC
* @license http://www.horde.org/licenses/lgpl LGPL-2
* @package Horde
*/
class Horde_Api extends Horde_Registry_Api
{
/**
* Returns a list of adminstrative links.
*
* @return array Keys are link labels, values are array with these keys:
* - icon: (string) Graphic for page.
* - link: (string) Registry encoded link to page.
* - name: (string) Gettext label for page.
*/
public function admin_list()
{
$admin = array(
'configuration' => array(
'link' => '%application%/admin/config/',
'name' => _("_Configuration"),
'icon' => 'config'
),
'users' => array(
'link' => '%application%/admin/user.php',
'name' => _("_Users"),
'icon' => 'user'
),
'groups' => array(
'link' => '%application%/admin/groups.php',
'name' => _("_Groups"),
'icon' => 'group'
),
'perms' => array(
'link' => '%application%/admin/perms/',
'name' => _("_Permissions"),
'icon' => 'perms'
),
'locks' => array(
'link' => '%application%/admin/locks.php',
'name' => _("_Locks"),
'icon' => 'locked'
),
'alarms' => array(
'link' => '%application%/admin/alarms.php',
'name' => _("_Alarms"),
'icon' => 'alarm'
),
'sessions' => array(
'link' => '%application%/admin/sessions.php',
'name' => _("Sessions"),
'icon' => 'user'
),
'phpshell' => array(
'link' => '%application%/admin/phpshell.php',
'name' => _("P_HP Shell"),
'icon' => 'php'
),
'sqlshell' => array(
'link' => '%application%/admin/sqlshell.php',
'name' => _("S_QL Shell"),
'icon' => 'sql'
),
'cmdshell' => array(
'link' => '%application%/admin/cmdshell.php',
'name' => _("_CLI"),
'icon' => 'shell'
)
);
if (!empty($GLOBALS['conf']['activesync']['enabled'])) {
$admin['activesync'] = array(
'link' => '%application%/admin/activesync.php',
'name' => _("ActiveSync Devices"),
'icon' => 'mobile'
);
}
return $admin;
}
/**
* Returns a list of the installed and registered applications.
*
* @param array $filter An array of the statuses that should be returned.
* Defaults to non-hidden.
*
* @return array List of apps registered with Horde. If no applications
* are defined returns an empty array.
*/
public function listApps($filter = null)
{
return $GLOBALS['registry']->listApps($filter);
}
/**
* Returns all available registry APIs.
*
* @return array The API list.
*/
public function listAPIs()
{
return $GLOBALS['registry']->listAPIs();
}
/* Blocks. */
/**
* Returns a Horde_Block's title.
*
* @param string $app The block application name.
* @param string $name The block name (NOT the class name).
* @param array $params Block parameters.
*
* @return string The block title.
*/
public function blockTitle($app, $name, $params = array())
{
$class = $app . '_Block_' . basename($name);
try {
return $GLOBALS['injector']->getInstance('Horde_Core_Factory_BlockCollection')->create()->getBlock($app, $class, $params)->getTitle();
} catch (Horde_Exception $e) {
return $e->getMessage();
}
}
/**
* Returns a Horde_Block's content.
*
* @param string $app The block application name.
* @param string $name The block name (NOT the classname).
* @param array $params Block parameters.
*
* @return string The block content.
*/
public function blockContent($app, $name, $params = array())
{
$class = $app . '_Block_' . basename($name);
try {
return $GLOBALS['injector']->getInstance('Horde_Core_Factory_BlockCollection')->create()->getBlock($app, $class, $params)->getContent();
} catch (Horde_Exception $e) {
return $e->getMessage();
}
}
/**
* Returns a pretty printed list of all available blocks.
*
* @return array A hash with block IDs as keys and application plus block
* block names as values.
*/
public function blocks()
{
return $GLOBALS['injector']->getInstance('Horde_Core_Factory_BlockCollection')->create()->getBlocksList();
}
/* User data. */
/**
* Returns the value of the requested preference.
*
* @param string $app The application of the preference to retrieve.
* @param string $pref The name of the preference to retrieve.
*
* @return string The value of the preference, null if it doesn't exist.
*/
public function getPreference($app, $pref)
{
$pushed = $GLOBALS['registry']->pushApp($app);
$GLOBALS['registry']->loadPrefs($app);
$value = $GLOBALS['prefs']->getValue($pref);
if ($pushed) {
$GLOBALS['registry']->popApp();
}
return $value;
}
/**
* Sets a preference to the specified value, if the preference is allowed
* to be modified.
*
* @param string $app The application of the preference to modify.
* @param string $pref The name of the preference to modify.
* @param string $val The new value for this preference.
*/
public function setPreference($app, $pref, $value)
{
$pushed = $GLOBALS['registry']->pushApp($app);
$GLOBALS['registry']->loadPrefs($app);
$value = $GLOBALS['prefs']->setValue($pref, $value);
if ($pushed) {
$GLOBALS['registry']->popApp();
}
}
/**
* Removes user data.
*
* @param string $user Name of user to remove data for.
* @param string $app Remove data from this application. If boolean
* true, removes all applications. If boolean false,
* removes only base Horde data.
*
* @throws Horde_Exception
*/
public function removeUserData($user, $app = false)
{
if ($app === true) {
$app = null;
} elseif ($app === false || !strlen($app)) {
$app = false;
}
$GLOBALS['registry']->removeUserData($user, $app);
}
/* Groups. */
/**
* Adds a group to the groups system.
*
* @param string $name The group's name.
*
* @return mixed The group's ID.
* @throws Horde_Exception
*/
public function addGroup($name)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to add groups."));
}
return $GLOBALS['injector']
->getInstance('Horde_Group')
->create($name);
}
/**
* Removes a group from the groups system.
*
* @param mixed $group The group ID.
*
* @throws Horde_Exception
*/
public function removeGroup($group)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to delete groups."));
}
$GLOBALS['injector']->getInstance('Horde_Group')->remove($group);
}
/**
* Adds a user to a group.
*
* @param mixed $group The group ID.
* @param string $user The user to add.
*
* @throws Horde_Exception
*/
public function addUserToGroup($group, $user)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to change groups."));
}
$GLOBALS['injector']
->getInstance('Horde_Group')
->addUser($group, $user);
}
/**
* Removes a user from a group.
*
* @param mixed $group The group ID.
* @param string $user The user to add.
*
* @throws Horde_Exception
*/
public function removeUserFromGroup($group, $user)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to change groups."));
}
$GLOBALS['injector']
->getInstance('Horde_Group')
->removeUser($group, $user);
}
/**
* Returns a list of users that are part of this group (and only this
* group).
*
* @param mixed $group The group ID.
*
* @return array The user list.
* @throws Horde_Exception
*/
public function listUsersOfGroup($group)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to list users of groups."));
}
return $GLOBALS['injector']
->getInstance('Horde_Group')
->listUsers($group);
}
/* Shares. */
/**
* Adds a share to the shares system.
*
* @param string $scope The name of the share root, e.g. the
* application that the share belongs to.
* @param string $shareName The share's name.
* @param string $shareTitle The share's human readable title.
* @param string $userName The share's owner.
*
* @throws Horde_Exception
*/
public function addShare($scope, $shareName, $shareTitle, $userName)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to add shares."));
}
$shares = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Share')->create($scope);
$share = $shares->newShare($GLOBALS['registry']->getAuth(), $shareName, $shareTitle);
$share->set('owner', $userName);
$shares->addShare($share);
}
/**
* Removes a share from the shares system permanently.
*
* @param string $scope The name of the share root, e.g. the
* application that the share belongs to.
* @param string $shareName The share's name.
*
* @throws Horde_Exception
*/
public function removeShare($scope, $shareName)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to delete shares."));
}
$shares = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Share')->create($scope);
$share = $shares->getShare($shareName);
$shares->removeShare($share);
}
/**
* Returns an array of all shares that $userName is the owner of.
*
* @param string $scope The name of the share root, e.g. the
* application that the share belongs to.
* @param string $userName The share's owner.
*
* @return array The list of shares.
* @throws Horde_Exception
*/
public function listSharesOfOwner($scope, $userName)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to list shares."));
}
$shares = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Share')->create($scope);
$share_list = $shares->listShares($userName,
array('perm' => Horde_Perms::SHOW,
'attributes' => $userName));
$myshares = array();
foreach ($share_list as $share) {
$myshares[] = $share->getName();
}
return $myshares;
}
/**
* Gives a user certain privileges for a share.
*
* @param string $scope The name of the share root, e.g. the
* application that the share belongs to.
* @param string $shareName The share's name.
* @param string $userName The user's name.
* @param array $permissions A list of permissions (show, read, edit,
* delete).
*
* @throws Horde_Exception
*/
public function addUserPermissions($scope, $shareName, $userName,
$permissions)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to change shares."));
}
$share = $GLOBALS['injector']
->getInstance('Horde_Core_Factory_Share')
->create($scope)
->getShare($shareName);
$perm = $share->getPermission();
foreach ($permissions as $permission) {
$permission = Horde_String::upper($permission);
if (defined('Horde_Perms::' . $permission)) {
$perm->addUserPermission($userName, constant('Horde_Perms::' . $permission), false);
}
}
$share->setPermission($perm);
}
/**
* Gives a group certain privileges for a share.
*
* @param string $scope The name of the share root, e.g. the
* application that the share belongs to.
* @param string $shareName The share's name.
* @param mixed $groupId The group ID.
* @param array $permissions A list of permissions (show, read, edit,
* delete).
*
* @throws Horde_Exception
*/
public function addGroupPermissions($scope, $shareName, $groupId,
$permissions)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to change shares."));
}
$share = $GLOBALS['injector']
->getInstance('Horde_Core_Factory_Share')
->create($scope)
->getShare($shareName);
$perm = $share->getPermission();
foreach ($permissions as $permission) {
$permission = Horde_String::upper($permission);
if (defined('Horde_Perms::' . $permission)) {
$perm->addGroupPermission($groupId, constant('Horde_Perms::' . $permission), false);
}
}
$share->setPermission($perm);
}
/**
* Removes a user from a share.
*
* @param string $scope The name of the share root, e.g. the
* application that the share belongs to.
* @param string $shareName The share's name.
* @param string $userName The user's name.
*
* @throws Horde_Exception
*/
public function removeUserPermissions($scope, $shareName, $userName)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to change shares."));
}
$shares = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Share')->create($scope);
$share = $shares->getShare($shareName);
$share->removeUser($userName);
}
/**
* Removes a group from a share.
*
* @param string $scope The name of the share root, e.g. the
* application that the share belongs to.
* @param string $shareName The share's name.
* @param mixed $groupId The group ID.
*
* @throws Horde_Exception
*/
public function removeGroupPermissions($scope, $shareName, $groupId)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to change shares."));
}
$shares = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Share')->create($scope);
$share = $shares->getShare($shareName);
$share->removeGroup($groupId);
}
/**
* Returns an array of all user permissions on a share.
*
* @param string $scope The name of the share root, e.g. the
* application that the share belongs to.
* @param string $shareName The share's name.
* @param string $userName The user's name.
*
* @return array All user permissions for this share.
* @throws Horde_Exception
*/
public function listUserPermissions($scope, $shareName, $userName)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to list share permissions."));
}
$perm_map = array(Horde_Perms::SHOW => 'show',
Horde_Perms::READ => 'read',
Horde_Perms::EDIT => 'edit',
Horde_Perms::DELETE => 'delete');
$shares = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Share')->create($scope);
$share = $shares->getShare($shareName);
$perm = $share->getPermission();
$permissions = $perm->getUserPermissions();
if (empty($permissions[$userName])) {
return array();
}
$user_permissions = array();
foreach (array_keys(Horde_Perms::integerToArray($permissions[$userName])) as $permission) {
$user_permissions[] = $perm_map[$permission];
}
return $user_permissions;
}
/**
* Returns an array of all group permissions on a share.
*
* @param string $scope The name of the share root, e.g. the
* application that the share belongs to.
* @param string $shareName The share's name.
* @param string $groupName The group's name.
*
* @return array All group permissions for this share.
* @throws Horde_Exception
*/
public function listGroupPermissions($scope, $shareName, $groupName)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to list share permissions."));
}
$perm_map = array(Horde_Perms::SHOW => 'show',
Horde_Perms::READ => 'read',
Horde_Perms::EDIT => 'edit',
Horde_Perms::DELETE => 'delete');
$shares = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Share')->create($scope);
$share = $shares->getShare($shareName);
$perm = $share->getPermission();
$permissions = $perm->getGroupPermissions();
if (empty($permissions[$groupName])) {
return array();
}
$group_permissions = array();
foreach (array_keys(Horde_Perms::integerToArray($permissions[$groupName])) as $permission) {
$group_permissions[] = $perm_map[$permission];
}
return $group_permissions;
}
/**
* Returns a list of users which have have certain permissions on a share.
*
* @param string $scope The name of the share root, e.g. the
* application that the share belongs to.
* @param string $shareName The share's name.
* @param array $permissions A list of permissions (show, read, edit,
* delete).
*
* @return array List of users with the specified permissions.
* @throws Horde_Exception
*/
public function listUsersOfShare($scope, $shareName, $permissions)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to list users of shares."));
}
$shares = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Share')->create($scope);
$share = $shares->getShare($shareName);
$perm = 0;
foreach ($permissions as $permission) {
$permission = Horde_String::upper($permission);
if (defined('Horde_Perms::' . $permission)) {
$perm &= constant('Horde_Perms::' . $permission);
}
}
return $share->listUsers($perm);
}
/**
* Returns a list of groups which have have certain permissions on a
* share.
*
* @param string $scope The name of the share root, e.g. the
* application that the share belongs to.
* @param string $shareName The share's name.
* @param array $permissions A list of permissions (show, read, edit,
* delete).
*
* @return array List of groups with the specified permissions.
* @throws Horde_Exception
*/
public function listGroupsOfShare($scope, $shareName, $permissions)
{
if (!$GLOBALS['registry']->isAdmin()) {
throw new Horde_Exception(_("You are not allowed to list groups of shares."));
}
$shares = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Share')->create($scope);
$share = $shares->getShare($shareName);
$perm = 0;
foreach ($permissions as $permission) {
$permission = Horde_String::upper($permission);
if (defined('Horde_Perms::' . $permission)) {
$perm &= constant('Horde_Perms::' . $permission);
}
}
return $share->listGroups($perm);
}
/**
* Returns a list of ActiveSync devices that are partnered with Horde.
*
* @param array $filter An array of parameters to filter on:
* - user: Only return devices owned by user. If not present will default
* to returning devices for current user only. If present, but
* empty and current user is admin, will return all devices.
* Otherwise, will return devices matching the parameter (must be
* admin to list users other than current).
*
* @return array List of device properties.
* @since 5.2.0
*/
public function listActiveSyncDevices($filter = array())
{
global $registry, $injector, $conf;
if (empty($conf['activesync']['enabled'])) {
return array();
}
$state = $injector->getInstance('Horde_ActiveSyncState');
$state->setLogger($injector->getInstance('Horde_Log_Logger'));
if (!isset($filter['user'])) {
$filter['user'] = $registry->getAuth();
} elseif (empty($filter['user'])) {
if (!$registry->isAdmin()) {
throw new Horde_Exception_PermissionDenied();
}
$filter['user'] = null;
} elseif ($filter['user'] != $registry->getAuth() && !$registry->isAdmin()) {
throw new Horde_Exception_PermissionDenied();
}
try {
$devices = $state->listDevices($filter['user']);
} catch (Horde_ActiveSync_Exception $e) {
throw new Horde_Exception($e);
}
foreach ($devices as &$device) {
$device['device_properties'] = unserialize($device['device_properties']);
$device['last_synctime'] = $state->getLastSyncTimestamp($device['device_id']);
}
return $devices;
}
/**
* Perform an administrative action on a single paired ActiveSync device.
*
* @param string $action The action to perform. One of:
* WIPE, CANCEL_WIPE, REMOVE.
* @param string $deviceid The device's deviceid.
* @param string $user Restrict actions to only this user's
* account on the device in the case where the
* device may have multiple user accounts on this
* server. If empty, all users' state information
* will be removed. If a non-admin calls this
* method, this will always be set to the current
* horde username.
* @return boolean
* @throws Horde_Exception
*/
public function performActiveSyncDeviceAction($action, $deviceid, $user = null)
{
global $injector, $conf, $registry;
if (empty($conf['activesync']['enabled'])) {
throw new Horde_Exception(_("ActiveSync not activated."));
}
if (!in_array($action, array('WIPE', 'CANCEL_WIPE', 'REMOVE'))) {
throw new Horde_Exception(_("Unsupported action."));
}
$state = $injector->getInstance('Horde_ActiveSyncState');
$state->setLogger($injector->getInstance('Horde_Log_Logger'));
// If not an admin, ensure the device is attached to the $user.
// Otherwise, any user could wipe any device if the deviceid is known.
if (!$registry->isAdmin()) {
$user = $registry->getAuth();
if (!$state->deviceExists($deviceid, $user)) {
throw new Horde_Exception_PermissionDenied();
}
}
switch ($action) {
case 'WIPE':
try {
$state->setDeviceRWStatus($deviceid, Horde_ActiveSync::RWSTATUS_PENDING);
} catch (Horde_ActiveSync_Exception $e) {
throw new Horde_Exception($e);
}
return true;
case 'CANCEL_WIPE':
try {
$state->setDeviceRWStatus($deviceid, Horde_ActiveSync::RWSTATUS_OK);
} catch (Horde_ActiveSync_Exception $e) {
throw new Horde_Exception($e);
}
return true;
case 'REMOVE':
try {
$state->removeState(array(
'devId' => $deviceid,
'user' => $user)
);
} catch (Horde_ActiveSync_Exception $e) {
throw new Horde_Exception($e);
}
return true;
}
}
/**
* Perform an admistrative action on ALL paired ActiveSync devices.
*
* @param string $action The action. Currently, only 'RESET' is supported.
* - 'RESET': Causes all state for all devices to be removed. I.e., sets
* the synckey for all devices to 0.
*
* @return boolean
*/
public function performBulkActiveSyncDeviceAction($action)
{
global $injector, $conf, $registry;
if (!$registry->isAdmin()) {
throw new Horde_Exception_PermissionDenied();
}
if (empty($conf['activesync']['enabled'])) {
throw new Horde_Exception(_("ActiveSync not activated."));
}
if (!in_array($action, array('RESET'))) {
throw new Horde_Exception(_("Unsupported action."));
}
try {
$injector->getInstance('Horde_ActiveSyncState')->resetAllPolicyKeys();
} catch (Horde_ActiveSync_Exception $e) {
throw new Horde_Exception($e);
}
return true;
}
}