* @package Share
*/
abstract class Horde_Share_Base
{
/**
* The application we're managing shares for.
*
* @var string
*/
protected $_app;
/**
* The root of the Share tree.
*
* @var mixed
*/
protected $_root = null;
/**
* A cache of all shares that have been retrieved, so we don't hit the
* backend again and again for them.
*
* @var array
*/
protected $_cache = array();
/**
* Id-name-map of already cached share objects.
*
* @var array
*/
protected $_shareMap = array();
/**
* Cache used for listShares().
*
* @var array
*/
protected $_listcache = array();
/**
* A list of objects that we're currently sorting, for reference during the
* sorting algorithm.
*
* @var array
*/
protected $_sortList;
/**
* The Horde_Share_Object subclass to instantiate objects as
*
* @var string
*/
protected $_shareObject;
/**
* The Horde_Perms object
*
* @var Horde_Perms_Base
*/
protected $_permsObject;
/**
* The current user
*
* @var string
*/
protected $_user;
/**
* The Horde_Group driver
*
* @var Horde_Group_Base
*/
protected $_groups;
/**
* A callback that is passed to the share objects for setting the objects'
* Horde_Share object.
*
* @var callback
*/
protected $_shareCallback;
/**
* Logger
*
* @var Horde_Log_Logger
*/
protected $_logger;
/**
* Configured callbacks. We currently support:
*
* add - Called immediately before a new share is added. Receives the
* share object as a parameter.
* modify - Called immediately before a share object's changes are saved
* to storage. Receives the share object as a parameter.
* remove - Called immediately before a share is removed from storage.
* Receives the share object as a parameter.
* list - Called immediately after a list of shares is received from
* storage. Passed the userid, share list, and any parameters
* passed to the listShare call. Should return the (possibly
* modified) share list. @see listShares() for more
* info.
*
*
* @var array
*/
protected $_callbacks;
/**
* Constructor.
*
* @param string $app The application that the shares belong
* to.
* @param string $user The current user.
* @param Horde_Perms_Base $perms The permissions object.
* @param Horde_Group_Base $groups The Horde_Group driver.
*
*/
public function __construct($app, $user, Horde_Perms_Base $perms,
Horde_Group_Base $groups)
{
$this->_app = $app;
$this->_user = $user;
$this->_permsObject = $perms;
$this->_groups = $groups;
$this->_logger = new Horde_Support_Stub();
}
/**
* Set a logger object.
*
* @inject
*
* @var Horde_Log_Logger $logger The logger object.
*/
public function setLogger(Horde_Log_Logger $logger)
{
$this->_logger = $logger;
}
/**
* (Re)connects the share object to this share driver.
*
* @param Horde_Share_Object $object
*/
public function initShareObject(Horde_Share_Object $object)
{
$object->setShareOb(empty($this->_shareCallback) ? $this : $this->_shareCallback);
}
public function setShareCallback($callback)
{
$this->_shareCallback = $callback;
}
/**
* Returns the application we're managing shares for.
*
* @return string The application this share belongs to.
*/
public function getApp()
{
return $this->_app;
}
/**
* Returns a Horde_Share_Object object corresponding to the given share
* name, with the details retrieved appropriately.
*
* @param string $name The name of the share to retrieve.
*
* @return Horde_Share_Object The requested share.
*/
public function getShare($name)
{
if (isset($this->_cache[$name])) {
return $this->_cache[$name];
}
$share = $this->_getShare($name);
$this->_shareMap[$share->getId()] = $name;
$this->_cache[$name] = $share;
return $share;
}
/**
* Returns a Horde_Share_Object object corresponding to the given
* share name, with the details retrieved appropriately.
*
* @param string $name The name of the share to retrieve.
*
* @return Horde_Share_Object The requested share.
* @throws Horde_Exception_NotFound
* @throws Horde_Share_Exception
*/
abstract protected function _getShare($name);
/**
* Returns a Horde_Share_Object object corresponding to the given unique
* ID, with the details retrieved appropriately.
*
* @param string $cid The id of the share to retrieve.
*
* @return Horde_Share_Object The requested share.
*/
public function getShareById($cid)
{
if (!isset($this->_shareMap[$cid])) {
$share = $this->_getShareById($cid);
$name = $share->getName();
$this->_cache[$name] = $share;
$this->_shareMap[$cid] = $name;
}
return $this->_cache[$this->_shareMap[$cid]];
}
/**
* Returns a Horde_Share_Object object corresponding to the given
* unique ID, with the details retrieved appropriately.
*
* @param integer $id The id of the share to retrieve.
*
* @return Horde_Share_Object_sql The requested share.
* @throws Horde_Share_Exception, Horde_Exception_NotFound
*/
abstract protected function _getShareById($id);
/**
* Returns an array of Horde_Share_Object objects corresponding to the
* given set of unique IDs, with the details retrieved appropriately.
*
* @param array $cids The array of ids to retrieve.
*
* @return array The requested shares.
*/
public function getShares(array $cids)
{
$all_shares = $missing_ids = array();
foreach ($cids as $cid) {
if (!isset($this->_shareMap[$cid])) {
$missing_ids[] = $cid;
}
}
if (count($missing_ids)) {
$shares = $this->_getShares($missing_ids);
foreach (array_keys($shares) as $key) {
$this->_cache[$key] = $shares[$key];
$this->_shareMap[$shares[$key]->getId()] = $key;
}
}
foreach ($cids as $cid) {
$all_shares[$this->_shareMap[$cid]] = $this->_cache[$this->_shareMap[$cid]];
}
return $all_shares;
}
/**
* Returns an array of Horde_Share_Object objects corresponding
* to the given set of unique IDs, with the details retrieved
* appropriately.
*
* @param array $ids The array of ids to retrieve.
*
* @return array The requested shares.
* @throws Horde_Share_Exception
*/
abstract protected function _getShares(array $ids);
/**
* Lists *all* shares for the current app/share, regardless of
* permissions.
*
* This is for admin functionality and scripting tools, and shouldn't be
* called from user-level code!
*
* @return array All shares for the current app/share.
*/
public function listAllShares()
{
$shares = $this->_listAllShares();
$this->_sortList = $shares;
uasort($shares, array($this, '_sortShares'));
$this->_sortList = null;
return $shares;
}
/**
* Lists *all* shares for the current app/share, regardless of permissions.
*
* @return array All shares for the current app/share.
* @throws Horde_Share_Exception
*/
abstract protected function _listAllShares();
/**
* Returns an array of all shares that $userid has access to.
*
* @param string $userid The userid of the user to check access for. An
* empty value for the userid will only return shares
* with guest access.
* @param array $params Additional parameters for the search.
*
* 'perm' Require this level of permissions. Horde_Perms constant.
* 'attributes' Restrict shares to these attributes. A hash or username.
* 'from' Offset. Start at this share
* 'count' Limit. Only return this many.
* 'sort_by' Sort by attribute.
* 'direction' Sort by direction.
*
*
* @return array The shares the user has access to.
*/
public function listShares($userid, array $params = array())
{
$params = array_merge(array('perm' => Horde_Perms::SHOW,
'attributes' => null,
'from' => 0,
'count' => 0,
'sort_by' => null,
'direction' => 0),
$params);
$shares = $this->_listShares($userid, $params);
if (!count($shares)) {
return $shares;
}
$shares = $this->getShares($shares);
if (is_null($params['sort_by'])) {
$this->_sortList = $shares;
uasort($shares, array($this, '_sortShares'));
$this->_sortList = null;
}
// Run the results through the callback, if configured.
if (!empty($this->_callbacks['list'])) {
return $this->runCallback('list', array($userid, $shares, $params));
}
return $shares;
}
/**
* Returns an array of all shares that $userid has access to.
*
* @param string $userid The userid of the user to check access for.
* @param array $params See listShares().
*
* @return array The shares the user has access to.
*/
abstract protected function _listShares($userid, array $params = array());
/**
* Returns an array of all system shares.
*
* @return array All system shares.
*/
public function listSystemShares()
{
return array();
}
/**
* Returns the number of shares that $userid has access to.
*
* @param string $userid The userid of the user to check access for.
* @param integer $perm The level of permissions required.
* @param mixed $attributes Restrict the shares counted to those
* matching $attributes. An array of
* attribute/values pairs or a share owner
* username.
*
* @return integer The number of shares
*/
public function countShares($userid, $perm = Horde_Perms::SHOW,
$attributes = null)
{
return count($this->_listShares($userid, array('perm' => $perm, 'attributes' => $attributes)));
}
/**
* Returns a new share object.
*
* @param string $owner The share owner name.
* @param string $share_name The share's name.
* @param string $name_attribute The name displayed to the user.
*
* @return Horde_Share_Object A new share object.
* @throws Horde_Share_Exception
*/
public function newShare($owner, $share_name = '', $name_attribute = '')
{
$share = $this->_newShare($share_name);
$share->set('owner', $owner);
$share->set('name', $name_attribute);
return $share;
}
/**
* Returns a new share object.
*
* @param string $name The share's name.
*
* @return Horde_Share_Object A new share object
* @throws InvalidArgumentException
*/
abstract protected function _newShare($name);
/**
* Adds a share to the shares system.
*
* The share must first be created with newShare(), and have any initial
* details added to it, before this function is called.
*
* @param Horde_Share_Object $share The new share object.
*
* @throws Horde_Share_Exception
*/
public function addShare(Horde_Share_Object $share)
{
// Run the results through the callback, if configured.
$this->runCallback('add', array($share));
$this->_addShare($share);
/* Store new share in the caches. */
$id = $share->getId();
$name = $share->getName();
$this->_cache[$name] = $share;
$this->_shareMap[$id] = $name;
/* Reset caches that depend on unknown criteria. */
$this->expireListCache();
}
/**
* Adds a share to the shares system.
*
* The share must first be created with
* Horde_Share_sql::_newShare(), and have any initial details added
* to it, before this function is called.
*
* @param Horde_Share_Object $share The new share object.
*/
abstract protected function _addShare(Horde_Share_Object $share);
/**
* Adds a share created from a hash.
*
* @since Horde_Share 2.2.0
*
* @param array $hash A hash like exported from
* Horde_Share_Object#toHash().
*
* @return Horde_Share_Object A new share object.
*/
public function fromHash(array $hash)
{
$share = $this->newShare($hash['owner'], $hash['name']);
if (isset($hash['attributes'])) {
foreach ($hash['attributes'] as $attribute => $value) {
$share->set($attribute, $value);
}
}
if (isset($hash['permissions'])) {
$permission = $share->getPermission();
$permission->setData($hash['permissions']);
$share->setPermission($permission, false);
}
$this->addShare($share);
return $share;
}
/**
* Renames a share in the shares system.
*
* @param Horde_Share_Object $share The share to rename.
* @param string $name The share's new name.
*
* @throws Horde_Share_Exception
*/
public function renameShare(Horde_Share_Object $share, $name)
{
/* Move share in the caches. */
unset($this->_cache[$share->getName()]);
$this->_cache[$name] = $share;
/* Reset caches that depend on unknown criteria. */
$this->expireListCache();
$this->_renameShare($share, $name);
}
/**
* Renames a share in the shares system.
*
* @param Horde_Share_Object $share The share to rename.
* @param string $name The share's new name.
*
* @throws Horde_Share_Exception
*/
abstract protected function _renameShare(Horde_Share_Object $share, $name);
/**
* Removes a share from the shares system permanently.
*
* @param Horde_Share_Object $share The share to remove.
*
* @throws Horde_Share_Exception
*/
public function removeShare(Horde_Share_Object $share)
{
// Run the results through the callback, if configured.
$this->runCallback('remove', array($share));
/* Remove share from the caches. */
$id = $share->getId();
unset($this->_shareMap[$id]);
unset($this->_cache[$share->getName()]);
/* Reset caches that depend on unknown criteria. */
$this->expireListCache();
$this->_removeShare($share);
}
/**
* Removes a share from the shares system permanently.
*
* @param Horde_Share_Object $share The share to remove.
*
* @throws Horde_Share_Exception
*/
abstract protected function _removeShare(Horde_Share_Object $share);
/**
* Checks if a share name exists in the system.
*
* @param string $share The share name to check.
*
* @return boolean True if the share exists.
*/
public function exists($share)
{
if (isset($this->_cache[$share])) {
return true;
}
return $this->_exists($share);
}
/**
* Check that a share id exists in the system.
*
* @param integer $id The share id
*
* @return boolean True if the share exists.
*/
public function idExists($id)
{
if (isset($this->_shareMap[$id])) {
return true;
}
return $this->_idExists($id);
}
/**
* Checks if a share exists in the system.
*
* @param string $share The share to check.
*
* @return boolean True if the share exists.
* @throws Horde_Share_Exception
*/
abstract protected function _exists($share);
/**
* Check that a share id exists in the system.
*
* @param integer $id The share id
*
* @return boolean True if the share exists.
*/
abstract protected function _idExists($id);
/**
* Finds out what rights the given user has to this object.
*
* @see Horde_Perms::getPermissions
*
* @param mixed $share The share that should be checked for the users
* permissions.
* @param string $user The user to check for.
*
* @return mixed A bitmask of permissions, a permission value, or an array
* of permission values the user has, depending on the
* permission type and whether the permission value is
* ambiguous. False if there is no such permsission.
*/
public function getPermissions($share, $user = null)
{
if (!($share instanceof Horde_Share_Object)) {
$share = $this->getShare($share);
}
return $this->_permsObject->getPermissions($share->getPermission(), $user);
}
/**
* Set the class type to use for creating share objects.
*
* @var string $classname The classname to use.
*/
public function setShareClass($classname)
{
$this->_shareObject = $classname;
}
/**
* Getter for Horde_Perms object
*
* @return Horde_Perms_Base
*/
public function getPermsObject()
{
return $this->_permsObject;
}
/**
* Convert TO the storage driver's charset. Individual share objects should
* implement this method if needed.
*
* @param array $data Data to be converted.
*/
public function toDriverCharset($data)
{
return $data;
}
/**
* Add a callback to the collection
*
* @param string $type
* @param array $callback
*/
public function addCallback($type, $callback)
{
$this->_callbacks[$type] = $callback;
}
/**
* Returns the share's list cache.
*
* @return array
*/
public function getListCache()
{
return $this->_listcache;
}
/**
* Set the list cache.
*
* @param array $cache
*/
public function setListCache($cache)
{
$this->_listcache = $cache;
}
/**
* Resets the internal caches.
*/
public function resetCache()
{
$this->_cache = $this->_shareMap = array();
$this->expireListCache();
}
/**
* Give public access to call the share callbacks. Needed to run the
* callbacks from the Horde_Share_Object objects.
*
* @param string $type The callback to run
* @param array $params The parameters to pass to the callback.
*
* @return mixed
*/
public function runCallback($type, $params)
{
if (!empty($this->_callbacks[$type])) {
return call_user_func_array($this->_callbacks[$type], $params);
}
}
/**
* Expire the current list cache. This would be needed anytime a share is
* either added, deleted, had a change in owner, parent, or perms.
*/
public function expireListCache()
{
$this->_listcache = array();
}
/**
* Utility function to be used with uasort() for sorting arrays of
* Horde_Share objects.
*
* Example:
*
* uasort($list, array('Horde_Share', '_sortShares'));
*
*/
protected function _sortShares($a, $b)
{
$aParts = explode(':', $a->getName());
$bParts = explode(':', $b->getName());
$min = min(count($aParts), count($bParts));
$idA = '';
$idB = '';
for ($i = 0; $i < $min; $i++) {
if ($idA) {
$idA .= ':';
$idB .= ':';
}
$idA .= $aParts[$i];
$idB .= $bParts[$i];
if ($idA != $idB) {
$curA = isset($this->_sortList[$idA]) ? $this->_sortList[$idA]->get('name') : '';
$curB = isset($this->_sortList[$idB]) ? $this->_sortList[$idB]->get('name') : '';
return strnatcasecmp($curA, $curB);
}
}
return count($aParts) > count($bParts);
}
}
Horde_Share-2.2.0/lib/Horde/Share/Exception.php 0000664 0001750 0001750 00000000154 13166706112 017325 0 ustar jan jan
* @author Gunnar Wrobel
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @link http://pear.horde.org/index.php?package=Share
*/
/**
* Horde_Share_Kolab:: provides the Kolab backend for the horde share driver.
*
* Copyright 2004-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
*
* @category Horde
* @package Share
* @author Stuart Binge
* @author Gunnar Wrobel
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @link http://pear.horde.org/index.php?package=Share
*/
class Horde_Share_Kolab extends Horde_Share_Base
{
const VERSION = 1;
/**
* The Kolab storage handler
*
* @var Horde_Kolab_Storage
*/
private $_storage;
/**
* The folder type in the storage backend.
*
* @var string
*/
private $_type;
/**
* A map of IDs to folder names.
*
* @var array
*/
private $_id_map = array();
/**
* Constructor.
*
* @param string $app The application that the shares belong
* to
* @param string $user The current user
* @param Horde_Perms_Base $perms The permissions object
* @param Horde_Group_Base $groups The Horde_Group driver.
*
*/
public function __construct($app, $user, Horde_Perms_Base $perms,
Horde_Group_Base $groups)
{
switch ($app) {
case 'mnemo':
case 'jonah':
$this->_type = 'note';
break;
case 'kronolith':
$this->_type = 'event';
break;
case 'turba':
$this->_type = 'contact';
break;
case 'nag':
$this->_type = 'task';
break;
default:
throw new Horde_Share_Exception(sprintf(Horde_Share_Translation::t("The Horde/Kolab integration engine does not support \"%s\""), $app));
}
parent::__construct($app, $user, $perms, $groups);
}
/**
* Set the Kolab storage backend.
*
* @param Horde_Kolab_Storage $storage The Kolab storage handler.
*
* @return NULL
*/
public function setStorage(Horde_Kolab_Storage $storage)
{
$this->_storage = $storage;
}
/**
* Return the Kolab storage backend associated with this driver.
*
* @return Horde_Kolab_Storage The Kolab storage driver.
*/
public function getStorage()
{
if ($this->_storage === null) {
throw new Horde_Share_Exception('The storage backend has not yet been set!');
}
return $this->_storage;
}
/**
* Return the Kolab storage folder list handler.
*
* @return Horde_Kolab_Storage_List The folder list handler.
*/
public function getList()
{
try {
return $this->getStorage()->getList();
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
}
/**
* Return the type of folder this share driver will access in the Kolab
* storage backend (depends on the application calling the share driver).
*
* @return string
*/
public function getType()
{
return $this->_type;
}
/**
* Encode a share ID.
*
* @todo: In Horde3 share IDs were not properly escaped everywhere and it
* made sense to escape them here just in case they are placed in a
* URL. Needs checking in Horde4.
*
* @param string $id The ID to be encoded.
*
* @return string The encoded ID.
*/
private function _idEncode($id)
{
try {
$folder = $this->getStorage()->getFolder($id);
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
return $this->constructId($folder->getOwner(), $folder->getSubpath(), $folder->getPrefix());
}
/**
* Construct the ID from the owner name and the folder subpath.
*
* @param string $owner The share owner.
* @param string $name The name of the folder without the namespace prefix.
* @param string $prefix The namespace prefix.
*
* @return string The encoded ID.
*/
public function constructId($owner, $name, $prefix = null)
{
return Horde_Url::uriB64Encode(serialize(array($owner, $name, $prefix)));
}
/**
* Construct the Kolab storage folder name based on the share name and owner
* attributes.
*
* @param string $owner The owner of the share.
* @param string $subpath The folder subpath.
* @param string $prefix The namespace prefix.
*
* @return string The folder name for the Kolab backend.
*/
public function constructFolderName($owner, $subpath, $prefix = null)
{
try {
return $this->getList()
->getNamespace()
->constructFolderName($owner, $subpath, $prefix);
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
}
/**
* Retrieve namespace information for a folder name.
*
* @param string $folder The folder name.
*
* @return array A list of namespace prefix, the delimiter and the folder
* subpath.
*/
public function getFolderNameElements($folder)
{
try {
$ns = $this->getList()->getNamespace()->matchNamespace($folder);
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
return array(
$ns->getName(), $ns->getDelimiter(), $ns->getSubpath($folder)
);
}
/**
* Decode a share ID.
*
* @param string $id The ID to be decoded.
*
* @return string The decoded ID.
*/
private function _idDecode($id)
{
if (!isset($this->_id_map[$id])) {
$result = $this->_idDeconstruct($id);
$this->_id_map[$id] = $this->constructFolderName(
$result[0],
$result[1],
isset($result[2]) ? $result[2] : null
);
}
return $this->_id_map[$id];
}
/**
* Deconstruct the ID elements from the ID string
*
* @param string $id The ID to be deconstructed.
*
* @return array A tuple of (owner, folder subpath).
*/
private function _idDeconstruct($id)
{
if (!$decoded_id = Horde_Url::uriB64Decode($id)) {
$msg = sprintf('Share id %s is invalid.', $id);
$this->_logger->err($msg);
throw new Horde_Exception_NotFound($msg);
}
if (!$sid = @unserialize($decoded_id)) {
$msg = sprintf('Share id %s is invalid.', $decoded_id);
$this->_logger->err($msg);
throw new Horde_Exception_NotFound($msg);
}
return $sid;
}
/**
* Returns a Horde_Share_Object_Kolab object corresponding to the given
* share name, with the details retrieved appropriately.
*
* @param string $id The id of the share to retrieve.
* @param array $data The share data.
*
* @return Horde_Share_Object The requested share.
*/
private function _createObject($id, array $data = array())
{
$object = new Horde_Share_Object_Kolab($id, $this->_groups, $data);
$this->initShareObject($object);
return $object;
}
/**
* Returns a Horde_Share_Object_Kolab object corresponding to the given
* share name, with the details retrieved appropriately.
*
* @param string $name The name of the share to retrieve.
*
* @return Horde_Share_Object The requested share.
* @throws Horde_Exception_NotFound
* @throws Horde_Share_Exception
*/
protected function _getShare($name)
{
try {
$list = $this->getList()
->getQuery()
->dataByType($this->_type);
$query = $this->getList()
->getQuery(Horde_Kolab_Storage_List_Tools::QUERY_SHARE);
foreach ($list as $folder => $folder_data) {
$data = $query->getParameters($folder);
if (isset($data['share_name']) && $data['share_name'] == $name) {
return $this->getShareById(
$this->constructId(
$folder_data['owner'],
$folder_data['subpath'],
isset($folder_data['prefix']) ? $folder_data['prefix'] : null
)
);
}
}
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
throw new Horde_Exception_NotFound(sprintf('Share name %s not found', $name));
}
/**
* Returns a Horde_Share_Object_sql object corresponding to the given
* unique ID, with the details retrieved appropriately.
*
* @param integer $id The id of the share to retrieve.
*
* @return Horde_Share_Object_sql The requested share.
* @throws Horde_Share_Exception, Horde_Exception_NotFound
*/
protected function _getShareById($id)
{
try {
$list = $this->getList()
->getQuery()
->dataByType($this->_type);
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
if (!isset($list[$this->_idDecode($id)])) {
throw new Horde_Exception_NotFound(sprintf('Share id %s not found', $id));
}
try {
$query = $this->getList()
->getQuery(Horde_Kolab_Storage_List_Tools::QUERY_SHARE);
$data = array_merge(
$query->getParameters($this->_idDecode($id)),
$list[$this->_idDecode($id)]
);
$data['desc'] = $query->getDescription($this->_idDecode($id));
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
if (isset($data['parent'])) {
try {
$data['parent'] = $this->_idEncode($data['parent']);
} catch (Horde_Kolab_Storage_Exception $e) {
unset($data['parent']);
}
}
return $this->_createObject($id, $data);
}
/**
* Returns an array of Horde_Share_Object_kolab objects corresponding to
* the requested folders.
*
* @param string $ids The ids of the shares to fetch.
*
* @return array An array of Horde_Share_Object_kolab objects.
*/
protected function _getShares(array $ids)
{
$objects = array();
foreach ($ids as $id) {
$share = $this->_getShareById($id);
$objects[$share->getName()] = $share;
}
return $objects;
}
/**
* Checks if a share exists in the system.
*
* @param string $share The share to check.
*
* @return boolean True if the share exists.
* @throws Horde_Share_Exception
*/
protected function _exists($share)
{
try {
$this->getShare($share);
return true;
} catch (Horde_Exception_NotFound $e) {
return false;
}
}
/**
* Check that a share id exists in the system.
*
* @param integer $id The share id
*
* @return boolean True if the share exists.
*/
protected function _idExists($id)
{
try {
return in_array(
$this->_idDecode($id),
$this->getList()->getQuery()->listByType($this->_type)
);
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
}
/**
* Returns an array of all shares that $userid has access to.
*
* @param string $userid The userid of the user to check access for.
* @param array $params See listShares().
*
* @return array The shares the user has access to.
*/
protected function _listShares($userid, array $params = array())
{
try {
$stamp = $this->getList()->getQuery()->getStamp();
$key = md5(serialize(array($userid, $params, $stamp)));
if (isset($this->_listcache[$key])) {
return $this->_listcache[$key];
}
$shares = array_map(
array($this, '_idEncode'),
$this->getList()->getQuery()->listByType($this->_type)
);
$remove = array();
if ($params['perm'] != Horde_Perms::SHOW || empty($userid)) {
foreach ($shares as $share) {
$object = $this->_getShareById($share);
if (!$object->hasPermission($userid, $params['perm'], $object->get('owner'))) {
$remove[] = $share;
}
}
}
if (isset($params['parent'])) {
foreach ($shares as $share) {
$object = $this->getShareById($share);
if ($params['parent'] instanceof Horde_Share_Object) {
$parent = $params['parent'];
} else {
$parent = $this->getShare($params['parent']);
}
if (!$object->getParent() || $object->getParent()->getId() != $parent->getId()) {
$remove[] = $share;
}
}
}
if (isset($params['all_levels']) && empty($params['all_levels'])) {
foreach ($shares as $share) {
$object = $this->getShareById($share);
$parent = $object->get('parent');
if (!empty($parent) && in_array($parent, $shares)) {
$remove[] = $share;
}
}
}
if (isset($params['attributes'])) {
if (!is_array($params['attributes'])) {
$attributes = array('owner' => $params['attributes']);
} else {
$attributes = $params['attributes'];
}
foreach ($shares as $share) {
$object = $this->getShareById($share);
foreach ($attributes as $key => $value) {
if ($object->get($key) != $value) {
$remove[] = $share;
}
}
}
}
if (!empty($remove)) {
$shares = array_diff($shares, $remove);
}
if (isset($params['sort_by'])) {
if ($params['sort_by'] == 'id') {
sort($shares);
} else {
$sorted = array();
foreach ($shares as $share) {
$object = $this->getShareById($share);
$sorted[$object->getId()] = $object->get($params['sort_by']);
}
asort($sorted);
$shares = array_keys($sorted);
}
}
if (!empty($params['direction'])) {
$shares = array_reverse($shares);
}
if (isset($params['from']) && !empty($params['from'])) {
$shares = array_slice($shares, $params['from']);
}
if (isset($params['count']) && !empty($params['count'])) {
$shares = array_slice($shares, 0, $params['count']);
}
$this->_listcache[$key] = $shares;
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
return $this->_listcache[$key];
}
/**
* Returns the count of all shares that $userid has access to.
*
* @param string $userid The userid of the user to check access for.
* @param integer $perm The level of permissions required.
* @param mixed $attributes Restrict the shares counted to those
* matching $attributes. An array of
* attribute/values pairs or a share owner
* username.
* @param mixed $parent The share to start searching from
* (Horde_Share_Object, share_id, or null)
* @param boolean $allLevels Return all levels, or just the direct
* children of $parent?
*
* @return integer Number of shares the user has access to.
* @throws Horde_Share_Exception
*/
public function countShares($userid, $perm = Horde_Perms::SHOW,
$attributes = null, $parent = null, $allLevels = true)
{
return count(
$this->listShares(
$userid,
array(
'perm' => $perm,
'attributes' => $attributes,
'parent' => $parent,
'all_levels' => $allLevels
)
)
);
}
/**
* Returns an array of all system shares.
*
* @return array All system shares.
*/
public function listSystemShares()
{
try {
$shares = array_map(
array($this, '_idEncode'),
$this->getList()->getQuery()->listByType($this->_type)
);
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
$result = array();
foreach ($shares as $share) {
$object = $this->_getShareById($share);
//@todo: Remove "null" check as this is only required for BC
if ($object->get('owner') === false ||
$object->get('owner') === null) {
$result[$object->getName()] = $object;
}
}
return $result;
}
/**
* Lists *all* shares for the current app/share, regardless of
* permissions.
*
* For the Kolab backend this cannot work in the same way as for the SQL
* based backend. Permissions are always handled by the backend
* automatically (IMAP ACLs) and cannot be disabled.
*
* listAllShares() is apparently used during command line scipts where it
* represents administrator access. This is possible on Kolab by using the
* "manager" user. In that case a standard listShares() authenticated as
* "manager" should be sufficient.
*
* @return array All shares for the current app/share.
*/
protected function _listAllShares()
{
try {
$shares = array_map(
array($this, '_idEncode'),
$this->getList()->getQuery()->listByType($this->_type)
);
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
$result = array();
foreach ($shares as $share) {
$object = $this->_getShareById($share);
$result[$object->getName()] = $object;
}
return $result;
}
/**
* Returns a new share object.
*
* @param string $name The share's name.
*
* @return Horde_Share_Object_kolab A new share object.
*/
protected function _newShare($name)
{
return $this->_createObject(
null,
array(
'type' => $this->_type,
'share_name' => $name
)
);
}
/**
* Adds a share to the shares system.
*
* The share must first be created with Horde_Share::newShare(),
* and have any initial details added to it, before this function is
* called.
*
* @param Horde_Share_Object $share The new share object.
*/
protected function _addShare(Horde_Share_Object $share)
{
$share->save();
}
/**
* Removes a share from the shares system permanently.
*
* @param Horde_Share_Object $share The share to remove.
*/
protected function _removeShare(Horde_Share_Object $share)
{
try {
$this->getList()
->getListManipulation()
->deleteFolder($this->_idDecode($share->getId()));
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
}
/**
* Renames a share in the shares system.
*
* @param Horde_Share_Object $share The share to rename.
* @param string $name The share's new name.
*
* @throws Horde_Share_Exception
*/
protected function _renameShare(Horde_Share_Object $share, $name)
{
$share->set('share_name', $name);
}
/**
* Retrieve the Kolab specific access rights for a share.
*
* @param string $id The share ID.
*
* @return An array of rights.
*/
public function getAcl($id)
{
try {
return $this->getList()
->getQuery(Horde_Kolab_Storage_List_Tools::QUERY_ACL)
->getAcl($this->_idDecode($id));
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
}
/**
* Set the Kolab specific access rights for a share.
*
* @param string $id The share ID.
* @param string $user The user to set the ACL for.
* @param string $acl The ACL.
*
* @return NULL
*/
public function setAcl($id, $user, $acl)
{
try {
$this->getList()
->getQuery(Horde_Kolab_Storage_List_Tools::QUERY_ACL)
->setAcl($this->_idDecode($id), $user, $acl);
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
}
/**
* Delete Kolab specific access rights for a share.
*
* @param string $id The share ID.
* @param string $user The user to delete the ACL for
*
* @return NULL
*/
public function deleteAcl($id, $user)
{
try {
$this->getList()
->getQuery(Horde_Kolab_Storage_List_Tools::QUERY_ACL)
->deleteAcl($this->_idDecode($id), $user);
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
}
/**
* Save share data to the storage backend.
*
* @param string $id The share id.
* @param string $old_id The old share id.
* @param array $data The share data.
*
* @return NULL
*/
public function save($id, $old_id, $data)
{
try {
if ($old_id === null) {
$this->getList()->getListManipulation()->createFolder(
$this->_idDecode($id), $this->_type
);
} elseif ($id != $old_id) {
$this->getList()->getListManipulation()->renameFolder(
$this->_idDecode($old_id), $this->_idDecode($id), $this->_type
);
}
if (!empty($data['default'])) {
$this->getList()->getQuery()->setDefault($this->_idDecode($id));
}
$query = $this->getList()
->getQuery(Horde_Kolab_Storage_List_Tools::QUERY_SHARE);
if (isset($data['desc']) && strlen($data['desc'])) {
$query->setDescription($this->_idDecode($id), $data['desc']);
}
unset(
$data['desc'],
$data['owner'],
$data['name'],
$data['default'],
$data['parent'],
$data['type'],
$data['delimiter'],
$data['prefix'],
$data['subpath'],
$data['folder'],
$data['namespace']
);
$query->setParameters($this->_idDecode($id), $data);
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Horde_Share_Exception($e);
}
}
}
Horde_Share-2.2.0/lib/Horde/Share/Object.php 0000664 0001750 0001750 00000024051 13166706112 016577 0 ustar jan jan
* @author Jan Schneider
* @author Gunnar Wrobel
* @package Share
*/
abstract class Horde_Share_Object implements Serializable
{
/**
* A function to be called when a Horde_Share object is needed and not
* available.
*
* @var callback
*/
protected $_shareCallback;
/**
* The Horde_Share object which this share is associated with.
* If this is empty, the $_shareCallback is called to obtain it.
*
* @var Horde_Share
*/
protected $_shareOb;
/**
* Associates a Share object with this share, or provides a callback that
* knows how to provide it.
*
* @param mixed Horde_Share | Callback $shareOb The Share object.
*/
public function setShareOb($shareOb)
{
if ($shareOb instanceof Horde_Share_Base) {
$this->_shareOb = $shareOb;
} else {
$this->_shareCallback = $shareOb;
}
}
/**
* Obtain this object's share driver.
*
* @return Horde_Share The share driver.
*/
public function getShareOb()
{
if (empty($this->_shareOb)) {
$this->_shareOb = call_user_func($this->_shareCallback);
}
if (empty($this->_shareOb)) {
throw new Horde_Share_Exception('Unable to obtain a Horde_Share object');
}
return $this->_shareOb;
}
/**
* Sets an attribute value in this object.
*
* @param string $attribute The attribute to set.
* @param mixed $value The value for $attribute.
* @param boolean $update Immediately update only this change.
*
* @return boolean
*/
abstract public function set($attribute, $value, $update = false);
/**
* Returns an attribute value from this object.
*
* @param string $attribute The attribute to return.
*
* @return mixed The value for $attribute.
*/
abstract public function get($attribute);
/**
* Returns the ID of this share.
*
* @return string The share's ID.
*/
abstract public function getId();
/**
* Returns the name of this share.
*
* @return string The share's name.
*/
abstract public function getName();
/**
* Saves the current attribute values.
*
* @return boolean
* @throws Horde_Exception
*/
public function save()
{
$this->getShareOb()->runCallback('modify', array($this));
$this->getShareOb()->expireListCache();
return $this->_save();
}
/**
* Saves the current attribute values.
*/
abstract protected function _save();
/**
* Exports the share object as a PHP hash.
*
* @since Horde_Shares 2.2.0
*
* @return array Hash representation of this share.
*/
public function toHash()
{
return array(
'id' => $this->getId(),
'name' => $this->getName(),
'attributes' => $this->_getAttributes(),
'permissions' => $this->getPermission()->getData(),
);
}
/**
* Returns the share attributes.
*
* @return array All share attributes as a hash.
*/
abstract protected function _getAttributes();
/**
* Gives a user a certain privilege for this share.
*
* @param string $userid The userid of the user.
* @param integer $permission A Horde_Perms::* constant.
*/
public function addUserPermission($userid, $permission)
{
$perm = $this->getPermission();
$perm->addUserPermission($userid, $permission, false);
$this->setPermission($perm);
}
/**
* Removes a certain privilege for a user from this share.
*
* @param string $userid The userid of the user.
* @param integer $permission A Horde_Perms::* constant.
*/
public function removeUserPermission($userid, $permission)
{
$perm = $this->getPermission();
$perm->removeUserPermission($userid, $permission, false);
$this->setPermission($perm);
}
/**
* Gives a group certain privileges for this share.
*
* @param string $group The group to add permissions for.
* @param integer $permission A Horde_Perms::* constant.
*/
public function addGroupPermission($group, $permission)
{
$perm = $this->getPermission();
$perm->addGroupPermission($group, $permission, false);
$this->setPermission($perm);
}
/**
* Removes a certain privilege from a group.
*
* @param string $group The group to remove permissions from.
* @param constant $permission A Horde_Perms::* constant.
*/
public function removeGroupPermission($group, $permission)
{
$perm = $this->getPermission();
$perm->removeGroupPermission($group, $permission, false);
$this->setPermission($perm);
}
/**
* Removes a user from this share.
*
* @param string $userid The userid of the user to remove.
*/
public function removeUser($userid)
{
/* Remove all $userid's permissions. */
$perm = $this->getPermission();
$perm->removeUserPermission($userid, null, false);
$this->setPermission($perm);
}
/**
* Removes a group from this share.
*
* @param integer $groupId The group to remove.
*/
public function removeGroup($groupId)
{
/* Remove all $groupId's permissions. */
$perm = $this->getPermission();
$perm->removeGroupPermission($groupId, null, false);
return $this->setPermission($perm);
}
/**
* Returns an array containing all the userids of the users with access to
* this share.
*
* @param integer $perm_level List only users with this permission level.
* Defaults to all users.
*
* @return array The users with access to this share.
*/
public function listUsers($perm_level = null)
{
$perm = $this->getPermission();
$results = array_keys($perm->getUserPermissions($perm_level));
// Always return the share's owner.
$owner = $this->get('owner');
if ($owner && !in_array($owner, $results)) {
$results[] = $owner;
}
return $results;
}
/**
* Returns an array containing all the groupids of the groups with access
* to this share.
*
* @param integer $perm_level List only users with this permission level.
* Defaults to all users.
*
* @return array The IDs of the groups with access to this share.
*/
public function listGroups($perm_level = null)
{
$perm = $this->getPermission();
return array_keys($perm->getGroupPermissions($perm_level));
}
/**
* Gives guests a certain privilege for this share.
*
* @param integer $permission A Horde_Perms::* constant.
*/
public function addGuestPermission($permission)
{
$perm = $this->getPermission();
$perm->addGuestPermission($permission, false);
$this->setPermission($perm);
}
/**
* Removes a certain privilege for guests from this share.
*
* @param integer $permission A Horde_Perms::* constant.
*/
public function removeGuestPermission($permission)
{
$perm = $this->getPermission();
$perm->removeGuestPermission($permission, false);
$this->setPermission($perm);
}
/**
* Gives creators a certain privilege for this share.
*
* @param integer $permission A Horde_Perms::* constant.
*/
public function addCreatorPermission($permission)
{
$perm = $this->getPermission();
$perm->addCreatorPermission($permission, false);
$this->setPermission($perm);
}
/**
* Removes a certain privilege for creators from this share.
*
* @param integer $permission A Horde_Perms::* constant.
*/
public function removeCreatorPermission($permission)
{
$perm = $this->getPermission();
$perm->removeCreatorPermission($permission, false);
$this->setPermission($perm);
}
/**
* Gives all authenticated users a certain privilege for this share.
*
* @param integer $permission A Horde_Perms::* constant.
*/
public function addDefaultPermission($permission)
{
$perm = $this->getPermission();
$perm->addDefaultPermission($permission, false);
$this->setPermission($perm);
}
/**
* Removes a certain privilege for all authenticated users from this share.
*
* @param integer $permission A Horde_Perms::* constant.
*/
public function removeDefaultPermission($permission)
{
$perm = $this->getPermission();
$perm->removeDefaultPermission($permission, false);
$this->setPermission($perm);
}
/**
* Checks to see if a user has a given permission.
*
* @param string $userid The userid of the user.
* @param integer $permission A Horde_Perms::* constant to test for.
* @param string $creator The creator of the event.
*
* @return boolean Whether or not $userid has $permission.
*/
abstract public function hasPermission($userid, $permission,
$creator = null);
/**
* Sets the permission of this share.
*
* @param Horde_Perms_Permission $perm Permission object.
* @param boolean $update Should the share be saved
* after this operation?
*/
abstract public function setPermission($perm, $update = true);
/**
* Returns the permission of this share.
*
* @return Horde_Perms_Permission Permission object that represents the
* permissions on this share.
*/
abstract public function getPermission();
}
Horde_Share-2.2.0/lib/Horde/Share/Sql.php 0000664 0001750 0001750 00000104774 13166706112 016143 0 ustar jan jan
* @author Michael J. Rubinsky
* @package Share
*/
/**
* @package Share
*/
class Horde_Share_Sql extends Horde_Share_Base
{
/* Share has user perms */
const SQL_FLAG_USERS = 1;
/* Share has group perms */
const SQL_FLAG_GROUPS = 2;
/* Serializable version */
const VERSION = 1;
/**
* Handle for the current database connection.
*
* @var Horde_Db_Adapter
*/
protected $_db;
/**
* Main share table for the current scope.
*
* @var string
*/
protected $_table;
/**
* The Horde_Share_Object subclass to instantiate objects as
*
* @var string
*/
protected $_shareObject = 'Horde_Share_Object_Sql';
/**
* Local cache of text/clob fields
*
* @var array
*/
protected $_clobFields;
/**
* Local cache of non-text/clob fields
*
* @var array
*/
protected $_nonClobFields;
/**
*
* @see Horde_Share_Base::__construct()
*/
public function __construct($app, $user, Horde_Perms_Base $perms,
Horde_Group_Base $groups)
{
parent::__construct($app, $user, $perms, $groups);
$this->_table = $this->_app . '_shares';
}
/**
* Set the SQL table name to use for the current scope's share storage.
*
* @var string $table The table name
*/
public function setTable($table)
{
$this->_table = $table;
}
/**
* Get storage table
*
* @return string
*/
public function getTable()
{
return $this->_table;
}
public function setStorage(Horde_Db_Adapter $db)
{
$this->_db = $db;
}
/**
*
* @return Horde_Db_Adapter
*/
public function getStorage()
{
return $this->_db;
}
/**
* Return a list of fields in the table that ARE text/clob fields.
*
* @return array An array of clob field names.
*/
protected function _getClobFields()
{
if (!isset($this->_clobFields)) {
$this->_clobFields = array();
$columns = $this->_db->columns($this->_table);
foreach ($columns as $column) {
if ($column->getType() == 'text') {
$this->_clobFields[] = $column->getName();
}
}
}
return $this->_clobFields;
}
/**
* Return a list of fields in the table that are NOT text/clob fields.
*
* @return array An array of non-clob field names.
*/
protected function _getNonClobFields()
{
if (!isset($this->_nonClobFields)) {
$this->_nonClobFields = array();
$columns = $this->_db->columns($this->_table);
foreach ($columns as $column) {
if ($column->getType() != 'text') {
$this->_nonClobFields[] = $column->getName();
}
}
}
return $this->_nonClobFields;
}
/**
* Return a DISTINCT clause containing all non-clob field names.
*
* @return string The DISTINCT clause.
*/
protected function _getDistinctClause()
{
$clause = 'DISTINCT ';
$fields = array_map(function($f) { return 's.' . $f; }, $this->_getNonClobFields());
return 'DISTINCT ' . implode(', ', $fields);
}
/**
* Finds out if the share has user set
*
* @param boolean
*/
protected function _hasUsers($share)
{
return $share['share_flags'] & self::SQL_FLAG_USERS;
}
/**
* Finds out if the share has user set
*/
protected function _hasGroups($share)
{
return $share['share_flags'] & self::SQL_FLAG_GROUPS;
}
/**
* Get users permissions
*
* @param array $share Share data array
*
* @throws Horde_Share_Exception
*/
protected function _getShareUsers(&$share)
{
if (!$this->_hasUsers($share)) {
return;
}
try {
$rows = $this->_db->select('SELECT * FROM ' . $this->_table . '_users WHERE share_id = ?', array($share['share_id']));
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
foreach ($rows as $row) {
$share['perm']['users'][$row['user_uid']] = $this->_buildPermsFromRow($row);
}
}
/**
* Get groups permissions
*
* @param array $share Share data array
*
* @throws Horde_Share_Exception
*/
protected function _getShareGroups(&$share)
{
if (!$this->_hasGroups($share)) {
return;
}
try {
$rows = $this->_db->select('SELECT * FROM ' . $this->_table . '_groups WHERE share_id = ?', array($share['share_id']));
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
foreach ($rows as $row) {
$share['perm']['groups'][$row['group_uid']] = $this->_buildPermsFromRow($row);
}
}
/**
* Returns a Horde_Share_Object_sql object corresponding to the given
* share name, with the details retrieved appropriately.
*
* @param string $name The name of the share to retrieve.
*
* @return Horde_Share_Object The requested share.
* @throws Horde_Exception_NotFound
* @throws Horde_Share_Exception
*/
protected function _getShare($name)
{
try {
$results = $this->_db->selectOne('SELECT * FROM ' . $this->_table . ' WHERE share_name = ?', array($name));
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
if (!$results) {
throw new Horde_Exception_NotFound(sprintf('Share name %s not found', $name));
}
$this->_convertClobs($results);
$data = $this->_fromDriverCharset($results);
$this->_loadPermissions($data);
return $this->_createObject($data);
}
protected function _createObject(array $data = array())
{
$object = new $this->_shareObject($data);
$this->initShareObject($object);
return $object;
}
/**
* Convert clob data to string.
*
* @param array &$data An array of share data.
*/
protected function _convertClobs(&$data)
{
$columns = $this->_db->columns($this->_table);
foreach ($data as $row => &$value) {
if (in_array($row, $this->_getClobFields())) {
$value = $columns[$row]->binaryToString($value);
}
}
}
/**
* Helper function to load the permissions data into the share data
*
* @param array $data Array of share attributes
*/
protected function _loadPermissions(&$data)
{
$this->_getShareUsers($data);
$this->_getShareGroups($data);
$this->_getSharePerms($data);
}
protected function _getSharePerms(&$data)
{
$data['perm']['type'] = 'matrix';
$data['perm']['default'] = isset($data['perm_default']) ? (int)$data['perm_default'] : 0;
$data['perm']['guest'] = isset($data['perm_guest']) ? (int)$data['perm_guest'] : 0;
$data['perm']['creator'] = isset($data['perm_creator']) ? (int)$data['perm_creator'] : 0;
unset($data['perm_creator'], $data['perm_guest'], $data['perm_default']);
}
/**
* Returns a Horde_Share_Object_sql object corresponding to the given
* unique ID, with the details retrieved appropriately.
*
* @param integer $id The id of the share to retrieve.
*
* @return Horde_Share_Object_sql The requested share.
* @throws Horde_Share_Exception, Horde_Exception_NotFound
*/
protected function _getShareById($id)
{
try {
$results = $this->_db->selectOne('SELECT * FROM ' . $this->_table . ' WHERE share_id = ?', array($id));
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
if (!$results) {
throw new Horde_Exception_NotFound(sprintf('Share id %s not found', $id));
}
$this->_convertClobs($results);
$data = $this->_fromDriverCharset($results);
$this->_loadPermissions($data);
return $this->_createObject($data);
}
/**
* Returns an array of Horde_Share_Object objects corresponding
* to the given set of unique IDs, with the details retrieved
* appropriately.
*
* @param array $ids The array of ids to retrieve.
* @param string $key The column name that should for the list keys.
*
* @return array The requested shares.
* @throws Horde_Share_Exception
*/
protected function _getShares(array $ids)
{
try {
$rows = $this->_db->select('SELECT * FROM ' . $this->_table . ' WHERE share_id IN (' . str_repeat('?, ', count($ids) - 1) . '?)', $ids);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
$sharelist = array();
foreach ($rows as $share) {
$this->_loadPermissions($share);
$this->_convertClobs($share);
$sharelist[$share['share_name']] = $this->_createObject($share);
}
return $sharelist;
}
/**
* Lists *all* shares for the current app/share, regardless of permissions.
*
* This is for admin functionality and scripting tools, and shouldn't be
* called from user-level code!
*
* @return array All shares for the current app/share.
* @throws Horde_Share_Exception
*/
public function listAllShares()
{
return $this->_listAllShares();
}
/**
* Lists *all* shares for the current app/share, regardless of permissions.
*
* @return array All shares for the current app/share.
* @throws Horde_Share_Exception
*/
protected function _listAllShares()
{
$shares = array();
try {
$rows = $this->_db->select('SELECT * FROM ' . $this->_table . ' ORDER BY share_name ASC');
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
foreach ($rows as $share) {
$this->_convertClobs($share);
$shares[(int)$share['share_id']] = $this->_fromDriverCharset($share);
}
// Get users permissions
try {
$rows = $this->_db->select('SELECT * FROM ' . $this->_table . '_users');
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
foreach ($rows as $row) {
if (isset($shares[$row['share_id']])) {
$shares[$row['share_id']]['perm']['users'][$row['user_uid']] = $this->_buildPermsFromRow($row);
}
}
// Get groups permissions
try {
$rows = $this->_db->select('SELECT * FROM ' . $this->_table . '_groups');
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
foreach ($rows as $row) {
if (isset($shares[$row['share_id']])) {
$shares[$row['share_id']]['perm']['groups'][$row['group_uid']] = $this->_buildPermsFromRow($row);
}
}
$sharelist = array();
foreach ($shares as $data) {
$this->_getSharePerms($data);
$sharelist[$data['share_name']] = $this->_createObject($data);
}
return $sharelist;
}
/**
* Returns an array of all shares that $userid has access to.
*
* @param string $userid The userid of the user to check access for. An
* empty value for the userid will only return shares
* with guest access.
* @param array $params Additional parameters for the search.
*
* 'perm' Require this level of permissions. Horde_Perms constant.
* 'attribtues' Restrict shares to these attributes. A hash or username.
* 'from' Offset. Start at this share
* 'count' Limit. Only return this many.
* 'sort_by' Sort by attribute.
* 'direction' Sort by direction.
* 'parent' Start at this share in the hierarchy. Either share_id or
* Horde_Share_Object
* 'all_levels' List all levels or just the direct children of parent?
*
*
* @return array The shares the user has access to.
* @throws Horde_Share_Exception
*/
public function listShares($userid, array $params = array())
{
$params = array_merge(array('perm' => Horde_Perms::SHOW,
'attributes' => null,
'from' => 0,
'count' => 0,
'sort_by' => null,
'direction' => 0,
'parent' => null,
'all_levels' => true),
$params);
$key = md5(serialize(array($userid, $params)));
if (isset($this->_listcache[$key])) {
return $this->_listcache[$key];
}
$shares = array();
if (is_null($params['sort_by'])) {
$sortfield = 's.share_id';
} elseif ($params['sort_by'] == 'owner' || $params['sort_by'] == 'id') {
$sortfield = 's.share_' . $params['sort_by'];
} else {
$sortfield = 's.attribute_' . $params['sort_by'];
}
$query = 'SELECT ' . $this->_getDistinctClause() . ' '
. $this->getShareCriteria($userid, $params['perm'], $params['attributes'], $params['parent'], $params['all_levels'])
. ' ORDER BY ' . $sortfield
. (($params['direction'] == 0) ? ' ASC' : ' DESC');
$query = $this->_db->addLimitOffset($query, array('limit' => $params['count'], 'offset' => $params['from']));
try {
$rows = $this->_db->select($query);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
$users = array();
$groups = array();
foreach ($rows as $share) {
$shares[(int)$share['share_id']] = $this->_fromDriverCharset($share);
if ($this->_hasUsers($share)) {
$users[] = (int)$share['share_id'];
}
if ($this->_hasGroups($share)) {
$groups[] = (int)$share['share_id'];
}
}
$this->_fetchClobFields($shares);
// Get users permissions
if (!empty($users)) {
$query = 'SELECT share_id, user_uid, perm FROM ' . $this->_table
. '_users WHERE share_id IN (' . str_repeat('?,', count($users) - 1) . '?)';
try {
$rows = $this->_db->select($query, $users);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
foreach ($rows as $share) {
$shares[$share['share_id']]['perm']['users'][$share['user_uid']] = (int)$share['perm'];
}
}
// Get groups permissions
if (!empty($groups)) {
$query = 'SELECT share_id, group_uid, perm FROM ' . $this->_table
. '_groups WHERE share_id IN (' . str_repeat('?,', count($groups) - 1) . '?)';
try {
$rows = $this->_db->select($query, $groups);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
foreach ($rows as $share) {
$shares[$share['share_id']]['perm']['groups'][$share['group_uid']] = (int)$share['perm'];
}
}
$sharelist = array();
foreach ($shares as $id => $data) {
$this->_getSharePerms($data);
$sharelist[$data['share_name']] = $this->_createObject($data);
}
unset($shares);
// Run the results through the callback, if configured.
if (!empty($this->_callbacks['list'])) {
$sharelist = $this->runCallback('list', array($userid, $sharelist, $params));
}
$this->_listcache[$key] = $sharelist;
return $sharelist;
}
/**
* Fetch data for all clob fields of each share passed in $shares.
*
* @param array &$shares List of share data to populate with clob data.
*/
protected function _fetchClobFields(&$shares)
{
$clobs = $this->_getClobFields();
if (!empty($clobs) && !empty($shares)) {
$ids = array_map(function($ar) { return $ar['share_id']; }, $shares);
$query = 'SELECT share_id, ' . implode(', ', $clobs) . ' FROM '
. $this->_table . ' WHERE share_id IN ('
. str_repeat('?,', count($ids) - 1) . '?)';
try {
$rows = $this->_db->select($query, $ids);
foreach ($rows as $share_properties) {
$this->_convertClobs($share_properties);
foreach ($share_properties as $name => $property) {
$shares[$share_properties['share_id']][$name] = $property;
}
}
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
}
}
/**
* Return a list of users who have shares with the given permissions
* for the current user.
*
* @param integer $perm The level of permissions required.
* @param mixed $parent The parent share to start looking in.
* (Horde_Share_Object, share_id, or null)
* @param boolean $allLevels Return all levels, or just the direct
* children of $parent? Defaults to all levels.
* @param integer $from The user to start listing at.
* @param integer $count The number of users to return.
*
* @return array List of users.
* @throws Horde_Share_Exception
*/
public function listOwners($perm = Horde_Perms::SHOW, $parent = null, $allLevels = true,
$from = 0, $count = 0)
{
$sql = 'SELECT DISTINCT(s.share_owner) '
. $this->getShareCriteria($this->_user, $perm, null, $parent, $allLevels);
if ($count) {
$sql = $this->_db->addLimitOffset($sql, array('limit' => $count, 'offset' => $from));
}
try {
$allowners = $this->_db->selectValues($sql);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
$owners = array();
foreach ($allowners as $owner) {
if ($this->countShares($this->_user, $perm, $owner, $parent, $allLevels)) {
$owners[] = $owner;
}
}
return $owners;
}
/**
* Count the number of users who have shares with the given permissions
* for the current user.
*
* @param integer $perm The level of permissions required.
* @param mixed $parent The parent share to start looking in.
* (Horde_Share_Object, share_id, or null).
* @param boolean $allLevels Return all levels, or just the direct
* children of $parent?
*
* @return integer Number of users.
* @throws Horde_Share_Exception
*/
public function countOwners($perm = Horde_Perms::SHOW, $parent = null, $allLevels = true)
{
$sql = 'SELECT COUNT(DISTINCT(s.share_owner)) '
. $this->getShareCriteria($this->_user, $perm, null, $parent, $allLevels);
try {
$results = $this->_db->selectValue($sql);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
return $results;
}
/**
* Returns a share's direct parent object.
*
* @param Horde_Share_Object $child The share to get parent for.
*
* @return Horde_Share_Object The parent share, if it exists.
*/
public function getParent(Horde_Share_Object $child)
{
$parents = $child->get('parents');
// No parents, this is at the root.
if (empty($parents)) {
return null;
}
$parents = explode(':', $parents);
return $this->getShareById(array_pop($parents));
}
/**
* Returns an array of all shares that $userid has access to.
*
* @param string $userid The userid of the user to check access for.
* @param array $params See listShares().
*
* @return array The shares the user has access to.
*/
protected function _listShares($userid, array $params = array())
{
// We overwrite listShares(), this method is only implemented because
// it's abstract in the base class.
}
/**
* Returns an array of all system shares.
*
* @return array All system shares.
* @throws Horde_Share_Exception
*/
public function listSystemShares()
{
$query = 'SELECT * FROM ' . $this->_table . ' WHERE share_owner IS NULL';
try {
$rows = $this->_db->select($query);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
$sharelist = array();
foreach ($rows as $share) {
$this->_convertClobs($share);
$data = $this->_fromDriverCharset($share);
$this->_getSharePerms($data);
$sharelist[$data['share_name']] = $this->_createObject($data);
}
return $sharelist;
}
/**
* Returns the count of all shares that $userid has access to.
*
* @param string $userid The userid of the user to check access for.
* @param integer $perm The level of permissions required.
* @param mixed $attributes Restrict the shares counted to those
* matching $attributes. An array of
* attribute/values pairs or a share owner
* username.
* @param mixed $parent The share to start searching from
* (Horde_Share_Object, share_id, or null)
* @param boolean $allLevels Return all levels, or just the direct
* children of $parent?
*
* @return integer Number of shares the user has access to.
* @throws Horde_Share_Exception
*/
public function countShares($userid, $perm = Horde_Perms::SHOW,
$attributes = null, $parent = null, $allLevels = true)
{
$query = 'SELECT COUNT(DISTINCT s.share_id) '
. $this->getShareCriteria($userid, $perm, $attributes, $parent, $allLevels);
try {
$this->_db->selectValue($query);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
return $this->_db->selectValue($query);
}
/**
* Returns a new share object.
*
* @param string $name The share's name.
*
* @return Horde_Share_Object A new share object
* @throws InvalidArgumentException
*/
protected function _newShare($name)
{
if (empty($name)) {
throw new InvalidArgumentException('Share names must be non-empty');
}
return $this->_createObject(array('share_name' => $name));
}
/**
* Adds a share to the shares system.
*
* The share must first be created with
* Horde_Share_sql::_newShare(), and have any initial details added
* to it, before this function is called.
*
* @param Horde_Share_Object $share The new share object.
*/
protected function _addShare(Horde_Share_Object $share)
{
$share->save();
}
/**
* Removes a share from the shares system permanently.
*
* @param Horde_Share_Object $share The share to remove.
*
* @throws Horde_Share_Exception
*/
public function removeShare(Horde_Share_Object $share)
{
// First Remove Children
foreach ($share->getChildren(null, null, true) as $child) {
$this->removeShare($child);
}
// Run the results through the callback, if configured.
$this->runCallback('remove', array($share));
/* Remove share from the caches. */
$id = $share->getId();
unset($this->_shareMap[$id]);
unset($this->_cache[$share->getName()]);
/* Reset caches that depend on unknown criteria. */
$this->expireListCache();
$this->_removeShare($share);
}
/**
* Removes a share from the shares system permanently.
*
* @param Horde_Share_Object $share The share to remove.
*
* @return boolean
* @throws Horde_Share_Exception
*/
protected function _removeShare(Horde_Share_Object $share)
{
$params = array($share->getId());
$tables = array($this->_table,
$this->_table . '_users',
$this->_table . '_groups');
foreach ($tables as $table) {
try {
$this->_db->delete('DELETE FROM ' . $table . ' WHERE share_id = ?', $params);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
}
}
/**
* Renames a share in the shares system.
*
* @param Horde_Share_Object $share The share to rename.
* @param string $name The share's new name.
*
* @throws Horde_Share_Exception
*/
protected function _renameShare(Horde_Share_Object $share, $name)
{
try {
$this->_db->update(
'UPDATE ' . $this->_table . ' SET share_name = ? WHERE share_id = ?',
array($name, $share->getId()));
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
}
/**
* Checks if a share exists in the system.
*
* @param string $share The share to check.
*
* @return boolean True if the share exists.
* @throws Horde_Share_Exception
*/
protected function _exists($share)
{
try {
return (boolean)$this->_db->selectOne('SELECT 1 FROM ' . $this->_table . ' WHERE share_name = ?', array($share));
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
}
/**
* Check that a share id exists in the system.
*
* @param integer $id The share id
*
* @return boolean True if the share exists.
*/
protected function _idExists($id)
{
try {
return (boolean)$this->_db->selectOne('SELECT 1 FROM ' . $this->_table . ' WHERE share_id = ?', array($id));
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
}
/**
* Returns an array of criteria for querying shares.
*
* @TODO Make this method protected, like all the other drivers.
*
* @param string $userid The userid of the user to check access for.
* @param integer $perm The level of permissions required. Set to null
* to skip permission filtering.
* @param mixed $attributes Restrict the shares returned to those who
* have these attribute values.
* @param mixed $parent The share to start searching in.
* (A Horde_Share_Object, share_id or null)
* @param boolean $allLevels Return all levels, or just the direct
* children of $parent? Defaults to all levels.
*
* @return string The criteria string for fetching this user's shares.
* @throws Horde_Share_Exception
*/
public function getShareCriteria($userid, $perm = Horde_Perms::SHOW,
$attributes = null, $parent = null,
$allLevels = true)
{
$query = $where = '';
if (!is_null($perm)) {
list($query, $where) = $this->_getUserAndGroupCriteria($userid, $perm);
}
$query = ' FROM ' . $this->_table . ' s ' . $query;
/* Convert to driver's keys */
$attributes = $this->_toDriverKeys($attributes);
/* ...and to driver charset */
$attributes = $this->toDriverCharset($attributes);
if (is_array($attributes)) {
// Build attribute/key filter.
if (!empty($where)) {
$where = ' (' . $where . ') ';
}
foreach ($attributes as $key => $value) {
if (is_array($value)) {
$value = array_map(array($this->_db, 'quote'), $value);
$where .= ' AND ' . $key . ' IN (' . implode(', ', $value) . ')';
} else {
$where .= ' AND ' . $key . ' = ' . $this->_db->quote($value);
}
}
} elseif (!empty($attributes)) {
// Restrict to shares owned by the user specified
$where = (!empty($where) ? ' (' . $where . ') AND ' : ' ') . 's.share_owner = ' . $this->_db->quote($attributes);
}
// See if we need to filter by parent or get the parent object
if ($parent != null) {
if (!($parent instanceof Horde_Share_Object)) {
$parent = $this->getShareById($parent);
}
// Need to append the parent's share id to the list of parents in
// order to search the share_parents field.
$parents = $parent->get('parents') . ':' . $parent->getId();
if ($allLevels) {
$where_parent = '(share_parents = ' . $this->_db->quote($parents)
. ' OR share_parents LIKE ' . $this->_db->quote($parents . ':%') . ')';
} else {
$where_parent = 's.share_parents = ' . $this->_db->quote($parents);
}
} elseif (!$allLevels) {
// No parents, and we only want the root.
$where_parent = "(s.share_parents = '' OR s.share_parents IS NULL)";
}
if (!empty($where_parent)) {
if (empty($where)) {
$where = $where_parent;
} else {
$where = '(' . $where . ') AND ' . $where_parent;
}
}
return $query . ' WHERE ' . $where;
}
/**
* Returns criteria statement fragments for querying shares.
*
* @param string $userid The userid of the user to check access for.
* @param integer $perm The level of permissions required.
*
* @return array An array with query and where string fragments.
*/
protected function _getUserAndGroupCriteria($userid,
$perm = Horde_Perms::SHOW)
{
$query = $where = '';
if (empty($userid)) {
$where = '(' . $this->_db->buildClause('s.perm_guest', '&', $perm) . ' > 0)';
} else {
// (owner == $userid)
$where .= 's.share_owner = ' . $this->_db->quote($userid);
// (name == perm_creator and val & $perm)
$where .= ' OR (' . $this->_db->buildClause('s.perm_creator', '&', $perm) . ' > 0)';
// (name == perm_creator and val & $perm)
$where .= ' OR (' . $this->_db->buildClause('s.perm_default', '&', $perm) . ' > 0)';
// (name == perm_users and key == $userid and val & $perm)
$query .= ' LEFT JOIN ' . $this->_table . '_users u ON u.share_id = s.share_id';
$where .= ' OR ( u.user_uid = ' . $this->_db->quote($userid)
. ' AND (' . $this->_db->buildClause('u.perm', '&', $perm) . ' > 0))';
// If the user has any group memberships, check for those also.
try {
$groups = $this->_groups->listGroups($userid);
if ($groups) {
// (name == perm_groups and key in ($groups) and val & $perm)
$ids = array_keys($groups);
$group_ids = array();
foreach ($ids as $id) {
$group_ids[] = $this->_db->quote((string)$id);
}
$query .= ' LEFT JOIN ' . $this->_table . '_groups g ON g.share_id = s.share_id';
$where .= ' OR (g.group_uid IN (' . implode(',', $group_ids)
. ') AND (' . $this->_db->buildClause('g.perm', '&', $perm) . ' > 0))';
}
} catch (Horde_Group_Exception $e) {
$this->_logger->err($e);
}
}
return array($query, $where);
}
/**
* Builds a permission bit mask from the "perm" column.
*
* @param array $row A data row including permission columns.
*
* @return integer A permission mask.
*/
protected function _buildPermsFromRow($row)
{
return (int)$row['perm'];
}
/**
* Utility function to convert from the SQL server's charset.
*/
protected function _fromDriverCharset($data)
{
foreach ($data as $key => &$value) {
if (substr($key, 0, 9) == 'attribute') {
$value = Horde_String::convertCharset(
$value, $this->_db->getOption('charset'), 'UTF-8');
}
}
return $data;
}
/**
* Utility function to convert TO the SQL server's charset.
*
* @see Horde_Share#toDriverCharset
*/
public function toDriverCharset($data)
{
if (!is_array($data)) {
return $data;
}
foreach ($data as $key => &$value) {
if (substr($key, 0, 9) == 'attribute') {
$value = Horde_String::convertCharset(
$value, 'UTF-8', $this->_db->getOption('charset'));
}
}
return $data;
}
/**
* Convert an array keyed on client keys to an array keyed on the driver
* keys.
*
* @param array $data The client code keyed array.
*
* @return array The driver keyed array.
*/
protected function _toDriverKeys($data)
{
if (!is_array($data)) {
return $data;
}
$driver_keys = array();
foreach ($data as $key => $value) {
if ($key == 'owner') {
$driver_keys['share_owner'] = $value;
} else {
$driver_keys['attribute_' . $key] = $value;
}
}
return $driver_keys;
}
}
Horde_Share-2.2.0/lib/Horde/Share/Sqlng.php 0000664 0001750 0001750 00000043560 13166706112 016463 0 ustar jan jan
* @package Share
*/
/**
* @package Share
*/
class Horde_Share_Sqlng extends Horde_Share_Sql
{
/* Serializable version */
const VERSION = 1;
/**
* The Horde_Share_Object subclass to instantiate objects as
*
* @var string
*/
protected $_shareObject = 'Horde_Share_Object_Sqlng';
/**
* A list of available permission.
*
* This is necessary to unset certain permission when updating existing
* share objects.
*
* @param array
*/
protected $_availablePermissions = array();
/**
*
* @see Horde_Share_Base::__construct()
*/
public function __construct($app, $user, Horde_Perms_Base $perms,
Horde_Group_Base $groups)
{
parent::__construct($app, $user, $perms, $groups);
$this->_table = $this->_app . '_sharesng';
}
/**
* Passes the available permissions to the share object.
*
* @param Horde_Share_Object $object
*/
public function initShareObject(Horde_Share_Object $object)
{
parent::initShareObject($object);
$object->availablePermissions = array_keys($this->_availablePermissions);
}
/**
* Returns an array of all shares that $userid has access to.
*
* @param string $userid The userid of the user to check access for.
* @param array $params Additional parameters for the search.
*
* 'perm' Require this level of permissions. Horde_Perms constant.
* 'attributes' Restrict shares to these attributes. A hash or username.
* 'from' Offset. Start at this share
* 'count' Limit. Only return this many.
* 'sort_by' Sort by attribute.
* 'direction' Sort by direction.
* 'parent' Start at this share in the hierarchy. Either share_id or
* Horde_Share_Object
* 'all_levels' List all levels or just the direct children of parent?
*
*
* @return array The shares the user has access to.
* @throws Horde_Share_Exception
*/
public function listShares($userid, array $params = array())
{
$params = array_merge(array('perm' => Horde_Perms::SHOW,
'attributes' => null,
'from' => 0,
'count' => 0,
'sort_by' => null,
'direction' => 0,
'parent' => null,
'all_levels' => true),
$params);
$key = md5(serialize(array($userid, $params)));
if (isset($this->_listcache[$key])) {
return $this->_listcache[$key];
}
$perms = $this->convertBitmaskToArray($params['perm']);
$shareids = null;
if (!empty($userid)) {
list($users, $groups, $shareids) = $this->_getUserAndGroupShares($userid, $perms);
}
if (is_null($params['sort_by'])) {
$sortfield = 'share_id';
} elseif ($params['sort_by'] == 'owner' || $params['sort_by'] == 'id') {
$sortfield = 'share_' . $params['sort_by'];
} else {
$sortfield = 'attribute_' . $params['sort_by'];
}
$where = $this->_getShareCriteria($userid, $perms, $params['attributes'], $shareids, $params['parent'], $params['all_levels']);
$query = 'SELECT ' . $this->_getDistinctClause() . ' FROM ' . $this->_table . ' s ' .
(!empty($where) ? ' WHERE ' . $where : '')
. ' ORDER BY ' . $sortfield
. (($params['direction'] == 0) ? ' ASC' : ' DESC');
$query = $this->_db->addLimitOffset($query, array('limit' => $params['count'], 'offset' => $params['from']));
try {
$rows = $this->_db->select($query);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
$sharelist = array();
$shares = array();
foreach ($rows as $share) {
$shares[(int)$share['share_id']] = $this->_fromDriverCharset($share);
}
$this->_fetchClobFields($shares);
foreach ($shares as $share) {
$this->_loadPermissions($share);
$sharelist[$share['share_name']] = $this->_createObject($share);
}
unset($shares);
// Run the results through the callback, if configured.
if (!empty($this->_callbacks['list'])) {
$sharelist = $this->runCallback('list', array($userid, $sharelist, $params));
}
$this->_listcache[$key] = $sharelist;
return $this->_listcache[$key];
}
/**
* Returns an array of all system shares.
*
* @return array All system shares.
* @throws Horde_Share_Exception
*/
public function listSystemShares()
{
$query = 'SELECT * FROM ' . $this->_table . ' WHERE share_owner IS NULL';
try {
$rows = $this->_db->select($query);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e->getMessage());
}
$sharelist = array();
foreach ($rows as $share) {
$this->_convertClobs($share);
$data = $this->_fromDriverCharset($share);
$this->_loadPermissions($data);
$sharelist[$data['share_name']] = $this->_createObject($data);
}
return $sharelist;
}
/**
* Returns the count of all shares that $userid has access to.
*
* @param string $userid The userid of the user to check access for.
* @param integer $perm The level of permissions required.
* @param mixed $attributes Restrict the shares counted to those
* matching $attributes. An array of
* attribute/values pairs or a share owner
* username.
* @param mixed $parent The share to start searching from
* (Horde_Share_Object, share_id, or null)
* @param boolean $allLevels Return all levels, or just the direct
* children of $parent?
*
* @return integer Number of shares the user has access to.
* @throws Horde_Share_Exception
*/
public function countShares($userid, $perm = Horde_Perms::SHOW,
$attributes = null, $parent = null, $allLevels = true)
{
$perms = $this->convertBitmaskToArray($perm);
$shareids = null;
if (!empty($userid)) {
list(, , $shareids) = $this->_getUserAndGroupShares($userid, $perms);
}
$query = 'SELECT COUNT(DISTINCT share_id) FROM '
. $this->_table . ' s WHERE '
. $this->_getShareCriteria($userid, $perms, $attributes, $shareids, $parent, $allLevels);
try {
return $this->_db->selectValue($query);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
}
/**
* Count the number of users who have shares with the given permissions
* for the current user.
*
* @param integer $perm The level of permissions required.
* @param mixed $parent The parent share to start looking in.
* (Horde_Share_Object, share_id, or null).
* @param boolean $allLevels Return all levels, or just the direct
* children of $parent?
*
* @return integer Number of users.
* @throws Horde_Share_Exception
*/
public function countOwners($perm = Horde_Perms::SHOW, $parent = null, $allLevels = true)
{
$perms = self::convertBitmaskToArray($perm);
$sql = 'SELECT COUNT(DISTINCT(s.share_owner)) FROM ' . $this->_table . ' s WHERE '
. $this->_getShareCriteria($this->_user, $perms, null, $parent, $allLevels);
try {
$results = $this->_db->selectValue($sql);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
return $results;
}
/**
* Return a list of users who have shares with the given permissions
* for the current user.
*
* @param integer $perm The level of permissions required.
* @param mixed $parent The parent share to start looking in.
* (Horde_Share_Object, share_id, or null)
* @param boolean $allLevels Return all levels, or just the direct
* children of $parent? Defaults to all levels.
* @param integer $from The user to start listing at.
* @param integer $count The number of users to return.
*
* @return array List of users.
* @throws Horde_Share_Exception
*/
public function listOwners($perm = Horde_Perms::SHOW, $parent = null, $allLevels = true,
$from = 0, $count = 0)
{
$perms = self::convertBitmaskToArray($perm);
$sql = 'SELECT DISTINCT(s.share_owner) FROM ' . $this->_table . ' s WHERE '
. $this->_getShareCriteria($this->_user, $perms, null, $parent, $allLevels);
if ($count) {
$sql = $this->_db->addLimitOffset($sql, array('limit' => $count, 'offset' => $from));
}
try {
$allowners = $this->_db->selectValues($sql);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e);
}
$owners = array();
foreach ($allowners as $owner) {
if ($this->countShares($this->_user, $perm, $owner, $parent, $allLevels)) {
$owners[] = $owner;
}
}
return $owners;
}
/**
* Converts a bit mask number to a bit mask array.
*
* @param integer A bit mask.
*
* @return array The bit mask as an array.
*/
public static function convertBitmaskToArray($perm)
{
$perms = array();
for ($bit = 1; $perm; $bit *= 2, $perm >>= 1) {
if ($perm % 2) {
$perms[] = $bit;
}
}
return $perms;
}
/**
* Builds a permission bit mask from all columns in a data row prefixed
* with "perm_".
*
* @param array $row A data row including permission columns.
*
* @return integer A permission mask.
*/
protected function _buildPermsFromRow($row)
{
$perms = 0;
foreach ($row as $column => $value) {
if (substr($column, 0, 5) != 'perm_') {
continue;
}
$perm = (int)substr($column, 5);
$this->_availablePermissions[$perm] = true;
if ($value) {
$perms |= $perm;
}
}
return $perms;
}
/**
* Converts the permissions from the database table format into the
* Horde_Share format.
*
* @param array $data The share object data to convert.
*/
protected function _getSharePerms(&$data)
{
$data['perm']['type'] = 'matrix';
$data['perm']['default'] = $data['perm']['guest'] = $data['perm']['creator'] = 0;
foreach ($data as $column => $value) {
$perm = explode('_', $column, 3);
if ($perm[0] != 'perm' || count($perm) != 3) {
continue;
}
$permvalue = (int)$perm[2];
$this->_availablePermissions[$permvalue] = true;
if ($value) {
$data['perm'][$perm[1]] |= $permvalue;
}
unset($data[$column]);
}
}
/**
* Returns the records and share IDs from the user and group tables that
* match the search criteria.
*
* @param string $userid The userid of the user to check access for.
* @param array $perms The level of permissions required.
*
* @return array A set of user, groups, and shareids.
*/
protected function _getUserAndGroupShares($userid, array $perms)
{
$shareids = array();
// Get users permissions.
$query = 'SELECT * FROM ' . $this->_table
. '_users WHERE user_uid = ' . $this->_db->quote($userid)
. ' AND (' . $this->_getPermsCriteria('perm', $perms) . ')';
try {
$users = $this->_db->select($query);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e->getMessage());
}
foreach ($users as $user) {
$shareids[] = $user['share_id'];
}
// Get groups permissions.
$groups = array();
try {
$groupNames = $this->_groups->listGroups($userid);
if ($groupNames) {
$group_ids = array();
foreach (array_keys($groupNames) as $id) {
$group_ids[] = $this->_db->quote((string)$id);
}
$query = 'SELECT * FROM ' . $this->_table
. '_groups WHERE group_uid IN ('
. implode(',', $group_ids) . ') AND ('
. $this->_getPermsCriteria('perm', $perms) . ')';
try {
$groups = $this->_db->select($query);
} catch (Horde_Db_Exception $e) {
throw new Horde_Share_Exception($e->getMessage());
}
foreach ($groups as $group) {
$shareids[] = $group['share_id'];
}
}
} catch (Horde_Group_Exception $e) {
$this->_logger->err($e);
}
return array($users, $groups, array_unique($shareids));
}
/**
* Returns a criteria statement for querying shares.
*
* @param string $userid The userid of the user to check access for.
* @param array $perms The level of permissions required.
* @param array $attributes Restrict the shares returned to those who
* have these attribute values.
* @param array $shareids Additional share IDs from user and group
* permissions.
*
* @return string The criteria string for fetching this user's shares.
*/
protected function _getShareCriteria($userid, array $perms, $attributes,
$shareids = null, $parent = null,
$allLevels = true)
{
/* Convert to driver's keys */
$attributes = $this->_toDriverKeys($attributes);
/* ...and to driver charset */
$attributes = $this->toDriverCharset($attributes);
$where = '';
if (empty($userid)) {
$where = $this->_getPermsCriteria('perm_guest', $perms);
} else {
// (owner == $userid)
$where .= 'share_owner = ' . $this->_db->quote($userid);
// (name == perm_creator and val & $perm)
$where .= ' OR ' . $this->_getPermsCriteria('perm_creator', $perms);
// (name == perm_default and val & $perm)
$where .= ' OR ' . $this->_getPermsCriteria('perm_default', $perms);
if ($shareids) {
$where .= ' OR share_id IN (' . implode(',', $shareids) . ')';
}
}
if (is_array($attributes)) {
// Build attribute/key filter.
$where = '(' . $where . ') ';
foreach ($attributes as $key => $value) {
if (is_array($value)) {
$value = array_map(array($this->_db, 'quote'), $value);
$where .= ' AND ' . $key . ' IN (' . implode(', ', $value) . ')';
} else {
$where .= ' AND ' . $key . ' = ' . $this->_db->quote($value);
}
}
} elseif (!empty($attributes)) {
// Restrict to shares owned by the user specified in the
// $attributes string.
$where = '(' . $where . ') AND share_owner = ' . $this->_db->quote($attributes);
}
// See if we need to filter by parent or get the parent object
if ($parent != null) {
if (!($parent instanceof Horde_Share_Object)) {
$parent = $this->getShareById($parent);
}
// Need to append the parent's share id to the list of parents in
// order to search the share_parents field.
$parents = $parent->get('parents') . ':' . $parent->getId();
if ($allLevels) {
$where_parent = '(share_parents = ' . $this->_db->quote($parents)
. ' OR share_parents LIKE ' . $this->_db->quote($parents . ':%') . ')';
} else {
$where_parent = 's.share_parents = ' . $this->_db->quote($parents);
}
} elseif (!$allLevels) {
// No parents, and we only want the root.
$where_parent = "(s.share_parents = '' OR s.share_parents IS NULL)";
}
if (!empty($where_parent)) {
if (empty($where)) {
$where = $where_parent;
} else {
$where = '(' . $where . ') AND ' . $where_parent;
}
}
return $where;
}
/**
* Builds an ANDed criteria snippet for a set or permissions.
*
* @param string $base A column name prefix.
* @param array $perms A list of permissions.
*
* @return string The generated criteria string.
*/
protected function _getPermsCriteria($base, array $perms)
{
$criteria = array();
foreach ($perms as $perm) {
$criteria[] = $base . '_' . $perm . ' = ' . $this->_db->quoteTrue();
}
return implode(' OR ', $criteria);
}
}
Horde_Share-2.2.0/lib/Horde/Share/Translation.php 0000664 0001750 0001750 00000001365 13166706112 017672 0 ustar jan jan
* @package Share
*/
class Horde_Share_Translation extends Horde_Translation_Autodetect
{
/**
* The translation domain
*
* @var string
*/
protected static $_domain = 'Horde_Share';
/**
* The absolute PEAR path to the translations for the default gettext handler.
*
* @var string
*/
protected static $_pearDirectory = '@data_dir@';
}
Horde_Share-2.2.0/locale/ar/LC_MESSAGES/Horde_Share.mo 0000664 0001750 0001750 00000000762 13166706112 020160 0 ustar jan jan <