diff --git a/apps/calendar/css/style.css b/apps/calendar/css/style.css
index 1701a36a1f..373a456563 100644
--- a/apps/calendar/css/style.css
+++ b/apps/calendar/css/style.css
@@ -58,6 +58,10 @@ button.category{margin:0 3px;}
#event {padding: 0;margin: 0;margin-top:-5px}
+.calendar_share_dropdown{ display:block; position:absolute; z-index:100; width:16em; right:0; margin-right:7em; background:#F8F8F8; padding:1em;
+-moz-box-shadow:0 1px 1px #777; -webkit-box-shadow:0 1px 1px #777; box-shadow:0 1px 1px #777;
+-moz-border-radius:0 0 1em 1em; -webkit-border-radius:0 0 1em 1em; border-radius:0 0 1em 1em;}
+
.fc-list-table
{
margin: 10px;
diff --git a/apps/calendar/js/calendar.js b/apps/calendar/js/calendar.js
index 6b24fbc2f9..bbefa1bcf2 100644
--- a/apps/calendar/js/calendar.js
+++ b/apps/calendar/js/calendar.js
@@ -454,7 +454,7 @@ Calendar={
$('#calendar_holder').fullCalendar('removeEventSource', data.eventSource.url);
$('#calendar_holder').fullCalendar('addEventSource', data.eventSource);
if (calendarid == 'new'){
- $('#choosecalendar_dialog > table').append(' ');
+ $('#choosecalendar_dialog > table:first').append(' ');
}
}else{
$("#displayname_"+calendarid).css('background-color', '#FF2626');
@@ -493,6 +493,106 @@ Calendar={
left: -10000
});
}
+ },
+ Share:{
+ currentid: 'false',
+ idtype: '',
+ dropdown:function(userid, calid){
+ $('.calendar_share_dropdown').remove();
+ $('
').appendTo('#'+userid+'_'+calid);
+ $.get(OC.filePath('calendar', 'ajax', 'share.dropdown.php') + '?calid=' + calid, function(data){
+ $('#'+userid+'_'+calid+' > .calendar_share_dropdown').html(data);
+ $('#'+userid+'_'+calid+' > .calendar_share_dropdown').show('blind');
+ $('#share_user').chosen();
+ $('#share_group').chosen();
+ });
+ Calendar.UI.Share.currentid = calid;
+ Calendar.UI.Share.idtype = 'calendar';
+ },
+ share:function(id, idtype, sharewith, sharetype){
+ $.getJSON(OC.filePath('calendar', 'ajax', 'share.php'),{id:id, idtype:idtype, sharewith:sharewith, sharetype:sharetype}, function(data){
+ if(sharetype == 'public'){
+ $('#public_token').val(OC.linkTo('calendar', 'share.php?t=' + data.message));
+ $('#public_token').css('display', 'block');
+ }
+ });
+ },
+ unshare:function(id, idtype, sharewith, sharetype){
+ $.getJSON(OC.filePath('calendar', 'ajax', 'unshare.php'),{id:id, idtype:idtype, sharewith:sharewith, sharetype:sharetype}, function(){
+ if(sharetype == 'public'){
+ $('#public_token').val('');
+ $('#public_token').css('display', 'none');
+ }
+ });
+ },
+ changepermission:function(id, idtype, sharewith, sharetype, permission){
+ $.getJSON(OC.filePath('calendar', 'ajax', 'changepermission.php'),{id:id, idtype:idtype, sharewith: sharewith, sharetype:sharetype, permission: (permission?1:0)});
+ },
+ init:function(){
+ $('.calendar_share_dropdown').live('mouseleave', function(){
+ $('.calendar_share_dropdown').hide('blind', function(){
+ $('.calendar_share_dropdown').remove();
+ });
+ });
+ $('#share_user').live('change', function(){
+ if($('#sharewithuser_' + $('#share_user option:selected').text()).length == 0){
+ Calendar.UI.Share.share(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $('#share_user option:selected').text(), 'user');
+ var newitem = ' ' + $('#share_user option:selected').text() + ' ';
+ $('#sharewithuser_list').append(newitem);
+ $('#sharewithuser_' + $('#share_user option:selected').text() + ' > img').click(function(){
+ $('#share_user option[value="' + $(this).parent().text() + '"]').attr('disabled', 'false');
+ Calendar.UI.Share.unshare(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $(this).parent().text(), 'user' );
+ $(this).parent().remove();
+ });
+ $('#share_user option:selected').attr('disabled', 'disabled');
+ $("#share_user").trigger("liszt:updated");
+ }
+ });
+ $('#share_group').live('change', function(){
+ if($('#sharewithgroup_' + $('#share_group option:selected').text()).length == 0){
+ Calendar.UI.Share.share(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $('#share_group option:selected').text(), 'group');
+ var newitem = ' ' + $('#share_group option:selected').text() + ' ';
+ $('#sharewithgroup_list').append(newitem);
+ $('#sharewithgroup_' + $('#share_user option:selected').text() + ' > img').click(function(){
+ $('#share_group option[value="' + $(this).parent().text() + '"]').attr('disabled', 'false');
+ Calendar.UI.Share.unshare(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $(this).parent().text(), 'group');
+ $(this).parent().remove();
+ });
+ $('#share_group option:selected').attr('disabled', 'disabled');
+ $("#share_group").trigger("liszt:updated");
+ }
+ });
+ $('#sharewithuser_list > li > input:checkbox').live('change', function(){
+ Calendar.UI.Share.changepermission(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $(this).parent().text(), 'user', this.checked);
+ });
+ $('#sharewithgroup_list > li > input:checkbox').live('change', function(){
+ Calendar.UI.Share.changepermission(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $(this).parent().text(), 'group', this.checked);
+ });
+ $('#publish').live('change', function(){
+ if(this.checked == 1){
+ Calendar.UI.Share.share(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, '', 'public');
+ }else{
+ Calendar.UI.Share.unshare(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, '', 'public');
+ }
+ });
+ $('#sharewithuser_list').live('mouseenter', function(){
+ $('#sharewithuser_list > li > img').css('display', 'block');
+ $('#sharewithuser_list > li > input').css('visibility', 'visible');
+ });
+ $('#sharewithuser_list').live('mouseleave', function(){
+ $('#sharewithuser_list > li > img').css('display', 'none');
+ $('#sharewithuser_list > li > input').css('visibility', 'hidden');
+ });
+ $('#sharewithgroup_list').live('mouseenter', function(){
+ $('#sharewithgroup_list > li > img').css('display', 'block');
+ $('#sharewithgroup_list > li > input').css('visibility', 'visible');
+ });
+ $('#sharewithgroup_list').live('mouseleave', function(){
+ $('#sharewithgroup_list > li > img').css('display', 'none');
+ $('#sharewithgroup_list > li > input').css('visibility', 'hidden');
+ });
+ /*var permissions = (this.checked) ? 1 : 0;*/
+ }
}
}
}
@@ -732,4 +832,5 @@ $(document).ready(function(){
$('#datecontrol_right').click(function(){
$('#calendar_holder').fullCalendar('next');
});
+ Calendar.UI.Share.init();
});
diff --git a/apps/calendar/lib/share.php b/apps/calendar/lib/share.php
new file mode 100644
index 0000000000..bbc8770f65
--- /dev/null
+++ b/apps/calendar/lib/share.php
@@ -0,0 +1,163 @@
+
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+/*
+ * This class manages shared calendars
+ */
+class OC_Calendar_Share{
+ const CALENDAR = 'calendar';
+ const EVENT = 'event';
+ /*
+ * @brief: returns informations about all calendar or events which users are sharing with the user - userid
+ * @param: (string) $userid - id of the user
+ * @param: (string) $type - use const self::CALENDAR or self::EVENT
+ * @return: (array) $return - information about calendars
+ */
+ public static function allSharedwithuser($userid, $type){
+ $group_where = 'false';
+ $groups = OC_Group::getUserGroups($userid);
+ $i = 0;
+ foreach($groups as $group){
+ if($i == 0){
+ $group_where = '';
+ }else{
+ $group_where .= ' OR ';
+ }
+ $group_where .= ' (share = "' . $group . '" and sharetype = "group") ';
+ $i++;
+ }
+ $stmt = OC_DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . $type . ' WHERE (share = ? AND sharetype = "user") OR (' . $group_where . ')');
+ $result = $stmt->execute(array($userid));
+ $return = array();
+ while( $row = $result->fetchRow()){
+ $return[] = $row;
+ }
+ return $return;
+ }
+ /*
+ * @brief: returns all users a calendar / event is shared with
+ * @param: (int) id - id of the calendar / event
+ * @param: (string) $type - use const self::CALENDAR or self::EVENT
+ * @return: (array) $users - information about users a calendar / event is shared with
+ */
+ public static function allUsersSharedwith($id, $type){
+ $stmt = OC_DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . $type . ' WHERE ' . $type . 'id = ? ORDER BY share');
+ $result = $stmt->execute(array($id));
+ $users = array();
+ while( $row = $result->fetchRow()){
+ $users[] = $row;
+ }
+ return $users;
+ }
+ /*
+ * @brief: shares a calendar / event
+ * @param: (string) $owner - userid of the owner
+ * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public)
+ * @param: (string) $sharetype - type of sharing (can be: user/group/public)
+ * @param: (string) $id - id of the calendar / event
+ * @param: (string) $type - use const self::CALENDAR or self::EVENT
+ * @return (mixed) - token (if $sharetype == public) / bool (if $sharetype != public)
+ */
+ public static function share($owner, $share, $sharetype, $id, $type){
+ if(self::is_already_shared($owner, $share, $sharetype, $id, $type)){
+ return false;
+ }
+ switch($sharetype){
+ case 'user':
+ case 'group':
+ case 'public':
+ break;
+ default:
+ return false;
+ }
+ if($sharetype == 'public'){
+ $share = self::generate_token();
+ }
+ $stmt = OC_DB::prepare('INSERT INTO *PREFIX*calendar_share_' . $type . ' (owner,share,sharetype,' . $type . 'id,permissions' . (($type == self::CALENDAR)?', active':'') . ') VALUES(?,?,?,?,0' . (($type == self::CALENDAR)?', 1':'') . ')' );
+ $result = $stmt->execute(array($owner,$share,$sharetype,$id));
+ if($sharetype == 'public'){
+ return $share;
+ }else{
+ return true;
+ }
+ }
+ /*
+ * @brief: stops sharing a calendar / event
+ * @param: (string) $owner - userid of the owner
+ * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public)
+ * @param: (string) $sharetype - type of sharing (can be: user/group/public)
+ * @param: (string) $id - id of the calendar / event
+ * @param: (string) $type - use const self::CALENDAR or self::EVENT
+ * @return (bool)
+ */
+ public static function unshare($owner, $share, $sharetype, $id, $type){
+ $stmt = OC_DB::prepare('DELETE FROM *PREFIX*calendar_share_' . $type . ' WHERE owner = ? ' . (($sharetype != 'public')?'AND share = ?':'') . ' AND sharetype = ? AND ' . $type . 'id = ?');
+ if($sharetype != 'public'){
+ $stmt->execute(array($owner,$share,$sharetype,$id));
+ }else{
+ $stmt->execute(array($owner,$sharetype,$id));
+ }
+ return true;
+ }
+ /*
+ * @brief: changes the permission for a calendar / event
+ * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public)
+ * @param: (string) $sharetype - type of sharing (can be: user/group/public)
+ * @param: (string) $id - id of the calendar / event
+ * @param: (int) $permission - permission of user the calendar / event is shared with (if $sharetype == public then $permission = 0)
+ * @param: (string) $type - use const self::CALENDAR or self::EVENT
+ * @return (bool)
+ */
+ public static function changepermission($share, $sharetype, $id, $permission, $type){
+ if($sharetype == 'public' && $permission == 1){
+ $permission = 0;
+ }
+ $stmt = OC_DB::prepare('UPDATE *PREFIX*calendar_share_' . $type . ' SET permissions = ? WHERE share = ? AND sharetype = ? AND ' . $type . 'id = ?');
+ $stmt->execute(array($permission, $share, $sharetype, $id));
+ return true;
+ }
+ /*
+ * @brief: generates a token for public calendars / events
+ * @return: (string) $token
+ */
+ private static function generate_token($id, $type){
+ $uniqid = uniqid();
+ if($type == self::CALENDAR){
+ $events = OC_Calendar_Objects::all($id);
+ $string = '';
+ foreach($events as $event){
+ $string .= $event['calendardata'];
+ }
+ }else{
+ $string = OC_Calendar_Object::find($id);
+ }
+ $string = sha1($string);
+ $id = sha1($id);
+ $array = array($uniqid,$string,$id);
+ shuffle($array);
+ $string = implode('', $array);
+ $token = md5($string);
+ return substr($token, rand(0,16), 15);
+ }
+ /*
+ * @brief: checks if it is already shared
+ * @param: (string) $owner - userid of the owner
+ * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public)
+ * @param: (string) $sharetype - type of sharing (can be: user/group/public)
+ * @param: (string) $id - id of the calendar / event
+ * @param: (string) $type - use const self::CALENDAR or self::EVENT
+ * @return (bool)
+ */
+ private static function is_already_shared($owner, $share, $sharetype, $id, $type){
+ $stmt = OC_DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . $type . ' WHERE owner = ? AND share = ? AND sharetype = ? AND ' . $type . 'id = ?');
+ $result = $stmt->execute(array($owner, $share, $sharetype, $id));
+ if($result->numRows() > 0){
+ return true;
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/apps/calendar/share.php b/apps/calendar/share.php
new file mode 100644
index 0000000000..8d1c8b69c3
--- /dev/null
+++ b/apps/calendar/share.php
@@ -0,0 +1 @@
+
diff --git a/apps/calendar/templates/part.choosecalendar.php b/apps/calendar/templates/part.choosecalendar.php
index 86f09d6207..21da5dd7cd 100644
--- a/apps/calendar/templates/part.choosecalendar.php
+++ b/apps/calendar/templates/part.choosecalendar.php
@@ -1,4 +1,5 @@
">
+
t('Your calendars'); ?>:
+
t('Shared calendars'); ?>:
+
+';
+ $tmpl = new OC_Template('calendar', 'part.choosecalendar.rowfields.shared');
+ $tmpl->assign('share', $share[$i]);
+ $tmpl->printpage();
+ echo '';
+}
+?>
+
' . $l->t('No shared calendars') . ' ';
+}
+?>
+
\ No newline at end of file
diff --git a/apps/calendar/templates/part.choosecalendar.rowfields.php b/apps/calendar/templates/part.choosecalendar.rowfields.php
index a789be45a4..156d50bc48 100644
--- a/apps/calendar/templates/part.choosecalendar.rowfields.php
+++ b/apps/calendar/templates/part.choosecalendar.rowfields.php
@@ -1,4 +1,8 @@
";
- echo "" . $_['calendar']["displayname"] . " ";
- echo "t("CalDav Link") . "\" class=\"action\"> t("Download") . "\" class=\"action\"> t("Edit") . "\" class=\"action\" onclick=\"Calendar.UI.Calendar.edit(this, " . $_['calendar']["id"] . ");\"> t("Delete") . "\" class=\"action\"> ";
+echo ' ';
+echo '' . $_['calendar']['displayname'] . ' ';
+echo ' ';
+echo ' ';
+echo ' ';
+echo ' ';
+echo ' ';
diff --git a/apps/calendar/templates/part.choosecalendar.rowfields.shared.php b/apps/calendar/templates/part.choosecalendar.rowfields.shared.php
new file mode 100644
index 0000000000..2e1210415b
--- /dev/null
+++ b/apps/calendar/templates/part.choosecalendar.rowfields.shared.php
@@ -0,0 +1,4 @@
+ ';
+echo '' . $_['share']['calendar']['displayname'] . ' ';
+echo '' . $l->t('shared with you by') . ' ' . $_['share']['owner'] . ' ';
\ No newline at end of file
diff --git a/apps/calendar/templates/part.eventform.php b/apps/calendar/templates/part.eventform.php
index 1b7aa1acb4..4a9a467549 100644
--- a/apps/calendar/templates/part.eventform.php
+++ b/apps/calendar/templates/part.eventform.php
@@ -231,6 +231,6 @@
t('Summary'); ?>:
-
-
-
\ No newline at end of file
+//Alarm
+//Attendees
+//Share
\ No newline at end of file
diff --git a/apps/calendar/templates/share.dropdown.php b/apps/calendar/templates/share.dropdown.php
new file mode 100644
index 0000000000..6a944f1f09
--- /dev/null
+++ b/apps/calendar/templates/share.dropdown.php
@@ -0,0 +1,71 @@
+
+t('Users');?>:
+
+
+
+
+
+t('Groups');?>:
+
+
+
+
+
+
+ >t('make public'); ?>
+
+
\ No newline at end of file