[#6519] email alarm shows from-to instead of title
Summary email alarm shows from-to instead of title
Queue Horde Base
Queue Version 3.2-RC3
Type Bug
State Resolved
Priority 1. Low
Owners Jan Schneider <jan (at) horde (dot) org>
Requester Michael (dot) Redinger (at) uibk (dot) ac (dot) at
Created 03/22/2008 (48 days ago)
Due
Updated 03/22/2008 (48 days ago)
Assigned
Resolved 03/22/2008 (48 days ago)
Attachments
Milestone
Patch

History
03/22/2008 Jan Schneider Comment #2
State ⇒ Resolved
Assigned to Jan Schneider
Reply to this comment
It's much easier, we simply allow admins full access to the event title in getTitle() now.
03/22/2008 Michael (dot) Redinger (at) uibk (dot) ac (dot) at Comment #1
Patch ⇒
Milestone ⇒
Queue ⇒ Horde Base
Summary ⇒ email alarm shows from-to instead of title
Type ⇒ Bug
Priority ⇒ 1. Low
State ⇒ Unconfirmed
Reply to this comment
When a user is reminded by email of an upcoming event, Horde/Kronolith always sends
"Event from %s to %s"
instead of  the title of the event.
The reason for this is that the admin user the alarm script is run as does not heave the permissions to view a calendar (at least the one I use does not).
Horde does not check for admin permissions when listing the shares but only looks at the share permissions.

Note:
- This problem does not occur if your admin happens to have the right to at least read the calendar.
- This does not occur if the user you are trying this with is also the first entry in the horde admin array.
- For the admin alarms script to work correctly, I have used scripts-alarms.php from CVS


The problem starts in kronolith/lib/Driver.php:

In function getTitle, the permissions are checked. If the user does not have enough permissions, "Event from %s to %s" is returned.

    function getTitle($user = null)

        if ($this->isPrivate() && $this->getCreatorId() != $user) {
            return sprintf(_("Private Event from %s to %s"), $start, $end);
        } elseif ($this->hasPermission(PERMS_READ, $user)) {
            return strlen($this->title) ? $this->title : _("[Unnamed event]");
        } else {
            return sprintf(_("Event from %s to %s"), $start, $end);
        }

hasPermission calls getShare(). Because a PEAR error is returned, the function returns false.

        return (!is_a($share = &$this->getShare(), 'PEAR_Error') &&
                $share->hasPermission($user, $permission, $this->getCreatorId()));


getShare checks if the $GLOBALS['all_calendars'] array contains the current calender.
In the case of the alarm script, $this->getCalendar() returns the user's calendar (eg. "myuser"). But the global list of all calendars (the current user may access) does not contain this calendar. Eg. when the alarms.php script is run as admin "root" ((because that is the first entry in the horde admins array), all_calendars only contains "root".
Therefore the function raises a PEAR error - which makes getShare() return false (above).

    function &getShare()
    {       
        if (isset($GLOBALS['all_calendars'][$this->getCalendar()])) {
            $share = $GLOBALS['all_calendars'][$this->getCalendar()];
        } else {
            $share = PEAR::raiseError('Share not found');
        }
        return $share;
    }


Tracking this further down, I came to /lib/Horde/Share/datatree.php.
In function _listShares, the list of readable shares is generated.

function &_listShares($userid, $perm = PERMS_SHOW, $attributes = null)
    $criteria = $this->_getShareCriteria($userid, $perm, $attributes);
    ...
    $sharelist = $this->_datatree->getByAttributes($criteria, DATATREE_ROOT, true, 'id');


$criteria holds the output of _getShareCriteria(), whose first parameter is the current user (eg. root). _getShareCriteria now builds a criteria list that makes sure only the readable shares are returned. It does not check for admin permissions.
$criteria is then passed to $this->_datatree->getByAttributes() which builds and runs the actual SQL queries. Eg.:


SELECT c.datatree_id, c.datatree_name FROM horde_datatree c LEFT JOIN horde_datatree_attributes a1 ON a1.datatree_id = c.datatree_id
    WHERE c.group_uid = 'horde.shares.kronolith' AND (a1.attribute_name = 'owner' AND a1.attribute_value = 'root')   
    GROUP BY c.datatree_id, c.datatree_name, c.datatree_order
    ORDER BY c.datatree_order, c.datatree_name, c.datatree_id;
   
SELECT c.datatree_id, c.datatree_name FROM horde_datatree c LEFT JOIN horde_datatree_attributes a1 ON a1.datatree_id = c.datatree_id
    WHERE c.group_uid = 'horde.shares.kronolith' AND (a1.attribute_name = 'perm_users' AND a1.attribute_key = 'root' AND a1.attribute_value \\& 2)   
    GROUP BY c.datatree_id, c.datatree_name, c.datatree_order
    ORDER BY c.datatree_order, c.datatree_name, c.datatree_id;
   
SELECT c.datatree_id, c.datatree_name FROM horde_datatree c LEFT JOIN horde_datatree_attributes a1 ON a1.datatree_id = c.datatree_id
    WHERE c.group_uid = 'horde.shares.kronolith' AND (a1.attribute_name = 'perm_creator' AND a1.attribute_value \\& '2')   
    GROUP BY c.datatree_id, c.datatree_name, c.datatree_order
    ORDER BY c.datatree_order, c.datatree_name, c.datatree_id;

SELECT c.datatree_id, c.datatree_name FROM horde_datatree c LEFT JOIN horde_datatree_attributes a1 ON a1.datatree_id = c.datatree_id
    WHERE c.group_uid = 'horde.shares.kronolith' AND (a1.attribute_name = 'perm_default' AND a1.attribute_value \\& '2')   
    GROUP BY c.datatree_id, c.datatree_name, c.datatree_order
    ORDER BY c.datatree_order, c.datatree_name, c.datatree_id;




I am not sure how to handle this correctly. Should _getShareCriteria check if the user is admin (and AUTH_HANDLER is set to true)?