/** * Helper method to fetch free/busy data for the user and turn it into calendar data */ private function fetch_freebusy($limit_changed = null) { // ask kolab server first try { $request_config = array('store_body' => true, 'follow_redirects' => true); $request = libkolab::http_request(kolab_storage::get_freebusy_url($this->userdata['mail']), 'GET', $request_config); $response = $request->send(); // authentication required if ($response->getStatus() == 401) { $request->setAuth($this->rc->user->get_username(), $this->rc->decrypt($_SESSION['password'])); $response = $request->send(); } if ($response->getStatus() == 200) { $fbdata = $response->getBody(); } unset($request, $response); } catch (Exception $e) { rcube::raise_error(array('code' => 900, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, 'message' => "Error fetching free/busy information: " . $e->getMessage()), true, false); return false; } $statusmap = array('FREE' => 'free', 'BUSY' => 'busy', 'BUSY-TENTATIVE' => 'tentative', 'X-OUT-OF-OFFICE' => 'outofoffice', 'OOF' => 'outofoffice'); $titlemap = array('FREE' => $this->cal->gettext('availfree'), 'BUSY' => $this->cal->gettext('availbusy'), 'BUSY-TENTATIVE' => $this->cal->gettext('availtentative'), 'X-OUT-OF-OFFICE' => $this->cal->gettext('availoutofoffice')); // console('_fetch_freebusy', kolab_storage::get_freebusy_url($this->userdata['mail']), $fbdata); // parse free-busy information $count = 0; if ($fbdata) { $ical = $this->cal->get_ical(); $ical->import($fbdata); if ($fb = $ical->freebusy) { // consider 'changed >= X' queries if ($limit_changed && $fb['created'] && $fb['created'] < $limit_changed) { return 0; } foreach ($fb['periods'] as $tuple) { list($from, $to, $type) = $tuple; $event = array('id' => md5($this->id . $from->format('U') . '/' . $to->format('U')), 'calendar' => $this->id, 'changed' => $fb['created'] ?: new DateTime(), 'title' => $this->get_name() . ' ' . ($titlemap[$type] ?: $type), 'start' => $from, 'end' => $to, 'free_busy' => $statusmap[$type] ?: 'busy', 'className' => 'fc-type-freebusy', 'organizer' => array('email' => $this->userdata['mail'], 'name' => $this->userdata['displayname'])); // avoid duplicate entries $key = $this->time_key($event); if (!$this->timeindex[$key]) { $this->events[$event['id']] = $event; $this->timeindex[$key] = $event['id']; $count++; } } } } return $count; }
/** * Fetch free/busy information from a person within the given range */ public function get_freebusy_list($email, $start, $end) { if (empty($email)) { return false; } // map vcalendar fbtypes to internal values $fbtypemap = array('FREE' => calendar::FREEBUSY_FREE, 'BUSY-TENTATIVE' => calendar::FREEBUSY_TENTATIVE, 'X-OUT-OF-OFFICE' => calendar::FREEBUSY_OOF, 'OOF' => calendar::FREEBUSY_OOF); // ask kolab server first try { $request_config = array('store_body' => true, 'follow_redirects' => true); $request = libkolab::http_request(kolab_storage::get_freebusy_url($email), 'GET', $request_config); $response = $request->send(); // authentication required if ($response->getStatus() == 401) { $request->setAuth($this->rc->user->get_username(), $this->rc->decrypt($_SESSION['password'])); $response = $request->send(); } if ($response->getStatus() == 200) { $fbdata = $response->getBody(); } unset($request, $response); } catch (Exception $e) { PEAR::raiseError("Error fetching free/busy information: " . $e->getMessage()); } // get free-busy url from contacts if (!$fbdata) { $fburl = null; foreach ((array) $this->rc->config->get('autocomplete_addressbooks', 'sql') as $book) { $abook = $this->rc->get_address_book($book); if ($result = $abook->search(array('email'), $email, true, true, true)) { while ($contact = $result->iterate()) { if ($fburl = $contact['freebusyurl']) { $fbdata = @file_get_contents($fburl); break; } } } if ($fbdata) { break; } } } // parse free-busy information using Horde classes if ($fbdata) { $ical = $this->cal->get_ical(); $ical->import($fbdata); if ($fb = $ical->freebusy) { $result = array(); foreach ($fb['periods'] as $tuple) { list($from, $to, $type) = $tuple; $result[] = array($from->format('U'), $to->format('U'), isset($fbtypemap[$type]) ? $fbtypemap[$type] : calendar::FREEBUSY_BUSY); } // we take 'dummy' free-busy lists as "unknown" if (empty($result) && !empty($fb['comment']) && stripos($fb['comment'], 'dummy')) { return false; } // set period from $start till the begin of the free-busy information as 'unknown' if ($fb['start'] && ($fbstart = $fb['start']->format('U')) && $start < $fbstart) { array_unshift($result, array($start, $fbstart, calendar::FREEBUSY_UNKNOWN)); } // pad period till $end with status 'unknown' if ($fb['end'] && ($fbend = $fb['end']->format('U')) && $fbend < $end) { $result[] = array($fbend, $end, calendar::FREEBUSY_UNKNOWN); } return $result; } } return false; }