DAViCal
Loading...
Searching...
No Matches
caldav-BIND.php
1<?php
11dbg_error_log('BIND', 'method handler');
12require_once('AwlQuery.php');
13
14$request->NeedPrivilege('DAV::bind');
15
16if ( ! $request->IsCollection() ) {
17 $request->PreconditionFailed(403,'DAV::bind-into-collection',translate('The BIND Request-URI MUST identify a collection.'));
18}
19$parent_container = $request->path;
20if ( preg_match( '{[^/]$}', $parent_container ) ) $parent_container .= '/';
21
22require_once('DAVResource.php');
23$parent = new DAVResource( $parent_container );
24if ( ! $parent->Exists() || $parent->IsSchedulingCollection() ) {
25 $request->PreconditionFailed(403, 'DAV::method-not-allowed',translate('The BIND method is not allowed at that location.') );
26}
27
28require_once('XMLDocument.php');
29$reply = new XMLDocument(array( 'DAV:' => '' ));
30
31$xmltree = BuildXMLTree( $request->xml_tags );
32
33$segment = $xmltree->GetElements('DAV::segment');
34$segment = $segment[0]->GetContent();
35
36if ( preg_match( '{[/\\\\]}', $segment ) ) {
37 $request->PreconditionFailed(403, 'DAV::name-allowed',translate('That destination name contains invalid characters.') );
38}
39
40$href = $xmltree->GetElements('DAV::href');
41$href = $href[0]->GetContent();
42
43$destination_path = $parent_container . $segment .'/';
44$destination = new DAVResource( $destination_path );
45if ( $destination->Exists() ) {
46 $request->PreconditionFailed(403,'DAV::can-overwrite',translate('A resource already exists at the destination.'));
47}
48
49// external binds shouldn't ever point back to ourselves but they should be a valid http[s] url
50if ( preg_match ( '{^(?:https?://|file:///)([^/]+)(:[0-9]\+)?/.+$}', $href, $matches )
51 && strcasecmp( $matches[0], 'localhost' ) !== 0 && strcasecmp( $matches[0], '127.0.0.1' ) !== 0
52 && strcasecmp( $matches[0], $_SERVER['SERVER_NAME'] ) !== 0 && strcasecmp( $matches[0], $_SERVER['SERVER_ADDR'] ) !== 0 ) {
53 require_once('external-fetch.php');
54 $qry = new AwlQuery( );
55 $qry->QDo('SELECT collection_id FROM collection WHERE dav_name = :dav_name ', array( ':dav_name' => '/.external/'. md5($href) ));
56 if ( $qry->rows() == 1 && ($row = $qry->Fetch()) ) {
57 $dav_id = $row->collection_id;
58 }
59 else {
60 create_external ( '/.external/'. md5($href) ,true,false );
61 $qry->QDo('SELECT collection_id FROM collection WHERE dav_name = :dav_name ', array( ':dav_name' => '/.external/'. md5($href) ));
62 if ( $qry->rows() != 1 || !($row = $qry->Fetch()) )
63 $request->DoResponse(500,translate('Database Error'));
64 $dav_id = $row->collection_id;
65 }
66
67 $sql = 'INSERT INTO dav_binding ( bound_source_id, access_ticket_id, dav_owner_id, parent_container, dav_name, dav_displayname, external_url, type )
68 VALUES( :target_id, :ticket_id, :session_principal, :parent_container, :dav_name, :displayname, :external_url, :external_type )';
69 $params = array(
70 ':target_id' => $dav_id,
71 ':ticket_id' => null,
72 ':parent_container' => $parent->dav_name(),
73 ':session_principal' => $session->principal_id,
74 ':dav_name' => $destination_path,
75 ':displayname' => $segment,
76 ':external_url' => $href,
77 ':external_type' => 'calendar'
78 );
79 $qry = new AwlQuery( $sql, $params );
80 if ( $qry->Exec('BIND',__LINE__,__FILE__) ) {
81 $qry = new AwlQuery( 'SELECT bind_id from dav_binding where dav_name = :dav_name', array( ':dav_name' => $destination_path ) );
82 if ( ! $qry->Exec('BIND',__LINE__,__FILE__) || $qry->rows() != 1 || !($row = $qry->Fetch()) )
83 $request->DoResponse(500,translate('Database Error'));
84 fetch_external ( $row->bind_id, '', $c->external_ua_string );
85 $request->DoResponse(201);
86 }
87 else {
88 $request->DoResponse(500,translate('Database Error'));
89 }
90}
91else {
92 $source = new DAVResource( $href );
93 if ( !$source->Exists() ) {
94 $request->PreconditionFailed(403,'DAV::bind-source-exists',translate('The BIND Request MUST identify an existing resource.'));
95 }
96
97 if ( $source->IsPrincipal() || !$source->IsCollection() ) {
98 $request->PreconditionFailed(403,'DAV::binding-allowed',translate('DAViCal only allows BIND requests for collections at present.'));
99 }
100
101 if ( $source->IsBinding() )
102 $source = new DAVResource( $source->bound_from() );
103
104
105 /*
106 bind_id INT8 DEFAULT nextval('dav_id_seq') PRIMARY KEY,
107 bound_source_id INT8 REFERENCES collection(collection_id) ON UPDATE CASCADE ON DELETE CASCADE,
108 access_ticket_id TEXT REFERENCES access_ticket(ticket_id) ON UPDATE CASCADE ON DELETE SET NULL,
109 parent_container TEXT NOT NULL,
110 dav_name TEXT UNIQUE NOT NULL,
111 dav_displayname TEXT,
112 external_url TEXT,
113 type TEXT
114 */
115
116 $sql = 'INSERT INTO dav_binding ( bound_source_id, access_ticket_id, dav_owner_id, parent_container, dav_name, dav_displayname )
117 VALUES( :target_id, :ticket_id, :session_principal, :parent_container, :dav_name, :displayname )';
118 $params = array(
119 ':target_id' => $source->GetProperty('collection_id'),
120 ':ticket_id' => (isset($request->ticket) ? $request->ticket->id() : null),
121 ':parent_container' => $parent->dav_name(),
122 ':session_principal' => $session->principal_id,
123 ':dav_name' => $destination_path,
124 ':displayname' => $source->GetProperty('displayname')
125 );
126 $qry = new AwlQuery( $sql, $params );
127 if ( $qry->Exec('BIND',__LINE__,__FILE__) ) {
128 header('Location: '. ConstructURL($destination_path) );
129
130 // Uncache anything to do with the target
131 $cache = getCacheInstance();
132 $cache_ns = 'collection-'.$destination_path;
133 $cache->delete( $cache_ns, null );
134
135 $request->DoResponse(201);
136 }
137 else {
138 $request->DoResponse(500,translate('Database Error'));
139 }
140}