diff --git a/apps/admin_migrate/templates/settings.php b/apps/admin_migrate/templates/settings.php index 91e305074e4..f81c9199ece 100644 --- a/apps/admin_migrate/templates/settings.php +++ b/apps/admin_migrate/templates/settings.php @@ -6,9 +6,9 @@

What would you like to export?

- ownCloud instance (suitable for import )
- ownCloud system files
- Just user files
+ ownCloud instance (suitable for import )
+ ownCloud system files
+ Just user files
diff --git a/apps/bookmarks/templates/bookmarklet.php b/apps/bookmarks/templates/bookmarklet.php index f7074462a79..a2ca0bba0e3 100644 --- a/apps/bookmarks/templates/bookmarklet.php +++ b/apps/bookmarks/templates/bookmarklet.php @@ -3,6 +3,6 @@ function createBookmarklet() { $l = OC_L10N::get('bookmarks'); echo '' . $l->t('Drag this to your browser bookmarks and click it, when you want to bookmark a webpage quickly:') . '' - . '' + . '' . $l->t('Read later') . ''; } diff --git a/apps/calendar/ajax/changeview.php b/apps/calendar/ajax/changeview.php index 707c8c59ebf..736a5625530 100644 --- a/apps/calendar/ajax/changeview.php +++ b/apps/calendar/ajax/changeview.php @@ -1,12 +1,10 @@ + * Copyright (c) 2012 Georg Ehrke * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. */ - - OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('calendar'); $view = $_GET['v']; diff --git a/apps/calendar/ajax/event/delete.php b/apps/calendar/ajax/event/delete.php index 49b740656de..3b726651641 100644 --- a/apps/calendar/ajax/event/delete.php +++ b/apps/calendar/ajax/event/delete.php @@ -11,7 +11,10 @@ OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('calendar'); $id = $_POST['id']; -$event_object = OC_Calendar_App::getEventObject($id); +$access = OC_Calendar_App::getaccess($id, OC_Calendar_App::EVENT); +if($access != 'owner' && $access != 'rw'){ + OC_JSON::error(array('message'=>'permission denied')); + exit; +} $result = OC_Calendar_Object::delete($id); OC_JSON::success(); -?> diff --git a/apps/calendar/ajax/event/edit.form.php b/apps/calendar/ajax/event/edit.form.php index 1634e7ea416..ec50b78be6f 100644 --- a/apps/calendar/ajax/event/edit.form.php +++ b/apps/calendar/ajax/event/edit.form.php @@ -14,7 +14,13 @@ if(!OC_USER::isLoggedIn()) { OC_JSON::checkAppEnabled('calendar'); $id = $_GET['id']; -$data = OC_Calendar_App::getEventObject($id); +$data = OC_Calendar_App::getEventObject($id, true, true); + +if(!$data){ + OC_JSON::error(array('data' => array('message' => self::$l10n->t('Wrong calendar')))); + exit; +} +$access = OC_Calendar_App::getaccess($id, OC_Calendar_Share::EVENT); $object = OC_VObject::parse($data['calendardata']); $vevent = $object->VEVENT; @@ -182,8 +188,12 @@ if($data['repeating'] == 1){ }else{ $repeat['repeat'] = 'doesnotrepeat'; } - -$calendar_options = OC_Calendar_Calendar::allCalendars(OC_User::getUser()); +if($access == 'owner'){ + $calendar_options = OC_Calendar_Calendar::allCalendars(OC_User::getUser()); +}else{ + $calendar_options = array(OC_Calendar_App::getCalendar($data['calendarid'], false)); +} +$category_options = OC_Calendar_App::getCategoryOptions(); $repeat_options = OC_Calendar_App::getRepeatOptions(); $repeat_end_options = OC_Calendar_App::getEndOptions(); $repeat_month_options = OC_Calendar_App::getMonthOptions(); @@ -195,8 +205,14 @@ $repeat_bymonth_options = OC_Calendar_App::getByMonthOptions(); $repeat_byweekno_options = OC_Calendar_App::getByWeekNoOptions(); $repeat_bymonthday_options = OC_Calendar_App::getByMonthDayOptions(); -$tmpl = new OC_Template('calendar', 'part.editevent'); -$tmpl->assign('id', $id); +if($access == 'owner' || $access == 'rw'){ + $tmpl = new OC_Template('calendar', 'part.editevent'); +}elseif($access == 'r'){ + $tmpl = new OC_Template('calendar', 'part.showevent'); +} + +$tmpl->assign('eventid', $id); +$tmpl->assign('access', $access); $tmpl->assign('lastmodified', $lastmodified); $tmpl->assign('calendar_options', $calendar_options); $tmpl->assign('repeat_options', $repeat_options); diff --git a/apps/calendar/ajax/event/edit.php b/apps/calendar/ajax/event/edit.php index 53912cb4c93..172488f6241 100644 --- a/apps/calendar/ajax/event/edit.php +++ b/apps/calendar/ajax/event/edit.php @@ -10,21 +10,34 @@ OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('calendar'); +$id = $_POST['id']; + +if(!array_key_exists('calendar', $_POST)){ + $cal = OC_Calendar_Object::getCalendarid($id); + $_POST['calendar'] = $cal; +}else{ + $cal = $_POST['calendar']; +} + +$access = OC_Calendar_App::getaccess($id, OC_Calendar_App::EVENT); +if($access != 'owner' && $access != 'rw'){ + OC_JSON::error(array('message'=>'permission denied')); + exit; +} + $errarr = OC_Calendar_Object::validateRequest($_POST); if($errarr){ //show validate errors OC_JSON::error($errarr); exit; }else{ - $id = $_POST['id']; - $cal = $_POST['calendar']; - $data = OC_Calendar_App::getEventObject($id); + $data = OC_Calendar_App::getEventObject($id, false, false); $vcalendar = OC_VObject::parse($data['calendardata']); OC_Calendar_App::isNotModified($vcalendar->VEVENT, $_POST['lastmodified']); OC_Calendar_Object::updateVCalendarFromRequest($_POST, $vcalendar); - $result = OC_Calendar_Object::edit($id, $vcalendar->serialize()); + OC_Calendar_Object::edit($id, $vcalendar->serialize()); if ($data['calendarid'] != $cal) { OC_Calendar_Object::moveToCalendar($id, $cal); } diff --git a/apps/calendar/ajax/event/move.php b/apps/calendar/ajax/event/move.php index bfebefb8fe0..0552c7bbc5b 100644 --- a/apps/calendar/ajax/event/move.php +++ b/apps/calendar/ajax/event/move.php @@ -9,15 +9,18 @@ OC_JSON::checkLoggedIn(); $id = $_POST['id']; - -$vcalendar = OC_Calendar_App::getVCalendar($id); +$access = OC_Calendar_App::getaccess($id, OC_Calendar_App::EVENT); +if($access != 'owner' && $access != 'rw'){ + OC_JSON::error(array('message'=>'permission denied')); + exit; +} +$vcalendar = OC_Calendar_App::getVCalendar($id, false, false); $vevent = $vcalendar->VEVENT; $allday = $_POST['allDay']; $delta = new DateInterval('P0D'); $delta->d = $_POST['dayDelta']; $delta->i = $_POST['minuteDelta']; - OC_Calendar_App::isNotModified($vevent, $_POST['lastmodified']); $dtstart = $vevent->DTSTART; diff --git a/apps/calendar/ajax/event/new.form.php b/apps/calendar/ajax/event/new.form.php index 2e03c02af27..62087e9a817 100644 --- a/apps/calendar/ajax/event/new.form.php +++ b/apps/calendar/ajax/event/new.form.php @@ -44,6 +44,7 @@ $repeat_byweekno_options = OC_Calendar_App::getByWeekNoOptions(); $repeat_bymonthday_options = OC_Calendar_App::getByMonthDayOptions(); $tmpl = new OC_Template('calendar', 'part.newevent'); +$tmpl->assign('access', 'owner'); $tmpl->assign('calendar_options', $calendar_options); $tmpl->assign('repeat_options', $repeat_options); $tmpl->assign('repeat_month_options', $repeat_month_options); diff --git a/apps/calendar/ajax/event/resize.php b/apps/calendar/ajax/event/resize.php index 9a9d37ff3d4..593835d86c5 100644 --- a/apps/calendar/ajax/event/resize.php +++ b/apps/calendar/ajax/event/resize.php @@ -10,7 +10,13 @@ OC_JSON::checkLoggedIn(); $id = $_POST['id']; -$vcalendar = OC_Calendar_App::getVCalendar($id); +$access = OC_Calendar_App::getaccess($id, OC_Calendar_App::EVENT); +if($access != 'owner' && $access != 'rw'){ + OC_JSON::error(array('message'=>'permission denied')); + exit; +} + +$vcalendar = OC_Calendar_App::getVCalendar($id, false, false); $vevent = $vcalendar->VEVENT; $delta = new DateInterval('P0D'); @@ -27,6 +33,6 @@ unset($vevent->DURATION); $vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Element_DateTime::UTC); $vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC); -$result = OC_Calendar_Object::edit($id, $vcalendar->serialize()); +OC_Calendar_Object::edit($id, $vcalendar->serialize()); $lastmodified = $vevent->__get('LAST-MODIFIED')->getDateTime(); OC_JSON::success(array('lastmodified'=>(int)$lastmodified->format('U'))); diff --git a/apps/calendar/ajax/events.php b/apps/calendar/ajax/events.php index 0cfee0dbdc1..3aa487fd231 100755 --- a/apps/calendar/ajax/events.php +++ b/apps/calendar/ajax/events.php @@ -1,6 +1,6 @@ + * Copyright (c) 2011, 2012 Georg Ehrke * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. @@ -8,102 +8,19 @@ require_once('when/When.php'); -$l = OC_L10N::get('calendar'); -$unnamed = $l->t('unnamed'); -function create_return_event($event, $vevent){ - $return_event = array(); - global $unnamed; - $return_event['id'] = (int)$event['id']; - $return_event['title'] = htmlspecialchars(($event['summary']!=NULL || $event['summary'] != '')?$event['summary']: $unnamed); - $return_event['description'] = isset($vevent->DESCRIPTION)?htmlspecialchars($vevent->DESCRIPTION->value):''; - $last_modified = $vevent->__get('LAST-MODIFIED'); - if ($last_modified){ - $lastmodified = $last_modified->getDateTime()->format('U'); - }else{ - $lastmodified = 0; - } - $return_event['lastmodified'] = (int)$lastmodified; - return $return_event; -} OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('calendar'); -if(version_compare(PHP_VERSION, '5.3.0', '>=')){ - $start = DateTime::createFromFormat('U', $_GET['start']); - $end = DateTime::createFromFormat('U', $_GET['end']); -}else{ - $start = new DateTime('@' . $_GET['start']); - $end = new DateTime('@' . $_GET['end']); -} +$start = (version_compare(PHP_VERSION, '5.3.0', '>='))?DateTime::createFromFormat('U', $_GET['start']):new DateTime('@' . $_GET['start']); +$end = (version_compare(PHP_VERSION, '5.3.0', '>='))?DateTime::createFromFormat('U', $_GET['end']):new DateTime('@' . $_GET['end']); -$calendar_id = $_GET['calendar_id']; -if (is_numeric($calendar_id)) { - $calendar = OC_Calendar_App::getCalendar($calendar_id); - OC_Response::enableCaching(0); - OC_Response::setETagHeader($calendar['ctag']); - $events = OC_Calendar_Object::allInPeriod($calendar_id, $start, $end); -} else { - $events = array(); - OC_Hook::emit('OC_Calendar', 'getEvents', array('calendar_id' => $calendar_id, 'events' => &$events)); -} +$events = OC_Calendar_App::getrequestedEvents($_GET['calendar_id'], $start, $end); -$user_timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); -$return = array(); +$output = array(); foreach($events as $event){ - if (isset($event['calendardata'])) { - $object = OC_VObject::parse($event['calendardata']); - $vevent = $object->VEVENT; - } else { - $vevent = $event['vevent']; - } - - $return_event = create_return_event($event, $vevent); - - $dtstart = $vevent->DTSTART; - $start_dt = $dtstart->getDateTime(); - $dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent); - $end_dt = $dtend->getDateTime(); - if ($dtstart->getDateType() == Sabre_VObject_Element_DateTime::DATE){ - $return_event['allDay'] = true; - }else{ - $return_event['allDay'] = false; - $start_dt->setTimezone(new DateTimeZone($user_timezone)); - $end_dt->setTimezone(new DateTimeZone($user_timezone)); - } - - //Repeating Events - if($event['repeating'] == 1){ - $duration = (double) $end_dt->format('U') - (double) $start_dt->format('U'); - $r = new When(); - $r->recur($start_dt)->rrule((string) $vevent->RRULE); - while($result = $r->next()){ - if($result < $start){ - continue; - } - if($result > $end){ - break; - } - if($return_event['allDay'] == true){ - $return_event['start'] = $result->format('Y-m-d'); - $return_event['end'] = date('Y-m-d', $result->format('U') + --$duration); - }else{ - $return_event['start'] = $result->format('Y-m-d H:i:s'); - $return_event['end'] = date('Y-m-d H:i:s', $result->format('U') + $duration); - } - $return[] = $return_event; - } - }else{ - if($return_event['allDay'] == true){ - $return_event['start'] = $start_dt->format('Y-m-d'); - $end_dt->modify('-1 sec'); - $return_event['end'] = $end_dt->format('Y-m-d'); - }else{ - $return_event['start'] = $start_dt->format('Y-m-d H:i:s'); - $return_event['end'] = $end_dt->format('Y-m-d H:i:s'); - } - $return[] = $return_event; - } + $output[] = OC_Calendar_App::generateEventOutput($event, $start, $end); + } -OC_JSON::encodedPrint($return); +OC_JSON::encodedPrint($output); ?> diff --git a/apps/calendar/ajax/import/import.php b/apps/calendar/ajax/import/import.php index 95294948f75..5848cac448d 100644 --- a/apps/calendar/ajax/import/import.php +++ b/apps/calendar/ajax/import/import.php @@ -7,11 +7,11 @@ */ //check for calendar rights or create new one ob_start(); - OC_JSON::checkLoggedIn(); OC_Util::checkAppEnabled('calendar'); -$nl = "\n\r"; -$progressfile = OC::$APPSROOT . '/apps/calendar/import_tmp/' . md5(session_id()) . '.txt'; +$nl="\r\n"; +$comps = array('VEVENT'=>true, 'VTODO'=>true, 'VJOURNAL'=>true); +$progressfile = 'import_tmp/' . md5(session_id()) . '.txt'; if(is_writable('import_tmp/')){ $progressfopen = fopen($progressfile, 'w'); fwrite($progressfopen, '10'); @@ -29,85 +29,94 @@ if($_POST['method'] == 'new'){ } $id = $_POST['id']; } -//analyse the calendar file if(is_writable('import_tmp/')){ $progressfopen = fopen($progressfile, 'w'); fwrite($progressfopen, '20'); fclose($progressfopen); } -$searchfor = array('VEVENT', 'VTODO', 'VJOURNAL'); -$parts = $searchfor; -$filearr = explode($nl, $file); -$inelement = false; -$parts = array(); +// normalize the newlines +$file = str_replace(array("\r","\n\n"), array("\n","\n"), $file); +$lines = explode("\n", $file); +unset($file); +if(is_writable('import_tmp/')){ + $progressfopen = fopen($progressfile, 'w'); + fwrite($progressfopen, '30'); + fclose($progressfopen); +} +// analyze the file, group components by uid, and keep refs to originating calendar object +// $cals is array calendar objects, keys are 1st line# $cal, ie array( $cal => $caldata ) +// $caldata is array( 'first' => 1st component line#, 'last' => last comp line#, 'end' => end line# ) +// $caldata is used to create prefix/suffix strings when building import text +// $uids is array of component arrays, keys are $uid, ie array( $uid => array( $beginlineno => $component ) ) +// $component is array( 'end' => end line#, 'cal'=> $cal ) +$comp=$uid=$cal=false; +$cals=$uids=array(); $i = 0; -foreach($filearr as $line){ - foreach($searchfor as $search){ - if(substr_count($line, $search) == 1){ - list($attr, $val) = explode(':', $line); - if($attr == 'BEGIN'){ - $parts[]['begin'] = $i; - $inelement = true; +foreach($lines as $line) { + + if(strpos($line, ':')!==false) { + list($attr, $val) = explode(':', strtoupper($line)); + if ($attr == 'BEGIN' && $val == 'VCALENDAR') { + $cal = $i; + $cals[$cal] = array('first'=>$i,'last'=>$i,'end'=>$i); + } elseif ($attr =='BEGIN' && $cal!==false && isset($comps[$val])) { + $comp = $val; + $beginNo = $i; + } elseif ($attr == 'END' && $cal!==false && $val == 'VCALENDAR') { + if($comp!==false) { + unset($cals[$cal]); // corrupt calendar, unset it + } else { + $cals[$cal]['end'] = $i; + } + $comp=$uid=$cal=false; // reset calendar + } elseif ($attr == 'END' && $comp!==false && $val == $comp) { + if(! $uid) { + $uid = OC_Calendar_Object::createUID(); } - if($attr == 'END'){ - $parts[count($parts) - 1]['end'] = $i; - $inelement = false; + $uids[$uid][$beginNo] = array('end'=>$i, 'cal'=>$cal); + if ($cals[$cal]['first'] == $cal) { + $cals[$cal]['first'] = $beginNo; } + $cals[$cal]['last'] = $i; + $comp=$uid=false; // reset component + } elseif ($attr =="UID" && $comp!==false) { + list($attr, $uid) = explode(':', $line); } } $i++; } -//import the calendar +// import the calendar if(is_writable('import_tmp/')){ $progressfopen = fopen($progressfile, 'w'); - fwrite($progressfopen, '40'); + fwrite($progressfopen, '60'); fclose($progressfopen); } -$start = ''; -for ($i = 0; $i < $parts[0]['begin']; $i++) { - if($i == 0){ - $start = $filearr[0]; - }else{ - $start .= $nl . $filearr[$i]; - } -} -$end = ''; -for($i = $parts[count($parts) - 1]['end'] + 1;$i <= count($filearr) - 1; $i++){ - if($i == $parts[count($parts) - 1]['end'] + 1){ - $end = $filearr[$parts[count($parts) - 1]['end'] + 1]; - }else{ - $end .= $nl . $filearr[$i]; - } -} -if(is_writable('import_tmp/')){ - $progressfopen = fopen($progressfile, 'w'); - fwrite($progressfopen, '50'); - fclose($progressfopen); -} -$importready = array(); -foreach($parts as $part){ - for($i = $part['begin']; $i <= $part['end'];$i++){ - if($i == $part['begin']){ - $content = $filearr[$i]; - }else{ - $content .= $nl . $filearr[$i]; +foreach($uids as $uid) { + + $prefix=$suffix=$content=array(); + foreach($uid as $begin=>$details) { + + $cal = $details['cal']; + if(!isset($cals[$cal])) { + continue; // from corrupt/incomplete calendar + } + $cdata = $cals[$cal]; + // if we have multiple components from different calendar objects, + // we should really merge their elements (enhancement?) -- 1st one wins for now. + if(! count($prefix)) { + $prefix = array_slice($lines, $cal, $cdata['first'] - $cal); } + if(! count($suffix)) { + $suffix = array_slice($lines, $cdata['last']+1, $cdata['end'] - $cdata['last']); + } + $content = array_merge($content, array_slice($lines, $begin, $details['end'] - $begin + 1)); } - $importready[] = $start . $nl . $content . $nl . $end; -} -if(is_writable('import_tmp/')){ - $progressfopen = fopen($progressfile, 'w'); - fwrite($progressfopen, '70'); - fclose($progressfopen); -} -if(count($parts) == 1){ - OC_Calendar_Object::add($id, $file); -}else{ - foreach($importready as $import){ + if(count($content)) { + $import = join($nl, array_merge($prefix, $content, $suffix)) . $nl; OC_Calendar_Object::add($id, $import); } } -//done the import +// finished import if(is_writable('import_tmp/')){ $progressfopen = fopen($progressfile, 'w'); fwrite($progressfopen, '100'); diff --git a/apps/calendar/ajax/share/activation.php b/apps/calendar/ajax/share/activation.php new file mode 100644 index 00000000000..a4a3ce48192 --- /dev/null +++ b/apps/calendar/ajax/share/activation.php @@ -0,0 +1,12 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +require_once('../../../../lib/base.php'); +$id = strip_tags($_GET['id']); +$activation = strip_tags($_GET['activation']); +OC_Calendar_Share::set_active(OC_User::getUser(), $id, $activation); +OC_JSON::success(); \ No newline at end of file diff --git a/apps/calendar/ajax/share/changepermission.php b/apps/calendar/ajax/share/changepermission.php index 5538637eab4..faf2a13c56b 100644 --- a/apps/calendar/ajax/share/changepermission.php +++ b/apps/calendar/ajax/share/changepermission.php @@ -36,5 +36,5 @@ if($sharetype == 'group' && !OC_Group::groupExists($sharewith)){ OC_JSON::error(array('message'=>'group not found')); exit; } -$success = OC_Calendar_Share::changepermission($sharewith, $sharetype, $id, $permission, (($idtype=='calendar') ? OC_Calendar_Share::CALENDAR : OC_Calendar_Share::Event)); +$success = OC_Calendar_Share::changepermission($sharewith, $sharetype, $id, $permission, (($idtype=='calendar') ? OC_Calendar_Share::CALENDAR : OC_Calendar_Share::EVENT)); OC_JSON::success(); \ No newline at end of file diff --git a/apps/calendar/ajax/share/share.php b/apps/calendar/ajax/share/share.php index 88885cd7c10..70f1ec26ae6 100644 --- a/apps/calendar/ajax/share/share.php +++ b/apps/calendar/ajax/share/share.php @@ -16,6 +16,14 @@ switch($idtype){ OC_JSON::error(array('message'=>'unexspected parameter')); exit; } +if($idtype == 'calendar' && !OC_Calendar_App::getCalendar($id)){ + OC_JSON::error(array('message'=>'permission denied')); + exit; +} +if($idtype == 'event' && !OC_Calendar_App::getEventObject($id)){ + OC_JSON::error(array('message'=>'permission denied')); + exit; +} $sharewith = $_GET['sharewith']; $sharetype = strip_tags($_GET['sharetype']); switch($sharetype){ @@ -38,7 +46,7 @@ if($sharetype == 'group' && !OC_Group::groupExists($sharewith)){ if($sharetype == 'user' && OC_User::getUser() == $sharewith){ OC_JSON::error(array('meesage'=>'you can not share with yourself')); } -$success = OC_Calendar_Share::share(OC_User::getUser(), $sharewith, $sharetype, $id, (($idtype=='calendar') ? OC_Calendar_Share::CALENDAR : OC_Calendar_Share::Event)); +$success = OC_Calendar_Share::share(OC_User::getUser(), $sharewith, $sharetype, $id, (($idtype=='calendar') ? OC_Calendar_Share::CALENDAR : OC_Calendar_Share::EVENT)); if($success){ if($sharetype == 'public'){ OC_JSON::success(array('message'=>$success)); diff --git a/apps/calendar/ajax/share/unshare.php b/apps/calendar/ajax/share/unshare.php index 97ef7ab2cb0..c68fc23a6cb 100644 --- a/apps/calendar/ajax/share/unshare.php +++ b/apps/calendar/ajax/share/unshare.php @@ -30,12 +30,11 @@ switch($sharetype){ if($sharetype == 'user' && !OC_User::userExists($sharewith)){ OC_JSON::error(array('message'=>'user not found')); exit; -} -if($sharetype == 'group' && !OC_Group::groupExists($sharewith)){ +}elseif($sharetype == 'group' && !OC_Group::groupExists($sharewith)){ OC_JSON::error(array('message'=>'group not found')); exit; } -$success = OC_Calendar_Share::unshare(OC_User::getUser(), $sharewith, $sharetype, $id, (($idtype=='calendar') ? OC_Calendar_Share::CALENDAR : OC_Calendar_Share::Event)); +$success = OC_Calendar_Share::unshare(OC_User::getUser(), $sharewith, $sharetype, $id, (($idtype=='calendar') ? OC_Calendar_Share::CALENDAR : OC_Calendar_Share::EVENT)); if($success){ OC_JSON::success(); }else{ diff --git a/apps/calendar/appinfo/app.php b/apps/calendar/appinfo/app.php index ea743674fe8..21d128e7b8a 100644 --- a/apps/calendar/appinfo/app.php +++ b/apps/calendar/appinfo/app.php @@ -5,9 +5,12 @@ OC::$CLASSPATH['OC_Calendar_Calendar'] = 'apps/calendar/lib/calendar.php'; OC::$CLASSPATH['OC_Calendar_Object'] = 'apps/calendar/lib/object.php'; OC::$CLASSPATH['OC_Calendar_Hooks'] = 'apps/calendar/lib/hooks.php'; OC::$CLASSPATH['OC_Connector_Sabre_CalDAV'] = 'apps/calendar/lib/connector_sabre.php'; +OC::$CLASSPATH['OC_Calendar_Share'] = 'apps/calendar/lib/share.php'; OC::$CLASSPATH['OC_Search_Provider_Calendar'] = 'apps/calendar/lib/search.php'; OC_HOOK::connect('OC_User', 'post_deleteUser', 'OC_Calendar_Hooks', 'deleteUser'); OC_Util::addScript('calendar','loader'); +OC_Util::addScript("3rdparty", "chosen/chosen.jquery.min"); +OC_Util::addStyle("3rdparty", "chosen/chosen"); OC_App::register( array( 'order' => 10, 'id' => 'calendar', @@ -19,4 +22,4 @@ OC_App::addNavigationEntry( array( 'icon' => OC_Helper::imagePath( 'calendar', 'icon.svg' ), 'name' => $l->t('Calendar'))); OC_App::registerPersonal('calendar', 'settings'); -OC_Search::registerProvider('OC_Search_Provider_Calendar'); +OC_Search::registerProvider('OC_Search_Provider_Calendar'); \ No newline at end of file diff --git a/apps/calendar/appinfo/database.xml b/apps/calendar/appinfo/database.xml index 7f7b6457559..b065ab3f94a 100644 --- a/apps/calendar/appinfo/database.xml +++ b/apps/calendar/appinfo/database.xml @@ -187,5 +187,107 @@ + + + + *dbprefix*calendar_share_event + + + + + owner + text + true + 255 + + + + share + text + true + 255 + + + + sharetype + text + true + 6 + + + + eventid + integer + + true + true + 11 + + + + permissions + integer + true + 1 + + + + +
+ + + + *dbprefix*calendar_share_calendar + + + + + owner + text + true + 255 + + + + share + text + true + 255 + + + + sharetype + text + true + 6 + + + + calendarid + integer + + true + true + 11 + + + + permissions + integer + true + 1 + + + active + integer + 1 + true + 4 + + + + +
+ diff --git a/apps/calendar/appinfo/version b/apps/calendar/appinfo/version index 7dff5b89211..1d71ef97443 100644 --- a/apps/calendar/appinfo/version +++ b/apps/calendar/appinfo/version @@ -1 +1 @@ -0.2.1 \ No newline at end of file +0.3 \ No newline at end of file diff --git a/apps/calendar/css/style.css b/apps/calendar/css/style.css index cffaf356402..373a4565638 100644 --- a/apps/calendar/css/style.css +++ b/apps/calendar/css/style.css @@ -56,6 +56,12 @@ button.category{margin:0 3px;} .calendar-colorpicker-color{display:inline-block;width:20px;height:20px;margin-right:2px;cursor:pointer;border:2px solid transparent;} .calendar-colorpicker-color.active{border:2px solid black;} +#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/export.php b/apps/calendar/export.php index bf0503defbc..0972ee0f788 100644 --- a/apps/calendar/export.php +++ b/apps/calendar/export.php @@ -13,7 +13,7 @@ $cal = isset($_GET['calid']) ? $_GET['calid'] : NULL; $event = isset($_GET['eventid']) ? $_GET['eventid'] : NULL; $nl = "\r\n"; if(isset($cal)){ - $calendar = OC_Calendar_App::getCalendar($cal); + $calendar = OC_Calendar_App::getCalendar($cal, true); $calobjects = OC_Calendar_Object::all($cal); header('Content-Type: text/Calendar'); header('Content-Disposition: inline; filename=' . $calendar['displayname'] . '.ics'); @@ -21,7 +21,7 @@ if(isset($cal)){ echo $calobject['calendardata'] . $nl; } }elseif(isset($event)){ - $data = OC_Calendar_App::getEventObject($_GET['eventid']); + $data = OC_Calendar_App::getEventObject($_GET['eventid'], true); $calendarid = $data['calendarid']; $calendar = OC_Calendar_App::getCalendar($calendarid); header('Content-Type: text/Calendar'); diff --git a/apps/calendar/import.php b/apps/calendar/import.php deleted file mode 100644 index 9494ed89fca..00000000000 --- a/apps/calendar/import.php +++ /dev/null @@ -1,130 +0,0 @@ - - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ -//check for calendar rights or create new one -ob_start(); - -OC_JSON::checkLoggedIn(); -OC_Util::checkAppEnabled('calendar'); -$nl="\r\n"; -$comps = array('VEVENT'=>true, 'VTODO'=>true, 'VJOURNAL'=>true); -$progressfile = 'import_tmp/' . md5(session_id()) . '.txt'; -if(is_writable('import_tmp/')){ - $progressfopen = fopen($progressfile, 'w'); - fwrite($progressfopen, '10'); - fclose($progressfopen); -} -$file = OC_Filesystem::file_get_contents($_POST['path'] . '/' . $_POST['file']); -if($_POST['method'] == 'new'){ - $id = OC_Calendar_Calendar::addCalendar(OC_User::getUser(), $_POST['calname']); - OC_Calendar_Calendar::setCalendarActive($id, 1); -}else{ - $calendar = OC_Calendar_App::getCalendar($_POST['id']); - if($calendar['userid'] != OC_USER::getUser()){ - OC_JSON::error(); - exit(); - } - $id = $_POST['id']; -} -if(is_writable('import_tmp/')){ - $progressfopen = fopen($progressfile, 'w'); - fwrite($progressfopen, '20'); - fclose($progressfopen); -} -// normalize the newlines -$file = str_replace(array("\r","\n\n"), array("\n","\n"), $file); -$lines = explode("\n", $file); -unset($file); -if(is_writable('import_tmp/')){ - $progressfopen = fopen($progressfile, 'w'); - fwrite($progressfopen, '30'); - fclose($progressfopen); -} -// analyze the file, group components by uid, and keep refs to originating calendar object -// $cals is array calendar objects, keys are 1st line# $cal, ie array( $cal => $caldata ) -// $caldata is array( 'first' => 1st component line#, 'last' => last comp line#, 'end' => end line# ) -// $caldata is used to create prefix/suffix strings when building import text -// $uids is array of component arrays, keys are $uid, ie array( $uid => array( $beginlineno => $component ) ) -// $component is array( 'end' => end line#, 'cal'=> $cal ) -$comp=$uid=$cal=false; -$cals=$uids=array(); -$i = 0; -foreach($lines as $line) { - - if(strpos($line, ':')!==false) { - list($attr, $val) = explode(':', strtoupper($line)); - if ($attr == 'BEGIN' && $val == 'VCALENDAR') { - $cal = $i; - $cals[$cal] = array('first'=>$i,'last'=>$i,'end'=>$i); - } elseif ($attr =='BEGIN' && $cal!==false && isset($comps[$val])) { - $comp = $val; - $beginNo = $i; - } elseif ($attr == 'END' && $cal!==false && $val == 'VCALENDAR') { - if($comp!==false) { - unset($cals[$cal]); // corrupt calendar, unset it - } else { - $cals[$cal]['end'] = $i; - } - $comp=$uid=$cal=false; // reset calendar - } elseif ($attr == 'END' && $comp!==false && $val == $comp) { - if(! $uid) { - $uid = OC_Calendar_Object::createUID(); - } - $uids[$uid][$beginNo] = array('end'=>$i, 'cal'=>$cal); - if ($cals[$cal]['first'] == $cal) { - $cals[$cal]['first'] = $beginNo; - } - $cals[$cal]['last'] = $i; - $comp=$uid=false; // reset component - } elseif ($attr =="UID" && $comp!==false) { - list($attr, $uid) = explode(':', $line); - } - } - $i++; -} -// import the calendar -if(is_writable('import_tmp/')){ - $progressfopen = fopen($progressfile, 'w'); - fwrite($progressfopen, '60'); - fclose($progressfopen); -} -foreach($uids as $uid) { - - $prefix=$suffix=$content=array(); - foreach($uid as $begin=>$details) { - - $cal = $details['cal']; - if(!isset($cals[$cal])) { - continue; // from corrupt/incomplete calendar - } - $cdata = $cals[$cal]; - // if we have multiple components from different calendar objects, - // we should really merge their elements (enhancement?) -- 1st one wins for now. - if(! count($prefix)) { - $prefix = array_slice($lines, $cal, $cdata['first'] - $cal); - } - if(! count($suffix)) { - $suffix = array_slice($lines, $cdata['last']+1, $cdata['end'] - $cdata['last']); - } - $content = array_merge($content, array_slice($lines, $begin, $details['end'] - $begin + 1)); - } - if(count($content)) { - $import = join($nl, array_merge($prefix, $content, $suffix)) . $nl; - OC_Calendar_Object::add($id, $import); - } -} -// finished import -if(is_writable('import_tmp/')){ - $progressfopen = fopen($progressfile, 'w'); - fwrite($progressfopen, '100'); - fclose($progressfopen); -} -sleep(3); -if(is_writable('import_tmp/')){ - unlink($progressfile); -} -OC_JSON::success(); \ No newline at end of file diff --git a/apps/calendar/index.php b/apps/calendar/index.php index 4aa1f695e31..66f51c97226 100644 --- a/apps/calendar/index.php +++ b/apps/calendar/index.php @@ -21,6 +21,10 @@ $eventSources = array(); foreach($calendars as $calendar){ $eventSources[] = OC_Calendar_Calendar::getEventSourceInfo($calendar); } + +$eventSources[] = array('url' => 'ajax/events.php?calendar_id=shared_rw', 'backgroundColor' => '#1D2D44', 'borderColor' => '#888', 'textColor' => 'white', 'editable'=>'true'); +$eventSources[] = array('url' => 'ajax/events.php?calendar_id=shared_r', 'backgroundColor' => '#1D2D44', 'borderColor' => '#888', 'textColor' => 'white', 'editable' => 'false'); + OC_Hook::emit('OC_Calendar', 'getSources', array('sources' => &$eventSources)); $categories = OC_Calendar_App::getCategoryOptions(); diff --git a/apps/calendar/js/calendar.js b/apps/calendar/js/calendar.js index 858990fb89d..a16856938ce 100644 --- a/apps/calendar/js/calendar.js +++ b/apps/calendar/js/calendar.js @@ -46,6 +46,7 @@ Calendar={ $('#advanced_month').change(function(){ Calendar.UI.repeat('month'); }); + $( "#event" ).tabs({ selected: 0}); $('#event').dialog({ width : 500, close : function(event, ui) { @@ -455,7 +456,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'); @@ -494,6 +495,109 @@ Calendar={ left: -10000 }); } + }, + Share:{ + currentid: 'false', + idtype: '', + activation:function(object,owner,id){ + $.getJSON(OC.filePath('calendar', 'ajax/share', 'activation.php'),{id:id, idtype:'calendar', activation:object.checked?1:0}); + $('#calendar_holder').fullCalendar('refetchEvents'); + }, + 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', 'share.php'),{id:id, idtype:idtype, sharewith:sharewith, sharetype:sharetype}, function(data){ + + }); + }, + unshare:function(id, idtype, sharewith, sharetype){ + $.getJSON(OC.filePath('calendar', 'ajax/share', '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/share', '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() + '"]').removeAttr('disabled'); + Calendar.UI.Share.unshare(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $(this).parent().text(), 'user' ); + $("#share_user").trigger("liszt:updated"); + $(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_group option:selected').text() + ' > img').click(function(){ + $('#share_group option[value="' + $(this).parent().text() + '"]').removeAttr('disabled'); + Calendar.UI.Share.unshare(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $(this).parent().text(), 'group'); + $("#share_group").trigger("liszt:updated"); + $(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;*/ + } } } } @@ -749,4 +853,5 @@ $(document).ready(function(){ $('#datecontrol_right').click(function(){ $('#calendar_holder').fullCalendar('next'); }); + Calendar.UI.Share.init(); }); diff --git a/apps/calendar/js/loader.js b/apps/calendar/js/loader.js index 54003879759..60d92f448ee 100644 --- a/apps/calendar/js/loader.js +++ b/apps/calendar/js/loader.js @@ -44,7 +44,7 @@ Calendar_Import={ $('#newcalendar').attr('readonly', 'readonly'); $('#calendar').attr('disabled', 'disabled'); var progressfile = $('#progressfile').val(); - $.post(OC.filePath('calendar', '', 'import.php'), {method: String (method), calname: String (calname), path: String (path), file: String (filename), id: String (calid)}, function(data){ + $.post(OC.filePath('calendar', 'ajax/import', 'import.php'), {method: String (method), calname: String (calname), path: String (path), file: String (filename), id: String (calid)}, function(data){ if(data.status == 'success'){ $('#progressbar').progressbar('option', 'value', 100); $('#import_done').css('display', 'block'); diff --git a/apps/calendar/lib/alarm.php b/apps/calendar/lib/alarm.php new file mode 100644 index 00000000000..a71cc086827 --- /dev/null +++ b/apps/calendar/lib/alarm.php @@ -0,0 +1,13 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +/* + * This class manages reminders for calendars + */ +class OC_Calendar_Alarm{ + +} \ No newline at end of file diff --git a/apps/calendar/lib/app.php b/apps/calendar/lib/app.php index 4b481a4f286..3ce0d6fa1d4 100644 --- a/apps/calendar/lib/app.php +++ b/apps/calendar/lib/app.php @@ -1,60 +1,121 @@ + * Copyright (c) 2012 Georg Ehrke * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. - */ - -/** + * * This class manages our app actions */ -OC_Calendar_App::$l10n = OC_L10N::get('calendar'); +OC_Calendar_App::$l10n = new OC_L10N('calendar'); +OC_Calendar_App::$tz = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); class OC_Calendar_App{ + const CALENDAR = 'calendar'; + const EVENT = 'event'; + /* + * @brief language object for calendar app + */ public static $l10n; + + /* + * @brief categories of the user + */ protected static $categories = null; - public static function getCalendar($id){ - $calendar = OC_Calendar_Calendar::find( $id ); - if( $calendar === false || $calendar['userid'] != OC_User::getUser()){ - OC_JSON::error(array('data' => array('message' => self::$l10n->t('Wrong calendar')))); - exit(); + /* + * @brief timezone of the user + */ + public static $tz; + + /* + * @brief returns informations about a calendar + * @param int $id - id of the calendar + * @param bool $security - check access rights or not + * @param bool $shared - check if the user got access via sharing + * @return mixed - bool / array + */ + public static function getCalendar($id, $security = true, $shared = false){ + $calendar = OC_Calendar_Calendar::find($id); + if($shared === true){ + if(OC_Calendar_Share::check_access(OC_User::getUser(), $id, OC_Calendar_Share::CALENDAR)){ + return $calendar; + } + } + if($security === true){ + if($calendar['userid'] != OC_User::getUser()){ + return false; + } } - return $calendar; + if($calendar === false){ + return false; + } + return OC_Calendar_Calendar::find($id); } - - public static function getEventObject($id){ - $event_object = OC_Calendar_Object::find( $id ); - if( $event_object === false ){ - OC_JSON::error(); - exit(); + + /* + * @brief returns informations about an event + * @param int $id - id of the event + * @param bool $security - check access rights or not + * @param bool $shared - check if the user got access via sharing + * @return mixed - bool / array + */ + public static function getEventObject($id, $security = true, $shared = false){ + $event = OC_Calendar_Object::find($id); + if($shared === true){ + if(OC_Calendar_Share::check_access(OC_User::getUser(), $id, OC_Calendar_Share::EVENT)){ + return $event; + } } - - self::getCalendar( $event_object['calendarid'] );//access check - return $event_object; + if($security === true){ + $calendar = self::getCalendar($event['calendarid'], false); + if($calendar['userid'] != OC_User::getUser()){ + return false; + } + } + if($event === false){ + return false; + } + return $event; } - - public static function getVCalendar($id){ - $event_object = self::getEventObject( $id ); - - $vcalendar = OC_VObject::parse($event_object['calendardata']); - // Check if the vcalendar is valid - if(is_null($vcalendar)){ - OC_JSON::error(); - exit(); + + /* + * @brief returns the parsed calendar data + * @param int $id - id of the event + * @param bool $security - check access rights or not + * @return mixed - bool / object + */ + public static function getVCalendar($id, $security = true, $shared = false){ + $event_object = self::getEventObject($id, $security, $shared); + if($event_object === false){ + return false; + } + $vobject = OC_VObject::parse($event_object['calendardata']); + if(is_null($vobject)){ + return false; } - return $vcalendar; + return $vobject; } - - public static function isNotModified($vevent, $lastmodified) - { + + /* + * @brief checks if an event was edited and dies if it was + * @param (object) $vevent - vevent object of the event + * @param (int) $lastmodified - time of last modification as unix timestamp + * @return (bool) + */ + public static function isNotModified($vevent, $lastmodified){ $last_modified = $vevent->__get('LAST-MODIFIED'); if($last_modified && $lastmodified != $last_modified->getDateTime()->format('U')){ OC_JSON::error(array('modified'=>true)); exit; } + return true; } - + + /* + * @brief returns the default categories of ownCloud + * @return (array) $categories + */ protected static function getDefaultCategories() { return array( @@ -75,14 +136,22 @@ class OC_Calendar_App{ self::$l10n->t('Work'), ); } - + + /* + * @brief returns the vcategories object of the user + * @return (object) $vcategories + */ protected static function getVCategories() { if (is_null(self::$categories)) { self::$categories = new OC_VCategories('calendar', null, self::getDefaultCategories()); } return self::$categories; } - + + /* + * @brief returns the categories of the vcategories object + * @return (array) $categories + */ public static function getCategoryOptions() { $categories = self::getVCategories()->categories(); @@ -127,40 +196,226 @@ class OC_Calendar_App{ public static function getRepeatOptions(){ return OC_Calendar_Object::getRepeatOptions(self::$l10n); } - + + /* + * @brief returns the options for the end of an repeating event + * @return array - valid inputs for the end of an repeating events + */ public static function getEndOptions(){ return OC_Calendar_Object::getEndOptions(self::$l10n); } - + + /* + * @brief returns the options for an monthly repeating event + * @return array - valid inputs for monthly repeating events + */ public static function getMonthOptions(){ return OC_Calendar_Object::getMonthOptions(self::$l10n); } - + + /* + * @brief returns the options for an weekly repeating event + * @return array - valid inputs for weekly repeating events + */ public static function getWeeklyOptions(){ return OC_Calendar_Object::getWeeklyOptions(self::$l10n); } - + + /* + * @brief returns the options for an yearly repeating event + * @return array - valid inputs for yearly repeating events + */ public static function getYearOptions(){ return OC_Calendar_Object::getYearOptions(self::$l10n); } - + + /* + * @brief returns the options for an yearly repeating event which occurs on specific days of the year + * @return array - valid inputs for yearly repeating events + */ public static function getByYearDayOptions(){ return OC_Calendar_Object::getByYearDayOptions(); } - + + /* + * @brief returns the options for an yearly repeating event which occurs on specific month of the year + * @return array - valid inputs for yearly repeating events + */ public static function getByMonthOptions(){ return OC_Calendar_Object::getByMonthOptions(self::$l10n); } + /* + * @brief returns the options for an yearly repeating event which occurs on specific week numbers of the year + * @return array - valid inputs for yearly repeating events + */ public static function getByWeekNoOptions(){ return OC_Calendar_Object::getByWeekNoOptions(); } - + + /* + * @brief returns the options for an yearly or monthly repeating event which occurs on specific days of the month + * @return array - valid inputs for yearly or monthly repeating events + */ public static function getByMonthDayOptions(){ return OC_Calendar_Object::getByMonthDayOptions(); } + /* + * @brief returns the options for an monthly repeating event which occurs on specific weeks of the month + * @return array - valid inputs for monthly repeating events + */ public static function getWeekofMonth(){ return OC_Calendar_Object::getWeekofMonth(self::$l10n); } + + /* + * @brief checks the access for a calendar / an event + * @param (int) $id - id of the calendar / event + * @param (string) $type - type of the id (calendar/event) + * @return (string) $access - level of access + */ + public static function getaccess($id, $type){ + if($type == self::CALENDAR){ + $calendar = self::getCalendar($id, false, false); + if($calendar['userid'] == OC_User::getUser()){ + return 'owner'; + } + $isshared = OC_Calendar_Share::check_access(OC_User::getUser(), $id, OC_Calendar_Share::CALENDAR); + if($isshared){ + $writeaccess = OC_Calendar_Share::is_editing_allowed(OC_User::getUser(), $id, OC_Calendar_Share::CALENDAR); + if($writeaccess){ + return 'rw'; + }else{ + return 'r'; + } + }else{ + return false; + } + }elseif($type == self::EVENT){ + if(OC_Calendar_Object::getowner($id) == OC_User::getUser()){ + return 'owner'; + } + $isshared = OC_Calendar_Share::check_access(OC_User::getUser(), $id, OC_Calendar_Share::EVENT); + if($isshared){ + $writeaccess = OC_Calendar_Share::is_editing_allowed(OC_User::getUser(), $id, OC_Calendar_Share::EVENT); + if($writeaccess){ + return 'rw'; + }else{ + return 'r'; + } + }else{ + return false; + } + } + } + + /* + * @brief analyses the parameter for calendar parameter and returns the objects + * @param (string) $calendarid - calendarid + * @param (int) $start - unixtimestamp of start + * @param (int) $end - unixtimestamp of end + * @return (array) $events + */ + public static function getrequestedEvents($calendarid, $start, $end){ + $events = array(); + if($calendarid == 'shared_rw' || $_GET['calendar_id'] == 'shared_r'){ + $calendars = OC_Calendar_Share::allSharedwithuser(OC_USER::getUser(), OC_Calendar_Share::CALENDAR, 1, ($_GET['calendar_id'] == 'shared_rw')?'rw':'r'); + foreach($calendars as $calendar){ + $calendarevents = OC_Calendar_Object::allInPeriod($calendar['calendarid'], $start, $end); + $events = array_merge($events, $calendarevents); + } + $singleevents = OC_Calendar_Share::allSharedwithuser(OC_USER::getUser(), OC_Calendar_Share::EVENT, 1, ($_GET['calendar_id'] == 'shared_rw')?'rw':'r'); + foreach($singleevents as $singleevent){ + $event = OC_Calendar_Object::find($singleevent['eventid']); + $events[] = $event; + } + }else{ + $calendar_id = $_GET['calendar_id']; + if (is_numeric($calendar_id)) { + $calendar = self::getCalendar($calendar_id); + OC_Response::enableCaching(0); + OC_Response::setETagHeader($calendar['ctag']); + $events = OC_Calendar_Object::allInPeriod($calendar_id, $start, $end); + } else { + OC_Hook::emit('OC_Calendar', 'getEvents', array('calendar_id' => $calendar_id, 'events' => &$events)); + } + } + return $events; + } + + /* + * @brief generates the output for an event which will be readable for our js + * @param (mixed) $event - event object / array + * @param (int) $start - unixtimestamp of start + * @param (int) $end - unixtimestamp of end + * @return (array) $output - readable output + */ + public static function generateEventOutput($event, $start, $end){ + $output = array(); + + if(isset($event['calendardata'])){ + $object = OC_VObject::parse($event['calendardata']); + $vevent = $object->VEVENT; + }else{ + $vevent = $event['vevent']; + } + + $last_modified = @$vevent->__get('LAST-MODIFIED'); + $lastmodified = ($last_modified)?$last_modified->getDateTime()->format('U'):0; + + $output = array('id'=>(int)$event['id'], + 'title' => htmlspecialchars(($event['summary']!=NULL || $event['summary'] != '')?$event['summary']: self::$l10n->t('unnamed')), + 'description' => isset($vevent->DESCRIPTION)?htmlspecialchars($vevent->DESCRIPTION->value):'', + 'lastmodified'=>$lastmodified); + + $dtstart = $vevent->DTSTART; + $start_dt = $dtstart->getDateTime(); + $dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent); + $end_dt = $dtend->getDateTime(); + + if ($dtstart->getDateType() == Sabre_VObject_Element_DateTime::DATE){ + $output['allDay'] = true; + }else{ + $output['allDay'] = false; + $start_dt->setTimezone(new DateTimeZone(self::$tz)); + $end_dt->setTimezone(new DateTimeZone(self::$tz)); + } + + if($event['repeating'] == 1){ + $duration = (double) $end_dt->format('U') - (double) $start_dt->format('U'); + $r = new When(); + $r->recur($start_dt)->rrule((string) $vevent->RRULE); + /*$r = new iCal_Repeat_Generator(array('RECUR' => $start_dt, + * 'RRULE' => (string)$vevent->RRULE + * 'RDATE' => (string)$vevent->RDATE + * 'EXRULE' => (string)$vevent->EXRULE + * 'EXDATE' => (string)$vevent->EXDATE));*/ + while($result = $r->next()){ + if($result < $start){ + continue; + } + if($result > $end){ + break; + } + if($output['allDay'] == true){ + $output['start'] = $result->format('Y-m-d'); + $output['end'] = date('Y-m-d', $result->format('U') + --$duration); + }else{ + $output['start'] = $result->format('Y-m-d H:i:s'); + $output['end'] = date('Y-m-d H:i:s', $result->format('U') + $duration); + } + } + }else{ + if($output['allDay'] == true){ + $output['start'] = $start_dt->format('Y-m-d'); + $end_dt->modify('-1 sec'); + $output['end'] = $end_dt->format('Y-m-d'); + }else{ + $output['start'] = $start_dt->format('Y-m-d H:i:s'); + $output['end'] = $end_dt->format('Y-m-d H:i:s'); + } + } + return $output; + } } diff --git a/apps/calendar/lib/attendees.php b/apps/calendar/lib/attendees.php new file mode 100644 index 00000000000..ac30e11b3be --- /dev/null +++ b/apps/calendar/lib/attendees.php @@ -0,0 +1,13 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +/* + * This class manages Attendees for calendars + */ +class OC_Calendar_Attendees{ + +} \ No newline at end of file diff --git a/apps/calendar/lib/object.php b/apps/calendar/lib/object.php index d5622f6251f..825977c17c5 100644 --- a/apps/calendar/lib/object.php +++ b/apps/calendar/lib/object.php @@ -104,7 +104,7 @@ class OC_Calendar_Object{ $uri = 'owncloud-'.md5($data.rand().time()).'.ics'; $stmt = OC_DB::prepare( 'INSERT INTO *PREFIX*calendar_objects (calendarid,objecttype,startdate,enddate,repeating,summary,calendardata,uri,lastmodified) VALUES(?,?,?,?,?,?,?,?,?)' ); - $result = $stmt->execute(array($id,$type,$startdate,$enddate,$repeating,$summary,$data,$uri,time())); + $stmt->execute(array($id,$type,$startdate,$enddate,$repeating,$summary,$data,$uri,time())); OC_Calendar_Calendar::touchCalendar($id); @@ -123,7 +123,7 @@ class OC_Calendar_Object{ list($type,$startdate,$enddate,$summary,$repeating,$uid) = self::extractData($object); $stmt = OC_DB::prepare( 'INSERT INTO *PREFIX*calendar_objects (calendarid,objecttype,startdate,enddate,repeating,summary,calendardata,uri,lastmodified) VALUES(?,?,?,?,?,?,?,?,?)' ); - $result = $stmt->execute(array($id,$type,$startdate,$enddate,$repeating,$summary,$data,$uri,time())); + $stmt->execute(array($id,$type,$startdate,$enddate,$repeating,$summary,$data,$uri,time())); OC_Calendar_Calendar::touchCalendar($id); @@ -144,7 +144,7 @@ class OC_Calendar_Object{ list($type,$startdate,$enddate,$summary,$repeating,$uid) = self::extractData($object); $stmt = OC_DB::prepare( 'UPDATE *PREFIX*calendar_objects SET objecttype=?,startdate=?,enddate=?,repeating=?,summary=?,calendardata=?, lastmodified = ? WHERE id = ?' ); - $result = $stmt->execute(array($type,$startdate,$enddate,$repeating,$summary,$data,time(),$id)); + $stmt->execute(array($type,$startdate,$enddate,$repeating,$summary,$data,time(),$id)); OC_Calendar_Calendar::touchCalendar($oldobject['calendarid']); @@ -165,7 +165,7 @@ class OC_Calendar_Object{ list($type,$startdate,$enddate,$summary,$repeating,$uid) = self::extractData($object); $stmt = OC_DB::prepare( 'UPDATE *PREFIX*calendar_objects SET objecttype=?,startdate=?,enddate=?,repeating=?,summary=?,calendardata=?, lastmodified = ? WHERE id = ?' ); - $result = $stmt->execute(array($type,$startdate,$enddate,$repeating,$summary,$data,time(),$oldobject['id'])); + $stmt->execute(array($type,$startdate,$enddate,$repeating,$summary,$data,time(),$oldobject['id'])); OC_Calendar_Calendar::touchCalendar($oldobject['calendarid']); @@ -202,7 +202,7 @@ class OC_Calendar_Object{ public static function moveToCalendar($id, $calendarid){ $stmt = OC_DB::prepare( 'UPDATE *PREFIX*calendar_objects SET calendarid=? WHERE id = ?' ); - $result = $stmt->execute(array($calendarid,$id)); + $stmt->execute(array($calendarid,$id)); OC_Calendar_Calendar::touchCalendar($id); @@ -432,11 +432,6 @@ class OC_Calendar_Object{ $errarr['title'] = 'true'; $errnum++; } - $calendar = OC_Calendar_Calendar::find($request['calendar']); - if($calendar['userid'] != OC_User::getUser()){ - $errarr['cal'] = 'true'; - $errnum++; - } $fromday = substr($request['from'], 0, 2); $frommonth = substr($request['from'], 3, 2); @@ -461,11 +456,11 @@ class OC_Calendar_Object{ if($request['repeat'] != 'doesnotrepeat'){ if(is_nan($request['interval']) && $request['interval'] != ''){ $errarr['interval'] = 'true'; - $ernum++; + $errnum++; } if(array_key_exists('repeat', $request) && !array_key_exists($request['repeat'], self::getRepeatOptions(OC_Calendar_App::$l10n))){ $errarr['repeat'] = 'true'; - $ernum++; + $errnum++; } if(array_key_exists('advanced_month_select', $request) && !array_key_exists($request['advanced_month_select'], self::getMonthOptions(OC_Calendar_App::$l10n))){ $errarr['advanced_month_select'] = 'true'; @@ -760,8 +755,6 @@ class OC_Calendar_Object{ $vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC); $vevent->setString('SUMMARY', $title); - $dtstart = new Sabre_VObject_Element_DateTime('DTSTART'); - $dtend = new Sabre_VObject_Element_DateTime('DTEND'); if($allday){ $start = new DateTime($from); $end = new DateTime($to.' +1 day'); @@ -787,4 +780,15 @@ class OC_Calendar_Object{ return $vcalendar; } + + public static function getowner($id){ + $event = self::find($id); + $cal = OC_Calendar_Calendar::find($event['calendarid']); + return $cal['userid']; + } + + public static function getCalendarid($id){ + $event = self::find($id); + return $event['calendarid']; + } } diff --git a/apps/calendar/lib/share.php b/apps/calendar/lib/share.php new file mode 100644 index 00000000000..8f91be97474 --- /dev/null +++ b/apps/calendar/lib/share.php @@ -0,0 +1,259 @@ + + * 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, $active=null, $permission=null){ + $group_where = self::group_sql(OC_Group::getUserGroups($userid)); + $permission_where = self::permission_sql($permission); + if($type == self::CALENDAR){ + $active_where = self::active_sql($active); + }else{ + $active_where = ''; + } + $stmt = OC_DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . $type . ' WHERE ((share = ? AND sharetype = "user") ' . $group_where . ') AND owner <> ? ' . $permission_where . ' ' . $active_where); + $result = $stmt->execute(array($userid, $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($id, $type); + } + $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_Object::all($id); + $string = ''; + foreach($events as $event){ + $string .= $event['calendardata']; + } + }else{ + $string = OC_Calendar_Object::find($id); + } + $string = sha1($string['calendardata']); + $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) + */ + public 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; + } + private static function group_sql($groups){ + $group_where = ''; + $i = 0; + foreach($groups as $group){ + $group_where .= ' OR '; + $group_where .= ' (share = "' . $group . '" AND sharetype = "group") '; + $i++; + } + return $group_where; + } + private static function permission_sql($permission = null){ + $permission_where = ''; + if(!is_null($permission)){ + $permission_where = ' AND permissions = '; + $permission_where .= ($permission=='rw')?'"1"':'"0"'; + } + return $permission_where; + } + private static function active_sql($active = null){ + $active_where = ''; + if(!is_null($active)){ + $active_where = 'AND active = '; + $active_where .= (!is_null($active) && $active)?'1':'0'; + } + return $active_where; + } + /* + * @brief: checks the permission for editing an event + * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public) + * @param: (string) $id - id of the calendar / event + * @param: (string) $type - use const self::CALENDAR or self::EVENT + * @return (bool) + */ + public static function is_editing_allowed($share, $id, $type){ + $group_where = self::group_sql(OC_Group::getUserGroups($share)); + $permission_where = self::permission_sql('rw'); + $stmt = OC_DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . $type . ' WHERE ((share = ? AND sharetype = "user") ' . $group_where . ') ' . $permission_where); + $result = $stmt->execute(array($share)); + if($result->numRows() == 1){ + return true; + } + if($type == self::EVENT){ + $event = OC_Calendar_App::getEventObject($id, false, false); + return self::is_editing_allowed($share, $event['calendarid'], self::CALENDAR); + } + return false; + } + /* + * @brief: checks the access of + * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public) + * @param: (string) $id - id of the calendar / event + * @param: (string) $type - use const self::CALENDAR or self::EVENT + * @return (bool) + */ + public static function check_access($share, $id, $type){ + $group_where = self::group_sql(OC_Group::getUserGroups($share)); + $stmt = OC_DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . $type . ' WHERE (' . $type . 'id = ? AND (share = ? AND sharetype = "user") ' . $group_where . ')'); + $result = $stmt->execute(array($id,$share)); + $rows = $result->numRows(); + if($rows > 0){ + return true; + }elseif($type == self::EVENT){ + $event = OC_Calendar_App::getEventObject($id, false, false); + return self::check_access($share, $event['calendarid'], self::CALENDAR); + }else{ + return false; + } + } + /* + * @brief: returns the calendardata of an event or a calendar + * @param: (string) $token - token which should be searched + * @return: mixed - bool if false, array with type and id if true + */ + public static function getElementByToken($token){ + $stmt_calendar = OC_DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . OC_Calendar_Share::CALENDAR . ' WHERE sharetype = "public" AND share = ?'); + $result_calendar = $stmt_calendar->execute(array($token)); + $stmt_event = OC_DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . OC_Calendar_Share::EVENT . ' WHERE sharetype = "public" AND share = ?'); + $result_event = $stmt_event->execute(array($token)); + $return = array(); + if($result_calendar->numRows() == 0 && $result_event->numRows() == 0){ + return false; + }elseif($result_calendar->numRows() != 0){ + $return ['type'] = 'calendar'; + $calendar = $result_calendar->fetchRow(); + $return ['id'] = $calendar['calendarid']; + }else{ + $return ['type'] = 'event'; + $event = $result_event->fetchRow(); + $return ['id'] = $event['eventid']; + } + return $return; + } + + /* + * @brief sets the active status of the calendar + * @param (string) $ + */ + public static function set_active($share, $id, $active){ + $stmt = OC_DB::prepare('UPDATE *PREFIX*calendar_share_calendar SET active = ? WHERE share = ? AND sharetype = "user" AND calendarid = ?'); + $stmt->execute(array($active, $share, $id)); + } +} \ No newline at end of file diff --git a/apps/calendar/resettimezone.php b/apps/calendar/resettimezone.php deleted file mode 100644 index 0996924b5ad..00000000000 --- a/apps/calendar/resettimezone.php +++ /dev/null @@ -1,4 +0,0 @@ - \ No newline at end of file diff --git a/apps/calendar/share.php b/apps/calendar/share.php new file mode 100644 index 00000000000..1cc8a2ef15e --- /dev/null +++ b/apps/calendar/share.php @@ -0,0 +1,23 @@ +t("Choose active calendars"); ?>"> +

    t('Your calendars'); ?>:

    "; $tmpl = new OC_Template('calendar', 'part.choosecalendar.rowfields'); $tmpl->assign('calendar', $option_calendars[$i]); + if(OC_Calendar_Share::allUsersSharedwith($option_calendars[$i]['id'], OC_Calendar_Share::CALENDAR) == array()){ + $shared = false; + }else{ + $shared = true; + } + $tmpl->assign('shared', $shared); $tmpl->printpage(); echo ""; } @@ -20,4 +27,25 @@ for($i = 0; $i < count($option_calendars); $i++){

    ">

    +

    +

    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 d3bf6c0501c..cf85f0dc53e 100644 --- a/apps/calendar/templates/part.choosecalendar.rowfields.php +++ b/apps/calendar/templates/part.choosecalendar.rowfields.php @@ -1,4 +1,8 @@ "; - echo ""; - 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 ''; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; \ No newline at end of file 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 00000000000..a23266da0c3 --- /dev/null +++ b/apps/calendar/templates/part.choosecalendar.rowfields.shared.php @@ -0,0 +1,4 @@ +'; +echo ''; +echo '' . $l->t('shared with you by') . ' ' . $_['share']['owner'] . ''; \ No newline at end of file diff --git a/apps/calendar/templates/part.editevent.php b/apps/calendar/templates/part.editevent.php index 6e319e1b4e0..58314db1a6b 100644 --- a/apps/calendar/templates/part.editevent.php +++ b/apps/calendar/templates/part.editevent.php @@ -1,13 +1,13 @@
    ">
    - + inc("part.eventform"); ?>
    " onclick="Calendar.UI.validateEventForm('ajax/event/edit.php');"> " onclick="Calendar.UI.submitDeleteEventForm('ajax/event/delete.php');"> - " onclick="window.location='export.php?eventid=';"> + " onclick="window.location='export.php?eventid=';">
    diff --git a/apps/calendar/templates/part.eventform.php b/apps/calendar/templates/part.eventform.php index 3830c273a73..1eee099d0d1 100644 --- a/apps/calendar/templates/part.eventform.php +++ b/apps/calendar/templates/part.eventform.php @@ -1,3 +1,19 @@ + + + +
    @@ -26,7 +42,7 @@ @@ -59,7 +75,27 @@
    t("Title");?>:   - +
    " onclick="Calendar.UI.showadvancedoptions();" id="advanced_options_button"> +
    +
    +
    t("Repeat");?>: @@ -112,7 +148,7 @@
    + t('Summary'); ?>:
    -
    - - - - - - -
    t("Location");?>: - " value="" maxlength="100" name="location" /> -
    - - - - - -
    t("Description");?>: - -
    - + + + +
    + inc('share.dropdown'); ?> +
    + diff --git a/apps/calendar/templates/part.import.php b/apps/calendar/templates/part.import.php index 8f46484b42b..90691a33e50 100644 --- a/apps/calendar/templates/part.import.php +++ b/apps/calendar/templates/part.import.php @@ -3,7 +3,7 @@ -

    t('Please choose the calendar'); ?> +

    t('Please choose the calendar'); ?>

    '; + echo html_select_options($_['categories'], $_['categories'], array('combine'=>true)); + echo ''; + } + ?> + +    t("Calendar");?>: + + + +   + + + + + +
    + + + + + + + + + + + + + +
    + id="allday_checkbox" name="allday" disabled="disabled"> + t("All Day Event");?> +
    t("From");?>: + +    t('at'):''; ?>    + +
    t("To");?>: + +    t('at'):''; ?>    + +
    + " onclick="Calendar.UI.showadvancedoptions();" id="advanced_options_button"> + + +
    + + + + + + +
    t("Repeat");?>: + " onclick="Calendar.UI.showadvancedoptionsforrepeating();" id="advanced_options_button">
    + +
    + + + \ No newline at end of file diff --git a/apps/calendar/templates/settings.php b/apps/calendar/templates/settings.php index fb2a04a6498..3488fec0187 100644 --- a/apps/calendar/templates/settings.php +++ b/apps/calendar/templates/settings.php @@ -9,7 +9,7 @@ ?>
    - t('Calendar'); ?> + t('Calendar'); ?>
    + + +
    +
      + +
    • style="visibility:hidden;" title="t('Editable'); ?>">
    • + + +
    +t('Groups');?>:
    +
    +
      + +
    • style="visibility:hidden;" title="t('Editable'); ?>">
    • + + +
    +
    + >
    + +
    \ No newline at end of file diff --git a/apps/contacts/ajax/savecrop.php b/apps/contacts/ajax/savecrop.php index 36ba6a046dc..84c94da50b8 100644 --- a/apps/contacts/ajax/savecrop.php +++ b/apps/contacts/ajax/savecrop.php @@ -44,19 +44,15 @@ function bailOut($msg) { $image = null; -$x1 = (isset($_POST['x1']) && $_POST['x1']) ? $_POST['x1'] : -1; +$x1 = (isset($_POST['x1']) && $_POST['x1']) ? $_POST['x1'] : 0; //$x2 = isset($_POST['x2']) ? $_POST['x2'] : -1; -$y1 = (isset($_POST['y1']) && $_POST['y1']) ? $_POST['y1'] : -1; +$y1 = (isset($_POST['y1']) && $_POST['y1']) ? $_POST['y1'] : 0; //$y2 = isset($_POST['y2']) ? $_POST['y2'] : -1; $w = (isset($_POST['w']) && $_POST['w']) ? $_POST['w'] : -1; $h = (isset($_POST['h']) && $_POST['h']) ? $_POST['h'] : -1; $tmp_path = isset($_POST['tmp_path']) ? $_POST['tmp_path'] : ''; $id = isset($_POST['id']) ? $_POST['id'] : ''; -if(in_array(-1, array($x1, $y1, $w, $h))) { - bailOut('Wrong crop dimensions: '.implode(', ', array($x1, $y1, $w, $h))); -} - if($tmp_path == '') { bailOut('Missing path to temporary file.'); } @@ -70,6 +66,9 @@ OC_Log::write('contacts','savecrop.php: files: '.$tmp_path.' exists: '.file_exi if(file_exists($tmp_path)) { $image = new OC_Image(); if($image->loadFromFile($tmp_path)) { + $w = ($w != -1 ? $w : $image->width()); + $h = ($h != -1 ? $h : $image->height()); + OC_Log::write('contacts','savecrop.php, x: '.$x1.' y: '.$y1.' w: '.$w.' h: '.$h, OC_Log::DEBUG); if($image->crop($x1, $y1, $w, $h)) { if($image->resize(200)) { $tmpfname = tempnam("/tmp", "occCropped"); // create a new file because of caching issues. @@ -81,7 +80,7 @@ if(file_exists($tmp_path)) { bailOut('Error getting contact object.'); } if($card->__isset('PHOTO')) { - OC_Log::write('contacts','savecrop.php: files: PHOTO property exists.', OC_Log::DEBUG); + OC_Log::write('contacts','savecrop.php: PHOTO property exists.', OC_Log::DEBUG); $property = $card->__get('PHOTO'); if(!$property) { unlink($tmpfname); diff --git a/apps/contacts/css/contacts.css b/apps/contacts/css/contacts.css index 2d207943841..c19c6cc7113 100644 --- a/apps/contacts/css/contacts.css +++ b/apps/contacts/css/contacts.css @@ -1,10 +1,14 @@ /*dl > dt { font-weight: bold; }*/ - -#contacts { padding-left:2px; padding-top: 5px; background: #fff; } +#leftcontent { top: 3.5em !important; } +#rightcontent { top: 3.5em !important; padding-top: 5px; } +#contacts { background: #fff; width: 20em; top: 3.7em; bottom:3em; position: fixed; overflow: auto; } +#bottomcontrols { padding: 0; bottom:0px; height:2.8em; width: 20em; margin:0; background:#eee; border-top:1px solid #ccc; position:fixed; -moz-box-shadow: 0 0 0 #000, -3px 0 7px #000; -webkit-box-shadow: 0 0 0 #000, -3px 0 7px #000; box-shadow: 0 0 0 #000, -3px 0 7px #000;} +#contacts_newcontact { float: left; margin: 0.2em 0 0 1em; } +#chooseaddressbook { float: right; margin: 0.2em 1em 0 0; } #leftcontent a { height: 23px; display: block; margin: 0 0 0 0; padding: 0 0 0 25px; } -#chooseaddressbook {margin-right: 170px; float: right;} +#actionbar { height: 30px; width: 60px; position: fixed; right: 0px; top: 4em; margin: 0 0 0 0; padding: 0 0 0 0; z-index: 1000; } #contacts_deletecard {position:absolute;top:15px;right:25px;} #contacts_downloadcard {position:absolute;top:15px;right:50px;} #contacts_propertymenu_button { position:absolute;top:15px;right:150px; background:url('../../../core/img/actions/add.svg') no-repeat center; } @@ -13,7 +17,6 @@ #contacts_propertymenu li a { padding: 3px; display: block } #contacts_propertymenu li:hover { background-color: #1d2d44; } #contacts_propertymenu li a:hover { color: #fff } -#actionbar { height: 30px; width: 200px; position: fixed; right: 0px; top: 75px; margin: 0 0 0 0; padding: 0 0 0 0; z-index: 1000; } #card { width: auto;/*max-width: 70em; border: thin solid lightgray; display: block;*/ } #firstrun { width: 100%; position: absolute; top: 5em; left: 0; text-align: center; font-weight:bold; font-size:1.5em; color:#777; } #firstrun #selections { font-size:0.8em; margin: 2em auto auto auto; clear: both; } @@ -21,7 +24,8 @@ #card input[type="text"].contacts_property,input[type="email"].contacts_property { width: 14em; float: left; } .categories { float: left; width: 16em; } #card input[type="text"],input[type="email"],input[type="tel"],input[type="date"], select, textarea { background-color: #fefefe; border: 0 !important; -webkit-appearance:none !important; -moz-appearance:none !important; -webkit-box-sizing:none !important; -moz-box-sizing:none !important; box-sizing:none !important; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; -moz-border-radius: 0px; -webkit-border-radius: 0px; border-radius: 0px; float: left; } -#card input[type="text"]:hover, input[type="text"]:focus, input[type="text"]:active,input[type="email"]:hover,input[type="tel"]:hover,input[type="date"]:hover,input[type="date"],input[type="date"]:hover,input[type="date"]:active,input[type="date"]:active,input[type="date"]:active,input[type="email"]:active,input[type="tel"]:active, select:hover, select:focus, select:active, textarea:focus, textarea:hover { border: 0 !important; -webkit-appearance:textfield; -moz-appearance:textfield; -webkit-box-sizing:content-box; -moz-box-sizing:content-box; box-sizing:content-box; background:#fff; color:#333; border:1px solid #ddd; -moz-box-shadow:0 1px 1px #fff, 0 2px 0 #bbb inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; outline:none; float: left; } +#card input[type="text"]:hover, input[type="text"]:focus, input[type="text"]:active,input[type="email"]:hover,input[type="tel"]:hover,input[type="date"]:hover,input[type="date"],input[type="date"]:hover,input[type="date"]:active,input[type="date"]:active,input[type="date"]:active,input[type="email"]:active,input[type="tel"]:active, select:hover, select:focus, select:active { border: 0 !important; -webkit-appearance:textfield; -moz-appearance:textfield; -webkit-box-sizing:content-box; -moz-box-sizing:content-box; box-sizing:content-box; background:#fff; color:#333; border:1px solid #ddd; -moz-box-shadow:0 1px 1px #fff, 0 2px 0 #bbb inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; outline:none; float: left; } +textarea:focus, textarea:hover { background:#fff; color:#333; border:1px solid #ddd; -moz-box-shadow:0 1px 1px #fff, 0 2px 0 #bbb inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; outline:none; float: left; } input[type="text"]:invalid,input[type="email"]:invalid,input[type="tel"]:invalid,input[type="date"]:invalid, textarea:invalid { color: #bbb !important; } textarea { min-height: 4em; } dl.form { width: 100%; float: left; clear: right; margin: 0; padding: 0; } diff --git a/apps/contacts/img/contact-new.svg b/apps/contacts/img/contact-new.svg new file mode 100644 index 00000000000..3c824dd10c9 --- /dev/null +++ b/apps/contacts/img/contact-new.svg @@ -0,0 +1,449 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index 5f2bd6e9df9..b491b3a90ef 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -387,10 +387,11 @@ Contacts={ $('#note').data('checksum', this.data.NOTE[0]['checksum']); $('#note').find('textarea').val(this.data.NOTE[0]['value']); $('#note').show(); + $('#contacts_propertymenu a[data-type="NOTE"]').parent().hide(); } else { $('#note').data('checksum', ''); $('#note').find('textarea').val(''); - //$('#note').hide(); + $('#note').hide(); } }, loadSingleProperties:function() { @@ -536,7 +537,7 @@ Contacts={ },*/ editNew:function(){ // add a new contact this.id = ''; this.fn = ''; this.fullname = ''; this.givname = ''; this.famname = ''; this.addname = ''; this.honpre = ''; this.honsuf = ''; - Contacts.UI.Card.add(';;;;', '', '', true); + Contacts.UI.Card.add(t('contacts', 'Contact')+';'+t('contacts', 'New')+';;;', t('contacts', 'New Contact'), '', true); /*$.getJSON(OC.filePath('contacts', 'ajax', 'newcontact.php'),{},function(jsondata){ if(jsondata.status == 'success'){ id = ''; @@ -1403,6 +1404,14 @@ $(document).ready(function(){ Contacts.UI.Card.saveProperty(this); }); + $('#fn').blur(function(){ + if($('#fn').val() == '') { + OC.dialogs.alert(t('contacts','The name field cannot be empty. Please enter a name for this contact.'), t('contacts','Name is empty'), function() { $('#fn').focus(); }); + $('#fn').focus(); + return false; + } + }); + // Name has changed. Update it and reorder. $('#fn').live('change',function(){ var name = $('#fn').val(); @@ -1429,19 +1438,19 @@ $(document).ready(function(){ $('#file_upload_start').live('change',function(){ Contacts.UI.Card.uploadPhoto(this.files); }); - $('#contacts_details_photo').bind('dragover',function(event){ + $('#contacts_details_photo_wrapper').bind('dragover',function(event){ console.log('dragover'); $(event.target).css('background-color','red'); event.stopPropagation(); event.preventDefault(); }); - $('#contacts_details_photo').bind('dragleave',function(event){ + $('#contacts_details_photo_wrapper').bind('dragleave',function(event){ console.log('dragleave'); $(event.target).css('background-color','white'); //event.stopPropagation(); //event.preventDefault(); }); - $('#contacts_details_photo').bind('drop',function(event){ + $('#contacts_details_photo_wrapper').bind('drop',function(event){ event.stopPropagation(); event.preventDefault(); console.log('drop'); diff --git a/apps/contacts/js/jquery.multi-autocomplete.js b/apps/contacts/js/jquery.multi-autocomplete.js index e1c5d63dc5f..5516a74b039 100644 --- a/apps/contacts/js/jquery.multi-autocomplete.js +++ b/apps/contacts/js/jquery.multi-autocomplete.js @@ -31,7 +31,9 @@ } else { self.element.val(tmp); } - self.element.trigger('change'); // Changes wasn't saved when only using the dropdown. + if(self.element.val().trim() != '') { + self.element.trigger('change'); // Changes wasn't saved when only using the dropdown. + } }); this.element.bind( "keydown", function( event ) { if ( event.keyCode === $.ui.keyCode.TAB && diff --git a/apps/contacts/templates/index.php b/apps/contacts/templates/index.php index b14a35e19ed..256d10afc07 100644 --- a/apps/contacts/templates/index.php +++ b/apps/contacts/templates/index.php @@ -3,17 +3,23 @@ var categories = ; var lang = ''; -
    +
      inc("part.contacts"); ?>
    +
    + + <?php echo $l->t('Add Contact'); ?> + <?php echo $l->t('Addressbooks'); ?> + +
    - t('Contacts'); ?>
    - t('CardDAV syncing addresses:'); ?> + t('Contacts'); ?> + t('CardDAV syncing addresses'); ?> (t('more info'); ?>)
    t('Primary address (Kontact et al)'); ?>
    /
    diff --git a/apps/files/templates/admin.php b/apps/files/templates/admin.php index 9bcc40e9361..01fe1105260 100644 --- a/apps/files/templates/admin.php +++ b/apps/files/templates/admin.php @@ -7,9 +7,13 @@ '/>(t('max. possible: '); echo $_['maxPossibleUploadSize'] ?>)
    />
    -
    - ' title="t( '0 is unlimited' ); ?>" />
    -
    + + ' title="t( '0 is unlimited' ); ?>" /> +
    +
    + + + diff --git a/apps/media/templates/settings.php b/apps/media/templates/settings.php index 2907c616cf6..941c17ff597 100644 --- a/apps/media/templates/settings.php +++ b/apps/media/templates/settings.php @@ -2,6 +2,6 @@
    Media
    Ampache address: -
    +
    diff --git a/apps/remoteStorage/templates/settings.php b/apps/remoteStorage/templates/settings.php index 9b5c3b6229c..b940282b2cc 100644 --- a/apps/remoteStorage/templates/settings.php +++ b/apps/remoteStorage/templates/settings.php @@ -1,6 +1,6 @@
    ' + echo ' ' .''.$l->t('remoteStorage').' user address: ' .OC_User::getUser().'@'.$_SERVER['SERVER_NAME'] .' (more info)'; diff --git a/apps/user_migrate/templates/admin.php b/apps/user_migrate/templates/admin.php index b01e5c7579a..ff51f43ffde 100644 --- a/apps/user_migrate/templates/admin.php +++ b/apps/user_migrate/templates/admin.php @@ -6,7 +6,7 @@ t('Import user account');?>

    -

    +

    diff --git a/config/config.sample.php b/config/config.sample.php index 9f6d674fc0e..8561d0a7580 100755 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -24,6 +24,10 @@ $CONFIG = array( "mail_smtpauth" => "false", "mail_smtpname" => "", "mail_smtppassword" => "", +"appcodechecker" => "", +"log_type" => "", +"logfile" => "", +"loglevel" => "", // "datadirectory" => "" ); ?> diff --git a/core/css/styles.css b/core/css/styles.css index afb02041129..ccebc984fbb 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -33,7 +33,7 @@ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#35537a', end /* INPUTS */ input[type="text"], input[type="password"] { cursor:text; } -input, select, button, .button, #quota, div.jp-progress, .pager li a { font-size:1em; width:10em; margin:.3em; padding:.6em .5em .4em; background:#fff; color:#333; border:1px solid #ddd; -moz-box-shadow:0 1px 1px #fff, 0 2px 0 #bbb inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; outline:none; } +input, textarea, select, button, .button, #quota, div.jp-progress, .pager li a { font-size:1em; width:10em; margin:.3em; padding:.6em .5em .4em; background:#fff; color:#333; border:1px solid #ddd; -moz-box-shadow:0 1px 1px #fff, 0 2px 0 #bbb inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; outline:none; } input[type="text"], input[type="password"], input[type="search"] { background:#f8f8f8; color:#555; cursor:text; } input[type="text"], input[type="password"], input[type="search"] { -webkit-appearance:textfield; -moz-appearance:textfield; -webkit-box-sizing:content-box; -moz-box-sizing:content-box; box-sizing:content-box; } input[type="text"]:hover, input[type="text"]:focus, input[type="text"]:active, @@ -121,6 +121,8 @@ tbody tr:hover, tr:active { background-color:#f8f8f8; } #body-settings .personalblock#quota { position:relative; padding:0; } #body-settings #controls+.helpblock { position:relative; margin-top: 3em; } .personalblock > legend { margin-top:2em; } +.personalblock > legend, th, dt, label { font-weight: bold; } +code { font-family: "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", monospace; } #quota div, div.jp-play-bar, div.jp-seek-bar { padding:0; background:#e6e6e6; font-weight:normal; white-space:nowrap; -moz-border-radius-bottomleft:.4em; -webkit-border-bottom-left-radius:.4em; border-bottom-left-radius:.4em; -moz-border-radius-topleft:.4em; -webkit-border-top-left-radius:.4em; border-top-left-radius:.4em; } #quotatext {padding: .6em 1em;} diff --git a/lib/installer.php b/lib/installer.php index 6edf4ce1b74..d5592273815 100644 --- a/lib/installer.php +++ b/lib/installer.php @@ -47,6 +47,7 @@ class OC_Installer{ * This function works as follows * -# fetching the file * -# unzipping it + * -# check the code * -# installing the database at appinfo/database.xml * -# including appinfo/install.php * -# setting the installed version @@ -91,6 +92,7 @@ class OC_Installer{ //extract the archive in a temporary folder $extractDir=OC_Helper::tmpFolder(); + OC_Helper::rmdirr($extractDir); mkdir($extractDir); if($archive=OC_Archive::open($path)){ $archive->extract($extractDir); @@ -102,7 +104,7 @@ class OC_Installer{ } return false; } - + //load the info.xml file of the app if(!is_file($extractDir.'/appinfo/info.xml')){ //try to find it in a subdir @@ -125,6 +127,12 @@ class OC_Installer{ } $info=OC_App::getAppInfo($extractDir.'/appinfo/info.xml',true); $basedir=OC::$APPSROOT.'/apps/'.$info['id']; + + // check the code for not allowed calls + if(!OC_Installer::checkCode($info['id'],$extractDir)){ + OC_Helper::rmdirr($extractDir); + return false; + } //check if an app with the same id is already installed if(self::isInstalled( $info['id'] )){ @@ -151,8 +159,8 @@ class OC_Installer{ } //copy the app to the correct place - if(!mkdir($basedir)){ - OC_Log::write('core','Can\'t create app folder ('.$basedir.')',OC_Log::ERROR); + if(@!mkdir($basedir)){ + OC_Log::write('core','Can\'t create app folder. Please fix permissions. ('.$basedir.')',OC_Log::ERROR); OC_Helper::rmdirr($extractDir); if($data['source']=='http'){ unlink($path); @@ -300,4 +308,49 @@ class OC_Installer{ OC_Appconfig::setValue($app,'installed_version',OC_App::getAppVersion($app)); return $info; } + + + /** + * check the code of an app with some static code checks + * @param string $folder the folder of the app to check + * @returns true for app is o.k. and false for app is not o.k. + */ + public static function checkCode($appname,$folder){ + + $blacklist=array( + 'fopen(', + 'eval(' + // more evil pattern will go here later + // will will also check if an app is using private api once the public api is in place + + ); + + // is the code checker enabled? + if(OC_Config::getValue('appcodechecker', false)){ + + // check if grep is installed + $grep = exec('which grep'); + if($grep=='') { + OC_Log::write('core','grep not installed. So checking the code of the app "'.$appname.'" was not possible',OC_Log::ERROR); + return true; + } + + // iterate the bad patterns + foreach($blacklist as $bl) { + $cmd = 'grep -ri '.escapeshellarg($bl).' '.$folder.''; + $result = exec($cmd); + // bad pattern found + if($result<>'') { + OC_Log::write('core','App "'.$appname.'" is using a not allowed call "'.$bl.'". Installation refused.',OC_Log::ERROR); + return false; + } + } + return true; + + }else{ + return true; + } + } + + } diff --git a/lib/ocsclient.php b/lib/ocsclient.php index 9ad9ef21c66..aef51f38fb7 100755 --- a/lib/ocsclient.php +++ b/lib/ocsclient.php @@ -162,6 +162,7 @@ class OC_OCSClient{ $app['preview3']=$tmp->smallpreviewpic3; $app['changed']=strtotime($tmp->changed); $app['description']=$tmp->description; + $app['detailpage']=$tmp->detailpage; return $app; } diff --git a/settings/apps.php b/settings/apps.php index 0889b0c45ed..cc161026020 100644 --- a/settings/apps.php +++ b/settings/apps.php @@ -39,6 +39,9 @@ foreach($registeredApps as $app){ $info=OC_App::getAppInfo($app); $active=(OC_Appconfig::getValue($app,'enabled','no')=='yes')?true:false; $info['active']=$active; + $info['internal']=true; + $info['internallabel']='Internal App'; + $info['preview']='trans.png'; $apps[]=$info; } } @@ -64,6 +67,7 @@ usort($apps, 'app_sort'); } if(!$local) { + if($app['preview']=='') $pre='trans.png'; else $pre=$app['preview']; $apps[]=array( 'name'=>$app['name'], 'id'=>$app['id'], @@ -71,6 +75,9 @@ usort($apps, 'app_sort'); 'description'=>$app['description'], 'author'=>$app['personid'], 'license'=>$app['license'], + 'preview'=>$pre, + 'internal'=>false, + 'internallabel'=>'3rd Party App', ); } } diff --git a/settings/css/settings.css b/settings/css/settings.css index 42576953d04..62e84654d55 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -40,7 +40,8 @@ select.quota.active { background: #fff; } /* APPS */ li { color:#888; } li.active { color:#000; } +small.externalapp { color:#FFF; background-color:#BBB; font-weight:bold; font-size:6pt; padding:4px; border-radius: 4px;} span.version { margin-left:3em; color:#ddd; } /* LOF */ -#log { white-space:normal; } \ No newline at end of file +#log { white-space:normal; } diff --git a/settings/js/apps.js b/settings/js/apps.js index 12d09ac69db..df5300911aa 100644 --- a/settings/js/apps.js +++ b/settings/js/apps.js @@ -13,8 +13,11 @@ $(document).ready(function(){ var app=$(this).data('app'); $('#rightcontent p').show(); $('#rightcontent span.name').text(app.name); + $('#rightcontent small.externalapp').text(app.internallabel); $('#rightcontent span.version').text(app.version); $('#rightcontent p.description').text(app.description); + $('#rightcontent img.preview').attr('src',app.preview); + $('#rightcontent small.externalapp').attr('style','visibility:visible'); $('#rightcontent span.author').text(app.author); $('#rightcontent span.licence').text(app.licence); diff --git a/settings/templates/apps.php b/settings/templates/apps.php index 1e49b4c8928..d25ca1bc7fb 100644 --- a/settings/templates/apps.php +++ b/settings/templates/apps.php @@ -5,7 +5,7 @@ */?>
      @@ -14,12 +14,14 @@ + 3rd party' ?>
    -

    t('Select an App');?>

    +

    t('Select an App');?>

    +
    diff --git a/settings/templates/help.php b/settings/templates/help.php index 754bf8b6376..df640d97469 100644 --- a/settings/templates/help.php +++ b/settings/templates/help.php @@ -5,6 +5,7 @@ */?>
    + t( 'Documentation' ); ?> t( 'Ask a question' ); ?> t('You use');?> t('of the available');?>

    +
    + t('Desktop and Mobile Syncing Clients');?> + t('Download');?> +
    + +
    t('Your password got changed');?>
    @@ -41,7 +47,7 @@

    WebDAV -
    +
    t('use this address to connect to your ownCloud in your file manager');?>

    diff --git a/settings/trans.png b/settings/trans.png new file mode 100644 index 00000000000..e6920168bf2 Binary files /dev/null and b/settings/trans.png differ