diff options
author | Bart Visscher <bartv@thisnet.nl> | 2012-03-07 21:49:46 +0100 |
---|---|---|
committer | Bart Visscher <bartv@thisnet.nl> | 2012-03-07 21:49:46 +0100 |
commit | 9908adb320171c0a12fa7d78964b5ddc3527f9fd (patch) | |
tree | 06544ba73bced1ddc104cb2bf87e3c7672c026ad /apps | |
parent | faf6055baa224fbf4248a70d28ae4416c9c7eb1c (diff) | |
parent | d8cfe77ba5348d29a9e2b046e2c7efc1dd4758cb (diff) | |
download | nextcloud-server-9908adb320171c0a12fa7d78964b5ddc3527f9fd.tar.gz nextcloud-server-9908adb320171c0a12fa7d78964b5ddc3527f9fd.zip |
Merge branch 'master' into vcategories
Conflicts:
apps/contacts/lib/vcard.php
Diffstat (limited to 'apps')
154 files changed, 2903 insertions, 1197 deletions
diff --git a/apps/bookmarks/addBm.php b/apps/bookmarks/addBm.php index f56022c42c2..861b677222d 100644 --- a/apps/bookmarks/addBm.php +++ b/apps/bookmarks/addBm.php @@ -28,19 +28,6 @@ OC_Util::checkLoggedIn(); OC_Util::checkAppEnabled('bookmarks'); require_once('bookmarksHelper.php'); +addBookmark($_GET['url'], '', 'Read-Later'); -OC_App::setActiveNavigationEntry( 'bookmarks_index' ); - -OC_Util::addScript('bookmarks','addBm'); -OC_Util::addStyle('bookmarks', 'bookmarks'); - -$tmpl = new OC_Template( 'bookmarks', 'addBm', 'user' ); - -$url = isset($_GET['url']) ? urldecode($_GET['url']) : ''; -$metadata = getURLMetadata($url); - -$tmpl->assign('URL', htmlentities($metadata['url'],ENT_COMPAT,'utf-8')); -$title = isset($metadata['title']) ? $metadata['title'] : (isset($_GET['title']) ? $_GET['title'] : ''); -$tmpl->assign('TITLE', htmlentities($title,ENT_COMPAT,'utf-8')); - -$tmpl->printPage(); +include 'templates/addBm.php'; diff --git a/apps/bookmarks/ajax/addBookmark.php b/apps/bookmarks/ajax/addBookmark.php index 45b16ae5fa6..8cda7f0f060 100644 --- a/apps/bookmarks/ajax/addBookmark.php +++ b/apps/bookmarks/ajax/addBookmark.php @@ -30,50 +30,6 @@ require_once('../../../lib/base.php'); OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('bookmarks'); -$CONFIG_DBTYPE = OC_Config::getValue( "dbtype", "sqlite" ); -if( $CONFIG_DBTYPE == 'sqlite' or $CONFIG_DBTYPE == 'sqlite3' ){ - $_ut = "strftime('%s','now')"; -} elseif($CONFIG_DBTYPE == 'pgsql') { - $_ut = 'date_part(\'epoch\',now())::integer'; -} else { - $_ut = "UNIX_TIMESTAMP()"; -} - -//FIXME: Detect when user adds a known URL -$query = OC_DB::prepare(" - INSERT INTO *PREFIX*bookmarks - (url, title, user_id, public, added, lastmodified) - VALUES (?, ?, ?, 0, $_ut, $_ut) - "); - - -$params=array( - htmlspecialchars_decode($_GET["url"]), - htmlspecialchars_decode($_GET["title"]), - OC_User::getUser() - ); -$query->execute($params); - -$b_id = OC_DB::insertid('*PREFIX*bookmarks'); - - -if($b_id !== false) { - $query = OC_DB::prepare(" - INSERT INTO *PREFIX*bookmarks_tags - (bookmark_id, tag) - VALUES (?, ?) - "); - - $tags = explode(' ', urldecode($_GET["tags"])); - foreach ($tags as $tag) { - if(empty($tag)) { - //avoid saving blankspaces - continue; - } - $params = array($b_id, trim($tag)); - $query->execute($params); - } - - OC_JSON::success(array('data' => $b_id)); -} - +require_once('../bookmarksHelper.php'); +$id = addBookmark($_GET['url'], $_GET['title'], $_GET['tags']); +OC_JSON::success(array('data' => $id));
\ No newline at end of file diff --git a/apps/bookmarks/ajax/getMeta.php b/apps/bookmarks/ajax/getMeta.php deleted file mode 100644 index ca797315ef4..00000000000 --- a/apps/bookmarks/ajax/getMeta.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -/** -* ownCloud - bookmarks plugin -* -* @author Arthur Schiwon -* @copyright 2011 Arthur Schiwon blizzz@arthur-schiwon.de -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE -* License as published by the Free Software Foundation; either -* version 3 of the License, or any later version. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU AFFERO GENERAL PUBLIC LICENSE for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library. If not, see <http://www.gnu.org/licenses/>. -* -*/ - -//no apps or filesystem -$RUNTIME_NOSETUPFS=true; - -require_once('../../../lib/base.php'); - -// Check if we are a user -OC_JSON::checkLoggedIn(); -OC_JSON::checkAppEnabled('bookmarks'); - -// $metadata = array(); - -require '../bookmarksHelper.php'; -$metadata = getURLMetadata(htmlspecialchars_decode($_GET["url"])); - - -OC_JSON::success(array('data' => $metadata)); diff --git a/apps/bookmarks/appinfo/app.php b/apps/bookmarks/appinfo/app.php index 479d8ed4767..09d7b5df525 100644 --- a/apps/bookmarks/appinfo/app.php +++ b/apps/bookmarks/appinfo/app.php @@ -1,6 +1,6 @@ <?php /** -* Copyright (c) 2011 Marvin Thomas Rabe <m.rabe@echtzeitraum.de> +* Copyright (c) 2011 Marvin Thomas Rabe <mrabe@marvinrabe.de> * Copyright (c) 2011 Arthur Schiwon <blizzz@arthur-schiwon.de> * This file is licensed under the Affero General Public License version 3 or * later. @@ -8,6 +8,7 @@ */ OC::$CLASSPATH['OC_Bookmarks_Bookmarks'] = 'apps/bookmarks/lib/bookmarks.php'; +OC::$CLASSPATH['OC_Search_Provider_Bookmarks'] = 'apps/bookmarks/lib/search.php'; OC_App::register( array( 'order' => 70, 'id' => 'bookmark', 'name' => 'Bookmarks' )); @@ -15,5 +16,5 @@ $l = new OC_l10n('bookmarks'); OC_App::addNavigationEntry( array( 'id' => 'bookmarks_index', 'order' => 70, 'href' => OC_Helper::linkTo( 'bookmarks', 'index.php' ), 'icon' => OC_Helper::imagePath( 'bookmarks', 'bookmarks.png' ), 'name' => $l->t('Bookmarks'))); OC_App::registerPersonal('bookmarks', 'settings'); -require_once('apps/bookmarks/lib/search.php'); OC_Util::addScript('bookmarks','bookmarksearch'); +OC_Search::registerProvider('OC_Search_Provider_Bookmarks'); diff --git a/apps/bookmarks/appinfo/database.xml b/apps/bookmarks/appinfo/database.xml index fca38ad84b2..f2fc68e4b58 100644 --- a/apps/bookmarks/appinfo/database.xml +++ b/apps/bookmarks/appinfo/database.xml @@ -75,14 +75,6 @@ <sorting>descending</sorting> </field> </index> -<!-- <index> - <name>url</name> - <unique>true</unique> - <field> - <name>url</name> - <sorting>ascending</sorting> - </field> - </index>--> </declaration> </table> diff --git a/apps/bookmarks/appinfo/info.xml b/apps/bookmarks/appinfo/info.xml index 23aa6c219a9..862ab805a60 100644 --- a/apps/bookmarks/appinfo/info.xml +++ b/apps/bookmarks/appinfo/info.xml @@ -3,8 +3,8 @@ <id>bookmarks</id> <name>Bookmarks</name> <description>Bookmark manager for ownCloud</description> - <version>0.1</version> + <version>0.2</version> <licence>AGPL</licence> - <author>Arthur Schiwon</author> + <author>Arthur Schiwon, Marvin Thomas Rabe</author> <require>2</require> </info>
\ No newline at end of file diff --git a/apps/bookmarks/bookmarksHelper.php b/apps/bookmarks/bookmarksHelper.php index ac512fbc241..8def7401e2f 100644 --- a/apps/bookmarks/bookmarksHelper.php +++ b/apps/bookmarks/bookmarksHelper.php @@ -70,3 +70,55 @@ function getURLMetadata($url) { return $metadata; } + +function addBookmark($url, $title='', $tags='') { + $CONFIG_DBTYPE = OC_Config::getValue( "dbtype", "sqlite" ); + if( $CONFIG_DBTYPE == 'sqlite' or $CONFIG_DBTYPE == 'sqlite3' ){ + $_ut = "strftime('%s','now')"; + } elseif($CONFIG_DBTYPE == 'pgsql') { + $_ut = 'date_part(\'epoch\',now())::integer'; + } else { + $_ut = "UNIX_TIMESTAMP()"; + } + + //FIXME: Detect when user adds a known URL + $query = OC_DB::prepare(" + INSERT INTO *PREFIX*bookmarks + (url, title, user_id, public, added, lastmodified) + VALUES (?, ?, ?, 0, $_ut, $_ut) + "); + + if(empty($title)) { + $metadata = getURLMetadata($url); + $title = $metadata['title']; + } + + $params=array( + htmlspecialchars_decode($url), + htmlspecialchars_decode($title), + OC_User::getUser() + ); + $query->execute($params); + + $b_id = OC_DB::insertid('*PREFIX*bookmarks'); + + if($b_id !== false) { + $query = OC_DB::prepare(" + INSERT INTO *PREFIX*bookmarks_tags + (bookmark_id, tag) + VALUES (?, ?) + "); + + $tags = explode(' ', urldecode($tags)); + foreach ($tags as $tag) { + if(empty($tag)) { + //avoid saving blankspaces + continue; + } + $params = array($b_id, trim($tag)); + $query->execute($params); + } + + return $b_id; + } +}
\ No newline at end of file diff --git a/apps/bookmarks/css/bookmarks.css b/apps/bookmarks/css/bookmarks.css index 8dfdc8a07b9..3a3e0fbf6b3 100644 --- a/apps/bookmarks/css/bookmarks.css +++ b/apps/bookmarks/css/bookmarks.css @@ -1,4 +1,8 @@ -#content { overflow: auto; } +#content { overflow: auto; height: 100%; } +#firstrun { width: 80%; margin: 5em auto auto auto; text-align: center; font-weight:bold; font-size:1.5em; color:#777;} +#firstrun small { display: block; font-weight: normal; font-size: 0.5em; margin-bottom: 1.5em; } +#firstrun .button { font-size: 0.7em; } +#firstrun #selections { font-size:0.8em; font-weight: normal; width: 100%; margin: 2em auto auto auto; clear: both; } .bookmarks_headline { font-size: large; @@ -12,13 +16,10 @@ padding: 0.5ex; } -.bookmarks_add { - display: none; - margin-top: 45px; -} - .bookmarks_list { - margin-top: 36px; + overflow: auto; + position: fixed; + top: 6.5em; } .bookmarks_addBml { @@ -32,7 +33,7 @@ } .bookmarks_input { - width: 20em; + width: 8em; } .bookmark_actions { @@ -84,16 +85,3 @@ display: none; margin-left: 5px; } - -#footer { - color: #999; - font-size: medium; - text-align: center; - position: absolute; - bottom: 10px; - left: 0px; - width: 100%; - height: 20px; - visibility: visible; - display: block -} diff --git a/apps/bookmarks/js/addBm.js b/apps/bookmarks/js/addBm.js index 6e13b59bb2e..d64e55e8920 100644 --- a/apps/bookmarks/js/addBm.js +++ b/apps/bookmarks/js/addBm.js @@ -4,13 +4,12 @@ $(document).ready(function() { function addBookmark(event) { var url = $('#bookmark_add_url').val(); - var title = $('#bookmark_add_title').val(); var tags = $('#bookmark_add_tags').val(); $.ajax({ url: 'ajax/addBookmark.php', - data: 'url=' + encodeURI(url) + '&title=' + encodeURI(title) + '&tags=' + encodeURI(tags), + data: 'url=' + encodeURI(url) + '&tags=' + encodeURI(tags), success: function(data){ - location.href='index.php'; + window.close(); } }); }
\ No newline at end of file diff --git a/apps/bookmarks/js/bookmarks.js b/apps/bookmarks/js/bookmarks.js index fadbbd5513a..fa5adde2545 100644 --- a/apps/bookmarks/js/bookmarks.js +++ b/apps/bookmarks/js/bookmarks.js @@ -3,19 +3,16 @@ var bookmarks_loading = false; var bookmarks_sorting = 'bookmarks_sorting_recent'; -$(document).ready(function() { - $('.bookmarks_addBtn').click(function(event){ - $('.bookmarks_add').slideToggle(); - }); - +$(document).ready(function() { $('#bookmark_add_submit').click(addOrEditBookmark); - $(window).scroll(updateOnBottom); - - $('#bookmark_add_url').focusout(getMetadata); + $(window).resize(function () { + fillWindow($('.bookmarks_list')); + }); + $(window).resize(); + $($('.bookmarks_list')).scroll(updateOnBottom); $('.bookmarks_list').empty(); getBookmarks(); - }); function getBookmarks() { @@ -28,13 +25,19 @@ function getBookmarks() { url: 'ajax/updateList.php', data: 'tag=' + encodeURI($('#bookmarkFilterTag').val()) + '&page=' + bookmarks_page + '&sort=' + bookmarks_sorting, success: function(bookmarks){ - bookmarks_page += 1; + if (bookmarks.data.length) { + bookmarks_page += 1; + } $('.bookmark_link').unbind('click', recordClick); $('.bookmark_delete').unbind('click', delBookmark); $('.bookmark_edit').unbind('click', showBookmark); for(var i in bookmarks.data) { updateBookmarksList(bookmarks.data[i]); + $("#firstrun").hide(); + } + if($('.bookmarks_list').is(':empty')) { + $("#firstrun").show(); } $('.bookmark_link').click(recordClick); @@ -42,24 +45,13 @@ function getBookmarks() { $('.bookmark_edit').click(showBookmark); bookmarks_loading = false; + if (bookmarks.data.length) { + updateOnBottom() + } } }); } -function getMetadata() { - var url = encodeEntities($('#bookmark_add_url').val()); - $('.loading_meta').css('display','inline'); - $.ajax({ - url: 'ajax/getMeta.php', - data: 'url=' + encodeURIComponent(url), - success: function(pageinfo){ - $('#bookmark_add_url').val(pageinfo.data.url); - $('#bookmark_add_title').val(pageinfo.data.title); - $('.loading_meta').css('display','none'); - } - }); -} - // function addBookmark() { // Instead of creating editBookmark() function, Converted the one above to // addOrEditBookmark() to make .js file more compact. @@ -69,35 +61,17 @@ function addOrEditBookmark(event) { var url = encodeEntities($('#bookmark_add_url').val()); var title = encodeEntities($('#bookmark_add_title').val()); var tags = encodeEntities($('#bookmark_add_tags').val()); - var taglist = tags.split(' '); - var tagshtml = ''; - for ( var i=0, len=taglist.length; i<len; ++i ){ - tagshtml += '<a class="bookmark_tag" href="?tag=' + encodeURI(taglist[i]) + '">' + taglist[i] + '</a> '; - } + $("#firstrun").hide(); if (id == 0) { $.ajax({ url: 'ajax/addBookmark.php', data: 'url=' + encodeURI(url) + '&title=' + encodeURI(title) + '&tags=' + encodeURI(tags), success: function(response){ - var bookmark_id = response.data; - $('.bookmarks_add').slideToggle(); - $('.bookmarks_add').children('p').children('.bookmarks_input').val(''); - $('.bookmarks_list').prepend( - '<div class="bookmark_single" data-id="' + bookmark_id + '" >' + - '<p class="bookmark_actions">' + - '<span class="bookmark_delete">' + - '<img class="svg" src="'+OC.imagePath('core', 'actions/delete')+'" title="Delete">' + - '</span> ' + - '<span class="bookmark_edit">' + - '<img class="svg" src="'+OC.imagePath('core', 'actions/rename')+'" title="Edit">' + - '</span>' + - '</p>' + - '<p class="bookmark_title"><a href="' + url + '" target="_blank" class="bookmark_link">' + title + '</a></p>' + - '<p class="bookmark_tags">' + tagshtml + '</p>' + - '<p class="bookmark_url">' + url + '</p>' + - '</div>' - ); + $('.bookmarks_input').val(''); + $('.bookmarks_list').empty(); + bookmarks_page = 0; + getBookmarks(); } }); } @@ -106,18 +80,11 @@ function addOrEditBookmark(event) { url: 'ajax/editBookmark.php', data: 'id=' + id + '&url=' + encodeURI(url) + '&title=' + encodeURI(title) + '&tags=' + encodeURI(tags), success: function(){ - $('.bookmarks_add').slideToggle(); - $('.bookmarks_add').children('p').children('.bookmarks_input').val(''); + $('.bookmarks_input').val(''); $('#bookmark_add_id').val('0'); - - var record = $('.bookmark_single[data-id = "' + id + '"]'); - record.children('.bookmark_url:first').text(url); - - var record_title = record.children('.bookmark_title:first').children('a:first'); - record_title.attr('href', url); - record_title.text(title); - - record.children('.bookmark_tags:first').html(tagshtml); + $('.bookmarks_list').empty(); + bookmarks_page = 0; + getBookmarks(); } }); } @@ -129,7 +96,12 @@ function delBookmark(event) { $.ajax({ url: 'ajax/delBookmark.php', data: 'url=' + encodeURI($(this).parent().parent().children('.bookmark_url:first').text()), - success: function(data){ record.animate({ opacity: 'hide' }, 'fast'); } + success: function(data){ + record.remove(); + if($('.bookmarks_list').is(':empty')) { + $("#firstrun").show(); + } + } }); } @@ -159,15 +131,16 @@ function updateBookmarksList(bookmark) { if(!hasProtocol(bookmark.url)) { bookmark.url = 'http://' + bookmark.url; } + if(bookmark.title == '') bookmark.title = bookmark.url; $('.bookmarks_list').append( '<div class="bookmark_single" data-id="' + bookmark.id +'" >' + '<p class="bookmark_actions">' + - '<span class="bookmark_delete">' + - '<img class="svg" src="'+OC.imagePath('core', 'actions/delete')+'" title="Delete">' + - '</span> ' + '<span class="bookmark_edit">' + '<img class="svg" src="'+OC.imagePath('core', 'actions/rename')+'" title="Edit">' + '</span>' + + '<span class="bookmark_delete">' + + '<img class="svg" src="'+OC.imagePath('core', 'actions/delete')+'" title="Delete">' + + '</span> ' + '</p>' + '<p class="bookmark_title">'+ '<a href="' + encodeEntities(bookmark.url) + '" target="_blank" class="bookmark_link">' + encodeEntities(bookmark.title) + '</a>' + @@ -182,7 +155,11 @@ function updateBookmarksList(bookmark) { function updateOnBottom() { //check wether user is on bottom of the page - if ($('body').height() <= ($(window).height() + $(window).scrollTop())) { + var top = $('.bookmarks_list>:last-child').position().top; + var height = $('.bookmarks_list').height(); + // use a bit of margin to begin loading before we are really at the + // bottom + if (top < height * 1.2) { getBookmarks(); } } diff --git a/apps/bookmarks/lib/search.php b/apps/bookmarks/lib/search.php index 59495db82ea..235587855d9 100644 --- a/apps/bookmarks/lib/search.php +++ b/apps/bookmarks/lib/search.php @@ -20,8 +20,8 @@ * */ -class OC_Search_Provider_Bookmarks extends OC_Search_Provider{ - function search($query){ +class OC_Search_Provider_Bookmarks implements OC_Search_Provider{ + static function search($query){ $results=array(); $offset = 0; @@ -45,6 +45,3 @@ class OC_Search_Provider_Bookmarks extends OC_Search_Provider{ return $results; } } -new OC_Search_Provider_Bookmarks(); - -?> diff --git a/apps/bookmarks/settings.php b/apps/bookmarks/settings.php index 0ace04fa2c8..9d945f64dad 100644 --- a/apps/bookmarks/settings.php +++ b/apps/bookmarks/settings.php @@ -1,6 +1,6 @@ <?php /** - * Copyright (c) 2011 Marvin Thomas Rabe <m.rabe@echtzeitraum.de> + * Copyright (c) 2011 Marvin Thomas Rabe <mrabe@marvinrabe.de> * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. @@ -8,6 +8,4 @@ $tmpl = new OC_Template( 'bookmarks', 'settings'); -//OC_Util::addScript('bookmarks','settings'); - return $tmpl->fetchPage(); diff --git a/apps/bookmarks/templates/addBm.php b/apps/bookmarks/templates/addBm.php index c285c3579c5..dbe673f53a8 100644 --- a/apps/bookmarks/templates/addBm.php +++ b/apps/bookmarks/templates/addBm.php @@ -1,7 +1,11 @@ -<div class="bookmarks_addBm"> - <p><label class="bookmarks_label"><?php echo $l->t('Address'); ?></label><input type="text" id="bookmark_add_url" class="bookmarks_input" value="<?php echo $_['URL']; ?>"/></p> - <p><label class="bookmarks_label"><?php echo $l->t('Title'); ?></label><input type="text" id="bookmark_add_title" class="bookmarks_input" value="<?php echo $_['TITLE']; ?>" /></p> - <p><label class="bookmarks_label"><?php echo $l->t('Tags'); ?></label><input type="text" id="bookmark_add_tags" class="bookmarks_input" /></p> - <p><label class="bookmarks_label"> </label><label class="bookmarks_hint"><?php echo $l->t('Hint: Use space to separate tags.'); ?></label></p> - <p><label class="bookmarks_label"></label><input type="submit" value="<?php echo $l->t('Add bookmark'); ?>" id="bookmark_add_submit" /></p> -</div> +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <title>Read later - ownCloud</title> + <link rel="stylesheet" href="css/readlater.css"> + </head> + <body> + <div class="message"><h1>Saved!</h1></div> + </body> +</html>
\ No newline at end of file diff --git a/apps/bookmarks/templates/bookmarklet.php b/apps/bookmarks/templates/bookmarklet.php new file mode 100644 index 00000000000..5ea67f04df2 --- /dev/null +++ b/apps/bookmarks/templates/bookmarklet.php @@ -0,0 +1,8 @@ +<?php + +function createBookmarklet() { + $l = new OC_L10N('bookmarks'); + echo '<small>' . $l->t('Drag this to your browser bookmarks and click it, when you want to bookmark a webpage quickly:') . '</small>' + . '<a class="bookmarklet" href="javascript:(function(){var a=window,b=document,c=encodeURIComponent,d=a.open(\'' . OC_Helper::linkToAbsolute('bookmarks', 'addBm.php') . '?output=popup&url=\'+c(b.location),\'bkmk_popup\',\'left=\'+((a.screenX||a.screenLeft)+10)+\',top=\'+((a.screenY||a.screenTop)+10)+\',height=230px,width=230px,resizable=1,alwaysRaised=1\');a.setTimeout(function(){d.focus()},300);})();">' + . $l->t('Read later') . '</a>'; +} diff --git a/apps/bookmarks/templates/list.php b/apps/bookmarks/templates/list.php index d44a0ecbcdb..1abdbb7f838 100644 --- a/apps/bookmarks/templates/list.php +++ b/apps/bookmarks/templates/list.php @@ -1,6 +1,6 @@ <?php /** - * Copyright (c) 2011 Marvin Thomas Rabe <m.rabe@echtzeitraum.de> + * Copyright (c) 2011 Marvin Thomas Rabe <mrabe@marvinrabe.de> * Copyright (c) 2011 Arthur Schiwon <blizzz@arthur-schiwon.de> * This file is licensed under the Affero General Public License version 3 or * later. @@ -9,21 +9,18 @@ ?> <input type="hidden" id="bookmarkFilterTag" value="<?php if(isset($_GET['tag'])) echo htmlentities($_GET['tag']); ?>" /> <div id="controls"> - <input type="button" class="bookmarks_addBtn" value="<?php echo $l->t('Add bookmark'); ?>"/> -</div> -<div class="bookmarks_add"> <input type="hidden" id="bookmark_add_id" value="0" /> - <p><label class="bookmarks_label"><?php echo $l->t('Address'); ?></label><input type="text" id="bookmark_add_url" class="bookmarks_input" /></p> - <p><label class="bookmarks_label"><?php echo $l->t('Title'); ?></label><input type="text" id="bookmark_add_title" class="bookmarks_input" /> - <img class="loading_meta" src="<?php echo OC_Helper::imagePath('core', 'loading.gif'); ?>" /></p> - <p><label class="bookmarks_label"><?php echo $l->t('Tags'); ?></label><input type="text" id="bookmark_add_tags" class="bookmarks_input" /></p> - <p><label class="bookmarks_label"> </label><label class="bookmarks_hint"><?php echo $l->t('Hint: Use space to separate tags.'); ?></label></p> - <p><label class="bookmarks_label"></label><input type="submit" value="<?php echo $l->t('Add bookmark'); ?>" id="bookmark_add_submit" /></p> + <input type="text" id="bookmark_add_url" placeholder="<?php echo $l->t('Address'); ?>" class="bookmarks_input" /> + <input type="text" id="bookmark_add_title" placeholder="<?php echo $l->t('Title'); ?>" class="bookmarks_input" /> + <input type="text" id="bookmark_add_tags" placeholder="<?php echo $l->t('Tags'); ?>" class="bookmarks_input" /> + <input type="submit" value="<?php echo $l->t('Add bookmark'); ?>" id="bookmark_add_submit" /> </div> <div class="bookmarks_list"> - <?php echo $l->t('You have no bookmarks'); ?> </div> -<div id="footer"> -Bookmark pages more easily. Drag this bookmarklet to the Bookmarks bar of your browser: -<a style='background-color:#dddddd;border:1px groove #999; padding:5px;padding-top:0px;padding-bottom:2px; text-decoration:none; margin-top:5px' href='javascript:(function(){var a=window,b=document,c=encodeURIComponent,d=a.open("<?php echo OC_Helper::linkToAbsolute('bookmarks', 'addBm.php') ?>?output=popup&url="+c(b.location)+"&title="+c(b.title),"bkmk_popup","left="+((a.screenX||a.screenLeft)+10)+",top="+((a.screenY||a.screenTop)+10)+",height=510px,width=550px,resizable=1,alwaysRaised=1");a.setTimeout(function(){d.focus()},300)})();'>ownCloud bookmark</a> +<div id="firstrun" style="display: none;"> + <?php + echo $l->t('You have no bookmarks'); + require_once('bookmarklet.php'); + createBookmarklet(); + ?> </div> diff --git a/apps/bookmarks/templates/settings.php b/apps/bookmarks/templates/settings.php index a985ee9d61b..31edf7478bf 100644 --- a/apps/bookmarks/templates/settings.php +++ b/apps/bookmarks/templates/settings.php @@ -1,6 +1,6 @@ <?php /** - * Copyright (c) 2011 Marvin Thomas Rabe <m.rabe@echtzeitraum.de> + * Copyright (c) 2011 Marvin Thomas Rabe <mrabe@marvinrabe.de> * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. @@ -8,7 +8,10 @@ ?> <form id="bookmarks"> <fieldset class="personalblock"> - <span class="bold"><?php echo $l->t('Bookmarklet:');?></span> <a class="bookmarks_addBml" href="javascript:(function(){url=encodeURIComponent(location.href);window.open('<?php echo OC_Helper::linkToAbsolute('bookmarks', 'addBm.php'); ?>?url='+url, 'owncloud-bookmarks') })()"><?php echo $l->t('Add page to ownCloud'); ?></a> - <br/><em><?php echo $l->t('Drag this to your browser bookmarks and click it, when you want to bookmark a webpage.'); ?></em><br /> + <span class="bold"><?php echo $l->t('Bookmarklet <br />');?></span> + <?php + require_once('bookmarklet.php'); + createBookmarklet(); + ?> </fieldset> </form> diff --git a/apps/calendar/ajax/activation.php b/apps/calendar/ajax/calendar/activation.php index ada2e44547b..7677d85aff3 100644 --- a/apps/calendar/ajax/activation.php +++ b/apps/calendar/ajax/calendar/activation.php @@ -6,7 +6,7 @@ * See the COPYING-README file. */ -require_once ("../../../lib/base.php"); +require_once('../../../../lib/base.php'); OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('calendar'); $calendarid = $_POST['calendarid']; diff --git a/apps/calendar/ajax/deletecalendar.php b/apps/calendar/ajax/calendar/delete.php index 901cbbfcb08..a2f5311731c 100644 --- a/apps/calendar/ajax/deletecalendar.php +++ b/apps/calendar/ajax/calendar/delete.php @@ -5,7 +5,7 @@ * later. * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('calendar'); diff --git a/apps/calendar/ajax/editcalendar.php b/apps/calendar/ajax/calendar/edit.form.php index 7aeb5bbe305..8922b3eba4e 100644 --- a/apps/calendar/ajax/editcalendar.php +++ b/apps/calendar/ajax/calendar/edit.form.php @@ -6,7 +6,7 @@ * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('calendar'); diff --git a/apps/calendar/ajax/calendar/edit.php b/apps/calendar/ajax/calendar/edit.php new file mode 100644 index 00000000000..8922b3eba4e --- /dev/null +++ b/apps/calendar/ajax/calendar/edit.php @@ -0,0 +1,20 @@ +<?php +/** + * Copyright (c) 2011 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +require_once('../../../../lib/base.php'); +OC_JSON::checkLoggedIn(); +OC_JSON::checkAppEnabled('calendar'); + +$calendarcolor_options = OC_Calendar_Calendar::getCalendarColorOptions(); +$calendar = OC_Calendar_App::getCalendar($_GET['calendarid']); +$tmpl = new OC_Template("calendar", "part.editcalendar"); +$tmpl->assign('new', false); +$tmpl->assign('calendarcolor_options', $calendarcolor_options); +$tmpl->assign('calendar', $calendar); +$tmpl->printPage(); +?> diff --git a/apps/calendar/ajax/newcalendar.php b/apps/calendar/ajax/calendar/new.form.php index af3ba4fbbea..6e7423cbe92 100644 --- a/apps/calendar/ajax/newcalendar.php +++ b/apps/calendar/ajax/calendar/new.form.php @@ -6,7 +6,7 @@ * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); $l10n = new OC_L10N('calendar'); OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('calendar'); diff --git a/apps/calendar/ajax/createcalendar.php b/apps/calendar/ajax/calendar/new.php index 8d7b12f9b89..228e6247724 100644 --- a/apps/calendar/ajax/createcalendar.php +++ b/apps/calendar/ajax/calendar/new.php @@ -6,7 +6,7 @@ * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); // Check if we are a user OC_JSON::checkLoggedIn(); diff --git a/apps/calendar/ajax/choosecalendar.php b/apps/calendar/ajax/calendar/overview.php index 9281c8edbdc..2f73f5d0710 100644 --- a/apps/calendar/ajax/choosecalendar.php +++ b/apps/calendar/ajax/calendar/overview.php @@ -6,7 +6,7 @@ * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); $l10n = new OC_L10N('calendar'); OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('calendar'); diff --git a/apps/calendar/ajax/updatecalendar.php b/apps/calendar/ajax/calendar/update.php index 20c225d8a29..f400c8c14b4 100644 --- a/apps/calendar/ajax/updatecalendar.php +++ b/apps/calendar/ajax/calendar/update.php @@ -6,7 +6,7 @@ * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); // Check if we are a user OC_JSON::checkLoggedIn(); @@ -25,16 +25,8 @@ foreach($calendars as $cal){ } $calendarid = $_POST['id']; -$calendarcolor = $_POST['color']; -if (preg_match('/^#?([0-9a-f]{6})/', $calendarcolor, $matches)) { - $calendarcolor = '#'.$matches[1]; -} -else { - $calendarcolor = null; -} - $calendar = OC_Calendar_App::getCalendar($calendarid);//access check -OC_Calendar_Calendar::editCalendar($calendarid, strip_tags($_POST['name']), null, null, null, $calendarcolor); +OC_Calendar_Calendar::editCalendar($calendarid, strip_tags($_POST['name']), null, null, null, $_POST['color']); OC_Calendar_Calendar::setCalendarActive($calendarid, $_POST['active']); $calendar = OC_Calendar_App::getCalendar($calendarid); diff --git a/apps/calendar/ajax/changeview.php b/apps/calendar/ajax/changeview.php index ef05c7cd496..ae48b229b16 100644 --- a/apps/calendar/ajax/changeview.php +++ b/apps/calendar/ajax/changeview.php @@ -9,7 +9,16 @@ require_once ("../../../lib/base.php"); OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('calendar'); -$currentview = $_GET["v"]; -OC_Preferences::setValue(OC_USER::getUser(), "calendar", "currentview", $currentview); +$view = $_GET['v']; +switch($view){ + case 'agendaWeek': + case 'month'; + case 'list': + break; + default: + OC_JSON::error(array('message'=>'unexspected parameter: ' . $view)); + exit; +} +OC_Preferences::setValue(OC_USER::getUser(), 'calendar', 'currentview', $view); OC_JSON::success(); ?> diff --git a/apps/calendar/ajax/deleteevent.php b/apps/calendar/ajax/event/delete.php index b25a5af1a29..862dec6bf5b 100644 --- a/apps/calendar/ajax/deleteevent.php +++ b/apps/calendar/ajax/event/delete.php @@ -5,7 +5,7 @@ * later. * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); $l10n = new OC_L10N('calendar'); diff --git a/apps/calendar/ajax/editeventform.php b/apps/calendar/ajax/event/edit.form.php index 19f6a80a167..837edbbbf05 100644 --- a/apps/calendar/ajax/editeventform.php +++ b/apps/calendar/ajax/event/edit.form.php @@ -6,7 +6,7 @@ * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); if(!OC_USER::isLoggedIn()) { die('<script type="text/javascript">document.location = oc_webroot;</script>'); @@ -243,16 +243,6 @@ if($repeat['repeat'] != 'doesnotrepeat'){ $tmpl->assign('repeat_bymonth', $repeat['bymonth']); $tmpl->assign('repeat_byweekno', $repeat['byweekno']); } -else { - $tmpl->assign('repeat_month', 'monthday'); - $tmpl->assign('repeat_weekdays', array()); - $tmpl->assign('repeat_interval', 1); - $tmpl->assign('repeat_end', 'never'); - $tmpl->assign('repeat_count', '10'); - $tmpl->assign('repeat_weekofmonth', 'auto'); - $tmpl->assign('repeat_date', ''); - $tmpl->assign('repeat_year', 'bydate'); -} $tmpl->printpage(); -?> +?>
\ No newline at end of file diff --git a/apps/calendar/ajax/editevent.php b/apps/calendar/ajax/event/edit.php index 5a487da1758..64daffddef0 100644 --- a/apps/calendar/ajax/editevent.php +++ b/apps/calendar/ajax/event/edit.php @@ -6,7 +6,7 @@ * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('calendar'); diff --git a/apps/calendar/ajax/moveevent.php b/apps/calendar/ajax/event/move.php index f2256d4eee6..8150fdbaa32 100644 --- a/apps/calendar/ajax/moveevent.php +++ b/apps/calendar/ajax/event/move.php @@ -5,7 +5,7 @@ * later. * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); OC_JSON::checkLoggedIn(); $id = $_POST['id']; diff --git a/apps/calendar/ajax/neweventform.php b/apps/calendar/ajax/event/new.form.php index 3870c879b0e..c19928a727e 100644 --- a/apps/calendar/ajax/neweventform.php +++ b/apps/calendar/ajax/event/new.form.php @@ -6,7 +6,7 @@ * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); if(!OC_USER::isLoggedIn()) { die('<script type="text/javascript">document.location = oc_webroot;</script>'); diff --git a/apps/calendar/ajax/newevent.php b/apps/calendar/ajax/event/new.php index c7c4d29943a..59fda79da73 100644 --- a/apps/calendar/ajax/newevent.php +++ b/apps/calendar/ajax/event/new.php @@ -6,7 +6,7 @@ * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); $l10n = new OC_L10N('calendar'); diff --git a/apps/calendar/ajax/resizeevent.php b/apps/calendar/ajax/event/resize.php index 68347906529..aa2d420e77d 100644 --- a/apps/calendar/ajax/resizeevent.php +++ b/apps/calendar/ajax/event/resize.php @@ -5,7 +5,7 @@ * later. * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); OC_JSON::checkLoggedIn(); $id = $_POST['id']; diff --git a/apps/calendar/ajax/events.php b/apps/calendar/ajax/events.php index 7734129bd95..922df90b76b 100755 --- a/apps/calendar/ajax/events.php +++ b/apps/calendar/ajax/events.php @@ -7,7 +7,7 @@ */ require_once ('../../../lib/base.php'); -require_once('../../../3rdparty/when/When.php'); +require_once('when/When.php'); function create_return_event($event, $vevent){ $return_event = array(); @@ -27,25 +27,40 @@ function create_return_event($event, $vevent){ OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('calendar'); -$start = DateTime::createFromFormat('U', $_GET['start']); -$end = DateTime::createFromFormat('U', $_GET['end']); +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']); +} -$calendar = OC_Calendar_App::getCalendar($_GET['calendar_id']); -OC_Response::enableCaching(0); -OC_Response::setETagHeader($calendar['ctag']); +$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_Object::allInPeriod($_GET['calendar_id'], $start, $end); $user_timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); $return = array(); foreach($events as $event){ - $object = OC_VObject::parse($event['calendardata']); - $vevent = $object->VEVENT; + 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; - $dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent); $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; diff --git a/apps/calendar/ajax/guesstimezone.php b/apps/calendar/ajax/guesstimezone.php deleted file mode 100755 index 41aea26985f..00000000000 --- a/apps/calendar/ajax/guesstimezone.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php -/** - * Copyright (c) 2011, 2012 Georg Ehrke <ownclouddev at georgswebsite dot de> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ -function make_array_out_of_xml ($xml){ - $returnarray = array(); - $xml = (array)$xml ; - foreach ($xml as $property => $value){ - $value = (array)$value; - if(!isset($value[0])){ - $returnarray[$property] = make_array_out_of_xml($value); - }else{ - $returnarray[$property] = trim($value[0]); - } - } - return $returnarray; -} -require_once ("../../../lib/base.php"); -OC_JSON::checkLoggedIn(); -OC_JSON::checkAppEnabled('calendar'); -$l = new OC_L10N('calendar'); -$lat = $_GET['lat']; -$long = $_GET['long']; -if(OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'position') == $lat . '-' . $long && OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone') != null){ - OC_JSON::success(); - exit; -} -OC_Preferences::setValue(OC_USER::getUser(), 'calendar', 'position', $lat . '-' . $long); -$geolocation = file_get_contents('http://ws.geonames.org/timezone?lat=' . $lat . '&lng=' . $long); -//Information are by Geonames (http://www.geonames.org) and licensed under the Creative Commons Attribution 3.0 License -$geoxml = simplexml_load_string($geolocation); -$geoarray = make_array_out_of_xml($geoxml); -if($geoarray['timezone']['timezoneId'] == OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone')){ - OC_JSON::success(); - exit; -} -if(in_array($geoarray['timezone']['timezoneId'], DateTimeZone::listIdentifiers())){ - OC_Preferences::setValue(OC_USER::getUser(), 'calendar', 'timezone', $geoarray['timezone']['timezoneId']); - $message = array('message'=> $l->t('New Timezone:') . $geoarray['timezone']['timezoneId']); - OC_JSON::success($message); -}else{ - OC_JSON::error(); -} - -?> diff --git a/apps/calendar/ajax/importdialog.php b/apps/calendar/ajax/import/dialog.php index f6b8453fc22..2e002092150 100644 --- a/apps/calendar/ajax/importdialog.php +++ b/apps/calendar/ajax/import/dialog.php @@ -6,7 +6,7 @@ * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); OC_JSON::checkLoggedIn(); OC_Util::checkAppEnabled('calendar'); $l10n = new OC_L10N('calendar'); diff --git a/apps/calendar/ajax/import/import.php b/apps/calendar/ajax/import/import.php new file mode 100644 index 00000000000..c0797f6e425 --- /dev/null +++ b/apps/calendar/ajax/import/import.php @@ -0,0 +1,120 @@ +<?php +/** + * Copyright (c) 2012 Georg Ehrke <ownclouddev at georgswebsite dot de> + * 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(); +require_once('../../../../lib/base.php'); +OC_JSON::checkLoggedIn(); +OC_Util::checkAppEnabled('calendar'); +$nl = "\n"; +$progressfile = OC::$APPSROOT . '/apps/calendar/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']; +} +//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(); +$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; + } + if($attr == 'END'){ + $parts[count($parts) - 1]['end'] = $i; + $inelement = false; + } + } + } + $i++; +} +//import the calendar +if(is_writable('import_tmp/')){ + $progressfopen = fopen($progressfile, 'w'); + fwrite($progressfopen, '40'); + 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]; + } + } + $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){ + OC_Calendar_Object::add($id, $import); + } +} +//done the 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(); diff --git a/apps/calendar/ajax/settings/getfirstday.php b/apps/calendar/ajax/settings/getfirstday.php new file mode 100644 index 00000000000..cab5870509a --- /dev/null +++ b/apps/calendar/ajax/settings/getfirstday.php @@ -0,0 +1,12 @@ +<?php +/** + * Copyright (c) 2012 Georg Ehrke <ownclouddev at georgswebsite dot de> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +require_once('../../../../lib/base.php'); +OC_JSON::checkLoggedIn(); +$firstday = OC_Preferences::getValue( OC_User::getUser(), 'calendar', 'firstday', 'mo'); +OC_JSON::encodedPrint(array('firstday' => $firstday)); +?> diff --git a/apps/calendar/ajax/gettimezonedetection.php b/apps/calendar/ajax/settings/gettimezonedetection.php index ae58370712d..11255fe8ef3 100644 --- a/apps/calendar/ajax/gettimezonedetection.php +++ b/apps/calendar/ajax/settings/gettimezonedetection.php @@ -5,7 +5,7 @@ * later. * See the COPYING-README file. */ -require_once ("../../../lib/base.php"); +require_once('../../../../lib/base.php'); OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('calendar'); OC_JSON::success(array('detection' => OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezonedetection')));
\ No newline at end of file diff --git a/apps/calendar/ajax/settings/guesstimezone.php b/apps/calendar/ajax/settings/guesstimezone.php new file mode 100755 index 00000000000..d45a70e1ce3 --- /dev/null +++ b/apps/calendar/ajax/settings/guesstimezone.php @@ -0,0 +1,27 @@ +<?php +/** + * Copyright (c) 2011, 2012 Georg Ehrke <ownclouddev at georgswebsite dot de> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +require_once('../../../../lib/base.php'); + +OC_JSON::checkLoggedIn(); +OC_JSON::checkAppEnabled('calendar'); + +$l = new OC_L10N('calendar'); + +$lat = $_GET['lat']; +$lng = $_GET['long']; + +$timezone = OC_Geo::timezone($lat, $lng); + +if($timezone == OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone')){ + OC_JSON::success(); + exit; +} +OC_Preferences::setValue(OC_USER::getUser(), 'calendar', 'timezone', $timezone); +$message = array('message'=> $l->t('New Timezone:') . $timezone); +OC_JSON::success($message); +?>
\ No newline at end of file diff --git a/apps/calendar/ajax/settings/setfirstday.php b/apps/calendar/ajax/settings/setfirstday.php new file mode 100644 index 00000000000..3b652212205 --- /dev/null +++ b/apps/calendar/ajax/settings/setfirstday.php @@ -0,0 +1,17 @@ +<?php +/** + * Copyright (c) 2012 Georg Ehrke <ownclouddev at georgswebsite dot de> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +require_once('../../../../lib/base.php'); +OC_JSON::checkLoggedIn(); +if(isset($_POST["firstday"])){ + OC_Preferences::setValue(OC_User::getUser(), 'calendar', 'firstday', $_POST["firstday"]); + OC_JSON::success(); +}else{ + OC_JSON::error(); +} +?> + diff --git a/apps/calendar/ajax/settimeformat.php b/apps/calendar/ajax/settings/settimeformat.php index 7805120ba5e..8f65447065c 100644 --- a/apps/calendar/ajax/settimeformat.php +++ b/apps/calendar/ajax/settings/settimeformat.php @@ -5,7 +5,7 @@ * later. * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); OC_JSON::checkLoggedIn(); if(isset($_POST["timeformat"])){ OC_Preferences::setValue(OC_User::getUser(), 'calendar', 'timeformat', $_POST["timeformat"]); diff --git a/apps/calendar/ajax/settimezone.php b/apps/calendar/ajax/settings/settimezone.php index c726a11471d..c639753fe2f 100644 --- a/apps/calendar/ajax/settimezone.php +++ b/apps/calendar/ajax/settings/settimezone.php @@ -7,7 +7,7 @@ */ // Init owncloud -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); $l=new OC_L10N('calendar'); diff --git a/apps/calendar/ajax/timeformat.php b/apps/calendar/ajax/settings/timeformat.php index 3533adcf8e0..e0dbe8d3cd7 100644 --- a/apps/calendar/ajax/timeformat.php +++ b/apps/calendar/ajax/settings/timeformat.php @@ -5,7 +5,7 @@ * later. * See the COPYING-README file. */ -require_once('../../../lib/base.php'); +require_once('../../../../lib/base.php'); OC_JSON::checkLoggedIn(); $timeformat = OC_Preferences::getValue( OC_User::getUser(), 'calendar', 'timeformat', "24"); OC_JSON::encodedPrint(array("timeformat" => $timeformat)); diff --git a/apps/calendar/ajax/timezonedetection.php b/apps/calendar/ajax/settings/timezonedetection.php index 77e4c4f6ebe..f67bab901e7 100644 --- a/apps/calendar/ajax/timezonedetection.php +++ b/apps/calendar/ajax/settings/timezonedetection.php @@ -5,7 +5,7 @@ * later. * See the COPYING-README file. */ -require_once ("../../../lib/base.php"); +require_once('../../../../lib/base.php'); OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('calendar'); if($_POST['timezonedetection'] == 'on'){ diff --git a/apps/calendar/ajax/share/changepermission.php b/apps/calendar/ajax/share/changepermission.php new file mode 100644 index 00000000000..d91f87b613f --- /dev/null +++ b/apps/calendar/ajax/share/changepermission.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright (c) 2012 Georg Ehrke <ownclouddev@georgswebsite.de> + * 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']); +$idtype = strip_tags($_GET['idtype']); +$permission = (int) strip_tags($_GET['permission']); +switch($idtype){ + case 'calendar': + case 'event': + break; + default: + OC_JSON::error(array('message'=>'unexspected parameter')); + exit; +} +$sharewith = $_GET['sharewith']; +$sharetype = strip_tags($_GET['sharetype']); +switch($sharetype){ + case 'user': + case 'group': + case 'public': + break; + default: + OC_JSON::error(array('message'=>'unexspected parameter')); + exit; +} +if($sharetype == 'user' && !OC_User::userExists($sharewith)){ + OC_JSON::error(array('message'=>'user not found')); + exit; +} +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)); +OC_JSON::success();
\ No newline at end of file diff --git a/apps/calendar/ajax/share/dropdown.php b/apps/calendar/ajax/share/dropdown.php new file mode 100644 index 00000000000..eb396d38fd9 --- /dev/null +++ b/apps/calendar/ajax/share/dropdown.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright (c) 2012 Georg Ehrke <ownclouddev@georgswebsite.de> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +require_once('../../../../lib/base.php'); +$user = OC_USER::getUser(); +$calid = $_GET['calid']; +$calendar = OC_Calendar_Calendar::find($calid); +if($calendar['userid'] != $user){ + OC_JSON::error(); + exit; +} +$tmpl = new OC_Template('calendar', 'share.dropdown'); +$tmpl->assign('calid', $calid); +$tmpl->printPage();
\ No newline at end of file diff --git a/apps/calendar/ajax/share/share.php b/apps/calendar/ajax/share/share.php new file mode 100644 index 00000000000..d892727701a --- /dev/null +++ b/apps/calendar/ajax/share/share.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright (c) 2012 Georg Ehrke <ownclouddev@georgswebsite.de> + * 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']); +$idtype = strip_tags($_GET['idtype']); +switch($idtype){ + case 'calendar': + case 'event': + break; + default: + OC_JSON::error(array('message'=>'unexspected parameter')); + exit; +} +$sharewith = $_GET['sharewith']; +$sharetype = strip_tags($_GET['sharetype']); +switch($sharetype){ + case 'user': + case 'group': + case 'public': + break; + default: + OC_JSON::error(array('message'=>'unexspected parameter')); + exit; +} +if($sharetype == 'user' && !OC_User::userExists($sharewith)){ + OC_JSON::error(array('message'=>'user not found')); + exit; +} +if($sharetype == 'group' && !OC_Group::groupExists($sharewith)){ + OC_JSON::error(array('message'=>'group not found')); + exit; +} +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)); +if($success){ + if($sharetype == 'public'){ + OC_JSON::success(array('message'=>$success)); + }else{ + OC_JSON::success(array('message'=>'shared')); + } +}else{ + OC_JSON::error(array('message'=>'can not share')); + exit; +}
\ No newline at end of file diff --git a/apps/calendar/ajax/share/unshare.php b/apps/calendar/ajax/share/unshare.php new file mode 100644 index 00000000000..ec3150a89aa --- /dev/null +++ b/apps/calendar/ajax/share/unshare.php @@ -0,0 +1,44 @@ +<?php +/** + * Copyright (c) 2012 Georg Ehrke <ownclouddev@georgswebsite.de> + * 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']); +$idtype = strip_tags($_GET['idtype']); +switch($idtype){ + case 'calendar': + case 'event': + break; + default: + OC_JSON::error(array('message'=>'unexspected parameter')); + exit; +} +$sharewith = $_GET['sharewith']; +$sharetype = strip_tags($_GET['sharetype']); +switch($sharetype){ + case 'user': + case 'group': + case 'public': + break; + default: + OC_JSON::error(array('message'=>'unexspected parameter')); + exit; +} +if($sharetype == 'user' && !OC_User::userExists($sharewith)){ + OC_JSON::error(array('message'=>'user not found')); + exit; +} +if($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)); +if($success){ + OC_JSON::success(); +}else{ + OC_JSON::error(array('message'=>'can not unshare')); + exit; +}
\ No newline at end of file diff --git a/apps/calendar/appinfo/app.php b/apps/calendar/appinfo/app.php index 9c95768895f..f297c4d16d4 100644 --- a/apps/calendar/appinfo/app.php +++ b/apps/calendar/appinfo/app.php @@ -1,23 +1,23 @@ <?php -if(version_compare(PHP_VERSION, '5.3.0', '>=')){ - $l=new OC_L10N('calendar'); - OC::$CLASSPATH['OC_Calendar_App'] = 'apps/calendar/lib/app.php'; - 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_HOOK::connect('OC_User', 'post_deleteUser', 'OC_Calendar_Hooks', 'deleteUser'); - OC_Util::addScript('calendar','loader'); - OC_App::register( array( - 'order' => 10, - 'id' => 'calendar', - 'name' => 'Calendar' )); - OC_App::addNavigationEntry( array( - 'id' => 'calendar_index', - 'order' => 10, - 'href' => OC_Helper::linkTo( 'calendar', 'index.php' ), - 'icon' => OC_Helper::imagePath( 'calendar', 'icon.svg' ), - 'name' => $l->t('Calendar'))); - OC_App::registerPersonal('calendar', 'settings'); - require_once('apps/calendar/lib/search.php'); -} +$l=new OC_L10N('calendar'); +OC::$CLASSPATH['OC_Calendar_App'] = 'apps/calendar/lib/app.php'; +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_Search_Provider_Calendar'] = 'apps/calendar/lib/search.php'; +OC_HOOK::connect('OC_User', 'post_deleteUser', 'OC_Calendar_Hooks', 'deleteUser'); +OC_Hook::connect('OC_DAV', 'initialize', 'OC_Calendar_Hooks', 'initializeCalDAV'); +OC_Util::addScript('calendar','loader'); +OC_App::register( array( + 'order' => 10, + 'id' => 'calendar', + 'name' => 'Calendar' )); +OC_App::addNavigationEntry( array( + 'id' => 'calendar_index', + 'order' => 10, + 'href' => OC_Helper::linkTo( 'calendar', 'index.php' ), + 'icon' => OC_Helper::imagePath( 'calendar', 'icon.svg' ), + 'name' => $l->t('Calendar'))); +OC_App::registerPersonal('calendar', 'settings'); +OC_Search::registerProvider('OC_Search_Provider_Calendar');
\ No newline at end of file diff --git a/apps/calendar/caldav.php b/apps/calendar/caldav.php index db0b35da118..b710b99ea43 100644 --- a/apps/calendar/caldav.php +++ b/apps/calendar/caldav.php @@ -25,7 +25,7 @@ $nodes = array( // Fire up server $server = new Sabre_DAV_Server($nodes); -$server->setBaseUri(OC::$WEBROOT.'/apps/calendar/caldav.php'); +$server->setBaseUri(OC::$APPSWEBROOT.'/apps/calendar/caldav.php'); // Add plugins $server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend,'ownCloud')); $server->addPlugin(new Sabre_CalDAV_Plugin()); diff --git a/apps/calendar/index.php b/apps/calendar/index.php index 12b51f564b4..c00a4098f7a 100644 --- a/apps/calendar/index.php +++ b/apps/calendar/index.php @@ -9,16 +9,20 @@ require_once ('../../lib/base.php'); OC_Util::checkLoggedIn(); OC_Util::checkAppEnabled('calendar'); + // Create default calendar ... $calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), 1); if( count($calendars) == 0){ OC_Calendar_Calendar::addCalendar(OC_User::getUser(),'Default calendar'); $calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), 1); } + $eventSources = array(); foreach($calendars as $calendar){ $eventSources[] = OC_Calendar_Calendar::getEventSourceInfo($calendar); } +OC_Hook::emit('OC_Calendar', 'getSources', array('sources' => &$eventSources)); + //Fix currentview for fullcalendar if(OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'currentview', 'month') == "oneweekview"){ OC_Preferences::setValue(OC_USER::getUser(), "calendar", "currentview", "agendaWeek"); diff --git a/apps/calendar/js/calendar.js b/apps/calendar/js/calendar.js index ba8e293819a..907d94edb02 100644 --- a/apps/calendar/js/calendar.js +++ b/apps/calendar/js/calendar.js @@ -69,17 +69,20 @@ Calendar={ $('#event').dialog('destroy').remove(); }else{ Calendar.UI.loading(true); - $('#dialog_holder').load(OC.filePath('calendar', 'ajax', 'neweventform.php'), {start:start, end:end, allday:allday?1:0}, Calendar.UI.startEventDialog); + $('#dialog_holder').load(OC.filePath('calendar', 'ajax/event', 'new.form.php'), {start:start, end:end, allday:allday?1:0}, Calendar.UI.startEventDialog); } }, editEvent:function(calEvent, jsEvent, view){ + if (calEvent.editable == false || calEvent.source.editable == false) { + return; + } var id = calEvent.id; if($('#event').dialog('isOpen') == true){ // TODO: save event $('#event').dialog('destroy').remove(); }else{ Calendar.UI.loading(true); - $('#dialog_holder').load(OC.filePath('calendar', 'ajax', 'editeventform.php') + '?id=' + id, Calendar.UI.startEventDialog); + $('#dialog_holder').load(OC.filePath('calendar', 'ajax/event', 'edit.form.php') + '?id=' + id, Calendar.UI.startEventDialog); } }, submitDeleteEventForm:function(url){ @@ -141,7 +144,7 @@ Calendar={ moveEvent:function(event, dayDelta, minuteDelta, allDay, revertFunc){ $('.tipsy').remove(); Calendar.UI.loading(true); - $.post(OC.filePath('calendar', 'ajax', 'moveevent.php'), { id: event.id, dayDelta: dayDelta, minuteDelta: minuteDelta, allDay: allDay?1:0, lastmodified: event.lastmodified}, + $.post(OC.filePath('calendar', 'ajax/event', 'move.php'), { id: event.id, dayDelta: dayDelta, minuteDelta: minuteDelta, allDay: allDay?1:0, lastmodified: event.lastmodified}, function(data) { Calendar.UI.loading(false); if (data.status == 'success'){ @@ -156,7 +159,7 @@ Calendar={ resizeEvent:function(event, dayDelta, minuteDelta, revertFunc){ $('.tipsy').remove(); Calendar.UI.loading(true); - $.post(OC.filePath('calendar', 'ajax', 'resizeevent.php'), { id: event.id, dayDelta: dayDelta, minuteDelta: minuteDelta, lastmodified: event.lastmodified}, + $.post(OC.filePath('calendar', 'ajax/event', 'resize.php'), { id: event.id, dayDelta: dayDelta, minuteDelta: minuteDelta, lastmodified: event.lastmodified}, function(data) { Calendar.UI.loading(false); if (data.status == 'success'){ @@ -214,7 +217,7 @@ Calendar={ }, initScroll:function(){ if(window.addEventListener) - document.addEventListener('DOMMouseScroll', Calendar.UI.scrollCalendar); + document.addEventListener('DOMMouseScroll', Calendar.UI.scrollCalendar, false); //}else{ document.onmousewheel = Calendar.UI.scrollCalendar; //} @@ -373,7 +376,7 @@ Calendar={ $('#choosecalendar_dialog').dialog('moveToTop'); }else{ Calendar.UI.loading(true); - $('#dialog_holder').load(OC.filePath('calendar', 'ajax', 'choosecalendar.php'), function(){ + $('#dialog_holder').load(OC.filePath('calendar', 'ajax/calendar', 'overview.php'), function(){ $('#choosecalendar_dialog').dialog({ width : 600, close : function(event, ui) { @@ -387,7 +390,7 @@ Calendar={ activation:function(checkbox, calendarid) { Calendar.UI.loading(true); - $.post(OC.filePath('calendar', 'ajax', 'activation.php'), { calendarid: calendarid, active: checkbox.checked?1:0 }, + $.post(OC.filePath('calendar', 'ajax/calendar', 'activation.php'), { calendarid: calendarid, active: checkbox.checked?1:0 }, function(data) { Calendar.UI.loading(false); if (data.status == 'success'){ @@ -402,13 +405,13 @@ Calendar={ }, newCalendar:function(object){ var tr = $(document.createElement('tr')) - .load(OC.filePath('calendar', 'ajax', 'newcalendar.php'), + .load(OC.filePath('calendar', 'ajax/calendar', 'new.form.php'), function(){Calendar.UI.Calendar.colorPicker(this)}); $(object).closest('tr').after(tr).hide(); }, edit:function(object, calendarid){ var tr = $(document.createElement('tr')) - .load(OC.filePath('calendar', 'ajax', 'editcalendar.php') + "?calendarid="+calendarid, + .load(OC.filePath('calendar', 'ajax/calendar', 'edit.form.php') + "?calendarid="+calendarid, function(){Calendar.UI.Calendar.colorPicker(this)}); $(object).closest('tr').after(tr).hide(); }, @@ -417,7 +420,7 @@ Calendar={ if(check == false){ return false; }else{ - $.post(OC.filePath('calendar', 'ajax', 'deletecalendar.php'), { calendarid: calid}, + $.post(OC.filePath('calendar', 'ajax/calendar', 'delete.php'), { calendarid: calid}, function(data) { if (data.status == 'success'){ var url = 'ajax/events.php?calendar_id='+calid; @@ -442,9 +445,9 @@ Calendar={ var url; if (calendarid == 'new'){ - url = OC.filePath('calendar', 'ajax', 'createcalendar.php'); + url = OC.filePath('calendar', 'ajax/calendar', 'new.php'); }else{ - url = OC.filePath('calendar', 'ajax', 'updatecalendar.php'); + url = OC.filePath('calendar', 'ajax/calendar', 'update.php'); } $.post(url, { id: calendarid, name: displayname, active: active, description: description, color: calendarcolor }, function(data){ @@ -661,7 +664,7 @@ $(document).ready(function(){ Calendar.UI.initScroll(); $('#calendar_holder').fullCalendar({ header: false, - firstDay: 1, + firstDay: firstDay, editable: true, defaultView: defaultView, timeFormat: { diff --git a/apps/calendar/js/geo.js b/apps/calendar/js/geo.js index ae6a971e938..7018c6298a2 100755 --- a/apps/calendar/js/geo.js +++ b/apps/calendar/js/geo.js @@ -6,11 +6,10 @@ */ if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(function(position) { - $.getJSON(OC.filePath('calendar', 'ajax', 'guesstimezone.php?lat=' + position.coords.latitude + '&long=' + position.coords.longitude + ''), + $.getJSON(OC.filePath('calendar', 'ajax/settings', 'guesstimezone.php?lat=' + position.coords.latitude + '&long=' + position.coords.longitude + ''), function(data){ if (data.status == 'success' && typeof(data.message) != 'undefined'){ $('#notification').html(data.message); - $('#notification').attr('title', 'CC BY 3.0 by Geonames.org'); $('#notification').slideDown(); window.setTimeout(function(){$('#notification').slideUp();}, 5000); }else{ diff --git a/apps/calendar/js/loader.js b/apps/calendar/js/loader.js index 4e483f9864e..54003879759 100644 --- a/apps/calendar/js/loader.js +++ b/apps/calendar/js/loader.js @@ -8,7 +8,7 @@ Calendar_Import={ importdialog: function(filename){ var path = $('#dir').val(); $('body').append('<div id="calendar_import"></div>'); - $('#calendar_import').load(OC.filePath('calendar', 'ajax', 'importdialog.php'), {filename:filename, path:path}, function(){Calendar_Import.initdialog(filename);}); + $('#calendar_import').load(OC.filePath('calendar', 'ajax/import', 'dialog.php'), {filename:filename, path:path}, function(){Calendar_Import.initdialog(filename);}); }, initdialog: function(filename){ $('#calendar_import_dialog').dialog({ @@ -68,7 +68,7 @@ Calendar_Import={ if(percent < 100){ window.setTimeout('Calendar_Import.getimportstatus(\'' + progressfile + '\')', 500); }else{ - $('#import_done').css('display', 'block');
+ $('#import_done').css('display', 'block'); } }); } @@ -78,4 +78,4 @@ $(document).ready(function(){ FileActions.register('text/calendar','importcal', '', Calendar_Import.importdialog); FileActions.setDefault('text/calendar','importcal'); }; -});
\ No newline at end of file +}); diff --git a/apps/calendar/js/settings.js b/apps/calendar/js/settings.js index 73300885565..c768a47a797 100644 --- a/apps/calendar/js/settings.js +++ b/apps/calendar/js/settings.js @@ -3,7 +3,7 @@ $(document).ready(function(){ OC.msg.startSaving('#calendar .msg') // Serialize the data var post = $( '#timezone' ).serialize(); - $.post( OC.filePath('calendar', 'ajax', 'settimezone.php'), post, function(data){ + $.post( OC.filePath('calendar', 'ajax/settings', 'settimezone.php'), post, function(data){ //OC.msg.finishedSaving('#calendar .msg', data); }); return false; @@ -11,25 +11,37 @@ $(document).ready(function(){ $('#timezone').chosen(); $('#timeformat').change( function(){ var data = $('#timeformat').serialize(); - $.post( OC.filePath('calendar', 'ajax', 'settimeformat.php'), data, function(data){ + $.post( OC.filePath('calendar', 'ajax/settings', 'settimeformat.php'), data, function(data){ if(data == 'error'){ console.log('saving timeformat failed'); } }); }); + $('#firstday').change( function(){ + var data = $('#firstday').serialize(); + $.post( OC.filePath('calendar', 'ajax/settings', 'setfirstday.php'), data, function(data){ + if(data == 'error'){ + console.log('saving firstday failed'); + } + }); + }); $('#timezonedetection').change( function(){ var post = $('#timezonedetection').serialize(); - $.post( OC.filePath('calendar', 'ajax', 'timezonedetection.php'), post, function(data){ + $.post( OC.filePath('calendar', 'ajax/settings', 'timezonedetection.php'), post, function(data){ }); }); - $.getJSON(OC.filePath('calendar', 'ajax', 'timeformat.php'), function(jsondata, status) { + $.getJSON(OC.filePath('calendar', 'ajax/settings', 'timeformat.php'), function(jsondata, status) { $('#' + jsondata.timeformat).attr('selected',true); $('#timeformat').chosen(); }); - $.getJSON(OC.filePath('calendar', 'ajax', 'gettimezonedetection.php'), function(jsondata, status){ + $.getJSON(OC.filePath('calendar', 'ajax/settings', 'gettimezonedetection.php'), function(jsondata, status){ if(jsondata.detection == 'true'){ $('#timezonedetection').attr('checked', 'checked'); } }); + $.getJSON(OC.filePath('calendar', 'ajax/settings', 'getfirstday.php'), function(jsondata, status) { + $('#' + jsondata.firstday).attr('selected',true); + $('#firstday').chosen(); + }); }); diff --git a/apps/calendar/lib/calendar.php b/apps/calendar/lib/calendar.php index 277539af97d..7eeb004d181 100644 --- a/apps/calendar/lib/calendar.php +++ b/apps/calendar/lib/calendar.php @@ -240,9 +240,10 @@ class OC_Calendar_Calendar{ '#9fc6e7', // "light blue" ); } + public static function getEventSourceInfo($calendar){ return array( - 'url' => 'ajax/events.php?calendar_id='.$calendar['id'], + 'url' => OC_Helper::linkTo('calendar', 'ajax/events.php').'?calendar_id='.$calendar['id'], 'backgroundColor' => $calendar['calendarcolor'], 'borderColor' => '#888', 'textColor' => 'black', diff --git a/apps/calendar/lib/hooks.php b/apps/calendar/lib/hooks.php index 14f96bb5fe1..54f1680a36e 100644 --- a/apps/calendar/lib/hooks.php +++ b/apps/calendar/lib/hooks.php @@ -17,11 +17,24 @@ class OC_Calendar_Hooks{ */ public static function deleteUser($parameters) { $calendars = OC_Calendar_Calendar::allCalendars($parameters['uid']); - + foreach($calendars as $calendar) { OC_Calendar_Calendar::deleteCalendar($calendar['id']); } return true; } + + /** + * @brief Adds the CardDAV resource to the DAV server + * @param paramters parameters from initialize-Hook + * @return array + */ + public static function initializeCalDAV($parameters){ + // We need a backend, the root node and the caldav plugin + $parameters['backends']['caldav'] = new OC_Connector_Sabre_CalDAV(); + $parameters['nodes'][] = new Sabre_CalDAV_CalendarRootNode($parameters['backends']['principal'], $parameters['backends']['caldav']); + $parameters['plugins'][] = new Sabre_CalDAV_Plugin(); + return true; + } } diff --git a/apps/calendar/lib/object.php b/apps/calendar/lib/object.php index 230c610d35a..e0c0e83d5d0 100644 --- a/apps/calendar/lib/object.php +++ b/apps/calendar/lib/object.php @@ -96,8 +96,7 @@ class OC_Calendar_Object{ list($type,$startdate,$enddate,$summary,$repeating,$uid) = self::extractData($object); if(is_null($uid)){ - $uid = self::createUID(); - $object->add('UID',$uid); + $object->setUID(); $data = $object->serialize(); } @@ -209,14 +208,6 @@ class OC_Calendar_Object{ } /** - * @brief Creates a UID - * @return string - */ - protected static function createUID(){ - return substr(md5(rand().time()),0,10); - } - - /** * @brief Extracts data from a vObject-Object * @param Sabre_VObject $object * @return array @@ -309,6 +300,8 @@ class OC_Calendar_Object{ $dtend = $vevent->DTEND; }else{ $dtend = clone $vevent->DTSTART; + // clone creates a shallow copy, also clone DateTime + $dtend->setDateTime(clone $dtend->getDateTime(), $dtend->getDateType()); if ($vevent->DURATION){ $duration = strval($vevent->DURATION); $invert = 0; @@ -817,4 +810,4 @@ class OC_Calendar_Object{ return $vcalendar; } -}
\ No newline at end of file +} diff --git a/apps/calendar/lib/search.php b/apps/calendar/lib/search.php index 0016751a66a..8405866392d 100644 --- a/apps/calendar/lib/search.php +++ b/apps/calendar/lib/search.php @@ -1,6 +1,6 @@ <?php -class OC_Search_Provider_Calendar extends OC_Search_Provider{ - function search($query){ +class OC_Search_Provider_Calendar implements OC_Search_Provider{ + static function search($query){ $calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), 1); if(count($calendars)==0 || !OC_App::isEnabled('calendar')){ //return false; @@ -44,4 +44,3 @@ class OC_Search_Provider_Calendar extends OC_Search_Provider{ return $results; } } -new OC_Search_Provider_Calendar(); diff --git a/apps/calendar/templates/calendar.php b/apps/calendar/templates/calendar.php index eb82d0d02ad..63c3b500296 100755 --- a/apps/calendar/templates/calendar.php +++ b/apps/calendar/templates/calendar.php @@ -19,6 +19,7 @@ var missing_field_startsbeforeends = '<?php echo addslashes($l->t('The event ends before it starts')) ?>'; var missing_field_dberror = '<?php echo addslashes($l->t('There was a database fail')) ?>'; var totalurl = '<?php echo OC_Helper::linkToAbsolute('calendar', 'caldav.php'); ?>/calendars'; + var firstDay = '<?php echo (OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'firstday', 'mo') == 'mo' ? '1' : '0'); ?>'; $(document).ready(function() { <?php if(array_key_exists('showevent', $_)){ diff --git a/apps/calendar/templates/part.editevent.php b/apps/calendar/templates/part.editevent.php index b3acfc4a072..6e319e1b4e0 100644 --- a/apps/calendar/templates/part.editevent.php +++ b/apps/calendar/templates/part.editevent.php @@ -5,8 +5,8 @@ <?php echo $this->inc("part.eventform"); ?> <div style="width: 100%;text-align: center;color: #FF1D1D;" id="errorbox"></div> <span id="actions"> - <input type="button" class="submit" style="float: left;" value="<?php echo $l->t("Submit");?>" onclick="Calendar.UI.validateEventForm('ajax/editevent.php');"> - <input type="button" class="submit" style="float: left;" name="delete" value="<?php echo $l->t("Delete");?>" onclick="Calendar.UI.submitDeleteEventForm('ajax/deleteevent.php');"> + <input type="button" class="submit" style="float: left;" value="<?php echo $l->t("Submit");?>" onclick="Calendar.UI.validateEventForm('ajax/event/edit.php');"> + <input type="button" class="submit" style="float: left;" name="delete" value="<?php echo $l->t("Delete");?>" onclick="Calendar.UI.submitDeleteEventForm('ajax/event/delete.php');"> <input type="button" class="submit" style="float: right;" name="export" value="<?php echo $l->t("Export");?>" onclick="window.location='export.php?eventid=<?php echo $_['id'] ?>';"> </span> </form> diff --git a/apps/calendar/templates/part.eventform.php b/apps/calendar/templates/part.eventform.php index 49214aca77c..8a8f420f846 100644 --- a/apps/calendar/templates/part.eventform.php +++ b/apps/calendar/templates/part.eventform.php @@ -17,6 +17,7 @@ ?> </select> </td> + <?php if(count($_['calendar_options']) > 1) { ?> <th width="75px"> <?php echo $l->t("Calendar");?>:</th> <td> <select style="width:140px;" name="calendar"> @@ -26,6 +27,12 @@ ?> </select> </td> + <?php } else { ?> + <th width="75px"> </th> + <td> + <input type="hidden" name="calendar" value="<?php echo $_['calendar_options'][0]['id'] ?>"> + </td> + <?php } ?> </tr> </table> <hr> diff --git a/apps/calendar/templates/part.newevent.php b/apps/calendar/templates/part.newevent.php index b1e2a5eab84..11416260344 100644 --- a/apps/calendar/templates/part.newevent.php +++ b/apps/calendar/templates/part.newevent.php @@ -3,7 +3,7 @@ <?php echo $this->inc("part.eventform"); ?> <div style="width: 100%;text-align: center;color: #FF1D1D;" id="errorbox"></div> <span id="actions"> - <input type="button" class="submit" style="float: left;" value="<?php echo $l->t("Submit");?>" onclick="Calendar.UI.validateEventForm('ajax/newevent.php');"> + <input type="button" class="submit" style="float: left;" value="<?php echo $l->t("Submit");?>" onclick="Calendar.UI.validateEventForm('ajax/event/new.php');"> </span> </form> </div> diff --git a/apps/calendar/templates/settings.php b/apps/calendar/templates/settings.php index 979634874e4..f74a45203e1 100644 --- a/apps/calendar/templates/settings.php +++ b/apps/calendar/templates/settings.php @@ -37,6 +37,13 @@ </select> </td></tr> + <tr><td><label for="firstday" class="bold"><?php echo $l->t('First day of the week');?></label></td><td> + <select style="display: none;" id="firstday" title="<?php echo "First day"; ?>" name="firstday"> + <option value="mo" id="mo"><?php echo $l->t("Monday"); ?></option> + <option value="su" id="su"><?php echo $l->t("Sunday"); ?></option> + </select> + </td></tr> + </table> <?php echo $l->t('Calendar CalDAV syncing address:');?> diff --git a/apps/contacts/ajax/addcard.php b/apps/contacts/ajax/addcard.php index b1dc69a4691..49a4a16170b 100644 --- a/apps/contacts/ajax/addcard.php +++ b/apps/contacts/ajax/addcard.php @@ -92,7 +92,7 @@ foreach( $add as $propname){ } } } -$id = OC_Contacts_VCard::add($aid,$vcard->serialize()); +$id = OC_Contacts_VCard::add($aid,$vcard); if(!$id) { OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('There was an error adding the contact.')))); OC_Log::write('contacts','ajax/addcard.php: Recieved non-positive ID on adding card: '.$id, OC_Log::ERROR); diff --git a/apps/contacts/ajax/addcontact.php b/apps/contacts/ajax/addcontact.php index 5d17631caa4..839a3919981 100644 --- a/apps/contacts/ajax/addcontact.php +++ b/apps/contacts/ajax/addcontact.php @@ -52,7 +52,7 @@ $vcard->setUID(); $vcard->setString('FN',$fn); $vcard->setString('N',$n); -$id = OC_Contacts_VCard::add($aid,$vcard->serialize()); +$id = OC_Contacts_VCard::add($aid,$vcard); if(!$id) { OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('There was an error adding the contact.')))); OC_Log::write('contacts','ajax/addcontact.php: Recieved non-positive ID on adding card: '.$id, OC_Log::ERROR); diff --git a/apps/contacts/ajax/addproperty.php b/apps/contacts/ajax/addproperty.php index 028974e1c66..b6b5dc7c416 100644 --- a/apps/contacts/ajax/addproperty.php +++ b/apps/contacts/ajax/addproperty.php @@ -113,7 +113,7 @@ foreach ($parameters as $key=>$element) { } $checksum = md5($vcard->children[$line]->serialize()); -if(!OC_Contacts_VCard::edit($id,$vcard->serialize())) { +if(!OC_Contacts_VCard::edit($id,$vcard)) { OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error adding contact property.')))); OC_Log::write('contacts','ajax/addproperty.php: Error updating contact property: '.$name, OC_Log::ERROR); exit(); diff --git a/apps/contacts/ajax/deleteproperty.php b/apps/contacts/ajax/deleteproperty.php index a9afffaad4c..ab0958cac58 100644 --- a/apps/contacts/ajax/deleteproperty.php +++ b/apps/contacts/ajax/deleteproperty.php @@ -39,7 +39,7 @@ if(is_null($line)){ unset($vcard->children[$line]); -if(!OC_Contacts_VCard::edit($id,$vcard->serialize())) { +if(!OC_Contacts_VCard::edit($id,$vcard)) { OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error deleting contact property.')))); OC_Log::write('contacts','ajax/deleteproperty.php: Error deleting contact property', OC_Log::ERROR); exit(); diff --git a/apps/contacts/ajax/savecrop.php b/apps/contacts/ajax/savecrop.php index 1a84f6fdfae..ffbfaeb6e38 100644 --- a/apps/contacts/ajax/savecrop.php +++ b/apps/contacts/ajax/savecrop.php @@ -95,7 +95,7 @@ if(file_exists($tmp_path)) { OC_Log::write('contacts','savecrop.php: files: Adding PHOTO property.', OC_Log::DEBUG); $card->addProperty('PHOTO', $image->__toString(), array('ENCODING' => 'b', 'TYPE' => $image->mimeType())); } - if(!OC_Contacts_VCard::edit($id,$card->serialize())) { + if(!OC_Contacts_VCard::edit($id,$card)) { bailOut('Error saving contact.'); } unlink($tmpfname); diff --git a/apps/contacts/ajax/saveproperty.php b/apps/contacts/ajax/saveproperty.php index 6f8366243fe..db209fedfc7 100644 --- a/apps/contacts/ajax/saveproperty.php +++ b/apps/contacts/ajax/saveproperty.php @@ -122,7 +122,7 @@ switch($element) { $checksum = md5($vcard->children[$line]->serialize()); debug('New checksum: '.$checksum); -if(!OC_Contacts_VCard::edit($id,$vcard->serialize())) { +if(!OC_Contacts_VCard::edit($id,$vcard)) { OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error updating contact property.')))); OC_Log::write('contacts','ajax/setproperty.php: Error updating contact property: '.$value, OC_Log::ERROR); exit(); diff --git a/apps/contacts/ajax/setproperty.php b/apps/contacts/ajax/setproperty.php index f9e2a8e8647..8e07b4a8f1c 100644 --- a/apps/contacts/ajax/setproperty.php +++ b/apps/contacts/ajax/setproperty.php @@ -80,7 +80,7 @@ foreach($missingparameters as $i){ // NOTE: This checksum is not used..? $checksum = md5($vcard->children[$line]->serialize()); -if(!OC_Contacts_VCard::edit($id,$vcard->serialize())) { +if(!OC_Contacts_VCard::edit($id,$vcard)) { OC_JSON::error(array('data' => array('message' => $l->t('Error updating contact property.')))); OC_Log::write('contacts','ajax/setproperty.php: Error updating contact property: '.$value, OC_Log::ERROR); exit(); diff --git a/apps/contacts/appinfo/app.php b/apps/contacts/appinfo/app.php index 9e424aa89f8..85c383c4c32 100644 --- a/apps/contacts/appinfo/app.php +++ b/apps/contacts/appinfo/app.php @@ -4,7 +4,11 @@ OC::$CLASSPATH['OC_Contacts_Addressbook'] = 'apps/contacts/lib/addressbook.php'; OC::$CLASSPATH['OC_Contacts_VCard'] = 'apps/contacts/lib/vcard.php'; OC::$CLASSPATH['OC_Contacts_Hooks'] = 'apps/contacts/lib/hooks.php'; OC::$CLASSPATH['OC_Connector_Sabre_CardDAV'] = 'apps/contacts/lib/connector_sabre.php'; +OC::$CLASSPATH['OC_Search_Provider_Contacts'] = 'apps/contacts/lib/search.php'; OC_HOOK::connect('OC_User', 'post_deleteUser', 'OC_Contacts_Hooks', 'deleteUser'); +OC_HOOK::connect('OC_Calendar', 'getEvents', 'OC_Contacts_Hooks', 'getBirthdayEvents'); +OC_HOOK::connect('OC_Calendar', 'getSources', 'OC_Contacts_Hooks', 'getCalenderSources'); +OC_Hook::connect('OC_DAV', 'initialize', 'OC_Contacts_Hooks', 'initializeCardDAV'); OC_App::register( array( 'order' => 10, @@ -21,4 +25,4 @@ OC_App::addNavigationEntry( array( OC_APP::registerPersonal('contacts','settings'); OC_UTIL::addScript('contacts', 'loader'); -require_once('apps/contacts/lib/search.php'); +OC_Search::registerProvider('OC_Search_Provider_Contacts'); diff --git a/apps/contacts/carddav.php b/apps/contacts/carddav.php index a2bf492e206..654aeb66a72 100644 --- a/apps/contacts/carddav.php +++ b/apps/contacts/carddav.php @@ -39,7 +39,7 @@ $nodes = array( // Fire up server $server = new Sabre_DAV_Server($nodes); -$server->setBaseUri(OC::$WEBROOT.'/apps/contacts/carddav.php'); +$server->setBaseUri(OC::$APPSWEBROOT.'/apps/contacts/carddav.php'); // Add plugins $server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend,'ownCloud')); $server->addPlugin(new Sabre_CardDAV_Plugin()); diff --git a/apps/contacts/css/contacts.css b/apps/contacts/css/contacts.css index 384541f3751..b24ec438f24 100644 --- a/apps/contacts/css/contacts.css +++ b/apps/contacts/css/contacts.css @@ -17,8 +17,8 @@ #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;} #card { /*max-width: 70em; border: thin solid lightgray; display: block;*/ } -#firstrun { /*border: thin solid lightgray;*/ width: 80%; margin: 5em auto auto auto; text-align: center; font-weight:bold; font-size:1.5em; color:#777;} -#firstrun #selections { /*border: thin solid lightgray;*/ font-size:0.8em; width: 100%; margin: 2em auto auto auto; clear: both; } +#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; } #card input[type="text"].contacts_property,input[type="email"].contacts_property { width: 16em; } #card input[type="text"],input[type="email"],input[type="tel"],input[type="date"], select { background-color: #f8f8f8; 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; } diff --git a/apps/contacts/import.php b/apps/contacts/import.php index 4638bf0d73c..04cfc397d56 100644 --- a/apps/contacts/import.php +++ b/apps/contacts/import.php @@ -97,11 +97,15 @@ if(is_writable('import_tmp/')){ fclose($progressfopen); } if(count($parts) == 1){ - OC_Contacts_VCard::add($id, $file); -}else{ - foreach($importready as $import){ - OC_Contacts_VCard::add($id, $import); + $importready = array($file); +} +foreach($importready as $import){ + $card = OC_VObject::parse($import); + if (!$card) { + OC_Log::write('contacts','Import: skipping card. Error parsing VCard: '.$import, OC_Log::ERROR); + continue; // Ditch cards that can't be parsed by Sabre. } + OC_Contacts_VCard::add($id, $card); } //done the import if(is_writable('import_tmp/')){ @@ -113,4 +117,4 @@ sleep(3); if(is_writable('import_tmp/')){ unlink($progressfile); } -OC_JSON::success();
\ No newline at end of file +OC_JSON::success(); diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index 11661320c59..94876f5cd09 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -8,7 +8,7 @@ String.prototype.strip_tags = function(){ tags = this; stripped = tags.replace(/[\<\>]/gi, ""); return stripped; -} +}; Contacts={ @@ -68,7 +68,7 @@ Contacts={ return $(obj).parents('.propertycontainer').first().data('element'); }, showHideContactInfo:function() { - var show = ($('#emaillist li[class*="propertycontainer"]').length > 0 || $('#phonelist li[class*="propertycontainer"]').length > 0 || $('#addressdisplay dl[class*="propertycontainer"]').length > 0); + var show = ($('#emaillist li.propertycontainer').length > 0 || $('#phonelist li.propertycontainer').length > 0 || $('#addressdisplay dl.propertycontainer').length > 0); console.log('showHideContactInfo: ' + show); if(show) { $('#contact_communication').show(); @@ -82,19 +82,19 @@ Contacts={ switch (type) { case 'EMAIL': console.log('emails: '+$('#emaillist>li').length); - if($('#emaillist li[class*="propertycontainer"]').length == 0) { + if($('#emaillist li.propertycontainer').length == 0) { $('#emails').hide(); } break; case 'TEL': console.log('phones: '+$('#phonelist>li').length); - if($('#phonelist li[class*="propertycontainer"]').length == 0) { + if($('#phonelist li.propertycontainer').length == 0) { $('#phones').hide(); } break; case 'ADR': console.log('addresses: '+$('#addressdisplay>dl').length); - if($('#addressdisplay dl[class*="propertycontainer"]').length == 0) { + if($('#addressdisplay dl.propertycontainer').length == 0) { $('#addresses').hide(); } break; @@ -142,7 +142,7 @@ Contacts={ } }); }); - } + }; }, loadListHandlers:function() { //$('.add,.delete').hide(); @@ -183,7 +183,7 @@ Contacts={ dateFormat : 'dd-mm-yy' }); // Style phone types - $('#phonelist').find('select[class*="contacts_property"]').multiselect({ + $('#phonelist').find('select.contacts_property').multiselect({ noneSelectedText: t('contacts', 'Select type'), header: false, selectedList: 4, @@ -323,7 +323,7 @@ Contacts={ } }); }, - delete:function() { + delete: function() { $('#contacts_deletecard').tipsy('hide'); $.getJSON('ajax/deletecard.php',{'id':this.id},function(jsondata){ if(jsondata.status == 'success'){ @@ -373,7 +373,7 @@ Contacts={ loadSingleProperties:function() { var props = ['BDAY', 'NICKNAME', 'ORG']; // Clear all elements - $('#ident .propertycontainer[class*="propertycontainer"]').each(function(){ + $('#ident .propertycontainer').each(function(){ if(props.indexOf($(this).data('element')) > -1) { $(this).data('checksum', ''); $(this).find('input').val(''); @@ -448,6 +448,9 @@ Contacts={ $('#fn_select option').remove(); $('#fn_select').combobox('value', this.fn); var names = [this.fullname, this.givname + ' ' + this.famname, this.famname + ' ' + this.givname, this.famname + ', ' + this.givname]; + if(this.data.ORG) { + names[names.length]=this.data.ORG[0].value; + } $.each(names, function(key, value) { $('#fn_select') .append($('<option></option>') @@ -518,8 +521,8 @@ Contacts={ var checksum = container.data('checksum'); var name = container.data('element'); console.log('saveProperty: ' + name); - var fields = container.find('input[class*="contacts_property"],select[class*="contacts_property"]').serializeArray(); - var q = container.find('input[class*="contacts_property"],select[class*="contacts_property"]').serialize(); + var fields = container.find('input.contacts_property,select.contacts_property').serializeArray(); + var q = container.find('input.contacts_property,select.contacts_property').serialize(); if(q == '' || q == undefined) { console.log('Couldn\'t serialize elements.'); Contacts.UI.loading(container, false); @@ -708,7 +711,7 @@ Contacts={ }, loadAddresses:function(){ $('#addresses').hide(); - $('#addressdisplay dl[class*="propertycontainer"]').remove(); + $('#addressdisplay dl.propertycontainer').remove(); for(var adr in this.data.ADR) { $('#addressdisplay dl').first().clone().insertAfter($('#addressdisplay dl').last()).show(); $('#addressdisplay dl').last().removeClass('template').addClass('propertycontainer'); @@ -920,15 +923,15 @@ Contacts={ }, addMail:function() { //alert('addMail'); - $('#emaillist li[class*="template"]:first-child').clone().appendTo($('#emaillist')).show(); - $('#emaillist li[class*="template"]:last-child').removeClass('template').addClass('propertycontainer'); + $('#emaillist li.template:first-child').clone().appendTo($('#emaillist')).show(); + $('#emaillist li.template:last-child').removeClass('template').addClass('propertycontainer'); $('#emaillist li:last-child').find('input[type="email"]').focus(); Contacts.UI.loadListHandlers(); return false; }, loadMails:function() { $('#emails').hide(); - $('#emaillist li[class*="propertycontainer"]').remove(); + $('#emaillist li.propertycontainer').remove(); for(var mail in this.data.EMAIL) { this.addMail(); //$('#emaillist li:first-child').clone().appendTo($('#emaillist')).show(); @@ -950,9 +953,9 @@ Contacts={ return false; }, addPhone:function() { - $('#phonelist li[class*="template"]:first-child').clone().appendTo($('#phonelist')); //.show(); - $('#phonelist li[class*="template"]:last-child').find('select').addClass('contacts_property'); - $('#phonelist li[class*="template"]:last-child').removeClass('template').addClass('propertycontainer'); + $('#phonelist li.template:first-child').clone().appendTo($('#phonelist')); //.show(); + $('#phonelist li.template:last-child').find('select').addClass('contacts_property'); + $('#phonelist li.template:last-child').removeClass('template').addClass('propertycontainer'); $('#phonelist li:last-child').find('input[type="text"]').focus(); Contacts.UI.loadListHandlers(); $('#phonelist li:last-child').find('select').multiselect({ @@ -966,7 +969,7 @@ Contacts={ }, loadPhones:function() { $('#phones').hide(); - $('#phonelist li[class*="propertycontainer"]').remove(); + $('#phonelist li.propertycontainer').remove(); for(var phone in this.data.TEL) { this.addPhone(); $('#phonelist li:last-child').find('select').multiselect('destroy'); diff --git a/apps/contacts/lib/app.php b/apps/contacts/lib/app.php index 48298952c12..1fa441475d2 100644 --- a/apps/contacts/lib/app.php +++ b/apps/contacts/lib/app.php @@ -85,7 +85,7 @@ class OC_Contacts_App { $vcard = OC_VObject::parse($card['carddata']); // Try to fix cards with missing 'N' field from pre ownCloud 4. Hot damn, this is ugly... if(!is_null($vcard) && !$vcard->__isset('N')) { - $appinfo = $info=OC_App::getAppInfo('contacts'); + $appinfo = OC_App::getAppInfo('contacts'); if($appinfo['version'] >= 5) { OC_Log::write('contacts','OC_Contacts_App::getContactVCard. Deprecated check for missing N field', OC_Log::DEBUG); } @@ -94,7 +94,7 @@ class OC_Contacts_App { OC_Log::write('contacts','getContactVCard, found FN field: '.$vcard->__get('FN'), OC_Log::DEBUG); $n = implode(';', array_reverse(array_slice(explode(' ', $vcard->__get('FN')), 0, 2))).';;;'; $vcard->setString('N', $n); - OC_Contacts_VCard::edit( $id, $vcard->serialize()); + OC_Contacts_VCard::edit( $id, $vcard); } else { // Else just add an empty 'N' field :-P $vcard->setString('N', 'Unknown;Name;;;'); } diff --git a/apps/contacts/lib/hooks.php b/apps/contacts/lib/hooks.php index 155cf40f914..e09da20be86 100644 --- a/apps/contacts/lib/hooks.php +++ b/apps/contacts/lib/hooks.php @@ -29,7 +29,7 @@ class OC_Contacts_Hooks{ * @param paramters parameters from postDeleteUser-Hook * @return array */ - public function deleteUser($parameters) { + static public function deleteUser($parameters) { $addressbooks = OC_Contacts_Addressbook::all($parameters['uid']); foreach($addressbooks as $addressbook) { @@ -38,4 +38,62 @@ class OC_Contacts_Hooks{ return true; } + + /** + * @brief Adds the CardDAV resource to the DAV server + * @param paramters parameters from initialize-Hook + * @return array + */ + static public function initializeCardDAV($parameters){ + // We need a backend, the root node and the carddav plugin + $parameters['backends']['carddav'] = new OC_Connector_Sabre_CardDAV(); + $parameters['nodes'][] = new Sabre_CardDAV_AddressBookRoot($parameters['backends']['principal'], $parameters['backends']['carddav']); + $parameters['plugins'][] = new Sabre_CardDAV_Plugin(); + return true; + } + + static public function getCalenderSources($parameters) { + $base_url = OC_Helper::linkTo('calendar', 'ajax/events.php').'?calendar_id='; + foreach(OC_Contacts_Addressbook::all(OC_User::getUser()) as $addressbook) { + $parameters['sources'][] = + array( + 'url' => $base_url.'birthday_'. $addressbook['id'], + 'backgroundColor' => '#cccccc', + 'borderColor' => '#888', + 'textColor' => 'black', + 'cache' => true, + 'editable' => false, + ); + } + } + + static public function getBirthdayEvents($parameters) { + $name = $parameters['calendar_id']; + if (strpos('birthday_', $name) != 0) { + return; + } + $info = explode('_', $name); + $aid = $info[1]; + OC_Contacts_App::getAddressbook($aid); + foreach(OC_Contacts_VCard::all($aid) as $card){ + $vcard = OC_VObject::parse($card['carddata']); + $birthday = $vcard->BDAY; + if ($birthday) { + $date = new DateTime($birthday); + $vevent = new OC_VObject('VEVENT'); + $vevent->setDateTime('LAST-MODIFIED', new DateTime($vcard->REV)); + $vevent->setDateTime('DTSTART', $date, Sabre_VObject_Element_DateTime::DATE); + $vevent->setString('DURATION', 'P1D'); + // DESCRIPTION? + $vevent->setString('RRULE', 'FREQ=YEARLY'); + $title = str_replace('{name}', $vcard->getAsString('FN'), OC_Contacts_App::$l10n->t('{name}\'s Birthday')); + $parameters['events'][] = array( + 'id' => 0,//$card['id'], + 'vevent' => $vevent, + 'repeating' => true, + 'summary' => $title, + ); + } + } + } } diff --git a/apps/contacts/lib/search.php b/apps/contacts/lib/search.php index 5aad6a25f09..cf0a5fe6997 100644 --- a/apps/contacts/lib/search.php +++ b/apps/contacts/lib/search.php @@ -1,6 +1,6 @@ <?php -class OC_Search_Provider_Contacts extends OC_Search_Provider{ - function search($query){ +class OC_Search_Provider_Contacts implements OC_Search_Provider{ + static function search($query){ $addressbooks = OC_Contacts_Addressbook::all(OC_User::getUser(), 1); // if(count($calendars)==0 || !OC_App::isEnabled('contacts')){ // //return false; @@ -26,4 +26,3 @@ class OC_Search_Provider_Contacts extends OC_Search_Provider{ return $results; } } -new OC_Search_Provider_Contacts(); diff --git a/apps/contacts/lib/vcard.php b/apps/contacts/lib/vcard.php index 99b1edd656f..40e17b6ddd8 100644 --- a/apps/contacts/lib/vcard.php +++ b/apps/contacts/lib/vcard.php @@ -174,6 +174,9 @@ class OC_Contacts_VCard{ if($property->name == 'UID'){ $uid = $property->value; } + if($property->name == 'ORG'){ + $org = $property->value; + } if($property->name == 'EMAIL' && is_null($email)){ // only use the first email as substitute for missing N or FN. $email = $property->value; } @@ -184,6 +187,8 @@ class OC_Contacts_VCard{ $fn = join(' ', array_reverse(array_slice(explode(';', $n), 0, 2))); } elseif($email) { $fn = $email; + } elseif($org) { + $fn = $org; } else { $fn = 'Unknown Name'; } @@ -217,32 +222,37 @@ class OC_Contacts_VCard{ /** * @brief Adds a card - * @param integer $id Addressbook id - * @param string $data vCard file - * @return insertid on success or null if card is not parseable. + * @param integer $aid Addressbook id + * @param OC_VObject $card vCard file + * @param string $uri the uri of the card, default based on the UID + * @return insertid on success or null if no card. */ - public static function add($id,$data){ - $fn = null; - - $card = OC_VObject::parse($data); - if(!is_null($card)){ - OC_Contacts_App::$categories->loadFromVObject($card); - self::updateValuesFromAdd($card); - $data = $card->serialize(); - } - else{ - OC_Log::write('contacts','OC_Contacts_VCard::add. Error parsing VCard: '.$data,OC_Log::ERROR); - return null; // Ditch cards that can't be parsed by Sabre. + public static function add($aid, $card, $uri=null){ + if(is_null($card)){ + OC_Log::write('contacts','OC_Contacts_VCard::add. No vCard supplied', OC_Log::ERROR); + return null; }; + OC_Contacts_App::$categories->loadFromVObject($card); + + self::updateValuesFromAdd($card); + $fn = $card->getAsString('FN'); - $uid = $card->getAsString('UID'); - $uri = $uid.'.vcf'; + if (empty($fn)) { + $fn = null; + } + + if (!$uri) { + $uid = $card->getAsString('UID'); + $uri = $uid.'.vcf'; + } + + $data = $card->serialize(); $stmt = OC_DB::prepare( 'INSERT INTO *PREFIX*contacts_cards (addressbookid,fullname,carddata,uri,lastmodified) VALUES(?,?,?,?,?)' ); - $result = $stmt->execute(array($id,$fn,$data,$uri,time())); + $result = $stmt->execute(array($aid,$fn,$data,$uri,time())); $newid = OC_DB::insertid('*PREFIX*contacts_cards'); - OC_Contacts_Addressbook::touch($id); + OC_Contacts_Addressbook::touch($aid); return $newid; } @@ -256,51 +266,33 @@ class OC_Contacts_VCard{ */ public static function addFromDAVData($id,$uri,$data){ $card = OC_VObject::parse($data); - if(!is_null($card)){ - OC_Contacts_App::$categories->loadFromVObject($card); - self::updateValuesFromAdd($card); - $data = $card->serialize(); - } else { - OC_Log::write('contacts','OC_Contacts_VCard::addFromDAVData. Error parsing VCard: '.$data, OC_Log::ERROR); - return null; // Ditch cards that can't be parsed by Sabre. - }; - $fn = $card->getAsString('FN'); - - $stmt = OC_DB::prepare( 'INSERT INTO *PREFIX*contacts_cards (addressbookid,fullname,carddata,uri,lastmodified) VALUES(?,?,?,?,?)' ); - $result = $stmt->execute(array($id,$fn,$data,$uri,time())); - $newid = OC_DB::insertid('*PREFIX*contacts_cards'); - - OC_Contacts_Addressbook::touch($id); - - return $newid; + return self::add($id, $data, $uri); } /** * @brief edits a card * @param integer $id id of card - * @param string $data vCard file + * @param OC_VObject $card vCard file * @return boolean */ - public static function edit($id, $data){ + public static function edit($id, OC_VObject $card){ $oldcard = self::find($id); - $fn = null; - $card = OC_VObject::parse($data); - if(!is_null($card)){ - OC_Contacts_App::$categories->loadFromVObject($card); - foreach($card->children as $property){ - if($property->name == 'FN'){ - $fn = $property->value; - break; - } - } - } else { + if(is_null($card)) { return false; } + + OC_Contacts_App::$categories->loadFromVObject($card); + + $fn = $card->getAsString('FN'); + if (empty($fn)) { + $fn = null; + } + $now = new DateTime; $card->setString('REV', $now->format(DateTime::W3C)); - $data = $card->serialize(); + $data = $card->serialize(); $stmt = OC_DB::prepare( 'UPDATE *PREFIX*contacts_cards SET fullname = ?,carddata = ?, lastmodified = ? WHERE id = ?' ); $result = $stmt->execute(array($fn,$data,time(),$id)); @@ -318,28 +310,8 @@ class OC_Contacts_VCard{ */ public static function editFromDAVData($aid,$uri,$data){ $oldcard = self::findWhereDAVDataIs($aid,$uri); - - $fn = null; $card = OC_VObject::parse($data); - if(!is_null($card)){ - OC_Contacts_App::$categories->loadFromVObject($card); - foreach($card->children as $property){ - if($property->name == 'FN'){ - $fn = $property->value; - break; - } - } - } - $now = new DateTime; - $card->setString('REV', $now->format(DateTime::W3C)); - $data = $card->serialize(); - - $stmt = OC_DB::prepare( 'UPDATE *PREFIX*contacts_cards SET fullname = ?,carddata = ?, lastmodified = ? WHERE id = ?' ); - $result = $stmt->execute(array($fn,$data,time(),$oldcard['id'])); - - OC_Contacts_Addressbook::touch($oldcard['addressbookid']); - - return true; + return self::edit($oldcard['id'], $card); } /** @@ -356,14 +328,6 @@ class OC_Contacts_VCard{ } /** - * @brief Creates a UID - * @return string - */ - public static function createUID(){ - return substr(md5(rand().time()),0,10); - } - - /** * @brief deletes a card with the data provided by sabredav * @param integer $aid Addressbook id * @param string $uri the uri of the card diff --git a/apps/contacts/templates/part.contactphoto.php b/apps/contacts/templates/part.contactphoto.php index 9e3f5876cd1..8107650d161 100644 --- a/apps/contacts/templates/part.contactphoto.php +++ b/apps/contacts/templates/part.contactphoto.php @@ -3,7 +3,7 @@ $id = $_['id']; $wattr = isset($_['width'])?'width="'.$_['width'].'"':''; $hattr = isset($_['height'])?'height="'.$_['height'].'"':''; ?> -<img class="loading" id="contacts_details_photo" <?php echo $wattr; ?> <?php echo $hattr; ?> src="<?php echo OC_Helper::linkToAbsolute('contacts', 'photo.php'); ?>?id=<?php echo $id; ?>&refresh=<?php echo rand(); ?>" /> +<img class="loading" id="contacts_details_photo" <?php echo $wattr; ?> <?php echo $hattr; ?> src="<?php echo OC_Helper::linkToAbsolute('contacts', 'photo.php'); ?>?id=<?php echo $id; ?>" /> <progress id="contacts_details_photo_progress" style="display:none;" value="0" max="100">0 %</progress> diff --git a/apps/external/ajax/setsites.php b/apps/external/ajax/setsites.php new file mode 100644 index 00000000000..0537b7ea581 --- /dev/null +++ b/apps/external/ajax/setsites.php @@ -0,0 +1,25 @@ +<?php + +/** + * Copyright (c) 2011, Frank Karlitschek <karlitschek@kde.org> + * This file is licensed under the Affero General Public License version 3 or later. + * See the COPYING-README file. + */ + +require_once('../../../lib/base.php'); +OC_Util::checkAdminUser(); + +$sites = array(); +for ($i = 0; $i < sizeof($_POST['site_name']); $i++) { + if (!empty($_POST['site_name'][$i]) && !empty($_POST['site_url'][$i])) { + array_push($sites, array($_POST['site_name'][$i], $_POST['site_url'][$i])); + } +} + +if (sizeof($sites) == 0) + OC_Appconfig::deleteKey('external', 'sites'); +else + OC_Appconfig::setValue('external', 'sites', json_encode($sites)); + +echo 'true'; +?> diff --git a/apps/external/ajax/seturls.php b/apps/external/ajax/seturls.php deleted file mode 100644 index e994385a199..00000000000 --- a/apps/external/ajax/seturls.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php -/** - * Copyright (c) 2011, Frank Karlitschek <karlitschek@kde.org> - * This file is licensed under the Affero General Public License version 3 or later. - * See the COPYING-README file. - */ - -require_once('../../../lib/base.php'); -OC_Util::checkAdminUser(); - -if(isset($_POST['s1name'])) OC_Appconfig::setValue( 'external','site1name', $_POST['s1name'] ); -if(isset($_POST['s1url'])) OC_Appconfig::setValue( 'external','site1url', $_POST['s1url'] ); -if(isset($_POST['s2name'])) OC_Appconfig::setValue( 'external','site2name', $_POST['s2name'] ); -if(isset($_POST['s2url'])) OC_Appconfig::setValue( 'external','site2url', $_POST['s2url'] ); -if(isset($_POST['s3name'])) OC_Appconfig::setValue( 'external','site3name', $_POST['s3name'] ); -if(isset($_POST['s3url'])) OC_Appconfig::setValue( 'external','site3url', $_POST['s3url'] ); -if(isset($_POST['s4name'])) OC_Appconfig::setValue( 'external','site4name', $_POST['s4name'] ); -if(isset($_POST['s4url'])) OC_Appconfig::setValue( 'external','site4url', $_POST['s4url'] ); -if(isset($_POST['s5name'])) OC_Appconfig::setValue( 'external','site5name', $_POST['s5name'] ); -if(isset($_POST['s5url'])) OC_Appconfig::setValue( 'external','site5url', $_POST['s5url'] ); - -echo 'true'; - -?> diff --git a/apps/external/appinfo/app.php b/apps/external/appinfo/app.php index 0f536cbf418..74e6d5c94c6 100644 --- a/apps/external/appinfo/app.php +++ b/apps/external/appinfo/app.php @@ -1,37 +1,35 @@ <?php /** -* ownCloud - External plugin -* -* @author Frank Karlitschek -* @copyright 2011 Frank Karlitschek karlitschek@kde.org -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE -* License as published by the Free Software Foundation; either -* version 3 of the License, or any later version. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU AFFERO GENERAL PUBLIC LICENSE for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library. If not, see <http://www.gnu.org/licenses/>. -* -*/ - -OC_APP::registerAdmin('external','settings'); - -OC_App::register( array( 'order' => 70, 'id' => 'external', 'name' => 'External' )); - -if(OC_Appconfig::getValue( "external","site1name", '' )<>'') OC_App::addNavigationEntry( array( 'id' => 'external_index1', 'order' => 80, 'href' => OC_Helper::linkTo( 'external', 'index.php' ).'?id=1', 'icon' => OC_Helper::imagePath( 'external', 'external.png' ), 'name' => OC_Appconfig::getValue( "external","site1name", '' ))); - -if(OC_Appconfig::getValue( "external","site2name", '' )<>'') OC_App::addNavigationEntry( array( 'id' => 'external_index2', 'order' => 80, 'href' => OC_Helper::linkTo( 'external', 'index.php' ).'?id=2', 'icon' => OC_Helper::imagePath( 'external', 'external.png' ), 'name' => OC_Appconfig::getValue( "external","site2name", '' ))); - -if(OC_Appconfig::getValue( "external","site3name", '' )<>'') OC_App::addNavigationEntry( array( 'id' => 'external_index3', 'order' => 80, 'href' => OC_Helper::linkTo( 'external', 'index.php' ).'?id=3', 'icon' => OC_Helper::imagePath( 'external', 'external.png' ), 'name' => OC_Appconfig::getValue( "external","site3name", '' ))); - -if(OC_Appconfig::getValue( "external","site4name", '' )<>'') OC_App::addNavigationEntry( array( 'id' => 'external_index4', 'order' => 80, 'href' => OC_Helper::linkTo( 'external', 'index.php' ).'?id=4', 'icon' => OC_Helper::imagePath( 'external', 'external.png' ), 'name' => OC_Appconfig::getValue( "external","site4name", '' ))); - -if(OC_Appconfig::getValue( "external","site5name", '' )<>'') OC_App::addNavigationEntry( array( 'id' => 'external_index5', 'order' => 80, 'href' => OC_Helper::linkTo( 'external', 'index.php' ).'?id=5', 'icon' => OC_Helper::imagePath( 'external', 'external.png' ), 'name' => OC_Appconfig::getValue( "external","site5name", '' ))); - + * ownCloud - External plugin + * + * @author Frank Karlitschek + * @copyright 2011 Frank Karlitschek karlitschek@kde.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +OC::$CLASSPATH['OC_External'] = 'apps/external/lib/external.php'; +OC_Util::addStyle( 'external', 'style'); + +OC_APP::registerAdmin('external', 'settings'); + +OC_App::register(array('order' => 70, 'id' => 'external', 'name' => 'External')); + +$sites = OC_External::getSites(); +for ($i = 0; $i < sizeof($sites); $i++) { + OC_App::addNavigationEntry( + array('id' => 'external_index' . ($i + 1), 'order' => 80 + $i, 'href' => OC_Helper::linkTo('external', 'index.php') . '?id=' . ($i + 1), 'icon' => OC_Helper::imagePath('external', 'external.png'), 'name' => $sites[$i][0])); +}
\ No newline at end of file diff --git a/apps/external/css/style.css b/apps/external/css/style.css new file mode 100644 index 00000000000..f891cb4bc55 --- /dev/null +++ b/apps/external/css/style.css @@ -0,0 +1,14 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- / +/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */ + +.site_url { + width: 250px; +} + +.delete_button { + display: none; +} + +.external_sites { + width: 450px; +} diff --git a/apps/external/index.php b/apps/external/index.php index 51cdc344bbf..1c20f59eaff 100644 --- a/apps/external/index.php +++ b/apps/external/index.php @@ -1,42 +1,43 @@ <?php /** -* ownCloud - External plugin -* -* @author Frank Karlitschek -* @copyright 2011 Frank Karlitschek karlitschek@kde.org -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE -* License as published by the Free Software Foundation; either -* version 3 of the License, or any later version. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU AFFERO GENERAL PUBLIC LICENSE for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library. If not, see <http://www.gnu.org/licenses/>. -* -*/ - + * ownCloud - External plugin + * + * @author Frank Karlitschek + * @copyright 2011 Frank Karlitschek karlitschek@kde.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ require_once('../../lib/base.php'); +require_once('lib/external.php'); OC_Util::checkLoggedIn(); -if(isset($_GET['id'])){ +if (isset($_GET['id'])) { - $id=$_GET['id']; + $id = $_GET['id']; $id = (int) $id; - $url=OC_Appconfig::getValue( "external","site".$id."url", '' ); - OC_App::setActiveNavigationEntry( 'external_index'.$id ); - - $tmpl = new OC_Template( 'external', 'frame', 'user' ); - $tmpl->assign('url',$url); - $tmpl->printPage(); + $sites = OC_External::getSites(); + if (sizeof($sites) >= $id) { + $url = $sites[$id - 1][1]; + OC_App::setActiveNavigationEntry('external_index' . $id); + $tmpl = new OC_Template('external', 'frame', 'user'); + $tmpl->assign('url', $url); + $tmpl->printPage(); + } } - ?> diff --git a/apps/external/js/admin.js b/apps/external/js/admin.js index 6b9b6c67737..0caaabd0b96 100644 --- a/apps/external/js/admin.js +++ b/apps/external/js/admin.js @@ -1,67 +1,56 @@ $(document).ready(function(){ + newSiteHtml = '<li><input type="text" class="site_name" name="site_name[]" value="" placeholder="Name" />\n\ + <input type="text" name="site_url[]" class="site_url" value="" placeholder="URL" />\n\ +<img class="svg action delete_button" src="'+OC.imagePath("core", "actions/delete") +'" title="Remove site" /></li>'; - - - $('#s1name').blur(function(event){ + // Handler functions + function addSiteEventHandler(event) { event.preventDefault(); - var post = $( "#s1name" ).serialize(); - $.post( OC.filePath('external','ajax','seturls.php') , post, function(data){ OC.msg.finishedSaving('#s1name .msg', data); }); - }); + + saveSites(); + } - $('#s2name').blur(function(event){ + function deleteButtonEventHandler(event) { event.preventDefault(); - var post = $( "#s2name" ).serialize(); - $.post( OC.filePath('external','ajax','seturls.php') , post, function(data){ OC.msg.finishedSaving('#s2name .msg', data); }); - }); - $('#s3name').blur(function(event){ - event.preventDefault(); - var post = $( "#s3name" ).serialize(); - $.post( OC.filePath('external','ajax','seturls.php') , post, function(data){ OC.msg.finishedSaving('#s3name .msg', data); }); - }); + $(this).tipsy('hide'); + $(this).parent().remove(); - $('#s4name').blur(function(event){ - event.preventDefault(); - var post = $( "#s4name" ).serialize(); - $.post( OC.filePath('external','ajax','seturls.php') , post, function(data){ OC.msg.finishedSaving('#s4name .msg', data); }); - }); + saveSites(); + } - $('#s5name').blur(function(event){ - event.preventDefault(); - var post = $( "#s5name" ).serialize(); - $.post( OC.filePath('external','ajax','seturls.php') , post, function(data){ OC.msg.finishedSaving('#s5name .msg', data); }); - }); + function saveSites() { + var post = $('#external').serialize(); + $.post( OC.filePath('external','ajax','setsites.php') , post, function(data) { + // OC.msg.finishedSaving('#site_name .msg', data); + }); + } - $('#s1url').blur(function(event){ - event.preventDefault(); - var post = $( "#s1url" ).serialize(); - $.post( OC.filePath('external','ajax','seturls.php') , post, function(data){ OC.msg.finishedSaving('#s1url .msg', data); }); - }); + function showDeleteButton(event) { + $(this).find('img.delete_button').fadeIn(100); + } - $('#s2url').blur(function(event){ - event.preventDefault(); - var post = $( "#s2url" ).serialize(); - $.post( OC.filePath('external','ajax','seturls.php') , post, function(data){ OC.msg.finishedSaving('#s2url .msg', data); }); - }); + function hideDeleteButton(event) { + $(this).find('img.delete_button').fadeOut(100); + } - $('#s3url').blur(function(event){ - event.preventDefault(); - var post = $( "#s3url" ).serialize(); - $.post( OC.filePath('external','ajax','seturls.php') , post, function(data){ OC.msg.finishedSaving('#s3url .msg', data); }); - }); + // Initialize events + $('input[name^=site_]').change(addSiteEventHandler); + $('img.delete_button').click(deleteButtonEventHandler); + $('img.delete_button').tipsy(); - $('#s4url').blur(function(event){ - event.preventDefault(); - var post = $( "#s4url" ).serialize(); - $.post( OC.filePath('external','ajax','seturls.php') , post, function(data){ OC.msg.finishedSaving('#s4url .msg', data); }); - }); + $('#external li').hover(showDeleteButton, hideDeleteButton); - $('#s5url').blur(function(event){ + $('#add_external_site').click(function(event) { event.preventDefault(); - var post = $( "#s5url" ).serialize(); - $.post( OC.filePath('external','ajax','seturls.php') , post, function(data){ OC.msg.finishedSaving('#s5url .msg', data); }); - }); + $('#external ul').append(newSiteHtml); + $('input.site_url:last').prev('input.site_name').andSelf().change(addSiteEventHandler); + $('img.delete_button').click(deleteButtonEventHandler); + $('img.delete_button:last').tipsy(); + $('#external li:last').hover(showDeleteButton, hideDeleteButton); + + }); }); diff --git a/apps/external/lib/external.php b/apps/external/lib/external.php new file mode 100644 index 00000000000..9dd32321135 --- /dev/null +++ b/apps/external/lib/external.php @@ -0,0 +1,36 @@ +<?php + +/** + * ownCloud - gallery application + * + * @author Bartek Przybylski + * @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +class OC_External { + + public static function getSites() { + if (($sites = json_decode(OC_Appconfig::getValue("external", "sites", ''))) != NULL) { + return $sites; + } + + return array(); + } + +} + +?> diff --git a/apps/external/settings.php b/apps/external/settings.php index 3e0c3425128..416c9a5c11f 100644 --- a/apps/external/settings.php +++ b/apps/external/settings.php @@ -6,17 +6,5 @@ OC_Util::addScript( "external", "admin" ); $tmpl = new OC_Template( 'external', 'settings'); - $tmpl->assign('s1name',OC_Appconfig::getValue( "external","site1name", '' )); - $tmpl->assign('s2name',OC_Appconfig::getValue( "external","site2name", '' )); - $tmpl->assign('s3name',OC_Appconfig::getValue( "external","site3name", '' )); - $tmpl->assign('s4name',OC_Appconfig::getValue( "external","site4name", '' )); - $tmpl->assign('s5name',OC_Appconfig::getValue( "external","site5name", '' )); - - $tmpl->assign('s1url',OC_Appconfig::getValue( "external","site1url", '' )); - $tmpl->assign('s2url',OC_Appconfig::getValue( "external","site2url", '' )); - $tmpl->assign('s3url',OC_Appconfig::getValue( "external","site3url", '' )); - $tmpl->assign('s4url',OC_Appconfig::getValue( "external","site4url", '' )); - $tmpl->assign('s5url',OC_Appconfig::getValue( "external","site5url", '' )); - return $tmpl->fetchPage(); ?> diff --git a/apps/external/templates/settings.php b/apps/external/templates/settings.php index a72327d35c8..a130477d465 100644 --- a/apps/external/templates/settings.php +++ b/apps/external/templates/settings.php @@ -1,23 +1,21 @@ <form id="external"> <fieldset class="personalblock"> <strong>External Sites</strong><br /> - <input type="text" name="s1name" id="s1name" value="<?php echo $_['s1name']; ?>" placeholder="<?php echo $l->t('Name');?>" /> - <input type="text" name="s1url" id="s1url" value="<?php echo $_['s1url']; ?>" placeholder="<?php echo $l->t('Url');?>" /> - <br /> - <input type="text" name="s2name" id="s2name" value="<?php echo $_['s2name']; ?>" placeholder="<?php echo $l->t('Name');?>" /> - <input type="text" name="s2url" id="s2url" value="<?php echo $_['s2url']; ?>" placeholder="<?php echo $l->t('Url');?>" /> - <br /> - <input type="text" name="s3name" id="s3name" value="<?php echo $_['s3name']; ?>" placeholder="<?php echo $l->t('Name');?>" /> - <input type="text" name="s3url" id="s3url" value="<?php echo $_['s3url']; ?>" placeholder="<?php echo $l->t('Url');?>" /> - <br /> - <input type="text" name="s4name" id="s4name" value="<?php echo $_['s4name']; ?>" placeholder="<?php echo $l->t('Name');?>" /> - <input type="text" name="s4url" id="s4url" value="<?php echo $_['s4url']; ?>" placeholder="<?php echo $l->t('Url');?>" /> - <br /> - <input type="text" name="s5name" id="s5name" value="<?php echo $_['s5name']; ?>" placeholder="<?php echo $l->t('Name');?>" /> - <input type="text" name="s5url" id="s5url" value="<?php echo $_['s5url']; ?>" placeholder="<?php echo $l->t('Url');?>" /> - <br /> + <ul class="external_sites"> + <?php + $sites = OC_External::getSites(); + for($i = 0; $i < sizeof($sites); $i++) { + echo '<li><input type="text" name="site_name[]" class="site_name" value="'.$sites[$i][0].'" placeholder="'.$l->t('Name').'" /> + <input type="text" class="site_url" name="site_url[]" value="'.$sites[$i][1].'" placeholder="'.$l->t('URL').'" /> + <img class="svg action delete_button" src="'.image_path("", "actions/delete.svg") .'" title="'.$l->t("Remove site").'" /> + </li>'; + } + ?> -<span class="msg"></span> + </ul> + + <input type="button" id="add_external_site" value="Add" /> + <span class="msg"></span> </fieldset> </form> diff --git a/apps/files_archive/appinfo/app.php b/apps/files_archive/appinfo/app.php new file mode 100644 index 00000000000..693c28d98a0 --- /dev/null +++ b/apps/files_archive/appinfo/app.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +OC::$CLASSPATH['OC_Archive'] = 'apps/files_archive/lib/archive.php'; +foreach(array('ZIP') as $type){ + OC::$CLASSPATH['OC_Archive_'.$type] = 'apps/files_archive/lib/'.strtolower($type).'.php'; +} + +OC::$CLASSPATH['OC_Filestorage_Archive']='apps/files_archive/lib/storage.php'; + +OC_Hook::connect('OC_Filesystem','get_mountpoint','OC_Filestorage_Archive','autoMount'); + +OC_Util::addScript( 'files_archive', 'archive' ); diff --git a/apps/files_archive/appinfo/info.xml b/apps/files_archive/appinfo/info.xml new file mode 100644 index 00000000000..df767d39f6b --- /dev/null +++ b/apps/files_archive/appinfo/info.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<info> + <id>files_archive</id> + <name>Archive support</name> + <description>Transparent opening of archives</description> + <version>0.1</version> + <licence>AGPL</licence> + <author>Robin Appelman</author> + <require>3</require> +</info> diff --git a/apps/files_archive/js/archive.js b/apps/files_archive/js/archive.js new file mode 100644 index 00000000000..ec316c7bf2c --- /dev/null +++ b/apps/files_archive/js/archive.js @@ -0,0 +1,15 @@ +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +$(document).ready(function() { + if(typeof FileActions!=='undefined'){ + FileActions.register('application/zip','Open','',function(filename){ + window.location='index.php?dir='+encodeURIComponent($('#dir').val()).replace(/%2F/g, '/')+'/'+encodeURIComponent(filename); + }); + FileActions.setDefault('application/zip','Open'); + } +}); diff --git a/apps/files_archive/lib/archive.php b/apps/files_archive/lib/archive.php new file mode 100644 index 00000000000..be89f894fb7 --- /dev/null +++ b/apps/files_archive/lib/archive.php @@ -0,0 +1,99 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +abstract class OC_Archive{ + /** + * open any of the supporeted archive types + * @param string path + * @return OC_Archive + */ + public static function open($path){ + $ext=substr($path,strrpos($path,'.')); + switch($ext){ + case '.zip': + return new OC_Archive_ZIP($path); + } + } + + abstract function __construct($source); + /** + * add an empty folder to the archive + * @param string path + * @return bool + */ + abstract function addFolder($path); + /** + * add a file to the archive + * @param string path + * @param string source either a local file or string data + * @return bool + */ + abstract function addFile($path,$source=''); + /** + * rename a file or folder in the archive + * @param string source + * @param string dest + * @return bool + */ + abstract function rename($source,$dest); + /** + * get the uncompressed size of a file in the archive + * @param string path + * @return int + */ + abstract function filesize($path); + /** + * get the last modified time of a file in the archive + * @param string path + * @return int + */ + abstract function mtime($path); + /** + * get the files in a folder + * @param path + * @return array + */ + abstract function getFolder($path); + /** + *get all files in the archive + * @return array + */ + abstract function getFiles(); + /** + * get the content of a file + * @param string path + * @return string + */ + abstract function getFile($path); + /** + * extract a single file from the archive + * @param string path + * @param string dest + * @return bool + */ + abstract function extractFile($path,$dest); + /** + * check if a file or folder exists in the archive + * @param string path + * @return bool + */ + abstract function fileExists($path); + /** + * remove a file or folder from the archive + * @param string path + * @return bool + */ + abstract function remove($path); + /** + * get a file handler + * @param string path + * @param string mode + * @return resource + */ + abstract function getStream($path,$mode); +} diff --git a/apps/files_archive/lib/storage.php b/apps/files_archive/lib/storage.php new file mode 100644 index 00000000000..72a96ca5a5d --- /dev/null +++ b/apps/files_archive/lib/storage.php @@ -0,0 +1,142 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class OC_Filestorage_Archive extends OC_Filestorage_Common{ + /** + * underlying local storage used for missing functions + * @var OC_Archive + */ + private $archive; + private $path; + private static $mounted=array(); + private static $enableAutomount=true; + private static $rootView; + + private function stripPath($path){//files should never start with / + if(substr($path,0,1)=='/'){ + $path=substr($path,1); + } + return $path; + } + + public function __construct($params){ + $this->archive=OC_Archive::open($params['archive']); + $this->path=$params['archive']; + } + + public function mkdir($path){ + $path=$this->stripPath($path); + return $this->archive->addFolder($path); + } + public function rmdir($path){ + $path=$this->stripPath($path); + return $this->archive->remove($path.'/'); + } + public function opendir($path){ + $path=$this->stripPath($path); + $content=$this->archive->getFolder($path); + foreach($content as &$file){ + if(substr($file,-1)=='/'){ + $file=substr($file,0,-1); + } + } + $id=md5($this->path.$path); + OC_FakeDirStream::$dirs[$id]=$content; + return opendir('fakedir://'.$id); + } + public function stat($path){ + $ctime=filectime($this->path); + $path=$this->stripPath($path); + if($path==''){ + $stat=stat($this->path); + }else{ + if($this->is_dir($path)){ + $stat=array('size'=>0); + $stat['mtime']=filemtime($this->path); + }else{ + $stat=array(); + $stat['mtime']=$this->archive->mtime($path); + $stat['size']=$this->archive->filesize($path); + } + } + $stat['ctime']=$ctime; + return $stat; + } + public function filetype($path){ + $path=$this->stripPath($path); + if($path==''){ + return 'dir'; + } + if(substr($path,-1)=='/'){ + return $this->archive->fileExists($path)?'dir':'file'; + }else{ + return $this->archive->fileExists($path.'/')?'dir':'file'; + } + } + public function is_readable($path){ + return is_readable($this->path); + } + public function is_writable($path){ + return is_writable($this->path); + } + public function file_exists($path){ + $path=$this->stripPath($path); + if($path==''){ + return file_exists($this->path); + } + return $this->archive->fileExists($path) or $this->archive->fileExists($path.'/'); + } + public function unlink($path){ + $path=$this->stripPath($path); + return $this->archive->remove($path); + } + public function fopen($path,$mode){ + $path=$this->stripPath($path); + return $this->archive->getStream($path,$mode); + } + public function free_space($path){ + return 0; + } + public function touch($path, $mtime=null){ + if(is_null($mtime)){ + $tmpFile=OC_Helper::tmpFile(); + $this->archive->extractFile($path,$tmpFile); + $this->archive->addfile($path,$tmpFile); + }else{ + return false;//not supported + } + } + + /** + * automount paths from file hooks + * @param aray params + */ + public static function autoMount($params){ + if(!self::$enableAutomount){ + return; + } + $path=$params['path']; + if(!self::$rootView){ + self::$rootView=new OC_FilesystemView(''); + } + self::$enableAutomount=false;//prevent recursion + $supported=array('zip'); + foreach($supported as $type){ + $ext='.'.$type.'/'; + if(($pos=strpos(strtolower($path),$ext))!==false){ + $archive=substr($path,0,$pos+strlen($ext)-1); + if(self::$rootView->file_exists($archive) and array_search($archive,self::$mounted)===false){ + $localArchive=self::$rootView->getLocalFile($archive); + OC_Filesystem::mount('OC_Filestorage_Archive',array('archive'=>$localArchive),$archive.'/'); + self::$mounted[]=$archive; + } + } + } + self::$enableAutomount=true; + } +} diff --git a/apps/files_archive/lib/zip.php b/apps/files_archive/lib/zip.php new file mode 100644 index 00000000000..eab101b3a5c --- /dev/null +++ b/apps/files_archive/lib/zip.php @@ -0,0 +1,182 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class OC_Archive_ZIP extends OC_Archive{ + /** + * @var ZipArchive zip + */ + private $zip=null; + private $contents=array(); + private $success=false; + private $path; + + function __construct($source){ + $this->path=$source; + $this->zip=new ZipArchive(); + if($this->zip->open($source,ZipArchive::CREATE)){ + }else{ + OC_LOG::write('files_archive','Error while opening archive '.$source,OC_Log::WARN); + } + } + /** + * add an empty folder to the archive + * @param string path + * @return bool + */ + function addFolder($path){ + return $this->zip->addEmptyDir($path); + } + /** + * add a file to the archive + * @param string path + * @param string source either a local file or string data + * @return bool + */ + function addFile($path,$source=''){ + if(file_exists($source)){ + $result=$this->zip->addFile($source,$path); + }else{ + $result=$this->zip->addFromString($path,$source); + } + if($result){ + $this->zip->close();//close and reopen to save the zip + $this->zip->open($this->path); + } + return $result; + } + /** + * rename a file or folder in the archive + * @param string source + * @param string dest + * @return bool + */ + function rename($source,$dest){ + return $this->zip->renameName($source,$dest); + } + /** + * get the uncompressed size of a file in the archive + * @param string path + * @return int + */ + function filesize($path){ + $stat=$this->zip->statName($path); + return $stat['size']; + } + /** + * get the last modified time of a file in the archive + * @param string path + * @return int + */ + function mtime($path){ + $stat=$this->zip->statName($path); + return $stat['mtime']; + } + /** + * get the files in a folder + * @param path + * @return array + */ + function getFolder($path){ + $files=$this->getFiles(); + $folderContent=array(); + $pathLength=strlen($path); + foreach($files as $file){ + if(substr($file,0,$pathLength)==$path and $file!=$path){ + if(strrpos(substr($file,0,-1),'/')<=$pathLength){ + $folderContent[]=substr($file,$pathLength); + } + } + } + return $folderContent; + } + /** + *get all files in the archive + * @return array + */ + function getFiles(){ + if(count($this->contents)){ + return $this->contents; + } + $fileCount=$this->zip->numFiles; + $files=array(); + for($i=0;$i<$fileCount;$i++){ + $files[]=$this->zip->getNameIndex($i); + } + $this->contents=$files; + return $files; + } + /** + * get the content of a file + * @param string path + * @return string + */ + function getFile($path){ + return $this->zip->getFromName($path); + } + /** + * extract a single file from the archive + * @param string path + * @param string dest + * @return bool + */ + function extractFile($path,$dest){ + $fp = $this->zip->getStream($path); + file_put_contents($dest,$fp); + } + /** + * check if a file or folder exists in the archive + * @param string path + * @return bool + */ + function fileExists($path){ + return $this->zip->locateName($path)!==false; + } + /** + * remove a file or folder from the archive + * @param string path + * @return bool + */ + function remove($path){ + return $this->zip->deleteName($path); + } + /** + * get a file handler + * @param string path + * @param string mode + * @return resource + */ + function getStream($path,$mode){ + if($mode=='r' or $mode=='rb'){ + return $this->zip->getStream($path); + }else{//since we cant directly get a writable stream, make a temp copy of the file and put it back in the archive when the stream is closed + if(strrpos($path,'.')!==false){ + $ext=substr($path,strrpos($path,'.')); + }else{ + $ext=''; + } + $tmpFile=OC_Helper::tmpFile($ext); + OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack'); + if($this->fileExists($path)){ + $this->extractFile($path,$tmpFile); + } + self::$tempFiles[$tmpFile]=$path; + return fopen('close://'.$tmpFile,$mode); + } + } + + private static $tempFiles=array(); + /** + * write back temporary files + */ + function writeBack($tmpFile){ + if(isset(self::$tempFiles[$tmpFile])){ + $this->addFile(self::$tempFiles[$tmpFile],$tmpFile); + unlink($tmpFile); + } + } +} diff --git a/apps/files_archive/tests/archive.php b/apps/files_archive/tests/archive.php new file mode 100644 index 00000000000..2e26b5e03b5 --- /dev/null +++ b/apps/files_archive/tests/archive.php @@ -0,0 +1,97 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +abstract class Test_Archive extends UnitTestCase { + /** + * @var OC_Archive + */ + protected $instance; + + /** + * get the existing test archive + * @return OC_Archive + */ + abstract protected function getExisting(); + /** + * get a new archive for write testing + * @return OC_Archive + */ + abstract protected function getNew(); + + public function testGetFiles(){ + $this->instance=$this->getExisting(); + $allFiles=$this->instance->getFiles(); + $expected=array('lorem.txt','logo-wide.png','dir/','dir/lorem.txt'); + $this->assertEqual(4,count($allFiles)); + foreach($expected as $file){ + $this->assertNotIdentical(false,array_search($file,$allFiles),'cant find '.$file.' in archive'); + $this->assertTrue($this->instance->fileExists($file)); + } + $this->assertFalse($this->instance->fileExists('non/existing/file')); + + $rootContent=$this->instance->getFolder(''); + $expected=array('lorem.txt','logo-wide.png','dir/'); + $this->assertEqual(3,count($rootContent)); + foreach($expected as $file){ + $this->assertNotIdentical(false,array_search($file,$rootContent),'cant find '.$file.' in archive'); + } + + $dirContent=$this->instance->getFolder('dir/'); + $expected=array('lorem.txt'); + $this->assertEqual(1,count($dirContent)); + foreach($expected as $file){ + $this->assertNotIdentical(false,array_search($file,$dirContent),'cant find '.$file.' in archive'); + } + } + + public function testContent(){ + $this->instance=$this->getExisting(); + $dir=OC::$SERVERROOT.'/apps/files_archive/tests/data'; + $textFile=$dir.'/lorem.txt'; + $this->assertEqual(file_get_contents($textFile),$this->instance->getFile('lorem.txt')); + + $tmpFile=OC_Helper::tmpFile('.txt'); + $this->instance->extractFile('lorem.txt',$tmpFile); + $this->assertEqual(file_get_contents($textFile),file_get_contents($tmpFile)); + } + + public function testWrite(){ + $dir=OC::$SERVERROOT.'/apps/files_archive/tests/data'; + $textFile=$dir.'/lorem.txt'; + $this->instance=$this->getNew(); + $this->assertEqual(0,count($this->instance->getFiles())); + $this->instance->addFile('lorem.txt',$textFile); + $this->assertEqual(1,count($this->instance->getFiles())); + $this->assertTrue($this->instance->fileExists('lorem.txt')); + + $this->assertEqual(file_get_contents($textFile),$this->instance->getFile('lorem.txt')); + $this->instance->addFile('lorem.txt','foobar'); + $this->assertEqual('foobar',$this->instance->getFile('lorem.txt')); + } + + public function testReadStream(){ + $dir=OC::$SERVERROOT.'/apps/files_archive/tests/data'; + $this->instance=$this->getExisting(); + $fh=$this->instance->getStream('lorem.txt','r'); + $this->assertTrue($fh); + $content=fread($fh,$this->instance->filesize('lorem.txt')); + fclose($fh); + $this->assertEqual(file_get_contents($dir.'/lorem.txt'),$content); + } + public function testWriteStream(){ + $dir=OC::$SERVERROOT.'/apps/files_archive/tests/data'; + $this->instance=$this->getNew(); + $fh=$this->instance->getStream('lorem.txt','w'); + $source=fopen($dir.'/lorem.txt','r'); + OC_Helper::streamCopy($source,$fh); + fclose($source); + fclose($fh); + $this->assertTrue($this->instance->fileExists('lorem.txt')); + $this->assertEqual(file_get_contents($dir.'/lorem.txt'),$this->instance->getFile('lorem.txt')); + } +} diff --git a/apps/files_archive/tests/storage.php b/apps/files_archive/tests/storage.php new file mode 100644 index 00000000000..4d0a83356bd --- /dev/null +++ b/apps/files_archive/tests/storage.php @@ -0,0 +1,25 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class Test_Filestorage_Archive_Zip extends Test_FileStorage { + /** + * @var string tmpDir + */ + private $tmpFile; + + public function setUp(){ + $this->tmpFile=OC_Helper::tmpFile('.zip'); + $this->instance=new OC_Filestorage_Archive(array('archive'=>$this->tmpFile)); + } + + public function tearDown(){ + unlink($this->tmpFile); + } +} + +?>
\ No newline at end of file diff --git a/apps/files_archive/tests/zip.php b/apps/files_archive/tests/zip.php new file mode 100644 index 00000000000..3ff713eda70 --- /dev/null +++ b/apps/files_archive/tests/zip.php @@ -0,0 +1,20 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +require_once('archive.php'); + +class Test_Archive_ZIP extends Test_Archive{ + protected function getExisting(){ + $dir=OC::$SERVERROOT.'/apps/files_archive/tests/data'; + return new OC_Archive_ZIP($dir.'/data.zip'); + } + + protected function getNew(){ + return new OC_Archive_ZIP(OC_Helper::tmpFile('.zip')); + } +} diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php new file mode 100644 index 00000000000..68c445d5d77 --- /dev/null +++ b/apps/files_encryption/appinfo/app.php @@ -0,0 +1,19 @@ +<?php + +OC::$CLASSPATH['OC_Crypt'] = 'apps/files_encryption/lib/crypt.php'; +OC::$CLASSPATH['OC_CryptStream'] = 'apps/files_encryption/lib/cryptstream.php'; +OC::$CLASSPATH['OC_FileProxy_Encryption'] = 'apps/files_encryption/lib/proxy.php'; + +OC_FileProxy::register(new OC_FileProxy_Encryption()); + +OC_Hook::connect('OC_User','post_login','OC_Crypt','loginListener'); + +stream_wrapper_register('crypt','OC_CryptStream'); + +if(!isset($_SESSION['enckey']) and OC_User::isLoggedIn()){//force the user to re-loggin if the encryption key isn't unlocked (happens when a user is logged in before the encryption app is enabled) + OC_User::logout(); + header("Location: ".OC::$WEBROOT.'/'); + exit(); +} + +OC_App::registerAdmin('files_encryption', 'settings'); diff --git a/apps/files_encryption/appinfo/info.xml b/apps/files_encryption/appinfo/info.xml new file mode 100644 index 00000000000..053044aaed2 --- /dev/null +++ b/apps/files_encryption/appinfo/info.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<info> + <id>files_encryption</id> + <name>Encryption</name> + <description>Server side encryption of files</description> + <version>0.1</version> + <licence>AGPL</licence> + <author>Robin Appelman</author> + <require>3</require> +</info> diff --git a/apps/files_encryption/js/settings.js b/apps/files_encryption/js/settings.js new file mode 100644 index 00000000000..adbf0c87245 --- /dev/null +++ b/apps/files_encryption/js/settings.js @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com> + * This file is licensed under the Affero General Public License version 3 or later. + * See the COPYING-README file. + */ + + +$(document).ready(function(){ + $('#encryption_blacklist').multiSelect({ + oncheck:blackListChange, + onuncheck:blackListChange, + createText:'...', + }); + + function blackListChange(){ + var blackList=$('#encryption_blacklist').val().join(','); + OC.AppConfig.setValue('files_encryption','type_blacklist',blackList); + } +})
\ No newline at end of file diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php new file mode 100644 index 00000000000..0a593b98c4b --- /dev/null +++ b/apps/files_encryption/lib/crypt.php @@ -0,0 +1,206 @@ +<?php +/** + * ownCloud + * + * @author Frank Karlitschek + * @copyright 2010 Frank Karlitschek karlitschek@kde.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + + + +// Todo: +// - Crypt/decrypt button in the userinterface +// - Setting if crypto should be on by default +// - Add a setting "Don´t encrypt files larger than xx because of performance reasons" +// - Transparent decrypt/encrpt in filesystem.php. Autodetect if a file is encrypted (.encrypted extensio) +// - Don't use a password directly as encryption key. but a key which is stored on the server and encrypted with the user password. -> password change faster +// - IMPORTANT! Check if the block lenght of the encrypted data stays the same + + +require_once('Crypt_Blowfish/Blowfish.php'); + +/** + * This class is for crypting and decrypting + */ +class OC_Crypt { + static private $bf = null; + + public static function loginListener($params){ + self::init($params['uid'],$params['password']); + } + + public static function init($login,$password) { + $view=new OC_FilesystemView('/'.$login); + OC_FileProxy::$enabled=false; + if(!$view->file_exists('/encryption.key')){// does key exist? + OC_Crypt::createkey($login,$password); + } + $key=$view->file_get_contents('/encryption.key'); + OC_FileProxy::$enabled=true; + $_SESSION['enckey']=OC_Crypt::decrypt($key, $password); + } + + /** + * get the blowfish encryption handeler for a key + * @param string $key (optional) + * @return Crypt_Blowfish + * + * if the key is left out, the default handeler will be used + */ + public static function getBlowfish($key=''){ + if($key){ + return new Crypt_Blowfish($key); + }else{ + if(!isset($_SESSION['enckey'])){ + return false; + } + if(!self::$bf){ + self::$bf=new Crypt_Blowfish($_SESSION['enckey']); + } + return self::$bf; + } + } + + public static function createkey($username,$passcode) { + // generate a random key + $key=mt_rand(10000,99999).mt_rand(10000,99999).mt_rand(10000,99999).mt_rand(10000,99999); + + // encrypt the key with the passcode of the user + $enckey=OC_Crypt::encrypt($key,$passcode); + + // Write the file + $proxyEnabled=OC_FileProxy::$enabled; + OC_FileProxy::$enabled=false; + $view=new OC_FilesystemView('/'.$username); + $view->file_put_contents('/encryption.key',$enckey); + OC_FileProxy::$enabled=$proxyEnabled; + } + + public static function changekeypasscode($oldPassword, $newPassword) { + if(OC_User::isLoggedIn()){ + $username=OC_USER::getUser(); + $view=new OC_FilesystemView('/'.$username); + + // read old key + $key=$view->file_get_contents('/encryption.key'); + + // decrypt key with old passcode + $key=OC_Crypt::decrypt($key, $oldPassword); + + // encrypt again with new passcode + $key=OC_Crypt::encrypt($key, $newPassword); + + // store the new key + $view->file_put_contents('/encryption.key', $key ); + } + } + + /** + * @brief encrypts an content + * @param $content the cleartext message you want to encrypt + * @param $key the encryption key (optional) + * @returns encrypted content + * + * This function encrypts an content + */ + public static function encrypt( $content, $key='') { + $bf = self::getBlowfish($key); + return($bf->encrypt($content)); + } + + /** + * @brief decryption of an content + * @param $content the cleartext message you want to decrypt + * @param $key the encryption key (optional) + * @returns cleartext content + * + * This function decrypts an content + */ + public static function decrypt( $content, $key='') { + $bf = self::getBlowfish($key); + return($bf->decrypt($content)); + } + + /** + * @brief encryption of a file + * @param $filename + * @param $key the encryption key + * + * This function encrypts a file + */ + public static function encryptfile( $filename, $key) { + $handleread = fopen($filename, "rb"); + if($handleread<>FALSE) { + $handlewrite = fopen($filename.OC_Crypt::$encription_extension, "wb"); + while (!feof($handleread)) { + $content = fread($handleread, 8192); + $enccontent=OC_CRYPT::encrypt( $content, $key); + fwrite($handlewrite, $enccontent); + } + fclose($handlewrite); + unlink($filename); + } + fclose($handleread); + } + + + /** + * @brief decryption of a file + * @param $filename + * @param $key the decryption key + * + * This function decrypts a file + */ + public static function decryptfile( $filename, $key) { + $handleread = fopen($filename.OC_Crypt::$encription_extension, "rb"); + if($handleread<>FALSE) { + $handlewrite = fopen($filename, "wb"); + while (!feof($handleread)) { + $content = fread($handleread, 8192); + $enccontent=OC_CRYPT::decrypt( $content, $key); + fwrite($handlewrite, $enccontent); + } + fclose($handlewrite); + unlink($filename.OC_Crypt::$encription_extension); + } + fclose($handleread); + } + + /** + * encrypt data in 8192b sized blocks + */ + public static function blockEncrypt($data){ + $result=''; + while(strlen($data)){ + $result=self::encrypt(substr($data,0,8192)); + $data=substr($data,8192); + } + return $result; + } + + /** + * decrypt data in 8192b sized blocks + */ + public static function blockDecrypt($data){ + $result=''; + while(strlen($data)){ + $result=self::decrypt(substr($data,0,8192)); + $data=substr($data,8192); + } + return $result; + } +} diff --git a/apps/files_encryption/lib/cryptstream.php b/apps/files_encryption/lib/cryptstream.php new file mode 100644 index 00000000000..86583096f1d --- /dev/null +++ b/apps/files_encryption/lib/cryptstream.php @@ -0,0 +1,153 @@ +<?php +/** + * ownCloud + * + * @author Robin Appelman + * @copyright 2011 Robin Appelman icewind1991@gmail.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +/** + * transparently encrypted filestream + * + * you can use it as wrapper around an existing stream by setting OC_CryptStream::$sourceStreams['foo']=array('path'=>$path,'stream'=>$stream) + * and then fopen('crypt://streams/foo'); + */ + +class OC_CryptStream{ + public static $sourceStreams=array(); + private $source; + private $path; + private $readBuffer;//for streams that dont support seeking + private $meta=array();//header/meta for source stream + + public function stream_open($path, $mode, $options, &$opened_path){ + $path=str_replace('crypt://','',$path); + if(dirname($path)=='streams' and isset(self::$sourceStreams[basename($path)])){ + $this->source=self::$sourceStreams[basename($path)]['stream']; + $this->path=self::$sourceStreams[basename($path)]['path']; + }else{ + $this->path=$path; + OC_Log::write('files_encryption','open encrypted '.$path. ' in '.$mode,OC_Log::DEBUG); + OC_FileProxy::$enabled=false;//disable fileproxies so we can open the source file + $this->source=OC_FileSystem::fopen($path,$mode); + OC_FileProxy::$enabled=true; + if(!is_resource($this->source)){ + OC_Log::write('files_encryption','failed to open '.$path,OC_Log::ERROR); + } + } + if(is_resource($this->source)){ + $this->meta=stream_get_meta_data($this->source); + } + return is_resource($this->source); + } + + public function stream_seek($offset, $whence=SEEK_SET){ + fseek($this->source,$offset,$whence); + } + + public function stream_tell(){ + return ftell($this->source); + } + + public function stream_read($count){ + $pos=0; + $currentPos=ftell($this->source); + $offset=$currentPos%8192; + $result=''; + if($offset>0){ + if($this->meta['seekable']){ + fseek($this->source,-$offset,SEEK_CUR);//if seeking isnt supported the internal read buffer will be used + }else{ + $pos=strlen($this->readBuffer); + $result=$this->readBuffer; + } + } + while($count>$pos){ + $data=fread($this->source,8192); + $pos+=8192; + if(strlen($data)){ + $result.=OC_Crypt::decrypt($data); + } + } + if(!$this->meta['seekable']){ + $this->readBuffer=substr($result,$count); + } + return substr($result,0,$count); + } + + public function stream_write($data){ + $length=strlen($data); + $written=0; + $currentPos=ftell($this->source); + if($currentPos%8192!=0){ + //make sure we always start on a block start + fseek($this->source,-($currentPos%8192),SEEK_CUR); + $encryptedBlock=fread($this->source,8192); + fseek($this->source,-($currentPos%8192),SEEK_CUR); + $block=OC_Crypt::decrypt($encryptedBlock); + $data=substr($block,0,$currentPos%8192).$data; + } + while(strlen($data)>0){ + if(strlen($data)<8192){ + //fetch the current data in that block and append it to the input so we always write entire blocks + $oldPos=ftell($this->source); + $encryptedBlock=fread($this->source,8192); + fseek($this->source,$oldPos); + $block=OC_Crypt::decrypt($encryptedBlock); + $data.=substr($block,strlen($data)); + } + $encrypted=OC_Crypt::encrypt(substr($data,0,8192)); + fwrite($this->source,$encrypted); + $data=substr($data,8192); + } + return $length; + } + + public function stream_set_option($option,$arg1,$arg2){ + switch($option){ + case STREAM_OPTION_BLOCKING: + stream_set_blocking($this->source,$arg1); + break; + case STREAM_OPTION_READ_TIMEOUT: + stream_set_timeout($this->source,$arg1,$arg2); + break; + case STREAM_OPTION_WRITE_BUFFER: + stream_set_write_buffer($this->source,$arg1,$arg2); + } + } + + public function stream_stat(){ + return fstat($this->source); + } + + public function stream_lock($mode){ + flock($this->source,$mode); + } + + public function stream_flush(){ + return fflush($this->source); + } + + public function stream_eof(){ + return feof($this->source); + } + + public function stream_close(){ + OC_FileCache::put($this->path,array('encrypted'=>true)); + return fclose($this->source); + } +}
\ No newline at end of file diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php new file mode 100644 index 00000000000..c1c26d7754f --- /dev/null +++ b/apps/files_encryption/lib/proxy.php @@ -0,0 +1,115 @@ +<?php + +/** +* ownCloud +* +* @author Robin Appelman +* @copyright 2011 Robin Appelman icewind1991@gmail.com +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +* License as published by the Free Software Foundation; either +* version 3 of the License, or any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU AFFERO GENERAL PUBLIC LICENSE for more details. +* +* You should have received a copy of the GNU Affero General Public +* License along with this library. If not, see <http://www.gnu.org/licenses/>. +* +*/ + +/** + * transparent encryption + */ + +class OC_FileProxy_Encryption extends OC_FileProxy{ + private static $blackList=null; //mimetypes blacklisted from encryption + private static $metaData=array(); //metadata cache + + /** + * check if a file should be encrypted during write + * @param string $path + * @return bool + */ + private static function shouldEncrypt($path){ + if(is_null(self::$blackList)){ + self::$blackList=explode(',',OC_Appconfig::getValue('files_encryption','type_blacklist','jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg')); + } + if(self::isEncrypted($path)){ + return true; + } + $extention=substr($path,strrpos($path,'.')+1); + if(array_search($extention,self::$blackList)===false){ + return true; + } + } + + /** + * check if a file is encrypted + * @param string $path + * @return bool + */ + private static function isEncrypted($path){ + if(isset(self::$metaData[$path])){ + $metadata=self::$metaData[$path]; + }else{ + $metadata=OC_FileCache::getCached($path); + self::$metaData[$path]=$metadata; + } + return (bool)$metadata['encrypted']; + } + + public function preFile_put_contents($path,&$data){ + if(self::shouldEncrypt($path)){ + if (!is_resource($data)) {//stream put contents should have been converter to fopen + $data=OC_Crypt::blockEncrypt($data); + OC_FileCache::put($path,array('encrypted'=>true)); + } + } + } + + public function postFile_get_contents($path,$data){ + if(self::isEncrypted($path)){ + $data=OC_Crypt::blockDecrypt($data); + } + return $data; + } + + public function postFopen($path,&$result){ + if(!$result){ + return $result; + } + $meta=stream_get_meta_data($result); + if(self::isEncrypted($path)){ + fclose($result); + $result=fopen('crypt://'.$path,$meta['mode']); + }elseif(self::shouldEncrypt($path) and $meta['mode']!='r' and $meta['mode']!='rb'){ + if(OC_Filesystem::file_exists($path) and OC_Filesystem::filesize($path)>0){ + //first encrypt the target file so we don't end up with a half encrypted file + OC_Log::write('files_encryption','Decrypting '.$path.' before writing',OC_Log::DEBUG); + $tmp=fopen('php://temp'); + while(!feof($result)){ + $chunk=fread($result,8192); + if($chunk){ + fwrite($tmp,$chunk); + } + } + fclose($result); + OC_Filesystem::file_put_contents($path,$tmp); + fclose($tmp); + } + $result=fopen('crypt://'.$path,$meta['mode']); + } + return $result; + } + + public function postGetMimeType($path,$mime){ + if(self::isEncrypted($path)){ + $mime=OC_Helper::getMimeType('crypt://'.$path,'w'); + } + return $mime; + } +} diff --git a/apps/files_encryption/settings.php b/apps/files_encryption/settings.php new file mode 100644 index 00000000000..396ad1ba78d --- /dev/null +++ b/apps/files_encryption/settings.php @@ -0,0 +1,16 @@ +<?php +/** + * Copyright (c) 2011 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +$tmpl = new OC_Template( 'files_encryption', 'settings'); +$blackList=explode(',',OC_Appconfig::getValue('files_encryption','type_blacklist','jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg')); +$tmpl->assign('blacklist',$blackList); + +OC_Util::addScript('files_encryption','settings'); +OC_Util::addScript('core','multiselect'); + +return $tmpl->fetchPage(); diff --git a/apps/files_encryption/templates/settings.php b/apps/files_encryption/templates/settings.php new file mode 100644 index 00000000000..724a03836a8 --- /dev/null +++ b/apps/files_encryption/templates/settings.php @@ -0,0 +1,11 @@ +<form id="calendar"> + <fieldset class="personalblock"> + <strong><?php echo $l->t('Encryption'); ?></strong> + <?php echo $l->t("Exclude the following file types from encryption"); ?> + <select id='encryption_blacklist' title="<?php echo $l->t('None')?>" multiple="multiple"> + <?php foreach($_["blacklist"] as $type): ?> + <option selected="selected" value="<?php echo $type;?>"><?php echo $type;?></option> + <?php endforeach;?> + </select> + </fieldset> +</form> diff --git a/apps/files_pdfviewer/appinfo/info.xml b/apps/files_pdfviewer/appinfo/info.xml index 86a6c3f22f7..f133f1900d7 100755 --- a/apps/files_pdfviewer/appinfo/info.xml +++ b/apps/files_pdfviewer/appinfo/info.xml @@ -1,7 +1,8 @@ <?xml version="1.0"?> <info> <id>files_pdfviewer</id> - <name>PDF viewer (pdfjs-based)</name> + <name>PDF Viewer</name> + <description>Inline PDF viewer (pdfjs-based)</description> <version>0.1</version> <licence>GPL</licence> <author>Joan Creus</author> diff --git a/apps/files_sharing/css/sharing.css b/apps/files_sharing/css/sharing.css index 0759af2c274..db59a3d340b 100644 --- a/apps/files_sharing/css/sharing.css +++ b/apps/files_sharing/css/sharing.css @@ -5,4 +5,5 @@ #shared_list { padding:0.5em; list-style-type: none; } #public { border-top:1px solid #ddd; padding-top:0.5em; } a.unshare { float:right; display:inline; margin:0 .5em; padding:.3em .3em 0 .3em !important; opacity:.5; } -a.unshare:hover { opacity:1; }
\ No newline at end of file +a.unshare:hover { opacity:1; } +#share_with { width: 16em; }
\ No newline at end of file diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js index d01a07447a6..fc9e17c25c7 100644 --- a/apps/files_sharing/js/share.js +++ b/apps/files_sharing/js/share.js @@ -174,7 +174,7 @@ $(document).ready(function() { function createDropdown(filename, files) { var html = '<div id="dropdown" class="drop" data-file="'+files+'">'; html += '<div id="private">'; - html += '<select data-placeholder="User or Group" style="width:220px;" id="share_with" class="chzen-select">'; + html += '<select data-placeholder="User or Group" id="share_with" class="chzen-select">'; html += '<option value=""></option>'; html += '</select>'; html += '<ul id="shared_list"></ul>'; diff --git a/apps/files_sharing/sharedstorage.php b/apps/files_sharing/sharedstorage.php index cb641e68a84..845659588ef 100644 --- a/apps/files_sharing/sharedstorage.php +++ b/apps/files_sharing/sharedstorage.php @@ -58,7 +58,7 @@ class OC_Filestorage_Shared extends OC_Filestorage { } public function mkdir($path) { - if ($path == "" || $path == "/" || !$this->is_writeable($path)) { + if ($path == "" || $path == "/" || !$this->is_writable($path)) { return false; } else { $source = $this->getSource($path); @@ -79,7 +79,6 @@ class OC_Filestorage_Shared extends OC_Filestorage { if ($path == "" || $path == "/") { $path = $this->datadir.$path; $sharedItems = OC_Share::getItemsInFolder($path); - global $FAKEDIRS; $files = array(); foreach ($sharedItems as $item) { // If item is in the root of the shared storage provider and the item exists add it to the fakedirs @@ -87,7 +86,7 @@ class OC_Filestorage_Shared extends OC_Filestorage { $files[] = basename($item['target']); } } - $FAKEDIRS['shared'] = $files; + OC_FakeDirStream::$dirs['shared']=$files; return opendir('fakedir://shared'); } else { $source = $this->getSource($path); @@ -281,14 +280,6 @@ class OC_Filestorage_Shared extends OC_Filestorage { } } - public function readfile($path) { - $source = $this->getSource($path); - if ($source) { - $storage = OC_Filesystem::getStorage($source); - return $storage->readfile($this->getInternalPath($source)); - } - } - public function filectime($path) { if ($path == "" || $path == "/") { $ctime = 0; @@ -514,7 +505,13 @@ class OC_Filestorage_Shared extends OC_Filestorage { return $storage->getLocalFile($this->getInternalPath($source)); } } - + public function touch($path, $mtime=null){ + $source = $this->getSource($path); + if ($source) { + $storage = OC_Filesystem::getStorage($source); + return $storage->touch($this->getInternalPath($source),$time); + } + } } ?> diff --git a/apps/files_texteditor/css/style.css b/apps/files_texteditor/css/style.css index cf24950232f..e260ab0dd46 100644 --- a/apps/files_texteditor/css/style.css +++ b/apps/files_texteditor/css/style.css @@ -1,8 +1,8 @@ #editor{ - position: absoloute; + position: fixed; display: block; - top: 80px; - left: 160px; + top: 6.5em; + left: 12.5em; } #editorwrapper{ position: absoloute; diff --git a/apps/files_texteditor/js/editor.js b/apps/files_texteditor/js/editor.js index 7473d532304..e45652b6ef3 100644 --- a/apps/files_texteditor/js/editor.js +++ b/apps/files_texteditor/js/editor.js @@ -172,6 +172,7 @@ function giveEditorFocus(){ function showFileEditor(dir,filename){ if(!editorIsShown()){ // Loads the file editor and display it. + $('#content').append('<div id="editor"></div>'); var data = $.getJSON( OC.filePath('files_texteditor','ajax','loadfile.php'), {file:filename,dir:dir}, @@ -273,10 +274,10 @@ $(document).ready(function(){ var dir=text.substr(0,text.length-file.length-1); showFileEditor(dir,file); }); - } + }; // Binds the file save and close editor events, and gotoline button bindControlEvents(); - + $('#editor').remove(); // Binds the save keyboard shortcut events //$(document).unbind('keydown').bind('keydown',checkForSaveKeyPress); }); diff --git a/apps/gallery/ajax/galleryOp.php b/apps/gallery/ajax/galleryOp.php index 5ac6d295108..64f1b1697ba 100644 --- a/apps/gallery/ajax/galleryOp.php +++ b/apps/gallery/ajax/galleryOp.php @@ -41,7 +41,7 @@ function handleRemove($name) { function handleGetThumbnails($albumname) { OC_Response::enableCaching(3600 * 24); // 24 hour - $thumbnail = OC::$CONFIG_DATADIRECTORY.'/../gallery/'.$albumname.'.png'; + $thumbnail = OC::$CONFIG_DATADIRECTORY.'/../gallery/'.urldecode($albumname).'.png'; header('Content-Type: '.OC_Image::getMimeTypeForFile($thumbnail)); OC_Response::sendFile($thumbnail); } @@ -61,7 +61,7 @@ function handleFilescan($cleanup) { function handlePartialCreate($path) { if (empty($path)) OC_JSON::error(array('cause' => 'No path specified')); - if (!OC_Filesystem::is_dir($path)) OC_JSON::error(array('cause' => 'Invalid path given')); + if (!OC_Filesystem::is_dir($path.'/')) OC_JSON::error(array('cause' => 'Invalid path given')); $album = OC_Gallery_Album::find(OC_User::getUser(), null, $path); $albums = array(); @@ -87,6 +87,37 @@ function handleStoreSettings($root, $order) { OC_JSON::success(array('rescan' => $rescan)); } +function handleGetGallery($path) { + $a = array(); + $root = OC_Preferences::getValue(OC_User::getUser(),'gallery', 'root', '/'); + if (strlen($root) > 1) + $path = $root.'/'.trim($path, '/'); + else + $path = '/'.ltrim($path, '/'); + if (strlen($path) > 1) $path = rtrim($path, '/'); + $result = OC_Gallery_Album::find(OC_User::getUser(), null, $path); + $album_details = $result->fetchRow(); + + $result = OC_Gallery_Album::find(OC_User::getUser(), null, null, $path); + + while ($r = $result->fetchRow()) { + $album_name = $r['album_name']; + $size=OC_Gallery_Album::getAlbumSize($r['album_id']); + + $a[] = array('name' => utf8_encode($album_name), 'numOfItems' => min($size, 10),'path'=>$r['album_path']); + } + + $result = OC_Gallery_Photo::find($album_details['album_id']); + + $p = array(); + + while ($r = $result->fetchRow()) { + $p[] = utf8_encode($r['file_path']); + } + + OC_JSON::success(array('albums'=>$a, 'photos'=>$p)); +} + if ($_GET['operation']) { switch($_GET['operation']) { case 'rename': @@ -112,6 +143,12 @@ if ($_GET['operation']) { case 'store_settings': handleStoreSettings($_GET['root'], $_GET['order']); break; + case 'get_galleries': + handleGetGalleries($_GET['path']); + break; + case 'get_gallery': + handleGetGallery($_GET['path']); + break; default: OC_JSON::error(array('cause' => 'Unknown operation')); } diff --git a/apps/gallery/ajax/getAlbums.php b/apps/gallery/ajax/getAlbums.php deleted file mode 100644 index 9e9c6ef496c..00000000000 --- a/apps/gallery/ajax/getAlbums.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/** -* ownCloud - gallery application -* -* @author Bartek Przybylski -* @copyright 2012 Bartek Przybylski bart.p.pl@gmail.com -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE -* License as published by the Free Software Foundation; either -* version 3 of the License, or any later version. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU AFFERO GENERAL PUBLIC LICENSE for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library. If not, see <http://www.gnu.org/licenses/>. -* -*/ - -require_once('../../../lib/base.php'); -OC_JSON::checkLoggedIn(); -OC_JSON::checkAppEnabled('gallery'); - -$a = array(); - -$result = OC_Gallery_Album::find(OC_User::getUser()); - -while ($r = $result->fetchRow()) { - $album_name = $r['album_name']; - $tmp_res = OC_Gallery_Photo::find($r['album_id']); - - $a[] = array('name' => $album_name, 'numOfItems' => min($tmp_res->numRows(), 10), 'bgPath' => OC::$WEBROOT.'/data/'.OC_User::getUser().'/gallery/'.$album_name.'.png'); -} - -OC_JSON::success(array('albums'=>$a)); - -?> diff --git a/apps/gallery/appinfo/app.php b/apps/gallery/appinfo/app.php index b8de32ea587..1e5e27d408f 100644 --- a/apps/gallery/appinfo/app.php +++ b/apps/gallery/appinfo/app.php @@ -40,8 +40,8 @@ OC_App::addNavigationEntry( array( 'icon' => OC_Helper::imagePath('core', 'places/picture.svg'), 'name' => $l->t('Gallery'))); - class OC_GallerySearchProvider extends OC_Search_Provider{ - function search($query){ + class OC_GallerySearchProvider implements OC_Search_Provider{ + static function search($query){ $stmt = OC_DB::prepare('SELECT * FROM *PREFIX*gallery_albums WHERE uid_owner = ? AND album_name LIKE ?'); $result = $stmt->execute(array(OC_User::getUser(),'%'.$query.'%')); $results=array(); @@ -52,7 +52,7 @@ OC_App::addNavigationEntry( array( } } -new OC_GallerySearchProvider(); +OC_Search::registerProvider('OC_GallerySearchProvider'); require_once('apps/gallery/lib/hooks_handlers.php'); ?> diff --git a/apps/gallery/appinfo/database.xml b/apps/gallery/appinfo/database.xml index db88e4c1b5a..62fdbee9cd8 100644 --- a/apps/gallery/appinfo/database.xml +++ b/apps/gallery/appinfo/database.xml @@ -11,9 +11,9 @@ <name>album_id</name> <type>integer</type> <default>0</default> - <notnull>true</notnull> - <autoincrement>1</autoincrement> - <length>4</length> + <notnull>true</notnull> + <autoincrement>1</autoincrement> + <length>4</length> </field> <field> <name>uid_owner</name> @@ -27,12 +27,18 @@ <notnull>true</notnull> <length>100</length> </field> - <field> - <name>album_path</name> - <type>text</type> - <notnull>true</notnull> - <length>100</length> - </field> + <field> + <name>album_path</name> + <type>text</type> + <notnull>true</notnull> + <length>100</length> + </field> + <field> + <name>parent_path</name> + <type>text</type> + <notnull>true</notnull> + <length>100</length> + </field> </declaration> </table> <table> @@ -42,16 +48,16 @@ <name>photo_id</name> <type>integer</type> <default>0</default> - <notnull>true</notnull> - <autoincrement>1</autoincrement> - <length>4</length> + <notnull>true</notnull> + <autoincrement>1</autoincrement> + <length>4</length> </field> <field> <name>album_id</name> <type>integer</type> <default>0</default> - <notnull>true</notnull> - <length>4</length> + <notnull>true</notnull> + <length>4</length> </field> <field> <name>file_path</name> diff --git a/apps/gallery/appinfo/info.xml b/apps/gallery/appinfo/info.xml index 9aecb0c781d..19c5dc8b25e 100644 --- a/apps/gallery/appinfo/info.xml +++ b/apps/gallery/appinfo/info.xml @@ -2,7 +2,7 @@ <info> <id>gallery</id> <name>Gallery</name> - <version>0.3</version> + <version>0.4</version> <licence>AGPL</licence> <author>Bartek Przybylski</author> <require>2</require> diff --git a/apps/gallery/css/styles.css b/apps/gallery/css/styles.css index c039cd5ec02..013cd1b262d 100644 --- a/apps/gallery/css/styles.css +++ b/apps/gallery/css/styles.css @@ -1,13 +1,14 @@ -div#gallery_list { margin: 70pt 20pt 0 20pt; } +div#gallery_list { margin: 4.5em 2em 0 2em; } div#gallery_list.leftcontent { padding-top: 15pt; margin: 0; position: absolute; bottom:0px; text-align: center; overflow: auto; } -div.gallery_album_box { width: 200px; position:relative; text-align: center; border: 0; display: inline-block; margin: 5pt; vertical-align: top; padding: 20px 5px 5px 5px; position: relative; -webkit-transition: color 0.5s ease-in-out; -o-transition: color 0.5s ease-in-out; -moz-transition: color 0.5s ease-in-out;color: #BBB;} -div.gallery_album_box h1 { font-size: 9pt; font-family: Verdana; } -div.gallery_album_decoration { width: 200px; position: absolute; border: 0; height: 20px; top: 20px; text-align:right; vertical-align:middle; background-color: #eee; opacity: 0; -webkit-transition: opacity 0.5s ease-in-out; -moz-transition: opacity 0.5s ease-in-out; -o-transition: opacity 0.5s ease-in-out; border-bottom-right-radius: 7px; border-bottom-left-radius: 7px; -moz-border-radius-bottomright: 7px; -moz-border-radius-bottomleft:7px;} -div.gallery_album_box:hover { color: black; } -div.gallery_album_box:hover div.gallery_album_decoration { opacity: 0.7;} +div.gallery_box { width: 200px; position:relative; text-align: center; border: 0; display: inline-block; margin: 5pt; vertical-align: top; padding: 5px 5px 5px 5px; position: relative; -webkit-transition: color 0.5s ease-in-out; -o-transition: color 0.5s ease-in-out; -moz-transition: color 0.5s ease-in-out;color: #BBB;} +div.album {border: 1px solid #e0e0e0; border-radius: 7px;} +div.gallery_box h1 { font-size: 9pt; font-family: Verdana; } +div.gallery_album_decoration { width: 200px; position: absolute; border: 0; height: 20px; top: 5px; text-align:right; vertical-align:middle; background-color: #eee; opacity: 0; -webkit-transition: opacity 0.5s ease-in-out; -moz-transition: opacity 0.5s ease-in-out; -o-transition: opacity 0.5s ease-in-out; } +div.gallery_box:hover { color: black; } +div.gallery_box:hover div.gallery_album_decoration { opacity: 0.7;} div.gallery_album_decoration a {padding: 0 4pt; cursor: pointer;} div.gallery_album_cover { width: 200px; height: 200px; border: 0; padding: 0; position:relative;} -div.gallery_album_box:hover div.gallery_control_overlay { opacity:0.5 } +div.gallery_box:hover div.gallery_control_overlay { opacity:0.5 } div.gallery_control_overlay a { color:white; } #gallery_images.rightcontent { padding:10px 5px; bottom: 0px; overflow: auto; right:0px} #scan { position:absolute; right:13.5em; top:0em; } diff --git a/apps/gallery/js/album_cover.js b/apps/gallery/js/album_cover.js index 4ddac2f2111..71de1adae11 100644 --- a/apps/gallery/js/album_cover.js +++ b/apps/gallery/js/album_cover.js @@ -1,190 +1,187 @@ var actual_cover; -$(document).ready(function() { - $.getJSON('ajax/getAlbums.php', function(r) { - if (r.status == 'success') { - for (var i in r.albums) { - var a = r.albums[i]; - Albums.add(a.name, a.numOfItems); - } - var targetDiv = document.getElementById('gallery_list'); - if (targetDiv) { - $(targetDiv).html(''); - Albums.display(targetDiv); - $('#gallery_list').sortable({revert:true}); - $('.gallery_album_box').each(function(i, e) { - $(e).draggable({connectToSortable: '#gallery_list', handle: '.dummy'}) - }); - } else { - alert('Error occured: no such layer `gallery_list`'); - } - } else { - alert('Error occured: ' + r.message); - } - }); -}); +var paths = []; +var crumbCount = 0; +$(document).ready(returnToElement(0)); + +function returnToElement(num) { + while (crumbCount != num) { + $('#g-album-navigation .last').remove(); + $('#g-album-navigation .crumb :last').parent().addClass('last'); + crumbCount--; + paths.pop(); + } + path=paths[paths.length-1]; + $.getJSON(OC.filePath('gallery','ajax','galleryOp.php'), {operation: 'get_gallery', path: path }, albumClickHandler); +} + +function albumClick(title,path) { + paths.push(path); + crumbCount++; + $.getJSON(OC.filePath('gallery','ajax','galleryOp.php'), {operation: 'get_gallery', path: path }, albumClickHandler); + if ($('#g-album-navigation :last-child')) + $('#g-album-navigation :last-child').removeClass('last'); + $('#g-album-navigation').append('<div class="crumb last real" style="background-image:url(\''+OC.imagePath('core','breadcrumb')+'\')"><a href=\"javascript:returnToElement('+crumbCount+');\">'+title+'</a></div>'); +} + +function albumClickHandler(r) { + Albums.photos = []; + Albums.albums = []; + if (r.status == 'success') { + for (var i in r.albums) { + var a = r.albums[i]; + Albums.add(a.name, a.numOfItems,a.path); + } + for (var i in r.photos) { + Albums.photos.push(r.photos[i]); + } + var targetDiv = document.getElementById('gallery_list'); + if (targetDiv) { + $(targetDiv).html(''); + Albums.display(targetDiv); + //$('#gallery_list').sortable({revert:true}); + $('.album').each(function(i, el) { + $(el).click(albumClick.bind(null,$(el).attr('title'),$(el).data('path'))); + //$(el).draggable({connectToSortable: '#gallery_list', handle: '.dummy'}); + }); + } else { + OC.dialogs.alert(t('gallery', 'Error: no such layer `gallery_list`'), t('gallery', 'Internal error')); + } + } else { + OC.dialogs.alert(t('gallery', 'Error: ') + r.message, t('gallery', 'Internal error')); + } +} function createNewAlbum() { - var name = prompt("album name", ""); - if (name != null && name != "") { - $.getJSON("ajax/createAlbum.php", {album_name: name}, function(r) { - if (r.status == "success") { - var v = '<div class="gallery_album_box"><a href="?view='+r.name+'"><img class="gallery_album_cover"/></a><h1>'+r.name+'</h1></div>'; - $('div#gallery_list').append(v); - } - }); - } + var name = prompt("album name", ""); + if (name != null && name != "") { + $.getJSON(OC.filePath('gallery','ajax','createAlbum.php'), {album_name: name}, function(r) { + if (r.status == "success") { + var v = '<div class="gallery_box"><a href="?view='+r.name+'"><img class="gallery_album_cover"/></a><h1>'+r.name+'</h1></div>'; + $('div#gallery_list').append(v); + } + }); + } } var albumCounter = 0; var totalAlbums = 0; function scanForAlbums(cleanup) { - cleanup = cleanup?true:false; - var albumCounter = 0; - var totalAlbums = 0; - $('#g-scan-button').attr('disabled', 'true'); - $.getJSON('ajax/galleryOp.php?operation=filescan', {cleanup: cleanup}, function(r) { - - if (r.status == 'success') { - totalAlbums = r.paths.length; - if (totalAlbums == 0) { - $('#notification').text(t('gallery', "No photos found")).fadeIn().slideDown().delay(3000).fadeOut().slideUp(); - return; - } - $('#scanprogressbar').progressbar({ value: (albumCounter/totalAlbums)*100 }).fadeIn(); - for(var a in r.paths) { - $.getJSON('ajax/galleryOp.php?operation=partial_create&path='+r.paths[a], function(r) { + cleanup = cleanup?true:false; + var albumCounter = 0; + var totalAlbums = 0; + $('#g-scan-button').attr('disabled', 'true'); + $.getJSON(OC.filePath('gallery','ajax','galleryOp.php'), {cleanup: cleanup,operation:'filescan'}, function(r) { - if (r.status == 'success') { - Albums.add(r.album_details.albumName, r.album_details.imagesCount); - } + if (r.status == 'success') { + totalAlbums = r.paths.length; + if (totalAlbums == 0) { + $('#notification').text(t('gallery', "No photos found")).fadeIn().slideDown().delay(3000).fadeOut().slideUp(); + return; + } + $('#scanprogressbar').progressbar({ value: (albumCounter/totalAlbums)*100 }).fadeIn(); + for(var a in r.paths) { + $.getJSON(OC.filePath('gallery','ajax','galleryOp.php'),{operation:'partial_create','path':r.paths[a]}, function(r) { - albumCounter++; - $('#scanprogressbar').progressbar({ value: (albumCounter/totalAlbums)*100 }); - if (albumCounter == totalAlbums) { - $('#scanprogressbar').fadeOut(); - var targetDiv = document.getElementById('gallery_list'); - if (targetDiv) { - targetDiv.innerHTML = ''; - Albums.display(targetDiv); - } else { - alert('Error occured: no such layer `gallery_list`'); - } - $('#g-scan-button').attr('disabled', null); - } - }); - } - } else { - alert('Error occured: ' + r.message); - } - }); + albumCounter++; + $('#scanprogressbar').progressbar({ value: (albumCounter/totalAlbums)*100 }); + if (albumCounter == totalAlbums) { + $('#scanprogressbar').fadeOut(); + var targetDiv = document.getElementById('gallery_list'); + if (targetDiv) { + targetDiv.innerHTML = ''; + Albums.photos = []; + Albums.albums = []; + returnToElement(0); + } else { + alert('Error occured: no such layer `gallery_list`'); + } + $('#g-scan-button').attr('disabled', null); + } + }); + } + } else { + alert('Error occured: ' + r.message); + } + }); } function galleryRemove(albumName) { - // a workaround for a flaw in the demo system (http://dev.jqueryui.com/ticket/4375), ignore! - $( "#dialog:ui-dialog" ).dialog( "destroy" ); - $('#albumName', $("#dialog-confirm")).text(albumName); - - $( '#dialog-confirm' ).dialog({ - resizable: false, - height:150, - buttons: [{ - text: t('gallery', 'OK'), - click: function() { - $.getJSON("ajax/galleryOp.php", {operation: "remove", name: albumName}, function(r) { - if (r.status == "success") { - $(".gallery_album_box").filterAttr('data-album',albumName).remove(); - Albums.remove(albumName); - } else { - alert("Error: " + r.cause); - } - $('#dialog-confirm').dialog('close'); - }); - }}, - { - text: t('gallery', 'Cancel'), - click: function() { - $( this ).dialog( 'close' ); - }}] - }); + OC.dialogs.confirm(t('gallery', 'Do you want to remove album ') + decodeURIComponent(escape(albumName)), + t('gallery', 'Remove confirmation'), + function(decision) { + if (decision) { + $.getJSON(OC.filePath('gallery','ajax','galleryOp.php'), {operation: "remove", name: decodeURIComponent(escape(albumName))}, function(r) { + if (r.status == "success") { + $(".gallery_box").filterAttr('data-album',albumName).remove(); + Albums.remove(albumName); + } else { + OC.dialogs.alert(r.cause, "Error"); + } + }); + } + } + ); } function galleryRename(name) { - $('#name', $('#dialog-form')).val(name); - $( "#dialog-form" ).dialog({ - height: 140, - width: 350, - modal: false, - buttons: [{ - text: t('gallery', 'Change name'), - click: function() { - var newname = $('#name', $('#dialog-form')).val(); - if (newname == name || newname == '') { - $(this).dialog("close"); - return; - } - if (Albums.find(newname)) { - alert("Album ", newname, " exists"); - $(this).dialog("close"); - return; - } - $.getJSON('ajax/galleryOp.php', {operation: 'rename', oldname: name, newname: newname}, function(r) { - if (r.status == "success") { - Albums.rename($(".gallery_album_box").filterAttr('data-album',name), newname); - } else { - alert("Error: " + r.cause); - } - $('#dialog-form').dialog('close'); - }); - - } - }, - { - text: t('gallery', 'Cancel'), - click: function() { - $( this ).dialog('close'); - } - } - ], - }); + OC.dialogs.prompt(t('gallery', 'New album name'), + t('gallery', 'Change name'), + name, + function(newname) { + if (newname == name || newname == '') return; + if (Albums.find(newname)) { + OC.dialogs.alert('Album ' + newname + ' exists', 'Alert'); + return; + } + $.getJSON(OC.filePath('gallery','ajax','galleryOp.php'), {operation: 'rename', oldname: name, newname: newname}, function(r) { + if (r.status == 'success') { + Albums.rename($(".gallery_box").filterAttr('data-album',name), newname); + } else { + OC.dialogs.alert('Error: ' + r.cause, 'Error'); + } + }); + } + ); } function settings() { - $( '#g-dialog-settings' ).dialog({ - height: 180, - width: 350, - modal: false, - buttons: [{ - text: t('gallery', 'Apply'), - click: function() { - var scanning_root = $('#g-scanning-root').val(); - var disp_order = $('#g-display-order option:selected').val(); - if (scanning_root == '') { - alert('Scanning root cannot be empty'); - return; - } - $.getJSON('ajax/galleryOp.php', {operation: 'store_settings', root: scanning_root, order: disp_order}, function(r) { - if (r.status == 'success') { - if (r.rescan == 'yes') { - $('#g-dialog-settings').dialog('close'); - Albums.clear(document.getElementById('gallery_list')); - scanForAlbums(true); - return; - } - } else { - alert('Error: ' + r.cause); - return; - } - $('#g-dialog-settings').dialog('close'); - }); - } - }, - { - text: t('gallery', 'Cancel'), - click: function() { - $(this).dialog('close'); - } - } - ], - }); + $( '#g-dialog-settings' ).dialog({ + height: 180, + width: 350, + modal: false, + buttons: [ + { + text: t('gallery', 'Apply'), + click: function() { + var scanning_root = $('#g-scanning-root').val(); + var disp_order = $('#g-display-order option:selected').val(); + if (scanning_root == '') { + alert('Scanning root cannot be empty'); + return; + } + $.getJSON(OC.filePath('gallery','ajax','galleryOp.php'), {operation: 'store_settings', root: scanning_root, order: disp_order}, function(r) { + if (r.status == 'success') { + if (r.rescan == 'yes') { + $('#g-dialog-settings').dialog('close'); + Albums.clear(document.getElementById('gallery_list')); + scanForAlbums(true); + return; + } + } else { + alert('Error: ' + r.cause); + return; + } + $('#g-dialog-settings').dialog('close'); + }); + } + }, + { + text: t('gallery', 'Cancel'), + click: function() { + $(this).dialog('close'); + } + } + ], + }); } diff --git a/apps/gallery/js/albums.js b/apps/gallery/js/albums.js index 987412f28e0..afdfbd3cc83 100644 --- a/apps/gallery/js/albums.js +++ b/apps/gallery/js/albums.js @@ -1,89 +1,98 @@ Albums={ - // album item in this array should look as follow - // {name: string, - // numOfCovers: int} - // - // previews array should be an array of base64 decoded images - // to display to user as preview picture when scrolling throught - // the album cover - albums:new Array(), - // add simply adds new album to internal structure - // however albums names must be unique so other - // album with the same name wont be insered, - // and false will be returned - // true on success - add: function(album_name, num) { - if (Albums.albums[album_name] != undefined) return false; - Albums.albums[album_name] = {name: album_name, numOfCovers: num}; - return true; - }, - // remove element with given name - // returns remove element or undefined if no such element was present - remove: function(name) { - var i = -1, tmp = 0; - for (var a in Albums.albums) { - if (a.name == name) { - i = tmp; - break; - } - tmp++; - } - if (i != -1) { - return Albums.albums.splice(i,1); - } - return undefined; - }, - // return element which match given name - // of undefined if such element do not exist - find: function(name) { - return Albums.albums[name]; - }, - // displays gallery in linear representation - // on given element, and apply default styles for gallery - display: function(element) { - var displayTemplate = '<div class="gallery_album_box"><div class="dummy"></div><a class="view"><div class="gallery_album_cover"></div></a><h1></h1><div class="gallery_album_decoration"><a><img src="img/share.png" title="Share"></a><a class="rename"><img src="img/rename.png" title="Rename"></a><a class="remove"><img src="img/delete.png" title="Delete"></a></div></div>'; - for (var i in Albums.albums) { - var a = Albums.albums[i]; - var local=$(displayTemplate); - local.attr('data-album',a.name); - $(".gallery_album_decoration a.rename", local).bind('click', {name: a.name},function(event){ - event.preventDefault(); - galleryRename(event.data.name); - }); - $(".gallery_album_decoration a.remove", local).bind('click', {name: a.name},function(event){ - event.preventDefault(); - galleryRemove(event.data.name); - }); - $("a.view", local).attr('href','?view='+escape(a.name)); - $('h1',local).text(a.name); - $(".gallery_album_cover", local).attr('title',a.name); - $(".gallery_album_cover", local).css('background-repeat', 'no-repeat'); - $(".gallery_album_cover", local).css('background-position', '0'); - $(".gallery_album_cover", local).css('background-image','url("ajax/galleryOp.php?operation=get_covers&albumname='+escape(a.name)+'")'); - $(".gallery_album_cover", local).mousemove(function(e) { - - var albumMetadata = Albums.find(this.title); - if (albumMetadata == undefined) { - return; - } - var x = Math.floor((e.layerX - this.offsetLeft)/(this.offsetWidth/albumMetadata.numOfCovers)); - x *= this.offsetWidth; - if (x < 0) x=0; - $(this).css('background-position', -x+'px 0'); - }); - $(element).append(local); - } - }, - rename: function(element, new_name) { - if (new_name) { - $(element).attr("data-album", new_name); - $("a.view", element).attr("href", "?view="+new_name); - $("h1", element).text(new_name); + // album item in this array should look as follow + // {name: string, + // numOfCovers: int} + // + // previews array should be an array of base64 decoded images + // to display to user as preview picture when scrolling throught + // the album cover + albums:new Array(), + photos:new Array(), + // add simply adds new album to internal structure + // however albums names must be unique so other + // album with the same name wont be insered, + // and false will be returned + // true on success + add: function(album_name, num,path) { + if (Albums.albums[album_name] != undefined) return false; + Albums.albums[album_name] = {name: album_name, numOfCovers: num, path:path}; + return true; + }, + // remove element with given name + // returns remove element or undefined if no such element was present + remove: function(name) { + var i = -1, tmp = 0; + for (var a in Albums.albums) { + if (a.name == name) { + i = tmp; + break; + } + tmp++; + } + if (i != -1) { + return Albums.albums.splice(i,1); + } + return undefined; + }, + // return element which match given name + // of undefined if such element do not exist + find: function(name) { + return Albums.albums[name]; + }, + // displays gallery in linear representation + // on given element, and apply default styles for gallery + display: function(element) { + var displayTemplate = '<div class="gallery_box album"><div class="dummy"></div><a class="view"><div class="gallery_album_cover"></div></a><h1></h1><div class="gallery_album_decoration"><a><img src="img/share.png" title="Share"></a><a class="rename"><img src="img/rename.png" title="Rename"></a><a class="remove"><img src="img/delete.png" title="Delete"></a></div></div>'; + for (var i in Albums.albums) { + var a = Albums.albums[i]; + var local=$(displayTemplate); + local.attr('title', a.name); + local.attr('data-path', a.path); + local.attr('data-album',a.name); + $(".gallery_album_decoration a.rename", local).bind('click', {name: a.name},function(name,event){ + event.preventDefault(); + event.stopPropagation(); + galleryRename(name); + }.bind(null,a.name)); + $(".gallery_album_decoration a.remove", local).bind('click', {name: a.name},function(name,event){ + event.preventDefault(); + event.stopPropagation(); + galleryRemove(name); + }.bind(null,a.name)); + $('h1',local).text(decodeURIComponent(escape(a.name))); + $(".gallery_album_cover", local).attr('title',decodeURIComponent(escape(a.name))); + $(".gallery_album_cover", local).css('background-repeat', 'no-repeat'); + $(".gallery_album_cover", local).css('background-position', '0'); + $(".gallery_album_cover", local).css('background-image','url("'+OC.filePath('gallery','ajax','galleryOp.php')+'?operation=get_covers&albumname='+escape(a.name)+'")'); + $(".gallery_album_cover", local).mousemove(function(e) { + var albumMetadata = Albums.find(this.title); + if (albumMetadata == undefined) { + return; + } + var x = Math.floor((e.layerX - this.offsetLeft)/(this.offsetWidth/albumMetadata.numOfCovers)); + x *= this.offsetWidth; + if (x < 0) x=0; + $(this).css('background-position', -x+'px 0'); + }); + $(element).append(local); + } + var photoDisplayTemplate = '<div class="gallery_box"><div class="dummy"></div><div><a rel="images" href="'+OC.linkTo('files','download.php')+'?file=URLPATH"><img src="'+OC.filePath('gallery','ajax','thumbnail.php')+'?img=IMGPATH"></a></div></div>'; + for (var i in Albums.photos) { + $(element).append(photoDisplayTemplate.replace("IMGPATH", escape(Albums.photos[i])).replace("URLPATH", escape(Albums.photos[i]))); + } + $("a[rel=images]").fancybox({ + 'titlePosition': 'inside' + }); + }, + rename: function(element, new_name) { + if (new_name) { + $(element).attr("data-album", new_name); + $("a.view", element).attr("href", "?view="+new_name); + $("h1", element).text(new_name); + } + }, + clear: function(element) { + Albums.albums = new Array(); + element.innerHTML = ''; } - }, - clear: function(element) { - Albums.albums = new Array(); - element.innerHTML = ''; - } - } diff --git a/apps/gallery/lib/album.php b/apps/gallery/lib/album.php index d1405333ac7..5adb57b554d 100644 --- a/apps/gallery/lib/album.php +++ b/apps/gallery/lib/album.php @@ -23,10 +23,11 @@ class OC_Gallery_Album { public static function create($owner, $name, $path){ - $stmt = OC_DB::prepare('INSERT INTO *PREFIX*gallery_albums (uid_owner, album_name, album_path) VALUES (?, ?, ?)'); - $stmt->execute(array($owner, $name, $path)); + $id = self::getParentPath($path); + $stmt = OC_DB::prepare('INSERT INTO *PREFIX*gallery_albums (uid_owner, album_name, album_path, parent_path) VALUES (?, ?, ?, ?)'); + $stmt->execute(array($owner, $name, $path, $id)); } - + public static function rename($oldname, $newname, $owner) { $stmt = OC_DB::prepare('UPDATE *PREFIX*gallery_albums SET album_name=? WHERE uid_owner=? AND album_name=?'); $stmt->execute(array($newname, $owner, $oldname)); @@ -39,7 +40,14 @@ class OC_Gallery_Album { self::remove(OC_User::getUser(), $r['album_name']); } } - + + public static function getParentPath($path) { + if (strlen($path)==1) return ''; + $path = substr($path, 0, strrpos($path, '/')); + if ($path == '') $path = '/'; + return $path; + } + public static function remove($owner, $name=null) { $sql = 'DELETE FROM *PREFIX*gallery_albums WHERE uid_owner = ?'; $args = array($owner); @@ -66,7 +74,7 @@ class OC_Gallery_Album { } } - public static function find($owner, $name=null, $path=null){ + public static function find($owner, $name=null, $path=null, $parent=null){ $sql = 'SELECT * FROM *PREFIX*gallery_albums WHERE uid_owner = ?'; $args = array($owner); if (!is_null($name)){ @@ -77,6 +85,10 @@ class OC_Gallery_Album { $sql .= ' AND album_path = ?'; $args[] = $path; } + if (!is_null($parent)){ + $sql .= ' AND parent_path = ?'; + $args[] = $parent; + } $order = OC_Preferences::getValue(OC_User::getUser(), 'gallery', 'order', 'ASC'); $sql .= ' ORDER BY album_name ' . $order; @@ -95,6 +107,13 @@ class OC_Gallery_Album { rename($thumbpath.$oldname.'.png', $thumbpath.$newname.'.png'); } + public static function getAlbumSize($id){ + $sql = 'SELECT COUNT(*) as size FROM *PREFIX*gallery_photos WHERE album_id = ?'; + $stmt = OC_DB::prepare($sql); + $result=$stmt->execute(array($id))->fetchRow(); + return $result['size']; + } + } ?> diff --git a/apps/gallery/lib/hooks_handlers.php b/apps/gallery/lib/hooks_handlers.php index 046866e5c5d..3c101b1f8a1 100644 --- a/apps/gallery/lib/hooks_handlers.php +++ b/apps/gallery/lib/hooks_handlers.php @@ -37,7 +37,7 @@ class OC_Gallery_Hooks_Handlers { } private static function directoryContainsPhotos($dirpath) { - $dirhandle = opendir(OC::$CONFIG_DATADIRECTORY.$dirpath); + $dirhandle = OC_Filesystem::opendir($dirpath.'/'); if ($dirhandle != FALSE) { while (($filename = readdir($dirhandle)) != FALSE) { if ($filename[0] == '.') continue; @@ -76,9 +76,9 @@ class OC_Gallery_Hooks_Handlers { public static function removePhoto($params) { $path = $params[OC_Filesystem::signal_param_path]; - if (OC_Filesystem::is_dir($path) && self::directoryContainsPhotos($path)) { + if (OC_Filesystem::is_dir($path.'/') && self::directoryContainsPhotos($path)) { if(!self::pathInRoot($path)) return; - OC_Gallery_Album::removeByPath($path.'/', OC_User::getUser()); + OC_Gallery_Album::removeByPath($path, OC_User::getUser()); } elseif (self::isPhoto($path)) { OC_Gallery_Photo::removeByPath($path); } @@ -87,11 +87,11 @@ class OC_Gallery_Hooks_Handlers { public static function renamePhoto($params) { $oldpath = $params[OC_Filesystem::signal_param_oldpath]; $newpath = $params[OC_Filesystem::signal_param_newpath]; - if (OC_Filesystem::is_dir($newpath) && self::directoryContainsPhotos($newpath)) { + if (OC_Filesystem::is_dir($newpath.'/') && self::directoryContainsPhotos($newpath)) { OC_Gallery_Album::changePath($oldpath, $newpath, OC_User::getUser()); - } elseif (!self::isPhoto($newpath)) { - $olddir = substr($oldpath, 0, strrpos($oldpath, '/')); - $newdir = substr($newpath, 0, strrpos($newpath, '/')); + } elseif (self::isPhoto($newpath)) { + $olddir = dirname($oldpath); + $newdir = dirname($newpath); if ($olddir == '') $olddir = '/'; if ($newdir == '') $newdir = '/'; if (!self::isPhoto($newpath)) return; @@ -101,25 +101,26 @@ class OC_Gallery_Hooks_Handlers { $oldAlbumId; if ($olddir == $newdir) { // album changing is not needed - $album = OC_Gallery_Album::find(OC_User::getUser(), null, $olddir); - if ($album->numRows() == 0) { - $album = self::createAlbum($newdir); + $albums = OC_Gallery_Album::find(OC_User::getUser(), null, $olddir); + $album = $albums->fetchRow(); + if (!$album) { + $albums = self::createAlbum($newdir); + $album = $albums->fetchRow(); } - $album = $album->fetchRow(); $newAlbumId = $oldAlbumId = $album['album_id']; } else { $newalbum = OC_Gallery_Album::find(OC_User::getUser(), null, $newdir); $oldalbum = OC_Gallery_Album::find(OC_User::getUser(), null, $olddir); - if ($newalbum->numRows() == 0) { + if (!($newalbum = $newalbum->fetchRow())) { $newalbum = self::createAlbum($newdir); + $newalbum = $newalbum->fetchRow(); } - $newalbum = $newalbum->fetchRow(); - if ($oldalbum->numRows() == 0) { + $oldalbum = $oldalbum->fetchRow(); + if (!$oldalbum) { OC_Gallery_Photo::create($newalbum['album_id'], $newpath); return; } - $oldalbum = $oldalbum->fetchRow(); $newAlbumId = $newalbum['album_id']; $oldAlbumId = $oldalbum['album_id']; diff --git a/apps/gallery/lib/photo.php b/apps/gallery/lib/photo.php index 4eb313bfc33..872ecc9488a 100644 --- a/apps/gallery/lib/photo.php +++ b/apps/gallery/lib/photo.php @@ -69,7 +69,6 @@ class OC_Gallery_Photo { public static function getThumbnail($image_name) { $save_dir = OC_Config::getValue("datadirectory").'/'. OC_User::getUser() .'/gallery/'; $save_dir .= dirname($image_name). '/'; - $image_name = basename($image_name); $thumb_file = $save_dir . $image_name; if (file_exists($thumb_file)) { $image = new OC_Image($thumb_file); diff --git a/apps/gallery/lib/scanner.php b/apps/gallery/lib/scanner.php index 64efb006ad1..dbe1abff10e 100644 --- a/apps/gallery/lib/scanner.php +++ b/apps/gallery/lib/scanner.php @@ -21,7 +21,7 @@ * */ -require_once('base.php'); // base lib +require_once('base.php'); require_once('images_utils.php'); class OC_Gallery_Scanner { @@ -40,20 +40,14 @@ class OC_Gallery_Scanner { } public static function createName($name) { - $root = OC_Preferences::getValue(OC_User::getUser(), 'gallery', 'root', '/'); - $name = str_replace('/', '.', str_replace(OC::$CONFIG_DATADIRECTORY, '', $name)); - if (substr($name, 0, strlen($root)) == str_replace('/','.',$root)) { - $name = substr($name, strlen($root)); - } - $name = ($name==='.') ? 'main' : trim($name,'.'); - return $name; + return basename($name); } public static function scanDir($path, &$albums) { $current_album = array('name'=> $path, 'imagesCount' => 0, 'images' => array()); $current_album['name'] = self::createName($current_album['name']); - if ($dh = OC_Filesystem::opendir($path)) { + if ($dh = OC_Filesystem::opendir($path.'/')) { while (($filename = readdir($dh)) !== false) { $filepath = ($path[strlen($path)-1]=='/'?$path:$path.'/').$filename; if (substr($filename, 0, 1) == '.') continue; @@ -64,19 +58,19 @@ class OC_Gallery_Scanner { } $current_album['imagesCount'] = count($current_album['images']); $albums['imagesCount'] = $current_album['imagesCount']; - $albums['albumName'] = $current_album['name']; + $albums['albumName'] = utf8_encode($current_album['name']); $result = OC_Gallery_Album::find(OC_User::getUser(), /*$current_album['name']*/ null, $path); // don't duplicate galleries with same path (bug oc-33) - if ($result->numRows() == 0 && count($current_album['images'])) { - OC_Gallery_Album::create(OC_User::getUser(), $current_album['name'], $path); + if (!($albumId = $result->fetchRow()) && count($current_album['images'])) { + OC_Gallery_Album::create(OC_User::getUser(), $current_album['name'], $path); $result = OC_Gallery_Album::find(OC_User::getUser(), $current_album['name']); + $albumId = $result->fetchRow(); } - $albumId = $result->fetchRow(); $albumId = $albumId['album_id']; foreach ($current_album['images'] as $img) { $result = OC_Gallery_Photo::find($albumId, $img); - if ($result->numRows() == 0) { + if (!$result->fetchRow()) { OC_Gallery_Photo::create($albumId, $img); } } @@ -103,21 +97,15 @@ class OC_Gallery_Scanner { } public static function find_paths($path) { - $ret = array(); - $dirres; - $addpath = FALSE; - if (($dirres = OC_Filesystem::opendir($path)) == FALSE) return $ret; - - while (($file = readdir($dirres)) != FALSE) { - if ($file[0] == '.') continue; - if (OC_Filesystem::is_dir($path.$file)) - $ret = array_merge($ret, self::find_paths($path.$file.'/')); - if (self::isPhoto($path.$file)) $addpath = TRUE; - } - - if ($addpath) $ret[] = urlencode($path); - - return $ret; + $images=OC_FileCache::searchByMime('image'); + $paths=array(); + foreach($images as $image){ + $path=dirname($image); + if(array_search($path,$paths)===false){ + $paths[]=$path; + } + } + return $paths; } } ?> diff --git a/apps/gallery/templates/index.php b/apps/gallery/templates/index.php index 7cc7dad3ac6..7f0281e6a39 100644 --- a/apps/gallery/templates/index.php +++ b/apps/gallery/templates/index.php @@ -2,18 +2,24 @@ OC_Util::addStyle('gallery', 'styles'); OC_Util::addScript('gallery', 'albums'); OC_Util::addScript('gallery', 'album_cover'); +OC_Util::addStyle('files', 'files'); +OC_Util::addScript('files_imageviewer', 'jquery.mousewheel-3.0.4.pack'); +OC_Util::addScript('files_imageviewer', 'jquery.fancybox-1.3.4.pack'); +OC_Util::addStyle( 'files_imageviewer', 'jquery.fancybox-1.3.4' ); $l = new OC_L10N('gallery'); ?> -<div id="notification"><div id="gallery_notification_text">Creating thumbnails</div></div> <div id="controls"> <div id="scan"> <div id="scanprogressbar"></div> <input type="button" id="g-scan-button" value="<?php echo $l->t('Rescan');?>" onclick="javascript:scanForAlbums();" /> - </div> - <div id="g-settings"> <input type="button" id="g-settings-button" value="<?php echo $l->t('Settings');?>" onclick="javascript:settings();"/> </div> + <div id="g-album-navigation"> + <div class="crumb last" style="background-image:url('/owncloud/core/img/breadcrumb.png')"> + <a href="javascript:returnToElement(0);">main</a> + </div> + </div> </div> <div id="gallery_list"> </div> diff --git a/apps/media/ajax/api.php b/apps/media/ajax/api.php index bb4502690b5..9d9c14deb17 100644 --- a/apps/media/ajax/api.php +++ b/apps/media/ajax/api.php @@ -120,7 +120,10 @@ if($arguments['action']){ OC_Filesystem::readfile($arguments['path']); exit; case 'find_music': - OC_JSON::encodedPrint(OC_FileCache::searchByMime('audio')); + $music=OC_FileCache::searchByMime('audio'); + $ogg=OC_FileCache::searchByMime('application','ogg'); + $music=array_merge($music,$ogg); + OC_JSON::encodedPrint($music); exit; } } diff --git a/apps/media/appinfo/app.php b/apps/media/appinfo/app.php index 475a33500f4..651067fbbe1 100644 --- a/apps/media/appinfo/app.php +++ b/apps/media/appinfo/app.php @@ -30,4 +30,5 @@ OC_APP::registerPersonal('media','settings'); OC_App::register( array( 'order' => 3, 'id' => 'media', 'name' => 'Media' )); OC_App::addNavigationEntry(array('id' => 'media_index', 'order' => 2, 'href' => OC_Helper::linkTo('media', 'index.php'), 'icon' => OC_Helper::imagePath('core', 'places/music.svg'), 'name' => $l->t('Music'))); -?> + +OC_Search::registerProvider('OC_MediaSearchProvider'); diff --git a/apps/media/js/collection.js b/apps/media/js/collection.js index 2249acf3cc4..753785f77b0 100644 --- a/apps/media/js/collection.js +++ b/apps/media/js/collection.js @@ -1,3 +1,5 @@ +var initScanned = false; + Collection={ artists:[], albums:[], @@ -68,10 +70,10 @@ Collection={ for(var i=0;i<Collection.loadedListeners.length;i++){ Collection.loadedListeners[i](); } - if(data.songs.length==0){ + if(data.songs.length==0 && initScanned == false){ $('#scan input.start').click(); + initScanned = true; } - } }); } @@ -81,13 +83,11 @@ Collection={ Collection.parent.show(); } if(!Collection.loaded){ - Collection.load(Collection.display) + Collection.load(Collection.display); }else{ if(Collection.parent){ Collection.parent.find('tr:not(.template)').remove(); var template=Collection.parent.find('tr.template'); - var lastArtist=''; - var lastAlbum=''; $.each(Collection.artists,function(i,artist){ if(artist.name && artist.songs.length>0){ var tr=template.clone().removeClass('template'); @@ -108,7 +108,7 @@ Collection={ $('tr[data-artist="'+artist.name+'"]').addClass('active'); }); if(artist.songs.length>1){ - var expander=$('<a class="expander">></a>'); + expander=$('<a class="expander">></a>'); expander.data('expanded',false); expander.click(function(event){ var tr=$(this).parent().parent(); @@ -136,10 +136,11 @@ Collection={ var first=true; $.each(artist.albums,function(j,album){ $.each(album.songs,function(i,song){ + var newRow; if(first){ newRow=tr; }else{ - var newRow=tr.clone(); + newRow=tr.clone(); newRow.find('td.artist').text(''); newRow.find('.expander').remove(); } @@ -221,13 +222,14 @@ Collection={ tr.find('td.album-expander a.expander').addClass('expanded'); tr.find('td.album-expander a.expander').text('v'); $.each(albumData.songs,function(i,song){ + var newRow; if(i>0){ - var newRow=tr.clone(); + newRow=tr.clone(); newRow.find('a.expander').remove(); newRow.find('td.album a').text(''); newRow.find('td.artist a').text(''); }else{ - var newRow=tr; + newRow=tr; } newRow.find('td.title a').text(song.name); newRow.find('td.title a').click(function(event){ @@ -339,11 +341,11 @@ Collection={ path:song.song_path, playCount:song.song_playcount, }; - album.songs.push(songData) + album.songs.push(songData); artist.songs.push(songData); Collection.songs.push(songData); } -} +}; $(document).ready(function(){ Collection.parent=$('#collection'); diff --git a/apps/media/js/loader.js b/apps/media/js/loader.js index 055f858ae16..a832180d1e3 100644 --- a/apps/media/js/loader.js +++ b/apps/media/js/loader.js @@ -1,7 +1,7 @@ function musicTypeFromFile(file){ var extention=file.substr(file.indexOf('.')+1); if(extention=='ogg'){ - return 'oga' + return 'oga'; } //TODO check for more specific cases return extention; @@ -39,7 +39,7 @@ function loadPlayer(type,ready){ } $(document).ready(function() { - loadPlayer.done=false + loadPlayer.done=false; // FileActions.register('audio','Add to playlist','',addAudio); // FileActions.register('application/ogg','Add to playlist','',addAudio); diff --git a/apps/media/js/music.js b/apps/media/js/music.js index 3373cbac257..1ffe4e10087 100644 --- a/apps/media/js/music.js +++ b/apps/media/js/music.js @@ -16,7 +16,7 @@ $(document).ready(function(){ PlayList.render(); }); var button=$('<input type="button" title="'+t('media','Add album to playlist')+'" class="add"></input>'); - button.css('background-image','url('+OC.imagePath('core','actions/play-add')+')') + button.css('background-image','url('+OC.imagePath('core','actions/play-add')+')'); button.click(function(event){ event.stopPropagation(); PlayList.add(media); @@ -24,7 +24,7 @@ $(document).ready(function(){ }); row.find('div.name').append(button); button.tipsy({gravity:'n', fade:true, delayIn: 400, live:true}); - } + }; Collection.display(); Collection.load(function(){ @@ -34,11 +34,9 @@ $(document).ready(function(){ PlayList.add(song); PlayList.play(0); } - }) + }); }); - - function getUrlVars(){ var vars = {}, hash; var hashes = window.location.hash.substr(1).split('&'); @@ -52,8 +50,8 @@ function getUrlVars(){ function musicTypeFromFile(file){ var extention=file.split('.').pop(); if(extention=='ogg'){ - return 'oga' + return 'oga'; } //TODO check for more specific cases return extention; -}
\ No newline at end of file +} diff --git a/apps/media/js/playlist.js b/apps/media/js/playlist.js index 089065989ae..8e9e2a91537 100644 --- a/apps/media/js/playlist.js +++ b/apps/media/js/playlist.js @@ -26,19 +26,19 @@ PlayList.render=function(){ li.click(function(event){ PlayList.play($(this).data('index')); }); - li.append(img) + li.append(img); li.data('index',i); li.addClass('song'); PlayList.parent.append(li); } $(".jp-playlist-" + PlayList.current).addClass("collection_playing"); -} +}; PlayList.getSelected=function(){ return $('tbody td.name input:checkbox:checked').parent().parent(); -} +}; PlayList.hide=function(){ $('#playlist').hide(); -} +}; $(document).ready(function(){ PlayList.parent=$('#leftcontent'); diff --git a/apps/media/js/scanner.js b/apps/media/js/scanner.js index 0baa9db419a..6c991b60d52 100644 --- a/apps/media/js/scanner.js +++ b/apps/media/js/scanner.js @@ -6,7 +6,7 @@ Scanner={ $.getJSON(OC.linkTo('media','ajax/api.php')+'?action=find_music',function(songs){ Scanner.songsFound=songs.length; if(ready){ - ready(songs) + ready(songs); } }); }, @@ -24,13 +24,13 @@ Scanner={ Scanner.songsScanned=data.count; $('#scan span.songCount').text(Scanner.songsScanned); var progress=(Scanner.songsScanned/Scanner.songsFound)*100; - $('#scanprogressbar').progressbar('value',progress) + $('#scanprogressbar').progressbar('value',progress); }); Scanner.eventSource.listen('done',function(count){ $('#scan input.start').show(); $('#scan input.stop').hide(); $('#scanprogressbar').hide(); - Collection.load(Collection.display) + Collection.load(Collection.display); if(ready){ ready(); } @@ -41,4 +41,4 @@ Scanner={ Scanner.close(); }, -} +}; diff --git a/apps/media/lib_media.php b/apps/media/lib_media.php index 1bcd0f08c80..9de291e8da2 100644 --- a/apps/media/lib_media.php +++ b/apps/media/lib_media.php @@ -56,6 +56,7 @@ class OC_MEDIA{ */ public static function updateFile($params){ $path=$params['path']; + if(!$path) return; require_once 'lib_scanner.php'; require_once 'lib_collection.php'; //fix a bug where there were multiply '/' in front of the path, it should only be one @@ -81,8 +82,8 @@ class OC_MEDIA{ } } -class OC_MediaSearchProvider extends OC_Search_Provider{ - function search($query){ +class OC_MediaSearchProvider implements OC_Search_Provider{ + static function search($query){ require_once('lib_collection.php'); $artists=OC_MEDIA_COLLECTION::getArtists($query); $albums=OC_MEDIA_COLLECTION::getAlbums(0,$query); @@ -106,5 +107,3 @@ class OC_MediaSearchProvider extends OC_Search_Provider{ } } -new OC_MediaSearchProvider(); -?> diff --git a/apps/media/lib_scanner.php b/apps/media/lib_scanner.php index ea594ee8e3c..39658b27ba9 100644 --- a/apps/media/lib_scanner.php +++ b/apps/media/lib_scanner.php @@ -38,6 +38,8 @@ class OC_MEDIA_SCANNER{ */ public static function scanCollection($eventSource=null){ $music=OC_FileCache::searchByMime('audio'); + $ogg=OC_FileCache::searchByMime('application','ogg'); + $music=array_merge($music,$ogg); $eventSource->send('count',count($music)); $songs=0; foreach($music as $file){ diff --git a/apps/remoteStorage/BearerAuth.php b/apps/remoteStorage/BearerAuth.php new file mode 100644 index 00000000000..ebcf189dfb9 --- /dev/null +++ b/apps/remoteStorage/BearerAuth.php @@ -0,0 +1,61 @@ +<?php + +/** + * HTTP Bearer Authentication handler + * + * Use this class for easy http authentication setup + * + * @package Sabre + * @subpackage HTTP + * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License + */ +class Sabre_HTTP_BearerAuth extends Sabre_HTTP_AbstractAuth { + + /** + * Returns the supplied username and password. + * + * The returned array has two values: + * * 0 - username + * * 1 - password + * + * If nothing was supplied, 'false' will be returned + * + * @return mixed + */ + public function getUserPass() { + + // Apache and mod_php + if (($user = $this->httpRequest->getRawServerValue('PHP_AUTH_USER')) && ($pass = $this->httpRequest->getRawServerValue('PHP_AUTH_PW'))) { + + return array($user,$pass); + + } + + // Most other webservers + $auth = $this->httpRequest->getHeader('Authorization'); + + if (!$auth) return false; + + if (strpos(strtolower($auth),'bearer')!==0) return false; + + return explode(':', base64_decode(substr($auth, 7))); + + } + + /** + * Returns an HTTP 401 header, forcing login + * + * This should be called when username and password are incorrect, or not supplied at all + * + * @return void + */ + public function requireLogin() { + + $this->httpResponse->setHeader('WWW-Authenticate','Basic realm="' . $this->realm . '"'); + $this->httpResponse->sendStatus(401); + + } + +} diff --git a/apps/remoteStorage/WebDAV.php b/apps/remoteStorage/WebDAV.php index e048d19e8f2..cad465181a9 100644 --- a/apps/remoteStorage/WebDAV.php +++ b/apps/remoteStorage/WebDAV.php @@ -33,6 +33,7 @@ require_once('../../lib/base.php'); OC_Util::checkAppEnabled('remoteStorage'); require_once('Sabre/autoload.php'); require_once('lib_remoteStorage.php'); +require_once('BearerAuth.php'); require_once('oauth_ro_auth.php'); ini_set('default_charset', 'UTF-8'); @@ -68,7 +69,10 @@ if(count($pathParts) >= 3 && $pathParts[0] == '') { $server->setBaseUri(OC::$WEBROOT."/apps/remoteStorage/WebDAV.php/$ownCloudUser"); // Auth backend - $authBackend = new OC_Connector_Sabre_Auth_ro_oauth(OC_remoteStorage::getValidTokens($ownCloudUser, $category)); + $authBackend = new OC_Connector_Sabre_Auth_ro_oauth( + OC_remoteStorage::getValidTokens($ownCloudUser, $category), + $category + ); $authPlugin = new Sabre_DAV_Auth_Plugin($authBackend,'ownCloud');//should use $validTokens here $server->addPlugin($authPlugin); @@ -81,5 +85,6 @@ if(count($pathParts) >= 3 && $pathParts[0] == '') { // And off we go! $server->exec(); } else { - die('not the right address format '.var_export($pathParts, true)); + //die('not the right address format '.var_export($pathParts, true)); + die('not the right address format'); } diff --git a/apps/remoteStorage/ajax/revokeToken.php b/apps/remoteStorage/ajax/revokeToken.php new file mode 100644 index 00000000000..ca56cf560ec --- /dev/null +++ b/apps/remoteStorage/ajax/revokeToken.php @@ -0,0 +1,41 @@ +<?php + +/** +* ownCloud +* +* Original: +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* Adapted: +* @author Michiel de Jong, 2012 +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +* License as published by the Free Software Foundation; either +* version 3 of the License, or any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU AFFERO GENERAL PUBLIC LICENSE for more details. +* +* You should have received a copy of the GNU Affero General Public +* License along with this library. If not, see <http://www.gnu.org/licenses/>. +* +*/ + + +// Do not load FS ... +$RUNTIME_NOSETUPFS = true; + +require_once('../../../lib/base.php'); +OC_Util::checkAppEnabled('remoteStorage'); +require_once('Sabre/autoload.php'); +require_once('../lib_remoteStorage.php'); + +ini_set('default_charset', 'UTF-8'); +#ini_set('error_reporting', ''); +@ob_clean(); + +echo OC_remoteStorage::deleteToken(file_get_contents("php://input")); diff --git a/apps/remoteStorage/appinfo/app.php b/apps/remoteStorage/appinfo/app.php index ac1ecde5082..a1fbebc42f5 100644 --- a/apps/remoteStorage/appinfo/app.php +++ b/apps/remoteStorage/appinfo/app.php @@ -3,3 +3,4 @@ OC_App::register( array( 'order' => 10, 'id' => 'remoteStorage', 'name' => 'remoteStorage compatibility' )); +OC_APP::registerPersonal('remoteStorage','settings'); diff --git a/apps/remoteStorage/appinfo/info.xml b/apps/remoteStorage/appinfo/info.xml index 8179ca99112..121587795db 100644 --- a/apps/remoteStorage/appinfo/info.xml +++ b/apps/remoteStorage/appinfo/info.xml @@ -3,8 +3,8 @@ <id>remoteStorage</id> <name>remoteStorage compatibility</name> <description>Enables your users to use ownCloud as their remote storage for unhosted applications.</description> - <version>0.2</version> - <licence>AGPL</licence> + <version>0.5</version> + <licence>AGPL or MIT</licence> <author>Michiel de Jong</author> <require>2</require> </info> diff --git a/apps/remoteStorage/auth.css b/apps/remoteStorage/auth.css new file mode 100644 index 00000000000..2dedad5dd0f --- /dev/null +++ b/apps/remoteStorage/auth.css @@ -0,0 +1,8 @@ +h2 { font-size:2em; font-weight:bold; margin-bottom:1em; white-space:nowrap; } +ul.scopes { list-style:disc; } +ul.scopes li { white-space:nowrap; } +h2 img { width: 50% } +#oauth { margin:4em auto 2em; width:20em; } +#allow-auth { background-color:#5c3; text-shadow:#5e3 0 1px 0; color:#fff; +-webkit-box-shadow:0 1px 1px #fff, 0 1px 1px #5f3 inset; -moz-box-shadow:0 1px 1px #fff, 0 1px 1px #5f3 inset; box-shadow:0 1px 1px #fff, 0 1px 1px #5f3 inset; } +#deny-auth { padding:0; margin:.7em; border:0; background:none; font-size:1.2em; -moz-box-shadow: 0 0 0 #fff, 0 0 0 #fff inset; -webkit-box-shadow: 0 0 0 #fff, 0 0 0 #fff inset; box-shadow: 0 0 0 #fff, 0 0 0 #fff inset; } diff --git a/apps/remoteStorage/auth.php b/apps/remoteStorage/auth.php index 85421ba3d88..c00f9d5555c 100644 --- a/apps/remoteStorage/auth.php +++ b/apps/remoteStorage/auth.php @@ -8,7 +8,7 @@ * @copyright 2010 Frank Karlitschek karlitschek@kde.org * * Adapted: -* @author Michiel de Jong, 2011 +* @author Michiel de Jong, 2012 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -17,11 +17,11 @@ * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU AFFERO GENERAL PUBLIC LICENSE for more details. * * You should have received a copy of the GNU Affero General Public -* License along with this library. If not, see <http://www.gnu.org/licenses/>. +* License along with this library. If not, see <http://www.gnu.org/licenses/>. * */ @@ -39,24 +39,8 @@ ini_set('default_charset', 'UTF-8'); #ini_set('error_reporting', ''); @ob_clean(); -//allow use as remote storage for other websites -if(isset($_SERVER['HTTP_ORIGIN'])) { - header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); - header('Access-Control-Max-Age: 3600'); - header('Access-Control-Allow-Methods: OPTIONS, GET, PUT, DELETE, PROPFIND'); - header('Access-Control-Allow-Headers: Authorization, Content-Type'); -} else { - header('Access-Control-Allow-Origin: *'); -} - $path = substr($_SERVER["REQUEST_URI"], strlen($_SERVER["SCRIPT_NAME"])); -$pathParts = explode('/', $path); -// for webdav: -// 0/ 1 / 2 / 3 / 4 / 5 / 6 / 7 -// /$ownCloudUser/remoteStorage/webdav/$userHost/$userName/$dataScope/$key -// for oauth: -// 0/ 1 / 2 / 3 / 4 -// /$ownCloudUser/remoteStorage/oauth/auth +$pathParts = explode('/', $path); if(count($pathParts) == 2 && $pathParts[0] == '') { //TODO: input checking. these explodes may fail to produces the desired arrays: @@ -66,19 +50,69 @@ if(count($pathParts) == 2 && $pathParts[0] == '') { if($k=='user_address'){ $userAddress=$v; } else if($k=='redirect_uri'){ - $appUrl=$v; + $appUrlParts=explode('/', $v); + $appUrl = $appUrlParts[2];//bit dodgy i guess } else if($k=='scope'){ - $category=$v; + $categories=$v; } } $currUser = OC_User::getUser(); if($currUser == $ownCloudUser) { if(isset($_POST['allow'])) { //TODO: check if this can be faked by editing the cookie in firebug! - $token=OC_remoteStorage::createCategory($appUrl, $category); + $token=OC_remoteStorage::createCategories($appUrl, $categories); header('Location: '.$_GET['redirect_uri'].'#access_token='.$token.'&token_type=bearer'); } else { - echo '<form method="POST"><input name="allow" type="submit" value="Allow this web app to store stuff on your owncloud."></form>'; +?> +<!DOCTYPE html> +<html> + <head> + <title>ownCloud</title> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <link rel="shortcut icon" href="../../../core/img/favicon.png" /><link rel="apple-touch-icon-precomposed" href="../../../core/img/favicon-touch.png" /> + <link rel="stylesheet" href="../../../core/css/styles.css" type="text/css" media="screen" /> + <link rel="stylesheet" href="../auth.css" type="text/css" media="screen" /> + </head> + <body id="body-login"> + <div id="login"> + <header> + <div id="header"> + <img src="../../../core/img/owncloud-logo-medium-white.png" alt="ownCloud" /> + </div> + </header> + <section id="main"> + <div id="oauth"> + <h2><img src="../remoteStorage-big.png" alt="remoteStorage" /></h2> + <p><strong><?php $appUrlParts = explode('/', $_GET['redirect_uri']); echo htmlentities($appUrlParts[2]); ?></strong> + requests read & write access to your + <?php + $categories = explode(',', htmlentities($_GET['scope'])); + if(!count($categories)) { + echo htmlentities($_GET['scope']); + } else { + echo '<em>'.$categories[0].'</em>'; + if(count($categories)==2) { + echo ' and <em>'.$categories[1].'</em>'; + } else if(count($categories)>2) { + for($i=1; $i<count($categories)-1; $i++) { + echo ', <em>'.$categories[$i].'</em>'; + } + echo ', and <em>'.$categories[$i].'</em>'; + } + } + ?>. + </p> + <form accept-charset="UTF-8" method="post"> + <input id="allow-auth" name="allow" type="submit" value="Allow" /> + <input id="deny-auth" name="deny" type="submit" value="Deny" /> + </form> + </div> + </section> + </div> + <footer><p class="info"><a href="http://owncloud.org/">ownCloud</a> – web services under your control</p></footer> + </body> +</html> +<?php } } else { if((isset($_SERVER['HTTPS'])) && ($_SERVER['HTTPS'])) { @@ -88,13 +122,13 @@ if(count($pathParts) == 2 && $pathParts[0] == '') { } $url .= $_SERVER['SERVER_NAME']; $url .= substr($_SERVER['SCRIPT_NAME'], 0, -strlen('apps/remoteStorage/compat.php')); - die('You are '.($currUser?'logged in as '.$currUser.' instead of '.$ownCloudUser:'not logged in').'. Please ' - .'<input type="submit" onclick="' - ."window.open('$url','Close me!','height=600,width=300');" - .'" value="log in">' - .', close the pop-up, and ' - .'<form method="POST"><input name="allow" type="submit" value="Click here"></form>'); + if($currUser) { + die('You are logged in as '.$currUser.' instead of '.$ownCloudUser); + } else { + header('Location: /?redirect_url='.urlencode('/apps/remoteStorage/auth.php'.$_SERVER['PATH_INFO'].'?'.$_SERVER['QUERY_STRING'])); + } } } else { - die('please use auth.php/username?params. '.var_export($pathParts, true)); + //die('please use auth.php/username?params. '.var_export($pathParts, true)); + die('please use auth.php/username?params.'); } diff --git a/apps/remoteStorage/lib_remoteStorage.php b/apps/remoteStorage/lib_remoteStorage.php index 4f19310904e..6e6a19c739f 100644 --- a/apps/remoteStorage/lib_remoteStorage.php +++ b/apps/remoteStorage/lib_remoteStorage.php @@ -2,11 +2,13 @@ class OC_remoteStorage { public static function getValidTokens($ownCloudUser, $category) { - $query=OC_DB::prepare("SELECT token,appUrl FROM *PREFIX*authtoken WHERE user=? AND category=? LIMIT 100"); - $result=$query->execute(array($ownCloudUser,$category)); + $query=OC_DB::prepare("SELECT token,appUrl,category FROM *PREFIX*authtoken WHERE user=? LIMIT 100"); + $result=$query->execute(array($ownCloudUser)); $ret = array(); while($row=$result->fetchRow()){ - $ret[$row['token']]=true; + if(in_array($category, explode(',', $row['category']))) { + $ret[$row['token']]=true; + } } return $ret; } @@ -18,8 +20,8 @@ class OC_remoteStorage { $ret = array(); while($row=$result->fetchRow()){ $ret[$row['token']] = array( - 'appUrl' => $row['appurl'], - 'category' => $row['category'], + 'appUrl' => $row['appUrl'], + 'categories' => $row['category'], ); } return $ret; @@ -29,22 +31,25 @@ class OC_remoteStorage { $user=OC_User::getUser(); $query=OC_DB::prepare("DELETE FROM *PREFIX*authtoken WHERE token=? AND user=?"); $result=$query->execute(array($token,$user)); + return 'unknown';//how can we see if any rows were affected? } - private static function addToken($token, $appUrl, $category){ + private static function addToken($token, $appUrl, $categories){ $user=OC_User::getUser(); $query=OC_DB::prepare("INSERT INTO *PREFIX*authtoken (`token`,`appUrl`,`user`,`category`) VALUES(?,?,?,?)"); - $result=$query->execute(array($token,$appUrl,$user,$category)); + $result=$query->execute(array($token,$appUrl,$user,$categories)); } - public static function createCategory($appUrl, $category) { + public static function createCategories($appUrl, $categories) { $token=uniqid(); - self::addToken($token, $appUrl, $category); - //TODO: input checking on $category OC_Util::setupFS(OC_User::getUser()); - $scopePathParts = array('remoteStorage', $category); - for($i=0;$i<=count($scopePathParts);$i++){ - $thisPath = '/'.implode('/', array_slice($scopePathParts, 0, $i)); - if(!OC_Filesystem::file_exists($thisPath)) { - OC_Filesystem::mkdir($thisPath); + self::addToken($token, $appUrl, $categories); + foreach(explode(',', $categories) as $category) { + //TODO: input checking on $category + $scopePathParts = array('remoteStorage', $category); + for($i=0;$i<=count($scopePathParts);$i++){ + $thisPath = '/'.implode('/', array_slice($scopePathParts, 0, $i)); + if(!OC_Filesystem::file_exists($thisPath)) { + OC_Filesystem::mkdir($thisPath); + } } } return base64_encode('remoteStorage:'.$token); diff --git a/apps/remoteStorage/oauth_ro_auth.php b/apps/remoteStorage/oauth_ro_auth.php index 5403fbe20c9..085a5469920 100644 --- a/apps/remoteStorage/oauth_ro_auth.php +++ b/apps/remoteStorage/oauth_ro_auth.php @@ -16,9 +16,10 @@ class OC_Connector_Sabre_Auth_ro_oauth extends Sabre_DAV_Auth_Backend_AbstractBasic { private $validTokens; - - public function __construct($validTokensArg) { + private $category; + public function __construct($validTokensArg, $categoryArg) { $this->validTokens = $validTokensArg; + $this->category = $categoryArg; } /** @@ -31,29 +32,31 @@ class OC_Connector_Sabre_Auth_ro_oauth extends Sabre_DAV_Auth_Backend_AbstractBa */ protected function validateUserPass($username, $password){ //always give read-only: - if(in_array($_SERVER['REQUEST_METHOD'], array('GET', 'HEAD', 'OPTIONS'))) { - OC_Util::setUpFS(); - return true; - } else if(isset($this->validTokens[$password]) && $this->validTokens[$password] == $username) { + if(($_SERVER['REQUEST_METHOD'] == 'OPTIONS') + || (isset($this->validTokens[$password])) + || (($_SERVER['REQUEST_METHOD'] == 'GET') && ($this->category == 'public')) + ) { OC_Util::setUpFS(); return true; } else { -var_export($_SERVER); -var_export($this->validTokens); -die('not getting in with "'.$username.'"/"'.$password.'"!'); + //var_export($_SERVER); + //var_export($this->validTokens); + //die('not getting in with "'.$username.'"/"'.$password.'"!'); return false; } } //overwriting this to make it not automatically fail if no auth header is found: public function authenticate(Sabre_DAV_Server $server,$realm) { - $auth = new Sabre_HTTP_BasicAuth(); + $auth = new Sabre_HTTP_BearerAuth(); $auth->setHTTPRequest($server->httpRequest); $auth->setHTTPResponse($server->httpResponse); $auth->setRealm($realm); $userpass = $auth->getUserPass(); if (!$userpass) { - if(in_array($_SERVER['REQUEST_METHOD'], array('OPTIONS'))) { + if(($_SERVER['REQUEST_METHOD'] == 'OPTIONS') + ||(($_SERVER['REQUEST_METHOD'] == 'GET') && ($this->category == 'public')) + ) { $userpass = array('', ''); } else { $auth->requireLogin(); diff --git a/apps/remoteStorage/remoteStorage-big.png b/apps/remoteStorage/remoteStorage-big.png Binary files differnew file mode 100644 index 00000000000..7c429a6a738 --- /dev/null +++ b/apps/remoteStorage/remoteStorage-big.png diff --git a/apps/remoteStorage/remoteStorage.png b/apps/remoteStorage/remoteStorage.png Binary files differnew file mode 100644 index 00000000000..6b751c09997 --- /dev/null +++ b/apps/remoteStorage/remoteStorage.png diff --git a/apps/remoteStorage/settings.php b/apps/remoteStorage/settings.php new file mode 100644 index 00000000000..fa85f77a535 --- /dev/null +++ b/apps/remoteStorage/settings.php @@ -0,0 +1,7 @@ +<?php + +require_once('lib_remoteStorage.php'); +$tmpl = new OC_Template( 'remoteStorage', 'settings'); + +return $tmpl->fetchPage(); +?> diff --git a/apps/remoteStorage/templates/settings.php b/apps/remoteStorage/templates/settings.php new file mode 100644 index 00000000000..9b5c3b6229c --- /dev/null +++ b/apps/remoteStorage/templates/settings.php @@ -0,0 +1,28 @@ + <fieldset class="personalblock"> + <?php + echo '<img src="/apps/remoteStorage/remoteStorage.png" style="width:16px"> ' + .'<strong>'.$l->t('remoteStorage').'</strong> user address: ' + .OC_User::getUser().'@'.$_SERVER['SERVER_NAME'] + .' (<a href="http://unhosted.org/">more info</a>)'; + ?> + <p><em>Apps that currently have access to your ownCloud:</em></p> + <script> + function revokeToken(token) { + var xhr = new XMLHttpRequest(); + xhr.open('POST', '/apps/remoteStorage/ajax/revokeToken.php', true); + xhr.send(token); + } + </script> + <ul> + <?php + foreach(OC_remoteStorage::getAllTokens() as $token => $details) { + echo '<li onmouseover="' + .'document.getElementById(\'revoke_'.$token.'\').style.display=\'inline\';"' + .'onmouseout="document.getElementById(\'revoke_'.$token.'\').style.display=\'none\';"' + .'> <strong>'.$details['appUrl'].'</strong>: '.$details['categories'] + .' <a href="#" title="Revoke" class="action" style="display:none" id="revoke_'.$token.'" onclick="' + .'revokeToken(\''.$token.'\');this.parentNode.style.display=\'none\';"' + .'><img src="/core/img/actions/delete.svg"></a></li>'."\n"; + } + ?></ul> + </fieldset> diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php index 1f2d8ed9af3..ad44fe95f9e 100644 --- a/apps/user_ldap/settings.php +++ b/apps/user_ldap/settings.php @@ -20,7 +20,7 @@ * License along with this library. If not, see <http://www.gnu.org/licenses/>. * */ -$params = array('ldap_host', 'ldap_port', 'ldap_dn', 'ldap_password', 'ldap_base', 'ldap_filter', 'ldap_display_name', 'ldap_tls', 'ldap_nocase'); +$params = array('ldap_host', 'ldap_port', 'ldap_dn', 'ldap_password', 'ldap_base', 'ldap_userlist_filter', 'ldap_login_filter', 'ldap_display_name', 'ldap_tls', 'ldap_nocase'. 'ldap_quota_def', 'ldap_quota_attr', 'ldap_email_attr'); if ($_POST) { foreach($params as $param){ @@ -29,12 +29,12 @@ if ($_POST) { } elseif('ldap_tls' == $param) { // unchecked checkboxes are not included in the post paramters - OC_Appconfig::setValue('user_ldap', $param, 0); + OC_Appconfig::setValue('user_ldap', $param, 0); } elseif('ldap_nocase' == $param) { OC_Appconfig::setValue('user_ldap', $param, 0); } - + } } diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index 5bbd5d4008d..828c72cba97 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -6,15 +6,16 @@ <p><label for="ldap_dn"><?php echo $l->t('Name');?></label><input type="text" id="ldap_dn" name="ldap_dn" value="<?php echo $_['ldap_dn']; ?>" /> <label for="ldap_password"><?php echo $l->t('Password');?></label><input type="password" id="ldap_password" name="ldap_password" value="<?php echo $_['ldap_password']; ?>" /> <small><?php echo $l->t('Leave both empty for anonymous bind for search, then bind with users credentials.');?></small></p> - <p><label for="ldap_base"><?php echo $l->t('Base');?></label><input type="text" id="ldap_base" name="ldap_base" value="<?php echo $_['ldap_base']; ?>" /> - <label for="ldap_filter"><?php echo $l->t('Filter (use %%uid placeholder)');?></label><input type="text" id="ldap_filter" name="ldap_filter" value="<?php echo $_['ldap_filter']; ?>" /></p> + <p><label for="ldap_base"><?php echo $l->t('Base');?></label><input type="text" id="ldap_base" name="ldap_base" value="<?php echo $_['ldap_base']; ?>" /></p> + <p><label for="ldap_login_filter"><?php echo $l->t('User Login Filter');?></label><input type="text" id="ldap_login_filter" name="ldap_login_filter" value="<?php echo $_['ldap_login_filter']; ?>" /><small><?php echo $l->t('use %%uid placeholder, e.g. uid=%%uid');?></small></p> + <p><label for="ldap_userlist_filter"><?php echo $l->t('User List Filter');?></label><input type="text" id="ldap_userlist_filter" name="ldap_userlist_filter" value="<?php echo $_['ldap_userlist_filter']; ?>" /><small><?php echo $l->t('without any placeholder, e.g. "objectClass=person".');?> </p> <p><label for="ldap_display_name"><?php echo $l->t('Display Name Field');?></label><input type="text" id="ldap_display_name" name="ldap_display_name" value="<?php echo $_['ldap_display_name']; ?>" /> <small><?php echo $l->t('Currently the display name field needs to be the same you matched %%uid against in the filter above, because ownCloud doesn\'t distinguish between user id and user name.');?></small></p> <p><input type="checkbox" id="ldap_tls" name="ldap_tls" value="1"<?php if ($_['ldap_tls']) echo ' checked'; ?>><label for="ldap_tls"><?php echo $l->t('Use TLS');?></label></p> <p><input type="checkbox" id="ldap_nocase" name="ldap_nocase" value="1"<?php if ($_['ldap_nocase']) echo ' checked'; ?>><label for="ldap_nocase"><?php echo $l->t('Case insensitve LDAP server (Windows)');?></label></p> - <p><label for="ldap_quota">Quota Attribute</label><input type="text" id="ldap_quota" name="ldap_quota" value="<?php echo $_['ldap_quota']; ?>" /> + <p><label for="ldap_quota_attr">Quota Attribute</label><input type="text" id="ldap_quota_attr" name="ldap_quota_attr" value="<?php echo $_['ldap_quota_attr']; ?>" /> <label for="ldap_quota_def">Quota Default</label><input type="text" id="ldap_quota_def" name="ldap_quota_def" value="<?php echo $_['ldap_quota_def']; ?>" />bytes</p> - <p><label for="ldap_email">Email Attribute</label><input type="text" id="ldap_email" name="ldap_email" value="<?php echo $_['ldap_email']; ?>" /></p> + <p><label for="ldap_email_attr">Email Attribute</label><input type="text" id="ldap_email_attr" name="ldap_email_attr" value="<?php echo $_['ldap_email_attr']; ?>" /></p> <input type="submit" value="Save" /> </fieldset> </form> diff --git a/apps/user_ldap/user_ldap.php b/apps/user_ldap/user_ldap.php index 670d938ea95..3521a9d90cf 100644 --- a/apps/user_ldap/user_ldap.php +++ b/apps/user_ldap/user_ldap.php @@ -32,7 +32,8 @@ class OC_USER_LDAP extends OC_User_Backend { protected $ldap_dn; protected $ldap_password; protected $ldap_base; - protected $ldap_filter; + protected $ldap_login_filter; + protected $ldap_userlist_filter; protected $ldap_tls; protected $ldap_nocase; protected $ldap_display_name; @@ -49,7 +50,8 @@ class OC_USER_LDAP extends OC_User_Backend { $this->ldap_dn = OC_Appconfig::getValue('user_ldap', 'ldap_dn',''); $this->ldap_password = OC_Appconfig::getValue('user_ldap', 'ldap_password',''); $this->ldap_base = OC_Appconfig::getValue('user_ldap', 'ldap_base',''); - $this->ldap_filter = OC_Appconfig::getValue('user_ldap', 'ldap_filter',''); + $this->ldap_login_filter = OC_Appconfig::getValue('user_ldap', 'ldap_login_filter',''); + $this->ldap_userlist_filter = OC_Appconfig::getValue('user_ldap', 'ldap_userlist_filter','objectClass=person'); $this->ldap_tls = OC_Appconfig::getValue('user_ldap', 'ldap_tls', 0); $this->ldap_nocase = OC_Appconfig::getValue('user_ldap', 'ldap_nocase', 0); $this->ldap_display_name = OC_Appconfig::getValue('user_ldap', 'ldap_display_name', OC_USER_BACKEND_LDAP_DEFAULT_DISPLAY_NAME); @@ -61,7 +63,7 @@ class OC_USER_LDAP extends OC_User_Backend { && !empty($this->ldap_port) && ((!empty($this->ldap_dn) && !empty($this->ldap_password)) || (empty($this->ldap_dn) && empty($this->ldap_password))) && !empty($this->ldap_base) - && !empty($this->ldap_filter) + && !empty($this->ldap_login_filter) && !empty($this->ldap_display_name) ) { @@ -79,9 +81,13 @@ class OC_USER_LDAP extends OC_User_Backend { if( !$this->ldap_dc ) return false; - $quota = $this->ldap_dc[$this->ldap_quota_attr][0]; + if(!empty($this->ldap_quota_attr)) { + $quota = $this->ldap_dc[strtolower($this->ldap_quota_attr)][0]; + } else { + $quota = false; + } $quota = $quota != -1 ? $quota : $this->ldap_quota_def; - OC_Preferences::setValue($uid, 'files', 'quota', $quota); + OC_Preferences::setValue($uid, 'files', 'quota', OC_Helper::computerFileSize($quota)); } private function setEmail( $uid ) { @@ -127,7 +133,7 @@ class OC_USER_LDAP extends OC_User_Backend { return false; // get dn - $filter = str_replace('%uid', $uid, $this->ldap_filter); + $filter = str_replace('%uid', $uid, $this->ldap_login_filter); $sr = ldap_search( $this->getDs(), $this->ldap_base, $filter ); $entries = ldap_get_entries( $this->getDs(), $sr ); @@ -152,7 +158,7 @@ class OC_USER_LDAP extends OC_User_Backend { return false; } - if(!empty($this->ldap_quota) && !empty($this->ldap_quota_def)) { + if(!empty($this->ldap_quota_attr) || !empty($this->ldap_quota_def)) { $this->setQuota($uid); } @@ -161,7 +167,7 @@ class OC_USER_LDAP extends OC_User_Backend { } if($this->ldap_nocase) { - $filter = str_replace('%uid', $uid, $this->ldap_filter); + $filter = str_replace('%uid', $uid, $this->ldap_login_filter); $sr = ldap_search( $this->getDs(), $this->ldap_base, $filter ); $entries = ldap_get_entries( $this->getDs(), $sr ); if( $entries['count'] == 1 ) { @@ -187,7 +193,7 @@ class OC_USER_LDAP extends OC_User_Backend { if(!$this->configured){ return false; } - $dn = $this->getDn($uid); + $dn = $this->getDc($uid); return !empty($dn); } @@ -202,8 +208,7 @@ class OC_USER_LDAP extends OC_User_Backend { return false; // get users - $filter = 'objectClass=person'; - $sr = ldap_search( $this->getDs(), $this->ldap_base, $filter ); + $sr = ldap_search( $this->getDs(), $this->ldap_base, $this->ldap_userlist_filter ); $entries = ldap_get_entries( $this->getDs(), $sr ); if( $entries['count'] == 0 ) return false; diff --git a/apps/user_webfinger/appinfo/info.xml b/apps/user_webfinger/appinfo/info.xml index a4071dae172..55cf2cf2201 100644 --- a/apps/user_webfinger/appinfo/info.xml +++ b/apps/user_webfinger/appinfo/info.xml @@ -3,8 +3,8 @@ <id>user_webfinger</id> <name>Webfinger</name> <description>Provide WebFinger for all users so they get a user address like user@owncloudinstance which can be used for unhosted applications. If you don't run ownCloud in the root of your domain, for instance if you run it on example.com/owncloud/, then make sure you link example.com/.well-known/ to example.com/owncloud/apps/user_webfinger/ - by running something like "ln -s /var/www/owncloud/apps/user_webfinger /var/www/.well-known". Only enable this app if you run this ownCloud installation on a public web address, not if you run it on an intranet or on localhost.</description> - <version>0.1</version> - <licence>AGPL</licence> + <version>0.2</version> + <licence>AGPL or MIT</licence> <author>Michiel de Jong</author> <require>2</require> </info> diff --git a/apps/user_webfinger/host-meta.php b/apps/user_webfinger/host-meta.php index ceb15f22da4..ac577cf9a0c 100644 --- a/apps/user_webfinger/host-meta.php +++ b/apps/user_webfinger/host-meta.php @@ -4,13 +4,13 @@ if($_SERVER['SCRIPT_NAME'] == '/.well-known/host-meta.php') { } else { header('Please-first: activate'); } -header("Content-Type: application/xml+xrd"); +header("Content-Type: application/xrd+xml"); echo "<"; ?> ?xml version="1.0" encoding="UTF-8"?> <XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0" xmlns:hm="http://host-meta.net/xrd/1.0"> <hm:Host xmlns="http://host-meta.net/xrd/1.0"><?php echo $_SERVER['SERVER_NAME'] ?></hm:Host> - <Link rel="lrdd" template="http<?php echo ($_SERVER['HTTPS']?'s':''); ?>://<?php echo $_SERVER['SERVER_NAME'] ?>/.well-known/webfinger.php?q={uri}"> + <Link rel="lrdd" template="http<?php echo (isset($_SERVER['HTTPS'])?'s':''); ?>://<?php echo $_SERVER['SERVER_NAME'] ?>/.well-known/webfinger.php?q={uri}"> </Link> </XRD> diff --git a/apps/user_webfinger/webfinger.php b/apps/user_webfinger/webfinger.php index d695a833f31..5c2a24aa070 100644 --- a/apps/user_webfinger/webfinger.php +++ b/apps/user_webfinger/webfinger.php @@ -4,7 +4,7 @@ if($_SERVER['SCRIPT_NAME'] == '/.well-known/webfinger.php') { } else { header('Please-first: activate'); } -// header("Content-Type: application/xml+xrd"); +header("Content-Type: application/xrd+xml"); // calculate the documentroot // modified version of the one in lib/base.php that takes the .well-known symlink into account @@ -22,7 +22,7 @@ if($_GET['q']) { if(substr($userName, 0, 5) == 'acct:') { $userName = substr($userName, 5); } -if($_SERVER['HTTPS']) { +if(isset($_SERVER['HTTPS'])) { $baseAddress = 'https://'.$_SERVER['SERVER_NAME'].'/apps/remoteStorage/'; } else { $baseAddress = 'http://'.$_SERVER['SERVER_NAME'].'/apps/remoteStorage/'; |