EzDevInfo.com

sabre-dav

sabre/dav is a CalDAV, CardDAV and WebDAV framework for PHP sabre/dav

carddav and caldav configuration with sogo using php in web app

I'm newbie in cardav and caldav protocol, I have do lot of search in regarding this like .. baikal sogosync , but really i'm fustrate with this. all the scripts api gives a different error to setup with sogo server.

I have trying to configure sogo server to my local server using php, i have try with sabredav package and follow the installation guide.

https://sabre.io/dav/

Finally i have also try with CardDav-PHP library but i don't know he is giving a response code 200 but i have got response like..

HTTP/1.1 200 OK
Date: Sat, 26 Oct 2013 14:12:12 GMT
content-length: 2595
content-type: text/html; charset=utf-8
set-cookie: 0xHIGHFLYxSOGo=discard; expires=Fri, 25-Oct-2013 14:12:12 GMT; path=/SOGo/
Vary: Accept-Encoding
Connection: close*  
We've detected that your browser version is currently not supported on this site. Our    recommendation is to use Firefox. Click on the link below to download the most current version of this 

I don't know why this happen on simple api call!!

require_once 'carddav.php';
$carddav = new carddav_backend('https://mysogourl/SOGo/mysogousername/Contacts/');
$carddav->set_auth('mysogousername', 'mysogopassword');
$obj = $carddav->get();
echo "<pre>";print_r($obj);exit;

Please help me to bring me front from this!!! really i frustrate.. Any tutorial or example would be great.!!


Source: (StackOverflow)

How to expose CardDAV address books / CalDAV calendars with arbitrary filters?

I want to provide access to address books and calendars that may have search filters (e.g. tags, user, groups) applied.

They should not be auto-discoverable because there may be billions of combinations but must nonetheless be compatible with common clients (e.g. iOS / OS X, Windows Phones), i.e. it should be possible to add the URL with filters to the client.

One issue seems to be that some clients rely on discovery features rather than the URL you give them, e.g. iOS (you try to add one address book by exact URL and it adds all discoverable ones instead).

Another thing is structuring the optional filters.
What about using paths?
What is considered best practice here?


Source: (StackOverflow)

Advertisements

Create a new calendar from CalDav API

I am trying to create a new calendar in my principal's home folder using SabreDav.

I couldn't find how to achieve this - is it even possible ?

UPDATE: I found out about MKCALENDAR method, but the following returns an "abandoned" request error:

<C:mkcalendar xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav"  xmlns:ical="http://apple.com/ns/ical/" >"
    <D:set>
        <D:prop>
            <D:displayname>cal Display Name</D:displayname> 
            <ical:calendar-color>cal Color</ical:calendar-color>
        </D:prop>
    </D:set>
</C:mkcalendar>

Sending it with a HttpWebRequest fails with a canceled request messgage...

Thanks in advance!

UPDATE 2: Some more details:

HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create("http://my.sabredavcalendar.srv/calendarserver.php/calendars/admin/my_new_calendar/");
Request.Method = "MKCALENDAR";
Request..Credentials = new NetworkCredentials("usr", "pwd");
Request.ContentType = "application/xml";
string body = "<C:mkcalendar [.....]  </C:mkcalendar>";
Request.ContentLength = body.Length;
// ---
// The using block throws an error...
using (Stream reqStream = Request.GetRequestStream()) {
    byte[] encodedBody = Encoding.UTF8.GetBytes(body);
    reqStream.Write(encodedBody, 0, encodedBody.Length);
    reqStream.Close();
}
Response = (HttpWebResponse)Request.GetResponse();

The error message I get is

The request was aborted: The request was canceled

On the server side, here is the access log:

192.168.1.200 - - [06/Jul/2015:09:51:48 +0200] "MKCALENDAR /calendarserver.php/calendars/admin/my_new_calendar/ HTTP/1.1" 400 25 "-" "-"

The error log is empty... so it seems I get a "bad request" response which is not caught when preparing the request?!

UPDATE 3: the body contains special characters as "éàê..." which is why the contentlength part was wrong !


Source: (StackOverflow)

Sabredav with no php://input (Kohana)

I have a framework that eats up php://input before sabredav can get to it on a PUT.

Is there a way to call setBody() in Sabre\HTTP\Request so I can pass this from my framework (http://kohanaframework.org) so that getBody() doesn't try to get it from the blank php://input?

I want to try to avoid hacking Sabre\DAV\Server and/or Sabre\HTTP\Request but not sure what the best approach would be.

Framework "wrapped" code is here (implementation of server.php in the Sabredav example)

https://github.com/chrisgo/kohana-sabredav/blob/master/classes/Kohana/Controller/Webdav.php


Original question: SabreDAV + Nginx + PUT (creates 0 byte file)


Source: (StackOverflow)

How to implement SabreDav/CalDav in CakePHP 3.0?

I'm trying to implement CalDav in CakePHP 3.0 and I'm new to both of them. I've created a Customer portal and want that every single user has access to his appointments.

I followed the tutorial http://sabre.io/dav/caldav/, but when I try to run mypage/calendarserver.php/ (which i've located in webroot), it only appears my own created login page (it should display a login from sabredav).

The real problem is: when I try to create for example: "mypage/calendarserver.php/principals" Cake tells me that the principals controller is missing. I don't want to use any controller of Cake when I access this url. Does somebody know how to avoid calling the controller of Cake?

Thanks for your help.


Source: (StackOverflow)

How can I forcibly update the Folders Panel after "drilling in" using ITHit's Ajax File Browser File Panel?

Preface: In the demo online - this issue does not exist, but we have done a lot of things on our back-end and front-end and I fully admit that our "modifications" might be affecting the default behavior.

The problem simply is this:

When we bring up the ITHit Ajax File Browser in our UI, and then navigate to deeper folders using the FILES PANEL, the folder into which we've navigated can no longer be selected or refreshed - programmatically or interactively in the FOLDERS PANEL. This issue ONLY seems to occur when using the FILES PANEL immediately without expanding or interacting with the FOLDERS PANEL. If the user interacts with the FOLDERS PANEL prior to "drilling in" to the FILES PANEL, this issue does not arise. If we navigate (described below) to a "new" root - and navigate using the FOLDERS PANEL - the issue does NOT persist. This navigation does NOT reinitialize or reinstantiate ITHit or any associated controllers in any way (trying to keep requests lean).

Background:

  1. We have an AngularJS SPA, serviced by a custom PHP Api, and a heavily customized version of SabreDAV 2.1.6.
  2. We have constructed our UI to consume WebDAV requests on Same domain AND Cross-domain - and have resolved all related cross-domain issues.
  3. In addition to Cross-domain, we have implemented a dynamic authentication/navigation scheme that causes the UI to fire pre-authorization calls to our DAV server - wherein our customizations authenticate with Oauth, confirm navigation requests, and pass through resulting digest authentication to the DAV server.
  4. Authorization along with Navigation in the UI is directly tied to the results of DAV - wherein a folder structure may change based on user's navigation selections and permissions (effectively changing the structure of the dav server - without re-logging in). These structural changes take effect a the SAME DAV URL dynamically using authorization and navigation HTTP headers.

All of the above took a couple months to resolve - but now seems to be working swimmingly.

What I'm hoping for is some way - or some documentation on the Tree Controller (baked into the ITHit WebDav Client Controller) - just something to give me a way to completely or partially refresh NOT ONLY the data for these folders, but ALSO the TREE VIEW (FOLDERS PANEL).

To be clear - I have figured out how to cause ITHit to request the folder structures, and see the data transfer going and returning - but the view just WON'T UPDATE! The view just won't refresh through either programmatic OR interactive selection - it's like the "drilled in" folder just dies in the Tree view (FOLDERS PANEL).

ANY help would be GREATLY appreciated! THANK YOU!


Source: (StackOverflow)

SabreDav authentication fails

I started creating my own test server using SabreDav in a local environment and all worked just fine.

Now, I am trying to migrate my config to my production web server and I am experiencing all sorts of trouble with the PDO authentication as described here.

I successfully created my database and, without authentication, I am able to navigate principal nodes (meaning my DB connection is working fine).

When adding the server pdo authentication plugin, it keeps asking for the login/password, although I have used the default values, as if login/pwd were wrong.

I tested many scenarios and cannot figure out why it keeps preventing me from login - as I am quite sure login / pwd are correct!

Test scenario: see the nodes in myServer/server.php/principals/admin/ (admin being the default user created in the mysql scripts as found here).

Attempt 0: SUCCESS disable authentication in my server.php

$authBackend = new Sabre\DAV\Auth\Backend\PDO($pdo);
// -- comment out $authPlugin = new Sabre\DAV\Auth\Plugin($authBackend);
// -- comment out $server->addPlugin($authPlugin);

Attempt 1: FAIL using default configuration in my server.php fails and keeps prompting for password

$authBackend = new Sabre\DAV\Auth\Backend\PDO($pdo);
$authPlugin = new Sabre\DAV\Auth\Plugin($authBackend);
$server->addPlugin($authPlugin);

Attempt 2: FAIL forcing the default realm in server.php keeps prompting for password

$authBackend = new Sabre\DAV\Auth\Backend\PDO($pdo);
$authBackend->setRealm('SabreDAV');
$authPlugin = new Sabre\DAV\Auth\Plugin($authBackend);
$server->addPlugin($authPlugin);

Attempt 3: FAIL alternate method to forcing the default realm in server.php keeps prompting for password

$authBackend = new Sabre\DAV\Auth\Backend\PDO($pdo);
$authPlugin = new Sabre\DAV\Auth\Plugin($authBackend, 'SabreDAV');
$server->addPlugin($authPlugin);

Attempt 4: FAIL keep the same realm 'SabreDAV' and generate a different digest (actually, I made sure to use the exact same login/password as in my local server which works locally, but not on the web production server...)

$authBackend = new Sabre\DAV\Auth\Backend\PDO($pdo);
$authPlugin = new Sabre\DAV\Auth\Plugin($authBackend, 'SabreDAV');
$server->addPlugin($authPlugin);

IMPORTANT NOTE: It appears my production mysql DB stores encripted data - if this is the origin of the problem, is there a way to resolve the issue ?


Source: (StackOverflow)

How to deal with large files in SbreDav?

I am using the SabreDAV PHP library to connect to a WebDAV server and download some files but it is taking forever to download a 1MB file and I have to download up to 1GB files from that server. I looked at this link http://code.google.com/p/sabredav/wiki/WorkingWithLargeFiles but it is not helpful because it's telling me that I will get a stream when I do a GET but it is not the case.

Here is my code:

$settings = array(
    'baseUri' => 'file url',
    'userName' => 'user',
    'password' => 'pwd'
);

$client = new \Sabre\DAV\Client($settings);
$response = $client->request('GET'); 

response is an array with a 'body' key that contains the content of the file. What am I doing wrong? I only need the file for read only. How can I can read through the file line by line as quick as possible?

Thanks in advance.


Source: (StackOverflow)

SabreDAV + Nginx Configuration

I'm using RoundCube for my webmail and I'm trying to get the SabreDAV/CalDAV support from MyRoundCube working on my nginx. If I go to dav.warrenheld.com and click cancel when the authentication form comes up I get an XML response. If I log in or log in and then navigate to dav.warrenheld.com/calendars/warren@warrenheld.com/events/ I get a blank response. I'm wondering if the authentication isn't being passed properly to the PHP script. I've been following the directions here http://myroundcube.com/myroundcube-plugins/sabredav-plugin and here http://myroundcube.com/myroundcube-plugins/sabredav-plugin/sabredav-framework. On the framework page there is some configuration information for Apache that includes something about authentication under the cgi tab. I'm using fastcgi for PHP so I wonder if the authenticaiton information isn't being passed to fastcgi? Does anyone know how to convert the Apache config to nginx config?


Source: (StackOverflow)

CalDav sync-token expiry

In a previous question, I asked about syncing data with a DaviCal server. I ended up concluding that there was a bug on DaviCal as when querying a CalDav server with an invalid sync token, the server should return an error but, instead, it returns the whole set of events on the server.

So I started looking for an alternative CalDav server. I use SabreDav. I followed their very handy tutorial here.

On there it says:

Caveats

Note that a server is free to 'forget' any sync-tokens that have been previously issued. In this case it may be needed to do a full-sync again.

In case the supplied sync-token is not recognized by the server, a HTTP error is emitted. SabreDAV emits a 403.

That looks promising : exactly what I need !

So what I do is getting my sync-token which is http://sabre.io/ns/sync/15.

I then submit my REPORT query as follows (maybe that's where I do things wrong?!)

string syncToken = "http://sabre.io/ns/sync/15";
string body = " <d:sync-collection xmlns:d=\"DAV:\"> " +
              "   <d:sync-token>" + syncToken + "</d:sync-token> " +
              "   <d:sync-level>1</d:sync-level> " +
              "   <d:prop> " +
              "     <d:getetag/> " +
              "   </d:prop> " +
              " </d:sync-collection> ";
Request = (HttpWebRequest)HttpWebRequest.Create("http://my.sabredav.com/calendars/example/home/");
Request.Credentials = new NetworkCredential("my_user", "my_pwd");
Request.Method = "REPORT";
Request.ContentType = "application/xml";
// set the body of the request...
Request.ContentLength = body.Length;
using (Stream reqStream = Request.GetRequestStream()) {
    // Write the string to the destination as a text file.
    byte[] encodedBody = Encoding.UTF8.GetBytes(body);
    reqStream.Write(encodedBody, 0, encodedBody.Length);
    reqStream.Close();
}

// Send the method request and get the response from the server.
Response = (HttpWebResponse)Request.GetResponse();

So when I send the request using the valid sync-token http://sabre.io/ns/sync/15 I just got, I get an empty response:

<?xml version="1.0"?>
    <d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:cal="urn:ietf:params:xml:ns:caldav" xmlns:cs="http://calendarserver.or /ns/">
    <d:sync-token>http://sabre.io/ns/sync/15</d:sync-token>
</d:multistatus>

So far so good.

If I use a previous sync-token that I know was valid at some point (http://sabre.io/ns/sync/14 in this case - by chance it is the previous number...) I get changes as expected:

    <?xml version="1.0"?>
    <d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:cal="urn:ietf:params:xml:ns:caldav" xmlns:cs="http://calendarserver.org/ns/">
     <d:response>
      <d:href>/calendarserver.php/calendars/admin/default/23b351ee-7677-46e3-b5c5-5263e8fca351.ics</d:href>
      <d:propstat>
       <d:prop>
        <d:getetag>&quot;8d8d122a66625ca990252fae652cd2e5&quot;</d:getetag>
       </d:prop>
       <d:status>HTTP/1.1 200 OK</d:status>
      </d:propstat>
     </d:response>
     <d:sync-token>http://sabre.io/ns/sync/15</d:sync-token>
    </d:multistatus>

But the issue is, that if I use a RANDOM sync token that I definitely know has never been issued: http://sabre.io/ns/sync/1234312231344324

I get the SAME answer as when I was using the latest (current) token:

    <?xml version="1.0"?>
    <d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:cal="urn:ietf:params:xml:ns:caldav" xmlns:cs="http://calendarserver.org/ns/">
     <d:sync-token>http://sabre.io/ns/sync/15</d:sync-token>
    </d:multistatus>

SabreDav says it's supposed to throw an error 403, but clearly, it's not what I get here... However, if I use INVALID sync-token format, say token1234, I do indeed get an error 403...

So the question is: HOW can I make sure my sync-token is still valid ? So, if the token is valid and nothing is returned, I know my local cache is up to date or, in case the sync-token is INVALID, I need to do full sync!


Source: (StackOverflow)

Sabre Travel REST service

Had a look at their documentation and it seems that in PHP, we cant do all request via the REST service.

For example:

I could fetch flights by REST (Instaflights Search)

But when I want to book something, I need to jump into SOAP (Book Air Segment)

I would prefer to do everything in REST rather than SOAP or half and half.

Is this the right way to create a booking engine? Or I am missing something?


Source: (StackOverflow)

SabreDAV - Why are calendar events stored as BLOB in the PDO backend?

I'm currently experimenting with SabreDAV, a WebDAV/CalDAV/CardDAV server for PHP.

As part of the download, there is a PDO backend that stores calendar events in a database like MySQL.

I noticed that SabreDAV uses a BLOB field to store the iCal data for the event in 1 field, and not in properly normalised fields in the row.

mysql> select * from calendarobjects \G
*************************** 1. row ***************************
        id: 2
  calendardata: BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Apple Inc.//Mac OS X 10.10.5//EN
CALSCALE:GREGORIAN
BEGIN:VTIMEZONE
TZID:Europe/Brussels
BEGIN:DAYLIGHT
TZOFFSETFROM:+0100
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
DTSTART:19810329T020000
TZNAME:CEST
TZOFFSETTO:+0200
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:+0200
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
DTSTART:19961027T030000
TZNAME:CET
TZOFFSETTO:+0100
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
CREATED:20150825T141801Z
UID:B26931A6-6F8A-4CB6-95F2-C5567B7D64BA
DTEND;TZID=Europe/Brussels:20150826T151500
TRANSP:OPAQUE
SUMMARY:My meeting
DTSTART;TZID=Europe/Brussels:20150826T143000
DTSTAMP:20150825T141801Z
SEQUENCE:0
END:VEVENT
END:VCALENDAR

           uri: B26931A6-6F8A-4CB6-95F2-C5567B7D64BA.ics
    calendarid: 1
  lastmodified: 1440512292
          etag: 969a888bab9c906f0d7f10c23a856341
          size: 712
 componenttype: VEVENT
firstoccurence: 1440592200
 lastoccurence: 1440594900
           uid: B26931A6-6F8A-4CB6-95F2-C5567B7D64BA
1 row in set (0.00 sec)

As you can see there is 1 big field "calendar data" that contains everything in iCal format.

From my brief exploration of Milton (the Java counterpart of SabreDAV) it looked like this was also the case there, so it's not only in SabreDAV. But, I may be mistaken.

Is there a particular architectural reason why one would store the iCal data in a BLOB instead of storing the parsed data? I iCal data potentially so complex it cannot fit in a fully normalised way? Or, do you think the developer chose this to save time?

I was hoping to store the data in columns and rows, so I could easily generate a table on a website with calendar events...but now I'd need to parse out all the data and I cannot use SQL... or I'd need to use a full CalDAV client...but that's a overkill.

One particular problem I have already discovered is that a repeating event is 1 record in the DB and not multiple records. Determining the individual events will be very difficult now.


Source: (StackOverflow)

how to integrate sabredav in laravel controller?

I'm trying to create a SabreDAV-Server in a Laravel Route. The following Code shows that I tried:

Illuminate\Routing\Router::$verbs = [
    'GET',
    'HEAD',
    'POST',
    'PUT',
    'PATCH',
    'DELETE', 
    'PROPFIND',
    'PROPPATCH',
    'MKCOL',
    'COPY',
    'MOVE',
    'LOCK',
    'UNLOCK'
];


    Route::match(['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'PATCH', 'PROPFIND', 'PROPPATCH', 'MKCOL', 'COPY', 'MOVE', 'LOCK', 'UNLOCK'], 'carddav{test}', function()
{
        date_default_timezone_set('Europe/Berlin');

        $baseUri = '/carddav';

        $pdo = new PDO('mysql:host=localhost;dbname=dav', 'root', 'root');
        $pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);

        $authBackend = new \Sabre\DAV\Auth\Backend\PDO($pdo);
        $principalBackend = new \Sabre\DAVACL\PrincipalBackend\PDO($pdo);
        $carddavBackend = new \Sabre\CardDAV\Backend\PDO($pdo);

        $nodes = [
                new \Sabre\DAVACL\PrincipalCollection($principalBackend),
                new \Sabre\CardDAV\AddressBookRoot($principalBackend, $carddavBackend)
        ];

        $server = new \Sabre\DAV\Server($nodes);
        $server->setBaseUri($baseUri);

        $server->addPlugin(new \Sabre\DAV\Auth\Plugin($authBackend, 'SabreDAV'));
        $server->addPlugin(new \Sabre\DAV\Browser\Plugin());
        $server->addPlugin(new \Sabre\CardDAV\Plugin());
        $server->addPlugin(new \Sabre\DAVACL\Plugin());
        $server->addPlugin(new \Sabre\DAV\Sync\Plugin());

        $server->exec();
})->where('path', '(.)*';

But if I try to call it in the Browser there is an error:

<?xml version="1.0" encoding="utf-8"?>
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
  <s:sabredav-version>2.0.4</s:sabredav-version>
  <s:exception>Sabre\DAV\Exception\NotAuthenticated</s:exception>
  <s:message>No digest authentication headers were found</s:message>
</d:error>

There was no authentication prompt.

If I try to connect from Evolution there was the message: "Method Not Allowed".

Has someone any idea what the problem is?

Thanks, pepe


Source: (StackOverflow)

Google CALDAV XML request using curl (php)

I'm trying to do a CalDAV XML request to the google caldav server with PHP.

For some reason the google calDAV is very poorly documented.

The purpose is to get a list of all events, including the event-specific data. (eg. Begin, End, Summary, ...). The goal is to do this as efficiently as possible.(all event data in one request).

I figured out that this can be accomplished by a REPORT request.

I'm using code found in this post.

My exact code :

    $xml= '<c:calendar-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav"><d:prop><c:calendar-data /></d:prop></c:calendar-query>';
    $url = "https://apidata.googleusercontent.com/caldav/v2/*email*/events";
    $user = "**********@gmail.com";
    $pw = "*********";

    $data = $this->doRequest($user, $pw, $url, $xml);
    print_r($data);

}

public function doRequest($user, $pw, $url, $xml)
{
    $c=curl_init();
    $url = preg_replace('{^https?://[^/]+}', '', $url);
    curl_setopt($c, CURLOPT_URL, $url);
    curl_setopt($c, CURLOPT_HTTPHEADER, array("Depth: 1", "Content-Type: text/xml; charset='UTF-8'", "Prefer: return-minimal"));
    curl_setopt($c, CURLOPT_HEADER, 0);
    curl_setopt($c, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($c, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_setopt($c, CURLOPT_USERPWD, $user.":".$pw);
    curl_setopt($c, CURLOPT_CUSTOMREQUEST, "REPORT");
    curl_setopt($c, CURLOPT_POSTFIELDS, $xml);
    curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
    $data=curl_exec($c);

    curl_close($c);

    return $data;
}    

The xml request is copy-pasted from the SabreDAV wiki.

What google returns on this code is "Unknown Error". I know the credentials from the google are working, since i successfully tried some request using SabreDAV's built-in requests (eg. propfind). But a report request cannot be generated by SabreDAV.

So i think there must be something in the xml request that google caldav cannot handle properly.

I have been fiddling around with this for several days, but i can't seem to figure out a proper solution.


Source: (StackOverflow)

Why does default Windows WebDAV Client ignore 403 Forbidden response?

I'm using sabre/dav library for my project and I'm having some difficulties with preventing default Windows WebDAV client "deleting" a file that shouldn't be deleted. The implementation in the server part is ok and Forbidden statuses are thrown and acknowledged apparently by other clients (Finder, CyberDuck) that abort the deletion process with a forbidden error to user. The same statuses are thrown back at Windows client, but it seems that it simply "deletes" the files, that are still available on server-side. By refreshing the folder those files are again visible. It seems that Win client simply ignores the forbidden responses and virtually deletes folder, so that it isn't visible anymore.

The bigger problem is that if for a reason you decide to delete a folder, where there are protected and unprotected files/folders underneath, it deletes all of the unprotected ones, because it fails to acknowledge the first (or any) Forbidden response. Other WebDAV clients detect this and stop the deletion process therefore the designated folder and its child folders/files are untouched.

Example of a forbidden response, when trying to delete a folder or file:

HTTP/1.1 403 Forbidden
Server: nginx/1.8.0
Date: Wed, 29 Jul 2015 13:55:11 GMT
Content-Type: application/xml; charset=utf-8
Connection: keep-alive
X-Frame-Options: SAMEORIGIN
X-Powered-By: PHP/5.4.41-1~dotdeb+7.1
X-Sabre-Version: 2.1.3
Vary: Accept-Encoding,User-Agent
Content-Length: 320

<?xml version="1.0" encoding="utf-8"?>
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
  <s:sabredav-version>2.1.3</s:sabredav-version>
  <s:exception>Sabre\DAV\Exception\Forbidden</s:exception>
  <s:message>Permission denied to delete node</s:message>
</d:error>

Tested default Win client on Win8.1 x86.

Any idea how to force Win WebDav client to detect Forbidden responses and terminate deletion process?

Thanks.


Source: (StackOverflow)