Exemplo n.º 1
0
function rollback($response_code = 412)
{
    global $request;
    $qry = new AwlQuery('ROLLBACK');
    $qry->Exec('move');
    // Just in case
    $request->DoResponse($response_code);
    // And we don't return from that.
}
Exemplo n.º 2
0
 /**
  * Method used to get the user's roles
  */
 function GetRoles()
 {
     $this->roles = array();
     $sql = 'SELECT role_name FROM roles JOIN role_member ON roles.role_no=role_member.role_no WHERE user_no = ' . $this->user_no;
     $qry = new AwlQuery($sql);
     if ($qry->Exec('DAViCalSession') && $qry->rows() > 0) {
         while ($role = $qry->Fetch()) {
             $this->roles[$role->role_name] = 1;
         }
     }
 }
Exemplo n.º 3
0
 static function getInstance($name)
 {
     $qry = new AwlQuery('SELECT * FROM timezones WHERE tzid = ? ORDER BY active DESC', $name);
     if ($qry->Exec('VTimezone', __LINE__, __FILE__) && $qry->rows() > 0 && ($row = $qry->Fetch())) {
         $vtz = new vComponent($row->vtimezone);
         if ($vtz->GetType() == 'VTIMEZONE') {
             return $vtz;
         }
         $tmp = $vtz->GetComponents('VTIMEZONE');
         if (count($tmp) < 1 || $tmp[0]->GetType() != 'VTIMEZONE') {
             return null;
         }
         $vtz = $tmp[0];
         return $vtz;
     }
     return null;
 }
Exemplo n.º 4
0
 function SQLTest()
 {
     $result = '';
     $sql = "SELECT event_instances::timestamp AS event_date FROM event_instances(?,?) LIMIT 30;";
     $qry = new AwlQuery($sql, $this->dtstart, $this->recur);
     // printf( "%s\n", $qry->querystring);
     if ($qry->Exec("test") && $qry->rows > 0) {
         $i = 0;
         while ($row = $qry->Fetch()) {
             if ($i++ % 4 == 0) {
                 $result .= "\n";
             }
             $result .= "   " . $row->event_date;
         }
     }
     return $result;
 }
Exemplo n.º 5
0
function delete_collection($id)
{
    $params = array(':collection_id' => $id);
    $qry = new AwlQuery('SELECT child.collection_id AS child_id FROM collection child JOIN collection parent ON (parent.dav_name = child.parent_container) WHERE parent.collection_id = :collection_id', $params);
    if ($qry->Exec('DELETE', __LINE__, __FILE__) && $qry->rows() > 0) {
        while ($row = $qry->Fetch()) {
            delete_collection($row->child_id);
        }
    }
    if ($qry->QDo("SELECT write_sync_change(collection_id, 404, caldav_data.dav_name) FROM caldav_data WHERE collection_id = :collection_id", $params) && $qry->QDo("DELETE FROM property WHERE dav_name LIKE (SELECT dav_name FROM collection WHERE collection_id = :collection_id) || '%'", $params) && $qry->QDo("DELETE FROM locks WHERE dav_name LIKE (SELECT dav_name FROM collection WHERE collection_id = :collection_id) || '%'", $params) && $qry->QDo("DELETE FROM caldav_data WHERE collection_id = :collection_id", $params) && $qry->QDo("DELETE FROM collection WHERE collection_id = :collection_id", $params)) {
        @dbg_error_log("DELETE", "DELETE (collection): User: %d, ETag: %s, Path: %s", $session->user_no, $request->etag_if_match, $request->path);
        return true;
    }
    return false;
}
Exemplo n.º 6
0
 function SQLTest()
 {
     $result = '';
     $sql = "SELECT event_instances::timestamp AS event_date FROM event_instances(:dtstart,:rrule) LIMIT " . $this->result_limit;
     $start = microtime(true);
     $qry = new AwlQuery($sql, array(':dtstart' => $this->dtstart, ':rrule' => $this->recur));
     // printf( "%s\n", $qry->querystring);
     if ($qry->Exec("test") && $qry->rows() > 0) {
         $i = 0;
         while ($row = $qry->Fetch()) {
             if ($i++ % 4 == 0) {
                 $result .= "\n";
             }
             $result .= "   " . $row->event_date;
         }
     }
     $this->SQL_time = microtime(true) - $start;
     return $result;
 }
Exemplo n.º 7
0
 /**
  * Constructor
  * @param string $ticket_id
  */
 function __construct($ticket_id)
 {
     global $c;
     $this->dav_name = null;
     $this->target_collection_id = null;
     $this->target_resource_id = null;
     $this->expiry = null;
     $this->expired = true;
     $this->dav_owner_id = null;
     $this->ticket_id = $ticket_id;
     $this->privileges = 0;
     $this->grantor_collection_privileges = 0;
     $qry = new AwlQuery('SELECT access_ticket.*, collection.dav_name, (access_ticket.expires < current_timestamp) AS expired,
             path_privs(access_ticket.dav_owner_id,collection.dav_name,:scan_depth) AS grantor_collection_privileges
        FROM access_ticket JOIN collection ON (target_collection_id = collection_id)
       WHERE ticket_id = :ticket_id::text', array(':ticket_id' => $ticket_id, ':scan_depth' => $c->permission_scan_depth));
     if ($qry->Exec('DAVTicket', __LINE__, __FILE__) && $qry->rows() == 1 && ($t = $qry->Fetch())) {
         if (!$t->expired) {
             foreach ($t as $k => $v) {
                 $this->{$k} = $v;
             }
             $this->expired = false;
             $this->privileges = bindec($this->privileges);
             $this->grantor_collection_privileges = bindec($this->grantor_collection_privileges);
             dbg_error_log('DAVTicket', 'Found a current ticket for "%s"', implode(', ', bits_to_privilege($this->privileges())));
         } else {
             dbg_error_log('DAVTicket', 'Found an expired ticket: %s - %s', $ticket_id, $t->expires);
         }
     }
     if (isset($this->target_resource_id)) {
         $qry = new AwlQuery('SELECT dav_name FROM caldav_data WHERE dav_id = :dav_id', array(':dav_id' => $this->target_resource_id));
         if ($qry->Exec('DAVTicket', __LINE__, __FILE__) && $qry->rows() == 1 && ($r = $qry->Fetch())) {
             $this->dav_name = $r->dav_name;
         }
     }
 }
Exemplo n.º 8
0
    if ($dest->IsCollection()) {
        if (!isset($c->readonly_webdav_collections) || $c->readonly_webdav_collections) {
            $request->PreconditionFailed(405, 'method-not-allowed', translate('You may not PUT to a collection URL'));
        }
        $request->DoResponse(403, translate('PUT on a collection is only allowed for text/calendar content against a calendar collection'));
    }
    $dest->NeedPrivilege('DAV::write-content');
}
if (isset($request->etag_none_match) && $request->etag_none_match != '*' && $dest->Exists()) {
    $request->PreconditionFailed(412, 'if-none-match', translate('A resource already exists at the destination.'));
}
if (isset($request->etag_if_match) && $request->etag_if_match != $dest->unique_tag()) {
    $request->PreconditionFailed(412, 'if-match', sprintf('Existing resource ETag of "%s" does not match "%s"', $dest->unique_tag(), $request->etag_if_match));
}
$collection_id = $container->GetProperty('collection_id');
$qry = new AwlQuery();
$qry->Begin();
$etag = md5($request->raw_post);
$params = array(':user_no' => $dest->GetProperty('user_no'), ':dav_name' => $dest->bound_from(), ':etag' => $etag, ':dav_data' => $request->raw_post, ':session_user' => $session->user_no);
if ($dest->Exists()) {
    $sql = 'UPDATE caldav_data SET caldav_data=:dav_data, dav_etag=:etag, logged_user=:session_user,
          modified=current_timestamp, user_no=:user_no, caldav_type=\'VCARD\' WHERE dav_name=:dav_name';
    $response_code = 200;
    $qry->QDo($sql, $params);
    $qry->QDo("SELECT dav_id FROM caldav_data WHERE dav_name = :dav_name ", array(':dav_name' => $params[':dav_name']));
} else {
    $sql = 'INSERT INTO caldav_data ( user_no, dav_name, dav_etag, caldav_data, caldav_type, logged_user, created, modified, collection_id )
          VALUES( :user_no, :dav_name, :etag, :dav_data, \'VCARD\', :session_user, current_timestamp, current_timestamp, :collection_id )';
    $params[':collection_id'] = $collection_id;
    $response_code = 201;
    $qry->QDo($sql, $params);
Exemplo n.º 9
0
/**
* sync LDAP against the DB
*/
function sync_LDAP()
{
    global $c;
    $ldapDriver = getStaticLdap();
    if ($ldapDriver->valid) {
        $mapping = $c->authenticate_hook['config']['mapping_field'];
        $attributes = array_values($mapping);
        $ldap_users_tmp = $ldapDriver->getAllUsers($attributes);
        if (sizeof($ldap_users_tmp) == 0) {
            return;
        }
        foreach ($ldap_users_tmp as $key => $ldap_user) {
            $ldap_users_info[$ldap_user[$mapping["username"]]] = $ldap_user;
            unset($ldap_users_tmp[$key]);
        }
        $qry = new AwlQuery("SELECT username, user_no, modified as updated FROM dav_principal where type_id=1");
        $qry->Exec('sync_LDAP', __LINE__, __FILE__);
        while ($db_user = $qry->Fetch()) {
            $db_users[] = $db_user->username;
            $db_users_info[$db_user->username] = array('user_no' => $db_user->user_no, 'updated' => $db_user->updated);
        }
        $ldap_users = array_keys($ldap_users_info);
        // users only in ldap
        $users_to_create = array_diff($ldap_users, $db_users);
        // users only in db
        $users_to_deactivate = array_diff($db_users, $ldap_users);
        // users present in ldap and in the db
        $users_to_update = array_intersect($db_users, $ldap_users);
        // creation of all users;
        if (sizeof($users_to_create)) {
            $c->messages[] = sprintf(i18n('- creating record for users :  %s'), join(', ', $users_to_create));
            foreach ($users_to_create as $username) {
                $user = (object) array('user_no' => 0, 'username' => $username);
                $valid = $ldap_users_info[$username];
                $ldap_timestamp = $valid[$mapping["updated"]];
                /**
                 * This splits the LDAP timestamp apart and assigns values to $Y $m $d $H $M and $S
                 */
                foreach ($c->authenticate_hook['config']['format_updated'] as $k => $v) {
                    ${$k} = substr($ldap_timestamp, $v[0], $v[1]);
                }
                $ldap_timestamp = "{$Y}" . "{$m}" . "{$d}" . "{$H}" . "{$M}" . "{$S}";
                $valid[$mapping["updated"]] = "{$Y}-{$m}-{$d} {$H}:{$M}:{$S}";
                sync_user_from_LDAP($user, $mapping, $valid);
            }
        }
        // deactivating all users
        $params = array();
        $i = 0;
        foreach ($users_to_deactivate as $v) {
            if (isset($c->do_not_sync_from_ldap) && isset($c->do_not_sync_from_ldap[$v])) {
                continue;
            }
            $params[':u' . $i++] = strtolower($v);
        }
        if (count($params) > 0) {
            $c->messages[] = sprintf(i18n('- deactivating users : %s'), join(', ', $users_to_deactivate));
            $qry = new AwlQuery('UPDATE usr SET active = FALSE WHERE lower(username) IN (' . implode(',', array_keys($params)) . ')', $params);
            $qry->Exec('sync_LDAP', __LINE__, __FILE__);
        }
        // updating all users
        if (sizeof($users_to_update)) {
            foreach ($users_to_update as $key => $username) {
                $valid = $ldap_users_info[$username];
                $ldap_timestamp = $valid[$mapping["updated"]];
                $valid["user_no"] = $db_users_info[$username]["user_no"];
                $mapping["user_no"] = "user_no";
                /**
                 * This splits the LDAP timestamp apart and assigns values to $Y $m $d $H $M and $S
                 */
                foreach ($c->authenticate_hook['config']['format_updated'] as $k => $v) {
                    ${$k} = substr($ldap_timestamp, $v[0], $v[1]);
                }
                $ldap_timestamp = "{$Y}" . "{$m}" . "{$d}" . "{$H}" . "{$M}" . "{$S}";
                $valid[$mapping["updated"]] = "{$Y}-{$m}-{$d} {$H}:{$M}:{$S}";
                $db_timestamp = substr(strtr($db_users_info[$username]['updated'], array(':' => '', ' ' => '', '-' => '')), 0, 14);
                if ($ldap_timestamp > $db_timestamp) {
                    sync_user_from_LDAP($usr, $mapping, $valid);
                } else {
                    unset($users_to_update[$key]);
                    $users_nothing_done[] = $username;
                }
            }
            if (sizeof($users_to_update)) {
                $c->messages[] = sprintf(i18n('- updating user records : %s'), join(', ', $users_to_update));
            }
            if (sizeof($users_nothing_done)) {
                $c->messages[] = sprintf(i18n('- nothing done on : %s'), join(', ', $users_nothing_done));
            }
        }
        $admins = 0;
        $qry = new AwlQuery("select count(*) as admins from usr join role_member using ( user_no ) join roles using (role_no) where usr.active = true and role_name='Admin'");
        $qry->Exec('sync_LDAP', __LINE__, __FILE__);
        while ($db_user = $qry->Fetch()) {
            $admins = $db_user->admins;
        }
        if ($admins == 0) {
            $c->messages[] = sprintf(i18n('Warning: there are no active admin users, you should fix this before logging out.'));
        }
    }
}
Exemplo n.º 10
0
            }
            break;
    }
}
if ($ticket_timeout == 'infinity') {
    $sql_timeout = null;
} else {
    if (preg_match('{^([a-z]+)-(\\d+)$}i', $ticket_timeout, $matches)) {
        /** It isn't specified, but timeout seems to be 'unit-number' like 'Seconds-3600', so we make it '3600 Seconds' which PostgreSQL understands */
        $sql_timeout = $matches[2] . ' ' . $matches[1];
    } else {
        $sql_timeout = $ticket_timeout;
    }
}
$collection_id = $target->GetProperty('collection_id');
$resource_id = $target->GetProperty('dav_id');
$i = 0;
do {
    $ticket_id = substr(str_replace('/', '', str_replace('+', '', base64_encode(sha1(date('r') . rand(0, 2100000000) . microtime(true), true)))), 7, 8);
    $qry = new AwlQuery('INSERT INTO access_ticket ( ticket_id, dav_owner_id, privileges, target_collection_id, target_resource_id, expires )
                VALUES( :ticket_id, :owner, :privs::INT::BIT(24), :collection, :resource, (current_timestamp + :expires::interval) )', array(':ticket_id' => $ticket_id, ':owner' => $session->principal_id, ':privs' => $ticket_privileges, ':collection' => $collection_id, ':resource' => $resource_id, ':expires' => $sql_timeout));
    $result = $qry->Exec('MKTICKET', __LINE__, __FILE__);
} while (!$result && $i++ < 2);
$privs = new XMLElement('privilege');
foreach (bits_to_privilege($ticket_privileges) as $k => $v) {
    $reply->NSElement($privs, $v);
}
$ticketinfo = new XMLElement('T:ticketinfo', array(new XMLElement('T:id', $ticket_id), new XMLElement('owner', $reply->href(ConstructURL('/' . $session->username . '/'))), $privs, new XMLElement('T:timeout', $ticket_timeout), new XMLElement('T:visits', 'infinity')));
$prop = new XMLElement("prop", new XMLElement('T:ticketdiscovery', $ticketinfo), $reply->GetXmlNsArray());
header('Ticket: ' . $ticket_id);
$request->XMLResponse(200, $prop);
Exemplo n.º 11
0
    /**
     * Writes the data to a member in the collection and returns the segment_name of the resource in our internal namespace. 
     * @param $data iCalendar The resource to be written.
     * @param $create_resource boolean True if this is a new resource.
     * @param $segment_name The name of the resource within the collection.
     */
    function WriteCalendarMember($data, $create_resource, $segment_name = null)
    {
        if (!$this->IsSchedulingCollection() && !$this->IsCalendar()) {
            return false;
        }
        // function write_resource( $user_no, $path, $caldav_data, $collection_id, $author, $etag, $ic, $put_action_type, $caldav_context, $log_action=true, $weak_etag=null ) {
        global $tz_regex;
        $resources = $ic->GetComponents('VTIMEZONE', false);
        // Not matching VTIMEZONE
        if (!isset($resources[0])) {
            $resource_type = 'Unknown';
            /** @TODO: Handle writing non-calendar resources, like address book entries or random file data */
            rollback_on_error($caldav_context, $user_no, $path, translate('No calendar content'), 412);
            return false;
        } else {
            $first = $resources[0];
            $resource_type = $first->GetType();
        }
        $qry = new AwlQuery();
        $qry->Begin();
        $params = array(':dav_name' => $path, ':user_no' => $user_no, ':etag' => $etag, ':dav_data' => $caldav_data, ':caldav_type' => $resource_type, ':session_user' => $author, ':weak_etag' => $weak_etag);
        if ($put_action_type == 'INSERT') {
            create_scheduling_requests($vcal);
            $sql = 'INSERT INTO caldav_data ( user_no, dav_name, dav_etag, caldav_data, caldav_type, logged_user, created, modified, collection_id, weak_etag )
            VALUES( :user_no, :dav_name, :etag, :dav_data, :caldav_type, :session_user, current_timestamp, current_timestamp, :collection_id, :weak_etag )';
            $params[':collection_id'] = $collection_id;
        } else {
            update_scheduling_requests($vcal);
            $sql = 'UPDATE caldav_data SET caldav_data=:dav_data, dav_etag=:etag, caldav_type=:caldav_type, logged_user=:session_user,
            modified=current_timestamp, weak_etag=:weak_etag WHERE user_no=:user_no AND dav_name=:dav_name';
        }
        if (!$qry->QDo($sql, $params)) {
            rollback_on_error($caldav_context, $user_no, $path);
            return false;
        }
        $qry->QDo('SELECT dav_id FROM caldav_data WHERE dav_name = :dav_name ', array(':dav_name' => $path));
        if ($qry->rows() == 1 && ($row = $qry->Fetch())) {
            $dav_id = $row->dav_id;
        }
        $calitem_params = array(':dav_name' => $path, ':user_no' => $user_no, ':etag' => $etag);
        $dtstart = $first->GetPValue('DTSTART');
        $calitem_params[':dtstart'] = $dtstart;
        if ((!isset($dtstart) || $dtstart == '') && $first->GetPValue('DUE') != '') {
            $dtstart = $first->GetPValue('DUE');
        }
        $dtend = $first->GetPValue('DTEND');
        if (isset($dtend) && $dtend != '') {
            dbg_error_log('PUT', ' DTEND: "%s", DTSTART: "%s", DURATION: "%s"', $dtend, $dtstart, $first->GetPValue('DURATION'));
            $calitem_params[':dtend'] = $dtend;
            $dtend = ':dtend';
        } else {
            $dtend = 'NULL';
            if ($first->GetPValue('DURATION') != '' and $dtstart != '') {
                $duration = preg_replace('#[PT]#', ' ', $first->GetPValue('DURATION'));
                $dtend = '(:dtstart::timestamp with time zone + :duration::interval)';
                $calitem_params[':duration'] = $duration;
            } elseif ($first->GetType() == 'VEVENT') {
                /**
                 * From RFC2445 4.6.1:
                 * For cases where a "VEVENT" calendar component specifies a "DTSTART"
                 * property with a DATE data type but no "DTEND" property, the events
                 * non-inclusive end is the end of the calendar date specified by the
                 * "DTSTART" property. For cases where a "VEVENT" calendar component specifies
                 * a "DTSTART" property with a DATE-TIME data type but no "DTEND" property,
                 * the event ends on the same calendar date and time of day specified by the
                 * "DTSTART" property.
                 *
                 * So we're looking for 'VALUE=DATE', to identify the duration, effectively.
                 *
                 */
                $value_type = $first->GetPParamValue('DTSTART', 'VALUE');
                dbg_error_log('PUT', 'DTSTART without DTEND. DTSTART value type is %s', $value_type);
                if (isset($value_type) && $value_type == 'DATE') {
                    $dtend = '(:dtstart::timestamp with time zone::date + \'1 day\'::interval)';
                } else {
                    $dtend = ':dtstart';
                }
            }
        }
        $last_modified = $first->GetPValue('LAST-MODIFIED');
        if (!isset($last_modified) || $last_modified == '') {
            $last_modified = gmdate('Ymd\\THis\\Z');
        }
        $calitem_params[':modified'] = $last_modified;
        $dtstamp = $first->GetPValue('DTSTAMP');
        if (!isset($dtstamp) || $dtstamp == '') {
            $dtstamp = $last_modified;
        }
        $calitem_params[':dtstamp'] = $dtstamp;
        $class = $first->GetPValue('CLASS');
        /* Check and see if we should over ride the class. */
        /** @TODO: is there some way we can move this out of this function? Or at least get rid of the need for the SQL query here. */
        if (public_events_only($user_no, $path)) {
            $class = 'PUBLIC';
        }
        /*
         * It seems that some calendar clients don't set a class...
         * RFC2445, 4.8.1.3:
         * Default is PUBLIC
         */
        if (!isset($class) || $class == '') {
            $class = 'PUBLIC';
        }
        $calitem_params[':class'] = $class;
        /** Calculate what timezone to set, first, if possible */
        $last_tz_locn = 'Turkmenikikamukau';
        // I really hope this location doesn't exist!
        $tzid = $first->GetPParamValue('DTSTART', 'TZID');
        if (!isset($tzid) || $tzid == '') {
            $tzid = $first->GetPParamValue('DUE', 'TZID');
        }
        $timezones = $ic->GetComponents('VTIMEZONE');
        foreach ($timezones as $k => $tz) {
            if ($tz->GetPValue('TZID') != $tzid) {
                /**
                 * We'll pretend they didn't forget to give us a TZID and that they
                 * really hope the server is running in the timezone they supplied... but be noisy about it.
                 */
                dbg_error_log('ERROR', ' Event includes TZID[%s] but uses TZID[%s]!', $tz->GetPValue('TZID'), $tzid);
                $tzid = $tz->GetPValue('TZID');
            }
            // This is the one
            $tz_locn = $tz->GetPValue('X-LIC-LOCATION');
            if (!isset($tz_locn)) {
                if (preg_match('#([^/]+/[^/]+)$#', $tzid, $matches)) {
                    $tz_locn = $matches[1];
                } else {
                    if (isset($tzid) && $tzid != '') {
                        dbg_error_log('ERROR', ' Couldn\'t guess Olsen TZ from TZID[%s].  This may end in tears...', $tzid);
                    }
                }
            } else {
                if (!preg_match($tz_regex, $tz_locn)) {
                    if (preg_match('#([^/]+/[^/]+)$#', $tzid, $matches)) {
                        $tz_locn = $matches[1];
                    }
                }
            }
            dbg_error_log('PUT', ' Using TZID[%s] and location of [%s]', $tzid, isset($tz_locn) ? $tz_locn : '');
            if (isset($tz_locn) && $tz_locn != $last_tz_locn && preg_match($tz_regex, $tz_locn)) {
                dbg_error_log('PUT', ' Setting timezone to %s', $tz_locn);
                if ($tz_locn != '') {
                    $qry->QDo('SET TIMEZONE TO \'' . $tz_locn . "'");
                }
                $last_tz_locn = $tz_locn;
            }
            $params = array(':tzid' => $tzid);
            $qry = new AwlQuery('SELECT tz_locn FROM time_zone WHERE tz_id = :tzid', $params);
            if ($qry->Exec('PUT', __LINE__, __FILE__) && $qry->rows() == 0) {
                $params[':tzlocn'] = $tz_locn;
                $params[':tzspec'] = isset($tz) ? $tz->Render() : null;
                $qry->QDo('INSERT INTO time_zone (tz_id, tz_locn, tz_spec) VALUES(:tzid,:tzlocn,:tzspec)', $params);
            }
            if (!isset($tz_locn) || $tz_locn == '') {
                $tz_locn = $tzid;
            }
        }
        $created = $first->GetPValue('CREATED');
        if ($created == '00001231T000000Z') {
            $created = '20001231T000000Z';
        }
        $calitem_params[':created'] = $created;
        $calitem_params[':tzid'] = $tzid;
        $calitem_params[':uid'] = $first->GetPValue('UID');
        $calitem_params[':summary'] = $first->GetPValue('SUMMARY');
        $calitem_params[':location'] = $first->GetPValue('LOCATION');
        $calitem_params[':transp'] = $first->GetPValue('TRANSP');
        $calitem_params[':description'] = $first->GetPValue('DESCRIPTION');
        $calitem_params[':rrule'] = $first->GetPValue('RRULE');
        $calitem_params[':url'] = $first->GetPValue('URL');
        $calitem_params[':priority'] = $first->GetPValue('PRIORITY');
        $calitem_params[':due'] = $first->GetPValue('DUE');
        $calitem_params[':percent_complete'] = $first->GetPValue('PERCENT-COMPLETE');
        $calitem_params[':status'] = $first->GetPValue('STATUS');
        if ($put_action_type == 'INSERT') {
            $sql = <<<EOSQL
INSERT INTO calendar_item (user_no, dav_name, dav_id, dav_etag, uid, dtstamp,
                dtstart, dtend, summary, location, class, transp,
                description, rrule, tz_id, last_modified, url, priority,
                created, due, percent_complete, status, collection_id )
   VALUES ( :user_no, :dav_name, currval('dav_id_seq'), :etag, :uid, :dtstamp,
                :dtstart, {$dtend}, :summary, :location, :class, :transp,
                :description, :rrule, :tzid, :modified, :url, :priority,
                :created, :due, :percent_complete, :status, {$collection_id} )
EOSQL;
            $sync_change = 201;
        } else {
            $sql = <<<EOSQL
UPDATE calendar_item SET dav_etag=:etag, uid=:uid, dtstamp=:dtstamp,
                dtstart=:dtstart, dtend={$dtend}, summary=:summary, location=:location, class=:class, transp=:transp,
                description=:description, rrule=:rrule, tz_id=:tzid, last_modified=:modified, url=:url, priority=:priority,
                created=:created, due=:due, percent_complete=:percent_complete, status=:status
       WHERE user_no=:user_no AND dav_name=:dav_name
EOSQL;
            $sync_change = 200;
        }
        write_alarms($dav_id, $first);
        write_attendees($dav_id, $first);
        if ($log_action && function_exists('log_caldav_action')) {
            log_caldav_action($put_action_type, $first->GetPValue('UID'), $user_no, $collection_id, $path);
        } else {
            if ($log_action) {
                dbg_error_log('PUT', 'No log_caldav_action( %s, %s, %s, %s, %s) can be called.', $put_action_type, $first->GetPValue('UID'), $user_no, $collection_id, $path);
            }
        }
        $qry = new AwlQuery($sql, $calitem_params);
        if (!$qry->Exec('PUT', __LINE__, __FILE__)) {
            rollback_on_error($caldav_context, $user_no, $path);
            return false;
        }
        $qry->QDo("SELECT write_sync_change( {$collection_id}, {$sync_change}, :dav_name)", array(':dav_name' => $path));
        $qry->Commit();
        dbg_error_log('PUT', 'User: %d, ETag: %s, Path: %s', $author, $etag, $path);
        return $segment_name;
    }
Exemplo n.º 12
0
function ticket_row_editor()
{
    global $c, $id, $editor, $can_write_principal, $privilege_names;
    $ticketrow = new Editor("Tickets", "access_ticket");
    $ticketrow->SetSubmitName('ticketrow');
    if ($can_write_principal && $ticketrow->IsSubmit()) {
        $username = $editor->Value('username');
        $ugly_path = $_POST['target'];
        if ($ugly_path == '/' . $username || $ugly_path == '/' . $username . '/') {
            $target_collection = $id;
        } else {
            $username_len = strlen($username) + 2;
            $sql = "SELECT collection_id FROM collection WHERE dav_name = :exact_name";
            $sql .= " AND substring(dav_name FROM 1 FOR {$username_len}) = '/{$username}/'";
            $params = array(':exact_name' => $ugly_path);
            if (!preg_match('#/$#', $ugly_path)) {
                $sql .= " OR dav_name = :truncated_name OR dav_name = :trailing_slash_name";
                $params[':truncated_name'] = preg_replace('#[^/]*$#', '', $ugly_path);
                $params[':trailing_slash_name'] = $ugly_path . "/";
            }
            $sql .= " ORDER BY LENGTH(dav_name) DESC LIMIT 1";
            $qry = new AwlQuery($sql, $params);
            if ($qry->Exec() && $qry->rows() > 0) {
                $row = $qry->Fetch();
                $target_collection = $row->collection_id;
            } else {
                $c->messages[] = translate('Can only add tickets for existing collection paths which you own');
                return $ticketrow;
            }
        }
        $_POST['dav_owner_id'] = $id;
        $_POST['target_collection_id'] = $target_collection;
        $ticket_id = check_by_regex($_POST['ticket_id'], '/[A-Za-z0-9]+/');
        $ticketrow->SetWhere('dav_owner_id=' . $id . ' AND ticket_id=' . AwlQuery::quote($ticket_id));
        if (isset($_POST['ticket_privileges'])) {
            $privilege_bitpos = array_flip($privilege_names);
            $priv_names = array_keys($_POST['ticket_privileges']);
            $privs_dec = privilege_to_bits($priv_names);
            $_POST['privileges'] = sprintf('%024s', decbin($privs_dec));
            $ticketrow->Assign('privileges', $privs_dec);
        }
        $c->messages[] = translate('Creating new ticket granting privileges to this Principal');
        $ticketrow->Write();
    }
    return $ticketrow;
}
Exemplo n.º 13
0
    }
}
if ($target_collection->Privileges() != privilege_to_bits('DAV::all')) {
    $where .= " AND (calendar_item.class != 'PRIVATE' OR calendar_item.class IS NULL) ";
}
if (isset($c->hide_TODO) && ($c->hide_TODO === true || is_string($c->hide_TODO) && preg_match($c->hide_TODO, $_SERVER['HTTP_USER_AGENT'])) && !$target_collection->HavePrivilegeTo('all')) {
    $where .= " AND caldav_data.caldav_type NOT IN ('VTODO') ";
}
if (isset($c->hide_older_than) && intval($c->hide_older_than > 0)) {
    $where .= " AND (CASE WHEN caldav_data.caldav_type<>'VEVENT' OR calendar_item.dtstart IS NULL THEN true ELSE calendar_item.dtstart > (now() - interval '" . intval($c->hide_older_than) . " days') END) ";
}
$sql = 'SELECT ' . $distinct . ' caldav_data.*,calendar_item.*  FROM collection INNER JOIN caldav_data USING(collection_id) INNER JOIN calendar_item USING(dav_id) ' . $where;
if (isset($c->strict_result_ordering) && $c->strict_result_ordering) {
    $sql .= " ORDER BY caldav_data.dav_id";
}
$qry = new AwlQuery($sql, $params);
if ($qry->Exec("calquery", __LINE__, __FILE__) && $qry->rows() > 0) {
    while ($dav_object = $qry->Fetch()) {
        try {
            if (!$need_post_filter || apply_filter($qry_filters, $dav_object)) {
                if ($bound_from != $target_collection->dav_name()) {
                    $dav_object->dav_name = str_replace($bound_from, $target_collection->dav_name(), $dav_object->dav_name);
                }
                if ($need_expansion) {
                    $vResource = new vComponent($dav_object->caldav_data);
                    $expanded = getVCalendarRange($vResource);
                    if (!$expanded->overlaps($range_filter)) {
                        continue;
                    }
                    $expanded = expand_event_instances($vResource, $expand_range_start, $expand_range_end, $expand_as_floating);
                    if ($expanded->ComponentCount() == 0) {
Exemplo n.º 14
0
if (isset($c->version_string) && preg_match('/(\\d+)\\.(\\d+)\\.(\\d+)(.*)/', $c->version_string, $matches)) {
    $c->code_major = $matches[1];
    $c->code_minor = $matches[2];
    $c->code_patch = $matches[3];
    $c->code_version = $c->code_major * 1000 + $c->code_minor . '.' . $c->code_patch;
    dbg_error_log('caldav', 'Version (%d.%d.%d) == %s', $c->code_major, $c->code_minor, $c->code_patch, $c->code_version);
    @header(sprintf('Server: %d.%d', $c->code_major, $c->code_minor));
}
/**
* Force the domain name to what was in the configuration file
*/
$_SERVER['SERVER_NAME'] = $c->domain_name;
require_once 'AwlQuery.php';
$c->want_dbversion = array(1, 2, 11);
$c->schema_version = 0;
$qry = new AwlQuery('SELECT schema_major, schema_minor, schema_patch FROM awl_db_revision ORDER BY schema_id DESC LIMIT 1;');
if ($qry->Exec('always', __LINE__, __FILE__) && ($row = $qry->Fetch())) {
    $c->schema_version = doubleval(sprintf('%d%03d.%03d', $row->schema_major, $row->schema_minor, $row->schema_patch));
    $c->wanted_version = doubleval(sprintf('%d%03d.%03d', $c->want_dbversion[0], $c->want_dbversion[1], $c->want_dbversion[2]));
    $c->schema_major = $row->schema_major;
    $c->schema_minor = $row->schema_minor;
    $c->schema_patch = $row->schema_patch;
    if ($c->schema_version < $c->wanted_version) {
        $c->messages[] = sprintf('Database schema needs upgrading. Current: %d.%d.%d, Desired: %d.%d.%d', $row->schema_major, $row->schema_minor, $row->schema_patch, $c->want_dbversion[0], $c->want_dbversion[1], $c->want_dbversion[2]);
    }
    if (isset($c->default_timezone)) {
        $qry->QDo('SET TIMEZONE TO ?', $c->default_timezone);
    }
}
require_once 'Principal.php';
/**
Exemplo n.º 15
0
function handle_remote_attendee_reply(vCalendar $ical)
{
    $attendees = $ical->GetAttendees();
    // attendee reply have just one attendee
    if (count($attendees) != 1) {
        return;
    }
    $attendee = $attendees[0];
    $uidparam = $ical->GetPropertiesByPath("VCALENDAR/*/UID");
    $uid = $uidparam[0]->Value();
    $qry = new AwlQuery('UPDATE calendar_attendee SET email_status=:statusTo WHERE attendee=:attendee AND dav_id = (SELECT dav_id FROM calendar_item WHERE uid = :uid)');
    // user accepted
    $qry->Bind(':statusTo', EMAIL_STATUS::NORMAL);
    $qry->Bind(':attendee', $attendee->Value());
    $qry->Bind(':uid', $uid);
    $qry->Exec('changeStatusTo');
    return true;
}
Exemplo n.º 16
0
    }
}
$sql = 'SELECT calendar_item.*, addressbook_resource.*, caldav_data.* FROM caldav_data
                  LEFT JOIN calendar_item USING(dav_id, user_no, dav_name, collection_id)
                  LEFT JOIN addressbook_resource USING(dav_id)
                  LEFT JOIN collection USING(collection_id)';
/**
 * @todo: Add stanzas for missing rows, so we don't just return a blank multistatus but
 * actually return <response> stanzas with a 404 for each absent href.  We could do
 * this relatively easily with an array_flip($params) and remove each matching dav_name
 * as we process it.
 */
if (isset($c->strict_result_ordering) && $c->strict_result_ordering) {
    $where .= " ORDER BY caldav_data.dav_id";
}
$qry = new AwlQuery($sql . $where, $params);
if ($qry->Exec('REPORT', __LINE__, __FILE__) && $qry->rows() > 0) {
    while ($dav_object = $qry->Fetch()) {
        if ($bound_from != $collection->dav_name()) {
            $dav_object->dav_name = str_replace($bound_from, $collection->dav_name(), $dav_object->dav_name);
        }
        //if ( $need_expansion ) {
        $vResource = new vComponent($dav_object->caldav_data);
        $expanded = expand_event_instances($vResource, $expand_range_start, $expand_range_end);
        //      $event = $expanded->GetComponents("VEVENT")[0];
        //
        //      $attendeeName = "ATTENDEE";
        //
        //      $event->ClearProperties($attendeeName);
        //
        //      $attendeeQry = new AwlQuery("SELECT params, attendee FROM calendar_attendee WHERE dav_id = :dav_id", array(':dav_id' => $dav_object->dav_id));
Exemplo n.º 17
0
 /**
  * Get the calendar_free_busy_set, as lazily as possible
  */
 function calendar_free_busy_set()
 {
     if (!isset($this->calendar_free_busy_set)) {
         /**
          * calendar-free-busy-set has been dropped from draft 5 of the scheduling extensions for CalDAV
          * in favour of
          */
         $this->calendar_free_busy_set = array();
         $qry = new AwlQuery('SELECT dav_name FROM collection WHERE user_no = :user_no AND is_calendar AND (schedule_transp = \'opaque\' OR schedule_transp IS NULL) ORDER BY user_no, collection_id', array(':user_no' => $this->user_no));
         if ($qry->Exec('principal', __LINE__, __FILE__)) {
             while ($calendar = $qry->Fetch()) {
                 $this->calendar_free_busy_set[] = ConstructURL($calendar->dav_name, true);
             }
         }
     }
     return $this->calendar_free_busy_set;
 }
Exemplo n.º 18
0
function get_freebusy($path_match, $range_start, $range_end, $bin_privs = null)
{
    global $request, $c;
    $debugging = false;
    //    if ( $debugging ) {
    //        printf( "Path: %s\n", $path_match );
    //        print_r( $range_start );
    //        print_r( $range_end );
    //    }
    if (!isset($bin_privs)) {
        $bin_privs = $request->Privileges();
    }
    if (!isset($range_start) || !isset($range_end)) {
        $request->DoResponse(400, 'All valid freebusy requests MUST contain a time-range filter');
    }
    $params = array(':path_match' => $path_match, ':start' => $range_start->UTC(), ':end' => $range_end->UTC());
    $where = ' WHERE caldav_data.dav_name ~ :path_match ';
    $where .= 'AND rrule_event_overlaps( dtstart, dtend, rrule, :start, :end) ';
    $where .= "AND caldav_data.caldav_type IN ( 'VEVENT', 'VTODO' ) ";
    $where .= "AND (calendar_item.transp != 'TRANSPARENT' OR calendar_item.transp IS NULL) ";
    $where .= "AND (calendar_item.status != 'CANCELLED' OR calendar_item.status IS NULL) ";
    $where .= "AND collection.is_calendar AND collection.schedule_transp = 'opaque' ";
    if ($bin_privs != privilege_to_bits('all')) {
        $where .= "AND (calendar_item.class != 'PRIVATE' OR calendar_item.class IS NULL) ";
    }
    $fbtimes = array();
    $sql = 'SELECT caldav_data.caldav_data, calendar_item.rrule, calendar_item.transp, calendar_item.status, ';
    $sql .= "to_char(calendar_item.dtstart at time zone 'GMT'," . AWLDatabase::SqlUTCFormat . ') AS start, ';
    $sql .= "to_char(calendar_item.dtend at time zone 'GMT'," . AWLDatabase::SqlUTCFormat . ') AS finish, ';
    $sql .= "calendar_item.class, calendar_item.dav_id ";
    $sql .= 'FROM caldav_data INNER JOIN calendar_item USING(dav_id,user_no,dav_name,collection_id) ';
    $sql .= 'INNER JOIN collection USING(collection_id)';
    $sql .= $where;
    if (isset($c->strict_result_ordering) && $c->strict_result_ordering) {
        $sql .= ' ORDER BY dav_id';
    }
    $qry = new AwlQuery($sql, $params);
    if ($qry->Exec("REPORT", __LINE__, __FILE__) && $qry->rows() > 0) {
        while ($calendar_object = $qry->Fetch()) {
            $extra = '';
            if ($calendar_object->status == 'TENTATIVE') {
                $extra = ';BUSY-TENTATIVE';
            } else {
                if (isset($c->_workaround_client_freebusy_bug) && $c->_workaround_client_freebusy_bug) {
                    $extra = ';BUSY';
                }
            }
            //      if ( $debugging ) {
            //        $extra = ';'.$calendar_object->dav_id;
            //      }
            //      dbg_error_log( "REPORT", " FreeBusy: Not transparent, tentative or cancelled: %s, %s, %s", $calendar_object->start, $calendar_object->finish, $calendar_object->class );
            $ics = new vComponent($calendar_object->caldav_data);
            $expanded = expand_event_instances($ics, $range_start, $range_end);
            $expansion = $expanded->GetComponents(array('VEVENT' => true, 'VTODO' => true, 'VJOURNAL' => true));
            //      if ( $debugging ) echo "===================   $calendar_object->dav_id   ========================\n";
            $dtstart_type = 'DTSTART';
            foreach ($expansion as $k => $v) {
                //        if ( $debugging ) print $k."\n".$v->Render();
                $start_date = $v->GetProperty($dtstart_type);
                if (!isset($start_date) && $v->GetType() != 'VTODO') {
                    $dtstart_type = 'DUE';
                    $start_date = $v->GetProperty($dtstart_type);
                }
                $start_date = new RepeatRuleDateTime($start_date);
                $duration = $v->GetProperty('DURATION');
                $duration = !isset($duration) ? 'P1D' : $duration->Value();
                $end_date = clone $start_date;
                $end_date->modify($duration);
                if ($end_date == $start_date || $end_date < $range_start || $start_date > $range_end) {
                    //            if ( $debugging )
                    //              echo "-----------------------------------------------------\n";
                    continue;
                }
                //        if ( $debugging )
                //            echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
                $thisfb = $start_date->UTC() . '/' . $end_date->UTC() . $extra;
                array_push($fbtimes, $thisfb);
            }
        }
    }
    $freebusy = new vComponent();
    $freebusy->setType('VFREEBUSY');
    $freebusy->AddProperty('DTSTAMP', date('Ymd\\THis\\Z'));
    $freebusy->AddProperty('DTSTART', $range_start->UTC());
    $freebusy->AddProperty('DTEND', $range_end->UTC());
    sort($fbtimes);
    foreach ($fbtimes as $k => $v) {
        $text = explode(';', $v, 2);
        $freebusy->AddProperty('FREEBUSY', $text[0], isset($text[1]) ? array('FBTYPE' => $text[1]) : null);
    }
    return $freebusy;
}
Exemplo n.º 19
0
 /**
  * Do what must be done with time zones from on file.  Attempt to turn
  * them into something that PostgreSQL can understand...
  *
  * @DEPRECATED: This class will be removed soon.
  * @todo Remove this function.
  */
 function DealWithTimeZones()
 {
     global $c;
     deprecated('iCalendar::DealWithTimeZones');
     $tzid = $this->Get('TZID');
     if (isset($c->save_time_zone_defs) && $c->save_time_zone_defs) {
         $qry = new AwlQuery("SELECT tz_locn FROM time_zone WHERE tz_id = ?;", $tzid);
         if ($qry->Exec('iCalendar') && $qry->rows() == 1) {
             $row = $qry->Fetch();
             $this->tz_locn = $row->tz_locn;
         }
         dbg_error_log('iCalendar', " TZCrap2: TZID '%s', DB Rows=%d, Location '%s'", $tzid, $qry->rows(), $this->tz_locn);
     }
     if ((!isset($this->tz_locn) || $this->tz_locn == '') && $tzid != '') {
         /**
          * In case there was no X-LIC-LOCATION defined, let's hope there is something in the TZID
          * that we can use.  We are looking for a string like "Pacific/Auckland" if possible.
          */
         $tzname = preg_replace('#^(.*[^a-z])?([a-z]+/[a-z]+)$#i', '$1', $tzid);
         /**
         * Unfortunately this kind of thing will never work well :-(
         *
         if ( strstr( $tzname, ' ' ) ) {
           $words = preg_split('/\s/', $tzname );
           $tzabbr = '';
           foreach( $words AS $i => $word ) {
             $tzabbr .= substr( $word, 0, 1);
           }
           $this->tz_locn = $tzabbr;
         }
         */
         if (preg_match('#\\S+/\\S+#', $tzname)) {
             $this->tz_locn = $tzname;
         }
         dbg_error_log('iCalendar', " TZCrap3: TZID '%s', Location '%s', Perhaps: %s", $tzid, $this->tz_locn, $tzname);
     }
     if ($tzid != '' && isset($c->save_time_zone_defs) && $c->save_time_zone_defs && $qry->rows() != 1 && isset($this->vtimezone) && $this->vtimezone != "") {
         $qry2 = new AwlQuery("INSERT INTO time_zone (tz_id, tz_locn, tz_spec) VALUES( ?, ?, ? );", $tzid, $this->tz_locn, $this->vtimezone);
         $qry2->Exec('iCalendar');
     }
     if ((!isset($this->tz_locn) || $this->tz_locn == "") && isset($c->local_tzid)) {
         $this->tz_locn = $c->local_tzid;
     }
 }
Exemplo n.º 20
0
    $request->DoResponse(412);
}
if (isset($request->etag_if_match) && $request->etag_if_match != $dest->unique_tag()) {
    $request->DoResponse(412);
}
$collection_id = $container->GetProperty('collection_id');
$qry = new AwlQuery();
$qry->Begin();
$etag = md5($request->raw_post);
$params = array(':user_no' => $dest->GetProperty('user_no'), ':dav_name' => $dest->bound_from(), ':etag' => $etag, ':dav_data' => $request->raw_post, ':session_user' => $session->user_no);
if ($dest->Exists()) {
    $sql = 'UPDATE caldav_data SET caldav_data=:dav_data, dav_etag=:etag, logged_user=:session_user,
          modified=current_timestamp WHERE user_no=:user_no AND dav_name=:dav_name';
    $response_code = 200;
} else {
    $sql = 'INSERT INTO caldav_data ( user_no, dav_name, dav_etag, caldav_data, logged_user, created, modified, collection_id )
          VALUES( :user_no, :dav_name, :etag, :dav_data, :session_user, current_timestamp, current_timestamp, :collection_id )';
    $params[':collection_id'] = $collection_id;
    $response_code = 201;
}
$qry->QDo($sql, $params);
$qry->QDo("SELECT write_sync_change( {$collection_id}, {$response_code}, :dav_name)", array(':dav_name' => $dest->bound_from()));
$qry = new AwlQuery('COMMIT');
if (!$qry->Exec('move')) {
    rollback(500);
}
header('ETag: "' . $etag . '"');
if ($response_code == 200) {
    $response_code = 204;
}
$request->DoResponse($response_code);
Exemplo n.º 21
0
  * used as a .ics download for the whole collection, which is what we do also.
  */
 $sql = 'SELECT caldav_data, class, caldav_type, calendar_item.user_no, logged_user ';
 $sql .= 'FROM collection INNER JOIN caldav_data USING(collection_id) INNER JOIN calendar_item USING ( dav_id ) WHERE ';
 if (isset($c->get_includes_subcollections) && $c->get_includes_subcollections) {
     $sql .= '(collection.dav_name ~ :path_match ';
     $sql .= 'OR collection.collection_id IN (SELECT bound_source_id FROM dav_binding WHERE dav_binding.dav_name ~ :path_match)) ';
     $params = array(':path_match' => '^' . $request->path);
 } else {
     $sql .= 'caldav_data.collection_id = :collection_id ';
     $params = array(':collection_id' => $dav_resource->resource_id());
 }
 if (isset($c->strict_result_ordering) && $c->strict_result_ordering) {
     $sql .= ' ORDER BY dav_id';
 }
 $qry = new AwlQuery($sql, $params);
 if (!$qry->Exec("GET", __LINE__, __FILE__)) {
     $request->DoResponse(500, translate("Database Error"));
 }
 /**
  * Here we are constructing a whole calendar response for this collection, including
  * the timezones that are referred to by the events we have selected.
  */
 $vcal = new iCalComponent();
 $vcal->VCalendar();
 $displayname = $dav_resource->GetProperty('displayname');
 if (isset($displayname)) {
     $vcal->AddProperty("X-WR-CALNAME", $displayname);
 }
 $need_zones = array();
 $timezones = array();
Exemplo n.º 22
0
 /**
 CREATE TABLE addressbook_address_email (
 dav_id INT8 NOT NULL REFERENCES caldav_data(dav_id) ON UPDATE CASCADE ON DELETE CASCADE,
 type TEXT,
 email TEXT,
 property TEXT -- The full text of the property
 );
 */
 function WriteEmails($dav_id)
 {
     $emails = $this->GetProperties('EMAIL');
     $qry = new AwlQuery();
     // Only run a local transaction if we're not in one already.
     $in_transaction = $qry->TransactionState() == 1;
     if (!$in_transaction) {
         $qry->Begin();
     }
     $params = array(':dav_id' => $dav_id);
     $qry->QDo('DELETE FROM addressbook_address_email WHERE dav_id = :dav_id', $params);
     foreach ($emails as $email) {
         $params[':type'] = $email->GetParameterValue('TYPE');
         $params[':email'] = $email->Value();
         $params[':property'] = $email->Render();
         $qry->QDo('INSERT INTO addressbook_address_email (dav_id, type, email, property) VALUES( :dav_id, :type, :email, :property)', $params);
     }
     if (!$in_transaction) {
         $qry->Commit();
     }
 }
Exemplo n.º 23
0
 /**
  * Returns the locked row, either from the cache or from the database
  *
  * @param string $dav_name The resource which we want to know the lock status for
  */
 function GetLockRow($lock_token)
 {
     if (isset($this->_locks_found) && isset($this->_locks_found[$lock_token])) {
         return $this->_locks_found[$lock_token];
     }
     $qry = new AwlQuery('SELECT * FROM locks WHERE opaquelocktoken = :lock_token', array(':lock_token' => $lock_token));
     if ($qry->Exec('caldav', __LINE__, __FILE__)) {
         $lock_row = $qry->Fetch();
         $this->_locks_found = array($lock_token => $lock_row);
         return $this->_locks_found[$lock_token];
     } else {
         $this->DoResponse(500, translate("Database Error"));
     }
     return false;
     // Nothing matched
 }
Exemplo n.º 24
0
/**
* Authenticate against a different PostgreSQL database which contains a usr table in
* the AWL format.
*
* Use this as in the following example config snippet:
*
* require_once('auth-functions.php');
*  $c->authenticate_hook = array(
*      'call'   => 'AuthExternalAwl',
*      'config' => array(
*           // A PgSQL database connection string for the database containing user records
*          'connection[]' => 'dbname=wrms host=otherhost port=5433 user=general',
*           // Which columns should be fetched from the database
*          'columns'    => "user_no, active, email_ok, joined, last_update AS updated, last_used, username, password, fullname, email",
*           // a WHERE clause to limit the records returned.
*          'where'    => "active AND org_code=7"
*      )
*  );
*
*/
function AuthExternalAWL($username, $password)
{
    global $c;
    $persistent = isset($c->authenticate_hook['config']['use_persistent']) && $c->authenticate_hook['config']['use_persistent'];
    if (isset($c->authenticate_hook['config']['columns'])) {
        $cols = $c->authenticate_hook['config']['columns'];
    } else {
        $cols = '*';
    }
    if (isset($c->authenticate_hook['config']['where'])) {
        $andwhere = ' AND ' . $c->authenticate_hook['config']['where'];
    } else {
        $andwhere = '';
    }
    $qry = new AwlQuery('SELECT ' . $cols . ' FROM usr WHERE lower(username) = :username ' . $andwhere, array(':username' => strtolower($username)));
    $authconn = $qry->SetConnection($c->authenticate_hook['config']['connection'], $persistent ? array(PDO::ATTR_PERSISTENT => true) : null);
    if (!$authconn) {
        echo <<<EOERRMSG
  <html><head><title>Database Connection Failure</title></head><body>
  <h1>Database Error</h1>
  <h3>Could not connect to PostgreSQL database</h3>
  </body>
  </html>
EOERRMSG;
        exit(1);
    }
    if ($qry->Exec('Login', __LINE__, __FILE__) && $qry->rows() == 1) {
        $usr = $qry->Fetch();
        if (session_validate_password($password, $usr->password)) {
            UpdateUserFromExternal($usr);
            /**
             * We disallow login by inactive users _after_ we have updated the local copy
             */
            if (isset($usr->active) && $usr->active == 'f') {
                return false;
            }
            $qry = new AwlQuery('SELECT * FROM dav_principal WHERE username = :username', array(':username' => $usr->username));
            if ($qry->Exec() && $qry->rows() == 1) {
                $principal = $qry->Fetch();
                return $principal;
            }
            return $usr;
            // Somewhat optimistically
        }
    }
    return false;
}
Exemplo n.º 25
0
/**
* Get XML response for items in the collection
* If '/' is requested, a list of visible users is given, otherwise
* a list of calendars for the user which are parented by this path.
*/
function get_collection_contents($depth, $collection, $parent_path = null)
{
    global $c, $session, $request, $reply, $property_list;
    $bound_from = $collection->bound_from();
    $bound_to = $collection->dav_name();
    if (!isset($parent_path)) {
        $parent_path = $collection->dav_name();
    }
    dbg_error_log('PROPFIND', 'Getting collection contents: Depth %d, Path: %s, Bound from: %s, Bound to: %s', $depth, $collection->dav_name(), $bound_from, $bound_to);
    $date_format = AwlDatabase::HttpDateFormat;
    $responses = array();
    if (!$collection->IsCalendar() && !$collection->IsAddressbook()) {
        /**
         * Calendar/Addressbook collections may not contain collections, so we are only looking in the other ones
         */
        $params = array(':session_principal' => $session->principal_id, ':scan_depth' => $c->permission_scan_depth);
        if ($bound_from == '/') {
            $sql = "SELECT usr.*, '/' || username || '/' AS dav_name, md5(username || updated::text) AS dav_etag, ";
            $sql .= "to_char(joined at time zone 'GMT',{$date_format}) AS created, ";
            $sql .= "to_char(updated at time zone 'GMT',{$date_format}) AS modified, ";
            $sql .= 'FALSE AS is_calendar, TRUE AS is_principal, FALSE AS is_addressbook, \'principal\' AS type, ';
            $sql .= 'principal_id AS collection_id, ';
            $sql .= 'principal.* ';
            $sql .= 'FROM usr JOIN principal USING (user_no) ';
            $sql .= "WHERE (pprivs(:session_principal::int8,principal.principal_id,:scan_depth::int) & 1::BIT(24))::INT4::BOOLEAN ";
            $sql .= 'ORDER BY usr.user_no';
        } else {
            $qry = new AwlQuery('SELECT * FROM dav_binding WHERE dav_binding.parent_container = :this_dav_name ORDER BY bind_id', array(':this_dav_name' => $bound_from));
            if ($qry->Exec('PROPFIND', __LINE__, __FILE__) && $qry->rows() > 0) {
                while ($binding = $qry->Fetch()) {
                    $resource = new DAVResource($binding->dav_name);
                    if ($resource->IsExternal()) {
                        require_once "external-fetch.php";
                        update_external($resource);
                    }
                    if ($resource->HavePrivilegeTo('DAV::read', false)) {
                        $resource->set_bind_location(str_replace($bound_from, $bound_to, $binding->dav_name));
                        $responses[] = $resource->RenderAsXML($property_list, $reply);
                        if ($depth > 0) {
                            $responses = array_merge($responses, get_collection_contents($depth - 1, $resource, $binding->dav_name));
                        }
                    }
                }
            }
            $sql = 'SELECT principal.*, collection.*, \'collection\' AS type ';
            $sql .= 'FROM collection LEFT JOIN principal USING (user_no) ';
            $sql .= 'WHERE parent_container = :this_dav_name ';
            $sql .= ' ORDER BY collection_id';
            $params[':this_dav_name'] = $bound_from;
            unset($params[':session_principal']);
            unset($params[':scan_depth']);
        }
        $qry = new AwlQuery($sql, $params);
        if ($qry->Exec('PROPFIND', __LINE__, __FILE__) && $qry->rows() > 0) {
            while ($subcollection = $qry->Fetch()) {
                $resource = new DAVResource($subcollection);
                if (!$resource->HavePrivilegeTo('DAV::read')) {
                    continue;
                }
                $resource->set_bind_location(str_replace($bound_from, $bound_to, $subcollection->dav_name));
                $responses[] = $resource->RenderAsXML($property_list, $reply);
                if ($depth > 0) {
                    $responses = array_merge($responses, get_collection_contents($depth - 1, $resource, str_replace($resource->parent_path(), $parent_path, $resource->dav_name())));
                }
            }
        }
        if ((!isset($c->disable_caldav_proxy) || $c->disable_caldav_proxy == false) && $collection->IsPrincipal()) {
            // Caldav Proxy: 5.1 par. 2: Add child resources calendar-proxy-(read|write)
            dbg_error_log('PROPFIND', 'Adding calendar-proxy-read and write. Path: %s', $bound_from);
            $response = add_proxy_response('read', $bound_from);
            if (isset($response)) {
                $responses[] = $response;
            }
            $response = add_proxy_response('write', $bound_from);
            if (isset($response)) {
                $responses[] = $response;
            }
        }
    }
    /**
     * freebusy permission is not allowed to see the items in a collection.  Must have at least read permission.
     */
    if ($collection->HavePrivilegeTo('DAV::read', false)) {
        dbg_error_log('PROPFIND', 'Getting collection items: Depth %d, Path: %s', $depth, $bound_from);
        $privacy_clause = ' ';
        $todo_clause = ' ';
        $time_limit_clause = ' ';
        if ($collection->IsCalendar()) {
            if (!$collection->HavePrivilegeTo('all', false)) {
                $privacy_clause = " AND (calendar_item.class != 'PRIVATE' OR calendar_item.class IS NULL) ";
            }
            if (isset($c->hide_TODO) && ($c->hide_TODO === true || is_string($c->hide_TODO) && preg_match($c->hide_TODO, $_SERVER['HTTP_USER_AGENT'])) && !$collection->HavePrivilegeTo('all')) {
                $todo_clause = " AND caldav_data.caldav_type NOT IN ('VTODO') ";
            }
            if (isset($c->hide_older_than) && intval($c->hide_older_than > 0)) {
                $time_limit_clause = " AND (CASE WHEN caldav_data.caldav_type<>'VEVENT' OR calendar_item.dtstart IS NULL THEN true ELSE calendar_item.dtstart > (now() - interval '" . intval($c->hide_older_than) . " days') END) ";
            }
        }
        $sql = 'SELECT collection.*, principal.*, calendar_item.*, caldav_data.*, ';
        $sql .= "to_char(coalesce(calendar_item.created, caldav_data.created) at time zone 'GMT',{$date_format}) AS created, ";
        $sql .= "to_char(coalesce(calendar_item.last_modified, caldav_data.modified) at time zone 'GMT',{$date_format}) AS modified, ";
        $sql .= 'summary AS dav_displayname ';
        $sql .= 'FROM caldav_data LEFT JOIN calendar_item USING( dav_id, user_no, dav_name, collection_id) ';
        $sql .= 'LEFT JOIN collection USING(collection_id,user_no) LEFT JOIN principal USING(user_no) ';
        $sql .= 'WHERE collection.dav_name = :collection_dav_name ' . $time_limit_clause . ' ' . $todo_clause . ' ' . $privacy_clause;
        if (isset($c->strict_result_ordering) && $c->strict_result_ordering) {
            $sql .= " ORDER BY caldav_data.dav_id";
        }
        $qry = new AwlQuery($sql, array(':collection_dav_name' => $bound_from));
        if ($qry->Exec('PROPFIND', __LINE__, __FILE__) && $qry->rows() > 0) {
            while ($item = $qry->Fetch()) {
                if ($bound_from != $bound_to) {
                    $item->bound_from = $item->dav_name;
                    $item->dav_name = str_replace($bound_from, $bound_to, $item->dav_name);
                }
                $resource = new DAVResource($item);
                $responses[] = $resource->RenderAsXML($property_list, $reply, $parent_path);
            }
        }
    }
    return $responses;
}
        $sql = <<<EOSQL
  SELECT collection.*, calendar_item.*, caldav_data.*, addressbook_resource.*, sync_changes.*
    FROM collection LEFT JOIN sync_changes USING(collection_id)
                           LEFT JOIN caldav_data USING (collection_id,dav_id)
                           LEFT JOIN calendar_item USING (collection_id,dav_id)
                           LEFT JOIN addressbook_resource USING (dav_id)
                           WHERE collection.collection_id = :collection_id {$hide_older} {$hide_todo}
         AND sync_time >= (SELECT modification_time FROM sync_tokens WHERE sync_token = :sync_token)
EOSQL;
        if (isset($c->strict_result_ordering) && $c->strict_result_ordering) {
            $sql .= " ORDER BY collection.collection_id, lower(sync_changes.dav_name), sync_changes.sync_time";
        } else {
            $sql .= " ORDER BY collection.collection_id, sync_changes.dav_name, sync_changes.sync_time";
        }
    }
    $qry = new AwlQuery($sql, $params);
    $last_dav_name = '';
    $first_status = 0;
    if ($qry->Exec("REPORT", __LINE__, __FILE__)) {
        if ($qry->rows() > 50) {
            // If there are more than 50 rows to send we should not send full data in response ...
            $c->sync_resource_data_ok = false;
        }
        while ($object = $qry->Fetch()) {
            if ($request_via_binding) {
                $object->dav_name = str_replace($bound_from, $collection_path, $object->dav_name);
            }
            if ($object->dav_name == $last_dav_name) {
                /** The complex case: this is the second or subsequent for this dav_id */
                if ($object->sync_status == 404) {
                    array_pop($responses);
Exemplo n.º 27
0
                break;
            default:
                /**
                 * @todo We should handle a lot more properties here.  principal-URL seems a likely one to be used.
                 * @todo We should catch the unsupported properties in the query and fire back an error indicating so.
                 */
                dbg_error_log("principal", "Unhandled tag '%s' to match '%s'\n", $v1->GetNSTag(), $match);
        }
    }
    if ($subwhere != "") {
        $where .= sprintf("%s(%s)", $where == "" ? "" : $clause_joiner, $subwhere);
    }
}
if ($where != "") {
    $where = "WHERE {$where}";
}
$sql = "SELECT * FROM dav_principal {$where} ORDER BY principal_id LIMIT 100";
$qry = new AwlQuery($sql, $params);
$get_props = $xmltree->GetPath('/DAV::principal-property-search/DAV::prop/*');
$properties = array();
foreach ($get_props as $k1 => $v1) {
    $properties[] = $v1->GetNSTag();
}
if ($qry->Exec("REPORT", __LINE__, __FILE__) && $qry->rows() > 0) {
    while ($row = $qry->Fetch()) {
        $principal = new DAVResource($row);
        $responses[] = $principal->RenderAsXML($properties, $reply);
    }
}
$multistatus = new XMLElement("multistatus", $responses, $reply->GetXmlNsArray());
$request->XMLResponse(207, $multistatus);
Exemplo n.º 28
0
if (is_array($qry_filters)) {
    dbg_log_array('cardquery', 'qry_filters', $qry_filters, true);
    $components = array();
    $filter_fragment = SqlFilterCardDAV($qry_filters, $components);
    if ($filter_fragment !== false) {
        $where .= ' ' . $filter_fragment['sql'];
        $params = $filter_fragment['params'];
    }
} else {
    dbg_error_log('cardquery', 'No query filters');
}
$sql = 'SELECT * FROM caldav_data INNER JOIN addressbook_resource USING(dav_id)' . $where;
if (isset($c->strict_result_ordering) && $c->strict_result_ordering) {
    $sql .= " ORDER BY dav_id";
}
$qry = new AwlQuery($sql, $params);
if ($qry->Exec("cardquery", __LINE__, __FILE__) && $qry->rows() > 0) {
    while ($address_object = $qry->Fetch()) {
        if (!$need_post_filter || apply_filter($qry_filters, $address_object)) {
            if ($bound_from != $target_collection->dav_name()) {
                $address_object->dav_name = str_replace($bound_from, $target_collection->dav_name(), $address_object->dav_name);
            }
            if (count($address_data_properties) > 0) {
                $vcard = new VCard($address_object->caldav_data);
                $vcard->MaskProperties($address_data_properties);
                $address_object->caldav_data = $vcard->Render();
            }
            $responses[] = component_to_xml($properties, $address_object);
        }
    }
}
Exemplo n.º 29
0
         * A fresh lock
         */
        $lock_token = uuid();
        $sql = 'INSERT INTO locks ( dav_name, opaquelocktoken, type, scope, depth, owner, timeout, start )
             VALUES( :dav_name, :lock_token, :type, :scope, :request_depth, :owner, :timeout::interval, current_timestamp )';
        $params = array(':dav_name' => $request->path, ':lock_token' => $lock_token, ':type' => $lockinfo['type'], ':scope' => $lockinfo['scope'], ':request_depth' => $request->depth, ':owner' => $lockinfo['owner'], ':timeout' => $request->timeout . ' seconds');
        header("Lock-Token: <opaquelocktoken:{$lock_token}>");
    }
    $qry = new AwlQuery($sql, $params);
    $qry->Exec("LOCK", __LINE__, __FILE__);
    $lock_row = $request->GetLockRow($lock_token);
    $activelock = array(new XMLElement('locktype', new XMLElement($lock_row->type)), new XMLElement('lockscope', new XMLElement($lock_row->scope)), new XMLElement('depth', $request->GetDepthName()), new XMLElement('owner', new XMLElement('href', $lock_row->owner)), new XMLElement('timeout', 'Second-' . $request->timeout), new XMLElement('locktoken', new XMLElement('href', 'opaquelocktoken:' . $lock_token)));
    $response = new XMLElement("lockdiscovery", new XMLElement("activelock", $activelock), array("xmlns" => "DAV:"));
} elseif ($request->method == "UNLOCK") {
    /**
     * @TODO: respond with preconditionfailed(409,'lock-token-matches-request-uri') if
     * there is no lock to be deleted.
     */
    dbg_error_log("LOCK", "Attempting to unlock resource '%s'", $request->path);
    if ($lock_token = $request->IsLocked()) {
        // NOTE Assignment in if() is expected here.
        $sql = 'DELETE FROM locks WHERE opaquelocktoken = :lock_token';
        $qry = new AwlQuery($sql, array(':lock_token' => $lock_token));
        $qry->Exec("LOCK", __LINE__, __FILE__);
    }
    $request->DoResponse(204);
}
$prop = new XMLElement("prop", $response, array('xmlns' => 'DAV:'));
// dbg_log_array( "LOCK", "XML", $response, true );
$xmldoc = $prop->Render(0, '<?xml version="1.0" encoding="utf-8" ?>');
$request->DoResponse(200, $xmldoc, 'text/xml; charset="utf-8"');
Exemplo n.º 30
0
* we use the xmlns="http://www.xythos.com/namespaces/StorageServer" rather
* than the DAV: namespace.
*
* @package   davical
* @subpackage   caldav
* @author    Andrew McMillan <*****@*****.**>
* @copyright Morphoss Ltd - http://www.morphoss.com/
* @license   http://gnu.org/copyleft/gpl.html GNU GPL v2 or later
*/
dbg_error_log('DELTICKET', 'method handler');
require_once 'DAVResource.php';
if (!$request->HavePrivilegeTo('DAV::unbind') && $request->ticket->owner() != $session->principal_id) {
    $request->NeedPrivilege('DAV::unbind');
}
if (!isset($request->ticket)) {
    if (isset($_GET['ticket']) || isset($_SERVER['HTTP_TICKET'])) {
        $r = new DAVResource($request->path);
        if (!$r->Exists()) {
            $request->PreconditionFailed(404, 'not-found');
        } else {
            $request->PreconditionFailed(412, 'ticket-does-not-exist', 'The specified ticket does not exist');
        }
    } else {
        $request->MalformedRequest('No ticket specified');
    }
}
$qry = new AwlQuery('DELETE FROM access_ticket WHERE ticket_id=:ticket_id', array(':ticket_id' => $request->ticket->id()));
if ($qry->Exec('DELTICKET', __LINE__, __FILE__)) {
    $request->DoResponse(204);
}
$request->DoResponse(500);