Skip to content

Commit

Permalink
Module DAV
Browse files Browse the repository at this point in the history
  • Loading branch information
eldy committed Mar 27, 2018
1 parent b6a0b1f commit fb2885b
Show file tree
Hide file tree
Showing 3 changed files with 356 additions and 13 deletions.
294 changes: 294 additions & 0 deletions htdocs/dav/dav.class.php
@@ -0,0 +1,294 @@
<?php
/* Copyright (C) 2018 Destailleur Laurent <eldy@users.sourceforge.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/**
* \file htdocs/dav/dav.class.php
* \ingroup dav
* \brief Server DAV
*/


/**
* Define Common function to access calendar items
* And format it in vCalendar
* */

class CdavLib
{

private $db;

private $user;

private $langs;

function __construct($user, $db, $langs)
{
$this->user = $user;
$this->db = $db;
$this->langs = $langs;
}

/**
* Base sql request for calendar events
*
* @param int calendar user id
* @param int actioncomm object id
* @return string
*/
public function getSqlCalEvents($calid, $oid=false, $ouri=false)
{
// TODO : replace GROUP_CONCAT by
$sql = 'SELECT
a.tms AS lastupd,
a.*,
sp.firstname,
sp.lastname,
sp.address,
sp.zip,
sp.town,
co.label country_label,
sp.phone,
sp.phone_perso,
sp.phone_mobile,
s.nom AS soc_nom,
s.address soc_address,
s.zip soc_zip,
s.town soc_town,
cos.label soc_country_label,
s.phone soc_phone,
ac.sourceuid,
(SELECT GROUP_CONCAT(u.login) FROM '.MAIN_DB_PREFIX.'actioncomm_resources ar
LEFT OUTER JOIN '.MAIN_DB_PREFIX.'user AS u ON (u.rowid=fk_element)
WHERE ar.element_type=\'user\' AND fk_actioncomm=a.id) AS other_users
FROM '.MAIN_DB_PREFIX.'actioncomm AS a';
if (! $this->user->rights->societe->client->voir )//FIXME si 'voir' on voit plus de chose ?
{
$sql.=' LEFT OUTER JOIN '.MAIN_DB_PREFIX.'societe_commerciaux AS sc ON (a.fk_soc = sc.fk_soc AND sc.fk_user='.$this->user->id.')
LEFT JOIN '.MAIN_DB_PREFIX.'societe AS s ON (s.rowid = sc.fk_soc)
LEFT JOIN '.MAIN_DB_PREFIX.'socpeople AS sp ON (sp.fk_soc = sc.fk_soc AND sp.rowid = a.fk_contact)
LEFT JOIN '.MAIN_DB_PREFIX.'actioncomm_cdav AS ac ON (a.id = ac.fk_object)';
}
else
{
$sql.=' LEFT JOIN '.MAIN_DB_PREFIX.'societe AS s ON (s.rowid = a.fk_soc)
LEFT JOIN '.MAIN_DB_PREFIX.'socpeople AS sp ON (sp.rowid = a.fk_contact)
LEFT JOIN '.MAIN_DB_PREFIX.'actioncomm_cdav AS ac ON (a.id = ac.fk_object)';
}

$sql.=' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as co ON co.rowid = sp.fk_pays
LEFT JOIN '.MAIN_DB_PREFIX.'c_country as cos ON cos.rowid = s.fk_pays
WHERE a.id IN (SELECT ar.fk_actioncomm FROM '.MAIN_DB_PREFIX.'actioncomm_resources ar WHERE ar.element_type=\'user\' AND ar.fk_element='.intval($calid).')
AND a.code IN (SELECT cac.code FROM '.MAIN_DB_PREFIX.'c_actioncomm cac WHERE cac.type<>\'systemauto\')
AND a.entity IN ('.getEntity('societe', 1).')';
if($oid!==false) {
if($ouri===false)
{
$sql.=' AND a.id = '.intval($oid);
}
else
{
$sql.=' AND (a.id = '.intval($oid).' OR ac.uuidext = \''.$this->db->escape($ouri).'\')';
}
}

return $sql;

}

/**
* Convert calendar row to VCalendar string
*
* @param row object
* @return string
*/
public function toVCalendar($calid, $obj)
{

$categ = [];
/*if($obj->soc_client)
{
$nick[] = $obj->soc_code_client;
$categ[] = $this->langs->transnoentitiesnoconv('Customer');
}*/

$location=$obj->location;

// contact address
if(empty($location) && !empty($obj->address))
{
$location = trim(str_replace(array("\r","\t","\n"),' ', $obj->address));
$location = trim($location.', '.$obj->zip);
$location = trim($location.' '.$obj->town);
$location = trim($location.', '.$obj->country_label);
}

// contact address
if(empty($location) && !empty($obj->soc_address))
{
$location = trim(str_replace(array("\r","\t","\n"),' ', $obj->soc_address));
$location = trim($location.', '.$obj->soc_zip);
$location = trim($location.' '.$obj->soc_town);
$location = trim($location.', '.$obj->soc_country_label);
}

$address=explode("\n",$obj->address,2);
foreach($address as $kAddr => $vAddr)
{
$address[$kAddr] = trim(str_replace(array("\r","\t"),' ', str_replace("\n",' | ', trim($vAddr))));
}
$address[]='';
$address[]='';

if($obj->percent==-1 && trim($obj->datep)!='')
$type='VEVENT';
else
$type='VTODO';

$timezone = date_default_timezone_get();

$caldata ="BEGIN:VCALENDAR\n";
$caldata.="VERSION:2.0\n";
$caldata.="METHOD:PUBLISH\n";
$caldata.="PRODID:-//Dolibarr CDav//FR\n";
$caldata.="BEGIN:".$type."\n";
$caldata.="CREATED:".gmdate('Ymd\THis', strtotime($obj->datec))."Z\n";
$caldata.="LAST-MODIFIED:".gmdate('Ymd\THis', strtotime($obj->lastupd))."Z\n";
$caldata.="DTSTAMP:".gmdate('Ymd\THis', strtotime($obj->lastupd))."Z\n";
if($obj->sourceuid=='')
$caldata.="UID:".$obj->id.'-ev-'.$calid.'-cal-'.CDAV_URI_KEY."\n";
else
$caldata.="UID:".$obj->sourceuid."\n";
$caldata.="SUMMARY:".$obj->label."\n";
$caldata.="LOCATION:".$location."\n";
$caldata.="PRIORITY:".$obj->priority."\n";
if($obj->fulldayevent)
{
$caldata.="DTSTART;VALUE=DATE:".date('Ymd', strtotime($obj->datep))."\n";
if($type=='VEVENT')
{
if(trim($obj->datep2)!='')
$caldata.="DTEND;VALUE=DATE:".date('Ymd', strtotime($obj->datep2)+1)."\n";
else
$caldata.="DTEND;VALUE=DATE:".date('Ymd', strtotime($obj->datep)+(25*3600))."\n";
}
elseif(trim($obj->datep2)!='')
$caldata.="DUE;VALUE=DATE:".date('Ymd', strtotime($obj->datep2)+1)."\n";
}
else
{
$caldata.="DTSTART;TZID=".$timezone.":".strtr($obj->datep,array(" "=>"T", ":"=>"", "-"=>""))."\n";
if($type=='VEVENT')
{
if(trim($obj->datep2)!='')
$caldata.="DTEND;TZID=".$timezone.":".strtr($obj->datep2,array(" "=>"T", ":"=>"", "-"=>""))."\n";
else
$caldata.="DTEND;TZID=".$timezone.":".strtr($obj->datep,array(" "=>"T", ":"=>"", "-"=>""))."\n";
}
elseif(trim($obj->datep2)!='')
$caldata.="DUE;TZID=".$timezone.":".strtr($obj->datep2,array(" "=>"T", ":"=>"", "-"=>""))."\n";
}
$caldata.="CLASS:PUBLIC\n";
if($obj->transparency==1)
$caldata.="TRANSP:TRANSPARENT\n";
else
$caldata.="TRANSP:OPAQUE\n";

if($type=='VEVENT')
$caldata.="STATUS:CONFIRMED\n";
elseif($obj->percent==0)
$caldata.="STATUS:NEEDS-ACTION\n";
elseif($obj->percent==100)
$caldata.="STATUS:COMPLETED\n";
else
{
$caldata.="STATUS:IN-PROCESS\n";
$caldata.="PERCENT-COMPLETE:".$obj->percent."\n";
}

$caldata.="DESCRIPTION:";
$caldata.=strtr($obj->note, array("\n"=>"\\n", "\r"=>""));
if(!empty($obj->soc_nom))
$caldata.="\\n*DOLIBARR-SOC: ".$obj->soc_nom;
if(!empty($obj->soc_phone))
$caldata.="\\n*DOLIBARR-SOC-TEL: ".$obj->soc_phone;
if(!empty($obj->firstname) || !empty($obj->lastname))
$caldata.="\\n*DOLIBARR-CTC: ".trim($obj->firstname.' '.$obj->lastname);
if(!empty($obj->phone) || !empty($obj->phone_perso) || !empty($obj->phone_mobile))
$caldata.="\\n*DOLIBARR-CTC-TEL: ".trim($obj->phone.' '.$obj->phone_perso.' '.$obj->phone_mobile);
if(strpos($obj->other_users,',')) // several
$caldata.="\\n*DOLIBARR-USR: ".$obj->other_users;
$caldata.="\n";

$caldata.="END:".$type."\n";
$caldata.="END:VCALENDAR\n";

return $caldata;
}

public function getFullCalendarObjects($calendarId, $bCalendarData)
{

$calid = ($calendarId*1);
$calevents = [] ;

if(! $this->user->rights->agenda->myactions->read)
return $calevents;

if($calid!=$this->user->id && (!isset($this->user->rights->agenda->allactions->read) || !$this->user->rights->agenda->allactions->read))
return $calevents;

$sql = $this->getSqlCalEvents($calid);

$result = $this->db->query($sql);

if ($result)
{
while ($obj = $this->db->fetch_object($result))
{
$calendardata = $this->toVCalendar($calid, $obj);

if($bCalendarData)
{
$calevents[] = [
'calendardata' => $calendardata,
'uri' => $obj->id.'-ev-'.CDAV_URI_KEY,
'lastmodified' => strtotime($obj->lastupd),
'etag' => '"'.md5($calendardata).'"',
'calendarid' => $calendarId,
'size' => strlen($calendardata),
'component' => strpos($calendardata, 'BEGIN:VEVENT')>0 ? 'vevent' : 'vtodo',
];
}
else
{
$calevents[] = [
// 'calendardata' => $calendardata, not necessary because etag+size are present
'uri' => $obj->id.'-ev-'.CDAV_URI_KEY,
'lastmodified' => strtotime($obj->lastupd),
'etag' => '"'.md5($calendardata).'"',
'calendarid' => $calendarId,
'size' => strlen($calendardata),
'component' => strpos($calendardata, 'BEGIN:VEVENT')>0 ? 'vevent' : 'vtodo',
];
}
}
}
return $calevents;
}

}
40 changes: 40 additions & 0 deletions htdocs/dav/dav.lib.php
@@ -0,0 +1,40 @@
<?php
/* Copyright (C) 2018 Destailleur Laurent <eldy@users.sourceforge.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/**
* \file htdocs/dav/dav.lib.php
* \ingroup dav
* \brief Server DAV
*/

// define CDAV_CONTACT_TAG if not
if(!defined('CDAV_CONTACT_TAG'))
{
if(isset($conf->global->CDAV_CONTACT_TAG))
define('CDAV_CONTACT_TAG', $conf->global->CDAV_CONTACT_TAG);
else
define('CDAV_CONTACT_TAG', '');
}

// define CDAV_URI_KEY if not
if(!defined('CDAV_URI_KEY'))
{
if(isset($conf->global->CDAV_URI_KEY))
define('CDAV_URI_KEY', $conf->global->CDAV_URI_KEY);
else
define('CDAV_URI_KEY', substr(md5($_SERVER['HTTP_HOST']),0,8));
}
35 changes: 22 additions & 13 deletions htdocs/dav/fileserver.php
Expand Up @@ -35,10 +35,11 @@
require ("../main.inc.php");
require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';

// Files we need
require_once DOL_DOCUMENT_ROOT.'/dav/dav.class.php';
require_once DOL_DOCUMENT_ROOT.'/dav/dav.lib.php';
require_once DOL_DOCUMENT_ROOT.'/includes/sabre/autoload.php';


$user = new User($db);
if(isset($_SERVER['PHP_AUTH_USER']) && $_SERVER['PHP_AUTH_USER']!='')
{
Expand Down Expand Up @@ -83,7 +84,7 @@
return true;
});

$authBackend->setRealm('Dolibarr');
$authBackend->setRealm(constant('DOL_APPLICATION_TITLE'));



Expand All @@ -95,16 +96,24 @@

// Create the root node
// Setting up the directory tree //
$nodes = array(
// /principals
//new \Sabre\DAVACL\PrincipalCollection($principalBackend),
// /addressbook
//new \Sabre\CardDAV\AddressBookRoot($principalBackend, $carddavBackend),
// /calendars
//new \Sabre\CalDAV\CalendarRoot($principalBackend, $caldavBackend),
// / Public docs
new \Sabre\DAV\FS\Directory($dolibarr_main_data_root. '/dav/public')
);
$nodes = array();

// Enable directories and features according to DAV setup
// / Public docs
$nodes[] = new \Sabre\DAV\FS\Directory($dolibarr_main_data_root. '/dav/public');

// Principals Backend
//$principalBackend = new \Sabre\DAVACL\PrincipalBackend\Dolibarr($user,$db);
// /principals
//$nodes[] = new \Sabre\DAVACL\PrincipalCollection($principalBackend);
// CardDav & CalDav Backend
//$carddavBackend = new \Sabre\CardDAV\Backend\Dolibarr($user,$db,$langs);
//$caldavBackend = new \Sabre\CalDAV\Backend\Dolibarr($user,$db,$langs, $cdavLib);
// /addressbook
//$nodes[] = new \Sabre\CardDAV\AddressBookRoot($principalBackend, $carddavBackend);
// /calendars
//$nodes[] = new \Sabre\CalDAV\CalendarRoot($principalBackend, $caldavBackend);


// The rootnode needs in turn to be passed to the server class
$server = new \Sabre\DAV\Server($nodes);
Expand Down

0 comments on commit fb2885b

Please sign in to comment.