2023-02-10 22:10:47 +01:00
# This file is part of Radicale - CalDAV and CardDAV server
2018-08-28 16:19:36 +02:00
# Copyright © 2008 Nicolas Kandel
# Copyright © 2008 Pascal Halter
# Copyright © 2008-2017 Guillaume Ayoub
2019-06-17 04:13:24 +02:00
# Copyright © 2017-2018 Unrud <unrud@outlook.com>
2024-09-29 17:44:05 +02:00
# Copyright © 2024-2024 Peter Bieringer <pb@bieringer.de>
2018-08-28 16:19:36 +02:00
#
# This library is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Radicale. If not, see <http://www.gnu.org/licenses/>.
2023-02-10 22:10:47 +01:00
import xml . etree . ElementTree as ET
2018-08-28 16:19:36 +02:00
from http import client
2023-02-10 22:10:47 +01:00
from typing import Optional
2018-08-28 16:19:36 +02:00
2023-02-10 22:10:47 +01:00
from radicale import httputils , storage , types , xmlutils
from radicale . app . base import Access , ApplicationBase
2025-06-19 02:00:09 -06:00
from radicale . hook import DeleteHookNotificationItem , HookNotificationItemTypes
2024-09-29 17:44:21 +02:00
from radicale . log import logger
2018-08-28 16:19:36 +02:00
2023-02-10 22:10:47 +01:00
def xml_delete ( base_prefix : str , path : str , collection : storage . BaseCollection ,
item_href : Optional [ str ] = None ) - > ET . Element :
2018-08-28 16:19:36 +02:00
""" Read and answer DELETE requests.
Read rfc4918 - 9.6 for info .
"""
2023-02-10 22:10:47 +01:00
collection . delete ( item_href )
2018-08-28 16:19:36 +02:00
2020-01-19 18:53:05 +01:00
multistatus = ET . Element ( xmlutils . make_clark ( " D:multistatus " ) )
response = ET . Element ( xmlutils . make_clark ( " D:response " ) )
2018-08-28 16:19:36 +02:00
multistatus . append ( response )
2023-02-10 22:10:47 +01:00
href_element = ET . Element ( xmlutils . make_clark ( " D:href " ) )
href_element . text = xmlutils . make_href ( base_prefix , path )
response . append ( href_element )
2018-08-28 16:19:36 +02:00
2020-01-19 18:53:05 +01:00
status = ET . Element ( xmlutils . make_clark ( " D:status " ) )
2018-08-28 16:19:36 +02:00
status . text = xmlutils . make_response ( 200 )
response . append ( status )
return multistatus
2023-02-10 22:10:47 +01:00
class ApplicationPartDelete ( ApplicationBase ) :
def do_DELETE ( self , environ : types . WSGIEnviron , base_prefix : str ,
path : str , user : str ) - > types . WSGIResponse :
2018-08-28 16:19:36 +02:00
""" Manage DELETE request. """
2023-02-10 22:10:47 +01:00
access = Access ( self . _rights , user , path )
2020-04-22 19:20:07 +02:00
if not access . check ( " w " ) :
2018-08-28 16:19:36 +02:00
return httputils . NOT_ALLOWED
2020-01-14 06:19:11 +01:00
with self . _storage . acquire_lock ( " w " , user ) :
2023-02-10 22:10:47 +01:00
item = next ( iter ( self . _storage . discover ( path ) ) , None )
2018-08-28 16:19:36 +02:00
if not item :
return httputils . NOT_FOUND
2020-04-22 19:20:07 +02:00
if not access . check ( " w " , item ) :
2018-08-28 16:19:36 +02:00
return httputils . NOT_ALLOWED
if_match = environ . get ( " HTTP_IF_MATCH " , " * " )
if if_match not in ( " * " , item . etag ) :
# ETag precondition not verified, do not delete item
return httputils . PRECONDITION_FAILED
2020-08-17 03:30:18 +02:00
hook_notification_item_list = [ ]
2018-08-28 16:19:36 +02:00
if isinstance ( item , storage . BaseCollection ) :
2024-03-09 06:43:39 +01:00
if self . _permit_delete_collection :
2024-09-29 19:52:53 +02:00
if access . check ( " d " , item ) :
logger . info ( " delete of collection is permitted by config/option [rights] permit_delete_collection but explicit forbidden by permission ' d ' : %s " , path )
return httputils . NOT_ALLOWED
2024-03-09 06:43:39 +01:00
else :
2024-09-29 19:52:53 +02:00
if not access . check ( " D " , item ) :
logger . info ( " delete of collection is prevented by config/option [rights] permit_delete_collection and not explicit allowed by permission ' D ' : %s " , path )
return httputils . NOT_ALLOWED
for i in item . get_all ( ) :
hook_notification_item_list . append (
2025-06-19 02:00:09 -06:00
DeleteHookNotificationItem (
2024-09-29 19:52:53 +02:00
HookNotificationItemTypes . DELETE ,
access . path ,
2025-06-19 02:00:09 -06:00
i . uid ,
old_content = item . serialize ( )
2024-09-29 19:52:53 +02:00
)
)
xml_answer = xml_delete ( base_prefix , path , item )
2018-08-28 16:19:36 +02:00
else :
2023-02-10 22:10:47 +01:00
assert item . collection is not None
assert item . href is not None
2020-08-17 03:30:18 +02:00
hook_notification_item_list . append (
2025-06-19 02:00:09 -06:00
DeleteHookNotificationItem (
2020-08-17 03:30:18 +02:00
HookNotificationItemTypes . DELETE ,
2020-08-17 14:43:52 +02:00
access . path ,
2025-06-19 02:00:09 -06:00
item . uid ,
old_content = item . serialize ( )
2020-08-17 03:30:18 +02:00
)
)
2018-08-28 16:19:36 +02:00
xml_answer = xml_delete (
base_prefix , path , item . collection , item . href )
2024-03-02 19:44:10 +01:00
for notification_item in hook_notification_item_list :
self . _hook . notify ( notification_item )
2020-01-14 06:19:11 +01:00
headers = { " Content-Type " : " text/xml; charset= %s " % self . _encoding }
2023-02-10 23:32:32 +01:00
return client . OK , headers , self . _xml_response ( xml_answer )