Index: openacs-4/packages/caldav/tcl/caldav-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/caldav/tcl/caldav-procs.tcl,v
diff -u -r1.1.2.5 -r1.1.2.6
--- openacs-4/packages/caldav/tcl/caldav-procs.tcl 4 Dec 2022 13:08:26 -0000 1.1.2.5
+++ openacs-4/packages/caldav/tcl/caldav-procs.tcl 4 Dec 2022 13:09:03 -0000 1.1.2.6
@@ -34,11 +34,11 @@
ad_proc -private get_sync_calendar {
-user_id:required
} {
-
+
Get the calendar, to which we want to sync. This method
returns the first (and only in usual installations)
calendar_id if it is found.
-
+
} {
set calendar_id [ns_cache_eval ns:memoize caldav-sync-cal-$user_id \
::xo::dc list get_sync_calendar {
@@ -109,12 +109,12 @@
# of every HTTP method implementation, "response" should be used
# for delivering the result.
#
-
+
CalDAV instproc response {code mimetype response} {
ns_log Debug(caldav-request) "Response ([ns_conn partialtimes]) for ${:method} $code ${:uri}\n$response"
ns_return $code $mimetype $response
}
-
+
CalDAV instproc getcontent {{headers ""}} {
lappend headers Content-Type "" User-Agent ""
foreach {tag default} $headers {
@@ -135,7 +135,7 @@
return $uid
}
-
+
###
### HTTP method GET
###
@@ -147,18 +147,18 @@
syntax of the URL.
- individual cal_items (must end with .ics)
-
+
/caldav/calendar/12872/12907.ics
-
+
- complete calendar
-
+
/caldav/calendar
/caldav/calendar?calendar_ids=12872
/caldav/calendar/12872
where the "12872" is a calendar_id and "12907"
is the UID of a calendar item.
-
+
} {
# the following getcontent call is just for consistent logging
:getcontent
@@ -177,9 +177,9 @@
set uid [:get_uid_from_href ${:uri}]
:debug "return single calendar item for uid $uid"
- #
+ #
# We need the calendar_ids for consistent naming of
- # calendars (aggregated, etc.)....
+ # calendars (aggregated, etc.)....
#
if {[string is integer -strict [lindex ${:urlv} end-1]]} {
set calendar_ids [lindex ${:urlv} end-1]
@@ -214,7 +214,7 @@
limit 1
}]
}
-
+
#:debug "cal_items 2: <$cal_items>"
if {[llength $cal_items] == 1} {
lassign [lindex $cal_items 0] cal_item_id ical_vars creation_date last_modified
@@ -235,7 +235,7 @@
array unset c
append resp [$vevent as_ical_calendar -calendar_name [:calendarName]]
$vevent destroy
-
+
# GN TODO: do we need always the database to get an etag ?
ns_set put [ns_conn outputheaders] ETag [subst {"[:getETagByUID $uid]"}]
set code 200
@@ -262,15 +262,15 @@
# The query parameter "calendar_ids" is used e.g. for
# regression testing.
#
- # GN TODO:
+ # GN TODO:
#
if {[llength ${:urlv}] > 1} {
set calendar_ids [lindex ${:urlv} 1]
} else {
set calendar_ids [ns_queryget calendar_ids ""]
}
:calendar_ids $calendar_ids
-
+
if {$calendar_ids ne ""} {
#
# For specified calendars, return the calendar name of
@@ -320,8 +320,8 @@
# SHOULD support "infinity" requests. Servers SHOULD treat a
# request without a Depth header as if a "Depth: infinity"
# header was included.
- #
-
+ #
+
set depth [ns_set iget [ns_conn headers] Depth "infinity"]
#ns_log notice "caldav: depth = $depth"
@@ -380,7 +380,7 @@
# - PRINCIPAL: /caldav/principal
# - FULL CALENDAR: /caldav/calendar
#
-
+
# GN TODO: remove the following test when we are sure it is ok.
#ns_log notice "PROPFIND <${:uri}>, tail <[file tail ${:uri}]> urlv: <${:urlv}>"
if {[file tail ${:uri}] ne [lindex ${:urlv} end]} {
@@ -418,7 +418,7 @@
#append response [:generateResponse -queryType calendar -calendar_id $calendar_id $prop]
append response [:generateResponse -queryType calendar -calendar_id "" $prop]
#ns_log notice "=== CALENDAR depth $depth FIND getetag=[$prop selectNodes -namespaces {d DAV:} //d:getetag] PROP [$prop asXML] "
-
+
if {$depth ne "0"} {
#
# Search in depth 1 to deeper. Since all our
@@ -472,7 +472,7 @@
#
set :calendar_ids $value
}
-
+
CalDAV instproc calendarName {} {
:debug "calendarName has :calendar_ids <${:calendar_ids}>"
if {${:calendar_ids} eq ""} {
@@ -484,7 +484,7 @@
}
return $calendar_name
}
-
+
CalDAV instproc aggregatedCalendarName {} {
set d [site_node::get_from_object_id -object_id [ad_conn subsite_id]]
set instance_name [lang::util::localize [dict get $d instance_name]]
@@ -647,14 +647,14 @@
# followed by US-ASCII decimal 10).
#
# https://www.ietf.org/mail-archive/web/caldav/current/msg00551.html
-
+
if {${:queryType} eq "resource"} {
return [ns_quotehtml [$res as_ical_calendar]]
} else {
ns_log warning "CalDav can't return c-calendar-data for ${:queryType}"
}
}
-
+
CalDAV instproc property=c-calendar-home-set {res node} {
return ${:url}calendar
}
@@ -742,7 +742,7 @@
-cal_item
node
} {
-
+
Return a <response> ... </response> entry for the
URL specified in the ${:url} and for the query attributes
specified in the tdom node. The attributes user_id,
@@ -751,11 +751,11 @@
@param queryType is an abstraction of the query url and
can be "calendar", "resource", "top", or "principal"
-
+
} {
# @prop: requested properties as tdom nodes
# generate xml for this resource
-
+
#ns_log notice "generateResponse $queryType"
set :queryType $queryType
switch $queryType {
@@ -794,7 +794,7 @@
append result \
\n \
$href \n
-
+
if {$found_props ne ""} {
#
# return 200 for properties that were found
@@ -824,10 +824,10 @@
### HTTP method PROPPATCH
###
CalDAV instproc PROPPATCH {} {
-
+
set content [:getcontent]
set doc [:parseRequest $content]
-
+
# TODO: we assume, we are working on the aggregated calendar
:calendar_ids ""
@@ -836,7 +836,7 @@
}
set reply ""
set innerresponse ""
-
+
set root [$doc documentElement]
set props [$root selectNodes -namespaces ${:namespaces} /d:propertyupdate/d:set/d:prop]
if {[llength $props] == 0} {
@@ -871,12 +871,12 @@
CalDAV ad_instproc REPORT {} {
CalDAV REPORT Method, see RFC 3253, section 3.6
-
+
} {
set content [:getcontent]
set doc [:parseRequest $content]
-
+
if {$doc eq ""} {
return [:request_error "empty reports are not allowed"]
}
@@ -896,10 +896,10 @@
if {[$root selectNodes -namespaces {c urn:ietf:params:xml:ns:caldav} "//c:calendar-multiget"] ne ""} {
set ics_set [:calendar-multiget [$root firstChild]]
-
+
} elseif {[$root selectNodes -namespaces {c urn:ietf:params:xml:ns:caldav} "//c:calendar-query"] ne ""} {
set ics_set [:calendar-query $root]
-
+
} elseif {[$root selectNodes -namespaces {d DAV:} "//d:sync-collection"] ne ""} {
set ics_set [:sync-collection $root responses_xml]
@@ -924,10 +924,10 @@
$doc delete
}
-
-
+
+
CalDAV ad_instproc calendar-multiget {prop} {
-
+
calendar-multiget REPORT is used to retrieve specific calendar
object resources from within a collection, if the Request- URI
is a collection, or to retrieve a specific calendar object
@@ -936,7 +936,7 @@
REPORT (see Section 7.8), except that it takes a list of
DAV:href elements, instead of a CALDAV:filter element, to
determine which calendar object resources to return.
-
+
https://icalendar.org/CalDAV-Access-RFC-4791/7-9-caldav-calendar-multiget-report.html
} {
#ns_log notice "==== calendar-multiget {$prop}"
@@ -960,7 +960,7 @@
lappend cal_uids [ns_urldecode $id]
}
}
-
+
#
# GN TODO: it is probably better to use a UNION instead of the
# construct of "coalesce()" and "OR" below. We need to
@@ -975,14 +975,14 @@
lappend uid_clauses "e.activity_id in ([ns_dbquotelist $act_ids])"
}
ns_log notice uid_clauses=$uid_clauses
-
+
set recurrences {}
set ics_set {}
#
# TODO: why not [calendar get_calitems] ?
#
-
+
foreach row [::xo::dc list_of_lists get_calitems [subst {
select
md5(last_modified::text) as etag,
@@ -1017,7 +1017,7 @@
lassign $row etag cal_uid ical_vars calendar_id item_type \
start_date end_date name description \
cal_item_id recurrence_id creation_date last_modified
-
+
if {$recurrence_id ne "" && $recurrence_id in $recurrences} {
continue
}
@@ -1067,7 +1067,7 @@
#
set time_range [$root selectNodes -namespaces {c urn:ietf:params:xml:ns:caldav} "//c:time-range"]
#ns_log notice "time-range : $time_range"
-
+
if {$time_range ne ""} {
if {[$time_range hasAttribute start]} {
set start [$time_range getAttribute start]
@@ -1079,7 +1079,7 @@
}
}
ns_log notice "calendar-query: start time $start end time $end"
-
+
#
# components
#
@@ -1101,7 +1101,7 @@
sync
} {
upvar $extraXMLvar extraXML
-
+
set props [$root selectNodes -namespaces {d DAV:} "//d:prop"]
#set sync_level_node [$root selectNodes -namespaces {d DAV:} "//d:sync-level"]
set sync_token_node [$root selectNodes -namespaces {d DAV:} "//d:sync-token"]
@@ -1117,13 +1117,13 @@
#
set new_sync_token [:calcSyncToken ${:user_id}]
set extraXML $new_sync_token
-
+
if {$sync_token eq ""} {
#
# return all cal_items
#
set ics_set [calendars get_calitems -user_id ${:user_id}]
-
+
} elseif {$sync_token ne $new_sync_token} {
#
# return cal_items since last sync_token
@@ -1156,7 +1156,7 @@
:response 200 "text/plain" {}
}
-
+
CalDAV ad_instproc calcCtag {user_id} {
Generate a ctag (collection entity tag). The calendar ctag is
@@ -1262,7 +1262,7 @@
UPDATE (SAVE?) a single calendar item denoted by a uid of a
calendar item.
-
+
} {
set content [:getcontent {If-Match ""}]
set ifmatch [ns_set iget [ns_conn headers] If-Match "*"]
@@ -1274,7 +1274,7 @@
if {![string match *.ics ${:uri}]} {
return [:request_error "Trying to PUT on a calendar that does not end with *.ics: ${:uri}"]
}
-
+
try {
set sync_calendar_id [::caldav::get_sync_calendar -user_id ${:user_id}]
} on error {errorMsg} {
@@ -1300,7 +1300,7 @@
# we know, the sync calendar is always writable for the
# current user.
#
- # - GN TODO: not sure, when mutating the UID is necessary, and
+ # - GN TODO: not sure, when mutating the UID is necessary, and
# whether adding a suffix with the user_id is the best solution.
# So we deactivate this code for now....
#
@@ -1338,7 +1338,7 @@
lassign $cal_info calendar_id cal_item_id
:debug "write check needed? [expr {$calendar_id ne $sync_calendar_id}]"
-
+
if {$calendar_id != $sync_calendar_id} {
set can_write_p [permission::permission_p -object_id $cal_item_id -privilege write]
:debug "write check: $can_write_p (calendar_id $calendar_id, sync_calendar_id $sync_calendar_id)"
@@ -1372,7 +1372,7 @@
#
:debug "updating item [$item cget -uid] in calendar $sync_calendar_id"
:item_update -calendar_id $sync_calendar_id -item $item
-
+
#ns_log notice "CalDAV PUT: [$item serialize]"
ns_set put [ns_conn outputheaders] ETag [subst {"[:getETagByUID [$item cget -uid]]"}]
$item destroy
@@ -1445,15 +1445,15 @@
-location $location \
-cal_uid $uid \
-ical_vars $ical_vars]
-
+
$item add_recurrence -cal_item_id $cal_item_id
-
+
} else {
#
# Update an existing item
#
:debug "update/edit cal_item_id $cal_item_id uid <$uid> ical_vars $ical_vars"
-
+
calendar::item::edit \
-cal_item_id $cal_item_id \
-start_date ${dtstart} \
@@ -1469,7 +1469,7 @@
set recurrence_id [::xo::dc get_value -prepare integer get_recurrence {
select recurrence_id from acs_events where event_id = :cal_item_id
}]
-
+
$item edit_recurrence \
-cal_item_id $cal_item_id \
-recurrence_id $recurrence_id