Exemplo n.º 1
0
/**
* Check the username / password against the PAM system
*/
function SQUID_PAM_check($username, $password)
{
    global $c;
    $script = $c->authenticate_hook['config']['script'];
    if (empty($script)) {
        $script = $c->authenticate_hook['config']['path'];
    }
    $cmd = sprintf('echo %s %s | %s -n common-auth', escapeshellarg($username), escapeshellarg($password), $script);
    $auth_result = exec($cmd);
    if ($auth_result == "OK") {
        dbg_error_log('pwauth', 'User %s successfully authenticated', $username);
        $principal = new Principal('username', $username);
        if (!$principal->Exists()) {
            dbg_error_log('pwauth', 'User %s does not exist in local db, creating', $username);
            $pwent = posix_getpwnam($username);
            $gecos = explode(',', $pwent['gecos']);
            $fullname = $gecos[0];
            $principal->Create(array('username' => $username, 'user_active' => 't', 'email' => sprintf('%s@%s', $username, $email_base), 'fullname' => $fullname));
            if (!$principal->Exists()) {
                dbg_error_log("PAM", "Unable to create local principal for '%s'", $username);
                return false;
            }
            CreateHomeCalendar($username);
        }
        return $principal;
    } else {
        dbg_error_log("PAM", "User %s is not a valid username (or password was wrong)", $username);
        return false;
    }
}
Exemplo n.º 2
0
/**
* Check the username / password against the PAM system
*/
function SQUID_PAM_check($username, $password)
{
    global $c;
    /**
     * @todo Think of the children!  This is a horribly insecure use of unvalidated user input!  Probably it should be done with a popen or something, and it seems remarkably dodgy to expect that naively quoted strings will work in any way reliably.
     * Meanwhile, I've quickly hacked something basic in place to improve the situation.  No quotes/backslashes in passwords for YOU!
     */
    $username = str_replace("'", "", str_replace('"', "", str_replace('\\', "", $username)));
    $password = str_replace("'", "", str_replace('"', "", str_replace('\\', "", $password)));
    $cmd = "echo '" . $username . "' '" . $password . "' | " . $c->authenticate_hook['config']['script'] . " -n common-auth";
    $auth_result = exec($cmd);
    if ($auth_result == "OK") {
        if ($usr = getUserByName($username)) {
            return $usr;
        } else {
            dbg_error_log("PAM", "user %s doesn't exist in local DB, we need to create it", $username);
            $fullname = exec('getent passwd "' . $username . '"');
            $fullname = preg_replace('{^[^:]+:[^:]+:\\d+:\\d+:([^:,]+)(,?[^:]*):.*$}', '$1', $fullname);
            $usr = (object) array('user_no' => 0, 'username' => $username, 'active' => 't', 'email' => $username . "@" . $c->authenticate_hook['config']['email_base'], 'updated' => date(), 'fullname' => $fullname);
            UpdateUserFromExternal($usr);
            return $usr;
        }
    } else {
        dbg_error_log("PAM", "User %s is not a valid username (or password was wrong)", $username);
        return false;
    }
}
Exemplo n.º 3
0
 /**
  * CheckPassword does all of the password checking and
  * returns a user record object, or false if it all ends in tears.
  */
 function CheckPassword($username, $password)
 {
     $qry = new PgQuery("SELECT * FROM usr WHERE lower(username) = ? ", $username);
     if ($qry->Exec('BasicAuthSession', __LINE, __FILE__) && $qry->rows == 1) {
         $usr = $qry->Fetch();
         dbg_error_log("BasicAuthSession", "Name:%s, Pass:%s, File:%s", $username, $password, $usr->password);
         if (session_validate_password($password, $usr->password)) {
             return $usr;
         }
     }
     return false;
 }
Exemplo n.º 4
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.º 5
0
/**
* Check the username / password against the PAM system
*/
function IMAP_PAM_check($username, $password)
{
    global $c;
    $imap_username = $username;
    if (function_exists('mb_convert_encoding')) {
        $imap_username = mb_convert_encoding($imap_username, "UTF7-IMAP", mb_detect_encoding($imap_username));
    } else {
        $imap_username = imap_utf7_encode($imap_username);
    }
    //$imap_url = '{localhost:143/imap/notls}';
    //$imap_url = '{localhost:993/imap/ssl/novalidate-cert}';
    $imap_url = $c->authenticate_hook['config']['imap_url'];
    $auth_result = "ERR";
    $imap_stream = @imap_open($imap_url, $imap_username, $password, OP_HALFOPEN);
    //print_r(imap_errors());
    if ($imap_stream) {
        // disconnect
        imap_close($imap_stream);
        // login ok
        $auth_result = "OK";
    }
    if ($auth_result == "OK") {
        $principal = new Principal('username', $username);
        if (!$principal->Exists()) {
            dbg_error_log("PAM", "Principal '%s' doesn't exist in local DB, we need to create it", $username);
            $cmd = "getent passwd '{$username}'";
            $getent_res = exec($cmd);
            $getent_arr = explode(":", $getent_res);
            $fullname = $getent_arr[4];
            if (empty($fullname)) {
                $fullname = $username;
            }
            $principal->Create(array('username' => $username, 'user_active' => true, 'email' => $username . "@" . $c->authenticate_hook['config']['email_base'], 'modified' => date('c'), 'fullname' => $fullname));
            if (!$principal->Exists()) {
                dbg_error_log("PAM", "Unable to create local principal for '%s'", $username);
                return false;
            }
            CreateHomeCalendar($username);
        }
        return $principal;
    } else {
        dbg_error_log("PAM", "User %s is not a valid username (or password was wrong)", $username);
        return false;
    }
}
Exemplo n.º 6
0
function logRequestHeaders()
{
    global $c;
    /** Log the request headers */
    $lines = apache_request_headers();
    dbg_error_log("LOG ", "***************** Request Header ****************");
    dbg_error_log("LOG ", "%s %s", $_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);
    foreach ($lines as $k => $v) {
        if ($k != 'Authorization' || isset($c->dbg['password']) && $c->dbg['password']) {
            dbg_error_log("LOG headers", "-->%s: %s", $k, $v);
        } else {
            dbg_error_log("LOG headers", "-->%s: %s", $k, 'Delicious tasty password eaten by debugging monster!');
        }
    }
    dbg_error_log("LOG ", "******************** Request ********************");
    // Log the request in all it's gory detail.
    $lines = preg_split('#[\\r\\n]+#', $c->raw_post);
    foreach ($lines as $v) {
        dbg_error_log("LOG request", "-->%s", $v);
    }
    unset($lines);
}
Exemplo n.º 7
0
 public function __construct($in_dtz = null)
 {
     $this->tz_defined = false;
     if (!isset($in_dtz)) {
         return;
     }
     $olson = olson_from_tzstring($in_dtz);
     if (isset($olson)) {
         try {
             parent::__construct($olson);
             $this->tz_defined = $olson;
         } catch (Exception $e) {
             dbg_error_log('ERROR', 'Could not handle timezone "%s" (%s) - will use floating time', $in_dtz, $olson);
             parent::__construct('UTC');
             $this->tz_defined = false;
         }
     } else {
         dbg_error_log('ERROR', 'Could not recognize timezone "%s" - will use floating time', $in_dtz);
         parent::__construct('UTC');
         $this->tz_defined = false;
     }
 }
Exemplo n.º 8
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.º 9
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;
}
Exemplo n.º 10
0
<?php

/**
* CalDAV Server - handle PUT method
*
* @package   davical
* @subpackage   caldav
* @author    Andrew McMillan <*****@*****.**>
* @copyright Catalyst .Net Ltd, Morphoss Ltd
* @license   http://gnu.org/copyleft/gpl.html GNU GPL v2 or later
*/
dbg_error_log("PUT", "method handler");
require_once 'DAVResource.php';
$dav_resource = new DAVResource($request->path);
if (!$dav_resource->HavePrivilegeTo('DAV::write-content')) {
    $request->DoResponse(403);
}
if (!$dav_resource->Exists() && !$dav_resource->HavePrivilegeTo('DAV::bind')) {
    $request->DoResponse(403);
}
if (!ini_get('open_basedir') && (isset($c->dbg['ALL']) || isset($c->dbg['put']) && $c->dbg['put'])) {
    $fh = fopen('/tmp/PUT.txt', 'w');
    if ($fh) {
        fwrite($fh, $request->raw_post);
        fclose($fh);
    }
}
include_once 'caldav-PUT-functions.php';
controlRequestContainer($dav_resource->GetProperty('username'), $dav_resource->GetProperty('user_no'), $dav_resource->bound_from(), true);
$lock_opener = $request->FailIfLocked();
if ($dav_resource->IsCollection()) {
Exemplo n.º 11
0
 /**
  * Returns the footer we always use at the finish of our iCalendar resources
  *
  * @deprecated This function is deprecated and will be removed eventually.
  * @todo Remove this function.
  */
 function iCalFooter()
 {
     dbg_error_log("LOG", " iCalendar: Call to deprecated method '%s'", 'iCalFooter');
     return "END:VCALENDAR\r\n";
 }
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');
    dbg_error_log("ERROR", "Creating ticketrow editor: %s - %s", $can_write_principal, $ticketrow->IsSubmit());
    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 = clean_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
function check_string($ics)
{
    $ics_file = explode("\n", $ics);
    foreach ($ics_file as $line => $str) {
        if (false === utf8ToUnicode($str)) {
            $error[] = $line;
        }
    }
    if (isset($error) && is_array($error)) {
        foreach ($error as $line) {
            dbg_error_log("LOG check_string", "error on lines %  invalid character in string %s", $line + 1, $ics_file[$line]);
            return false;
        }
    } else {
        dbg_error_log("LOG check_string", "the string is UTF8 compliant");
        return true;
    }
}
Exemplo n.º 14
0
/**
* Update the local cache of the remote user details
* @param object $usr The user details we read from the remote.
*/
function UpdateUserFromExternal(&$usr)
{
    global $c;
    /**
     * When we're doing the create we will usually need to generate a user number
     */
    if (!isset($usr->user_no) || intval($usr->user_no) == 0) {
        $qry = new AwlQuery("SELECT nextval('usr_user_no_seq');");
        $qry->Exec('Login', __LINE__, __FILE__);
        $sequence_value = $qry->Fetch(true);
        // Fetch as an array
        $usr->user_no = $sequence_value[0];
    }
    $qry = new AwlQuery('SELECT * FROM usr WHERE user_no = :user_no', array(':user_no' => $usr->user_no));
    if ($qry->Exec('Login', __LINE__, __FILE__) && $qry->rows() == 1) {
        $type = "UPDATE";
        if ($old = $qry->Fetch()) {
            $changes = false;
            foreach ($usr as $k => $v) {
                if ($old->{$k} != $v) {
                    $changes = true;
                    dbg_error_log("Login", "User '%s' field '%s' changed from '%s' to '%s'", $usr->username, $k, $old->{$k}, $v);
                    break;
                }
            }
            if (!$changes) {
                dbg_error_log("Login", "No changes to user record for '%s' - leaving as-is.", $usr->username);
                if (isset($usr->active) && $usr->active == 'f') {
                    return false;
                }
                return;
                // Normal case, if there are no changes
            } else {
                dbg_error_log("Login", "Changes to user record for '%s' - updating.", $usr->username);
            }
        }
    } else {
        $type = "INSERT";
    }
    $params = array();
    if ($type != 'INSERT') {
        $params[':user_no'] = $usr->user_no;
    }
    $qry = new AwlQuery(sql_from_object($usr, $type, 'usr', 'WHERE user_no= :user_no'), $params);
    $qry->Exec('Login', __LINE__, __FILE__);
    /**
     * We disallow login by inactive users _after_ we have updated the local copy
     */
    if (isset($usr->active) && ($usr->active === 'f' || $usr->active === false)) {
        return false;
    }
    if ($type == 'INSERT') {
        $qry = new AwlQuery('INSERT INTO principal( type_id, user_no, displayname, default_privileges) SELECT 1, user_no, fullname, :privs::INT::BIT(24) FROM usr WHERE username=:username', array(':privs' => privilege_to_bits($c->default_privileges), ':username' => $usr->username));
        $qry->Exec('Login', __LINE__, __FILE__);
        CreateHomeCalendar($usr->username);
    } else {
        if ($usr->fullname != $old->{'fullname'}) {
            // Also update the displayname if the fullname has been updated.
            $qry->QDo('UPDATE principal SET displayname=:new_display WHERE user_no=:user_no', array(':new_display' => $usr->fullname, ':user_no' => $usr->user_no));
        }
    }
}
Exemplo n.º 15
0
*
* Why are we using a defunct RFC?  Well, we want to support some kind of system
* for providing a URI to people to give out for granting privileged access
* without requiring logins.  Using a defunct proposed spec seems better than
* inventing our own.  As well as Xythos, Cosmo follows this specification,
* with some documented variations, which we will also follow.  In particular
* 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('MKTICKET', 'method handler');
require_once 'DAVResource.php';
$request->NeedPrivilege('DAV::bind');
require_once 'XMLDocument.php';
$reply = new XMLDocument(array('DAV:' => '', 'http://www.xythos.com/namespaces/StorageServer' => 'T'));
$target = new DAVResource($request->path);
if (!$target->Exists()) {
    $request->XMLResponse(404, new XMLElement('error', new XMLElement('resource-must-not-be-null'), $reply->GetXmlNsArray()));
}
if (!isset($request->xml_tags)) {
    $request->XMLResponse(400, new XMLElement('error', new XMLElement('missing-xml-for-request'), $reply->GetXmlNsArray()));
}
$xmltree = BuildXMLTree($request->xml_tags, $position);
if ($xmltree->GetTag() != 'http://www.xythos.com/namespaces/StorageServer:ticketinfo' && $xmltree->GetTag() != 'DAV::ticketinfo') {
    $request->XMLResponse(400, new XMLElement('error', new XMLElement('invalid-xml-for-request'), $reply->GetXmlNsArray()));
}
    } else {
        $sync_level = 1;
    }
}
if ($sync_level == DEPTH_INFINITY) {
    $request->PreconditionFailed(403, 'DAV::sync-traversal-supported', 'This server does not support sync-traversal');
}
$sync_tokens = $xmltree->GetPath('/DAV::sync-collection/DAV::sync-token');
if (isset($sync_tokens[0])) {
    $sync_token = $sync_tokens[0]->GetContent();
}
if (!isset($sync_token)) {
    $sync_token = 0;
}
$sync_token = intval(str_ireplace('data:,', '', $sync_token));
dbg_error_log('sync', " sync-token: %s", $sync_token);
$proplist = array();
$props = $xmltree->GetPath('/DAV::sync-collection/DAV::prop/*');
if (!empty($props)) {
    foreach ($props as $k => $v) {
        $proplist[] = $v->GetNSTag();
    }
}
function display_status($status_code)
{
    return sprintf('HTTP/1.1 %03d %s', intval($status_code), getStatusMessage($status_code));
}
$collection = new DAVResource($request->path);
if (!$collection->Exists()) {
    $request->DoResponse(404);
}
Exemplo n.º 17
0
<?php

/**
* CalDAV Server - handle GET method
*
* @package   davical
* @subpackage   caldav
* @author    Andrew McMillan <*****@*****.**>
* @copyright Catalyst .Net Ltd, Morphoss Ltd <http://www.morphoss.com/>
* @license   http://gnu.org/copyleft/gpl.html GNU GPL v2 or later
*/
dbg_error_log("get", "GET method handler");
require_once "iCalendar.php";
require_once "DAVResource.php";
$dav_resource = new DAVResource($request->path);
$dav_resource->NeedPrivilege(array('urn:ietf:params:xml:ns:caldav:read-free-busy', 'DAV::read'));
if (!$dav_resource->Exists()) {
    $request->DoResponse(404, translate("Resource Not Found."));
}
function obfuscated_event($icalendar)
{
    // The user is not admin / owner of this calendar looking at his calendar and can not admin the other cal,
    // or maybe they don't have *read* access but they got here, so they must at least have free/busy access
    // so we will present an obfuscated version of the event that just says "Busy" (translated :-)
    $confidential = new iCalComponent();
    $confidential->SetType($icalendar->GetType());
    $confidential->AddProperty('SUMMARY', translate('Busy'));
    $confidential->AddProperty('CLASS', 'CONFIDENTIAL');
    $confidential->SetProperties($icalendar->GetProperties('DTSTART'), 'DTSTART');
    $confidential->SetProperties($icalendar->GetProperties('RRULE'), 'RRULE');
    $confidential->SetProperties($icalendar->GetProperties('DURATION'), 'DURATION');
Exemplo n.º 18
0
 /**
  * The constructor takes a start date and an RRULE definition.  Both of these
  * follow the iCalendar standard.
  */
 function RRule($start, $rrule)
 {
     $this->_first = new iCalDate($start);
     $this->_finished = false;
     $this->_started = false;
     $this->_dates = array();
     $this->_current = -1;
     $this->_rule = preg_replace('/\\s/m', '', $rrule);
     if (substr($this->_rule, 0, 6) == 'RRULE:') {
         $this->_rule = substr($this->_rule, 6);
     }
     dbg_error_log("RRule", " new RRule: Start: %s, RRULE: %s", $start->Render(), $this->_rule);
     $parts = explode(';', $this->_rule);
     $this->_part = array('INTERVAL' => 1);
     foreach ($parts as $k => $v) {
         list($type, $value) = explode('=', $v, 2);
         //      dbg_error_log( "RRule", " Parts of %s explode into %s and %s", $v, $type, $value );
         $this->_part[$type] = $value;
     }
     // A little bit of validation
     if (!isset($this->_part['FREQ'])) {
         dbg_error_log("ERROR", " RRULE MUST have FREQ=value (%s)", $rrule);
     }
     if (isset($this->_part['COUNT']) && isset($this->_part['UNTIL'])) {
         dbg_error_log("ERROR", " RRULE MUST NOT have both COUNT=value and UNTIL=value (%s)", $rrule);
     }
     if (isset($this->_part['COUNT']) && intval($this->_part['COUNT']) < 1) {
         dbg_error_log("ERROR", " RRULE MUST NOT have both COUNT=value and UNTIL=value (%s)", $rrule);
     }
     if (!preg_match('/(YEAR|MONTH|WEEK|DAI)LY/', $this->_part['FREQ'])) {
         dbg_error_log("ERROR", " RRULE Only FREQ=(YEARLY|MONTHLY|WEEKLY|DAILY) are supported at present (%s)", $rrule);
     }
     if ($this->_part['FREQ'] == "YEARLY") {
         $this->_part['INTERVAL'] *= 12;
         $this->_part['FREQ'] = "MONTHLY";
     }
 }
Exemplo n.º 19
0
function handle_subaction($subaction)
{
    global $session, $c, $id, $editor;
    global $delete_collection_confirmation_required;
    global $delete_principal_confirmation_required;
    global $delete_ticket_confirmation_required;
    global $delete_bind_in_confirmation_required;
    global $delete_binding_confirmation_required;
    dbg_error_log('admin-principal-edit', ':handle_action: Action %s', $subaction);
    switch ($subaction) {
        case 'delete_collection':
            dbg_error_log('admin-principal-edit', ':handle_action: Deleting collection %s for principal %d', $_GET['dav_name'], $id);
            if ($session->AllowedTo('Admin') || $id > 0 && $session->principal_id == $id) {
                if ($session->CheckConfirmationHash('GET', 'confirm')) {
                    dbg_error_log('admin-principal-edit', ':handle_action: Allowed to delete collection %s for principal %d', $_GET['dav_name'], $id);
                    $qry = new AwlQuery('DELETE FROM collection WHERE dav_name=?;', $_GET['dav_name']);
                    if ($qry->Exec()) {
                        $c->messages[] = i18n('Collection deleted');
                        return true;
                    } else {
                        $c->messages[] = i18n('There was an error writing to the database.');
                        return false;
                    }
                } else {
                    $c->messages[] = i18n('Please confirm deletion of collection - see below');
                    $delete_collection_confirmation_required = $session->BuildConfirmationHash('GET', 'confirm');
                    return false;
                }
            }
            break;
        case 'delete_principal':
            dbg_error_log('admin-principal-edit', ':handle_action: Deleting principal %d', $id);
            if ($session->AllowedTo('Admin')) {
                if (isset($id) && $id > 1 && $session->CheckConfirmationHash('GET', 'confirm')) {
                    dbg_error_log('admin-principal-edit', ':handle_action: Allowed to delete principal %d -%s', $id);
                    $qry = new AwlQuery('DELETE FROM dav_principal WHERE principal_id=?', $id);
                    if ($qry->Exec()) {
                        $c->messages[] = i18n('Principal deleted');
                        return true;
                    } else {
                        $c->messages[] = i18n('There was an error writing to the database.');
                        return false;
                    }
                } else {
                    $c->messages[] = i18n('Please confirm deletion of the principal');
                    $delete_principal_confirmation_required = $session->BuildConfirmationHash('GET', 'confirm');
                    return false;
                }
            }
            break;
        case 'delete_ticket':
            dbg_error_log('admin-principal-edit', ':handle_action: Deleting ticket "%s" for principal %d', $_GET['ticket_id'], $id);
            if ($session->AllowedTo('Admin') || $id > 0 && $session->principal_id == $id) {
                if ($session->CheckConfirmationHash('GET', 'confirm')) {
                    dbg_error_log('admin-principal-edit', ':handle_action: Allowed to delete ticket "%s" for principal %d', $_GET['ticket_id'], $id);
                    $qry = new AwlQuery('DELETE FROM access_ticket WHERE ticket_id=?;', $_GET['ticket_id']);
                    if ($qry->Exec()) {
                        $c->messages[] = i18n('Access ticket deleted');
                        return true;
                    } else {
                        $c->messages[] = i18n('There was an error writing to the database.');
                        return false;
                    }
                } else {
                    $c->messages[] = i18n('Please confirm deletion of access ticket - see below');
                    $delete_ticket_confirmation_required = $session->BuildConfirmationHash('GET', 'confirm');
                    return false;
                }
            }
            break;
        case 'delete_bind_in':
        case 'delete_binding':
            dbg_error_log('admin-principal-edit', ':handle_action: Deleting binding "%s" for principal %d', $_GET['bind_id'], $id);
            if ($session->AllowedTo('Admin') || $id > 0 && $session->principal_id == $id) {
                if ($session->CheckConfirmationHash('GET', 'confirm')) {
                    dbg_error_log('admin-principal-edit', ':handle_action: Allowed to delete ticket "%s" for principal %d', $_GET['bind_id'], $id);
                    $qry = new AwlQuery('DELETE FROM dav_binding WHERE bind_id=?;', $_GET['bind_id']);
                    if ($qry->Exec()) {
                        $c->messages[] = i18n('Binding deleted');
                        return true;
                    } else {
                        $c->messages[] = i18n('There was an error writing to the database.');
                        return false;
                    }
                } else {
                    $c->messages[] = i18n('Please confirm deletion of binding - see below');
                    if ($subaction == 'delete_bind_in') {
                        $delete_bind_in_confirmation_required = $session->BuildConfirmationHash('GET', 'confirm');
                    } else {
                        $delete_binding_confirmation_required = $session->BuildConfirmationHash('GET', 'confirm');
                    }
                    return false;
                }
            }
            break;
        default:
            return false;
    }
    return false;
}
Exemplo n.º 20
0
function SqlFilterCardDAV($filter, $components, $property = null, $parameter = null)
{
    global $need_post_filter, $target_collection, $matchnum;
    $sql = "";
    $params = array();
    if (!is_array($filter)) {
        dbg_error_log("cardquery", "Filter is of type '%s', but should be an array of XML Tags.", gettype($filter));
    }
    foreach ($filter as $k => $v) {
        $tag = $v->GetTag();
        dbg_error_log("cardquery", "Processing {$tag} into SQL - %d, '%s', %d\n", count($components), $property, isset($parameter));
        $not_defined = "";
        switch ($tag) {
            case 'urn:ietf:params:xml:ns:carddav:text-match':
                $search = $v->GetContent();
                $negate = $v->GetAttribute("negate-condition");
                $collation = $v->GetAttribute("collation");
                switch (strtolower($collation)) {
                    case 'i;octet':
                        $comparison = 'LIKE';
                        break;
                    case 'i;ascii-casemap':
                    case 'i;unicode-casemap':
                    default:
                        $comparison = 'ILIKE';
                        break;
                }
                $pname = ':text_match_' . $matchnum++;
                $params[$pname] = '%' . $search . '%';
                dbg_error_log("cardquery", " text-match: (%s%s %s '%s') ", isset($negate) && strtolower($negate) == "yes" ? "NOT " : "", $property, $comparison, $params[$pname]);
                $sql .= sprintf("AND (%s%s %s {$pname}) ", isset($negate) && strtolower($negate) == "yes" ? "NOT " : "", $property, $comparison);
                break;
            case 'urn:ietf:params:xml:ns:carddav:prop-filter':
                $propertyname = $v->GetAttribute("name");
                switch ($propertyname) {
                    case 'VERSION':
                    case 'UID':
                    case 'NICKNAME':
                    case 'FN':
                    case 'NOTE':
                    case 'ORG':
                    case 'URL':
                    case 'FBURL':
                    case 'CALADRURI':
                    case 'CALURI':
                        $property = strtolower($propertyname);
                        break;
                    case 'N':
                        $property = 'name';
                        break;
                    default:
                        $need_post_filter = true;
                        dbg_error_log("cardquery", "Could not handle 'prop-filter' on %s in SQL", $propertyname);
                        continue;
                }
                $subfilter = $v->GetContent();
                $success = SqlFilterCardDAV($subfilter, $components, $property, $parameter);
                if ($success === false) {
                    continue;
                } else {
                    $sql .= $success['sql'];
                    $params = array_merge($params, $success['params']);
                }
                break;
            case 'urn:ietf:params:xml:ns:carddav:param-filter':
                $need_post_filter = true;
                return false;
                /** Figure out how to handle PARAM-FILTER conditions in the SQL */
                /*
                $parameter = $v->GetAttribute("name");
                $subfilter = $v->GetContent();
                $success = SqlFilterCardDAV( $subfilter, $components, $property, $parameter );
                if ( $success === false ) continue; else {
                  $sql .= $success['sql'];
                  $params = array_merge( $params, $success['params'] );
                }
                break;
                */
            /** Figure out how to handle PARAM-FILTER conditions in the SQL */
            /*
            $parameter = $v->GetAttribute("name");
            $subfilter = $v->GetContent();
            $success = SqlFilterCardDAV( $subfilter, $components, $property, $parameter );
            if ( $success === false ) continue; else {
              $sql .= $success['sql'];
              $params = array_merge( $params, $success['params'] );
            }
            break;
            */
            default:
                dbg_error_log("cardquery", "Could not handle unknown tag '%s' in calendar query report", $tag);
                break;
        }
    }
    dbg_error_log("cardquery", "Generated SQL was '%s'", $sql);
    return array('sql' => $sql, 'params' => $params);
}
Exemplo n.º 21
0
 /**
  * @DEPRECATED: This class will be removed soon.
  * Applies the filter conditions, possibly recursively, to the value which will be either
  * a single property, or an array of lines of the component under test.
  *
  * @todo Eventually we need to handle all of these possibilities, which will mean writing
  * several routines:
  *  - Get Property from Component
  *  - Get Parameter from Property
  *  - Test TimeRange
  * For the moment we will leave these, until there is a perceived need.
  *
  * @param array $filter An array of XMLElement defining the filter(s)
  * @param mixed $value Either a string which is the single property, or an array of lines, for the component.
  * @return boolean Whether the filter passed / failed.
  */
 function ApplyFilter($filter, $value)
 {
     deprecated('iCalendar::ApplyFilter');
     foreach ($filter as $k => $v) {
         $tag = $v->GetTag();
         $value_type = gettype($value);
         $value_defined = isset($value) && $value_type == 'string' || $value_type == 'array' && count($value) > 0;
         if ($tag == 'urn:ietf:params:xml:ns:caldav:is-not-defined' && $value_defined) {
             dbg_error_log('iCalendar', ":ApplyFilter: Value is set ('%s'), want unset, for filter %s", count($value), $tag);
             return false;
         } elseif ($tag == 'urn:ietf:params:xml:ns:caldav:is-defined' && !$value_defined) {
             dbg_error_log('iCalendar', ":ApplyFilter: Want value, but it is not set for filter %s", $tag);
             return false;
         } else {
             switch ($tag) {
                 case 'urn:ietf:params:xml:ns:caldav:time-range':
                     /** todo:: While this is unimplemented here at present, most time-range tests should occur at the SQL level. */
                     break;
                 case 'urn:ietf:params:xml:ns:caldav:text-match':
                     $search = $v->GetContent();
                     // In this case $value will either be a string, or an array of iCalProp objects
                     // since TEXT-MATCH does not apply to COMPONENT level - only property/parameter
                     if (gettype($value) != 'string') {
                         if (gettype($value) == 'array') {
                             $match = false;
                             foreach ($value as $k1 => $v1) {
                                 // $v1 could be an iCalProp object
                                 if ($match = $v1->TextMatch($search)) {
                                     break;
                                 }
                             }
                         } else {
                             dbg_error_log('iCalendar', ":ApplyFilter: TEXT-MATCH will only work on strings or arrays of iCalProp.  %s unsupported", gettype($value));
                             return true;
                             // We return _true_ in this case, so the client sees the item
                         }
                     } else {
                         $match = strstr($value, $search[0]);
                     }
                     $negate = $v->GetAttribute("negate-condition");
                     if (isset($negate) && strtolower($negate) == "yes" && $match) {
                         dbg_error_log('iCalendar', ":ApplyFilter: TEXT-MATCH of %s'%s' against '%s'", isset($negate) && strtolower($negate) == "yes" ? '!' : '', $search, $value);
                         return false;
                     }
                     break;
                 case 'urn:ietf:params:xml:ns:caldav:comp-filter':
                     $subfilter = $v->GetContent();
                     $component = $this->ExtractSubComponent($value, $v->GetAttribute("name"));
                     if (!$this->ApplyFilter($subfilter, $component)) {
                         return false;
                     }
                     break;
                 case 'urn:ietf:params:xml:ns:caldav:prop-filter':
                     $subfilter = $v->GetContent();
                     $properties = $this->ExtractProperty($value, $v->GetAttribute("name"));
                     if (!$this->ApplyFilter($subfilter, $properties)) {
                         return false;
                     }
                     break;
                 case 'urn:ietf:params:xml:ns:caldav:param-filter':
                     $subfilter = $v->GetContent();
                     $parameter = $this->ExtractParameter($value, $v->GetAttribute("NAME"));
                     if (!$this->ApplyFilter($subfilter, $parameter)) {
                         return false;
                     }
                     break;
             }
         }
     }
     return true;
 }
Exemplo n.º 22
0
if ($c->enable_scheduling != true) {
    $request->DoResponse(404, translate('The application program does not understand that request.'));
    // Does not return
}
dbg_log_array('well-known', 'method:' . $request->method);
switch ($request->method) {
    case 'GET':
        ischedule_get();
        break;
    case 'POST':
        include 'iSchedule-POST.php';
        break;
    default:
        dbg_error_log('well-known', 'Unhandled request method >>%s<<', $request->method);
        dbg_log_array('well-known', '_SERVER', $_SERVER, true);
        dbg_error_log('well-known', 'RAW: %s', str_replace("\n", '', str_replace("\r", '', $request->raw_post)));
}
$request->DoResponse(500, translate('The application program does not understand that request.'));
function ischedule_get()
{
    global $request, $c;
    if ($request->path != '/.well-known/ischedule' || $_GET['query'] != 'capabilities') {
        $request->DoResponse(404, translate('The application program does not understand that request.' . $request->path));
        return false;
    }
    header('iSchedule-Version: 1.0');
    header('Content-Type: application/xml; charset=utf-8');
    echo '<?xml version="1.0" encoding="utf-8" ?>';
    echo <<<RESPONSE
  <query-result xmlns="urn:ietf:params:xml:ns:ischedule">
    <capability-set>
Exemplo n.º 23
0
 /**
  * Checks whether a user is allowed to do something.
  *
  * The check is performed to see if the user has that role.
  *
  * @param string $whatever The role we want to know if the user has.
  * @return boolean Whether or not the user has the specified role.
  */
 function AllowedTo($whatever)
 {
     dbg_error_log('session', 'Checking whether "Public" is allowed to "%s"', $whatever);
     return isset($this->roles[$whatever]) && $this->roles[$whatever];
 }
Exemplo n.º 24
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.º 25
0
/**
* Return XML for a single component from the DB
*
* @param array $properties The properties for this component
* @param string $item The DB row data for this component
*
* @return string An XML document which is the response for the component
*/
function component_to_xml($properties, $item)
{
    global $session, $c, $request, $reply;
    dbg_error_log("REPORT", "Building XML Response for item '%s'", $item->dav_name);
    $denied = array();
    $unsupported = array();
    $caldav_data = $item->caldav_data;
    $displayname = preg_replace('{^.*/}', '', $item->dav_name);
    $type = 'unknown';
    $contenttype = 'text/plain';
    switch ($item->caldav_type) {
        case 'VJOURNAL':
        case 'VEVENT':
        case 'VTODO':
            $displayname = $item->summary;
            $type = 'calendar';
            $contenttype = 'text/calendar';
            break;
        case 'VCARD':
            $displayname = $item->fn;
            $type = 'vcard';
            $contenttype = 'text/vcard';
            break;
    }
    if (isset($properties['calendar-data']) || isset($properties['displayname'])) {
        if (!$request->AllowedTo('all') && $session->user_no != $item->user_no) {
            // the user is not admin / owner of this calendarlooking at his calendar and can not admin the other cal
            /** @todo We should examine the ORGANIZER and ATTENDEE fields in the event.  If this person is there then they should see this */
            if ($type == 'calendar' && $item->class == 'CONFIDENTIAL' || !$request->AllowedTo('read')) {
                $ical = new iCalComponent($caldav_data);
                $resources = $ical->GetComponents('VTIMEZONE', false);
                $first = $resources[0];
                // if the event is confidential we fake one that just says "Busy"
                $confidential = new iCalComponent();
                $confidential->SetType($first->GetType());
                $confidential->AddProperty('SUMMARY', translate('Busy'));
                $confidential->AddProperty('CLASS', 'CONFIDENTIAL');
                $confidential->SetProperties($first->GetProperties('DTSTART'), 'DTSTART');
                $confidential->SetProperties($first->GetProperties('RRULE'), 'RRULE');
                $confidential->SetProperties($first->GetProperties('DURATION'), 'DURATION');
                $confidential->SetProperties($first->GetProperties('DTEND'), 'DTEND');
                $confidential->SetProperties($first->GetProperties('UID'), 'UID');
                $ical->SetComponents(array($confidential), $confidential->GetType());
                $caldav_data = $ical->Render();
                $displayname = translate('Busy');
            }
        }
    }
    $url = ConstructURL($item->dav_name);
    $prop = new XMLElement("prop");
    foreach ($properties as $k => $v) {
        switch ($k) {
            case 'getcontentlength':
                $contentlength = strlen($caldav_data);
                $prop->NewElement($k, $contentlength);
                break;
            case 'getlastmodified':
                $prop->NewElement($k, ISODateToHTTPDate($item->modified));
                break;
            case 'calendar-data':
                if ($type == 'calendar') {
                    $reply->CalDAVElement($prop, $k, $caldav_data);
                } else {
                    $unsupported[] = $k;
                }
                break;
            case 'address-data':
                if ($type == 'vcard') {
                    $reply->CardDAVElement($prop, $k, $caldav_data);
                } else {
                    $unsupported[] = $k;
                }
                break;
            case 'getcontenttype':
                $prop->NewElement($k, $contenttype);
                break;
            case 'current-user-principal':
                $prop->NewElement("current-user-principal", $request->current_user_principal_xml);
                break;
            case 'displayname':
                $prop->NewElement($k, $displayname);
                break;
            case 'resourcetype':
                $prop->NewElement($k);
                // Just an empty resourcetype for a non-collection.
                break;
            case 'getetag':
                $prop->NewElement($k, '"' . $item->dav_etag . '"');
                break;
            case '"current-user-privilege-set"':
                $prop->NewElement($k, privileges($request->permissions));
                break;
            case 'SOME-DENIED-PROPERTY':
                /** indicating the style for future expansion */
                $denied[] = $k;
                break;
            default:
                dbg_error_log('REPORT', "Request for unsupported property '%s' of calendar item.", $v);
                $unsupported[] = $k;
        }
    }
    $status = new XMLElement("status", "HTTP/1.1 200 OK");
    $propstat = new XMLElement("propstat", array($prop, $status));
    $href = new XMLElement("href", $url);
    $elements = array($href, $propstat);
    if (count($denied) > 0) {
        $status = new XMLElement("status", "HTTP/1.1 403 Forbidden");
        $noprop = new XMLElement("prop");
        foreach ($denied as $k => $v) {
            $noprop->NewElement(strtolower($v));
        }
        $elements[] = new XMLElement("propstat", array($noprop, $status));
    }
    if (count($unsupported) > 0) {
        $status = new XMLElement("status", "HTTP/1.1 404 Not Found");
        $noprop = new XMLElement("prop");
        foreach ($unsupported as $k => $v) {
            $noprop->NewElement(strtolower($v));
        }
        $elements[] = new XMLElement("propstat", array($noprop, $status));
    }
    $response = new XMLElement("response", $elements);
    return $response;
}
Exemplo n.º 26
0
 /**
  * Utility function we call when we have a simple status-based response to
  * return to the client.  Possibly
  *
  * @param int $status The HTTP status code to send.
  * @param string $message The friendly text message to send with the response.
  */
 function DoResponse($status, $message = "", $content_type = "text/plain; charset=\"utf-8\"")
 {
     global $session, $c;
     if (!headers_sent()) {
         @header(sprintf("HTTP/1.1 %d %s", $status, getStatusMessage($status)));
     }
     if (!headers_sent()) {
         @header(sprintf("X-DAViCal-Version: DAViCal/%d.%d.%d; DB/%d.%d.%d", $c->code_major, $c->code_minor, $c->code_patch, $c->schema_major, $c->schema_minor, $c->schema_patch));
     }
     if (!headers_sent()) {
         header("Content-type: " . $content_type);
     }
     if (isset($c->dbg['ALL']) && $c->dbg['ALL'] || isset($c->dbg['response']) && $c->dbg['response'] || $status == 400 || $status == 402 || $status == 403 || $status > 404) {
         @dbg_error_log("LOG ", 'Response status %03d for %s %s', $status, $this->method, $_SERVER['REQUEST_URI']);
         $lines = headers_list();
         dbg_error_log("LOG ", "***************** Response Header ****************");
         foreach ($lines as $v) {
             dbg_error_log("LOG headers", "-->%s", $v);
         }
         dbg_error_log("LOG ", "******************** Response ********************");
         // Log the request in all it's gory detail.
         $lines = preg_split('#[\\r\\n]+#', $message);
         foreach ($lines as $v) {
             dbg_error_log("LOG response", "-->%s", $v);
         }
     }
     if ($message != '') {
         if (!headers_sent()) {
             header("Content-Length: " . strlen($message));
         }
         echo $message;
     }
     if (isset($c->dbg['caldav']) && $c->dbg['caldav']) {
         if (strlen($message) > 100 || strstr($message, "\n")) {
             $message = substr(preg_replace("#\\s+#m", ' ', $message), 0, 100) . (strlen($message) > 100 ? "..." : "");
         }
         dbg_error_log("caldav", "Status: %d, Message: %s, User: %d, Path: %s", $status, $message, $session->principal->user_no(), $this->path);
     }
     if (isset($c->dbg['statistics']) && $c->dbg['statistics']) {
         $script_time = microtime(true) - $c->script_start_time;
         $memory = '';
         if (function_exists('memory_get_usage')) {
             $memory = sprintf(', Memory: %dk, Peak: %dk', memory_get_usage() / 1024, memory_get_peak_usage(true) / 1024);
         }
         @dbg_error_log("statistics", "Method: %s, Status: %d, Script: %5.3lfs, Queries: %5.3lfs, URL: %s%s", $this->method, $status, $script_time, $c->total_query_time, $this->path, $memory);
     }
     try {
         @ob_flush();
         // Seems like it should be better to do the following but is problematic on PHP5.3 at least: while ( ob_get_level() > 0 ) ob_end_flush();
     } catch (Exception $ignored) {
     }
     if (isset($c->exit_after_memory_exceeds) && function_exists('memory_get_peak_usage') && memory_get_peak_usage(true) > $c->exit_after_memory_exceeds) {
         // 64M
         @dbg_error_log("statistics", "Peak memory use exceeds %d bytes (%d) - killing process %d", $c->exit_after_memory_exceeds, memory_get_peak_usage(true), getmypid());
         register_shutdown_function('CalDAVRequest::kill_on_exit');
     }
     exit(0);
 }
Exemplo n.º 27
0
                $match = preg_replace('{^.*/caldav.php/([^/]+)(/.*)?$}', '\\1', $match);
                $match = preg_replace('{^mailto:}', '', $match);
                $subwhere .= ' (email ILIKE :user_address_match OR username ILIKE :user_address_match) ';
                $params[':user_address_match'] = '%' . $match . '%';
                break;
            case 'urn:ietf:params:xml:ns:caldav:calendar-home-set':
                $match = preg_replace('{^.*/caldav.php}', '', $match);
                $subwhere .= ' dav_name LIKE :calendar_home_match ';
                $params[':calendar_home_match'] = $match . '%';
                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();
Exemplo n.º 28
0
<?php

/**
* CalDAV Server - handle MOVE method
*
* @package   davical
* @subpackage   caldav
* @author    Andrew McMillan <*****@*****.**>
* @copyright Morphoss Ltd
* @license   http://gnu.org/copyleft/gpl.html GNU GPL v2
*/
dbg_error_log("MOVE", "method handler");
require_once 'DAVResource.php';
$request->NeedPrivilege('DAV::unbind');
if (!ini_get('open_basedir') && (isset($c->dbg['ALL']) || isset($c->dbg['move']) && $c->dbg['move'])) {
    $fh = fopen('/var/log/davical/MOVE.debug', 'w');
    if ($fh) {
        fwrite($fh, $request->raw_post);
        fclose($fh);
    }
}
$lock_opener = $request->FailIfLocked();
$dest = new DAVResource($request->destination);
if ($dest->dav_name() == '/' || $dest->IsPrincipal()) {
    $dest->NeedPrivilege('DAV::bind');
}
if (!$dest->ContainerExists()) {
    $request->DoResponse(409, translate('Destination collection does not exist'));
}
if (!$request->overwrite && $dest->Exists()) {
    $request->DoResponse(412, translate('Not overwriting existing destination resource'));
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
 /**
  * Returns the result of the LDAP query
  *
  * @param string $filter The filter used to search entries
  * @param array $attributes Attributes to be returned
  * @param string $passwd password to check
  * @return array Contains selected attributes from all entries corresponding to the given filter
  */
 function requestUser($filter, $attributes = NULL, $username, $passwd)
 {
     global $c;
     $entry = NULL;
     // We get the DN of the USER
     $query = $this->ldap_query_one;
     foreach ($this->baseDNUsers as $baseDNUsers) {
         $entry = $query($this->connect, $baseDNUsers, $filter, $attributes);
         if (ldap_first_entry($this->connect, $entry)) {
             break;
         }
         dbg_error_log("LDAP", "drivers_ldap : Failed to find user with baseDN: %s", $baseDNUsers);
     }
     if (!ldap_first_entry($this->connect, $entry)) {
         dbg_error_log("ERROR", "drivers_ldap : Unable to find the user with filter %s", $filter);
         return false;
     } else {
         dbg_error_log("LDAP", "drivers_ldap : Found a user using filter %s", $filter);
     }
     $dnUser = ldap_get_dn($this->connect, ldap_first_entry($this->connect, $entry));
     if (isset($c->authenticate_hook['config']['i_use_mode_kerberos']) && $c->authenticate_hook['config']['i_use_mode_kerberos'] == "i_know_what_i_am_doing") {
         dbg_error_log("LOG", "drivers_ldap : Skipping password Check for user %s which should be the same as %s", $username, $_SERVER["REMOTE_USER"]);
         if ($username != $_SERVER["REMOTE_USER"]) {
             return false;
         }
     } else {
         if (!@ldap_bind($this->connect, $dnUser, $passwd)) {
             dbg_error_log("LDAP", "drivers_ldap : Failed to bind to user %s using password %s", $dnUser, $passwd);
             return false;
         }
     }
     dbg_error_log("LDAP", "drivers_ldap : Bound to user %s using password %s", $dnUser, $passwd);
     $i = ldap_first_entry($this->connect, $entry);
     $arr = ldap_get_attributes($this->connect, $i);
     for ($i = 0; $i < $arr['count']; $i++) {
         $ret[$arr[$i]] = $arr[$arr[$i]][0];
     }
     return $ret;
 }