17 $sync_level = $xmltree->GetPath(
'/DAV::sync-collection/DAV::sync-level');
18 if ( empty($sync_level) ) {
19 $sync_level = $request->depth;
22 $sync_level = $sync_level[0]->GetContent();
23 if ( $sync_level ==
'infinity' )
24 $sync_level = DEPTH_INFINITY;
29 if ( $sync_level == DEPTH_INFINITY ) {
30 $request->PreconditionFailed(403,
'DAV::sync-traversal-supported',
'This server does not support sync-traversal');
33 $sync_tokens = $xmltree->GetPath(
'/DAV::sync-collection/DAV::sync-token');
34 if ( isset($sync_tokens[0]) ) $sync_token = $sync_tokens[0]->GetContent();
35 if ( !isset($sync_token) ) $sync_token = 0;
36 $sync_token = intval(str_replace(
'data:,',
'', strtolower($sync_token) ));
37 dbg_error_log(
'sync',
" sync-token: %s", $sync_token );
40 $props = $xmltree->GetPath(
'/DAV::sync-collection/DAV::prop/*');
41 if ( !empty($props) ) {
42 foreach( $props AS $k => $v ) {
43 $proplist[] = $v->GetNSTag();
47 function display_status( $status_code ) {
48 return sprintf(
'HTTP/1.1 %03d %s', intval($status_code), getStatusMessage($status_code) );
52 if ( !$collection->Exists() ) {
53 $request->DoResponse( 404 );
55 $bound_from = $collection->bound_from();
56 $collection_path = $collection->dav_name();
57 $request_via_binding = ($bound_from != $collection_path);
59 $params = array(
':collection_id' => $collection->GetProperty(
'collection_id'),
':sync_token' => $sync_token );
60 $sql =
"SELECT new_sync_token( :sync_token, :collection_id)";
61 $qry =
new AwlQuery($sql, $params);
62 if ( !$qry->Exec(
"REPORT",__LINE__,__FILE__) || $qry->rows() <= 0 ) {
63 $request->DoResponse( 500, translate(
"Database error") );
67 if ( !isset($row->new_sync_token) ) {
70 $params[
':sync_token'] = $sync_token;
71 if ( !$qry->QDo($sql, $params) || $qry->rows() <= 0 ) {
72 $request->DoResponse( 500, translate(
"Database error") );
76 $new_token = $row->new_sync_token;
78 if ( $sync_token == $new_token ) {
80 $responses[] =
new XMLElement(
'sync-token',
'data:,'.$new_token );
84 if ( isset($c->hide_older_than) && intval($c->hide_older_than) > 0 )
85 $hide_older =
" AND (CASE WHEN caldav_data.caldav_type<>'VEVENT' OR calendar_item.dtstart IS NULL OR calendar_item.rrule IS NOT NULL THEN true ELSE calendar_item.dtstart > (now() - interval '".intval($c->hide_older_than).
" days') END)";
88 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') )
89 $hide_todo =
" AND (caldav_data.caldav_type NOT IN ('VTODO') OR caldav_data.caldav_type IS NULL) ";
91 if ( $sync_token == 0 ) {
93 SELECT collection.*, calendar_item.*, caldav_data.*, addressbook_resource.*, 201 AS sync_status FROM collection
94 LEFT JOIN caldav_data USING (collection_id)
95 LEFT JOIN calendar_item USING (dav_id)
96 LEFT JOIN addressbook_resource USING (dav_id)
97 WHERE collection.collection_id = :collection_id $hide_older $hide_todo
98 ORDER BY collection.collection_id, caldav_data.dav_id
100 unset($params[
':sync_token']);
104 SELECT collection.*, calendar_item.*, caldav_data.*, addressbook_resource.*, sync_changes.*
105 FROM collection LEFT JOIN sync_changes USING(collection_id)
106 LEFT JOIN caldav_data USING (collection_id,dav_id)
107 LEFT JOIN calendar_item USING (collection_id,dav_id)
108 LEFT JOIN addressbook_resource USING (dav_id)
109 WHERE collection.collection_id = :collection_id $hide_older $hide_todo
110 AND sync_time >= (SELECT modification_time FROM sync_tokens WHERE sync_token = :sync_token)
112 if ( isset($c->strict_result_ordering) && $c->strict_result_ordering ) {
113 $sql .=
" ORDER BY collection.collection_id, lower(sync_changes.dav_name), sync_changes.sync_time";
116 $sql .=
" ORDER BY collection.collection_id, sync_changes.dav_name, sync_changes.sync_time";
119 $qry =
new AwlQuery($sql, $params );
124 if ( $qry->Exec(
"REPORT",__LINE__,__FILE__) ) {
125 if ( $qry->rows() > 50 ) {
127 $c->sync_resource_data_ok =
false;
129 while( $object = $qry->Fetch() ) {
130 if ( $request_via_binding )
131 $object->dav_name = str_replace( $bound_from, $collection_path, $object->dav_name);
133 if ( $object->dav_name == $last_dav_name ) {
135 if ( $object->sync_status == 404 ) {
136 array_pop($responses);
138 new XMLElement(
'href', ConstructURL($object->dav_name) ),
139 new XMLElement(
'status', display_status($object->sync_status) )
141 $responses[] =
new XMLElement(
'response', $resultset );
144 else if ( $object->sync_status == 201 && $first_status == 404 ) {
146 array_pop($responses);
147 $dav_resource =
new DAVResource($object, $collection);
148 $resultset = $dav_resource->GetPropStat($proplist,$reply);
149 array_unshift($resultset,
new XMLElement(
'href', ConstructURL($object->dav_name)));
150 $responses[] =
new XMLElement(
'response', $resultset );
162 if ( $object->sync_status == 404 ) {
164 new XMLElement(
'href', ConstructURL($object->dav_name) ),
165 new XMLElement(
'status', display_status($object->sync_status) )
170 $dav_resource =
new DAVResource($object, $collection);
171 $resultset = $dav_resource->GetPropStat($proplist,$reply);
172 array_unshift($resultset,
new XMLElement(
'href', ConstructURL($object->dav_name)));
173 $first_status = $object->sync_status;
175 $responses[] =
new XMLElement(
'response', $resultset );
176 $last_dav_name = $object->dav_name;
179 $responses[] =
new XMLElement(
'sync-token',
'data:,'.$new_token );
182 $request->DoResponse( 500, translate(
"Database error") );
186 $multistatus =
new XMLElement(
"multistatus", $responses, $reply->GetXmlNsArray() );
188 $request->XMLResponse( 207, $multistatus );