caldav::CalDAV instproc PUT (public)
<instance of caldav::CalDAV> PUT
Defined in /var/www/openacs.org/packages/caldav/tcl/caldav-procs.tcl
UPDATE (SAVE?) a single calendar item denoted by a uid of a calendar item.
- Testcases:
- Thunderbird_add_event, macOS_add_location, macOS_add_event
Source code: set content [:getcontent {If-Match ""}] set ifmatch [ns_set iget [ns_conn headers] If-Match "*"] # # The request URI has to end with UID.ics, but we get the # actual UID from the ical UID field of the parsed content. # 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} { return [:request_error "no private calendar found for ${:user_id}"] } set items [calendars parse $content] :debug "caldav parser returned items <$items>" foreach item $items { set uid [$item cget -uid] :debug [$item serialize] if {$ifmatch eq "*"} { # # Create new entry # :debug "add a new entry" set calendar_id $sync_calendar_id # # We should probably check, whether we can really # write on the calendar in the general case, but here, # we know, the sync calendar is always writable for the # current user. # # - 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.... # if {0} { set user_id ${:user_id} if {[::xo::dc get_value -prepare varchar,integer uid_exists { select 1 from cal_uids u join acs_objects o on (o.object_id = u.on_which_activity) where cal_uid = :uid and o.creation_user != :user_id } 0]} { ad_log warning "uid already exists for another user, suffixing ${uid}-${:user_id}" $item set uid "${uid}-${:user_id}" } } } else { # # Update an existing entry # :debug "update existing entry..." lappend clauses {*}[calendars communityCalendarClause ${:user_id}] {*}[calendars alwaysQueriedClause ${:user_id}] set all_calendar_ids [::xo::dc list read_only_cals [subst { select calendar_id from ([join $clauses " union "]) as cals }]] set cal_infos [calendars get_calendar_and_cal_item_from_uid -calendar_ids $all_calendar_ids $uid] :debug "cal_infos for calendar_ids $all_calendar_ids uid $uid -> <$cal_infos>" if {$cal_infos ne ""} { set cal_info [lindex $cal_infos 0] 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)" if {!$can_write_p} { ns_log warning "CalDAV: user tried to perform a PUT on a read only item item: $cal_item_id user ${:user_id}" if {[string match "*CalDavSynchronizer*" ${:user_agent}]} { # # Outlook synchronizer will continue # hammering if 403 is returned, # therefore try a different status # code. # # GN TODO: please check, what happens # with status code 412 on Outlook, # since 202 probably silently swallows # the update, which never happens. # :debug "CalDav: outlook client encountered" set statusCode 202 } else { set statusCode 412 } return [:response $statusCode text/plain {}] } } } } # # save the item # :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 :response 201 text/plain {} return } # TODO what happens hereXQL Not present: Generic, PostgreSQL, Oracle