Davical: Unterschied zwischen den Versionen

Aus SchnallIchNet
Wechseln zu: Navigation, Suche
(Die Seite wurde neu angelegt: „== Setup == since the documentation is quite good, look at project page for installation.<br/> http://davical.org == Hints == Some hints regarding davical... …“)
 
 
(9 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 3: Zeile 3:
 
since the documentation is quite good, look at project page for installation.<br/>
 
since the documentation is quite good, look at project page for installation.<br/>
 
http://davical.org
 
http://davical.org
 +
 +
 +
=== nginx config ===
 +
 +
Finally got nginx working with this config:
 +
 +
<pre>
 +
server {
 +
    listen              80;
 +
    listen              [::]:80;
 +
    listen              443 ssl http2; # http2;
 +
    listen              [::]:443 ssl http2; # http2;
 +
    keepalive_timeout  0;
 +
 +
    server_name        caldav2 caldav;
 +
    root                /usr/share/davical/htdocs;
 +
 +
        index index.php;
 +
        access_log /var/log/nginx/access.davical.log;
 +
        error_log /var/log/nginx/error.davical.log; # debug;
 +
 +
        ssl_certificate /path/to/fullchain.pem;
 +
        ssl_certificate_key /path/to/privkey.pem;
 +
        # SSL hardening
 +
        ssl_session_cache  shared:SSL:10m;
 +
        ssl_session_timeout 15m;
 +
        ssl_prefer_server_ciphers On;
 +
        ssl_protocols TLSv1.1 TLSv1.2;
 +
        ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
 +
        # PFS
 +
        ssl_dhparam /etc/nginx/ssl/dhparam.pem;
 +
 +
        location /images/ {
 +
                access_log off;
 +
                expires 30d;
 +
        }
 +
 +
        location / {
 +
            try_files $uri $uri/ @rewrite;
 +
        }
 +
 +
        location @rewrite {
 +
                index  caldav.php;
 +
                rewrite ^/(.*)$ /caldav.php/$1;
 +
        }
 +
 +
        location ~ \.php$ {
 +
              include /etc/nginx/fastcgi_params;
 +
              fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
 +
              fastcgi_pass    unix:/tmp/php5-fpm-davical.sock;
 +
              fastcgi_index index.php;
 +
    }
 +
 +
        location ~ ^(.+\.php)/(.*)$ {
 +
              include fastcgi_params;
 +
              fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 +
              fastcgi_pass unix:/tmp/php5-fpm-davical.sock;
 +
                     
 +
              fastcgi_split_path_info ^(.+\.php)(.*)$;
 +
              fastcgi_param PATH_INFO $fastcgi_path_info;
 +
              #fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
 +
              # PATH_TRANSLATED caused errors in my setup, so commented it out
 +
 +
              fastcgi_read_timeout 180;
 +
              fastcgi_buffers 4 256k;
 +
              fastcgi_buffer_size 128k;
 +
              }
 +
 +
}
 +
</pre>
 +
 +
 +
== Webinterfaces ==
 +
 +
there are 2 webinterfaces to calDAV and cardDAV which work fine for me with davical:
 +
 +
one for calDAV:
 +
 +
[http://boxacle.net/jqcaldav/ jqCaldav]
 +
 +
 +
and there is one for cardDAV:
 +
 +
[http://www.inf-it.com/ cardDAV-Mate]
  
  
Zeile 10: Zeile 94:
  
  
== bind ==
+
=== bind ===
  
create bindings:
+
create bindings... <br/>
 +
for self-signed certs while using https/SSL additionaly use '--insecure' <br/>
  
 
  curl --basic --user 'user1' -X BIND -H 'Content-Type: text/xml; charset="UTF-8"' \
 
  curl --basic --user 'user1' -X BIND -H 'Content-Type: text/xml; charset="UTF-8"' \
  --url 'https://davical.example.com/caldav.php/user1/' \
+
  --insecure --url 'https://davical.example.com/caldav.php/user1/' \
 
  -d '<?xml version="1.0" encoding="utf-8"?> <bind xmlns="DAV:"><segment>collection</segment> <href>/caldav.php/sourceprincipal/collection</href> </bind>';
 
  -d '<?xml version="1.0" encoding="utf-8"?> <bind xmlns="DAV:"><segment>collection</segment> <href>/caldav.php/sourceprincipal/collection</href> </bind>';
 +
 +
 +
if you want to use an SQL query:
 +
 +
insert into dav_binding(bound_source_id,dav_owner_id,parent_container,dav_name,dav_displayname)
 +
VALUES(<ID_OF_SOURCE_COLLECTION>, <DAV_OWNER_ID>, '/user1/', '/user1/teamCal/', 'Teamcalendar');
 +
 +
as you can see, you will have to collect some informations from DB/webinterface.<br/>
 +
 +
{{Achtung|DAV_OWNER_ID is _NOT_ the usr_no from the 'usr'!! use the 'principal_id' from 'principal'-table instead}}
 +
 +
<br/>
 +
 +
=== cardDAV mass import ===
 +
 +
because it's bullshit filling every card by the phone or carddavMATE or so, i wrote a simple (absolute) importer in php...<br/>
 +
tested with a .vcf-File exported from my email-client btw. from my iPhone/iTunes<br/>
 +
 +
{{Achtung|Make sure the .vcf-file has std. unix line-endings}}
 +
 +
 +
you may run the file from command-line:
 +
 +
php /path/to/davicalVcfImporter.php /path/to/your/contacts-file.vcf
 +
 +
 +
or put it to the webroot of any webserver:
 +
 +
http://localhost/davicalVcfImporter.php?vcfFileName=/path/to/your/contacts-file.vcf
 +
 +
if you use the webserver method of calling the script, make sure the file is accessable and readable <br/>
 +
by the user running your httpd!
 +
 +
<pre>
 +
<?php
 +
 +
/**
 +
* CarddavImporter
 +
* for CalDAV Server - daviCal
 +
*
 +
* (may be works with other servers with little modifications)
 +
*
 +
* TODO:
 +
* - add checks against collection to avoid duplicates...
 +
* - check syntax of input-vcards against some rfc
 +
*
 +
* @package  davical-carddav-import
 +
* @copyright Christoph Steidl <chris@rubbish.de>
 +
* @license  http://gnu.org/copyleft/gpl.html GNU GPL V2
 +
*/
 +
 +
/// configuration
 +
$user            = 'USERNAME';
 +
$pass            = 'securePASSWORD';
 +
$cardsCollection = 'contacts';
 +
$serverURL      = 'https://caldav.example.com/caldav.php/' . $user . '/' . $cardsCollection;
 +
 +
if(PHP_SAPI === 'cli') {
 +
    $vcfFileName = $argv[1];
 +
} else {
 +
    echo "<pre>\n";
 +
    $vcfFileName = $_REQUEST['vcfFileName'];
 +
}
 +
 +
if( file_exists($vcfFileName) ) {
 +
    $vcfFile = file_get_contents($vcfFileName);
 +
} else {
 +
    die("File not found: " . $vcfFileName . "\n");
 +
}
 +
 +
 +
$is_multivcard = false;
 +
 +
class uuid {
 +
    protected $uuidobject;
 +
 +
    protected function create() {
 +
        if(!is_resource($this->uuidobject))
 +
            uuid_create(&$this->uuidobject);
 +
    }
 +
 +
    public function v4() {
 +
        $this->create();
 +
        uuid_make($this->uuidobject, UUID_MAKE_V4);
 +
        uuid_export($this->uuidobject, UUID_FMT_STR, &$uuidstring);
 +
        return trim($uuidstring);
 +
    }
 +
}
 +
 +
function vcard_split($vcf) {
 +
    $result = array();
 +
    $is_started = false;
 +
    $is_finished = false;
 +
    $cardcnt = 0;
 +
 +
    foreach($vcf as $line) {
 +
        if($is_started === false) {
 +
            if(preg_match('/BEGIN:VCARD/', $line) > 0) {
 +
                $is_started = true;
 +
                $cardcnt = $cardcnt + 1;
 +
            }
 +
        } else if($is_started === true && $is_finished === false) {
 +
            if(preg_match('/END:VCARD/', $line) > 0) {
 +
                $is_finished = true;
 +
            }
 +
        }
 +
 +
        if($is_started === true && $is_finished === false) {
 +
            $result[$cardcnt] .= $line;
 +
        } else if($is_started === true && $is_finished === true) {
 +
            $is_started = false;
 +
            $is_finished = false;
 +
            $uuid = new uuid;
 +
            $UID = $uuid->v4();
 +
 +
            $result[$cardcnt] .= "UID:$UID\n";
 +
            $result[$cardcnt] .= "PRODID:-//SiliconHome IT-Systems//CardDavImporter 0.1.0//EN\n";
 +
            $result[$cardcnt] .= $line; // <-- this should be 'END:VCARD'
 +
        }
 +
    }
 +
 +
    return $result;
 +
}
 +
 +
$begin_cnt = preg_match_all('/BEGIN:VCARD/', $vcfFile, $matches);
 +
$end_cnt  = preg_match_all('/END:VCARD/', $vcfFile, $matches);
 +
 +
// very simple validation of file
 +
// TODO: should be checked against RFC or so...
 +
if($begin_cnt > 0) {
 +
    if($begin_cnt == $end_cnt) {
 +
        if($begin_cnt > 1) {
 +
            $is_multivcard = true;
 +
        } else {
 +
            $is_multivcard = false;
 +
        }
 +
    } else {
 +
        echo "Counted BEGIN:VCARD are not equal counted END:VCARD";
 +
        exit(2);
 +
    }
 +
} else {
 +
    echo "No VCARD-File?? BEGIN:VCARD not found in file...";
 +
    exit(1);
 +
}
 +
 +
// create an array of lines
 +
$vcfFile = file($vcfFileName);
 +
 +
// split cards if multiple cards in file
 +
if($is_multivcard === true) {
 +
    $cards = vcard_split($vcfFile);
 +
} else {
 +
    $cards[0] = $vcfFile;
 +
}
 +
 +
// now we have one card per array member...
 +
// storing it to davical-carddav...
 +
foreach($cards as $vcard) {
 +
    $fileName = hash( 'sha256', $vcard . time(void) ) . ".vcf";
 +
 +
    $url = $serverURL . "/" . $fileName;
 +
    $ch = curl_init();
 +
    curl_setopt($ch, CURLOPT_URL,              "$url");
 +
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,    false);
 +
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,    false);
 +
    curl_setopt($ch, CURLOPT_RETURNTRANSFER,    true);
 +
    // post vals
 +
    curl_setopt($ch, CURLOPT_HTTPHEADER,        array('Content-type: text/vcard; charset="UTF-8"', 'Content-Length: ' . strlen($vcard)));
 +
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST,    'PUT');
 +
    curl_setopt($ch, CURLOPT_POSTFIELDS,        $vcard);
 +
    curl_setopt($ch, CURLOPT_USERPWD,          "$user:$pass");
 +
    // exec request
 +
    $chresponse = curl_exec($ch);
 +
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
 +
    curl_close($ch);
 +
 +
    // TODO: check curl-status
 +
}
 +
 +
// you want to see what was imported?
 +
// comment in next 2 lines
 +
//print_r( $cards );
 +
//print "\n";
 +
 +
exit(0);
 +
 +
</pre>

Aktuelle Version vom 19. Oktober 2017, 11:02 Uhr

Setup

since the documentation is quite good, look at project page for installation.
http://davical.org


nginx config

Finally got nginx working with this config:

server {
    listen              80;
    listen              [::]:80;
    listen              443 ssl http2; # http2;
    listen              [::]:443 ssl http2; # http2;
    keepalive_timeout   0; 

    server_name         caldav2 caldav;
    root                /usr/share/davical/htdocs;

        index index.php;
        access_log /var/log/nginx/access.davical.log;
        error_log /var/log/nginx/error.davical.log; # debug;

        ssl_certificate /path/to/fullchain.pem;
        ssl_certificate_key /path/to/privkey.pem;
        # SSL hardening
        ssl_session_cache   shared:SSL:10m;
        ssl_session_timeout 15m;
        ssl_prefer_server_ciphers On;
        ssl_protocols TLSv1.1 TLSv1.2;
        ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
        # PFS
        ssl_dhparam /etc/nginx/ssl/dhparam.pem;

        location /images/ {
                access_log off;
                expires 30d;
        }

        location / {
            try_files $uri $uri/ @rewrite;
        }

        location @rewrite {
                index   caldav.php;
                rewrite ^/(.*)$ /caldav.php/$1;
        }

        location ~ \.php$ {
               include /etc/nginx/fastcgi_params;
               fastcgi_param   SCRIPT_FILENAME  $document_root$fastcgi_script_name;
               fastcgi_pass    unix:/tmp/php5-fpm-davical.sock;
               fastcgi_index index.php;
    }

        location ~ ^(.+\.php)/(.*)$ {
               include fastcgi_params;
               fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
               fastcgi_pass unix:/tmp/php5-fpm-davical.sock;
                       
               fastcgi_split_path_info ^(.+\.php)(.*)$;
               fastcgi_param PATH_INFO $fastcgi_path_info;
               #fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
               # PATH_TRANSLATED caused errors in my setup, so commented it out

               fastcgi_read_timeout 180;
               fastcgi_buffers 4 256k;
               fastcgi_buffer_size 128k;
               }

}


Webinterfaces

there are 2 webinterfaces to calDAV and cardDAV which work fine for me with davical:

one for calDAV:

jqCaldav


and there is one for cardDAV:

cardDAV-Mate


Hints

Some hints regarding davical...


bind

create bindings...
for self-signed certs while using https/SSL additionaly use '--insecure'

curl --basic --user 'user1' -X BIND -H 'Content-Type: text/xml; charset="UTF-8"' \
--insecure --url 'https://davical.example.com/caldav.php/user1/' \
-d '<?xml version="1.0" encoding="utf-8"?> <bind xmlns="DAV:"><segment>collection</segment> <href>/caldav.php/sourceprincipal/collection</href> </bind>';


if you want to use an SQL query:

insert into dav_binding(bound_source_id,dav_owner_id,parent_container,dav_name,dav_displayname) 
VALUES(<ID_OF_SOURCE_COLLECTION>, <DAV_OWNER_ID>, '/user1/', '/user1/teamCal/', 'Teamcalendar');

as you can see, you will have to collect some informations from DB/webinterface.

Achtung.jpeg DAV_OWNER_ID is _NOT_ the usr_no from the 'usr'!! use the 'principal_id' from 'principal'-table instead


cardDAV mass import

because it's bullshit filling every card by the phone or carddavMATE or so, i wrote a simple (absolute) importer in php...
tested with a .vcf-File exported from my email-client btw. from my iPhone/iTunes

Achtung.jpeg Make sure the .vcf-file has std. unix line-endings


you may run the file from command-line:

php /path/to/davicalVcfImporter.php /path/to/your/contacts-file.vcf


or put it to the webroot of any webserver:

http://localhost/davicalVcfImporter.php?vcfFileName=/path/to/your/contacts-file.vcf

if you use the webserver method of calling the script, make sure the file is accessable and readable
by the user running your httpd!

<?php

/**
* CarddavImporter
* for CalDAV Server - daviCal
*
* (may be works with other servers with little modifications)
*
* TODO:
* - add checks against collection to avoid duplicates...
* - check syntax of input-vcards against some rfc
*
* @package   davical-carddav-import
* @copyright Christoph Steidl <chris@rubbish.de>
* @license   http://gnu.org/copyleft/gpl.html GNU GPL V2
*/

/// configuration
$user            = 'USERNAME';
$pass            = 'securePASSWORD';
$cardsCollection = 'contacts';
$serverURL       = 'https://caldav.example.com/caldav.php/' . $user . '/' . $cardsCollection;

if(PHP_SAPI === 'cli') {
    $vcfFileName = $argv[1];
} else {
    echo "<pre>\n";
    $vcfFileName = $_REQUEST['vcfFileName'];
}

if( file_exists($vcfFileName) ) {
    $vcfFile = file_get_contents($vcfFileName);
} else {
    die("File not found: " . $vcfFileName . "\n");
}


$is_multivcard = false;

class uuid {
    protected $uuidobject;

    protected function create() {
        if(!is_resource($this->uuidobject))
            uuid_create(&$this->uuidobject);
    }

    public function v4() {
        $this->create();
        uuid_make($this->uuidobject, UUID_MAKE_V4);
        uuid_export($this->uuidobject, UUID_FMT_STR, &$uuidstring);
        return trim($uuidstring);
    }
}

function vcard_split($vcf) {
    $result = array();
    $is_started = false;
    $is_finished = false;
    $cardcnt = 0;

    foreach($vcf as $line) {
        if($is_started === false) {
            if(preg_match('/BEGIN:VCARD/', $line) > 0) {
                $is_started = true;
                $cardcnt = $cardcnt + 1;
            }
        } else if($is_started === true && $is_finished === false) {
            if(preg_match('/END:VCARD/', $line) > 0) {
                $is_finished = true;
            }
        }

        if($is_started === true && $is_finished === false) {
            $result[$cardcnt] .= $line;
        } else if($is_started === true && $is_finished === true) {
            $is_started = false;
            $is_finished = false;
            $uuid = new uuid;
            $UID = $uuid->v4();

            $result[$cardcnt] .= "UID:$UID\n";
            $result[$cardcnt] .= "PRODID:-//SiliconHome IT-Systems//CardDavImporter 0.1.0//EN\n";
            $result[$cardcnt] .= $line; // <-- this should be 'END:VCARD'
        }
    }

    return $result;
}

$begin_cnt = preg_match_all('/BEGIN:VCARD/', $vcfFile, $matches);
$end_cnt   = preg_match_all('/END:VCARD/', $vcfFile, $matches);

// very simple validation of file
// TODO: should be checked against RFC or so...
if($begin_cnt > 0) {
    if($begin_cnt == $end_cnt) {
        if($begin_cnt > 1) {
            $is_multivcard = true;
        } else {
            $is_multivcard = false;
        }
    } else {
        echo "Counted BEGIN:VCARD are not equal counted END:VCARD";
        exit(2);
    }
} else {
    echo "No VCARD-File?? BEGIN:VCARD not found in file...";
    exit(1);
}

// create an array of lines
$vcfFile = file($vcfFileName);

// split cards if multiple cards in file
if($is_multivcard === true) {
    $cards = vcard_split($vcfFile);
} else {
    $cards[0] = $vcfFile;
}

// now we have one card per array member...
// storing it to davical-carddav...
foreach($cards as $vcard) {
    $fileName = hash( 'sha256', $vcard . time(void) ) . ".vcf";

    $url = $serverURL . "/" . $fileName;
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,               "$url");
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,    false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,    false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER,    true);
    // post vals
    curl_setopt($ch, CURLOPT_HTTPHEADER,        array('Content-type: text/vcard; charset="UTF-8"', 'Content-Length: ' . strlen($vcard)));
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST,     'PUT');
    curl_setopt($ch, CURLOPT_POSTFIELDS,        $vcard);
    curl_setopt($ch, CURLOPT_USERPWD,           "$user:$pass");
    // exec request
    $chresponse = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    // TODO: check curl-status
}

// you want to see what was imported?
// comment in next 2 lines
//print_r( $cards );
//print "\n";

exit(0);