Coder Social home page Coder Social logo

cdav's Introduction

CDav module for Dolibarr

What is it ?

This module for Dolibarr 14.0/15.0 adds CardDAV / CalDAV and ICS synchronisation. It uses included Sabre/DAV server library.

You can :

  • Read and edit calendars through CalDAV
  • Read and edit project tasks through CalDAV
  • Read and edit address books through CardDAV
  • Read calendars through ICS Full version or only Free/Busy (hide details)
  • Access Dolibarr documents through WebDAV (if admin)
  • Generate project tasks from documents like proposals and/or orders

Each user can access his/her contacts and thirdparties address books (public and own private contacts), his/her own calendar and other users calendars according to his/her rights.

Dolibarr contact informations fill personnal informations in client software cards (including contact photo).

Society (thirdparty) informations (to which contact is attached) fill professional informations in client software cards.

Two adress books are proposed to sync : Contacts and Thirdparties. If you ant to modify a thirdparty infomation, do it in thirdparties address book.

It is possible to select which contacts to sync with CDAV_CONTACT_TAG configuration value in Home / Setup / Other setup. Enter a contact tag value and then only contacts with this tag will be synced (empty value for all).

Calendar records with "Status / Percentage" set to "Not applicable" are converted to events in CalDAV (VEVENT), others are converted to tasks (VTODO).

Recurring events are not handled (Dolibarr does not handle them).

Automatic tasks generation in projects with services from linked Propositions and/or Orders Module setup offer you to :

  • generate tasks from linked docuement(s) OR not
  • synchronize project tasks as calendar events AND/OR todo tasks
  • set up 3 initial tasks that will appear before services coming from document(s)
  • set up 3 final tasks that will appear after services coming from document(s)
  • define user role in project to select user to attribute on generated tasks from document(s)
  • define user role on new project task creation
  • define start and end time of a working day
  • restrict services to be converted as task by specifying a tag
  • force generation of tasks for each service lines from attached documents with cdav duration if tag is missing

Durations are retrieved from service's card if defined (minutes, hours, days or weeks only), otherwise from extrafield filled in documents All tasks are begining at the starting date of the project, at the begining of the working day Multi-day durations tasks are maintained as a single task, eg from 31/07/2018 at 8am to 02/08/2018 at 7pm

Usage :

  • Manually create a project, link it to a third party, and set up the date ; leave it in draft status
  • Attach document(s) : proposals or orders including at least 1 concerned service.
  • Affect contact(s) with correct role
  • Validate project : all tasks are created ; use your ics client software to retrieve and drag-drop events if necessary

Notes :

  • Description of services are useful to create subtasks if '- ' are detected at the begining of a line ; then, with DAVx⁵ (CalDAV/CardDAV Synchronization and Client) and Tasks (Keep track of your list of goals) you will be able to use checkboxes for these tasks
  • If you chose to synchronize project tasks as calendar events AND todo tasks, modifying a task will autoamticaly modify the corresponding event and reciprocally.
  • Tasks can be modified from client application but not cancelled : Dolibarr keep trace of last affectation
  • After generating tasks, you can modify/complete each of them or create more tasks manually (here too you can fill description zone with '- ' at the begining of lines to create subtasks)

Help improvements

If you find the module is useful and want to finance improvements, consider to pay it on Dolistore

How to install

PHP 8.0+ is required.

Dolibarr native calendar module must be activated before installing CDav module.

Enable CDav module in Interfaces Modules list.

It would add a link in Agenda left menu and in Contacts left menu to access DAV / ICS URLs.

Use these URLs in your CardDAV or CalDAV client software.

How to upgrade

  • Disable CDav module in Interfaces Modules list.
  • Unzip last version or git pull in dolibarr/htdocs/cdav
  • Enable CDav module in Modules list.

DAV URLs

Thunderbird

Thunderbird (with Lightning, TBSync and its Provider for CalDAV/CardDAV addons) needs a precise URL for each address book and calendar :

https://server.example.com/dolibarr/htdocs/cdav/server.php/calendars/<connected-user-login>/<calendar-user-id>-cal-<calendar-user-login>

https://server.example.com/dolibarr/htdocs/cdav/server.php/addressbooks/<connected-user-login>/default/

DAVx⁵

DAVx⁵ can detect automatically address book and all existing calendars (if an event exists) with generic DAV URL :

https://server.example.com/dolibarr/htdocs/cdav/

You can use a tasks application to manage Dolibarr tasks (VTODO) on Android. DAVx⁵ is compatible with OpenTasks.

Be carefull, if you use https, DAVx⁵ needs a valid SSL certificate, excluding auto-signed certificates.

DAVx⁵ is also available on F-Droid.

iOS

iOS uses principals url to grab list of CalDAV or CardDAV resources :

https://server.example.com/dolibarr/htdocs/cdav/server.php/principals/<connected-user-login>

WebDAV

Admin users can also access Dolibarr documents through WebDAV with WebDAV URL :

https://server.example.com/dolibarr/htdocs/cdav/server.php/documents/

Troubleshooting

To test cdav module, you can use DAVx⁵ url https://server.example.com/dolibarr/htdocs/cdav/ in a web browser. Error messages are clearer.

Apache web server

Apache rewrite module is necessary if you use fcgi or php-fpm mode. In this case, .htacess file in cdav module has to be read by Apache or reported in your Apache configuration.

SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

or

<IfModule mod_fastcgi.c>
	<IfModule mod_rewrite.c>
		RewriteEngine on
		RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
	</IfModule>
</IfModule>

or (this is usefull on Plesk when nginx is proxying Apache)

FcgidPassHeader AUTHORIZATION

It is recommanded to disable these Apache modules : dav / dav_fs / dav_lock

nginx web server

To solve authentication loop, add these directives to your nginx "location" rubrique :

fastcgi_param PHP_AUTH_USER $remote_user;
fastcgi_param PHP_AUTH_PW $http_authorization;

or

fastcgi_pass_header Authorization;

nginx reverse proxy

To solve authentication loop, add this directive to your nginx "location" rubrique :

proxy_pass_header Authorization;

cdav's People

Contributors

bagu avatar bjoern86 avatar carlos22 avatar dbeniamine avatar fhenry avatar jpfox avatar webmasterproxy-media avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cdav's Issues

TbSync is able to do autodetect

In your Readme you State, TbSync needs the full url. I actually designed it to autodetect all resources. Are you sure it is not working with your sever?

2.20 NullLogger issue

I tested the 2.10 which is working fine as far as I can see.

2.20 and 2.21 only give a 500 error when accessing DAV

[Tue Dec 06 12:36:30.452678 2022] [proxy_fcgi:error] [pid 2229022:tid 140390678103808] [client 10.1.15.1:0] AH01071: Got error 'PHP message: PHP Fatal error:  Declaration of Psr\\Log\\NullLogger::log($level, Stringable|string $message, array $context = []): void must be compatible with Psr\\Log\\LoggerInterface::log($level, $message, array $context = []) in /home/runcloud/webapps/erp-staging/htdocs/cdav/lib/SabreDAV/vendor/psr/log/src/NullLogger.php on line 26'

gets logged to the server log

Liens non fonctionnels après installation du module

Bonjour,

Sur une instance Dolibarr 5.0.7 / Debian stretch, php7.0.33-0+deb9u1, les liens URL CardDAV, URL CalDAV et URL ICS affichent des pages blanches.

Le module apache dav n'est pas actif, le paquet php-sabre-dav-2.1 est bien installé.

J'ai les erreurs apache suivantes au chargement de la page:
[Fri Dec 21 17:04:17.934811 2018] [:error] [pid 7847] [client 78.209.46.78:54746] PHP Warning: require(../../main.inc.php): failed to open stream: No such file or directory in /usr/local/share/dolibarr/htdocs/cdav/server.php on line 88 [Fri Dec 21 17:04:17.934849 2018] [:error] [pid 7847] [client 78.209.46.78:54746] PHP Fatal error: require(): Failed opening required '../../main.inc.php' (include_path='.:/usr/share/php') in /usr/local/share/dolibarr/htdocs/cdav/server.php on line 88

Problème de synchro si un TIERS est affecté à l'événement CalDAVDolibarr.php

Bonjour,
J'ai acheté le module sur le Dolistore et je rencontre un problème.
Lors de la synchro avec un client (en l'occurence Roundcube et son plugin https://plugins.roundcube.net/packages/texxasrulez/caldav_calendar qui fonctionne à merveille avec d'autre serveur CalDAV) la synchro se passe bien tant qu'aucun Tiers n'est affecté à l'événement dans Dolibarr. Cependant dés lors qu'un Tiers est affecté, alors la synchro ne fonctionne plus et il y a des erreurs dans la concaténantion entre le Tiers et la note pour créer la description de l'événement.
Il y a des ajouts de caractères en UTF8 ("ߒ슉") vraiment étrange avec un traitement que je ne comprends pas dans CalDAVDolibarr.php vers la ligne 870.
De plus notre Dolibarr à plus de 10 ans et la table llx_actioncomm à le champ 'note' en Latin1_swedish_ci alors que le champs description du CalDAV est en UTF8.
Une évolution de ce traitement est-elle prévue?
En vous remerciant.

Salutation in French MME and MR not beeing translated; allow to hide salutation

  1. The salutation MME and MR is not beeing translated on carddav client.
    Should be "Herr" for MR and "Frau" for MME. Within Dolibarr the Translation works fine.

  2. There should be a Checkbox in dolibarr module setting "Transfer salutation" which needs to be checked if salutation shall be synced. If unchecked only sync forename and surename.

  3. On mobile (Android) I see e.g. MR Peter Mueller, on VW car I only see "Mueller, MR" and no forename. (Should be "MR Peter Müller", or in German "Herr Peter Müller" or only "Peter Müller" if Checkbox is unchecked)

LDAP Compatible?

I authenticate with LDAP on dolibarr.

I have installed this module but i can never successfully login. If i go to http://mydomain.com/cdav enter a user and password it fails and asks for it again. I can't authenticate on any client either. Same credential log me into dolibarr no issues.

Running:
dolibarr 3.9.0
cdav 1.03
Apache
Php 5.5.31

(great module btw)

cdav works in web broswer but not on client app : help needed ?

Hi,

Thank you for this very usefull plugin.

I installed th plugin and tested it folowing the troubleshooting section of the read me and can browse through the DAVx⁵ url https://mydomain.com/custom/cdav/

However I can't access to the XX-DAV server from thunderbird or androix DAVx⁵ and I can'f figure out what I may have done wrong ?

From my web server dolibarr is install at this path / ; and not inside the htdocs folder ; and my module are all installed and running from /custom/moduleXX/

Thank's in advance !


thunderbird, TbSync and CalDav & CardDav Provider module are installed

I did try the auto detect and manual install folowing the instruction and the readme, but the connexion fails with the folowing logs :

Could not connect to serveur (NS_ERROR_NET_INTERUPT)
Account: myTbSyncAccountName
URL : https://mydomain.com/custom/cdav/server.php/calendars/MyDolibarrUser/1-cal-MyDolibarrUser (PROPFIND)

Could not connect to serveur (NS_ERROR_NET_INTERUPT)
Account: myTbSyncAccountName
URL : https://mydomain.com/custom/cdav/server.php/addressbooks/MyDolibarrUser/default (PROPFIND)


in DAVx⁵ on adroid I used the url https://mydomain.com/custom/cdav/ and I get :

LOGS:
2019-08-29 12:18:22 15072 [ui.setup.DavResourceFinder] Finding initial carddav service configuration
2019-08-29 12:18:22 15072 [ui.setup.DavResourceFinder] Checking user-given URL: https://mydomain.com/custom/cdav/
2019-08-29 12:18:22 15072 [HttpClient] --> PROPFIND https://mydomain.com/custom/cdav/
2019-08-29 12:18:22 15072 [HttpClient] Content-Type: application/xml; charset=utf-8
2019-08-29 12:18:22 15072 [HttpClient] Content-Length: 290
2019-08-29 12:18:22 15072 [HttpClient] Depth: 0
2019-08-29 12:18:22 15072 [HttpClient]
2019-08-29 12:18:22 15072 [HttpClient] <CARD:addressbook-description /><CARD:addressbook-home-set />
2019-08-29 12:18:22 15072 [HttpClient] --> END PROPFIND (290-byte body)
2019-08-29 12:18:22 15072 [HttpClient] <-- HTTP FAILED: okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
2019-08-29 12:18:22 15072 [ui.setup.DavResourceFinder] PROPFIND/OPTIONS on user-given URL failed
EXCEPTION okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
at okhttp3.internal.http2.Http2Stream.takeHeaders(Http2Stream.java:158)
at okhttp3.internal.http2.Http2Codec.readResponseHeaders(Http2Codec.java:131)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.dav4jvm.BasicDigestAuthHandler.intercept(BasicDigestAuthHandler.kt:291)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.davdroid.HttpClient$UserAgentInterceptor.intercept(HttpClient.kt:247)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:225)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:250)
at okhttp3.RealCall.execute(RealCall.java:93)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:323)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:34)
at at.bitfire.dav4jvm.DavResource.followRedirects(DavResource.kt:378)
at at.bitfire.dav4jvm.DavResource.propfind(DavResource.kt:318)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.checkUserGivenURL(DavResourceFinder.kt:180)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:115)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:73)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:83)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:62)
at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)

2019-08-29 12:18:22 15072 [HttpClient] --> PROPFIND https://mydomain.com/.well-known/carddav
2019-08-29 12:18:22 15072 [HttpClient] Content-Type: application/xml; charset=utf-8
2019-08-29 12:18:22 15072 [HttpClient] Content-Length: 198
2019-08-29 12:18:22 15072 [HttpClient] Depth: 0
2019-08-29 12:18:22 15072 [HttpClient]
2019-08-29 12:18:22 15072 [HttpClient]
2019-08-29 12:18:22 15072 [HttpClient] --> END PROPFIND (198-byte body)
2019-08-29 12:18:22 15072 [HttpClient] <-- HTTP FAILED: okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
2019-08-29 12:18:22 15072 [ui.setup.DavResourceFinder] Well-known URL detection failed
EXCEPTION okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
at okhttp3.internal.http2.Http2Stream.takeHeaders(Http2Stream.java:158)
at okhttp3.internal.http2.Http2Codec.readResponseHeaders(Http2Codec.java:131)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.dav4jvm.BasicDigestAuthHandler.intercept(BasicDigestAuthHandler.kt:291)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.davdroid.HttpClient$UserAgentInterceptor.intercept(HttpClient.kt:247)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:225)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:250)
at okhttp3.RealCall.execute(RealCall.java:93)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:323)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:34)
at at.bitfire.dav4jvm.DavResource.followRedirects(DavResource.kt:378)
at at.bitfire.dav4jvm.DavResource.propfind(DavResource.kt:318)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.getCurrentUserPrincipal(DavResourceFinder.kt:385)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:119)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:73)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:83)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:62)
at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)

2019-08-29 12:18:23 15072 [ui.setup.DavResourceFinder] No principal found at user-given URL, trying to discover
2019-08-29 12:18:23 15072 [ui.setup.DavResourceFinder] Looking up SRV records for _carddavs._tcp.mydomain.com
2019-08-29 12:18:23 15072 [ui.setup.DavResourceFinder] Didn't find carddav service, trying at https://mydomain.com:443
2019-08-29 12:18:23 15072 [ui.setup.DavResourceFinder] Trying to determine principal from initial context path=https://mydomain.com/.well-known/carddav
2019-08-29 12:18:23 15072 [HttpClient] --> PROPFIND https://mydomain.com/.well-known/carddav
2019-08-29 12:18:23 15072 [HttpClient] Content-Type: application/xml; charset=utf-8
2019-08-29 12:18:23 15072 [HttpClient] Content-Length: 198
2019-08-29 12:18:23 15072 [HttpClient] Depth: 0
2019-08-29 12:18:23 15072 [HttpClient]
2019-08-29 12:18:23 15072 [HttpClient]
2019-08-29 12:18:23 15072 [HttpClient] --> END PROPFIND (198-byte body)
2019-08-29 12:18:23 15072 [HttpClient] <-- HTTP FAILED: okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
2019-08-29 12:18:23 15072 [ui.setup.DavResourceFinder] No resource found
EXCEPTION okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
at okhttp3.internal.http2.Http2Stream.takeHeaders(Http2Stream.java:158)
at okhttp3.internal.http2.Http2Codec.readResponseHeaders(Http2Codec.java:131)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.dav4jvm.BasicDigestAuthHandler.intercept(BasicDigestAuthHandler.kt:291)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.davdroid.HttpClient$UserAgentInterceptor.intercept(HttpClient.kt:247)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:225)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:250)
at okhttp3.RealCall.execute(RealCall.java:93)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:323)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:34)
at at.bitfire.dav4jvm.DavResource.followRedirects(DavResource.kt:378)
at at.bitfire.dav4jvm.DavResource.propfind(DavResource.kt:318)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.getCurrentUserPrincipal(DavResourceFinder.kt:385)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.discoverPrincipalUrl(DavResourceFinder.kt:365)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:138)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:73)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:83)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:62)
at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)

2019-08-29 12:18:23 15072 [ui.setup.DavResourceFinder] Trying to determine principal from initial context path=https://mydomain.com/
2019-08-29 12:18:23 15072 [HttpClient] --> PROPFIND https://mydomain.com/
2019-08-29 12:18:23 15072 [HttpClient] Content-Type: application/xml; charset=utf-8
2019-08-29 12:18:23 15072 [HttpClient] Content-Length: 198
2019-08-29 12:18:23 15072 [HttpClient] Depth: 0
2019-08-29 12:18:23 15072 [HttpClient]
2019-08-29 12:18:23 15072 [HttpClient]
2019-08-29 12:18:23 15072 [HttpClient] --> END PROPFIND (198-byte body)
2019-08-29 12:18:23 15072 [HttpClient] <-- HTTP FAILED: okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
2019-08-29 12:18:23 15072 [ui.setup.DavResourceFinder] No resource found
EXCEPTION okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
at okhttp3.internal.http2.Http2Stream.takeHeaders(Http2Stream.java:158)
at okhttp3.internal.http2.Http2Codec.readResponseHeaders(Http2Codec.java:131)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.dav4jvm.BasicDigestAuthHandler.intercept(BasicDigestAuthHandler.kt:291)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.davdroid.HttpClient$UserAgentInterceptor.intercept(HttpClient.kt:247)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:225)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:250)
at okhttp3.RealCall.execute(RealCall.java:93)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:323)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:34)
at at.bitfire.dav4jvm.DavResource.followRedirects(DavResource.kt:378)
at at.bitfire.dav4jvm.DavResource.propfind(DavResource.kt:318)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.getCurrentUserPrincipal(DavResourceFinder.kt:385)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.discoverPrincipalUrl(DavResourceFinder.kt:365)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:138)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:73)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:83)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:62)
at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)

2019-08-29 12:18:23 15072 [ui.setup.DavResourceFinder] Finding initial caldav service configuration
2019-08-29 12:18:23 15072 [ui.setup.DavResourceFinder] Checking user-given URL: https://mydomain.com/custom/cdav/
2019-08-29 12:18:23 15072 [HttpClient] --> PROPFIND https://mydomain.com/custom/cdav/
2019-08-29 12:18:23 15072 [HttpClient] Content-Type: application/xml; charset=utf-8
2019-08-29 12:18:23 15072 [HttpClient] Content-Length: 435
2019-08-29 12:18:23 15072 [HttpClient] Depth: 0
2019-08-29 12:18:23 15072 [HttpClient]
2019-08-29 12:18:23 15072 [HttpClient] <n0:calendar-color xmlns:n0="http://apple.com/ns/ical/" /><CAL:calendar-description /><CAL:calendar-timezone /><CAL:supported-calendar-component-set /><CAL:calendar-home-set />
2019-08-29 12:18:23 15072 [HttpClient] --> END PROPFIND (435-byte body)
2019-08-29 12:18:24 15072 [HttpClient] <-- HTTP FAILED: okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
2019-08-29 12:18:24 15072 [ui.setup.DavResourceFinder] PROPFIND/OPTIONS on user-given URL failed
EXCEPTION okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
at okhttp3.internal.http2.Http2Stream.takeHeaders(Http2Stream.java:158)
at okhttp3.internal.http2.Http2Codec.readResponseHeaders(Http2Codec.java:131)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.dav4jvm.BasicDigestAuthHandler.intercept(BasicDigestAuthHandler.kt:291)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.davdroid.HttpClient$UserAgentInterceptor.intercept(HttpClient.kt:247)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:225)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:250)
at okhttp3.RealCall.execute(RealCall.java:93)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:323)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:34)
at at.bitfire.dav4jvm.DavResource.followRedirects(DavResource.kt:378)
at at.bitfire.dav4jvm.DavResource.propfind(DavResource.kt:318)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.checkUserGivenURL(DavResourceFinder.kt:189)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:115)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:80)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:83)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:62)
at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)

2019-08-29 12:18:24 15072 [HttpClient] --> PROPFIND https://mydomain.com/.well-known/caldav
2019-08-29 12:18:24 15072 [HttpClient] Content-Type: application/xml; charset=utf-8
2019-08-29 12:18:24 15072 [HttpClient] Content-Length: 198
2019-08-29 12:18:24 15072 [HttpClient] Depth: 0
2019-08-29 12:18:24 15072 [HttpClient]
2019-08-29 12:18:24 15072 [HttpClient]
2019-08-29 12:18:24 15072 [HttpClient] --> END PROPFIND (198-byte body)
2019-08-29 12:18:24 15072 [HttpClient] <-- HTTP FAILED: okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
2019-08-29 12:18:24 15072 [ui.setup.DavResourceFinder] Well-known URL detection failed
EXCEPTION okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
at okhttp3.internal.http2.Http2Stream.takeHeaders(Http2Stream.java:158)
at okhttp3.internal.http2.Http2Codec.readResponseHeaders(Http2Codec.java:131)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.dav4jvm.BasicDigestAuthHandler.intercept(BasicDigestAuthHandler.kt:291)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.davdroid.HttpClient$UserAgentInterceptor.intercept(HttpClient.kt:247)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:225)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:250)
at okhttp3.RealCall.execute(RealCall.java:93)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:323)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:34)
at at.bitfire.dav4jvm.DavResource.followRedirects(DavResource.kt:378)
at at.bitfire.dav4jvm.DavResource.propfind(DavResource.kt:318)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.getCurrentUserPrincipal(DavResourceFinder.kt:385)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:119)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:80)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:83)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:62)
at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)

2019-08-29 12:18:24 15072 [ui.setup.DavResourceFinder] No principal found at user-given URL, trying to discover
2019-08-29 12:18:24 15072 [ui.setup.DavResourceFinder] Looking up SRV records for _caldavs._tcp.mydomain.com
2019-08-29 12:18:24 15072 [ui.setup.DavResourceFinder] Didn't find caldav service, trying at https://mydomain.com:443
2019-08-29 12:18:24 15072 [ui.setup.DavResourceFinder] Trying to determine principal from initial context path=https://mydomain.com/.well-known/caldav
2019-08-29 12:18:24 15072 [HttpClient] --> PROPFIND https://mydomain.com/.well-known/caldav
2019-08-29 12:18:24 15072 [HttpClient] Content-Type: application/xml; charset=utf-8
2019-08-29 12:18:24 15072 [HttpClient] Content-Length: 198
2019-08-29 12:18:24 15072 [HttpClient] Depth: 0
2019-08-29 12:18:24 15072 [HttpClient]
2019-08-29 12:18:24 15072 [HttpClient]
2019-08-29 12:18:24 15072 [HttpClient] --> END PROPFIND (198-byte body)
2019-08-29 12:18:24 15072 [HttpClient] <-- HTTP FAILED: okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
2019-08-29 12:18:24 15072 [ui.setup.DavResourceFinder] No resource found
EXCEPTION okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
at okhttp3.internal.http2.Http2Stream.takeHeaders(Http2Stream.java:158)
at okhttp3.internal.http2.Http2Codec.readResponseHeaders(Http2Codec.java:131)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.dav4jvm.BasicDigestAuthHandler.intercept(BasicDigestAuthHandler.kt:291)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.davdroid.HttpClient$UserAgentInterceptor.intercept(HttpClient.kt:247)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:225)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:250)
at okhttp3.RealCall.execute(RealCall.java:93)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:323)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:34)
at at.bitfire.dav4jvm.DavResource.followRedirects(DavResource.kt:378)
at at.bitfire.dav4jvm.DavResource.propfind(DavResource.kt:318)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.getCurrentUserPrincipal(DavResourceFinder.kt:385)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.discoverPrincipalUrl(DavResourceFinder.kt:365)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:138)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:80)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:83)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:62)
at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)

2019-08-29 12:18:24 15072 [ui.setup.DavResourceFinder] Trying to determine principal from initial context path=https://mydomain.com/
2019-08-29 12:18:24 15072 [HttpClient] --> PROPFIND https://mydomain.com/
2019-08-29 12:18:24 15072 [HttpClient] Content-Type: application/xml; charset=utf-8
2019-08-29 12:18:24 15072 [HttpClient] Content-Length: 198
2019-08-29 12:18:24 15072 [HttpClient] Depth: 0
2019-08-29 12:18:24 15072 [HttpClient]
2019-08-29 12:18:24 15072 [HttpClient]
2019-08-29 12:18:24 15072 [HttpClient] --> END PROPFIND (198-byte body)
2019-08-29 12:18:25 15072 [HttpClient] <-- HTTP FAILED: okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
2019-08-29 12:18:25 15072 [ui.setup.DavResourceFinder] No resource found
EXCEPTION okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR
at okhttp3.internal.http2.Http2Stream.takeHeaders(Http2Stream.java:158)
at okhttp3.internal.http2.Http2Codec.readResponseHeaders(Http2Codec.java:131)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.dav4jvm.BasicDigestAuthHandler.intercept(BasicDigestAuthHandler.kt:291)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at at.bitfire.davdroid.HttpClient$UserAgentInterceptor.intercept(HttpClient.kt:247)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:225)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:250)
at okhttp3.RealCall.execute(RealCall.java:93)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:323)
at at.bitfire.dav4jvm.DavResource$propfind$1.invoke(DavResource.kt:34)
at at.bitfire.dav4jvm.DavResource.followRedirects(DavResource.kt:378)
at at.bitfire.dav4jvm.DavResource.propfind(DavResource.kt:318)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.getCurrentUserPrincipal(DavResourceFinder.kt:385)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.discoverPrincipalUrl(DavResourceFinder.kt:365)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:138)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:80)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:83)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:62)
at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)

SOFTWARE INFORMATION

  • at.bitfire.davdroid 2.5.4.1-ose (299) from com.google.android.packageinstaller
  • com.android.providers.contacts 7.0 (24)
  • com.android.providers.calendar 7.0 (24)
  • com.android.contacts 9.6.0.8 (100)
  • com.android.calendar 9.2.1.4 (9020104)

CONNECTIVITY (at the moment)
Active connection: mobile, CONNECTED

CONFIGURATION
Power saving disabled: yes
android.permission.READ_CONTACTS: denied
android.permission.WRITE_CONTACTS: denied
android.permission.READ_CALENDAR: denied
android.permission.WRITE_CALENDAR: denied
org.dmfs.permission.READ_TASKS: denied
org.dmfs.permission.WRITE_TASKS: denied
android.permission.ACCESS_COARSE_LOCATION: denied
System-wide synchronization: manually

SQLITE DUMP
android_metadata
| locale |
| fr_FR |

room_master_table
| id | identity_hash |
| 42 | a7554d1ebc5ecfe0c7aefe271485d63c |

service
| id | accountName | type | principal |

sqlite_sequence
| name | seq |

homeset
| id | serviceId | url | privBind | displayName |

collection
| id | serviceId | type | url | privWriteContent | privUnbind | forceReadOnly | displayName | description | color | timezone | supportsVEVENT | supportsVTODO | supportsVJOURNAL | source | sync |

SYSTEM INFORMATION
Android version: 7.0 (AL1512-mido-build-XXXXXXXXXX)
Device: Xiaomi Redmi Note 4 (mido)

Not every contacts in thunderbird, but everything work fine in DavX and TBSync

Bonjour,

Tout d'abord merci pour cet excellent module.
Ensuite, j'ai mis à jour Thunderbird vers la version 91 afin d'envisager de me passer de TBSync.
Mais ce faisant, le carnet d'adresse obtenu ne contient que 522 contacts en lieu et place des 1905 attendus.
Cela vient-il de Thunderbird ou bien d'un fonctionnement du module ?

Je me pose la question, car j'ai eu un soucis similaire avec un carnet d'adresse Gmail.
Ce dernier contenait des contacts datant d'avant la migration vers l'api v2 de google.
Ces contacts n'appartenait pas au groupe default.
De fait, ils n'étaient pas synchronisés.
Une fois remis dans ce groupe, tout se passe bien.

Je parle de ceci car je me pose la question de comment Thunderbird récupère les contacts en passant par votre module.

La version de dolibarr en 15.0.2
La version de PHP est 7.4.29
La version d'apache est 2.4.53
La version de Thunderbird est 91.9.1
La version de Cdav est 2.10

Merci

adding Sabre/DAV plug-in ?

Hi

I wonder if we can and how could we add Sabre/DAV module ?
for instance I would like to export my contact in vcard as explained here

Thank's

Error while activating module CDav

Hi,

I'm actually having issue activating your module on my dolibarr installation. Each time I try to activate CDav, module stays Off. After some investigations, it appears that an insert in database is the cause.

Environment :

  • dolibarr 6.0.5
  • Ubuntu 16.04
  • PHP 7.0.30
  • MySQL 5.7.22
  • Main "non-initial" modules : multi-company

dolibarr.log :

2018-06-04 11:38:56 ERR     212.234.107.51->192.168.0.241  DoliDBMysqli::query SQL Error query: INSERT INTO llx_const (name,type,value,note,visible,entity) VALUES ('CDAV_URI_KEY','CDav uri key','751726bf','Change it to force client to resync','1',2)
2018-06-04 11:38:56 ERR     212.234.107.51->192.168.0.241  DoliDBMysqli::query SQL Error message: DB_ERROR_1406 Data too long for column 'type' at row 1

Table llx_const :

mysql> describe llx_const;
+---------+--------------+------+-----+-------------------+-----------------------------+
| Field   | Type         | Null | Key | Default           | Extra                       |
+---------+--------------+------+-----+-------------------+-----------------------------+
| rowid   | int(11)      | NO   | PRI | NULL              | auto_increment              |
| name    | varchar(255) | NO   | MUL | NULL              |                             |
| entity  | int(11)      | NO   |     | 1                 |                             |
| value   | text         | NO   |     | NULL              |                             |
| type    | varchar(6)   | YES  |     | NULL              |                             |
| visible | tinyint(4)   | NO   |     | 1                 |                             |
| note    | text         | YES  |     | NULL              |                             |
| tms     | timestamp    | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+---------+--------------+------+-----+-------------------+-----------------------------+

As I'm on a testing instance, I handle it by changing my type on table llx_const :
alter table llx_const MODIFY type varchar(12);

But It would by better if it is handled directly into source code (shorten string for type).

Mathieu

unable to use cdav 1.06 with dolibarr 9 using php 5.4.16 on apache

i cannot upgrade the php version of our serrver as they are already many services running, so I was obliged to install version 1.06.
then i get this error : Fatal error: Can't use function return value in write context in /var/www/html/IEFC/dolibarr/htdocs/cdav/class/CardDAVDolibarr.php on line 384
Any chance to fix it?
Thanking you in advance

Multi company compatibility

I tried to use cdav with the well known multicompany module and I encountered two issues :

  1. It is not possible to transmit the entity in cdav's url parameters

    Their is actually two parts on this problem :

    1. While cdav does correctly a GETPOST() on entity, multicompany
      version 8.0.0 does not correcty use it during auth. I am sending a patch to
      multicompany's maintainer
    2. If we use an url like server.php?entity=2 with cdav, Sabre\Dav
      does not ignore the ?.. part and gives the following error :
      LogicException /custom/cdav/server.php?entity=2 out of base uri
  2. Another issue is that dav resources are stored by username yet with
    multicompany, username or not necessarily unique, is it possible to store
    resources by id, like for ICS urls ?

Ics urls seems to work well

Suport Dolibar 7.0.0

Not compatible with dolibarr 7.0.0?
I get the following error:

No 'Authorization: Basic' header found. Either the client didn't send one, or the server is mis-configured

Any ideas?

PHP7 - Call to undefined function mcrypt_ecb() (function REMOVED from PHP)

Hi,

Still experimenting your module, I'm facing another issue with URL ICS this time, page content stops after first employee without giving the URL:

==> /var/log/apache2/labo.mydoli-error.log <==
[Wed Jun 06 11:14:26.894262 2018] [:error] [pid 10900] [client 192.168.0.241:55159] PHP Fatal error:  Uncaught Error: Call to undefined function mcrypt_ecb() in /usr/share/dolibarr/htdocs/cdav/cdavurls.php:128\nStack trace:\n#0 {main}\n  thrown in /usr/share/dolibarr/htdocs/cdav/cdavurls.php on line 128, referer: http://labo.mydoli/comm/action/listactions.php?

But page loading is 200 HTTP status code

192.168.0.241 - - [06/Jun/2018:11:14:26 +0200] "GET /cdav/cdavurls.php?type=ICS&mainmenu=agenda&idmenu=26438 HTTP/1.1" 200 5832

I saw on PHP doc that whole extension Mcrypt is deprecated since PHP7.1 and will be removed in PHP7.2, but function incriminated is deprecated since PHP5.5.0 and removed since PHP7.0.0 (http://be2.php.net/manual/en/function.mcrypt-ecb.php)

My configuration :

Settings Value
PHP Version 7.0.30-0ubuntu0.16.04.1
Registered Stream Filters zlib., string.rot13, string.toupper, string.tolower, string.strip_tags, convert., consumed, dechunk, convert.iconv., mcrypt., mdecrypt.*

Mathieu,
Dolibarr 6.0.5
PHP7.0.3
CDav1.02

No info shown using link "URL ICS" in Agenda

Hi folks,

All I get is the following output:

URL ICS
This URL can be used by a synchronisation client tool (read only) :
SuperAdmin :

I tested this on Dolibarr v14.0.5.

Screenshot_2022-11-15_08-45-59

Kind regards,
Roman

Only getting 404.

I am using Dolibarr 8.0.3 and installed and activated cdav.

I can successfully access https://server.example.com/dolibarr/htdocs/cdav/server.php after entering my credentials and get a page with links to adddressbooks, calendars, principals, public, and, for administrators, documents.

However, all links just give me the standard dolibarr 404 page. What am I doing wrong here? Do I need to setup a rewrite rule to enable resoling links like https://server.example.com/dolibarr/htdocs/cdav/server.php/addressbook?
Since I can successfully authenticate, I guess that the rewrite issues described in the readme do not apply here.

My environment:

  • Debian Stretch
  • Nginx as reverse proxy for HTTPS
  • Nginx as serving proxy using php-fpm for php
  • Dolibarr 8.0.3 installed from the Debian package.

Thanks for your support!

BUG - Calendar alarm disappears

Calendar alarm disappears

In reference to ticket #57

  • I have created a calendar entry
  • synchronized with cdav and DAVx5 on android 9
  • with acalender changed the calendar entry in that it should alert me 1 hour before
  • PROBLEM the automatic sync and match with cdav/dolibarr causes my ALARM to be disabled again or better said not present.

FEATURE REQUEST - Calender Smartphone Reminder Alarm

The reminder in the calendar entry is not synchronized.
With other programs this is normal, if you select pop-up, this is also transferred to smartphones as a calendar reminder alarm. I live only with smartphone calendar alarm ;-)

My functional wish would be to include this in the sync.

Don't work on my server

hi, thanks for your job, bur that don't work on my server

I try with dolibar 3.7 and 3.8 on debian server
the links "url Cardav" appear but display a blank page
the apache log display an error 500 and 410

Dolibarr 9.0Upgrade

Hi!
Do you have any plans to publish upgrades for the latest version of Dolibarr in the near future..? Even better, are you interested in merging Your module with the Dolibarr core? Please advise!

Disparition des events lors de l'ajout sous Calendrier / Rappels (Apple)

Bonjour,

Lorsque j'ajoute un évènement ou un rappel sour Calendrier / Rappels, ils s'ajoutent sur Dolibarr mais disparaissent des applications quelques secondes après... Et je ne vois aucun évènement de Dolibarr. J'ai l'impression que la communication ne se fait que dans un sens.

Avez-vous une idée du problème ?

Merci

URL CALDDAV et CARDDAV ne fonctionne ni avec Thunderbird ni avec DAVx5

Bonjour,

Depuis Thunderbird, l'accès au serveur DOLIBARR est impossible.
Si je mets le lien URL directement dans un navigateur cela fonctionne.
DOLIBARR est installé sur un serveur O2switch avec une redirection en https.

Les URL ne fonctionnent pas non plus sur DAVx5 sur un mobile Android.

Dans les deux cas, ils semblent qu'il soit impossible d'accéder au serveur.

J'ai installé le module CDAV directement sous le répertoire dolibarr.mondomaine.com.

Bonne réception

Display of "Title" of a contact

Hi folks,

All contact are nicely synchronized with my Android phone except for "Title".

On my phone the title shows the rather ugly code set in dictionary, e.g. MME, MLE or MTRE instead of e.g. Mr.

Also, if I create a new contact on my phone and I set the title to "M.", then it is ignored by Dolibarr and the entry is not picked up.

How can I fix this?

Kind regards,
Roman

URL CalDAV - Use of undefined constant CDAV_URI_KEY - assumed 'CDAV_URI_KEY'

Hi,

When I open my CalDAV URL (given by URL CalDAV page in agenda), it returns me an error in XML:

<d:error>
  <s:sabredav-version>3.0.0</s:sabredav-version>
  <s:exception>ErrorException</s:exception>
  <s:message>Use of undefined constant CDAV_URI_KEY - assumed 'CDAV_URI_KEY'</s:message>
</d:error>

I saw that CDAV_URI_KEY is define with conf->global->CDAV_URI_KEY by I can't find such configuration neither in module neither in dolibarr configuration. Where does I need to be configured?

So I can't sync my dolibarr agenda with my calendar client due to this error.

Mathieu
Dolibarr 6.0.5
PHP7.0.3
CDav1.02

the plugin put all on agenda as task

Hello,

testing the latest code with ldap support, it now connect correctly to dolibarr and sync the calendar entries but it put everything as task.

i think it should put the calendar of dolibarr (events) as clendar entries and put projects task as task.

i join screnshoot to show the actual behaviour

caldav-taches-agendas

Definition of constant CDAV_URI_KEY missing in cdavurls.php

Hi,

i think the definition of CDAV_URI_KEY missing in cdavurls.php. Following line needs to be added after require $dir.'main.inc.php';

define ('CDAV_URI_KEY', $conf->global->CDAV_URI_KEY);

Do you accept PR in this repository? If yes, I can create one

carddav client settings (mac contacts)

to set up a carddav client, it takes:
type of account : (advanced?)
username: (superadmin user name, for instance)
password: (password, ok)
server: http(s?)://mywebsite.net/../cdav/server.php/addressbooks/SameUsernameAsAbove/default/
or
https://mywebsite.net:8843/../cdav/server.php
path: /addressbooks/tresorier/default/ ?
Port: 443? 8843? SSL, no SSL?
or ..
or ..
which makes more than a hundred possibilities to test :/ ..

so far: "impossible de vérifier le nom et le mot de passe du compte"
the sabre interface is accessible in Safari
but impossible to "log in" and have the user validated in Contacts ..

could someone share precisely one's functioning settings please XXL?

bitte schone
punk, france

(contacts mac os x catalina)

Support for Dolibarr 6.0

Hi Jean-Pierre!

Thank you for developing this interesting module for Dolibarr. Do you have any plans to adapt it for the recently published Dolibarr 6.0?

Best regards
xelan

Issue in Thunderbird

There are 2 issues in thunderbird on Sync adress book :

  • First, when we sync, there are empty cards
  • Second sometimes, somehow... the adress book is summing card on sync, and at a moment, there are thousand of card in adress book instead of hundred for example

Not all events show up in Calendar

Hi everybody,
thanks for the work on the nice tool. Unfortunately, only specific types of events in Dolibarr calendar are shown in external calendars synced via CDav. For example, I see all the events "Reception of Email - ..." auto-created by Scheduled Jobs and Email Collector, but not anything else, no self-created events for instance.

This way, the product is basically unusable.

Kind regards
ryker

What type of events are synchronized?

I've been able to synchronize events with thunderbird and DAVx5, but only the events created/updated since the 1st sync appear in T-bird (and other).

Is it that only manually created/modified events are synced?

What type of events are supposed to be synced?

Https?

Is it possible to use this caldav without https?
i always get a 401 Error with davdroid.
Thank you for you help...

Sabre DAV Exception NotAuthenticated

When trying to enter from the web url / cdav does not authorize the password. And in DAVx5 Unauthorized 401 Error.

Environment

  • OS: Linux
  • Web server: Apache
  • PHP: cgi-fcgi 5.6.40
  • Database: MySQL or MariaDB 5.5.5-10.3.23-MariaDB
    • Sabre DAV Version: 3.2.2
  • URL(s): /cdav

Membership Module Contact Information

Is there any way to include the contact details of the people in the membership module into the carddav sync? These are important contact details as well, for example for email communication outside of Dolibarr. But I don´t want to need to enter or modify multiple times (in the membership module and the contact module).

Error Code 405 --> SSO

i have dolibarr installed on Yunohost.
as per the readme I put cdav in the path dolibarr/htdocs/custom/
activated cdav and see it in dolibarr
BUT i tried with DAVx5 and can't connect.
I have tried these paths

https://mydomain.net/dolibarr/custom/cdav
https://mydomain.net/dolibarr/custom/cdav/server.php
https://mydomain.net/dolibarr/custom/cdav/server.php/principals/user/
https://mydomain.net/dolibarr/custom/cdav/server.php/addressbooks/user/default/

now i have seen that it is because of the login option SSO which i have no influence on at Dolibarr.

wish would be that also works.

DAVx5 Fehlercode

2022-04-07 07:41:51 141981 [HttpClient] <-- END HTTP (138-byte body)
2022-04-07 07:41:51 141981 [at.bitfire.dav4jvm.DavResource] Redirected, new location = https://mydomain.net/yunohost/sso/CODE
2022-04-07 07:41:51 141981 [HttpClient] --> PROPFIND https://mydomain.net/yunohost/sso/CODE h2
2022-04-07 07:41:51 141981 [HttpClient] Depth: 0
2022-04-07 07:41:51 141981 [HttpClient] User-Agent: DAVx5/4.2.0.3-gplay (2022/03/23; dav4jvm; okhttp/4.9.3) Android/12
2022-04-07 07:41:51 141981 [HttpClient] Accept-Language: de-AT, de;q=0.7, *;q=0.5
2022-04-07 07:41:51 141981 [HttpClient] Content-Type: application/xml; charset=utf-8
2022-04-07 07:41:51 141981 [HttpClient] Content-Length: 198
2022-04-07 07:41:51 141981 [HttpClient] Host: mydomain.net
2022-04-07 07:41:51 141981 [HttpClient] Connection: Keep-Alive
2022-04-07 07:41:51 141981 [HttpClient] Accept-Encoding: gzip
2022-04-07 07:41:51 141981 [HttpClient] 
2022-04-07 07:41:51 141981 [HttpClient] <?xml version='1.0' encoding='UTF-8' ?><propfind xmlns="DAV:" xmlns:CAL="urn:ietf:params:xml:ns:caldav" xmlns:CARD="urn:ietf:params:xml:ns:carddav"><prop><current-user-principal /></prop></propfind>
2022-04-07 07:41:51 141981 [HttpClient] --> END PROPFIND (198-byte body)
2022-04-07 07:41:51 141981 [HttpClient] <-- 405 https://mydomain.net/yunohost/sso/CODE (61ms)
2022-04-07 07:41:51 141981 [HttpClient] server: nginx
2022-04-07 07:41:51 141981 [HttpClient] date: Thu, 07 Apr 2022 05:41:43 GMT
2022-04-07 07:41:51 141981 [HttpClient] content-type: text/html
2022-04-07 07:41:51 141981 [HttpClient] content-length: 150
2022-04-07 07:41:51 141981 [HttpClient] x-sso-wat: You've just been SSOed
2022-04-07 07:41:51 141981 [HttpClient] content-security-policy: upgrade-insecure-requests
2022-04-07 07:41:51 141981 [HttpClient] content-security-policy-report-only: default-src https: data: blob: ; object-src https: data: 'unsafe-inline'; style-src https: data: 'unsafe-inline' ; script-src https: data: 'unsafe-inline' 'unsafe-eval'
2022-04-07 07:41:51 141981 [HttpClient] x-content-type-options: nosniff
2022-04-07 07:41:51 141981 [HttpClient] x-xss-protection: 1; mode=block
2022-04-07 07:41:51 141981 [HttpClient] x-download-options: noopen
2022-04-07 07:41:51 141981 [HttpClient] x-permitted-cross-domain-policies: none
2022-04-07 07:41:51 141981 [HttpClient] x-frame-options: SAMEORIGIN
2022-04-07 07:41:51 141981 [HttpClient] permissions-policy: interest-cohort=()
2022-04-07 07:41:51 141981 [HttpClient] strict-transport-security: max-age=63072000; includeSubDomains; preload
2022-04-07 07:41:51 141981 [HttpClient] 
2022-04-07 07:41:51 141981 [HttpClient] <html>
<head><title>405 Not Allowed</title></head>
<body>
<center><h1>405 Not Allowed</h1></center>
<hr><center>nginx</center>
</body>
</html>

2022-04-07 07:41:51 141981 [HttpClient] <-- END HTTP (150-byte body)
2022-04-07 07:41:51 141981 [ui.setup.DavResourceFinder] No resource found
EXCEPTION at.bitfire.dav4jvm.exception.HttpException: HTTP 405 
at at.bitfire.dav4jvm.DavResource.checkStatus(DavResource.kt:5)
at at.bitfire.dav4jvm.DavResource.checkStatus(DavResource.kt:3)
at at.bitfire.dav4jvm.DavResource.processMultiStatus(DavResource.kt:2)
at at.bitfire.dav4jvm.DavResource.propfind(DavResource.kt:11)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.getCurrentUserPrincipal(DavResourceFinder.kt:2)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.discoverPrincipalUrl(DavResourceFinder.kt:28)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:31)
at at.bitfire.davdroid.ui.setup.DavResourceFinder.findInitialConfiguration(DavResourceFinder.kt:4)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:6)
at at.bitfire.davdroid.ui.setup.DetectConfigurationFragment$DetectConfigurationModel$detectConfiguration$2.invoke(DetectConfigurationFragment.kt:1)
at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:1)

strangely enough i see the contacts in the weblink
Screenshot 2022-05-02 154432

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.