From 9e9d14f3dde0a7742651fcbae6995d3cb9857dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96sterreicher?= Date: Thu, 22 Mar 2012 13:14:19 +0000 Subject: [PATCH] =?UTF-8?q?Caldav=20Schnittstelle=20f=C3=BCr=20LVPlan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cis/private/lvplan/index.php | 4 +- include/wochenplan.class.php | 42 +++- webdav/Caldav_Backend.php | 358 ++++++++++++++++++++++++++++++++++ webdav/DMSdirectory.class.php | 2 +- webdav/DMSfile.class.php | 41 +++- webdav/Principal.php | 172 ++++++++++++++++ webdav/dms.php | 6 +- webdav/lvplan.php | 47 +++++ 8 files changed, 649 insertions(+), 23 deletions(-) create mode 100644 webdav/Caldav_Backend.php create mode 100644 webdav/Principal.php create mode 100644 webdav/lvplan.php diff --git a/cis/private/lvplan/index.php b/cis/private/lvplan/index.php index ff63def0e..b3e69ddb8 100644 --- a/cis/private/lvplan/index.php +++ b/cis/private/lvplan/index.php @@ -37,7 +37,7 @@ if (!$uid=get_uid()) -$sql_query="SET search_path TO campus; SELECT titelpre, titelpost, uid, nachname, vorname FROM vw_benutzer WHERE uid LIKE '$uid'"; +$sql_query="SELECT titelpre, titelpost, uid, nachname, vorname FROM campus.vw_benutzer WHERE uid LIKE '$uid'"; //echo $sql_query; $result=$db->db_query($sql_query); @@ -71,7 +71,7 @@ if(!$result_ort) die("ort not found!"); $num_rows_ort=$db->db_num_rows($result_ort); -$sql_query="SELECT uid, kurzbz FROM vw_mitarbeiter ORDER BY kurzbz"; +$sql_query="SELECT uid, kurzbz FROM campus.vw_mitarbeiter ORDER BY kurzbz"; $result_lektor=$db->db_query($sql_query); if(!$result_lektor) die("lektor not found!"); diff --git a/include/wochenplan.class.php b/include/wochenplan.class.php index b035fbc53..cd394183b 100644 --- a/include/wochenplan.class.php +++ b/include/wochenplan.class.php @@ -1907,6 +1907,7 @@ class wochenplan extends basis_db */ public function draw_week_csv($target, $lvplan_kategorie) { + $return = array(); if (!date("w",$this->datum)) $this->datum=jump_day($this->datum,1); $num_rows_stunde=$this->db_num_rows($this->stunde); @@ -2161,17 +2162,39 @@ class wochenplan extends basis_db $start_date_time_ical = $sda[2].$sda[1].$sda[0].'T'.sprintf('%02s',($sta[0])).$sta[1].$sta[2]; //neu gruppieren der Startzeit und des Startdatums $end_date_time_ical = $eda[2].$eda[1].$eda[0].'T'.sprintf('%02s',($eta[0])).$eta[1].$eta[2]; //neu gruppieren der Startzeit und des Startdatums echo $this->crlf,'FREEBUSY: ',$start_date_time_ical,'/',$end_date_time_ical; - /* - echo $this->crlf.'BEGIN:VEVENT'.$this->crlf - .'UID:'.'FH'.$lvb.$this->std_plan[$i][$j][$idx]->ort.$this->std_plan[$i][$j][$idx]->lektor.$lehrfach[$idx].$start_date_time_ical.$this->crlf - .'SUMMARY:'.$lehrfach[$idx].' '.$this->std_plan[$i][$j][$idx]->ort.' - '.$lvb.$this->crlf - .'DESCRIPTION:'.$lehrfach[$idx].'\n'.$this->std_plan[$i][$j][$idx]->lektor.'\n'.$lvb.'\n'.$this->std_plan[$i][$j][$idx]->ort.$this->crlf + } + elseif ($target=='return') + { + $sda = explode(".",$start_date); //sda start date array + $sta = explode(":",$start_time); //sta start time array + $eda = explode(".",$end_date); //eda end date array + $eta = explode(":",$end_time); //eta end time array + + //Die Zeitzone muss angegeben werden, da sonst der Google Kalender die Endzeiten nicht richtig erkennt + // diese wird in stpl_kalender global definiert und bei den Start und Ende Zeiten mitangegeben + $start_date_time_ical = $sda[2].$sda[1].$sda[0].'T'.sprintf('%02s',($sta[0])).$sta[1].$sta[2]; //neu gruppieren der Startzeit und des Startdatums + $end_date_time_ical = $eda[2].$eda[1].$eda[0].'T'.sprintf('%02s',($eta[0])).$eta[1].$eta[2]; //neu gruppieren der Startzeit und des Startdatums + + $UID = 'FH'.$lvb.$this->std_plan[$i][$j][$idx]->ort.$this->std_plan[$i][$j][$idx]->lektor.$lehrfach[$idx].$start_date_time_ical; + $Summary = $lehrfach[$idx].' '.$this->std_plan[$i][$j][$idx]->ort.' - '.$lvb; + $description = $lehrfach[$idx].'\n'.$this->std_plan[$i][$j][$idx]->lektor.'\n'.$lvb.'\n'.$this->std_plan[$i][$j][$idx]->ort; + + $return[]=array('UID'=>$UID, + 'unr'=>$unr, + 'Summary'=>$Summary, + 'Description'=>$description, + 'dtstart'=>$start_date_time_ical, + 'dtend'=>$end_date_time_ical, + 'updateamum'=>$this->std_plan[$i][$j][$idx]->updateamum, + 'data'=>'BEGIN:VEVENT'.$this->crlf + .'UID:'.$UID.$this->crlf + .'SUMMARY:'.$Summary.$this->crlf + .'DESCRIPTION:'.$description.$this->crlf .'LOCATION:'.$this->std_plan[$i][$j][$idx]->ort.$this->crlf .'CATEGORIES:'.$lvplan_kategorie.$this->crlf .'DTSTART;TZID=Europe/Vienna:'.$start_date_time_ical.$this->crlf .'DTEND;TZID=Europe/Vienna:'.$end_date_time_ical.$this->crlf - .'END:VEVENT'; - */ + .'END:VEVENT'); } else { @@ -2184,7 +2207,10 @@ class wochenplan extends basis_db } $this->datum=jump_day($this->datum, 1); } - return true; + if($target=='return') + return $return; + else + return true; } /** diff --git a/webdav/Caldav_Backend.php b/webdav/Caldav_Backend.php new file mode 100644 index 000000000..22d227dcf --- /dev/null +++ b/webdav/Caldav_Backend.php @@ -0,0 +1,358 @@ +auth = $auth; + } + + /** + * Liefert den eingeloggten User + */ + function getUser() + { + return $this->auth->getCurrentUser(); + } + + /** + * Returns a list of calendars for a principal. + * + * Every project is an array with the following keys: + * * id, a unique id that will be used by other functions to modify the + * calendar. This can be the same as the uri or a database key. + * * uri, which the basename of the uri with which the calendar is + * accessed. + * * principalUri. The owner of the calendar. Almost always the same as + * principalUri passed to this method. + * + * Furthermore it can contain webdav properties in clark notation. A very + * common one is '{DAV:}displayname'. + * + * @param string $principalUri + * @return array + */ + public function getCalendarsForUser($principalUri) + { + //error_log("Caldav_Backend.php/getCalendarsForUser($principalUri)"); + $user = $this->getUser(); + $calendars = array(); + $calendar = array( + 'id' => $user, + 'uri' => 'LVPlan-'.$user, + 'principaluri' => 'principals/'.$user, + '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}getctag' => 'LVPlan-'.$user.'-'.time(), + '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}supported-calendar-component-set' => new Sabre_CalDAV_Property_SupportedCalendarComponentSet(array('VEVENT','VTODO')), + '{DAV:}displayname' => 'LVPlan', + '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'description comes here', + '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => 'Europe/Vienna', + '{http://apple.com/ns/ical/}calendar-order' => '1', + '{http://apple.com/ns/ical/}calendar-color' => '#FF0000' + ); + $calendars[] = $calendar; + + return $calendars; + } + + /** + * Creates a new calendar for a principal. + * + * If the creation was a success, an id must be returned that can be used to reference + * this calendar in other methods, such as updateCalendar + * + * @param string $principalUri + * @param string $calendarUri + * @param array $properties + */ + public function createCalendar($principalUri,$calendarUri, array $properties) + { + throw new Sabre_DAV_Exception('Not Implemented'); + } + + /** + * Updates properties for a calendar. + * + * The mutations array uses the propertyName in clark-notation as key, + * and the array value for the property value. In the case a property + * should be deleted, the property value will be null. + * + * This method must be atomic. If one property cannot be changed, the + * entire operation must fail. + * + * If the operation was successful, true can be returned. + * If the operation failed, false can be returned. + * + * Deletion of a non-existant property is always succesful. + * + * Lastly, it is optional to return detailed information about any + * failures. In this case an array should be returned with the following + * structure: + * + * array( + * 403 => array( + * '{DAV:}displayname' => null, + * ), + * 424 => array( + * '{DAV:}owner' => null, + * ) + * ) + * + * In this example it was forbidden to update {DAV:}displayname. + * (403 Forbidden), which in turn also caused {DAV:}owner to fail + * (424 Failed Dependency) because the request needs to be atomic. + * + * @param string $calendarId + * @param array $mutations + * @return bool|array + */ + public function updateCalendar($calendarId, array $mutations) + { + + return false; + } + + /** + * Delete a calendar and all it's objects + * + * @param string $calendarId + * @return void + */ + public function deleteCalendar($calendarId) + { + throw new Sabre_DAV_Exception('Not Implemented'); + } + + public function getCalendarData($user, $objectUri=null) + { + $bn = new benutzer(); + if(!$bn->load($user)) + die('User invalid'); + + if(check_lektor($user)) + $type='lektor'; + else + $type='student'; + + // Stundenplanobjekt erzeugen + $stdplan = new wochenplan($type); + $stdplan->crlf="\n"; + + // Zusaetzliche Daten laden + if(!$stdplan->load_data($type,$user)) + { + die($stdplan->errormsg); + } + if(!is_null($objectUri)) + { + $unr = mb_substr($objectUri, mb_strpos($objectUri,'-')+1); + $dtstart = mb_substr($objectUri,0,mb_strpos($objectUri,'-')); + + //dtstart: 19700325T020000Z + $jahr = mb_substr($dtstart,0,4); + $monat = mb_substr($dtstart,4,2); + $tag = mb_substr($dtstart,6,2); + $stunde = mb_substr($dtstart,9,2); + $minute = mb_substr($dtstart,11,2); + $sekunde = mb_substr($dtstart,13,2); + $begin = mktime($stunde, $minute, $sekunde, $monat, $tag-1, $jahr); + $ende = mktime($stunde, $minute, $sekunde, $monat, $tag+1, $jahr); + error_log("getCalendarData unr: $unr dtstart: $dtstart"); + error_log($begin.'/'.$ende); + } + else + { + //TODO Datum eventuell anpassen derzeit nur aktuell +/- 6 Monate + $begin = mktime(0,0,0,date('m')-6,date('d'),date('Y')); + $ende = mktime(0,0,0,date('m')+6,date('d'),date('Y')); + } + $db_stpl_table = 'stundenplan'; + $i=0; + $data = array(); + // Kalender erstellen + while($begin<$ende) + { + error_log("while"); + $i++; + if(!date("w",$begin)) + $begin=jump_day($begin,1); + + $stdplan->init_stdplan(); + $datum=$begin; + $begin+=604800; // eine Woche + + // Stundenplan einer Woche laden + if(!$stdplan->load_week($datum,$db_stpl_table)) + { + die($stdplan->errormsg); + } + $val = $stdplan->draw_week_csv('return', LVPLAN_KATEGORIE); + if(!is_null($objectUri)) + { + foreach($val as $row) + { + error_log("search dtstart:".$dtstart." unr:".$unr); + error_log("row dtstart:".$row['dtstart']." unr:".$row['unr'][0]); + if($row['dtstart']==$dtstart && $row['unr'][0]==$unr) + { + error_log("found!"); + return $row; + } + } + } + else + $data=array_merge($data, $val); + } + + //$data.="\nEND:VCALENDAR"; + return $data; + } + public function makeCal($event) + { + return "BEGIN:VCALENDAR +VERSION:2.0 +PRODID:FH Technikum Wien +BEGIN:VTIMEZONE +TZID:Europe/Vienna +BEGIN:DAYLIGHT +TZOFFSETFROM:+0100 +RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU +DTSTART:19810329T020000 +TZNAME:GMT+02:00 +TZOFFSETTO:+0200 +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+0200 +RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU +DTSTART:19961027T030000 +TZNAME:GMT+01:00 +TZOFFSETTO:+0100 +END:STANDARD +END:VTIMEZONE\n".$event."\nEND:VCALENDAR"; + } + /** + * Returns all calendar objects within a calendar. + * + * Every item contains an array with the following keys: + * * id - unique identifier which will be used for subsequent updates + * * calendardata - The iCalendar-compatible calnedar data + * * uri - a unique key which will be used to construct the uri. This can be any arbitrary string. + * * lastmodified - a timestamp of the last modification time + * * etag - An arbitrary string, surrounded by double-quotes. (e.g.: + * ' "abcdef"') + * * calendarid - The calendarid as it was passed to this function. + * + * Note that the etag is optional, but it's highly encouraged to return for + * speed reasons. + * + * The calendardata is also optional. If it's not returned + * 'getCalendarObject' will be called later, which *is* expected to return + * calendardata. + * + * @param string $calendarId + * @return array + */ + public function getCalendarObjects($calendarId) + { + //$user = $this->getUser(); + $user = $calendarId; + $data = $this->getCalendarData($user); + + error_log("Caldav_Backend.php/getCalendarObjects($calendarId) data:".print_r($data,true)); + $return = array(); + foreach($data as $row) + { + $return[] = array("id"=>$row['UID'], + "calendardata"=>$this->makeCal($row['data']), + "uri"=>$row['dtstart'].'-'.$row['unr'][0], + "lastmodified"=>$row['updateamum'], + "etag"=>'"'.$row['UID'].'"', + "calendarid"=>$calendarId); + + } + return $return; + } + + /** + * Returns information from a single calendar object, based on it's object + * uri. + * + * The returned array must have the same keys as getCalendarObjects. The + * 'calendardata' object is required here though, while it's not required + * for getCalendarObjects. + * + * @param string $calendarId + * @param string $objectUri + * @return array + */ + public function getCalendarObject($calendarId,$objectUri) + { + error_log("Caldav_Backend.php/getCalendarObject($calendarId, $objectUri)"); + $user = $this->getUser(); + $data = $this->getCalendarData($user,$objectUri); + if(count($data)==0) + { + $ret=array("id"=>'', + "calendardata"=>'', + "uri"=>'', + "lastmodified"=>'', + "etag"=>'', + "calendarid"=>$calendarId); + } + else + { + $ret = array("id"=>$data['UID'], + "calendardata"=>$this->makeCal($data['data']), + "uri"=>'principals/'.$user.'/LVPlan/'.$data['dtstart'].'-'.$data['unr'][0], + "lastmodified"=>$data['updateamum'], + "etag"=>'"'.$data['UID'].'"', + "calendarid"=>$calendarId); + } + return $ret; + } + + /** + * Creates a new calendar object. + * + * @param string $calendarId + * @param string $objectUri + * @param string $calendarData + * @return void + */ + public function createCalendarObject($calendarId,$objectUri,$calendarData) + { + throw new Sabre_DAV_Exception('Not Implemented'); + } + + /** + * Updates an existing calendarobject, based on it's uri. + * + * @param string $calendarId + * @param string $objectUri + * @param string $calendarData + * @return void + */ + public function updateCalendarObject($calendarId,$objectUri,$calendarData) + { + throw new Sabre_DAV_Exception('Not Implemented'); + } + + /** + * Deletes an existing calendar object. + * + * @param string $calendarId + * @param string $objectUri + * @return void + */ + public function deleteCalendarObject($calendarId,$objectUri) + { + throw new Sabre_DAV_Exception('Not Implemented'); + } +} diff --git a/webdav/DMSdirectory.class.php b/webdav/DMSdirectory.class.php index bada2bf1e..45d5e7a88 100644 --- a/webdav/DMSdirectory.class.php +++ b/webdav/DMSdirectory.class.php @@ -204,7 +204,7 @@ class DMSDirectory extends Sabre_DAV_Collection $ext = '.'.mb_substr($name, $pos); else $ext =''; - $filename=uniqid(); + $filename=uniqid().$ext; $dms->version='0'; $dms->kategorie_kurzbz=$this->kategorie_kurzbz; $dms->insertamum=date('Y-m-d H:i:s'); diff --git a/webdav/DMSfile.class.php b/webdav/DMSfile.class.php index f24931f84..a6fda8267 100644 --- a/webdav/DMSfile.class.php +++ b/webdav/DMSfile.class.php @@ -191,15 +191,38 @@ class DMSFile extends Sabre_DAV_File $dms = new dms(); if($dms->load($this->dms_id)) { - $dms->updateamum = date('Y-m-d H:i:s'); - $dms->updatevon = $this->getUser(); - - file_put_contents(DMS_PATH.$dms->filename, $data); - $dms->save(false); - } - else - { - throw new Sabre_DAV_Exception_FileNotFound('Failed '.$dms->errormsg); + $dms->version = $dms->version++; + + $pos = mb_strrpos($dms->name,'.')+1; + if($pos>1) + $ext = '.'.mb_substr($dms->name, $pos); + else + $ext =''; + $filename=uniqid().$ext; + $dms->version++; + $dms->insertamum=date('Y-m-d H:i:s'); + $dms->insertvon = $this->getUser(); + $dms->filename = $filename; + + if($dms->save(true)) + { + if(file_put_contents(DMS_PATH.$filename, $data)) + { + if(!chgrp(DMS_PATH.$filename,'dms')) + echo 'CHGRP failed'; + if(!chmod(DMS_PATH.$filename, 0774)) + echo 'CHMOD failed'; + exec('sudo chown wwwrun '.$filename); + + $dms->save(false); + } + else + throw new Sabre_DAV_Exception_FileNotFound('Failed to Write File'); + } + else + { + throw new Sabre_DAV_Exception_FileNotFound('Failed '.$dms->errormsg); + } } } } diff --git a/webdav/Principal.php b/webdav/Principal.php new file mode 100644 index 000000000..a7181db08 --- /dev/null +++ b/webdav/Principal.php @@ -0,0 +1,172 @@ +auth = $auth; + } + + /** + * Liefert den eingeloggten User + */ + function getUser() + { + return $this->auth->getCurrentUser(); + } + + + /** + * Returns a list of principals based on a prefix. + * + * This prefix will often contain something like 'principals'. You are only + * expected to return principals that are in this base path. + * + * You are expected to return at least a 'uri' for every user, you can + * return any additional properties if you wish so. Common properties are: + * {DAV:}displayname + * {http://sabredav.org/ns}email-address - This is a custom SabreDAV + * field that's actualy injected in a number of other properties. If + * you have an email address, use this property. + * + * @param string $prefixPath + * @return array + */ + public function getPrincipalsByPrefix($prefixPath) + { + //$prefixPath = principals + error_log('Principal.php/getPrincipalsByPrefix('.$prefixPath.')'); + $principals = array(); + $user = $this->getUser(); + if($prefixPath=='principals') + { + $principals[] = array( + 'id' => 1, + 'uri' => 'principals/'.$user, + '{DAV:}displayname' => $user, + '{http://sabredav.org/ns}email-address' => $user.'@example.com', + ); + } + elseif($prefixPath=='principals/oesi') + { + $principals[] = array( + 'id' => 2, + 'uri' => 'principals/'.$user.'/calendar-proxy-read', + '{DAV:}displayname' => '', + '{http://sabredav.org/ns}email-address' => '', + ); + $principals[] = array( + 'id' => 3, + 'uri' => 'principals/'.$user.'/calendar-proxy-write', + '{DAV:}displayname' => '', + '{http://sabredav.org/ns}email-address' => '', + ); + } + + return $principals; + + } + + /** + * Returns a specific principal, specified by it's path. + * The returned structure should be the exact same as from + * getPrincipalsByPrefix. + * + * @param string $path + * @return array + */ + public function getPrincipalByPath($path) + { + //$path = principals/oesi + error_log('Principal.php/getPrincipalByPath('.$path.')'); + $user = $this->getUser(); + $result = array( + 'id' => $user, + 'uri' => 'principals/'.$user, + '{DAV:}displayname' => $user, + '{http://sabredav.org/ns}email-address' => $user.'@example.com', + ); + + //error_log("data:".print_r($result,true)); + return $result; + + } + + /** + * Returns the list of members for a group-principal + * + * @param string $principal + * @return array + */ + public function getGroupMemberSet($principal) + { + //error_log('Principal.php/getGroupMemberSet('.$principal.')'); + $result = array(); + return $result; + + } + + /** + * Returns the list of groups a principal is a member of + * + * @param string $principal + * @return array + */ + public function getGroupMembership($principal) + { + //$principal = username + $result = array(); + return $result; + + } + + /** + * Updates the list of group members for a group principal. + * + * The principals should be passed as a list of uri's. + * + * @param string $principal + * @param array $members + * @return void + */ + public function setGroupMemberSet($principal, array $members) + { + throw new Sabre_DAV_Exception('Not implemented'); + } + +} diff --git a/webdav/dms.php b/webdav/dms.php index 6325338cc..8ca2089dd 100644 --- a/webdav/dms.php +++ b/webdav/dms.php @@ -50,9 +50,9 @@ $server->setBaseUri($path); // The lock manager is reponsible for making sure users don't overwrite each others changes. Change 'data' to a different // directory, if you're storing your data somewhere else. -//$lockBackend = new Sabre_DAV_Locks_Backend_File('data/locks'); -//$lockPlugin = new Sabre_DAV_Locks_Plugin($lockBackend); -//$server->addPlugin($lockPlugin); +$lockBackend = new Sabre_DAV_Locks_Backend_File('data/locks'); +$lockPlugin = new Sabre_DAV_Locks_Plugin($lockBackend); +$server->addPlugin($lockPlugin); //GUI fuer Browser $browser = new Sabre_DAV_Browser_Plugin(); diff --git a/webdav/lvplan.php b/webdav/lvplan.php new file mode 100644 index 000000000..cac5c133c --- /dev/null +++ b/webdav/lvplan.php @@ -0,0 +1,47 @@ +setBaseUri($path); + +// Authentication plugin +$authPlugin = new Sabre_DAV_Auth_Plugin($authBackend,'SabreDAV'); +$server->addPlugin($authPlugin); + +// CalDAV plugin +$caldavPlugin = new Sabre_CalDAV_Plugin(); +$server->addPlugin($caldavPlugin); + +// ACL plugin +$aclPlugin = new Sabre_DAVACL_Plugin(); +$server->addPlugin($aclPlugin); + +// Support for html frontend +$browser = new Sabre_DAV_Browser_Plugin(); +$server->addPlugin($browser); + +// And off we go! +$server->exec(); +