mirror of
https://gitlab.com/davical-project/davical.git
synced 2026-05-29 03:14:38 +00:00
Getting 'MOVE' working has proven surprisingly complex.
This commit is contained in:
parent
a7d7bb63d5
commit
3df6ccc4ba
@ -35,6 +35,7 @@ GRANT SELECT,INSERT,UPDATE,DELETE
|
|||||||
ON relationship_type
|
ON relationship_type
|
||||||
ON sync_tokens
|
ON sync_tokens
|
||||||
ON sync_changes
|
ON sync_changes
|
||||||
|
ON grants
|
||||||
|
|
||||||
GRANT SELECT,UPDATE
|
GRANT SELECT,UPDATE
|
||||||
ON relationship_type_rt_id_seq
|
ON relationship_type_rt_id_seq
|
||||||
|
|||||||
@ -417,7 +417,8 @@ BEGIN
|
|||||||
IF TG_OP = 'UPDATE' THEN
|
IF TG_OP = 'UPDATE' THEN
|
||||||
IF NEW.dav_name != OLD.dav_name THEN
|
IF NEW.dav_name != OLD.dav_name THEN
|
||||||
UPDATE caldav_data
|
UPDATE caldav_data
|
||||||
SET dav_name = replace( dav_name, OLD.dav_name, NEW.dav_name)
|
SET dav_name = replace( dav_name, OLD.dav_name, NEW.dav_name),
|
||||||
|
user_no = NEW.user_no
|
||||||
WHERE substring(dav_name from 1 for char_length(OLD.dav_name)) = OLD.dav_name;
|
WHERE substring(dav_name from 1 for char_length(OLD.dav_name)) = OLD.dav_name;
|
||||||
END IF;
|
END IF;
|
||||||
END IF;
|
END IF;
|
||||||
@ -475,6 +476,44 @@ CREATE TRIGGER caldav_data_modified AFTER INSERT OR UPDATE OR DELETE ON caldav_d
|
|||||||
FOR EACH ROW EXECUTE PROCEDURE caldav_data_modified();
|
FOR EACH ROW EXECUTE PROCEDURE caldav_data_modified();
|
||||||
|
|
||||||
|
|
||||||
|
DROP TRIGGER caldav_data_sync_dav_id ON caldav_data CASCADE;
|
||||||
|
DROP TRIGGER calendar_item_sync_dav_id ON calendar_item CASCADE;
|
||||||
|
CREATE or REPLACE FUNCTION sync_dav_id ( ) RETURNS TRIGGER AS $$
|
||||||
|
DECLARE
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
IF TG_OP = 'DELETE' THEN
|
||||||
|
-- Just let the ON DELETE CASCADE handle this case
|
||||||
|
RETURN OLD;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF NEW.dav_id IS NULL THEN
|
||||||
|
NEW.dav_id = nextval('dav_id_seq');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF TG_OP = 'UPDATE' THEN
|
||||||
|
IF OLD.dav_id != NEW.dav_id OR OLD.collection_id != NEW.collection_id
|
||||||
|
OR OLD.user_no != NEW.user_no OR OLD.dav_name != NEW.dav_name THEN
|
||||||
|
UPDATE calendar_item SET dav_id = NEW.dav_id, user_no = NEW.user_no,
|
||||||
|
collection_id = NEW.collection_id, dav_name = NEW.dav_name
|
||||||
|
WHERE dav_name = OLD.dav_name OR dav_id = OLD.dav_id;
|
||||||
|
END IF;
|
||||||
|
RETURN NEW;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
UPDATE calendar_item SET dav_id = NEW.dav_id, user_no = NEW.user_no,
|
||||||
|
collection_id = NEW.collection_id, dav_name = NEW.dav_name
|
||||||
|
WHERE dav_name = NEW.dav_name OR dav_id = NEW.dav_id;
|
||||||
|
|
||||||
|
RETURN NEW;
|
||||||
|
|
||||||
|
END
|
||||||
|
$$ LANGUAGE 'plpgsql';
|
||||||
|
CREATE TRIGGER caldav_data_sync_dav_id AFTER INSERT OR UPDATE ON caldav_data
|
||||||
|
FOR EACH ROW EXECUTE PROCEDURE sync_dav_id();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- New in 1.2.6
|
-- New in 1.2.6
|
||||||
|
|
||||||
CREATE or REPLACE FUNCTION legacy_privilege_to_bits( TEXT ) RETURNS BIT(24) AS $$
|
CREATE or REPLACE FUNCTION legacy_privilege_to_bits( TEXT ) RETURNS BIT(24) AS $$
|
||||||
@ -927,14 +966,14 @@ BEGIN
|
|||||||
-- We need to canonicalise the path, so:
|
-- We need to canonicalise the path, so:
|
||||||
-- If it matches '/' + some characters (+ optional '/') => a principal URL
|
-- If it matches '/' + some characters (+ optional '/') => a principal URL
|
||||||
IF in_path ~ '^/[^/]+/?$' THEN
|
IF in_path ~ '^/[^/]+/?$' THEN
|
||||||
alt1_path := replace(in_path, '/', '')
|
alt1_path := replace(in_path, '/', '');
|
||||||
SELECT principal_privileges(in_accessor,principal_id) INTO out_conferred FROM usr JOIN principal USING(user_no) WHERE username = alt1_path;
|
SELECT principal_privileges(in_accessor,principal_id) INTO out_conferred FROM usr JOIN principal USING(user_no) WHERE username = alt1_path;
|
||||||
RETURN out_conferred;
|
RETURN out_conferred;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- Otherwise look for the longest segment matching up to the last '/', or if we append one, or if we replace a final '.ics' with one.
|
-- Otherwise look for the longest segment matching up to the last '/', or if we append one, or if we replace a final '.ics' with one.
|
||||||
alt1_path := in_path;
|
alt1_path := in_path;
|
||||||
IF alt1_path ~ '\.ics$' THEN
|
IF alt1_path ~ E'\\.ics$' THEN
|
||||||
alt1_path := substr(alt1_path, 1, length(alt1_path) - 4) || '/';
|
alt1_path := substr(alt1_path, 1, length(alt1_path) - 4) || '/';
|
||||||
END IF;
|
END IF;
|
||||||
alt2_path := regexp_replace( in_path, '[^/]*$', '');
|
alt2_path := regexp_replace( in_path, '[^/]*$', '');
|
||||||
|
|||||||
@ -209,43 +209,41 @@ CREATE TABLE freebusy_ticket (
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
CREATE or REPLACE FUNCTION sync_dav_id ( ) RETURNS TRIGGER AS '
|
|
||||||
|
CREATE or REPLACE FUNCTION sync_dav_id ( ) RETURNS TRIGGER AS $$
|
||||||
DECLARE
|
DECLARE
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
||||||
IF TG_OP = ''DELETE'' THEN
|
IF TG_OP = 'DELETE' THEN
|
||||||
-- Just let the ON DELETE CASCADE handle this case
|
-- Just let the ON DELETE CASCADE handle this case
|
||||||
RETURN OLD;
|
RETURN OLD;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
IF NEW.dav_id IS NULL THEN
|
IF NEW.dav_id IS NULL THEN
|
||||||
NEW.dav_id = nextval(''dav_id_seq'');
|
NEW.dav_id = nextval('dav_id_seq');
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
IF TG_OP = ''UPDATE'' THEN
|
IF TG_OP = 'UPDATE' THEN
|
||||||
IF OLD.dav_id = NEW.dav_id THEN
|
IF OLD.dav_id != NEW.dav_id OR OLD.collection_id != NEW.collection_id
|
||||||
-- Nothing to do
|
OR OLD.user_no != NEW.user_no OR OLD.dav_name != NEW.dav_name THEN
|
||||||
|
UPDATE calendar_item SET dav_id = NEW.dav_id, user_no = NEW.user_no,
|
||||||
|
collection_id = NEW.collection_id, dav_name = NEW.dav_name
|
||||||
|
WHERE dav_name = OLD.dav_name OR dav_id = OLD.dav_id;
|
||||||
|
END IF;
|
||||||
RETURN NEW;
|
RETURN NEW;
|
||||||
END IF;
|
END IF;
|
||||||
END IF;
|
|
||||||
|
|
||||||
IF TG_RELNAME = ''caldav_data'' THEN
|
UPDATE calendar_item SET dav_id = NEW.dav_id, user_no = NEW.user_no,
|
||||||
UPDATE calendar_item SET dav_id = NEW.dav_id WHERE user_no = NEW.user_no AND dav_name = NEW.dav_name;
|
collection_id = NEW.collection_id, dav_name = NEW.dav_name
|
||||||
ELSE
|
WHERE dav_name = NEW.dav_name OR dav_id = NEW.dav_id;
|
||||||
UPDATE caldav_data SET dav_id = NEW.dav_id WHERE user_no = NEW.user_no AND dav_name = NEW.dav_name;
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
RETURN NEW;
|
RETURN NEW;
|
||||||
|
|
||||||
END
|
END
|
||||||
' LANGUAGE 'plpgsql';
|
$$ LANGUAGE 'plpgsql';
|
||||||
|
|
||||||
CREATE TRIGGER caldav_data_sync_dav_id AFTER INSERT OR UPDATE ON caldav_data
|
CREATE TRIGGER caldav_data_sync_dav_id AFTER INSERT OR UPDATE ON caldav_data
|
||||||
FOR EACH ROW EXECUTE PROCEDURE sync_dav_id();
|
FOR EACH ROW EXECUTE PROCEDURE sync_dav_id();
|
||||||
|
|
||||||
CREATE TRIGGER calendar_item_sync_dav_id AFTER INSERT OR UPDATE ON calendar_item
|
|
||||||
FOR EACH ROW EXECUTE PROCEDURE sync_dav_id();
|
|
||||||
|
|
||||||
|
|
||||||
-- Only needs SELECT access by website.
|
-- Only needs SELECT access by website.
|
||||||
CREATE TABLE principal_type (
|
CREATE TABLE principal_type (
|
||||||
|
|||||||
@ -53,6 +53,7 @@ switch ( $request->method ) {
|
|||||||
case 'MKCOL': include_once("caldav-MKCOL.php"); break;
|
case 'MKCOL': include_once("caldav-MKCOL.php"); break;
|
||||||
case 'PUT': include_once("caldav-PUT.php"); break;
|
case 'PUT': include_once("caldav-PUT.php"); break;
|
||||||
case 'POST': include_once("caldav-POST.php"); break;
|
case 'POST': include_once("caldav-POST.php"); break;
|
||||||
|
case 'MOVE': include_once("caldav-MOVE.php"); break;
|
||||||
case 'GET': include_once("caldav-GET.php"); break;
|
case 'GET': include_once("caldav-GET.php"); break;
|
||||||
case 'HEAD': include_once("caldav-GET.php"); break;
|
case 'HEAD': include_once("caldav-GET.php"); break;
|
||||||
case 'DELETE': include_once("caldav-DELETE.php"); break;
|
case 'DELETE': include_once("caldav-DELETE.php"); break;
|
||||||
|
|||||||
@ -350,6 +350,14 @@ class AwlQuery
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the count of rows retrieved/affected
|
||||||
|
*/
|
||||||
|
function rows() {
|
||||||
|
return $this->rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the query, logging any debugging.
|
* Execute the query, logging any debugging.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -163,6 +163,8 @@ class CalDAVPrincipal
|
|||||||
if ( !isset($this->modified) ) $this->modified = ISODateToHTTPDate($this->updated);
|
if ( !isset($this->modified) ) $this->modified = ISODateToHTTPDate($this->updated);
|
||||||
if ( !isset($this->created) ) $this->created = ISODateToHTTPDate($this->joined);
|
if ( !isset($this->created) ) $this->created = ISODateToHTTPDate($this->joined);
|
||||||
|
|
||||||
|
$this->dav_etag = md5($this->username . $this->updated);
|
||||||
|
|
||||||
$this->by_email = false;
|
$this->by_email = false;
|
||||||
$this->principal_url = ConstructURL( '/'.$this->username.'/', true );
|
$this->principal_url = ConstructURL( '/'.$this->username.'/', true );
|
||||||
$this->url = $this->principal_url;
|
$this->url = $this->principal_url;
|
||||||
@ -284,7 +286,7 @@ class CalDAVPrincipal
|
|||||||
$username = $user->username;
|
$username = $user->username;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elseif( $user = getUserByName( $username, 'caldav') ) {
|
elseif( $user = getUserByName( $username, 'principal') ) {
|
||||||
$user_no = $user->user_no;
|
$user_no = $user->user_no;
|
||||||
}
|
}
|
||||||
return $username;
|
return $username;
|
||||||
@ -315,6 +317,14 @@ class CalDAVPrincipal
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the privileges bits for the current session user to this resource
|
||||||
|
*/
|
||||||
|
function Privileges() {
|
||||||
|
return $this->privileges;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a representation of the principal as a collection
|
* Returns a representation of the principal as a collection
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -77,6 +77,12 @@ class CalDAVRequest
|
|||||||
*/
|
*/
|
||||||
var $collection_type;
|
var $collection_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of collection being requested:
|
||||||
|
* calendar, schedule-inbox, schedule-outbox
|
||||||
|
*/
|
||||||
|
protected $exists;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A static structure of supported privileges.
|
* A static structure of supported privileges.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -26,25 +26,25 @@ function privilege_to_bits( $raw_privs ) {
|
|||||||
foreach( $raw_privs AS $priv ) {
|
foreach( $raw_privs AS $priv ) {
|
||||||
$trim_priv = trim(strtolower(preg_replace( '/^.*:/', '', $priv)));
|
$trim_priv = trim(strtolower(preg_replace( '/^.*:/', '', $priv)));
|
||||||
switch( $trim_priv ) {
|
switch( $trim_priv ) {
|
||||||
case 'read' : $out_priv &= 4609; break; // 1 + 512 + 4096
|
case 'read' : $out_priv |= 4609; break; // 1 + 512 + 4096
|
||||||
case 'write' : $out_priv &= 198; break; // 2 + 4 + 64 + 128
|
case 'write' : $out_priv |= 198; break; // 2 + 4 + 64 + 128
|
||||||
case 'write-properties' : $out_priv &= 2; break;
|
case 'write-properties' : $out_priv |= 2; break;
|
||||||
case 'write-content' : $out_priv &= 4; break;
|
case 'write-content' : $out_priv |= 4; break;
|
||||||
case 'unlock' : $out_priv &= 8; break;
|
case 'unlock' : $out_priv |= 8; break;
|
||||||
case 'read-acl' : $out_priv &= 16; break;
|
case 'read-acl' : $out_priv |= 16; break;
|
||||||
case 'read-current-user-privilege-set' : $out_priv &= 32; break;
|
case 'read-current-user-privilege-set' : $out_priv |= 32; break;
|
||||||
case 'bind' : $out_priv &= 64; break;
|
case 'bind' : $out_priv |= 64; break;
|
||||||
case 'unbind' : $out_priv &= 128; break;
|
case 'unbind' : $out_priv |= 128; break;
|
||||||
case 'write-acl' : $out_priv &= 256; break;
|
case 'write-acl' : $out_priv |= 256; break;
|
||||||
case 'read-free-busy' : $out_priv &= 4608; break; // 512 + 4096
|
case 'read-free-busy' : $out_priv |= 4608; break; // 512 + 4096
|
||||||
case 'schedule-deliver' : $out_priv &= 7168; break; // 1024 + 2048 + 4096
|
case 'schedule-deliver' : $out_priv |= 7168; break; // 1024 + 2048 + 4096
|
||||||
case 'schedule-deliver-invite' : $out_priv &= 1024; break;
|
case 'schedule-deliver-invite' : $out_priv |= 1024; break;
|
||||||
case 'schedule-deliver-reply' : $out_priv &= 2048; break;
|
case 'schedule-deliver-reply' : $out_priv |= 2048; break;
|
||||||
case 'schedule-query-freebusy' : $out_priv &= 4096; break;
|
case 'schedule-query-freebusy' : $out_priv |= 4096; break;
|
||||||
case 'schedule-send' : $out_priv &= 57344; break; // 8192 + 16384 + 32768
|
case 'schedule-send' : $out_priv |= 57344; break; // 8192 + 16384 + 32768
|
||||||
case 'schedule-send-invite' : $out_priv &= 8192; break;
|
case 'schedule-send-invite' : $out_priv |= 8192; break;
|
||||||
case 'schedule-send-reply' : $out_priv &= 16384; break;
|
case 'schedule-send-reply' : $out_priv |= 16384; break;
|
||||||
case 'schedule-send-freebusy' : $out_priv &= 32768; break;
|
case 'schedule-send-freebusy' : $out_priv |= 32768; break;
|
||||||
default:
|
default:
|
||||||
dbg_error_log( 'ERROR', 'Cannot convert privilege of "%s" into bits.', $priv );
|
dbg_error_log( 'ERROR', 'Cannot convert privilege of "%s" into bits.', $priv );
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ class DAVResource
|
|||||||
/**
|
/**
|
||||||
* @var The actual resource content, if it exists and is not a collection
|
* @var The actual resource content, if it exists and is not a collection
|
||||||
*/
|
*/
|
||||||
protected $content;
|
protected $resource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var The type of the resource, possibly multiple
|
* @var The type of the resource, possibly multiple
|
||||||
@ -195,7 +195,7 @@ class DAVResource
|
|||||||
$this->exists = null;
|
$this->exists = null;
|
||||||
$this->dav_name = null;
|
$this->dav_name = null;
|
||||||
$this->unique_tag = null;
|
$this->unique_tag = null;
|
||||||
$this->content = null;
|
$this->resource = null;
|
||||||
$this->collection = null;
|
$this->collection = null;
|
||||||
$this->principal = null;
|
$this->principal = null;
|
||||||
$this->resourcetype = null;
|
$this->resourcetype = null;
|
||||||
@ -231,7 +231,7 @@ class DAVResource
|
|||||||
|
|
||||||
$this->exists = true;
|
$this->exists = true;
|
||||||
foreach( $row AS $k => $v ) {
|
foreach( $row AS $k => $v ) {
|
||||||
dbg_error_log( 'resource', 'Processing resource property "%s" has "%s".', $row->dav_name, $k );
|
dbg_error_log( 'DAVResource', 'Processing resource property "%s" has "%s".', $row->dav_name, $k );
|
||||||
switch ( $k ) {
|
switch ( $k ) {
|
||||||
case 'dav_etag':
|
case 'dav_etag':
|
||||||
$this->unique_tag = '"'.$v.'"';
|
$this->unique_tag = '"'.$v.'"';
|
||||||
@ -258,16 +258,20 @@ class DAVResource
|
|||||||
$ourpath = $matches[1]. '/';
|
$ourpath = $matches[1]. '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** remove any leading protocol/server/port/prefix... */
|
||||||
|
$base_path = ConstructURL('/');
|
||||||
|
if ( preg_match( '%^(.*?)'.str_replace('%', '\\%',$base_path).'(.*)$%', $ourpath, $matches ) ) {
|
||||||
|
if ( $matches[1] == '' || $matches[1] == $c->protocol_server_port ) {
|
||||||
|
$ourpath = $matches[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** strip doubled slashes */
|
/** strip doubled slashes */
|
||||||
if ( strstr($ourpath,'//') ) $ourpath = preg_replace( '#//+#', '/', $ourpath);
|
if ( strstr($ourpath,'//') ) $ourpath = preg_replace( '#//+#', '/', $ourpath);
|
||||||
|
|
||||||
/** remove any leading protocol/server/port/prefix... */
|
if ( substr($ourpath,0,1) != '/' ) $ourpath = '/'.$ourpath;
|
||||||
$base_path = ConstructURL('/');
|
|
||||||
$this->dav_name = str_replace( $base_path, '/', $ourpath );
|
|
||||||
|
|
||||||
if ( substr($this->dav_name,0,1) != '/' ) {
|
$this->dav_name = $ourpath;
|
||||||
$this->dav_name = '/'.$this->dav_name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -300,13 +304,13 @@ class DAVResource
|
|||||||
$sql = $base_sql .'dav_name = :raw_path ';
|
$sql = $base_sql .'dav_name = :raw_path ';
|
||||||
$params = array( ':raw_path' => $this->dav_name, ':session_principal' => $session->principal_id );
|
$params = array( ':raw_path' => $this->dav_name, ':session_principal' => $session->principal_id );
|
||||||
if ( !preg_match( '#/$#', $this->dav_name ) ) {
|
if ( !preg_match( '#/$#', $this->dav_name ) ) {
|
||||||
$sql .= ' OR dav_name = :up_to_slash OR dav_name = :plus_slash';
|
$sql .= ' OR dav_name = :up_to_slash OR dav_name = :plus_slash ';
|
||||||
$params[':up_to_slash'] = preg_replace( '#[^/]*$#', '', $this->dav_name);
|
$params[':up_to_slash'] = preg_replace( '#[^/]*$#', '', $this->dav_name);
|
||||||
$params[':plus_slash'] = $this->dav_name.'/';
|
$params[':plus_slash'] = $this->dav_name.'/';
|
||||||
}
|
}
|
||||||
$sql .= 'ORDER BY LENGTH(dav_name) DESC LIMIT 1';
|
$sql .= 'ORDER BY LENGTH(dav_name) DESC LIMIT 1';
|
||||||
$qry = new AwlQuery( $sql, $params );
|
$qry = new AwlQuery( $sql, $params );
|
||||||
if ( $qry->Exec('DAVResource') && $qry->rows == 1 && ($row = $qry->Fetch()) ) {
|
if ( $qry->Exec('DAVResource') && $qry->rows() == 1 && ($row = $qry->Fetch()) ) {
|
||||||
$this->collection = $row;
|
$this->collection = $row;
|
||||||
if ( $row->is_calendar == 't' )
|
if ( $row->is_calendar == 't' )
|
||||||
$this->collection->type = 'calendar';
|
$this->collection->type = 'calendar';
|
||||||
@ -331,8 +335,9 @@ EOSQL;
|
|||||||
$qry->Exec('DAVResource');
|
$qry->Exec('DAVResource');
|
||||||
dbg_error_log( 'DAVResource', 'Created new collection as "$displayname".' );
|
dbg_error_log( 'DAVResource', 'Created new collection as "$displayname".' );
|
||||||
|
|
||||||
$qry = new AwlQuery( $base_sql . 'user_no = :user_no AND dav_name = :dav_name', $params );
|
$params = array( ':raw_path' => $this->dav_name, ':session_principal' => $session->principal_id );
|
||||||
if ( $qry->Exec('DAVResource') && $qry->rows == 1 && ($row = $qry->Fetch()) ) {
|
$qry = new AwlQuery( $base_sql . ' dav_name = :raw_path', $params );
|
||||||
|
if ( $qry->Exec('DAVResource') && $qry->rows() == 1 && ($row = $qry->Fetch()) ) {
|
||||||
$this->collection = $row;
|
$this->collection = $row;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -342,12 +347,6 @@ EOSQL;
|
|||||||
$this->proxy_type = $matches[3];
|
$this->proxy_type = $matches[3];
|
||||||
$this->collection->dav_name = $matches[1].'/';
|
$this->collection->dav_name = $matches[1].'/';
|
||||||
}
|
}
|
||||||
else if ( $this->options['allow_by_email'] && preg_match( '#^/(\S+@\S+[.]\S+)/?$#', $this->dav_name, $matches) ) {
|
|
||||||
/** @TODO: perhaps we should deprecate this in favour of scheduling extensions */
|
|
||||||
$this->collection->type = 'principal_email';
|
|
||||||
$this->collection->dav_name = $matches[1].'/';
|
|
||||||
$this->_is_principal = true;
|
|
||||||
}
|
|
||||||
else if ( preg_match( '#^(/[^/]+)/?$#', $this->dav_name, $matches) ) {
|
else if ( preg_match( '#^(/[^/]+)/?$#', $this->dav_name, $matches) ) {
|
||||||
$this->collection->dav_name = $matches[1].'/';
|
$this->collection->dav_name = $matches[1].'/';
|
||||||
$this->collection->type = 'principal';
|
$this->collection->type = 'principal';
|
||||||
@ -362,12 +361,31 @@ EOSQL;
|
|||||||
$this->collection->dav_name = '/';
|
$this->collection->dav_name = '/';
|
||||||
$this->collection->type = 'root';
|
$this->collection->type = 'root';
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
dbg_error_log( 'DAVResource', 'No collection for path "%s".', $this->dav_name );
|
||||||
|
$this->collection->exists = false;
|
||||||
|
$this->collection->dav_name = preg_replace('{/[^/]*$}', '/', $this->dav_name);
|
||||||
|
}
|
||||||
|
|
||||||
$this->_is_collection = ( $this->collection->dav_name == $this->dav_name || $this->collection->dav_name == $this->dav_name.'/' );
|
$this->_is_collection = ( $this->collection->dav_name == $this->dav_name || $this->collection->dav_name == $this->dav_name.'/' );
|
||||||
if ( $this->_is_collection ) {
|
if ( $this->_is_collection ) {
|
||||||
$this->_is_calendar = $this->collection->is_calendar;
|
$this->dav_name = $this->collection->dav_name;
|
||||||
$this->_is_addressbook = $this->collection->is_addressbook;
|
$this->_is_calendar = ($this->collection->type == 'calendar');
|
||||||
|
$this->_is_addressbook = ($this->collection->type == 'addressbook');
|
||||||
$this->contenttype = 'httpd/unix-directory';
|
$this->contenttype = 'httpd/unix-directory';
|
||||||
|
if ( isset($this->collection->dav_etag) ) $this->unique_tag = $this->collection->dav_etag;
|
||||||
|
if ( isset($this->collection->created) ) $this->created = $this->collection->created;
|
||||||
|
if ( isset($this->collection->modified) ) $this->modified = $this->collection->modified;
|
||||||
|
if ( isset($this->collection->resourcetype) )
|
||||||
|
$this->resourcetype = $this->collection->resourcetype;
|
||||||
|
else {
|
||||||
|
$this->resourcetype = '<DAV::collection/>';
|
||||||
|
if ( $this->_is_principal )
|
||||||
|
$this->resourcetype .= '<DAV::principal/>';
|
||||||
|
else {
|
||||||
|
$this->exists = (!isset($this->collection->exists) || $this->collection->exists);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,6 +396,13 @@ EOSQL;
|
|||||||
function FetchPrincipal() {
|
function FetchPrincipal() {
|
||||||
global $c, $session;
|
global $c, $session;
|
||||||
$this->principal = new CalDAVPrincipal( array( "path" => $this->dav_name ) );
|
$this->principal = new CalDAVPrincipal( array( "path" => $this->dav_name ) );
|
||||||
|
if ( $this->IsPrincipal() ) {
|
||||||
|
$this->contenttype = 'httpd/unix-directory';
|
||||||
|
$this->unique_tag = $this->principal->dav_etag;
|
||||||
|
$this->created = $this->principal->created;
|
||||||
|
$this->modified = $this->principal->modified;
|
||||||
|
$this->resourcetype = '<DAV::principal/>';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -398,9 +423,14 @@ EOQRY;
|
|||||||
$params = array( ':dav_name' => $this->dav_name );
|
$params = array( ':dav_name' => $this->dav_name );
|
||||||
|
|
||||||
$qry = new AwlQuery( $sql, $params );
|
$qry = new AwlQuery( $sql, $params );
|
||||||
if ( $qry->Exec('DAVResource') && $qry->rows > 0 ) {
|
if ( $qry->Exec('DAVResource') && $qry->rows() > 0 ) {
|
||||||
$this->exists = true;
|
$this->exists = true;
|
||||||
$this->resource = $qry->Fetch();
|
$this->resource = $qry->Fetch();
|
||||||
|
$this->unique_tag = $this->resource->dav_etag;
|
||||||
|
$this->created = $this->resource->created;
|
||||||
|
$this->modified = $this->resource->modified;
|
||||||
|
$this->contenttype = 'text/calendar';
|
||||||
|
$this->resourcetype = '';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$this->exists = false;
|
$this->exists = false;
|
||||||
@ -416,29 +446,54 @@ EOQRY;
|
|||||||
|
|
||||||
if ( $this->dav_name == '/' || $this->dav_name == '' ) {
|
if ( $this->dav_name == '/' || $this->dav_name == '' ) {
|
||||||
$this->privileges = 1; // read
|
$this->privileges = 1; // read
|
||||||
dbg_error_log( 'DAVResource', 'Read permissions for user accessing /' );
|
// dbg_error_log( 'DAVResource', 'Read permissions for user accessing /' );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $session->AllowedTo('Admin') || $session->user_no == $this->user_no ) {
|
if ( $session->AllowedTo('Admin') ) {
|
||||||
$this->privileges = privilege_to_bits('all');
|
$this->privileges = privilege_to_bits('all');
|
||||||
dbg_error_log( 'DAVResource', 'Full permissions for %s', ( $session->user_no == $this->user_no ? 'user accessing their own hierarchy' : 'an administrator') );
|
// dbg_error_log( 'DAVResource', 'Full permissions for an administrator.' );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( $this->IsPrincipal() ) {
|
||||||
|
if ( !isset($this->principal) ) $this->FetchPrincipal();
|
||||||
|
$this->privileges = $this->principal->Privileges();
|
||||||
|
// dbg_error_log( 'DAVResource', 'Privileges of "%s" for user accessing principal "%s"', $this->privileges, $this->principal->username );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$this->privileges = 0;
|
$this->privileges = 0;
|
||||||
if ( !isset($this->collection) ) $this->FetchCollection();
|
if ( !isset($this->collection) ) $this->FetchCollection();
|
||||||
|
if ( !isset($this->collection->path_privileges) ) {
|
||||||
|
$parent_path = preg_replace('{/[^/]*/$}', '/', $this->collection->dav_name );
|
||||||
|
// dbg_error_log( 'DAVResource', 'Checking privileges of "%s" - parent of "%s"', $parent_path, $this->collection->dav_name );
|
||||||
|
$parent = new DAVResource( $parent_path );
|
||||||
|
|
||||||
|
$this->collection->path_privileges = $parent->Privileges();
|
||||||
|
}
|
||||||
|
|
||||||
$this->privileges = $this->collection->path_privileges;
|
$this->privileges = $this->collection->path_privileges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the privileges bits for the current session user to this resource
|
||||||
|
*/
|
||||||
|
function Privileges() {
|
||||||
|
if ( !isset($this->privileges) ) $this->FetchPrivileges();
|
||||||
|
return $this->privileges;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the user has the privileges to do what is requested.
|
* Is the user has the privileges to do what is requested.
|
||||||
*/
|
*/
|
||||||
function HavePrivilegeTo( $do_what ) {
|
function HavePrivilegeTo( $do_what ) {
|
||||||
if ( !isset($this->privileges) ) $this->FetchPrivileges();
|
if ( !isset($this->privileges) ) $this->FetchPrivileges();
|
||||||
$test_bits = privilege_to_bits( $do_what );
|
$test_bits = privilege_to_bits( $do_what );
|
||||||
|
// dbg_error_log( 'DAVResource', 'Testing privileges of "%s"(%d) against allowed "%s" => "%s"', $do_what, $test_bits, $this->privileges, ($this->privileges & $test_bits) );
|
||||||
return ($this->privileges & $test_bits) > 0;
|
return ($this->privileges & $test_bits) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,7 +509,7 @@ EOQRY;
|
|||||||
if ( !isset($xmldoc) && isset($GLOBALS['reply']) ) $xmldoc = $GLOBALS['reply'];
|
if ( !isset($xmldoc) && isset($GLOBALS['reply']) ) $xmldoc = $GLOBALS['reply'];
|
||||||
$privileges = array();
|
$privileges = array();
|
||||||
foreach( $privilege_names AS $k ) {
|
foreach( $privilege_names AS $k ) {
|
||||||
dbg_error_log( 'DAVResource', 'Adding privilege "%s".', $k );
|
// dbg_error_log( 'DAVResource', 'Adding privilege "%s".', $k );
|
||||||
$privilege = new XMLElement('privilege');
|
$privilege = new XMLElement('privilege');
|
||||||
if ( isset($xmldoc) )
|
if ( isset($xmldoc) )
|
||||||
$xmldoc->NSElement($privilege,$k);
|
$xmldoc->NSElement($privilege,$k);
|
||||||
@ -572,15 +627,56 @@ EOQRY;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this resource is a collection
|
||||||
|
*/
|
||||||
|
function IsCollection() {
|
||||||
|
return $this->_is_collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this resource is a principal
|
||||||
|
*/
|
||||||
|
function IsPrincipal() {
|
||||||
|
return $this->_is_collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this resource is a calendar
|
||||||
|
*/
|
||||||
|
function IsCalendar() {
|
||||||
|
return $this->_is_calendar;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this resource is an addressbook
|
||||||
|
*/
|
||||||
|
function IsAddressbook() {
|
||||||
|
return $this->_is_addressbook;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether this resource actually exists, in the virtual sense, within the hierarchy
|
* Checks whether this resource actually exists, in the virtual sense, within the hierarchy
|
||||||
*/
|
*/
|
||||||
function Exists() {
|
function Exists() {
|
||||||
if ( isset($this->exists) ) return $this->exists;
|
if ( ! isset($this->exists) ) {
|
||||||
if ( isset($this->collection) && isset($this->collection->publicly_readable) && $this->collection->publicly_readable == 't' ) {
|
if ( $this->IsPrincipal() ) {
|
||||||
return true;
|
if ( !isset($this->principal) ) $this->FetchPrincipal();
|
||||||
|
$this->exists = $this->principal->Exists();
|
||||||
}
|
}
|
||||||
return false;
|
else if ( $this->IsCollection() ) {
|
||||||
|
if ( !isset($this->collection) ) $this->FetchCollection();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( !isset($this->resource) ) $this->FetchResource();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbg_error_log('DAVResource',' Checking whether "%s" exists. It would appear %s.', $this->dav_name, ($this->exists ? 'so' : 'not') );
|
||||||
|
return $this->exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -605,6 +701,23 @@ EOQRY;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the principal-URL for this resource
|
||||||
|
*/
|
||||||
|
function unique_tag() {
|
||||||
|
if ( isset($this->unique_tag) ) return $this->unique_tag;
|
||||||
|
if ( $this->IsCollection() && !isset($this->collection) ) {
|
||||||
|
$this->FetchCollection();
|
||||||
|
if ( $this->IsPrincipal() && !isset($this->principal) ) $this->FetchPrincipal();
|
||||||
|
}
|
||||||
|
else if ( !isset($this->resource) ) $this->FetchResource();
|
||||||
|
|
||||||
|
if ( $this->exists !== true || !isset($this->unique_tag) ) $this->unique_tag = '';
|
||||||
|
|
||||||
|
return $this->unique_tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the target collection is publicly_readable
|
* Checks whether the target collection is publicly_readable
|
||||||
*/
|
*/
|
||||||
@ -632,7 +745,7 @@ EOQRY;
|
|||||||
else {
|
else {
|
||||||
$qry = new AwlQuery('SELECT * FROM collection WHERE dav_name = :parent_name',
|
$qry = new AwlQuery('SELECT * FROM collection WHERE dav_name = :parent_name',
|
||||||
array( ':parent_name' => $this->collection->parent_container ) );
|
array( ':parent_name' => $this->collection->parent_container ) );
|
||||||
if ( $qry->Exec('DAVResource') && $qry->rows > 0 && $parent = $qry->Fetch() ) {
|
if ( $qry->Exec('DAVResource') && $qry->rows() > 0 && $parent = $qry->Fetch() ) {
|
||||||
if ( $parent->is_calendar == 't' )
|
if ( $parent->is_calendar == 't' )
|
||||||
$this->parent_container_type = 'calendar';
|
$this->parent_container_type = 'calendar';
|
||||||
else if ( $parent->is_addressbook == 't' )
|
else if ( $parent->is_addressbook == 't' )
|
||||||
@ -649,15 +762,56 @@ EOQRY;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return general server-related properties, in plain form
|
||||||
|
*/
|
||||||
|
function GetProperty( $name ) {
|
||||||
|
global $c, $session;
|
||||||
|
|
||||||
|
// dbg_error_log( 'DAVResource', 'Processing "%s".', $name );
|
||||||
|
$value = null;
|
||||||
|
|
||||||
|
switch( $name ) {
|
||||||
|
case 'collection_id':
|
||||||
|
if ( !isset($this->collection) ) $this->FetchCollection();
|
||||||
|
return $this->collection->collection_id;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if ( $this->_is_principal ) {
|
||||||
|
if ( !isset($this->principal) ) $this->FetchPrincipal();
|
||||||
|
if ( isset($this->principal->{$name}) ) return $this->principal->{$name};
|
||||||
|
if ( isset($this->collection->{$name}) ) return $this->collection->{$name};
|
||||||
|
}
|
||||||
|
else if ( $this->_is_collection ) {
|
||||||
|
if ( !isset($this->collection) ) $this->FetchCollection();
|
||||||
|
if ( isset($this->collection->{$name}) ) return $this->collection->{$name};
|
||||||
|
if ( isset($this->principal->{$name}) ) return $this->principal->{$name};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( !isset($this->resource) ) $this->FetchResource();
|
||||||
|
if ( isset($this->resource->{$name}) ) return $this->resource->{$name};
|
||||||
|
if ( !isset($this->principal) ) $this->FetchPrincipal();
|
||||||
|
if ( isset($this->principal->{$name}) ) return $this->principal->{$name};
|
||||||
|
if ( !isset($this->collection) ) $this->FetchCollection();
|
||||||
|
if ( isset($this->collection->{$name}) ) return $this->collection->{$name};
|
||||||
|
}
|
||||||
|
dbg_error_log( 'ERROR', 'Request for property "%s" which is not understood.', $name );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return general server-related properties for this URL
|
* Return general server-related properties for this URL
|
||||||
*/
|
*/
|
||||||
function ResourceProperty( $tag, $prop, $reply = null ) {
|
function ResourceProperty( $tag, $prop, $reply = null, &$denied ) {
|
||||||
global $c, $session;
|
global $c, $session;
|
||||||
|
|
||||||
if ( $reply === null ) $reply = $GLOBALS['reply'];
|
if ( $reply === null ) $reply = $GLOBALS['reply'];
|
||||||
|
|
||||||
dbg_error_log( 'resource', 'Processing "%s" on "%s".', $tag, $this->dav_name );
|
dbg_error_log( 'DAVResource', 'Processing "%s" on "%s".', $tag, $this->dav_name );
|
||||||
|
|
||||||
switch( $tag ) {
|
switch( $tag ) {
|
||||||
case 'DAV::href':
|
case 'DAV::href':
|
||||||
@ -677,7 +831,7 @@ EOQRY;
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'DAV::getlastmodified':
|
case 'DAV::getlastmodified':
|
||||||
$prop->NewElement('getlastmodified', $this->last_modified );
|
$prop->NewElement('getlastmodified', $this->modified );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'DAV::creationdate':
|
case 'DAV::creationdate':
|
||||||
@ -703,7 +857,7 @@ EOQRY;
|
|||||||
|
|
||||||
case 'DAV::getetag':
|
case 'DAV::getetag':
|
||||||
if ( $this->_is_collection ) {
|
if ( $this->_is_collection ) {
|
||||||
$not_found[] = $reply->Tag($tag);
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$prop->NewElement('getetag', $this->unique_tag );
|
$prop->NewElement('getetag', $this->unique_tag );
|
||||||
@ -719,17 +873,22 @@ EOQRY;
|
|||||||
$prop->NewElement('http://calendarserver.org/ns/:getctag', $this->unique_tag );
|
$prop->NewElement('http://calendarserver.org/ns/:getctag', $this->unique_tag );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$not_found[] = $reply->Tag($tag);
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'urn:ietf:params:xml:ns:caldav:calendar-data':
|
case 'urn:ietf:params:xml:ns:caldav:calendar-data':
|
||||||
if ( isset($this->caldav_data) ) {
|
if ( $this->_is_collection ) {
|
||||||
|
if ( !isset($this->resource) ) $this->FetchResource();
|
||||||
|
$reply->CalDAVElement($prop, $k, $this->resource->caldav_data );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dbg_error_log( 'resource', 'Request for unsupported property "%s" of path "%s".', $tag, $this->dav_name );
|
dbg_error_log( 'DAVResource', 'Request for unsupported property "%s" of path "%s".', $tag, $this->dav_name );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -746,15 +905,15 @@ EOQRY;
|
|||||||
function GetPropStat( $properties ) {
|
function GetPropStat( $properties ) {
|
||||||
global $session, $c, $request, $reply;
|
global $session, $c, $request, $reply;
|
||||||
|
|
||||||
dbg_error_log('resource',': GetPropStat: href "%s"', $this->dav_name );
|
dbg_error_log('DAVResource',': GetPropStat: href "%s"', $this->dav_name );
|
||||||
|
|
||||||
$prop = new XMLElement('prop');
|
$prop = new XMLElement('prop');
|
||||||
$denied = array();
|
$denied = array();
|
||||||
$not_found = array();
|
$not_found = array();
|
||||||
foreach( $properties AS $k => $tag ) {
|
foreach( $properties AS $k => $tag ) {
|
||||||
dbg_error_log( 'resource', 'Looking at resource "%s" for property [%s]"%s".', $this->dav_name, $k, $tag );
|
// dbg_error_log( 'DAVResource', 'Looking at resource "%s" for property [%s]"%s".', $this->dav_name, $k, $tag );
|
||||||
if ( ! $this->ResourceProperty($tag, $prop, $reply) ) {
|
if ( ! $this->ResourceProperty($tag, $prop, $reply, $denied ) ) {
|
||||||
dbg_error_log( 'resource', 'Request for unsupported property "%s" of resource "%s".', $tag, $this->dav_name );
|
dbg_error_log( 'DAVResource', 'Request for unsupported property "%s" of resource "%s".', $tag, $this->dav_name );
|
||||||
$not_found[] = $reply->Tag($tag);
|
$not_found[] = $reply->Tag($tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -795,7 +954,7 @@ EOQRY;
|
|||||||
function RenderAsXML( $properties, &$reply, $props_only = false ) {
|
function RenderAsXML( $properties, &$reply, $props_only = false ) {
|
||||||
global $session, $c, $request;
|
global $session, $c, $request;
|
||||||
|
|
||||||
dbg_error_log('principal',': RenderAsXML: Principal "%s"', $this->username );
|
dbg_error_log('DAVResource',': RenderAsXML: Principal "%s"', $this->username );
|
||||||
|
|
||||||
$prop = new XMLElement('prop');
|
$prop = new XMLElement('prop');
|
||||||
$denied = array();
|
$denied = array();
|
||||||
@ -812,7 +971,7 @@ EOQRY;
|
|||||||
$status = new XMLElement('status', 'HTTP/1.1 200 OK' );
|
$status = new XMLElement('status', 'HTTP/1.1 200 OK' );
|
||||||
|
|
||||||
$propstat = new XMLElement( 'propstat', array( $prop, $status) );
|
$propstat = new XMLElement( 'propstat', array( $prop, $status) );
|
||||||
$href = $reply->href( ConstructURL($this->dav_name) ); /** TODO: make ::href() into an accessor */
|
$href = $reply->href( ConstructURL($this->dav_name) ); /** @TODO: make ::href() into an accessor */
|
||||||
|
|
||||||
$elements = array($href,$propstat);
|
$elements = array($href,$propstat);
|
||||||
|
|
||||||
|
|||||||
@ -23,25 +23,25 @@ class HTTPAuthSession {
|
|||||||
* User ID number
|
* User ID number
|
||||||
* @var user_no int
|
* @var user_no int
|
||||||
*/
|
*/
|
||||||
var $user_no;
|
public $user_no;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User e-mail
|
* User e-mail
|
||||||
* @var email string
|
* @var email string
|
||||||
*/
|
*/
|
||||||
var $email;
|
public $email;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User full name
|
* User full name
|
||||||
* @var fullname string
|
* @var fullname string
|
||||||
*/
|
*/
|
||||||
var $fullname;
|
public $fullname;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Group rights
|
* Group rights
|
||||||
* @var groups array
|
* @var groups array
|
||||||
*/
|
*/
|
||||||
var $groups;
|
public $groups;
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -68,7 +68,7 @@ if ( !isset($_SERVER['SERVER_NAME']) ) {
|
|||||||
/**
|
/**
|
||||||
* Calculate the simplest form of reference to this page, excluding the PATH_INFO following the script name.
|
* Calculate the simplest form of reference to this page, excluding the PATH_INFO following the script name.
|
||||||
*/
|
*/
|
||||||
$c->protocol_server_port_script = sprintf( '%s://%s%s%s',
|
$c->protocol_server_port = sprintf( '%s://%s%s',
|
||||||
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'? 'https' : 'http'),
|
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'? 'https' : 'http'),
|
||||||
$_SERVER['SERVER_NAME'],
|
$_SERVER['SERVER_NAME'],
|
||||||
(
|
(
|
||||||
@ -76,8 +76,8 @@ $c->protocol_server_port_script = sprintf( '%s://%s%s%s',
|
|||||||
|| (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' && $_SERVER['SERVER_PORT'] == 443 )
|
|| (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' && $_SERVER['SERVER_PORT'] == 443 )
|
||||||
? ''
|
? ''
|
||||||
: ':'.$_SERVER['SERVER_PORT']
|
: ':'.$_SERVER['SERVER_PORT']
|
||||||
),
|
) );
|
||||||
($_SERVER['SCRIPT_NAME'] == '/index.php' ? '' : $_SERVER['SCRIPT_NAME']) );
|
$c->protocol_server_port_script = $c->protocol_server_port . ($_SERVER['SCRIPT_NAME'] == '/index.php' ? '' : $_SERVER['SCRIPT_NAME']);
|
||||||
|
|
||||||
init_gettext( 'davical', '../locale' );
|
init_gettext( 'davical', '../locale' );
|
||||||
|
|
||||||
@ -167,7 +167,11 @@ function getUserByName( $username, $use_cache = true ) {
|
|||||||
// Provide some basic caching in case this ends up being overused.
|
// Provide some basic caching in case this ends up being overused.
|
||||||
if ( $use_cache && isset( $_known_users_name[$username] ) ) return $_known_users_name[$username];
|
if ( $use_cache && isset( $_known_users_name[$username] ) ) return $_known_users_name[$username];
|
||||||
|
|
||||||
$qry = new PgQuery( "SELECT *, to_char(updated at time zone 'GMT','Dy, DD Mon IYYY HH24:MI:SS \"GMT\"') AS modified FROM usr WHERE lower(username) = lower(?) ", $username );
|
global $session;
|
||||||
|
if ( isset($session->user_no) )
|
||||||
|
$qry = new PgQuery( "SELECT *, to_char(updated at time zone 'GMT','Dy, DD Mon IYYY HH24:MI:SS \"GMT\"') AS modified, principal.*, user_privileges(?,usr.user_no) AS privileges FROM usr LEFT JOIN principal USING(user_no) WHERE lower(username) = lower(?) ", $session->user_no, $username );
|
||||||
|
else
|
||||||
|
$qry = new PgQuery( "SELECT *, to_char(updated at time zone 'GMT','Dy, DD Mon IYYY HH24:MI:SS \"GMT\"') AS modified, principal.*, 0::BIT(24) AS privileges FROM usr LEFT JOIN principal USING(user_no) WHERE lower(username) = lower(?) ", $username );
|
||||||
if ( $qry->Exec('always',__LINE__,__FILE__) && $qry->rows == 1 ) {
|
if ( $qry->Exec('always',__LINE__,__FILE__) && $qry->rows == 1 ) {
|
||||||
$_known_users_name[$username] = $qry->Fetch();
|
$_known_users_name[$username] = $qry->Fetch();
|
||||||
$id = $_known_users_name[$username]->user_no;
|
$id = $_known_users_name[$username]->user_no;
|
||||||
@ -188,7 +192,8 @@ function getUserByID( $user_no, $use_cache = true ) {
|
|||||||
// Provide some basic caching in case this ends up being overused.
|
// Provide some basic caching in case this ends up being overused.
|
||||||
if ( $use_cache && isset( $_known_users_id[$user_no] ) ) return $_known_users_id[$user_no];
|
if ( $use_cache && isset( $_known_users_id[$user_no] ) ) return $_known_users_id[$user_no];
|
||||||
|
|
||||||
$qry = new PgQuery( "SELECT *, to_char(updated at time zone 'GMT','Dy, DD Mon IYYY HH24:MI:SS \"GMT\"') AS modified FROM usr WHERE user_no = ? ", intval($user_no) );
|
global $session;
|
||||||
|
$qry = new PgQuery( "SELECT *, to_char(updated at time zone 'GMT','Dy, DD Mon IYYY HH24:MI:SS \"GMT\"') AS modified, principal.*, user_privileges(?,usr.user_no) AS privileges FROM usr LEFT JOIN principal USING(user_no) WHERE user_no = ? ", $session->user_no, intval($user_no) );
|
||||||
if ( $qry->Exec('always',__LINE__,__FILE__) && $qry->rows == 1 ) {
|
if ( $qry->Exec('always',__LINE__,__FILE__) && $qry->rows == 1 ) {
|
||||||
$_known_users_id[$user_no] = $qry->Fetch();
|
$_known_users_id[$user_no] = $qry->Fetch();
|
||||||
$name = $_known_users_id[$user_no]->username;
|
$name = $_known_users_id[$user_no]->username;
|
||||||
|
|||||||
@ -68,7 +68,7 @@ if ( !isset($_SERVER['SERVER_NAME']) ) {
|
|||||||
/**
|
/**
|
||||||
* Calculate the simplest form of reference to this page, excluding the PATH_INFO following the script name.
|
* Calculate the simplest form of reference to this page, excluding the PATH_INFO following the script name.
|
||||||
*/
|
*/
|
||||||
$c->protocol_server_port_script = sprintf( '%s://%s%s%s',
|
$c->protocol_server_port = sprintf( '%s://%s%s',
|
||||||
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'? 'https' : 'http'),
|
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'? 'https' : 'http'),
|
||||||
$_SERVER['SERVER_NAME'],
|
$_SERVER['SERVER_NAME'],
|
||||||
(
|
(
|
||||||
@ -76,8 +76,8 @@ $c->protocol_server_port_script = sprintf( '%s://%s%s%s',
|
|||||||
|| (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' && $_SERVER['SERVER_PORT'] == 443 )
|
|| (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' && $_SERVER['SERVER_PORT'] == 443 )
|
||||||
? ''
|
? ''
|
||||||
: ':'.$_SERVER['SERVER_PORT']
|
: ':'.$_SERVER['SERVER_PORT']
|
||||||
),
|
) );
|
||||||
($_SERVER['SCRIPT_NAME'] == '/index.php' ? '' : $_SERVER['SCRIPT_NAME']) );
|
$c->protocol_server_port_script = $c->protocol_server_port . ($_SERVER['SCRIPT_NAME'] == '/index.php' ? '' : $_SERVER['SCRIPT_NAME']);
|
||||||
|
|
||||||
init_gettext( 'davical', '../locale' );
|
init_gettext( 'davical', '../locale' );
|
||||||
|
|
||||||
@ -167,7 +167,11 @@ function getUserByName( $username, $use_cache = true ) {
|
|||||||
// Provide some basic caching in case this ends up being overused.
|
// Provide some basic caching in case this ends up being overused.
|
||||||
if ( $use_cache && isset( $_known_users_name[$username] ) ) return $_known_users_name[$username];
|
if ( $use_cache && isset( $_known_users_name[$username] ) ) return $_known_users_name[$username];
|
||||||
|
|
||||||
$qry = new PgQuery( "SELECT *, to_char(updated at time zone 'GMT','Dy, DD Mon IYYY HH24:MI:SS \"GMT\"') AS modified FROM usr WHERE lower(username) = lower(?) ", $username );
|
global $session;
|
||||||
|
if ( isset($session->user_no) )
|
||||||
|
$qry = new PgQuery( "SELECT *, to_char(updated at time zone 'GMT','Dy, DD Mon IYYY HH24:MI:SS \"GMT\"') AS modified, principal.*, user_privileges(?,usr.user_no) AS privileges FROM usr LEFT JOIN principal USING(user_no) WHERE lower(username) = lower(?) ", $session->user_no, $username );
|
||||||
|
else
|
||||||
|
$qry = new PgQuery( "SELECT *, to_char(updated at time zone 'GMT','Dy, DD Mon IYYY HH24:MI:SS \"GMT\"') AS modified, principal.*, 0::BIT(24) AS privileges FROM usr LEFT JOIN principal USING(user_no) WHERE lower(username) = lower(?) ", $username );
|
||||||
if ( $qry->Exec('always',__LINE__,__FILE__) && $qry->rows == 1 ) {
|
if ( $qry->Exec('always',__LINE__,__FILE__) && $qry->rows == 1 ) {
|
||||||
$_known_users_name[$username] = $qry->Fetch();
|
$_known_users_name[$username] = $qry->Fetch();
|
||||||
$id = $_known_users_name[$username]->user_no;
|
$id = $_known_users_name[$username]->user_no;
|
||||||
@ -188,7 +192,8 @@ function getUserByID( $user_no, $use_cache = true ) {
|
|||||||
// Provide some basic caching in case this ends up being overused.
|
// Provide some basic caching in case this ends up being overused.
|
||||||
if ( $use_cache && isset( $_known_users_id[$user_no] ) ) return $_known_users_id[$user_no];
|
if ( $use_cache && isset( $_known_users_id[$user_no] ) ) return $_known_users_id[$user_no];
|
||||||
|
|
||||||
$qry = new PgQuery( "SELECT *, to_char(updated at time zone 'GMT','Dy, DD Mon IYYY HH24:MI:SS \"GMT\"') AS modified FROM usr WHERE user_no = ? ", intval($user_no) );
|
global $session;
|
||||||
|
$qry = new PgQuery( "SELECT *, to_char(updated at time zone 'GMT','Dy, DD Mon IYYY HH24:MI:SS \"GMT\"') AS modified, principal.*, user_privileges(?,usr.user_no) AS privileges FROM usr LEFT JOIN principal USING(user_no) WHERE user_no = ? ", $session->user_no, intval($user_no) );
|
||||||
if ( $qry->Exec('always',__LINE__,__FILE__) && $qry->rows == 1 ) {
|
if ( $qry->Exec('always',__LINE__,__FILE__) && $qry->rows == 1 ) {
|
||||||
$_known_users_id[$user_no] = $qry->Fetch();
|
$_known_users_id[$user_no] = $qry->Fetch();
|
||||||
$name = $_known_users_id[$user_no]->username;
|
$name = $_known_users_id[$user_no]->username;
|
||||||
|
|||||||
@ -10,6 +10,8 @@
|
|||||||
*/
|
*/
|
||||||
dbg_error_log("MOVE", "method handler");
|
dbg_error_log("MOVE", "method handler");
|
||||||
|
|
||||||
|
require_once('DAVResource.php');
|
||||||
|
|
||||||
if ( ! $request->AllowedTo("read") ) {
|
if ( ! $request->AllowedTo("read") ) {
|
||||||
$request->DoResponse(403);
|
$request->DoResponse(403);
|
||||||
}
|
}
|
||||||
@ -28,18 +30,26 @@ if ( $request->path == '/' || $request->IsPrincipal() || $request->destination =
|
|||||||
$request->DoResponse( 403 );
|
$request->DoResponse( 403 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !class_exists('DAVResource') ) require('DAVResource.php');
|
|
||||||
$dest = new DAVResource($request->destination);
|
$dest = new DAVResource($request->destination);
|
||||||
|
|
||||||
if ( $dest->path == '/' || $dest->IsPrincipal() ) {
|
if ( $dest->dav_name() == '/' || $dest->IsPrincipal() ) {
|
||||||
$request->DoResponse( 403 );
|
$request->DoResponse( 403 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! $request->overwrite && $dest->Exists() ) {
|
if ( ! $request->overwrite && $dest->Exists() ) {
|
||||||
$request->DoResponse( 412 );
|
$request->DoResponse( 412, translate('Not overwriting existing destination resource') );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $request->IsCollection() ) {
|
if ( isset($request->etag_none_match) && $request->etag_none_match != '*' ) {
|
||||||
|
$request->DoResponse( 412 ); /** request to move, but only if there is no source? WTF! */
|
||||||
|
}
|
||||||
|
|
||||||
|
$src = new DAVResource($request->path);
|
||||||
|
if ( ! $src->Exists() ) {
|
||||||
|
$request->DoResponse( 412, translate('Source resource does not exist.') );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $src->IsCollection() ) {
|
||||||
switch( $dest->ContainerType() ) {
|
switch( $dest->ContainerType() ) {
|
||||||
case 'calendar':
|
case 'calendar':
|
||||||
case 'addressbook':
|
case 'addressbook':
|
||||||
@ -48,14 +58,41 @@ if ( $request->IsCollection() ) {
|
|||||||
$request->DoResponse( 412, translate('Special collections may not contain a calendar or other special collection.') );
|
$request->DoResponse( 412, translate('Special collections may not contain a calendar or other special collection.') );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if ( (isset($request->etag_if_match) && $request->etag_if_match != '' )
|
||||||
|
|| ( isset($request->etag_none_match) && $request->etag_none_match != '') ) {
|
||||||
|
|
||||||
if ( ! $request->AllowedTo('delete') ) $request->DoResponse( 403 );
|
/**
|
||||||
if ( ! $dest->HaveRightsTo('DAV::write') ) $request->DoResponse( 403 );
|
* RFC2068, 14.25:
|
||||||
if ( ! $dest->Exists() && !$dest->HaveRightsTo('DAV::bind') ) $request->DoResponse( 403 );
|
* If none of the entity tags match, or if "*" is given and no current
|
||||||
// if ( ! $request->HaveRightsTo('DAV::unbind') ) $request->DoResponse( 403 );
|
* entity exists, the server MUST NOT perform the requested method, and
|
||||||
|
* MUST return a 412 (Precondition Failed) response.
|
||||||
|
*
|
||||||
|
* RFC2068, 14.26:
|
||||||
|
* If any of the entity tags match the entity tag of the entity that
|
||||||
|
* would have been returned in the response to a similar GET request
|
||||||
|
* (without the If-None-Match header) on that resource, or if "*" is
|
||||||
|
* given and any current entity exists for that resource, then the
|
||||||
|
* server MUST NOT perform the requested method.
|
||||||
|
*/
|
||||||
|
$error = '';
|
||||||
|
if ( isset($request->etag_if_match) && $request->etag_if_match != $src->unique_tag() ) {
|
||||||
|
$error = translate( 'Existing resource does not match "If-Match" header - not accepted.');
|
||||||
|
}
|
||||||
|
else if ( isset($request->etag_none_match) && $request->etag_none_match != '' && $request->etag_none_match == $src->unique_tag() ) {
|
||||||
|
$error = translate( 'Existing resource matches "If-None-Match" header - not accepted.');
|
||||||
|
}
|
||||||
|
if ( $error != '' ) $request->DoResponse( 412, $error );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! $src->HavePrivilegeTo('DAV::unbind') ) $request->DoResponse( 403 );
|
||||||
|
if ( ! $dest->HavePrivilegeTo('DAV::write') ) $request->DoResponse( 403 );
|
||||||
|
if ( ! $dest->Exists() && !$dest->HavePrivilegeTo('DAV::bind') ) $request->DoResponse( 403 );
|
||||||
|
|
||||||
|
|
||||||
function rollback( $response_code = 412 ) {
|
function rollback( $response_code = 412 ) {
|
||||||
|
global $request;
|
||||||
$qry = new AwlQuery('ROLLBACK');
|
$qry = new AwlQuery('ROLLBACK');
|
||||||
$qry->Exec('move'); // Just in case
|
$qry->Exec('move'); // Just in case
|
||||||
$request->DoResponse( $response_code );
|
$request->DoResponse( $response_code );
|
||||||
@ -66,21 +103,73 @@ function rollback( $response_code = 412 ) {
|
|||||||
$qry = new AwlQuery('BEGIN');
|
$qry = new AwlQuery('BEGIN');
|
||||||
if ( !$qry->Exec('move') ) rollback(500);
|
if ( !$qry->Exec('move') ) rollback(500);
|
||||||
|
|
||||||
if ( $request->IsCollection() ) {
|
$src_name = $src->dav_name();
|
||||||
|
$dst_name = $dest->dav_name();
|
||||||
|
$src_collection = $src->GetProperty('collection_id');
|
||||||
|
$dst_collection = $dest->GetProperty('collection_id');
|
||||||
|
$src_user_no = $src->GetProperty('user_no');
|
||||||
|
$dst_user_no = $dest->GetProperty('user_no');
|
||||||
|
|
||||||
|
|
||||||
|
if ( $src->IsCollection() ) {
|
||||||
|
if ( $dest->Exists() ) {
|
||||||
|
$qry = new AwlQuery( 'DELETE FROM collection WHERE dav_name = :dst_name', array( ':dst_name' => $dst_name ) );
|
||||||
|
if ( !$qry->Exec('move') ) rollback(500);
|
||||||
|
}
|
||||||
/** @TODO: Need to confirm this will work correctly if we move this into another user's hierarchy. */
|
/** @TODO: Need to confirm this will work correctly if we move this into another user's hierarchy. */
|
||||||
$qry = new AwlQuery( 'UPDATE collection SET dav_name = :new_dav_name WHERE collection_id = :collection_id', array(
|
$sql = 'UPDATE collection SET dav_name = :dst_name ';
|
||||||
':new_dav_name' => $dest->dav_name(),
|
$params = array(':dst_name' => $dst_name);
|
||||||
':collection_id' => $request->collection
|
if ( $src_user_no != $dst_user_no ) {
|
||||||
);
|
$sql .= ', user_no = :dst_user_no';
|
||||||
|
$params[':dst_user_no'] = $dst_user_no;
|
||||||
|
}
|
||||||
|
$sql .= 'WHERE collection_id = :src_collection';
|
||||||
|
$params[':src_collection'] = $src_collection;
|
||||||
|
$qry = new AwlQuery( $sql, $params );
|
||||||
|
if ( !$qry->Exec('move') ) rollback(500);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$qry = new AwlQuery( 'UPDATE caldav_data SET dav_name = :new_dav_name WHERE dav_name = :old_dav_name', array(
|
if ( $dest->Exists() ) {
|
||||||
':old_dav_name' => $request->dav_name(),
|
$qry = new AwlQuery( 'DELETE FROM caldav_data WHERE dav_name = :dst_name', array( ':dst_name' => $dst_name) );
|
||||||
':new_dav_name' => $dest->dav_name()
|
if ( !$qry->Exec('move') ) rollback(500);
|
||||||
);
|
}
|
||||||
|
$sql = 'UPDATE caldav_data SET dav_name = :dst_name';
|
||||||
|
$params = array( ':dst_name' => $dst_name );
|
||||||
|
if ( $src_user_no != $dst_user_no ) {
|
||||||
|
$sql .= ', user_no = :dst_user_no';
|
||||||
|
$params[':dst_user_no'] = $dst_user_no;
|
||||||
|
}
|
||||||
|
if ( $src_collection != $dst_collection ) {
|
||||||
|
$sql .= ', collection_id = :dst_collection';
|
||||||
|
$params[':dst_collection'] = $dst_collection;
|
||||||
|
}
|
||||||
|
$sql .=' WHERE dav_name = :src_name';
|
||||||
|
$params[':src_name'] = $src_name;
|
||||||
|
$qry = new AwlQuery( $sql, $params );
|
||||||
|
if ( !$qry->Exec('move') ) rollback(500);
|
||||||
|
|
||||||
|
$qry = new AwlQuery( 'SELECT write_sync_change( :src_collection, 404, :src_name );', array(
|
||||||
|
':src_name' => $src_name,
|
||||||
|
':src_collection' => $src_collection
|
||||||
|
) );
|
||||||
|
if ( !$qry->Exec('move') ) rollback(500);
|
||||||
|
if ( function_exists('log_caldav_action') ) {
|
||||||
|
log_caldav_action( 'DELETE', $src->GetProperty('uid'), $src_user_no, $src_collection, $src_name );
|
||||||
|
}
|
||||||
|
|
||||||
|
$qry = new AwlQuery( 'SELECT write_sync_change( :dst_collection, :sync_type, :dst_name );', array(
|
||||||
|
':dst_name' => $dst_name,
|
||||||
|
':dst_collection' => $dst_collection,
|
||||||
|
':sync_type' => ( $dest->Exists() ? 200 : 201 )
|
||||||
|
) );
|
||||||
|
if ( !$qry->Exec('move') ) rollback(500);
|
||||||
|
if ( function_exists('log_caldav_action') ) {
|
||||||
|
log_caldav_action( ( $dest->Exists() ? 'UPDATE' : 'INSERT' ), $src->GetProperty('uid'), $dst_user_no, $dst_collection, $dst_name );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$qry = new PgQuery('COMMIT');
|
$qry = new PgQuery('COMMIT');
|
||||||
if ( !$qry->Exec('move') ) rollback(500);
|
if ( !$qry->Exec('move') ) rollback(500);
|
||||||
|
|
||||||
$request->DoResponse( ($put_action_type == 'INSERT' ? 201 : 204) );
|
$request->DoResponse( 200 );
|
||||||
|
|||||||
@ -4,9 +4,9 @@
|
|||||||
*
|
*
|
||||||
* @package davical
|
* @package davical
|
||||||
* @subpackage caldav
|
* @subpackage caldav
|
||||||
* @author Andrew McMillan <andrew@catalyst.net.nz>
|
* @author Andrew McMillan <andrew@mcmillan.net.nz>
|
||||||
* @copyright Catalyst .Net Ltd
|
* @copyright Catalyst .Net Ltd, Morphoss Ltd <http://www.morphoss.com/>
|
||||||
* @license http://gnu.org/copyleft/gpl.html GNU GPL v2
|
* @license http://gnu.org/copyleft/gpl.html GNU GPL v2 or later
|
||||||
*/
|
*/
|
||||||
dbg_error_log("OPTIONS", "method handler");
|
dbg_error_log("OPTIONS", "method handler");
|
||||||
|
|
||||||
@ -53,8 +53,11 @@ if ( !$exists ) {
|
|||||||
*/
|
*/
|
||||||
if ( isset($c->override_allowed_methods) )
|
if ( isset($c->override_allowed_methods) )
|
||||||
$allowed = $c->override_allowed_methods;
|
$allowed = $c->override_allowed_methods;
|
||||||
|
else if ( isset($request->supported_methods) ) {
|
||||||
|
$allowed = implode( ', ', array_keys($request->supported_methods) );
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
$allowed = "OPTIONS, GET, HEAD, PUT, DELETE, PROPFIND, MKCOL, MKCALENDAR, LOCK, UNLOCK, REPORT, PROPPATCH, POST";
|
$allowed = "OPTIONS, GET, HEAD, PUT, DELETE, PROPFIND, MKCOL, MKCALENDAR, LOCK, UNLOCK, REPORT, PROPPATCH, POST, MOVE";
|
||||||
if ( $request->path == '/' ) {
|
if ( $request->path == '/' ) {
|
||||||
$exists = true;
|
$exists = true;
|
||||||
$allowed = "OPTIONS, GET, HEAD, PROPFIND, REPORT";
|
$allowed = "OPTIONS, GET, HEAD, PROPFIND, REPORT";
|
||||||
@ -65,4 +68,3 @@ header( "Allow: $allowed");
|
|||||||
|
|
||||||
$request->DoResponse( 200, "" );
|
$request->DoResponse( 200, "" );
|
||||||
|
|
||||||
?>
|
|
||||||
|
|||||||
@ -365,9 +365,9 @@ function import_collection( $ics_content, $user_no, $path, $caldav_context ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$sql .= <<<EOSQL
|
$sql .= <<<EOSQL
|
||||||
INSERT INTO calendar_item (user_no, dav_name, dav_etag, uid, dtstamp, dtstart, dtend, summary, location, class, transp,
|
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 )
|
description, rrule, tz_id, last_modified, url, priority, created, due, percent_complete, status, collection_id )
|
||||||
VALUES ( ?, ?, ?, ?, ?, ?, $dtend, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
VALUES ( ?, ?, currval('dav_id_seq'), ?, ?, ?, ?, $dtend, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
||||||
EOSQL;
|
EOSQL;
|
||||||
|
|
||||||
$qry = new PgQuery( $sql, $user_no, $resource_path, $etag, $first->GetPValue('UID'), $dtstamp,
|
$qry = new PgQuery( $sql, $user_no, $resource_path, $etag, $first->GetPValue('UID'), $dtstamp,
|
||||||
@ -417,13 +417,13 @@ function putCalendarResource( &$request, $author, $caldav_context ) {
|
|||||||
* entity exists, the server MUST NOT perform the requested method, and
|
* entity exists, the server MUST NOT perform the requested method, and
|
||||||
* MUST return a 412 (Precondition Failed) response.
|
* MUST return a 412 (Precondition Failed) response.
|
||||||
*/
|
*/
|
||||||
rollback_on_error( $caldav_context, $request->user_no, $request->path, 412, translate('Resource changed on server - not changed.') );
|
rollback_on_error( $caldav_context, $request->user_no, $request->path, translate('Resource changed on server - not changed.'), 412 );
|
||||||
}
|
}
|
||||||
|
|
||||||
$put_action_type = 'INSERT';
|
$put_action_type = 'INSERT';
|
||||||
|
|
||||||
if ( ! $request->AllowedTo('create') ) {
|
if ( ! $request->AllowedTo('create') ) {
|
||||||
rollback_on_error( $caldav_context, $request->user_no, $request->path, 403, translate('You may not add entries to this calendar.') );
|
rollback_on_error( $caldav_context, $request->user_no, $request->path, translate('You may not add entries to this calendar.'), 403 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elseif ( $qry->rows == 1 ) {
|
elseif ( $qry->rows == 1 ) {
|
||||||
@ -447,7 +447,7 @@ function putCalendarResource( &$request, $author, $caldav_context ) {
|
|||||||
if ( isset($request->etag_if_match) && $request->etag_if_match != $icalendar->dav_etag ) {
|
if ( isset($request->etag_if_match) && $request->etag_if_match != $icalendar->dav_etag ) {
|
||||||
$error = translate( 'Existing resource does not match "If-Match" header - not accepted.');
|
$error = translate( 'Existing resource does not match "If-Match" header - not accepted.');
|
||||||
}
|
}
|
||||||
if ( isset($etag_none_match) && $etag_none_match != '' && ($etag_none_match == $icalendar->dav_etag || $etag_none_match == '*') ) {
|
if ( isset($request->etag_none_match) && $request->etag_none_match != '' && ($request->etag_none_match == $icalendar->dav_etag || $request->etag_none_match == '*') ) {
|
||||||
$error = translate( 'Existing resource matches "If-None-Match" header - not accepted.');
|
$error = translate( 'Existing resource matches "If-None-Match" header - not accepted.');
|
||||||
}
|
}
|
||||||
$request->DoResponse( 412, $error );
|
$request->DoResponse( 412, $error );
|
||||||
@ -490,12 +490,21 @@ function write_resource( $user_no, $path, $caldav_data, $collection_id, $author,
|
|||||||
global $tz_regex;
|
global $tz_regex;
|
||||||
|
|
||||||
$resources = $ic->GetComponents('VTIMEZONE',false); // Not matching VTIMEZONE
|
$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];
|
$first = $resources[0];
|
||||||
|
$resource_type = $first->GetType();
|
||||||
|
}
|
||||||
|
|
||||||
if ( $put_action_type == 'INSERT' ) {
|
if ( $put_action_type == 'INSERT' ) {
|
||||||
create_scheduling_requests($vcal);
|
create_scheduling_requests($vcal);
|
||||||
$qry = new PgQuery( 'BEGIN; INSERT INTO caldav_data ( user_no, dav_name, dav_etag, caldav_data, caldav_type, logged_user, created, modified, collection_id ) VALUES( ?, ?, ?, ?, ?, ?, current_timestamp, current_timestamp, ? )',
|
$qry = new PgQuery( 'BEGIN; INSERT INTO caldav_data ( user_no, dav_name, dav_etag, caldav_data, caldav_type, logged_user, created, modified, collection_id ) VALUES( ?, ?, ?, ?, ?, ?, current_timestamp, current_timestamp, ? )',
|
||||||
$user_no, $path, $etag, $caldav_data, $first->GetType(), $author, $collection_id );
|
$user_no, $path, $etag, $caldav_data, $resource_type, $author, $collection_id );
|
||||||
if ( !$qry->Exec('PUT') ) {
|
if ( !$qry->Exec('PUT') ) {
|
||||||
rollback_on_error( $caldav_context, $user_no, $path);
|
rollback_on_error( $caldav_context, $user_no, $path);
|
||||||
return false;
|
return false;
|
||||||
@ -504,7 +513,7 @@ function write_resource( $user_no, $path, $caldav_data, $collection_id, $author,
|
|||||||
else {
|
else {
|
||||||
update_scheduling_requests($vcal);
|
update_scheduling_requests($vcal);
|
||||||
$qry = new PgQuery( 'BEGIN;UPDATE caldav_data SET caldav_data=?, dav_etag=?, caldav_type=?, logged_user=?, modified=current_timestamp WHERE user_no=? AND dav_name=?',
|
$qry = new PgQuery( 'BEGIN;UPDATE caldav_data SET caldav_data=?, dav_etag=?, caldav_type=?, logged_user=?, modified=current_timestamp WHERE user_no=? AND dav_name=?',
|
||||||
$caldav_data, $etag, $first->GetType(), $author, $user_no, $path );
|
$caldav_data, $etag, $resource_type, $author, $user_no, $path );
|
||||||
if ( !$qry->Exec('PUT') ) {
|
if ( !$qry->Exec('PUT') ) {
|
||||||
rollback_on_error( $caldav_context, $user_no, $path);
|
rollback_on_error( $caldav_context, $user_no, $path);
|
||||||
return false;
|
return false;
|
||||||
@ -639,11 +648,11 @@ EOSQL;
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$sql .= <<<EOSQL
|
$sql .= <<<EOSQL
|
||||||
INSERT INTO calendar_item (user_no, dav_name, dav_etag, uid, dtstamp,
|
INSERT INTO calendar_item (user_no, dav_name, dav_id, dav_etag, uid, dtstamp,
|
||||||
dtstart, dtend, summary, location, class, transp,
|
dtstart, dtend, summary, location, class, transp,
|
||||||
description, rrule, tz_id, last_modified, url, priority,
|
description, rrule, tz_id, last_modified, url, priority,
|
||||||
created, due, percent_complete, status, collection_id )
|
created, due, percent_complete, status, collection_id )
|
||||||
VALUES ( $user_no, $escaped_path, ?, ?, ?,
|
VALUES ( $user_no, $escaped_path, currval('dav_id_seq'), ?, ?, ?,
|
||||||
?, $dtend, ?, ?, ?, ?,
|
?, $dtend, ?, ?, ?, ?,
|
||||||
?, ?, ?, ?, ?, ?,
|
?, ?, ?, ?, ?, ?,
|
||||||
?, ?, ?, ?, $collection_id );
|
?, ?, ?, ?, $collection_id );
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user