From 028d4d2b07c50f2854d3cfc06f05855fa358ead3 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 19 Jan 2021 14:59:13 +0100 Subject: [locationinfo] Add generic ical backend Closes #3824 --- .../locationinfo/inc/icalcoursebackend.inc.php | 151 +++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 modules-available/locationinfo/inc/icalcoursebackend.inc.php (limited to 'modules-available/locationinfo/inc/icalcoursebackend.inc.php') diff --git a/modules-available/locationinfo/inc/icalcoursebackend.inc.php b/modules-available/locationinfo/inc/icalcoursebackend.inc.php new file mode 100644 index 00000000..fba0866c --- /dev/null +++ b/modules-available/locationinfo/inc/icalcoursebackend.inc.php @@ -0,0 +1,151 @@ +verifyCert = $verifyCert; + $this->verifyHostname = $verifyHostname; + if (strpos($location, '%ID%') === false) { + $location .= '%ID%'; + } + $this->location = $location; + $this->authMethod = $authMethod; + $this->user = $user; + $this->pass = $pass; + } + + /** + * @param int $roomId room id + * @param callable $errorFunc + * @return ICalEvent[]|null all events for this room in the range -7 days to +7 days, or NULL on error + */ + protected function downloadIcal($roomId) + { + if (!$this->isOK()) + return null; + if ($this->curlHandle === false) { + $this->curlHandle = curl_init(); + } + + $ical = new ICalParser(['filterDaysBefore' => 7, 'filterDaysAfter' => 7]); + $options = [ + CURLOPT_WRITEFUNCTION => function ($ch, $data) use ($ical) { + $ical->feedData($data); + return strlen($data); + }, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_SSL_VERIFYHOST => $this->verifyHostname ? 2 : 0, + CURLOPT_SSL_VERIFYPEER => $this->verifyCert ? 1 : 0, + CURLOPT_URL => str_replace('%ID%', $roomId, $this->location), + CURLOPT_TIMEOUT => 60, + CURLOPT_CONNECTTIMEOUT => 4, + ]; + if ($this->authMethod !== 'NONE' && defined('CURLAUTH_' . $this->authMethod)) { + $options[CURLOPT_HTTPAUTH] = constant('CURLAUTH_' . $this->authMethod); + $options[CURLOPT_USERPWD] = $this->user; + if (!empty($this->pass)) { + $options[CURLOPT_USERPWD] .= ':' . $this->pass; + } + } + + curl_setopt_array($this->curlHandle, $options); + + $curlRet = curl_exec($this->curlHandle); + if (!$curlRet) { + $this->addError('Curl error: ' . curl_error($this->curlHandle) . ' for ' . $roomId, false); + } + $ical->finish(); + if (!$ical->isValid()) { + if ($curlRet) { + $this->addError("Did not find a VCALENDAR in returned data for $roomId", false); + } + return null; + } + return $ical->events(); + } + + public function fetchSchedulesInternal($requestedRoomIds): array + { + if (empty($requestedRoomIds) || !$this->isOK()) { + return array(); + } + $tTables = []; + foreach ($requestedRoomIds as $roomId) { + $data = $this->downloadIcal($roomId); + if ($data === null) { + $this->addError("Downloading ical for $roomId failed", false); + continue; + } + foreach ($data as $event) { + $tTables[$roomId][] = array( + 'title' => $this->toTitle($event), + 'start' => $event->dtstart, + 'end' => $event->dtend, + 'cancelled' => false, // ??? How + ); + } + } + return $tTables; + } + + /** + * Get a usable title from either SUMMARY or DESCRIPTION + * @param ICalEvent $event + */ + private function toTitle($event): string + { + $title = $event->summary; + if (empty($title)) { + $title = $event->description; + } + if (empty($title)) { + $title = 'Unknown'; + } + return (string)preg_replace([',(\s*\s*|\r|\n|\\\r|\\\n)+,', '/\\\\([,;:])/'], ["\n", '$1'], $title); + } + + protected function isOK(): bool + { + if (empty($this->location)) { + $this->addError("Credentials are not set", true); + return false; + } + return true; + } + + public function __destruct() + { + if ($this->curlHandle !== false) { + curl_close($this->curlHandle); + } + } + +} \ No newline at end of file -- cgit v1.2.3-55-g7522