1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/agendav_ynh.git synced 2024-09-03 20:36:12 +02:00
agendav_ynh/sources/web/application/controllers/calendar.php
2014-01-07 17:53:08 +01:00

443 lines
15 KiB
PHP

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/*
* Copyright 2011-2012 Jorge López Pérez <jorge@adobo.org>
*
* This file is part of AgenDAV.
*
* AgenDAV 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
* any later version.
*
* AgenDAV 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 AgenDAV. If not, see <http://www.gnu.org/licenses/>.
*/
class Calendar extends CI_Controller {
private $calendar_colors;
private $prefs;
function __construct() {
parent::__construct();
if (!$this->auth->is_authenticated()) {
$this->extended_logs->message('INFO',
'Anonymous access attempt to '
. uri_string());
$this->output->set_status_header('401');
$this->output->_display();
die();
}
$this->calendar_colors = $this->config->item('calendar_colors');
$this->prefs =
Preferences::singleton($this->session->userdata('prefs'));
$this->load->library('caldav');
$this->output->set_content_type('application/json');
}
function index() {
}
/**
* Retrieve a list of calendars (owned by current user or shared by
* other users with the current one)
*/
function all() {
$arr_calendars = $this->caldav->all_user_calendars(
$this->auth->get_user(),
$this->auth->get_passwd());
// Hide calendars user doesn't want to be shown
$hidden_calendars = $this->prefs->hidden_calendars;
if ($hidden_calendars !== null) {
foreach ($arr_calendars as $c => $data) {
if (isset($hidden_calendars[$c])) {
unset($arr_calendars[$c]);
}
}
}
// Default calendar
$default_calendar = $this->prefs->default_calendar;
if ($default_calendar !== null &&
isset($arr_calendars[$default_calendar])) {
$arr_calendars[$default_calendar]->default_calendar = TRUE;
} elseif (count($arr_calendars) > 0) {
$first = array_shift(array_keys($arr_calendars));
$arr_calendars[$first]->default_calendar = TRUE;
}
// Add public URL
if ($this->config->item('show_public_caldav_url')) {
foreach ($arr_calendars as $calendar) {
$calendar->public_url =
$this->caldav->build_calendar_url(
$this->auth->get_user(),
$calendar->calendar);
}
}
// Save calendars into session (avoid multiple CalDAV queries when
// editing/adding events)
$this->session->set_userdata('available_calendars', $arr_calendars);
$this->output->set_output(json_encode($arr_calendars));
}
/**
* Creates a calendar
*/
function create() {
$displayname = $this->input->post('displayname', TRUE);
$calendar_color = $this->input->post('calendar_color', TRUE);
// Display name
if (empty($displayname)) {
$this->_throw_exception($this->i18n->_('messages',
'error_calname_missing'));
}
// Default color
if (empty($calendar_color)) {
$calendar_color = '#' . $this->calendar_color[0];
}
// Get current own calendars
$current_calendars = $this->caldav->get_own_calendars(
$this->auth->get_user(),
$this->auth->get_passwd()
);
// Generate internal calendar name
do {
$calendar = $this->icshelper->generate_guid();
} while (isset($current_calendars[$calendar]));
// Add transparency to color
$calendar_color = $this->caldav->_rgb2rgba($calendar_color);
// Calendar properties
$props = array(
'displayname' => $displayname,
'color' => $calendar_color,
);
$res = $this->caldav->mkcalendar(
$this->auth->get_user(),
$this->auth->get_passwd(),
$calendar,
$props);
if ($res !== TRUE) {
$this->_throw_error($this->i18n->_('messages', $res[0], $res[1]));
} else {
$this->_throw_success();
}
}
/**
* Deletes a calendar
*/
function delete() {
$calendar = $this->input->post('calendar');
if ($calendar === FALSE) {
$this->extended_logs->message('ERROR',
'Call to delete_calendar() without calendar');
$this->_throw_error($this->i18n->_('messages',
'error_interfacefailure'));
}
// Get current own calendars and check if this one exists
$current_calendars = $this->caldav->get_own_calendars(
$this->auth->get_user(),
$this->auth->get_passwd()
);
if (!isset($current_calendars[$calendar])) {
$this->extended_logs->message('INTERNALS',
'Call to delete_calendar() with non-existent calendar ('
.$calendar.')');
$this->_throw_exception(
$this->i18n->_('messages', 'error_calendarnotfound',
array('%calendar' => $p['calendar'])));
}
// Delete calendar shares (if any), even if calendar sharing is not
// enabled
$shares =
$this->shared_calendars->get_shared_from($this->auth->get_user());
if (isset($shares[$calendar])) {
$this_calendar_shares = array_values($shares[$calendar]);
foreach ($this_calendar_shares as $k => $data) {
$this->shared_calendars->remove($data['sid']);
}
}
$replace_pattern = '/^' . $this->auth->get_user() . ':/';
$internal_calendar = preg_replace($replace_pattern, '', $calendar);
// Proceed to remove calendar from CalDAV server
$res = $this->caldav->delete_resource(
$this->auth->get_user(),
$this->auth->get_passwd(),
'',
$internal_calendar,
null);
if ($res === TRUE) {
$this->_throw_success($calendar);
} else {
// There was an error
$this->_throw_exception($this->i18n->_('messages', $res[0],
$res[1]));
}
}
/**
* Modifies a calendar
*/
function modify() {
$is_sharing_enabled =
$this->config->item('enable_calendar_sharing');
$calendar = $this->input->post('calendar');
$displayname = $this->input->post('displayname');
$calendar_color = $this->input->post('calendar_color');
$is_shared_calendar = $this->input->post('is_shared_calendar');
// Will be only used for shared calendars
$sid = null;
// In case this calendar is owned by current user, this will contain
// a list of users he/she wants to share the calendar with
$share_with = $this->input->post('share_with');
if ($calendar === FALSE || $displayname === FALSE || $calendar_color ===
FALSE || ($is_sharing_enabled && $is_shared_calendar === FALSE)) {
$this->extended_logs->message('ERROR',
'Call to modify_calendar() with incomplete parameters');
$this->_throw_error($this->i18n->_('messages',
'error_interfacefailure'));
}
// Calculate boolean value for is_shared_calendar
$is_shared_calendar = ($is_shared_calendar === FALSE ?
FALSE :
($is_shared_calendar == 'true'));
// Check if calendar is valid
if (!$this->caldav->is_valid_calendar(
$this->auth->get_user(),
$this->auth->get_passwd(),
$calendar)) {
$this->extended_logs->message('INTERNALS',
'Call to modify_calendar() with non-existent calendar '
.' or with access forbidden ('
.$calendar.')');
$this->_throw_exception(
$this->i18n->_('messages', 'error_calendarnotfound',
array('%calendar' => $calendar)));
}
// Retrieve ID on shared calendars table
if ($is_sharing_enabled && $is_shared_calendar) {
$current_calendar_shares =
$this->shared_calendars->users_with_access_to($calendar);
$current_user = $this->auth->get_user();
foreach ($current_calendar_shares as $sh) {
if ($sh['username'] == $current_user) {
$sid = $sh['sid'];
break;
}
}
if ($sid === null) {
$this->extended_logs->message('ERROR',
'Call to modify_calendar() with shared calendar, '
.'but no sid was found');
$this->_throw_error($this->i18n->_('messages',
'error_interfacefailure'));
}
}
// Add transparency to color
$calendar_color = $this->caldav->_rgb2rgba($calendar_color);
// Calendar properties
$props = array(
'displayname' => $displayname,
'color' => $calendar_color,
);
// Proceed to modify calendar
if (!$is_shared_calendar) {
$replace_pattern = '/^' . $this->auth->get_user() . ':/';
$internal_calendar = preg_replace($replace_pattern, '', $calendar);
$res = $this->caldav->proppatch(
$this->auth->get_user(),
$this->auth->get_passwd(),
$internal_calendar,
$props);
} else if ($is_sharing_enabled) {
// If this a shared calendar, store settings locally
$success = $this->shared_calendars->store($sid,
null,
$calendar,
$this->auth->get_user(),
$props);
if ($success === FALSE) {
$this->_throw_exception($this->i18n->_('messages',
'error_internal'));
} else {
$res = TRUE;
}
} else {
// Tried to modify a shared calendar when sharing is disabled
$this->extended_logs->message('ERROR',
'Tried to modify the shared calendar ' . $calendar
.' when calendar sharing is disabled');
$this->_throw_exception($this->i18n->_('messages',
'error_interfacefailure'));
}
// Set ACLs
if ($is_sharing_enabled && $res === TRUE && !$is_shared_calendar) {
$set_shares = array();
if (is_array($share_with) && isset($share_with['sid'])
&& isset($share_with['username'])
&& isset($share_with['write_access'])) {
$num_shares = count($share_with['sid']);
for ($i=0;$i<$num_shares;$i++) {
$exists_username =
isset($share_with['username'][$i]);
$exists_write_access =
isset($share_with['write_access'][$i]);
if (!$exists_username || !$exists_write_access) {
$this->extended_logs->message('ERROR',
'Ignoring incomplete share row ('.$i.') attributes'
.' on calendar modification: '
. serialize($share_with));
} else {
$new_share = array(
'username' => $share_with['username'][$i],
'write_access' => $share_with['write_access'][$i],
);
if (!empty($share_with['sid'][$i])) {
$new_share['sid'] = $share_with['sid'][$i];
}
$set_shares[] = $new_share;
}
}
}
$res = $this->caldav->setacl(
$this->auth->get_user(),
$this->auth->get_passwd(),
$internal_calendar,
$set_shares);
// Update shares on database
if ($res === TRUE) {
$current_shares =
$this->shared_calendars->users_with_access_to($calendar);
$orig_sids = array();
foreach ($current_shares as $db_share_row) {
$orig_sids[$db_share_row['sid']] = TRUE;
}
$updated_sids = array();
foreach ($set_shares as $share) {
$this_sid = isset($share['sid']) ?
$share['sid'] : null;
$this->shared_calendars->store(
$this_sid,
$this->auth->get_user(),
$internal_calendar,
$share['username'],
null, // Preserve options
$share['write_access']);
if (!is_null($this_sid)) {
$updated_sids[$this_sid] = true;
}
}
// Removed shares
foreach (array_keys($orig_sids) as $sid) {
if (!isset($updated_sids[$sid])) {
$this->shared_calendars->remove($sid);
}
}
}
}
if ($res === TRUE) {
$this->_throw_success();
} else {
// There was an error
$this->_throw_exception($this->i18n->_('messages', $res[0],
$res[1]));
}
}
/**
* Throws an exception message
*/
function _throw_exception($message) {
$this->output->set_output(json_encode(array(
'result' => 'EXCEPTION',
'message' => $message)));
$this->output->_display();
die();
}
/**
* Throws an error message
*/
function _throw_error($message) {
$this->output->set_output(json_encode(array(
'result' => 'ERROR',
'message' => $message)));
$this->output->_display();
die();
}
/**
* Throws a success message
*/
function _throw_success($message = '') {
$this->output->set_output(json_encode(array(
'result' => 'SUCCESS',
'message' => $message)));
$this->output->_display();
die();
}
}