diff options
author | Tom Needham <needham.thomas@gmail.com> | 2012-07-26 11:26:22 +0000 |
---|---|---|
committer | Tom Needham <needham.thomas@gmail.com> | 2012-07-26 11:26:22 +0000 |
commit | edb04b25dea733e0ac3a1f87c55cfd368dcdf731 (patch) | |
tree | e8b951b8162955d7f2282c83d06cf803e61396f3 | |
parent | 7de97ed20003d1f5ab9e2bfde9386bba07d0eff8 (diff) | |
parent | b3848581bf5f77008a71cf79ba6e3d61b33baed6 (diff) | |
download | nextcloud-server-edb04b25dea733e0ac3a1f87c55cfd368dcdf731.tar.gz nextcloud-server-edb04b25dea733e0ac3a1f87c55cfd368dcdf731.zip |
Fix merge conflicts
580 files changed, 8758 insertions, 3766 deletions
diff --git a/.gitignore b/.gitignore index e2ff07d14d8..ae636931706 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,9 @@ RCS/* # netbeans nbproject +# phpStorm +.idea + # geany *.geany diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000000..0f4ad588071 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "3rdparty/Symfony/Component/Routing"] + path = 3rdparty/Symfony/Component/Routing + url = git://github.com/symfony/Routing.git diff --git a/3rdparty/Sabre.includes.php b/3rdparty/Sabre.includes.php index c1334373663..c1334373663 100644..100755 --- a/3rdparty/Sabre.includes.php +++ b/3rdparty/Sabre.includes.php diff --git a/3rdparty/Sabre/CalDAV/Backend/Abstract.php b/3rdparty/Sabre/CalDAV/Backend/Abstract.php index 7aba1d69ffe..7aba1d69ffe 100644..100755 --- a/3rdparty/Sabre/CalDAV/Backend/Abstract.php +++ b/3rdparty/Sabre/CalDAV/Backend/Abstract.php diff --git a/3rdparty/Sabre/CalDAV/Backend/PDO.php b/3rdparty/Sabre/CalDAV/Backend/PDO.php index ddacf940c74..ddacf940c74 100644..100755 --- a/3rdparty/Sabre/CalDAV/Backend/PDO.php +++ b/3rdparty/Sabre/CalDAV/Backend/PDO.php diff --git a/3rdparty/Sabre/CalDAV/Calendar.php b/3rdparty/Sabre/CalDAV/Calendar.php index 623df2dd1b8..623df2dd1b8 100644..100755 --- a/3rdparty/Sabre/CalDAV/Calendar.php +++ b/3rdparty/Sabre/CalDAV/Calendar.php diff --git a/3rdparty/Sabre/CalDAV/CalendarObject.php b/3rdparty/Sabre/CalDAV/CalendarObject.php index 72f0a578d16..72f0a578d16 100644..100755 --- a/3rdparty/Sabre/CalDAV/CalendarObject.php +++ b/3rdparty/Sabre/CalDAV/CalendarObject.php diff --git a/3rdparty/Sabre/CalDAV/CalendarQueryParser.php b/3rdparty/Sabre/CalDAV/CalendarQueryParser.php index bd0d343382f..bd0d343382f 100644..100755 --- a/3rdparty/Sabre/CalDAV/CalendarQueryParser.php +++ b/3rdparty/Sabre/CalDAV/CalendarQueryParser.php diff --git a/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php b/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php index 1bb6b5d53fa..4bcd32cdf88 100644..100755 --- a/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php +++ b/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php @@ -294,6 +294,7 @@ class Sabre_CalDAV_CalendarQueryValidator { // in the VALARM component code, so this is a hack, and an // expensive one too. if ($component->parent->name === 'VEVENT' && $component->parent->RRULE) { + // Fire up the iterator! $it = new Sabre_VObject_RecurrenceIterator($component->parent->parent, (string)$component->parent->UID); while($it->valid()) { @@ -304,14 +305,35 @@ class Sabre_CalDAV_CalendarQueryValidator { // determine if we can 'give up' expanding events. $firstAlarm = null; foreach($expandedEvent->VALARM as $expandedAlarm) { + $effectiveTrigger = $expandedAlarm->getEffectiveTriggerTime(); - if (!$firstAlarm || $effectiveTrigger < $firstAlarm) { - $firstAlarm = $effectiveTrigger; - } if ($expandedAlarm->isInTimeRange($start, $end)) { return true; } + if ((string)$expandedAlarm->TRIGGER['VALUE'] === 'DATE-TIME') { + // This is an alarm with a non-relative trigger + // time, likely created by a buggy client. The + // implication is that every alarm in this + // recurring event trigger at the exact same + // time. It doesn't make sense to traverse + // further. + } else { + // We store the first alarm as a means to + // figure out when we can stop traversing. + if (!$firstAlarm || $effectiveTrigger < $firstAlarm) { + $firstAlarm = $effectiveTrigger; + } + } + + } + if (is_null($firstAlarm)) { + // No alarm was found. + // + // Or technically: No alarm that will change for + // every instance of the recurrence was found, + // which means we can assume there was no match. + return false; } if ($firstAlarm > $end) { return false; diff --git a/3rdparty/Sabre/CalDAV/CalendarRootNode.php b/3rdparty/Sabre/CalDAV/CalendarRootNode.php index 3907913cc78..3907913cc78 100644..100755 --- a/3rdparty/Sabre/CalDAV/CalendarRootNode.php +++ b/3rdparty/Sabre/CalDAV/CalendarRootNode.php diff --git a/3rdparty/Sabre/CalDAV/ICSExportPlugin.php b/3rdparty/Sabre/CalDAV/ICSExportPlugin.php index ec42b406b2f..ec42b406b2f 100644..100755 --- a/3rdparty/Sabre/CalDAV/ICSExportPlugin.php +++ b/3rdparty/Sabre/CalDAV/ICSExportPlugin.php diff --git a/3rdparty/Sabre/CalDAV/ICalendar.php b/3rdparty/Sabre/CalDAV/ICalendar.php index 15d51ebcf79..15d51ebcf79 100644..100755 --- a/3rdparty/Sabre/CalDAV/ICalendar.php +++ b/3rdparty/Sabre/CalDAV/ICalendar.php diff --git a/3rdparty/Sabre/CalDAV/ICalendarObject.php b/3rdparty/Sabre/CalDAV/ICalendarObject.php index 280f982a310..280f982a310 100644..100755 --- a/3rdparty/Sabre/CalDAV/ICalendarObject.php +++ b/3rdparty/Sabre/CalDAV/ICalendarObject.php diff --git a/3rdparty/Sabre/CalDAV/Plugin.php b/3rdparty/Sabre/CalDAV/Plugin.php index d7d1d970518..5903968c003 100644..100755 --- a/3rdparty/Sabre/CalDAV/Plugin.php +++ b/3rdparty/Sabre/CalDAV/Plugin.php @@ -672,6 +672,42 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin { } + if ($vobj->name !== 'VCALENDAR') { + throw new Sabre_DAV_Exception_UnsupportedMediaType('This collection can only support iCalendar objects.'); + } + + $foundType = null; + $foundUID = null; + foreach($vobj->getComponents() as $component) { + switch($component->name) { + case 'VTIMEZONE' : + continue 2; + case 'VEVENT' : + case 'VTODO' : + case 'VJOURNAL' : + if (is_null($foundType)) { + $foundType = $component->name; + if (!isset($component->UID)) { + throw new Sabre_DAV_Exception_BadRequest('Every ' . $component->name . ' component must have an UID'); + } + $foundUID = (string)$component->UID; + } else { + if ($foundType !== $component->name) { + throw new Sabre_DAV_Exception_BadRequest('A calendar object must only contain 1 component. We found a ' . $component->name . ' as well as a ' . $foundType); + } + if ($foundUID !== (string)$component->UID) { + throw new Sabre_DAV_Exception_BadRequest('Every ' . $component->name . ' in this object must have identical UIDs'); + } + } + break; + default : + throw new Sabre_DAV_Exception_BadRequest('You are not allowed to create components of type: ' . $component->name . ' here'); + + } + } + if (!$foundType) + throw new Sabre_DAV_Exception_BadRequest('iCalendar object must contain at least 1 of VEVENT, VTODO or VJOURNAL'); + } /** diff --git a/3rdparty/Sabre/CalDAV/Principal/Collection.php b/3rdparty/Sabre/CalDAV/Principal/Collection.php index abbefa5567a..abbefa5567a 100644..100755 --- a/3rdparty/Sabre/CalDAV/Principal/Collection.php +++ b/3rdparty/Sabre/CalDAV/Principal/Collection.php diff --git a/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php b/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php index 4b3f035634a..4b3f035634a 100644..100755 --- a/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php +++ b/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php diff --git a/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php b/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php index dd0c2e86edd..dd0c2e86edd 100644..100755 --- a/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php +++ b/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php diff --git a/3rdparty/Sabre/CalDAV/Principal/User.php b/3rdparty/Sabre/CalDAV/Principal/User.php index 8453b877a73..8453b877a73 100644..100755 --- a/3rdparty/Sabre/CalDAV/Principal/User.php +++ b/3rdparty/Sabre/CalDAV/Principal/User.php diff --git a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php index 2ea078d7dac..2ea078d7dac 100644..100755 --- a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php +++ b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php diff --git a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php index 1d848dd5cf6..1d848dd5cf6 100644..100755 --- a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php +++ b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php diff --git a/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php b/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php index 24e84d4c17d..24e84d4c17d 100644..100755 --- a/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php +++ b/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php diff --git a/3rdparty/Sabre/CalDAV/Schedule/IMip.php b/3rdparty/Sabre/CalDAV/Schedule/IMip.php index 37e75fcc4a7..37e75fcc4a7 100644..100755 --- a/3rdparty/Sabre/CalDAV/Schedule/IMip.php +++ b/3rdparty/Sabre/CalDAV/Schedule/IMip.php diff --git a/3rdparty/Sabre/CalDAV/Schedule/IOutbox.php b/3rdparty/Sabre/CalDAV/Schedule/IOutbox.php index 46d77514bc0..46d77514bc0 100644..100755 --- a/3rdparty/Sabre/CalDAV/Schedule/IOutbox.php +++ b/3rdparty/Sabre/CalDAV/Schedule/IOutbox.php diff --git a/3rdparty/Sabre/CalDAV/Schedule/Outbox.php b/3rdparty/Sabre/CalDAV/Schedule/Outbox.php index 014c37230d1..014c37230d1 100644..100755 --- a/3rdparty/Sabre/CalDAV/Schedule/Outbox.php +++ b/3rdparty/Sabre/CalDAV/Schedule/Outbox.php diff --git a/3rdparty/Sabre/CalDAV/Server.php b/3rdparty/Sabre/CalDAV/Server.php index 325e3d80a7f..325e3d80a7f 100644..100755 --- a/3rdparty/Sabre/CalDAV/Server.php +++ b/3rdparty/Sabre/CalDAV/Server.php diff --git a/3rdparty/Sabre/CalDAV/UserCalendars.php b/3rdparty/Sabre/CalDAV/UserCalendars.php index b8d3f0573fa..b8d3f0573fa 100644..100755 --- a/3rdparty/Sabre/CalDAV/UserCalendars.php +++ b/3rdparty/Sabre/CalDAV/UserCalendars.php diff --git a/3rdparty/Sabre/CalDAV/Version.php b/3rdparty/Sabre/CalDAV/Version.php index 939e903c89f..289a0c83a34 100644..100755 --- a/3rdparty/Sabre/CalDAV/Version.php +++ b/3rdparty/Sabre/CalDAV/Version.php @@ -14,7 +14,7 @@ class Sabre_CalDAV_Version { /** * Full version number */ - const VERSION = '1.6.2'; + const VERSION = '1.6.3'; /** * Stability : alpha, beta, stable diff --git a/3rdparty/Sabre/CalDAV/includes.php b/3rdparty/Sabre/CalDAV/includes.php index 1ecb870a0e1..1ecb870a0e1 100644..100755 --- a/3rdparty/Sabre/CalDAV/includes.php +++ b/3rdparty/Sabre/CalDAV/includes.php diff --git a/3rdparty/Sabre/CardDAV/AddressBook.php b/3rdparty/Sabre/CardDAV/AddressBook.php index 3b381e1eea3..12297175a85 100644..100755 --- a/3rdparty/Sabre/CardDAV/AddressBook.php +++ b/3rdparty/Sabre/CardDAV/AddressBook.php @@ -108,7 +108,9 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca */ public function createFile($name,$vcardData = null) { - $vcardData = stream_get_contents($vcardData); + if (is_resource($vcardData)) { + $vcardData = stream_get_contents($vcardData); + } // Converting to UTF-8, if needed $vcardData = Sabre_DAV_StringUtil::ensureUTF8($vcardData); diff --git a/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php b/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php index 85a4963127b..46bb8ff18dd 100644..100755 --- a/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php +++ b/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php @@ -9,7 +9,7 @@ * @package Sabre * @subpackage CardDAV * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ class Sabre_CardDAV_AddressBookQueryParser { @@ -88,12 +88,22 @@ class Sabre_CardDAV_AddressBookQueryParser { if (is_nan($limit)) $limit = null; $filter = $this->xpath->query('/card:addressbook-query/card:filter'); - if ($filter->length !== 1) { + + // According to the CardDAV spec there needs to be exactly 1 filter + // element. However, KDE 4.8.2 contains a bug that will encode 0 filter + // elements, so this is a workaround for that. + // + // See: https://bugs.kde.org/show_bug.cgi?id=300047 + if ($filter->length === 0) { + $test = null; + $filter = null; + } elseif ($filter->length === 1) { + $filter = $filter->item(0); + $test = $this->xpath->evaluate('string(@test)', $filter); + } else { throw new Sabre_DAV_Exception_BadRequest('Only one filter element is allowed'); } - $filter = $filter->item(0); - $test = $this->xpath->evaluate('string(@test)', $filter); if (!$test) $test = self::TEST_ANYOF; if ($test !== self::TEST_ANYOF && $test !== self::TEST_ALLOF) { throw new Sabre_DAV_Exception_BadRequest('The test attribute must either hold "anyof" or "allof"'); diff --git a/3rdparty/Sabre/CardDAV/AddressBookRoot.php b/3rdparty/Sabre/CardDAV/AddressBookRoot.php index 9d37b15f08e..9d37b15f08e 100644..100755 --- a/3rdparty/Sabre/CardDAV/AddressBookRoot.php +++ b/3rdparty/Sabre/CardDAV/AddressBookRoot.php diff --git a/3rdparty/Sabre/CardDAV/Backend/Abstract.php b/3rdparty/Sabre/CardDAV/Backend/Abstract.php index e4806b7161f..e4806b7161f 100644..100755 --- a/3rdparty/Sabre/CardDAV/Backend/Abstract.php +++ b/3rdparty/Sabre/CardDAV/Backend/Abstract.php diff --git a/3rdparty/Sabre/CardDAV/Backend/PDO.php b/3rdparty/Sabre/CardDAV/Backend/PDO.php index 413a77f3bcc..413a77f3bcc 100644..100755 --- a/3rdparty/Sabre/CardDAV/Backend/PDO.php +++ b/3rdparty/Sabre/CardDAV/Backend/PDO.php diff --git a/3rdparty/Sabre/CardDAV/Card.php b/3rdparty/Sabre/CardDAV/Card.php index d7c66333837..d7c66333837 100644..100755 --- a/3rdparty/Sabre/CardDAV/Card.php +++ b/3rdparty/Sabre/CardDAV/Card.php diff --git a/3rdparty/Sabre/CardDAV/IAddressBook.php b/3rdparty/Sabre/CardDAV/IAddressBook.php index 2bc275bcf74..2bc275bcf74 100644..100755 --- a/3rdparty/Sabre/CardDAV/IAddressBook.php +++ b/3rdparty/Sabre/CardDAV/IAddressBook.php diff --git a/3rdparty/Sabre/CardDAV/ICard.php b/3rdparty/Sabre/CardDAV/ICard.php index a17299316c1..a17299316c1 100644..100755 --- a/3rdparty/Sabre/CardDAV/ICard.php +++ b/3rdparty/Sabre/CardDAV/ICard.php diff --git a/3rdparty/Sabre/CardDAV/IDirectory.php b/3rdparty/Sabre/CardDAV/IDirectory.php index 22d4afeb24a..22d4afeb24a 100644..100755 --- a/3rdparty/Sabre/CardDAV/IDirectory.php +++ b/3rdparty/Sabre/CardDAV/IDirectory.php diff --git a/3rdparty/Sabre/CardDAV/Plugin.php b/3rdparty/Sabre/CardDAV/Plugin.php index 9ebec243eb0..ca20e468497 100644..100755 --- a/3rdparty/Sabre/CardDAV/Plugin.php +++ b/3rdparty/Sabre/CardDAV/Plugin.php @@ -52,6 +52,8 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { $server->subscribeEvent('report', array($this,'report')); $server->subscribeEvent('onHTMLActionsPanel', array($this,'htmlActionsPanel')); $server->subscribeEvent('onBrowserPostAction', array($this,'browserPostAction')); + $server->subscribeEvent('beforeWriteContent', array($this, 'beforeWriteContent')); + $server->subscribeEvent('beforeCreateFile', array($this, 'beforeCreateFile')); /* Namespaces */ $server->xmlNamespaces[self::NS_CARDDAV] = 'card'; @@ -284,6 +286,81 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { } /** + * This method is triggered before a file gets updated with new content. + * + * This plugin uses this method to ensure that Card nodes receive valid + * vcard data. + * + * @param string $path + * @param Sabre_DAV_IFile $node + * @param resource $data + * @return void + */ + public function beforeWriteContent($path, Sabre_DAV_IFile $node, &$data) { + + if (!$node instanceof Sabre_CardDAV_ICard) + return; + + $this->validateVCard($data); + + } + + /** + * This method is triggered before a new file is created. + * + * This plugin uses this method to ensure that Card nodes receive valid + * vcard data. + * + * @param string $path + * @param resource $data + * @param Sabre_DAV_ICollection $parentNode + * @return void + */ + public function beforeCreateFile($path, &$data, Sabre_DAV_ICollection $parentNode) { + + if (!$parentNode instanceof Sabre_CardDAV_IAddressBook) + return; + + $this->validateVCard($data); + + } + + /** + * Checks if the submitted iCalendar data is in fact, valid. + * + * An exception is thrown if it's not. + * + * @param resource|string $data + * @return void + */ + protected function validateVCard(&$data) { + + // If it's a stream, we convert it to a string first. + if (is_resource($data)) { + $data = stream_get_contents($data); + } + + // Converting the data to unicode, if needed. + $data = Sabre_DAV_StringUtil::ensureUTF8($data); + + try { + + $vobj = Sabre_VObject_Reader::read($data); + + } catch (Sabre_VObject_ParseException $e) { + + throw new Sabre_DAV_Exception_UnsupportedMediaType('This resource only supports valid vcard data. Parse error: ' . $e->getMessage()); + + } + + if ($vobj->name !== 'VCARD') { + throw new Sabre_DAV_Exception_UnsupportedMediaType('This collection can only support vcard objects.'); + } + + } + + + /** * This function handles the addressbook-query REPORT * * This report is used by the client to filter an addressbook based on a @@ -362,6 +439,8 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin { $vcard = Sabre_VObject_Reader::read($vcardData); + if (!$filters) return true; + foreach($filters as $filter) { $isDefined = isset($vcard->{$filter['name']}); diff --git a/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php b/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php index 36d9306e7aa..36d9306e7aa 100644..100755 --- a/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php +++ b/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php diff --git a/3rdparty/Sabre/CardDAV/UserAddressBooks.php b/3rdparty/Sabre/CardDAV/UserAddressBooks.php index 3f11fb11238..3f11fb11238 100644..100755 --- a/3rdparty/Sabre/CardDAV/UserAddressBooks.php +++ b/3rdparty/Sabre/CardDAV/UserAddressBooks.php diff --git a/3rdparty/Sabre/CardDAV/Version.php b/3rdparty/Sabre/CardDAV/Version.php index 811b929e397..d0623f0d3e8 100644..100755 --- a/3rdparty/Sabre/CardDAV/Version.php +++ b/3rdparty/Sabre/CardDAV/Version.php @@ -16,7 +16,7 @@ class Sabre_CardDAV_Version { /** * Full version number */ - const VERSION = '1.6.1'; + const VERSION = '1.6.3'; /** * Stability : alpha, beta, stable diff --git a/3rdparty/Sabre/CardDAV/includes.php b/3rdparty/Sabre/CardDAV/includes.php index c3b8c04b077..c3b8c04b077 100644..100755 --- a/3rdparty/Sabre/CardDAV/includes.php +++ b/3rdparty/Sabre/CardDAV/includes.php diff --git a/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php b/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php index 1e89b84f9a1..1e89b84f9a1 100644..100755 --- a/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php +++ b/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php diff --git a/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php b/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php index 9833928b976..9833928b976 100644..100755 --- a/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php +++ b/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php diff --git a/3rdparty/Sabre/DAV/Auth/Backend/Apache.php b/3rdparty/Sabre/DAV/Auth/Backend/Apache.php index d4294ea4d86..d4294ea4d86 100644..100755 --- a/3rdparty/Sabre/DAV/Auth/Backend/Apache.php +++ b/3rdparty/Sabre/DAV/Auth/Backend/Apache.php diff --git a/3rdparty/Sabre/DAV/Auth/Backend/File.php b/3rdparty/Sabre/DAV/Auth/Backend/File.php index de308d64a67..de308d64a67 100644..100755 --- a/3rdparty/Sabre/DAV/Auth/Backend/File.php +++ b/3rdparty/Sabre/DAV/Auth/Backend/File.php diff --git a/3rdparty/Sabre/DAV/Auth/Backend/PDO.php b/3rdparty/Sabre/DAV/Auth/Backend/PDO.php index eac18a23fbb..eac18a23fbb 100644..100755 --- a/3rdparty/Sabre/DAV/Auth/Backend/PDO.php +++ b/3rdparty/Sabre/DAV/Auth/Backend/PDO.php diff --git a/3rdparty/Sabre/DAV/Auth/IBackend.php b/3rdparty/Sabre/DAV/Auth/IBackend.php index 5be5d1bc93d..5be5d1bc93d 100644..100755 --- a/3rdparty/Sabre/DAV/Auth/IBackend.php +++ b/3rdparty/Sabre/DAV/Auth/IBackend.php diff --git a/3rdparty/Sabre/DAV/Auth/Plugin.php b/3rdparty/Sabre/DAV/Auth/Plugin.php index 55a4e391674..55a4e391674 100644..100755 --- a/3rdparty/Sabre/DAV/Auth/Plugin.php +++ b/3rdparty/Sabre/DAV/Auth/Plugin.php diff --git a/3rdparty/Sabre/DAV/Browser/GuessContentType.php b/3rdparty/Sabre/DAV/Browser/GuessContentType.php index b6c00d461cb..b6c00d461cb 100644..100755 --- a/3rdparty/Sabre/DAV/Browser/GuessContentType.php +++ b/3rdparty/Sabre/DAV/Browser/GuessContentType.php diff --git a/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php b/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php index 15884887641..15884887641 100644..100755 --- a/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php +++ b/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php diff --git a/3rdparty/Sabre/DAV/Browser/Plugin.php b/3rdparty/Sabre/DAV/Browser/Plugin.php index 09bbdd2ae02..09bbdd2ae02 100644..100755 --- a/3rdparty/Sabre/DAV/Browser/Plugin.php +++ b/3rdparty/Sabre/DAV/Browser/Plugin.php diff --git a/3rdparty/Sabre/DAV/Browser/assets/favicon.ico b/3rdparty/Sabre/DAV/Browser/assets/favicon.ico Binary files differindex 2b2c10a22cc..2b2c10a22cc 100644..100755 --- a/3rdparty/Sabre/DAV/Browser/assets/favicon.ico +++ b/3rdparty/Sabre/DAV/Browser/assets/favicon.ico diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.png b/3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.png Binary files differindex c9acc84172d..c9acc84172d 100644..100755 --- a/3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.png +++ b/3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.png diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/calendar.png b/3rdparty/Sabre/DAV/Browser/assets/icons/calendar.png Binary files differindex 3ecd6a800a0..3ecd6a800a0 100644..100755 --- a/3rdparty/Sabre/DAV/Browser/assets/icons/calendar.png +++ b/3rdparty/Sabre/DAV/Browser/assets/icons/calendar.png diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/card.png b/3rdparty/Sabre/DAV/Browser/assets/icons/card.png Binary files differindex 2ce954866d8..2ce954866d8 100644..100755 --- a/3rdparty/Sabre/DAV/Browser/assets/icons/card.png +++ b/3rdparty/Sabre/DAV/Browser/assets/icons/card.png diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/collection.png b/3rdparty/Sabre/DAV/Browser/assets/icons/collection.png Binary files differindex 156fa64fd50..156fa64fd50 100644..100755 --- a/3rdparty/Sabre/DAV/Browser/assets/icons/collection.png +++ b/3rdparty/Sabre/DAV/Browser/assets/icons/collection.png diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/file.png b/3rdparty/Sabre/DAV/Browser/assets/icons/file.png Binary files differindex 3b98551cec3..3b98551cec3 100644..100755 --- a/3rdparty/Sabre/DAV/Browser/assets/icons/file.png +++ b/3rdparty/Sabre/DAV/Browser/assets/icons/file.png diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/parent.png b/3rdparty/Sabre/DAV/Browser/assets/icons/parent.png Binary files differindex 156fa64fd50..156fa64fd50 100644..100755 --- a/3rdparty/Sabre/DAV/Browser/assets/icons/parent.png +++ b/3rdparty/Sabre/DAV/Browser/assets/icons/parent.png diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/principal.png b/3rdparty/Sabre/DAV/Browser/assets/icons/principal.png Binary files differindex f8988f828e6..f8988f828e6 100644..100755 --- a/3rdparty/Sabre/DAV/Browser/assets/icons/principal.png +++ b/3rdparty/Sabre/DAV/Browser/assets/icons/principal.png diff --git a/3rdparty/Sabre/DAV/Client.php b/3rdparty/Sabre/DAV/Client.php index 075e84caa1d..9a428765e90 100644..100755 --- a/3rdparty/Sabre/DAV/Client.php +++ b/3rdparty/Sabre/DAV/Client.php @@ -11,7 +11,7 @@ * @package Sabre * @subpackage DAVClient * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved. - * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @author Evert Pot (http://www.rooftopsolutions.nl/) * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License */ class Sabre_DAV_Client { @@ -24,6 +24,28 @@ class Sabre_DAV_Client { protected $proxy; /** + * Basic authentication + */ + const AUTH_BASIC = 1; + + /** + * Digest authentication + */ + const AUTH_DIGEST = 2; + + /** + * The authentication type we're using. + * + * This is a bitmask of AUTH_BASIC and AUTH_DIGEST. + * + * If DIGEST is used, the client makes 1 extra request per request, to get + * the authentication tokens. + * + * @var int + */ + protected $authType; + + /** * Constructor * * Settings are provided through the 'settings' argument. The following @@ -46,16 +68,21 @@ class Sabre_DAV_Client { 'baseUri', 'userName', 'password', - 'proxy' + 'proxy', ); - foreach($validSettings as $validSetting) { if (isset($settings[$validSetting])) { $this->$validSetting = $settings[$validSetting]; } } + if (isset($settings['authType'])) { + $this->authType = $settings['authType']; + } else { + $this->authType = self::AUTH_BASIC | self::AUTH_DIGEST; + } + $this->propertyMap['{DAV:}resourcetype'] = 'Sabre_DAV_Property_ResourceType'; } @@ -250,14 +277,9 @@ class Sabre_DAV_Client { // Automatically follow redirects CURLOPT_FOLLOWLOCATION => true, CURLOPT_MAXREDIRS => 5, - CURLOPT_SSL_VERIFYPEER => true, - //CURLOPT_SSL_VERIFYPEER => false, ); switch ($method) { - case 'PUT': - $curlSettings[CURLOPT_PUT] = true; - break; case 'HEAD' : // do not read body with HEAD requests (this is neccessary because cURL does not ignore the body with HEAD @@ -288,8 +310,15 @@ class Sabre_DAV_Client { $curlSettings[CURLOPT_PROXY] = $this->proxy; } - if ($this->userName) { - $curlSettings[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC | CURLAUTH_DIGEST; + if ($this->userName && $this->authType) { + $curlType = 0; + if ($this->authType & self::AUTH_BASIC) { + $curlType |= CURLAUTH_BASIC; + } + if ($this->authType & self::AUTH_DIGEST) { + $curlType |= CURLAUTH_DIGEST; + } + $curlSettings[CURLOPT_HTTPAUTH] = $curlType; $curlSettings[CURLOPT_USERPWD] = $this->userName . ':' . $this->password; } diff --git a/3rdparty/Sabre/DAV/Collection.php b/3rdparty/Sabre/DAV/Collection.php index 776c22531b2..776c22531b2 100644..100755 --- a/3rdparty/Sabre/DAV/Collection.php +++ b/3rdparty/Sabre/DAV/Collection.php diff --git a/3rdparty/Sabre/DAV/Directory.php b/3rdparty/Sabre/DAV/Directory.php index 6db8febc02e..6db8febc02e 100644..100755 --- a/3rdparty/Sabre/DAV/Directory.php +++ b/3rdparty/Sabre/DAV/Directory.php diff --git a/3rdparty/Sabre/DAV/Exception.php b/3rdparty/Sabre/DAV/Exception.php index a2cd6cf5820..a2cd6cf5820 100644..100755 --- a/3rdparty/Sabre/DAV/Exception.php +++ b/3rdparty/Sabre/DAV/Exception.php diff --git a/3rdparty/Sabre/DAV/Exception/BadRequest.php b/3rdparty/Sabre/DAV/Exception/BadRequest.php index b198648a754..b198648a754 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/BadRequest.php +++ b/3rdparty/Sabre/DAV/Exception/BadRequest.php diff --git a/3rdparty/Sabre/DAV/Exception/Conflict.php b/3rdparty/Sabre/DAV/Exception/Conflict.php index 6b0bd1fad73..6b0bd1fad73 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/Conflict.php +++ b/3rdparty/Sabre/DAV/Exception/Conflict.php diff --git a/3rdparty/Sabre/DAV/Exception/ConflictingLock.php b/3rdparty/Sabre/DAV/Exception/ConflictingLock.php index 6121868e69e..6121868e69e 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/ConflictingLock.php +++ b/3rdparty/Sabre/DAV/Exception/ConflictingLock.php diff --git a/3rdparty/Sabre/DAV/Exception/FileNotFound.php b/3rdparty/Sabre/DAV/Exception/FileNotFound.php index d76e400c93b..d76e400c93b 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/FileNotFound.php +++ b/3rdparty/Sabre/DAV/Exception/FileNotFound.php diff --git a/3rdparty/Sabre/DAV/Exception/Forbidden.php b/3rdparty/Sabre/DAV/Exception/Forbidden.php index 20b1056e31b..20b1056e31b 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/Forbidden.php +++ b/3rdparty/Sabre/DAV/Exception/Forbidden.php diff --git a/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php b/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php index 1a15089b0a3..1a15089b0a3 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php +++ b/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php diff --git a/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php b/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php index 2230f1d0811..2230f1d0811 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php +++ b/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php diff --git a/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php b/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php index 80ab7aff65a..80ab7aff65a 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php +++ b/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php diff --git a/3rdparty/Sabre/DAV/Exception/Locked.php b/3rdparty/Sabre/DAV/Exception/Locked.php index 976365ac1f8..976365ac1f8 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/Locked.php +++ b/3rdparty/Sabre/DAV/Exception/Locked.php diff --git a/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php b/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php index 31875751505..31875751505 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php +++ b/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php diff --git a/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php b/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php index 87ca624429f..87ca624429f 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php +++ b/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php diff --git a/3rdparty/Sabre/DAV/Exception/NotFound.php b/3rdparty/Sabre/DAV/Exception/NotFound.php index 2b9da560d23..2b9da560d23 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/NotFound.php +++ b/3rdparty/Sabre/DAV/Exception/NotFound.php diff --git a/3rdparty/Sabre/DAV/Exception/NotImplemented.php b/3rdparty/Sabre/DAV/Exception/NotImplemented.php index d017a19f559..d017a19f559 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/NotImplemented.php +++ b/3rdparty/Sabre/DAV/Exception/NotImplemented.php diff --git a/3rdparty/Sabre/DAV/Exception/PaymentRequired.php b/3rdparty/Sabre/DAV/Exception/PaymentRequired.php index 4982f45a4b5..4982f45a4b5 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/PaymentRequired.php +++ b/3rdparty/Sabre/DAV/Exception/PaymentRequired.php diff --git a/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php b/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php index 213e9c52317..213e9c52317 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php +++ b/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php diff --git a/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php b/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php index e86800f3038..e86800f3038 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php +++ b/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php diff --git a/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php b/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php index 29ee3654a7e..29ee3654a7e 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php +++ b/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php diff --git a/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php b/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php index 9a4693b21a8..9a4693b21a8 100644..100755 --- a/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php +++ b/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php diff --git a/3rdparty/Sabre/DAV/FS/Directory.php b/3rdparty/Sabre/DAV/FS/Directory.php index 3af2d755583..3af2d755583 100644..100755 --- a/3rdparty/Sabre/DAV/FS/Directory.php +++ b/3rdparty/Sabre/DAV/FS/Directory.php diff --git a/3rdparty/Sabre/DAV/FS/File.php b/3rdparty/Sabre/DAV/FS/File.php index 6a8039fe303..6a8039fe303 100644..100755 --- a/3rdparty/Sabre/DAV/FS/File.php +++ b/3rdparty/Sabre/DAV/FS/File.php diff --git a/3rdparty/Sabre/DAV/FS/Node.php b/3rdparty/Sabre/DAV/FS/Node.php index 1283e9d0fdc..1283e9d0fdc 100644..100755 --- a/3rdparty/Sabre/DAV/FS/Node.php +++ b/3rdparty/Sabre/DAV/FS/Node.php diff --git a/3rdparty/Sabre/DAV/FSExt/Directory.php b/3rdparty/Sabre/DAV/FSExt/Directory.php index 540057183b3..540057183b3 100644..100755 --- a/3rdparty/Sabre/DAV/FSExt/Directory.php +++ b/3rdparty/Sabre/DAV/FSExt/Directory.php diff --git a/3rdparty/Sabre/DAV/FSExt/File.php b/3rdparty/Sabre/DAV/FSExt/File.php index b93ce5aee21..b93ce5aee21 100644..100755 --- a/3rdparty/Sabre/DAV/FSExt/File.php +++ b/3rdparty/Sabre/DAV/FSExt/File.php diff --git a/3rdparty/Sabre/DAV/FSExt/Node.php b/3rdparty/Sabre/DAV/FSExt/Node.php index 68ca06beb7e..68ca06beb7e 100644..100755 --- a/3rdparty/Sabre/DAV/FSExt/Node.php +++ b/3rdparty/Sabre/DAV/FSExt/Node.php diff --git a/3rdparty/Sabre/DAV/File.php b/3rdparty/Sabre/DAV/File.php index 3126bd8d364..3126bd8d364 100644..100755 --- a/3rdparty/Sabre/DAV/File.php +++ b/3rdparty/Sabre/DAV/File.php diff --git a/3rdparty/Sabre/DAV/ICollection.php b/3rdparty/Sabre/DAV/ICollection.php index 4626038a66e..4626038a66e 100644..100755 --- a/3rdparty/Sabre/DAV/ICollection.php +++ b/3rdparty/Sabre/DAV/ICollection.php diff --git a/3rdparty/Sabre/DAV/IExtendedCollection.php b/3rdparty/Sabre/DAV/IExtendedCollection.php index 6ec345f9a62..6ec345f9a62 100644..100755 --- a/3rdparty/Sabre/DAV/IExtendedCollection.php +++ b/3rdparty/Sabre/DAV/IExtendedCollection.php diff --git a/3rdparty/Sabre/DAV/IFile.php b/3rdparty/Sabre/DAV/IFile.php index 478f822ae71..478f822ae71 100644..100755 --- a/3rdparty/Sabre/DAV/IFile.php +++ b/3rdparty/Sabre/DAV/IFile.php diff --git a/3rdparty/Sabre/DAV/INode.php b/3rdparty/Sabre/DAV/INode.php index c57d3923105..c57d3923105 100644..100755 --- a/3rdparty/Sabre/DAV/INode.php +++ b/3rdparty/Sabre/DAV/INode.php diff --git a/3rdparty/Sabre/DAV/IProperties.php b/3rdparty/Sabre/DAV/IProperties.php index 38eaab16dad..38eaab16dad 100644..100755 --- a/3rdparty/Sabre/DAV/IProperties.php +++ b/3rdparty/Sabre/DAV/IProperties.php diff --git a/3rdparty/Sabre/DAV/IQuota.php b/3rdparty/Sabre/DAV/IQuota.php index 3fe4c4eced4..3fe4c4eced4 100644..100755 --- a/3rdparty/Sabre/DAV/IQuota.php +++ b/3rdparty/Sabre/DAV/IQuota.php diff --git a/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php b/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php index 127e643a2b9..127e643a2b9 100644..100755 --- a/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php +++ b/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php diff --git a/3rdparty/Sabre/DAV/Locks/Backend/FS.php b/3rdparty/Sabre/DAV/Locks/Backend/FS.php index 02cab87fc82..02cab87fc82 100644..100755 --- a/3rdparty/Sabre/DAV/Locks/Backend/FS.php +++ b/3rdparty/Sabre/DAV/Locks/Backend/FS.php diff --git a/3rdparty/Sabre/DAV/Locks/Backend/File.php b/3rdparty/Sabre/DAV/Locks/Backend/File.php index c33f963514b..c33f963514b 100644..100755 --- a/3rdparty/Sabre/DAV/Locks/Backend/File.php +++ b/3rdparty/Sabre/DAV/Locks/Backend/File.php diff --git a/3rdparty/Sabre/DAV/Locks/Backend/PDO.php b/3rdparty/Sabre/DAV/Locks/Backend/PDO.php index acce80638ec..acce80638ec 100644..100755 --- a/3rdparty/Sabre/DAV/Locks/Backend/PDO.php +++ b/3rdparty/Sabre/DAV/Locks/Backend/PDO.php diff --git a/3rdparty/Sabre/DAV/Locks/LockInfo.php b/3rdparty/Sabre/DAV/Locks/LockInfo.php index 9df014a4281..9df014a4281 100644..100755 --- a/3rdparty/Sabre/DAV/Locks/LockInfo.php +++ b/3rdparty/Sabre/DAV/Locks/LockInfo.php diff --git a/3rdparty/Sabre/DAV/Locks/Plugin.php b/3rdparty/Sabre/DAV/Locks/Plugin.php index fd956950b8a..fd956950b8a 100644..100755 --- a/3rdparty/Sabre/DAV/Locks/Plugin.php +++ b/3rdparty/Sabre/DAV/Locks/Plugin.php diff --git a/3rdparty/Sabre/DAV/Mount/Plugin.php b/3rdparty/Sabre/DAV/Mount/Plugin.php index b37a90ae993..b37a90ae993 100644..100755 --- a/3rdparty/Sabre/DAV/Mount/Plugin.php +++ b/3rdparty/Sabre/DAV/Mount/Plugin.php diff --git a/3rdparty/Sabre/DAV/Node.php b/3rdparty/Sabre/DAV/Node.php index 070b7176afd..070b7176afd 100644..100755 --- a/3rdparty/Sabre/DAV/Node.php +++ b/3rdparty/Sabre/DAV/Node.php diff --git a/3rdparty/Sabre/DAV/ObjectTree.php b/3rdparty/Sabre/DAV/ObjectTree.php index bce51463900..bce51463900 100644..100755 --- a/3rdparty/Sabre/DAV/ObjectTree.php +++ b/3rdparty/Sabre/DAV/ObjectTree.php diff --git a/3rdparty/Sabre/DAV/Property.php b/3rdparty/Sabre/DAV/Property.php index 1cfada3236c..1cfada3236c 100644..100755 --- a/3rdparty/Sabre/DAV/Property.php +++ b/3rdparty/Sabre/DAV/Property.php diff --git a/3rdparty/Sabre/DAV/Property/GetLastModified.php b/3rdparty/Sabre/DAV/Property/GetLastModified.php index bd63f573140..bd63f573140 100644..100755 --- a/3rdparty/Sabre/DAV/Property/GetLastModified.php +++ b/3rdparty/Sabre/DAV/Property/GetLastModified.php diff --git a/3rdparty/Sabre/DAV/Property/Href.php b/3rdparty/Sabre/DAV/Property/Href.php index dac564f24d7..dac564f24d7 100644..100755 --- a/3rdparty/Sabre/DAV/Property/Href.php +++ b/3rdparty/Sabre/DAV/Property/Href.php diff --git a/3rdparty/Sabre/DAV/Property/HrefList.php b/3rdparty/Sabre/DAV/Property/HrefList.php index 7a52272e885..7a52272e885 100644..100755 --- a/3rdparty/Sabre/DAV/Property/HrefList.php +++ b/3rdparty/Sabre/DAV/Property/HrefList.php diff --git a/3rdparty/Sabre/DAV/Property/IHref.php b/3rdparty/Sabre/DAV/Property/IHref.php index 5c0409064cb..5c0409064cb 100644..100755 --- a/3rdparty/Sabre/DAV/Property/IHref.php +++ b/3rdparty/Sabre/DAV/Property/IHref.php diff --git a/3rdparty/Sabre/DAV/Property/LockDiscovery.php b/3rdparty/Sabre/DAV/Property/LockDiscovery.php index 2ded5649a44..2ded5649a44 100644..100755 --- a/3rdparty/Sabre/DAV/Property/LockDiscovery.php +++ b/3rdparty/Sabre/DAV/Property/LockDiscovery.php diff --git a/3rdparty/Sabre/DAV/Property/ResourceType.php b/3rdparty/Sabre/DAV/Property/ResourceType.php index f6269611e54..f6269611e54 100644..100755 --- a/3rdparty/Sabre/DAV/Property/ResourceType.php +++ b/3rdparty/Sabre/DAV/Property/ResourceType.php diff --git a/3rdparty/Sabre/DAV/Property/Response.php b/3rdparty/Sabre/DAV/Property/Response.php index 88afbcfb26d..88afbcfb26d 100644..100755 --- a/3rdparty/Sabre/DAV/Property/Response.php +++ b/3rdparty/Sabre/DAV/Property/Response.php diff --git a/3rdparty/Sabre/DAV/Property/ResponseList.php b/3rdparty/Sabre/DAV/Property/ResponseList.php index cae923afbf9..cae923afbf9 100644..100755 --- a/3rdparty/Sabre/DAV/Property/ResponseList.php +++ b/3rdparty/Sabre/DAV/Property/ResponseList.php diff --git a/3rdparty/Sabre/DAV/Property/SupportedLock.php b/3rdparty/Sabre/DAV/Property/SupportedLock.php index 4e3aaf23a1a..4e3aaf23a1a 100644..100755 --- a/3rdparty/Sabre/DAV/Property/SupportedLock.php +++ b/3rdparty/Sabre/DAV/Property/SupportedLock.php diff --git a/3rdparty/Sabre/DAV/Property/SupportedReportSet.php b/3rdparty/Sabre/DAV/Property/SupportedReportSet.php index e62699f3b5a..e62699f3b5a 100644..100755 --- a/3rdparty/Sabre/DAV/Property/SupportedReportSet.php +++ b/3rdparty/Sabre/DAV/Property/SupportedReportSet.php diff --git a/3rdparty/Sabre/DAV/Server.php b/3rdparty/Sabre/DAV/Server.php index 50b190e8fab..0dfac8b0c71 100644..100755 --- a/3rdparty/Sabre/DAV/Server.php +++ b/3rdparty/Sabre/DAV/Server.php @@ -215,7 +215,7 @@ class Sabre_DAV_Server { $DOM->appendChild($error); $error->appendChild($DOM->createElement('s:exception',get_class($e))); - $error->appendChild($DOM->createElement('s:message',htmlentities($e->getMessage()))); + $error->appendChild($DOM->createElement('s:message',$e->getMessage())); if ($this->debugExceptions) { $error->appendChild($DOM->createElement('s:file',$e->getFile())); $error->appendChild($DOM->createElement('s:line',$e->getLine())); @@ -1784,7 +1784,14 @@ class Sabre_DAV_Server { $etag = $node->getETag(); if ($etag===$ifMatchItem) { $haveMatch = true; + } else { + // Evolution has a bug where it sometimes prepends the " + // with a \. This is our workaround. + if (str_replace('\\"','"', $ifMatchItem) === $etag) { + $haveMatch = true; + } } + } if (!$haveMatch) { throw new Sabre_DAV_Exception_PreconditionFailed('An If-Match header was specified, but none of the specified the ETags matched.','If-Match'); diff --git a/3rdparty/Sabre/DAV/ServerPlugin.php b/3rdparty/Sabre/DAV/ServerPlugin.php index 131863d13fb..131863d13fb 100644..100755 --- a/3rdparty/Sabre/DAV/ServerPlugin.php +++ b/3rdparty/Sabre/DAV/ServerPlugin.php diff --git a/3rdparty/Sabre/DAV/SimpleCollection.php b/3rdparty/Sabre/DAV/SimpleCollection.php index 4acf971caa5..4acf971caa5 100644..100755 --- a/3rdparty/Sabre/DAV/SimpleCollection.php +++ b/3rdparty/Sabre/DAV/SimpleCollection.php diff --git a/3rdparty/Sabre/DAV/SimpleDirectory.php b/3rdparty/Sabre/DAV/SimpleDirectory.php index 621222ebc53..621222ebc53 100644..100755 --- a/3rdparty/Sabre/DAV/SimpleDirectory.php +++ b/3rdparty/Sabre/DAV/SimpleDirectory.php diff --git a/3rdparty/Sabre/DAV/SimpleFile.php b/3rdparty/Sabre/DAV/SimpleFile.php index 58330d6861d..58330d6861d 100644..100755 --- a/3rdparty/Sabre/DAV/SimpleFile.php +++ b/3rdparty/Sabre/DAV/SimpleFile.php diff --git a/3rdparty/Sabre/DAV/StringUtil.php b/3rdparty/Sabre/DAV/StringUtil.php index b126a94c825..b126a94c825 100644..100755 --- a/3rdparty/Sabre/DAV/StringUtil.php +++ b/3rdparty/Sabre/DAV/StringUtil.php diff --git a/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php b/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php index 36096e67775..36096e67775 100644..100755 --- a/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php +++ b/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php diff --git a/3rdparty/Sabre/DAV/Tree.php b/3rdparty/Sabre/DAV/Tree.php index 50216394155..50216394155 100644..100755 --- a/3rdparty/Sabre/DAV/Tree.php +++ b/3rdparty/Sabre/DAV/Tree.php diff --git a/3rdparty/Sabre/DAV/Tree/Filesystem.php b/3rdparty/Sabre/DAV/Tree/Filesystem.php index 85a9ee317be..40580ae366f 100644..100755 --- a/3rdparty/Sabre/DAV/Tree/Filesystem.php +++ b/3rdparty/Sabre/DAV/Tree/Filesystem.php @@ -42,9 +42,9 @@ class Sabre_DAV_Tree_Filesystem extends Sabre_DAV_Tree { $realPath = $this->getRealPath($path); if (!file_exists($realPath)) throw new Sabre_DAV_Exception_NotFound('File at location ' . $realPath . ' not found'); if (is_dir($realPath)) { - return new Sabre_DAV_FS_Directory($path); + return new Sabre_DAV_FS_Directory($realPath); } else { - return new Sabre_DAV_FS_File($path); + return new Sabre_DAV_FS_File($realPath); } } diff --git a/3rdparty/Sabre/DAV/URLUtil.php b/3rdparty/Sabre/DAV/URLUtil.php index 794665a44f6..794665a44f6 100644..100755 --- a/3rdparty/Sabre/DAV/URLUtil.php +++ b/3rdparty/Sabre/DAV/URLUtil.php diff --git a/3rdparty/Sabre/DAV/UUIDUtil.php b/3rdparty/Sabre/DAV/UUIDUtil.php index f0eebe598e5..f0eebe598e5 100644..100755 --- a/3rdparty/Sabre/DAV/UUIDUtil.php +++ b/3rdparty/Sabre/DAV/UUIDUtil.php diff --git a/3rdparty/Sabre/DAV/Version.php b/3rdparty/Sabre/DAV/Version.php index 5e5d15e4039..40cfe81b34f 100644..100755 --- a/3rdparty/Sabre/DAV/Version.php +++ b/3rdparty/Sabre/DAV/Version.php @@ -14,7 +14,7 @@ class Sabre_DAV_Version { /** * Full version number */ - const VERSION = '1.6.2'; + const VERSION = '1.6.3'; /** * Stability : alpha, beta, stable diff --git a/3rdparty/Sabre/DAV/XMLUtil.php b/3rdparty/Sabre/DAV/XMLUtil.php index 60eff3b159a..60eff3b159a 100644..100755 --- a/3rdparty/Sabre/DAV/XMLUtil.php +++ b/3rdparty/Sabre/DAV/XMLUtil.php diff --git a/3rdparty/Sabre/DAV/includes.php b/3rdparty/Sabre/DAV/includes.php index 6a4890677ea..6a4890677ea 100644..100755 --- a/3rdparty/Sabre/DAV/includes.php +++ b/3rdparty/Sabre/DAV/includes.php diff --git a/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php b/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php index e05b7749805..e05b7749805 100644..100755 --- a/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php +++ b/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php diff --git a/3rdparty/Sabre/DAVACL/Exception/AceConflict.php b/3rdparty/Sabre/DAVACL/Exception/AceConflict.php index 4b9f93b0036..4b9f93b0036 100644..100755 --- a/3rdparty/Sabre/DAVACL/Exception/AceConflict.php +++ b/3rdparty/Sabre/DAVACL/Exception/AceConflict.php diff --git a/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php b/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php index 9b055dd9709..9b055dd9709 100644..100755 --- a/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php +++ b/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php diff --git a/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php b/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php index f44e3e32281..f44e3e32281 100644..100755 --- a/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php +++ b/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php diff --git a/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php b/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php index 8d1e38ca1b4..8d1e38ca1b4 100644..100755 --- a/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php +++ b/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php diff --git a/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php b/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php index 3b5d012d7fa..3b5d012d7fa 100644..100755 --- a/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php +++ b/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php diff --git a/3rdparty/Sabre/DAVACL/IACL.php b/3rdparty/Sabre/DAVACL/IACL.php index 003e6993483..003e6993483 100644..100755 --- a/3rdparty/Sabre/DAVACL/IACL.php +++ b/3rdparty/Sabre/DAVACL/IACL.php diff --git a/3rdparty/Sabre/DAVACL/IPrincipal.php b/3rdparty/Sabre/DAVACL/IPrincipal.php index fc7605bf625..fc7605bf625 100644..100755 --- a/3rdparty/Sabre/DAVACL/IPrincipal.php +++ b/3rdparty/Sabre/DAVACL/IPrincipal.php diff --git a/3rdparty/Sabre/DAVACL/IPrincipalBackend.php b/3rdparty/Sabre/DAVACL/IPrincipalBackend.php index e798bf890c0..e798bf890c0 100644..100755 --- a/3rdparty/Sabre/DAVACL/IPrincipalBackend.php +++ b/3rdparty/Sabre/DAVACL/IPrincipalBackend.php diff --git a/3rdparty/Sabre/DAVACL/Plugin.php b/3rdparty/Sabre/DAVACL/Plugin.php index 5c828c6d97b..5c828c6d97b 100644..100755 --- a/3rdparty/Sabre/DAVACL/Plugin.php +++ b/3rdparty/Sabre/DAVACL/Plugin.php diff --git a/3rdparty/Sabre/DAVACL/Principal.php b/3rdparty/Sabre/DAVACL/Principal.php index 51c6658afd6..51c6658afd6 100644..100755 --- a/3rdparty/Sabre/DAVACL/Principal.php +++ b/3rdparty/Sabre/DAVACL/Principal.php diff --git a/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php b/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php index a76b4a9d727..a76b4a9d727 100644..100755 --- a/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php +++ b/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php diff --git a/3rdparty/Sabre/DAVACL/PrincipalCollection.php b/3rdparty/Sabre/DAVACL/PrincipalCollection.php index c3e4cb83f23..c3e4cb83f23 100644..100755 --- a/3rdparty/Sabre/DAVACL/PrincipalCollection.php +++ b/3rdparty/Sabre/DAVACL/PrincipalCollection.php diff --git a/3rdparty/Sabre/DAVACL/Property/Acl.php b/3rdparty/Sabre/DAVACL/Property/Acl.php index 05e1a690b3c..05e1a690b3c 100644..100755 --- a/3rdparty/Sabre/DAVACL/Property/Acl.php +++ b/3rdparty/Sabre/DAVACL/Property/Acl.php diff --git a/3rdparty/Sabre/DAVACL/Property/AclRestrictions.php b/3rdparty/Sabre/DAVACL/Property/AclRestrictions.php index a8b054956dd..a8b054956dd 100644..100755 --- a/3rdparty/Sabre/DAVACL/Property/AclRestrictions.php +++ b/3rdparty/Sabre/DAVACL/Property/AclRestrictions.php diff --git a/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php b/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php index 94a29640615..94a29640615 100644..100755 --- a/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php +++ b/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php diff --git a/3rdparty/Sabre/DAVACL/Property/Principal.php b/3rdparty/Sabre/DAVACL/Property/Principal.php index c36328a58e0..c36328a58e0 100644..100755 --- a/3rdparty/Sabre/DAVACL/Property/Principal.php +++ b/3rdparty/Sabre/DAVACL/Property/Principal.php diff --git a/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php b/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php index 276d57ae093..276d57ae093 100644..100755 --- a/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php +++ b/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php diff --git a/3rdparty/Sabre/DAVACL/Version.php b/3rdparty/Sabre/DAVACL/Version.php index 9950f748741..9950f748741 100644..100755 --- a/3rdparty/Sabre/DAVACL/Version.php +++ b/3rdparty/Sabre/DAVACL/Version.php diff --git a/3rdparty/Sabre/DAVACL/includes.php b/3rdparty/Sabre/DAVACL/includes.php index 28fa3eed225..28fa3eed225 100644..100755 --- a/3rdparty/Sabre/DAVACL/includes.php +++ b/3rdparty/Sabre/DAVACL/includes.php diff --git a/3rdparty/Sabre/HTTP/AWSAuth.php b/3rdparty/Sabre/HTTP/AWSAuth.php index fb8245c8cbf..fb8245c8cbf 100644..100755 --- a/3rdparty/Sabre/HTTP/AWSAuth.php +++ b/3rdparty/Sabre/HTTP/AWSAuth.php diff --git a/3rdparty/Sabre/HTTP/AbstractAuth.php b/3rdparty/Sabre/HTTP/AbstractAuth.php index 3bccabcd1c1..3bccabcd1c1 100644..100755 --- a/3rdparty/Sabre/HTTP/AbstractAuth.php +++ b/3rdparty/Sabre/HTTP/AbstractAuth.php diff --git a/3rdparty/Sabre/HTTP/BasicAuth.php b/3rdparty/Sabre/HTTP/BasicAuth.php index a747cc6a31b..a747cc6a31b 100644..100755 --- a/3rdparty/Sabre/HTTP/BasicAuth.php +++ b/3rdparty/Sabre/HTTP/BasicAuth.php diff --git a/3rdparty/Sabre/HTTP/DigestAuth.php b/3rdparty/Sabre/HTTP/DigestAuth.php index ee7f05c08ed..ee7f05c08ed 100644..100755 --- a/3rdparty/Sabre/HTTP/DigestAuth.php +++ b/3rdparty/Sabre/HTTP/DigestAuth.php diff --git a/3rdparty/Sabre/HTTP/Request.php b/3rdparty/Sabre/HTTP/Request.php index 4746ef77704..4746ef77704 100644..100755 --- a/3rdparty/Sabre/HTTP/Request.php +++ b/3rdparty/Sabre/HTTP/Request.php diff --git a/3rdparty/Sabre/HTTP/Response.php b/3rdparty/Sabre/HTTP/Response.php index ffe9bda2082..ffe9bda2082 100644..100755 --- a/3rdparty/Sabre/HTTP/Response.php +++ b/3rdparty/Sabre/HTTP/Response.php diff --git a/3rdparty/Sabre/HTTP/Util.php b/3rdparty/Sabre/HTTP/Util.php index 67bdd489e1e..67bdd489e1e 100644..100755 --- a/3rdparty/Sabre/HTTP/Util.php +++ b/3rdparty/Sabre/HTTP/Util.php diff --git a/3rdparty/Sabre/HTTP/Version.php b/3rdparty/Sabre/HTTP/Version.php index 23dc7f8a7a1..23dc7f8a7a1 100644..100755 --- a/3rdparty/Sabre/HTTP/Version.php +++ b/3rdparty/Sabre/HTTP/Version.php diff --git a/3rdparty/Sabre/HTTP/includes.php b/3rdparty/Sabre/HTTP/includes.php index 9d34bf3a8be..9d34bf3a8be 100644..100755 --- a/3rdparty/Sabre/HTTP/includes.php +++ b/3rdparty/Sabre/HTTP/includes.php diff --git a/3rdparty/Sabre/VObject/Component.php b/3rdparty/Sabre/VObject/Component.php index b78a26133fa..b78a26133fa 100644..100755 --- a/3rdparty/Sabre/VObject/Component.php +++ b/3rdparty/Sabre/VObject/Component.php diff --git a/3rdparty/Sabre/VObject/Component/VAlarm.php b/3rdparty/Sabre/VObject/Component/VAlarm.php index ebb4a9b18f6..ebb4a9b18f6 100644..100755 --- a/3rdparty/Sabre/VObject/Component/VAlarm.php +++ b/3rdparty/Sabre/VObject/Component/VAlarm.php diff --git a/3rdparty/Sabre/VObject/Component/VCalendar.php b/3rdparty/Sabre/VObject/Component/VCalendar.php index f3be29afdbb..f3be29afdbb 100644..100755 --- a/3rdparty/Sabre/VObject/Component/VCalendar.php +++ b/3rdparty/Sabre/VObject/Component/VCalendar.php diff --git a/3rdparty/Sabre/VObject/Component/VEvent.php b/3rdparty/Sabre/VObject/Component/VEvent.php index 4cc1e36d7d6..4cc1e36d7d6 100644..100755 --- a/3rdparty/Sabre/VObject/Component/VEvent.php +++ b/3rdparty/Sabre/VObject/Component/VEvent.php diff --git a/3rdparty/Sabre/VObject/Component/VJournal.php b/3rdparty/Sabre/VObject/Component/VJournal.php index 22b3ec921e5..22b3ec921e5 100644..100755 --- a/3rdparty/Sabre/VObject/Component/VJournal.php +++ b/3rdparty/Sabre/VObject/Component/VJournal.php diff --git a/3rdparty/Sabre/VObject/Component/VTodo.php b/3rdparty/Sabre/VObject/Component/VTodo.php index 79d06298d7f..79d06298d7f 100644..100755 --- a/3rdparty/Sabre/VObject/Component/VTodo.php +++ b/3rdparty/Sabre/VObject/Component/VTodo.php diff --git a/3rdparty/Sabre/VObject/DateTimeParser.php b/3rdparty/Sabre/VObject/DateTimeParser.php index 1e2d54ef3a9..23a4bb69916 100644..100755 --- a/3rdparty/Sabre/VObject/DateTimeParser.php +++ b/3rdparty/Sabre/VObject/DateTimeParser.php @@ -125,6 +125,9 @@ class Sabre_VObject_DateTimeParser { } + if ($duration==='P') { + $duration = 'PT0S'; + } $iv = new DateInterval($duration); if ($invert) $iv->invert = true; @@ -150,6 +153,7 @@ class Sabre_VObject_DateTimeParser { } $newDur = ($matches['plusminus']==='-'?'-':'+') . trim($newDur); + if ($newDur === '+') { $newDur = '+0 seconds'; }; return $newDur; } diff --git a/3rdparty/Sabre/VObject/Element.php b/3rdparty/Sabre/VObject/Element.php index e20ff0b353c..e20ff0b353c 100644..100755 --- a/3rdparty/Sabre/VObject/Element.php +++ b/3rdparty/Sabre/VObject/Element.php diff --git a/3rdparty/Sabre/VObject/Element/DateTime.php b/3rdparty/Sabre/VObject/Element/DateTime.php index 5e5eb7ab6f2..5e5eb7ab6f2 100644..100755 --- a/3rdparty/Sabre/VObject/Element/DateTime.php +++ b/3rdparty/Sabre/VObject/Element/DateTime.php diff --git a/3rdparty/Sabre/VObject/Element/MultiDateTime.php b/3rdparty/Sabre/VObject/Element/MultiDateTime.php index 8a12ced94a8..8a12ced94a8 100644..100755 --- a/3rdparty/Sabre/VObject/Element/MultiDateTime.php +++ b/3rdparty/Sabre/VObject/Element/MultiDateTime.php diff --git a/3rdparty/Sabre/VObject/ElementList.php b/3rdparty/Sabre/VObject/ElementList.php index 7e508db20f0..7e508db20f0 100644..100755 --- a/3rdparty/Sabre/VObject/ElementList.php +++ b/3rdparty/Sabre/VObject/ElementList.php diff --git a/3rdparty/Sabre/VObject/FreeBusyGenerator.php b/3rdparty/Sabre/VObject/FreeBusyGenerator.php index 1c96a64a004..1c96a64a004 100644..100755 --- a/3rdparty/Sabre/VObject/FreeBusyGenerator.php +++ b/3rdparty/Sabre/VObject/FreeBusyGenerator.php diff --git a/3rdparty/Sabre/VObject/Node.php b/3rdparty/Sabre/VObject/Node.php index d89e01b56c6..d89e01b56c6 100644..100755 --- a/3rdparty/Sabre/VObject/Node.php +++ b/3rdparty/Sabre/VObject/Node.php diff --git a/3rdparty/Sabre/VObject/Parameter.php b/3rdparty/Sabre/VObject/Parameter.php index 2e39af5f78a..2e39af5f78a 100644..100755 --- a/3rdparty/Sabre/VObject/Parameter.php +++ b/3rdparty/Sabre/VObject/Parameter.php diff --git a/3rdparty/Sabre/VObject/ParseException.php b/3rdparty/Sabre/VObject/ParseException.php index 1b5e95bf16e..1b5e95bf16e 100644..100755 --- a/3rdparty/Sabre/VObject/ParseException.php +++ b/3rdparty/Sabre/VObject/ParseException.php diff --git a/3rdparty/Sabre/VObject/Property.php b/3rdparty/Sabre/VObject/Property.php index ce74fe3865b..ce74fe3865b 100644..100755 --- a/3rdparty/Sabre/VObject/Property.php +++ b/3rdparty/Sabre/VObject/Property.php diff --git a/3rdparty/Sabre/VObject/Property/DateTime.php b/3rdparty/Sabre/VObject/Property/DateTime.php index fe2372caa81..fe2372caa81 100644..100755 --- a/3rdparty/Sabre/VObject/Property/DateTime.php +++ b/3rdparty/Sabre/VObject/Property/DateTime.php diff --git a/3rdparty/Sabre/VObject/Property/MultiDateTime.php b/3rdparty/Sabre/VObject/Property/MultiDateTime.php index ae53ab6a617..ae53ab6a617 100644..100755 --- a/3rdparty/Sabre/VObject/Property/MultiDateTime.php +++ b/3rdparty/Sabre/VObject/Property/MultiDateTime.php diff --git a/3rdparty/Sabre/VObject/Reader.php b/3rdparty/Sabre/VObject/Reader.php index eea73fa3dce..eea73fa3dce 100644..100755 --- a/3rdparty/Sabre/VObject/Reader.php +++ b/3rdparty/Sabre/VObject/Reader.php diff --git a/3rdparty/Sabre/VObject/RecurrenceIterator.php b/3rdparty/Sabre/VObject/RecurrenceIterator.php index 833aa091ab7..833aa091ab7 100644..100755 --- a/3rdparty/Sabre/VObject/RecurrenceIterator.php +++ b/3rdparty/Sabre/VObject/RecurrenceIterator.php diff --git a/3rdparty/Sabre/VObject/Version.php b/3rdparty/Sabre/VObject/Version.php index 00110febc07..2617c7b129d 100644..100755 --- a/3rdparty/Sabre/VObject/Version.php +++ b/3rdparty/Sabre/VObject/Version.php @@ -14,7 +14,7 @@ class Sabre_VObject_Version { /** * Full version number */ - const VERSION = '1.3.2'; + const VERSION = '1.3.3'; /** * Stability : alpha, beta, stable diff --git a/3rdparty/Sabre/VObject/WindowsTimezoneMap.php b/3rdparty/Sabre/VObject/WindowsTimezoneMap.php index 5e1cc5d479b..5e1cc5d479b 100644..100755 --- a/3rdparty/Sabre/VObject/WindowsTimezoneMap.php +++ b/3rdparty/Sabre/VObject/WindowsTimezoneMap.php diff --git a/3rdparty/Sabre/VObject/includes.php b/3rdparty/Sabre/VObject/includes.php index 0177a8f1ba6..0177a8f1ba6 100644..100755 --- a/3rdparty/Sabre/VObject/includes.php +++ b/3rdparty/Sabre/VObject/includes.php diff --git a/3rdparty/Sabre/autoload.php b/3rdparty/Sabre/autoload.php index c7b537d83d3..c7b537d83d3 100644..100755 --- a/3rdparty/Sabre/autoload.php +++ b/3rdparty/Sabre/autoload.php diff --git a/3rdparty/Symfony/Component/Routing b/3rdparty/Symfony/Component/Routing new file mode 160000 +Subproject d72483890880a987afa679503af096d2aaf7d2e diff --git a/3rdparty/miniColors/GPL-LICENSE.txt b/3rdparty/miniColors/GPL-LICENSE.txt new file mode 100644 index 00000000000..11dddd00ef0 --- /dev/null +++ b/3rdparty/miniColors/GPL-LICENSE.txt @@ -0,0 +1,278 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. diff --git a/3rdparty/miniColors/MIT-LICENSE.txt b/3rdparty/miniColors/MIT-LICENSE.txt new file mode 100644 index 00000000000..ec6f7581576 --- /dev/null +++ b/3rdparty/miniColors/MIT-LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) Cory LaViska + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/3rdparty/miniColors/css/images/colors.png b/3rdparty/miniColors/css/images/colors.png Binary files differnew file mode 100755 index 00000000000..1b4f819d8d9 --- /dev/null +++ b/3rdparty/miniColors/css/images/colors.png diff --git a/3rdparty/miniColors/css/images/trigger.png b/3rdparty/miniColors/css/images/trigger.png Binary files differnew file mode 100755 index 00000000000..8c169fd6053 --- /dev/null +++ b/3rdparty/miniColors/css/images/trigger.png diff --git a/3rdparty/miniColors/css/jquery.miniColors.css b/3rdparty/miniColors/css/jquery.miniColors.css new file mode 100755 index 00000000000..381bc1dc065 --- /dev/null +++ b/3rdparty/miniColors/css/jquery.miniColors.css @@ -0,0 +1,81 @@ +.miniColors-trigger { + height: 22px; + width: 22px; + background: url(images/trigger.png) center no-repeat; + vertical-align: middle; + margin: 0 .25em; + display: inline-block; + outline: none; +} + +.miniColors-selector { + position: absolute; + width: 175px; + height: 150px; + background: #FFF; + border: solid 1px #BBB; + -moz-box-shadow: 0 0 6px rgba(0, 0, 0, .25); + -webkit-box-shadow: 0 0 6px rgba(0, 0, 0, .25); + box-shadow: 0 0 6px rgba(0, 0, 0, .25); + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + padding: 5px; + z-index: 999999; +} + +.miniColors-selector.black { + background: #000; + border-color: #000; +} + +.miniColors-colors { + position: absolute; + top: 5px; + left: 5px; + width: 150px; + height: 150px; + background: url(images/colors.png) right no-repeat; + cursor: crosshair; +} + +.miniColors-hues { + position: absolute; + top: 5px; + left: 160px; + width: 20px; + height: 150px; + background: url(images/colors.png) left no-repeat; + cursor: crosshair; +} + +.miniColors-colorPicker { + position: absolute; + width: 9px; + height: 9px; + border: 1px solid #fff; + -moz-border-radius: 11px; + -webkit-border-radius: 11px; + border-radius: 11px; +} +.miniColors-colorPicker-inner { + position: absolute; + top: 0; + left: 0; + width: 7px; + height: 7px; + border: 1px solid #000; + -moz-border-radius: 9px; + -webkit-border-radius: 9px; + border-radius: 9px; +} + +.miniColors-huePicker { + position: absolute; + left: -3px; + width: 24px; + height: 1px; + border: 1px solid #fff; + border-radius: 2px; + background: #000; +}
\ No newline at end of file diff --git a/3rdparty/miniColors/js/jquery.miniColors.js b/3rdparty/miniColors/js/jquery.miniColors.js new file mode 100755 index 00000000000..187db3fa84e --- /dev/null +++ b/3rdparty/miniColors/js/jquery.miniColors.js @@ -0,0 +1,580 @@ +/* + * jQuery miniColors: A small color selector + * + * Copyright 2011 Cory LaViska for A Beautiful Site, LLC. (http://abeautifulsite.net/) + * + * Dual licensed under the MIT or GPL Version 2 licenses + * +*/ +if(jQuery) (function($) { + + $.extend($.fn, { + + miniColors: function(o, data) { + + var create = function(input, o, data) { + // + // Creates a new instance of the miniColors selector + // + + // Determine initial color (defaults to white) + var color = expandHex(input.val()); + if( !color ) color = 'ffffff'; + var hsb = hex2hsb(color); + + // Create trigger + var trigger = $('<a class="miniColors-trigger" style="background-color: #' + color + '" href="#"></a>'); + trigger.insertAfter(input); + + // Set input data and update attributes + input + .addClass('miniColors') + .data('original-maxlength', input.attr('maxlength') || null) + .data('original-autocomplete', input.attr('autocomplete') || null) + .data('letterCase', 'uppercase') + .data('trigger', trigger) + .data('hsb', hsb) + .data('change', o.change ? o.change : null) + .data('close', o.close ? o.close : null) + .data('open', o.open ? o.open : null) + .attr('maxlength', 7) + .attr('autocomplete', 'off') + .val('#' + convertCase(color, o.letterCase)); + + // Handle options + if( o.readonly ) input.prop('readonly', true); + if( o.disabled ) disable(input); + + // Show selector when trigger is clicked + trigger.bind('click.miniColors', function(event) { + event.preventDefault(); + if( input.val() === '' ) input.val('#'); + show(input); + + }); + + // Show selector when input receives focus + input.bind('focus.miniColors', function(event) { + if( input.val() === '' ) input.val('#'); + show(input); + }); + + // Hide on blur + input.bind('blur.miniColors', function(event) { + var hex = expandHex( hsb2hex(input.data('hsb')) ); + input.val( hex ? '#' + convertCase(hex, input.data('letterCase')) : '' ); + }); + + // Hide when tabbing out of the input + input.bind('keydown.miniColors', function(event) { + if( event.keyCode === 9 ) hide(input); + }); + + // Update when color is typed in + input.bind('keyup.miniColors', function(event) { + setColorFromInput(input); + }); + + // Handle pasting + input.bind('paste.miniColors', function(event) { + // Short pause to wait for paste to complete + setTimeout( function() { + setColorFromInput(input); + }, 5); + }); + + }; + + var destroy = function(input) { + // + // Destroys an active instance of the miniColors selector + // + + hide(); + input = $(input); + + // Restore to original state + input.data('trigger').remove(); + input + .attr('autocomplete', input.data('original-autocomplete')) + .attr('maxlength', input.data('original-maxlength')) + .removeData() + .removeClass('miniColors') + .unbind('.miniColors'); + $(document).unbind('.miniColors'); + }; + + var enable = function(input) { + // + // Enables the input control and the selector + // + input + .prop('disabled', false) + .data('trigger') + .css('opacity', 1); + }; + + var disable = function(input) { + // + // Disables the input control and the selector + // + hide(input); + input + .prop('disabled', true) + .data('trigger') + .css('opacity', 0.5); + }; + + var show = function(input) { + // + // Shows the miniColors selector + // + if( input.prop('disabled') ) return false; + + // Hide all other instances + hide(); + + // Generate the selector + var selector = $('<div class="miniColors-selector"></div>'); + selector + .append('<div class="miniColors-colors" style="background-color: #FFF;"><div class="miniColors-colorPicker"><div class="miniColors-colorPicker-inner"></div></div>') + .append('<div class="miniColors-hues"><div class="miniColors-huePicker"></div></div>') + .css({ + top: input.is(':visible') ? input.offset().top + input.outerHeight() : input.data('trigger').offset().top + input.data('trigger').outerHeight(), + left: input.is(':visible') ? input.offset().left : input.data('trigger').offset().left, + display: 'none' + }) + .addClass( input.attr('class') ); + + // Set background for colors + var hsb = input.data('hsb'); + selector + .find('.miniColors-colors') + .css('backgroundColor', '#' + hsb2hex({ h: hsb.h, s: 100, b: 100 })); + + // Set colorPicker position + var colorPosition = input.data('colorPosition'); + if( !colorPosition ) colorPosition = getColorPositionFromHSB(hsb); + selector.find('.miniColors-colorPicker') + .css('top', colorPosition.y + 'px') + .css('left', colorPosition.x + 'px'); + + // Set huePicker position + var huePosition = input.data('huePosition'); + if( !huePosition ) huePosition = getHuePositionFromHSB(hsb); + selector.find('.miniColors-huePicker').css('top', huePosition.y + 'px'); + + // Set input data + input + .data('selector', selector) + .data('huePicker', selector.find('.miniColors-huePicker')) + .data('colorPicker', selector.find('.miniColors-colorPicker')) + .data('mousebutton', 0); + + $('BODY').append(selector); + selector.fadeIn(100); + + // Prevent text selection in IE + selector.bind('selectstart', function() { return false; }); + + $(document).bind('mousedown.miniColors touchstart.miniColors', function(event) { + + input.data('mousebutton', 1); + var testSubject = $(event.target).parents().andSelf(); + + if( testSubject.hasClass('miniColors-colors') ) { + event.preventDefault(); + input.data('moving', 'colors'); + moveColor(input, event); + } + + if( testSubject.hasClass('miniColors-hues') ) { + event.preventDefault(); + input.data('moving', 'hues'); + moveHue(input, event); + } + + if( testSubject.hasClass('miniColors-selector') ) { + event.preventDefault(); + return; + } + + if( testSubject.hasClass('miniColors') ) return; + + hide(input); + }); + + $(document) + .bind('mouseup.miniColors touchend.miniColors', function(event) { + event.preventDefault(); + input.data('mousebutton', 0).removeData('moving'); + }) + .bind('mousemove.miniColors touchmove.miniColors', function(event) { + event.preventDefault(); + if( input.data('mousebutton') === 1 ) { + if( input.data('moving') === 'colors' ) moveColor(input, event); + if( input.data('moving') === 'hues' ) moveHue(input, event); + } + }); + + // Fire open callback + if( input.data('open') ) { + input.data('open').call(input.get(0), '#' + hsb2hex(hsb), hsb2rgb(hsb)); + } + + }; + + var hide = function(input) { + + // + // Hides one or more miniColors selectors + // + + // Hide all other instances if input isn't specified + if( !input ) input = '.miniColors'; + + $(input).each( function() { + var selector = $(this).data('selector'); + $(this).removeData('selector'); + $(selector).fadeOut(100, function() { + // Fire close callback + if( input.data('close') ) { + var hsb = input.data('hsb'), hex = hsb2hex(hsb); + input.data('close').call(input.get(0), '#' + hex, hsb2rgb(hsb)); + } + $(this).remove(); + }); + }); + + $(document).unbind('.miniColors'); + + }; + + var moveColor = function(input, event) { + + var colorPicker = input.data('colorPicker'); + + colorPicker.hide(); + + var position = { + x: event.pageX, + y: event.pageY + }; + + // Touch support + if( event.originalEvent.changedTouches ) { + position.x = event.originalEvent.changedTouches[0].pageX; + position.y = event.originalEvent.changedTouches[0].pageY; + } + position.x = position.x - input.data('selector').find('.miniColors-colors').offset().left - 5; + position.y = position.y - input.data('selector').find('.miniColors-colors').offset().top - 5; + if( position.x <= -5 ) position.x = -5; + if( position.x >= 144 ) position.x = 144; + if( position.y <= -5 ) position.y = -5; + if( position.y >= 144 ) position.y = 144; + + input.data('colorPosition', position); + colorPicker.css('left', position.x).css('top', position.y).show(); + + // Calculate saturation + var s = Math.round((position.x + 5) * 0.67); + if( s < 0 ) s = 0; + if( s > 100 ) s = 100; + + // Calculate brightness + var b = 100 - Math.round((position.y + 5) * 0.67); + if( b < 0 ) b = 0; + if( b > 100 ) b = 100; + + // Update HSB values + var hsb = input.data('hsb'); + hsb.s = s; + hsb.b = b; + + // Set color + setColor(input, hsb, true); + }; + + var moveHue = function(input, event) { + + var huePicker = input.data('huePicker'); + + huePicker.hide(); + + var position = { + y: event.pageY + }; + + // Touch support + if( event.originalEvent.changedTouches ) { + position.y = event.originalEvent.changedTouches[0].pageY; + } + + position.y = position.y - input.data('selector').find('.miniColors-colors').offset().top - 1; + if( position.y <= -1 ) position.y = -1; + if( position.y >= 149 ) position.y = 149; + input.data('huePosition', position); + huePicker.css('top', position.y).show(); + + // Calculate hue + var h = Math.round((150 - position.y - 1) * 2.4); + if( h < 0 ) h = 0; + if( h > 360 ) h = 360; + + // Update HSB values + var hsb = input.data('hsb'); + hsb.h = h; + + // Set color + setColor(input, hsb, true); + + }; + + var setColor = function(input, hsb, updateInput) { + input.data('hsb', hsb); + var hex = hsb2hex(hsb); + if( updateInput ) input.val( '#' + convertCase(hex, input.data('letterCase')) ); + input.data('trigger').css('backgroundColor', '#' + hex); + if( input.data('selector') ) input.data('selector').find('.miniColors-colors').css('backgroundColor', '#' + hsb2hex({ h: hsb.h, s: 100, b: 100 })); + + // Fire change callback + if( input.data('change') ) { + if( hex === input.data('lastChange') ) return; + input.data('change').call(input.get(0), '#' + hex, hsb2rgb(hsb)); + input.data('lastChange', hex); + } + + }; + + var setColorFromInput = function(input) { + + input.val('#' + cleanHex(input.val())); + var hex = expandHex(input.val()); + if( !hex ) return false; + + // Get HSB equivalent + var hsb = hex2hsb(hex); + + // If color is the same, no change required + var currentHSB = input.data('hsb'); + if( hsb.h === currentHSB.h && hsb.s === currentHSB.s && hsb.b === currentHSB.b ) return true; + + // Set colorPicker position + var colorPosition = getColorPositionFromHSB(hsb); + var colorPicker = $(input.data('colorPicker')); + colorPicker.css('top', colorPosition.y + 'px').css('left', colorPosition.x + 'px'); + input.data('colorPosition', colorPosition); + + // Set huePosition position + var huePosition = getHuePositionFromHSB(hsb); + var huePicker = $(input.data('huePicker')); + huePicker.css('top', huePosition.y + 'px'); + input.data('huePosition', huePosition); + + setColor(input, hsb); + + return true; + + }; + + var convertCase = function(string, letterCase) { + if( letterCase === 'lowercase' ) return string.toLowerCase(); + if( letterCase === 'uppercase' ) return string.toUpperCase(); + return string; + }; + + var getColorPositionFromHSB = function(hsb) { + var x = Math.ceil(hsb.s / 0.67); + if( x < 0 ) x = 0; + if( x > 150 ) x = 150; + var y = 150 - Math.ceil(hsb.b / 0.67); + if( y < 0 ) y = 0; + if( y > 150 ) y = 150; + return { x: x - 5, y: y - 5 }; + }; + + var getHuePositionFromHSB = function(hsb) { + var y = 150 - (hsb.h / 2.4); + if( y < 0 ) h = 0; + if( y > 150 ) h = 150; + return { y: y - 1 }; + }; + + var cleanHex = function(hex) { + return hex.replace(/[^A-F0-9]/ig, ''); + }; + + var expandHex = function(hex) { + hex = cleanHex(hex); + if( !hex ) return null; + if( hex.length === 3 ) hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; + return hex.length === 6 ? hex : null; + }; + + var hsb2rgb = function(hsb) { + var rgb = {}; + var h = Math.round(hsb.h); + var s = Math.round(hsb.s*255/100); + var v = Math.round(hsb.b*255/100); + if(s === 0) { + rgb.r = rgb.g = rgb.b = v; + } else { + var t1 = v; + var t2 = (255 - s) * v / 255; + var t3 = (t1 - t2) * (h % 60) / 60; + if( h === 360 ) h = 0; + if( h < 60 ) { rgb.r = t1; rgb.b = t2; rgb.g = t2 + t3; } + else if( h < 120 ) {rgb.g = t1; rgb.b = t2; rgb.r = t1 - t3; } + else if( h < 180 ) {rgb.g = t1; rgb.r = t2; rgb.b = t2 + t3; } + else if( h < 240 ) {rgb.b = t1; rgb.r = t2; rgb.g = t1 - t3; } + else if( h < 300 ) {rgb.b = t1; rgb.g = t2; rgb.r = t2 + t3; } + else if( h < 360 ) {rgb.r = t1; rgb.g = t2; rgb.b = t1 - t3; } + else { rgb.r = 0; rgb.g = 0; rgb.b = 0; } + } + return { + r: Math.round(rgb.r), + g: Math.round(rgb.g), + b: Math.round(rgb.b) + }; + }; + + var rgb2hex = function(rgb) { + var hex = [ + rgb.r.toString(16), + rgb.g.toString(16), + rgb.b.toString(16) + ]; + $.each(hex, function(nr, val) { + if (val.length === 1) hex[nr] = '0' + val; + }); + return hex.join(''); + }; + + var hex2rgb = function(hex) { + hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16); + + return { + r: hex >> 16, + g: (hex & 0x00FF00) >> 8, + b: (hex & 0x0000FF) + }; + }; + + var rgb2hsb = function(rgb) { + var hsb = { h: 0, s: 0, b: 0 }; + var min = Math.min(rgb.r, rgb.g, rgb.b); + var max = Math.max(rgb.r, rgb.g, rgb.b); + var delta = max - min; + hsb.b = max; + hsb.s = max !== 0 ? 255 * delta / max : 0; + if( hsb.s !== 0 ) { + if( rgb.r === max ) { + hsb.h = (rgb.g - rgb.b) / delta; + } else if( rgb.g === max ) { + hsb.h = 2 + (rgb.b - rgb.r) / delta; + } else { + hsb.h = 4 + (rgb.r - rgb.g) / delta; + } + } else { + hsb.h = -1; + } + hsb.h *= 60; + if( hsb.h < 0 ) { + hsb.h += 360; + } + hsb.s *= 100/255; + hsb.b *= 100/255; + return hsb; + }; + + var hex2hsb = function(hex) { + var hsb = rgb2hsb(hex2rgb(hex)); + // Zero out hue marker for black, white, and grays (saturation === 0) + if( hsb.s === 0 ) hsb.h = 360; + return hsb; + }; + + var hsb2hex = function(hsb) { + return rgb2hex(hsb2rgb(hsb)); + }; + + + // Handle calls to $([selector]).miniColors() + switch(o) { + + case 'readonly': + + $(this).each( function() { + if( !$(this).hasClass('miniColors') ) return; + $(this).prop('readonly', data); + }); + + return $(this); + + case 'disabled': + + $(this).each( function() { + if( !$(this).hasClass('miniColors') ) return; + if( data ) { + disable($(this)); + } else { + enable($(this)); + } + }); + + return $(this); + + case 'value': + + // Getter + if( data === undefined ) { + if( !$(this).hasClass('miniColors') ) return; + var input = $(this), + hex = expandHex(input.val()); + return hex ? '#' + convertCase(hex, input.data('letterCase')) : null; + } + + // Setter + $(this).each( function() { + if( !$(this).hasClass('miniColors') ) return; + $(this).val(data); + setColorFromInput($(this)); + }); + + return $(this); + + case 'destroy': + + $(this).each( function() { + if( !$(this).hasClass('miniColors') ) return; + destroy($(this)); + }); + + return $(this); + + default: + + if( !o ) o = {}; + + $(this).each( function() { + + // Must be called on an input element + if( $(this)[0].tagName.toLowerCase() !== 'input' ) return; + + // If a trigger is present, the control was already created + if( $(this).data('trigger') ) return; + + // Create the control + create($(this), o, data); + + }); + + return $(this); + + } + + } + + }); + +})(jQuery);
\ No newline at end of file diff --git a/3rdparty/miniColors/js/jquery.miniColors.min.js b/3rdparty/miniColors/js/jquery.miniColors.min.js new file mode 100755 index 00000000000..c00e0ace6b5 --- /dev/null +++ b/3rdparty/miniColors/js/jquery.miniColors.min.js @@ -0,0 +1,9 @@ +/* + * jQuery miniColors: A small color selector + * + * Copyright 2011 Cory LaViska for A Beautiful Site, LLC. (http://abeautifulsite.net/) + * + * Dual licensed under the MIT or GPL Version 2 licenses + * +*/ +if(jQuery)(function($){$.extend($.fn,{miniColors:function(o,data){var create=function(input,o,data){var color=expandHex(input.val());if(!color)color='ffffff';var hsb=hex2hsb(color);var trigger=$('<a class="miniColors-trigger" style="background-color: #'+color+'" href="#"></a>');trigger.insertAfter(input);input.addClass('miniColors').data('original-maxlength',input.attr('maxlength')||null).data('original-autocomplete',input.attr('autocomplete')||null).data('letterCase','uppercase').data('trigger',trigger).data('hsb',hsb).data('change',o.change?o.change:null).data('close',o.close?o.close:null).data('open',o.open?o.open:null).attr('maxlength',7).attr('autocomplete','off').val('#'+convertCase(color,o.letterCase));if(o.readonly)input.prop('readonly',true);if(o.disabled)disable(input);trigger.bind('click.miniColors',function(event){event.preventDefault();if(input.val()==='')input.val('#');show(input)});input.bind('focus.miniColors',function(event){if(input.val()==='')input.val('#');show(input)});input.bind('blur.miniColors',function(event){var hex=expandHex(hsb2hex(input.data('hsb')));input.val(hex?'#'+convertCase(hex,input.data('letterCase')):'')});input.bind('keydown.miniColors',function(event){if(event.keyCode===9)hide(input)});input.bind('keyup.miniColors',function(event){setColorFromInput(input)});input.bind('paste.miniColors',function(event){setTimeout(function(){setColorFromInput(input)},5)})};var destroy=function(input){hide();input=$(input);input.data('trigger').remove();input.attr('autocomplete',input.data('original-autocomplete')).attr('maxlength',input.data('original-maxlength')).removeData().removeClass('miniColors').unbind('.miniColors');$(document).unbind('.miniColors')};var enable=function(input){input.prop('disabled',false).data('trigger').css('opacity',1)};var disable=function(input){hide(input);input.prop('disabled',true).data('trigger').css('opacity',0.5)};var show=function(input){if(input.prop('disabled'))return false;hide();var selector=$('<div class="miniColors-selector"></div>');selector.append('<div class="miniColors-colors" style="background-color: #FFF;"><div class="miniColors-colorPicker"><div class="miniColors-colorPicker-inner"></div></div>').append('<div class="miniColors-hues"><div class="miniColors-huePicker"></div></div>').css({top:input.is(':visible')?input.offset().top+input.outerHeight():input.data('trigger').offset().top+input.data('trigger').outerHeight(),left:input.is(':visible')?input.offset().left:input.data('trigger').offset().left,display:'none'}).addClass(input.attr('class'));var hsb=input.data('hsb');selector.find('.miniColors-colors').css('backgroundColor','#'+hsb2hex({h:hsb.h,s:100,b:100}));var colorPosition=input.data('colorPosition');if(!colorPosition)colorPosition=getColorPositionFromHSB(hsb);selector.find('.miniColors-colorPicker').css('top',colorPosition.y+'px').css('left',colorPosition.x+'px');var huePosition=input.data('huePosition');if(!huePosition)huePosition=getHuePositionFromHSB(hsb);selector.find('.miniColors-huePicker').css('top',huePosition.y+'px');input.data('selector',selector).data('huePicker',selector.find('.miniColors-huePicker')).data('colorPicker',selector.find('.miniColors-colorPicker')).data('mousebutton',0);$('BODY').append(selector);selector.fadeIn(100);selector.bind('selectstart',function(){return false});$(document).bind('mousedown.miniColors touchstart.miniColors',function(event){input.data('mousebutton',1);var testSubject=$(event.target).parents().andSelf();if(testSubject.hasClass('miniColors-colors')){event.preventDefault();input.data('moving','colors');moveColor(input,event)}if(testSubject.hasClass('miniColors-hues')){event.preventDefault();input.data('moving','hues');moveHue(input,event)}if(testSubject.hasClass('miniColors-selector')){event.preventDefault();return}if(testSubject.hasClass('miniColors'))return;hide(input)});$(document).bind('mouseup.miniColors touchend.miniColors',function(event){event.preventDefault();input.data('mousebutton',0).removeData('moving')}).bind('mousemove.miniColors touchmove.miniColors',function(event){event.preventDefault();if(input.data('mousebutton')===1){if(input.data('moving')==='colors')moveColor(input,event);if(input.data('moving')==='hues')moveHue(input,event)}});if(input.data('open')){input.data('open').call(input.get(0),'#'+hsb2hex(hsb),hsb2rgb(hsb))}};var hide=function(input){if(!input)input='.miniColors';$(input).each(function(){var selector=$(this).data('selector');$(this).removeData('selector');$(selector).fadeOut(100,function(){if(input.data('close')){var hsb=input.data('hsb'),hex=hsb2hex(hsb);input.data('close').call(input.get(0),'#'+hex,hsb2rgb(hsb))}$(this).remove()})});$(document).unbind('.miniColors')};var moveColor=function(input,event){var colorPicker=input.data('colorPicker');colorPicker.hide();var position={x:event.pageX,y:event.pageY};if(event.originalEvent.changedTouches){position.x=event.originalEvent.changedTouches[0].pageX;position.y=event.originalEvent.changedTouches[0].pageY}position.x=position.x-input.data('selector').find('.miniColors-colors').offset().left-5;position.y=position.y-input.data('selector').find('.miniColors-colors').offset().top-5;if(position.x<=-5)position.x=-5;if(position.x>=144)position.x=144;if(position.y<=-5)position.y=-5;if(position.y>=144)position.y=144;input.data('colorPosition',position);colorPicker.css('left',position.x).css('top',position.y).show();var s=Math.round((position.x+5)*0.67);if(s<0)s=0;if(s>100)s=100;var b=100-Math.round((position.y+5)*0.67);if(b<0)b=0;if(b>100)b=100;var hsb=input.data('hsb');hsb.s=s;hsb.b=b;setColor(input,hsb,true)};var moveHue=function(input,event){var huePicker=input.data('huePicker');huePicker.hide();var position={y:event.pageY};if(event.originalEvent.changedTouches){position.y=event.originalEvent.changedTouches[0].pageY}position.y=position.y-input.data('selector').find('.miniColors-colors').offset().top-1;if(position.y<=-1)position.y=-1;if(position.y>=149)position.y=149;input.data('huePosition',position);huePicker.css('top',position.y).show();var h=Math.round((150-position.y-1)*2.4);if(h<0)h=0;if(h>360)h=360;var hsb=input.data('hsb');hsb.h=h;setColor(input,hsb,true)};var setColor=function(input,hsb,updateInput){input.data('hsb',hsb);var hex=hsb2hex(hsb);if(updateInput)input.val('#'+convertCase(hex,input.data('letterCase')));input.data('trigger').css('backgroundColor','#'+hex);if(input.data('selector'))input.data('selector').find('.miniColors-colors').css('backgroundColor','#'+hsb2hex({h:hsb.h,s:100,b:100}));if(input.data('change')){if(hex===input.data('lastChange'))return;input.data('change').call(input.get(0),'#'+hex,hsb2rgb(hsb));input.data('lastChange',hex)}};var setColorFromInput=function(input){input.val('#'+cleanHex(input.val()));var hex=expandHex(input.val());if(!hex)return false;var hsb=hex2hsb(hex);var currentHSB=input.data('hsb');if(hsb.h===currentHSB.h&&hsb.s===currentHSB.s&&hsb.b===currentHSB.b)return true;var colorPosition=getColorPositionFromHSB(hsb);var colorPicker=$(input.data('colorPicker'));colorPicker.css('top',colorPosition.y+'px').css('left',colorPosition.x+'px');input.data('colorPosition',colorPosition);var huePosition=getHuePositionFromHSB(hsb);var huePicker=$(input.data('huePicker'));huePicker.css('top',huePosition.y+'px');input.data('huePosition',huePosition);setColor(input,hsb);return true};var convertCase=function(string,letterCase){if(letterCase==='lowercase')return string.toLowerCase();if(letterCase==='uppercase')return string.toUpperCase();return string};var getColorPositionFromHSB=function(hsb){var x=Math.ceil(hsb.s/0.67);if(x<0)x=0;if(x>150)x=150;var y=150-Math.ceil(hsb.b/0.67);if(y<0)y=0;if(y>150)y=150;return{x:x-5,y:y-5}};var getHuePositionFromHSB=function(hsb){var y=150-(hsb.h/2.4);if(y<0)h=0;if(y>150)h=150;return{y:y-1}};var cleanHex=function(hex){return hex.replace(/[^A-F0-9]/ig,'')};var expandHex=function(hex){hex=cleanHex(hex);if(!hex)return null;if(hex.length===3)hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];return hex.length===6?hex:null};var hsb2rgb=function(hsb){var rgb={};var h=Math.round(hsb.h);var s=Math.round(hsb.s*255/100);var v=Math.round(hsb.b*255/100);if(s===0){rgb.r=rgb.g=rgb.b=v}else{var t1=v;var t2=(255-s)*v/255;var t3=(t1-t2)*(h%60)/60;if(h===360)h=0;if(h<60){rgb.r=t1;rgb.b=t2;rgb.g=t2+t3}else if(h<120){rgb.g=t1;rgb.b=t2;rgb.r=t1-t3}else if(h<180){rgb.g=t1;rgb.r=t2;rgb.b=t2+t3}else if(h<240){rgb.b=t1;rgb.r=t2;rgb.g=t1-t3}else if(h<300){rgb.b=t1;rgb.g=t2;rgb.r=t2+t3}else if(h<360){rgb.r=t1;rgb.g=t2;rgb.b=t1-t3}else{rgb.r=0;rgb.g=0;rgb.b=0}}return{r:Math.round(rgb.r),g:Math.round(rgb.g),b:Math.round(rgb.b)}};var rgb2hex=function(rgb){var hex=[rgb.r.toString(16),rgb.g.toString(16),rgb.b.toString(16)];$.each(hex,function(nr,val){if(val.length===1)hex[nr]='0'+val});return hex.join('')};var hex2rgb=function(hex){hex=parseInt(((hex.indexOf('#')>-1)?hex.substring(1):hex),16);return{r:hex>>16,g:(hex&0x00FF00)>>8,b:(hex&0x0000FF)}};var rgb2hsb=function(rgb){var hsb={h:0,s:0,b:0};var min=Math.min(rgb.r,rgb.g,rgb.b);var max=Math.max(rgb.r,rgb.g,rgb.b);var delta=max-min;hsb.b=max;hsb.s=max!==0?255*delta/max:0;if(hsb.s!==0){if(rgb.r===max){hsb.h=(rgb.g-rgb.b)/delta}else if(rgb.g===max){hsb.h=2+(rgb.b-rgb.r)/delta}else{hsb.h=4+(rgb.r-rgb.g)/delta}}else{hsb.h=-1}hsb.h*=60;if(hsb.h<0){hsb.h+=360}hsb.s*=100/255;hsb.b*=100/255;return hsb};var hex2hsb=function(hex){var hsb=rgb2hsb(hex2rgb(hex));if(hsb.s===0)hsb.h=360;return hsb};var hsb2hex=function(hsb){return rgb2hex(hsb2rgb(hsb))};switch(o){case'readonly':$(this).each(function(){if(!$(this).hasClass('miniColors'))return;$(this).prop('readonly',data)});return $(this);case'disabled':$(this).each(function(){if(!$(this).hasClass('miniColors'))return;if(data){disable($(this))}else{enable($(this))}});return $(this);case'value':if(data===undefined){if(!$(this).hasClass('miniColors'))return;var input=$(this),hex=expandHex(input.val());return hex?'#'+convertCase(hex,input.data('letterCase')):null}$(this).each(function(){if(!$(this).hasClass('miniColors'))return;$(this).val(data);setColorFromInput($(this))});return $(this);case'destroy':$(this).each(function(){if(!$(this).hasClass('miniColors'))return;destroy($(this))});return $(this);default:if(!o)o={};$(this).each(function(){if($(this)[0].tagName.toLowerCase()!=='input')return;if($(this).data('trigger'))return;create($(this),o,data)});return $(this)}}})})(jQuery);
\ No newline at end of file diff --git a/apps/user_openid/class.openid.v3.php b/3rdparty/openid/class.openid.v3.php index eeb31986659..eeb31986659 100644 --- a/apps/user_openid/class.openid.v3.php +++ b/3rdparty/openid/class.openid.v3.php diff --git a/apps/user_openid/phpmyid.php b/3rdparty/openid/phpmyid.php index 5aaab642856..13fd31c47ca 100644 --- a/apps/user_openid/phpmyid.php +++ b/3rdparty/openid/phpmyid.php @@ -1705,4 +1705,3 @@ $run_mode = (isset($_REQUEST['openid_mode']) debug("Run mode: $run_mode at: " . time()); debug($_REQUEST, 'Request params'); call_user_func($run_mode . '_mode'); -?> diff --git a/apps/bookmarks/ajax/addBookmark.php b/apps/bookmarks/ajax/addBookmark.php index 6b5a0f71d4e..483716405a1 100644 --- a/apps/bookmarks/ajax/addBookmark.php +++ b/apps/bookmarks/ajax/addBookmark.php @@ -28,6 +28,8 @@ $RUNTIME_NOSETUPFS=true; // Check if we are a user OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); + OCP\JSON::checkAppEnabled('bookmarks'); require_once(OC_App::getAppPath('bookmarks').'/bookmarksHelper.php'); diff --git a/apps/bookmarks/ajax/delBookmark.php b/apps/bookmarks/ajax/delBookmark.php index 5a067701c9f..f40f02ebab7 100644 --- a/apps/bookmarks/ajax/delBookmark.php +++ b/apps/bookmarks/ajax/delBookmark.php @@ -28,6 +28,8 @@ $RUNTIME_NOSETUPFS=true; // Check if we are a user OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); + OCP\JSON::checkAppEnabled('bookmarks'); $id = $_POST['id']; diff --git a/apps/bookmarks/ajax/editBookmark.php b/apps/bookmarks/ajax/editBookmark.php index 439b680dc20..0b37d161af1 100644 --- a/apps/bookmarks/ajax/editBookmark.php +++ b/apps/bookmarks/ajax/editBookmark.php @@ -28,6 +28,8 @@ $RUNTIME_NOSETUPFS=true; // Check if we are a user OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); + OCP\JSON::checkAppEnabled('bookmarks'); $CONFIG_DBTYPE = OCP\Config::getSystemValue( "dbtype", "sqlite" ); diff --git a/apps/bookmarks/lib/bookmarks.php b/apps/bookmarks/lib/bookmarks.php index e0005968f31..86fba45a50c 100644 --- a/apps/bookmarks/lib/bookmarks.php +++ b/apps/bookmarks/lib/bookmarks.php @@ -145,5 +145,4 @@ class OC_Bookmarks_Bookmarks{ $result = $query->execute(); return true; } -} -?> +}
\ No newline at end of file diff --git a/apps/calendar/ajax/calendar/activation.php b/apps/calendar/ajax/calendar/activation.php index e31908beb14..f4aadc5b017 100644 --- a/apps/calendar/ajax/calendar/activation.php +++ b/apps/calendar/ajax/calendar/activation.php @@ -9,6 +9,8 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('calendar'); +OCP\JSON::callCheck(); + $calendarid = $_POST['calendarid']; $calendar = OC_Calendar_App::getCalendar($calendarid, true); if(!$calendar){ diff --git a/apps/calendar/ajax/calendar/delete.php b/apps/calendar/ajax/calendar/delete.php index 4d6706f6002..089255cae39 100644 --- a/apps/calendar/ajax/calendar/delete.php +++ b/apps/calendar/ajax/calendar/delete.php @@ -9,6 +9,7 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('calendar'); +OCP\JSON::callCheck(); $cal = $_POST["calendarid"]; $calendar = OC_Calendar_App::getCalendar($cal, true); diff --git a/apps/calendar/ajax/calendar/new.php b/apps/calendar/ajax/calendar/new.php index e77d4ebff03..67d12822378 100644 --- a/apps/calendar/ajax/calendar/new.php +++ b/apps/calendar/ajax/calendar/new.php @@ -6,11 +6,10 @@ * See the COPYING-README file. */ - - // Check if we are a user OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('calendar'); +OCP\JSON::callCheck(); if(trim($_POST['name']) == ''){ OCP\JSON::error(array('message'=>'empty')); diff --git a/apps/calendar/ajax/calendar/update.php b/apps/calendar/ajax/calendar/update.php index a2c898c8075..c09b1008c9c 100644 --- a/apps/calendar/ajax/calendar/update.php +++ b/apps/calendar/ajax/calendar/update.php @@ -11,6 +11,7 @@ // Check if we are a user OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('calendar'); +OCP\JSON::callCheck(); if(trim($_POST['name']) == ''){ OCP\JSON::error(array('message'=>'empty')); diff --git a/apps/calendar/ajax/categories/rescan.php b/apps/calendar/ajax/categories/rescan.php index f0060cb23b2..08c32865b6f 100644 --- a/apps/calendar/ajax/categories/rescan.php +++ b/apps/calendar/ajax/categories/rescan.php @@ -9,6 +9,7 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('calendar'); +OCP\JSON::callCheck(); foreach ($_POST as $key=>$element) { debug('_POST: '.$key.'=>'.print_r($element, true)); diff --git a/apps/calendar/ajax/event/delete.php b/apps/calendar/ajax/event/delete.php index f183d431afa..17e45c001e8 100644 --- a/apps/calendar/ajax/event/delete.php +++ b/apps/calendar/ajax/event/delete.php @@ -9,6 +9,7 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('calendar'); +OCP\JSON::callCheck(); $id = $_POST['id']; $access = OC_Calendar_App::getaccess($id, OC_Calendar_App::EVENT); diff --git a/apps/calendar/ajax/event/edit.php b/apps/calendar/ajax/event/edit.php index 1c3babc3d90..db78bf6e5e0 100644 --- a/apps/calendar/ajax/event/edit.php +++ b/apps/calendar/ajax/event/edit.php @@ -9,6 +9,7 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('calendar'); +OCP\JSON::callCheck(); $id = $_POST['id']; diff --git a/apps/calendar/ajax/event/move.php b/apps/calendar/ajax/event/move.php index 04cf2fb0513..f4e2b36376d 100644 --- a/apps/calendar/ajax/event/move.php +++ b/apps/calendar/ajax/event/move.php @@ -7,6 +7,7 @@ */ OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); $id = $_POST['id']; $access = OC_Calendar_App::getaccess($id, OC_Calendar_App::EVENT); diff --git a/apps/calendar/ajax/event/new.form.php b/apps/calendar/ajax/event/new.form.php index 0b19e7e92f9..db04cdf2d49 100644 --- a/apps/calendar/ajax/event/new.form.php +++ b/apps/calendar/ajax/event/new.form.php @@ -27,7 +27,7 @@ if (!$end){ } $start = new DateTime('@'.$start); $end = new DateTime('@'.$end); -$timezone = OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); +$timezone = OC_Calendar_App::getTimezone(); $start->setTimezone(new DateTimeZone($timezone)); $end->setTimezone(new DateTimeZone($timezone)); diff --git a/apps/calendar/ajax/event/new.php b/apps/calendar/ajax/event/new.php index 30e2b0cae36..bc0439cc315 100644 --- a/apps/calendar/ajax/event/new.php +++ b/apps/calendar/ajax/event/new.php @@ -10,6 +10,7 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('calendar'); +OCP\JSON::callCheck(); $errarr = OC_Calendar_Object::validateRequest($_POST); if($errarr){ diff --git a/apps/calendar/ajax/event/resize.php b/apps/calendar/ajax/event/resize.php index 56b83205e85..15b687b55da 100644 --- a/apps/calendar/ajax/event/resize.php +++ b/apps/calendar/ajax/event/resize.php @@ -7,6 +7,7 @@ */ OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); $id = $_POST['id']; diff --git a/apps/calendar/ajax/import/calendarcheck.php b/apps/calendar/ajax/import/calendarcheck.php new file mode 100644 index 00000000000..a91bab70573 --- /dev/null +++ b/apps/calendar/ajax/import/calendarcheck.php @@ -0,0 +1,18 @@ +<?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. + */ +OCP\JSON::checkLoggedIn(); +OCP\App::checkAppEnabled('calendar'); +$calname = strip_tags($_POST['calname']); +$calendars = OC_Calendar_Calendar::allCalendars(OCP\User::getUser()); +foreach($calendars as $calendar){ + if($calendar['displayname'] == $calname){ + OCP\JSON::success(array('message'=>'exists')); + exit; + } +} +OCP\JSON::error();
\ No newline at end of file diff --git a/apps/calendar/ajax/import/dialog.php b/apps/calendar/ajax/import/dialog.php index b99c32278c4..18fe226172c 100644 --- a/apps/calendar/ajax/import/dialog.php +++ b/apps/calendar/ajax/import/dialog.php @@ -5,8 +5,6 @@ * later. * See the COPYING-README file. */ - - OCP\JSON::checkLoggedIn(); OCP\App::checkAppEnabled('calendar'); $tmpl = new OCP\Template('calendar', 'part.import'); diff --git a/apps/calendar/ajax/import/dropimport.php b/apps/calendar/ajax/import/dropimport.php index 87667d4de68..f46e7314098 100644 --- a/apps/calendar/ajax/import/dropimport.php +++ b/apps/calendar/ajax/import/dropimport.php @@ -1,73 +1,32 @@ <?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. + */ $data = $_POST['data']; $data = explode(',', $data); $data = end($data); $data = base64_decode($data); OCP\JSON::checkLoggedIn(); OCP\App::checkAppEnabled('calendar'); -$nl="\r\n"; -$comps = array('VEVENT'=>true, 'VTODO'=>true, 'VJOURNAL'=>true); -$data = str_replace(array("\r","\n\n"), array("\n","\n"), $data); -$lines = explode("\n", $data); -unset($data); -$comp=$uid=$cal=false; -$cals=$uids=array(); -$i = 0; -foreach($lines as $line) { - if(strpos($line, ':')!==false) { - list($attr, $val) = explode(':', strtoupper($line)); - if ($attr == 'BEGIN' && $val == 'VCALENDAR') { - $cal = $i; - $cals[$cal] = array('first'=>$i,'last'=>$i,'end'=>$i); - } elseif ($attr =='BEGIN' && $cal!==false && isset($comps[$val])) { - $comp = $val; - $beginNo = $i; - } elseif ($attr == 'END' && $cal!==false && $val == 'VCALENDAR') { - if($comp!==false) { - unset($cals[$cal]); // corrupt calendar, unset it - } else { - $cals[$cal]['end'] = $i; - } - $comp=$uid=$cal=false; // reset calendar - } elseif ($attr == 'END' && $comp!==false && $val == $comp) { - if(! $uid) { - $uid = OC_Calendar_Object::createUID(); - } - $uids[$uid][$beginNo] = array('end'=>$i, 'cal'=>$cal); - if ($cals[$cal]['first'] == $cal) { - $cals[$cal]['first'] = $beginNo; - } - $cals[$cal]['last'] = $i; - $comp=$uid=false; // reset component - } elseif ($attr =="UID" && $comp!==false) { - list($attr, $uid) = explode(':', $line); - } - } - $i++; +$import = new OC_Calendar_Import($data); +$import->setUserID(OCP\User::getUser()); +$import->setTimeZone(OC_Calendar_App::$tz); +$import->disableProgressCache(); +if(!$import->isValid()){ + OCP\JSON::error(); + exit; } -$calendars = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser(), true); -$id = $calendars[0]['id']; -foreach($uids as $uid) { - $prefix=$suffix=$content=array(); - foreach($uid as $begin=>$details) { - $cal = $details['cal']; - if(!isset($cals[$cal])) { - continue; // from corrupt/incomplete calendar - } - $cdata = $cals[$cal]; - // if we have multiple components from different calendar objects, - // we should really merge their elements (enhancement?) -- 1st one wins for now. - if(! count($prefix)) { - $prefix = array_slice($lines, $cal, $cdata['first'] - $cal); - } - if(! count($suffix)) { - $suffix = array_slice($lines, $cdata['last']+1, $cdata['end'] - $cdata['last']); - } - $content = array_merge($content, array_slice($lines, $begin, $details['end'] - $begin + 1)); - } - if(count($content)) { - $import = join($nl, array_merge($prefix, $content, $suffix)) . $nl; - OC_Calendar_Object::add($id, $import); - } -} -OCP\JSON::success();
\ No newline at end of file +$newcalendarname = strip_tags($import->createCalendarName()); +$newid = OC_Calendar_Calendar::addCalendar(OCP\User::getUser(),$newcalendarname,'VEVENT,VTODO,VJOURNAL',null,0,$import->createCalendarColor()); +$import->setCalendarID($newid); +$import->import(); +$count = $import->getCount(); +if($count == 0){ + OC_Calendar_Calendar::deleteCalendar($newid); + OCP\JSON::error(array('message'=>OC_Calendar_App::$l10n->t('The file contained either no events or all events are already saved in your calendar.'))); +}else{ + OCP\JSON::success(array('message'=>$count . ' ' . OC_Calendar_App::$l10n->t('events has been saved in the new calendar') . ' ' . $newcalendarname, 'eventSource'=>OC_Calendar_Calendar::getEventSourceInfo(OC_Calendar_Calendar::find($newid)))); +}
\ No newline at end of file diff --git a/apps/calendar/ajax/import/import.php b/apps/calendar/ajax/import/import.php index 1facedfe0da..b1dfc464d00 100644 --- a/apps/calendar/ajax/import/import.php +++ b/apps/calendar/ajax/import/import.php @@ -5,41 +5,71 @@ * later. * See the COPYING-README file. */ -//check for calendar rights or create new one -ob_start(); - OCP\JSON::checkLoggedIn(); OCP\App::checkAppEnabled('calendar'); +OCP\JSON::callCheck(); session_write_close(); - -$nl="\r\n"; -$comps = array('VEVENT'=>true, 'VTODO'=>true, 'VJOURNAL'=>true); - -global $progresskey; -$progresskey = 'calendar.import-' . $_POST['progresskey']; - -if (isset($_POST['progress']) && $_POST['progress']) { - echo OC_Cache::get($progresskey); - die; +if (isset($_POST['progresskey']) && isset($_POST['getprogress'])) { + echo OCP\JSON::success(array('percent'=>OC_Cache::get($_POST['progresskey']))); + exit; } - -function writeProgress($pct) { - global $progresskey; - OC_Cache::set($progresskey, $pct, 300); -} -writeProgress('10'); $file = OC_Filesystem::file_get_contents($_POST['path'] . '/' . $_POST['file']); +if(!$file){ + OCP\JSON::error(array('error'=>'404')); +} +$import = new OC_Calendar_Import($file); +$import->setUserID(OCP\User::getUser()); +$import->setTimeZone(OC_Calendar_App::$tz); +$import->enableProgressCache(); +$import->setProgresskey($_POST['progresskey']); +if(!$import->isValid()){ + OCP\JSON::error(array('error'=>'notvalid')); + exit; +} +$newcal = false; if($_POST['method'] == 'new'){ - $id = OC_Calendar_Calendar::addCalendar(OCP\USER::getUser(), $_POST['calname']); - OC_Calendar_Calendar::setCalendarActive($id, 1); + $calendars = OC_Calendar_Calendar::allCalendars(OCP\User::getUser()); + foreach($calendars as $calendar){ + if($calendar['displayname'] == $_POST['calname']){ + $id = $calendar['id']; + $newcal = false; + break; + } + $newcal = true; + } + if($newcal){ + $id = OC_Calendar_Calendar::addCalendar(OCP\USER::getUser(), strip_tags($_POST['calname']),'VEVENT,VTODO,VJOURNAL',null,0,strip_tags($_POST['calcolor'])); + OC_Calendar_Calendar::setCalendarActive($id, 1); + } }else{ $calendar = OC_Calendar_App::getCalendar($_POST['id']); if($calendar['userid'] != OCP\USER::getUser()){ - OCP\JSON::error(); + OCP\JSON::error(array('error'=>'missingcalendarrights')); exit(); } $id = $_POST['id']; } +$import->setCalendarID($id); +try{ + $import->import(); +}catch (Exception $e) { + OCP\JSON::error(array('message'=>OC_Calendar_App::$l10n->t('Import failed'), 'debug'=>$e->getMessage())); + //write some log +} +$count = $import->getCount(); +if($count == 0){ + if($newcal){ + OC_Calendar_Calendar::deleteCalendar($id); + } + OCP\JSON::error(array('message'=>OC_Calendar_App::$l10n->t('The file contained either no events or all events are already saved in your calendar.'))); +}else{ + if($newcal){ + OCP\JSON::success(array('message'=>$count . ' ' . OC_Calendar_App::$l10n->t('events has been saved in the new calendar') . ' ' . strip_tags($_POST['calname']))); + }else{ + OCP\JSON::success(array('message'=>$count . ' ' . OC_Calendar_App::$l10n->t('events has been saved in your calendar'))); + } +} +/* //////////////////////////// Attention: following code is quite painfull !!! /////////////////////// writeProgress('20'); // normalize the newlines $file = str_replace(array("\r","\n\n"), array("\n","\n"), $file); @@ -91,7 +121,6 @@ foreach($lines as $line) { // import the calendar writeProgress('60'); foreach($uids as $uid) { - $prefix=$suffix=$content=array(); foreach($uid as $begin=>$details) { @@ -119,4 +148,4 @@ foreach($uids as $uid) { writeProgress('100'); sleep(3); OC_Cache::remove($progresskey); -OCP\JSON::success();
\ No newline at end of file +OCP\JSON::success();*/ diff --git a/apps/calendar/ajax/settings/setfirstday.php b/apps/calendar/ajax/settings/setfirstday.php index 056a6037524..73cf0c19b78 100644 --- a/apps/calendar/ajax/settings/setfirstday.php +++ b/apps/calendar/ajax/settings/setfirstday.php @@ -7,6 +7,7 @@ */ OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); if(isset($_POST["firstday"])){ OCP\Config::setUserValue(OCP\USER::getUser(), 'calendar', 'firstday', $_POST["firstday"]); OCP\JSON::success(); diff --git a/apps/calendar/ajax/settings/settimeformat.php b/apps/calendar/ajax/settings/settimeformat.php index 8e95f6f3bf5..6136857e2fe 100644 --- a/apps/calendar/ajax/settings/settimeformat.php +++ b/apps/calendar/ajax/settings/settimeformat.php @@ -7,6 +7,7 @@ */ OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); if(isset($_POST["timeformat"])){ OCP\Config::setUserValue(OCP\USER::getUser(), 'calendar', 'timeformat', $_POST["timeformat"]); OCP\JSON::success(); diff --git a/apps/calendar/ajax/settings/settimezone.php b/apps/calendar/ajax/settings/settimezone.php index 6d029a6643a..06db66d578e 100644 --- a/apps/calendar/ajax/settings/settimezone.php +++ b/apps/calendar/ajax/settings/settimezone.php @@ -14,6 +14,7 @@ $l=OC_L10N::get('calendar'); // Check if we are a user OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('calendar'); +OCP\JSON::callCheck(); // Get data if( isset( $_POST['timezone'] ) ){ diff --git a/apps/calendar/ajax/share/changepermission.php b/apps/calendar/ajax/share/changepermission.php index e807c164a23..5aff7666f79 100644 --- a/apps/calendar/ajax/share/changepermission.php +++ b/apps/calendar/ajax/share/changepermission.php @@ -5,7 +5,9 @@ * later. * See the COPYING-README file. */ - + +OCP\JSON::callCheck(); + $id = strip_tags($_POST['id']); $idtype = strip_tags($_POST['idtype']); $permission = (int) strip_tags($_POST['permission']); diff --git a/apps/calendar/ajax/share/share.php b/apps/calendar/ajax/share/share.php index 838db619f62..77e1ab9d657 100644 --- a/apps/calendar/ajax/share/share.php +++ b/apps/calendar/ajax/share/share.php @@ -6,6 +6,8 @@ * See the COPYING-README file. */ +OCP\JSON::callCheck(); + $id = strip_tags($_POST['id']); $idtype = strip_tags($_POST['idtype']); switch($idtype){ diff --git a/apps/calendar/ajax/share/unshare.php b/apps/calendar/ajax/share/unshare.php index 1ce04677fb1..c7c06113189 100644 --- a/apps/calendar/ajax/share/unshare.php +++ b/apps/calendar/ajax/share/unshare.php @@ -5,7 +5,9 @@ * later. * See the COPYING-README file. */ - + +OCP\JSON::callCheck(); + $id = strip_tags($_POST['id']); $idtype = strip_tags($_POST['idtype']); switch($idtype){ diff --git a/apps/calendar/appinfo/app.php b/apps/calendar/appinfo/app.php index 3c8cc76133e..4fdba291262 100644 --- a/apps/calendar/appinfo/app.php +++ b/apps/calendar/appinfo/app.php @@ -9,7 +9,9 @@ OC::$CLASSPATH['OC_Calendar_Repeat'] = 'apps/calendar/lib/repeat.php'; OC::$CLASSPATH['OC_Calendar_Share'] = 'apps/calendar/lib/share.php'; OC::$CLASSPATH['OC_Search_Provider_Calendar'] = 'apps/calendar/lib/search.php'; OC::$CLASSPATH['OC_Calendar_Export'] = 'apps/calendar/lib/export.php'; +OC::$CLASSPATH['OC_Calendar_Import'] = 'apps/calendar/lib/import.php'; //General Hooks +OCP\Util::connectHook('OC_User', 'post_createUser', 'OC_Calendar_Hooks', 'createUser'); OCP\Util::connectHook('OC_User', 'post_deleteUser', 'OC_Calendar_Hooks', 'deleteUser'); //Repeating Events Hooks OCP\Util::connectHook('OC_Calendar', 'addEvent', 'OC_Calendar_Repeat', 'generate'); @@ -23,6 +25,8 @@ OCP\Util::connectHook('OC_Calendar', 'deleteCalendar', 'OC_Calendar_Share', 'pos OCP\Util::addscript('calendar','loader'); OCP\Util::addscript("3rdparty", "chosen/chosen.jquery.min"); OCP\Util::addStyle("3rdparty", "chosen/chosen"); +OCP\Util::addStyle('3rdparty/miniColors', 'jquery.miniColors'); +OCP\Util::addscript('3rdparty/miniColors', 'jquery.miniColors.min'); OCP\App::addNavigationEntry( array( 'id' => 'calendar_index', 'order' => 10, diff --git a/apps/calendar/appinfo/remote.php b/apps/calendar/appinfo/remote.php index 7ab546245f6..e8f9e80c7a8 100644 --- a/apps/calendar/appinfo/remote.php +++ b/apps/calendar/appinfo/remote.php @@ -34,6 +34,6 @@ $server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend,'ownCloud')); $server->addPlugin(new Sabre_CalDAV_Plugin()); $server->addPlugin(new Sabre_DAVACL_Plugin()); $server->addPlugin(new Sabre_DAV_Browser_Plugin(false)); // Show something in the Browser, but no upload - +$server->addPlugin(new Sabre_CalDAV_ICSExportPlugin()); // And off we go! $server->exec(); diff --git a/apps/calendar/appinfo/version b/apps/calendar/appinfo/version index 2eb3c4fe4ee..cb0c939a936 100644 --- a/apps/calendar/appinfo/version +++ b/apps/calendar/appinfo/version @@ -1 +1 @@ -0.5 +0.5.2 diff --git a/apps/calendar/css/import.css b/apps/calendar/css/import.css new file mode 100644 index 00000000000..8abdc3aecd1 --- /dev/null +++ b/apps/calendar/css/import.css @@ -0,0 +1,14 @@ +/** + * 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. + */ +#calendar_import_newcalform, #calendar_import_mergewarning, #calendar_import_process, #calendar_import_done{display:none;} +#calendar_import_process_message, #calendar_import_status, #calendar_import_form_message, #calendar_import_mergewarning{text-align:center;} +#calendar_import_form_message{font-weight: bold;} +#calendar_import_newcalendar{width:415px;float:right;} +#calendar_import_mergewarning{clear: both;} +#calendar_import_defaultcolors{clear:both;margin: 0 auto;text-align: center;} +.calendar_import_warning{border-color: #fc3333;} +.calendar-colorpicker-color{display:inline-block;width:20px;height:5px;margin: 0 auto;cursor:pointer;border:2px solid transparent;}
\ No newline at end of file diff --git a/apps/calendar/js/calendar.js b/apps/calendar/js/calendar.js index 004b2386fb1..25311fa0df4 100644 --- a/apps/calendar/js/calendar.js +++ b/apps/calendar/js/calendar.js @@ -622,18 +622,11 @@ Calendar={ drop:function(e){ var files = e.dataTransfer.files; for(var i = 0;i < files.length;i++){ - var file = files[i] + var file = files[i]; reader = new FileReader(); reader.onload = function(event){ - if(file.type != 'text/calendar'){ - $('#notification').html('At least one file don\'t seems to be a calendar file. File skipped.'); - $('#notification').slideDown(); - window.setTimeout(function(){$('#notification').slideUp();}, 5000); - return false; - }else{ - Calendar.UI.Drop.import(event.target.result); - $('#calendar_holder').fullCalendar('refetchEvents'); - } + Calendar.UI.Drop.import(event.target.result); + $('#calendar_holder').fullCalendar('refetchEvents'); } reader.readAsDataURL(file); } @@ -641,9 +634,13 @@ Calendar={ import:function(data){ $.post(OC.filePath('calendar', 'ajax/import', 'dropimport.php'), {'data':data},function(result) { if(result.status == 'success'){ + $('#calendar_holder').fullCalendar('addEventSource', result.eventSource); + $('#notification').html(result.message); + $('#notification').slideDown(); + window.setTimeout(function(){$('#notification').slideUp();}, 5000); return true; }else{ - $('#notification').html('ownCloud wasn\'t able to import at least one file. File skipped.'); + $('#notification').html(result.message); $('#notification').slideDown(); window.setTimeout(function(){$('#notification').slideUp();}, 5000); } diff --git a/apps/calendar/js/loader.js b/apps/calendar/js/loader.js index cef95afc3aa..b28d19ab00e 100644 --- a/apps/calendar/js/loader.js +++ b/apps/calendar/js/loader.js @@ -5,77 +5,175 @@ * See the COPYING-README file. */ Calendar_Import={ - importdialog: function(filename){ - var path = $('#dir').val(); - $('body').append('<div id="calendar_import"></div>'); - $('#calendar_import').load(OC.filePath('calendar', 'ajax/import', 'dialog.php'), {filename:filename, path:path}, function(){Calendar_Import.initdialog(filename);}); + Store:{ + file: '', + path: '', + id: 0, + method: '', + calname: '', + calcolor: '', + progresskey: '', + percentage: 0 }, - initdialog: function(filename){ - $('#calendar_import_dialog').dialog({ - width : 500, - close : function() { - $(this).dialog('destroy').remove(); - $('#calendar_import').remove(); + Dialog:{ + open: function(filename){ + OC.addStyle('calendar', 'import'); + Calendar_Import.Store.file = filename; + Calendar_Import.Store.path = $('#dir').val(); + $('body').append('<div id="calendar_import"></div>'); + $('#calendar_import').load(OC.filePath('calendar', 'ajax/import', 'dialog.php'), {filename:Calendar_Import.Store.file, path:Calendar_Import.Store.path},function(){ + Calendar_Import.Dialog.init(); + }); + }, + close: function(){ + Calendar_Import.reset(); + $(this).dialog('destroy').remove(); + $('#calendar_import_dialog').remove(); + }, + init: function(){ + //init dialog + $('#calendar_import_dialog').dialog({ + width : 500, + resizable: false, + close : function() { + Calendar_Import.Dialog.close(); + } + }); + //init buttons + $('#calendar_import_done').click(function(){ + Calendar_Import.Dialog.close(); + }); + $('#calendar_import_submit').click(function(){ + Calendar_Import.Core.process(); + }); + $('#calendar_import_mergewarning').click(function(){ + $('#calendar_import_newcalendar').attr('value', $('#calendar_import_availablename').val()); + Calendar_Import.Dialog.mergewarning($('#calendar_import_newcalendar').val()); + }); + $('#calendar_import_calendar').change(function(){ + if($('#calendar_import_calendar option:selected').val() == 'newcal'){ + $('#calendar_import_newcalform').slideDown('slow'); + Calendar_Import.Dialog.mergewarning($('#calendar_import_newcalendar').val()); + }else{ + $('#calendar_import_newcalform').slideUp('slow'); + $('#calendar_import_mergewarning').slideUp('slow'); + } + }); + $('#calendar_import_newcalendar').keyup(function(){ + Calendar_Import.Dialog.mergewarning($.trim($('#calendar_import_newcalendar').val())); + }); + $('#calendar_import_newcalendar_color').miniColors({ + letterCase: 'uppercase' + }); + $('.calendar-colorpicker-color').click(function(){ + var str = $(this).attr('rel'); + str = str.substr(1); + $('#calendar_import_newcalendar_color').attr('value', str); + $(".color-picker").miniColors('value', '#' + str); + }); + //init progressbar + $('#calendar_import_progressbar').progressbar({value: Calendar_Import.Store.percentage}); + Calendar_Import.Store.progresskey = $('#calendar_import_progresskey').val(); + }, + mergewarning: function(newcalname){ + $.post(OC.filePath('calendar', 'ajax/import', 'calendarcheck.php'), {calname: newcalname}, function(data){ + if(data.message == 'exists'){ + $('#calendar_import_mergewarning').slideDown('slow'); + }else{ + $('#calendar_import_mergewarning').slideUp('slow'); + } + }); + }, + update: function(){ + if(Calendar_Import.Store.percentage == 100){ + return false; } - }); - $('#import_done_button').click(function(){ - $('#calendar_import_dialog').dialog('destroy').remove(); - $('#calendar_import').remove(); - }); - $('#progressbar').progressbar({value: 0}); - $('#startimport').click(function(){ - var filename = $('#filename').val(); - var path = $('#path').val(); - var calid = $('#calendar option:selected').val(); - if($('#calendar option:selected').val() == 'newcal'){ - var method = 'new'; - var calname = $('#newcalendar').val(); - var calname = $.trim(calname); - if(calname == ''){ - $('#newcalendar').css('background-color', '#FF2626'); - $('#newcalendar').focus(function(){ - $('#newcalendar').css('background-color', '#F8F8F8'); - }); - return false; + $.post(OC.filePath('calendar', 'ajax/import', 'import.php'), {progresskey: Calendar_Import.Store.progresskey, getprogress: true}, function(data){ + if(data.status == 'success'){ + if(data.percent == null){ + return false; + } + Calendar_Import.Store.percentage = parseInt(data.percent); + $('#calendar_import_progressbar').progressbar('option', 'value', parseInt(data.percent)); + if(data.percent < 100 ){ + window.setTimeout('Calendar_Import.Dialog.update()', 250); + }else{ + $('#calendar_import_done').css('display', 'block'); + } + }else{ + $('#calendar_import_progressbar').progressbar('option', 'value', 100); + $('#calendar_import_progressbar > div').css('background-color', '#FF2626'); + $('#calendar_import_status').html(data.message); } - }else{ - var method = 'old'; + }); + return 0; + }, + warning: function(selector){ + $(selector).addClass('calendar_import_warning'); + $(selector).focus(function(){ + $(selector).removeClass('calendar_import_warning'); + }); + } + }, + Core:{ + process: function(){ + var validation = Calendar_Import.Core.prepare(); + if(validation){ + $('#calendar_import_form').css('display', 'none'); + $('#calendar_import_process').css('display', 'block'); + $('#calendar_import_newcalendar').attr('readonly', 'readonly'); + $('#calendar_import_calendar').attr('disabled', 'disabled'); + Calendar_Import.Core.send(); + window.setTimeout('Calendar_Import.Dialog.update()', 250); } - $('#newcalendar').attr('readonly', 'readonly'); - $('#calendar').attr('disabled', 'disabled'); - var progresskey = $('#progresskey').val(); - $.post(OC.filePath('calendar', 'ajax/import', 'import.php'), {progresskey: progresskey, method: String (method), calname: String (calname), path: String (path), file: String (filename), id: String (calid)}, function(data){ + }, + send: function(){ + $.post(OC.filePath('calendar', 'ajax/import', 'import.php'), + {progresskey: Calendar_Import.Store.progresskey, method: String (Calendar_Import.Store.method), calname: String (Calendar_Import.Store.calname), path: String (Calendar_Import.Store.path), file: String (Calendar_Import.Store.file), id: String (Calendar_Import.Store.id), calcolor: String (Calendar_Import.Store.calcolor)}, function(data){ if(data.status == 'success'){ - $('#progressbar').progressbar('option', 'value', 100); - $('#import_done').css('display', 'block'); + $('#calendar_import_progressbar').progressbar('option', 'value', 100); + Calendar_Import.Store.percentage = 100; + $('#calendar_import_done').css('display', 'block'); + $('#calendar_import_status').html(data.message); + }else{ + $('#calendar_import_progressbar').progressbar('option', 'value', 100); + $('#calendar_import_progressbar > div').css('background-color', '#FF2626'); + $('#calendar_import_status').html(data.message); } }); - $('#form_container').css('display', 'none'); - $('#progressbar_container').css('display', 'block'); - window.setTimeout('Calendar_Import.getimportstatus(\'' + progresskey + '\')', 500); - }); - $('#calendar').change(function(){ - if($('#calendar option:selected').val() == 'newcal'){ - $('#newcalform').slideDown('slow'); + }, + prepare: function(){ + Calendar_Import.Store.id = $('#calendar_import_calendar option:selected').val(); + if($('#calendar_import_calendar option:selected').val() == 'newcal'){ + Calendar_Import.Store.method = 'new'; + Calendar_Import.Store.calname = $.trim($('#calendar_import_newcalendar').val()); + if(Calendar_Import.Store.calname == ''){ + Calendar_Import.Dialog.warning('#calendar_import_newcalendar'); + return false; + } + Calendar_Import.Store.calcolor = $.trim($('#calendar_import_newcalendar_color').val()); + if(Calendar_Import.Store.calcolor == ''){ + Calendar_Import.Store.calcolor = $('.calendar-colorpicker-color:first').attr('rel'); + } }else{ - $('#newcalform').slideUp('slow'); + Calendar_Import.Store.method = 'old'; } - }); + return true; + } }, - getimportstatus: function(progresskey){ - $.post(OC.filePath('calendar', 'ajax/import', 'import.php'), {progress:1,progresskey: progresskey}, function(percent){ - $('#progressbar').progressbar('option', 'value', parseInt(percent)); - if(percent < 100){ - window.setTimeout('Calendar_Import.getimportstatus(\'' + progresskey + '\')', 500); - }else{ - $('#import_done').css('display', 'block'); - } - }); + reset: function(){ + Calendar_Import.Store.file = ''; + Calendar_Import.Store.path = ''; + Calendar_Import.Store.id = 0; + Calendar_Import.Store.method = ''; + Calendar_Import.Store.calname = ''; + Calendar_Import.Store.progresskey = ''; + Calendar_Import.Store.percentage = 0; } } $(document).ready(function(){ if(typeof FileActions !== 'undefined'){ - FileActions.register('text/calendar','importcal', '', Calendar_Import.importdialog); - FileActions.setDefault('text/calendar','importcal'); + FileActions.register('text/calendar','importCalendar', '', Calendar_Import.Dialog.open); + FileActions.setDefault('text/calendar','importCalendar'); }; }); diff --git a/apps/calendar/js/settings.js b/apps/calendar/js/settings.js index 03e4217573d..60741f2b6fc 100644 --- a/apps/calendar/js/settings.js +++ b/apps/calendar/js/settings.js @@ -34,6 +34,7 @@ $(document).ready(function(){ $.getJSON(OC.filePath('calendar', 'ajax/settings', 'timeformat.php'), function(jsondata, status) { $('#' + jsondata.timeformat).attr('selected',true); $('#timeformat').chosen(); + $('#timeformat_chzn').css('width', '100px'); }); $.getJSON(OC.filePath('calendar', 'ajax/settings', 'gettimezonedetection.php'), function(jsondata, status){ if(jsondata.detection == 'true'){ @@ -43,6 +44,7 @@ $(document).ready(function(){ $.getJSON(OC.filePath('calendar', 'ajax/settings', 'getfirstday.php'), function(jsondata, status) { $('#' + jsondata.firstday).attr('selected',true); $('#firstday').chosen(); + $('#firstday_chzn').css('width', '100px'); }); $('#cleancalendarcache').click(function(){ $.getJSON(OC.filePath('calendar', 'ajax/cache', 'rescan.php'), function(){ @@ -55,7 +57,7 @@ function calendarcachecheck(){ $.getJSON(OC.filePath('calendar', 'ajax/cache', 'status.php'), function(jsondata, status) { $('#cleancalendarcache').attr('title', jsondata.l10n.text); if(jsondata.status == 'success'){ - $('#cleancalendarcache').css('background', '#90EE90'); + $('#cleancalendarcache').css('background', '#F8F8F8'); $('#cleancalendarcache').css('color', '#333'); $('#cleancalendarcache').css('text-shadow', '#fff 0 1px 0'); }else{ diff --git a/apps/calendar/lib/app.php b/apps/calendar/lib/app.php index 1a13f2958c0..29e5ab5b0c8 100644 --- a/apps/calendar/lib/app.php +++ b/apps/calendar/lib/app.php @@ -9,7 +9,7 @@ * This class manages our app actions */ OC_Calendar_App::$l10n = new OC_L10N('calendar'); -OC_Calendar_App::$tz = OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); +OC_Calendar_App::$tz = OC_Calendar_App::getTimezone(); class OC_Calendar_App{ const CALENDAR = 'calendar'; const EVENT = 'event'; @@ -282,7 +282,17 @@ class OC_Calendar_App{ public static function getWeekofMonth(){ return OC_Calendar_Object::getWeekofMonth(self::$l10n); } - + + /** + * @return (string) $timezone as set by user or the default timezone + */ + public static function getTimezone() { + return OCP\Config::getUserValue(OCP\User::getUser(), + 'calendar', + 'timezone', + date_default_timezone_get()); + } + /** * @brief checks the access for a calendar / an event * @param (int) $id - id of the calendar / event diff --git a/apps/calendar/lib/calendar.php b/apps/calendar/lib/calendar.php index 128b55c48e9..7778242464c 100644 --- a/apps/calendar/lib/calendar.php +++ b/apps/calendar/lib/calendar.php @@ -267,8 +267,42 @@ class OC_Calendar_Calendar{ 'url' => OCP\Util::linkTo('calendar', 'ajax/events.php').'?calendar_id='.$calendar['id'], 'backgroundColor' => $calendar['calendarcolor'], 'borderColor' => '#888', - 'textColor' => 'black', + 'textColor' => self::generateTextColor($calendar['calendarcolor']), 'cache' => true, ); } + + /* + * @brief checks if a calendar name is available for a user + * @param string $calendarname + * @param string $userid + * @return boolean + */ + public static function isCalendarNameavailable($calendarname, $userid){ + $calendars = self::allCalendars($userid); + foreach($calendars as $calendar){ + if($calendar['displayname'] == $calendarname){ + return false; + } + } + return true; + } + + /* + * @brief generates the text color for the calendar + * @param string $calendarcolor rgb calendar color code in hex format (with or without the leading #) + * (this function doesn't pay attention on the alpha value of rgba color codes) + * @return boolean + */ + public static function generateTextColor($calendarcolor){ + if(substr_count($calendarcolor, '#') == 1){ + $calendarcolor = substr($calendarcolor,1); + } + $red = hexdec(substr($calendarcolor,0,2)); + $green = hexdec(substr($calendarcolor,2,2)); + $blue = hexdec(substr($calendarcolor,2,2)); + //recommendation by W3C + $computation = ((($red * 299) + ($green * 587) + ($blue * 114)) / 1000); + return ($computation > 130)?'#000000':'#FAFAFA'; + } } diff --git a/apps/calendar/lib/hooks.php b/apps/calendar/lib/hooks.php index 328d2951d23..bc0b02c62b8 100644 --- a/apps/calendar/lib/hooks.php +++ b/apps/calendar/lib/hooks.php @@ -11,7 +11,18 @@ */ class OC_Calendar_Hooks{ /** - * @brief Deletes all Addressbooks of a certain user + * @brief Creates default calendar for a user + * @param paramters parameters from postCreateUser-Hook + * @return array + */ + public static function createUser($parameters) { + OC_Calendar_Calendar::addCalendar($parameters['uid'],'Default calendar'); + + return true; + } + + /** + * @brief Deletes all calendars of a certain user * @param paramters parameters from postDeleteUser-Hook * @return array */ diff --git a/apps/calendar/lib/import.php b/apps/calendar/lib/import.php new file mode 100644 index 00000000000..d36891cb2b9 --- /dev/null +++ b/apps/calendar/lib/import.php @@ -0,0 +1,334 @@ +<?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. + */ +/* + * This class does import and converts all times to the users current timezone + */ +class OC_Calendar_Import{ + /* + * @brief counts the absolute number of parsed elements + */ + private $abscount; + + /* + * @brief var saves if the percentage should be saved with OC_Cache + */ + private $cacheprogress; + + /* + * @brief Sabre_VObject_Component_VCalendar object - for documentation see http://code.google.com/p/sabredav/wiki/Sabre_VObject_Component_VCalendar + */ + private $calobject; + + /* + * @brief var counts the number of imported elements + */ + private $count; + + /* + * @brief var to check if errors happend while initialization + */ + private $error; + + /* + * @brief var saves the ical string that was submitted with the __construct function + */ + private $ical; + + /* + * @brief calendar id for import + */ + private $id; + + /* + * @brief var saves the percentage of the import's progress + */ + private $progress; + + /* + * @brief var saves the key for the percentage of the import's progress + */ + private $progresskey; + + /* + * @brief var saves the timezone the events shell converted to + */ + private $tz; + + /* + * @brief var saves the userid + */ + private $userid; + + /* + * public methods + */ + + /* + * @brief does general initialization for import object + * @param string $calendar content of ical file + * @param string $tz timezone of the user + * @return boolean + */ + public function __construct($ical){ + $this->error = null; + $this->ical = $ical; + $this->abscount = 0; + $this->count = 0; + try{ + $this->calobject = OC_VObject::parse($this->ical); + }catch(Exception $e){ + //MISSING: write some log + $this->error = true; + return false; + } + return true; + } + + /* + * @brief imports a calendar + * @return boolean + */ + public function import(){ + if(!$this->isValid()){ + return false; + } + $numofcomponents = count($this->calobject->getComponents()); + foreach($this->calobject->getComponents() as $object){ + if(!($object instanceof Sabre_VObject_Component_VEvent) && !($object instanceof Sabre_VObject_Component_VJournal) && !($object instanceof Sabre_VObject_Component_VTodo)){ + continue; + } + $dtend = OC_Calendar_Object::getDTEndFromVEvent($object); + $object->DTSTART->getDateTime()->setTimezone(new DateTimeZone($this->tz)); + $object->DTEND->setDateTime($dtend->getDateTime(), $object->DTSTART->getDateType()); + $object->DTEND->getDateTime()->setTimezone(new DateTimeZone($this->tz)); + $vcalendar = $this->createVCalendar($object->serialize()); + $insertid = OC_Calendar_Object::add($this->id, $vcalendar); + $this->abscount++; + if($this->isDuplicate($insertid)){ + OC_Calendar_Object::delete($insertid); + }else{ + $this->count++; + } + $this->updateProgress(intval(($this->abscount / $numofcomponents)*100)); + } + OC_Cache::remove($this->progresskey); + return true; + } + + /* + * @brief sets the timezone + * @return boolean + */ + public function setTimeZone($tz){ + $this->tz = $tz; + return true; + } + + /* + * @brief sets the progresskey + * @return boolean + */ + public function setProgresskey($progresskey){ + $this->progresskey = $progresskey; + return true; + } + + /* + * @brief checks if something went wrong while initialization + * @return boolean + */ + public function isValid(){ + if(is_null($this->error)){ + return true; + } + return false; + } + + /* + * @brief returns the percentage of progress + * @return integer + */ + public function getProgress(){ + return $this->progress; + } + + /* + * @brief enables the cache for the percentage of progress + * @return boolean + */ + public function enableProgressCache(){ + $this->cacheprogress = true; + return true; + } + + /* + * @brief disables the cache for the percentage of progress + * @return boolean + */ + public function disableProgressCache(){ + $this->cacheprogress = false; + return false; + } + + /* + * @brief generates a new calendar name + * @return string + */ + public function createCalendarName(){ + $calendars = OC_Calendar_Calendar::allCalendars($this->userid); + $calendarname = $guessedcalendarname = !is_null($this->guessCalendarName())?($this->guessCalendarName()):(OC_Calendar_App::$l10n->t('New Calendar')); + $i = 1; + while(!OC_Calendar_Calendar::isCalendarNameavailable($calendarname, $this->userid)){ + $calendarname = $guessedcalendarname . ' (' . $i . ')'; + $i++; + } + return $calendarname; + } + + /* + * @brief generates a new calendar color + * @return string + */ + public function createCalendarColor(){ + if(is_null($this->guessCalendarColor())){ + return '#9fc6e7'; + } + return $this->guessCalendarColor(); + } + + /* + * @brief sets the id for the calendar + * @param integer $id of the calendar + * @return boolean + */ + public function setCalendarID($id){ + $this->id = $id; + return true; + } + + /* + * @brief sets the userid to import the calendar + * @param string $id of the user + * @return boolean + */ + public function setUserID($userid){ + $this->userid = $userid; + return true; + } + + /* + * @brief returns the private + * @param string $id of the user + * @return boolean + */ + public function getCount(){ + return $this->count; + } + + /* + * private methods + */ + + /* + * @brief generates an unique ID + * @return string + */ + //private function createUID(){ + // return substr(md5(rand().time()),0,10); + //} + + /* + * @brief checks is the UID is already in use for another event + * @param string $uid uid to check + * @return boolean + */ + //private function isUIDAvailable($uid){ + // + //} + + /* + * @brief generates a proper VCalendar string + * @param string $vobject + * @return string + */ + private function createVCalendar($vobject){ + if(is_object($vobject)){ + $vobject = @$vobject->serialize(); + } + $vcalendar = "BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:ownCloud Calendar " . OCP\App::getAppVersion('calendar') . "\n"; + $vcalendar .= $vobject; + $vcalendar .= "END:VCALENDAR"; + return $vcalendar; + } + + /* + * @brief checks if an event already exists in the user's calendars + * @param integer $insertid id of the new object + * @return boolean + */ + private function isDuplicate($insertid){ + $newobject = OC_Calendar_Object::find($insertid); + $stmt = OCP\DB::prepare('SELECT COUNT(*) as count FROM *PREFIX*calendar_objects WHERE objecttype=? AND startdate=? AND enddate=? AND repeating=? AND summary=? AND calendardata=?'); + $result = $stmt->execute(array($newobject['objecttype'],$newobject['startdate'],$newobject['enddate'],$newobject['repeating'],$newobject['summary'],$newobject['calendardata'])); + $result = $result->fetchRow(); + if($result['count'] >= 2){ + return true; + } + return false; + } + + /* + * @brief updates the progress var + * @param integer $percentage + * @return boolean + */ + private function updateProgress($percentage){ + $this->progress = $percentage; + if($this->cacheprogress){ + OC_Cache::set($this->progresskey, $this->progress, 300); + } + return true; + } + + /* + * public methods for (pre)rendering of X-... Attributes + */ + + /* + * @brief guesses the calendar color + * @return mixed - string or boolean + */ + public function guessCalendarColor(){ + if(!is_null($this->calobject->__get('X-APPLE-CALENDAR-COLOR'))){ + return $this->calobject->__get('X-APPLE-CALENDAR-COLOR'); + } + return null; + } + + /* + * @brief guesses the calendar description + * @return mixed - string or boolean + */ + public function guessCalendarDescription(){ + if(!is_null($this->calobject->__get('X-WR-CALDESC'))){ + return $this->calobject->__get('X-WR-CALDESC'); + } + return null; + } + + /* + * @brief guesses the calendar name + * @return mixed - string or boolean + */ + public function guessCalendarName(){ + if(!is_null($this->calobject->__get('X-WR-CALNAME'))){ + return $this->calobject->__get('X-WR-CALNAME'); + } + return null; + } +} diff --git a/apps/calendar/lib/object.php b/apps/calendar/lib/object.php index 140542bf4fb..34676830205 100644 --- a/apps/calendar/lib/object.php +++ b/apps/calendar/lib/object.php @@ -856,7 +856,7 @@ class OC_Calendar_Object{ $vevent->setDateTime('DTSTART', $start, Sabre_VObject_Property_DateTime::DATE); $vevent->setDateTime('DTEND', $end, Sabre_VObject_Property_DateTime::DATE); }else{ - $timezone = OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); + $timezone = OC_Calendar_App::getTimezone(); $timezone = new DateTimeZone($timezone); $start = new DateTime($from.' '.$fromtime, $timezone); $end = new DateTime($to.' '.$totime, $timezone); diff --git a/apps/calendar/lib/search.php b/apps/calendar/lib/search.php index 560330f65e9..551489672b9 100644 --- a/apps/calendar/lib/search.php +++ b/apps/calendar/lib/search.php @@ -12,7 +12,7 @@ class OC_Search_Provider_Calendar extends OC_Search_Provider{ }else{ $searchquery[] = $query; } - $user_timezone = OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); + $user_timezone = OC_Calendar_App::getTimezone(); $l = new OC_l10n('calendar'); foreach($calendars as $calendar){ $objects = OC_Calendar_Object::all($calendar['id']); diff --git a/apps/calendar/settings.php b/apps/calendar/settings.php index a18b1ca9f42..eaa20c6c9b4 100644 --- a/apps/calendar/settings.php +++ b/apps/calendar/settings.php @@ -10,6 +10,7 @@ $tmpl = new OCP\Template( 'calendar', 'settings'); $timezone=OCP\Config::getUserValue(OCP\USER::getUser(),'calendar','timezone',''); $tmpl->assign('timezone',$timezone); $tmpl->assign('timezones',DateTimeZone::listIdentifiers()); +$tmpl->assign('calendars', OC_Calendar_Calendar::allCalendars(OCP\USER::getUser()), false); OCP\Util::addscript('calendar','settings'); diff --git a/apps/calendar/templates/calendar.php b/apps/calendar/templates/calendar.php index 2246a0178e3..29b9bf6bc54 100644 --- a/apps/calendar/templates/calendar.php +++ b/apps/calendar/templates/calendar.php @@ -2,10 +2,10 @@ var defaultView = '<?php echo OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'currentview', 'month') ?>'; var eventSources = <?php echo json_encode($_['eventSources']) ?>; var categories = <?php echo json_encode($_['categories']); ?>; - var dayNames = <?php echo json_encode($l->tA(array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'))) ?>; - var dayNamesShort = <?php echo json_encode($l->tA(array('Sun.', 'Mon.', 'Tue.', 'Wed.', 'Thu.', 'Fri.', 'Sat.'))) ?>; - var monthNames = <?php echo json_encode($l->tA(array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'))) ?>; - var monthNamesShort = <?php echo json_encode($l->tA(array('Jan.', 'Feb.', 'Mar.', 'Apr.', 'May.', 'Jun.', 'Jul.', 'Aug.', 'Sep.', 'Oct.', 'Nov.', 'Dec.'))) ?>; + var dayNames = new Array("<?php echo $l -> t("Sunday");?>", "<?php echo $l -> t("Monday");?>", "<?php echo $l -> t("Tuesday");?>", "<?php echo $l -> t("Wednesday");?>", "<?php echo $l -> t("Thursday");?>", "<?php echo $l -> t("Friday");?>", "<?php echo $l -> t("Saturday");?>"); + var dayNamesShort = new Array("<?php echo $l -> t("Sun.");?>", "<?php echo $l -> t("Mon.");?>", "<?php echo $l -> t("Tue.");?>", "<?php echo $l -> t("Wed.");?>", "<?php echo $l -> t("Thu.");?>", "<?php echo $l -> t("Fri.");?>", "<?php echo $l -> t("Sat.");?>"); + var monthNames = new Array("<?php echo $l -> t("January");?>", "<?php echo $l -> t("February");?>", "<?php echo $l -> t("March");?>", "<?php echo $l -> t("April");?>", "<?php echo $l -> t("May");?>", "<?php echo $l -> t("June");?>", "<?php echo $l -> t("July");?>", "<?php echo $l -> t("August");?>", "<?php echo $l -> t("September");?>", "<?php echo $l -> t("October");?>", "<?php echo $l -> t("November");?>", "<?php echo $l -> t("December");?>"); + var monthNamesShort = new Array("<?php echo $l -> t("Jan.");?>", "<?php echo $l -> t("Feb.");?>", "<?php echo $l -> t("Mar.");?>", "<?php echo $l -> t("Apr.");?>", "<?php echo $l -> t("May.");?>", "<?php echo $l -> t("Jun.");?>", "<?php echo $l -> t("Jul.");?>", "<?php echo $l -> t("Aug.");?>", "<?php echo $l -> t("Sep.");?>", "<?php echo $l -> t("Oct.");?>", "<?php echo $l -> t("Nov.");?>", "<?php echo $l -> t("Dec.");?>"); var agendatime = '<?php echo ((int) OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timeformat', '24') == 24 ? 'HH:mm' : 'hh:mm tt'); ?>{ - <?php echo ((int) OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timeformat', '24') == 24 ? 'HH:mm' : 'hh:mm tt'); ?>}'; var defaulttime = '<?php echo ((int) OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timeformat', '24') == 24 ? 'HH:mm' : 'hh:mm tt'); ?>'; var allDayText = '<?php echo addslashes($l->t('All day')) ?>'; diff --git a/apps/calendar/templates/part.import.php b/apps/calendar/templates/part.import.php index 70ff9612157..2ce3cc34239 100644 --- a/apps/calendar/templates/part.import.php +++ b/apps/calendar/templates/part.import.php @@ -1,30 +1,58 @@ -<div id="calendar_import_dialog" title="<?php echo $l->t("Import a calendar file"); ?>"> -<div id="form_container"> -<input type="hidden" id="filename" value="<?php echo $_['filename'];?>"> -<input type="hidden" id="path" value="<?php echo $_['path'];?>"> -<input type="hidden" id="progresskey" value="<?php echo rand() ?>"> -<p style="text-align:center;"><b><?php echo $l->t('Please choose the calendar'); ?></b></p> -<select style="width:100%;" id="calendar" name="calendar"> <?php +//Prerendering for iCalendar file +$file = OC_Filesystem::file_get_contents($_['path'] . '/' . $_['filename']); +if(!$file){ + OCP\JSON::error(array('error'=>'404')); +} +$import = new OC_Calendar_Import($file); +$import->setUserID(OCP\User::getUser()); +$newcalendarname = strip_tags($import->createCalendarName()); +$guessedcalendarname = strip_tags($import->guessCalendarName()); +$calendarcolor = strip_tags($import->createCalendarColor()); +//loading calendars for select box $calendar_options = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser()); $calendar_options[] = array('id'=>'newcal', 'displayname'=>$l->t('create a new calendar')); -for($i = 0;$i<count($calendar_options);$i++){ - $calendar_options[$i]['displayname'] = $calendar_options[$i]['displayname']; -} -echo OCP\html_select_options($calendar_options, $calendar_options[0]['id'], array('value'=>'id', 'label'=>'displayname')); +$defaultcolors = OC_Calendar_Calendar::getCalendarColorOptions(); ?> -</select> -<div id="newcalform" style="display: none;"> - <input type="text" style="width: 97%;" placeholder="<?php echo $l->t('Name of new calendar'); ?>" id="newcalendar" name="newcalendar"> -</div> -<input type="button" value="<?php echo $l->t("Import");?>!" id="startimport"> -</div> -<div id="progressbar_container" style="display: none"> -<p style="text-align:center;"><b><?php echo $l->t('Importing calendar'); ?></b></p> -<div id="progressbar"></div> -<div id="import_done" style="display: none;"> -<p style="text-align:center;"><b><?php echo $l->t('Calendar imported successfully'); ?></b></p> -<input type="button" value="<?php echo $l->t('Close Dialog'); ?>" id="import_done_button"> +<div id="calendar_import_dialog" title="<?php echo $l->t("Import a calendar file");?>"> +<div id="calendar_import_form"> + <form> + <input type="hidden" id="calendar_import_filename" value="<?php echo $_['filename'];?>"> + <input type="hidden" id="calendar_import_path" value="<?php echo $_['path'];?>"> + <input type="hidden" id="calendar_import_progresskey" value="<?php echo rand() ?>"> + <input type="hidden" id="calendar_import_availablename" value="<?php echo $newcalendarname ?>"> + <div id="calendar_import_form_message"><?php echo $l->t('Please choose a calendar'); ?></div> + <select style="width:100%;" id="calendar_import_calendar" name="calendar_import_calendar"> + <?php + for($i = 0;$i<count($calendar_options);$i++){ + $calendar_options[$i]['displayname'] = $calendar_options[$i]['displayname']; + } + echo OCP\html_select_options($calendar_options, $calendar_options[0]['id'], array('value'=>'id', 'label'=>'displayname')); + ?> + </select> + <br><br> + <div id="calendar_import_newcalform"> + <input id="calendar_import_newcalendar_color" class="color-picker" type="hidden" size="6" value="<?php echo substr($calendarcolor,1); ?>"> + <input id="calendar_import_newcalendar" class="" type="text" placeholder="<?php echo $l->t('Name of new calendar'); ?>" value="<?php echo $guessedcalendarname ?>"><br> + <div id="calendar_import_defaultcolors"> + <?php + foreach($defaultcolors as $color){ + echo '<span class="calendar-colorpicker-color" rel="' . $color . '" style="background-color: ' . $color . ';"></span>'; + } + ?> + </div> + <!--<input id="calendar_import_generatename" type="button" class="button" value="<?php echo $l->t('Take an available name!'); ?>"><br>--> + <div id="calendar_import_mergewarning" class="hint"><?php echo $l->t('A Calendar with this name already exists. If you continue anyhow, these calendars will be merged.'); ?></div> + </div> + <input id="calendar_import_submit" type="button" class="button" value="» <?php echo $l->t('Import'); ?> »" id="startimport"> + <form> </div> +<div id="calendar_import_process"> + <div id="calendar_import_process_message"></div> + <div id="calendar_import_progressbar"></div> + <br> + <div id="calendar_import_status" class="hint"></div> + <br> + <input id="calendar_import_done" type="button" value="<?php echo $l->t('Close Dialog'); ?>"> </div> </div>
\ No newline at end of file diff --git a/apps/calendar/templates/settings.php b/apps/calendar/templates/settings.php index 6d018f15110..28c357621a8 100644 --- a/apps/calendar/templates/settings.php +++ b/apps/calendar/templates/settings.php @@ -56,6 +56,12 @@ <dd><code><?php echo OCP\Util::linkToRemote('caldav'); ?></code></dd> <dt><?php echo $l->t('iOS/OS X'); ?></dt> <dd><code><?php echo OCP\Util::linkToRemote('caldav'); ?>principals/<?php echo OCP\USER::getUser(); ?></code>/</dd> + <dt><?php echo $l->t('Read only iCalendar link(s)'); ?></dt> + <dd> + <?php foreach($_['calendars'] as $calendar) { ?> + <a href="<?php echo OCP\Util::linkToRemote('caldav').'calendars/'.OCP\USER::getUser().'/'.rawurlencode($calendar['uri']) ?>?export"><?php echo $calendar['displayname'] ?></a><br /> + <?php } ?> + </dd> </dl> </fieldset> </form> diff --git a/apps/contacts/ajax/activation.php b/apps/contacts/ajax/activation.php index 74cb738ab8f..69173c54c44 100644 --- a/apps/contacts/ajax/activation.php +++ b/apps/contacts/ajax/activation.php @@ -16,8 +16,12 @@ $bookid = $_POST['bookid']; $book = OC_Contacts_App::getAddressbook($bookid);// is owner access check if(!OC_Contacts_Addressbook::setActive($bookid, $_POST['active'])) { - OCP\Util::writeLog('contacts','ajax/activation.php: Error activating addressbook: '.$bookid, OCP\Util::ERROR); - OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error (de)activating addressbook.')))); + OCP\Util::writeLog('contacts', + 'ajax/activation.php: Error activating addressbook: '. $bookid, + OCP\Util::ERROR); + OCP\JSON::error(array( + 'data' => array( + 'message' => OC_Contacts_App::$l10n->t('Error (de)activating addressbook.')))); exit(); } diff --git a/apps/contacts/ajax/addaddressbook.php b/apps/contacts/ajax/addaddressbook.php new file mode 100644 index 00000000000..40773704bb4 --- /dev/null +++ b/apps/contacts/ajax/addaddressbook.php @@ -0,0 +1,37 @@ +<?php +/** + * Copyright (c) 2011-2012 Thomas Tanghus <thomas@tanghus.net> + * 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. + */ + + +// Check if we are a user +OCP\JSON::checkLoggedIn(); +OCP\JSON::checkAppEnabled('contacts'); +OCP\JSON::callCheck(); +require_once 'loghandler.php'; + +debug('name: '.$_POST['name']); + +$userid = OCP\USER::getUser(); +$name = isset($_POST['name'])?trim(strip_tags($_POST['name'])):null; +$description = isset($_POST['description']) + ? trim(strip_tags($_POST['description'])) + : null; + +if(is_null($name)) { + bailOut('Cannot add addressbook with an empty name.'); +} +$bookid = OC_Contacts_Addressbook::add($userid, $name, $description); +if(!$bookid) { + bailOut('Error adding addressbook: '.$name); +} + +if(!OC_Contacts_Addressbook::setActive($bookid, 1)) { + bailOut('Error activating addressbook.'); +} +$addressbook = OC_Contacts_App::getAddressbook($bookid); +OCP\JSON::success(array('data' => $addressbook)); diff --git a/apps/contacts/ajax/addbook.php b/apps/contacts/ajax/addbook.php index 70f47cc8123..751185b44fd 100644 --- a/apps/contacts/ajax/addbook.php +++ b/apps/contacts/ajax/addbook.php @@ -17,4 +17,3 @@ $tmpl = new OCP\Template('contacts', 'part.editaddressbook'); $tmpl->assign('new', true); $tmpl->assign('addressbook', $book); $tmpl->printPage(); -?> diff --git a/apps/contacts/ajax/addcontact.php b/apps/contacts/ajax/addcontact.php index 12f7bb9db96..6aaf5a9df35 100644 --- a/apps/contacts/ajax/addcontact.php +++ b/apps/contacts/ajax/addcontact.php @@ -37,13 +37,15 @@ $n = trim($_POST['n']); $vcard = new OC_VObject('VCARD'); $vcard->setUID(); -$vcard->setString('FN',$fn); -$vcard->setString('N',$n); +$vcard->setString('FN', $fn); +$vcard->setString('N', $n); $id = OC_Contacts_VCard::add($aid, $vcard, null, $isnew); if(!$id) { - OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('There was an error adding the contact.')))); - OCP\Util::writeLog('contacts','ajax/addcontact.php: Recieved non-positive ID on adding card: '.$id, OCP\Util::ERROR); + OCP\JSON::error(array( + 'data' => array( + 'message' => OC_Contacts_App::$l10n->t('There was an error adding the contact.')))); + OCP\Util::writeLog('contacts', 'ajax/addcontact.php: Recieved non-positive ID on adding card: '.$id, OCP\Util::ERROR); exit(); } diff --git a/apps/contacts/ajax/addproperty.php b/apps/contacts/ajax/addproperty.php index 1b6db0c8f81..58b857547fb 100644 --- a/apps/contacts/ajax/addproperty.php +++ b/apps/contacts/ajax/addproperty.php @@ -25,7 +25,7 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('contacts'); OCP\JSON::callCheck(); -require_once('loghandler.php'); +require_once 'loghandler.php'; $id = isset($_POST['id'])?$_POST['id']:null; $name = isset($_POST['name'])?$_POST['name']:null; @@ -33,22 +33,27 @@ $value = isset($_POST['value'])?$_POST['value']:null; $parameters = isset($_POST['parameters'])?$_POST['parameters']:array(); $vcard = OC_Contacts_App::getContactVCard($id); +$l10n = OC_Contacts_App::$l10n; if(!$name) { - bailOut(OC_Contacts_App::$l10n->t('element name is not set.')); + bailOut($l10n->t('element name is not set.')); } if(!$id) { - bailOut(OC_Contacts_App::$l10n->t('id is not set.')); + bailOut($l10n->t('id is not set.')); } if(!$vcard) { - bailOut(OC_Contacts_App::$l10n->t('Could not parse contact: ').$id); + bailOut($l10n->t('Could not parse contact: ').$id); } -if(!is_array($value)){ +if(!is_array($value)) { $value = trim($value); - if(!$value && in_array($name, array('TEL', 'EMAIL', 'ORG', 'BDAY', 'URL', 'NICKNAME', 'NOTE'))) { - bailOut(OC_Contacts_App::$l10n->t('Cannot add empty property.')); + if(!$value + && in_array( + $name, + array('TEL', 'EMAIL', 'ORG', 'BDAY', 'URL', 'NICKNAME', 'NOTE')) + ) { + bailOut($l10n->t('Cannot add empty property.')); } } elseif($name === 'ADR') { // only add if non-empty elements. $empty = true; @@ -59,7 +64,7 @@ if(!is_array($value)){ } } if($empty) { - bailOut(OC_Contacts_App::$l10n->t('At least one of the address fields has to be filled out.')); + bailOut($l10n->t('At least one of the address fields has to be filled out.')); } } @@ -68,12 +73,14 @@ $current = $vcard->select($name); foreach($current as $item) { $tmpvalue = (is_array($value)?implode(';', $value):$value); if($tmpvalue == $item->value) { - bailOut(OC_Contacts_App::$l10n->t('Trying to add duplicate property: '.$name.': '.$tmpvalue)); + bailOut($l10n->t('Trying to add duplicate property: '.$name.': '.$tmpvalue)); } } if(is_array($value)) { - ksort($value); // NOTE: Important, otherwise the compound value will be set in the order the fields appear in the form! + // NOTE: Important, otherwise the compound value will + // be set in the order the fields appear in the form! + ksort($value); $value = array_map('strip_tags', $value); } else { $value = strip_tags($value); @@ -116,24 +123,25 @@ switch($name) { $line = count($vcard->children) - 1; -// Apparently Sabre_VObject_Parameter doesn't do well with multiple values or I don't know how to do it. Tanghus. +// Apparently Sabre_VObject_Parameter doesn't do well with +// multiple values or I don't know how to do it. Tanghus. foreach ($parameters as $key=>$element) { if(is_array($element) && strtoupper($key) == 'TYPE') { // NOTE: Maybe this doesn't only apply for TYPE? // And it probably shouldn't be done here anyways :-/ - foreach($element as $e){ - if($e != '' && !is_null($e)){ - $vcard->children[$line]->parameters[] = new Sabre_VObject_Parameter($key,$e); + foreach($element as $e) { + if($e != '' && !is_null($e)) { + $vcard->children[$line]->parameters[] = new Sabre_VObject_Parameter($key, $e); } } } else { - $vcard->children[$line]->parameters[] = new Sabre_VObject_Parameter($key,$element); + $vcard->children[$line]->parameters[] = new Sabre_VObject_Parameter($key, $element); } } $checksum = md5($vcard->children[$line]->serialize()); -if(!OC_Contacts_VCard::edit($id,$vcard)) { - bailOut(OC_Contacts_App::$l10n->t('Error adding contact property: '.$name)); +if(!OC_Contacts_VCard::edit($id, $vcard)) { + bailOut($l10n->t('Error adding contact property: '.$name)); } OCP\JSON::success(array('data' => array( 'checksum' => $checksum ))); diff --git a/apps/contacts/ajax/categories/categoriesfor.php b/apps/contacts/ajax/categories/categoriesfor.php index 846af300de8..8391b14b545 100644 --- a/apps/contacts/ajax/categories/categoriesfor.php +++ b/apps/contacts/ajax/categories/categoriesfor.php @@ -12,17 +12,23 @@ OCP\JSON::checkAppEnabled('contacts'); $id = isset($_GET['id'])?$_GET['id']:null; if(is_null($id)) { - OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('No ID provided')))); + OCP\JSON::error(array( + 'data' => array( + 'message' => OC_Contacts_App::$l10n->t('No ID provided')))); exit(); } $vcard = OC_Contacts_App::getContactVCard( $id ); foreach($vcard->children as $property){ - //OCP\Util::writeLog('contacts','ajax/categories/checksumfor.php: '.$property->name, OCP\Util::DEBUG); if($property->name == 'CATEGORIES') { $checksum = md5($property->serialize()); - OCP\JSON::success(array('data' => array('value'=>$property->value, 'checksum'=>$checksum))); + OCP\JSON::success(array( + 'data' => array( + 'value' => $property->value, + 'checksum' => $checksum, + ))); exit(); } } -OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error setting checksum.')))); -?> +OCP\JSON::error(array( + 'data' => array( + 'message' => OC_Contacts_App::$l10n->t('Error setting checksum.')))); diff --git a/apps/contacts/ajax/categories/delete.php b/apps/contacts/ajax/categories/delete.php index 76c23d6487d..bc9f3e14e87 100644 --- a/apps/contacts/ajax/categories/delete.php +++ b/apps/contacts/ajax/categories/delete.php @@ -9,8 +9,9 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('contacts'); +OCP\JSON::callCheck(); -require_once('../loghandler.php'); +require_once __DIR__.'/../loghandler.php'; $categories = isset($_POST['categories'])?$_POST['categories']:null; @@ -45,5 +46,3 @@ $catman->delete($categories, $cards); debug('After delete: '.print_r($catman->categories(), true)); OC_Contacts_VCard::updateDataByID($cards); OCP\JSON::success(array('data' => array('categories'=>$catman->categories()))); - -?> diff --git a/apps/contacts/ajax/categories/list.php b/apps/contacts/ajax/categories/list.php index 3ae7635390c..f234116ba8c 100644 --- a/apps/contacts/ajax/categories/list.php +++ b/apps/contacts/ajax/categories/list.php @@ -13,5 +13,3 @@ OCP\JSON::checkAppEnabled('contacts'); $categories = OC_Contacts_App::getCategories(); OCP\JSON::success(array('data' => array('categories'=>$categories))); - -?> diff --git a/apps/contacts/ajax/categories/rescan.php b/apps/contacts/ajax/categories/rescan.php index 679f57aa26a..a06e7803955 100644 --- a/apps/contacts/ajax/categories/rescan.php +++ b/apps/contacts/ajax/categories/rescan.php @@ -9,25 +9,9 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('contacts'); +OCP\JSON::callCheck(); -require_once(__DIR__.'/../loghandler.php'); - -$addressbooks = OC_Contacts_Addressbook::all(OCP\USER::getUser()); -if(count($addressbooks) == 0) { - bailOut(OC_Contacts_App::$l10n->t('No address books found.')); -} -$addressbookids = array(); -foreach($addressbooks as $addressbook) { - $addressbookids[] = $addressbook['id']; -} -$contacts = OC_Contacts_VCard::all($addressbookids); -if(count($contacts) == 0) { - bailOut(OC_Contacts_App::$l10n->t('No contacts found.')); -} - -OC_Contacts_App::scanCategories($contacts); +OC_Contacts_App::scanCategories(); $categories = OC_Contacts_App::getCategories(); OCP\JSON::success(array('data' => array('categories'=>$categories))); - -?> diff --git a/apps/contacts/ajax/contactdetails.php b/apps/contacts/ajax/contactdetails.php index b697b1a8e5b..27d7611ade9 100644 --- a/apps/contacts/ajax/contactdetails.php +++ b/apps/contacts/ajax/contactdetails.php @@ -20,7 +20,7 @@ * */ -require_once('loghandler.php'); +require_once 'loghandler.php'; // Check if we are a user OCP\JSON::checkLoggedIn(); @@ -30,6 +30,7 @@ $id = isset($_GET['id'])?$_GET['id']:null; if(is_null($id)) { bailOut(OC_Contacts_App::$l10n->t('Missing ID')); } +$card = OC_Contacts_VCard::find($id); $vcard = OC_Contacts_App::getContactVCard( $id ); if(is_null($vcard)) { bailOut(OC_Contacts_App::$l10n->t('Error parsing VCard for ID: "'.$id.'"')); @@ -50,5 +51,7 @@ if(isset($details['PHOTO'])) { $details['PHOTO'] = false; } $details['id'] = $id; +$details['displayname'] = $card['fullname']; +$details['addressbookid'] = $card['addressbookid']; OC_Contacts_App::setLastModifiedHeader($vcard); OCP\JSON::success(array('data' => $details)); diff --git a/apps/contacts/ajax/createaddressbook.php b/apps/contacts/ajax/createaddressbook.php index 2ec5f542bb3..8dbd63f6425 100644 --- a/apps/contacts/ajax/createaddressbook.php +++ b/apps/contacts/ajax/createaddressbook.php @@ -12,7 +12,7 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('contacts'); OCP\JSON::callCheck(); -require_once('loghandler.php'); +require_once 'loghandler.php'; $userid = OCP\USER::getUser(); $name = trim(strip_tags($_POST['name'])); diff --git a/apps/contacts/ajax/currentphoto.php b/apps/contacts/ajax/currentphoto.php index b10e752c453..96080e661ef 100644 --- a/apps/contacts/ajax/currentphoto.php +++ b/apps/contacts/ajax/currentphoto.php @@ -24,7 +24,7 @@ OCP\JSON::setContentTypeHeader('text/plain'); OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('contacts'); -require_once('loghandler.php'); +require_once 'loghandler.php'; if (!isset($_GET['id'])) { bailOut(OC_Contacts_App::$l10n->t('No contact ID was submitted.')); @@ -51,5 +51,3 @@ if( is_null($contact)) { bailOut(OC_Contacts_App::$l10n->t('The loading photo is not valid.')); } } - -?> diff --git a/apps/contacts/ajax/deletecard.php b/apps/contacts/ajax/deletecard.php index 1161c18abda..9777046fc82 100644 --- a/apps/contacts/ajax/deletecard.php +++ b/apps/contacts/ajax/deletecard.php @@ -23,17 +23,7 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('contacts'); OCP\JSON::callCheck(); -require_once('loghandler.php'); - -// foreach($_SERVER as $key=>$value) { -// OCP\Util::writeLog('contacts','ajax/saveproperty.php: _SERVER: '.$key.'=>'.$value, OCP\Util::DEBUG); -// } -// foreach($_POST as $key=>$value) { -// debug($key.'=>'.print_r($value, true)); -// } -// foreach($_GET as $key=>$value) { -// debug($key.'=>'.print_r($value, true)); -// } +require_once 'loghandler.php'; $id = isset($_POST['id'])?$_POST['id']:null; if(!$id) { diff --git a/apps/contacts/ajax/deleteproperty.php b/apps/contacts/ajax/deleteproperty.php index 90e5e64903e..205df8bc184 100644 --- a/apps/contacts/ajax/deleteproperty.php +++ b/apps/contacts/ajax/deleteproperty.php @@ -24,22 +24,23 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('contacts'); OCP\JSON::callCheck(); -require_once('loghandler.php'); +require_once 'loghandler.php'; $id = $_POST['id']; $checksum = $_POST['checksum']; +$l10n = OC_Contacts_App::$l10n; $vcard = OC_Contacts_App::getContactVCard( $id ); $line = OC_Contacts_App::getPropertyLineByChecksum($vcard, $checksum); -if(is_null($line)){ - bailOut(OC_Contacts_App::$l10n->t('Information about vCard is incorrect. Please reload the page.')); +if(is_null($line)) { + bailOut($l10n->t('Information about vCard is incorrect. Please reload the page.')); exit(); } unset($vcard->children[$line]); -if(!OC_Contacts_VCard::edit($id,$vcard)) { - bailOut(OC_Contacts_App::$l10n->t('Error deleting contact property.')); +if(!OC_Contacts_VCard::edit($id, $vcard)) { + bailOut($l10n->t('Error deleting contact property.')); } OCP\JSON::success(array('data' => array( 'id' => $id ))); diff --git a/apps/contacts/ajax/editaddress.php b/apps/contacts/ajax/editaddress.php index 2d7aba11b0e..b5e4b72ed57 100644 --- a/apps/contacts/ajax/editaddress.php +++ b/apps/contacts/ajax/editaddress.php @@ -34,10 +34,8 @@ if($checksum) { $tmpl->assign('adr', $adr, false); } -$tmpl->assign('id',$id); -$tmpl->assign('adr_types',$adr_types); +$tmpl->assign('id', $id); +$tmpl->assign('adr_types', $adr_types); $page = $tmpl->fetchPage(); OCP\JSON::success(array('data' => array('page'=>$page, 'checksum'=>$checksum))); - -?> diff --git a/apps/contacts/ajax/editaddressbook.php b/apps/contacts/ajax/editaddressbook.php index 7a9b757ae0d..4bc77302e5b 100644 --- a/apps/contacts/ajax/editaddressbook.php +++ b/apps/contacts/ajax/editaddressbook.php @@ -14,4 +14,3 @@ $tmpl = new OCP\Template("contacts", "part.editaddressbook"); $tmpl->assign('new', false); $tmpl->assign('addressbook', $addressbook); $tmpl->printPage(); -?> diff --git a/apps/contacts/ajax/editname.php b/apps/contacts/ajax/editname.php index 868ca222e0a..eb55634011d 100644 --- a/apps/contacts/ajax/editname.php +++ b/apps/contacts/ajax/editname.php @@ -9,7 +9,7 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('contacts'); -require_once('loghandler.php'); +require_once 'loghandler.php'; $tmpl = new OCP\Template("contacts", "part.edit_name_dialog"); @@ -25,12 +25,10 @@ if($id) { } } $name = array_map('htmlspecialchars', $name['value']); - $tmpl->assign('name',$name, false); - $tmpl->assign('id',$id, false); + $tmpl->assign('name', $name, false); + $tmpl->assign('id', $id, false); } else { bailOut(OC_Contacts_App::$l10n->t('Contact ID is missing.')); } $page = $tmpl->fetchPage(); OCP\JSON::success(array('data' => array('page'=>$page))); - -?> diff --git a/apps/contacts/ajax/importaddressbook.php b/apps/contacts/ajax/importaddressbook.php deleted file mode 100644 index f93bbfa4d9d..00000000000 --- a/apps/contacts/ajax/importaddressbook.php +++ /dev/null @@ -1,23 +0,0 @@ -<?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. - */ - -OCP\JSON::checkLoggedIn(); -OCP\App::checkAppEnabled('contacts'); -$upload_max_filesize = OCP\Util::computerFileSize(ini_get('upload_max_filesize')); -$post_max_size = OCP\Util::computerFileSize(ini_get('post_max_size')); -$maxUploadFilesize = min($upload_max_filesize, $post_max_size); - -$freeSpace=OC_Filesystem::free_space('/'); -$freeSpace=max($freeSpace,0); -$maxUploadFilesize = min($maxUploadFilesize ,$freeSpace); - -$tmpl = new OCP\Template('contacts', 'part.importaddressbook'); -$tmpl->assign('uploadMaxFilesize', $maxUploadFilesize); -$tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize)); -$tmpl->printpage(); -?> diff --git a/apps/contacts/ajax/importdialog.php b/apps/contacts/ajax/importdialog.php index 5f8805a6106..691522538fb 100644 --- a/apps/contacts/ajax/importdialog.php +++ b/apps/contacts/ajax/importdialog.php @@ -13,4 +13,3 @@ $tmpl = new OCP\Template('contacts', 'part.import'); $tmpl->assign('path', $_POST['path']); $tmpl->assign('filename', $_POST['filename']); $tmpl->printpage(); -?> diff --git a/apps/contacts/ajax/loadcard.php b/apps/contacts/ajax/loadcard.php index 1309faaa7a2..75fe33ada6f 100644 --- a/apps/contacts/ajax/loadcard.php +++ b/apps/contacts/ajax/loadcard.php @@ -30,20 +30,20 @@ $maxUploadFilesize = min($upload_max_filesize, $post_max_size); $requesttoken = $_GET['requesttoken']; $freeSpace=OC_Filesystem::free_space('/'); -$freeSpace=max($freeSpace,0); -$maxUploadFilesize = min($maxUploadFilesize ,$freeSpace); +$freeSpace=max($freeSpace, 0); +$maxUploadFilesize = min($maxUploadFilesize, $freeSpace); $adr_types = OC_Contacts_App::getTypesOfProperty('ADR'); $phone_types = OC_Contacts_App::getTypesOfProperty('TEL'); $email_types = OC_Contacts_App::getTypesOfProperty('EMAIL'); -$tmpl = new OCP\Template('contacts','part.contact'); +$tmpl = new OCP\Template('contacts', 'part.contact'); $tmpl->assign('uploadMaxFilesize', $maxUploadFilesize); $tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize)); -$tmpl->assign('adr_types',$adr_types); -$tmpl->assign('phone_types',$phone_types); -$tmpl->assign('email_types',$email_types); +$tmpl->assign('adr_types', $adr_types); +$tmpl->assign('phone_types', $phone_types); +$tmpl->assign('email_types', $email_types); $tmpl->assign('requesttoken', $requesttoken); -$tmpl->assign('id',''); +$tmpl->assign('id', ''); $page = $tmpl->fetchPage(); OCP\JSON::success(array('data' => array( 'page' => $page ))); diff --git a/apps/contacts/ajax/loadintro.php b/apps/contacts/ajax/loadintro.php index 6e8fcc4b049..1da08950ca0 100644 --- a/apps/contacts/ajax/loadintro.php +++ b/apps/contacts/ajax/loadintro.php @@ -25,7 +25,7 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('contacts'); -$tmpl = new OCP\Template('contacts','part.no_contacts'); +$tmpl = new OCP\Template('contacts', 'part.no_contacts'); $page = $tmpl->fetchPage(); OCP\JSON::success(array('data' => array( 'page' => $page ))); diff --git a/apps/contacts/ajax/loadphoto.php b/apps/contacts/ajax/loadphoto.php deleted file mode 100644 index a35631055eb..00000000000 --- a/apps/contacts/ajax/loadphoto.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -/** - * ownCloud - Addressbook - * - * @author Thomas Tanghus - * @copyright 2012 Thomas Tanghus <thomas@tanghus.net> - * - * 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/>. - * - */ - -// Check if we are a user -OCP\JSON::checkLoggedIn(); -OCP\JSON::checkAppEnabled('contacts'); - -require_once('loghandler.php'); - -$id = isset($_GET['id']) ? $_GET['id'] : ''; -$refresh = isset($_GET['refresh']) ? true : false; - -if($id == '') { - bailOut(OC_Contacts_App::$l10n->t('Missing contact id.')); -} - -$checksum = ''; -$vcard = OC_Contacts_App::getContactVCard( $id ); -foreach($vcard->children as $property){ - if($property->name == 'PHOTO') { - $checksum = md5($property->serialize()); - break; - } -} - -OCP\JSON::success(array('data' => array('checksum'=>$checksum))); - diff --git a/apps/contacts/ajax/loghandler.php b/apps/contacts/ajax/loghandler.php index 831b2e50c1e..be4b98c1112 100644 --- a/apps/contacts/ajax/loghandler.php +++ b/apps/contacts/ajax/loghandler.php @@ -20,13 +20,15 @@ * */ -function bailOut($msg, $tracelevel=1, $debuglevel=OCP\Util::ERROR) { +function bailOut($msg, $tracelevel=1, $debuglevel=OCP\Util::ERROR) +{ OCP\JSON::error(array('data' => array('message' => $msg))); debug($msg, $tracelevel, $debuglevel); exit(); } -function debug($msg, $tracelevel=0, $debuglevel=OCP\Util::DEBUG) { +function debug($msg, $tracelevel=0, $debuglevel=OCP\Util::DEBUG) +{ if(PHP_VERSION >= "5.4") { $call = debug_backtrace(false, $tracelevel+1); } else { @@ -35,6 +37,8 @@ function debug($msg, $tracelevel=0, $debuglevel=OCP\Util::DEBUG) { error_log('trace: '.print_r($call, true)); $call = $call[$tracelevel]; if($debuglevel !== false) { - OCP\Util::writeLog('contacts', $call['file'].'. Line: '.$call['line'].': '.$msg, $debuglevel); + OCP\Util::writeLog('contacts', + $call['file'].'. Line: '.$call['line'].': '.$msg, + $debuglevel); } } diff --git a/apps/contacts/ajax/oc_photo.php b/apps/contacts/ajax/oc_photo.php index 5c50ba92dbe..fe37b530f82 100644 --- a/apps/contacts/ajax/oc_photo.php +++ b/apps/contacts/ajax/oc_photo.php @@ -22,7 +22,7 @@ // Check if we are a user OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('contacts'); -require_once('loghandler.php'); +require_once 'loghandler.php'; if(!isset($_GET['id'])) { bailOut(OC_Contacts_App::$l10n->t('No contact ID was submitted.')); @@ -50,7 +50,9 @@ if($image->width() > 400 || $image->height() > 400) { $image->resize(400); // Prettier resizing than with browser and saves bandwidth. } if(!$image->fixOrientation()) { // No fatal error so we don't bail out. - OCP\Util::writeLog('contacts','ajax/oc_photo.php: Couldn\'t save correct image orientation: '.$localpath, OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', + 'ajax/oc_photo.php: Couldn\'t save correct image orientation: '.$localpath, + OCP\Util::DEBUG); } if(OC_Cache::set($tmpkey, $image->data(), 600)) { OCP\JSON::success(array('data' => array('id'=>$_GET['id'], 'tmp'=>$tmpkey))); @@ -58,5 +60,3 @@ if(OC_Cache::set($tmpkey, $image->data(), 600)) { } else { bailOut('Couldn\'t save temporary image: '.$tmpkey); } - -?> diff --git a/apps/contacts/ajax/savecrop.php b/apps/contacts/ajax/savecrop.php index adce6be3b39..8ee2e46bf0c 100644 --- a/apps/contacts/ajax/savecrop.php +++ b/apps/contacts/ajax/savecrop.php @@ -27,7 +27,7 @@ OCP\JSON::callCheck(); // Firefox and Konqueror tries to download application/json for me. --Arthur OCP\JSON::setContentTypeHeader('text/plain'); -require_once('loghandler.php'); +require_once 'loghandler.php'; $image = null; @@ -48,7 +48,7 @@ if($id == '') { bailOut('Missing contact id.'); } -OCP\Util::writeLog('contacts','savecrop.php: key: '.$tmpkey, OCP\Util::DEBUG); +OCP\Util::writeLog('contacts', 'savecrop.php: key: '.$tmpkey, OCP\Util::DEBUG); $data = OC_Cache::get($tmpkey); if($data) { @@ -56,7 +56,9 @@ if($data) { if($image->loadFromdata($data)) { $w = ($w != -1 ? $w : $image->width()); $h = ($h != -1 ? $h : $image->height()); - OCP\Util::writeLog('contacts','savecrop.php, x: '.$x1.' y: '.$y1.' w: '.$w.' h: '.$h, OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', + 'savecrop.php, x: '.$x1.' y: '.$y1.' w: '.$w.' h: '.$h, + OCP\Util::DEBUG); if($image->crop($x1, $y1, $w, $h)) { if(($image->width() <= 200 && $image->height() <= 200) || $image->resize(200)) { $card = OC_Contacts_App::getContactVCard($id); @@ -65,7 +67,9 @@ if($data) { bailOut(OC_Contacts_App::$l10n->t('Error getting contact object.')); } if($card->__isset('PHOTO')) { - OCP\Util::writeLog('contacts','savecrop.php: PHOTO property exists.', OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', + 'savecrop.php: PHOTO property exists.', + OCP\Util::DEBUG); $property = $card->__get('PHOTO'); if(!$property) { OC_Cache::remove($tmpkey); @@ -76,12 +80,16 @@ if($data) { $property->parameters[] = new Sabre_VObject_Parameter('TYPE', $image->mimeType()); $card->__set('PHOTO', $property); } else { - OCP\Util::writeLog('contacts','savecrop.php: files: Adding PHOTO property.', OCP\Util::DEBUG); - $card->addProperty('PHOTO', $image->__toString(), array('ENCODING' => 'b', 'TYPE' => $image->mimeType())); + OCP\Util::writeLog('contacts', + 'savecrop.php: files: Adding PHOTO property.', + OCP\Util::DEBUG); + $card->addProperty('PHOTO', + $image->__toString(), array('ENCODING' => 'b', + 'TYPE' => $image->mimeType())); } $now = new DateTime; $card->setString('REV', $now->format(DateTime::W3C)); - if(!OC_Contacts_VCard::edit($id,$card)) { + if(!OC_Contacts_VCard::edit($id, $card)) { bailOut(OC_Contacts_App::$l10n->t('Error saving contact.')); } $tmpl = new OCP\Template("contacts", "part.contactphoto"); diff --git a/apps/contacts/ajax/saveproperty.php b/apps/contacts/ajax/saveproperty.php index 34fc3cc5351..5d743c99df4 100644 --- a/apps/contacts/ajax/saveproperty.php +++ b/apps/contacts/ajax/saveproperty.php @@ -19,7 +19,7 @@ * License along with this library. If not, see <http://www.gnu.org/licenses/>. * */ -require_once('loghandler.php'); +require_once 'loghandler.php'; // Check if we are a user OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('contacts'); @@ -39,9 +39,11 @@ if(!$id) { if(!$checksum) { bailOut(OC_Contacts_App::$l10n->t('checksum is not set.')); } -if(is_array($value)){ +if(is_array($value)) { $value = array_map('strip_tags', $value); - ksort($value); // NOTE: Important, otherwise the compound value will be set in the order the fields appear in the form! + // NOTE: Important, otherwise the compound value will be + // set in the order the fields appear in the form! + ksort($value); //if($name == 'CATEGORIES') { // $value = OC_Contacts_VCard::escapeDelimiters($value, ','); //} else { @@ -66,8 +68,7 @@ if($element != $name) { switch($element) { case 'BDAY': $date = New DateTime($value); - //$vcard->setDateTime('BDAY', $date, Sabre_VObject_Element_DateTime::DATE); - $value = $date->format(DateTime::ATOM); + $value = $date->format('Y-m-d'); break; case 'FN': if(!$value) { @@ -89,6 +90,14 @@ if(!$value) { } else { /* setting value */ switch($element) { + case 'BDAY': + // I don't use setDateTime() because that formats it as YYYYMMDD instead of YYYY-MM-DD + // which is what the RFC recommends. + $vcard->children[$line]->setValue($value); + $vcard->children[$line]->parameters = array(); + $vcard->children[$line]->add(new Sabre_VObject_Parameter('VALUE', 'DATE')); + debug('Setting value:'.$name.' '.$vcard->children[$line]); + break; case 'CATEGORIES': debug('Setting string:'.$name.' '.$value); $vcard->children[$line]->setValue($value); @@ -120,7 +129,7 @@ if(!$value) { } //debug('New checksum: '.$checksum); -if(!OC_Contacts_VCard::edit($id,$vcard)) { +if(!OC_Contacts_VCard::edit($id, $vcard)) { bailOut(OC_Contacts_App::$l10n->t('Error updating contact property.')); exit(); } diff --git a/apps/contacts/ajax/selectaddressbook.php b/apps/contacts/ajax/selectaddressbook.php new file mode 100644 index 00000000000..6c35d08c829 --- /dev/null +++ b/apps/contacts/ajax/selectaddressbook.php @@ -0,0 +1,16 @@ +<?php +/** + * Copyright (c) 2011 Thomas Tanghus <thomas@tanghus.net> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +OCP\JSON::checkLoggedIn(); +OCP\JSON::checkAppEnabled('contacts'); + +$addressbooks = OC_Contacts_Addressbook::all(OCP\USER::getUser()); +$tmpl = new OCP\Template("contacts", "part.selectaddressbook"); +$tmpl->assign('addressbooks', $addressbooks); +$page = $tmpl->fetchPage(); +OCP\JSON::success(array('data' => array('page' => $page ))); diff --git a/apps/contacts/ajax/updateaddressbook.php b/apps/contacts/ajax/updateaddressbook.php index d3a772c727f..a14b2158431 100644 --- a/apps/contacts/ajax/updateaddressbook.php +++ b/apps/contacts/ajax/updateaddressbook.php @@ -11,7 +11,7 @@ // Check if we are a user OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('contacts'); -require_once('loghandler.php'); +require_once 'loghandler.php'; $bookid = $_POST['id']; OC_Contacts_App::getAddressbook($bookid); // is owner access check diff --git a/apps/contacts/ajax/uploadimport.php b/apps/contacts/ajax/uploadimport.php index 9511520828f..87032b731a5 100644 --- a/apps/contacts/ajax/uploadimport.php +++ b/apps/contacts/ajax/uploadimport.php @@ -24,52 +24,57 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('contacts'); OCP\JSON::callCheck(); -require_once('loghandler.php'); +require_once 'loghandler.php'; + +$l10n = OC_Contacts_App::$l10n; $view = OCP\Files::getStorage('contacts'); +if(!$view->file_exists('imports')) { + $view->mkdir('imports'); +} $tmpfile = md5(rand()); // If it is a Drag'n'Drop transfer it's handled here. $fn = (isset($_SERVER['HTTP_X_FILE_NAME']) ? $_SERVER['HTTP_X_FILE_NAME'] : false); if($fn) { - if($view->file_put_contents('/'.$tmpfile, file_get_contents('php://input'))) { - OCP\JSON::success(array('data' => array('path'=>'', 'file'=>$tmpfile))); + if($view->file_put_contents('/imports/'.$fn, file_get_contents('php://input'))) { + OCP\JSON::success(array('data' => array('file'=>$tmpfile, 'name'=>$fn))); exit(); } else { - bailOut(OC_Contacts_App::$l10n->t('Error uploading contacts to storage.')); + bailOut($l10n->t('Error uploading contacts to storage.')); } } // File input transfers are handled here if (!isset($_FILES['importfile'])) { - OCP\Util::writeLog('contacts','ajax/uploadphoto.php: No file was uploaded. Unknown error.', OCP\Util::DEBUG); - OCP\JSON::error(array('data' => array( 'message' => 'No file was uploaded. Unknown error' ))); + OCP\Util::writeLog('contacts', + 'ajax/uploadphoto.php: No file was uploaded. Unknown error.', + OCP\Util::DEBUG); + OCP\JSON::error(array(' + data' => array( + 'message' => 'No file was uploaded. Unknown error' ))); exit(); } $error = $_FILES['importfile']['error']; if($error !== UPLOAD_ERR_OK) { $errors = array( - 0=>OC_Contacts_App::$l10n->t("There is no error, the file uploaded with success"), - 1=>OC_Contacts_App::$l10n->t("The uploaded file exceeds the upload_max_filesize directive in php.ini").ini_get('upload_max_filesize'), - 2=>OC_Contacts_App::$l10n->t("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"), - 3=>OC_Contacts_App::$l10n->t("The uploaded file was only partially uploaded"), - 4=>OC_Contacts_App::$l10n->t("No file was uploaded"), - 6=>OC_Contacts_App::$l10n->t("Missing a temporary folder") + 0=>$l10n->t("There is no error, the file uploaded with success"), + 1=>$l10n->t("The uploaded file exceeds the upload_max_filesize directive in php.ini").ini_get('upload_max_filesize'), + 2=>$l10n->t("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"), + 3=>$l10n->t("The uploaded file was only partially uploaded"), + 4=>$l10n->t("No file was uploaded"), + 6=>$l10n->t("Missing a temporary folder") ); bailOut($errors[$error]); } $file=$_FILES['importfile']; -$tmpfname = tempnam(get_temp_dir(), "occOrig"); if(file_exists($file['tmp_name'])) { - if($view->file_put_contents('/'.$tmpfile, file_get_contents($file['tmp_name']))) { - OCP\JSON::success(array('data' => array('path'=>'', 'file'=>$tmpfile))); + if($view->file_put_contents('/imports/'.$file['name'], file_get_contents($file['tmp_name']))) { + OCP\JSON::success(array('data' => array('file'=>$file['name'], 'name'=>$file['name']))); } else { - bailOut(OC_Contacts_App::$l10n->t('Error uploading contacts to storage.')); + bailOut($l10n->t('Error uploading contacts to storage.')); } } else { bailOut('Temporary file: \''.$file['tmp_name'].'\' has gone AWOL?'); } - - -?> diff --git a/apps/contacts/ajax/uploadphoto.php b/apps/contacts/ajax/uploadphoto.php index 8545ca84eee..4cd38db8c72 100644 --- a/apps/contacts/ajax/uploadphoto.php +++ b/apps/contacts/ajax/uploadphoto.php @@ -27,13 +27,13 @@ OCP\JSON::callCheck(); // Firefox and Konqueror tries to download application/json for me. --Arthur OCP\JSON::setContentTypeHeader('text/plain'); -require_once('loghandler.php'); - +require_once 'loghandler.php'; +$l10n = OC_Contacts_App::$l10n; // If it is a Drag'n'Drop transfer it's handled here. $fn = (isset($_SERVER['HTTP_X_FILE_NAME']) ? $_SERVER['HTTP_X_FILE_NAME'] : false); if ($fn) { if (!isset($_GET['id'])) { - bailOut(OC_Contacts_App::$l10n->t('No contact ID was submitted.')); + bailOut($l10n->t('No contact ID was submitted.')); } $id = $_GET['id']; $tmpkey = 'contact-photo-'.md5($fn); @@ -48,33 +48,38 @@ if ($fn) { debug('Couldn\'t save correct image orientation: '.$tmpkey); } if(OC_Cache::set($tmpkey, $image->data(), 600)) { - OCP\JSON::success(array('data' => array('mime'=>$_SERVER['CONTENT_TYPE'], 'name'=>$fn, 'id'=>$id, 'tmp'=>$tmpkey))); + OCP\JSON::success(array( + 'data' => array( + 'mime'=>$_SERVER['CONTENT_TYPE'], + 'name'=>$fn, + 'id'=>$id, + 'tmp'=>$tmpkey))); exit(); } else { - bailOut(OC_Contacts_App::$l10n->t('Couldn\'t save temporary image: ').$tmpkey); + bailOut($l10n->t('Couldn\'t save temporary image: ').$tmpkey); } } else { - bailOut(OC_Contacts_App::$l10n->t('Couldn\'t load temporary image: ').$tmpkey); + bailOut($l10n->t('Couldn\'t load temporary image: ').$tmpkey); } } // Uploads from file dialog are handled here. if (!isset($_POST['id'])) { - bailOut(OC_Contacts_App::$l10n->t('No contact ID was submitted.')); + bailOut($l10n->t('No contact ID was submitted.')); } if (!isset($_FILES['imagefile'])) { - bailOut(OC_Contacts_App::$l10n->t('No file was uploaded. Unknown error')); + bailOut($l10n->t('No file was uploaded. Unknown error')); } $error = $_FILES['imagefile']['error']; if($error !== UPLOAD_ERR_OK) { $errors = array( - 0=>OC_Contacts_App::$l10n->t("There is no error, the file uploaded with success"), - 1=>OC_Contacts_App::$l10n->t("The uploaded file exceeds the upload_max_filesize directive in php.ini").ini_get('upload_max_filesize'), - 2=>OC_Contacts_App::$l10n->t("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"), - 3=>OC_Contacts_App::$l10n->t("The uploaded file was only partially uploaded"), - 4=>OC_Contacts_App::$l10n->t("No file was uploaded"), - 6=>OC_Contacts_App::$l10n->t("Missing a temporary folder") + 0=>$l10n->t("There is no error, the file uploaded with success"), + 1=>$l10n->t("The uploaded file exceeds the upload_max_filesize directive in php.ini").ini_get('upload_max_filesize'), + 2=>$l10n->t("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"), + 3=>$l10n->t("The uploaded file was only partially uploaded"), + 4=>$l10n->t("No file was uploaded"), + 6=>$l10n->t("Missing a temporary folder") ); bailOut($errors[$error]); } @@ -91,15 +96,21 @@ if(file_exists($file['tmp_name'])) { debug('Couldn\'t save correct image orientation: '.$tmpkey); } if(OC_Cache::set($tmpkey, $image->data(), 600)) { - OCP\JSON::success(array('data' => array('mime'=>$file['type'],'size'=>$file['size'],'name'=>$file['name'], 'id'=>$_POST['id'], 'tmp'=>$tmpkey))); + OCP\JSON::success(array( + 'data' => array( + 'mime'=>$file['type'], + 'size'=>$file['size'], + 'name'=>$file['name'], + 'id'=>$_POST['id'], + 'tmp'=>$tmpkey, + ))); exit(); } else { - bailOut(OC_Contacts_App::$l10n->t('Couldn\'t save temporary image: ').$tmpkey); + bailOut($l10n->t('Couldn\'t save temporary image: ').$tmpkey); } } else { - bailOut(OC_Contacts_App::$l10n->t('Couldn\'t load temporary image: ').$file['tmp_name']); + bailOut($l10n->t('Couldn\'t load temporary image: ').$file['tmp_name']); } } else { bailOut('Temporary file: \''.$file['tmp_name'].'\' has gone AWOL?'); } -?> diff --git a/apps/contacts/appinfo/app.php b/apps/contacts/appinfo/app.php index 64fe00eef10..cbbbbc79e58 100644 --- a/apps/contacts/appinfo/app.php +++ b/apps/contacts/appinfo/app.php @@ -4,6 +4,7 @@ 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['Sabre_CardDAV_VCFExportPlugin'] = 'apps/contacts/lib/VCFExportPlugin.php'; OC::$CLASSPATH['OC_Search_Provider_Contacts'] = 'apps/contacts/lib/search.php'; OCP\Util::connectHook('OC_User', 'post_createUser', 'OC_Contacts_Hooks', 'createUser'); OCP\Util::connectHook('OC_User', 'post_deleteUser', 'OC_Contacts_Hooks', 'deleteUser'); @@ -18,6 +19,6 @@ OCP\App::addNavigationEntry( array( 'name' => OC_L10N::get('contacts')->t('Contacts') )); -OCP\App::registerPersonal('contacts','settings'); +OCP\App::registerPersonal('contacts', 'settings'); OCP\Util::addscript('contacts', 'loader'); OC_Search::registerProvider('OC_Search_Provider_Contacts'); diff --git a/apps/contacts/appinfo/database.xml b/apps/contacts/appinfo/database.xml index 9b269d765dc..b814b0f1516 100644 --- a/apps/contacts/appinfo/database.xml +++ b/apps/contacts/appinfo/database.xml @@ -44,7 +44,7 @@ <type>text</type> <default></default> <notnull>false</notnull> - <length>100</length> + <length>200</length> </field> <field> @@ -118,7 +118,7 @@ <type>text</type> <default></default> <notnull>false</notnull> - <length>100</length> + <length>200</length> </field> <field> diff --git a/apps/contacts/appinfo/migrate.php b/apps/contacts/appinfo/migrate.php index 02026c5979c..2559b4ea456 100644 --- a/apps/contacts/appinfo/migrate.php +++ b/apps/contacts/appinfo/migrate.php @@ -2,7 +2,7 @@ class OC_Migration_Provider_Contacts extends OC_Migration_Provider{ // Create the xml for the user supplied - function export( ){ + function export( ) { $options = array( 'table'=>'contacts_addressbooks', 'matchcol'=>'userid', @@ -21,9 +21,8 @@ class OC_Migration_Provider_Contacts extends OC_Migration_Provider{ $ids2 = $this->content->copyRows( $options ); // If both returned some ids then they worked - if( is_array( $ids ) && is_array( $ids2 ) ) - { - return true; + if(is_array($ids) && is_array($ids2)) { + return true; } else { return false; } @@ -31,14 +30,14 @@ class OC_Migration_Provider_Contacts extends OC_Migration_Provider{ } // Import function for contacts - function import( ){ - switch( $this->appinfo->version ){ + function import( ) { + switch( $this->appinfo->version ) { default: // All versions of the app have had the same db structure, so all can use the same import function $query = $this->content->prepare( "SELECT * FROM contacts_addressbooks WHERE userid LIKE ?" ); $results = $query->execute( array( $this->olduid ) ); $idmap = array(); - while( $row = $results->fetchRow() ){ + while( $row = $results->fetchRow() ) { // Import each addressbook $addressbookquery = OCP\DB::prepare( "INSERT INTO *PREFIX*contacts_addressbooks (`userid`, `displayname`, `uri`, `description`, `ctag`) VALUES (?, ?, ?, ?, ?)" ); $addressbookquery->execute( array( $this->uid, $row['displayname'], $row['uri'], $row['description'], $row['ctag'] ) ); @@ -48,7 +47,7 @@ class OC_Migration_Provider_Contacts extends OC_Migration_Provider{ OC_Contacts_Addressbook::setActive($idmap[$row['id']], true); } // Now tags - foreach($idmap as $oldid => $newid){ + foreach($idmap as $oldid => $newid) { $query = $this->content->prepare( "SELECT * FROM contacts_cards WHERE addressbookid LIKE ?" ); $results = $query->execute( array( $oldid ) ); diff --git a/apps/contacts/appinfo/remote.php b/apps/contacts/appinfo/remote.php index 5add3bc6889..fd5604aec6f 100644 --- a/apps/contacts/appinfo/remote.php +++ b/apps/contacts/appinfo/remote.php @@ -22,7 +22,7 @@ OCP\App::checkAppEnabled('contacts'); -if(substr($_SERVER["REQUEST_URI"],0,strlen(OC_App::getAppWebPath('contacts').'/carddav.php')) == OC_App::getAppWebPath('contacts').'/carddav.php'){ +if(substr($_SERVER["REQUEST_URI"], 0, strlen(OC_App::getAppWebPath('contacts').'/carddav.php')) == OC_App::getAppWebPath('contacts').'/carddav.php') { $baseuri = OC_App::getAppWebPath('contacts').'/carddav.php'; } @@ -45,10 +45,11 @@ $nodes = array( $server = new Sabre_DAV_Server($nodes); $server->setBaseUri($baseuri); // Add plugins -$server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend,'ownCloud')); +$server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend, 'ownCloud')); $server->addPlugin(new Sabre_CardDAV_Plugin()); $server->addPlugin(new Sabre_DAVACL_Plugin()); $server->addPlugin(new Sabre_DAV_Browser_Plugin(false)); // Show something in the Browser, but no upload +$server->addPlugin(new Sabre_CardDAV_VCFExportPlugin()); // And off we go! $server->exec(); diff --git a/apps/contacts/appinfo/update.php b/apps/contacts/appinfo/update.php index 873899f578b..21e736bb446 100644 --- a/apps/contacts/appinfo/update.php +++ b/apps/contacts/appinfo/update.php @@ -1,7 +1,7 @@ <?php $installedVersion=OCP\Config::getAppValue('contacts', 'installed_version'); -if (version_compare($installedVersion, '0.2.90', '<')) { +if (version_compare($installedVersion, '0.2.3', '<')) { // First set all address books in-active. $stmt = OCP\DB::prepare( 'UPDATE *PREFIX*contacts_addressbooks SET active=0' ); $result = $stmt->execute(array()); diff --git a/apps/contacts/appinfo/version b/apps/contacts/appinfo/version index 7dff5b89211..72f9fa82020 100644 --- a/apps/contacts/appinfo/version +++ b/apps/contacts/appinfo/version @@ -1 +1 @@ -0.2.1
\ No newline at end of file +0.2.4
\ No newline at end of file diff --git a/apps/contacts/carddav.php b/apps/contacts/carddav.php index e0579e625d7..264eb30836b 100644 --- a/apps/contacts/carddav.php +++ b/apps/contacts/carddav.php @@ -1,6 +1,6 @@ <?php -if(!file_exists('../../lib/base.php')){ +if(!file_exists('../../lib/base.php')) { die('Please update the path to /lib/base.php in carddav.php or make use of /remote.php/carddav/'); } -require_once('../../lib/base.php'); -require_once('appinfo/remote.php');
\ No newline at end of file +require_once '../../lib/base.php'; +require_once 'appinfo/remote.php';
\ No newline at end of file diff --git a/apps/contacts/css/contacts.css b/apps/contacts/css/contacts.css index 5b6ccb7638a..ddae27da211 100644 --- a/apps/contacts/css/contacts.css +++ b/apps/contacts/css/contacts.css @@ -5,17 +5,18 @@ #leftcontent a { padding: 0 0 0 25px; } #rightcontent { top: 3.5em !important; padding-top: 5px; } #leftcontent h3 { cursor: pointer; -moz-transition: background 300ms ease 0s; background: none no-repeat scroll 1em center #eee; border-bottom: 1px solid #ddd; border-top: 1px solid #fff; display: block; max-width: 100%; padding: 0.5em 0.8em; color: #666; text-shadow: 0 1px 0 #f8f8f8; font-size: 1.2em; } -#leftcontent h3:hover,#leftcontent h3:active,#leftcontent h3.active { background-color: #DBDBDB; border-bottom: 1px solid #CCCCCC; border-top: 1px solid #D4D4D4; color: #333333; } +#leftcontent h3:hover,#leftcontent h3:active,#leftcontent h3.active { background-color: #DBDBDB; border-bottom: 1px solid #CCCCCC; border-top: 1px solid #D4D4D4; color: #333333; font-weight: bold; } #contacts { position: fixed; background: #fff; max-width: 100%; width: 20em; left: 12.5em; top: 3.7em; bottom: 3em; overflow: auto; padding: 0; margin: 0; } .contacts a { height: 23px; display: block; left: 12.5em; margin: 0 0 0 0; padding: 0 0 0 25px; } .contacts li.ui-draggable { height: 23px; } -.ui-draggable-dragging { width: 16em; } +.ui-draggable-dragging { width: 17em; cursor: move; } .ui-state-hover { border: 1px solid dashed; } #bottomcontrols { padding: 0; bottom:0px; height:2.8em; width: 20em; margin:0; background:#eee; border-top:1px solid #ccc; position:fixed; -moz-box-shadow: 0 -3px 3px -3px #000; -webkit-box-shadow: 0 -3px 3px -3px #000; box-shadow: 0 -3px 3px -3px #000;} #bottomcontrols img { margin-top: 0.35em; } -#contacts_newcontact { float: left; margin: 0.2em 0 0 1em; } +#uploadprogressbar { display: none; padding: 0; bottom: 3em; height:2em; width: 20em; margin:0; background:#eee; border:1px solid #ccc; position:fixed; } +#contacts_newcontact, #contacts_import, #chooseaddressbook { float: left; margin: 0.2em 0 0 1em; border: 0 none; border-radius: 0; -moz-box-shadow: none; box-shadow: none; outline: 0 none; } #chooseaddressbook { float: right; margin: 0.2em 1em 0 0; } -#actionbar { position: relative; clear: both; height: 30px;} +#actionbar { clear: both; height: 30px;} #contacts_deletecard {position:relative; float:left; background:url('%webroot%/core/img/actions/delete.svg') no-repeat center; } #contacts_downloadcard {position:relative; float:left; background:url('%webroot%/core/img/actions/download.svg') no-repeat center; } #contacts_propertymenu { clear: left; float:left; max-width: 15em; margin: 2em; } @@ -71,7 +72,7 @@ label:hover, dt:hover { color: #333; } #identityprops { /*position: absolute; top: 2.5em; left: 0px;*/ } /*#contact_photo { max-width: 250px; }*/ #contact_identity { min-width: 30em; } -.contactsection { position: relative; float: left; /*max-width: 40em;*/ padding: 0.5em; height: auto: border: thin solid lightgray;/* -webkit-border-radius: 0.5em; -moz-border-radius: 0.5em; border-radius: 0.5em; background-color: #f8f8f8;*/ } +.contactsection { position: relative; float: left; padding: 0.5em; height: auto; } #cropbox { margin: auto; } #contacts_details_photo_wrapper { width: 200px; } @@ -110,7 +111,7 @@ dl.addresscard .action { float: right; } #file_upload_form { width: 0; height: 0; } #file_upload_target, #import_upload_target, #crop_target { display:none; } #file_upload_start, #import_upload_start { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter:alpha(opacity=0); opacity:0; z-index:1001; width:0; height:0;} -#import_upload_start { width: 16px; height: 16px; margin: 0 0 0 0; } +#import_upload_start { width: 20px; height: 20px; margin: 0 0 -24px 0; padding: 0;} input[type="checkbox"] { width: 20px; height: 20px; vertical-align: bottom; } .big { font-weight:bold; font-size:1.2em; } .huge { font-weight:bold; font-size:1.5em; } @@ -124,3 +125,12 @@ input[type="checkbox"] { width: 20px; height: 20px; vertical-align: bottom; } .typelist[type="button"] { float: left; max-width: 10em; border: 0; background-color: #fff; color: #bbb} /* for multiselect */ .typelist[type="button"]:hover { color: #777; } /* for multiselect */ .addresslist { clear: both; font-weight: bold; } +#ninjahelp { position: absolute; bottom: 0; left: 0; right: 0; padding: 1em; margin: 1em; border: thin solid #eee; border-radius: 5px; background-color: #DBDBDB; opacity: 0.9; } +#ninjahelp .close { position: absolute; top: 5px; right: 5px; height: 20px; width: 20px; } +#ninjahelp h2, .help-section h3 { width: 100%; font-weight: bold; text-align: center; } +#ninjahelp h2 { font-size: 1.4em; } +.help-section { width: 45%; min-width: 35em; float: left; } +.help-section h3 { font-size: 1.2em; } +.help-section dl { width: 100%; float: left; clear: right; margin: 0; padding: 0; cursor: normal; } +.help-section dt { display: table-cell; clear: left; float: left; width: 35%; margin: 0; padding: 0.2em; text-align: right; text-overflow: ellipsis; vertical-align: text-bottom; font-weight: bold: } +.help-section dd { display: table-cell; clear: right; float: left; margin: 0; padding: 0.2em; white-space: nowrap; vertical-align: text-bottom; } diff --git a/apps/contacts/export.php b/apps/contacts/export.php index 58fdb040a5c..161ca8047ac 100644 --- a/apps/contacts/export.php +++ b/apps/contacts/export.php @@ -9,27 +9,30 @@ OCP\User::checkLoggedIn(); OCP\App::checkAppEnabled('contacts'); -$bookid = isset($_GET['bookid']) ? $_GET['bookid'] : NULL; -$contactid = isset($_GET['contactid']) ? $_GET['contactid'] : NULL; +$bookid = isset($_GET['bookid']) ? $_GET['bookid'] : null; +$contactid = isset($_GET['contactid']) ? $_GET['contactid'] : null; $nl = "\n"; -if(isset($bookid)){ +if(isset($bookid)) { $addressbook = OC_Contacts_App::getAddressbook($bookid); //$cardobjects = OC_Contacts_VCard::all($bookid); header('Content-Type: text/directory'); - header('Content-Disposition: inline; filename=' . str_replace(' ', '_', $addressbook['displayname']) . '.vcf'); + header('Content-Disposition: inline; filename=' + . str_replace(' ', '_', $addressbook['displayname']) . '.vcf'); $start = 0; - $batchsize = OCP\Config::getUserValue(OCP\User::getUser(), 'contacts', 'export_batch_size', 20); + $batchsize = OCP\Config::getUserValue(OCP\User::getUser(), + 'contacts', + 'export_batch_size', 20); while($cardobjects = OC_Contacts_VCard::all($bookid, $start, $batchsize)){ foreach($cardobjects as $card) { echo $card['carddata'] . $nl; } $start += $batchsize; } -}elseif(isset($contactid)){ +}elseif(isset($contactid)) { $data = OC_Contacts_App::getContactObject($contactid); header('Content-Type: text/vcard'); - header('Content-Disposition: inline; filename=' . str_replace(' ', '_', $data['fullname']) . '.vcf'); + header('Content-Disposition: inline; filename=' + . str_replace(' ', '_', $data['fullname']) . '.vcf'); echo $data['carddata']; } -?> diff --git a/apps/contacts/import.php b/apps/contacts/import.php index c95fd970fe1..1986d79f6d6 100644 --- a/apps/contacts/import.php +++ b/apps/contacts/import.php @@ -30,37 +30,51 @@ writeProgress('10'); $view = $file = null; if(isset($_POST['fstype']) && $_POST['fstype'] == 'OC_FilesystemView') { $view = OCP\Files::getStorage('contacts'); - $file = $view->file_get_contents('/' . $_POST['file']); + $file = $view->file_get_contents('/imports/' . $_POST['file']); } else { $file = OC_Filesystem::file_get_contents($_POST['path'] . '/' . $_POST['file']); } if(!$file) { - OCP\JSON::error(array('message' => 'Import file was empty.')); + OCP\JSON::error(array('data' => array('message' => 'Import file was empty.'))); exit(); } -if(isset($_POST['method']) && $_POST['method'] == 'new'){ - $id = OC_Contacts_Addressbook::add(OCP\USER::getUser(), $_POST['addressbookname']); +if(isset($_POST['method']) && $_POST['method'] == 'new') { + $id = OC_Contacts_Addressbook::add(OCP\USER::getUser(), + $_POST['addressbookname']); if(!$id) { - OCP\JSON::error(array('message' => 'Error creating address book.')); + OCP\JSON::error( + array( + 'data' => array('message' => 'Error creating address book.') + ) + ); exit(); } OC_Contacts_Addressbook::setActive($id, 1); }else{ $id = $_POST['id']; if(!$id) { - OCP\JSON::error(array('message' => 'Error getting the ID of the address book.')); + OCP\JSON::error( + array( + 'data' => array( + 'message' => 'Error getting the ID of the address book.', + 'file'=>$_POST['file'] + ) + ) + ); exit(); } OC_Contacts_App::getAddressbook($id); // is owner access check } //analyse the contacts file writeProgress('40'); +$file = str_replace(array("\r","\n\n"), array("\n","\n"), $file); $lines = explode($nl, $file); + $inelement = false; $parts = array(); $card = array(); foreach($lines as $line){ - if(strtoupper(trim($line)) == 'BEGIN:VCARD'){ + if(strtoupper(trim($line)) == 'BEGIN:VCARD') { $inelement = true; } elseif (strtoupper(trim($line)) == 'END:VCARD') { $card[] = $line; @@ -77,21 +91,40 @@ writeProgress('70'); $imported = 0; $failed = 0; if(!count($parts) > 0) { - OCP\JSON::error(array('message' => 'No contacts to import in .'.$_POST['file'].' Please check if the file is corrupted.')); + OCP\JSON::error( + array( + 'data' => array( + 'message' => 'No contacts to import in ' + . $_POST['file'].'. Please check if the file is corrupted.', + 'file'=>$_POST['file'] + ) + ) + ); + if(isset($_POST['fstype']) && $_POST['fstype'] == 'OC_FilesystemView') { + if(!$view->unlink('/imports/' . $_POST['file'])) { + OCP\Util::writeLog('contacts', + 'Import: Error unlinking OC_FilesystemView ' . '/' . $_POST['file'], + OCP\Util::ERROR); + } + } exit(); } foreach($parts as $part){ $card = OC_VObject::parse($part); if (!$card) { $failed += 1; - OCP\Util::writeLog('contacts','Import: skipping card. Error parsing VCard: '.$part, OCP\Util::ERROR); + OCP\Util::writeLog('contacts', + 'Import: skipping card. Error parsing VCard: ' . $part, + OCP\Util::ERROR); continue; // Ditch cards that can't be parsed by Sabre. } try { OC_Contacts_VCard::add($id, $card); $imported += 1; } catch (Exception $e) { - OCP\Util::writeLog('contacts', 'Error importing vcard: '.$e->getMessage().$nl.$card, OCP\Util::ERROR); + OCP\Util::writeLog('contacts', + 'Error importing vcard: ' . $e->getMessage() . $nl . $card, + OCP\Util::ERROR); $failed += 1; } } @@ -100,8 +133,18 @@ writeProgress('100'); sleep(3); OC_Cache::remove($progresskey); if(isset($_POST['fstype']) && $_POST['fstype'] == 'OC_FilesystemView') { - if(!$view->unlink('/' . $_POST['file'])) { - OCP\Util::writeLog('contacts','Import: Error unlinking OC_FilesystemView ' . '/' . $_POST['file'], OCP\Util::ERROR); + if(!$view->unlink('/imports/' . $_POST['file'])) { + OCP\Util::writeLog('contacts', + 'Import: Error unlinking OC_FilesystemView ' . '/' . $_POST['file'], + OCP\Util::ERROR); } } -OCP\JSON::success(array('data' => array('imported'=>$imported, 'failed'=>$failed))); +OCP\JSON::success( + array( + 'data' => array( + 'imported'=>$imported, + 'failed'=>$failed, + 'file'=>$_POST['file'], + ) + ) +); diff --git a/apps/contacts/index.php b/apps/contacts/index.php index 0b4f89b30c0..c35e1b85d4e 100644 --- a/apps/contacts/index.php +++ b/apps/contacts/index.php @@ -14,28 +14,20 @@ OCP\App::checkAppEnabled('contacts'); // Get active address books. This creates a default one if none exists. $ids = OC_Contacts_Addressbook::activeIds(OCP\USER::getUser()); -$contacts = OC_Contacts_VCard::all($ids); -if($contacts === false) { - OCP\Util::writeLog('contacts','index.html: No contacts found.',OCP\Util::DEBUG); +$has_contacts = (count(OC_Contacts_VCard::all($ids, 0, 1)) > 0 + ? true + : false); // just to check if there are any contacts. +if($has_contacts === false) { + OCP\Util::writeLog('contacts', + 'index.html: No contacts found.', + OCP\Util::DEBUG); } -$addressbooks = OC_Contacts_Addressbook::active(OCP\USER::getUser()); - // Load the files we need -OCP\App::setActiveNavigationEntry( 'contacts_index' ); +OCP\App::setActiveNavigationEntry('contacts_index'); // Load a specific user? $id = isset( $_GET['id'] ) ? $_GET['id'] : null; -$details = array(); - -if(is_null($id) && count($contacts) > 0) { - $id = $contacts[0]['id']; -} -unset($contacts); -if(!is_null($id)) { - $vcard = OC_Contacts_App::getContactVCard($id); - $details = OC_Contacts_VCard::structureContact($vcard); -} $property_types = OC_Contacts_App::getAddPropertyOptions(); $phone_types = OC_Contacts_App::getTypesOfProperty('TEL'); $email_types = OC_Contacts_App::getTypesOfProperty('EMAIL'); @@ -46,32 +38,31 @@ $post_max_size = OCP\Util::computerFileSize(ini_get('post_max_size')); $maxUploadFilesize = min($upload_max_filesize, $post_max_size); $freeSpace=OC_Filesystem::free_space('/'); -$freeSpace=max($freeSpace,0); -$maxUploadFilesize = min($maxUploadFilesize ,$freeSpace); +$freeSpace=max($freeSpace, 0); +$maxUploadFilesize = min($maxUploadFilesize, $freeSpace); -OCP\Util::addscript('','jquery.multiselect'); -OCP\Util::addscript('','oc-vcategories'); -OCP\Util::addscript('contacts','contacts'); -OCP\Util::addscript('contacts','expanding'); -OCP\Util::addscript('contacts','jquery.combobox'); -OCP\Util::addscript('contacts','jquery.inview'); -OCP\Util::addscript('contacts','jquery.Jcrop'); -OCP\Util::addscript('contacts','jquery.multi-autocomplete'); -OCP\Util::addStyle('','jquery.multiselect'); -OCP\Util::addStyle('contacts','jquery.combobox'); -OCP\Util::addStyle('contacts','jquery.Jcrop'); -OCP\Util::addStyle('contacts','contacts'); +OCP\Util::addscript('', 'jquery.multiselect'); +OCP\Util::addscript('', 'oc-vcategories'); +OCP\Util::addscript('contacts', 'contacts'); +OCP\Util::addscript('contacts', 'expanding'); +OCP\Util::addscript('contacts', 'jquery.combobox'); +OCP\Util::addscript('files', 'jquery.fileupload'); +OCP\Util::addscript('contacts', 'jquery.inview'); +OCP\Util::addscript('contacts', 'jquery.Jcrop'); +OCP\Util::addscript('contacts', 'jquery.multi-autocomplete'); +OCP\Util::addStyle('', 'jquery.multiselect'); +OCP\Util::addStyle('contacts', 'jquery.combobox'); +OCP\Util::addStyle('contacts', 'jquery.Jcrop'); +OCP\Util::addStyle('contacts', 'contacts'); $tmpl = new OCP\Template( "contacts", "index", "user" ); -$tmpl->assign('uploadMaxFilesize', $maxUploadFilesize); -$tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize)); -$tmpl->assign('property_types', $property_types); -$tmpl->assign('phone_types', $phone_types); -$tmpl->assign('email_types', $email_types); -$tmpl->assign('categories', $categories); -$tmpl->assign('addressbooks', $addressbooks); -$tmpl->assign('details', $details ); -$tmpl->assign('id',$id); +$tmpl->assign('uploadMaxFilesize', $maxUploadFilesize, false); +$tmpl->assign('uploadMaxHumanFilesize', + OCP\Util::humanFileSize($maxUploadFilesize), false); +$tmpl->assign('property_types', $property_types, false); +$tmpl->assign('phone_types', $phone_types, false); +$tmpl->assign('email_types', $email_types, false); +$tmpl->assign('categories', $categories, false); +$tmpl->assign('has_contacts', $has_contacts, false); +$tmpl->assign('id', $id, false); $tmpl->printPage(); - -?> diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index 39ef14e5062..4c6c8bf3d93 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -12,13 +12,42 @@ String.prototype.strip_tags = function(){ Contacts={ UI:{ - notification:function(msg, ndata) { - $('#notification').text(msg); - if(data) { - $('#notification').data(ndata[0],ndata[1]); + /** + * Arguments: + * message: The text message to show. The only mandatory parameter. + * timeout: The timeout in seconds before the notification disappears. Default 10. + * timeouthandler: A function to run on timeout. + * clickhandler: A function to run on click. If a timeouthandler is given it will be cancelled. + * data: An object that will be passed as argument to the timeouthandler and clickhandler functions. + */ + notify:function(params) { + self = this; + if(!self.notifier) { + self.notifier = $('#notification'); + } + self.notifier.text(params.message); + self.notifier.fadeIn(); + self.notifier.on('click', function() { $(this).fadeOut();}); + var timer = setTimeout(function() { + self.notifier.fadeOut(); + if(params.timeouthandler && $.isFunction(params.timeouthandler)) { + params.timeouthandler(self.notifier.data(dataid)); + self.notifier.off('click'); + self.notifier.removeData(dataid); + } + }, params.timeout && $.isNumeric(params.timeout) ? parseInt(params.timeout)*1000 : 10000); + var dataid = timer.toString(); + if(params.data) { + self.notifier.data(dataid, params.data); + } + if(params.clickhandler && $.isFunction(params.clickhandler)) { + self.notifier.on('click', function() { + clearTimeout(timer); + self.notifier.off('click'); + params.clickhandler(self.notifier.data(dataid)); + self.notifier.removeData(dataid); + }); } - $('#notification').fadeIn(); - setTimeout($('#notification').fadeOut(), 10000); }, notImplemented:function() { OC.dialogs.alert(t('contacts', 'Sorry, this functionality has not been implemented yet'), t('contacts', 'Not implemented')); @@ -99,7 +128,7 @@ Contacts={ $('.addresscard,.propertylist li,.propertycontainer').hover( function () { $(this).find('.globe,.mail,.delete,.edit').animate({ opacity: 1.0 }, 200, function() {}); - }, + }, function () { $(this).find('.globe,.mail,.delete,.edit').animate({ opacity: 0.1 }, 200, function() {}); } @@ -110,7 +139,7 @@ Contacts={ obj.tipsy('hide'); Contacts.UI.Card.deleteProperty(obj, 'single'); } - + var goToUrl = function(obj) { var url = Contacts.UI.propertyContainerFor(obj).find('#url').val(); if(url != '') { @@ -118,7 +147,7 @@ Contacts={ newWindow.focus(); } } - + $('#identityprops a.delete').click( function() { deleteItem($(this)) }); $('#identityprops a.delete').keydown( function() { deleteItem($(this)) }); $('#categories_value a.edit').click( function() { $(this).tipsy('hide');OCCategories.edit(); } ); @@ -143,7 +172,7 @@ Contacts={ }); $('#edit_name').click(function(){Contacts.UI.Card.editName()}); $('#edit_name').keydown(function(){Contacts.UI.Card.editName()}); - + $('#phototools li a').click(function() { $(this).tipsy('hide'); }); @@ -170,13 +199,13 @@ Contacts={ OC.dialogs.filepicker(t('contacts', 'Select photo'), Contacts.UI.Card.cloudPhotoSelected, false, 'image', true); }); /* Initialize the photo edit dialog */ - $('#edit_photo_dialog').dialog({ + $('#edit_photo_dialog').dialog({ autoOpen: false, modal: true, height: 'auto', width: 'auto' }); $('#edit_photo_dialog' ).dialog( 'option', 'buttons', [ { text: "Ok", - click: function() { + click: function() { Contacts.UI.Card.savePhoto(this); $(this).dialog('close'); } @@ -186,47 +215,28 @@ Contacts={ click: function() { $(this).dialog('close'); } } ] ); - - /*$('#fn').blur(function(){ - if($('#fn').val() == '') { - OC.dialogs.alert(t('contacts','The name field cannot be empty. Please enter a name for this contact.'), t('contacts','Name is empty'), function() { $('#fn').focus(); }); - $('#fn').focus(); - return false; - } - });*/ - + // Name has changed. Update it and reorder. - // TODO: Take addressbook into account $('#fn').change(function(){ var name = $('#fn').val().strip_tags(); - var item = $('.contacts li[data-id="'+Contacts.UI.Card.id+'"]'); + var item = $('.contacts li[data-id="'+Contacts.UI.Card.id+'"]').detach(); $(item).find('a').html(name); Contacts.UI.Card.fn = name; - var added = false; - $('.contacts li[data-bookid="'+Contacts.UI.Card.bookid+'"]').each(function(){ - if ($(this).text().toLowerCase() > name.toLowerCase()) { - $(this).before(item).fadeIn('fast'); - added = true; - return false; - } - }); - if(!added) { - $('#contacts ul[data-id="'+Contacts.UI.Card.bookid+'"]').append(item); - } + Contacts.UI.Contacts.insertContact({contact:item}); Contacts.UI.Contacts.scrollTo(Contacts.UI.Card.id); }); - $('#contacts_deletecard').click( function() { Contacts.UI.Card.doDelete();return false;} ); - $('#contacts_deletecard').keydown( function(event) { - if(event.which == 13) { - Contacts.UI.Card.doDelete(); + $('#contacts_deletecard').click( function() { Contacts.UI.Card.delayedDelete();return false;} ); + $('#contacts_deletecard').keydown( function(event) { + if(event.which == 13 || event.which == 32) { + Contacts.UI.Card.delayedDelete(); } return false; }); $('#contacts_downloadcard').click( function() { Contacts.UI.Card.doExport();return false;} ); - $('#contacts_downloadcard').keydown( function(event) { - if(event.which == 13) { + $('#contacts_downloadcard').keydown( function(event) { + if(event.which == 13 || event.which == 32) { Contacts.UI.Card.doExport(); } return false; @@ -240,12 +250,12 @@ Contacts={ $('#contacts_details_photo_wrapper').bind('dragover',function(event){ $(event.target).addClass('droppable'); event.stopPropagation(); - event.preventDefault(); + event.preventDefault(); }); $('#contacts_details_photo_wrapper').bind('dragleave',function(event){ $(event.target).removeClass('droppable'); //event.stopPropagation(); - //event.preventDefault(); + //event.preventDefault(); }); $('#contacts_details_photo_wrapper').bind('drop',function(event){ event.stopPropagation(); @@ -258,7 +268,7 @@ Contacts={ $('#contacts_deletecard').tipsy({gravity: 'ne'}); $('#contacts_downloadcard').tipsy({gravity: 'ne'}); $('#contacts_propertymenu_button').tipsy(); - $('#contacts_newcontact, #chooseaddressbook').tipsy({gravity: 'sw'}); + $('#contacts_newcontact, #contacts_import, #chooseaddressbook').tipsy({gravity: 'sw'}); $('body').click(function(e){ if(!$(e.target).is('#contacts_propertymenu_button')) { @@ -285,48 +295,64 @@ Contacts={ $('#contacts_propertymenu_dropdown a').keydown(propertyMenuItem); }, Card:{ - id:'', - fn:'', - fullname:'', - shortname:'', - famname:'', - givname:'', - addname:'', - honpre:'', - honsuf:'', - data:undefined, - update:function(id, bookid) { - var newid, firstitem; - if(!id) { + update:function(params) { // params {cid:int, aid:int} + if(!params) { params = {}; } + $('#contacts li,#contacts h3').removeClass('active'); + console.log('Card, cid: ' + params.cid + ' aid: ' + params.aid); + var newid, bookid, firstitem; + if(!parseInt(params.cid) && !parseInt(params.aid)) { firstitem = $('#contacts ul').first().find('li:first-child'); if(firstitem.length > 0) { - newid = firstitem.data('id'); - bookid = firstitem.data('bookid'); + newid = parseInt(firstitem.data('id')); + bookid = parseInt(firstitem.data('bookid')); + } + } else if(!parseInt(params.cid) && parseInt(params.aid)) { + bookid = parseInt(params.aid); + newid = parseInt($('#contacts').find('li[data-bookid="'+bookid+'"]').first().data('id')); + } else if(parseInt(params.cid) && !parseInt(params.aid)) { + newid = parseInt(params.cid); + var listitem = Contacts.UI.Contacts.getContact(newid); //$('#contacts li[data-id="'+newid+'"]'); + console.log('Is contact in list? ' + listitem.length); + if(listitem.length) { + //bookid = parseInt($('#contacts li[data-id="'+newid+'"]').data('bookid')); + bookid = parseInt(Contacts.UI.Contacts.getContact(newid).data('bookid')); + } else { // contact isn't in list yet. + bookid = 'unknown'; } } else { - newid = id; - bookid = bookid?bookid:$('#contacts li[data-id="'+newid+'"]').data('bookid'); + newid = parseInt(params.cid); + bookid = parseInt(params.aid); } - if(!bookid) { - bookid = $('#contacts h3').first().data('id'); + if(!bookid || !newid) { + bookid = parseInt($('#contacts h3').first().data('id')); + newid = parseInt($('#contacts').find('li[data-bookid="'+bookid+'"]').first().data('id')); } - console.log('bookid: ' +bookid); + console.log('newid: ' + newid + ' bookid: ' +bookid); var localLoadContact = function(newid, bookid) { if($('.contacts li').length > 0) { - $('#contacts li[data-id="'+newid+'"]').addClass('active'); $.getJSON(OC.filePath('contacts', 'ajax', 'contactdetails.php'),{'id':newid},function(jsondata){ if(jsondata.status == 'success'){ - $('#contacts h3[data-id="'+bookid+'"]').trigger('click'); + if(bookid == 'unknown') { + bookid = jsondata.data.addressbookid; + var contact = Contacts.UI.Contacts.insertContact({ + contactlist:$('#contacts ul[data-id="'+bookid+'"]'), + data:jsondata.data + }); + } + $('#contacts li[data-id="'+newid+'"],#contacts h3[data-id="'+bookid+'"]').addClass('active'); + $('#contacts ul[data-id="'+bookid+'"]').slideDown(300); Contacts.UI.Card.loadContact(jsondata.data, bookid); + Contacts.UI.Contacts.scrollTo(newid); } else { OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); } }); } } - + // Make sure proper DOM is loaded. - if(!$('#card')[0] && newid) { + if(!$('#card').length && newid) { + console.log('Loading card DOM'); $.getJSON(OC.filePath('contacts', 'ajax', 'loadcard.php'),{requesttoken:requesttoken},function(jsondata){ if(jsondata.status == 'success'){ $('#rightcontent').html(jsondata.data.page).ready(function() { @@ -339,6 +365,7 @@ Contacts={ }); } else if(!newid) { + console.log('Loading intro'); // load intro page $.getJSON(OC.filePath('contacts', 'ajax', 'loadintro.php'),{},function(jsondata){ if(jsondata.status == 'success'){ @@ -357,19 +384,14 @@ Contacts={ doExport:function() { document.location.href = OC.linkTo('contacts', 'export.php') + '?contactid=' + this.id; }, - doImport:function(){ - Contacts.UI.notImplemented(); - }, editNew:function(){ // add a new contact this.id = ''; this.fn = ''; this.fullname = ''; this.givname = ''; this.famname = ''; this.addname = ''; this.honpre = ''; this.honsuf = ''; //Contacts.UI.Card.add(t('contacts', 'Contact')+';'+t('contacts', 'New')+';;;', t('contacts', 'New Contact'), '', true); Contacts.UI.Card.add(';;;;;', '', '', true); return false; }, - createEntry:function(data) { - return $('<li data-id="'+data.id+'" data-bookid="'+data.addressbookid+'" role="button"><a href="'+OC.linkTo('contacts', 'index.php')+'&id='+data.id+'" style="background: url('+OC.filePath('contacts', '', 'thumbnail.php')+'?id='+data.id+') no-repeat scroll 0% 0% transparent;">'+data.displayname+'</a></li>'); - }, add:function(n, fn, aid, isnew){ // add a new contact + console.log('Adding ' + fn); aid = aid?aid:$('#contacts h3.active').first().data('id'); var localAddcontact = function(n, fn, aid, isnew) { $.post(OC.filePath('contacts', 'ajax', 'addcontact.php'), { n: n, fn: fn, aid: aid, isnew: isnew }, @@ -381,19 +403,7 @@ Contacts={ $.getJSON(OC.filePath('contacts', 'ajax', 'contactdetails.php'),{'id':id},function(jsondata){ if(jsondata.status == 'success'){ Contacts.UI.Card.loadContact(jsondata.data, aid); - $('#contacts .active').removeClass('active'); - var item = $('<li data-id="'+jsondata.data.id+'" class="active"><a href="index.php?id='+jsondata.data.id+'" style="background: url('+OC.filePath('contacts', '', 'thumbnail.php')+'?id='+jsondata.data.id+') no-repeat scroll 0% 0% transparent;">'+Contacts.UI.Card.fn+'</a></li>'); - var added = false; - $('#contacts ul[data-id="'+aid+'"] li').each(function(){ - if ($(this).text().toLowerCase() > Contacts.UI.Card.fn.toLowerCase()) { - $(this).before(item).fadeIn('fast'); - added = true; - return false; - } - }); - if(!added) { - $('#contacts ul[data-id="'+aid+'"]').append(item); - } + var item = Contacts.UI.Contacts.insertContact({data:jsondata.data}); if(isnew) { // add some default properties Contacts.UI.Card.addProperty('EMAIL'); Contacts.UI.Card.addProperty('TEL'); @@ -412,9 +422,9 @@ Contacts={ } }); } - - var card = $('#card')[0]; - if(!card) { + + if(!$('#card').length) { + console.log('Loading card DOM'); $.getJSON(OC.filePath('contacts', 'ajax', 'loadcard.php'),{'requesttoken': requesttoken},function(jsondata){ if(jsondata.status == 'success'){ $('#rightcontent').html(jsondata.data.page).ready(function() { @@ -429,47 +439,63 @@ Contacts={ localAddcontact(n, fn, aid, isnew); } }, - doDelete:function() { + delayedDelete:function() { + /* TODO: + $(window).unload(function() { + deleteFilesInQueue(); + }); + */ $('#contacts_deletecard').tipsy('hide'); - OC.dialogs.confirm(t('contacts', 'Are you sure you want to delete this contact?'), t('contacts', 'Warning'), function(answer) { - if(answer == true) { - $.post(OC.filePath('contacts', 'ajax', 'deletecard.php'),{'id':Contacts.UI.Card.id},function(jsondata){ - if(jsondata.status == 'success'){ - var newid = '', bookid; - var curlistitem = $('#contacts li[data-id="'+jsondata.data.id+'"]'); - var newlistitem = curlistitem.prev('li'); - if(newlistitem == undefined) { - newlistitem = curlistitem.next('li'); - } - curlistitem.remove(); - if(!$(newlistitem).is('li')) { - newid = newlistitem.data('id'); - bookid = newlistitem.data('id'); - } - $('#rightcontent').data('id',newid); - this.id = this.fn = this.fullname = this.shortname = this.famname = this.givname = this.addname = this.honpre = this.honsuf = ''; - this.data = undefined; - - if($('.contacts li').length > 0) { // Load first in list. - Contacts.UI.Card.update(newid, bookid); - } else { - // load intro page - $.getJSON(OC.filePath('contacts', 'ajax', 'loadintro.php'),{},function(jsondata){ - if(jsondata.status == 'success'){ - id = ''; - $('#rightcontent').data('id',''); - $('#rightcontent').html(jsondata.data.page); - } - else{ - OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); - } - }); - } - } - else{ - OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); - } - }); + var newid = '', bookid; + var curlistitem = Contacts.UI.Contacts.getContact(this.id); + curlistitem.removeClass('active'); + var newlistitem = curlistitem.prev('li'); + if(!newlistitem) { + newlistitem = curlistitem.next('li'); + } + curlistitem.detach(); + if($(newlistitem).is('li')) { + newid = newlistitem.data('id'); + bookid = newlistitem.data('bookid'); + } + $('#rightcontent').data('id', newid); + + with(this) { + delete id; delete fn; delete fullname; delete shortname; delete famname; + delete givname; delete addname; delete honpre; delete honsuf; delete data; + } + + if($('.contacts li').length > 0) { + Contacts.UI.Card.update({cid:newid, aid:bookid}); + } else { + // load intro page + $.getJSON(OC.filePath('contacts', 'ajax', 'loadintro.php'),{},function(jsondata){ + if(jsondata.status == 'success'){ + id = ''; + $('#rightcontent').html(jsondata.data.page).removeData('id'); + } + else{ + OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); + } + }); + } + Contacts.UI.notify({ + data:curlistitem, + message:t('contacts','Click to undo deletion of "') + curlistitem.find('a').text() + '"', + timeouthandler:function(contact) { + Contacts.UI.Card.doDelete(contact.data('id')); + delete contact; + }, + clickhandler:function(contact) { + Contacts.UI.Contacts.insertContact({contact:contact}); + Contacts.UI.notify({message:t('contacts', 'Cancelled deletion of: "') + curlistitem.find('a').text() + '"'}); + } + }); + }, + doDelete:function(id) { + $.post(OC.filePath('contacts', 'ajax', 'deletecard.php'),{'id':id},function(jsondata) { + if(jsondata.status == 'error'){ + OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); } }); return false; @@ -486,21 +512,22 @@ Contacts={ this.loadAddresses(); this.loadSingleProperties(); Contacts.UI.loadListHandlers(); + var note = $('#note'); if(this.data.NOTE) { - $('#note').data('checksum', this.data.NOTE[0]['checksum']); - var note = $('#note').find('textarea'); + note.data('checksum', this.data.NOTE[0]['checksum']); + var textarea = note.find('textarea'); var txt = this.data.NOTE[0]['value']; var nheight = txt.split('\n').length > 4 ? txt.split('\n').length+2 : 5; - note.css('min-height', nheight+'em'); - note.attr('rows', nheight); - note.val(txt); - $('#note').show(); - note.expandingTextarea(); + textarea.css('min-height', nheight+'em'); + textarea.attr('rows', nheight); + textarea.val(txt); + note.show(); + textarea.expandingTextarea(); $('#contacts_propertymenu_dropdown a[data-type="NOTE"]').parent().hide(); } else { - $('#note').data('checksum', ''); - $('#note').find('textarea').val(''); - $('#note').hide(); + note.removeData('checksum'); + note.find('textarea').val(''); + note.hide(); $('#contacts_propertymenu_dropdown a[data-type="NOTE"]').parent().show(); } }, @@ -521,15 +548,16 @@ Contacts={ $('#contacts_propertymenu_dropdown a[data-type="'+propname+'"]').parent().hide(); var property = this.data[propname][0]; var value = property['value'], checksum = property['checksum']; - + if(propname == 'BDAY') { var val = $.datepicker.parseDate('yy-mm-dd', value.substring(0, 10)); value = $.datepicker.formatDate('dd-mm-yy', val); } - $('#contact_identity').find('#'+propname.toLowerCase()).val(value); - $('#contact_identity').find('#'+propname.toLowerCase()+'_value').data('checksum', checksum); - $('#contact_identity').find('#'+propname.toLowerCase()+'_label').show(); - $('#contact_identity').find('#'+propname.toLowerCase()+'_value').show(); + var identcontainer = $('#contact_identity'); + identcontainer.find('#'+propname.toLowerCase()).val(value); + identcontainer.find('#'+propname.toLowerCase()+'_value').data('checksum', checksum); + identcontainer.find('#'+propname.toLowerCase()+'_label').show(); + identcontainer.find('#'+propname.toLowerCase()+'_value').show(); } else { $('#contacts_propertymenu_dropdown a[data-type="'+propname+'"]').parent().show(); } @@ -544,8 +572,12 @@ Contacts={ $(this).find('input').val(''); } }); - this.fn = ''; this.fullname = ''; this.givname = ''; this.famname = ''; this.addname = ''; this.honpre = ''; this.honsuf = ''; - var narray = undefined; + + with(this) { + delete fn; delete fullname; delete givname; delete famname; + delete addname; delete honpre; delete honsuf; + } + if(this.data.FN) { this.fn = this.data.FN[0]['value']; } @@ -586,7 +618,7 @@ Contacts={ $.each(names, function(key, value) { $('#fn_select') .append($('<option></option>') - .text(value)); + .text(value)); }); $('#fn_select').combobox('value', this.fn); $('#contact_identity').find('*[data-element="N"]').data('checksum', this.data.N[0]['checksum']); @@ -660,7 +692,7 @@ Contacts={ return false; } container = $(obj).parents('.propertycontainer').first(); // get the parent holding the metadata. - Contacts.UI.loading(container, true); + Contacts.UI.loading(obj, true); var checksum = container.data('checksum'); var name = container.data('element'); var fields = container.find('input.contacts_property,select.contacts_property').serializeArray(); @@ -683,7 +715,7 @@ Contacts={ var q = container.find('input.contacts_property,select.contacts_property,textarea.contacts_property').serialize(); if(q == '' || q == undefined) { OC.dialogs.alert(t('contacts', 'Couldn\'t serialize elements.'), t('contacts', 'Error')); - Contacts.UI.loading(container, false); + Contacts.UI.loading(obj, false); return false; } q = q + '&id=' + this.id + '&name=' + name; @@ -695,13 +727,13 @@ Contacts={ if(jsondata.status == 'success'){ container.data('checksum', jsondata.data.checksum); Contacts.UI.Card.savePropertyInternal(name, fields, checksum, jsondata.data.checksum); - Contacts.UI.loading(container, false); + Contacts.UI.loading(obj, false); $(obj).removeAttr('disabled'); return true; } else{ OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); - Contacts.UI.loading(container, false); + Contacts.UI.loading(obj, false); $(obj).removeAttr('disabled'); return false; } @@ -714,13 +746,13 @@ Contacts={ container.data('checksum', jsondata.data.checksum); // TODO: savePropertyInternal doesn't know about new fields //Contacts.UI.Card.savePropertyInternal(name, fields, checksum, jsondata.data.checksum); - Contacts.UI.loading(container, false); + Contacts.UI.loading(obj, false); $(obj).removeAttr('disabled'); return true; } else{ OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); - Contacts.UI.loading(container, false); + Contacts.UI.loading(obj, false); $(obj).removeAttr('disabled'); return false; } @@ -729,17 +761,9 @@ Contacts={ }, addProperty:function(type){ switch (type) { - case 'PHOTO': - this.loadPhoto(true); - $('#file_upload_form').show(); - $('#contacts_propertymenu_dropdown a[data-type="'+type+'"]').parent().hide(); - $('#file_upload_start').trigger('click'); - break; case 'NOTE': - $('#note').show(); $('#contacts_propertymenu_dropdown a[data-type="'+type+'"]').parent().hide(); - $('#note').find('textarea').expandingTextarea(); - $('#note').find('textarea').focus(); + $('#note').find('textarea').expandingTextarea().show().focus(); break; case 'EMAIL': if($('#emaillist>li').length == 1) { @@ -771,6 +795,7 @@ Contacts={ } }, deleteProperty:function(obj, type){ + console.log('deleteProperty'); Contacts.UI.loading(obj, true); var checksum = Contacts.UI.checksumFor(obj); if(checksum) { @@ -793,8 +818,7 @@ Contacts={ } } else { $('dl dt[data-element="'+proptype+'"],dd[data-element="'+proptype+'"]').hide(); - $('dl dd[data-element="'+proptype+'"]').data('checksum', ''); - $('dl dd[data-element="'+proptype+'"]').find('input').val(''); + $('dl dd[data-element="'+proptype+'"]').data('checksum', '').find('input').val(''); } $('#contacts_propertymenu_dropdown a[data-type="'+proptype+'"]').parent().show(); Contacts.UI.loading(obj, false); @@ -821,14 +845,14 @@ Contacts={ } } }, - editName:function(){ + editName:function() { var params = {id: this.id}; /* Initialize the name edit dialog */ - if($('#edit_name_dialog').dialog('isOpen') == true){ + if($('#edit_name_dialog').dialog('isOpen') == true) { $('#edit_name_dialog').dialog('moveToTop'); - }else{ - $.getJSON(OC.filePath('contacts', 'ajax', 'editname.php'),{id: this.id},function(jsondata){ - if(jsondata.status == 'success'){ + } else { + $.getJSON(OC.filePath('contacts', 'ajax', 'editname.php'),{id: this.id},function(jsondata) { + if(jsondata.status == 'success') { $('body').append('<div id="name_dialog"></div>'); $('#name_dialog').html(jsondata.data.page).find('#edit_name_dialog' ).dialog({ modal: true, @@ -836,7 +860,7 @@ Contacts={ title: t('contacts', 'Edit name'), height: 'auto', width: 'auto', buttons: { - 'Ok':function() { + 'Ok':function() { Contacts.UI.Card.saveName(this); $(this).dialog('close'); }, @@ -887,9 +911,9 @@ Contacts={ $.each(names, function(key, value) { $('#fn_select') .append($('<option></option>') - .text(value)); + .text(value)); }); - + if(this.id == '') { var aid = $(dlg).find('#aid').val(); Contacts.UI.Card.add(n.join(';'), $('#short').text(), aid); @@ -900,10 +924,11 @@ Contacts={ loadAddresses:function(){ $('#addresses').hide(); $('#addressdisplay dl.propertycontainer').remove(); + var addresscontainer = $('#addressdisplay'); for(var adr in this.data.ADR) { - $('#addressdisplay dl').first().clone().insertAfter($('#addressdisplay dl').last()).show(); - $('#addressdisplay dl').last().removeClass('template').addClass('propertycontainer'); - $('#addressdisplay dl').last().data('checksum', this.data.ADR[adr]['checksum']); + addresscontainer.find('dl').first().clone().insertAfter($('#addressdisplay dl').last()).show(); + addresscontainer.find('dl').last().removeClass('template').addClass('propertycontainer'); + addresscontainer.find('dl').last().data('checksum', this.data.ADR[adr]['checksum']); var adrarray = this.data.ADR[adr]['value']; var adrtxt = ''; if(adrarray[0] && adrarray[0].length > 0) { @@ -915,7 +940,7 @@ Contacts={ if(adrarray[2] && adrarray[2].length > 0) { adrtxt = adrtxt + '<li>' + adrarray[2].strip_tags() + '</li>'; } - if((adrarray[3] && adrarray[5]) && adrarray[3].length > 0 || adrarray[5].length > 0) { + if((3 in adrarray && 5 in adrarray) && adrarray[3].length > 0 || adrarray[5].length > 0) { adrtxt = adrtxt + '<li>' + adrarray[5].strip_tags() + ' ' + adrarray[3].strip_tags() + '</li>'; } if(adrarray[4] && adrarray[4].length > 0) { @@ -924,7 +949,7 @@ Contacts={ if(adrarray[6] && adrarray[6].length > 0) { adrtxt = adrtxt + '<li>' + adrarray[6].strip_tags() + '</li>'; } - $('#addressdisplay dl').last().find('.addresslist').html(adrtxt); + addresscontainer.find('dl').last().find('.addresslist').html(adrtxt); var types = new Array(); var ttypes = new Array(); for(var param in this.data.ADR[adr]['parameters']) { @@ -933,12 +958,12 @@ Contacts={ ttypes.push(this.data.ADR[adr]['parameters'][param]); } } - $('#addressdisplay dl').last().find('.adr_type_label').text(types.join('/')); - $('#addressdisplay dl').last().find('.adr_type').val(ttypes.join(',')); - $('#addressdisplay dl').last().find('.adr').val(adrarray.join(';')); - $('#addressdisplay dl').last().data('checksum', this.data.ADR[adr]['checksum']); + addresscontainer.find('dl').last().find('.adr_type_label').text(types.join('/')); + addresscontainer.find('dl').last().find('.adr_type').val(ttypes.join(',')); + addresscontainer.find('dl').last().find('.adr').val(adrarray.join(';')); + addresscontainer.find('dl').last().data('checksum', this.data.ADR[adr]['checksum']); } - if($('#addressdisplay dl').length > 1) { + if(addresscontainer.find('dl').length > 1) { $('#addresses').show(); $('#contact_communication').show(); } @@ -953,7 +978,7 @@ Contacts={ container = $('#addressdisplay dl').last(); container.removeClass('template').addClass('propertycontainer'); } else { - params['checksum'] = Contacts.UI.checksumFor(obj); + params['checksum'] = Contacts.UI.checksumFor(obj); } /* Initialize the address edit dialog */ if($('#edit_address_dialog').dialog('isOpen') == true){ @@ -983,9 +1008,6 @@ Contacts={ close : function(event, ui) { $(this).dialog('destroy').remove(); $('#address_dialog').remove(); - if(isnew) { - container.remove(); - } }, open : function(event, ui) { $( "#adr_city" ).autocomplete({ @@ -1024,7 +1046,7 @@ Contacts={ $( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" ); } }); - $( "#adr_country" ).autocomplete({ + $('#adr_country').autocomplete({ source: function( request, response ) { $.ajax({ url: "http://ws.geonames.org/searchJSON", @@ -1075,15 +1097,23 @@ Contacts={ saveAddress:function(dlg, obj, isnew){ if(isnew) { container = $('#addressdisplay dl').last(); - obj = $('#addressdisplay dl:last-child').find('input').first(); + obj = container.find('input').first(); } else { checksum = Contacts.UI.checksumFor(obj); container = Contacts.UI.propertyContainerFor(obj); } - var adr = new Array($(dlg).find('#adr_pobox').val().strip_tags(),$(dlg).find('#adr_extended').val().strip_tags(),$(dlg).find('#adr_street').val().strip_tags(),$(dlg).find('#adr_city').val().strip_tags(),$(dlg).find('#adr_region').val().strip_tags(),$(dlg).find('#adr_zipcode').val().strip_tags(),$(dlg).find('#adr_country').val().strip_tags()); - $(container).find('.adr').val(adr.join(';')); - $(container).find('.adr_type').val($(dlg).find('#adr_type').val()); - $(container).find('.adr_type_label').html(t('contacts',ucwords($(dlg).find('#adr_type').val().toLowerCase()))); + var adr = new Array( + $(dlg).find('#adr_pobox').val().strip_tags(), + $(dlg).find('#adr_extended').val().strip_tags(), + $(dlg).find('#adr_street').val().strip_tags(), + $(dlg).find('#adr_city').val().strip_tags(), + $(dlg).find('#adr_region').val().strip_tags(), + $(dlg).find('#adr_zipcode').val().strip_tags(), + $(dlg).find('#adr_country').val().strip_tags() + ); + container.find('.adr').val(adr.join(';')); + container.find('.adr_type').val($(dlg).find('#adr_type').val()); + container.find('.adr_type_label').html(t('contacts',ucwords($(dlg).find('#adr_type').val().toLowerCase()))); Contacts.UI.Card.saveProperty($(container).find('input').first()); var adrtxt = ''; if(adr[0].length > 0) { @@ -1104,7 +1134,7 @@ Contacts={ if(adr[6].length > 0) { adrtxt = adrtxt + '<li>' + adr[6] + '</li>'; } - $(container).find('.addresslist').html(adrtxt); + container.find('.addresslist').html(adrtxt); }, uploadPhoto:function(filelist) { if(!filelist) { @@ -1131,24 +1161,25 @@ Contacts={ form.submit(); } }, - loadPhotoHandlers:function(){ - $('#phototools li a').tipsy('hide'); - $('#phototools li a').tipsy(); + loadPhotoHandlers:function() { + var phototools = $('#phototools'); + phototools.find('li a').tipsy('hide'); + phototools.find('li a').tipsy(); if(this.data.PHOTO) { - $('#phototools .delete').click(function() { + phototools.find('.delete').click(function() { $(this).tipsy('hide'); Contacts.UI.Card.deleteProperty($('#contacts_details_photo'), 'single'); $(this).hide(); }); - $('#phototools .edit').click(function() { + phototools.find('.edit').click(function() { $(this).tipsy('hide'); Contacts.UI.Card.editCurrentPhoto(); }); - $('#phototools .delete').show(); - $('#phototools .edit').show(); + phototools.find('.delete').show(); + phototools.find('.edit').show(); } else { - $('#phototools .delete').hide(); - $('#phototools .edit').hide(); + phototools.find('.delete').hide(); + phototools.find('.edit').hide(); } }, cloudPhotoSelected:function(path){ @@ -1169,28 +1200,18 @@ Contacts={ $('#phototools li a').tipsy('hide'); var wrapper = $('#contacts_details_photo_wrapper'); wrapper.addClass('loading').addClass('wait'); - - var img = new Image(); - $(img).load(function () { + delete this.photo; + this.photo = new Image(); + $(this.photo).load(function () { $('img.contacts_details_photo').remove() - $(this).addClass('contacts_details_photo').hide(); + $(this).addClass('contacts_details_photo'); wrapper.removeClass('loading').removeClass('wait'); $(this).insertAfter($('#phototools')).fadeIn(); }).error(function () { // notify the user that the image could not be loaded - $(t('contacts','something went wrong.')).insertAfter($('#phototools')); + Contacts.UI.notify({message:t('contacts','Error loading profile picture.')}); }).attr('src', OC.linkTo('contacts', 'photo.php')+'?id='+self.id+refreshstr); - - $.getJSON(OC.filePath('contacts', 'ajax', 'loadphoto.php'),{'id':this.id, 'refresh': refresh},function(jsondata){ - if(jsondata.status == 'success'){ - $('#contacts_details_photo_wrapper').data('checksum', jsondata.data.checksum); - Contacts.UI.Card.loadPhotoHandlers(); - } - else{ - OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); - } - }); - $('#file_upload_form').show(); + this.loadPhotoHandlers() }, editCurrentPhoto:function(){ $.getJSON(OC.filePath('contacts', 'ajax', 'currentphoto.php'),{'id':this.id},function(jsondata){ @@ -1244,10 +1265,11 @@ Contacts={ }, addMail:function() { //alert('addMail'); - $('#emaillist li.template:first-child').clone(true).appendTo($('#emaillist')).show().find('a .tip').tipsy(); - $('#emaillist li.template:last-child').find('select').addClass('contacts_property'); - $('#emaillist li.template:last-child').removeClass('template').addClass('propertycontainer'); - $('#emaillist li:last-child').find('input[type="email"]').focus(); + var emaillist = $('#emaillist'); + emaillist.find('li.template:first-child').clone(true).appendTo(emaillist).show().find('a .tip').tipsy(); + emaillist.find('li.template:last-child').find('select').addClass('contacts_property'); + emaillist.find('li.template:last-child').removeClass('template').addClass('propertycontainer'); + emaillist.find('li:last-child').find('input[type="email"]').focus(); return false; }, loadMails:function() { @@ -1283,35 +1305,37 @@ Contacts={ return false; }, addPhone:function() { - $('#phonelist li.template:first-child').clone(true).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(); - $('#phonelist li:last-child').find('select').multiselect({ + var phonelist = $('#phonelist'); + phonelist.find('li.template:first-child').clone(true).appendTo(phonelist); //.show(); + phonelist.find('li.template:last-child').find('select').addClass('contacts_property'); + phonelist.find('li.template:last-child').removeClass('template').addClass('propertycontainer'); + phonelist.find('li:last-child').find('input[type="text"]').focus(); + phonelist.find('li:last-child').find('select').multiselect({ noneSelectedText: t('contacts', 'Select type'), header: false, selectedList: 4, classes: 'typelist' }); - $('#phonelist li:last-child').show(); + phonelist.find('li:last-child').show(); return false; }, loadPhones:function() { $('#phones').hide(); $('#phonelist li.propertycontainer').remove(); + var phonelist = $('#phonelist'); for(var phone in this.data.TEL) { this.addPhone(); - $('#phonelist li:last-child').find('select').multiselect('destroy'); - $('#phonelist li:last-child').data('checksum', this.data.TEL[phone]['checksum']) - $('#phonelist li:last-child').find('input[type="text"]').val(this.data.TEL[phone]['value']); + phonelist.find('li:last-child').find('select').multiselect('destroy'); + phonelist.find('li:last-child').data('checksum', this.data.TEL[phone]['checksum']) + phonelist.find('li:last-child').find('input[type="text"]').val(this.data.TEL[phone]['value']); for(var param in this.data.TEL[phone]['parameters']) { if(param.toUpperCase() == 'PREF') { - $('#phonelist li:last-child').find('input[type="checkbox"]').attr('checked', 'checked'); + phonelist.find('li:last-child').find('input[type="checkbox"]').attr('checked', 'checked'); } else if(param.toUpperCase() == 'TYPE') { for(ptype in this.data.TEL[phone]['parameters'][param]) { var pt = this.data.TEL[phone]['parameters'][param][ptype]; - $('#phonelist li:last-child').find('select option').each(function(){ + phonelist.find('li:last-child').find('select option').each(function(){ //if ($(this).val().toUpperCase() == pt.toUpperCase()) { if ($.inArray($(this).val().toUpperCase(), pt.toUpperCase().split(',')) > -1) { $(this).attr('selected', 'selected'); @@ -1320,14 +1344,14 @@ Contacts={ } } } - $('#phonelist li:last-child').find('select').multiselect({ - noneSelectedText: t('contacts', 'Select type'), - header: false, - selectedList: 4, - classes: 'typelist' - }); + phonelist.find('li:last-child').find('select').multiselect({ + noneSelectedText: t('contacts', 'Select type'), + header: false, + selectedList: 4, + classes: 'typelist' + }); } - if($('#phonelist li').length > 1) { + if(phonelist.find('li').length > 1) { $('#phones').show(); $('#contact_communication').show(); } @@ -1335,8 +1359,6 @@ Contacts={ }, }, Addressbooks:{ - droptarget:undefined, - droptext:t('contacts', 'Drop a VCF file<br />to import contacts.'), overview:function(){ if($('#chooseaddressbook_dialog').dialog('isOpen') == true){ $('#chooseaddressbook_dialog').dialog('moveToTop'); @@ -1374,6 +1396,20 @@ Contacts={ } }); }, + addAddressbook:function(name, description, cb) { + $.post(OC.filePath('contacts', 'ajax', 'addaddressbook.php'), { name: name, description: description, active: true }, + function(jsondata){ + if(jsondata.status == 'success'){ + if(cb) { + cb(jsondata.data); + } + } else { + OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); + return false; + } + }); + + }, newAddressbook:function(object){ var tr = $(document.createElement('tr')) .load(OC.filePath('contacts', 'ajax', 'addbook.php')); @@ -1393,6 +1429,7 @@ Contacts={ function(jsondata) { if (jsondata.status == 'success'){ $(obj).closest('tr').remove(); + $('#contacts h3[data-id="'+bookid+'"],#contacts ul[data-id="'+bookid+'"]').remove(); Contacts.UI.Contacts.update(); } else { OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); @@ -1400,135 +1437,20 @@ Contacts={ }); } }, - loadImportHandlers:function() { - $('#import_upload_start').change(function(){ - Contacts.UI.Addressbooks.uploadImport(this.files); - }); - $('#importaddressbook_dialog').find('.upload').click(function() { - Contacts.UI.Addressbooks.droptarget.html(t('contacts', 'Uploading...')); - Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, true); - //$('#import_upload_start').trigger('click'); - //return false; - }); - $('#importaddressbook_dialog').find('.upload').tipsy(); - this.droptarget = $('#import_drop_target'); - $(this.droptarget).bind('dragover',function(event){ - $(event.target).addClass('droppable'); - event.stopPropagation(); - event.preventDefault(); - }); - $(this.droptarget).bind('dragleave',function(event){ - $(event.target).removeClass('droppable'); - }); - $(this.droptarget).bind('drop',function(event){ - event.stopPropagation(); - event.preventDefault(); - $(event.target).removeClass('droppable'); - $(event.target).html(t('contacts', 'Uploading...')); - Contacts.UI.loading(event.target, true); - $.importUpload(event.originalEvent.dataTransfer.files); - }); - - $.importUpload = function(files){ - var file = files[0]; - if(file.size > $('#max_upload').val()){ - OC.dialogs.alert(t('contacts','The file you are trying to upload exceed the maximum size for file uploads on this server.'), t('contacts','Upload too large')); - $(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext); - Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, false); - return; - } - if(file.type.indexOf('text') != 0) { - OC.dialogs.alert(t('contacts','You have dropped a file type that cannot be imported: ') + file.type, t('contacts','Wrong file type')); - $(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext); - Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, false); - return; - } - var xhr = new XMLHttpRequest(); - - if (!xhr.upload) { - OC.dialogs.alert(t('contacts', 'Your browser doesn\'t support AJAX upload. Please upload the contacts file to ownCloud and import that way.'), t('contacts', 'Error')) - } - importUpload = xhr.upload, - xhr.onreadystatechange = function() { - if (xhr.readyState == 4){ - response = $.parseJSON(xhr.responseText); - if(response.status == 'success') { - if(xhr.status == 200) { - Contacts.UI.Addressbooks.doImport(response.data.path, response.data.file); - } else { - $(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext); - Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, false); - OC.dialogs.alert(xhr.status + ': ' + xhr.responseText, t('contacts', 'Error')); - } - } else { - OC.dialogs.alert(response.data.message, t('contacts', 'Error')); - } - } - }; - xhr.open('POST', OC.filePath('contacts', 'ajax', 'uploadimport.php') + '?file='+encodeURIComponent(file.name)+'&requesttoken='+requesttoken, true); - xhr.setRequestHeader('Cache-Control', 'no-cache'); - xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - xhr.setRequestHeader('X_FILE_NAME', encodeURIComponent(file.name)); - xhr.setRequestHeader('X-File-Size', file.size); - xhr.setRequestHeader('Content-Type', file.type); - xhr.send(file); - } - }, - uploadImport:function(filelist) { - if(!filelist) { - OC.dialogs.alert(t('contacts','No files selected for upload.'), t('contacts', 'Error')); - return; - } - //var file = filelist.item(0); - var file = filelist[0]; - var target = $('#import_upload_target'); - var form = $('#import_upload_form'); - var totalSize=0; - if(file.size > $('#max_upload').val()){ - OC.dialogs.alert(t('contacts','The file you are trying to upload exceed the maximum size for file uploads on this server.'), t('contacts', 'Error')); - return; - } else { - target.load(function(){ - var response=jQuery.parseJSON(target.contents().text()); - if(response != undefined && response.status == 'success'){ - Contacts.UI.Addressbooks.doImport(response.data.path, response.data.file); - }else{ - OC.dialogs.alert(response.data.message, t('contacts', 'Error')); - } - }); - form.submit(); - } - }, - importAddressbook:function(object){ - var tr = $(document.createElement('tr')) - .load(OC.filePath('contacts', 'ajax', 'importaddressbook.php')); - $(object).closest('tr').after(tr).hide(); - }, - doImport:function(path, file){ - $(Contacts.UI.Addressbooks.droptarget).html(t('contacts', 'Importing...')); - Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, true); - var id = $('#importaddressbook_dialog').find('#book').val(); - $.post(OC.filePath('contacts', '', 'import.php'), { id: id, path: path, file: file, fstype: 'OC_FilesystemView' }, + doImport:function(file, aid){ + $.post(OC.filePath('contacts', '', 'import.php'), { id: aid, file: file, fstype: 'OC_FilesystemView' }, function(jsondata){ - if(jsondata.status == 'success'){ - Contacts.UI.Addressbooks.droptarget.html(t('contacts', 'Import done. Success/Failure: ')+jsondata.data.imported+'/'+jsondata.data.failed); - $('#chooseaddressbook_dialog').find('#close_button').val(t('contacts', 'OK')); - Contacts.UI.Contacts.update(); - setTimeout( - function() { - $(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext); - }, 5000); - } else { - OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); + if(jsondata.status != 'success'){ + Contacts.UI.notify({message:jsondata.data.message}); } }); - Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, false); + return false; }, submit:function(button, bookid){ var displayname = $("#displayname_"+bookid).val().trim(); var active = $("#edit_active_"+bookid+":checked").length; var description = $("#description_"+bookid).val(); - + if(displayname.length == 0) { OC.dialogs.alert(t('contacts', 'Displayname cannot be empty.'), t('contacts', 'Error')); return false; @@ -1554,60 +1476,151 @@ Contacts={ } }, Contacts:{ + contacts:{}, batchnum:50, + getContact:function(id) { + if(!this.contacts[id]) { + this.contacts[id] = $('#contacts li[data-id="'+id+'"]'); + if(!this.contacts[id]) { + self = this; + $.getJSON(OC.filePath('contacts', 'ajax', 'contactdetails.php'),{'id':id},function(jsondata){ + if(jsondata.status == 'success'){ + self.contacts[id] = self.insertContact({data:jsondata.data}); + } + else{ + OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); + } + }); + } + } + return this.contacts[id]; + }, drop:function(event, ui) { var dragitem = ui.draggable, droptarget = $(this); - //console.log('Drop ' + dragitem.data('id') +' on: ' + droptarget.data('id')); + if(dragitem.is('li')) { + Contacts.UI.Contacts.dropContact(event, dragitem, droptarget); + } else { + Contacts.UI.Contacts.dropAddressbook(event, dragitem, droptarget); + } + }, + dropContact:function(event, dragitem, droptarget) { if(dragitem.data('bookid') == droptarget.data('id')) { return false; } var droplist = (droptarget.is('ul'))?droptarget:droptarget.next(); - $.post(OC.filePath('contacts', 'ajax', 'movetoaddressbook.php'), { ids: dragitem.data('id'), aid: $(this).data('id') }, + $.post(OC.filePath('contacts', 'ajax', 'movetoaddressbook.php'), { ids: dragitem.data('id'), aid: droptarget.data('id') }, function(jsondata){ if(jsondata.status == 'success'){ - // Do some inserting/removing/sorting magic - var name = $(dragitem).find('a').html(); - var added = false; - $(droplist).children().each(function(){ - if ($(this).text().toLowerCase() > name.toLowerCase()) { - $(this).before(dragitem.detach()); //.fadeIn('slow'); - added = true; - return false; - } - }); - if(!added) { - $(droplist).append(dragitem.detach()); - } + dragitem.attr('data-bookid', droptarget.data('id')) dragitem.data('bookid', droptarget.data('id')); + Contacts.UI.Contacts.insertContact({ + contactlist:droplist, + contact:dragitem.detach() + }); Contacts.UI.Contacts.scrollTo(dragitem.data('id')); } else { OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); } }); }, + dropAddressbook:function(event, dragitem, droptarget) { + alert('Dropping address books not implemented yet'); + }, + /** + * @params params An object with the properties 'contactlist':a jquery object of the ul to insert into, + * 'contacts':a jquery object of all items in the list and either 'data': an object with the properties + * id, addressbookid and displayname or 'contact': a listitem to be inserted directly. + * If 'contactlist' or 'contacts' aren't defined they will be search for based in the properties in 'data'. + */ + insertContact:function(params) { + var id, bookid; + if(!params.contactlist) { + // FIXME: Check if contact really exists. + bookid = params.data ? params.data.addressbookid : params.contact.data('bookid'); + id = params.data ? params.data.id : params.contact.data('id'); + params.contactlist = $('#contacts ul[data-id="'+bookid+'"]'); + } + if(!params.contacts) { + bookid = params.data ? params.data.addressbookid : params.contact.data('bookid'); + id = params.data ? params.data.id : params.contact.data('id'); + params.contacts = $('#contacts ul[data-id="'+bookid+'"] li'); + } + var contact = params.data + ? $('<li data-id="'+params.data.id+'" data-bookid="'+params.data.addressbookid+'" role="button"><a href="'+OC.linkTo('contacts', 'index.php')+'&id='+params.data.id+'" style="background: url('+OC.filePath('contacts', '', 'thumbnail.php')+'?id='+params.data.id+') no-repeat scroll 0% 0% transparent;">'+params.data.displayname+'</a></li>') + : params.contact; + var added = false; + var name = params.data ? params.data.displayname.toLowerCase() : contact.find('a').text().toLowerCase(); + if(params.contacts) { + params.contacts.each(function() { + if ($(this).text().toLowerCase() > name) { + $(this).before(contact); + added = true; + return false; + } + }); + } + if(!added || !params.contacts) { + params.contactlist.append(contact); + } + //this.contacts[id] = contact; + return contact; + }, + next:function(reverse) { + // TODO: Check if we're last-child/first-child and jump to next/prev address book. + var curlistitem = $('#contacts li[data-id="'+Contacts.UI.Card.id+'"]'); + var newlistitem = reverse ? curlistitem.prev('li') : curlistitem.next('li'); + if(newlistitem) { + curlistitem.removeClass('active'); + Contacts.UI.Card.update({ + cid:newlistitem.data('id'), + aid:newlistitem.data('bookid') + }); + } + }, + previous:function() { + this.next(true); + }, // Reload the contacts list. - update:function(id, aid, start){ + update:function(params){ + if(!params) { params = {}; } + if(!params.start) { + if(params.aid) { + $('#contacts h3[data-id="'+params.aid+'"],#contacts ul[data-id="'+params.aid+'"]').remove(); + } else { + $('#contacts').empty(); + } + } self = this; - console.log('update: ' + aid + ' ' + start); + console.log('update: ' + params.cid + ' ' + params.aid + ' ' + params.start); var firstrun = false; var opts = {}; - opts['startat'] = (start?start:0); - if(aid) { - opts['aid'] = aid; + opts['startat'] = (params.start?params.start:0); + if(params.aid) { + opts['aid'] = params.aid; } $.getJSON(OC.filePath('contacts', 'ajax', 'contacts.php'),opts,function(jsondata){ if(jsondata.status == 'success'){ var books = jsondata.data.entries; - $.each(jsondata.data.entries, function(b, book) { + $.each(books, function(b, book) { if($('#contacts h3[data-id="'+b+'"]').length == 0) { firstrun = true; - if($('#contacts h3').length == 0) { - $('#contacts').html('<h3 class="addressbook" data-id="'+b+'">'+book.displayname+'</h3><ul class="contacts" data-id="'+b+'"></ul>'); + $('#contacts').html('<h3 class="addressbook" contextmenu="addressbookmenu" data-id="'+b+'">'+book.displayname+'</h3><ul class="contacts hidden" data-id="'+b+'"></ul>'); } else { if(!$('#contacts h3[data-id="'+b+'"]').length) { - $('<h3 class="addressbook" data-id="'+b+'">'+book.displayname+'</h3><ul class="contacts" data-id="'+b+'"></ul>') - .appendTo('#contacts'); + var item = $('<h3 class="addressbook" contextmenu="addressbookmenu" data-id="'+b+'">'+book.displayname+'</h3><ul class="contacts hidden" data-id="'+b+'"></ul>') + var added = false; + $('#contacts h3').each(function(){ + if ($(this).text().toLowerCase() > book.displayname.toLowerCase()) { + $(this).before(item).fadeIn('fast'); + added = true; + return false; + } + }); + if(!added) { + $('#contacts').append(item); + } + } } $('#contacts h3[data-id="'+b+'"]').on('click', function(event) { @@ -1616,45 +1629,46 @@ Contacts={ $('#contacts ul[data-id="'+b+'"]').slideToggle(300); return false; }); - var accept = 'li:not([data-bookid="'+b+'"])'; - $('#contacts h3[data-id="'+b+'"]').droppable({ + var accept = 'li:not([data-bookid="'+b+'"]),h3:not([data-id="'+b+'"])'; + $('#contacts h3[data-id="'+b+'"],#contacts ul[data-id="'+b+'"]').droppable({ drop: Contacts.UI.Contacts.drop, activeClass: 'ui-state-hover', accept: accept }); } var contactlist = $('#contacts ul[data-id="'+b+'"]'); + var contacts = $('#contacts ul[data-id="'+b+'"] li'); for(var c in book.contacts) { if(book.contacts[c].id == undefined) { continue; } - if($('#contacts li[data-id="'+book.contacts[c]['id']+'"][data-id="'+book.contacts[c]['bookid']+'"]').length == 0) { - var contact = Contacts.UI.Card.createEntry(book.contacts[c]); - if(c == self.batchnum-5) { + if(!$('#contacts li[data-id="'+book.contacts[c]['id']+'"]').length) { + var contact = Contacts.UI.Contacts.insertContact({contactlist:contactlist, contacts:contacts, data:book.contacts[c]}); + if(c == self.batchnum-10) { contact.bind('inview', function(event, isInView, visiblePartX, visiblePartY) { $(this).unbind(event); var bookid = $(this).data('bookid'); var numsiblings = $('.contacts li[data-bookid="'+bookid+'"]').length; if (isInView && numsiblings >= self.batchnum) { console.log('This would be a good time to load more contacts.'); - Contacts.UI.Contacts.update(id, bookid, $('#contacts li[data-bookid="'+bookid+'"]').length); + Contacts.UI.Contacts.update({cid:params.cid, aid:bookid, start:$('#contacts li[data-bookid="'+bookid+'"]').length}); } }); } - contactlist.append(contact); } } }); if($('#contacts h3').length > 1) { - $('#contacts li').draggable({ + $('#contacts li,#contacts h3').draggable({ + distance: 10, revert: 'invalid', axis: 'y', containment: '#contacts', - scroll: true, scrollSensitivity: 100, + scroll: true, scrollSensitivity: 40, opacity: 0.7, helper: 'clone' }); } else { $('#contacts h3').first().addClass('active'); } if(opts['startat'] == 0) { // only update card on first load. - Contacts.UI.Card.update(); + Contacts.UI.Card.update(params); } } else{ @@ -1669,9 +1683,10 @@ Contacts={ }, scrollTo:function(id){ var item = $('#contacts li[data-id="'+id+'"]'); - if(item) { - $('.contacts').animate({ - scrollTop: $('#contacts li[data-id="'+id+'"]').offset().top-20}, 'slow','swing'); + if(item && $.isNumeric(item.offset().top)) { + console.log('scrollTo ' + parseInt(item.offset().top)); + $('#contacts').animate({ + scrollTop: parseInt(item.offset()).top-40}, 'slow','swing'); } } } @@ -1682,23 +1697,90 @@ $(document).ready(function(){ OCCategories.changed = Contacts.UI.Card.categoriesChanged; OCCategories.app = 'contacts'; - $('#notification').click(function(){ - $('#notification').fadeOut(); + $('#chooseaddressbook').on('click keydown', Contacts.UI.Addressbooks.overview); + $('#contacts_newcontact').on('click keydown', Contacts.UI.Card.editNew); + + var ninjahelp = $('#ninjahelp'); + + ninjahelp.find('.close').on('click keydown',function() { + ninjahelp.hide(); + }); + + $(document).on('keyup', function(event) { + console.log(event.which + ' ' + event.target.nodeName); + if(event.target.nodeName.toUpperCase() != 'BODY' + || $('#contacts li').length == 0 + || !Contacts.UI.Card.id) { + return; + } + /** + * To add: + * (Shift)n/p: next/prev addressbook + * u (85): hide/show leftcontent + * f (70): add field + */ + switch(event.which) { + case 27: // Esc + ninjahelp.hide(); + break; + case 46: + if(event.shiftKey) { + Contacts.UI.Card.delayedDelete(); + } + break; + case 32: // space + if(event.shiftKey) { + Contacts.UI.Contacts.previous(); + break; + } + case 40: // down + case 75: // k + Contacts.UI.Contacts.next(); + break; + case 65: // a + if(event.shiftKey) { + // add addressbook + Contacts.UI.notImplemented(); + break; + } + Contacts.UI.Card.editNew(); + break; + case 38: // up + case 74: // j + Contacts.UI.Contacts.previous(); + break; + case 78: // n + // next addressbook + Contacts.UI.notImplemented(); + break; + case 13: // Enter + case 79: // o + var aid = $('#contacts h3.active').first().data('id'); + if(aid) { + $('#contacts ul[data-id="'+aid+'"]').slideToggle(300); + } + break; + case 80: // p + // prev addressbook + Contacts.UI.notImplemented(); + break; + case 82: // r + Contacts.UI.Contacts.update({cid:Contacts.UI.Card.id}); + break; + case 191: // ? + ninjahelp.toggle('fast'); + break; + } + }); - - $('#chooseaddressbook').click(Contacts.UI.Addressbooks.overview); - $('#chooseaddressbook').keydown(Contacts.UI.Addressbooks.overview); - $('#contacts_newcontact').click(Contacts.UI.Card.editNew); - $('#contacts_newcontact').keydown(Contacts.UI.Card.editNew); - - // Load a contact. + // Load a contact. $('.contacts').keydown(function(event) { - if(event.which == 13) { + if(event.which == 13 || event.which == 32) { $('.contacts').click(); } }); - $(document).on('click', '.contacts', function(event){ + $(document).on('click', '#contacts', function(event){ var $tgt = $(event.target); if ($tgt.is('li') || $tgt.is('a')) { var item = $tgt.is('li')?$($tgt):($tgt).parent(); @@ -1707,7 +1789,13 @@ $(document).ready(function(){ item.addClass('active'); var oldid = $('#rightcontent').data('id'); if(oldid != 0){ - $('.contacts li[data-id="'+oldid+'"]').removeClass('active'); + var olditem = $('.contacts li[data-id="'+oldid+'"]'); + var oldbookid = olditem.data('bookid'); + olditem.removeClass('active'); + if(oldbookid != bookid) { + $('#contacts h3[data-id="'+oldbookid+'"]').removeClass('active'); + $('#contacts h3[data-id="'+bookid+'"]').addClass('active'); + } } $.getJSON(OC.filePath('contacts', 'ajax', 'contactdetails.php'),{'id':id},function(jsondata){ if(jsondata.status == 'success'){ @@ -1721,81 +1809,267 @@ $(document).ready(function(){ return false; }); - /*$('.contacts li').bind('inview', function(event, isInView, visiblePartX, visiblePartY) { - if (isInView) { //NOTE: I've kept all conditions for future reference ;-) - // element is now visible in the viewport - if (visiblePartY == 'top') { - // top part of element is visible - } else if (visiblePartY == 'bottom') { - // bottom part of element is visible - } else { - // whole part of element is visible - if (!$(this).find('a').attr('style')) { - //alert($(this).data('id') + ' has background: ' + $(this).attr('style')); - $(this).find('a').css('background','url('+OC.filePath('contacts', '', 'thumbnail.php')+'?id='+$(this).data('id')+') no-repeat'); - }// else { - // alert($(this).data('id') + ' has style ' + $(this).attr('style').match('url')); - //} - } - } else { - // element has gone out of viewport - } - });*/ - $('.contacts_property').live('change', function(){ Contacts.UI.Card.saveProperty(this); }); - /** - * Upload function for dropped files. Should go in the Contacts class/object. - */ - $.fileUpload = function(files){ - var file = files[0]; - if(file.size > $('#max_upload').val()){ - OC.dialogs.alert(t('contacts','The file you are trying to upload exceed the maximum size for file uploads on this server.'), t('contacts','Upload too large')); - return; - } - if (file.type.indexOf("image") != 0) { - OC.dialogs.alert(t('contacts','Only image files can be used as profile picture.'), t('contacts','Wrong file type')); - return; - } - var xhr = new XMLHttpRequest(); + $(function() { + // Upload function for dropped contact photos files. Should go in the Contacts class/object. + $.fileUpload = function(files){ + var file = files[0]; + if(file.size > $('#max_upload').val()){ + OC.dialogs.alert(t('contacts','The file you are trying to upload exceed the maximum size for file uploads on this server.'), t('contacts','Upload too large')); + return; + } + if (file.type.indexOf("image") != 0) { + OC.dialogs.alert(t('contacts','Only image files can be used as profile picture.'), t('contacts','Wrong file type')); + return; + } + var xhr = new XMLHttpRequest(); + + if (!xhr.upload) { + OC.dialogs.alert(t('contacts', 'Your browser doesn\'t support AJAX upload. Please click on the profile picture to select a photo to upload.'), t('contacts', 'Error')) + } + fileUpload = xhr.upload, + xhr.onreadystatechange = function() { + if (xhr.readyState == 4){ + response = $.parseJSON(xhr.responseText); + if(response.status == 'success') { + if(xhr.status == 200) { + Contacts.UI.Card.editPhoto(response.data.id, response.data.tmp); + } else { + OC.dialogs.alert(xhr.status + ': ' + xhr.responseText, t('contacts', 'Error')); + } + } else { + OC.dialogs.alert(response.data.message, t('contacts', 'Error')); + } + } + }; - if (!xhr.upload) { - OC.dialogs.alert(t('contacts', 'Your browser doesn\'t support AJAX upload. Please click on the profile picture to select a photo to upload.'), t('contacts', 'Error')) + fileUpload.onprogress = function(e){ + if (e.lengthComputable){ + var _progress = Math.round((e.loaded * 100) / e.total); + //if (_progress != 100){ + //} + } + }; + xhr.open('POST', OC.filePath('contacts', 'ajax', 'uploadphoto.php')+'?id='+Contacts.UI.Card.id+'&requesttoken='+requesttoken+'&imagefile='+encodeURIComponent(file.name), true); + xhr.setRequestHeader('Cache-Control', 'no-cache'); + xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + xhr.setRequestHeader('X_FILE_NAME', encodeURIComponent(file.name)); + xhr.setRequestHeader('X-File-Size', file.size); + xhr.setRequestHeader('Content-Type', file.type); + xhr.send(file); } - fileUpload = xhr.upload, - xhr.onreadystatechange = function() { - if (xhr.readyState == 4){ - response = $.parseJSON(xhr.responseText); - if(response.status == 'success') { - if(xhr.status == 200) { - Contacts.UI.Card.editPhoto(response.data.id, response.data.tmp); + }); + + $(document).bind('drop dragover', function (e) { + e.preventDefault(); // prevent browser from doing anything, if file isn't dropped in dropZone + }); + + //add multiply file upload attribute to all browsers except konqueror (which crashes when it's used) + if(navigator.userAgent.search(/konqueror/i)==-1){ + $('#import_upload_start').attr('multiple','multiple') + } + // Import using jquery.fileupload + $(function() { + var uploadingFiles = {}, numfiles = 0, uploadedfiles = 0, retries = 0; + var aid; + + $('#import_upload_start').fileupload({ + dropZone: $('#contacts'), // restrict dropZone to contacts list. + acceptFileTypes: /^text\/(directory|vcard|x-vcard)$/i, + add: function(e, data) { + var files = data.files; + var totalSize=0; + if(files) { + numfiles += files.length; uploadedfiles = 0; + for(var i=0;i<files.length;i++) { + if(files[i].size ==0 && files[i].type== '') { + OC.dialogs.alert(t('files', 'Unable to upload your file as it is a directory or has 0 bytes'), t('files', 'Upload Error')); + return; + } + totalSize+=files[i].size; + } + } + if(totalSize>$('#max_upload').val()){ + OC.dialogs.alert(t('contacts','The file you are trying to upload exceed the maximum size for file uploads on this server.'), t('contacts','Upload too large')); + numfiles = uploadedfiles = retries = aid = 0; + uploadingFiles = {}; + return; + }else{ + if($.support.xhrFileUpload) { + for(var i=0;i<files.length;i++){ + var fileName = files[i].name; + var dropTarget; + if($(e.originalEvent.target).is('h3')) { + dropTarget = $(e.originalEvent.target).next('ul'); + } else { + dropTarget = $(e.originalEvent.target).closest('ul'); + } + if(dropTarget && dropTarget.hasClass('contacts')) { // TODO: More thorough check for where we are. + aid = dropTarget.attr('data-id'); + } else { + aid = undefined; + } + var jqXHR = $('#import_upload_start').fileupload('send', {files: files[i], + formData: function(form) { + var formArray = form.serializeArray(); + formArray['aid'] = aid; + return formArray; + }}) + .success(function(result, textStatus, jqXHR) { + if(result.status == 'success') { + // import the file + uploadedfiles += 1; + } else { + Contacts.UI.notify({message:jsondata.data.message}); + } + return false; + }) + .error(function(jqXHR, textStatus, errorThrown) { + console.log(textStatus); + Contacts.UI.notify({message:errorThrown + ': ' + textStatus,}); + }); + uploadingFiles[fileName] = jqXHR; + } } else { - OC.dialogs.alert(xhr.status + ': ' + xhr.responseText, t('contacts', 'Error')); + data.submit().success(function(data, status) { + response = jQuery.parseJSON(data[0].body.innerText); + if(response[0] != undefined && response[0].status == 'success') { + var file=response[0]; + delete uploadingFiles[file.name]; + $('tr').filterAttr('data-file',file.name).data('mime',file.mime); + var size = $('tr').filterAttr('data-file',file.name).find('td.filesize').text(); + if(size==t('files','Pending')){ + $('tr').filterAttr('data-file',file.name).find('td.filesize').text(file.size); + } + FileList.loadingDone(file.name); + } else { + Contacts.UI.notify({message:response.data.message}); + } + }); } + } + }, + fail: function(e, data) { + console.log('fail'); + Contacts.UI.notify({message:data.errorThrown + ': ' + data.textStatus}); + // TODO: Remove file from upload queue. + }, + progressall: function(e, data) { + var progress = (data.loaded/data.total)*50; + $('#uploadprogressbar').progressbar('value',progress); + }, + start: function(e, data) { + $('#uploadprogressbar').progressbar({value:0}); + $('#uploadprogressbar').fadeIn(); + if(data.dataType != 'iframe ') { + $('#upload input.stop').show(); + } + }, + stop: function(e, data) { + // stop only gets fired once so we collect uploaded items here. + var importFiles = function(aid, fileList) { + // Create a closure that can be called from different places. + if(numfiles != uploadedfiles) { + Contacts.UI.notify({message:t('contacts', 'Not all files uploaded. Retrying...')}); + retries += 1; + if(retries > 3) { + numfiles = uploadedfiles = retries = aid = 0; + uploadingFiles = {}; + $('#uploadprogressbar').fadeOut(); + OC.dialogs.alert(t('contacts', 'Something went wrong with the upload, please retry.'), t('contacts', 'Error')); + return; + } + setTimeout(function() { // Just to let any uploads finish + importFiles(aid, uploadingFiles); + }, 1000); + } + $('#uploadprogressbar').progressbar('value',50); + var todo = uploadedfiles; + $.each(fileList, function(fileName, data) { + Contacts.UI.Addressbooks.doImport(fileName, aid); + delete fileList[fileName]; + numfiles -= 1; uploadedfiles -= 1; + $('#uploadprogressbar').progressbar('value',50+(50/(todo-uploadedfiles))); + }) + $('#uploadprogressbar').progressbar('value',100); + $('#uploadprogressbar').fadeOut(); + setTimeout(function() { + Contacts.UI.Contacts.update({aid:aid}); + numfiles = uploadedfiles = retries = aid = 0; + }, 1000); + } + if(!aid) { + // Either selected with filepicker or dropped outside of an address book. + $.getJSON(OC.filePath('contacts', 'ajax', 'selectaddressbook.php'),{},function(jsondata) { + if(jsondata.status == 'success') { + if($('#selectaddressbook_dialog').dialog('isOpen') == true) { + $('#selectaddressbook_dialog').dialog('moveToTop'); + } else { + $('#dialog_holder').html(jsondata.data.page).ready(function($) { + var select_dlg = $('#selectaddressbook_dialog'); + select_dlg.dialog({ + modal: true, height: 'auto', width: 'auto', + buttons: { + 'Ok':function() { + aid = select_dlg.find('input:checked').val(); + if(aid == 'new') { + var displayname = select_dlg.find('input.name').val(); + var description = select_dlg.find('input.desc').val(); + if(!displayname.trim()) { + OC.dialogs.alert(t('contacts', 'The address book name cannot be empty.'), t('contacts', 'Error')); + return false; + } + $(this).dialog('close'); + Contacts.UI.Addressbooks.addAddressbook(displayname, description, function(addressbook){ + aid = addressbook.id; + setTimeout(function() { + importFiles(aid, uploadingFiles); + }, 500); + console.log('aid ' + aid); + }); + } else { + setTimeout(function() { + importFiles(aid, uploadingFiles); + }, 500); + console.log('aid ' + aid); + $(this).dialog('close'); + } + }, + 'Cancel':function() { + $(this).dialog('close'); + numfiles = uploadedfiles = retries = aid = 0; + uploadingFiles = {}; + $('#uploadprogressbar').fadeOut(); + } + }, + close: function(event, ui) { + // TODO: If numfiles != 0 delete tmp files after a timeout. + $(this).dialog('destroy').remove(); + } + }); + }); + } + } else { + $('#uploadprogressbar').fadeOut(); + OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); + } + }); } else { - OC.dialogs.alert(response.data.message, t('contacts', 'Error')); + // Dropped on an address book or it's list. + setTimeout(function() { // Just to let any uploads finish + importFiles(aid, uploadingFiles); + }, 1000); + } + if(data.dataType != 'iframe ') { + $('#upload input.stop').hide(); } } - }; - - fileUpload.onprogress = function(e){ - if (e.lengthComputable){ - var _progress = Math.round((e.loaded * 100) / e.total); - //if (_progress != 100){ - //} - } - }; - xhr.open('POST', OC.filePath('contacts', 'ajax', 'uploadphoto.php')+'?id='+Contacts.UI.Card.id+'&requesttoken='+requesttoken+'&imagefile='+encodeURIComponent(file.name), true); - xhr.setRequestHeader('Cache-Control', 'no-cache'); - xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - xhr.setRequestHeader('X_FILE_NAME', encodeURIComponent(file.name)); - xhr.setRequestHeader('X-File-Size', file.size); - xhr.setRequestHeader('Content-Type', file.type); - xhr.send(file); - } + }) + }); Contacts.UI.loadHandlers(); - Contacts.UI.Contacts.update(id); + Contacts.UI.Contacts.update({cid:id}); }); diff --git a/apps/contacts/js/jquery.inview.js b/apps/contacts/js/jquery.inview.js index 01900b0b4b4..9687cd83368 100644 --- a/apps/contacts/js/jquery.inview.js +++ b/apps/contacts/js/jquery.inview.js @@ -62,8 +62,8 @@ function getViewportOffset() { return { - top: w.pageYOffset || documentElement.scrollTop || d.body.scrollTop, - left: w.pageXOffset || documentElement.scrollLeft || d.body.scrollLeft + top: w.pageYOffset || documentElement.scrollTop || (d.body?d.body.scrollTop:0), + left: w.pageXOffset || documentElement.scrollLeft || (d.body?d.body.scrollLeft:0) }; } diff --git a/apps/contacts/js/loader.js b/apps/contacts/js/loader.js index 577ad103064..5bca0ab7237 100644 --- a/apps/contacts/js/loader.js +++ b/apps/contacts/js/loader.js @@ -78,9 +78,9 @@ Contacts_Import={ }
$(document).ready(function(){
if(typeof FileActions !== 'undefined'){
- FileActions.register('text/vcard','importaddressbook', '', Contacts_Import.importdialog);
+ FileActions.register('text/vcard','importaddressbook', '', Contacts_Import.importdialog);
FileActions.setDefault('text/vcard','importaddressbook');
- FileActions.register('text/x-vcard','importaddressbook', '', Contacts_Import.importdialog);
+ FileActions.register('text/x-vcard','importaddressbook', '', Contacts_Import.importdialog);
FileActions.setDefault('text/x-vcard','importaddressbook');
};
});
\ No newline at end of file diff --git a/apps/contacts/lib/VCFExportPlugin.php b/apps/contacts/lib/VCFExportPlugin.php new file mode 100644 index 00000000000..9a64c964b06 --- /dev/null +++ b/apps/contacts/lib/VCFExportPlugin.php @@ -0,0 +1,100 @@ +<?php + +/** + * VCF Exporter + * + * This plugin adds the ability to export entire address books as .vcf files. + * This is useful for clients that don't support CardDAV yet. They often do + * support vcf files. + * + * @package Sabre + * @subpackage CardDAV + * @copyright Copyright (C) 2007-2012 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_CardDAV_VCFExportPlugin extends Sabre_DAV_ServerPlugin { + + /** + * Reference to Server class + * + * @var Sabre_DAV_Server + */ + private $server; + + /** + * Initializes the plugin and registers event handlers + * + * @param Sabre_DAV_Server $server + * @return void + */ + public function initialize(Sabre_DAV_Server $server) { + + $this->server = $server; + $this->server->subscribeEvent('beforeMethod', array($this,'beforeMethod'), 90); + + } + + /** + * 'beforeMethod' event handles. This event handles intercepts GET requests ending + * with ?export + * + * @param string $method + * @param string $uri + * @return bool + */ + public function beforeMethod($method, $uri) { + + if ($method!='GET') return; + if ($this->server->httpRequest->getQueryString()!='export') return; + + // splitting uri + list($uri) = explode('?', $uri, 2); + + $node = $this->server->tree->getNodeForPath($uri); + + if (!($node instanceof Sabre_CardDAV_IAddressBook)) return; + + // Checking ACL, if available. + if ($aclPlugin = $this->server->getPlugin('acl')) { + $aclPlugin->checkPrivileges($uri, '{DAV:}read'); + } + + $this->server->httpResponse->setHeader('Content-Type', 'text/directory'); + $this->server->httpResponse->sendStatus(200); + + $nodes = $this->server->getPropertiesForPath($uri, array( + '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}address-data', + ), 1); + + $this->server->httpResponse->sendBody($this->generateVCF($nodes)); + + // Returning false to break the event chain + return false; + + } + + /** + * Merges all vcard objects, and builds one big vcf export + * + * @param array $nodes + * @return string + */ + public function generateVCF(array $nodes) { + $objects = array(); + + foreach($nodes as $node) { + + if (!isset($node[200]['{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}address-data'])) { + continue; + } + $nodeData = $node[200]['{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}address-data']; + $objects[] = $nodeData; + + } + + return implode("\r\n", $objects); + + } + +} diff --git a/apps/contacts/lib/addressbook.php b/apps/contacts/lib/addressbook.php index 7549464f464..eb61b6dbced 100644 --- a/apps/contacts/lib/addressbook.php +++ b/apps/contacts/lib/addressbook.php @@ -37,17 +37,17 @@ /** * This class manages our addressbooks. */ -class OC_Contacts_Addressbook{ +class OC_Contacts_Addressbook { /** * @brief Returns the list of addressbooks for a specific user. * @param string $uid * @param boolean $active Only return addressbooks with this $active state, default(=false) is don't care * @return array or false. */ - public static function all($uid, $active=false){ + public static function all($uid, $active=false) { $values = array($uid); $active_where = ''; - if ($active){ + if ($active) { $active_where = ' AND active = ?'; $values[] = 1; } @@ -55,13 +55,13 @@ class OC_Contacts_Addressbook{ $stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*contacts_addressbooks WHERE userid = ? ' . $active_where . ' ORDER BY displayname' ); $result = $stmt->execute($values); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.' exception: '.$e->getMessage(),OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.' uid: '.$uid,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.' exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.' uid: '.$uid, OCP\Util::DEBUG); return false; } $addressbooks = array(); - while( $row = $result->fetchRow()){ + while( $row = $result->fetchRow()) { $addressbooks[] = $row; } if(!$active && !count($addressbooks)) { @@ -76,14 +76,14 @@ class OC_Contacts_Addressbook{ * @param integer $uid User id. If null current user will be used. * @return array */ - public static function activeIds($uid = null){ - if(is_null($uid)){ + public static function activeIds($uid = null) { + if(is_null($uid)) { $uid = OCP\USER::getUser(); } $activeaddressbooks = self::all($uid, true); $ids = array(); foreach($activeaddressbooks as $addressbook) { - $ids[] = $addressbook['userid']; + $ids[] = $addressbook['id']; } return $ids; } @@ -93,7 +93,7 @@ class OC_Contacts_Addressbook{ * @param string $uid * @return array */ - public static function active($uid){ + public static function active($uid) { return self::all($uid, true); } @@ -112,13 +112,13 @@ class OC_Contacts_Addressbook{ * @param integer $id * @return associative array or false. */ - public static function find($id){ + public static function find($id) { try { $stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*contacts_addressbooks WHERE id = ?' ); $result = $stmt->execute(array($id)); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(),OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', id: '.$id,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', id: '.$id, OCP\Util::DEBUG); return false; } @@ -129,11 +129,11 @@ class OC_Contacts_Addressbook{ * @brief Adds default address book * @return $id ID of the newly created addressbook or false on error. */ - public static function addDefault($uid = null){ + public static function addDefault($uid = null) { if(is_null($uid)) { $uid = OCP\USER::getUser(); } - $id = self::add($uid,'default','Default Address Book'); + $id = self::add($uid, 'Contacts', 'Default Address Book'); if($id !== false) { self::setActive($id, true); } @@ -147,13 +147,13 @@ class OC_Contacts_Addressbook{ * @param string $description * @return insertid */ - public static function add($uid,$name,$description=''){ + public static function add($uid,$name,$description='') { try { $stmt = OCP\DB::prepare( 'SELECT uri FROM *PREFIX*contacts_addressbooks WHERE userid = ? ' ); $result = $stmt->execute(array($uid)); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.' exception: '.$e->getMessage(),OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.' uid: '.$uid,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.' exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.' uid: '.$uid, OCP\Util::DEBUG); return false; } $uris = array(); @@ -166,8 +166,8 @@ class OC_Contacts_Addressbook{ $stmt = OCP\DB::prepare( 'INSERT INTO *PREFIX*contacts_addressbooks (userid,displayname,uri,description,ctag) VALUES(?,?,?,?,?)' ); $result = $stmt->execute(array($uid,$name,$uri,$description,1)); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(),OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', uid: '.$uid,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', uid: '.$uid, OCP\Util::DEBUG); return false; } @@ -182,16 +182,16 @@ class OC_Contacts_Addressbook{ * @param string $description * @return insertid or false */ - public static function addFromDAVData($principaluri,$uri,$name,$description){ + public static function addFromDAVData($principaluri,$uri,$name,$description) { $uid = self::extractUserID($principaluri); try { $stmt = OCP\DB::prepare('INSERT INTO *PREFIX*contacts_addressbooks (userid,displayname,uri,description,ctag) VALUES(?,?,?,?,?)'); $result = $stmt->execute(array($uid,$name,$uri,$description,1)); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(),OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', uid: '.$uid,OCP\Util::DEBUG); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', uri: '.$uri,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', uid: '.$uid, OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', uri: '.$uri, OCP\Util::DEBUG); return false; } @@ -205,14 +205,14 @@ class OC_Contacts_Addressbook{ * @param string $description * @return boolean */ - public static function edit($id,$name,$description){ + public static function edit($id,$name,$description) { // Need these ones for checking uri $addressbook = self::find($id); - if(is_null($name)){ + if(is_null($name)) { $name = $addressbook['name']; } - if(is_null($description)){ + if(is_null($description)) { $description = $addressbook['description']; } @@ -220,8 +220,8 @@ class OC_Contacts_Addressbook{ $stmt = OCP\DB::prepare('UPDATE *PREFIX*contacts_addressbooks SET displayname=?,description=?, ctag=ctag+1 WHERE id=?'); $result = $stmt->execute(array($name,$description,$id)); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(),OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', id: '.$id,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', id: '.$id, OCP\Util::DEBUG); return false; } @@ -234,15 +234,15 @@ class OC_Contacts_Addressbook{ * @param boolean $active * @return boolean */ - public static function setActive($id,$active){ + public static function setActive($id,$active) { $sql = 'UPDATE *PREFIX*contacts_addressbooks SET active = ? WHERE id = ?'; - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', id: '.$id.', active: '.intval($active),OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', id: '.$id.', active: '.intval($active), OCP\Util::ERROR); try { $stmt = OCP\DB::prepare($sql); $stmt->execute(array(intval($active), $id)); return true; } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception for '.$id.': '.$e->getMessage(),OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception for '.$id.': '.$e->getMessage(), OCP\Util::ERROR); return false; } } @@ -252,7 +252,7 @@ class OC_Contacts_Addressbook{ * @param integer $id ID of the address book. * @return boolean */ - public static function isActive($id){ + public static function isActive($id) { $sql = 'SELECT active FROM *PREFIX*contacts_addressbooks WHERE id = ?'; try { $stmt = OCP\DB::prepare( $sql ); @@ -260,7 +260,7 @@ class OC_Contacts_Addressbook{ $row = $result->fetchRow(); return (bool)$row['active']; } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(),OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); } } @@ -269,13 +269,13 @@ class OC_Contacts_Addressbook{ * @param integer $id * @return boolean */ - public static function delete($id){ + public static function delete($id) { self::setActive($id, false); try { $stmt = OCP\DB::prepare( 'DELETE FROM *PREFIX*contacts_addressbooks WHERE id = ?' ); $stmt->execute(array($id)); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception for '.$id.': '.$e->getMessage(),OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception for '.$id.': '.$e->getMessage(), OCP\Util::ERROR); return false; } @@ -292,7 +292,7 @@ class OC_Contacts_Addressbook{ * @param integer $id * @return boolean */ - public static function touch($id){ + public static function touch($id) { $stmt = OCP\DB::prepare( 'UPDATE *PREFIX*contacts_addressbooks SET ctag = ctag + 1 WHERE id = ?' ); $stmt->execute(array($id)); @@ -305,11 +305,11 @@ class OC_Contacts_Addressbook{ * @param array $existing existing addressbook URIs * @return string new name */ - public static function createURI($name,$existing){ - $name = strtolower($name); + public static function createURI($name,$existing) { + $name = str_replace(' ', '_', strtolower($name)); $newname = $name; $i = 1; - while(in_array($newname,$existing)){ + while(in_array($newname, $existing)) { $newname = $name.$i; $i = $i + 1; } @@ -320,8 +320,8 @@ class OC_Contacts_Addressbook{ * @brief gets the userid from a principal path * @return string */ - public static function extractUserID($principaluri){ - list($prefix,$userid) = Sabre_DAV_URLUtil::splitPath($principaluri); + public static function extractUserID($principaluri) { + list($prefix, $userid) = Sabre_DAV_URLUtil::splitPath($principaluri); return $userid; } } diff --git a/apps/contacts/lib/app.php b/apps/contacts/lib/app.php index 25461877e62..689149367fa 100644 --- a/apps/contacts/lib/app.php +++ b/apps/contacts/lib/app.php @@ -41,7 +41,7 @@ class OC_Contacts_App { $card = OC_Contacts_VCard::find( $id ); if( $card === false ) { OCP\Util::writeLog('contacts', 'Contact could not be found: '.$id, OCP\Util::ERROR); - OCP\JSON::error(array('data' => array( 'message' => self::$l10n->t('Contact could not be found.').' '.$id))); + OCP\JSON::error(array('data' => array( 'message' => self::$l10n->t('Contact could not be found.').' '.print_r($id, true)))); exit(); } @@ -61,11 +61,11 @@ class OC_Contacts_App { if(!is_null($vcard) && !$vcard->__isset('N')) { $version = OCP\App::getAppVersion('contacts'); if($version >= 5) { - OCP\Util::writeLog('contacts','OC_Contacts_App::getContactVCard. Deprecated check for missing N field', OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', 'OC_Contacts_App::getContactVCard. Deprecated check for missing N field', OCP\Util::DEBUG); } - OCP\Util::writeLog('contacts','getContactVCard, Missing N field', OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', 'getContactVCard, Missing N field', OCP\Util::DEBUG); if($vcard->__isset('FN')) { - OCP\Util::writeLog('contacts','getContactVCard, found FN field: '.$vcard->__get('FN'), OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', 'getContactVCard, found FN field: '.$vcard->__get('FN'), OCP\Util::DEBUG); $n = implode(';', array_reverse(array_slice(explode(' ', $vcard->__get('FN')), 0, 2))).';;;'; $vcard->setString('N', $n); OC_Contacts_VCard::edit( $id, $vcard); @@ -196,16 +196,19 @@ class OC_Contacts_App { foreach($vcaddressbooks as $vcaddressbook) { $vcaddressbookids[] = $vcaddressbook['id']; } - $vccontacts = OC_Contacts_VCard::all($vcaddressbookids); - } - } - if(is_array($vccontacts) && count($vccontacts) > 0) { - $cards = array(); - foreach($vccontacts as $vccontact) { - $cards[] = $vccontact['carddata']; + $start = 0; + $batchsize = 10; + while($vccontacts = OC_Contacts_VCard::all($vcaddressbookids, $start, $batchsize)){ + $cards = array(); + foreach($vccontacts as $vccontact) { + $cards[] = $vccontact['carddata']; + } + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', scanning: '.$batchsize.' starting from '.$start, OCP\Util::DEBUG); + // only reset on first batch. + self::getVCategories()->rescan($cards, true, ($start == 0 ? true : false)); + $start += $batchsize; + } } - - self::$categories->rescan($cards); } } diff --git a/apps/contacts/lib/connector_sabre.php b/apps/contacts/lib/connector_sabre.php index c967e906601..9fcfff08fa8 100644 --- a/apps/contacts/lib/connector_sabre.php +++ b/apps/contacts/lib/connector_sabre.php @@ -79,7 +79,7 @@ class OC_Connector_Sabre_CardDAV extends Sabre_CardDAV_Backend_Abstract { } } - OC_Contacts_Addressbook::edit($addressbookid,$name,$description); + OC_Contacts_Addressbook::edit($addressbookid, $name, $description); return true; @@ -113,7 +113,7 @@ class OC_Connector_Sabre_CardDAV extends Sabre_CardDAV_Backend_Abstract { } - OC_Contacts_Addressbook::addFromDAVData($principaluri,$url,$name,$description); + OC_Contacts_Addressbook::addFromDAVData($principaluri, $url, $name, $description); } /** @@ -138,7 +138,9 @@ class OC_Connector_Sabre_CardDAV extends Sabre_CardDAV_Backend_Abstract { foreach($data as $i){ $cards[] = array( 'id' => $i['id'], - 'carddata' => $i['carddata'], + //'carddata' => $i['carddata'], + 'size' => strlen($i['carddata']), + 'etag' => md5($i['carddata']), 'uri' => $i['uri'], 'lastmodified' => $i['lastmodified'] ); } @@ -154,7 +156,7 @@ class OC_Connector_Sabre_CardDAV extends Sabre_CardDAV_Backend_Abstract { * @return array */ public function getCard($addressbookid, $carduri) { - return OC_Contacts_VCard::findWhereDAVDataIs($addressbookid,$carduri); + return OC_Contacts_VCard::findWhereDAVDataIs($addressbookid, $carduri); } diff --git a/apps/contacts/lib/hooks.php b/apps/contacts/lib/hooks.php index d91d3c565b5..3344e3d6939 100644 --- a/apps/contacts/lib/hooks.php +++ b/apps/contacts/lib/hooks.php @@ -34,12 +34,12 @@ */ class OC_Contacts_Hooks{ /** - * @brief Add default Addressbooks of a certain user - * @param paramters parameters from postDeleteUser-Hook + * @brief Add default Addressbook for a certain user + * @param paramters parameters from postCreateUser-Hook * @return array */ static public function createUser($parameters) { - OC_Contacts_Addressbook::addDefault($parameters['uid'],'default','Default Address Book'); + OC_Contacts_Addressbook::addDefault($parameters['uid']); return true; } @@ -61,8 +61,8 @@ class OC_Contacts_Hooks{ static public function getCalenderSources($parameters) { $base_url = OCP\Util::linkTo('calendar', 'ajax/events.php').'?calendar_id='; foreach(OC_Contacts_Addressbook::all(OCP\USER::getUser()) as $addressbook) { - $parameters['sources'][] = - array( + $parameters['sources'][] + = array( 'url' => $base_url.'birthday_'. $addressbook['id'], 'backgroundColor' => '#cccccc', 'borderColor' => '#888', @@ -91,18 +91,24 @@ class OC_Contacts_Hooks{ $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->setDateTime('DTSTART', $date, + Sabre_VObject_Element_DateTime::DATE); $vevent->setString('DURATION', 'P1D'); - $vevent->setString('UID', substr(md5(rand().time()),0,10)); + $vevent->setString('UID', substr(md5(rand().time()), 0, 10)); // DESCRIPTION? $vevent->setString('RRULE', 'FREQ=YEARLY'); - $title = str_replace('{name}', $vcard->getAsString('FN'), OC_Contacts_App::$l10n->t('{name}\'s Birthday')); + $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, - 'calendardata' => "BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:ownCloud Contacts " . OCP\App::getAppVersion('contacts') . "\n" . $vevent->serialize() . "END:VCALENDAR" + 'calendardata' => "BEGIN:VCALENDAR\nVERSION:2.0\n" + . "PRODID:ownCloud Contacts " + . OCP\App::getAppVersion('contacts') . "\n" + . $vevent->serialize() . "END:VCALENDAR" ); } } diff --git a/apps/contacts/lib/search.php b/apps/contacts/lib/search.php index 5d9ca97e761..53aa2b48496 100644 --- a/apps/contacts/lib/search.php +++ b/apps/contacts/lib/search.php @@ -2,7 +2,7 @@ class OC_Search_Provider_Contacts extends OC_Search_Provider{ function search($query){ $addressbooks = OC_Contacts_Addressbook::all(OCP\USER::getUser(), 1); - if(count($addressbooks)==0 || !OCP\App::isEnabled('contacts')){ + if(count($addressbooks)==0 || !OCP\App::isEnabled('contacts')) { return array(); } $results=array(); @@ -10,9 +10,9 @@ class OC_Search_Provider_Contacts extends OC_Search_Provider{ foreach($addressbooks as $addressbook){ $vcards = OC_Contacts_VCard::all($addressbook['id']); foreach($vcards as $vcard){ - if(substr_count(strtolower($vcard['fullname']), strtolower($query)) > 0){ + if(substr_count(strtolower($vcard['fullname']), strtolower($query)) > 0) { $link = OCP\Util::linkTo('contacts', 'index.php').'&id='.urlencode($vcard['id']); - $results[]=new OC_Search_Result($vcard['fullname'],'', $link,(string)$l->t('Contact'));//$name,$text,$link,$type + $results[]=new OC_Search_Result($vcard['fullname'], '', $link, (string)$l->t('Contact'));//$name,$text,$link,$type } } } diff --git a/apps/contacts/lib/vcard.php b/apps/contacts/lib/vcard.php index e3b65605624..ca171e792fc 100644 --- a/apps/contacts/lib/vcard.php +++ b/apps/contacts/lib/vcard.php @@ -63,9 +63,9 @@ class OC_Contacts_VCard{ $stmt = OCP\DB::prepare( $prep ); $result = $stmt->execute($id); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(),OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', ids: '.join(',', $id),OCP\Util::DEBUG); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.'SQL:'.$prep,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', ids: '.join(',', $id), OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.'SQL:'.$prep, OCP\Util::DEBUG); return false; } } elseif(is_int($id) || is_string($id)) { @@ -74,12 +74,12 @@ class OC_Contacts_VCard{ $stmt = OCP\DB::prepare( $sql ); $result = $stmt->execute(array($id)); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(),OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', ids: '. $id,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', ids: '. $id, OCP\Util::DEBUG); return false; } } else { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.'. Addressbook id(s) argument is empty: '. $id,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.'. Addressbook id(s) argument is empty: '. $id, OCP\Util::DEBUG); return false; } $cards = array(); @@ -102,8 +102,8 @@ class OC_Contacts_VCard{ $stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE id = ?' ); $result = $stmt->execute(array($id)); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(),OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', id: '. $id,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', id: '. $id, OCP\Util::DEBUG); return false; } @@ -121,8 +121,8 @@ class OC_Contacts_VCard{ $stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid = ? AND uri = ?' ); $result = $stmt->execute(array($aid,$uri)); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', aid: '.$aid.' uri'.$uri, OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', aid: '.$aid.' uri'.$uri, OCP\Util::DEBUG); return false; } @@ -177,16 +177,16 @@ class OC_Contacts_VCard{ try { $result = $stmt->execute(array($aid,$uri)); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', aid: '.$aid.' uid'.$uid, OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', aid: '.$aid.' uid'.$uid, OCP\Util::DEBUG); return false; } - if($result->numRows() > 0){ + if($result->numRows() > 0) { while(true) { - $tmpuid = substr(md5(rand().time()),0,10); + $tmpuid = substr(md5(rand().time()), 0, 10); $uri = $tmpuid.'.vcf'; - $result = $stmt->execute(array($aid,$uri)); - if($result->numRows() > 0){ + $result = $stmt->execute(array($aid, $uri)); + if($result->numRows() > 0) { continue; } else { $uid = $tmpuid; @@ -212,7 +212,7 @@ class OC_Contacts_VCard{ // Add version if needed if($version && $version < '3.0') { $upgrade = true; - OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateValuesFromAdd. Updating from version: '.$version,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', 'OC_Contacts_VCard::updateValuesFromAdd. Updating from version: '.$version, OCP\Util::DEBUG); } foreach($vcard->children as &$property){ // Decode string properties and remove obsolete properties. @@ -225,29 +225,29 @@ class OC_Contacts_VCard{ } // Fix format of type parameters. if($upgrade && in_array($property->name, $typeprops)) { - OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateValuesFromAdd. before: '.$property->serialize(),OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', 'OC_Contacts_VCard::updateValuesFromAdd. before: '.$property->serialize(), OCP\Util::DEBUG); self::formatPropertyTypes($property); - OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateValuesFromAdd. after: '.$property->serialize(),OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', 'OC_Contacts_VCard::updateValuesFromAdd. after: '.$property->serialize(), OCP\Util::DEBUG); } - if($property->name == 'FN'){ + if($property->name == 'FN') { $fn = $property->value; } - if($property->name == 'N'){ + if($property->name == 'N') { $n = $property->value; } - if($property->name == 'UID'){ + if($property->name == 'UID') { $uid = $property->value; } - if($property->name == 'ORG'){ + 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. + if($property->name == 'EMAIL' && is_null($email)) { // only use the first email as substitute for missing N or FN. $email = $property->value; } } // Check for missing 'N', 'FN' and 'UID' properties if(!$fn) { - if($n && $n != ';;;;'){ + if($n && $n != ';;;;') { $fn = join(' ', array_reverse(array_slice(explode(';', $n), 0, 2))); } elseif($email) { $fn = $email; @@ -257,21 +257,21 @@ class OC_Contacts_VCard{ $fn = 'Unknown Name'; } $vcard->setString('FN', $fn); - OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateValuesFromAdd. Added missing \'FN\' field: '.$fn,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', 'OC_Contacts_VCard::updateValuesFromAdd. Added missing \'FN\' field: '.$fn, OCP\Util::DEBUG); } - if(!$n || $n == ';;;;'){ // Fix missing 'N' field. Ugly hack ahead ;-) + if(!$n || $n == ';;;;') { // Fix missing 'N' field. Ugly hack ahead ;-) $slice = array_reverse(array_slice(explode(' ', $fn), 0, 2)); // Take 2 first name parts of 'FN' and reverse. if(count($slice) < 2) { // If not enought, add one more... $slice[] = ""; } $n = implode(';', $slice).';;;'; $vcard->setString('N', $n); - OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateValuesFromAdd. Added missing \'N\' field: '.$n,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', 'OC_Contacts_VCard::updateValuesFromAdd. Added missing \'N\' field: '.$n, OCP\Util::DEBUG); } if(!$uid) { $vcard->setUID(); $uid = $vcard->getAsString('UID'); - OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateValuesFromAdd. Added missing \'UID\' field: '.$uid,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', 'OC_Contacts_VCard::updateValuesFromAdd. Added missing \'UID\' field: '.$uid, OCP\Util::DEBUG); } if(self::trueUID($aid, $uid)) { $vcard->setString('UID', $uid); @@ -288,8 +288,8 @@ class OC_Contacts_VCard{ * @return insertid on success or false. */ public static function add($aid, OC_VObject $card, $uri=null, $isnew=false){ - if(is_null($card)){ - OCP\Util::writeLog('contacts','OC_Contacts_VCard::add. No vCard supplied', OCP\Util::ERROR); + if(is_null($card)) { + OCP\Util::writeLog('contacts', 'OC_Contacts_VCard::add. No vCard supplied', OCP\Util::ERROR); return null; }; @@ -298,7 +298,7 @@ class OC_Contacts_VCard{ self::updateValuesFromAdd($aid, $card); } - $card->setString('VERSION','3.0'); + $card->setString('VERSION', '3.0'); // Add product ID is missing. $prodid = trim($card->getAsString('PRODID')); if(!$prodid) { @@ -323,8 +323,8 @@ class OC_Contacts_VCard{ try { $result = $stmt->execute(array($aid,$fn,$data,$uri,time())); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', aid: '.$aid.' uri'.$uri, OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', aid: '.$aid.' uri'.$uri, OCP\Util::DEBUG); return false; } $newid = OCP\DB::insertid('*PREFIX*contacts_cards'); @@ -355,15 +355,15 @@ class OC_Contacts_VCard{ $now = new DateTime; foreach($objects as $object) { $vcard = OC_VObject::parse($object[1]); - if(!is_null($vcard)){ + if(!is_null($vcard)) { $vcard->setString('REV', $now->format(DateTime::W3C)); $data = $vcard->serialize(); try { $result = $stmt->execute(array($data,time(),$object[0])); //OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateDataByID, id: '.$object[0].': '.$object[1],OCP\Util::DEBUG); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(),OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', id: '.$object[0],OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', id: '.$object[0], OCP\Util::DEBUG); } } } @@ -397,8 +397,8 @@ class OC_Contacts_VCard{ try { $result = $stmt->execute(array($fn,$data,time(),$id)); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', id'.$id, OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', id'.$id, OCP\Util::DEBUG); return false; } @@ -414,11 +414,11 @@ class OC_Contacts_VCard{ * @param string $data vCard file * @return boolean */ - public static function editFromDAVData($aid,$uri,$data){ - $oldcard = self::findWhereDAVDataIs($aid,$uri); + public static function editFromDAVData($aid, $uri, $data){ + $oldcard = self::findWhereDAVDataIs($aid, $uri); $card = OC_VObject::parse($data); if(!$card) { - OCP\Util::writeLog('contacts','OC_Contacts_VCard::editFromDAVData. Unable to parse VCARD, uri: '.$uri,OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', Unable to parse VCARD, uri: '.$uri, OCP\Util::ERROR); return false; } return self::edit($oldcard['id'], $card); @@ -430,14 +430,13 @@ class OC_Contacts_VCard{ * @return boolean */ public static function delete($id){ - // FIXME: Add error checking. OC_Hook::emit('OC_Contacts_VCard', 'pre_deleteVCard', array('aid' => null, 'id' => $id, 'uri' => null)); $stmt = OCP\DB::prepare( 'DELETE FROM *PREFIX*contacts_cards WHERE id = ?' ); try { $stmt->execute(array($id)); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', id: '.$id, OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', id: '.$id, OCP\Util::DEBUG); return false; } @@ -451,14 +450,13 @@ class OC_Contacts_VCard{ * @return boolean */ public static function deleteFromDAVData($aid,$uri){ - // FIXME: Add error checking. Deleting a card gives an Kontact/Akonadi error. OC_Hook::emit('OC_Contacts_VCard', 'pre_deleteVCard', array('aid' => $aid, 'id' => null, 'uri' => $uri)); $stmt = OCP\DB::prepare( 'DELETE FROM *PREFIX*contacts_cards WHERE addressbookid = ? AND uri=?' ); try { $stmt->execute(array($aid,$uri)); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', aid: '.$aid.' uri: '.$uri, OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', aid: '.$aid.' uri: '.$uri, OCP\Util::DEBUG); return false; } OC_Contacts_Addressbook::touch($aid); @@ -487,14 +485,14 @@ class OC_Contacts_VCard{ * @return array */ public static function unescapeDelimiters($value, $delimiter=';') { - $array = explode($delimiter,$value); + $array = explode($delimiter, $value); for($i=0;$i<count($array);$i++) { - if(substr($array[$i],-1,1)=="\\") { + if(substr($array[$i], -1, 1)=="\\") { if(isset($array[$i+1])) { - $array[$i] = substr($array[$i],0,count($array[$i])-2).$delimiter.$array[$i+1]; + $array[$i] = substr($array[$i], 0, count($array[$i])-2).$delimiter.$array[$i+1]; unset($array[$i+1]); } else { - $array[$i] = substr($array[$i],0,count($array[$i])-2).$delimiter; + $array[$i] = substr($array[$i], 0, count($array[$i])-2).$delimiter; } $i = $i - 1; } @@ -510,12 +508,12 @@ class OC_Contacts_VCard{ * * look at code ... */ - public static function structureContact($object){ + public static function structureContact($object) { $details = array(); foreach($object->children as $property){ $temp = self::structureProperty($property); if(!is_null($temp)) { - if(array_key_exists($property->name,$details)){ + if(array_key_exists($property->name, $details)) { $details[$property->name][] = $temp; } else{ @@ -539,10 +537,10 @@ class OC_Contacts_VCard{ * NOTE: $value is not escaped anymore. It shouldn't make any difference * but we should look out for any problems. */ - public static function structureProperty($property){ + public static function structureProperty($property) { $value = $property->value; //$value = htmlspecialchars($value); - if($property->name == 'ADR' || $property->name == 'N'){ + if($property->name == 'ADR' || $property->name == 'N') { $value = self::unescapeDelimiters($value); } elseif($property->name == 'BDAY') { if(strpos($value, '-') === false) { @@ -562,17 +560,17 @@ class OC_Contacts_VCard{ // Faulty entries by kaddressbook // Actually TYPE=PREF is correct according to RFC 2426 // but this way is more handy in the UI. Tanghus. - if($parameter->name == 'TYPE' && $parameter->value == 'PREF'){ + if($parameter->name == 'TYPE' && $parameter->value == 'PREF') { $parameter->name = 'PREF'; $parameter->value = '1'; } // NOTE: Apparently Sabre_VObject_Reader can't always deal with value list parameters // like TYPE=HOME,CELL,VOICE. Tanghus. - if (in_array($property->name, array('TEL', 'EMAIL')) && $parameter->name == 'TYPE'){ - if (isset($temp['parameters'][$parameter->name])){ + if (in_array($property->name, array('TEL', 'EMAIL')) && $parameter->name == 'TYPE') { + if (isset($temp['parameters'][$parameter->name])) { $temp['parameters'][$parameter->name][] = $parameter->value; } - else{ + else { $temp['parameters'][$parameter->name] = array($parameter->value); } } @@ -590,7 +588,7 @@ class OC_Contacts_VCard{ * @return boolean * */ - public static function moveToAddressBook($aid, $id){ + public static function moveToAddressBook($aid, $id) { OC_Contacts_App::getAddressbook($aid); // check for user ownership. if(is_array($id)) { $id_sql = join(',', array_fill(0, count($id), '?')); @@ -601,9 +599,9 @@ class OC_Contacts_VCard{ $vals = array_merge((array)$aid, $id); $result = $stmt->execute($vals); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(),OCP\Util::ERROR); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', ids: '.join(',', $vals),OCP\Util::DEBUG); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', SQL:'.$prep,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::ERROR); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', ids: '.join(',', $vals), OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', SQL:'.$prep, OCP\Util::DEBUG); return false; } } else { @@ -611,8 +609,8 @@ class OC_Contacts_VCard{ $stmt = OCP\DB::prepare( 'UPDATE *PREFIX*contacts_cards SET addressbookid = ? WHERE id = ?' ); $result = $stmt->execute(array($aid, $id)); } catch(Exception $e) { - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(),OCP\Util::DEBUG); - OCP\Util::writeLog('contacts',__CLASS__.'::'.__METHOD__.' id: '.$id,OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.', exception: '.$e->getMessage(), OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', __CLASS__.'::'.__METHOD__.' id: '.$id, OCP\Util::DEBUG); return false; } } diff --git a/apps/contacts/photo.php b/apps/contacts/photo.php index 4660d61f618..efdf157cd95 100644 --- a/apps/contacts/photo.php +++ b/apps/contacts/photo.php @@ -13,7 +13,7 @@ OCP\User::checkLoggedIn(); OCP\App::checkAppEnabled('contacts'); -function getStandardImage(){ +function getStandardImage() { //OCP\Response::setExpiresHeader('P10D'); OCP\Response::enableCaching(); OCP\Response::redirect(OCP\Util::imagePath('contacts', 'person_large.png')); @@ -27,37 +27,39 @@ if(is_null($id)) { } if(!extension_loaded('gd') || !function_exists('gd_info')) { - OCP\Util::writeLog('contacts','photo.php. GD module not installed',OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', + 'photo.php. GD module not installed', OCP\Util::DEBUG); getStandardImage(); } $contact = OC_Contacts_App::getContactVCard($id); $image = new OC_Image(); -if(!$image) { +if (!$image) { getStandardImage(); } // invalid vcard -if( is_null($contact)) { - OCP\Util::writeLog('contacts','photo.php. The VCard for ID '.$id.' is not RFC compatible',OCP\Util::ERROR); +if (is_null($contact)) { + OCP\Util::writeLog('contacts', + 'photo.php. The VCard for ID ' . $id . ' is not RFC compatible', + OCP\Util::ERROR); } else { OCP\Response::enableCaching($caching); OC_Contacts_App::setLastModifiedHeader($contact); // Photo :-) - if($image->loadFromBase64($contact->getAsString('PHOTO'))) { + if ($image->loadFromBase64($contact->getAsString('PHOTO'))) { // OK OCP\Response::setETagHeader(md5($contact->getAsString('PHOTO'))); } else // Logo :-/ - if($image->loadFromBase64($contact->getAsString('LOGO'))) { + if ($image->loadFromBase64($contact->getAsString('LOGO'))) { // OK OCP\Response::setETagHeader(md5($contact->getAsString('LOGO'))); } if ($image->valid()) { $max_size = 200; - if($image->width() > $max_size || - $image->height() > $max_size) { + if ($image->width() > $max_size || $image->height() > $max_size) { $image->resize($max_size); } } @@ -65,8 +67,7 @@ if( is_null($contact)) { if (!$image->valid()) { // Not found :-( getStandardImage(); - //$image->loadFromFile('img/person_large.png'); } header('Content-Type: '.$image->mimeType()); $image->show(); -//echo OC_Contacts_App::$l10n->t('This card does not contain a photo.'); + diff --git a/apps/contacts/settings.php b/apps/contacts/settings.php index c88fed0b4d6..a079499381b 100644 --- a/apps/contacts/settings.php +++ b/apps/contacts/settings.php @@ -1,6 +1,6 @@ <?php $tmpl = new OCP\Template( 'contacts', 'settings'); +$tmpl->assign('addressbooks', OC_Contacts_Addressbook::all(OCP\USER::getUser()), false); return $tmpl->fetchPage(); -?> diff --git a/apps/contacts/templates/index.php b/apps/contacts/templates/index.php index a8fb6c57c2c..b2dde12684c 100644 --- a/apps/contacts/templates/index.php +++ b/apps/contacts/templates/index.php @@ -1,3 +1,4 @@ +<div id='notification'></div> <script type='text/javascript'> var totalurl = '<?php echo OCP\Util::linkToRemote('carddav'); ?>addressbooks'; var categories = <?php echo json_encode($_['categories']); ?>; @@ -5,25 +6,69 @@ var lang = '<?php echo OCP\Config::getUserValue(OCP\USER::getUser(), 'core', 'lang', 'en'); ?>'; </script> <div id="leftcontent"> + <div class="hidden" id="statusbar"></div> <div id="contacts"> </div> + <div id="uploadprogressbar"></div> <div id="bottomcontrols"> - <form> - <button class="svg" id="contacts_newcontact" title="<?php echo $l->t('Add Contact'); ?>"><img class="svg" src="<?php echo OCP\Util::imagePath('contacts', 'contact-new.svg'); ?>" alt="<?php echo $l->t('Add Contact'); ?>" /></button> + <form id="import_upload_form" action="<?php echo OCP\Util::linkTo('contacts', 'ajax/uploadimport.php'); ?>" method="post" enctype="multipart/form-data" target="import_upload_target"> + <button class="svg" id="contacts_newcontact" title="<?php echo $l->t('Add Contact'); ?>"><img class="svg" src="<?php echo OCP\Util::imagePath('contacts', 'contact-new.svg'); ?>" alt="<?php echo $l->t('Add Contact'); ?>" /></button> + <span class="svg" id="contacts_import" title="<?php echo $l->t('Import'); ?>"> + <input class="float" id="import_upload_start" type="file" accept="text/directory,text/vcard,text/x-vcard" name="importfile" /> + <img class="svg" src="core/img/actions/upload.svg" alt="<?php echo $l->t('Import'); ?>" /> + </span> <button class="svg" id="chooseaddressbook" title="<?php echo $l->t('Addressbooks'); ?>"><img class="svg" src="core/img/actions/settings.svg" alt="<?php echo $l->t('Addressbooks'); ?>" /></button> + <input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $_['uploadMaxFilesize'] ?>" id="max_upload"> </form> + <iframe name="import_upload_target" id='import_upload_target' src=""></iframe> </div> </div> <div id="rightcontent" class="rightcontent" data-id="<?php echo $_['id']; ?>"> <?php - if ($_['id']){ + if($_['has_contacts']) { echo $this->inc('part.contact'); } else{ echo $this->inc('part.no_contacts'); } ?> + <div class="hidden" id="ninjahelp"> + <a class="close" tabindex="0" role="button"> + <img class="svg" src="core/img/actions/delete.svg" alt="<?php echo $l->t('Close'); ?>" /> + </a> + <h2><?php echo $l->t('Keyboard shortcuts'); ?></h2> + <div class="help-section"> + <h3><?php echo $l->t('Navigation'); ?></h3> + <dl> + <dt>j/Down/Space</dt> + <dd><?php echo $l->t('Next contact in list'); ?></dd> + <dt>k/Up/Shift-Space</dt> + <dd><?php echo $l->t('Previous contact in list'); ?></dd> + <dt>o/Enter</dt> + <dd><?php echo $l->t('Expand/collapse current addressbook'); ?></dd> + <dt>n/p</dt> + <dd><?php echo $l->t('Next/previous addressbook'); ?></dd> + </dl> + </div> + <div class="help-section"> + <h3><?php echo $l->t('Actions'); ?></h3> + <dl> + <dt>r</dt> + <dd><?php echo $l->t('Refresh contacts list'); ?></dd> + <dt>a</dt> + <dd><?php echo $l->t('Add new contact'); ?></dd> + <dt>Shift-a</dt> + <dd><?php echo $l->t('Add new addressbook'); ?></dd> + <dt>Shift-Delete</dt> + <dd><?php echo $l->t('Delete current contact'); ?></dd> + </dl> + </div> + </div> </div> <!-- Dialogs --> <div id="dialog_holder"></div> <!-- End of Dialogs --> +<menu type="context" id="addressbookmenu"> + <menuitem label="Delete" icon="core/img/actions/delete.svg" onclick="alert('Really? ' + $(this).attr('data-id'))"></menuitem> + <menuitem label="Rename" icon="core/img/actions/rename.svg" onclick="alert('Can\'t do that')"></menuitem> +</menu> diff --git a/apps/contacts/templates/part.chooseaddressbook.php b/apps/contacts/templates/part.chooseaddressbook.php index a0ec053ab91..caed67736c5 100644 --- a/apps/contacts/templates/part.chooseaddressbook.php +++ b/apps/contacts/templates/part.chooseaddressbook.php @@ -14,7 +14,6 @@ for($i = 0; $i < count($option_addressbooks); $i++){ <tr> <td colspan="5" style="padding: 0.5em;"> <a class="button" href="#" onclick="Contacts.UI.Addressbooks.newAddressbook(this);"><?php echo $l->t('New Address Book') ?></a> - <a class="button" href="#" onclick="Contacts.UI.Addressbooks.importAddressbook(this);"><?php echo $l->t('Import from VCF') ?></a> </td> </tr> <tr> diff --git a/apps/contacts/templates/part.cropphoto.php b/apps/contacts/templates/part.cropphoto.php index 6d7b1e44777..3f5817622b2 100644 --- a/apps/contacts/templates/part.cropphoto.php +++ b/apps/contacts/templates/part.cropphoto.php @@ -2,7 +2,6 @@ $id = $_['id']; $tmpkey = $_['tmpkey']; $requesttoken = $_['requesttoken']; -OCP\Util::writeLog('contacts','templates/part.cropphoto.php: tmpkey: '.$tmpkey, OCP\Util::DEBUG); ?> <script type="text/javascript"> jQuery(function($) { diff --git a/apps/contacts/templates/part.edit_categories_dialog.php b/apps/contacts/templates/part.edit_categories_dialog.php deleted file mode 100644 index 8997fa586bd..00000000000 --- a/apps/contacts/templates/part.edit_categories_dialog.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php -$categories = isset($_['categories'])?$_['categories']:array(); -?> -<div id="edit_categories_dialog" title="<?php echo $l->t('Edit categories'); ?>"> -<!-- ?php print_r($types); ? --> - <form method="post" id="categoryform"> - <div class="scrollarea"> - <ul id="categorylist"> - <?php foreach($categories as $category) { ?> - <li><input type="checkbox" name="categories[]" value="<?php echo $category; ?>" /><?php echo $category; ?></li> - <?php } ?> - </ul> - </div> - <div class="bottombuttons"><input type="text" id="category_addinput" name="category" /><button id="category_addbutton" disabled="disabled"><?php echo $l->t('Add'); ?></button></div> - </form> -</div> diff --git a/apps/contacts/templates/part.importaddressbook.php b/apps/contacts/templates/part.importaddressbook.php deleted file mode 100644 index 01f8dd77d0a..00000000000 --- a/apps/contacts/templates/part.importaddressbook.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -/** - * Copyright (c) 2012 Thomas Tanghus <thomas@tanghus.net> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ -?> -<td id="importaddressbook_dialog" colspan="6"> -<table> -<tr> - <th><?php echo $l->t('Select address book to import to:') ?></th> - <td> - <form id="import_upload_form" action="<?php echo OCP\Util::linkTo('contacts', 'ajax/uploadimport.php'); ?>" method="post" enctype="multipart/form-data" target="import_upload_target"> - <select id="book" name="book" class="float"> - <?php - $contacts_options = OC_Contacts_Addressbook::all(OCP\USER::getUser()); - echo OCP\html_select_options($contacts_options, $contacts_options[0]['id'], array('value'=>'id', 'label'=>'displayname')); - ?> - </select> - <span id="import_drop_target" class="droptarget float"><?php echo $l->t("Drop a VCF file<br />to import contacts."); ?> (Max. <?php echo $_['uploadMaxHumanFilesize']; ?>)</span> - <a class="svg upload float" title="<?php echo $l->t('Select from HD'); ?>"> - <input class="float" id="import_upload_start" type="file" accept="text/*" name="importfile" /></a> - <input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $_['uploadMaxFilesize'] ?>" id="max_upload"> - </form> - </td> -</tr> -</table> - -<input id="close_button" style="float: left;" type="button" onclick="Contacts.UI.Addressbooks.cancel(this);" value="<?php echo $l->t("Cancel"); ?>"> -<iframe name="import_upload_target" id='import_upload_target' src=""></iframe> -</td> -<script type="text/javascript"> -$(document).ready(function(){ - Contacts.UI.Addressbooks.loadImportHandlers(); -}); -</script>
\ No newline at end of file diff --git a/apps/contacts/templates/part.selectaddressbook.php b/apps/contacts/templates/part.selectaddressbook.php new file mode 100644 index 00000000000..c54ddaf2e67 --- /dev/null +++ b/apps/contacts/templates/part.selectaddressbook.php @@ -0,0 +1,27 @@ +<div id="selectaddressbook_dialog" title="<?php echo $l->t("Select Address Books"); ?>"> +<form> +<table style="width: 100%"> + <?php foreach($_['addressbooks'] as $idx => $addressbook) { ?> + <tr> + <td> + <input id="book_<?php echo $addressbook['id']; ?>" name="book" type="radio" value="<?php echo $addressbook['id']; ?>" <?php echo ($idx==0?'checked="checked"':'')?>> + </td> + <td> + <label for="book_<?php echo $addressbook['id']; ?>"><?php echo $addressbook['displayname']; ?></label> + </td> + <td><?php echo $addressbook['description']; ?></td> + </tr> + <?php } ?> + <tr> + <td> + <input id="book_new" name="book" type="radio" value="new"> + </td> + <th> + <input type="text" class="name" name="displayname" placeholder="<?php echo $l->t("Enter name"); ?>" /> + </th> + <td><input type="text" class="desc" name="description" placeholder="<?php echo $l->t("Enter description"); ?>" /></td> + </tr> +</table> +</form> +</div> + diff --git a/apps/contacts/templates/settings.php b/apps/contacts/templates/settings.php index 216003b6c69..f520559d143 100644 --- a/apps/contacts/templates/settings.php +++ b/apps/contacts/templates/settings.php @@ -7,6 +7,12 @@ <dd><code><?php echo OCP\Util::linkToRemote('carddav'); ?></code></dd> <dt><?php echo $l->t('iOS/OS X'); ?></dt> <dd><code><?php echo OCP\Util::linkToRemote('carddav'); ?>principals/<?php echo OCP\USER::getUser(); ?></code>/</dd> + <dt><?php echo $l->t('Read only vCard directory link(s)'); ?></dt> + <dd> + <?php foreach($_['addressbooks'] as $addressbook) { ?> + <a href="<?php echo OCP\Util::linkToRemote('carddav').'addressbooks/'.OCP\USER::getUser().'/'.rawurlencode($addressbook['uri']) ?>?export"><?php echo $addressbook['displayname'] ?></a><br /> + <?php } ?> + </dd> </dl> Powered by <a href="http://geonames.org/" target="_blank">geonames.org webservice</a> </fieldset> diff --git a/apps/contacts/thumbnail.php b/apps/contacts/thumbnail.php index a69e9c74f72..6deb5ca379e 100644 --- a/apps/contacts/thumbnail.php +++ b/apps/contacts/thumbnail.php @@ -25,14 +25,15 @@ OCP\JSON::checkLoggedIn(); OCP\App::checkAppEnabled('contacts'); session_write_close(); -function getStandardImage(){ +function getStandardImage() { //OCP\Response::setExpiresHeader('P10D'); OCP\Response::enableCaching(); OCP\Response::redirect(OCP\Util::imagePath('contacts', 'person.png')); } if(!extension_loaded('gd') || !function_exists('gd_info')) { - OCP\Util::writeLog('contacts','thumbnail.php. GD module not installed',OCP\Util::DEBUG); + OCP\Util::writeLog('contacts', + 'thumbnail.php. GD module not installed', OCP\Util::DEBUG); getStandardImage(); exit(); } @@ -43,8 +44,10 @@ $caching = isset($_GET['refresh']) ? 0 : null; $contact = OC_Contacts_App::getContactVCard($id); // invalid vcard -if(is_null($contact)){ - OCP\Util::writeLog('contacts','thumbnail.php. The VCard for ID '.$id.' is not RFC compatible',OCP\Util::ERROR); +if(is_null($contact)) { + OCP\Util::writeLog('contacts', + 'thumbnail.php. The VCard for ID ' . $id . ' is not RFC compatible', + OCP\Util::ERROR); getStandardImage(); exit(); } @@ -64,16 +67,24 @@ if($photo) { if($image->show()) { exit(); } else { - OCP\Util::writeLog('contacts','thumbnail.php. Couldn\'t display thumbnail for ID '.$id,OCP\Util::ERROR); + OCP\Util::writeLog('contacts', + 'thumbnail.php. Couldn\'t display thumbnail for ID ' . $id, + OCP\Util::ERROR); } } else { - OCP\Util::writeLog('contacts','thumbnail.php. Couldn\'t resize thumbnail for ID '.$id,OCP\Util::ERROR); + OCP\Util::writeLog('contacts', + 'thumbnail.php. Couldn\'t resize thumbnail for ID ' . $id, + OCP\Util::ERROR); } }else{ - OCP\Util::writeLog('contacts','thumbnail.php. Couldn\'t crop thumbnail for ID '.$id,OCP\Util::ERROR); + OCP\Util::writeLog('contacts', + 'thumbnail.php. Couldn\'t crop thumbnail for ID ' . $id, + OCP\Util::ERROR); } } else { - OCP\Util::writeLog('contacts','thumbnail.php. Couldn\'t load image string for ID '.$id,OCP\Util::ERROR); + OCP\Util::writeLog('contacts', + 'thumbnail.php. Couldn\'t load image string for ID ' . $id, + OCP\Util::ERROR); } } getStandardImage(); diff --git a/apps/contacts/tmpphoto.php b/apps/contacts/tmpphoto.php index 5fde8de9977..156d5c80308 100644 --- a/apps/contacts/tmpphoto.php +++ b/apps/contacts/tmpphoto.php @@ -24,7 +24,7 @@ $tmpkey = $_GET['tmpkey']; $maxsize = isset($_GET['maxsize']) ? $_GET['maxsize'] : -1; header("Cache-Control: no-cache, no-store, must-revalidate"); -OCP\Util::writeLog('contacts','tmpphoto.php: tmpkey: '.$tmpkey, OCP\Util::DEBUG); +OCP\Util::writeLog('contacts', 'tmpphoto.php: tmpkey: '.$tmpkey, OCP\Util::DEBUG); $image = new OC_Image(); $image->loadFromData(OC_Cache::get($tmpkey)); diff --git a/apps/external/ajax/setsites.php b/apps/external/ajax/setsites.php index 772863974ae..0f9e061d0e0 100644 --- a/apps/external/ajax/setsites.php +++ b/apps/external/ajax/setsites.php @@ -8,6 +8,7 @@ OCP\User::checkAdminUser(); +OCP\JSON::callCheck(); $sites = array(); for ($i = 0; $i < sizeof($_POST['site_name']); $i++) { @@ -22,4 +23,3 @@ else OCP\Config::setAppValue('external', 'sites', json_encode($sites)); echo 'true'; -?> diff --git a/apps/external/index.php b/apps/external/index.php index 81819e76e2f..3b6f06e1bff 100644 --- a/apps/external/index.php +++ b/apps/external/index.php @@ -40,4 +40,3 @@ if (isset($_GET['id'])) { $tmpl->printPage(); } } -?> diff --git a/apps/external/lib/external.php b/apps/external/lib/external.php index 9fff5d5569a..d13a7cf6dd7 100644 --- a/apps/external/lib/external.php +++ b/apps/external/lib/external.php @@ -32,5 +32,3 @@ class OC_External { } } - -?> diff --git a/apps/external/settings.php b/apps/external/settings.php index c109733e548..488444c119a 100644 --- a/apps/external/settings.php +++ b/apps/external/settings.php @@ -7,4 +7,3 @@ OCP\Util::addscript( "external", "admin" ); $tmpl = new OCP\Template( 'external', 'settings'); return $tmpl->fetchPage(); -?> diff --git a/apps/files/ajax/autocomplete.php b/apps/files/ajax/autocomplete.php index 7ff34da96b3..e504bb24bf8 100644 --- a/apps/files/ajax/autocomplete.php +++ b/apps/files/ajax/autocomplete.php @@ -52,5 +52,3 @@ if(OC_Filesystem::file_exists($base) and OC_Filesystem::is_dir($base)){ } } OCP\JSON::encodedPrint($files); - -?> diff --git a/apps/files/ajax/delete.php b/apps/files/ajax/delete.php index ed155de0dc7..695f803884e 100644 --- a/apps/files/ajax/delete.php +++ b/apps/files/ajax/delete.php @@ -4,6 +4,7 @@ OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); // Get data $dir = stripslashes($_GET["dir"]); @@ -25,5 +26,3 @@ if($success) { } else { OCP\JSON::error(array("data" => array( "message" => "Could not delete:\n" . $filesWithError ))); } - -?> diff --git a/apps/files/ajax/download.php b/apps/files/ajax/download.php index e9373f5f6ac..b9a4ddaf5e7 100644 --- a/apps/files/ajax/download.php +++ b/apps/files/ajax/download.php @@ -34,4 +34,3 @@ $files = $_GET["files"]; $dir = $_GET["dir"]; OC_Files::get($dir, $files, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false); -?> diff --git a/apps/files/ajax/list.php b/apps/files/ajax/list.php index f0600a179d0..dae0c1a828d 100644 --- a/apps/files/ajax/list.php +++ b/apps/files/ajax/list.php @@ -42,5 +42,3 @@ $list->assign( "files", $files, false ); $data = array('files' => $list->fetchPage()); OCP\JSON::success(array('data' => $data)); - -?> diff --git a/apps/files/ajax/mimeicon.php b/apps/files/ajax/mimeicon.php index 57898cd82d9..80d50f84528 100644 --- a/apps/files/ajax/mimeicon.php +++ b/apps/files/ajax/mimeicon.php @@ -7,5 +7,3 @@ $RUNTIME_NOAPPS=false; print OC_Helper::mimetypeIcon($_GET['mime']); - -?> diff --git a/apps/files/ajax/move.php b/apps/files/ajax/move.php index 945fe4e7b82..3d4003a8edc 100644 --- a/apps/files/ajax/move.php +++ b/apps/files/ajax/move.php @@ -4,6 +4,7 @@ OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); // Get data $dir = stripslashes($_GET["dir"]); @@ -16,5 +17,3 @@ if(OC_Files::move($dir,$file,$target,$file)){ }else{ OCP\JSON::error(array("data" => array( "message" => "Could not move $file" ))); } - -?> diff --git a/apps/files/ajax/newfile.php b/apps/files/ajax/newfile.php index edb78414872..cc9208ad08f 100644 --- a/apps/files/ajax/newfile.php +++ b/apps/files/ajax/newfile.php @@ -1,15 +1,25 @@ <?php // Init owncloud +global $eventSource; +if(!OC_User::isLoggedIn()){ + exit; +} -OCP\JSON::checkLoggedIn(); +session_write_close(); // Get the params -$dir = isset( $_POST['dir'] ) ? stripslashes($_POST['dir']) : ''; -$filename = isset( $_POST['filename'] ) ? stripslashes($_POST['filename']) : ''; -$content = isset( $_POST['content'] ) ? $_POST['content'] : ''; -$source = isset( $_POST['source'] ) ? stripslashes($_POST['source']) : ''; +$dir = isset( $_REQUEST['dir'] ) ? stripslashes($_REQUEST['dir']) : ''; +$filename = isset( $_REQUEST['filename'] ) ? stripslashes($_REQUEST['filename']) : ''; +$content = isset( $_REQUEST['content'] ) ? $_REQUEST['content'] : ''; +$source = isset( $_REQUEST['source'] ) ? stripslashes($_REQUEST['source']) : ''; + +if($source){ + $eventSource=new OC_EventSource(); +}else{ + OC_JSON::callCheck(); +} if($filename == '') { OCP\JSON::error(array("data" => array( "message" => "Empty Filename" ))); @@ -20,22 +30,49 @@ if(strpos($filename,'/')!==false){ exit(); } +function progress($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max){ + static $filesize = 0; + static $lastsize = 0; + global $eventSource; + + switch($notification_code) { + case STREAM_NOTIFY_FILE_SIZE_IS: + $filesize = $bytes_max; + break; + + case STREAM_NOTIFY_PROGRESS: + if ($bytes_transferred > 0) { + if (!isset($filesize)) { + } else { + $progress = (int)(($bytes_transferred/$filesize)*100); + if($progress>$lastsize){//limit the number or messages send + $eventSource->send('progress',$progress); + } + $lastsize=$progress; + } + } + break; + } +} + if($source){ if(substr($source,0,8)!='https://' and substr($source,0,7)!='http://'){ OCP\JSON::error(array("data" => array( "message" => "Not a valid source" ))); exit(); } - $sourceStream=fopen($source,'rb'); + + $ctx = stream_context_create(null, array('notification' =>'progress')); + $sourceStream=fopen($source,'rb', false, $ctx); $target=$dir.'/'.$filename; $result=OC_Filesystem::file_put_contents($target,$sourceStream); if($result){ $mime=OC_Filesystem::getMimetype($target); - OCP\JSON::success(array("data" => array('mime'=>$mime))); - exit(); + $eventSource->send('success',$mime); }else{ - OCP\JSON::error(array("data" => array( "message" => "Error while downloading ".$source. ' to '.$target ))); - exit(); + $eventSource->send('error',"Error while downloading ".$source. ' to '.$target); } + $eventSource->close(); + exit(); }else{ if($content){ if(OC_Filesystem::file_put_contents($dir.'/'.$filename,$content)){ diff --git a/apps/files/ajax/newfolder.php b/apps/files/ajax/newfolder.php index c5c37914c6a..ae92bcf09bb 100644 --- a/apps/files/ajax/newfolder.php +++ b/apps/files/ajax/newfolder.php @@ -4,6 +4,7 @@ OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); // Get the params $dir = isset( $_POST['dir'] ) ? stripslashes($_POST['dir']) : ''; diff --git a/apps/files/ajax/rawlist.php b/apps/files/ajax/rawlist.php index 7cb02f79673..d159f6e152f 100644 --- a/apps/files/ajax/rawlist.php +++ b/apps/files/ajax/rawlist.php @@ -22,5 +22,3 @@ foreach( OC_Files::getdirectorycontent( $dir, $mimetype ) as $i ){ } OCP\JSON::success(array('data' => $files)); - -?> diff --git a/apps/files/ajax/rename.php b/apps/files/ajax/rename.php index e2fa3d54a61..45448279fa1 100644 --- a/apps/files/ajax/rename.php +++ b/apps/files/ajax/rename.php @@ -4,6 +4,7 @@ OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); // Get data $dir = stripslashes($_GET["dir"]); @@ -17,5 +18,3 @@ if( OC_Files::move( $dir, $file, $dir, $newname )) { else{ OCP\JSON::error(array("data" => array( "message" => "Unable to rename file" ))); } - -?> diff --git a/apps/files/ajax/scan.php b/apps/files/ajax/scan.php index 6fcf97688c2..eef38858516 100644 --- a/apps/files/ajax/scan.php +++ b/apps/files/ajax/scan.php @@ -16,6 +16,11 @@ session_write_close(); if($force or !OC_FileCache::inCache('')){ if(!$checkOnly){ OCP\DB::beginTransaction(); + + if(OC_Cache::isFast()){ + OC_Cache::clear('fileid/'); //make sure the old fileid's don't mess things up + } + OC_FileCache::scan($dir,$eventSource); OC_FileCache::clean(); OCP\DB::commit(); diff --git a/apps/files/ajax/timezone.php b/apps/files/ajax/timezone.php index cafb5074ece..0be441a36a2 100644 --- a/apps/files/ajax/timezone.php +++ b/apps/files/ajax/timezone.php @@ -3,4 +3,4 @@ // see lib/base.php for an example //session_start(); $_SESSION['timezone'] = $_GET['time']; -?> +
\ No newline at end of file diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index b779924cfb4..74e6eb560d8 100644 --- a/apps/files/ajax/upload.php +++ b/apps/files/ajax/upload.php @@ -7,6 +7,7 @@ OCP\JSON::setContentTypeHeader('text/plain'); OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); if (!isset($_FILES['files'])) { OCP\JSON::error(array("data" => array( "message" => "No file was uploaded. Unknown error" ))); @@ -59,5 +60,3 @@ if(strpos($dir,'..') === false){ } OCP\JSON::error(array('data' => array('error' => $error, "file" => $fileName))); - -?> diff --git a/apps/files/appinfo/update.php b/apps/files/appinfo/update.php index f9953ba4de5..5514aed197f 100644 --- a/apps/files/appinfo/update.php +++ b/apps/files/appinfo/update.php @@ -1,5 +1,16 @@ <?php +// fix webdav properties, remove namespace information between curly bracket (update from OC4 to OC5) +$installedVersion=OCP\Config::getAppValue('files', 'installed_version');
+if (version_compare($installedVersion, '1.1.4', '<')) { + $query = OC_DB::prepare( "SELECT propertyname, propertypath, userid FROM `*PREFIX*properties`" );
+ $result = $query->execute();
+ while( $row = $result->fetchRow()){
+ $query = OC_DB::prepare( 'UPDATE *PREFIX*properties SET propertyname = ? WHERE userid = ? AND propertypath = ?' );
+ $query->execute( array( preg_replace("/^{.*}/", "", $row["propertyname"]),$row["userid"], $row["propertypath"] ));
+ } +} + //update from OC 3 //try to remove remaining files. diff --git a/apps/files/appinfo/version b/apps/files/appinfo/version index 8cfbc905b39..1b87bcd0b09 100644 --- a/apps/files/appinfo/version +++ b/apps/files/appinfo/version @@ -1 +1 @@ -1.1.1
\ No newline at end of file +1.1.4
\ No newline at end of file diff --git a/apps/files/download.php b/apps/files/download.php index 2b5d4e2d876..4e2478d1ad7 100644 --- a/apps/files/download.php +++ b/apps/files/download.php @@ -46,4 +46,3 @@ header('Content-Length: '.OC_Filesystem::filesize($filename)); @ob_end_clean(); OC_Filesystem::readfile( $filename ); -?> diff --git a/apps/files/index.php b/apps/files/index.php index ed36c5edab0..79bed8e357e 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -40,6 +40,7 @@ $dir = isset( $_GET['dir'] ) ? stripslashes($_GET['dir']) : ''; // Redirect if directory does not exist if(!OC_Filesystem::is_dir($dir.'/')) { header('Location: '.$_SERVER['PHP_SELF'].''); + exit(); } $files = array(); @@ -98,5 +99,3 @@ $tmpl->assign( 'uploadMaxFilesize', $maxUploadFilesize); $tmpl->assign( 'uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize)); $tmpl->assign( 'allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); $tmpl->printPage(); - -?> diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index e6a9a6883af..3645258f98f 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -14,7 +14,7 @@ FileList={ var extension=false; } html+='<td class="filename" style="background-image:url('+img+')"><input type="checkbox" />'; - html+='<a class="name" href="download.php?file='+$('#dir').val()+'/'+name+'"><span class="nametext">'+basename + html+='<a class="name" href="download.php?file='+$('#dir').val().replace(/</, '<').replace(/>/, '>')+'/'+name+'"><span class="nametext">'+basename if(extension){ html+='<span class="extension">'+extension+'</span>'; } diff --git a/apps/files/js/files.js b/apps/files/js/files.js index 86c5185bf72..a4e2361feeb 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -497,23 +497,27 @@ $(document).ready(function() { localName=(localName.match(/:\/\/(.[^/]+)/)[1]).replace('www.',''); } localName = getUniqueName(localName); - $.post( - OC.filePath('files','ajax','newfile.php'), - {dir:$('#dir').val(),source:name,filename:localName}, - function(result){ - if(result.status == 'success'){ - var date=new Date(); - FileList.addFile(localName,0,date); - var tr=$('tr').filterAttr('data-file',localName); - tr.data('mime',result.data.mime); - getMimeIcon(result.data.mime,function(path){ - tr.find('td.filename').attr('style','background-image:url('+path+')'); - }); - }else{ + $('#uploadprogressbar').progressbar({value:0}); + $('#uploadprogressbar').fadeIn(); - } - } - ); + var eventSource=new OC.EventSource(OC.filePath('files','ajax','newfile.php'),{dir:$('#dir').val(),source:name,filename:localName}); + eventSource.listen('progress',function(progress){ + $('#uploadprogressbar').progressbar('value',progress); + }); + eventSource.listen('success',function(mime){ + $('#uploadprogressbar').fadeOut(); + var date=new Date(); + FileList.addFile(localName,0,date); + var tr=$('tr').filterAttr('data-file',localName); + tr.data('mime',mime); + getMimeIcon(mime,function(path){ + tr.find('td.filename').attr('style','background-image:url('+path+')'); + }); + }); + eventSource.listen('error',function(error){ + $('#uploadprogressbar').fadeOut(); + alert(error); + }); break; } var li=$(this).parent(); diff --git a/apps/files/settings.php b/apps/files/settings.php index e5a66239ebd..cd6dd8c1616 100644 --- a/apps/files/settings.php +++ b/apps/files/settings.php @@ -56,5 +56,3 @@ $tmpl = new OCP\Template( "files", "index", "user" ); $tmpl->assign( 'files', $files ); $tmpl->assign( "breadcrumb", $breadcrumb ); $tmpl->printPage(); - -?> diff --git a/apps/files_encryption/js/settings.js b/apps/files_encryption/js/settings.js index 37d62265c94..8cc433246cb 100644 --- a/apps/files_encryption/js/settings.js +++ b/apps/files_encryption/js/settings.js @@ -17,8 +17,8 @@ $(document).ready(function(){ OC.AppConfig.setValue('files_encryption','type_blacklist',blackList); } - $('#enbale_encryption').change(function(){ - var checked=$('#enbale_encryption').is(':checked'); + $('#enable_encryption').change(function(){ + var checked=$('#enable_encryption').is(':checked'); OC.AppConfig.setValue('files_encryption','enable_encryption',(checked)?'true':'false'); }) })
\ No newline at end of file diff --git a/apps/files_encryption/lib/cryptstream.php b/apps/files_encryption/lib/cryptstream.php index e0020537563..46471911d94 100644 --- a/apps/files_encryption/lib/cryptstream.php +++ b/apps/files_encryption/lib/cryptstream.php @@ -31,9 +31,7 @@ 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 - private $count; private $writeCache; private $size; private static $rootView; @@ -100,7 +98,6 @@ class OC_CryptStream{ public function stream_write($data){ $length=strlen($data); - $written=0; $currentPos=ftell($this->source); if($this->writeCache){ $data=$this->writeCache.$data; diff --git a/apps/files_encryption/templates/settings.php b/apps/files_encryption/templates/settings.php index 25b5a06f56c..79780d694cf 100644 --- a/apps/files_encryption/templates/settings.php +++ b/apps/files_encryption/templates/settings.php @@ -7,6 +7,6 @@ <option selected="selected" value="<?php echo $type;?>"><?php echo $type;?></option> <?php endforeach;?> </select> - <input type='checkbox' id='enbale_encryption' <?php if($_['encryption_enabled']){echo 'checked="checked"';} ?>></input><label for='enbale_encryption'><?php echo $l->t('Enable Encryption')?></label> + <input type='checkbox' id='enable_encryption' <?php if($_['encryption_enabled']){echo 'checked="checked"';} ?>></input><label for='enable_encryption'><?php echo $l->t('Enable Encryption')?></label> </fieldset> </form> diff --git a/apps/files_external/ajax/addMountPoint.php b/apps/files_external/ajax/addMountPoint.php index 549cb6a3427..e08f805942f 100644 --- a/apps/files_external/ajax/addMountPoint.php +++ b/apps/files_external/ajax/addMountPoint.php @@ -1,6 +1,8 @@ <?php OCP\JSON::checkAppEnabled('files_external'); +OCP\JSON::callCheck(); + if ($_POST['isPersonal'] == 'true') { OCP\JSON::checkLoggedIn(); $isPersonal = true; @@ -9,5 +11,3 @@ if ($_POST['isPersonal'] == 'true') { $isPersonal = false; } OC_Mount_Config::addMountPoint($_POST['mountPoint'], $_POST['class'], $_POST['classOptions'], $_POST['mountType'], $_POST['applicable'], $isPersonal); - -?> diff --git a/apps/files_external/ajax/addRootCertificate.php b/apps/files_external/ajax/addRootCertificate.php index c5f49a82d36..d28a7d24b2d 100644 --- a/apps/files_external/ajax/addRootCertificate.php +++ b/apps/files_external/ajax/addRootCertificate.php @@ -5,6 +5,7 @@ OCP\JSON::checkAppEnabled('files_external'); $view = \OCP\Files::getStorage("files_external"); $from = $_FILES['rootcert_import']['tmp_name']; $path = \OCP\Config::getSystemValue('datadirectory').$view->getAbsolutePath("").'uploads/'; +if(!file_exists($path)) mkdir($path,0700,true); $to = $path.$_FILES['rootcert_import']['name']; move_uploaded_file($from, $to); diff --git a/apps/files_external/ajax/removeMountPoint.php b/apps/files_external/ajax/removeMountPoint.php index b77b306bcb5..aa446426202 100644 --- a/apps/files_external/ajax/removeMountPoint.php +++ b/apps/files_external/ajax/removeMountPoint.php @@ -1,6 +1,8 @@ <?php OCP\JSON::checkAppEnabled('files_external'); +OCP\JSON::callCheck(); + if ($_POST['isPersonal'] == 'true') { OCP\JSON::checkLoggedIn(); $isPersonal = true; @@ -9,5 +11,3 @@ if ($_POST['isPersonal'] == 'true') { $isPersonal = false; } OC_Mount_Config::removeMountPoint($_POST['mountPoint'], $_POST['mountType'], $_POST['applicable'], $isPersonal); - -?> diff --git a/apps/files_external/lib/dropbox.php b/apps/files_external/lib/dropbox.php index 35663d431f8..c849db38433 100755 --- a/apps/files_external/lib/dropbox.php +++ b/apps/files_external/lib/dropbox.php @@ -208,7 +208,7 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common { if (isset(self::$tempFiles[$tmpFile])) { $handle = fopen($tmpFile, 'r'); try { - $response = $this->dropbox->putFile(self::$tempFiles[$tmpFile], $handle); + $this->dropbox->putFile(self::$tempFiles[$tmpFile], $handle); unlink($tmpFile); } catch (Exception $exception) { diff --git a/apps/files_external/lib/google.php b/apps/files_external/lib/google.php index 41b560ae84e..2ad85d09d5f 100644 --- a/apps/files_external/lib/google.php +++ b/apps/files_external/lib/google.php @@ -178,7 +178,7 @@ class OC_Filestorage_Google extends OC_Filestorage_Common { if ($collection == '/' || $collection == '\.' || $collection == '.') { $uri = 'https://docs.google.com/feeds/default/private/full'; // Get parent content link - } else if ($dom = $this->getResource(basename($dir))) { + } else if ($dom = $this->getResource(basename($collection))) { $uri = $dom->getElementsByTagName('content')->item(0)->getAttribute('src'); } if (isset($uri)) { @@ -341,7 +341,7 @@ class OC_Filestorage_Google extends OC_Filestorage_Common { break; } } - $title = basename($path); + $title = basename($path2); // Construct post data $postData = '<?xml version="1.0" encoding="UTF-8"?>'; $postData .= '<entry xmlns="http://www.w3.org/2005/Atom" xmlns:docs="http://schemas.google.com/docs/2007" xmlns:gd="http://schemas.google.com/g/2005" gd:etag='.$etag.'>'; @@ -352,13 +352,13 @@ class OC_Filestorage_Google extends OC_Filestorage_Common { } else { // Move to different collection if ($collectionEntry = $this->getResource($collection)) { - $feedUri = $colelctionEntry->getElementsByTagName('content')->item(0)->getAttribute('src'); + $feedUri = $collectionEntry->getElementsByTagName('content')->item(0)->getAttribute('src'); // Construct post data $postData = '<?xml version="1.0" encoding="UTF-8"?>'; $postData .= '<entry xmlns="http://www.w3.org/2005/Atom">'; $postData .= '<id>'.$entry->getElementsByTagName('id')->item(0).'</id>'; $postData .= '</entry>'; - $this->sendRequest($uri, 'POST', $postData); + $this->sendRequest($feedUri, 'POST', $postData); return true; } } @@ -424,7 +424,6 @@ class OC_Filestorage_Google extends OC_Filestorage_Common { } } if (!isset($uploadUri) && $entry) { - $etag = $entry->getAttribute('gd:etag'); $links = $entry->getElementsByTagName('link'); foreach ($links as $link) { if ($link->getAttribute('rel') == 'http://schemas.google.com/g/2005#resumable-create-media') { diff --git a/apps/files_external/lib/smb.php b/apps/files_external/lib/smb.php index 5e34deb2337..8a5e993b1d0 100644 --- a/apps/files_external/lib/smb.php +++ b/apps/files_external/lib/smb.php @@ -15,8 +15,6 @@ class OC_FileStorage_SMB extends OC_FileStorage_StreamWrapper{ private $root; private $share; - private static $tempFiles=array(); - public function __construct($params){ $this->host=$params['host']; $this->user=$params['user']; diff --git a/apps/files_external/lib/webdav.php b/apps/files_external/lib/webdav.php index ea6ca65b976..84d64b65193 100644 --- a/apps/files_external/lib/webdav.php +++ b/apps/files_external/lib/webdav.php @@ -45,7 +45,10 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{ $this->client = new OC_Connector_Sabre_Client($settings); if($caview = \OCP\Files::getStorage('files_external')) { - $this->client->setCurlSettings(array(CURLOPT_CAINFO => \OCP\Config::getSystemValue('datadirectory').$caview->getAbsolutePath("").'rootcerts.crt')); + $certPath=\OCP\Config::getSystemValue('datadirectory').$caview->getAbsolutePath("").'rootcerts.crt'; + if (file_exists($certPath)) { + $this->client->addTrustedCertificates($certPath); + } } //create the root folder if necesary $this->mkdir(''); @@ -74,16 +77,11 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{ $path=$this->cleanPath($path); try{ $response=$this->client->propfind($path, array(),1); - $stripLength=strlen($this->root)+strlen($path); $id=md5('webdav'.$this->root.$path); OC_FakeDirStream::$dirs[$id]=array(); - $skip = true; - foreach($response as $file=>$data){ - // Skip the first file, because it is the current directory - if ($skip) { - $skip = false; - continue; - } + $files=array_keys($response); + array_shift($files);//the first entry is the current directory + foreach($files as $file){ $file = urldecode(basename($file)); OC_FakeDirStream::$dirs[$id][]=$file; } @@ -117,7 +115,7 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{ public function file_exists($path){ $path=$this->cleanPath($path); try{ - $response=$this->client->propfind($path, array('{DAV:}resourcetype')); + $this->client->propfind($path, array('{DAV:}resourcetype')); return true;//no 404 exception }catch(Exception $e){ return false; @@ -198,7 +196,7 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{ $mtime=time(); } $path=$this->cleanPath($path); - $this->client->proppatch($path, array('{DAV:}lastmodified' => $mtime,)); + $this->client->proppatch($path, array('{DAV:}lastmodified' => $mtime)); } public function getFile($path,$target){ diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php index 3d65e9b7473..e8bc94790dc 100644 --- a/apps/files_external/templates/settings.php +++ b/apps/files_external/templates/settings.php @@ -1,4 +1,4 @@ -<form id="files_external" method="post" enctype="multipart/form-data" action="/owncloud/?app=files_external&getfile=ajax%2FaddRootCertificate.php"> +<form id="files_external" method="post" enctype="multipart/form-data" action="<?php echo OCP\Util::linkTo('files_external', 'ajax/addRootCertificate.php'); ?>"> <fieldset class="personalblock"> <legend><strong><?php echo $l->t('External Storage'); ?></strong></legend> <table id="externalStorage" data-admin='<?php echo json_encode($_['isAdminPage']); ?>'> diff --git a/apps/files_external/tests/amazons3.php b/apps/files_external/tests/amazons3.php index d0084c94afd..b9b4cf65bd6 100644 --- a/apps/files_external/tests/amazons3.php +++ b/apps/files_external/tests/amazons3.php @@ -45,6 +45,3 @@ if (!is_array($config) or !isset($config['amazons3']) or !$config['amazons3']['r } } } - -?> - diff --git a/apps/files_external/tests/ftp.php b/apps/files_external/tests/ftp.php index 68481b4e66b..97796bca128 100644 --- a/apps/files_external/tests/ftp.php +++ b/apps/files_external/tests/ftp.php @@ -13,7 +13,6 @@ if(!is_array($config) or !isset($config['ftp']) or !$config['ftp']['run']){ }else{ class Test_Filestorage_FTP extends Test_FileStorage { private $config; - private $id; public function setUp(){ $id=uniqid(); diff --git a/apps/files_external/tests/google.php b/apps/files_external/tests/google.php index 08116f0e748..806db5a6aaa 100644 --- a/apps/files_external/tests/google.php +++ b/apps/files_external/tests/google.php @@ -28,7 +28,6 @@ if(!is_array($config) or !isset($config['google']) or !$config['google']['run']) class Test_Filestorage_Google extends Test_FileStorage { private $config; - private $id; public function setUp(){ $id=uniqid(); diff --git a/apps/files_external/tests/smb.php b/apps/files_external/tests/smb.php index e1495b7480d..001ef842276 100644 --- a/apps/files_external/tests/smb.php +++ b/apps/files_external/tests/smb.php @@ -14,7 +14,6 @@ if(!is_array($config) or !isset($config['smb']) or !$config['smb']['run']){ }else{ class Test_Filestorage_SMB extends Test_FileStorage { private $config; - private $id; public function setUp(){ $id=uniqid(); diff --git a/apps/files_external/tests/swift.php b/apps/files_external/tests/swift.php index f0bde6ed605..1520c9473d3 100644 --- a/apps/files_external/tests/swift.php +++ b/apps/files_external/tests/swift.php @@ -13,7 +13,6 @@ if(!is_array($config) or !isset($config['swift']) or !$config['swift']['run']){ }else{ class Test_Filestorage_SWIFT extends Test_FileStorage { private $config; - private $id; public function setUp(){ $id=uniqid(); diff --git a/apps/files_external/tests/webdav.php b/apps/files_external/tests/webdav.php index 144659819b6..14abbef2cbf 100644 --- a/apps/files_external/tests/webdav.php +++ b/apps/files_external/tests/webdav.php @@ -13,7 +13,6 @@ if(!is_array($config) or !isset($config['webdav']) or !$config['webdav']['run']) }else{ class Test_Filestorage_DAV extends Test_FileStorage { private $config; - private $id; public function setUp(){ $id=uniqid(); diff --git a/apps/files_imageviewer/appinfo/app.php b/apps/files_imageviewer/appinfo/app.php index 6c8d8c30cad..6184585cff3 100644 --- a/apps/files_imageviewer/appinfo/app.php +++ b/apps/files_imageviewer/appinfo/app.php @@ -4,5 +4,3 @@ OCP\Util::addscript( 'files_imageviewer', 'lightbox' ); OCP\Util::addscript('files_imageviewer', 'jquery.mousewheel-3.0.4.pack'); OCP\Util::addscript('files_imageviewer', 'jquery.fancybox-1.3.4.pack'); OCP\Util::addStyle( 'files_imageviewer', 'jquery.fancybox-1.3.4' ); - -?> diff --git a/apps/files_pdfviewer/appinfo/app.php b/apps/files_pdfviewer/appinfo/app.php index c8ca2dc8d94..e4771ee517f 100644 --- a/apps/files_pdfviewer/appinfo/app.php +++ b/apps/files_pdfviewer/appinfo/app.php @@ -6,4 +6,3 @@ OCP\Util::addscript( 'files_pdfviewer', 'pdfjs/compatibility'); OCP\Util::addscript( 'files_pdfviewer', 'viewer'); OCP\Util::addscript( 'files_pdfviewer', 'pdfjs/build/pdf'); OCP\Util::addscript( 'files_pdfviewer', 'pdfjs/viewer'); -?> diff --git a/apps/files_pdfviewer/js/pdfjs/viewer.js b/apps/files_pdfviewer/js/pdfjs/viewer.js index f49257d7929..90dd1eef020 100644 --- a/apps/files_pdfviewer/js/pdfjs/viewer.js +++ b/apps/files_pdfviewer/js/pdfjs/viewer.js @@ -1432,7 +1432,7 @@ var DocumentOutlineView = function documentOutlineView(outline) { queue.push({parent: itemsDiv, items: item.items}); } - levelData.parent.appendChild(div); +// levelData.parent.appendChild(div); } } }; @@ -1751,10 +1751,9 @@ function updateThumbViewArea() { } window.addEventListener('resize', function webViewerResize(evt) { - if (PDFView.initialized && + if (PDFView.initialized && PDFView.active && (document.getElementById('pageWidthOption').selected || - document.getElementById('pageFitOption').selected || - document.getElementById('pageAutoOption').selected)) + document.getElementById('pageFitOption').selected )) PDFView.parseScale(document.getElementById('scaleSelect').value); updateViewarea(); }); @@ -1788,8 +1787,8 @@ window.addEventListener('change', function webViewerChange(evt) { document.title = file.name; // URL does not reflect proper document location - hiding some icons. - document.getElementById('viewBookmark').setAttribute('hidden', 'true'); - document.getElementById('download').setAttribute('hidden', 'true'); +// document.getElementById('viewBookmark').setAttribute('hidden', 'true'); +// document.getElementById('download').setAttribute('hidden', 'true'); }, true); function selectScaleOption(value) { diff --git a/apps/files_sharing/ajax/email.php b/apps/files_sharing/ajax/email.php index 523c3d2078b..3026eb74675 100644 --- a/apps/files_sharing/ajax/email.php +++ b/apps/files_sharing/ajax/email.php @@ -1,6 +1,8 @@ <?php OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('files_sharing'); +OCP\JSON::callCheck(); + $user = OCP\USER::getUser(); // TODO translations $type = (strpos($_POST['file'], '.') === false) ? 'folder' : 'file'; @@ -8,6 +10,4 @@ $subject = $user.' shared a '.$type.' with you'; $link = $_POST['link']; $text = $user.' shared the '.$type.' '.$_POST['file'].' with you. It is available for download here: '.$link; $fromaddress = OCP\Config::getUserValue($user, 'settings', 'email', 'sharing-noreply@'.OCP\Util::getServerHost()); -OC_Mail::send($_POST['toaddress'], $_POST['toaddress'], $subject, $text, $fromaddress, $user); - -?> +OCP\Util::sendMail($_POST['toaddress'], $_POST['toaddress'], $subject, $text, $fromaddress, $user); diff --git a/apps/files_sharing/ajax/getitem.php b/apps/files_sharing/ajax/getitem.php index 94f0890d706..ff6c29b6a0a 100644 --- a/apps/files_sharing/ajax/getitem.php +++ b/apps/files_sharing/ajax/getitem.php @@ -64,5 +64,3 @@ while ($path != $userDirectory) { } OCP\JSON::success(array('data' => $item)); - -?> diff --git a/apps/files_sharing/ajax/getstatuses.php b/apps/files_sharing/ajax/getstatuses.php index 488cab13bc9..1be4d9a0d9c 100644 --- a/apps/files_sharing/ajax/getstatuses.php +++ b/apps/files_sharing/ajax/getstatuses.php @@ -20,5 +20,3 @@ if ($rows = OC_Share::getMySharedItems()) { } OCP\JSON::success(array('data' => $items)); - -?> diff --git a/apps/files_sharing/ajax/setpermissions.php b/apps/files_sharing/ajax/setpermissions.php index 4d19cd40f2d..0a2cf78f765 100644 --- a/apps/files_sharing/ajax/setpermissions.php +++ b/apps/files_sharing/ajax/setpermissions.php @@ -2,6 +2,7 @@ OCP\JSON::checkAppEnabled('files_sharing'); OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); $source = '/'.OCP\USER::getUser().'/files'.$_POST['source']; $uid_shared_with = $_POST['uid_shared_with']; @@ -9,5 +10,3 @@ $permissions = $_POST['permissions']; OC_Share::setPermissions($source, $uid_shared_with, $permissions); OCP\JSON::success(); - -?> diff --git a/apps/files_sharing/ajax/share.php b/apps/files_sharing/ajax/share.php index 1ee8c3f791a..3f224d1b67b 100644 --- a/apps/files_sharing/ajax/share.php +++ b/apps/files_sharing/ajax/share.php @@ -2,6 +2,7 @@ OCP\JSON::checkAppEnabled('files_sharing'); OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); $userDirectory = '/'.OCP\USER::getUser().'/files'; $sources = explode(';', $_POST['sources']); @@ -34,5 +35,3 @@ foreach ($sources as $source) { } } } - -?> diff --git a/apps/files_sharing/ajax/toggleresharing.php b/apps/files_sharing/ajax/toggleresharing.php index 673f00c5d18..7da4fdfeea8 100644 --- a/apps/files_sharing/ajax/toggleresharing.php +++ b/apps/files_sharing/ajax/toggleresharing.php @@ -7,5 +7,3 @@ if ($_POST['resharing'] == true) { } else { OCP\Config::setAppValue('files_sharing', 'resharing', 'no'); } - -?> diff --git a/apps/files_sharing/ajax/unshare.php b/apps/files_sharing/ajax/unshare.php index d50e7963a05..02a59c4016b 100644 --- a/apps/files_sharing/ajax/unshare.php +++ b/apps/files_sharing/ajax/unshare.php @@ -2,11 +2,10 @@ OCP\JSON::checkAppEnabled('files_sharing'); OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); $source = '/'.OCP\USER::getUser().'/files'.$_POST['source']; $uid_shared_with = $_POST['uid_shared_with']; OC_Share::unshare($source, $uid_shared_with); OCP\JSON::success(); - -?> diff --git a/apps/files_sharing/ajax/userautocomplete.php b/apps/files_sharing/ajax/userautocomplete.php index 0e1bf6d588e..388a4844b95 100644 --- a/apps/files_sharing/ajax/userautocomplete.php +++ b/apps/files_sharing/ajax/userautocomplete.php @@ -28,5 +28,3 @@ $users[] = "</optgroup>"; $groups[] = "</optgroup>"; $users = array_merge($users, $groups); OCP\JSON::encodedPrint($users); - -?> diff --git a/apps/files_sharing/appinfo/version b/apps/files_sharing/appinfo/version index 7dff5b89211..f4778493c50 100644 --- a/apps/files_sharing/appinfo/version +++ b/apps/files_sharing/appinfo/version @@ -1 +1 @@ -0.2.1
\ No newline at end of file +0.2.2
\ No newline at end of file diff --git a/apps/files_sharing/get.php b/apps/files_sharing/get.php index 40a90a1530c..70a5162d382 100644 --- a/apps/files_sharing/get.php +++ b/apps/files_sharing/get.php @@ -86,4 +86,3 @@ if (isset($_GET['token']) && $source = OC_Share::getSource($_GET['token'])) { $tmpl->printPage(); die(); } -?> diff --git a/apps/files_sharing/lib_share.php b/apps/files_sharing/lib_share.php index 6e092269250..0237acfc1ac 100644 --- a/apps/files_sharing/lib_share.php +++ b/apps/files_sharing/lib_share.php @@ -513,5 +513,3 @@ class OC_Share { } } - -?> diff --git a/apps/files_sharing/list.php b/apps/files_sharing/list.php index 2fd24840d36..54704c942fd 100644 --- a/apps/files_sharing/list.php +++ b/apps/files_sharing/list.php @@ -33,5 +33,3 @@ OCP\Util::addscript("files_sharing", "list"); $tmpl = new OCP\Template("files_sharing", "list", "user"); $tmpl->assign("shared_items", OC_Share::getMySharedItems()); $tmpl->printPage(); - -?> diff --git a/apps/files_sharing/sharedstorage.php b/apps/files_sharing/sharedstorage.php index 4138fc2b399..32fd2124429 100644 --- a/apps/files_sharing/sharedstorage.php +++ b/apps/files_sharing/sharedstorage.php @@ -67,7 +67,6 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { public function rmdir($path) { // The folder will be removed from the database, but won't be deleted from the owner's filesystem OC_Share::unshareFromMySelf($this->datadir.$path); - $this->clearFolderSizeCache($path); } public function opendir($path) { @@ -190,7 +189,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { public function filesize($path) { if ($path == "" || $path == "/" || $this->is_dir($path)) { - return $this->getFolderSize($path); + return 0; } else { $source = $this->getSource($path); if ($source) { @@ -200,55 +199,6 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { } } - public function getFolderSize($path) { - return 0; //depricated - } - - private function calculateFolderSize($path) { - if ($this->is_file($path)) { - $path = dirname($path); - } - $size = 0; - if ($dh = $this->opendir($path)) { - while (($filename = readdir($dh)) !== false) { - if ($filename != "." && $filename != "..") { - $subFile = $path."/".$filename; - if ($this->is_file($subFile)) { - $size += $this->filesize($subFile); - } else { - $size += $this->getFolderSize($subFile); - } - } - } - if ($size > 0) { - $dbpath = rtrim($this->datadir.$path, "/"); -// $query = OCP\DB::prepare("INSERT INTO *PREFIX*foldersize VALUES(?,?)"); -// $result = $query->execute(array($dbpath, $size)); - } - } - return $size; - } - - private function clearFolderSizeCache($path) { - $path = rtrim($path, "/"); - $path = preg_replace('{(/)\1+}', "/", $path); - if ($this->is_file($path)) { - $path = dirname($path); - } - $dbpath = rtrim($this->datadir.$path, "/"); -// $query = OCP\DB::prepare("DELETE FROM *PREFIX*/*foldersize*/ WHERE path = ?"); -// $result = $query->execute(array($dbpath)); - if ($path != "/" && $path != "") { - $parts = explode("/", $path); - $part = array_pop($parts); - if (empty($part)) { - array_pop($parts); - } - $parent = implode("/", $parts); - $this->clearFolderSizeCache($parent); - } - } - public function is_readable($path) { return true; } @@ -341,9 +291,6 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { OCP\Util::emitHook('OC_Filestorage_Shared', 'file_put_contents', $info); $storage = OC_Filesystem::getStorage($source); $result = $storage->file_put_contents($this->getInternalPath($source), $data); - if ($result) { - $this->clearFolderSizeCache($path); - } return $result; } } @@ -365,7 +312,6 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { } else { OC_Share::unshareFromMySelf($target); } - $this->clearFolderSizeCache($this->getInternalPath($target)); return true; } @@ -401,8 +347,6 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { } else { OC_Share::setTarget($oldTarget, $newTarget); } - $this->clearFolderSizeCache($this->getInternalPath($oldTarget)); - $this->clearFolderSizeCache($this->getInternalPath($newTarget)); return true; } @@ -413,9 +357,6 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { if ($this->is_writable($path2)) { $tmpFile = $this->toTmpFile($path1); $result = $this->fromTmpFile($tmpFile, $path2); - if ($result) { - $this->clearFolderSizeCache($path2); - } return $result; } else { return false; @@ -451,9 +392,6 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { if ($source) { $storage = OC_Filesystem::getStorage($source); $result = $storage->fromTmpFile($tmpFile, $this->getInternalPath($source)); - if ($result) { - $this->clearFolderSizeCache($path); - } return $result; } } else { @@ -520,7 +458,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { $source = $this->getSource($path); if ($source) { $storage = OC_Filesystem::getStorage($source); - return $storage->touch($this->getInternalPath($source),$time); + return $storage->touch($this->getInternalPath($source),$mtime); } } diff --git a/apps/files_sharing_log/appinfo/database.xml b/apps/files_sharing_log/appinfo/database.xml index 92e5f0125bd..dae811f87fa 100644 --- a/apps/files_sharing_log/appinfo/database.xml +++ b/apps/files_sharing_log/appinfo/database.xml @@ -3,7 +3,7 @@ <name>*dbname*</name> <create>true</create> <overwrite>false</overwrite> - <charset>latin1</charset> + <charset>utf8</charset> <table> <name>*dbprefix*sharing_log</name> <declaration> diff --git a/apps/files_texteditor/ajax/savefile.php b/apps/files_texteditor/ajax/savefile.php index 961db7105e3..f3ac323e32f 100644 --- a/apps/files_texteditor/ajax/savefile.php +++ b/apps/files_texteditor/ajax/savefile.php @@ -26,6 +26,7 @@ // Check if we are a user OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); // Get paramteres $filecontents = isset($_POST['filecontents']) ? $_POST['filecontents'] : false; diff --git a/apps/files_texteditor/appinfo/app.php b/apps/files_texteditor/appinfo/app.php index c745170018e..1f9773bca3a 100644 --- a/apps/files_texteditor/appinfo/app.php +++ b/apps/files_texteditor/appinfo/app.php @@ -4,4 +4,3 @@ OCP\Util::addStyle( 'files_texteditor', 'DroidSansMono/stylesheet' ); OCP\Util::addStyle( 'files_texteditor', 'style' ); OCP\Util::addscript( 'files_texteditor', 'editor'); OCP\Util::addscript( 'files_texteditor', 'aceeditor/ace'); -?> diff --git a/apps/files_versions/ajax/expireAll.php b/apps/files_versions/ajax/expireAll.php index 238e3bdad4d..2a678c7f0a5 100644 --- a/apps/files_versions/ajax/expireAll.php +++ b/apps/files_versions/ajax/expireAll.php @@ -27,8 +27,9 @@ // Check user and app status OCP\JSON::checkLoggedIn(); OCP\App::checkAppEnabled('files_versions'); +OCP\JSON::callCheck(); -$versions = new OCA_Versions\Storage( new OC_FilesystemView('') ); +$versions = new OCA_Versions\Storage(); if( $versions->expireAll() ){ diff --git a/apps/files_versions/ajax/rollbackVersion.php b/apps/files_versions/ajax/rollbackVersion.php index 8d1092f8b8e..24d71a914a4 100644 --- a/apps/files_versions/ajax/rollbackVersion.php +++ b/apps/files_versions/ajax/rollbackVersion.php @@ -1,6 +1,7 @@ <?php OCP\JSON::checkAppEnabled('files_versions'); +OCP\JSON::callCheck(); $userDirectory = "/".OCP\USER::getUser()."/files"; diff --git a/apps/files_versions/ajax/togglesettings.php b/apps/files_versions/ajax/togglesettings.php index d513d12dd6c..546b37ae1aa 100644 --- a/apps/files_versions/ajax/togglesettings.php +++ b/apps/files_versions/ajax/togglesettings.php @@ -2,10 +2,9 @@ OCP\JSON::checkAppEnabled('files_versions'); OCP\JSON::checkAdminUser(); +OCP\JSON::callCheck(); if (OCP\Config::getSystemValue('versions', 'true')=='true') { OCP\Config::setSystemValue('versions', 'false'); } else { OCP\Config::setSystemValue('versions', 'true'); } - -?> diff --git a/apps/files_versions/appinfo/update.php b/apps/files_versions/appinfo/update.php new file mode 100644 index 00000000000..9569ca10485 --- /dev/null +++ b/apps/files_versions/appinfo/update.php @@ -0,0 +1,16 @@ +<?php + +$installedVersion=OCP\Config::getAppValue('files_versions', 'installed_version'); +// move versions to new directory +if (version_compare($installedVersion, '1.0.2', '<')) { + $users = \OCP\User::getUsers(); + $datadir = \OCP\Config::getSystemValue('datadirectory').'/'; + foreach ($users as $user) { + $oldPath = $datadir.$user.'/versions';
+ $newPath = $datadir.$user.'/files_versions'; + if(is_dir($oldPath)) { + rename($oldPath, $newPath); + } + } + +} diff --git a/apps/files_versions/appinfo/version b/apps/files_versions/appinfo/version index 7f207341d5d..e6d5cb833c6 100644 --- a/apps/files_versions/appinfo/version +++ b/apps/files_versions/appinfo/version @@ -1 +1 @@ -1.0.1
\ No newline at end of file +1.0.2
\ No newline at end of file diff --git a/apps/files_versions/history.php b/apps/files_versions/history.php index e3332d7cdb6..a34c92ee422 100644 --- a/apps/files_versions/history.php +++ b/apps/files_versions/history.php @@ -30,7 +30,7 @@ if ( isset( $_GET['path'] ) ) { $path = $_GET['path']; $path = strip_tags( $path ); $tmpl->assign( 'path', $path ); - $versions = new OCA_Versions\Storage( new OC_FilesystemView('') ); + $versions = new OCA_Versions\Storage(); // roll back to old version if button clicked if( isset( $_GET['revert'] ) ) { @@ -71,5 +71,3 @@ if ( isset( $_GET['path'] ) ) { } $tmpl->printPage( ); - -?> diff --git a/apps/files_versions/lib/hooks.php b/apps/files_versions/lib/hooks.php index b43fdb9fd33..bfc8fd3a378 100644 --- a/apps/files_versions/lib/hooks.php +++ b/apps/files_versions/lib/hooks.php @@ -30,6 +30,7 @@ class Hooks { } } + /**
* @brief Erase versions of deleted file
* @param array
@@ -37,9 +38,10 @@ class Hooks { * This function is connected to the delete signal of OC_Filesystem
* cleanup the versions directory if the actual file gets deleted
*/
- public static function remove_hook($params) {
+ public static function remove_hook($params) { + $versions_fileview = \OCP\Files::getStorage('files_versions');
$rel_path = $params['path'];
- $abs_path = \OCP\Config::getSystemValue('datadirectory').'/'.\OCP\User::getUser()."/versions".$rel_path.'.v';
+ $abs_path = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('').$rel_path.'.v';
if(Storage::isversioned($rel_path)) {
$versions = Storage::getVersions($rel_path);
foreach ($versions as $v){
@@ -55,11 +57,14 @@ class Hooks { * This function is connected to the rename signal of OC_Filesystem and adjust the name and location
* of the stored versions along the actual file
*/
- public static function rename_hook($params) {
+ public static function rename_hook($params) { + $versions_fileview = \OCP\Files::getStorage('files_versions');
$rel_oldpath = $params['oldpath'];
- $abs_oldpath = \OCP\Config::getSystemValue('datadirectory').'/'.\OCP\User::getUser()."/versions".$rel_oldpath.'.v';
- $abs_newpath = \OCP\Config::getSystemValue('datadirectory').'/'.\OCP\User::getUser()."/versions".$params['newpath'].'.v';
- if(Storage::isversioned($rel_oldpath)) {
+ $abs_oldpath = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('').$rel_oldpath.'.v';
+ $abs_newpath = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('').$params['newpath'].'.v';
+ if(Storage::isversioned($rel_oldpath)) { + $info=pathinfo($abs_newpath);
+ if(!file_exists($info['dirname'])) mkdir($info['dirname'],0700,true);
$versions = Storage::getVersions($rel_oldpath);
foreach ($versions as $v){
rename($abs_oldpath.$v['version'], $abs_newpath.$v['version']);
@@ -68,5 +73,3 @@ class Hooks { } } - -?> diff --git a/apps/files_versions/lib/versions.php b/apps/files_versions/lib/versions.php index 4f0ee2c6d52..f146676757d 100644 --- a/apps/files_versions/lib/versions.php +++ b/apps/files_versions/lib/versions.php @@ -22,41 +22,26 @@ class Storage { // - files_versionsfolder
// - files_versionsblacklist
// - files_versionsmaxfilesize
- // - files_versionsinterval
- // - files_versionmaxversions
+ // - files_versionsinterval
+ // - files_versionmaxversions
//
// todo:
// - finish porting to OC_FilesystemView to enable network transparency
// - add transparent compression. first test if it´s worth it.
- const DEFAULTENABLED=true;
- const DEFAULTFOLDER='versions';
- const DEFAULTBLACKLIST='avi mp3 mpg mp4 ctmp';
- const DEFAULTMAXFILESIZE=1048576; // 10MB
+ const DEFAULTENABLED=true;
+ const DEFAULTBLACKLIST='avi mp3 mpg mp4 ctmp';
+ const DEFAULTMAXFILESIZE=1048576; // 10MB
const DEFAULTMININTERVAL=60; // 1 min
const DEFAULTMAXVERSIONS=50;
-
+
private $view;
-
- function __construct( $view ) {
-
- $this->view = $view;
-
- }
- /**
- * init the versioning and create the versions folder.
- */
- public static function init() {
- if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
- // create versions folder
- $foldername=\OCP\Config::getSystemValue('datadirectory').'/'. \OCP\USER::getUser() .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
- if(!is_dir($foldername)){
- mkdir($foldername);
- }
- }
- }
+ function __construct() {
+
+ $this->view = \OCP\Files::getStorage('files_versions');
+ }
/**
* listen to write event.
@@ -75,11 +60,11 @@ class Storage { */
public function store($filename) {
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
-
+
$files_view = \OCP\Files::getStorage("files");
$users_view = \OCP\Files::getStorage("files_versions");
$users_view->chroot(\OCP\User::getUser().'/');
-
+
if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) {
$pos = strpos($source, '/files', 1);
$uid = substr($source, 1, $pos - 1);
@@ -87,15 +72,14 @@ class Storage { } else {
$uid = \OCP\User::getUser();
}
- $versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
- $filesfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/files';
- Storage::init();
-
+
+ $versionsFolderName=\OCP\Config::getSystemValue('datadirectory') . $this->view->getAbsolutePath('');
+
//check if source file already exist as version to avoid recursions.
if ($users_view->file_exists($filename)) {
return false;
}
-
+
// check if filename is a directory
if($files_view->is_dir($filename)){
return false;
@@ -110,7 +94,7 @@ class Storage { return false;
}
}
-
+
// check filesize
if($files_view->filesize($filename)>\OCP\Config::getSystemValue('files_versionsmaxfilesize', Storage::DEFAULTMAXFILESIZE)){
return false;
@@ -129,12 +113,12 @@ class Storage { // create all parent folders
- $info=pathinfo($filename);
- if(!file_exists($versionsFolderName.'/'.$info['dirname'])) mkdir($versionsFolderName.'/'.$info['dirname'],0700,true);
+ $info=pathinfo($filename);
+ if(!file_exists($versionsFolderName.'/'.$info['dirname'])) mkdir($versionsFolderName.'/'.$info['dirname'],0700,true);
// store a new version of a file
- @$users_view->copy('files'.$filename, 'versions'.$filename.'.v'.time());
-
+ @$users_view->copy('files'.$filename, 'files_versions'.$filename.'.v'.time());
+
// expire old revisions if necessary
Storage::expire($filename);
}
@@ -145,11 +129,11 @@ class Storage { * rollback to an old version of a file.
*/
public static function rollback($filename,$revision) {
-
+
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
$users_view = \OCP\Files::getStorage("files_versions");
$users_view->chroot(\OCP\User::getUser().'/');
-
+
if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) {
$pos = strpos($source, '/files', 1);
$uid = substr($source, 1, $pos - 1);
@@ -157,23 +141,20 @@ class Storage { } else {
$uid = \OCP\User::getUser();
}
- $versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'.$uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
-
- $filesfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/files';
-
+
// rollback
- if( @$users_view->copy('versions'.$filename.'.v'.$revision, 'files'.$filename) ) {
-
+ if( @$users_view->copy('files_versions'.$filename.'.v'.$revision, 'files'.$filename) ) {
+
return true;
-
+
}else{
-
+
return false;
-
+
}
-
+
}
-
+
}
/**
@@ -181,18 +162,17 @@ class Storage { */
public static function isversioned($filename) {
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
+ $versions_fileview = \OCP\Files::getStorage("files_versions");
if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) {
$pos = strpos($source, '/files', 1);
- $uid = substr($source, 1, $pos - 1);
$filename = substr($source, $pos + 6);
- } else {
- $uid = \OCP\User::getUser();
}
- $versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
+ $versionsFolderName=\OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath('');
+
// check for old versions
- $matches=glob($versionsFolderName.'/'.$filename.'.v*');
- if(count($matches)>1){
+ $matches=glob($versionsFolderName.$filename.'.v*');
+ if(count($matches)>0){
return true;
}else{
return false;
@@ -203,17 +183,17 @@ class Storage { }
-
- /**
- * @brief get a list of all available versions of a file in descending chronological order
- * @param $filename file to find versions of, relative to the user files dir
- * @param $count number of versions to return
- * @returns array
- */
- public static function getVersions( $filename, $count = 0 ) {
-
- if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) {
-
+
+ /**
+ * @brief get a list of all available versions of a file in descending chronological order
+ * @param $filename file to find versions of, relative to the user files dir
+ * @param $count number of versions to return
+ * @returns array
+ */
+ public static function getVersions( $filename, $count = 0 ) {
+
+ if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) {
+
if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) {
$pos = strpos($source, '/files', 1);
$uid = substr($source, 1, $pos - 1);
@@ -221,71 +201,71 @@ class Storage { } else {
$uid = \OCP\User::getUser();
}
- $versionsFolderName = \OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
- $versions = array();
-
+ $versions_fileview = \OCP\Files::getStorage('files_versions');
+ $versionsFolderName = \OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath('');
+ $versions = array();
+
// fetch for old versions
$matches = glob( $versionsFolderName.'/'.$filename.'.v*' );
-
+
sort( $matches );
-
+
$i = 0;
-
- foreach( $matches as $ma ) {
+ $files_view = \OCP\Files::getStorage('files');
+ $local_file = $files_view->getLocalFile($filename);
+ foreach( $matches as $ma ) {
+
$i++;
$versions[$i]['cur'] = 0;
$parts = explode( '.v', $ma );
$versions[$i]['version'] = ( end( $parts ) );
-
+
// if file with modified date exists, flag it in array as currently enabled version
- $curFile['fileName'] = basename( $parts[0] );
- $curFile['filePath'] = \OCP\Config::getSystemValue('datadirectory').\OC_Filesystem::getRoot().'/'.$curFile['fileName'];
-
- ( \md5_file( $ma ) == \md5_file( $curFile['filePath'] ) ? $versions[$i]['fileMatch'] = 1 : $versions[$i]['fileMatch'] = 0 );
-
+ ( \md5_file( $ma ) == \md5_file( $local_file ) ? $versions[$i]['fileMatch'] = 1 : $versions[$i]['fileMatch'] = 0 );
+
}
-
+
$versions = array_reverse( $versions );
foreach( $versions as $key => $value ) {
-
+
// flag the first matched file in array (which will have latest modification date) as current version
- if ( $versions[$key]['fileMatch'] ) {
-
- $versions[$key]['cur'] = 1;
+ if ( $value['fileMatch'] ) {
+
+ $value['cur'] = 1;
break;
-
+
}
-
+
}
-
+
$versions = array_reverse( $versions );
-
+
// only show the newest commits
if( $count != 0 and ( count( $versions )>$count ) ) {
-
+
$versions = array_slice( $versions, count( $versions ) - $count );
-
+
}
-
+
return( $versions );
- } else {
-
+ } else {
+
// if versioning isn't enabled then return an empty array
- return( array() );
-
- }
-
- }
-
- /**
- * @brief Erase a file's versions which exceed the set quota
- */
- public static function expire($filename) {
- if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
+ return( array() );
+
+ }
+
+ }
+
+ /**
+ * @brief Erase a file's versions which exceed the set quota
+ */
+ public static function expire($filename) {
+ if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) {
$pos = strpos($source, '/files', 1);
@@ -294,36 +274,33 @@ class Storage { } else {
$uid = \OCP\User::getUser();
}
- $versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
+ $versions_fileview = \OCP\Files::getStorage("files_versions");
+ $versionsFolderName=\OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath('');
// check for old versions
$matches = glob( $versionsFolderName.'/'.$filename.'.v*' );
-
+
if( count( $matches ) > \OCP\Config::getSystemValue( 'files_versionmaxversions', Storage::DEFAULTMAXVERSIONS ) ) {
-
+
$numberToDelete = count( $matches-\OCP\Config::getSystemValue( 'files_versionmaxversions', Storage::DEFAULTMAXVERSIONS ) );
// delete old versions of a file
$deleteItems = array_slice( $matches, 0, $numberToDelete );
-
+
foreach( $deleteItems as $de ) {
-
+
unlink( $versionsFolderName.'/'.$filename.'.v'.$de );
-
+
}
}
- }
- }
-
- /**
- * @brief Erase all old versions of all user files
- * @return true/false
- */
- public function expireAll() {
-
- $dir = \OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
-
- return $this->view->deleteAll( $dir, true );
-
- }
+ }
+ }
+
+ /**
+ * @brief Erase all old versions of all user files
+ * @return true/false
+ */
+ public function expireAll() {
+ return $this->view->deleteAll('', true);
+ }
}
diff --git a/apps/files_versions/settings.php b/apps/files_versions/settings.php index 5f9e60fc589..f2873b8f7c2 100644 --- a/apps/files_versions/settings.php +++ b/apps/files_versions/settings.php @@ -7,4 +7,3 @@ OCP\Util::addscript( 'files_versions', 'versions' ); $tmpl = new OCP\Template( 'files_versions', 'settings'); return $tmpl->fetchPage(); -?> diff --git a/apps/gallery/ajax/createAlbum.php b/apps/gallery/ajax/createAlbum.php index 61e2e9ae2e9..5bfa5aa9a93 100644 --- a/apps/gallery/ajax/createAlbum.php +++ b/apps/gallery/ajax/createAlbum.php @@ -28,5 +28,3 @@ OCP\JSON::checkAppEnabled('gallery'); OC_Gallery_Album::create(OCP\USER::getUser(), $_GET['album_name']); OCP\JSON::success(array('name' => $_GET['album_name'])); - -?> diff --git a/apps/gallery/ajax/galleryOp.php b/apps/gallery/ajax/galleryOp.php index 7cbe3e46e21..ab8c64e28ad 100644 --- a/apps/gallery/ajax/galleryOp.php +++ b/apps/gallery/ajax/galleryOp.php @@ -186,4 +186,3 @@ if ($_GET['operation']) { OCP\JSON::error(array('cause' => 'Unknown operation')); } } -?> diff --git a/apps/gallery/ajax/viewImage.php b/apps/gallery/ajax/viewImage.php new file mode 100644 index 00000000000..daf0ab741f0 --- /dev/null +++ b/apps/gallery/ajax/viewImage.php @@ -0,0 +1,32 @@ +<?php + +/** + * ownCloud - gallery application + * + * @author Ike Devolder + * @copyright 2012 Ike Devolder + * + * 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/>. + * + */ +OCP\JSON::checkLoggedIn(); +OCP\JSON::checkAppEnabled('gallery'); + +$img = $_GET['img']; + +$image = OC_Gallery_Photo::getViewImage($img); +if ($image) { + OCP\Response::enableCaching(3600 * 24); // 24 hour + $image->show(); +} diff --git a/apps/gallery/appinfo/version b/apps/gallery/appinfo/version index 8f0916f768f..4b9fcbec101 100644 --- a/apps/gallery/appinfo/version +++ b/apps/gallery/appinfo/version @@ -1 +1 @@ -0.5.0 +0.5.1 diff --git a/apps/gallery/css/styles.css b/apps/gallery/css/styles.css index dcef1f08c6d..63f645662dd 100644 --- a/apps/gallery/css/styles.css +++ b/apps/gallery/css/styles.css @@ -1,11 +1,11 @@ #gallerycontent { margin-top: 2.8em; overflow: visible; } -#g-settings {position: absolute; left 13.5em; top: 0;} +#g-settings {position: absolute; left: 13.5em; top: 0;} div#controls input[type=button] { -webkit-transition: opacity 0.5s ease-in-out; -moz-transition: opacity 0.5s ease-in-out; -o-transition: opacity 0.5s ease-in-out; opacity: 1; position:absolute; right:13.5em; top:0em; } input[type=button]:disabled { opacity: 0.5 } .ui-dialog tr {background-color: #eee;} .ui-dialog input {width: 90%;} -div.gallery_div {position:relative; display: inline-block; height: 152px; width: 150px; margin: 5px;} +div.gallery_div {position:relative; display: inline-block; height: 150px; width: 150px; margin: 5px;} div.miniature_border {position:absolute; height: 150px; -moz-transition-duration: 0.2s; -o-transition-duration:0.2s; -webkit-transition-duration: .2s; background-position: 50%;} div.line {display:inline-block; border: 0; width: auto; height: 160px} div.gallery_div img{position:absolute; top: 1; left: 0; -moz-transition-duration: 0.3s; -o-transition-duration:0.3s; -webkit-transition-duration: 0.3s; height:150px; width: auto;} diff --git a/apps/gallery/css/supersized.css b/apps/gallery/css/supersized.css new file mode 100644 index 00000000000..57ee7e23a50 --- /dev/null +++ b/apps/gallery/css/supersized.css @@ -0,0 +1,25 @@ +/* + + Supersized - Fullscreen Slideshow jQuery Plugin + Version : 3.2.7 + Site : www.buildinternet.com/project/supersized + + Author : Sam Dunn + Company : One Mighty Roar (www.onemightyroar.com) + License : MIT License / GPL License + +*/ +#supersized-holder #supersized-loader { display:none; position:absolute; top:50%; left:50%; z-index:0; width:60px; height:60px; margin:-30px 0 0 -30px; text-indent:-999em; background:url('%appswebroot%/gallery/img/supersized/progress.gif') no-repeat center center;} + +#supersized-holder #supersized { visibility:hidden; display:block; position:fixed; left:0; top:0; overflow:hidden; z-index:200; height:100%; width:100%; } +#supersized-holder #supersized img { width:auto; height:auto; position:relative; display:none; outline:none; border:none; } +#supersized-holder #supersized.speed img { -ms-interpolation-mode:nearest-neighbor; image-rendering: -moz-crisp-edges; } /*Speed*/ +#supersized-holder #supersized.quality img { -ms-interpolation-mode:bicubic; image-rendering: optimizeQuality; } /*Quality*/ + +#supersized-holder #supersized li { display:block; list-style:none; z-index:150; position:fixed; overflow:hidden; top:0; left:0; width:100%; height:100%; background:#111; } +#supersized-holder #supersized a { width:100%; height:100%; display:block; } +#supersized-holder #supersized li.prevslide { z-index:160; } +#supersized-holder #supersized li.activeslide { z-index:170; } +#supersized-holder #supersized li.image-loading { background:#111 url('%appswebroot%/gallery/img/supersized/progress.gif') no-repeat center center; width:100%; height:100%; } +#supersized-holder #supersized li.image-loading img{ visibility:hidden; } +#supersized-holder #supersized li.prevslide img, #supersized-holder #supersized li.activeslide img{ display:inline; } diff --git a/apps/gallery/css/supersized.shutter.css b/apps/gallery/css/supersized.shutter.css new file mode 100644 index 00000000000..428c254c3b2 --- /dev/null +++ b/apps/gallery/css/supersized.shutter.css @@ -0,0 +1,74 @@ +/* + + Supersized - Fullscreen Slideshow jQuery Plugin + Version : 3.2.7 + Site : www.buildinternet.com/project/supersized + + Theme : Shutter 1.2 + Author : Sam Dunn + Company : One Mighty Roar (www.onemightyroar.com) + License : MIT License / GPL License + +*/ + +/* Controls Bar +----------------------------*/ +#slideshow-content #slideshow-controls-wrapper { margin:0 auto; height:42px; width:100%; bottom:0px; left:0; z-index:204; background:url('%appswebroot%/gallery/img/supersized/nav-bg.png') repeat-x; position:fixed; } +#slideshow-content #slideshow-controls { overflow:hidden; height:100%; position:relative; text-align:left; z-index:205; } +#slideshow-content #slidecounter { float:left; color:#999; font:14px "Helvetica Neue", Helvetica, Arial, sans-serif; text-shadow:#000 0 -1px 0; margin:0px 10px 0 15px; line-height:42px; } +#slideshow-content #slidecaption { overflow:hidden; float:left; color:#FFF; font:400 14px "Helvetica Neue", Helvetica, Arial, sans-serif; text-shadow:#000 1px 1px 2px; margin:0 20px 0 0; line-height:42px; } + +/*#navigation { float:right; margin:0px 20px 0 0; }*/ +#slideshow-content #play-button{ float:left; margin-top:1px;border-right:1px solid #333; background:url('%appswebroot%/gallery/img/supersized/bg-hover.png') repeat-x 0 44px; } +#slideshow-content #play-button:hover{ background-position:0 1px; cursor:pointer; } + +#slideshow-content #prevslide, #nextslide{ position:fixed; height:43px; width:43px; top:50%; margin-top:-21px; opacity:0.6; z-index:204; } +#slideshow-content #prevslide{ left:10px; background:url('%appswebroot%/gallery/img/supersized/back.png'); } +#slideshow-content #nextslide{ right:10px; background:url('%appswebroot%/gallery/img/supersized/forward.png'); } +#slideshow-content #prevslide:active, #nextslide:active{ margin-top:-19px; } +#slideshow-content #prevslide:hover, #nextslide:hover{ cursor:pointer; } + +#slideshow-content ul#slide-list{ padding:15px 0; float:left; position:absolute; left:50%; } +#slideshow-content ul#slide-list li{ list-style:none; width:12px; height:12px; float:left; margin:0 5px 0 0; } +#slideshow-content ul#slide-list li.current-slide a, ul#slide-list li.current-slide a:hover{ background-position:0 0px; } +#slideshow-content ul#slide-list li a{ display:block; width:12px; height:12px; background:url('%appswebroot%/gallery/img/supersized/nav-dot.png') no-repeat 0 -24px; } +#slideshow-content ul#slide-list li a:hover{ background-position:0 -12px; cursor:pointer; } + +#slideshow-content #tray-button{ float:right; margin-top:1px; border-left:1px solid #333; background:url('%appswebroot%/gallery/img/supersized/bg-hover.png') repeat-x 0 44px; } +#slideshow-content #tray-button:hover{ background-position:0 1px; cursor:pointer; } + + +/* Progress Bar +----------------------------*/ +#slideshow-content #progress-back{ z-index:205; position:fixed; bottom:42px; left:0; height:8px; width:100%; background:url('%appswebroot%/gallery/img/supersized/progress-back.png') repeat-x; } +#slideshow-content #progress-bar{ position:relative; height:8px; width:100%; background:url('%appswebroot%/gallery/img/supersized/progress-bar.png') repeat-x; } + + +/* Thumbnail Navigation +----------------------------*/ +#slideshow-content #nextthumb, #slideshow-content #prevthumb { z-index:202; display:none; position:fixed; bottom:61px; height:75px; width:100px; overflow:hidden; background:#ddd; border:1px solid #fff; -webkit-box-shadow:0 0 5px #000; } +#slideshow-content #nextthumb { right:12px; } +#slideshow-content #prevthumb { left:12px; } +#slideshow-content #nextthumb img, #slideshow-content #prevthumb img { width:150px; height:auto; } +#slideshow-content #nextthumb:active, #slideshow-content #prevthumb:active { bottom:59px; } +#slideshow-content #nextthumb:hover, #slideshow-content #prevthumb:hover { cursor:pointer; } + + +/* Thumbnail Tray +----------------------------*/ +#slideshow-content #thumb-tray{ position:fixed; z-index:203; bottom:0; left:0; background:url('%appswebroot%/gallery/img/supersized/bg-black.png'); height:150px; width:100%; overflow:hidden; text-align:center; -moz-box-shadow: 0px 0px 4px #000; -webkit-box-shadow: 0px 0px 4px #000; box-shadow: 0px 0px 4px #000; } + +#slideshow-content #thumb-back, #slideshow-content #thumb-forward{ position:absolute; z-index:5; bottom:42px; height:108px; width:40px; } +#slideshow-content #thumb-back{ left:0; background: url('%appswebroot%/gallery/img/supersized/thumb-back.png') no-repeat center center;} +#slideshow-content #thumb-forward{ right:0; background:url('%appswebroot%/gallery/img/supersized/thumb-forward.png') no-repeat center center;} +#slideshow-content #thumb-back:hover, #slideshow-content #thumb-forward:hover{ cursor:pointer; background-color:rgba(256,256,256, 0.1); } +#slideshow-content #thumb-back:hover{ border-right:1px solid rgba(256,256,256, 0.2); } +#slideshow-content #thumb-forward:hover{ border-left:1px solid rgba(256,256,256, 0.2); } + + +#slideshow-content ul#thumb-list{ display:inline-block; list-style:none; position:relative; left:0px; padding:0 0px; } +#slideshow-content ul#thumb-list li{ background:#111; list-style:none; display:inline; width:150px; height:108px; overflow:hidden; float:left; margin:0; } +#slideshow-content ul#thumb-list li img { width:200px; height:auto; opacity:0.5; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; filter:alpha(opacity=60); -webkit-transition: all 100ms ease-in-out; -moz-transition: all 100ms ease-in-out; -o-transition: all 100ms ease-in-out; -ms-transition: all 100ms ease-in-out; transition: all 100ms ease-in-out; } +#slideshow-content ul#thumb-list li.current-thumb img, #slideshow-content ul#thumb-list li:hover img{ opacity:1; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); } +#slideshow-content ul#thumb-list li:hover{ cursor:pointer; } + diff --git a/apps/gallery/img/supersized/back.png b/apps/gallery/img/supersized/back.png Binary files differnew file mode 100644 index 00000000000..44cd0ae703c --- /dev/null +++ b/apps/gallery/img/supersized/back.png diff --git a/apps/gallery/img/supersized/bg-black.png b/apps/gallery/img/supersized/bg-black.png Binary files differnew file mode 100644 index 00000000000..8c2f00140d6 --- /dev/null +++ b/apps/gallery/img/supersized/bg-black.png diff --git a/apps/gallery/img/supersized/bg-hover.png b/apps/gallery/img/supersized/bg-hover.png Binary files differnew file mode 100644 index 00000000000..1ca2022e106 --- /dev/null +++ b/apps/gallery/img/supersized/bg-hover.png diff --git a/apps/gallery/img/supersized/button-tray-down.png b/apps/gallery/img/supersized/button-tray-down.png Binary files differnew file mode 100644 index 00000000000..99b92aef122 --- /dev/null +++ b/apps/gallery/img/supersized/button-tray-down.png diff --git a/apps/gallery/img/supersized/button-tray-up.png b/apps/gallery/img/supersized/button-tray-up.png Binary files differnew file mode 100644 index 00000000000..7cc57785f0a --- /dev/null +++ b/apps/gallery/img/supersized/button-tray-up.png diff --git a/apps/gallery/img/supersized/forward.png b/apps/gallery/img/supersized/forward.png Binary files differnew file mode 100644 index 00000000000..e2084ab3faf --- /dev/null +++ b/apps/gallery/img/supersized/forward.png diff --git a/apps/gallery/img/supersized/nav-bg.png b/apps/gallery/img/supersized/nav-bg.png Binary files differnew file mode 100644 index 00000000000..800f904ddc7 --- /dev/null +++ b/apps/gallery/img/supersized/nav-bg.png diff --git a/apps/gallery/img/supersized/nav-dot.png b/apps/gallery/img/supersized/nav-dot.png Binary files differnew file mode 100644 index 00000000000..a28a50789f3 --- /dev/null +++ b/apps/gallery/img/supersized/nav-dot.png diff --git a/apps/gallery/img/supersized/pause.png b/apps/gallery/img/supersized/pause.png Binary files differnew file mode 100644 index 00000000000..a2c21a51cee --- /dev/null +++ b/apps/gallery/img/supersized/pause.png diff --git a/apps/gallery/img/supersized/play.png b/apps/gallery/img/supersized/play.png Binary files differnew file mode 100644 index 00000000000..16e53f86745 --- /dev/null +++ b/apps/gallery/img/supersized/play.png diff --git a/apps/gallery/img/supersized/progress-back.png b/apps/gallery/img/supersized/progress-back.png Binary files differnew file mode 100644 index 00000000000..68cd45b6706 --- /dev/null +++ b/apps/gallery/img/supersized/progress-back.png diff --git a/apps/gallery/img/supersized/progress-bar.png b/apps/gallery/img/supersized/progress-bar.png Binary files differnew file mode 100644 index 00000000000..49ebb0513b7 --- /dev/null +++ b/apps/gallery/img/supersized/progress-bar.png diff --git a/apps/gallery/img/supersized/progress.gif b/apps/gallery/img/supersized/progress.gif Binary files differnew file mode 100644 index 00000000000..f3e45e0569c --- /dev/null +++ b/apps/gallery/img/supersized/progress.gif diff --git a/apps/gallery/img/supersized/supersized-logo.png b/apps/gallery/img/supersized/supersized-logo.png Binary files differnew file mode 100644 index 00000000000..b1243a29784 --- /dev/null +++ b/apps/gallery/img/supersized/supersized-logo.png diff --git a/apps/gallery/img/supersized/thumb-back.png b/apps/gallery/img/supersized/thumb-back.png Binary files differnew file mode 100644 index 00000000000..3c969ebd527 --- /dev/null +++ b/apps/gallery/img/supersized/thumb-back.png diff --git a/apps/gallery/img/supersized/thumb-forward.png b/apps/gallery/img/supersized/thumb-forward.png Binary files differnew file mode 100644 index 00000000000..afe451c75d0 --- /dev/null +++ b/apps/gallery/img/supersized/thumb-forward.png diff --git a/apps/gallery/index.php b/apps/gallery/index.php index b8aadacb47f..ce79f8f8782 100644 --- a/apps/gallery/index.php +++ b/apps/gallery/index.php @@ -30,8 +30,14 @@ OCP\App::setActiveNavigationEntry( 'gallery_index' ); OCP\Util::addStyle('files', 'files'); OCP\Util::addStyle('gallery', 'styles'); OCP\Util::addScript('gallery', 'pictures'); +OCP\Util::addStyle( 'gallery', 'supersized' ); +OCP\Util::addStyle( 'gallery', 'supersized.shutter' ); +OCP\Util::addScript('gallery', 'slideshow'); +OCP\Util::addScript('gallery', 'jquery.easing.min'); +OCP\Util::addScript('gallery', 'supersized.3.2.7.min'); +OCP\Util::addScript('gallery', 'supersized.shutter.min'); -include('gallery/lib/tiles.php'); +include 'gallery/lib/tiles.php'; $root = !empty($_GET['root']) ? $_GET['root'] : '/'; $images = \OC_FileCache::searchByMime('image', null, '/'.\OCP\USER::getUser().'/files'.$root); @@ -97,4 +103,3 @@ $tmpl = new OCP\Template( 'gallery', 'index', 'user' ); $tmpl->assign('root', $root, false); $tmpl->assign('tl', $tl, false); $tmpl->printPage(); -?> diff --git a/apps/gallery/js/albums.js b/apps/gallery/js/albums.js index 413c71471a3..62d3f783ece 100644 --- a/apps/gallery/js/albums.js +++ b/apps/gallery/js/albums.js @@ -79,7 +79,7 @@ Albums={ }); 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>'; + var photoDisplayTemplate = '<div class="gallery_box"><div class="dummy"></div><div><a rel="images" href="'+OC.linkTo('gallery/ajax','viewImage.php')+'?img=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]))); } diff --git a/apps/gallery/js/jquery.easing.min.js b/apps/gallery/js/jquery.easing.min.js new file mode 100644 index 00000000000..bbf8410391a --- /dev/null +++ b/apps/gallery/js/jquery.easing.min.js @@ -0,0 +1,71 @@ +/* + * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ + * + * Uses the built in easing capabilities added In jQuery 1.1 + * to offer multiple easing options + * + * TERMS OF USE - jQuery Easing + * + * Open source under the BSD License. + * + * Copyright å© 2008 George McGinley Smith + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * Neither the name of the author nor the names of contributors may be used to endorse + * or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ + +jQuery.easing.jswing=jQuery.easing.swing;jQuery.extend(jQuery.easing,{def:"easeOutQuad",swing:function(e,f,a,h,g){return jQuery.easing[jQuery.easing.def](e,f,a,h,g)},easeInQuad:function(e,f,a,h,g){return h*(f/=g)*f+a},easeOutQuad:function(e,f,a,h,g){return -h*(f/=g)*(f-2)+a},easeInOutQuad:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f+a}return -h/2*((--f)*(f-2)-1)+a},easeInCubic:function(e,f,a,h,g){return h*(f/=g)*f*f+a},easeOutCubic:function(e,f,a,h,g){return h*((f=f/g-1)*f*f+1)+a},easeInOutCubic:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f*f+a}return h/2*((f-=2)*f*f+2)+a},easeInQuart:function(e,f,a,h,g){return h*(f/=g)*f*f*f+a},easeOutQuart:function(e,f,a,h,g){return -h*((f=f/g-1)*f*f*f-1)+a},easeInOutQuart:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f*f*f+a}return -h/2*((f-=2)*f*f*f-2)+a},easeInQuint:function(e,f,a,h,g){return h*(f/=g)*f*f*f*f+a},easeOutQuint:function(e,f,a,h,g){return h*((f=f/g-1)*f*f*f*f+1)+a},easeInOutQuint:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f*f*f*f+a}return h/2*((f-=2)*f*f*f*f+2)+a},easeInSine:function(e,f,a,h,g){return -h*Math.cos(f/g*(Math.PI/2))+h+a},easeOutSine:function(e,f,a,h,g){return h*Math.sin(f/g*(Math.PI/2))+a},easeInOutSine:function(e,f,a,h,g){return -h/2*(Math.cos(Math.PI*f/g)-1)+a},easeInExpo:function(e,f,a,h,g){return(f==0)?a:h*Math.pow(2,10*(f/g-1))+a},easeOutExpo:function(e,f,a,h,g){return(f==g)?a+h:h*(-Math.pow(2,-10*f/g)+1)+a},easeInOutExpo:function(e,f,a,h,g){if(f==0){return a}if(f==g){return a+h}if((f/=g/2)<1){return h/2*Math.pow(2,10*(f-1))+a}return h/2*(-Math.pow(2,-10*--f)+2)+a},easeInCirc:function(e,f,a,h,g){return -h*(Math.sqrt(1-(f/=g)*f)-1)+a},easeOutCirc:function(e,f,a,h,g){return h*Math.sqrt(1-(f=f/g-1)*f)+a},easeInOutCirc:function(e,f,a,h,g){if((f/=g/2)<1){return -h/2*(Math.sqrt(1-f*f)-1)+a}return h/2*(Math.sqrt(1-(f-=2)*f)+1)+a},easeInElastic:function(f,h,e,l,k){var i=1.70158;var j=0;var g=l;if(h==0){return e}if((h/=k)==1){return e+l}if(!j){j=k*0.3}if(g<Math.abs(l)){g=l;var i=j/4}else{var i=j/(2*Math.PI)*Math.asin(l/g)}return -(g*Math.pow(2,10*(h-=1))*Math.sin((h*k-i)*(2*Math.PI)/j))+e},easeOutElastic:function(f,h,e,l,k){var i=1.70158;var j=0;var g=l;if(h==0){return e}if((h/=k)==1){return e+l}if(!j){j=k*0.3}if(g<Math.abs(l)){g=l;var i=j/4}else{var i=j/(2*Math.PI)*Math.asin(l/g)}return g*Math.pow(2,-10*h)*Math.sin((h*k-i)*(2*Math.PI)/j)+l+e},easeInOutElastic:function(f,h,e,l,k){var i=1.70158;var j=0;var g=l;if(h==0){return e}if((h/=k/2)==2){return e+l}if(!j){j=k*(0.3*1.5)}if(g<Math.abs(l)){g=l;var i=j/4}else{var i=j/(2*Math.PI)*Math.asin(l/g)}if(h<1){return -0.5*(g*Math.pow(2,10*(h-=1))*Math.sin((h*k-i)*(2*Math.PI)/j))+e}return g*Math.pow(2,-10*(h-=1))*Math.sin((h*k-i)*(2*Math.PI)/j)*0.5+l+e},easeInBack:function(e,f,a,i,h,g){if(g==undefined){g=1.70158}return i*(f/=h)*f*((g+1)*f-g)+a},easeOutBack:function(e,f,a,i,h,g){if(g==undefined){g=1.70158}return i*((f=f/h-1)*f*((g+1)*f+g)+1)+a},easeInOutBack:function(e,f,a,i,h,g){if(g==undefined){g=1.70158}if((f/=h/2)<1){return i/2*(f*f*(((g*=(1.525))+1)*f-g))+a}return i/2*((f-=2)*f*(((g*=(1.525))+1)*f+g)+2)+a},easeInBounce:function(e,f,a,h,g){return h-jQuery.easing.easeOutBounce(e,g-f,0,h,g)+a},easeOutBounce:function(e,f,a,h,g){if((f/=g)<(1/2.75)){return h*(7.5625*f*f)+a}else{if(f<(2/2.75)){return h*(7.5625*(f-=(1.5/2.75))*f+0.75)+a}else{if(f<(2.5/2.75)){return h*(7.5625*(f-=(2.25/2.75))*f+0.9375)+a}else{return h*(7.5625*(f-=(2.625/2.75))*f+0.984375)+a}}}},easeInOutBounce:function(e,f,a,h,g){if(f<g/2){return jQuery.easing.easeInBounce(e,f*2,0,h,g)*0.5+a}return jQuery.easing.easeOutBounce(e,f*2-g,0,h,g)*0.5+h*0.5+a}}); + +/* + * + * TERMS OF USE - EASING EQUATIONS + * + * Open source under the BSD License. + * + * Copyright å© 2001 Robert Penner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * Neither the name of the author nor the names of contributors may be used to endorse + * or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */
\ No newline at end of file diff --git a/apps/gallery/js/slideshow.js b/apps/gallery/js/slideshow.js new file mode 100644 index 00000000000..cc5dfc44a26 --- /dev/null +++ b/apps/gallery/js/slideshow.js @@ -0,0 +1,58 @@ +$(document).ready(function(){ + + $.endSlideshow = function () { + if($.supersized.vars.slideshow_interval){ + clearInterval($.supersized.vars.slideshow_interval); + }; + + $('#supersized-holder').remove(); + $('#slideshow-content').hide(); + $('#thumb-list').remove(); + } + + // add slideshow in holder div + $('#slideshow input.start').click(function(){ + + var images=[]; + $('#gallerycontent div a').each(function(i,a){ + images.push({image : a.href, title : a.title.replace(/</, '<').replace(/>/, '>'), thumb : a.children[0].src, url : 'javascript:$.endSlideshow()'}); + }); + + if (images.length <= 0) { + return; + } + + $('body').append("<div id='supersized-holder'></div>"); + $('#supersized-loader').remove(); + $('#supersized').remove(); + $('#supersized-holder').append("<div id='supersized-loader'></div><ul id='supersized'></ul>"); + $('#supersized').show(); + $('#slideshow-content').show(); + + + jQuery(function($){ + + $.supersized({ + + // Functionality + slide_interval : 3000, // Length between transitions + transition : 1, // 0-None, 1-Fade, 2-Slide Top, 3-Slide Right, 4-Slide Bottom, 5-Slide Left, 6-Carousel Right, 7-Carousel Left + transition_speed : 700, // Speed of transition + + // Components + slide_links : 'blank', // Individual links for each slide (Options: false, 'num', 'name', 'blank') + slides : images // Slideshow Images + + }); + }); + + }); + + //close slideshow on esc and remove holder + $(document).keyup(function(e) { + if (e.keyCode == 27) { // esc + $.endSlideshow(); + } + }); + +}); diff --git a/apps/gallery/js/supersized.3.2.7.js b/apps/gallery/js/supersized.3.2.7.js new file mode 100644 index 00000000000..f5a1c0bbc2d --- /dev/null +++ b/apps/gallery/js/supersized.3.2.7.js @@ -0,0 +1,930 @@ +/* + + Supersized - Fullscreen Slideshow jQuery Plugin + Version : 3.2.7 + Site : www.buildinternet.com/project/supersized + + Author : Sam Dunn + Company : One Mighty Roar (www.onemightyroar.com) + License : MIT License / GPL License + +*/ + +(function($){ + + /* Place Supersized Elements + ----------------------------*/ + $(document).ready(function() { + $('body').append('<div id="supersized-loader"></div><ul id="supersized"></ul>'); + }); + + + $.supersized = function(options){ + + /* Variables + ----------------------------*/ + var el = '#supersized', + base = this; + // Access to jQuery and DOM versions of element + base.$el = $(el); + base.el = el; + vars = $.supersized.vars; + // Add a reverse reference to the DOM object + base.$el.data("supersized", base); + api = base.$el.data('supersized'); + + base.init = function(){ + // Combine options and vars + $.supersized.vars = $.extend($.supersized.vars, $.supersized.themeVars); + $.supersized.vars.options = $.extend({},$.supersized.defaultOptions, $.supersized.themeOptions, options); + base.options = $.supersized.vars.options; + + base._build(); + }; + + + /* Build Elements + ----------------------------*/ + base._build = function(){ + // Add in slide markers + var thisSlide = 0, + slideSet = '', + markers = '', + markerContent, + thumbMarkers = '', + thumbImage; + + while(thisSlide <= base.options.slides.length-1){ + //Determine slide link content + switch(base.options.slide_links){ + case 'num': + markerContent = thisSlide; + break; + case 'name': + markerContent = base.options.slides[thisSlide].title; + break; + case 'blank': + markerContent = ''; + break; + } + + slideSet = slideSet+'<li class="slide-'+thisSlide+'"></li>'; + + if(thisSlide == base.options.start_slide-1){ + // Slide links + if (base.options.slide_links)markers = markers+'<li class="slide-link-'+thisSlide+' current-slide"><a>'+markerContent+'</a></li>'; + // Slide Thumbnail Links + if (base.options.thumb_links){ + base.options.slides[thisSlide].thumb ? thumbImage = base.options.slides[thisSlide].thumb : thumbImage = base.options.slides[thisSlide].image; + thumbMarkers = thumbMarkers+'<li class="thumb'+thisSlide+' current-thumb"><img src="'+thumbImage+'"/></li>'; + }; + }else{ + // Slide links + if (base.options.slide_links) markers = markers+'<li class="slide-link-'+thisSlide+'" ><a>'+markerContent+'</a></li>'; + // Slide Thumbnail Links + if (base.options.thumb_links){ + base.options.slides[thisSlide].thumb ? thumbImage = base.options.slides[thisSlide].thumb : thumbImage = base.options.slides[thisSlide].image; + thumbMarkers = thumbMarkers+'<li class="thumb'+thisSlide+'"><img src="'+thumbImage+'"/></li>'; + }; + } + thisSlide++; + } + + if (base.options.slide_links) $(vars.slide_list).html(markers); + if (base.options.thumb_links && vars.thumb_tray.length){ + $(vars.thumb_tray).append('<ul id="'+vars.thumb_list.replace('#','')+'">'+thumbMarkers+'</ul>'); + } + + $(base.el).append(slideSet); + + // Add in thumbnails + if (base.options.thumbnail_navigation){ + // Load previous thumbnail + vars.current_slide - 1 < 0 ? prevThumb = base.options.slides.length - 1 : prevThumb = vars.current_slide - 1; + $(vars.prev_thumb).show().html($("<img/>").attr("src", base.options.slides[prevThumb].image)); + + // Load next thumbnail + vars.current_slide == base.options.slides.length - 1 ? nextThumb = 0 : nextThumb = vars.current_slide + 1; + $(vars.next_thumb).show().html($("<img/>").attr("src", base.options.slides[nextThumb].image)); + } + + base._start(); // Get things started + }; + + + /* Initialize + ----------------------------*/ + base._start = function(){ + + // Determine if starting slide random + if (base.options.start_slide){ + vars.current_slide = base.options.start_slide - 1; + }else{ + vars.current_slide = Math.floor(Math.random()*base.options.slides.length); // Generate random slide number + } + + // If links should open in new window + var linkTarget = base.options.new_window ? ' target="_blank"' : ''; + + // Set slideshow quality (Supported only in FF and IE, no Webkit) + if (base.options.performance == 3){ + base.$el.addClass('speed'); // Faster transitions + } else if ((base.options.performance == 1) || (base.options.performance == 2)){ + base.$el.addClass('quality'); // Higher image quality + } + + // Shuffle slide order if needed + if (base.options.random){ + arr = base.options.slides; + for(var j, x, i = arr.length; i; j = parseInt(Math.random() * i), x = arr[--i], arr[i] = arr[j], arr[j] = x); // Fisher-Yates shuffle algorithm (jsfromhell.com/array/shuffle) + base.options.slides = arr; + } + + /*-----Load initial set of images-----*/ + + if (base.options.slides.length > 1){ + if(base.options.slides.length > 2){ + // Set previous image + vars.current_slide - 1 < 0 ? loadPrev = base.options.slides.length - 1 : loadPrev = vars.current_slide - 1; // If slide is 1, load last slide as previous + var imageLink = (base.options.slides[loadPrev].url) ? "href='" + base.options.slides[loadPrev].url + "'" : ""; + + var imgPrev = $('<img src="'+base.options.slides[loadPrev].image+'"/>'); + var slidePrev = base.el+' li:eq('+loadPrev+')'; + imgPrev.appendTo(slidePrev).wrap('<a ' + imageLink + linkTarget + '></a>').parent().parent().addClass('image-loading prevslide'); + + imgPrev.load(function(){ + $(this).data('origWidth', $(this).width()).data('origHeight', $(this).height()); + base.resizeNow(); // Resize background image + }); // End Load + } + } else { + // Slideshow turned off if there is only one slide + base.options.slideshow = 0; + } + + // Set current image + imageLink = (api.getField('url')) ? "href='" + api.getField('url') + "'" : ""; + var img = $('<img src="'+api.getField('image')+'"/>'); + + var slideCurrent= base.el+' li:eq('+vars.current_slide+')'; + img.appendTo(slideCurrent).wrap('<a ' + imageLink + linkTarget + '></a>').parent().parent().addClass('image-loading activeslide'); + + img.load(function(){ + base._origDim($(this)); + base.resizeNow(); // Resize background image + base.launch(); + if( typeof theme != 'undefined' && typeof theme._init == "function" ) theme._init(); // Load Theme + }); + + if (base.options.slides.length > 1){ + // Set next image + vars.current_slide == base.options.slides.length - 1 ? loadNext = 0 : loadNext = vars.current_slide + 1; // If slide is last, load first slide as next + imageLink = (base.options.slides[loadNext].url) ? "href='" + base.options.slides[loadNext].url + "'" : ""; + + var imgNext = $('<img src="'+base.options.slides[loadNext].image+'"/>'); + var slideNext = base.el+' li:eq('+loadNext+')'; + imgNext.appendTo(slideNext).wrap('<a ' + imageLink + linkTarget + '></a>').parent().parent().addClass('image-loading'); + + imgNext.load(function(){ + $(this).data('origWidth', $(this).width()).data('origHeight', $(this).height()); + base.resizeNow(); // Resize background image + }); // End Load + } + /*-----End load initial images-----*/ + + // Hide elements to be faded in + base.$el.css('visibility','hidden'); + $('.load-item').hide(); + + }; + + + /* Launch Supersized + ----------------------------*/ + base.launch = function(){ + + base.$el.css('visibility','visible'); + $('#supersized-loader').remove(); //Hide loading animation + + // Call theme function for before slide transition + if( typeof theme != 'undefined' && typeof theme.beforeAnimation == "function" ) theme.beforeAnimation('next'); + $('.load-item').show(); + + // Keyboard Navigation + if (base.options.keyboard_nav){ + $(document.documentElement).keyup(function (event) { + + if(vars.in_animation) return false; // Abort if currently animating + + // Left Arrow or Down Arrow + if ((event.keyCode == 37) || (event.keyCode == 40)) { + clearInterval(vars.slideshow_interval); // Stop slideshow, prevent buildup + base.prevSlide(); + + // Right Arrow or Up Arrow + } else if ((event.keyCode == 39) || (event.keyCode == 38)) { + clearInterval(vars.slideshow_interval); // Stop slideshow, prevent buildup + base.nextSlide(); + + // Spacebar + } else if (event.keyCode == 32 && !vars.hover_pause) { + clearInterval(vars.slideshow_interval); // Stop slideshow, prevent buildup + base.playToggle(); + } + + }); + } + + // Pause when hover on image + if (base.options.slideshow && base.options.pause_hover){ + $(base.el).hover(function() { + if(vars.in_animation) return false; // Abort if currently animating + vars.hover_pause = true; // Mark slideshow paused from hover + if(!vars.is_paused){ + vars.hover_pause = 'resume'; // It needs to resume afterwards + base.playToggle(); + } + }, function() { + if(vars.hover_pause == 'resume'){ + base.playToggle(); + vars.hover_pause = false; + } + }); + } + + if (base.options.slide_links){ + // Slide marker clicked + $(vars.slide_list+'> li').click(function(){ + + index = $(vars.slide_list+'> li').index(this); + targetSlide = index + 1; + + base.goTo(targetSlide); + return false; + + }); + } + + // Thumb marker clicked + if (base.options.thumb_links){ + $(vars.thumb_list+'> li').click(function(){ + + index = $(vars.thumb_list+'> li').index(this); + targetSlide = index + 1; + + api.goTo(targetSlide); + return false; + + }); + } + + // Start slideshow if enabled + if (base.options.slideshow && base.options.slides.length > 1){ + + // Start slideshow if autoplay enabled + if (base.options.autoplay && base.options.slides.length > 1){ + vars.slideshow_interval = setInterval(base.nextSlide, base.options.slide_interval); // Initiate slide interval + }else{ + vars.is_paused = true; // Mark as paused + } + + //Prevent navigation items from being dragged + $('.load-item img').bind("contextmenu mousedown",function(){ + return false; + }); + + } + + // Adjust image when browser is resized + $(window).resize(function(){ + base.resizeNow(); + }); + + }; + + + /* Resize Images + ----------------------------*/ + base.resizeNow = function(){ + + return base.$el.each(function() { + // Resize each image seperately + $('img', base.el).each(function(){ + + thisSlide = $(this); + var ratio = (thisSlide.data('origHeight')/thisSlide.data('origWidth')).toFixed(2); // Define image ratio + + // Gather browser size + var browserwidth = base.$el.width(), + browserheight = base.$el.height(), + offset; + + /*-----Resize Image-----*/ + if (base.options.fit_always){ // Fit always is enabled + if ((browserheight/browserwidth) > ratio){ + resizeWidth(); + } else { + resizeHeight(); + } + }else{ // Normal Resize + if ((browserheight <= base.options.min_height) && (browserwidth <= base.options.min_width)){ // If window smaller than minimum width and height + + if ((browserheight/browserwidth) > ratio){ + base.options.fit_landscape && ratio < 1 ? resizeWidth(true) : resizeHeight(true); // If landscapes are set to fit + } else { + base.options.fit_portrait && ratio >= 1 ? resizeHeight(true) : resizeWidth(true); // If portraits are set to fit + } + + } else if (browserwidth <= base.options.min_width){ // If window only smaller than minimum width + + if ((browserheight/browserwidth) > ratio){ + base.options.fit_landscape && ratio < 1 ? resizeWidth(true) : resizeHeight(); // If landscapes are set to fit + } else { + base.options.fit_portrait && ratio >= 1 ? resizeHeight() : resizeWidth(true); // If portraits are set to fit + } + + } else if (browserheight <= base.options.min_height){ // If window only smaller than minimum height + + if ((browserheight/browserwidth) > ratio){ + base.options.fit_landscape && ratio < 1 ? resizeWidth() : resizeHeight(true); // If landscapes are set to fit + } else { + base.options.fit_portrait && ratio >= 1 ? resizeHeight(true) : resizeWidth(); // If portraits are set to fit + } + + } else { // If larger than minimums + + if ((browserheight/browserwidth) > ratio){ + base.options.fit_landscape && ratio < 1 ? resizeWidth() : resizeHeight(); // If landscapes are set to fit + } else { + base.options.fit_portrait && ratio >= 1 ? resizeHeight() : resizeWidth(); // If portraits are set to fit + } + + } + } + /*-----End Image Resize-----*/ + + + /*-----Resize Functions-----*/ + + function resizeWidth(minimum){ + if (minimum){ // If minimum height needs to be considered + if(thisSlide.width() < browserwidth || thisSlide.width() < base.options.min_width ){ + if (thisSlide.width() * ratio >= base.options.min_height){ + thisSlide.width(base.options.min_width); + thisSlide.height(thisSlide.width() * ratio); + }else{ + resizeHeight(); + } + } + }else{ + if (base.options.min_height >= browserheight && !base.options.fit_landscape){ // If minimum height needs to be considered + if (browserwidth * ratio >= base.options.min_height || (browserwidth * ratio >= base.options.min_height && ratio <= 1)){ // If resizing would push below minimum height or image is a landscape + thisSlide.width(browserwidth); + thisSlide.height(browserwidth * ratio); + } else if (ratio > 1){ // Else the image is portrait + thisSlide.height(base.options.min_height); + thisSlide.width(thisSlide.height() / ratio); + } else if (thisSlide.width() < browserwidth) { + thisSlide.width(browserwidth); + thisSlide.height(thisSlide.width() * ratio); + } + }else{ // Otherwise, resize as normal + thisSlide.width(browserwidth); + thisSlide.height(browserwidth * ratio); + } + } + }; + + function resizeHeight(minimum){ + if (minimum){ // If minimum height needs to be considered + if(thisSlide.height() < browserheight){ + if (thisSlide.height() / ratio >= base.options.min_width){ + thisSlide.height(base.options.min_height); + thisSlide.width(thisSlide.height() / ratio); + }else{ + resizeWidth(true); + } + } + }else{ // Otherwise, resized as normal + if (base.options.min_width >= browserwidth){ // If minimum width needs to be considered + if (browserheight / ratio >= base.options.min_width || ratio > 1){ // If resizing would push below minimum width or image is a portrait + thisSlide.height(browserheight); + thisSlide.width(browserheight / ratio); + } else if (ratio <= 1){ // Else the image is landscape + thisSlide.width(base.options.min_width); + thisSlide.height(thisSlide.width() * ratio); + } + }else{ // Otherwise, resize as normal + thisSlide.height(browserheight); + thisSlide.width(browserheight / ratio); + } + } + }; + + /*-----End Resize Functions-----*/ + + if (thisSlide.parents('li').hasClass('image-loading')){ + $('.image-loading').removeClass('image-loading'); + } + + // Horizontally Center + if (base.options.horizontal_center){ + $(this).css('left', (browserwidth - $(this).width())/2); + } + + // Vertically Center + if (base.options.vertical_center){ + $(this).css('top', (browserheight - $(this).height())/2); + } + + }); + + // Basic image drag and right click protection + if (base.options.image_protect){ + + $('img', base.el).bind("contextmenu mousedown",function(){ + return false; + }); + + } + + return false; + + }); + + }; + + + /* Next Slide + ----------------------------*/ + base.nextSlide = function(){ + + if(vars.in_animation || !api.options.slideshow) return false; // Abort if currently animating + else vars.in_animation = true; // Otherwise set animation marker + + clearInterval(vars.slideshow_interval); // Stop slideshow + + var slides = base.options.slides, // Pull in slides array + liveslide = base.$el.find('.activeslide'); // Find active slide + $('.prevslide').removeClass('prevslide'); + liveslide.removeClass('activeslide').addClass('prevslide'); // Remove active class & update previous slide + + // Get the slide number of new slide + vars.current_slide + 1 == base.options.slides.length ? vars.current_slide = 0 : vars.current_slide++; + + var nextslide = $(base.el+' li:eq('+vars.current_slide+')'), + prevslide = base.$el.find('.prevslide'); + + // If hybrid mode is on drop quality for transition + if (base.options.performance == 1) base.$el.removeClass('quality').addClass('speed'); + + + /*-----Load Image-----*/ + + loadSlide = false; + + vars.current_slide == base.options.slides.length - 1 ? loadSlide = 0 : loadSlide = vars.current_slide + 1; // Determine next slide + + var targetList = base.el+' li:eq('+loadSlide+')'; + if (!$(targetList).html()){ + + // If links should open in new window + var linkTarget = base.options.new_window ? ' target="_blank"' : ''; + + imageLink = (base.options.slides[loadSlide].url) ? "href='" + base.options.slides[loadSlide].url + "'" : ""; // If link exists, build it + var img = $('<img src="'+base.options.slides[loadSlide].image+'"/>'); + + img.appendTo(targetList).wrap('<a ' + imageLink + linkTarget + '></a>').parent().parent().addClass('image-loading').css('visibility','hidden'); + + img.load(function(){ + base._origDim($(this)); + base.resizeNow(); + }); // End Load + }; + + // Update thumbnails (if enabled) + if (base.options.thumbnail_navigation == 1){ + + // Load previous thumbnail + vars.current_slide - 1 < 0 ? prevThumb = base.options.slides.length - 1 : prevThumb = vars.current_slide - 1; + $(vars.prev_thumb).html($("<img/>").attr("src", base.options.slides[prevThumb].image)); + + // Load next thumbnail + nextThumb = loadSlide; + $(vars.next_thumb).html($("<img/>").attr("src", base.options.slides[nextThumb].image)); + + } + + + + /*-----End Load Image-----*/ + + + // Call theme function for before slide transition + if( typeof theme != 'undefined' && typeof theme.beforeAnimation == "function" ) theme.beforeAnimation('next'); + + //Update slide markers + if (base.options.slide_links){ + $('.current-slide').removeClass('current-slide'); + $(vars.slide_list +'> li' ).eq(vars.current_slide).addClass('current-slide'); + } + + nextslide.css('visibility','hidden').addClass('activeslide'); // Update active slide + + switch(base.options.transition){ + case 0: case 'none': // No transition + nextslide.css('visibility','visible'); vars.in_animation = false; base.afterAnimation(); + break; + case 1: case 'fade': // Fade + nextslide.animate({opacity : 0},0).css('visibility','visible').animate({opacity : 1, avoidTransforms : false}, base.options.transition_speed, function(){ base.afterAnimation(); }); + break; + case 2: case 'slideTop': // Slide Top + nextslide.animate({top : -base.$el.height()}, 0 ).css('visibility','visible').animate({ top:0, avoidTransforms : false }, base.options.transition_speed, function(){ base.afterAnimation(); }); + break; + case 3: case 'slideRight': // Slide Right + nextslide.animate({left : base.$el.width()}, 0 ).css('visibility','visible').animate({ left:0, avoidTransforms : false }, base.options.transition_speed, function(){ base.afterAnimation(); }); + break; + case 4: case 'slideBottom': // Slide Bottom + nextslide.animate({top : base.$el.height()}, 0 ).css('visibility','visible').animate({ top:0, avoidTransforms : false }, base.options.transition_speed, function(){ base.afterAnimation(); }); + break; + case 5: case 'slideLeft': // Slide Left + nextslide.animate({left : -base.$el.width()}, 0 ).css('visibility','visible').animate({ left:0, avoidTransforms : false }, base.options.transition_speed, function(){ base.afterAnimation(); }); + break; + case 6: case 'carouselRight': // Carousel Right + nextslide.animate({left : base.$el.width()}, 0 ).css('visibility','visible').animate({ left:0, avoidTransforms : false }, base.options.transition_speed, function(){ base.afterAnimation(); }); + liveslide.animate({ left: -base.$el.width(), avoidTransforms : false }, base.options.transition_speed ); + break; + case 7: case 'carouselLeft': // Carousel Left + nextslide.animate({left : -base.$el.width()}, 0 ).css('visibility','visible').animate({ left:0, avoidTransforms : false }, base.options.transition_speed, function(){ base.afterAnimation(); }); + liveslide.animate({ left: base.$el.width(), avoidTransforms : false }, base.options.transition_speed ); + break; + } + return false; + }; + + + /* Previous Slide + ----------------------------*/ + base.prevSlide = function(){ + + if(vars.in_animation || !api.options.slideshow) return false; // Abort if currently animating + else vars.in_animation = true; // Otherwise set animation marker + + clearInterval(vars.slideshow_interval); // Stop slideshow + + var slides = base.options.slides, // Pull in slides array + liveslide = base.$el.find('.activeslide'); // Find active slide + $('.prevslide').removeClass('prevslide'); + liveslide.removeClass('activeslide').addClass('prevslide'); // Remove active class & update previous slide + + // Get current slide number + vars.current_slide == 0 ? vars.current_slide = base.options.slides.length - 1 : vars.current_slide-- ; + + var nextslide = $(base.el+' li:eq('+vars.current_slide+')'), + prevslide = base.$el.find('.prevslide'); + + // If hybrid mode is on drop quality for transition + if (base.options.performance == 1) base.$el.removeClass('quality').addClass('speed'); + + + /*-----Load Image-----*/ + + loadSlide = vars.current_slide; + + var targetList = base.el+' li:eq('+loadSlide+')'; + if (!$(targetList).html()){ + // If links should open in new window + var linkTarget = base.options.new_window ? ' target="_blank"' : ''; + imageLink = (base.options.slides[loadSlide].url) ? "href='" + base.options.slides[loadSlide].url + "'" : ""; // If link exists, build it + var img = $('<img src="'+base.options.slides[loadSlide].image+'"/>'); + + img.appendTo(targetList).wrap('<a ' + imageLink + linkTarget + '></a>').parent().parent().addClass('image-loading').css('visibility','hidden'); + + img.load(function(){ + base._origDim($(this)); + base.resizeNow(); + }); // End Load + }; + + // Update thumbnails (if enabled) + if (base.options.thumbnail_navigation == 1){ + + // Load previous thumbnail + //prevThumb = loadSlide; + loadSlide == 0 ? prevThumb = base.options.slides.length - 1 : prevThumb = loadSlide - 1; + $(vars.prev_thumb).html($("<img/>").attr("src", base.options.slides[prevThumb].image)); + + // Load next thumbnail + vars.current_slide == base.options.slides.length - 1 ? nextThumb = 0 : nextThumb = vars.current_slide + 1; + $(vars.next_thumb).html($("<img/>").attr("src", base.options.slides[nextThumb].image)); + } + + /*-----End Load Image-----*/ + + + // Call theme function for before slide transition + if( typeof theme != 'undefined' && typeof theme.beforeAnimation == "function" ) theme.beforeAnimation('prev'); + + //Update slide markers + if (base.options.slide_links){ + $('.current-slide').removeClass('current-slide'); + $(vars.slide_list +'> li' ).eq(vars.current_slide).addClass('current-slide'); + } + + nextslide.css('visibility','hidden').addClass('activeslide'); // Update active slide + + switch(base.options.transition){ + case 0: case 'none': // No transition + nextslide.css('visibility','visible'); vars.in_animation = false; base.afterAnimation(); + break; + case 1: case 'fade': // Fade + nextslide.animate({opacity : 0},0).css('visibility','visible').animate({opacity : 1, avoidTransforms : false}, base.options.transition_speed, function(){ base.afterAnimation(); }); + break; + case 2: case 'slideTop': // Slide Top (reverse) + nextslide.animate({top : base.$el.height()}, 0 ).css('visibility','visible').animate({ top:0, avoidTransforms : false }, base.options.transition_speed, function(){ base.afterAnimation(); }); + break; + case 3: case 'slideRight': // Slide Right (reverse) + nextslide.animate({left : -base.$el.width()}, 0 ).css('visibility','visible').animate({ left:0, avoidTransforms : false }, base.options.transition_speed, function(){ base.afterAnimation(); }); + break; + case 4: case 'slideBottom': // Slide Bottom (reverse) + nextslide.animate({top : -base.$el.height()}, 0 ).css('visibility','visible').animate({ top:0, avoidTransforms : false }, base.options.transition_speed, function(){ base.afterAnimation(); }); + break; + case 5: case 'slideLeft': // Slide Left (reverse) + nextslide.animate({left : base.$el.width()}, 0 ).css('visibility','visible').animate({ left:0, avoidTransforms : false }, base.options.transition_speed, function(){ base.afterAnimation(); }); + break; + case 6: case 'carouselRight': // Carousel Right (reverse) + nextslide.animate({left : -base.$el.width()}, 0 ).css('visibility','visible').animate({ left:0, avoidTransforms : false }, base.options.transition_speed, function(){ base.afterAnimation(); }); + liveslide.animate({left : 0}, 0 ).animate({ left: base.$el.width(), avoidTransforms : false}, base.options.transition_speed ); + break; + case 7: case 'carouselLeft': // Carousel Left (reverse) + nextslide.animate({left : base.$el.width()}, 0 ).css('visibility','visible').animate({ left:0, avoidTransforms : false }, base.options.transition_speed, function(){ base.afterAnimation(); }); + liveslide.animate({left : 0}, 0 ).animate({ left: -base.$el.width(), avoidTransforms : false }, base.options.transition_speed ); + break; + } + return false; + }; + + + /* Play/Pause Toggle + ----------------------------*/ + base.playToggle = function(){ + + if (vars.in_animation || !api.options.slideshow) return false; // Abort if currently animating + + if (vars.is_paused){ + + vars.is_paused = false; + + // Call theme function for play + if( typeof theme != 'undefined' && typeof theme.playToggle == "function" ) theme.playToggle('play'); + + // Resume slideshow + vars.slideshow_interval = setInterval(base.nextSlide, base.options.slide_interval); + + }else{ + + vars.is_paused = true; + + // Call theme function for pause + if( typeof theme != 'undefined' && typeof theme.playToggle == "function" ) theme.playToggle('pause'); + + // Stop slideshow + clearInterval(vars.slideshow_interval); + + } + + return false; + + }; + + + /* Go to specific slide + ----------------------------*/ + base.goTo = function(targetSlide){ + if (vars.in_animation || !api.options.slideshow) return false; // Abort if currently animating + + var totalSlides = base.options.slides.length; + + // If target outside range + if(targetSlide < 0){ + targetSlide = totalSlides; + }else if(targetSlide > totalSlides){ + targetSlide = 1; + } + targetSlide = totalSlides - targetSlide + 1; + + clearInterval(vars.slideshow_interval); // Stop slideshow, prevent buildup + + // Call theme function for goTo trigger + if (typeof theme != 'undefined' && typeof theme.goTo == "function" ) theme.goTo(); + + if (vars.current_slide == totalSlides - targetSlide){ + if(!(vars.is_paused)){ + vars.slideshow_interval = setInterval(base.nextSlide, base.options.slide_interval); + } + return false; + } + + // If ahead of current position + if(totalSlides - targetSlide > vars.current_slide ){ + + // Adjust for new next slide + vars.current_slide = totalSlides-targetSlide-1; + vars.update_images = 'next'; + base._placeSlide(vars.update_images); + + //Otherwise it's before current position + }else if(totalSlides - targetSlide < vars.current_slide){ + + // Adjust for new prev slide + vars.current_slide = totalSlides-targetSlide+1; + vars.update_images = 'prev'; + base._placeSlide(vars.update_images); + + } + + // set active markers + if (base.options.slide_links){ + $(vars.slide_list +'> .current-slide').removeClass('current-slide'); + $(vars.slide_list +'> li').eq((totalSlides-targetSlide)).addClass('current-slide'); + } + + if (base.options.thumb_links){ + $(vars.thumb_list +'> .current-thumb').removeClass('current-thumb'); + $(vars.thumb_list +'> li').eq((totalSlides-targetSlide)).addClass('current-thumb'); + } + + }; + + + /* Place Slide + ----------------------------*/ + base._placeSlide = function(place){ + + // If links should open in new window + var linkTarget = base.options.new_window ? ' target="_blank"' : ''; + + loadSlide = false; + + if (place == 'next'){ + + vars.current_slide == base.options.slides.length - 1 ? loadSlide = 0 : loadSlide = vars.current_slide + 1; // Determine next slide + + var targetList = base.el+' li:eq('+loadSlide+')'; + + if (!$(targetList).html()){ + // If links should open in new window + var linkTarget = base.options.new_window ? ' target="_blank"' : ''; + + imageLink = (base.options.slides[loadSlide].url) ? "href='" + base.options.slides[loadSlide].url + "'" : ""; // If link exists, build it + var img = $('<img src="'+base.options.slides[loadSlide].image+'"/>'); + + img.appendTo(targetList).wrap('<a ' + imageLink + linkTarget + '></a>').parent().parent().addClass('image-loading').css('visibility','hidden'); + + img.load(function(){ + base._origDim($(this)); + base.resizeNow(); + }); // End Load + }; + + base.nextSlide(); + + }else if (place == 'prev'){ + + vars.current_slide - 1 < 0 ? loadSlide = base.options.slides.length - 1 : loadSlide = vars.current_slide - 1; // Determine next slide + + var targetList = base.el+' li:eq('+loadSlide+')'; + + if (!$(targetList).html()){ + // If links should open in new window + var linkTarget = base.options.new_window ? ' target="_blank"' : ''; + + imageLink = (base.options.slides[loadSlide].url) ? "href='" + base.options.slides[loadSlide].url + "'" : ""; // If link exists, build it + var img = $('<img src="'+base.options.slides[loadSlide].image+'"/>'); + + img.appendTo(targetList).wrap('<a ' + imageLink + linkTarget + '></a>').parent().parent().addClass('image-loading').css('visibility','hidden'); + + img.load(function(){ + base._origDim($(this)); + base.resizeNow(); + }); // End Load + }; + base.prevSlide(); + } + + }; + + + /* Get Original Dimensions + ----------------------------*/ + base._origDim = function(targetSlide){ + targetSlide.data('origWidth', targetSlide.width()).data('origHeight', targetSlide.height()); + }; + + + /* After Slide Animation + ----------------------------*/ + base.afterAnimation = function(){ + + // If hybrid mode is on swap back to higher image quality + if (base.options.performance == 1){ + base.$el.removeClass('speed').addClass('quality'); + } + + // Update previous slide + if (vars.update_images){ + vars.current_slide - 1 < 0 ? setPrev = base.options.slides.length - 1 : setPrev = vars.current_slide-1; + vars.update_images = false; + $('.prevslide').removeClass('prevslide'); + $(base.el+' li:eq('+setPrev+')').addClass('prevslide'); + } + + vars.in_animation = false; + + // Resume slideshow + if (!vars.is_paused && base.options.slideshow){ + vars.slideshow_interval = setInterval(base.nextSlide, base.options.slide_interval); + if (base.options.stop_loop && vars.current_slide == base.options.slides.length - 1 ) base.playToggle(); + } + + // Call theme function for after slide transition + if (typeof theme != 'undefined' && typeof theme.afterAnimation == "function" ) theme.afterAnimation(); + + return false; + + }; + + base.getField = function(field){ + return base.options.slides[vars.current_slide][field]; + }; + + // Make it go! + base.init(); + }; + + + /* Global Variables + ----------------------------*/ + $.supersized.vars = { + + // Elements + thumb_tray : '#thumb-tray', // Thumbnail tray + thumb_list : '#thumb-list', // Thumbnail list + slide_list : '#slide-list', // Slide link list + + // Internal variables + current_slide : 0, // Current slide number + in_animation : false, // Prevents animations from stacking + is_paused : false, // Tracks paused on/off + hover_pause : false, // If slideshow is paused from hover + slideshow_interval : false, // Stores slideshow timer + update_images : false, // Trigger to update images after slide jump + options : {} // Stores assembled options list + + }; + + + /* Default Options + ----------------------------*/ + $.supersized.defaultOptions = { + + // Functionality + slideshow : 1, // Slideshow on/off + autoplay : 1, // Slideshow starts playing automatically + start_slide : 1, // Start slide (0 is random) + stop_loop : 0, // Stops slideshow on last slide + random : 0, // Randomize slide order (Ignores start slide) + slide_interval : 5000, // Length between transitions + transition : 1, // 0-None, 1-Fade, 2-Slide Top, 3-Slide Right, 4-Slide Bottom, 5-Slide Left, 6-Carousel Right, 7-Carousel Left + transition_speed : 750, // Speed of transition + new_window : 1, // Image links open in new window/tab + pause_hover : 0, // Pause slideshow on hover + keyboard_nav : 1, // Keyboard navigation on/off + performance : 1, // 0-Normal, 1-Hybrid speed/quality, 2-Optimizes image quality, 3-Optimizes transition speed // (Only works for Firefox/IE, not Webkit) + image_protect : 1, // Disables image dragging and right click with Javascript + + // Size & Position + fit_always : 0, // Image will never exceed browser width or height (Ignores min. dimensions) + fit_landscape : 0, // Landscape images will not exceed browser width + fit_portrait : 1, // Portrait images will not exceed browser height + min_width : 0, // Min width allowed (in pixels) + min_height : 0, // Min height allowed (in pixels) + horizontal_center : 1, // Horizontally center background + vertical_center : 1, // Vertically center background + + + // Components + slide_links : 1, // Individual links for each slide (Options: false, 'num', 'name', 'blank') + thumb_links : 1, // Individual thumb links for each slide + thumbnail_navigation : 0 // Thumbnail navigation + + }; + + $.fn.supersized = function(options){ + return this.each(function(){ + (new $.supersized(options)); + }); + }; + +})(jQuery); + diff --git a/apps/gallery/js/supersized.3.2.7.min.js b/apps/gallery/js/supersized.3.2.7.min.js new file mode 100644 index 00000000000..b9cea9cee1c --- /dev/null +++ b/apps/gallery/js/supersized.3.2.7.min.js @@ -0,0 +1,13 @@ +/* + + Supersized - Fullscreen Slideshow jQuery Plugin + Version : 3.2.7 + Site : www.buildinternet.com/project/supersized + + Author : Sam Dunn + Company : One Mighty Roar (www.onemightyroar.com) + License : MIT License / GPL License + +*/ + +(function(a){a(document).ready(function(){a("body").append('<div id="supersized-loader"></div><ul id="supersized"></ul>')});a.supersized=function(b){var c="#supersized",d=this;d.$el=a(c);d.el=c;vars=a.supersized.vars;d.$el.data("supersized",d);api=d.$el.data("supersized");d.init=function(){a.supersized.vars=a.extend(a.supersized.vars,a.supersized.themeVars);a.supersized.vars.options=a.extend({},a.supersized.defaultOptions,a.supersized.themeOptions,b);d.options=a.supersized.vars.options;d._build()};d._build=function(){var g=0,e="",j="",h,f="",i;while(g<=d.options.slides.length-1){switch(d.options.slide_links){case"num":h=g;break;case"name":h=d.options.slides[g].title;break;case"blank":h="";break}e=e+'<li class="slide-'+g+'"></li>';if(g==d.options.start_slide-1){if(d.options.slide_links){j=j+'<li class="slide-link-'+g+' current-slide"><a>'+h+"</a></li>"}if(d.options.thumb_links){d.options.slides[g].thumb?i=d.options.slides[g].thumb:i=d.options.slides[g].image;f=f+'<li class="thumb'+g+' current-thumb"><img src="'+i+'"/></li>'}}else{if(d.options.slide_links){j=j+'<li class="slide-link-'+g+'" ><a>'+h+"</a></li>"}if(d.options.thumb_links){d.options.slides[g].thumb?i=d.options.slides[g].thumb:i=d.options.slides[g].image;f=f+'<li class="thumb'+g+'"><img src="'+i+'"/></li>'}}g++}if(d.options.slide_links){a(vars.slide_list).html(j)}if(d.options.thumb_links&&vars.thumb_tray.length){a(vars.thumb_tray).append('<ul id="'+vars.thumb_list.replace("#","")+'">'+f+"</ul>")}a(d.el).append(e);if(d.options.thumbnail_navigation){vars.current_slide-1<0?prevThumb=d.options.slides.length-1:prevThumb=vars.current_slide-1;a(vars.prev_thumb).show().html(a("<img/>").attr("src",d.options.slides[prevThumb].image));vars.current_slide==d.options.slides.length-1?nextThumb=0:nextThumb=vars.current_slide+1;a(vars.next_thumb).show().html(a("<img/>").attr("src",d.options.slides[nextThumb].image))}d._start()};d._start=function(){if(d.options.start_slide){vars.current_slide=d.options.start_slide-1}else{vars.current_slide=Math.floor(Math.random()*d.options.slides.length)}var o=d.options.new_window?' target="_blank"':"";if(d.options.performance==3){d.$el.addClass("speed")}else{if((d.options.performance==1)||(d.options.performance==2)){d.$el.addClass("quality")}}if(d.options.random){arr=d.options.slides;for(var h,m,k=arr.length;k;h=parseInt(Math.random()*k),m=arr[--k],arr[k]=arr[h],arr[h]=m){}d.options.slides=arr}if(d.options.slides.length>1){if(d.options.slides.length>2){vars.current_slide-1<0?loadPrev=d.options.slides.length-1:loadPrev=vars.current_slide-1;var g=(d.options.slides[loadPrev].url)?"href='"+d.options.slides[loadPrev].url+"'":"";var q=a('<img src="'+d.options.slides[loadPrev].image+'"/>');var n=d.el+" li:eq("+loadPrev+")";q.appendTo(n).wrap("<a "+g+o+"></a>").parent().parent().addClass("image-loading prevslide");q.load(function(){a(this).data("origWidth",a(this).width()).data("origHeight",a(this).height());d.resizeNow()})}}else{d.options.slideshow=0}g=(api.getField("url"))?"href='"+api.getField("url")+"'":"";var l=a('<img src="'+api.getField("image")+'"/>');var f=d.el+" li:eq("+vars.current_slide+")";l.appendTo(f).wrap("<a "+g+o+"></a>").parent().parent().addClass("image-loading activeslide");l.load(function(){d._origDim(a(this));d.resizeNow();d.launch();if(typeof theme!="undefined"&&typeof theme._init=="function"){theme._init()}});if(d.options.slides.length>1){vars.current_slide==d.options.slides.length-1?loadNext=0:loadNext=vars.current_slide+1;g=(d.options.slides[loadNext].url)?"href='"+d.options.slides[loadNext].url+"'":"";var e=a('<img src="'+d.options.slides[loadNext].image+'"/>');var p=d.el+" li:eq("+loadNext+")";e.appendTo(p).wrap("<a "+g+o+"></a>").parent().parent().addClass("image-loading");e.load(function(){a(this).data("origWidth",a(this).width()).data("origHeight",a(this).height());d.resizeNow()})}d.$el.css("visibility","hidden");a(".load-item").hide()};d.launch=function(){d.$el.css("visibility","visible");a("#supersized-loader").remove();if(typeof theme!="undefined"&&typeof theme.beforeAnimation=="function"){theme.beforeAnimation("next")}a(".load-item").show();if(d.options.keyboard_nav){a(document.documentElement).keyup(function(e){if(vars.in_animation){return false}if((e.keyCode==37)||(e.keyCode==40)){clearInterval(vars.slideshow_interval);d.prevSlide()}else{if((e.keyCode==39)||(e.keyCode==38)){clearInterval(vars.slideshow_interval);d.nextSlide()}else{if(e.keyCode==32&&!vars.hover_pause){clearInterval(vars.slideshow_interval);d.playToggle()}}}})}if(d.options.slideshow&&d.options.pause_hover){a(d.el).hover(function(){if(vars.in_animation){return false}vars.hover_pause=true;if(!vars.is_paused){vars.hover_pause="resume";d.playToggle()}},function(){if(vars.hover_pause=="resume"){d.playToggle();vars.hover_pause=false}})}if(d.options.slide_links){a(vars.slide_list+"> li").click(function(){index=a(vars.slide_list+"> li").index(this);targetSlide=index+1;d.goTo(targetSlide);return false})}if(d.options.thumb_links){a(vars.thumb_list+"> li").click(function(){index=a(vars.thumb_list+"> li").index(this);targetSlide=index+1;api.goTo(targetSlide);return false})}if(d.options.slideshow&&d.options.slides.length>1){if(d.options.autoplay&&d.options.slides.length>1){vars.slideshow_interval=setInterval(d.nextSlide,d.options.slide_interval)}else{vars.is_paused=true}a(".load-item img").bind("contextmenu mousedown",function(){return false})}a(window).resize(function(){d.resizeNow()})};d.resizeNow=function(){return d.$el.each(function(){a("img",d.el).each(function(){thisSlide=a(this);var f=(thisSlide.data("origHeight")/thisSlide.data("origWidth")).toFixed(2);var e=d.$el.width(),h=d.$el.height(),i;if(d.options.fit_always){if((h/e)>f){g()}else{j()}}else{if((h<=d.options.min_height)&&(e<=d.options.min_width)){if((h/e)>f){d.options.fit_landscape&&f<1?g(true):j(true)}else{d.options.fit_portrait&&f>=1?j(true):g(true)}}else{if(e<=d.options.min_width){if((h/e)>f){d.options.fit_landscape&&f<1?g(true):j()}else{d.options.fit_portrait&&f>=1?j():g(true)}}else{if(h<=d.options.min_height){if((h/e)>f){d.options.fit_landscape&&f<1?g():j(true)}else{d.options.fit_portrait&&f>=1?j(true):g()}}else{if((h/e)>f){d.options.fit_landscape&&f<1?g():j()}else{d.options.fit_portrait&&f>=1?j():g()}}}}}function g(k){if(k){if(thisSlide.width()<e||thisSlide.width()<d.options.min_width){if(thisSlide.width()*f>=d.options.min_height){thisSlide.width(d.options.min_width);thisSlide.height(thisSlide.width()*f)}else{j()}}}else{if(d.options.min_height>=h&&!d.options.fit_landscape){if(e*f>=d.options.min_height||(e*f>=d.options.min_height&&f<=1)){thisSlide.width(e);thisSlide.height(e*f)}else{if(f>1){thisSlide.height(d.options.min_height);thisSlide.width(thisSlide.height()/f)}else{if(thisSlide.width()<e){thisSlide.width(e);thisSlide.height(thisSlide.width()*f)}}}}else{thisSlide.width(e);thisSlide.height(e*f)}}}function j(k){if(k){if(thisSlide.height()<h){if(thisSlide.height()/f>=d.options.min_width){thisSlide.height(d.options.min_height);thisSlide.width(thisSlide.height()/f)}else{g(true)}}}else{if(d.options.min_width>=e){if(h/f>=d.options.min_width||f>1){thisSlide.height(h);thisSlide.width(h/f)}else{if(f<=1){thisSlide.width(d.options.min_width);thisSlide.height(thisSlide.width()*f)}}}else{thisSlide.height(h);thisSlide.width(h/f)}}}if(thisSlide.parents("li").hasClass("image-loading")){a(".image-loading").removeClass("image-loading")}if(d.options.horizontal_center){a(this).css("left",(e-a(this).width())/2)}if(d.options.vertical_center){a(this).css("top",(h-a(this).height())/2)}});if(d.options.image_protect){a("img",d.el).bind("contextmenu mousedown",function(){return false})}return false})};d.nextSlide=function(){if(vars.in_animation||!api.options.slideshow){return false}else{vars.in_animation=true}clearInterval(vars.slideshow_interval);var h=d.options.slides,e=d.$el.find(".activeslide");a(".prevslide").removeClass("prevslide");e.removeClass("activeslide").addClass("prevslide");vars.current_slide+1==d.options.slides.length?vars.current_slide=0:vars.current_slide++;var g=a(d.el+" li:eq("+vars.current_slide+")"),i=d.$el.find(".prevslide");if(d.options.performance==1){d.$el.removeClass("quality").addClass("speed")}loadSlide=false;vars.current_slide==d.options.slides.length-1?loadSlide=0:loadSlide=vars.current_slide+1;var k=d.el+" li:eq("+loadSlide+")";if(!a(k).html()){var j=d.options.new_window?' target="_blank"':"";imageLink=(d.options.slides[loadSlide].url)?"href='"+d.options.slides[loadSlide].url+"'":"";var f=a('<img src="'+d.options.slides[loadSlide].image+'"/>');f.appendTo(k).wrap("<a "+imageLink+j+"></a>").parent().parent().addClass("image-loading").css("visibility","hidden");f.load(function(){d._origDim(a(this));d.resizeNow()})}if(d.options.thumbnail_navigation==1){vars.current_slide-1<0?prevThumb=d.options.slides.length-1:prevThumb=vars.current_slide-1;a(vars.prev_thumb).html(a("<img/>").attr("src",d.options.slides[prevThumb].image));nextThumb=loadSlide;a(vars.next_thumb).html(a("<img/>").attr("src",d.options.slides[nextThumb].image))}if(typeof theme!="undefined"&&typeof theme.beforeAnimation=="function"){theme.beforeAnimation("next")}if(d.options.slide_links){a(".current-slide").removeClass("current-slide");a(vars.slide_list+"> li").eq(vars.current_slide).addClass("current-slide")}g.css("visibility","hidden").addClass("activeslide");switch(d.options.transition){case 0:case"none":g.css("visibility","visible");vars.in_animation=false;d.afterAnimation();break;case 1:case"fade":g.animate({opacity:0},0).css("visibility","visible").animate({opacity:1,avoidTransforms:false},d.options.transition_speed,function(){d.afterAnimation()});break;case 2:case"slideTop":g.animate({top:-d.$el.height()},0).css("visibility","visible").animate({top:0,avoidTransforms:false},d.options.transition_speed,function(){d.afterAnimation()});break;case 3:case"slideRight":g.animate({left:d.$el.width()},0).css("visibility","visible").animate({left:0,avoidTransforms:false},d.options.transition_speed,function(){d.afterAnimation()});break;case 4:case"slideBottom":g.animate({top:d.$el.height()},0).css("visibility","visible").animate({top:0,avoidTransforms:false},d.options.transition_speed,function(){d.afterAnimation()});break;case 5:case"slideLeft":g.animate({left:-d.$el.width()},0).css("visibility","visible").animate({left:0,avoidTransforms:false},d.options.transition_speed,function(){d.afterAnimation()});break;case 6:case"carouselRight":g.animate({left:d.$el.width()},0).css("visibility","visible").animate({left:0,avoidTransforms:false},d.options.transition_speed,function(){d.afterAnimation()});e.animate({left:-d.$el.width(),avoidTransforms:false},d.options.transition_speed);break;case 7:case"carouselLeft":g.animate({left:-d.$el.width()},0).css("visibility","visible").animate({left:0,avoidTransforms:false},d.options.transition_speed,function(){d.afterAnimation()});e.animate({left:d.$el.width(),avoidTransforms:false},d.options.transition_speed);break}return false};d.prevSlide=function(){if(vars.in_animation||!api.options.slideshow){return false}else{vars.in_animation=true}clearInterval(vars.slideshow_interval);var h=d.options.slides,e=d.$el.find(".activeslide");a(".prevslide").removeClass("prevslide");e.removeClass("activeslide").addClass("prevslide");vars.current_slide==0?vars.current_slide=d.options.slides.length-1:vars.current_slide--;var g=a(d.el+" li:eq("+vars.current_slide+")"),i=d.$el.find(".prevslide");if(d.options.performance==1){d.$el.removeClass("quality").addClass("speed")}loadSlide=vars.current_slide;var k=d.el+" li:eq("+loadSlide+")";if(!a(k).html()){var j=d.options.new_window?' target="_blank"':"";imageLink=(d.options.slides[loadSlide].url)?"href='"+d.options.slides[loadSlide].url+"'":"";var f=a('<img src="'+d.options.slides[loadSlide].image+'"/>');f.appendTo(k).wrap("<a "+imageLink+j+"></a>").parent().parent().addClass("image-loading").css("visibility","hidden");f.load(function(){d._origDim(a(this));d.resizeNow()})}if(d.options.thumbnail_navigation==1){loadSlide==0?prevThumb=d.options.slides.length-1:prevThumb=loadSlide-1;a(vars.prev_thumb).html(a("<img/>").attr("src",d.options.slides[prevThumb].image));vars.current_slide==d.options.slides.length-1?nextThumb=0:nextThumb=vars.current_slide+1;a(vars.next_thumb).html(a("<img/>").attr("src",d.options.slides[nextThumb].image))}if(typeof theme!="undefined"&&typeof theme.beforeAnimation=="function"){theme.beforeAnimation("prev")}if(d.options.slide_links){a(".current-slide").removeClass("current-slide");a(vars.slide_list+"> li").eq(vars.current_slide).addClass("current-slide")}g.css("visibility","hidden").addClass("activeslide");switch(d.options.transition){case 0:case"none":g.css("visibility","visible");vars.in_animation=false;d.afterAnimation();break;case 1:case"fade":g.animate({opacity:0},0).css("visibility","visible").animate({opacity:1,avoidTransforms:false},d.options.transition_speed,function(){d.afterAnimation()});break;case 2:case"slideTop":g.animate({top:d.$el.height()},0).css("visibility","visible").animate({top:0,avoidTransforms:false},d.options.transition_speed,function(){d.afterAnimation()});break;case 3:case"slideRight":g.animate({left:-d.$el.width()},0).css("visibility","visible").animate({left:0,avoidTransforms:false},d.options.transition_speed,function(){d.afterAnimation()});break;case 4:case"slideBottom":g.animate({top:-d.$el.height()},0).css("visibility","visible").animate({top:0,avoidTransforms:false},d.options.transition_speed,function(){d.afterAnimation()});break;case 5:case"slideLeft":g.animate({left:d.$el.width()},0).css("visibility","visible").animate({left:0,avoidTransforms:false},d.options.transition_speed,function(){d.afterAnimation()});break;case 6:case"carouselRight":g.animate({left:-d.$el.width()},0).css("visibility","visible").animate({left:0,avoidTransforms:false},d.options.transition_speed,function(){d.afterAnimation()});e.animate({left:0},0).animate({left:d.$el.width(),avoidTransforms:false},d.options.transition_speed);break;case 7:case"carouselLeft":g.animate({left:d.$el.width()},0).css("visibility","visible").animate({left:0,avoidTransforms:false},d.options.transition_speed,function(){d.afterAnimation()});e.animate({left:0},0).animate({left:-d.$el.width(),avoidTransforms:false},d.options.transition_speed);break}return false};d.playToggle=function(){if(vars.in_animation||!api.options.slideshow){return false}if(vars.is_paused){vars.is_paused=false;if(typeof theme!="undefined"&&typeof theme.playToggle=="function"){theme.playToggle("play")}vars.slideshow_interval=setInterval(d.nextSlide,d.options.slide_interval)}else{vars.is_paused=true;if(typeof theme!="undefined"&&typeof theme.playToggle=="function"){theme.playToggle("pause")}clearInterval(vars.slideshow_interval)}return false};d.goTo=function(f){if(vars.in_animation||!api.options.slideshow){return false}var e=d.options.slides.length;if(f<0){f=e}else{if(f>e){f=1}}f=e-f+1;clearInterval(vars.slideshow_interval);if(typeof theme!="undefined"&&typeof theme.goTo=="function"){theme.goTo()}if(vars.current_slide==e-f){if(!(vars.is_paused)){vars.slideshow_interval=setInterval(d.nextSlide,d.options.slide_interval)}return false}if(e-f>vars.current_slide){vars.current_slide=e-f-1;vars.update_images="next";d._placeSlide(vars.update_images)}else{if(e-f<vars.current_slide){vars.current_slide=e-f+1;vars.update_images="prev";d._placeSlide(vars.update_images)}}if(d.options.slide_links){a(vars.slide_list+"> .current-slide").removeClass("current-slide");a(vars.slide_list+"> li").eq((e-f)).addClass("current-slide")}if(d.options.thumb_links){a(vars.thumb_list+"> .current-thumb").removeClass("current-thumb");a(vars.thumb_list+"> li").eq((e-f)).addClass("current-thumb")}};d._placeSlide=function(e){var h=d.options.new_window?' target="_blank"':"";loadSlide=false;if(e=="next"){vars.current_slide==d.options.slides.length-1?loadSlide=0:loadSlide=vars.current_slide+1;var g=d.el+" li:eq("+loadSlide+")";if(!a(g).html()){var h=d.options.new_window?' target="_blank"':"";imageLink=(d.options.slides[loadSlide].url)?"href='"+d.options.slides[loadSlide].url+"'":"";var f=a('<img src="'+d.options.slides[loadSlide].image+'"/>');f.appendTo(g).wrap("<a "+imageLink+h+"></a>").parent().parent().addClass("image-loading").css("visibility","hidden");f.load(function(){d._origDim(a(this));d.resizeNow()})}d.nextSlide()}else{if(e=="prev"){vars.current_slide-1<0?loadSlide=d.options.slides.length-1:loadSlide=vars.current_slide-1;var g=d.el+" li:eq("+loadSlide+")";if(!a(g).html()){var h=d.options.new_window?' target="_blank"':"";imageLink=(d.options.slides[loadSlide].url)?"href='"+d.options.slides[loadSlide].url+"'":"";var f=a('<img src="'+d.options.slides[loadSlide].image+'"/>');f.appendTo(g).wrap("<a "+imageLink+h+"></a>").parent().parent().addClass("image-loading").css("visibility","hidden");f.load(function(){d._origDim(a(this));d.resizeNow()})}d.prevSlide()}}};d._origDim=function(e){e.data("origWidth",e.width()).data("origHeight",e.height())};d.afterAnimation=function(){if(d.options.performance==1){d.$el.removeClass("speed").addClass("quality")}if(vars.update_images){vars.current_slide-1<0?setPrev=d.options.slides.length-1:setPrev=vars.current_slide-1;vars.update_images=false;a(".prevslide").removeClass("prevslide");a(d.el+" li:eq("+setPrev+")").addClass("prevslide")}vars.in_animation=false;if(!vars.is_paused&&d.options.slideshow){vars.slideshow_interval=setInterval(d.nextSlide,d.options.slide_interval);if(d.options.stop_loop&&vars.current_slide==d.options.slides.length-1){d.playToggle()}}if(typeof theme!="undefined"&&typeof theme.afterAnimation=="function"){theme.afterAnimation()}return false};d.getField=function(e){return d.options.slides[vars.current_slide][e]};d.init()};a.supersized.vars={thumb_tray:"#thumb-tray",thumb_list:"#thumb-list",slide_list:"#slide-list",current_slide:0,in_animation:false,is_paused:false,hover_pause:false,slideshow_interval:false,update_images:false,options:{}};a.supersized.defaultOptions={slideshow:1,autoplay:1,start_slide:1,stop_loop:0,random:0,slide_interval:5000,transition:1,transition_speed:750,new_window:1,pause_hover:0,keyboard_nav:1,performance:1,image_protect:1,fit_always:0,fit_landscape:0,fit_portrait:1,min_width:0,min_height:0,horizontal_center:1,vertical_center:1,slide_links:1,thumb_links:1,thumbnail_navigation:0};a.fn.supersized=function(b){return this.each(function(){(new a.supersized(b))})}})(jQuery);
\ No newline at end of file diff --git a/apps/gallery/js/supersized.shutter.js b/apps/gallery/js/supersized.shutter.js new file mode 100644 index 00000000000..cc3025a94a3 --- /dev/null +++ b/apps/gallery/js/supersized.shutter.js @@ -0,0 +1,337 @@ +/* + + Supersized - Fullscreen Slideshow jQuery Plugin + Version : 3.2.7 + Theme : Shutter 1.1 + + Site : www.buildinternet.com/project/supersized + Author : Sam Dunn + Company : One Mighty Roar (www.onemightyroar.com) + License : MIT License / GPL License + +*/ + +(function($){ + + theme = { + + + /* Initial Placement + ----------------------------*/ + _init : function(){ + + // Center Slide Links + if (api.options.slide_links) $(vars.slide_list).css('margin-left', -$(vars.slide_list).width()/2); + + // Start progressbar if autoplay enabled + if (api.options.autoplay){ + if (api.options.progress_bar) theme.progressBar(); + }else{ + if ($(vars.play_button).attr('src')) $(vars.play_button).attr("src", vars.image_path + "play.png"); // If pause play button is image, swap src + if (api.options.progress_bar) $(vars.progress_bar).stop().animate({left : -$(window).width()}, 0 ); // Place progress bar + } + + + /* Thumbnail Tray + ----------------------------*/ + // Hide tray off screen + $(vars.thumb_tray).animate({bottom : -$(vars.thumb_tray).height()}, 0 ); + + // Thumbnail Tray Toggle + $(vars.tray_button).toggle(function(){ + $(vars.thumb_tray).stop().animate({bottom : 0, avoidTransforms : true}, 300 ); + if ($(vars.tray_arrow).attr('src')) $(vars.tray_arrow).attr("src", vars.image_path + "button-tray-down.png"); + return false; + }, function() { + $(vars.thumb_tray).stop().animate({bottom : -$(vars.thumb_tray).height(), avoidTransforms : true}, 300 ); + if ($(vars.tray_arrow).attr('src')) $(vars.tray_arrow).attr("src", vars.image_path + "button-tray-up.png"); + return false; + }); + + // Make thumb tray proper size + $(vars.thumb_list).width($('> li', vars.thumb_list).length * $('> li', vars.thumb_list).outerWidth(true)); //Adjust to true width of thumb markers + + // Display total slides + if ($(vars.slide_total).length){ + $(vars.slide_total).html(api.options.slides.length); + } + + + /* Thumbnail Tray Navigation + ----------------------------*/ + if (api.options.thumb_links){ + //Hide thumb arrows if not needed + if ($(vars.thumb_list).width() <= $(vars.thumb_tray).width()){ + $(vars.thumb_back +','+vars.thumb_forward).fadeOut(0); + } + + // Thumb Intervals + vars.thumb_interval = Math.floor($(vars.thumb_tray).width() / $('> li', vars.thumb_list).outerWidth(true)) * $('> li', vars.thumb_list).outerWidth(true); + vars.thumb_page = 0; + + // Cycle thumbs forward + $(vars.thumb_forward).click(function(){ + if (vars.thumb_page - vars.thumb_interval <= -$(vars.thumb_list).width()){ + vars.thumb_page = 0; + $(vars.thumb_list).stop().animate({'left': vars.thumb_page}, {duration:500, easing:'easeOutExpo'}); + }else{ + vars.thumb_page = vars.thumb_page - vars.thumb_interval; + $(vars.thumb_list).stop().animate({'left': vars.thumb_page}, {duration:500, easing:'easeOutExpo'}); + } + }); + + // Cycle thumbs backwards + $(vars.thumb_back).click(function(){ + if (vars.thumb_page + vars.thumb_interval > 0){ + vars.thumb_page = Math.floor($(vars.thumb_list).width() / vars.thumb_interval) * -vars.thumb_interval; + if ($(vars.thumb_list).width() <= -vars.thumb_page) vars.thumb_page = vars.thumb_page + vars.thumb_interval; + $(vars.thumb_list).stop().animate({'left': vars.thumb_page}, {duration:500, easing:'easeOutExpo'}); + }else{ + vars.thumb_page = vars.thumb_page + vars.thumb_interval; + $(vars.thumb_list).stop().animate({'left': vars.thumb_page}, {duration:500, easing:'easeOutExpo'}); + } + }); + + } + + + /* Navigation Items + ----------------------------*/ + $(vars.next_slide).click(function() { + api.nextSlide(); + }); + + $(vars.prev_slide).click(function() { + api.prevSlide(); + }); + + // Full Opacity on Hover + if(jQuery.support.opacity){ + $(vars.prev_slide +','+vars.next_slide).mouseover(function() { + $(this).stop().animate({opacity:1},100); + }).mouseout(function(){ + $(this).stop().animate({opacity:0.6},100); + }); + } + + if (api.options.thumbnail_navigation){ + // Next thumbnail clicked + $(vars.next_thumb).click(function() { + api.nextSlide(); + }); + // Previous thumbnail clicked + $(vars.prev_thumb).click(function() { + api.prevSlide(); + }); + } + + $(vars.play_button).click(function() { + api.playToggle(); + }); + + + /* Thumbnail Mouse Scrub + ----------------------------*/ + if (api.options.mouse_scrub){ + $(vars.thumb_tray).mousemove(function(e) { + var containerWidth = $(vars.thumb_tray).width(), + listWidth = $(vars.thumb_list).width(); + if (listWidth > containerWidth){ + var mousePos = 1, + diff = e.pageX - mousePos; + if (diff > 10 || diff < -10) { + mousePos = e.pageX; + newX = (containerWidth - listWidth) * (e.pageX/containerWidth); + diff = parseInt(Math.abs(parseInt($(vars.thumb_list).css('left'))-newX )).toFixed(0); + $(vars.thumb_list).stop().animate({'left':newX}, {duration:diff*3, easing:'easeOutExpo'}); + } + } + }); + } + + + /* Window Resize + ----------------------------*/ + $(window).resize(function(){ + + // Delay progress bar on resize + if (api.options.progress_bar && !vars.in_animation){ + if (vars.slideshow_interval) clearInterval(vars.slideshow_interval); + if (api.options.slides.length - 1 > 0) clearInterval(vars.slideshow_interval); + + $(vars.progress_bar).stop().animate({left : -$(window).width()}, 0 ); + + if (!vars.progressDelay && api.options.slideshow){ + // Delay slideshow from resuming so Chrome can refocus images + vars.progressDelay = setTimeout(function() { + if (!vars.is_paused){ + theme.progressBar(); + vars.slideshow_interval = setInterval(api.nextSlide, api.options.slide_interval); + } + vars.progressDelay = false; + }, 1000); + } + } + + // Thumb Links + if (api.options.thumb_links && vars.thumb_tray.length){ + // Update Thumb Interval & Page + vars.thumb_page = 0; + vars.thumb_interval = Math.floor($(vars.thumb_tray).width() / $('> li', vars.thumb_list).outerWidth(true)) * $('> li', vars.thumb_list).outerWidth(true); + + // Adjust thumbnail markers + if ($(vars.thumb_list).width() > $(vars.thumb_tray).width()){ + $(vars.thumb_back +','+vars.thumb_forward).fadeIn('fast'); + $(vars.thumb_list).stop().animate({'left':0}, 200); + }else{ + $(vars.thumb_back +','+vars.thumb_forward).fadeOut('fast'); + } + + } + }); + + + }, + + + /* Go To Slide + ----------------------------*/ + goTo : function(){ + if (api.options.progress_bar && !vars.is_paused){ + $(vars.progress_bar).stop().animate({left : -$(window).width()}, 0 ); + theme.progressBar(); + } + }, + + /* Play & Pause Toggle + ----------------------------*/ + playToggle : function(state){ + + if (state =='play'){ + // If image, swap to pause + if ($(vars.play_button).attr('src')) $(vars.play_button).attr("src", vars.image_path + "pause.png"); + if (api.options.progress_bar && !vars.is_paused) theme.progressBar(); + }else if (state == 'pause'){ + // If image, swap to play + if ($(vars.play_button).attr('src')) $(vars.play_button).attr("src", vars.image_path + "play.png"); + if (api.options.progress_bar && vars.is_paused)$(vars.progress_bar).stop().animate({left : -$(window).width()}, 0 ); + } + + }, + + + /* Before Slide Transition + ----------------------------*/ + beforeAnimation : function(direction){ + if (api.options.progress_bar && !vars.is_paused) $(vars.progress_bar).stop().animate({left : -$(window).width()}, 0 ); + + /* Update Fields + ----------------------------*/ + // Update slide caption + if ($(vars.slide_caption).length){ + (api.getField('title')) ? $(vars.slide_caption).html(api.getField('title')) : $(vars.slide_caption).html(''); + } + // Update slide number + if (vars.slide_current.length){ + $(vars.slide_current).html(vars.current_slide + 1); + } + + + // Highlight current thumbnail and adjust row position + if (api.options.thumb_links){ + + $('.current-thumb').removeClass('current-thumb'); + $('li', vars.thumb_list).eq(vars.current_slide).addClass('current-thumb'); + + // If thumb out of view + if ($(vars.thumb_list).width() > $(vars.thumb_tray).width()){ + // If next slide direction + if (direction == 'next'){ + if (vars.current_slide == 0){ + vars.thumb_page = 0; + $(vars.thumb_list).stop().animate({'left': vars.thumb_page}, {duration:500, easing:'easeOutExpo'}); + } else if ($('.current-thumb').offset().left - $(vars.thumb_tray).offset().left >= vars.thumb_interval){ + vars.thumb_page = vars.thumb_page - vars.thumb_interval; + $(vars.thumb_list).stop().animate({'left': vars.thumb_page}, {duration:500, easing:'easeOutExpo'}); + } + // If previous slide direction + }else if(direction == 'prev'){ + if (vars.current_slide == api.options.slides.length - 1){ + vars.thumb_page = Math.floor($(vars.thumb_list).width() / vars.thumb_interval) * -vars.thumb_interval; + if ($(vars.thumb_list).width() <= -vars.thumb_page) vars.thumb_page = vars.thumb_page + vars.thumb_interval; + $(vars.thumb_list).stop().animate({'left': vars.thumb_page}, {duration:500, easing:'easeOutExpo'}); + } else if ($('.current-thumb').offset().left - $(vars.thumb_tray).offset().left < 0){ + if (vars.thumb_page + vars.thumb_interval > 0) return false; + vars.thumb_page = vars.thumb_page + vars.thumb_interval; + $(vars.thumb_list).stop().animate({'left': vars.thumb_page}, {duration:500, easing:'easeOutExpo'}); + } + } + } + + + } + + }, + + + /* After Slide Transition + ----------------------------*/ + afterAnimation : function(){ + if (api.options.progress_bar && !vars.is_paused) theme.progressBar(); // Start progress bar + }, + + + /* Progress Bar + ----------------------------*/ + progressBar : function(){ + $(vars.progress_bar).stop().animate({left : -$(window).width()}, 0 ).animate({left:0}, api.options.slide_interval); + } + + + }; + + + /* Theme Specific Variables + ----------------------------*/ + $.supersized.themeVars = { + + // Internal Variables + progress_delay : false, // Delay after resize before resuming slideshow + thumb_page : false, // Thumbnail page + thumb_interval : false, // Thumbnail interval + image_path : OC.webroot+"/apps/gallery/img/supersized/", // Default image path + + // General Elements + play_button : '#pauseplay', // Play/Pause button + next_slide : '#nextslide', // Next slide button + prev_slide : '#prevslide', // Prev slide button + next_thumb : '#nextthumb', // Next slide thumb button + prev_thumb : '#prevthumb', // Prev slide thumb button + + slide_caption : '#slidecaption', // Slide caption + slide_current : '.slidenumber', // Current slide number + slide_total : '.totalslides', // Total Slides + slide_list : '#slide-list', // Slide jump list + + thumb_tray : '#thumb-tray', // Thumbnail tray + thumb_list : '#thumb-list', // Thumbnail list + thumb_forward : '#thumb-forward', // Cycles forward through thumbnail list + thumb_back : '#thumb-back', // Cycles backwards through thumbnail list + tray_arrow : '#tray-arrow', // Thumbnail tray button arrow + tray_button : '#tray-button', // Thumbnail tray button + + progress_bar : '#progress-bar' // Progress bar + + }; + + /* Theme Specific Options + ----------------------------*/ + $.supersized.themeOptions = { + + progress_bar : 1, // Timer for each slide + mouse_scrub : 0 // Thumbnails move with mouse + + }; + + +})(jQuery); diff --git a/apps/gallery/js/supersized.shutter.min.js b/apps/gallery/js/supersized.shutter.min.js new file mode 100644 index 00000000000..52ea4a3384a --- /dev/null +++ b/apps/gallery/js/supersized.shutter.min.js @@ -0,0 +1,14 @@ +/* + + Supersized - Fullscreen Slideshow jQuery Plugin + Version : 3.2.7 + Theme : Shutter 1.1 + + Site : www.buildinternet.com/project/supersized + Author : Sam Dunn + Company : One Mighty Roar (www.onemightyroar.com) + License : MIT License / GPL License + +*/ + +(function(a){theme={_init:function(){if(api.options.slide_links){a(vars.slide_list).css("margin-left",-a(vars.slide_list).width()/2)}if(api.options.autoplay){if(api.options.progress_bar){theme.progressBar()}}else{if(a(vars.play_button).attr("src")){a(vars.play_button).attr("src",vars.image_path+"play.png")}if(api.options.progress_bar){a(vars.progress_bar).stop().animate({left:-a(window).width()},0)}}a(vars.thumb_tray).animate({bottom:-a(vars.thumb_tray).height()},0);a(vars.tray_button).toggle(function(){a(vars.thumb_tray).stop().animate({bottom:0,avoidTransforms:true},300);if(a(vars.tray_arrow).attr("src")){a(vars.tray_arrow).attr("src",vars.image_path+"button-tray-down.png")}return false},function(){a(vars.thumb_tray).stop().animate({bottom:-a(vars.thumb_tray).height(),avoidTransforms:true},300);if(a(vars.tray_arrow).attr("src")){a(vars.tray_arrow).attr("src",vars.image_path+"button-tray-up.png")}return false});a(vars.thumb_list).width(a("> li",vars.thumb_list).length*a("> li",vars.thumb_list).outerWidth(true));if(a(vars.slide_total).length){a(vars.slide_total).html(api.options.slides.length)}if(api.options.thumb_links){if(a(vars.thumb_list).width()<=a(vars.thumb_tray).width()){a(vars.thumb_back+","+vars.thumb_forward).fadeOut(0)}vars.thumb_interval=Math.floor(a(vars.thumb_tray).width()/a("> li",vars.thumb_list).outerWidth(true))*a("> li",vars.thumb_list).outerWidth(true);vars.thumb_page=0;a(vars.thumb_forward).click(function(){if(vars.thumb_page-vars.thumb_interval<=-a(vars.thumb_list).width()){vars.thumb_page=0;a(vars.thumb_list).stop().animate({left:vars.thumb_page},{duration:500,easing:"easeOutExpo"})}else{vars.thumb_page=vars.thumb_page-vars.thumb_interval;a(vars.thumb_list).stop().animate({left:vars.thumb_page},{duration:500,easing:"easeOutExpo"})}});a(vars.thumb_back).click(function(){if(vars.thumb_page+vars.thumb_interval>0){vars.thumb_page=Math.floor(a(vars.thumb_list).width()/vars.thumb_interval)*-vars.thumb_interval;if(a(vars.thumb_list).width()<=-vars.thumb_page){vars.thumb_page=vars.thumb_page+vars.thumb_interval}a(vars.thumb_list).stop().animate({left:vars.thumb_page},{duration:500,easing:"easeOutExpo"})}else{vars.thumb_page=vars.thumb_page+vars.thumb_interval;a(vars.thumb_list).stop().animate({left:vars.thumb_page},{duration:500,easing:"easeOutExpo"})}})}a(vars.next_slide).click(function(){api.nextSlide()});a(vars.prev_slide).click(function(){api.prevSlide()});if(jQuery.support.opacity){a(vars.prev_slide+","+vars.next_slide).mouseover(function(){a(this).stop().animate({opacity:1},100)}).mouseout(function(){a(this).stop().animate({opacity:0.6},100)})}if(api.options.thumbnail_navigation){a(vars.next_thumb).click(function(){api.nextSlide()});a(vars.prev_thumb).click(function(){api.prevSlide()})}a(vars.play_button).click(function(){api.playToggle()});if(api.options.mouse_scrub){a(vars.thumb_tray).mousemove(function(f){var c=a(vars.thumb_tray).width(),g=a(vars.thumb_list).width();if(g>c){var b=1,d=f.pageX-b;if(d>10||d<-10){b=f.pageX;newX=(c-g)*(f.pageX/c);d=parseInt(Math.abs(parseInt(a(vars.thumb_list).css("left"))-newX)).toFixed(0);a(vars.thumb_list).stop().animate({left:newX},{duration:d*3,easing:"easeOutExpo"})}}})}a(window).resize(function(){if(api.options.progress_bar&&!vars.in_animation){if(vars.slideshow_interval){clearInterval(vars.slideshow_interval)}if(api.options.slides.length-1>0){clearInterval(vars.slideshow_interval)}a(vars.progress_bar).stop().animate({left:-a(window).width()},0);if(!vars.progressDelay&&api.options.slideshow){vars.progressDelay=setTimeout(function(){if(!vars.is_paused){theme.progressBar();vars.slideshow_interval=setInterval(api.nextSlide,api.options.slide_interval)}vars.progressDelay=false},1000)}}if(api.options.thumb_links&&vars.thumb_tray.length){vars.thumb_page=0;vars.thumb_interval=Math.floor(a(vars.thumb_tray).width()/a("> li",vars.thumb_list).outerWidth(true))*a("> li",vars.thumb_list).outerWidth(true);if(a(vars.thumb_list).width()>a(vars.thumb_tray).width()){a(vars.thumb_back+","+vars.thumb_forward).fadeIn("fast");a(vars.thumb_list).stop().animate({left:0},200)}else{a(vars.thumb_back+","+vars.thumb_forward).fadeOut("fast")}}})},goTo:function(b){if(api.options.progress_bar&&!vars.is_paused){a(vars.progress_bar).stop().animate({left:-a(window).width()},0);theme.progressBar()}},playToggle:function(b){if(b=="play"){if(a(vars.play_button).attr("src")){a(vars.play_button).attr("src",vars.image_path+"pause.png")}if(api.options.progress_bar&&!vars.is_paused){theme.progressBar()}}else{if(b=="pause"){if(a(vars.play_button).attr("src")){a(vars.play_button).attr("src",vars.image_path+"play.png")}if(api.options.progress_bar&&vars.is_paused){a(vars.progress_bar).stop().animate({left:-a(window).width()},0)}}}},beforeAnimation:function(b){if(api.options.progress_bar&&!vars.is_paused){a(vars.progress_bar).stop().animate({left:-a(window).width()},0)}if(a(vars.slide_caption).length){(api.getField("title"))?a(vars.slide_caption).html(api.getField("title")):a(vars.slide_caption).html("")}if(vars.slide_current.length){a(vars.slide_current).html(vars.current_slide+1)}if(api.options.thumb_links){a(".current-thumb").removeClass("current-thumb");a("li",vars.thumb_list).eq(vars.current_slide).addClass("current-thumb");if(a(vars.thumb_list).width()>a(vars.thumb_tray).width()){if(b=="next"){if(vars.current_slide==0){vars.thumb_page=0;a(vars.thumb_list).stop().animate({left:vars.thumb_page},{duration:500,easing:"easeOutExpo"})}else{if(a(".current-thumb").offset().left-a(vars.thumb_tray).offset().left>=vars.thumb_interval){vars.thumb_page=vars.thumb_page-vars.thumb_interval;a(vars.thumb_list).stop().animate({left:vars.thumb_page},{duration:500,easing:"easeOutExpo"})}}}else{if(b=="prev"){if(vars.current_slide==api.options.slides.length-1){vars.thumb_page=Math.floor(a(vars.thumb_list).width()/vars.thumb_interval)*-vars.thumb_interval;if(a(vars.thumb_list).width()<=-vars.thumb_page){vars.thumb_page=vars.thumb_page+vars.thumb_interval}a(vars.thumb_list).stop().animate({left:vars.thumb_page},{duration:500,easing:"easeOutExpo"})}else{if(a(".current-thumb").offset().left-a(vars.thumb_tray).offset().left<0){if(vars.thumb_page+vars.thumb_interval>0){return false}vars.thumb_page=vars.thumb_page+vars.thumb_interval;a(vars.thumb_list).stop().animate({left:vars.thumb_page},{duration:500,easing:"easeOutExpo"})}}}}}}},afterAnimation:function(){if(api.options.progress_bar&&!vars.is_paused){theme.progressBar()}},progressBar:function(){a(vars.progress_bar).stop().animate({left:-a(window).width()},0).animate({left:0},api.options.slide_interval)}};a.supersized.themeVars={progress_delay:false,thumb_page:false,thumb_interval:false,image_path:OC.webroot+"/apps/gallery/img/supersized/",play_button:"#pauseplay",next_slide:"#nextslide",prev_slide:"#prevslide",next_thumb:"#nextthumb",prev_thumb:"#prevthumb",slide_caption:"#slidecaption",slide_current:".slidenumber",slide_total:".totalslides",slide_list:"#slide-list",thumb_tray:"#thumb-tray",thumb_list:"#thumb-list",thumb_forward:"#thumb-forward",thumb_back:"#thumb-back",tray_arrow:"#tray-arrow",tray_button:"#tray-button",progress_bar:"#progress-bar"};a.supersized.themeOptions={progress_bar:1,mouse_scrub:0}})(jQuery); diff --git a/apps/gallery/lib/album.php b/apps/gallery/lib/album.php index 39d6d3aded1..701949d4d80 100644 --- a/apps/gallery/lib/album.php +++ b/apps/gallery/lib/album.php @@ -58,7 +58,7 @@ class OC_Gallery_Album { return $stmt->execute($args); } - public static function removeByName($owner, $name) { self::remove($ownmer, $name); } + public static function removeByName($owner, $name) { self::remove($owner, $name); } public static function removeByPath($owner, $path) { self::remove($owner, null, $path); } public static function removeByParentPath($owner, $parent) { self::remove($owner, null, null, $parent); } diff --git a/apps/gallery/lib/hooks_handlers.php b/apps/gallery/lib/hooks_handlers.php index 093979834da..3bafdb5cf4d 100644 --- a/apps/gallery/lib/hooks_handlers.php +++ b/apps/gallery/lib/hooks_handlers.php @@ -38,5 +38,3 @@ class OC_Gallery_Hooks_Handlers { //TODO: implement this } } - -?> diff --git a/apps/gallery/lib/images_utils.php b/apps/gallery/lib/images_utils.php index ac3a383c977..f5e37cf1dee 100644 --- a/apps/gallery/lib/images_utils.php +++ b/apps/gallery/lib/images_utils.php @@ -60,5 +60,3 @@ function CroppedThumbnail($imgSrc,$thumbnail_width,$thumbnail_height, $tgtImg, $ imagedestroy($process); imagedestroy($myImage); } - -?> diff --git a/apps/gallery/lib/managers.php b/apps/gallery/lib/managers.php index 17eb741a660..575d962dbe3 100644 --- a/apps/gallery/lib/managers.php +++ b/apps/gallery/lib/managers.php @@ -2,7 +2,7 @@ namespace OC\Pictures; -class DatabaseManager { +class DatabaseManager { private static $instance = null; protected $cache = array(); const TAG = 'DatabaseManager'; @@ -25,6 +25,15 @@ class DatabaseManager { } } + public function setFileData($path, $width, $height) { + $stmt = \OCP\DB::prepare('INSERT INTO *PREFIX*pictures_images_cache (uid_owner, path, width, height) VALUES (?, ?, ?, ?)'); + $stmt->execute(array(\OCP\USER::getUser(), $path, $width, $height)); + $ret = array('path' => $path, 'width' => $width, 'height' => $height); + $dir = dirname($path); + $this->cache[$dir][$path] = $ret; + return $ret; + } + public function getFileData($path) { $gallery_path = \OCP\Config::getSystemValue( 'datadirectory' ).'/'.\OC_User::getUser().'/gallery'; $path = $gallery_path.$path; @@ -39,9 +48,7 @@ class DatabaseManager { if (!$image->loadFromFile($path)) { return false; } - $stmt = \OCP\DB::prepare('INSERT INTO *PREFIX*pictures_images_cache (uid_owner, path, width, height) VALUES (?, ?, ?, ?)'); - $stmt->execute(array(\OCP\USER::getUser(), $path, $image->width(), $image->height())); - $ret = array('path' => $path, 'width' => $image->width(), 'height' => $image->height()); + $ret = $this->setFileData($path, $image->width(), $image->height()); unset($image); $this->cache[$dir][$path] = $ret; return $ret; @@ -54,6 +61,7 @@ class ThumbnailsManager { private static $instance = null; const TAG = 'ThumbnailManager'; + const THUMBNAIL_HEIGHT = 150; public static function getInstance() { if (self::$instance === null) @@ -62,9 +70,9 @@ class ThumbnailsManager { } public function getThumbnail($path) { - $gallery_path = \OCP\Config::getSystemValue( 'datadirectory' ).'/'.\OC_User::getUser().'/gallery'; - if (file_exists($gallery_path.$path)) { - return new \OC_Image($gallery_path.$path); + $gallery_storage = \OCP\Files::getStorage('gallery'); + if ($gallery_storage->file_exists($path)) { + return new \OC_Image($gallery_storage->getLocalFile($path)); } if (!\OC_Filesystem::file_exists($path)) { \OC_Log::write(self::TAG, 'File '.$path.' don\'t exists', \OC_Log::WARN); @@ -73,27 +81,39 @@ class ThumbnailsManager { $image = new \OC_Image(); $image->loadFromFile(\OC_Filesystem::getLocalFile($path)); if (!$image->valid()) return false; - + $image->fixOrientation(); - - $ret = $image->preciseResize(floor((150*$image->width())/$image->height()), 150); + + $ret = $image->preciseResize( floor((self::THUMBNAIL_HEIGHT*$image->width())/$image->height()), self::THUMBNAIL_HEIGHT ); if (!$ret) { \OC_Log::write(self::TAG, 'Couldn\'t resize image', \OC_Log::ERROR); unset($image); return false; } - - $image->save($gallery_path.'/'.$path); + $l = $gallery_storage->getLocalFile($path); + + $image->save($l); return $image; } - + + public function getThumbnailWidth($image) { + return floor((self::THUMBNAIL_HEIGHT*$image->widthTopLeft())/$image->heightTopLeft()); + } + public function getThumbnailInfo($path) { $arr = DatabaseManager::getInstance()->getFileData($path); if (!$arr) { - $thubnail = $this->getThumbnail($path); - unset($thubnail); - $arr = DatabaseManager::getInstance()->getFileData($path); + if (!\OC_Filesystem::file_exists($path)) { + \OC_Log::write(self::TAG, 'File '.$path.' don\'t exists', \OC_Log::WARN); + return false; + } + $image = new \OC_Image(); + $image->loadFromFile(\OC_Filesystem::getLocalFile($path)); + if (!$image->valid()) { + return false; + } + $arr = DatabaseManager::getInstance()->setFileData($path, $this->getThumbnailWidth($image), self::THUMBNAIL_HEIGHT); } $ret = array('filepath' => $arr['path'], 'width' => $arr['width'], @@ -102,13 +122,12 @@ class ThumbnailsManager { } public function delete($path) { - $thumbnail = \OCP\Config::getSystemValue('datadirectory').'/'.\OC_User::getUser()."/gallery".$path;
- if (file_exists($thumbnail)) {
- unlink($thumbnail);
+ $thumbnail_storage = \OCP\Files::getStorage('gallery'); + if ($thumbnail_storage->file_exists($path)) { + $thumbnail_storage->unlink($path); } } private function __construct() {} } -?> diff --git a/apps/gallery/lib/photo.php b/apps/gallery/lib/photo.php index f9527cb5fdb..3b4e74641b3 100644 --- a/apps/gallery/lib/photo.php +++ b/apps/gallery/lib/photo.php @@ -1,53 +1,55 @@ <?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/>. -* -*/ - + * 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_Gallery_Photo { - public static function create($albumId, $img){ + + public static function create($albumId, $img) { $stmt = OCP\DB::prepare('INSERT INTO *PREFIX*gallery_photos (album_id, file_path) VALUES (?, ?)'); $stmt->execute(array($albumId, $img)); } - public static function find($albumId, $img=null){ + + public static function find($albumId, $img = null) { $sql = 'SELECT * FROM *PREFIX*gallery_photos WHERE album_id = ?'; $args = array($albumId); - if (!is_null($img)){ + if (!is_null($img)) { $sql .= ' AND file_path = ?'; $args[] = $img; } $stmt = OCP\DB::prepare($sql); return $stmt->execute($args); } - public static function findForAlbum($owner, $album_name){ + + public static function findForAlbum($owner, $album_name) { $stmt = OCP\DB::prepare('SELECT *' - .' FROM *PREFIX*gallery_photos photos,' - .' *PREFIX*gallery_albums albums' - .' WHERE albums.uid_owner = ?' - .' AND albums.album_name = ?' - .' AND photos.album_id = albums.album_id'); + .' FROM *PREFIX*gallery_photos photos,' + .' *PREFIX*gallery_albums albums' + .' WHERE albums.uid_owner = ?' + .' AND albums.album_name = ?' + .' AND photos.album_id = albums.album_id'); return $stmt->execute(array($owner, $album_name)); } - public static function removeByPath($path, $album_id) { - $stmt = OCP\DB::prepare('DELETE FROM *PREFIX*gallery_photos WHERE file_path LIKE ? and album_id = ?'); + public static function removeByPath($path, $album_id) { + $stmt = OCP\DB::prepare('DELETE FROM *PREFIX*gallery_photos WHERE file_path LIKE ? and album_id = ?'); $stmt->execute(array($path, $album_id)); } @@ -67,19 +69,20 @@ class OC_Gallery_Photo { } public static function getThumbnail($image_name, $owner = null) { - if (!$owner) $owner = OCP\USER::getUser(); + if (!$owner) + $owner = OCP\USER::getUser(); $view = OCP\Files::getStorage('gallery'); $save_dir = dirname($image_name); if (!$view->is_dir($save_dir)) { $view->mkdir($save_dir); } - $view->chroot($view->getRoot().'/'.$save_dir); + $view->chroot($view->getRoot() . '/' . $save_dir); $thumb_file = basename($image_name); if ($view->file_exists($thumb_file)) { $image = new OC_Image($view->fopen($thumb_file, 'r')); } else { $image_path = OC_Filesystem::getLocalFile($image_name); - if(!file_exists($image_path)) { + if (!file_exists($image_path)) { return null; } $image = new OC_Image($image_path); @@ -91,7 +94,38 @@ class OC_Gallery_Photo { } if ($image->valid()) { return $image; - }else{ + } else { + $image->destroy(); + } + return null; + } + + public static function getViewImage($image_name, $owner = null) { + if (!$owner) $owner = OCP\USER::getUser(); + $save_dir = OCP\Config::getSystemValue("datadirectory") . '/' . $owner . '/gallery'; + $save_dir .= dirname($image_name) . '/view/'; + $image_path = $image_name; + $view_file = $save_dir . basename($image_name); + if (!is_dir($save_dir)) { + mkdir($save_dir, 0777, true); + } + if (file_exists($view_file)) { + $image = new OC_Image($view_file); + } else { + $image_path = OC_Filesystem::getLocalFile($image_path); + if (!file_exists($image_path)) { + return null; + } + $image = new OC_Image($image_path); + if ($image->valid()) { + $image->resize(1200); + $image->fixOrientation(); + $image->save($view_file); + } + } + if ($image->valid()) { + return $image; + } else { $image->destroy(); } return null; @@ -100,4 +134,5 @@ class OC_Gallery_Photo { public static function getGalleryRoot() { return OCP\Config::getUserValue(OCP\USER::getUser(), 'gallery', 'root', ''); } + } diff --git a/apps/gallery/lib/tiles.php b/apps/gallery/lib/tiles.php index 5efe0d7a299..e36d26d3191 100644 --- a/apps/gallery/lib/tiles.php +++ b/apps/gallery/lib/tiles.php @@ -33,7 +33,7 @@ class TilesLine { } public function setAvailableSpace($space) { - $available_space = $space; + $this->available_space = $space; } public function getTilesCount() { @@ -95,7 +95,7 @@ class TileSingle extends TileBase { public function get($extra = '') { // !HACK! file path needs to be encoded twice because files app decode twice url, so any special chars like + or & in filename // !HACK! will result in failing of opening them - return '<a rel="images" title="'.htmlentities(basename($this->getPath())).'" href="'.\OCP\Util::linkTo('files', 'download.php').'?file='.urlencode(urlencode($this->getPath())).'"><img rel="images" src="'.\OCP\Util::linkTo('gallery', 'ajax/thumbnail.php').'&filepath='.urlencode($this->getPath()).'" '.$extra.'></a>'; + return '<a rel="images" title="'.htmlentities(basename($this->getPath())).'" href="'.\OCP\Util::linkTo('gallery','ajax/viewImage.php').'?img='.urlencode(urlencode($this->getPath())).'"><img rel="images" src="'.\OCP\Util::linkTo('gallery', 'ajax/thumbnail.php').'&filepath='.urlencode($this->getPath()).'" '.$extra.'></a>'; } public function getMiniatureSrc() { @@ -174,5 +174,3 @@ class TileStack extends TileBase { private $tiles_array; private $stack_name; } - -?> diff --git a/apps/gallery/lib/tiles_test.php b/apps/gallery/lib/tiles_test.php index 022a88f75cc..02d567c628d 100644 --- a/apps/gallery/lib/tiles_test.php +++ b/apps/gallery/lib/tiles_test.php @@ -83,5 +83,3 @@ if ($ts->getCount() != 0) { } echo $tl->get(); - -?> diff --git a/apps/gallery/templates/index.php b/apps/gallery/templates/index.php index c90932cefd0..b2efd5342ff 100644 --- a/apps/gallery/templates/index.php +++ b/apps/gallery/templates/index.php @@ -22,7 +22,10 @@ $(document).ready(function() { } } -?><br/> +?> + <div id="slideshow"> + <input type="button" class="start" value="<?php echo $l->t('Slideshow')?>" /> + </div> </div> <div id="gallerycontent"> <?php @@ -32,3 +35,50 @@ echo $_['tl']->get(); ?> </div> + +<!-- start supersized block --> +<div id="slideshow-content" style="display:none;"> + + <!--Thumbnail Navigation--> + <div id="prevthumb"></div> + <div id="nextthumb"></div> + + <!--Arrow Navigation--> + <a id="prevslide" class="load-item"></a> + <a id="nextslide" class="load-item"></a> + + <div id="thumb-tray" class="load-item"> + <div id="thumb-back"></div> + <div id="thumb-forward"></div> + </div> + + <!--Time Bar--> + <div id="progress-back" class="load-item"> + <div id="progress-bar"></div> + </div> + + <!--Control Bar--> + <div id="slideshow-controls-wrapper" class="load-item"> + <div id="slideshow-controls"> + + <a id="play-button"><img id="pauseplay" src="<?php echo OCP\image_path('gallery', 'supersized/pause.png'); ?>"/></a> + + <!--Slide counter--> + <div id="slidecounter"> + <span class="slidenumber"></span> / <span class="totalslides"></span> + </div> + + <!--Slide captions displayed here--> + <div id="slidecaption"></div> + + <!--Thumb Tray button--> + <a id="tray-button"><img id="tray-arrow" src="<?php echo OCP\image_path('gallery', 'supersized/button-tray-up.png'); ?>"/></a> + + <!--Navigation--> + <!-- + <ul id="slide-list"></ul> + --> + </div> + </div> + +</div><!-- end supersized block --> diff --git a/apps/gallery/templates/view_album.php b/apps/gallery/templates/view_album.php index c16ed69c065..00e891103f1 100644 --- a/apps/gallery/templates/view_album.php +++ b/apps/gallery/templates/view_album.php @@ -1,9 +1,9 @@ <?php OCP\Util::addStyle('gallery', 'styles'); -OCP\Util::addscript('gallery', 'albums'); -OCP\Util::addscript('gallery', 'album_cover'); -OCP\Util::addscript('files_imageviewer', 'jquery.mousewheel-3.0.4.pack'); -OCP\Util::addscript('files_imageviewer', 'jquery.fancybox-1.3.4.pack'); +OCP\Util::addScript('gallery', 'albums'); +OCP\Util::addScript('gallery', 'album_cover'); +OCP\Util::addScript('files_imageviewer', 'jquery.mousewheel-3.0.4.pack'); +OCP\Util::addScript('files_imageviewer', 'jquery.fancybox-1.3.4.pack'); OCP\Util::addStyle( 'files_imageviewer', 'jquery.fancybox-1.3.4' ); $l = OC_L10N::get('gallery'); ?> diff --git a/apps/media/ajax/api.php b/apps/media/ajax/api.php index 23abc579272..7f5cdb22c12 100644 --- a/apps/media/ajax/api.php +++ b/apps/media/ajax/api.php @@ -131,4 +131,3 @@ if($arguments['action']){ exit; } } -?> diff --git a/apps/media/ajax/autoupdate.php b/apps/media/ajax/autoupdate.php index 3122c7e6754..c2dbf27a004 100644 --- a/apps/media/ajax/autoupdate.php +++ b/apps/media/ajax/autoupdate.php @@ -35,4 +35,3 @@ $autoUpdate=(isset($_GET['autoupdate']) and $_GET['autoupdate']=='true'); OCP\Config::setUserValue(OCP\USER::getUser(),'media','autoupdate',(integer)$autoUpdate); OCP\JSON::success(array('data' => $autoUpdate)); -?> diff --git a/apps/media/appinfo/version b/apps/media/appinfo/version index e6adf3fc7bb..44bb5d1f743 100644 --- a/apps/media/appinfo/version +++ b/apps/media/appinfo/version @@ -1 +1 @@ -0.4
\ No newline at end of file +0.4.1
\ No newline at end of file diff --git a/apps/media/index.php b/apps/media/index.php index fb51aa0b17a..ae85abc8aab 100644 --- a/apps/media/index.php +++ b/apps/media/index.php @@ -40,5 +40,3 @@ OCP\App::setActiveNavigationEntry( 'media_index' ); $tmpl = new OCP\Template( 'media', 'music', 'user' ); $tmpl->printPage(); -?> - diff --git a/apps/media/lib_ampache.php b/apps/media/lib_ampache.php index 255e6f468f8..d5a093338cc 100644 --- a/apps/media/lib_ampache.php +++ b/apps/media/lib_ampache.php @@ -271,7 +271,6 @@ class OC_MEDIA_AMPACHE{ </root>"); return; } - global $SITEROOT; $filter=$params['filter']; $albums=OC_MEDIA_COLLECTION::getAlbums($filter); $artist=OC_MEDIA_COLLECTION::getArtistName($filter); @@ -419,5 +418,3 @@ class OC_MEDIA_AMPACHE{ echo('</root>'); } } - -?> diff --git a/apps/media/lib_collection.php b/apps/media/lib_collection.php index 598c08d32e2..cacab8e959f 100644 --- a/apps/media/lib_collection.php +++ b/apps/media/lib_collection.php @@ -27,7 +27,6 @@ class OC_MEDIA_COLLECTION{ public static $uid; private static $artistIdCache=array(); private static $albumIdCache=array(); - private static $songIdCache=array(); private static $queries=array(); /** @@ -152,7 +151,7 @@ class OC_MEDIA_COLLECTION{ return $artistId; }else{ $query=OCP\DB::prepare("INSERT INTO `*PREFIX*media_artists` (`artist_name`) VALUES (?)"); - $result=$query->execute(array($name)); + $query->execute(array($name)); return self::getArtistId($name);; } } @@ -387,5 +386,3 @@ class OC_MEDIA_COLLECTION{ $query->execute(array($newPath,$oldPath)); } } - -?> diff --git a/apps/media/lib_media.php b/apps/media/lib_media.php index 9e687a4af2c..54502f42575 100644 --- a/apps/media/lib_media.php +++ b/apps/media/lib_media.php @@ -27,12 +27,12 @@ class OC_MEDIA{ * @param array $params, parameters passed from OC_Hook */ public static function loginListener($params){ - if(isset($_POST['user']) and $_POST['password']){ - $name=$_POST['user']; + if(isset($params['uid']) and $params['password']){ + $name=$params['uid']; $query=OCP\DB::prepare("SELECT user_id from *PREFIX*media_users WHERE user_id LIKE ?"); $uid=$query->execute(array($name))->fetchAll(); if(count($uid)==0){ - $password=hash('sha256',$_POST['password']); + $password=hash('sha256',$params['password']); $query=OCP\DB::prepare("INSERT INTO *PREFIX*media_users (user_id, user_password_sha256) VALUES (?, ?);"); $query->execute(array($name,$password)); } diff --git a/apps/media/settings.php b/apps/media/settings.php index 227298fafec..53738f02f9f 100644 --- a/apps/media/settings.php +++ b/apps/media/settings.php @@ -3,4 +3,3 @@ $tmpl = new OCP\Template( 'media', 'settings'); return $tmpl->fetchPage(); -?> diff --git a/apps/remoteStorage/appinfo/info.xml b/apps/remoteStorage/appinfo/info.xml index fa878762a05..1388ad9c316 100644 --- a/apps/remoteStorage/appinfo/info.xml +++ b/apps/remoteStorage/appinfo/info.xml @@ -7,4 +7,7 @@ <author>Michiel de Jong</author> <require>4</require> <shipped>true</shipped> + <remote> + <remoteStorage>webdav.php</remoteStorage> + </remote> </info> diff --git a/apps/remoteStorage/appinfo/version b/apps/remoteStorage/appinfo/version index 490f510fc27..0e2c93950bb 100644 --- a/apps/remoteStorage/appinfo/version +++ b/apps/remoteStorage/appinfo/version @@ -1 +1 @@ -0.6
\ No newline at end of file +0.7
\ No newline at end of file diff --git a/apps/remoteStorage/appinfo/webfinger.php b/apps/remoteStorage/appinfo/webfinger.php index 5d481f315f8..e8b237628c4 100644 --- a/apps/remoteStorage/appinfo/webfinger.php +++ b/apps/remoteStorage/appinfo/webfinger.php @@ -1,8 +1,8 @@ -<?php if(OC_User::userExists(WF_USER)) { ?> +<?php if(OC_User::userExists(WF_USER)): ?> { "rel":"remoteStorage", - "template":"<?php echo WF_BASEURL; ?>/apps/remoteStorage/WebDAV.php/<?php echo WF_USER; ?>/remoteStorage/{category}/", + "template":"<?php echo WF_BASEURL; ?>/remote.php/remoteStorage/<?php echo WF_USER; ?>/remoteStorage/{category}/", "api":"WebDAV", "auth":"<?php echo WF_BASEURL; ?>/?app=remoteStorage&getfile=auth.php&userid=<?php echo WF_USER; ?>" } -<?php } ?> +<?php endif ?> diff --git a/apps/remoteStorage/lib_remoteStorage.php b/apps/remoteStorage/lib_remoteStorage.php index 42cd9c90f64..c1765640c5d 100644 --- a/apps/remoteStorage/lib_remoteStorage.php +++ b/apps/remoteStorage/lib_remoteStorage.php @@ -17,12 +17,11 @@ class OC_remoteStorage { $user=OCP\USER::getUser(); $query=OCP\DB::prepare("SELECT token FROM *PREFIX*authtoken WHERE user=? AND appUrl=? AND category=? LIMIT 1"); $result=$query->execute(array($user, $appUrl, $categories)); - $ret = array(); if($row=$result->fetchRow()) { - return base64_encode('remoteStorage:'.$row['token']); - } else { - return false; - } + return base64_encode('remoteStorage:'.$row['token']); + } else { + return false; + } } public static function getAllTokens() { @@ -42,13 +41,13 @@ class OC_remoteStorage { public static function deleteToken($token) { $user=OCP\USER::getUser(); $query=OCP\DB::prepare("DELETE FROM *PREFIX*authtoken WHERE token=? AND user=?"); - $result=$query->execute(array($token,$user)); + $query->execute(array($token,$user)); return 'unknown';//how can we see if any rows were affected? } private static function addToken($token, $appUrl, $categories){ $user=OCP\USER::getUser(); $query=OCP\DB::prepare("INSERT INTO *PREFIX*authtoken (`token`,`appUrl`,`user`,`category`) VALUES(?,?,?,?)"); - $result=$query->execute(array($token,$appUrl,$user,$categories)); + $query->execute(array($token,$appUrl,$user,$categories)); } public static function createCategories($appUrl, $categories) { $token=uniqid(); diff --git a/apps/remoteStorage/oauth_ro_auth.php b/apps/remoteStorage/oauth_ro_auth.php index 12d02d1cf5d..bed3093c3b3 100644 --- a/apps/remoteStorage/oauth_ro_auth.php +++ b/apps/remoteStorage/oauth_ro_auth.php @@ -9,10 +9,10 @@ class OC_Connector_Sabre_Auth_ro_oauth extends Sabre_DAV_Auth_Backend_AbstractBasic { private $validTokens; - private $category; + private $category; public function __construct($validTokensArg, $categoryArg) { $this->validTokens = $validTokensArg; - $this->category = $categoryArg; + $this->category = $categoryArg; } /** @@ -25,16 +25,16 @@ class OC_Connector_Sabre_Auth_ro_oauth extends Sabre_DAV_Auth_Backend_AbstractBa */ protected function validateUserPass($username, $password){ //always give read-only: - if(($_SERVER['REQUEST_METHOD'] == 'OPTIONS') + if(($_SERVER['REQUEST_METHOD'] == 'OPTIONS') || (isset($this->validTokens[$password])) - || (($_SERVER['REQUEST_METHOD'] == 'GET') && ($this->category == 'public')) - ) { + || (($_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; } } @@ -48,8 +48,8 @@ class OC_Connector_Sabre_Auth_ro_oauth extends Sabre_DAV_Auth_Backend_AbstractBa $userpass = $auth->getUserPass(); if (!$userpass) { if(($_SERVER['REQUEST_METHOD'] == 'OPTIONS') - ||(($_SERVER['REQUEST_METHOD'] == 'GET') && ($this->category == 'public')) - ) { + ||(($_SERVER['REQUEST_METHOD'] == 'GET') && ($this->category == 'public')) + ) { $userpass = array('', ''); } else { $auth->requireLogin(); diff --git a/apps/remoteStorage/settings.php b/apps/remoteStorage/settings.php index 9c48549fe6d..3be8b0984d8 100644 --- a/apps/remoteStorage/settings.php +++ b/apps/remoteStorage/settings.php @@ -4,4 +4,3 @@ require_once('lib_remoteStorage.php'); $tmpl = new OCP\Template( 'remoteStorage', 'settings'); return $tmpl->fetchPage(); -?> diff --git a/apps/remoteStorage/WebDAV.php b/apps/remoteStorage/webdav.php index 7a81c18e0af..8d8ec6a45a1 100644 --- a/apps/remoteStorage/WebDAV.php +++ b/apps/remoteStorage/webdav.php @@ -25,22 +25,7 @@ * */ - -// Do not load FS ... -$RUNTIME_NOSETUPFS = true; - - -require_once('../../lib/base.php'); - -require_once('../../lib/user.php'); -require_once('../../lib/public/user.php'); - -require_once('../../lib/app.php'); -require_once('../../lib/public/app.php'); - -require_once('../../3rdparty/Sabre/DAV/Auth/IBackend.php'); -require_once('../../3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php'); -require_once('../../lib/connector/sabre/auth.php'); +OC_App::loadApps(array('filesystem','authentication')); OCP\App::checkAppEnabled('remoteStorage'); require_once('lib_remoteStorage.php'); @@ -61,14 +46,15 @@ if(isset($_SERVER['HTTP_ORIGIN'])) { header('Access-Control-Allow-Origin: *'); } -$path = substr($_SERVER["REQUEST_URI"], strlen($_SERVER["SCRIPT_NAME"])); +$path = substr($_SERVER["REQUEST_URI"], strlen($baseuri)); + $pathParts = explode('/', $path); // for webdav: -// 0/ 1 / 2 / 3... -// /$ownCloudUser/remoteStorage/$category/ +// 0 / 1 / 2... +// $ownCloudUser/remoteStorage/$category/ -if(count($pathParts) >= 3 && $pathParts[0] == '') { - list($dummy, $ownCloudUser, $dummy2, $category) = $pathParts; +if(count($pathParts) >= 2) { + list($ownCloudUser, $dummy2, $category) = $pathParts; OC_Util::setupFS($ownCloudUser); @@ -77,13 +63,13 @@ if(count($pathParts) >= 3 && $pathParts[0] == '') { $server = new Sabre_DAV_Server($publicDir); // Path to our script - $server->setBaseUri(OC::$WEBROOT."/apps/remoteStorage/WebDAV.php/$ownCloudUser"); + $server->setBaseUri($baseuri.$ownCloudUser); // Auth backend $authBackend = new OC_Connector_Sabre_Auth_ro_oauth( - OC_remoteStorage::getValidTokens($ownCloudUser, $category), - $category - ); + OC_remoteStorage::getValidTokens($ownCloudUser, $category), + $category + ); $authPlugin = new Sabre_DAV_Auth_Plugin($authBackend,'ownCloud');//should use $validTokens here $server->addPlugin($authPlugin); diff --git a/apps/tasks/ajax/addtask.php b/apps/tasks/ajax/addtask.php index 9f35e7f21ec..d98fdbf3888 100644 --- a/apps/tasks/ajax/addtask.php +++ b/apps/tasks/ajax/addtask.php @@ -3,6 +3,7 @@ // Init owncloud OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('tasks'); +OCP\JSON::callCheck(); $calendars = OC_Calendar_Calendar::allCalendars(OCP\User::getUser(), true); $first_calendar = reset($calendars); @@ -21,7 +22,7 @@ $request['description'] = null; $vcalendar = OC_Task_App::createVCalendarFromRequest($request); $id = OC_Calendar_Object::add($cid, $vcalendar->serialize()); -$user_timezone = OCP\Config::getUserValue(OCP\User::getUser(), 'calendar', 'timezone', date_default_timezone_get()); +$user_timezone = OC_Calendar_App::getTimezone(); $task = OC_Task_App::arrayForJSON($id, $vcalendar->VTODO, $user_timezone); OCP\JSON::success(array('task' => $task)); diff --git a/apps/tasks/ajax/addtaskform.php b/apps/tasks/ajax/addtaskform.php deleted file mode 100644 index d86232e2da5..00000000000 --- a/apps/tasks/ajax/addtaskform.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -// Init owncloud -OCP\JSON::checkLoggedIn(); -OCP\JSON::checkAppEnabled('tasks'); - -$calendars = OC_Calendar_Calendar::allCalendars(OCP\User::getUser(), true); -$category_options = OC_Calendar_App::getCategoryOptions(); -$percent_options = range(0, 100, 10); -$priority_options = OC_Task_App::getPriorityOptions(); -$tmpl = new OCP\Template('tasks','part.addtaskform'); -$tmpl->assign('calendars',$calendars); -$tmpl->assign('category_options', $category_options); -$tmpl->assign('percent_options', $percent_options); -$tmpl->assign('priority_options', $priority_options); -$tmpl->assign('details', new OC_VObject('VTODO')); -$tmpl->assign('categories', ''); -$page = $tmpl->fetchPage(); - -OCP\JSON::success(array('data' => array( 'page' => $page ))); diff --git a/apps/tasks/ajax/delete.php b/apps/tasks/ajax/delete.php index e29add9b556..cc22c3e3873 100644 --- a/apps/tasks/ajax/delete.php +++ b/apps/tasks/ajax/delete.php @@ -23,6 +23,7 @@ // Init owncloud OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('tasks'); +OCP\JSON::callCheck(); $id = $_POST['id']; $task = OC_Calendar_App::getEventObject( $id ); diff --git a/apps/tasks/ajax/edittask.php b/apps/tasks/ajax/edittask.php deleted file mode 100644 index edcc8a7cdcd..00000000000 --- a/apps/tasks/ajax/edittask.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -// Init owncloud -OCP\JSON::checkLoggedIn(); -OCP\JSON::checkAppEnabled('tasks'); - -$l10n = new OC_L10N('tasks'); - -$id = $_POST['id']; -$vcalendar = OC_Calendar_App::getVCalendar($id); - -$errors = OC_Task_App::validateRequest($_POST); -if (!empty($errors)) { - OCP\JSON::error(array('data' => array( 'errors' => $errors ))); - exit(); -} - -OC_Task_App::updateVCalendarFromRequest($_POST, $vcalendar); -OC_Calendar_Object::edit($id, $vcalendar->serialize()); - -$priority_options = OC_Task_App::getPriorityOptions(); -$tmpl = new OCP\Template('tasks','part.details'); -$tmpl->assign('priority_options', $priority_options); -$tmpl->assign('details', $vcalendar->VTODO); -$tmpl->assign('id', $id); -$page = $tmpl->fetchPage(); - -$user_timezone = OCP\Config::getUserValue(OCP\User::getUser(), 'calendar', 'timezone', date_default_timezone_get()); -$task = OC_Task_App::arrayForJSON($id, $vcalendar->VTODO, $user_timezone); - -OCP\JSON::success(array('data' => array( 'id' => $id, 'page' => $page, 'task' => $task ))); diff --git a/apps/tasks/ajax/edittaskform.php b/apps/tasks/ajax/edittaskform.php deleted file mode 100644 index e5a0a7297c5..00000000000 --- a/apps/tasks/ajax/edittaskform.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -// Init owncloud -OCP\JSON::checkLoggedIn(); -OCP\JSON::checkAppEnabled('tasks'); - -$id = $_GET['id']; -$details = OC_Calendar_App::getVCalendar($id)->VTODO; -$categories = $details->getAsString('CATEGORIES'); - -$category_options = OC_Calendar_App::getCategoryOptions(); -$percent_options = range(0, 100, 10); -$priority_options = OC_Task_App::getPriorityOptions(); - -$tmpl = new OCP\Template('tasks','part.edittaskform'); -$tmpl->assign('category_options', $category_options); -$tmpl->assign('percent_options', $percent_options); -$tmpl->assign('priority_options', $priority_options); -$tmpl->assign('id',$id); -$tmpl->assign('details',$details); -$tmpl->assign('categories', $categories); -$page = $tmpl->fetchPage(); - -OCP\JSON::success(array('data' => array( 'page' => $page ))); diff --git a/apps/tasks/ajax/getdetails.php b/apps/tasks/ajax/getdetails.php deleted file mode 100644 index 4ce469e0c9c..00000000000 --- a/apps/tasks/ajax/getdetails.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -// Init owncloud -OCP\JSON::checkLoggedIn(); -OCP\JSON::checkAppEnabled('tasks'); - -$l10n = new OC_L10N('tasks'); - -$id = $_GET['id']; -$task = OC_Calendar_Object::find($id); -$details = OC_VObject::parse($task['calendardata']); -if (!$details){ - OCP\JSON::error(); - exit; -} - -$priority_options = OC_Task_App::getPriorityOptions(); -$tmpl = new OCP\Template('tasks','part.details'); -$tmpl->assign('priority_options', $priority_options); -$tmpl->assign('details',$details->VTODO); -$tmpl->assign('id',$id); -$page = $tmpl->fetchPage(); - -OCP\JSON::success(array('data' => array( 'id' => $id, 'page' => $page ))); diff --git a/apps/tasks/ajax/gettasks.php b/apps/tasks/ajax/gettasks.php index 011730d0a13..b6183d9cb65 100644 --- a/apps/tasks/ajax/gettasks.php +++ b/apps/tasks/ajax/gettasks.php @@ -11,7 +11,7 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('tasks'); $calendars = OC_Calendar_Calendar::allCalendars(OCP\User::getUser(), true); -$user_timezone = OCP\Config::getUserValue(OCP\User::getUser(), 'calendar', 'timezone', date_default_timezone_get()); +$user_timezone = OC_Calendar_App::getTimezone(); $tasks = array(); foreach( $calendars as $calendar ){ diff --git a/apps/tasks/ajax/update_property.php b/apps/tasks/ajax/update_property.php index 46521cf6c58..679cfdefe48 100644 --- a/apps/tasks/ajax/update_property.php +++ b/apps/tasks/ajax/update_property.php @@ -9,6 +9,7 @@ // Init owncloud OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('tasks'); +OCP\JSON::callCheck(); $id = $_POST['id']; $property = $_POST['type']; @@ -38,7 +39,7 @@ switch($property) { $type = null; if ($due != 'false') { try { - $timezone = OCP\Config::getUserValue(OCP\User::getUser(), 'calendar', 'timezone', date_default_timezone_get()); + $timezone = OC_Calendar_App::getTimezone(); $timezone = new DateTimeZone($timezone); $due = new DateTime('@'.$due); $due->setTimezone($timezone); @@ -63,6 +64,6 @@ switch($property) { } OC_Calendar_Object::edit($id, $vcalendar->serialize()); -$user_timezone = OCP\Config::getUserValue(OCP\User::getUser(), 'calendar', 'timezone', date_default_timezone_get()); +$user_timezone = OC_Calendar_App::getTimezone(); $task_info = OC_Task_App::arrayForJSON($id, $vtodo, $user_timezone); OCP\JSON::success(array('data' => $task_info)); diff --git a/apps/tasks/index.php b/apps/tasks/index.php index 4ff304a5607..f1c4d1e765c 100644 --- a/apps/tasks/index.php +++ b/apps/tasks/index.php @@ -21,8 +21,8 @@ OCP\Util::addScript('3rdparty/timepicker', 'jquery.ui.timepicker'); OCP\Util::addStyle('3rdparty/timepicker', 'jquery.ui.timepicker'); OCP\Util::addScript('tasks', 'tasks'); OCP\Util::addStyle('tasks', 'style'); -OCP\Util::addScript('contacts','jquery.multi-autocomplete'); -OCP\Util::addScript('','oc-vcategories'); +OCP\Util::addScript('contacts', 'jquery.multi-autocomplete'); +OCP\Util::addScript('', 'oc-vcategories'); OCP\App::setActiveNavigationEntry('tasks_index'); $categories = OC_Calendar_App::getCategoryOptions(); diff --git a/apps/tasks/js/tasks.js b/apps/tasks/js/tasks.js index bc92965bb0b..de627927507 100644 --- a/apps/tasks/js/tasks.js +++ b/apps/tasks/js/tasks.js @@ -469,67 +469,5 @@ $(document).ready(function(){ return false; }); - $('#tasks_addtaskform input[type="submit"]').live('click',function(){ - $.post('ajax/addtask.php',$('#tasks_addtaskform').serialize(),function(jsondata){ - if(jsondata.status == 'success'){ - $('#task_details').data('id',jsondata.data.id); - $('#task_details').html(jsondata.data.page); - $('#tasks_list').append(OC.Tasks.create_task_div(jsondata.data.task)); - } - else{ - alert(jsondata.data.message); - } - }, 'json'); - return false; - }); - - $('#tasks_edit').live('click',function(){ - var id = $('#task_details').data('id'); - $.getJSON('ajax/edittaskform.php',{'id':id},function(jsondata){ - if(jsondata.status == 'success'){ - $('#task_details').html(jsondata.data.page); - $('#task_details #categories').multiple_autocomplete({source: categories}); - } - else{ - alert(jsondata.data.message); - } - }); - return false; - }); - - $('#tasks_edittaskform #percent_complete').live('change',function(event){ - if ($(event.target).val() == 100){ - $('#tasks_edittaskform #complete').show(); - }else{ - $('#tasks_edittaskform #complete').hide(); - } - }); - - $('#tasks_edittaskform input[type="submit"]').live('click',function(){ - $.post('ajax/edittask.php',$('#tasks_edittaskform').serialize(),function(jsondata){ - $('.error_msg').remove(); - $('.error').removeClass('error'); - if(jsondata.status == 'success'){ - var id = jsondata.data.id; - $('#task_details').data('id',id); - $('#task_details').html(jsondata.data.page); - var task = jsondata.data.task; - $('#tasks .task[data-id='+id+']') - .data('task', task) - .html(OC.Tasks.create_task_div(task).html()); - } - else{ - var errors = jsondata.data.errors; - for (k in errors){ - $('#'+k).addClass('error') - .after('<span class="error_msg">'+errors[k]+'</span>'); - } - $('.error_msg').effect('highlight', {}, 3000); - $('.error').effect('highlight', {}, 3000); - } - }, 'json'); - return false; - }); - OCCategories.app = 'calendar'; }); diff --git a/apps/tasks/lib/app.php b/apps/tasks/lib/app.php index 1b42968f0be..a97c6b95d1d 100644 --- a/apps/tasks/lib/app.php +++ b/apps/tasks/lib/app.php @@ -77,24 +77,24 @@ class OC_Task_App { public static function validateRequest($request) { $errors = array(); - if($request['summary'] == ''){ + if($request['summary'] == '') { $errors['summary'] = self::$l10n->t('Empty Summary'); } try { - $timezone = OCP\Config::getUserValue(OCP\User::getUser(), "calendar", "timezone", "Europe/London"); + $timezone = OC_Calendar_App::getTimezone(); $timezone = new DateTimeZone($timezone); new DateTime($request['due'], $timezone); } catch (Exception $e) { $errors['due'] = self::$l10n->t('Invalid date/time'); } - if ($request['percent_complete'] < 0 || $request['percent_complete'] > 100){ + if ($request['percent_complete'] < 0 || $request['percent_complete'] > 100) { $errors['percent_complete'] = self::$l10n->t('Invalid percent complete'); } - if ($request['percent_complete'] == 100 && !empty($request['completed'])){ + if ($request['percent_complete'] == 100 && !empty($request['completed'])) { try { - $timezone = OCP\Config::getUserValue(OCP\User::getUser(), "calendar", "timezone", "Europe/London"); + $timezone = OC_Calendar_App::getTimezone(); $timezone = new DateTimeZone($timezone); new DateTime($request['completed'], $timezone); } catch (Exception $e) { @@ -147,7 +147,7 @@ class OC_Task_App { $vtodo->setString('PRIORITY', $priority); if ($due) { - $timezone = OCP\Config::getUserValue(OCP\User::getUser(), 'calendar', 'timezone', date_default_timezone_get()); + $timezone = OC_Calendar_App::getTimezone(); $timezone = new DateTimeZone($timezone); $due = new DateTime($due, $timezone); $vtodo->setDateTime('DUE', $due); @@ -168,15 +168,15 @@ class OC_Task_App { $vtodo->__unset('PERCENT-COMPLETE'); } - if ($percent_complete == 100){ - if (!$completed){ + if ($percent_complete == 100) { + if (!$completed) { $completed = 'now'; } } else { $completed = null; } if ($completed) { - $timezone = OCP\Config::getUserValue(OCP\User::getUser(), 'calendar', 'timezone', date_default_timezone_get()); + $timezone = OC_Calendar_App::getTimezone(); $timezone = new DateTimeZone($timezone); $completed = new DateTime($completed, $timezone); $vtodo->setDateTime('COMPLETED', $completed); diff --git a/apps/tasks/templates/part.addtaskform.php b/apps/tasks/templates/part.addtaskform.php deleted file mode 100644 index 0fad5592aa7..00000000000 --- a/apps/tasks/templates/part.addtaskform.php +++ /dev/null @@ -1,15 +0,0 @@ -<form id="tasks_addtaskform"> - <?php if(count($_['calendars'])==1): ?> - <input type="hidden" name="id" value="<?php echo $_['calendars'][0]['id']; ?>"> - <?php else: ?> - <label for="id"><?php echo $l->t('Calendar'); ?></label> - <select name="id" size="1"> - <?php foreach($_['calendars'] as $calendar): ?> - <option value="<?php echo $calendar['id']; ?>"><?php echo $calendar['displayname']; ?></option> - <?php endforeach; ?> - </select> - <br> - <?php endif; ?> - <?php echo $this->inc('part.taskform'); ?> - <input type="submit" name="submit" value="<?php echo $l->t('Create Task'); ?>"> -</form> diff --git a/apps/tasks/templates/part.details.php b/apps/tasks/templates/part.details.php deleted file mode 100644 index 89636b6e762..00000000000 --- a/apps/tasks/templates/part.details.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php if(isset($_['details']->SUMMARY)): ?> -<table> -<?php -echo $this->inc('part.property', array('label' => $l->t('Summary'), 'property' => $_['details']->SUMMARY)); -if(isset($_['details']->LOCATION)): - echo $this->inc('part.property', array('label' => $l->t('Location'), 'property' => $_['details']->LOCATION)); -endif; -if(isset($_['details']->CATEGORIES)): - echo $this->inc('part.property', array('label' => $l->t('Categories'), 'property' => $_['details']->CATEGORIES)); -endif; -if(isset($_['details']->DUE)): - echo $this->inc('part.property', array('label' => $l->t('Due'), 'property' => $_['details']->DUE[0])); -endif; -if(isset($_['details']->PRIORITY)): - echo $this->inc('part.property', array('label' => $l->t('Priority'), 'property' => $_['details']->PRIORITY[0], 'options' => $_['priority_options'])); -endif; -if($_['details']->__isset('PERCENT-COMPLETE') || isset($_['details']->COMPLETED)): -?> -<tr> - <th> - <?php echo $l->t('Complete') ?> - </th> - <td> -<?php if($_['details']->__isset('PERCENT-COMPLETE')): - echo $_['details']->__get('PERCENT-COMPLETE')->value.' % '; - endif; - if(isset($_['details']->COMPLETED)): - echo $l->t('on '). $l->l('datetime', $_['details']->COMPLETED[0]->getDateTime()); - endif; - echo '</tr>'; -endif; -if(isset($_['details']->DESCRIPTION)): - echo $this->inc('part.property', array('label' => $l->t('Description'), 'property' => $_['details']->DESCRIPTION)); -endif; ?> -</table> -<form> - <input type="button" id="tasks_delete" value="<?php echo $l->t('Delete');?>"> - <input type="button" id="tasks_edit" value="<?php echo $l->t('Edit');?>"> -</form> -<?php else: ?> -<?php //var_dump($_['details']); ?> -<?php endif ?> diff --git a/apps/tasks/templates/part.edittaskform.php b/apps/tasks/templates/part.edittaskform.php deleted file mode 100644 index fe123f07ac6..00000000000 --- a/apps/tasks/templates/part.edittaskform.php +++ /dev/null @@ -1,5 +0,0 @@ -<form id="tasks_edittaskform"> - <input type="hidden" name="id" value="<?php echo $_['id']; ?>"> - <?php echo $this->inc('part.taskform'); ?> - <input type="submit" name="submit" value="<?php echo $l->t('Update Task'); ?>"> -</form> diff --git a/apps/tasks/templates/part.property.php b/apps/tasks/templates/part.property.php deleted file mode 100644 index 591fd363e6f..00000000000 --- a/apps/tasks/templates/part.property.php +++ /dev/null @@ -1,22 +0,0 @@ -<tr> - <th> - <?php echo $_['label'] ?> - </th> - <td> - <?php - switch (get_class($_['property'])) - { - case 'Sabre_VObject_Element_DateTime': - echo $l->l('datetime', $_['property']->getDateTime()); - break; - default: - $value = $_['property']->value; - if (isset($_['options'])) - { - $value = $_['options'][$value]; - } - echo nl2br($value); - } - ?> - </td> -</tr> diff --git a/apps/tasks/templates/part.taskform.php b/apps/tasks/templates/part.taskform.php deleted file mode 100644 index 0a25ed33c91..00000000000 --- a/apps/tasks/templates/part.taskform.php +++ /dev/null @@ -1,36 +0,0 @@ - <label for="summary"><?php echo $l->t('Summary'); ?></label> - <input type="text" id="summary" name="summary" placeholder="<?php echo $l->t('Summary of the task');?>" value="<?php echo isset($_['details']->SUMMARY) ? $_['details']->SUMMARY[0]->value : '' ?>"> - <br> - <label for="location"><?php echo $l->t('Location'); ?></label> - <input type="text" id="location" name="location" placeholder="<?php echo $l->t('Location of the task');?>" value="<?php echo isset($_['details']->LOCATION) ? $_['details']->LOCATION[0]->value : '' ?>"> - <br> - <label for="categories"><?php echo $l->t('Categories'); ?></label> - <input id="categories" name="categories" type="text" placeholder="<?php echo $l->t('Separate categories with commas'); ?>" value="<?php echo isset($_['categories']) ? $_['categories'] : '' ?>"> - <a class="action edit" onclick="$(this).tipsy('hide');OCCategories.edit();" title="<?php echo $l->t('Edit categories'); ?>"><img alt="<?php echo $l->t('Edit categories'); ?>" src="<?php echo OCP\image_path('core','actions/rename.svg')?>" class="svg action" style="width: 16px; height: 16px;"></a> - <br> - <label for="due"><?php echo $l->t('Due'); ?></label> - <input type="text" id="due" name="due" placeholder="<?php echo $l->t('Due date') ?>" value="<?php echo isset($_['details']->DUE) ? $l->l('datetime', $_['details']->DUE[0]->getDateTime()) : '' ?>"> - <br> - <select name="percent_complete" id="percent_complete"> - <?php - foreach($_['percent_options'] as $percent){ - echo '<option value="' . $percent . '"' . (($_['details']->__get('PERCENT-COMPLETE') && $percent == $_['details']->__get('PERCENT-COMPLETE')->value) ? ' selected="selected"' : '') . '>' . $percent . ' %</option>'; - } - ?> - </select> - <label for="percent_complete"><?php echo $l->t('Complete'); ?></label> - <span id="complete"<?php echo ($_['details']->__get('PERCENT-COMPLETE') && $_['details']->__get('PERCENT-COMPLETE')->value == 100) ? '' : ' style="display:none;"' ?>><label for="completed"><?php echo $l->t('completed on'); ?></label> - <input type="text" id="completed" name="completed" value="<?php echo isset($_['details']->COMPLETED) ? $l->l('datetime', $_['details']->COMPLETED[0]->getDateTime()) : '' ?>"></span> - <br> - <label for="priority"><?php echo $l->t('Priority'); ?></label> - <select name="priority"> - <?php - foreach($_['priority_options'] as $priority => $label){ - echo '<option value="' . $priority . '"' . ((isset($_['details']->PRIORITY) && $priority == $_['details']->PRIORITY->value) ? ' selected="selected"' : '') . '>' . $label . '</option>'; - } - ?> - </select> - <br> - <label for="description"><?php echo $l->t('Description'); ?></label><br> - <textarea placeholder="<?php echo $l->t('Description of the task');?>" name="description"><?php echo isset($_['details']->DESCRIPTION) ? $_['details']->DESCRIPTION[0]->value : '' ?></textarea> - <br> diff --git a/apps/tasks/templates/part.tasks.php b/apps/tasks/templates/part.tasks.php deleted file mode 100644 index 50be1cd6bed..00000000000 --- a/apps/tasks/templates/part.tasks.php +++ /dev/null @@ -1,3 +0,0 @@ -<?php foreach( $_['tasks'] as $task ): ?> - <li data-id="<?php echo $task['id']; ?>"><a href="index.php?id=<?php echo $task['id']; ?>"><?php echo $task['name']; ?></a> </li> -<?php endforeach; ?> diff --git a/apps/user_external/appinfo/app.php b/apps/user_external/appinfo/app.php new file mode 100644 index 00000000000..c7408ec30d9 --- /dev/null +++ b/apps/user_external/appinfo/app.php @@ -0,0 +1,4 @@ +<?php +OC::$CLASSPATH['OC_User_IMAP']='apps/user_external/lib/imap.php'; +OC::$CLASSPATH['OC_User_SMB']='apps/user_external/lib/smb.php'; +OC::$CLASSPATH['OC_User_FTP']='apps/user_external/lib/ftp.php'; diff --git a/apps/user_external/appinfo/info.xml b/apps/user_external/appinfo/info.xml new file mode 100644 index 00000000000..1d1dcee5401 --- /dev/null +++ b/apps/user_external/appinfo/info.xml @@ -0,0 +1,13 @@ +<?xml version="1.0"?> +<info> + <id>user_external</id> + <name>External user support</name> + <description>Use external user authentication methods</description> + <licence>AGPL</licence> + <author>Robin Appelman</author> + <require>4</require> + <shipped>true</shipped> + <types> + <authentication/> + </types> +</info> diff --git a/apps/user_external/appinfo/version b/apps/user_external/appinfo/version new file mode 100644 index 00000000000..ceab6e11ece --- /dev/null +++ b/apps/user_external/appinfo/version @@ -0,0 +1 @@ +0.1
\ No newline at end of file diff --git a/apps/user_external/lib/ftp.php b/apps/user_external/lib/ftp.php new file mode 100644 index 00000000000..e03e17d2b6a --- /dev/null +++ b/apps/user_external/lib/ftp.php @@ -0,0 +1,45 @@ +<?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_User_FTP extends OC_User_Backend{ + private $host; + private $secure; + private $protocol; + + public function __construct($host,$secure=false){ + $this->host=$host; + $this->secure=$secure; + $this->protocol='ftp'; + if($this->secure){ + $this->protocol.='s'; + } + $this->protocol.='://'; + } + + /** + * @brief Check if the password is correct + * @param $uid The username + * @param $password The password + * @returns true/false + * + * Check if the password is correct without logging in the user + */ + public function checkPassword($uid, $password){ + $url=$this->protocol.$uid.':'.$password.'@'.$this->host.'/'; + $result=@opendir($url); + if(is_resource($result)){ + return $uid; + }else{ + return false; + } + } + + public function userExists($uid){ + return true; + } +} diff --git a/apps/user_external/lib/imap.php b/apps/user_external/lib/imap.php new file mode 100644 index 00000000000..584e9804b18 --- /dev/null +++ b/apps/user_external/lib/imap.php @@ -0,0 +1,40 @@ +<?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_User_IMAP extends OC_User_Backend{ + private $mailbox; + + public function __construct($mailbox){ + $this->mailbox=$mailbox; + } + + /** + * @brief Check if the password is correct + * @param $uid The username + * @param $password The password + * @returns true/false + * + * Check if the password is correct without logging in the user + */ + public function checkPassword($uid, $password){ + $mbox = @imap_open($this->mailbox, $uid, $password); + imap_errors(); + imap_alerts(); + if($mbox){ + imap_close($mbox); + return $uid; + }else{ + return false; + } + } + + public function userExists($uid){ + return true; + } +} + diff --git a/apps/user_external/lib/smb.php b/apps/user_external/lib/smb.php new file mode 100644 index 00000000000..44d2b7903d8 --- /dev/null +++ b/apps/user_external/lib/smb.php @@ -0,0 +1,43 @@ +<?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_User_SMB extends OC_User_Backend{ + private $host; + + const smbclient='smbclient'; + const loginError='NT_STATUS_LOGON_FAILURE'; + + public function __construct($host){ + $this->host=$host; + } + + /** + * @brief Check if the password is correct + * @param $uid The username + * @param $password The password + * @returns true/false + * + * Check if the password is correct without logging in the user + */ + public function checkPassword($uid, $password){ + $uidEscaped=escapeshellarg($uid); + $password=escapeshellarg($password); + $result=array(); + $command=self::smbclient.' //'.$this->host.'/dummy -U'.$uidEscaped.'%'.$password; + $result=exec($command,$result); + if(substr($result,-strlen(self::loginError))==self::loginError){ + return false; + }else{ + return $uid; + } + } + + public function userExists($uid){ + return true; + } +}
\ No newline at end of file diff --git a/apps/user_external/tests/config.php b/apps/user_external/tests/config.php new file mode 100644 index 00000000000..64ee141d32d --- /dev/null +++ b/apps/user_external/tests/config.php @@ -0,0 +1,28 @@ +<?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. + */ + +return array( + 'imap'=>array( + 'run'=>false, + 'mailbox'=>'{imap.gmail.com:993/imap/ssl}INBOX', //see http://php.net/manual/en/function.imap-open.php + 'user'=>'foo',//valid username/password combination + 'password'=>'bar', + ), + 'smb'=>array( + 'run'=>false, + 'host'=>'localhost', + 'user'=>'test',//valid username/password combination + 'password'=>'test', + ), + 'ftp'=>array( + 'run'=>false, + 'host'=>'localhost', + 'user'=>'test',//valid username/password combination + 'password'=>'test', + ), +); diff --git a/apps/user_external/tests/ftp.php b/apps/user_external/tests/ftp.php new file mode 100644 index 00000000000..0cf7565f9c6 --- /dev/null +++ b/apps/user_external/tests/ftp.php @@ -0,0 +1,34 @@ +<?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_User_FTP extends UnitTestCase{ + /** + * @var OC_User_IMAP $instance + */ + private $instance; + + private function getConfig(){ + return include(__DIR__.'/config.php'); + } + + function skip(){ + $config=$this->getConfig(); + $this->skipUnless($config['ftp']['run']); + } + + function setUp(){ + $config=$this->getConfig(); + $this->instance=new OC_User_FTP($config['ftp']['host']); + } + + function testLogin(){ + $config=$this->getConfig(); + $this->assertEqual($config['ftp']['user'],$this->instance->checkPassword($config['ftp']['user'],$config['ftp']['password'])); + $this->assertFalse($this->instance->checkPassword($config['ftp']['user'],$config['ftp']['password'].'foo')); + } +} diff --git a/apps/user_external/tests/imap.php b/apps/user_external/tests/imap.php new file mode 100644 index 00000000000..c703b32107f --- /dev/null +++ b/apps/user_external/tests/imap.php @@ -0,0 +1,34 @@ +<?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_User_Imap extends UnitTestCase{ + /** + * @var OC_User_IMAP $instance + */ + private $instance; + + private function getConfig(){ + return include(__DIR__.'/config.php'); + } + + function skip(){ + $config=$this->getConfig(); + $this->skipUnless($config['imap']['run']); + } + + function setUp(){ + $config=$this->getConfig(); + $this->instance=new OC_User_IMAP($config['imap']['mailbox']); + } + + function testLogin(){ + $config=$this->getConfig(); + $this->assertEqual($config['imap']['user'],$this->instance->checkPassword($config['imap']['user'],$config['imap']['password'])); + $this->assertFalse($this->instance->checkPassword($config['imap']['user'],$config['imap']['password'].'foo')); + } +} diff --git a/apps/user_external/tests/smb.php b/apps/user_external/tests/smb.php new file mode 100644 index 00000000000..1ed7eb934be --- /dev/null +++ b/apps/user_external/tests/smb.php @@ -0,0 +1,34 @@ +<?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_User_SMB extends UnitTestCase{ + /** + * @var OC_User_IMAP $instance + */ + private $instance; + + private function getConfig(){ + return include(__DIR__.'/config.php'); + } + + function skip(){ + $config=$this->getConfig(); + $this->skipUnless($config['smb']['run']); + } + + function setUp(){ + $config=$this->getConfig(); + $this->instance=new OC_User_SMB($config['smb']['host']); + } + + function testLogin(){ + $config=$this->getConfig(); + $this->assertEqual($config['smb']['user'],$this->instance->checkPassword($config['smb']['user'],$config['smb']['password'])); + $this->assertFalse($this->instance->checkPassword($config['smb']['user'],$config['smb']['password'].'foo')); + } +} diff --git a/apps/user_ldap/appinfo/app.php b/apps/user_ldap/appinfo/app.php index 330574c1d42..3c6da47d71a 100644 --- a/apps/user_ldap/appinfo/app.php +++ b/apps/user_ldap/appinfo/app.php @@ -21,15 +21,17 @@ * */ -require_once('apps/user_ldap/lib_ldap.php'); -require_once('apps/user_ldap/user_ldap.php'); -require_once('apps/user_ldap/group_ldap.php'); +OCP\App::registerAdmin('user_ldap', 'settings'); -OCP\App::registerAdmin('user_ldap','settings'); +$connector = new OCA\user_ldap\lib\Connection('user_ldap'); +$userBackend = new OCA\user_ldap\USER_LDAP(); +$userBackend->setConnector($connector); +$groupBackend = new OCA\user_ldap\GROUP_LDAP(); +$groupBackend->setConnector($connector); // register user backend -OC_User::useBackend( 'LDAP' ); -OC_Group::useBackend( new OC_GROUP_LDAP() ); +OC_User::useBackend($userBackend); +OC_Group::useBackend($groupBackend); // add settings page to navigation $entry = array( diff --git a/apps/user_ldap/group_ldap.php b/apps/user_ldap/group_ldap.php index d438c7d84df..b9f4bdf1990 100644 --- a/apps/user_ldap/group_ldap.php +++ b/apps/user_ldap/group_ldap.php @@ -21,24 +21,22 @@ * */ -class OC_GROUP_LDAP extends OC_Group_Backend { -// //group specific settings - protected $ldapGroupFilter; - protected $ldapGroupMemberAssocAttr; - protected $configured = false; +namespace OCA\user_ldap; + +class GROUP_LDAP extends lib\Access implements \OCP\GroupInterface { + protected $enabled = false; protected $_group_user = array(); protected $_user_groups = array(); protected $_group_users = array(); protected $_groups = array(); - public function __construct() { - $this->ldapGroupFilter = OCP\Config::getAppValue('user_ldap', 'ldap_group_filter', '(objectClass=posixGroup)'); - $this->ldapGroupMemberAssocAttr = OCP\Config::getAppValue('user_ldap', 'ldap_group_member_assoc_attribute', 'uniqueMember'); - - if(!empty($this->ldapGroupFilter) && !empty($this->ldapGroupMemberAssocAttr)) { - $this->configured = true; + public function setConnector(lib\Connection &$connection) { + parent::setConnector($connection); + if(empty($this->connection->ldapGroupFilter) || empty($this->connection->ldapGroupMemberAssocAttr)) { + $this->enabled = false; } + $this->enabled = true; } /** @@ -50,31 +48,31 @@ class OC_GROUP_LDAP extends OC_Group_Backend { * Checks whether the user is member of a group or not. */ public function inGroup($uid, $gid) { - if(!$this->configured) { + if(!$this->enabled) { return false; } if(isset($this->_group_user[$gid][$uid])) { return $this->_group_user[$gid][$uid]; } - $dn_user = OC_LDAP::username2dn($uid); - $dn_group = OC_LDAP::groupname2dn($gid); + $dn_user = $this->username2dn($uid); + $dn_group = $this->groupname2dn($gid); // just in case if(!$dn_group || !$dn_user) { return false; } //usually, LDAP attributes are said to be case insensitive. But there are exceptions of course. - $members = OC_LDAP::readAttribute($dn_group, $this->ldapGroupMemberAssocAttr); + $members = $this->readAttribute($dn_group, $this->connection->ldapGroupMemberAssocAttr); if(!$members) { return false; } //extra work if we don't get back user DNs //TODO: this can be done with one LDAP query - if(strtolower($this->ldapGroupMemberAssocAttr) == 'memberuid') { + if(strtolower($this->connection->ldapGroupMemberAssocAttr) == 'memberuid') { $dns = array(); foreach($members as $mid) { - $filter = str_replace('%uid', $mid, OC_LDAP::conf('ldapLoginFilter')); - $ldap_users = OC_LDAP::fetchListOfUsers($filter, 'dn'); + $filter = str_replace('%uid', $mid, $this->connection->ldapLoginFilter); + $ldap_users = $this->fetchListOfUsers($filter, 'dn'); if(count($ldap_users) < 1) { continue; } @@ -96,36 +94,37 @@ class OC_GROUP_LDAP extends OC_Group_Backend { * if the user exists at all. */ public function getUserGroups($uid) { - if(!$this->configured) { + if(!$this->enabled) { return array(); } if(isset($this->_user_groups[$uid])) { return $this->_user_groups[$uid]; } - $userDN = OC_LDAP::username2dn($uid); + $userDN = $this->username2dn($uid); if(!$userDN) { $this->_user_groups[$uid] = array(); return array(); } //uniqueMember takes DN, memberuid the uid, so we need to distinguish - if((strtolower($this->ldapGroupMemberAssocAttr) == 'uniquemember') - || (strtolower($this->ldapGroupMemberAssocAttr) == 'member')) { + if((strtolower($this->connection->ldapGroupMemberAssocAttr) == 'uniquemember') + || (strtolower($this->connection->ldapGroupMemberAssocAttr) == 'member') + ) { $uid = $userDN; - } else if(strtolower($this->ldapGroupMemberAssocAttr) == 'memberuid') { - $result = OC_LDAP::readAttribute($userDN, 'uid'); + } else if(strtolower($this->connection->ldapGroupMemberAssocAttr) == 'memberuid') { + $result = $this->readAttribute($userDN, 'uid'); $uid = $result[0]; } else { // just in case $uid = $userDN; } - $filter = OC_LDAP::combineFilterWithAnd(array( - $this->ldapGroupFilter, - $this->ldapGroupMemberAssocAttr.'='.$uid + $filter = $this->combineFilterWithAnd(array( + $this->connection->ldapGroupFilter, + $this->connection->ldapGroupMemberAssocAttr.'='.$uid )); - $groups = OC_LDAP::fetchListOfGroups($filter, array(OC_LDAP::conf('ldapGroupDisplayName'),'dn')); - $this->_user_groups[$uid] = array_unique(OC_LDAP::ownCloudGroupNames($groups), SORT_LOCALE_STRING); + $groups = $this->fetchListOfGroups($filter, array($this->connection->ldapGroupDisplayName,'dn')); + $this->_user_groups[$uid] = array_unique($this->ownCloudGroupNames($groups), SORT_LOCALE_STRING); return $this->_user_groups[$uid]; } @@ -135,44 +134,44 @@ class OC_GROUP_LDAP extends OC_Group_Backend { * @returns array with user ids */ public function usersInGroup($gid) { - if(!$this->configured) { + if(!$this->enabled) { return array(); } if(isset($this->_group_users[$gid])) { return $this->_group_users[$gid]; } - $groupDN = OC_LDAP::groupname2dn($gid); + $groupDN = $this->groupname2dn($gid); if(!$groupDN) { $this->_group_users[$gid] = array(); return array(); } - $members = OC_LDAP::readAttribute($groupDN, $this->ldapGroupMemberAssocAttr); + $members = $this->readAttribute($groupDN, $this->connection->ldapGroupMemberAssocAttr); if(!$members) { $this->_group_users[$gid] = array(); return array(); } $result = array(); - $isMemberUid = (strtolower($this->ldapGroupMemberAssocAttr) == 'memberuid'); + $isMemberUid = (strtolower($this->connection->ldapGroupMemberAssocAttr) == 'memberuid'); foreach($members as $member) { if($isMemberUid) { - $filter = OCP\Util::mb_str_replace('%uid', $member, OC_LDAP::conf('ldapLoginFilter'), 'UTF-8'); - $ldap_users = OC_LDAP::fetchListOfUsers($filter, 'dn'); + $filter = \OCP\Util::mb_str_replace('%uid', $member, $this->connection->ldapLoginFilter, 'UTF-8'); + $ldap_users = $this->fetchListOfUsers($filter, 'dn'); if(count($ldap_users) < 1) { continue; } - $result[] = OC_LDAP::dn2username($ldap_users[0]); + $result[] = $this->dn2username($ldap_users[0]); continue; } else { - if($ocname = OC_LDAP::dn2username($member)){ + if($ocname = $this->dn2username($member)) { $result[] = $ocname; } } } if(!$isMemberUid) { - $result = array_intersect($result, OCP\User::getUsers()); + $result = array_intersect($result, \OCP\User::getUsers()); } $this->_group_users[$gid] = array_unique($result, SORT_LOCALE_STRING); return $this->_group_users[$gid]; @@ -185,12 +184,12 @@ class OC_GROUP_LDAP extends OC_Group_Backend { * Returns a list with all groups */ public function getGroups() { - if(!$this->configured) { + if(!$this->enabled) { return array(); } if(empty($this->_groups)) { - $ldap_groups = OC_LDAP::fetchListOfGroups($this->ldapGroupFilter, array(OC_LDAP::conf('ldapGroupDisplayName'), 'dn')); - $this->_groups = OC_LDAP::ownCloudGroupNames($ldap_groups); + $ldap_groups = $this->fetchListOfGroups($this->connection->ldapGroupFilter, array($this->connection->ldapGroupDisplayName, 'dn')); + $this->_groups = $this->ownCloudGroupNames($ldap_groups); } return $this->_groups; } @@ -203,4 +202,17 @@ class OC_GROUP_LDAP extends OC_Group_Backend { public function groupExists($gid){ return in_array($gid, $this->getGroups()); } + + /** + * @brief Check if backend implements actions + * @param $actions bitwise-or'ed actions + * @returns boolean + * + * Returns the supported actions as int to be + * compared with OC_USER_BACKEND_CREATE_USER etc. + */ + public function implementsActions($actions) { + //always returns false, because possible actions are modifying actions. We do not write to LDAP, at least for now. + return false; + } }
\ No newline at end of file diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php new file mode 100644 index 00000000000..870f6330edd --- /dev/null +++ b/apps/user_ldap/lib/access.php @@ -0,0 +1,593 @@ +<?php + +/** + * ownCloud – LDAP Access + * + * @author Arthur Schiwon + * @copyright 2012 Arthur Schiwon blizzz@owncloud.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/>. + * + */ + +namespace OCA\user_ldap\lib; + +abstract class Access { + protected $connection; + + public function setConnector(Connection &$connection) { + $this->connection = $connection; + } + + private function checkConnection() { + return ($this->connection instanceof Connection); + } + + /** + * @brief reads a given attribute for an LDAP record identified by a DN + * @param $dn the record in question + * @param $attr the attribute that shall be retrieved + * @returns the values in an array on success, false otherwise + * + * Reads an attribute from an LDAP entry + */ + public function readAttribute($dn, $attr) { + if(!$this->checkConnection()) { + \OCP\Util::writeLog('user_ldap', 'No LDAP Connector assigned, access impossible for readAttribute.', \OCP\Util::WARN); + return false; + } + $cr = $this->connection->getConnectionResource(); + $rr = @ldap_read($cr, $dn, 'objectClass=*', array($attr)); + if(!is_resource($rr)) { + \OCP\Util::writeLog('user_ldap', 'readAttribute failed for DN '.$dn, \OCP\Util::DEBUG); + //in case an error occurs , e.g. object does not exist + return false; + } + $er = ldap_first_entry($cr, $rr); + //LDAP attributes are not case sensitive + $result = \OCP\Util::mb_array_change_key_case(ldap_get_attributes($cr, $er), MB_CASE_LOWER, 'UTF-8'); + $attr = mb_strtolower($attr, 'UTF-8'); + + if(isset($result[$attr]) && $result[$attr]['count'] > 0) { + $values = array(); + for($i=0;$i<$result[$attr]['count'];$i++) { + $values[] = $this->resemblesDN($attr) ? $this->sanitizeDN($result[$attr][$i]) : $result[$attr][$i]; + } + return $values; + } + return false; + } + + /** + * @brief checks wether the given attribute`s valua is probably a DN + * @param $attr the attribute in question + * @return if so true, otherwise false + */ + private function resemblesDN($attr) { + $resemblingAttributes = array( + 'dn', + 'uniquemember', + 'member' + ); + return in_array($attr, $resemblingAttributes); + } + + /** + * @brief sanitizes a DN received from the LDAP server + * @param $dn the DN in question + * @return the sanitized DN + */ + private function sanitizeDN($dn) { + //OID sometimes gives back DNs with whitespace after the comma a la "uid=foo, cn=bar, dn=..." We need to tackle this! + $dn = preg_replace('/([^\\\]),(\s+)/u', '\1,', $dn); + + //make comparisons and everything work + $dn = mb_strtolower($dn, 'UTF-8'); + + return $dn; + } + + /** + * gives back the database table for the query + */ + private function getMapTable($isUser) { + if($isUser) { + return '*PREFIX*ldap_user_mapping'; + } else { + return '*PREFIX*ldap_group_mapping'; + } + } + + /** + * @brief returns the LDAP DN for the given internal ownCloud name of the group + * @param $name the ownCloud name in question + * @returns string with the LDAP DN on success, otherwise false + * + * returns the LDAP DN for the given internal ownCloud name of the group + */ + public function groupname2dn($name) { + return $this->ocname2dn($name, false); + } + + /** + * @brief returns the LDAP DN for the given internal ownCloud name of the user + * @param $name the ownCloud name in question + * @returns string with the LDAP DN on success, otherwise false + * + * returns the LDAP DN for the given internal ownCloud name of the user + */ + public function username2dn($name) { + $dn = $this->ocname2dn($name, true); + if($dn) { + return $dn; + } else { + //fallback: user is not mapped + $filter = $this->combineFilterWithAnd(array( + $this->connection->ldapUserFilter, + $this->connection->ldapUserDisplayName . '=' . $name, + )); + $result = $this->searchUsers($filter, 'dn'); + if(isset($result[0]['dn'])) { + $this->mapComponent($result[0], $name, true); + return $result[0]; + } + } + + return false; + } + + /** + * @brief returns the LDAP DN for the given internal ownCloud name + * @param $name the ownCloud name in question + * @param $isUser is it a user? otherwise group + * @returns string with the LDAP DN on success, otherwise false + * + * returns the LDAP DN for the given internal ownCloud name + */ + private function ocname2dn($name, $isUser) { + $table = $this->getMapTable($isUser); + + $query = \OCP\DB::prepare(' + SELECT ldap_dn + FROM '.$table.' + WHERE owncloud_name = ? + '); + + $record = $query->execute(array($name))->fetchOne(); + return $record; + } + + /** + * @brief returns the internal ownCloud name for the given LDAP DN of the group + * @param $dn the dn of the group object + * @param $ldapname optional, the display name of the object + * @returns string with with the name to use in ownCloud, false on DN outside of search DN + * + * returns the internal ownCloud name for the given LDAP DN of the group + */ + public function dn2groupname($dn, $ldapname = null) { + if(mb_strripos($dn, $this->connection->ldapBaseGroups, 0, 'UTF-8') !== (mb_strlen($dn, 'UTF-8')-mb_strlen($this->connection->ldapBaseGroups, 'UTF-8'))) { + return false; + } + return $this->dn2ocname($dn, $ldapname, false); + } + + /** + * @brief returns the internal ownCloud name for the given LDAP DN of the user + * @param $dn the dn of the user object + * @param $ldapname optional, the display name of the object + * @returns string with with the name to use in ownCloud + * + * returns the internal ownCloud name for the given LDAP DN of the user, false on DN outside of search DN + */ + public function dn2username($dn, $ldapname = null) { + if(mb_strripos($dn, $this->connection->ldapBaseUsers, 0, 'UTF-8') !== (mb_strlen($dn, 'UTF-8')-mb_strlen($this->connection->ldapBaseUsers, 'UTF-8'))) { + return false; + } + return $this->dn2ocname($dn, $ldapname, true); + } + + /** + * @brief returns an internal ownCloud name for the given LDAP DN + * @param $dn the dn of the user object + * @param $ldapname optional, the display name of the object + * @param $isUser optional, wether it is a user object (otherwise group assumed) + * @returns string with with the name to use in ownCloud + * + * returns the internal ownCloud name for the given LDAP DN of the user, false on DN outside of search DN + */ + public function dn2ocname($dn, $ldapname = null, $isUser = true) { + $dn = $this->sanitizeDN($dn); + $table = $this->getMapTable($isUser); + if($isUser) { + $nameAttribute = $this->connection->ldapUserDisplayName; + } else { + $nameAttribute = $this->connection->ldapGroupDisplayName; + } + + $query = \OCP\DB::prepare(' + SELECT owncloud_name + FROM '.$table.' + WHERE ldap_dn = ? + '); + + $component = $query->execute(array($dn))->fetchOne(); + if($component) { + return $component; + } + + if(is_null($ldapname)) { + $ldapname = $this->readAttribute($dn, $nameAttribute); + $ldapname = $ldapname[0]; + } + $ldapname = $this->sanitizeUsername($ldapname); + + //a new user/group! Then let's try to add it. We're shooting into the blue with the user/group name, assuming that in most cases there will not be a conflict. Otherwise an error will occur and we will continue with our second shot. + if($this->mapComponent($dn, $ldapname, $isUser)) { + return $ldapname; + } + + //doh! There is a conflict. We need to distinguish between users/groups. Adding indexes is an idea, but not much of a help for the user. The DN is ugly, but for now the only reasonable way. But we transform it to a readable format and remove the first part to only give the path where this object is located. + $oc_name = $this->alternateOwnCloudName($ldapname, $dn); + if($this->mapComponent($dn, $oc_name, $isUser)) { + return $oc_name; + } + + //TODO: do not simple die away! + //and this of course should never been thrown :) + throw new Exception('LDAP backend: unexpected collision of DN and ownCloud Name.'); + } + + /** + * @brief gives back the user names as they are used ownClod internally + * @param $ldapGroups an array with the ldap Users result in style of array ( array ('dn' => foo, 'uid' => bar), ... ) + * @returns an array with the user names to use in ownCloud + * + * gives back the user names as they are used ownClod internally + */ + public function ownCloudUserNames($ldapUsers) { + return $this->ldap2ownCloudNames($ldapUsers, true); + } + + /** + * @brief gives back the group names as they are used ownClod internally + * @param $ldapGroups an array with the ldap Groups result in style of array ( array ('dn' => foo, 'cn' => bar), ... ) + * @returns an array with the group names to use in ownCloud + * + * gives back the group names as they are used ownClod internally + */ + public function ownCloudGroupNames($ldapGroups) { + return $this->ldap2ownCloudNames($ldapGroups, false); + } + + private function ldap2ownCloudNames($ldapObjects, $isUsers) { + if($isUsers) { + $knownObjects = $this->mappedUsers(); + $nameAttribute = $this->connection->ldapUserDisplayName; + } else { + $knownObjects = $this->mappedGroups(); + $nameAttribute = $this->connection->ldapGroupDisplayName; + } + $ownCloudNames = array(); + + foreach($ldapObjects as $ldapObject) { + $key = \OCP\Util::recursiveArraySearch($knownObjects, $ldapObject['dn']); + + //everything is fine when we know the group + if($key !== false) { + $ownCloudNames[] = $knownObjects[$key]['owncloud_name']; + continue; + } + + //a new group! Then let's try to add it. We're shooting into the blue with the group name, assuming that in most cases there will not be a conflict. But first make sure, that the display name contains only allowed characters. + $ocname = $this->sanitizeUsername($ldapObject[$nameAttribute]); + if($this->mapComponent($ldapObject['dn'], $ocname, $isUsers)) { + $ownCloudNames[] = $ocname; + continue; + } + + //doh! There is a conflict. We need to distinguish between groups. Adding indexes is an idea, but not much of a help for the user. The DN is ugly, but for now the only reasonable way. But we transform it to a readable format and remove the first part to only give the path where this entry is located. + $ocname = $this->alternateOwnCloudName($ocname, $ldapObject['dn']); + if($this->mapComponent($ldapObject['dn'], $ocname, $isUsers)) { + $ownCloudNames[] = $ocname; + continue; + } + + //TODO: do not simple die away + //and this of course should never been thrown :) + throw new Exception('LDAP backend: unexpected collision of DN and ownCloud Name.'); + } + return $ownCloudNames; + } + + /** + * @brief creates a hopefully unique name for owncloud based on the display name and the dn of the LDAP object + * @param $name the display name of the object + * @param $dn the dn of the object + * @returns string with with the name to use in ownCloud + * + * creates a hopefully unique name for owncloud based on the display name and the dn of the LDAP object + */ + private function alternateOwnCloudName($name, $dn) { + $ufn = ldap_dn2ufn($dn); + $name = $name . '@' . trim(\OCP\Util::mb_substr_replace($ufn, '', 0, mb_strpos($ufn, ',', 0, 'UTF-8'), 'UTF-8')); + $name = $this->sanitizeUsername($name); + return $name; + } + + /** + * @brief retrieves all known groups from the mappings table + * @returns array with the results + * + * retrieves all known groups from the mappings table + */ + private function mappedGroups() { + return $this->mappedComponents(false); + } + + /** + * @brief retrieves all known users from the mappings table + * @returns array with the results + * + * retrieves all known users from the mappings table + */ + private function mappedUsers() { + return $this->mappedComponents(true); + } + + private function mappedComponents($isUsers) { + $table = $this->getMapTable($isUsers); + + $query = \OCP\DB::prepare(' + SELECT ldap_dn, owncloud_name + FROM '. $table + ); + + return $query->execute()->fetchAll(); + } + + /** + * @brief inserts a new user or group into the mappings table + * @param $dn the record in question + * @param $ocname the name to use in ownCloud + * @param $isUser is it a user or a group? + * @returns true on success, false otherwise + * + * inserts a new user or group into the mappings table + */ + private function mapComponent($dn, $ocname, $isUser = true) { + $table = $this->getMapTable($isUser); + $dn = $this->sanitizeDN($dn); + + $sqlAdjustment = ''; + $dbtype = \OCP\Config::getSystemValue('dbtype'); + if($dbtype == 'mysql') { + $sqlAdjustment = 'FROM dual'; + } + + $insert = \OCP\DB::prepare(' + INSERT INTO '.$table.' (ldap_dn, owncloud_name) + SELECT ?,? + '.$sqlAdjustment.' + WHERE NOT EXISTS ( + SELECT 1 + FROM '.$table.' + WHERE ldap_dn = ? + OR owncloud_name = ? ) + '); + + $res = $insert->execute(array($dn, $ocname, $dn, $ocname)); + + if(\OCP\DB::isError($res)) { + return false; + } + + $insRows = $res->numRows(); + + if($insRows == 0) { + return false; + } + + return true; + } + + public function fetchListOfUsers($filter, $attr) { + return $this->fetchList($this->searchUsers($filter, $attr), (count($attr) > 1)); + } + + public function fetchListOfGroups($filter, $attr) { + return $this->fetchList($this->searchGroups($filter, $attr), (count($attr) > 1)); + } + + private function fetchList($list, $manyAttributes) { + if(is_array($list)) { + if($manyAttributes) { + return $list; + } else { + return array_unique($list, SORT_LOCALE_STRING); + } + } + + //error cause actually, maybe throw an exception in future. + return array(); + } + + /** + * @brief executes an LDAP search, optimized for Users + * @param $filter the LDAP filter for the search + * @param $attr optional, when a certain attribute shall be filtered out + * @returns array with the search result + * + * Executes an LDAP search + */ + public function searchUsers($filter, $attr = null) { + return $this->search($filter, $this->connection->ldapBaseUsers, $attr); + } + + /** + * @brief executes an LDAP search, optimized for Groups + * @param $filter the LDAP filter for the search + * @param $attr optional, when a certain attribute shall be filtered out + * @returns array with the search result + * + * Executes an LDAP search + */ + public function searchGroups($filter, $attr = null) { + return $this->search($filter, $this->connection->ldapBaseGroups, $attr); + } + + /** + * @brief executes an LDAP search + * @param $filter the LDAP filter for the search + * @param $base the LDAP subtree that shall be searched + * @param $attr optional, when a certain attribute shall be filtered out + * @returns array with the search result + * + * Executes an LDAP search + */ + private function search($filter, $base, $attr = null) { + if(!is_null($attr) && !is_array($attr)) { + $attr = array(mb_strtolower($attr, 'UTF-8')); + } + + // See if we have a resource + $link_resource = $this->connection->getConnectionResource(); + if(is_resource($link_resource)) { + $sr = ldap_search($link_resource, $base, $filter, $attr); + $findings = ldap_get_entries($link_resource, $sr ); + + // if we're here, probably no connection resource is returned. + // to make ownCloud behave nicely, we simply give back an empty array. + if(is_null($findings)) { + return array(); + } + } else { + // Seems like we didn't find any resource. + // Return an empty array just like before. + \OCP\Util::writeLog('user_ldap', 'Could not search, because resource is missing.', \OCP\Util::DEBUG); + return array(); + } + + if(!is_null($attr)) { + $selection = array(); + $multiarray = false; + if(count($attr) > 1) { + $multiarray = true; + $i = 0; + } + foreach($findings as $item) { + if(!is_array($item)) { + continue; + } + $item = \OCP\Util::mb_array_change_key_case($item, MB_CASE_LOWER, 'UTF-8'); + + if($multiarray) { + foreach($attr as $key) { + $key = mb_strtolower($key, 'UTF-8'); + if(isset($item[$key])) { + if($key != 'dn') { + $selection[$i][$key] = $this->resemblesDN($key) ? $this->sanitizeDN($item[$key][0]) : $item[$key][0]; + } else { + $selection[$i][$key] = $this->sanitizeDN($item[$key]); + } + } + + } + $i++; + } else { + //tribute to case insensitivity + $key = mb_strtolower($attr[0], 'UTF-8'); + + if(isset($item[$key])) { + if($this->resemblesDN($key)) { + $selection[] = $this->sanitizeDN($item[$key]); + } else { + $selection[] = $item[$key]; + } + } + } + } + return $selection; + } + return $findings; + } + + public function sanitizeUsername($name) { + if($this->connection->ldapIgnoreNamingRules) { + return $name; + } + + //REPLACEMENTS + $name = \OCP\Util::mb_str_replace(' ', '_', $name, 'UTF-8'); + + //every remaining unallowed characters will be removed + $name = preg_replace('/[^a-zA-Z0-9_.@-]/u', '', $name); + + return $name; + } + + /** + * @brief combines the input filters with AND + * @param $filters array, the filters to connect + * @returns the combined filter + * + * Combines Filter arguments with AND + */ + public function combineFilterWithAnd($filters) { + return $this->combineFilter($filters, '&'); + } + + /** + * @brief combines the input filters with AND + * @param $filters array, the filters to connect + * @returns the combined filter + * + * Combines Filter arguments with AND + */ + public function combineFilterWithOr($filters) { + return $this->combineFilter($filters, '|'); + } + + /** + * @brief combines the input filters with given operator + * @param $filters array, the filters to connect + * @param $operator either & or | + * @returns the combined filter + * + * Combines Filter arguments with AND + */ + private function combineFilter($filters, $operator) { + $combinedFilter = '('.$operator; + foreach($filters as $filter) { + if($filter[0] != '(') { + $filter = '('.$filter.')'; + } + $combinedFilter.=$filter; + } + $combinedFilter.=')'; + return $combinedFilter; + } + + public function areCredentialsValid($name, $password) { + $testConnection = clone $this->connection; + $credentials = array( + 'ldapAgentName' => $name, + 'ldapAgentPassword' => $password + ); + if(!$testConnection->setConfiguration($credentials)) { + return false; + } + return $testConnection->bind(); + } +}
\ No newline at end of file diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php new file mode 100644 index 00000000000..c8ba9dad70e --- /dev/null +++ b/apps/user_ldap/lib/connection.php @@ -0,0 +1,245 @@ +<?php + +/** + * ownCloud – LDAP Access + * + * @author Arthur Schiwon + * @copyright 2012 Arthur Schiwon blizzz@owncloud.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/>. + * + */ + +namespace OCA\user_ldap\lib; + +class Connection { + private $ldapConnectionRes = null; + private $configID; + private $configured = false; + + //cached settings + protected $config = array( + 'ldapHost' => null, + 'ldapPort' => null, + 'ldapBase' => null, + 'ldapBaseUsers' => null, + 'ldapBaseGroups' => null, + 'ldapAgentName' => null, + 'ldapAgentPassword' => null, + 'ldapTLS' => null, + 'ldapNoCase' => null, + 'ldapIgnoreNamingRules' => null, + 'ldapUserDisplayName' => null, + 'ldapUserFilter' => null, + 'ldapGroupFilter' => null, + 'ldapGroupDisplayName' => null, + 'ldapLoginFilter' => null, + 'ldapQuotaAttribute' => null, + 'ldapQuotaDefault' => null, + 'ldapEmailAttribute' => null, + ); + + public function __construct($configID = 'user_ldap') { + $this->configID = $configID; + } + + public function __destruct() { + @ldap_unbind($this->ldapConnectionRes); + } + + public function __get($name) { + if(!$this->configured) { + $this->readConfiguration(); + } + + if(isset($this->config[$name])) { + return $this->config[$name]; + } + } + + /** + * @brief initializes the LDAP backend + * @param $force read the config settings no matter what + * + * initializes the LDAP backend + */ + public function init($force = false) { + $this->readConfiguration($force); + $this->establishConnection(); + } + + /** + * Returns the LDAP handler + */ + public function getConnectionResource() { + if(!$this->ldapConnectionRes) { + $this->init(); + } + if(is_null($this->ldapConnectionRes)) { + \OCP\Util::writeLog('user_ldap', 'Connection could not be established', \OCP\Util::ERROR); + } + return $this->ldapConnectionRes; + } + + /** + * Caches the general LDAP configuration. + */ + private function readConfiguration($force = false) { + \OCP\Util::writeLog('user_ldap','Checking conf state: isConfigured? '.print_r($this->configured, true).' isForce? '.print_r($force, true).' configID? '.print_r($this->configID, true), \OCP\Util::DEBUG); + if((!$this->configured || $force) && !is_null($this->configID)) { + \OCP\Util::writeLog('user_ldap','Reading the configuration', \OCP\Util::DEBUG); + $this->config['ldapHost'] = \OCP\Config::getAppValue($this->configID, 'ldap_host', ''); + $this->config['ldapPort'] = \OCP\Config::getAppValue($this->configID, 'ldap_port', 389); + $this->config['ldapAgentName'] = \OCP\Config::getAppValue($this->configID, 'ldap_dn',''); + $this->config['ldapAgentPassword'] = base64_decode(\OCP\Config::getAppValue($this->configID, 'ldap_agent_password','')); + $this->config['ldapBase'] = \OCP\Config::getAppValue($this->configID, 'ldap_base', ''); + $this->config['ldapBaseUsers'] = \OCP\Config::getAppValue($this->configID, 'ldap_base_users',$this->config['ldapBase']); + $this->config['ldapBaseGroups'] = \OCP\Config::getAppValue($this->configID, 'ldap_base_groups', $this->config['ldapBase']); + $this->config['ldapTLS'] = \OCP\Config::getAppValue($this->configID, 'ldap_tls',0); + $this->config['ldapNoCase'] = \OCP\Config::getAppValue($this->configID, 'ldap_nocase', 0); + $this->config['ldapUserDisplayName'] = mb_strtolower(\OCP\Config::getAppValue($this->configID, 'ldap_display_name', 'uid'), 'UTF-8'); + $this->config['ldapUserFilter'] = \OCP\Config::getAppValue($this->configID, 'ldap_userlist_filter','objectClass=person'); + $this->config['ldapGroupFilter'] = \OCP\Config::getAppValue($this->configID, 'ldap_group_filter','(objectClass=posixGroup)'); + $this->config['ldapLoginFilter'] = \OCP\Config::getAppValue($this->configID, 'ldap_login_filter', '(uid=%uid)'); + $this->config['ldapGroupDisplayName'] = mb_strtolower(\OCP\Config::getAppValue($this->configID, 'ldap_group_display_name', 'uid'), 'UTF-8'); + $this->config['ldapQuotaAttribute'] = \OCP\Config::getAppValue($this->configID, 'ldap_quota_attr', ''); + $this->config['ldapQuotaDefault'] = \OCP\Config::getAppValue($this->configID, 'ldap_quota_def', ''); + $this->config['ldapEmailAttribute'] = \OCP\Config::getAppValue($this->configID, 'ldap_email_attr', ''); + $this->config['ldapGroupMemberAssocAttr'] = \OCP\Config::getAppValue($this->configID, 'ldap_group_member_assoc_attribute', 'uniqueMember'); + $this->config['ldapIgnoreNamingRules'] = \OCP\Config::getSystemValue('ldapIgnoreNamingRules', false); + + $this->configured = $this->validateConfiguration(); + } + } + + /** + * @brief set LDAP configuration with values delivered by an array, not read from configuration + * @param $config array that holds the config parameters in an associated array + * @param &$setParameters optional; array where the set fields will be given to + * @return true if config validates, false otherwise. Check with $setParameters for detailed success on single parameters + */ + public function setConfiguration($config, &$setParameters = null) { + if(!is_array($config)) { + return false; + } + + foreach($config as $parameter => $value) { + if(isset($this->config[$parameter])) { + $this->config[$parameter] = $value; + if(is_array($setParameters)) { + $setParameters[] = $parameter; + } + } + } + + $this->configured = $this->validateConfiguration(); + + return $this->configured; + } + + /** + * @brief Validates the user specified configuration + * @returns true if configuration seems OK, false otherwise + */ + private function validateConfiguration() { + //first step: "soft" checks: settings that are not really necessary, but advisable. If left empty, give an info message + if(empty($this->config['ldapBaseUsers'])) { + \OCP\Util::writeLog('user_ldap', 'Base tree for Users is empty, using Base DN', \OCP\Util::INFO); + $this->config['ldapBaseUsers'] = $this->config['ldapBase']; + } + if(empty($this->config['ldapBaseGroups'])) { + \OCP\Util::writeLog('user_ldap', 'Base tree for Groups is empty, using Base DN', \OCP\Util::INFO); + $this->config['ldapBaseGroups'] = $this->config['ldapBase']; + } + if(empty($this->config['ldapGroupFilter']) && empty($this->config['ldapGroupMemberAssocAttr'])) { + \OCP\Util::writeLog('user_ldap', 'No group filter is specified, LDAP group feature will not be used.', \OCP\Util::INFO); + } + + //second step: critical checks. If left empty or filled wrong, set as unconfigured and give a warning. + $configurationOK = true; + if(empty($this->config['ldapHost'])) { + \OCP\Util::writeLog('user_ldap', 'No LDAP host given, won`t connect.', \OCP\Util::WARN); + $configurationOK = false; + } + if(empty($this->config['ldapPort'])) { + \OCP\Util::writeLog('user_ldap', 'No LDAP Port given, won`t connect.', \OCP\Util::WARN); + $configurationOK = false; + } + if((empty($this->config['ldapAgentName']) && !empty($this->config['ldapAgentPassword'])) + || (!empty($this->config['ldapAgentName']) && empty($this->config['ldapAgentPassword']))) { + \OCP\Util::writeLog('user_ldap', 'Either no password given for the user agent or a password is given, but no LDAP agent; won`t connect.', \OCP\Util::WARN); + $configurationOK = false; + } + //TODO: check if ldapAgentName is in DN form + if(empty($this->config['ldapBase']) && (empty($this->config['ldapBaseUsers']) && empty($this->config['ldapBaseGroups']))) { + \OCP\Util::writeLog('user_ldap', 'No Base DN given, won`t connect.', \OCP\Util::WARN); + $configurationOK = false; + } + if(empty($this->config['ldapUserDisplayName'])) { + \OCP\Util::writeLog('user_ldap', 'No user display name attribute specified, won`t connect.', \OCP\Util::WARN); + $configurationOK = false; + } + if(empty($this->config['ldapGroupDisplayName'])) { + \OCP\Util::writeLog('user_ldap', 'No group display name attribute specified, won`t connect.', \OCP\Util::WARN); + $configurationOK = false; + } + if(empty($this->config['ldapLoginFilter'])) { + \OCP\Util::writeLog('user_ldap', 'No login filter specified, won`t connect.', \OCP\Util::WARN); + $configurationOK = false; + } + if(mb_strpos($this->config['ldapLoginFilter'], '%uid', 0, 'UTF-8') === false) { + \OCP\Util::writeLog('user_ldap', 'Login filter does not contain %uid place holder, won`t connect.', \OCP\Util::WARN); + \OCP\Util::writeLog('user_ldap', 'Login filter was ' . $this->config['ldapLoginFilter'], \OCP\Util::DEBUG); + $configurationOK = false; + } + + return $configurationOK; + } + + /** + * Connects and Binds to LDAP + */ + private function establishConnection() { + if(!$this->configured) { + \OCP\Util::writeLog('user_ldap', 'Configuration is invalid, cannot connect', \OCP\Util::WARN); + return false; + } + if(!$this->ldapConnectionRes) { + $this->ldapConnectionRes = ldap_connect($this->config['ldapHost'], $this->config['ldapPort']); + if(ldap_set_option($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) { + if(ldap_set_option($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) { + if($this->config['ldapTLS']) { + ldap_start_tls($this->ldapConnectionRes); + } + } + } + + return $this->bind(); + } + } + + /** + * Binds to LDAP + */ + public function bind() { + $ldapLogin = @ldap_bind($this->getConnectionResource(), $this->config['ldapAgentName'], $this->config['ldapAgentPassword']); + if(!$ldapLogin) { + \OCP\Util::writeLog('user_ldap', 'Bind failed: ' . ldap_errno($this->ldapConnectionRes) . ': ' . ldap_error($this->ldapConnectionRes), \OCP\Util::ERROR); + $this->ldapConnectionRes = null; + return false; + } + return true; + } + +}
\ No newline at end of file diff --git a/apps/user_ldap/lib_ldap.php b/apps/user_ldap/lib_ldap.php deleted file mode 100644 index 08b09304d78..00000000000 --- a/apps/user_ldap/lib_ldap.php +++ /dev/null @@ -1,721 +0,0 @@ -<?php - -/** - * ownCloud – LDAP lib - * - * @author Arthur Schiwon - * @copyright 2012 Arthur Schiwon blizzz@owncloud.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/>. - * - */ - -define('LDAP_GROUP_MEMBER_ASSOC_ATTR','uniqueMember'); -define('LDAP_GROUP_DISPLAY_NAME_ATTR','cn'); - -//needed to unbind, because we use OC_LDAP only statically -class OC_LDAP_DESTRUCTOR { - public function __destruct() { - OC_LDAP::destruct(); - } -} - -class OC_LDAP { - static protected $ldapConnectionRes = false; - static protected $configured = false; - - //cached settings - static protected $ldapHost; - static protected $ldapPort; - static protected $ldapBase; - static protected $ldapBaseUsers; - static protected $ldapBaseGroups; - static protected $ldapAgentName; - static protected $ldapAgentPassword; - static protected $ldapTLS; - static protected $ldapNoCase; - static protected $ldapIgnoreNamingRules; - // user and group settings, that are needed in both backends - static protected $ldapUserDisplayName; - static protected $ldapUserFilter; - static protected $ldapGroupDisplayName; - static protected $ldapLoginFilter; - - static protected $__d; - - /** - * @brief initializes the LDAP backend - * @param $force read the config settings no matter what - * - * initializes the LDAP backend - */ - static public function init($force = false) { - if(is_null(self::$__d)) { - self::$__d = new OC_LDAP_DESTRUCTOR(); - } - self::readConfiguration($force); - self::establishConnection(); - } - - static public function destruct() { - @ldap_unbind(self::$ldapConnectionRes); - } - - /** - * @brief returns a read-only configuration value - * @param $key the name of the configuration value - * @returns the value on success, otherwise null - * - * returns a read-only configuration values - * - * we cannot work with getters, because it is a static class - */ - static public function conf($key) { - if(!self::$configured) { - self::init(); - } - - $availableProperties = array( - 'ldapUserDisplayName', - 'ldapGroupDisplayName', - 'ldapLoginFilter' - ); - - if(in_array($key, $availableProperties)) { - return self::$$key; - } - - return null; - } - - /** - * gives back the database table for the query - */ - static private function getMapTable($isUser) { - if($isUser) { - return '*PREFIX*ldap_user_mapping'; - } else { - return '*PREFIX*ldap_group_mapping'; - } - } - - /** - * @brief returns the LDAP DN for the given internal ownCloud name of the group - * @param $name the ownCloud name in question - * @returns string with the LDAP DN on success, otherwise false - * - * returns the LDAP DN for the given internal ownCloud name of the group - */ - static public function groupname2dn($name) { - return self::ocname2dn($name, false); - } - - /** - * @brief returns the LDAP DN for the given internal ownCloud name of the user - * @param $name the ownCloud name in question - * @returns string with the LDAP DN on success, otherwise false - * - * returns the LDAP DN for the given internal ownCloud name of the user - */ - static public function username2dn($name) { - $dn = self::ocname2dn($name, true); - if($dn) { - return $dn; - } else { - //fallback: user is not mapped - self::init(); - $filter = self::combineFilterWithAnd(array( - self::$ldapUserFilter, - self::$ldapUserDisplayName . '=' . $name, - )); - $result = self::searchUsers($filter, 'dn'); - if(isset($result[0]['dn'])) { - self::mapUser($result[0], $name); - return $result[0]; - } - } - - return false; - } - - static private function ocname2dn($name, $isUser) { - $table = self::getMapTable($isUser); - - $query = OCP\DB::prepare(' - SELECT ldap_dn - FROM '.$table.' - WHERE owncloud_name = ? - '); - - $record = $query->execute(array($name))->fetchOne(); - return $record; - } - - /** - * @brief returns the internal ownCloud name for the given LDAP DN of the group - * @param $dn the dn of the group object - * @param $ldapname optional, the display name of the object - * @returns string with with the name to use in ownCloud, false on DN outside of search DN - * - * returns the internal ownCloud name for the given LDAP DN of the group - */ - static public function dn2groupname($dn, $ldapname = null) { - if(mb_strripos($dn, self::$ldapBaseGroups, 0, 'UTF-8') !== (mb_strlen($dn, 'UTF-8')-mb_strlen(self::$ldapBaseGroups, 'UTF-8'))) { - return false; - } - return self::dn2ocname($dn, $ldapname, false); - } - - /** - * @brief returns the internal ownCloud name for the given LDAP DN of the user - * @param $dn the dn of the user object - * @param $ldapname optional, the display name of the object - * @returns string with with the name to use in ownCloud - * - * returns the internal ownCloud name for the given LDAP DN of the user, false on DN outside of search DN - */ - static public function dn2username($dn, $ldapname = null) { - if(mb_strripos($dn, self::$ldapBaseUsers, 0, 'UTF-8') !== (mb_strlen($dn, 'UTF-8')-mb_strlen(self::$ldapBaseUsers, 'UTF-8'))) { - return false; - } - return self::dn2ocname($dn, $ldapname, true); - } - - static public function dn2ocname($dn, $ldapname = null, $isUser = true) { - $dn = self::sanitizeDN($dn); - $table = self::getMapTable($isUser); - if($isUser) { - $nameAttribute = self::conf('ldapUserDisplayName'); - } else { - $nameAttribute = self::conf('ldapGroupDisplayName'); - } - - $query = OCP\DB::prepare(' - SELECT owncloud_name - FROM '.$table.' - WHERE ldap_dn = ? - '); - - $component = $query->execute(array($dn))->fetchOne(); - if($component) { - return $component; - } - - if(is_null($ldapname)) { - $ldapname = self::readAttribute($dn, $nameAttribute); - $ldapname = $ldapname[0]; - } - $ldapname = self::sanitizeUsername($ldapname); - - //a new user/group! Then let's try to add it. We're shooting into the blue with the user/group name, assuming that in most cases there will not be a conflict. Otherwise an error will occur and we will continue with our second shot. - if(self::mapComponent($dn, $ldapname, $isUser)) { - return $ldapname; - } - - //doh! There is a conflict. We need to distinguish between users/groups. Adding indexes is an idea, but not much of a help for the user. The DN is ugly, but for now the only reasonable way. But we transform it to a readable format and remove the first part to only give the path where this object is located. - $oc_name = self::alternateOwnCloudName($ldapname, $dn); - if(self::mapComponent($dn, $oc_name, $isUser)) { - return $oc_name; - } - - //and this of course should never been thrown :) - throw new Exception('LDAP backend: unexpected collision of DN and ownCloud Name.'); - } - - /** - * @brief gives back the user names as they are used ownClod internally - * @param $ldapGroups an array with the ldap Users result in style of array ( array ('dn' => foo, 'uid' => bar), ... ) - * @returns an array with the user names to use in ownCloud - * - * gives back the user names as they are used ownClod internally - */ - static public function ownCloudUserNames($ldapUsers) { - return self::ldap2ownCloudNames($ldapUsers, true); - } - - /** - * @brief gives back the group names as they are used ownClod internally - * @param $ldapGroups an array with the ldap Groups result in style of array ( array ('dn' => foo, 'cn' => bar), ... ) - * @returns an array with the group names to use in ownCloud - * - * gives back the group names as they are used ownClod internally - */ - static public function ownCloudGroupNames($ldapGroups) { - return self::ldap2ownCloudNames($ldapGroups, false); - } - - static private function ldap2ownCloudNames($ldapObjects, $isUsers) { - if($isUsers) { - $knownObjects = self::mappedUsers(); - $nameAttribute = self::conf('ldapUserDisplayName'); - } else { - $knownObjects = self::mappedGroups(); - $nameAttribute = self::conf('ldapGroupDisplayName'); - } - $ownCloudNames = array(); - - foreach($ldapObjects as $ldapObject) { - $key = self::recursiveArraySearch($knownObjects, $ldapObject['dn']); - - //everything is fine when we know the group - if($key !== false) { - $ownCloudNames[] = $knownObjects[$key]['owncloud_name']; - continue; - } - - //a new group! Then let's try to add it. We're shooting into the blue with the group name, assuming that in most cases there will not be a conflict. But first make sure, that the display name contains only allowed characters. - $ocname = self::sanitizeUsername($ldapObject[$nameAttribute]); - if(self::mapComponent($ldapObject['dn'], $ocname, $isUsers)) { - $ownCloudNames[] = $ocname; - continue; - } - - //doh! There is a conflict. We need to distinguish between groups. Adding indexes is an idea, but not much of a help for the user. The DN is ugly, but for now the only reasonable way. But we transform it to a readable format and remove the first part to only give the path where this entry is located. - $ocname = self::alternateOwnCloudName($ocname, $ldapObject['dn']); - if(self::mapComponent($ldapObject['dn'], $ocname, $isUsers)) { - $ownCloudNames[] = $ocname; - continue; - } - - //and this of course should never been thrown :) - throw new Exception('LDAP backend: unexpected collision of DN and ownCloud Name.'); - } - return $ownCloudNames; - } - - /** - * @brief creates a hopefully unique name for owncloud based on the display name and the dn of the LDAP object - * @param $name the display name of the object - * @param $dn the dn of the object - * @returns string with with the name to use in ownCloud - * - * creates a hopefully unique name for owncloud based on the display name and the dn of the LDAP object - */ - static private function alternateOwnCloudName($name, $dn) { - $ufn = ldap_dn2ufn($dn); - $name = $name . '@' . trim(OCP\Util::mb_substr_replace($ufn, '', 0, mb_strpos($ufn, ',', 0, 'UTF-8'), 'UTF-8')); - $name = self::sanitizeUsername($name); - return $name; - } - - /** - * @brief retrieves all known groups from the mappings table - * @returns array with the results - * - * retrieves all known groups from the mappings table - */ - static private function mappedGroups() { - return self::mappedComponents(false); - } - - /** - * @brief retrieves all known users from the mappings table - * @returns array with the results - * - * retrieves all known users from the mappings table - */ - static private function mappedUsers() { - return self::mappedComponents(true); - } - - static private function mappedComponents($isUsers) { - $table = self::getMapTable($isUsers); - - $query = OCP\DB::prepare(' - SELECT ldap_dn, owncloud_name - FROM '. $table - ); - - return $query->execute()->fetchAll(); - } - - /** - * @brief inserts a new user or group into the mappings table - * @param $dn the record in question - * @param $ocname the name to use in ownCloud - * @param $isUser is it a user or a group? - * @returns true on success, false otherwise - * - * inserts a new user or group into the mappings table - */ - static private function mapComponent($dn, $ocname, $isUser = true) { - $table = self::getMapTable($isUser); - $dn = self::sanitizeDN($dn); - - $sqlAdjustment = ''; - $dbtype = OCP\Config::getSystemValue('dbtype'); - if($dbtype == 'mysql') { - $sqlAdjustment = 'FROM dual'; - } - - $insert = OCP\DB::prepare(' - INSERT INTO '.$table.' (ldap_dn, owncloud_name) - SELECT ?,? - '.$sqlAdjustment.' - WHERE NOT EXISTS ( - SELECT 1 - FROM '.$table.' - WHERE ldap_dn = ? - OR owncloud_name = ? ) - '); - - $res = $insert->execute(array($dn, $ocname, $dn, $ocname)); - - if(OCP\DB::isError($res)) { - return false; - } - - $insRows = $res->numRows(); - - if($insRows == 0) { - return false; - } - - return true; - } - - static public function fetchListOfUsers($filter, $attr) { - return self::fetchList(OC_LDAP::searchUsers($filter, $attr), (count($attr) > 1)); - } - - static public function fetchListOfGroups($filter, $attr) { - return self::fetchList(OC_LDAP::searchGroups($filter, $attr), (count($attr) > 1)); - } - - static private function fetchList($list, $manyAttributes) { - if(is_array($list)) { - if($manyAttributes) { - return $list; - } else { - return array_unique($list, SORT_LOCALE_STRING); - } - } - - //error cause actually, maybe throw an exception in future. - return array(); - } - - /** - * @brief reads a given attribute for an LDAP record identified by a DN - * @param $dn the record in question - * @param $attr the attribute that shall be retrieved - * @returns the values in an array on success, false otherwise - * - * Reads an attribute from an LDAP entry - */ - static public function readAttribute($dn, $attr) { - $cr = self::getConnectionResource(); - $rr = ldap_read($cr, $dn, 'objectClass=*', array($attr)); - $er = ldap_first_entry($cr, $rr); - //LDAP attributes are not case sensitive - $result = OCP\Util::mb_array_change_key_case(ldap_get_attributes($cr, $er), MB_CASE_LOWER, 'UTF-8'); - $attr = mb_strtolower($attr, 'UTF-8'); - - if(isset($result[$attr]) && $result[$attr]['count'] > 0){ - $values = array(); - for($i=0;$i<$result[$attr]['count'];$i++) { - $values[] = self::resemblesDN($attr) ? self::sanitizeDN($result[$attr][$i]) : $result[$attr][$i]; - } - return $values; - } - return false; - } - - /** - * @brief executes an LDAP search, optimized for Users - * @param $filter the LDAP filter for the search - * @param $attr optional, when a certain attribute shall be filtered out - * @returns array with the search result - * - * Executes an LDAP search - */ - static public function searchUsers($filter, $attr = null) { - self::init(); - return self::search($filter, self::$ldapBaseUsers, $attr); - } - - /** - * @brief executes an LDAP search, optimized for Groups - * @param $filter the LDAP filter for the search - * @param $attr optional, when a certain attribute shall be filtered out - * @returns array with the search result - * - * Executes an LDAP search - */ - static public function searchGroups($filter, $attr = null) { - self::init(); - return self::search($filter, self::$ldapBaseGroups, $attr); - } - - /** - * @brief executes an LDAP search - * @param $filter the LDAP filter for the search - * @param $base the LDAP subtree that shall be searched - * @param $attr optional, when a certain attribute shall be filtered out - * @returns array with the search result - * - * Executes an LDAP search - */ - static private function search($filter, $base, $attr = null) { - if(!is_null($attr) && !is_array($attr)) { - $attr = array(mb_strtolower($attr, 'UTF-8')); - } - - // See if we have a resource - $link_resource = self::getConnectionResource(); - if(is_resource($link_resource)) { - $sr = ldap_search($link_resource, $base, $filter, $attr); - $findings = ldap_get_entries($link_resource, $sr ); - - // if we're here, probably no connection resource is returned. - // to make ownCloud behave nicely, we simply give back an empty array. - if(is_null($findings)) { - return array(); - } - } else { - // Seems like we didn't find any resource. - // Return an empty array just like before. - return array(); - } - - if(!is_null($attr)) { - $selection = array(); - $multiarray = false; - if(count($attr) > 1) { - $multiarray = true; - $i = 0; - } - foreach($findings as $item) { - if(!is_array($item)) { - continue; - } - $item = OCP\Util::mb_array_change_key_case($item, MB_CASE_LOWER, 'UTF-8'); - - if($multiarray) { - foreach($attr as $key) { - $key = mb_strtolower($key, 'UTF-8'); - if(isset($item[$key])) { - if($key != 'dn'){ - $selection[$i][$key] = self::resemblesDN($key) ? self::sanitizeDN($item[$key][0]) : $item[$key][0]; - } else { - $selection[$i][$key] = self::sanitizeDN($item[$key]); - } - } - - } - $i++; - } else { - //tribute to case insensitivity - $key = mb_strtolower($attr[0], 'UTF-8'); - - if(isset($item[$key])) { - if(self::resemblesDN($key)) { - $selection[] = self::sanitizeDN($item[$key]); - } else { - $selection[] = $item[$key]; - } - } - } - - } - return $selection; - } - - return $findings; - } - - static private function resemblesDN($attr) { - $resemblingAttributes = array( - 'dn', - 'uniquemember', - 'member' - ); - return in_array($attr, $resemblingAttributes); - } - - static private function sanitizeDN($dn) { - //OID sometimes gives back DNs with whitespace after the comma a la "uid=foo, cn=bar, dn=..." We need to tackle this! - $dn = preg_replace('/([^\\\]),(\s+)/u','\1,',$dn); - - //make comparisons and everything work - $dn = mb_strtolower($dn, 'UTF-8'); - - return $dn; - } - - static private function sanitizeUsername($name) { - if(self::$ldapIgnoreNamingRules) { - return $name; - } - - //REPLACEMENTS - $name = OCP\Util::mb_str_replace(' ', '_', $name, 'UTF-8'); - - //every remaining unallowed characters will be removed - $name = preg_replace('/[^a-zA-Z0-9_.@-]/u', '', $name); - - return $name; - } - - /** - * @brief combines the input filters with AND - * @param $filters array, the filters to connect - * @returns the combined filter - * - * Combines Filter arguments with AND - */ - static public function combineFilterWithAnd($filters) { - return self::combineFilter($filters,'&'); - } - - /** - * @brief combines the input filters with AND - * @param $filters array, the filters to connect - * @returns the combined filter - * - * Combines Filter arguments with AND - */ - static public function combineFilterWithOr($filters) { - return self::combineFilter($filters,'|'); - } - - /** - * @brief combines the input filters with given operator - * @param $filters array, the filters to connect - * @param $operator either & or | - * @returns the combined filter - * - * Combines Filter arguments with AND - */ - static private function combineFilter($filters, $operator) { - $combinedFilter = '('.$operator; - foreach($filters as $filter) { - if($filter[0] != '(') { - $filter = '('.$filter.')'; - } - $combinedFilter.=$filter; - } - $combinedFilter.=')'; - return $combinedFilter; - } - - /** - * Returns the LDAP handler - */ - static private function getConnectionResource() { - if(!self::$ldapConnectionRes) { - self::init(); - } - if(is_null(self::$ldapConnectionRes)) { - OCP\Util::writeLog('ldap', 'Connection could not be established', OCP\Util::INFO); - } - return self::$ldapConnectionRes; - } - - /** - * Caches the general LDAP configuration. - */ - static private function readConfiguration($force = false) { - if(!self::$configured || $force) { - self::$ldapHost = OCP\Config::getAppValue('user_ldap', 'ldap_host', ''); - self::$ldapPort = OCP\Config::getAppValue('user_ldap', 'ldap_port', 389); - self::$ldapAgentName = OCP\Config::getAppValue('user_ldap', 'ldap_dn',''); - self::$ldapAgentPassword = base64_decode(OCP\Config::getAppValue('user_ldap', 'ldap_agent_password','')); - self::$ldapBase = OCP\Config::getAppValue('user_ldap', 'ldap_base', ''); - self::$ldapBaseUsers = OCP\Config::getAppValue('user_ldap', 'ldap_base_users',self::$ldapBase); - self::$ldapBaseGroups = OCP\Config::getAppValue('user_ldap', 'ldap_base_groups', self::$ldapBase); - self::$ldapTLS = OCP\Config::getAppValue('user_ldap', 'ldap_tls',0); - self::$ldapNoCase = OCP\Config::getAppValue('user_ldap', 'ldap_nocase', 0); - self::$ldapUserDisplayName = mb_strtolower(OCP\Config::getAppValue('user_ldap', 'ldap_display_name', 'uid'), 'UTF-8'); - self::$ldapUserFilter = OCP\Config::getAppValue('user_ldap', 'ldap_userlist_filter','objectClass=person'); - self::$ldapLoginFilter = OCP\Config::getAppValue('user_ldap', 'ldap_login_filter', '(uid=%uid)'); - self::$ldapGroupDisplayName = mb_strtolower(OCP\Config::getAppValue('user_ldap', 'ldap_group_display_name', LDAP_GROUP_DISPLAY_NAME_ATTR), 'UTF-8'); - self::$ldapIgnoreNamingRules = OCP\Config::getSystemValue('ldapIgnoreNamingRules', false); - - if(empty(self::$ldapBaseUsers)) { - OCP\Util::writeLog('ldap', 'Base for Users is empty, using Base DN', OCP\Util::INFO); - self::$ldapBaseUsers = self::$ldapBase; - } - if(empty(self::$ldapBaseGroups)) { - OCP\Util::writeLog('ldap', 'Base for Groups is empty, using Base DN', OCP\Util::INFO); - self::$ldapBaseGroups = self::$ldapBase; - } - - if( - !empty(self::$ldapHost) - && !empty(self::$ldapPort) - && ( - (!empty(self::$ldapAgentName) && !empty(self::$ldapAgentPassword)) - || ( empty(self::$ldapAgentName) && empty(self::$ldapAgentPassword)) - ) - && !empty(self::$ldapBase) - && !empty(self::$ldapUserDisplayName) - ) - { - self::$configured = true; - } - } - } - - /** - * Connects and Binds to LDAP - */ - static private function establishConnection() { - if(!self::$configured) { - OCP\Util::writeLog('ldap', 'Configuration is invalid, cannot connect', OCP\Util::INFO); - return false; - } - if(!self::$ldapConnectionRes) { - self::$ldapConnectionRes = ldap_connect(self::$ldapHost, self::$ldapPort); - if(ldap_set_option(self::$ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) { - if(ldap_set_option(self::$ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) { - if(self::$ldapTLS) { - ldap_start_tls(self::$ldapConnectionRes); - } - } - } - - $ldapLogin = @ldap_bind(self::$ldapConnectionRes, self::$ldapAgentName, self::$ldapAgentPassword ); - if(!$ldapLogin) { - OCP\Util::writeLog('ldap', 'Bind failed: ' . ldap_errno(self::$ldapConnectionRes) . ': ' . ldap_error(self::$ldapConnectionRes), OCP\Util::ERROR); - self::$ldapConnectionRes = null; - return false; - } - } - } - - static public function areCredentialsValid($name, $password) { - return @ldap_bind(self::getConnectionResource(), $name, $password); - } - - /** - * taken from http://www.php.net/manual/en/function.array-search.php#97645 - * TODO: move somewhere, where its better placed since it is not LDAP specific. OC_Helper maybe? - */ - static public function recursiveArraySearch($haystack, $needle, $index = null) { - $aIt = new RecursiveArrayIterator($haystack); - $it = new RecursiveIteratorIterator($aIt); - - while($it->valid()) { - if (((isset($index) AND ($it->key() == $index)) OR (!isset($index))) AND ($it->current() == $needle)) { - return $aIt->key(); - } - - $it->next(); - } - - return false; - } - - } diff --git a/apps/user_ldap/tests/group_ldap.php b/apps/user_ldap/tests/group_ldap.php index 2be6b46fb23..106459580fa 100644 --- a/apps/user_ldap/tests/group_ldap.php +++ b/apps/user_ldap/tests/group_ldap.php @@ -26,8 +26,8 @@ class Test_Group_Ldap extends UnitTestCase { } function testSingleBackend(){ - OC_Group::useBackend(new OC_GROUP_LDAP()); - $group_ldap = new OC_GROUP_LDAP(); + OC_Group::useBackend(new OCA\user_ldap\GROUP_LDAP()); + $group_ldap = new OCA\user_ldap\GROUP_LDAP(); $this->assertIsA(OC_Group::getGroups(),gettype(array())); $this->assertIsA($group_ldap->getGroups(),gettype(array())); diff --git a/apps/user_ldap/user_ldap.php b/apps/user_ldap/user_ldap.php index b51d9a55cc7..a4a8921d08d 100644 --- a/apps/user_ldap/user_ldap.php +++ b/apps/user_ldap/user_ldap.php @@ -23,13 +23,9 @@ * */ -class OC_USER_LDAP extends OC_User_Backend { +namespace OCA\user_ldap; - // cached settings - protected $ldapUserFilter; - protected $ldapQuotaAttribute; - protected $ldapQuotaDefault; - protected $ldapEmailAttribute; +class USER_LDAP extends lib\Access implements \OCP\UserInterface { // will be retrieved from LDAP server protected $ldap_dc = false; @@ -37,39 +33,32 @@ class OC_USER_LDAP extends OC_User_Backend { // cache getUsers() protected $_users = null; - public function __construct() { - $this->ldapUserFilter = OCP\Config::getAppValue('user_ldap', 'ldap_userlist_filter', '(objectClass=posixAccount)'); - $this->ldapQuotaAttribute = OCP\Config::getAppValue('user_ldap', 'ldap_quota_attr', ''); - $this->ldapQuotaDefault = OCP\Config::getAppValue('user_ldap', 'ldap_quota_def', ''); - $this->ldapEmailAttribute = OCP\Config::getAppValue('user_ldap', 'ldap_email_attr', ''); - } - private function updateQuota($dn) { $quota = null; - if(!empty($this->ldapQuotaDefault)) { - $quota = $this->ldapQuotaDefault; + if(!empty($this->connection->ldapQuotaDefault)) { + $quota = $this->connection->ldapQuotaDefault; } - if(!empty($this->ldapQuotaAttribute)) { - $aQuota = OC_LDAP::readAttribute($dn, $this->ldapQuotaAttribute); + if(!empty($this->connection->ldapQuotaAttribute)) { + $aQuota = $this->readAttribute($dn, $this->connection->ldapQuotaAttribute); if($aQuota && (count($aQuota) > 0)) { $quota = $aQuota[0]; } } if(!is_null($quota)) { - OCP\Config::setUserValue(OC_LDAP::dn2username($dn), 'files', 'quota', OCP\Util::computerFileSize($quota)); + \OCP\Config::setUserValue($this->dn2username($dn), 'files', 'quota', \OCP\Util::computerFileSize($quota)); } } private function updateEmail($dn) { $email = null; - if(!empty($this->ldapEmailAttribute)) { - $aEmail = OC_LDAP::readAttribute($dn, $this->ldapEmailAttribute); + if(!empty($this->connection->ldapEmailAttribute)) { + $aEmail = $this->readAttribute($dn, $this->connection->ldapEmailAttribute); if($aEmail && (count($aEmail) > 0)) { $email = $aEmail[0]; } - if(!is_null($email)){ - OCP\Config::setUserValue(OC_LDAP::dn2username($dn), 'settings', 'email', $email); + if(!is_null($email)) { + \OCP\Config::setUserValue($this->dn2username($dn), 'settings', 'email', $email); } } } @@ -84,15 +73,15 @@ class OC_USER_LDAP extends OC_User_Backend { */ public function checkPassword($uid, $password){ //find out dn of the user name - $filter = OCP\Util::mb_str_replace('%uid', $uid, OC_LDAP::conf('ldapLoginFilter'), 'UTF-8'); - $ldap_users = OC_LDAP::fetchListOfUsers($filter, 'dn'); + $filter = \OCP\Util::mb_str_replace('%uid', $uid, $this->connection->ldapLoginFilter, 'UTF-8'); + $ldap_users = $this->fetchListOfUsers($filter, 'dn'); if(count($ldap_users) < 1) { return false; } $dn = $ldap_users[0]; //are the credentials OK? - if(!OC_LDAP::areCredentialsValid($dn, $password)) { + if(!$this->areCredentialsValid($dn, $password)) { return false; } @@ -101,7 +90,7 @@ class OC_USER_LDAP extends OC_User_Backend { $this->updateEmail($dn); //give back the display name - return OC_LDAP::dn2username($dn); + return $this->dn2username($dn); } /** @@ -112,8 +101,8 @@ class OC_USER_LDAP extends OC_User_Backend { */ public function getUsers(){ if(is_null($this->_users)) { - $ldap_users = OC_LDAP::fetchListOfUsers($this->ldapUserFilter, array(OC_LDAP::conf('ldapUserDisplayName'), 'dn')); - $this->_users = OC_LDAP::ownCloudUserNames($ldap_users); + $ldap_users = $this->fetchListOfUsers($this->connection->ldapUserFilter, array($this->connection->ldapUserDisplayName, 'dn')); + $this->_users = $this->ownCloudUserNames($ldap_users); } return $this->_users; } @@ -125,13 +114,13 @@ class OC_USER_LDAP extends OC_User_Backend { */ public function userExists($uid){ //getting dn, if false the user does not exist. If dn, he may be mapped only, requires more checking. - $dn = OC_LDAP::username2dn($uid); + $dn = $this->username2dn($uid); if(!$dn) { return false; } //if user really still exists, we will be able to read his cn - $cn = OC_LDAP::readAttribute($dn, 'cn'); + $cn = $this->readAttribute($dn, 'cn'); if(!$cn || empty($cn)) { return false; } @@ -139,4 +128,27 @@ class OC_USER_LDAP extends OC_User_Backend { return true; } + /** + * @brief delete a user + * @param $uid The username of the user to delete + * @returns true/false + * + * Deletes a user + */ + public function deleteUser($uid) { + return false; + } + + /** + * @brief Check if backend implements actions + * @param $actions bitwise-or'ed actions + * @returns boolean + * + * Returns the supported actions as int to be + * compared with OC_USER_BACKEND_CREATE_USER etc. + */ + public function implementsActions($actions) { + return (bool)(OC_USER_BACKEND_CHECK_PASSWORD & $actions); + } + }
\ No newline at end of file diff --git a/apps/user_migrate/appinfo/app.php b/apps/user_migrate/appinfo/app.php index 9d314b59ce7..366c4004932 100644 --- a/apps/user_migrate/appinfo/app.php +++ b/apps/user_migrate/appinfo/app.php @@ -31,4 +31,3 @@ $entry = array( 'href' => OCP\Util::linkTo( "user_migrate", "admin.php" ), 'name' => 'Import' ); -?> diff --git a/apps/user_migrate/templates/settings.php b/apps/user_migrate/templates/settings.php index 1718abe9e0f..bce5fb2d7ca 100644 --- a/apps/user_migrate/templates/settings.php +++ b/apps/user_migrate/templates/settings.php @@ -12,7 +12,7 @@ <?php } ?> <legend><strong><?php echo $l->t('Import user account');?></strong></legend> </p> - <p><input type="file" id="owncloud_import" name="owncloud_import" style="width:180px;"><label for="owncloud_import"> <?php echo $l->t('ownCloud User Zip');?></label> + <p><input type="file" id="owncloud_import" name="owncloud_import" style="width:280px;"><label for="owncloud_import"> <?php echo $l->t('ownCloud User Zip');?></label> </p> <input type="submit" name="user_import" value="<?php echo $l->t('Import'); ?>" /> </fieldset> diff --git a/apps/user_openid/user.php b/apps/user_openid/user.php index 392424795f8..88571ba618e 100644 --- a/apps/user_openid/user.php +++ b/apps/user_openid/user.php @@ -44,7 +44,4 @@ if(!OCP\User::userExists($USERNAME)){ } $IDENTITY=OCP\Util::linkToAbsolute( "user_openid", "user.php" ).'/'.$USERNAME; -require_once 'phpmyid.php'; - - -?> +require_once 'openid/phpmyid.php'; diff --git a/apps/user_openid/user_openid.php b/apps/user_openid/user_openid.php index 70b193a30b1..19f2f719b06 100644 --- a/apps/user_openid/user_openid.php +++ b/apps/user_openid/user_openid.php @@ -21,7 +21,7 @@ * */ -require_once('class.openid.v3.php'); +require_once('openid/class.openid.v3.php'); /** * Class for user OpenId backend diff --git a/apps/user_webfinger/.htaccess b/apps/user_webfinger/.htaccess new file mode 100644 index 00000000000..1b13cf788ff --- /dev/null +++ b/apps/user_webfinger/.htaccess @@ -0,0 +1,5 @@ +<IfModule mod_rewrite.c> +RewriteEngine on +RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}] +RewriteRule ^host-meta host-meta.php [QSA,L] +</IfModule> diff --git a/apps/user_webfinger/appinfo/app.php b/apps/user_webfinger/appinfo/app.php index 3336af66820..b3d9bbc7f37 100644 --- a/apps/user_webfinger/appinfo/app.php +++ b/apps/user_webfinger/appinfo/app.php @@ -1,3 +1 @@ <?php -OCP\CONFIG::setAppValue('core', 'public_host-meta', '/apps/user_webfinger/host-meta.php'); -OCP\CONFIG::setAppValue('core', 'public_webfinger', '/apps/user_webfinger/webfinger.php'); diff --git a/apps/user_webfinger/appinfo/info.xml b/apps/user_webfinger/appinfo/info.xml index 4e28814a26c..f74e5d3f93a 100644 --- a/apps/user_webfinger/appinfo/info.xml +++ b/apps/user_webfinger/appinfo/info.xml @@ -7,4 +7,8 @@ <author>Michiel de Jong, Florian Hülsmann</author> <require>4</require> <shipped>true</shipped> + <public> + <host-meta>host-meta.php</host-meta> + <webfinger>webfinger.php</webfinger> + </public> </info> diff --git a/apps/user_webfinger/appinfo/version b/apps/user_webfinger/appinfo/version index 1d71ef97443..a2268e2de44 100644 --- a/apps/user_webfinger/appinfo/version +++ b/apps/user_webfinger/appinfo/version @@ -1 +1 @@ -0.3
\ No newline at end of file +0.3.1
\ No newline at end of file diff --git a/apps/user_webfinger/host-meta.php b/apps/user_webfinger/host-meta.php index 32ffb512057..4ac37b1ea09 100644 --- a/apps/user_webfinger/host-meta.php +++ b/apps/user_webfinger/host-meta.php @@ -1,10 +1,27 @@ <?php + +if(class_exists('OC')){ + $WEBROOT=OC::$WEBROOT; +}else{//not called trough remote.php try to guess the webroot the best we can from here + // calculate the root directories + $SERVERROOT=str_replace("\\",'/',substr(__FILE__,0,-strlen('apps/user_webfinger/host-meta.php'))); + $WEBROOT=substr($SERVERROOT,strlen(realpath($_SERVER['DOCUMENT_ROOT']))); + + if($WEBROOT!='' and $WEBROOT[0]!=='/'){ + $WEBROOT='/'.$WEBROOT; + } +} + +if(substr($WEBROOT,-1)==='/'){ + $WEBROOT=substr($WEBROOT,0,-1); +} + $hostMetaHeader = array( 'Access-Control-Allow-Origin' => '*', 'Content-Type' => 'application/xrd+json' ); $serverName = $_SERVER['SERVER_NAME']; -$hostMetaContents = '{"links":[{"rel":"lrdd","template":"http'.(isset($_SERVER['HTTPS'])?'s':'').'://'.$serverName.'/public.php?service=webfinger&q={uri}"}]}'; +$hostMetaContents = '{"links":[{"rel":"lrdd","template":"http'.(isset($_SERVER['HTTPS'])?'s':'').'://'.$serverName.$WEBROOT.'/public.php?service=webfinger&q={uri}"}]}'; foreach($hostMetaHeader as $header => $value) { header($header . ": " . $value); } diff --git a/apps/user_webfinger/webfinger.php b/apps/user_webfinger/webfinger.php index 6b64a7e2860..e5b7f042d5a 100644 --- a/apps/user_webfinger/webfinger.php +++ b/apps/user_webfinger/webfinger.php @@ -58,4 +58,3 @@ foreach($apps as $app) { } } echo "]}"; -?> diff --git a/autotest.sh b/autotest.sh new file mode 100755 index 00000000000..a42c6ab059e --- /dev/null +++ b/autotest.sh @@ -0,0 +1,110 @@ +#!/bin/bash +# +# ownCloud +# +# @author Thomas Müller +# @copyright 2012 Thomas Müller thomas.mueller@tmit.eu +# + +DATADIR=data-autotest +BASEDIR=$PWD + +# create autoconfig for sqlite, mysql and (soon) postgresql +cat > ./tests/autoconfig-sqlite.php <<DELIM +<?php +\$AUTOCONFIG = array ( + 'installed' => false, + 'dbtype' => 'sqlite', + 'dbtableprefix' => 'oc_', + 'adminlogin' => 'admin', + 'adminpass' => 'admin', + 'directory' => '$BASEDIR/$DATADIR', +); +DELIM + +cat > ./tests/autoconfig-mysql.php <<DELIM +<?php +\$AUTOCONFIG = array ( + 'installed' => false, + 'dbtype' => 'mysql', + 'dbtableprefix' => 'oc_', + 'adminlogin' => 'admin', + 'adminpass' => 'admin', + 'directory' => '$BASEDIR/$DATADIR', + 'dbuser' => 'oc_autotest', + 'dbname' => 'oc_autotest', + 'dbhost' => 'localhost', + 'dbpass' => 'owncloud', +); +DELIM + +cat > ./tests/autoconfig-pgsql.php <<DELIM +<?php +\$AUTOCONFIG = array ( + 'installed' => false, + 'dbtype' => 'pgsql', + 'dbtableprefix' => 'oc_', + 'adminlogin' => 'admin', + 'adminpass' => 'admin', + 'directory' => '$BASEDIR/$DATADIR', + 'dbuser' => 'oc_autotest', + 'dbname' => 'oc_autotest', + 'dbhost' => 'localhost', + 'dbpass' => 'owncloud', +); +DELIM + +function execute_tests { + echo "Setup environment for $1 testing ..." + # back to root folder + cd $BASEDIR + + # revert changes to tests/data + git checkout tests/data/* + + # reset data directory + rm -rf $DATADIR + mkdir $DATADIR + + # remove the old config file + rm -rf config/config.php + + # drop database + if [ "$1" == "mysql" ] ; then + mysql -u oc_autotest -powncloud -e "DROP DATABASE oc_autotest" + fi + if [ "$1" == "pgsql" ] ; then + dropdb -U oc_autotest oc_autotest + fi + + # copy autoconfig + cp $BASEDIR/tests/autoconfig-$1.php $BASEDIR/config/autoconfig.php + + # trigger installation + php -f index.php + + #test execution + echo "Testing with $1 ..." + cd tests + php -f index.php -- xml $1 > autotest-results-$1.xml +} + +# +# start test execution +# +execute_tests "sqlite" +execute_tests 'mysql' +execute_tests 'pgsql' + +# +# NOTES on mysql: +# - CREATE USER 'oc_autotest'@'localhost' IDENTIFIED BY 'owncloud'; +# - grant access permissions: grant all on oc_autotest.* to 'oc_autotest'@'localhost'; +# +# NOTES on pgsql: +# - su - postgres +# - createuser -P (enter username and password and enable superuser) +# - to enable dropdb I decided to add following line to pg_hba.conf (this is not the safest way but I don't care for the testing machine): +# local all all trust +# + diff --git a/core/ajax/grouplist.php b/core/ajax/grouplist.php index cc15102bbc3..e3e92fcfa16 100644 --- a/core/ajax/grouplist.php +++ b/core/ajax/grouplist.php @@ -45,5 +45,3 @@ foreach( OC_Group::getGroups() as $i ){ } OC_JSON::encodedPrint($groups); - -?> diff --git a/core/ajax/translations.php b/core/ajax/translations.php index a6433b1964a..2bd6b7ed634 100644 --- a/core/ajax/translations.php +++ b/core/ajax/translations.php @@ -29,4 +29,3 @@ $app = $_POST["app"]; $l = OC_L10N::get( $app ); OC_JSON::success(array('data' => $l->getTranslations())); -?> diff --git a/core/ajax/userlist.php b/core/ajax/userlist.php index c8168eaf460..85ca004ae66 100644 --- a/core/ajax/userlist.php +++ b/core/ajax/userlist.php @@ -44,5 +44,3 @@ foreach( OC_User::getUsers() as $i ){ } OC_JSON::encodedPrint($users); - -?> diff --git a/core/ajax/validateuser.php b/core/ajax/validateuser.php index 258bd50fcad..78ec451fac2 100644 --- a/core/ajax/validateuser.php +++ b/core/ajax/validateuser.php @@ -36,5 +36,3 @@ if(!isset($_SERVER['PHP_AUTH_USER'])){ OC_JSON::encodedPrint(array("username" => $_SERVER["PHP_AUTH_USER"], "user_valid" => "false")); } } - -?> diff --git a/core/ajax/vcategories/add.php b/core/ajax/vcategories/add.php index a58489228d8..e69f8bb726b 100644 --- a/core/ajax/vcategories/add.php +++ b/core/ajax/vcategories/add.php @@ -39,5 +39,3 @@ if($categories->hasCategory($category)) { } OC_JSON::success(array('data' => array('categories'=>$categories->categories()))); - -?> diff --git a/core/ajax/vcategories/delete.php b/core/ajax/vcategories/delete.php index 75def433d30..a41fa083c38 100644 --- a/core/ajax/vcategories/delete.php +++ b/core/ajax/vcategories/delete.php @@ -34,5 +34,3 @@ if(is_null($categories)) { $vcategories = new OC_VCategories($app); $vcategories->delete($categories); OC_JSON::success(array('data' => array('categories'=>$vcategories->categories()))); - -?> diff --git a/core/ajax/vcategories/edit.php b/core/ajax/vcategories/edit.php index 252b3d3454c..3e5540cbc22 100644 --- a/core/ajax/vcategories/edit.php +++ b/core/ajax/vcategories/edit.php @@ -31,5 +31,3 @@ $categories = $vcategories->categories(); debug(print_r($categories, true)); $tmpl->assign('categories',$categories); $tmpl->printpage(); - -?> diff --git a/core/css/styles.css b/core/css/styles.css index 338518e5b2f..b818caa279f 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -139,6 +139,8 @@ li.error { width:640px; margin:4em auto; padding:1em 1em 1em 4em; background:#ff a.bookmarklet { background-color: #ddd; border:1px solid #ccc; padding: 5px;padding-top: 0px;padding-bottom: 2px; text-decoration: none; margin-top: 5px } +.exception{color: #000000;} +.exception textarea{width:95%;height: 200px;background:#ffe;border:0;} /* ---- DIALOGS ---- */ #dirtree {width: 100%;} diff --git a/core/js/eventsource.js b/core/js/eventsource.js index 08259e02cae..e3ad7e3a671 100644 --- a/core/js/eventsource.js +++ b/core/js/eventsource.js @@ -40,6 +40,7 @@ OC.EventSource=function(src,data){ dataStr+=name+'='+encodeURIComponent(data[name])+'&'; } } + dataStr+='requesttoken='+OC.EventSource.requesttoken; if(!this.useFallBack && typeof EventSource !='undefined'){ this.source=new EventSource(src+'?'+dataStr); this.source.onmessage=function(e){ diff --git a/core/strings.php b/core/strings.php index 8c3f64ef14f..01ab3866089 100644 --- a/core/strings.php +++ b/core/strings.php @@ -7,4 +7,3 @@ $l->t("Users"); $l->t("Apps"); $l->t("Admin"); $l->t("Help"); -?> diff --git a/core/templates/exception.php b/core/templates/exception.php new file mode 100644 index 00000000000..7f58ce252cf --- /dev/null +++ b/core/templates/exception.php @@ -0,0 +1,30 @@ +<ul> + <li class='error'> + <details> + <summary class="error">We're sorry, but something went terribly wrong.<br></summary> + <p class="exception"> + <?php + if($_['showsysinfo'] == true){ + echo 'If you would like to support ownCloud\'s developers and report this error in our <a href="http://bugs.owncloud.org">Bugtracker</a>, please copy the following informations into the description. <br><br><textarea readonly>'; + echo 'Message: ' . $_['message'] . "\n"; + echo 'Error Code: ' . $_['code'] . "\n"; + echo 'File: ' . $_['file'] . "\n"; + echo 'Line: ' . $_['line'] . "\n\n"; + echo 'PHP: ' . $_['sysinfo']['phpversion'] . "\n"; + echo 'OS: ' . $_['sysinfo']['os'] . "\n"; + echo 'OS Release: ' . $_['sysinfo']['osrelease'] . "\n"; + echo 'OS Arch.: ' . $_['sysinfo']['osarchitecture'] . "\n"; + echo 'PHP-Server-Interface: ' . $_['sysinfo']['phpserverinterface'] . "\n"; + echo 'Protocol: ' . $_['sysinfo']['serverprotocol'] . "\n"; + echo 'HTTPS: ' . $_['sysinfo']['https'] . "\n"; + echo 'Request Method: ' . $_['sysinfo']['requestmethod'] . "\n"; + echo 'Database: ' . $_['sysinfo']['database'] . "\n"; + echo '</textarea>'; + }else{ + echo 'Your administrator has disabled systeminformations.'; + } + ?> + </p> + </details> + </li> +</ul>
\ No newline at end of file diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php index 7e98fdedc2d..dc303ffc1a7 100644 --- a/core/templates/layout.user.php +++ b/core/templates/layout.user.php @@ -33,6 +33,7 @@ <script type="text/javascript"> $(function() { requesttoken = '<?php echo $_['requesttoken']; ?>'; + OC.EventSource.requesttoken=requesttoken; $(document).bind('ajaxSend', function(elm, xhr, s){ if(requesttoken) { xhr.setRequestHeader('requesttoken', requesttoken); diff --git a/core/templates/login.php b/core/templates/login.php index 985cf90c2a2..b35c4a33be8 100644 --- a/core/templates/login.php +++ b/core/templates/login.php @@ -7,7 +7,7 @@ <?php endif; ?> <p class="infield"> <label for="user" class="infield"><?php echo $l->t( 'Username' ); ?></label> - <input type="text" name="user" id="user" value="<?php echo !empty($_POST['user'])?OC_Util::sanitizeHTML($_POST['user'],ENT_COMPAT,'utf-8').'"':'" autofocus'; ?> autocomplete="off" required /> + <input type="text" name="user" id="user" value="<?php echo !empty($_POST['user'])?OC_Util::sanitizeHTML($_POST['user'],ENT_COMPAT,'utf-8').'"':'" autofocus'; ?> autocomplete="on" required /> </p> <p class="infield"> <label for="password" class="infield"><?php echo $l->t( 'Password' ); ?></label> diff --git a/lib/MDB2/Driver/Function/sqlite3.php b/lib/MDB2/Driver/Function/sqlite3.php index a013aea165a..1af262fd7a7 100644 --- a/lib/MDB2/Driver/Function/sqlite3.php +++ b/lib/MDB2/Driver/Function/sqlite3.php @@ -134,4 +134,3 @@ class MDB2_Driver_Function_sqlite3 extends MDB2_Driver_Function_Common // }}} } -?> diff --git a/lib/MDB2/Driver/Manager/sqlite3.php b/lib/MDB2/Driver/Manager/sqlite3.php index 8f4e1312eb8..10255a3619a 100644 --- a/lib/MDB2/Driver/Manager/sqlite3.php +++ b/lib/MDB2/Driver/Manager/sqlite3.php @@ -1360,4 +1360,3 @@ class MDB2_Driver_Manager_sqlite3 extends MDB2_Driver_Manager_Common // }}} } -?> diff --git a/lib/MDB2/Driver/sqlite3.php b/lib/MDB2/Driver/sqlite3.php index 39d3fb6727d..6bfccadad9a 100644 --- a/lib/MDB2/Driver/sqlite3.php +++ b/lib/MDB2/Driver/sqlite3.php @@ -1221,7 +1221,7 @@ class MDB2_Statement_sqlite3 extends MDB2_Statement_Common return $affected_rows; } - $result =& $this->db->_wrapResult($result, $this->result_types, + $result = $this->db->_wrapResult($result, $this->result_types, $result_class, $result_wrap_class, $this->limit, $this->offset); $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'post', 'result' => $result)); return $result; @@ -1332,5 +1332,3 @@ class MDB2_Statement_sqlite3 extends MDB2_Statement_Common $this->free(); } } - -?> diff --git a/lib/app.php b/lib/app.php index 4c2c43ec26b..56132c08671 100755 --- a/lib/app.php +++ b/lib/app.php @@ -27,7 +27,6 @@ * upgrading and removing apps. */ class OC_App{ - static private $init = false; static private $activeapp = ''; static private $navigation = array(); static private $settingsForms = array(); @@ -196,7 +195,7 @@ class OC_App{ // check if the app is compatible with this version of ownCloud $info=OC_App::getAppInfo($app); $version=OC_Util::getVersion(); - if(!isset($info['require']) or ($version[0]>$info['require'])){ + if(!isset($info['require']) or ($version[0]>$info['require'])){ OC_Log::write('core','App "'.$info['name'].'" can\'t be installed because it is not compatible with this version of ownCloud',OC_Log::ERROR); return false; }else{ @@ -332,8 +331,8 @@ class OC_App{ } /** - * Get the path where to install apps - */ + * Get the path where to install apps + */ public static function getInstallPath() { if(OC_Config::getValue('appstoreenabled', true)==false) { return false; @@ -608,7 +607,7 @@ class OC_App{ //set remote/public handelers $appData=self::getAppInfo($appid); foreach($appData['remote'] as $name=>$path){ - OCP\CONFIG::setAppValue('core', 'remote_'.$name, $path); + OCP\CONFIG::setAppValue('core', 'remote_'.$name, $appid.'/'.$path); } foreach($appData['public'] as $name=>$path){ OCP\CONFIG::setAppValue('core', 'public_'.$name, $appid.'/'.$path); diff --git a/lib/archive/zip.php b/lib/archive/zip.php index 6631a649b16..b2d6674d639 100644 --- a/lib/archive/zip.php +++ b/lib/archive/zip.php @@ -11,7 +11,6 @@ class OC_Archive_ZIP extends OC_Archive{ * @var ZipArchive zip */ private $zip=null; - private $success=false; private $path; function __construct($source){ @@ -74,8 +73,7 @@ class OC_Archive_ZIP extends OC_Archive{ * @return int */ function mtime($path){ - $stat=$this->zip->statName($path); - return $stat['mtime']; + return filemtime($this->path); } /** * get the files in a folder diff --git a/lib/base.php b/lib/base.php index fe69ad70c0f..5041f43648e 100644 --- a/lib/base.php +++ b/lib/base.php @@ -83,9 +83,15 @@ class OC{ elseif(strpos($className,'OCP\\')===0){ require_once 'public/'.strtolower(str_replace('\\','/',substr($className,3)) . '.php'); } + elseif(strpos($className,'OCA\\')===0){ + require_once 'apps/'.strtolower(str_replace('\\','/',substr($className,3)) . '.php'); + } elseif(strpos($className,'Sabre_')===0) { require_once str_replace('_','/',$className) . '.php'; } + elseif(strpos($className,'Symfony\\')===0){ + require_once str_replace('\\','/',$className) . '.php'; + } elseif(strpos($className,'Test_')===0){ require_once 'tests/lib/'.strtolower(str_replace('_','/',substr($className,5)) . '.php'); } @@ -345,7 +351,7 @@ class OC{ $_SESSION['user_id'] = ''; } - OC_User::useBackend( OC_Config::getValue( "userbackend", "database" )); + OC_User::useBackend(new OC_User_Database()); OC_Group::useBackend(new OC_Group_Database()); // Load Apps diff --git a/lib/cache.php b/lib/cache.php index 1f269174fad..55f189a5da8 100644 --- a/lib/cache.php +++ b/lib/cache.php @@ -7,48 +7,96 @@ */ class OC_Cache { + /** + * @var OC_Cache $user_cache + */ static protected $user_cache; + /** + * @var OC_Cache $global_cache + */ static protected $global_cache; + /** + * @var OC_Cache $global_cache_fast + */ + static protected $global_cache_fast; + /** + * @var OC_Cache $user_cache_fast + */ + static protected $user_cache_fast; + static protected $isFast=null; - static public function getGlobalCache() { + /** + * get the global cache + * @return OC_Cache + */ + static public function getGlobalCache($fast=false) { if (!self::$global_cache) { - $fast_cache = null; - if (!$fast_cache && function_exists('xcache_set')) { - $fast_cache = new OC_Cache_XCache(true); + self::$global_cache_fast = null; + if (!self::$global_cache_fast && function_exists('xcache_set')) { + self::$global_cache_fast = new OC_Cache_XCache(true); } - if (!$fast_cache && function_exists('apc_store')) { - $fast_cache = new OC_Cache_APC(true); + if (!self::$global_cache_fast && function_exists('apc_store')) { + self::$global_cache_fast = new OC_Cache_APC(true); } + self::$global_cache = new OC_Cache_FileGlobal(); - if ($fast_cache) { - self::$global_cache = new OC_Cache_Broker($fast_cache, self::$global_cache); + if (self::$global_cache_fast) { + self::$global_cache = new OC_Cache_Broker(self::$global_cache_fast, self::$global_cache); + } + } + if($fast){ + if(self::$global_cache_fast){ + return self::$global_cache_fast; + }else{ + return false; } } return self::$global_cache; } - static public function getUserCache() { + /** + * get the user cache + * @return OC_Cache + */ + static public function getUserCache($fast=false) { if (!self::$user_cache) { - $fast_cache = null; - if (!$fast_cache && function_exists('xcache_set')) { - $fast_cache = new OC_Cache_XCache(); + self::$user_cache_fast = null; + if (!self::$user_cache_fast && function_exists('xcache_set')) { + self::$user_cache_fast = new OC_Cache_XCache(); } - if (!$fast_cache && function_exists('apc_store')) { - $fast_cache = new OC_Cache_APC(); + if (!self::$user_cache_fast && function_exists('apc_store')) { + self::$user_cache_fast = new OC_Cache_APC(); } + self::$user_cache = new OC_Cache_File(); - if ($fast_cache) { - self::$user_cache = new OC_Cache_Broker($fast_cache, self::$user_cache); + if (self::$user_cache_fast) { + self::$user_cache = new OC_Cache_Broker(self::$user_cache_fast, self::$user_cache); + } + } + + if($fast){ + if(self::$user_cache_fast){ + return self::$user_cache_fast; + }else{ + return false; } } return self::$user_cache; } + /** + * get a value from the user cache + * @return mixed + */ static public function get($key) { $user_cache = self::getUserCache(); return $user_cache->get($key); } + /** + * set a value in the user cache + * @return bool + */ static public function set($key, $value, $ttl=0) { if (empty($key)) { return false; @@ -57,19 +105,43 @@ class OC_Cache { return $user_cache->set($key, $value, $ttl); } + /** + * check if a value is set in the user cache + * @return bool + */ static public function hasKey($key) { $user_cache = self::getUserCache(); return $user_cache->hasKey($key); } + /** + * remove an item from the user cache + * @return bool + */ static public function remove($key) { $user_cache = self::getUserCache(); return $user_cache->remove($key); } - static public function clear() { + /** + * clear the user cache of all entries starting with a prefix + * @param string prefix (optional) + * @return bool + */ + static public function clear($prefix='') { $user_cache = self::getUserCache(); - return $user_cache->clear(); + return $user_cache->clear($prefix); + } + + /** + * check if a fast memory based cache is available + * @return true + */ + static public function isFast() { + if(is_null(self::$isFast)){ + self::$isFast=function_exists('xcache_set') || function_exists('apc_store'); + } + return self::$isFast; } } diff --git a/lib/cache/apc.php b/lib/cache/apc.php index 6cf47d0c158..c192fe2f196 100644 --- a/lib/cache/apc.php +++ b/lib/cache/apc.php @@ -43,14 +43,15 @@ class OC_Cache_APC { return apc_delete($this->getNamespace().$key); } - public function clear(){ - $ns = $this->getNamespace(); + public function clear($prefix=''){ + $ns = $this->getNamespace().$prefix; $cache = apc_cache_info('user'); foreach($cache['cache_list'] as $entry) { if (strpos($entry['info'], $ns) === 0) { apc_delete($entry['info']); } } + return true; } } if(!function_exists('apc_exists')) { diff --git a/lib/cache/broker.php b/lib/cache/broker.php index 931d0dd407e..c2aceabaf53 100644 --- a/lib/cache/broker.php +++ b/lib/cache/broker.php @@ -46,8 +46,8 @@ class OC_Cache_Broker { return $this->slow_cache->remove($key); } - public function clear(){ - $this->fast_cache->clear(); - $this->slow_cache->clear(); + public function clear($prefix=''){ + $this->fast_cache->clear($prefix); + $this->slow_cache->clear($prefix); } } diff --git a/lib/cache/file.php b/lib/cache/file.php index 0b7d3e30508..562c3d17167 100644 --- a/lib/cache/file.php +++ b/lib/cache/file.php @@ -62,15 +62,16 @@ class OC_Cache_File{ return $storage->unlink($key); } - public function clear(){ + public function clear($prefix=''){ $storage = $this->getStorage(); if($storage and $storage->is_dir('/')){ $dh=$storage->opendir('/'); while($file=readdir($dh)){ - if($file!='.' and $file!='..'){ + if($file!='.' and $file!='..' and ($prefix==='' || strpos($file, $prefix) === 0)){ $storage->unlink('/'.$file); } } } + return true; } } diff --git a/lib/cache/xcache.php b/lib/cache/xcache.php index bd55cee8f6b..951f9b47545 100644 --- a/lib/cache/xcache.php +++ b/lib/cache/xcache.php @@ -43,7 +43,8 @@ class OC_Cache_XCache { return xcache_unset($this->getNamespace().$key); } - public function clear(){ - return xcache_unset_by_prefix($this->getNamespace()); + public function clear($prefix=''){ + xcache_unset_by_prefix($this->getNamespace().$prefix); + return true; } } diff --git a/lib/connector/sabre/auth.php b/lib/connector/sabre/auth.php index ee680391626..99f696e3a07 100644 --- a/lib/connector/sabre/auth.php +++ b/lib/connector/sabre/auth.php @@ -31,13 +31,18 @@ class OC_Connector_Sabre_Auth extends Sabre_DAV_Auth_Backend_AbstractBasic { * @return bool */ protected function validateUserPass($username, $password){ - OC_Util::setUpFS();//login hooks may need early access to the filesystem - if(OC_User::login($username,$password)){ - OC_Util::setUpFS($username); + if (OC_User::isLoggedIn()) { + OC_Util::setupFS($username); return true; - } - else{ - return false; + } else { + OC_Util::setUpFS();//login hooks may need early access to the filesystem + if(OC_User::login($username,$password)){ + OC_Util::setUpFS($username); + return true; + } + else{ + return false; + } } } } diff --git a/lib/connector/sabre/client.php b/lib/connector/sabre/client.php index b799b541a05..7e8f21264f9 100644 --- a/lib/connector/sabre/client.php +++ b/lib/connector/sabre/client.php @@ -23,29 +23,18 @@ class OC_Connector_Sabre_Client extends Sabre_DAV_Client {
- protected $curlSettings;
-
- public function __construct(array $settings) {
- //set default curl settings
- $this->curlSettings = array(
- CURLOPT_RETURNTRANSFER => true,
- // Return headers as part of the response
- CURLOPT_HEADER => true,
- // Automatically follow redirects
- CURLOPT_FOLLOWLOCATION => true,
- CURLOPT_MAXREDIRS => 5,
- CURLOPT_SSL_VERIFYPEER => true,
- //CURLOPT_SSL_VERIFYPEER => false,
- );
- parent::__construct($settings);
- }
-
- public function setCurlSettings($settings) {
- if (is_array($settings)) {
- foreach ($settings as $k => $v) {
- $this->curlSettings[$k] = $v;
- }
- }
+ protected $trustedCertificates;
+
+ /**
+ * Add trusted root certificates to the webdav client.
+ *
+ * The parameter certificates should be a absulute path to a file which contains
+ * all trusted certificates
+ *
+ * @param string $certificates
+ */
+ public function addTrustedCertificates($certificates) {
+ $this->trustedCertificates = $certificates;
}
/**
@@ -68,14 +57,24 @@ class OC_Connector_Sabre_Client extends Sabre_DAV_Client { * @return array
*/
public function request($method, $url = '', $body = null, $headers = array()) {
-
- $this->curlSettings[CURLOPT_POSTFIELDS] = $body;
+
$url = $this->getAbsoluteUrl($url);
+ $curlSettings = array(
+ CURLOPT_RETURNTRANSFER => true,
+ // Return headers as part of the response
+ CURLOPT_HEADER => true,
+ CURLOPT_POSTFIELDS => $body,
+ // Automatically follow redirects
+ CURLOPT_FOLLOWLOCATION => true,
+ CURLOPT_MAXREDIRS => 5,
+ );
+
+ if($this->trustedCertificates) {
+ $curlSettings[CURLOPT_CAINFO] = $this->trustedCertificates;
+ }
+
switch ($method) {
- case 'PUT':
- $this->curlSettings[CURLOPT_PUT] = true;
- break;
case 'HEAD' :
// do not read body with HEAD requests (this is neccessary because cURL does not ignore the body with HEAD
@@ -83,12 +82,12 @@ class OC_Connector_Sabre_Client extends Sabre_DAV_Client { // specs...) cURL does unfortunately return an error in this case ("transfer closed transfer closed with
// ... bytes remaining to read") this can be circumvented by explicitly telling cURL to ignore the
// response body
- $this->curlSettings[CURLOPT_NOBODY] = true;
- $this->curlSettings[CURLOPT_CUSTOMREQUEST] = 'HEAD';
+ $curlSettings[CURLOPT_NOBODY] = true;
+ $curlSettings[CURLOPT_CUSTOMREQUEST] = 'HEAD';
break;
default:
- $this->curlSettings[CURLOPT_CUSTOMREQUEST] = $method;
+ $curlSettings[CURLOPT_CUSTOMREQUEST] = $method;
break;
}
@@ -100,15 +99,22 @@ class OC_Connector_Sabre_Client extends Sabre_DAV_Client { $nHeaders[] = $key . ': ' . $value;
}
- $this->curlSettings[CURLOPT_HTTPHEADER] = $nHeaders;
+ $curlSettings[CURLOPT_HTTPHEADER] = $nHeaders;
if ($this->proxy) {
- $this->curlSettings[CURLOPT_PROXY] = $this->proxy;
+ $curlSettings[CURLOPT_PROXY] = $this->proxy;
}
- if ($this->userName) {
- $this->curlSettings[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC | CURLAUTH_DIGEST;
- $this->curlSettings[CURLOPT_USERPWD] = $this->userName . ':' . $this->password;
+ if ($this->userName && $this->authType) {
+ $curlType = 0;
+ if ($this->authType & self::AUTH_BASIC) {
+ $curlType |= CURLAUTH_BASIC;
+ }
+ if ($this->authType & self::AUTH_DIGEST) {
+ $curlType |= CURLAUTH_DIGEST;
+ }
+ $curlSettings[CURLOPT_HTTPAUTH] = $curlType;
+ $curlSettings[CURLOPT_USERPWD] = $this->userName . ':' . $this->password;
}
list(
@@ -116,7 +122,7 @@ class OC_Connector_Sabre_Client extends Sabre_DAV_Client { $curlInfo,
$curlErrNo,
$curlError
- ) = $this->curlRequest($url, $this->curlSettings);
+ ) = $this->curlRequest($url, $curlSettings);
$headerBlob = substr($response, 0, $curlInfo['header_size']);
$response = substr($response, $curlInfo['header_size']);
@@ -163,6 +169,5 @@ class OC_Connector_Sabre_Client extends Sabre_DAV_Client { return $response;
- }
-
+ }
}
\ No newline at end of file diff --git a/lib/connector/sabre/directory.php b/lib/connector/sabre/directory.php index b75bb5c50f5..0842fc4fc65 100644 --- a/lib/connector/sabre/directory.php +++ b/lib/connector/sabre/directory.php @@ -26,17 +26,33 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa /** * Creates a new file in the directory * - * data is a readable stream resource + * Data will either be supplied as a stream resource, or in certain cases + * as a string. Keep in mind that you may have to support either. + * + * After succesful creation of the file, you may choose to return the ETag + * of the new file here. + * + * The returned ETag must be surrounded by double-quotes (The quotes should + * be part of the actual string). + * + * If you cannot accurately determine the ETag, you should not return it. + * If you don't store the file exactly as-is (you're transforming it + * somehow) you should also not return an ETag. + * + * This means that if a subsequent GET to this new file does not exactly + * return the same contents of what was submitted here, you are strongly + * recommended to omit the ETag. * * @param string $name Name of the file - * @param resource $data Initial payload - * @return void + * @param resource|string $data Initial payload + * @return null|string */ public function createFile($name, $data = null) { $newPath = $this->path . '/' . $name; OC_Filesystem::file_put_contents($newPath,$data); + return OC_Connector_Sabre_Node::getETagPropertyForFile($newPath); } /** @@ -146,7 +162,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa * @return array */ public function getQuotaInfo() { - $rootInfo=OC_FileCache::get(''); + $rootInfo=OC_FileCache_Cached::get(''); return array( $rootInfo['size'], OC_Filesystem::free_space() diff --git a/lib/connector/sabre/file.php b/lib/connector/sabre/file.php index dd25df78c29..80f0a0ab4d8 100644 --- a/lib/connector/sabre/file.php +++ b/lib/connector/sabre/file.php @@ -26,13 +26,28 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D /** * Updates the data * + * The data argument is a readable stream resource. + * + * After a succesful put operation, you may choose to return an ETag. The + * etag must always be surrounded by double-quotes. These quotes must + * appear in the actual string you're returning. + * + * Clients may use the ETag from a PUT request to later on make sure that + * when they update the file, the contents haven't changed in the mean + * time. + * + * If you don't plan to store the file byte-by-byte, and you return a + * different object on a subsequent GET you are strongly recommended to not + * return an ETag, and just return null. + * * @param resource $data - * @return void + * @return string|null */ public function put($data) { OC_Filesystem::file_put_contents($this->path,$data); + return OC_Connector_Sabre_Node::getETagPropertyForFile($this->path); } /** @@ -42,7 +57,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D */ public function get() { - return OC_Filesystem::fopen($this->path,'r'); + return OC_Filesystem::fopen($this->path,'rb'); } @@ -79,9 +94,11 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D * @return mixed */ public function getETag() { - - return null; - + $properties = $this->getProperties(array(self::GETETAG_PROPERTYNAME)); + if (isset($properties[self::GETETAG_PROPERTYNAME])) { + return $properties[self::GETETAG_PROPERTYNAME]; + } + return $this->getETagPropertyForFile($this->path); } /** diff --git a/lib/connector/sabre/locks.php b/lib/connector/sabre/locks.php index 94382e68a1a..e95dcf02d27 100644 --- a/lib/connector/sabre/locks.php +++ b/lib/connector/sabre/locks.php @@ -108,7 +108,7 @@ class OC_Connector_Sabre_Locks extends Sabre_DAV_Locks_Backend_Abstract { $locks = $this->getLocks($uri,false); $exists = false; - foreach($locks as $k=>$lock) { + foreach($locks as $lock) { if ($lock->token == $lockInfo->token) $exists = true; } diff --git a/lib/connector/sabre/node.php b/lib/connector/sabre/node.php index be315a0ffd9..663970487fb 100644 --- a/lib/connector/sabre/node.php +++ b/lib/connector/sabre/node.php @@ -22,6 +22,7 @@ */ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IProperties { + const GETETAG_PROPERTYNAME = '{DAV:}getetag'; /** * The path to the current node @@ -141,6 +142,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr public function updateProperties($properties) { $existing = $this->getProperties(array()); foreach($properties as $propertyName => $propertyValue) { + $propertyName = preg_replace("/^{.*}/", "", $propertyName); // remove leading namespace from property name // If it was null, we need to delete the property if (is_null($propertyValue)) { if(array_key_exists( $propertyName, $existing )){ @@ -178,7 +180,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr * @param array $properties * @return void */ - function getProperties($properties) { + public function getProperties($properties) { if (is_null($this->property_cache)) { $query = OC_DB::prepare( 'SELECT * FROM *PREFIX*properties WHERE userid = ? AND propertypath = ?' ); $result = $query->execute( array( OC_User::getUser(), $this->path )); @@ -200,4 +202,29 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr } return $props; } + + /** + * Returns the ETag surrounded by double-quotes for this path. + * @param string $path Path of the file + * @return string|null Returns null if the ETag can not effectively be determined + */ + static public function getETagPropertyForFile($path) { + $tag = OC_Filesystem::hash('md5', $path); + if (empty($tag)) { + return null; + } + $etag = '"'.$tag.'"'; + $query = OC_DB::prepare( 'INSERT INTO *PREFIX*properties (userid,propertypath,propertyname,propertyvalue) VALUES(?,?,?,?)' ); + $query->execute( array( OC_User::getUser(), $path, self::GETETAG_PROPERTYNAME, $etag )); + return $etag; + } + + /** + * Remove the ETag from the cache. + * @param string $path Path of the file + */ + static public function removeETagPropertyForFile($path) { + $query = OC_DB::prepare( 'DELETE FROM *PREFIX*properties WHERE userid = ? AND propertypath = ? AND propertyname = ?' ); + $query->execute( array( OC_User::getUser(), $path, self::GETETAG_PROPERTYNAME )); + } } diff --git a/lib/db.php b/lib/db.php index 2a06d72ea32..6971fe4a583 100644 --- a/lib/db.php +++ b/lib/db.php @@ -33,8 +33,6 @@ class OC_DB { static private $MDB2=false; static private $PDO=false; static private $schema=false; - static private $affected=0; - static private $result=false; static private $inTransaction=false; static private $prefix=null; static private $type=null; @@ -222,7 +220,7 @@ class OC_DB { echo( '<b>can not connect to database, using '.$type.'. ('.self::$MDB2->getUserInfo().')</center>'); OC_Log::write('core',self::$MDB2->getUserInfo(),OC_Log::FATAL); OC_Log::write('core',self::$MDB2->getMessage(),OC_Log::FATAL); - die( $error ); + die(); } // We always, really always want associative arrays @@ -370,9 +368,6 @@ class OC_DB { if( $definition instanceof MDB2_Schema_Error ){ die( $definition->getMessage().': '.$definition->getUserInfo()); } -// if(OC_Config::getValue('dbtype','sqlite')=='sqlite'){ -// $definition['overwrite']=true;//always overwrite for sqlite -// } $ret=self::$schema->createDatabase( $definition ); // Die in case something went wrong @@ -519,8 +514,9 @@ class OC_DB { // Delete our temporary file unlink( $file2 ); - foreach($definition['tables'] as $name=>$table){ - self::dropTable($name); + $tables=array_keys($definition['tables']); + foreach($tables as $table){ + self::dropTable($table); } } @@ -528,8 +524,7 @@ class OC_DB { * @brief replaces the owncloud tables with a new set * @param $file string path to the MDB2 xml db export file */ - public static function replaceDB( $file ){ - + public static function replaceDB( $file ){ $apps = OC_App::getAllApps(); self::beginTransaction(); // Delete the old tables diff --git a/lib/eventsource.php b/lib/eventsource.php index cf10660b94c..95af2e471bc 100644 --- a/lib/eventsource.php +++ b/lib/eventsource.php @@ -36,12 +36,15 @@ class OC_EventSource{ header('Cache-Control: no-cache'); $this->fallback=isset($_GET['fallback']) and $_GET['fallback']=='true'; if($this->fallback){ - $fallBackId=$_GET['fallback_id']; + $this->fallBackId=$_GET['fallback_id']; header("Content-Type: text/html"); echo str_repeat('<span></span>'.PHP_EOL,10); //dummy data to keep IE happy }else{ header("Content-Type: text/event-stream"); } + if( !OC_Util::isCallRegistered()){ + exit(); + } flush(); } diff --git a/lib/exception.php b/lib/exception.php new file mode 100644 index 00000000000..db516fc12d2 --- /dev/null +++ b/lib/exception.php @@ -0,0 +1,93 @@ +<?php +/** + * ownCloud + * + * @author Georg Ehrke + * @copyright 2012 georg@owncloud.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/>. + * + */ +class OC_Exception extends Exception{ + + function __construct($message = null, $code = 0, $file = null, $line = null){ + parent::__construct($message, $code); + if(!is_null($file)){ + $this->file = $file; + } + if(!is_null($line)){ + $this->line = $line; + } + $this->writelog(); + } + + private function writelog(){ + @OC_Log::write(OC_App::getCurrentApp(), $this->getMessage() . '-' . $this->getFile() . '-' . $this->getLine(), OC_Log::FATAL); + } + + private function generatesysinfo(){ + return array('phpversion' => PHP_VERSION, + 'os' => php_uname('s'), + 'osrelease' => php_uname('r'), + 'osarchitecture' => php_uname('m'), + 'phpserverinterface' => php_sapi_name(), + 'serverprotocol' => $_SERVER['SERVER_PROTOCOL'], + 'requestmethod' => $_SERVER['REQUEST_METHOD'], + 'https' => ($_SERVER['HTTPS']==''?'false':'true'), + 'database'=>(@OC_Config::getValue('dbtype')!=''?@OC_Config::getValue('dbtype'):'') + ); + } + + function __toString(){ + $tmpl = new OC_Template('core', 'exception', 'guest'); + $tmpl->assign('showsysinfo', true); + $tmpl->assign('message', $this->getMessage()); + $tmpl->assign('code', $this->getCode()); + $tmpl->assign('file', $this->getFile()); + $tmpl->assign('line', $this->getLine()); + $tmpl->assign('sysinfo', $this->generatesysinfo()); + $tmpl->printPage(); + } +} + +function oc_exceptionhandler($exception){ + switch($exception->getCode()){ + case E_NOTICE: + case E_DEPRECATED: + case E_USER_NOTICE: + case E_USER_DEPRECATED: + break; + default: + throw new OC_Exception($exception->getMessage(), $exception->getCode(), $exception->getFile(), $exception->getLine()); + break; + } + return true; +} + +function oc_errorhandler($errno , $errstr , $errfile , $errline){ + switch($errno){ + case E_NOTICE: + case E_DEPRECATED: + case E_USER_NOTICE: + case E_USER_DEPRECATED: + break; + default: + throw new OC_Exception($errstr, $errno, $errfile, $errline); + break; + } + return true; +} +set_exception_handler('oc_exceptionhandler'); +set_error_handler('oc_errorhandler'); +error_reporting(E_ERROR | E_WARNING | E_PARSE);
\ No newline at end of file diff --git a/lib/filecache.php b/lib/filecache.php index d956f34dc48..22f7427ae42 100644 --- a/lib/filecache.php +++ b/lib/filecache.php @@ -98,6 +98,10 @@ class OC_FileCache{ if(OC_DB::isError($result)){ OC_Log::write('files','error while writing file('.$path.') to cache',OC_Log::ERROR); } + + if($cache=OC_Cache::getUserCache(true)){ + $cache->remove('fileid/'.$path);//ensure we don't have -1 cached + } } /** @@ -126,7 +130,7 @@ class OC_FileCache{ $query=OC_DB::prepare($sql); $result=$query->execute($arguments); if(OC_DB::isError($result)){ - OC_Log::write('files','error while updating file('.$path.') in cache',OC_Log::ERROR); + OC_Log::write('files','error while updating file('.$id.') in cache',OC_Log::ERROR); } } @@ -146,6 +150,11 @@ class OC_FileCache{ $query=OC_DB::prepare('UPDATE *PREFIX*fscache SET parent=? ,name=?, path=?, path_hash=? WHERE path_hash=?'); $query->execute(array($newParent,basename($newPath),$newPath,md5($newPath),md5($oldPath))); + if(($cache=OC_Cache::getUserCache(true)) && $cache->hasKey('fileid/'.$oldPath)){ + $cache->set('fileid/'.$newPath,$cache->get('fileid/'.$oldPath)); + $cache->remove('fileid/'.$oldPath); + } + $query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE path LIKE ?'); $oldLength=strlen($oldPath); $updateQuery=OC_DB::prepare('UPDATE *PREFIX*fscache SET path=?, path_hash=? WHERE path_hash=?'); @@ -153,6 +162,11 @@ class OC_FileCache{ $old=$row['path']; $new=$newPath.substr($old,$oldLength); $updateQuery->execute(array($new,md5($new),md5($old))); + + if(($cache=OC_Cache::getUserCache(true)) && $cache->hasKey('fileid/'.$old)){ + $cache->set('fileid/'.$new,$cache->get('fileid/'.$old)); + $cache->remove('fileid/'.$old); + } } } @@ -171,6 +185,8 @@ class OC_FileCache{ //delete everything inside the folder $query=OC_DB::prepare('DELETE FROM *PREFIX*fscache WHERE path LIKE ?'); $query->execute(array($root.$path.'/%')); + + OC_Cache::remove('fileid/'.$root.$path); } /** @@ -245,9 +261,14 @@ class OC_FileCache{ if($root===false){ $root=OC_Filesystem::getRoot(); } + + $fullPath=$root.$path; + if(($cache=OC_Cache::getUserCache(true)) && $cache->hasKey('fileid/'.$fullPath)){ + return $cache->get('fileid/'.$fullPath); + } $query=OC_DB::prepare('SELECT id FROM *PREFIX*fscache WHERE path_hash=?'); - $result=$query->execute(array(md5($root.$path))); + $result=$query->execute(array(md5($fullPath))); if(OC_DB::isError($result)){ OC_Log::write('files','error while getting file id of '.$path,OC_Log::ERROR); return -1; @@ -255,10 +276,15 @@ class OC_FileCache{ $result=$result->fetchRow(); if(is_array($result)){ - return $result['id']; + $id=$result['id']; }else{ - return -1; + $id=-1; } + if($cache=OC_Cache::getUserCache(true)){ + $cache->set('fileid/'.$fullPath,$id); + } + + return $id; } /** @@ -303,7 +329,7 @@ class OC_FileCache{ */ public static function increaseSize($path,$sizeDiff, $root=false){ if($sizeDiff==0) return; - $id=self::getId($path,''); + $id=self::getId($path,$root); while($id!=-1){//walk up the filetree increasing the size of all parent folders $query=OC_DB::prepare('UPDATE *PREFIX*fscache SET size=size+? WHERE id=?'); $query->execute(array($sizeDiff,$id)); diff --git a/lib/filecache/update.php b/lib/filecache/update.php index dd77f491ca0..93b632acb4e 100644 --- a/lib/filecache/update.php +++ b/lib/filecache/update.php @@ -207,7 +207,6 @@ class OC_FileCache_Update{ $cached=OC_FileCache_Cached::get($oldPath,$root); $oldSize=$cached['size']; - $size=$view->filesize($newPath); OC_FileCache::increaseSize(dirname($oldPath),-$oldSize,$root); OC_FileCache::increaseSize(dirname($newPath),$oldSize,$root); OC_FileCache::move($oldPath,$newPath); diff --git a/lib/filestorage.php b/lib/filestorage.php index 71ef4aed00b..e786127d525 100644 --- a/lib/filestorage.php +++ b/lib/filestorage.php @@ -24,7 +24,7 @@ * Provde a common interface to all different storage options */ abstract class OC_Filestorage{ - public function __construct($parameters){} + abstract public function __construct($parameters); abstract public function mkdir($path); abstract public function rmdir($path); abstract public function opendir($path); diff --git a/lib/filestorage/common.php b/lib/filestorage/common.php index ba78fca80e5..fd389d3e2d7 100644 --- a/lib/filestorage/common.php +++ b/lib/filestorage/common.php @@ -220,7 +220,7 @@ abstract class OC_Filestorage_Common extends OC_Filestorage { } $tmpFile=OC_Helper::tmpFile($extension); $target=fopen($tmpFile,'w'); - $count=OC_Helper::streamCopy($source,$target); + OC_Helper::streamCopy($source,$target); return $tmpFile; } // abstract public function touch($path, $mtime=null); diff --git a/lib/filestorage/local.php b/lib/filestorage/local.php index b2eba051515..d60f32b15be 100644 --- a/lib/filestorage/local.php +++ b/lib/filestorage/local.php @@ -4,7 +4,6 @@ */ class OC_Filestorage_Local extends OC_Filestorage_Common{ protected $datadir; - private static $mimetypes=null; public function __construct($arguments){ $this->datadir=$arguments['datadir']; if(substr($this->datadir,-1)!=='/'){ @@ -41,7 +40,7 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{ } public function filesize($path){ if($this->is_dir($path)){ - return $this->getFolderSize($path); + return 0; }else{ return filesize($this->datadir.$path); } @@ -157,7 +156,7 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{ return $return; } - public function hash($type,$path,$raw){ + public function hash($path,$type,$raw=false){ return hash_file($type,$this->datadir.$path,$raw); } @@ -187,15 +186,6 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{ } /** - * @brief get the size of folder and it's content - * @param string $path file path - * @return int size of folder and it's content - */ - public function getFolderSize($path){ - return 0;//depricated, use OC_FileCach instead - } - - /** * check if a file or folder has been updated since $time * @param int $time * @return bool diff --git a/lib/filesystem.php b/lib/filesystem.php index 65318fa3ab6..a5edcf5bab3 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -46,105 +46,106 @@ class OC_Filesystem{ static private $storages=array(); static private $mounts=array(); - static private $storageTypes=array(); public static $loaded=false; - private $fakeRoot=''; + /** + * @var OC_Filestorage $defaultInstance + */ static private $defaultInstance; - /** - * classname which used for hooks handling - * used as signalclass in OC_Hooks::emit() - */ - const CLASSNAME = 'OC_Filesystem'; - - /** - * signalname emited before file renaming - * @param oldpath - * @param newpath - */ - const signal_rename = 'rename'; - - /** - * signal emited after file renaming - * @param oldpath - * @param newpath - */ - const signal_post_rename = 'post_rename'; - - /** - * signal emited before file/dir creation - * @param path - * @param run changing this flag to false in hook handler will cancel event - */ - const signal_create = 'create'; - - /** - * signal emited after file/dir creation - * @param path - * @param run changing this flag to false in hook handler will cancel event - */ - const signal_post_create = 'post_create'; - - /** - * signal emits before file/dir copy - * @param oldpath - * @param newpath - * @param run changing this flag to false in hook handler will cancel event - */ - const signal_copy = 'copy'; - - /** - * signal emits after file/dir copy - * @param oldpath - * @param newpath - */ - const signal_post_copy = 'post_copy'; - - /** - * signal emits before file/dir save - * @param path - * @param run changing this flag to false in hook handler will cancel event - */ - const signal_write = 'write'; - - /** - * signal emits after file/dir save - * @param path - */ - const signal_post_write = 'post_write'; - - /** - * signal emits when reading file/dir - * @param path - */ - const signal_read = 'read'; - - /** - * signal emits when removing file/dir - * @param path - */ - const signal_delete = 'delete'; - - /** - * parameters definitions for signals - */ - const signal_param_path = 'path'; - const signal_param_oldpath = 'oldpath'; - const signal_param_newpath = 'newpath'; - - /** - * run - changing this flag to false in hook handler will cancel event - */ - const signal_param_run = 'run'; - - /** - * get the mountpoint of the storage object for a path - ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account - * - * @param string path - * @return string - */ + /** + * classname which used for hooks handling + * used as signalclass in OC_Hooks::emit() + */ + const CLASSNAME = 'OC_Filesystem'; + + /** + * signalname emited before file renaming + * @param oldpath + * @param newpath + */ + const signal_rename = 'rename'; + + /** + * signal emited after file renaming + * @param oldpath + * @param newpath + */ + const signal_post_rename = 'post_rename'; + + /** + * signal emited before file/dir creation + * @param path + * @param run changing this flag to false in hook handler will cancel event + */ + const signal_create = 'create'; + + /** + * signal emited after file/dir creation + * @param path + * @param run changing this flag to false in hook handler will cancel event + */ + const signal_post_create = 'post_create'; + + /** + * signal emits before file/dir copy + * @param oldpath + * @param newpath + * @param run changing this flag to false in hook handler will cancel event + */ + const signal_copy = 'copy'; + + /** + * signal emits after file/dir copy + * @param oldpath + * @param newpath + */ + const signal_post_copy = 'post_copy'; + + /** + * signal emits before file/dir save + * @param path + * @param run changing this flag to false in hook handler will cancel event + */ + const signal_write = 'write'; + + /** + * signal emits after file/dir save + * @param path + */ + const signal_post_write = 'post_write'; + + /** + * signal emits when reading file/dir + * @param path + */ + const signal_read = 'read'; + + /** + * signal emits when removing file/dir + * @param path + */ + const signal_delete = 'delete'; + + /** + * parameters definitions for signals + */ + const signal_param_path = 'path'; + const signal_param_oldpath = 'oldpath'; + const signal_param_newpath = 'newpath'; + + /** + * run - changing this flag to false in hook handler will cancel event + */ + const signal_param_run = 'run'; + + /** + * get the mountpoint of the storage object for a path + ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account + * + * @param string path + * @return string + */ static public function getMountPoint($path){ OC_Hook::emit(self::CLASSNAME,'get_mountpoint',array('path'=>$path)); if(!$path){ @@ -155,7 +156,8 @@ class OC_Filesystem{ } $path=str_replace('//', '/',$path); $foundMountPoint=''; - foreach(OC_Filesystem::$mounts as $mountpoint=>$storage){ + $mountPoints=array_keys(OC_Filesystem::$mounts); + foreach($mountPoints as $mountpoint){ if($mountpoint==$path){ return $mountpoint; } @@ -260,10 +262,7 @@ class OC_Filesystem{ * tear down the filesystem, removing all storage providers */ static public function tearDown(){ - foreach(self::$storages as $mountpoint=>$storage){ - unset(self::$storages[$mountpoint]); - } - $fakeRoot=''; + self::$storages=array(); } /** @@ -287,7 +286,7 @@ class OC_Filesystem{ * @return bool */ static public function chroot($fakeRoot){ - return self::$defaultInstance->chroot($path); + return self::$defaultInstance->chroot($fakeRoot); } /** @@ -320,22 +319,8 @@ class OC_Filesystem{ if(substr($mountpoint,-1)!=='/'){ $mountpoint=$mountpoint.'/'; } - if (self::getView() != null && $mountpoint != '/' && !self::is_dir(basename($mountpoint))) { - self::mkdir(basename($mountpoint)); - } self::$mounts[$mountpoint]=array('class'=>$class,'arguments'=>$arguments); } - - /** - * create all storage backends mounted in the filesystem - */ - static private function mountAll(){ - foreach(self::$mounts as $mountPoint=>$mount){ - if(!isset(self::$storages[$mountPoint])){ - self::$storages[$mountPoint]=self::createStorage($mount['type'],$mount['arguments']); - } - } - } /** * return the path to a local version of the file @@ -485,9 +470,17 @@ class OC_Filesystem{ * @return bool */ static public function hasUpdated($path,$time){ - return self::$defaultInstance->hasUpdated($path); + return self::$defaultInstance->hasUpdated($path,$time); + } + + static public function removeETagHook($params) { + $path=$params['path']; + OC_Connector_Sabre_Node::removeETagPropertyForFile($path); } } +OC_Hook::connect('OC_Filesystem','post_write', 'OC_Filesystem','removeETagHook'); +OC_Hook::connect('OC_Filesystem','post_delete','OC_Filesystem','removeETagHook'); +OC_Hook::connect('OC_Filesystem','post_rename','OC_Filesystem','removeETagHook'); OC_Util::setupFS(); require_once('filecache.php'); diff --git a/lib/filesystemview.php b/lib/filesystemview.php index 448663bb081..9beda01e5a1 100644 --- a/lib/filesystemview.php +++ b/lib/filesystemview.php @@ -22,19 +22,19 @@ /** - * Class to provide access to ownCloud filesystem via a "view", and methods for - * working with files within that view (e.g. read, write, delete, etc.). Each - * view is restricted to a set of directories via a virtual root. The default view - * uses the currently logged in user's data directory as root (parts of + * Class to provide access to ownCloud filesystem via a "view", and methods for + * working with files within that view (e.g. read, write, delete, etc.). Each + * view is restricted to a set of directories via a virtual root. The default view + * uses the currently logged in user's data directory as root (parts of * OC_Filesystem are merely a wrapper for OC_FilesystemView). - * + * * Apps that need to access files outside of the user data folders (to modify files * belonging to a user other than the one currently logged in, for example) should * use this class directly rather than using OC_Filesystem, or making use of PHP's - * built-in file manipulation functions. This will ensure all hooks and proxies + * built-in file manipulation functions. This will ensure all hooks and proxies * are triggered correctly. * - * Filesystem functions are not called directly; they are passed to the correct + * Filesystem functions are not called directly; they are passed to the correct * OC_Filestorage object */ @@ -43,11 +43,11 @@ class OC_FilesystemView { private $internal_path_cache=array(); private $storage_cache=array(); - public function __construct($root){ + public function __construct($root) { $this->fakeRoot=$root; } - public function getAbsolutePath($path){ + public function getAbsolutePath($path) { if(!$path){ $path='/'; } @@ -63,9 +63,9 @@ class OC_FilesystemView { * @param string fakeRoot * @return bool */ - public function chroot($fakeRoot){ + public function chroot($fakeRoot) { if(!$fakeRoot==''){ - if($fakeRoot[0]!=='/'){ + if($fakeRoot[0]!=='/') { $fakeRoot='/'.$fakeRoot; } } @@ -76,7 +76,7 @@ class OC_FilesystemView { * get the fake root * @return string */ - public function getRoot(){ + public function getRoot() { return $this->fakeRoot; } @@ -85,7 +85,7 @@ class OC_FilesystemView { * @param string path * @return bool */ - public function getInternalPath($path){ + public function getInternalPath($path) { if (!isset($this->internal_path_cache[$path])) { $this->internal_path_cache[$path] = OC_Filesystem::getInternalPath($this->getAbsolutePath($path)); } @@ -97,23 +97,23 @@ class OC_FilesystemView { * @param string path * @return string */ - public function getRelativePath($path){ - if($this->fakeRoot==''){ + public function getRelativePath($path) { + if($this->fakeRoot=='') { return $path; } - if(strpos($path,$this->fakeRoot)!==0){ + if(strpos($path, $this->fakeRoot)!==0) { return null; }else{ - return substr($path,strlen($this->fakeRoot)); + return substr($path, strlen($this->fakeRoot)); } } - + /** * get the storage object for a path * @param string path * @return OC_Filestorage */ - public function getStorage($path){ + public function getStorage($path) { if (!isset($this->storage_cache[$path])) { $this->storage_cache[$path] = OC_Filesystem::getStorage($this->getAbsolutePath($path)); } @@ -127,7 +127,7 @@ class OC_FilesystemView { * @param string path * @return string */ - public function getMountPoint($path){ + public function getMountPoint($path) { return OC_Filesystem::getMountPoint($this->getAbsolutePath($path)); } @@ -137,55 +137,55 @@ class OC_FilesystemView { * @param string path * @return string */ - public function getLocalFile($path){ - $parent=substr($path,0,strrpos($path,'/')); - if(OC_Filesystem::isValidPath($parent) and $storage=$this->getStorage($path)){ + public function getLocalFile($path) { + $parent=substr($path, 0, strrpos($path,'/')); + if(OC_Filesystem::isValidPath($parent) and $storage=$this->getStorage($path)) { return $storage->getLocalFile($this->getInternalPath($path)); } } /** - * the following functions operate with arguments and return values identical - * to those of their PHP built-in equivalents. Mostly they are merely wrappers + * the following functions operate with arguments and return values identical + * to those of their PHP built-in equivalents. Mostly they are merely wrappers * for OC_Filestorage via basicOperation(). */ - public function mkdir($path){ - return $this->basicOperation('mkdir',$path,array('create','write')); + public function mkdir($path) { + return $this->basicOperation('mkdir', $path, array('create', 'write')); } - public function rmdir($path){ - return $this->basicOperation('rmdir',$path,array('delete')); + public function rmdir($path) { + return $this->basicOperation('rmdir', $path, array('delete')); } - public function opendir($path){ - return $this->basicOperation('opendir',$path,array('read')); + public function opendir($path) { + return $this->basicOperation('opendir', $path, array('read')); } - public function readdir($handle){ + public function readdir($handle) { $fsLocal= new OC_Filestorage_Local( array( 'datadir' => '/' ) ); return $fsLocal->readdir( $handle ); } - public function is_dir($path){ + public function is_dir($path) { if($path=='/'){ return true; } - return $this->basicOperation('is_dir',$path); + return $this->basicOperation('is_dir', $path); } - public function is_file($path){ + public function is_file($path) { if($path=='/'){ return false; } - return $this->basicOperation('is_file',$path); + return $this->basicOperation('is_file', $path); } - public function stat($path){ - return $this->basicOperation('stat',$path); + public function stat($path) { + return $this->basicOperation('stat', $path); } - public function filetype($path){ - return $this->basicOperation('filetype',$path); + public function filetype($path) { + return $this->basicOperation('filetype', $path); } - public function filesize($path){ - return $this->basicOperation('filesize',$path); + public function filesize($path) { + return $this->basicOperation('filesize', $path); } - public function readfile($path){ + public function readfile($path) { @ob_end_clean(); - $handle=$this->fopen($path,'rb'); + $handle=$this->fopen($path, 'rb'); if ($handle) { $chunkSize = 8192;// 8 MB chunks while (!feof($handle)) { @@ -197,137 +197,210 @@ class OC_FilesystemView { } return false; } - public function is_readable($path){ - return $this->basicOperation('is_readable',$path); + public function is_readable($path) { + return $this->basicOperation('is_readable', $path); } - public function is_writable($path){ - return $this->basicOperation('is_writable',$path); + public function is_writable($path) { + return $this->basicOperation('is_writable', $path); } - public function file_exists($path){ + public function file_exists($path) { if($path=='/'){ return true; } - return $this->basicOperation('file_exists',$path); + return $this->basicOperation('file_exists', $path); } - public function filectime($path){ - return $this->basicOperation('filectime',$path); + public function filectime($path) { + return $this->basicOperation('filectime', $path); } - public function filemtime($path){ - return $this->basicOperation('filemtime',$path); + public function filemtime($path) { + return $this->basicOperation('filemtime', $path); } - public function touch($path, $mtime=null){ + public function touch($path, $mtime=null) { return $this->basicOperation('touch', $path, array('write'), $mtime); } - public function file_get_contents($path){ - return $this->basicOperation('file_get_contents',$path,array('read')); - } - public function file_put_contents($path,$data){ - if(is_resource($data)){//not having to deal with streams in file_put_contents makes life easier - $exists=$this->file_exists($path); - $run=true; - if(!$exists){ - OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_create, array( OC_Filesystem::signal_param_path => $path, OC_Filesystem::signal_param_run => &$run)); + public function file_get_contents($path) { + return $this->basicOperation('file_get_contents', $path, array('read')); + } + public function file_put_contents($path, $data) { + if(is_resource($data)) {//not having to deal with streams in file_put_contents makes life easier + $exists = $this->file_exists($path); + $run = true; + if(!$exists) { + OC_Hook::emit( + OC_Filesystem::CLASSNAME, + OC_Filesystem::signal_create, + array( + OC_Filesystem::signal_param_path => $path, + OC_Filesystem::signal_param_run => &$run + ) + ); } - OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_write, array( OC_Filesystem::signal_param_path => $path, OC_Filesystem::signal_param_run => &$run)); - if(!$run){ + OC_Hook::emit( + OC_Filesystem::CLASSNAME, + OC_Filesystem::signal_write, + array( + OC_Filesystem::signal_param_path => $path, + OC_Filesystem::signal_param_run => &$run + ) + ); + if(!$run) { return false; } - $target=$this->fopen($path,'w'); - if($target){ - $count=OC_Helper::streamCopy($data,$target); + $target=$this->fopen($path, 'w'); + if($target) { + $count=OC_Helper::streamCopy($data, $target); fclose($target); fclose($data); - if(!$exists){ - OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_create, array( OC_Filesystem::signal_param_path => $path)); + if(!$exists) { + OC_Hook::emit( + OC_Filesystem::CLASSNAME, + OC_Filesystem::signal_post_create, + array( OC_Filesystem::signal_param_path => $path) + ); } - OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_write, array( OC_Filesystem::signal_param_path => $path)); - return $count>0; + OC_Hook::emit( + OC_Filesystem::CLASSNAME, + OC_Filesystem::signal_post_write, + array( OC_Filesystem::signal_param_path => $path) + ); + return $count > 0; }else{ return false; } }else{ - return $this->basicOperation('file_put_contents',$path,array('create','write'),$data); + return $this->basicOperation('file_put_contents', $path, array('create', 'write'), $data); } } - public function unlink($path){ - return $this->basicOperation('unlink',$path,array('delete')); + public function unlink($path) { + return $this->basicOperation('unlink', $path, array('delete')); } public function deleteAll( $directory, $empty = false ) { return $this->basicOperation( 'deleteAll', $directory, array('delete'), $empty ); } - public function rename($path1,$path2){ - $absolutePath1=$this->getAbsolutePath($path1); - $absolutePath2=$this->getAbsolutePath($path2); - if(OC_FileProxy::runPreProxies('rename',$absolutePath1,$absolutePath2) and OC_Filesystem::isValidPath($path2)){ - $path1=$this->getRelativePath($absolutePath1); - $path2=$this->getRelativePath($absolutePath2); - if($path1==null or $path2==null){ + public function rename($path1, $path2) { + $absolutePath1 = $this->getAbsolutePath($path1); + $absolutePath2 = $this->getAbsolutePath($path2); + if(OC_FileProxy::runPreProxies('rename', $absolutePath1, $absolutePath2) and OC_Filesystem::isValidPath($path2)) { + $path1 = $this->getRelativePath($absolutePath1); + $path2 = $this->getRelativePath($absolutePath2); + if($path1 == null or $path2 == null) { return false; } $run=true; - OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_rename, array( OC_Filesystem::signal_param_oldpath => $path1 , OC_Filesystem::signal_param_newpath=>$path2, OC_Filesystem::signal_param_run => &$run)); - if($run){ - $mp1=$this->getMountPoint($path1); - $mp2=$this->getMountPoint($path2); - if($mp1==$mp2){ - if($storage=$this->getStorage($path1)){ - $result=$storage->rename($this->getInternalPath($path1),$this->getInternalPath($path2)); + OC_Hook::emit( + OC_Filesystem::CLASSNAME, OC_Filesystem::signal_rename, + array( + OC_Filesystem::signal_param_oldpath => $path1, + OC_Filesystem::signal_param_newpath => $path2, + OC_Filesystem::signal_param_run => &$run + ) + ); + if($run) { + $mp1 = $this->getMountPoint($path1); + $mp2 = $this->getMountPoint($path2); + if($mp1 == $mp2) { + if($storage = $this->getStorage($path1)) { + $result = $storage->rename($this->getInternalPath($path1), $this->getInternalPath($path2)); } - }else{ - $source=$this->fopen($path1,'r'); - $target=$this->fopen($path2,'w'); - $count=OC_Helper::streamCopy($source,$target); - $storage1=$this->getStorage($path1); + } else { + $source = $this->fopen($path1, 'r'); + $target = $this->fopen($path2, 'w'); + $count = OC_Helper::streamCopy($source, $target); + $storage1 = $this->getStorage($path1); $storage1->unlink($this->getInternalPath($path1)); - $result=$count>0; + $result = $count>0; } - OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_rename, array( OC_Filesystem::signal_param_oldpath => $path1, OC_Filesystem::signal_param_newpath=>$path2)); + OC_Hook::emit( + OC_Filesystem::CLASSNAME, + OC_Filesystem::signal_post_rename, + array( + OC_Filesystem::signal_param_oldpath => $path1, + OC_Filesystem::signal_param_newpath => $path2 + ) + ); return $result; } } } - public function copy($path1,$path2){ - $absolutePath1=$this->getAbsolutePath($path1); - $absolutePath2=$this->getAbsolutePath($path2); - if(OC_FileProxy::runPreProxies('copy',$absolutePath1,$absolutePath2) and OC_Filesystem::isValidPath($path2)){ - $path1=$this->getRelativePath($absolutePath1); - $path2=$this->getRelativePath($absolutePath2); - if($path1==null or $path2==null){ + public function copy($path1, $path2) { + $absolutePath1 = $this->getAbsolutePath($path1); + $absolutePath2 = $this->getAbsolutePath($path2); + if(OC_FileProxy::runPreProxies('copy', $absolutePath1, $absolutePath2) and OC_Filesystem::isValidPath($path2)) { + $path1 = $this->getRelativePath($absolutePath1); + $path2 = $this->getRelativePath($absolutePath2); + if($path1 == null or $path2 == null) { return false; } $run=true; - OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_copy, array( OC_Filesystem::signal_param_oldpath => $path1 , OC_Filesystem::signal_param_newpath=>$path2, OC_Filesystem::signal_param_run => &$run)); + OC_Hook::emit( + OC_Filesystem::CLASSNAME, + OC_Filesystem::signal_copy, + array( + OC_Filesystem::signal_param_oldpath => $path1, + OC_Filesystem::signal_param_newpath=>$path2, + OC_Filesystem::signal_param_run => &$run + ) + ); $exists=$this->file_exists($path2); - if($run and !$exists){ - OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_create, array( OC_Filesystem::signal_param_path => $path2, OC_Filesystem::signal_param_run => &$run)); + if($run and !$exists) { + OC_Hook::emit( + OC_Filesystem::CLASSNAME, + OC_Filesystem::signal_create, + array( + OC_Filesystem::signal_param_path => $path2, + OC_Filesystem::signal_param_run => &$run + ) + ); } - if($run){ - OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_write, array( OC_Filesystem::signal_param_path => $path2, OC_Filesystem::signal_param_run => &$run)); + if($run) { + OC_Hook::emit( + OC_Filesystem::CLASSNAME, + OC_Filesystem::signal_write, + array( + OC_Filesystem::signal_param_path => $path2, + OC_Filesystem::signal_param_run => &$run + ) + ); } - if($run){ + if($run) { $mp1=$this->getMountPoint($path1); $mp2=$this->getMountPoint($path2); - if($mp1==$mp2){ - if($storage=$this->getStorage($path1)){ - $result=$storage->copy($this->getInternalPath($path1),$this->getInternalPath($path2)); + if($mp1 == $mp2){ + if($storage = $this->getStorage($path1)) { + $result=$storage->copy($this->getInternalPath($path1), $this->getInternalPath($path2)); } - }else{ - $source=$this->fopen($path1,'r'); - $target=$this->fopen($path2,'w'); - $result=OC_Helper::streamCopy($source,$target); + } else { + $source = $this->fopen($path1, 'r'); + $target = $this->fopen($path2, 'w'); + $result = OC_Helper::streamCopy($source, $target); } - OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_copy, array( OC_Filesystem::signal_param_oldpath => $path1 , OC_Filesystem::signal_param_newpath=>$path2)); - if(!$exists){ - OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_create, array( OC_Filesystem::signal_param_path => $path2)); + OC_Hook::emit( + OC_Filesystem::CLASSNAME, + OC_Filesystem::signal_post_copy, + array( + OC_Filesystem::signal_param_oldpath => $path1, + OC_Filesystem::signal_param_newpath=>$path2 + ) + ); + if(!$exists) { + OC_Hook::emit( + OC_Filesystem::CLASSNAME, + OC_Filesystem::signal_post_create, + array(OC_Filesystem::signal_param_path => $path2) + ); } - OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_write, array( OC_Filesystem::signal_param_path => $path2)); + OC_Hook::emit( + OC_Filesystem::CLASSNAME, + OC_Filesystem::signal_post_write, + array( OC_Filesystem::signal_param_path => $path2) + ); return $result; } } } - public function fopen($path,$mode){ + public function fopen($path, $mode) { $hooks=array(); - switch($mode){ + switch($mode) { case 'r': case 'rb': $hooks[]='read'; @@ -355,49 +428,49 @@ class OC_FilesystemView { OC_Log::write('core','invalid mode ('.$mode.') for '.$path,OC_Log::ERROR); } - return $this->basicOperation('fopen',$path,$hooks,$mode); + return $this->basicOperation('fopen', $path, $hooks, $mode); } - public function toTmpFile($path){ - if(OC_Filesystem::isValidPath($path)){ - $source=$this->fopen($path,'r'); - if($source){ + public function toTmpFile($path) { + if(OC_Filesystem::isValidPath($path)) { + $source = $this->fopen($path, 'r'); + if($source) { $extension=''; - $extOffset=strpos($path,'.'); + $extOffset=strpos($path, '.'); if($extOffset !== false) { - $extension=substr($path,strrpos($path,'.')); + $extension=substr($path, strrpos($path,'.')); } - $tmpFile=OC_Helper::tmpFile($extension); - file_put_contents($tmpFile,$source); + $tmpFile = OC_Helper::tmpFile($extension); + file_put_contents($tmpFile, $source); return $tmpFile; } } } - public function fromTmpFile($tmpFile,$path){ - if(OC_Filesystem::isValidPath($path)){ - if(!$tmpFile){ + public function fromTmpFile($tmpFile, $path) { + if(OC_Filesystem::isValidPath($path)) { + if(!$tmpFile) { debug_print_backtrace(); } - $source=fopen($tmpFile,'r'); - if($source){ - $this->file_put_contents($path,$source); + $source=fopen($tmpFile, 'r'); + if($source) { + $this->file_put_contents($path, $source); unlink($tmpFile); return true; - }else{ + } else { } - }else{ + } else { return false; } } - public function getMimeType($path){ - return $this->basicOperation('getMimeType',$path); + public function getMimeType($path) { + return $this->basicOperation('getMimeType', $path); } - public function hash($type,$path){ - return $this->basicOperation('hash',$path,array('read')); + public function hash($type, $path) { + return $this->basicOperation('hash', $path, array('read'), $type); } - public function free_space($path='/'){ - return $this->basicOperation('free_space',$path); + public function free_space($path='/') { + return $this->basicOperation('free_space', $path); } /** @@ -407,41 +480,56 @@ class OC_FilesystemView { * @param array (optional) hooks * @param mixed (optional) $extraParam * @return mixed - * - * This method takes requests for basic filesystem functions (e.g. reading & writing - * files), processes hooks and proxies, sanitises paths, and finally passes them on to + * + * This method takes requests for basic filesystem functions (e.g. reading & writing + * files), processes hooks and proxies, sanitises paths, and finally passes them on to * OC_Filestorage for delegation to a storage backend for execution */ - private function basicOperation($operation,$path,$hooks=array(),$extraParam=null){ - $absolutePath=$this->getAbsolutePath($path); - if(OC_FileProxy::runPreProxies($operation,$absolutePath, $extraParam) and OC_Filesystem::isValidPath($path)){ - $path=$this->getRelativePath($absolutePath); - if($path==null){ + private function basicOperation($operation, $path, $hooks=array(), $extraParam=null) { + $absolutePath = $this->getAbsolutePath($path); + if(OC_FileProxy::runPreProxies($operation, $absolutePath, $extraParam) and OC_Filesystem::isValidPath($path)) { + $path = $this->getRelativePath($absolutePath); + if($path == null) { return false; } - $internalPath=$this->getInternalPath($path); - $run=true; - if(OC_Filesystem::$loaded and $this->fakeRoot==OC_Filesystem::getRoot()){ - foreach($hooks as $hook){ - if($hook!='read'){ - OC_Hook::emit( OC_Filesystem::CLASSNAME, $hook, array( OC_Filesystem::signal_param_path => $path, OC_Filesystem::signal_param_run => &$run)); - }else{ - OC_Hook::emit( OC_Filesystem::CLASSNAME, $hook, array( OC_Filesystem::signal_param_path => $path)); + $internalPath = $this->getInternalPath($path); + $run = true; + if(OC_Filesystem::$loaded and $this->fakeRoot==OC_Filesystem::getRoot()) { + foreach($hooks as $hook) { + if($hook!='read') { + OC_Hook::emit( + OC_Filesystem::CLASSNAME, + $hook, + array( + OC_Filesystem::signal_param_path => $path, + OC_Filesystem::signal_param_run => &$run + ) + ); + } else { + OC_Hook::emit( + OC_Filesystem::CLASSNAME, + $hook, + array( OC_Filesystem::signal_param_path => $path) + ); } } } - if($run and $storage=$this->getStorage($path)){ - if(!is_null($extraParam)){ - $result=$storage->$operation($internalPath,$extraParam); - }else{ - $result=$storage->$operation($internalPath); + if($run and $storage = $this->getStorage($path)) { + if(!is_null($extraParam)) { + $result = $storage->$operation($internalPath, $extraParam); + } else { + $result = $storage->$operation($internalPath); } - $result=OC_FileProxy::runPostProxies($operation,$this->getAbsolutePath($path),$result); - if(OC_Filesystem::$loaded and $this->fakeRoot==OC_Filesystem::getRoot()){ - if($operation!='fopen'){//no post hooks for fopen, the file stream is still open - foreach($hooks as $hook){ + $result = OC_FileProxy::runPostProxies($operation, $this->getAbsolutePath($path), $result); + if(OC_Filesystem::$loaded and $this->fakeRoot==OC_Filesystem::getRoot()) { + if($operation!='fopen') {//no post hooks for fopen, the file stream is still open + foreach($hooks as $hook) { if($hook!='read'){ - OC_Hook::emit( OC_Filesystem::CLASSNAME, 'post_'.$hook, array( OC_Filesystem::signal_param_path => $path)); + OC_Hook::emit( + OC_Filesystem::CLASSNAME, + 'post_'.$hook, + array( OC_Filesystem::signal_param_path => $path) + ); } } } @@ -457,7 +545,7 @@ class OC_FilesystemView { * @param int $time * @return bool */ - public function hasUpdated($path,$time){ - return $this->basicOperation('hasUpdated',$path,array(),$time); + public function hasUpdated($path, $time) { + return $this->basicOperation('hasUpdated', $path, array(), $time); } } diff --git a/lib/group.php b/lib/group.php index ceee5fa4edb..12e5f5ebb30 100644 --- a/lib/group.php +++ b/lib/group.php @@ -43,7 +43,7 @@ class OC_Group { * @returns true/false */ public static function useBackend( $backend ){ - if($backend instanceof OC_Group_Backend){ + if($backend instanceof OC_Group_Interface){ self::$_usedBackends[]=$backend; } } @@ -168,7 +168,7 @@ class OC_Group { if($run){ $succes=false; - + //add the user to the all backends that have the group foreach(self::$_usedBackends as $backend){ if(!$backend->implementsActions(OC_GROUP_BACKEND_ADD_TO_GROUP)) @@ -245,7 +245,7 @@ class OC_Group { asort($groups); return $groups; } - + /** * check if a group exists * @param string $gid @@ -259,7 +259,7 @@ class OC_Group { } return false; } - + /** * @brief get a list of all users in a group * @returns array with user ids diff --git a/lib/group/backend.php b/lib/group/backend.php index 24778afd1e5..ebc078f152a 100644 --- a/lib/group/backend.php +++ b/lib/group/backend.php @@ -37,7 +37,7 @@ define('OC_GROUP_BACKEND_REMOVE_FROM_GOUP', 0x00001000); /** * Abstract base class for user management */ -abstract class OC_Group_Backend { +abstract class OC_Group_Backend implements OC_Group_Interface { protected $possibleActions = array( OC_GROUP_BACKEND_CREATE_GROUP => 'createGroup', OC_GROUP_BACKEND_DELETE_GROUP => 'deleteGroup', diff --git a/lib/group/database.php b/lib/group/database.php index fb173665eb8..2770ec185c4 100644 --- a/lib/group/database.php +++ b/lib/group/database.php @@ -41,7 +41,6 @@ * Class for group management in a SQL Database (e.g. MySQL, SQLite) */ class OC_Group_Database extends OC_Group_Backend { - private $userGroupCache=array(); /** * @brief Try to create a new group @@ -116,7 +115,7 @@ class OC_Group_Database extends OC_Group_Backend { // No duplicate entries! if( !$this->inGroup( $uid, $gid )){ $query = OC_DB::prepare( "INSERT INTO `*PREFIX*group_user` ( `uid`, `gid` ) VALUES( ?, ? )" ); - $result = $query->execute( array( $uid, $gid )); + $query->execute( array( $uid, $gid )); return true; }else{ return false; @@ -133,7 +132,7 @@ class OC_Group_Database extends OC_Group_Backend { */ public function removeFromGroup( $uid, $gid ){ $query = OC_DB::prepare( "DELETE FROM *PREFIX*group_user WHERE uid = ? AND gid = ?" ); - $result = $query->execute( array( $uid, $gid )); + $query->execute( array( $uid, $gid )); return true; } diff --git a/lib/group/dummy.php b/lib/group/dummy.php index 0825b10708a..1243891023f 100644 --- a/lib/group/dummy.php +++ b/lib/group/dummy.php @@ -126,7 +126,8 @@ class OC_Group_Dummy extends OC_Group_Backend { */ public function getUserGroups($uid){ $groups=array(); - foreach($this->groups as $group=>$user){ + $allGroups=array_keys($this->groups); + foreach($allGroups as $group){ if($this->inGroup($uid,$group)){ $groups[]=$group; } diff --git a/lib/group/example.php b/lib/group/example.php index c18562db7a4..9c9ece5ac77 100644 --- a/lib/group/example.php +++ b/lib/group/example.php @@ -34,7 +34,7 @@ abstract class OC_Group_Example { * Trys to create a new group. If the group name already exists, false will * be returned. */ - public static function createGroup($gid){} + abstract public static function createGroup($gid); /** * @brief delete a group @@ -43,7 +43,7 @@ abstract class OC_Group_Example { * * Deletes a group and removes it from the group_user-table */ - public static function deleteGroup($gid){} + abstract public static function deleteGroup($gid); /** * @brief is user in group? @@ -53,7 +53,7 @@ abstract class OC_Group_Example { * * Checks whether the user is member of a group or not. */ - public static function inGroup($uid, $gid){} + abstract public static function inGroup($uid, $gid); /** * @brief Add a user to a group @@ -63,7 +63,7 @@ abstract class OC_Group_Example { * * Adds a user to a group. */ - public static function addToGroup($uid, $gid){} + abstract public static function addToGroup($uid, $gid); /** * @brief Removes a user from a group @@ -73,7 +73,7 @@ abstract class OC_Group_Example { * * removes the user from a group. */ - public static function removeFromGroup($uid,$gid){} + abstract public static function removeFromGroup($uid,$gid); /** * @brief Get all groups a user belongs to @@ -83,7 +83,7 @@ abstract class OC_Group_Example { * This function fetches all groups a user belongs to. It does not check * if the user exists at all. */ - public static function getUserGroups($uid){} + abstract public static function getUserGroups($uid); /** * @brief get a list of all groups @@ -91,19 +91,19 @@ abstract class OC_Group_Example { * * Returns a list with all groups */ - public static function getGroups(){} + abstract public static function getGroups(); /** * check if a group exists * @param string $gid * @return bool */ - public function groupExists($gid){} + abstract public function groupExists($gid); /** * @brief get a list of all users in a group * @returns array with user ids */ - public static function usersInGroup($gid){} + abstract public static function usersInGroup($gid); } diff --git a/lib/group/interface.php b/lib/group/interface.php new file mode 100644 index 00000000000..7cca6061e10 --- /dev/null +++ b/lib/group/interface.php @@ -0,0 +1,76 @@ +<?php + +/** + * ownCloud - group interface + * + * @author Arthur Schiwon + * @copyright 2012 Arthur Schiwon blizzz@owncloud.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/>. + * + */ + +interface OC_Group_Interface { + /** + * @brief Check if backend implements actions + * @param $actions bitwise-or'ed actions + * @returns boolean + * + * Returns the supported actions as int to be + * compared with OC_GROUP_BACKEND_CREATE_GROUP etc. + */ + public function implementsActions($actions); + + /** + * @brief is user in group? + * @param $uid uid of the user + * @param $gid gid of the group + * @returns true/false + * + * Checks whether the user is member of a group or not. + */ + public function inGroup($uid, $gid); + + /** + * @brief Get all groups a user belongs to + * @param $uid Name of the user + * @returns array with group names + * + * This function fetches all groups a user belongs to. It does not check + * if the user exists at all. + */ + public function getUserGroups($uid); + + /** + * @brief get a list of all groups + * @returns array with group names + * + * Returns a list with all groups + */ + public function getGroups(); + + /** + * check if a group exists + * @param string $gid + * @return bool + */ + public function groupExists($gid); + + /** + * @brief get a list of all users in a group + * @returns array with user ids + */ + public function usersInGroup($gid); + +}
\ No newline at end of file diff --git a/lib/helper.php b/lib/helper.php index 0d18098a4e7..666bc6badfc 100644 --- a/lib/helper.php +++ b/lib/helper.php @@ -175,10 +175,8 @@ class OC_Helper { */ public static function mimetypeIcon( $mimetype ){ $alias=array('application/xml'=>'code/xml'); -// echo $mimetype; if(isset($alias[$mimetype])){ $mimetype=$alias[$mimetype]; -// echo $mimetype; } // Replace slash with a minus $mimetype = str_replace( "/", "-", $mimetype ); @@ -345,18 +343,24 @@ class OC_Helper { */ static function getMimeType($path){ $isWrapped=(strpos($path,'://')!==false) and (substr($path,0,7)=='file://'); - $mimeType='application/octet-stream'; - if ($mimeType=='application/octet-stream') { - self::$mimetypes = include('mimetypes.fixlist.php'); - $extension=strtolower(strrchr(basename($path), ".")); - $extension=substr($extension,1);//remove leading . - $mimeType=(isset(self::$mimetypes[$extension]))?self::$mimetypes[$extension]:'application/octet-stream'; - } if (@is_dir($path)) { // directories are easy return "httpd/unix-directory"; } + + if(strpos($path,'.')){ + //try to guess the type by the file extension + if(!self::$mimetypes || self::$mimetypes != include('mimetypes.list.php')){ + self::$mimetypes=include('mimetypes.list.php'); + } + $extension=strtolower(strrchr(basename($path), ".")); + $extension=substr($extension,1);//remove leading . + $mimeType=(isset(self::$mimetypes[$extension]))?self::$mimetypes[$extension]:'application/octet-stream'; + }else{ + $mimeType='application/octet-stream'; + } + if($mimeType=='application/octet-stream' and function_exists('finfo_open') and function_exists('finfo_file') and $finfo=finfo_open(FILEINFO_MIME)){ $info = @strtolower(finfo_file($finfo,$path)); if($info){ @@ -385,15 +389,6 @@ class OC_Helper { } } - if ($mimeType=='application/octet-stream') { - // Fallback solution: (try to guess the type by the file extension - if(!self::$mimetypes || self::$mimetypes != include('mimetypes.list.php')){ - self::$mimetypes=include('mimetypes.list.php'); - } - $extension=strtolower(strrchr(basename($path), ".")); - $extension=substr($extension,1);//remove leading . - $mimeType=(isset(self::$mimetypes[$extension]))?self::$mimetypes[$extension]:'application/octet-stream'; - } return $mimeType; } @@ -676,12 +671,38 @@ class OC_Helper { */ public static function mb_str_replace($search, $replace, $subject, $encoding = 'UTF-8', &$count = null) { $offset = -1; - $length = mb_strlen($search, 'UTF-8'); - while(($i = mb_strrpos($subject, $search, $offset, 'UTF-8'))) { + $length = mb_strlen($search, $encoding); + while(($i = mb_strrpos($subject, $search, $offset, $encoding))) { $subject = OC_Helper::mb_substr_replace($subject, $replace, $i, $length); - $offset = $i - mb_strlen($subject, 'UTF-8') - 1; + $offset = $i - mb_strlen($subject, $encoding) - 1; $count++; } return $subject; } + + /** + * @brief performs a search in a nested array + * @param haystack the array to be searched + * @param needle the search string + * @param $index optional, only search this key name + * @return the key of the matching field, otherwise false + * + * performs a search in a nested array + * + * taken from http://www.php.net/manual/en/function.array-search.php#97645 + */ + public static function recursiveArraySearch($haystack, $needle, $index = null) { + $aIt = new RecursiveArrayIterator($haystack); + $it = new RecursiveIteratorIterator($aIt); + + while($it->valid()) { + if (((isset($index) AND ($it->key() == $index)) OR (!isset($index))) AND ($it->current() == $needle)) { + return $aIt->key(); + } + + $it->next(); + } + + return false; + } } diff --git a/lib/image.php b/lib/image.php index e5c59bacdc5..90c64320a7c 100644 --- a/lib/image.php +++ b/lib/image.php @@ -23,12 +23,12 @@ //From user comments at http://dk2.php.net/manual/en/function.exif-imagetype.php if ( ! function_exists( 'exif_imagetype' ) ) { - function exif_imagetype ( $filename ) { - if ( ( list($width, $height, $type, $attr) = getimagesize( $filename ) ) !== false ) { - return $type; - } - return false; - } + function exif_imagetype ( $filename ) { + if ( ( $info = getimagesize( $filename ) ) !== false ) { + return $info[2]; + } + return false; + } } function ellipsis($str, $maxlen) { @@ -66,7 +66,6 @@ class OC_Image { public function __construct($imageref = null) { //OC_Log::write('core',__METHOD__.'(): start', OC_Log::DEBUG); if(!extension_loaded('gd') || !function_exists('gd_info')) { - //if(!function_exists('imagecreatefromjpeg')) { OC_Log::write('core',__METHOD__.'(): GD module not installed', OC_Log::ERROR); return false; } @@ -108,6 +107,56 @@ class OC_Image { } /** + * @brief Returns the width when the image orientation is top-left. + * @returns int + */ + public function widthTopLeft() { + $o = $this->getOrientation(); + OC_Log::write('core','OC_Image->widthTopLeft() Orientation: '.$o, OC_Log::DEBUG); + switch($o) { + case -1: + case 1: + case 2: // Not tested + case 3: + case 4: // Not tested + return $this->width(); + break; + case 5: // Not tested + case 6: + case 7: // Not tested + case 8: + return $this->height(); + break; + } + return $this->width(); + } + + /** + * @brief Returns the height when the image orientation is top-left. + * @returns int + */ + public function heightTopLeft() { + $o = $this->getOrientation(); + OC_Log::write('core','OC_Image->heightTopLeft() Orientation: '.$o, OC_Log::DEBUG); + switch($o) { + case -1: + case 1: + case 2: // Not tested + case 3: + case 4: // Not tested + return $this->height(); + break; + case 5: // Not tested + case 6: + case 7: // Not tested + case 8: + return $this->width(); + break; + } + return $this->height(); + } + + /** * @brief Outputs the image. * @returns bool */ @@ -209,34 +258,46 @@ class OC_Image { /** * (I'm open for suggestions on better method name ;) - * @brief Fixes orientation based on EXIF data. - * @returns bool. + * @brief Get the orientation based on EXIF data. + * @returns The orientation or -1 if no EXIF data is available. */ - public function fixOrientation() { + public function getOrientation() { if(!is_callable('exif_read_data')){ OC_Log::write('core','OC_Image->fixOrientation() Exif module not enabled.', OC_Log::DEBUG); - return false; + return -1; } if(!$this->valid()) { OC_Log::write('core','OC_Image->fixOrientation() No image loaded.', OC_Log::DEBUG); - return false; + return -1; } if(is_null($this->filepath) || !is_readable($this->filepath)) { OC_Log::write('core','OC_Image->fixOrientation() No readable file path set.', OC_Log::DEBUG); - return false; + return -1; } $exif = @exif_read_data($this->filepath, 'IFD0'); if(!$exif) { - return false; + return -1; } if(!isset($exif['Orientation'])) { - return true; // Nothing to fix + return -1; } - $o = $exif['Orientation']; + return $exif['Orientation']; + } + + /** + * (I'm open for suggestions on better method name ;) + * @brief Fixes orientation based on EXIF data. + * @returns bool. + */ + public function fixOrientation() { + $o = $this->getOrientation(); OC_Log::write('core','OC_Image->fixOrientation() Orientation: '.$o, OC_Log::DEBUG); $rotate = 0; $flip = false; switch($o) { + case -1: + return false; //Nothing to fix + break; case 1: $rotate = 0; $flip = false; @@ -302,7 +363,7 @@ class OC_Image { public function load($imageref) { if(is_resource($imageref)) { if(get_resource_type($imageref) == 'gd') { - $this->resource = $res; + $this->resource = $imageref; return $this->resource; } elseif(in_array(get_resource_type($imageref), array('file','stream'))) { return $this->loadFromFileHandle($imageref); @@ -588,9 +649,6 @@ class OC_Image { OC_Log::write('core',__METHOD__.'(): No image loaded', OC_Log::ERROR); return false; } - $width_orig=imageSX($this->resource); - $height_orig=imageSY($this->resource); - //OC_Log::write('core',__METHOD__.'(): Original size: '.$width_orig.'x'.$height_orig, OC_Log::DEBUG); $process = imagecreatetruecolor($w, $h); if ($process == false) { OC_Log::write('core',__METHOD__.'(): Error creating true color image',OC_Log::ERROR); diff --git a/lib/installer.php b/lib/installer.php index 00feb6d4709..a8b56cb34f2 100644 --- a/lib/installer.php +++ b/lib/installer.php @@ -126,19 +126,19 @@ class OC_Installer{ return false; } $info=OC_App::getAppInfo($extractDir.'/appinfo/info.xml',true); - // check the code for not allowed calls - if(!OC_Installer::checkCode($info['id'],$extractDir)){ + // check the code for not allowed calls + if(!OC_Installer::checkCode($info['id'],$extractDir)){ OC_Log::write('core','App can\'t be installed because of not allowed code in the App',OC_Log::ERROR); OC_Helper::rmdirr($extractDir); - return false; + return false; } - // check if the app is compatible with this version of ownCloud + // check if the app is compatible with this version of ownCloud $version=OC_Util::getVersion(); - if(!isset($info['require']) or ($version[0]>$info['require'])){ + if(!isset($info['require']) or ($version[0]>$info['require'])){ OC_Log::write('core','App can\'t be installed because it is not compatible with this version of ownCloud',OC_Log::ERROR); OC_Helper::rmdirr($extractDir); - return false; + return false; } //check if an app with the same id is already installed @@ -339,12 +339,12 @@ class OC_Installer{ } - /** - * check the code of an app with some static code checks - * @param string $folder the folder of the app to check - * @returns true for app is o.k. and false for app is not o.k. - */ - public static function checkCode($appname,$folder){ + /** + * check the code of an app with some static code checks + * @param string $folder the folder of the app to check + * @returns true for app is o.k. and false for app is not o.k. + */ + public static function checkCode($appname,$folder){ $blacklist=array( 'exec(', @@ -377,9 +377,7 @@ class OC_Installer{ return true; }else{ - return true; + return true; } - } - - + } } diff --git a/lib/json.php b/lib/json.php index c49b831c12b..b46878375d5 100644 --- a/lib/json.php +++ b/lib/json.php @@ -94,12 +94,12 @@ class OC_JSON{ * Encode and print $data in json format */ public static function encodedPrint($data,$setContentType=true){ - // Disable mimesniffing, don't move this to setContentTypeHeader! - header( 'X-Content-Type-Options: nosniff' ); - if($setContentType){ - self::setContentTypeHeader(); - } - array_walk_recursive($data, array('OC_JSON', 'to_string')); - echo json_encode($data); + // Disable mimesniffing, don't move this to setContentTypeHeader! + header( 'X-Content-Type-Options: nosniff' ); + if($setContentType){ + self::setContentTypeHeader(); + } + array_walk_recursive($data, array('OC_JSON', 'to_string')); + echo json_encode($data); } } diff --git a/lib/l10n.php b/lib/l10n.php index de8514573d3..e7f5ffea0e4 100644 --- a/lib/l10n.php +++ b/lib/l10n.php @@ -154,8 +154,15 @@ class OC_L10N{ * * Returns the translation. If no translation is found, $textArray will be * returned. + * + * + * @deprecated deprecated since ownCloud version 5.0 + * This method will probably be removed with ownCloud 6.0 + * + * */ public function tA($textArray){ + OC_Log::write('core', 'DEPRECATED: the method tA is deprecated and will be removed soon.',OC_Log::WARN); $result = array(); foreach($textArray as $key => $text){ $result[$key] = (string)$this->t($text); diff --git a/lib/mail.php b/lib/mail.php index 7343f5f0d97..7eb2c4770c5 100644 --- a/lib/mail.php +++ b/lib/mail.php @@ -36,7 +36,7 @@ class OC_Mail { $SMTPPASSWORD = OC_Config::getValue( 'mail_smtppassword', '' ); - $mailo = new PHPMailer(); + $mailo = new PHPMailer(true); if($SMTPMODE=='sendmail') { $mailo->IsSendmail(); }elseif($SMTPMODE=='smtp'){ @@ -56,33 +56,35 @@ class OC_Mail { $mailo->From =$fromaddress; $mailo->FromName = $fromname;; $a=explode(' ',$toaddress); - foreach($a as $ad) { - $mailo->AddAddress($ad,$toname); + try { + foreach($a as $ad) { + $mailo->AddAddress($ad,$toname); + } + + if($ccaddress<>'') $mailo->AddCC($ccaddress,$ccname); + if($bcc<>'') $mailo->AddBCC($bcc); + + $mailo->AddReplyTo($fromaddress, $fromname); + + $mailo->WordWrap = 50; + if($html==1) $mailo->IsHTML(true); else $mailo->IsHTML(false); + + $mailo->Subject = $subject; + if($altbody=='') { + $mailo->Body = $mailtext.OC_MAIL::getfooter(); + $mailo->AltBody = ''; + }else{ + $mailo->Body = $mailtext; + $mailo->AltBody = $altbody; + } + $mailo->CharSet = 'UTF-8'; + + $mailo->Send(); + unset($mailo); + OC_Log::write('mail', 'Mail from '.$fromname.' ('.$fromaddress.')'.' to: '.$toname.'('.$toaddress.')'.' subject: '.$subject, OC_Log::DEBUG); + } catch (Exception $exception) { + OC_Log::write('mail', $exception->getMessage(), OC_Log::DEBUG); } - - if($ccaddress<>'') $mailo->AddCC($ccaddress,$ccname); - if($bcc<>'') $mailo->AddBCC($bcc); - - $mailo->AddReplyTo($fromaddress, $fromname); - - $mailo->WordWrap = 50; - if($html==1) $mailo->IsHTML(true); else $mailo->IsHTML(false); - - $mailo->Subject = $subject; - if($altbody=='') { - $mailo->Body = $mailtext.OC_MAIL::getfooter(); - $mailo->AltBody = ''; - }else{ - $mailo->Body = $mailtext; - $mailo->AltBody = $altbody; - } - $mailo->CharSet = 'UTF-8'; - - $mailo->Send(); - unset($mailo); - - OC_Log::write('Mail from '.$fromname.' ('.$fromaddress.')'.' to: '.$toname.'('.$toaddress.')'.' subject: '.$subject,'mail',OC_Log::DEBUG); - } diff --git a/lib/migrate.php b/lib/migrate.php index f788a637d3c..1b6367ed6ec 100644 --- a/lib/migrate.php +++ b/lib/migrate.php @@ -91,7 +91,7 @@ class OC_Migrate{ if( self::$exporttype == 'user' ){ // Check user exists if( !is_null($uid) ){ - $db = new OC_User_Database; + $db = new OC_User_Database; if( !$db->userExists( $uid ) ){ OC_Log::write('migration', 'User: '.$uid.' is not in the database and so cannot be exported.', OC_Log::ERROR); return json_encode( array( 'success' => false ) ); diff --git a/lib/mimetypes.fixlist.php b/lib/mimetypes.fixlist.php deleted file mode 100644 index 13e3f16b369..00000000000 --- a/lib/mimetypes.fixlist.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php -return array( - 'ics'=>'text/calendar', - 'ical'=>'text/calendar', - 'js'=>'application/javascript', - 'odt'=>'application/vnd.oasis.opendocument.text', - 'ods'=>'application/vnd.oasis.opendocument.spreadsheet', - 'odg'=>'application/vnd.oasis.opendocument.graphics', - 'odp'=>'application/vnd.oasis.opendocument.presentation', - 'pl'=>'text/x-script.perl', - 'py'=>'text/x-script.phyton', - 'vcf' => 'text/vcard', - 'vcard' => 'text/vcard', - 'doc'=>'application/msword', - 'docx'=>'application/msword', - 'xls'=>'application/msexcel', - 'xlsx'=>'application/msexcel', - 'ppt'=>'application/mspowerpoint', - 'pptx'=>'application/mspowerpoint', - 'sgf' => 'application/sgf', - 'cdr' => 'application/coreldraw' -); diff --git a/lib/mimetypes.list.php b/lib/mimetypes.list.php index ccf47999b1c..f7207493f7f 100644 --- a/lib/mimetypes.list.php +++ b/lib/mimetypes.list.php @@ -78,5 +78,16 @@ return array( 'mpeg'=>'video/mpeg', 'mov'=>'video/quicktime', 'webm'=>'video/webm', - 'wmv'=>'video/x-ms-asf' + 'wmv'=>'video/x-ms-asf', + 'py'=>'text/x-script.phyton', + 'vcf' => 'text/vcard', + 'vcard' => 'text/vcard', + 'doc'=>'application/msword', + 'docx'=>'application/msword', + 'xls'=>'application/msexcel', + 'xlsx'=>'application/msexcel', + 'ppt'=>'application/mspowerpoint', + 'pptx'=>'application/mspowerpoint', + 'sgf' => 'application/sgf', + 'cdr' => 'application/coreldraw', ); diff --git a/lib/minimizer.php b/lib/minimizer.php index 3bf5ff9980b..3dc89e331a6 100644 --- a/lib/minimizer.php +++ b/lib/minimizer.php @@ -46,3 +46,13 @@ abstract class OC_Minimizer { echo $out; } } + +if (!function_exists('gzdecode')) { + function gzdecode($data,$maxlength=null,&$filename='',&$error='') + { + if (strcmp(substr($data,0,9),"\x1f\x8b\x8\0\0\0\0\0\0")) { + return null; // Not the GZIP format we expect (See RFC 1952) + } + return gzinflate(substr($data,10,-8)); + } +} diff --git a/lib/ocs.php b/lib/ocs.php index 5e697b48304..d7a7951fab5 100644 --- a/lib/ocs.php +++ b/lib/ocs.php @@ -23,8 +23,6 @@ * */ - - /** * Class to handle open collaboration services API requests * @@ -92,77 +90,160 @@ class OC_OCS { exit(); } - // preprocess url - $url = strtolower($_SERVER['REQUEST_URI']); - if(substr($url,(strlen($url)-1))<>'/') $url.='/'; - $ex=explode('/',$url); - $paracount=count($ex); $format = self::readData($method, 'format', 'text', ''); - // eventhandler + + $router = new OC_Router(); + $router->useCollection('ocs'); // CONFIG - // apiconfig - GET - CONFIG - if(($method=='get') and ($ex[$paracount-3] == 'v1.php') and ($ex[$paracount-2] == 'config')){ - OC_OCS::apiconfig($format); + $router->create('config', '/config.{format}') + ->defaults(array('format' => $format)) + ->action('OC_OCS', 'apiConfig') + ->requirements(array('format'=>'xml|json')); // PERSON - // personcheck - POST - PERSON/CHECK - }elseif(($method=='post') and ($ex[$paracount-4] == 'v1.php') and ($ex[$paracount-3]=='person') and ($ex[$paracount-2] == 'check')){ - $login = self::readData($method, 'login', 'text'); - $passwd = self::readData($method, 'password', 'text'); - OC_OCS::personcheck($format,$login,$passwd); - } else if ($method == 'post' && $ex[$paracount - 4] == 'v1.php' && $ex[$paracount - 3] == 'person' && $ex[$paracount - 2] == 'add') { - if (OC_Group::inGroup(self::checkPassword(), 'admin')) { - $login = self::readData($method, 'login', 'text'); - $password = self::readData($method, 'password', 'text'); - try { - OC_User::createUser($login, $password); - echo self::generateXml($format, 'ok', 201, ''); - } catch (Exception $exception) { - echo self::generateXml($format, 'fail', 400, $exception->getMessage()); - } - } else { - echo self::generateXml($format, 'fail', 403, 'Permission denied'); - } + $router->create('person_check', '/person/check.{format}') + ->post() + ->defaults(array('format' => $format)) + ->action(function ($parameters) { + $format = $parameters['format']; + $login = OC_OCS::readData('post', 'login', 'text'); + $passwd = OC_OCS::readData('post', 'password', 'text'); + OC_OCS::personCheck($format,$login,$passwd); + }) + ->requirements(array('format'=>'xml|json')); + // ACTIVITY // activityget - GET ACTIVITY page,pagesize als urlparameter - }elseif(($method=='get') and ($ex[$paracount-3] == 'v1.php') and ($ex[$paracount-2] == 'activity')){ - $page = self::readData($method, 'page', 'int', 0); - $pagesize = self::readData($method, 'pagesize','int', 10); - if($pagesize<1 or $pagesize>100) $pagesize=10; - OC_OCS::activityget($format,$page,$pagesize); - + $router->create('activity_get', '/activity.{format}') + ->defaults(array('format' => $format)) + ->action(function ($parameters) { + $format = $parameters['format']; + $page = OC_OCS::readData('get', 'page', 'int', 0); + $pagesize = OC_OCS::readData('get', 'pagesize', 'int', 10); + if($pagesize<1 or $pagesize>100) $pagesize=10; + OC_OCS::activityGet($format, $page, $pagesize); + }) + ->requirements(array('format'=>'xml|json')); // activityput - POST ACTIVITY - }elseif(($method=='post') and ($ex[$paracount-3] == 'v1.php') and ($ex[$paracount-2] == 'activity')){ - $message = self::readData($method, 'message', 'text'); - OC_OCS::activityput($format,$message); + $router->create('activity_put', '/activity.{format}') + ->post() + ->defaults(array('format' => $format)) + ->action(function ($parameters) { + $format = $parameters['format']; + $message = OC_OCS::readData('post', 'message', 'text'); + OC_OCS::activityPut($format,$message); + }) + ->requirements(array('format'=>'xml|json')); // PRIVATEDATA // get - GET DATA - }elseif(($method=='get') and ($ex[$paracount-4] == 'v1.php') and ($ex[$paracount-2] == 'getattribute')){ - OC_OCS::privateDataGet($format); - - }elseif(($method=='get') and ($ex[$paracount-5] == 'v1.php') and ($ex[$paracount-3] == 'getattribute')){ - $app=$ex[$paracount-2]; - OC_OCS::privateDataGet($format, $app); - }elseif(($method=='get') and ($ex[$paracount-6] == 'v1.php') and ($ex[$paracount-4] == 'getattribute')){ - - $key=$ex[$paracount-2]; - $app=$ex[$paracount-3]; - OC_OCS::privateDataGet($format, $app,$key); - + $router->create('privatedata_get', + '/privatedata/getattribute/{app}/{key}.{format}') + ->defaults(array('app' => '', 'key' => '', 'format' => $format)) + ->action(function ($parameters) { + $format = $parameters['format']; + $app = addslashes(strip_tags($parameters['app'])); + $key = addslashes(strip_tags($parameters['key'])); + OC_OCS::privateDataGet($format, $app, $key); + }) + ->requirements(array('format'=>'xml|json')); // set - POST DATA - }elseif(($method=='post') and ($ex[$paracount-6] == 'v1.php') and ($ex[$paracount-4] == 'setattribute')){ - $key=$ex[$paracount-2]; - $app=$ex[$paracount-3]; - $value = self::readData($method, 'value', 'text'); - OC_OCS::privatedataset($format, $app, $key, $value); + $router->create('privatedata_set', + '/privatedata/setattribute/{app}/{key}.{format}') + ->post() + ->defaults(array('format' => $format)) + ->action(function ($parameters) { + $format = $parameters['format']; + $app = addslashes(strip_tags($parameters['app'])); + $key = addslashes(strip_tags($parameters['key'])); + $value=OC_OCS::readData('post', 'value', 'text'); + OC_OCS::privateDataSet($format, $app, $key, $value); + }) + ->requirements(array('format'=>'xml|json')); // delete - POST DATA - }elseif(($method=='post') and ($ex[$paracount-6] =='v1.php') and ($ex[$paracount-4] == 'deleteattribute')){ - $key=$ex[$paracount-2]; - $app=$ex[$paracount-3]; - OC_OCS::privatedatadelete($format, $app, $key); - - }else{ + $router->create('privatedata_delete', + '/privatedata/deleteattribute/{app}/{key}.{format}') + ->post() + ->defaults(array('format' => $format)) + ->action(function ($parameters) { + $format = $parameters['format']; + $app = addslashes(strip_tags($parameters['app'])); + $key = addslashes(strip_tags($parameters['key'])); + OC_OCS::privateDataDelete($format, $app, $key); + }) + ->requirements(array('format'=>'xml|json')); + + // CLOUD + // systemWebApps + $router->create('system_webapps', + '/cloud/system/webapps.{format}') + ->defaults(array('format' => $format)) + ->action(function ($parameters) { + $format = $parameters['format']; + OC_OCS::systemwebapps($format); + }) + ->requirements(array('format'=>'xml|json')); + + // quotaget + $router->create('quota_get', + '/cloud/user/{user}.{format}') + ->defaults(array('format' => $format)) + ->action(function ($parameters) { + $format = $parameters['format']; + $user = $parameters['user']; + OC_OCS::quotaGet($format, $user); + }) + ->requirements(array('format'=>'xml|json')); + // quotaset + $router->create('quota_set', + '/cloud/user/{user}.{format}') + ->post() + ->defaults(array('format' => $format)) + ->action(function ($parameters) { + $format = $parameters['format']; + $user = $parameters['user']; + $quota = self::readData('post', 'quota', 'int'); + OC_OCS::quotaSet($format, $user, $quota); + }) + ->requirements(array('format'=>'xml|json')); + + // keygetpublic + $router->create('keygetpublic', + '/cloud/user/{user}/publickey.{format}') + ->defaults(array('format' => $format)) + ->action(function ($parameters) { + $format = $parameters['format']; + $user = $parameters['user']; + OC_OCS::publicKeyGet($format,$user); + }) + ->requirements(array('format'=>'xml|json')); + + // keygetprivate + $router->create('keygetpublic', + '/cloud/user/{user}/privatekey.{format}') + ->defaults(array('format' => $format)) + ->action(function ($parameters) { + $format = $parameters['format']; + $user = $parameters['user']; + OC_OCS::privateKeyGet($format,$user); + }) + ->requirements(array('format'=>'xml|json')); + + +// add more calls here +// please document all the call in the draft spec +// http://www.freedesktop.org/wiki/Specifications/open-collaboration-services-1.7#CLOUD + +// TODO: +// users +// groups +// bookmarks +// sharing +// versioning +// news (rss) + try { + $router->match($_SERVER['PATH_INFO']); + } catch (ResourceNotFoundException $e) { $txt='Invalid query, please check the syntax. API specifications are here: http://www.freedesktop.org/wiki/Specifications/open-collaboration-services. DEBUG OUTPUT:'."\n"; $txt.=OC_OCS::getdebugoutput(); echo(OC_OCS::generatexml($format,'failed',999,$txt)); @@ -198,25 +279,25 @@ class OC_OCS { if(isset($_SERVER['PHP_AUTH_PW'])) $authpw=$_SERVER['PHP_AUTH_PW']; else $authpw=''; if(empty($authuser)) { - if($forceuser){ - header('WWW-Authenticate: Basic realm="your valid user account or api key"'); - header('HTTP/1.0 401 Unauthorized'); - exit; - }else{ - $identifieduser=''; - } - }else{ - if(!OC_User::login($authuser,$authpw)){ if($forceuser){ - header('WWW-Authenticate: Basic realm="your valid user account or api key"'); - header('HTTP/1.0 401 Unauthorized'); - exit; + header('WWW-Authenticate: Basic realm="your valid user account or api key"'); + header('HTTP/1.0 401 Unauthorized'); + exit; }else{ - $identifieduser=''; + $identifieduser=''; } }else{ - $identifieduser=$authuser; - } + if(!OC_User::login($authuser,$authpw)){ + if($forceuser){ + header('WWW-Authenticate: Basic realm="your valid user account or api key"'); + header('HTTP/1.0 401 Unauthorized'); + exit; + }else{ + $identifieduser=''; + } + }else{ + $identifieduser=$authuser; + } } return($identifieduser); @@ -350,11 +431,12 @@ class OC_OCS { * @param string $format * @return string xml/json */ - private static function apiConfig($format) { + public static function apiConfig($parameters) { + $format = $parameters['format']; $user=OC_OCS::checkpassword(false); $url=substr(OCP\Util::getServerHost().$_SERVER['SCRIPT_NAME'],0,-11).''; - $xml['version']='1.5'; + $xml['version']='1.7'; $xml['website']='ownCloud'; $xml['host']=OCP\Util::getServerHost(); $xml['contact']=''; @@ -524,4 +606,134 @@ class OC_OCS { public static function deleteData($user, $app, $key) { return OC_Preferences::deleteKey($user,$app,$key); } + + + // CLOUD API ############################################# + + /** + * get a list of installed web apps + * @param string $format + * @return string xml/json + */ + private static function systemWebApps($format) { + $login=OC_OCS::checkpassword(); + $apps=OC_App::getEnabledApps(); + $values=array(); + foreach($apps as $app) { + $info=OC_App::getAppInfo($app); + if(isset($info['standalone'])) { + $newvalue=array('name'=>$info['name'],'url'=>OC_Helper::linkToAbsolute($app,''),'icon'=>''); + $values[]=$newvalue; + } + + } + $txt=OC_OCS::generatexml($format, 'ok', 100, '', $values, 'cloud', '', 2, 0, 0); + echo($txt); + + } + + + /** + * get the quota of a user + * @param string $format + * @param string $user + * @return string xml/json + */ + private static function quotaGet($format,$user) { + $login=OC_OCS::checkpassword(); + if(OC_Group::inGroup($login, 'admin') or ($login==$user)) { + + if(OC_User::userExists($user)){ + // calculate the disc space + $user_dir = '/'.$user.'/files'; + OC_Filesystem::init($user_dir); + $rootInfo=OC_FileCache::get(''); + $sharedInfo=OC_FileCache::get('/Shared'); + $used=$rootInfo['size']-$sharedInfo['size']; + $free=OC_Filesystem::free_space(); + $total=$free+$used; + if($total==0) $total=1; // prevent division by zero + $relative=round(($used/$total)*10000)/100; + + $xml=array(); + $xml['quota']=$total; + $xml['free']=$free; + $xml['used']=$used; + $xml['relative']=$relative; + + $txt=OC_OCS::generatexml($format, 'ok', 100, '', $xml, 'cloud', '', 1, 0, 0); + echo($txt); + }else{ + echo self::generateXml('', 'fail', 300, 'User does not exist'); + } + }else{ + echo self::generateXml('', 'fail', 300, 'You don´t have permission to access this ressource.'); + } + } + + /** + * set the quota of a user + * @param string $format + * @param string $user + * @param string $quota + * @return string xml/json + */ + private static function quotaSet($format,$user,$quota) { + $login=OC_OCS::checkpassword(); + if(OC_Group::inGroup($login, 'admin')) { + + // todo + // not yet implemented + // add logic here + error_log('OCS call: user:'.$user.' quota:'.$quota); + + $xml=array(); + $txt=OC_OCS::generatexml($format, 'ok', 100, '', $xml, 'cloud', '', 1, 0, 0); + echo($txt); + }else{ + echo self::generateXml('', 'fail', 300, 'You don´t have permission to access this ressource.'); + } + } + + /** + * get the public key of a user + * @param string $format + * @param string $user + * @return string xml/json + */ + private static function publicKeyGet($format,$user) { + $login=OC_OCS::checkpassword(); + + if(OC_User::userExists($user)){ + // calculate the disc space + $txt='this is the public key of '.$user; + echo($txt); + }else{ + echo self::generateXml('', 'fail', 300, 'User does not exist'); + } + } + + /** + * get the private key of a user + * @param string $format + * @param string $user + * @return string xml/json + */ + private static function privateKeyGet($format,$user) { + $login=OC_OCS::checkpassword(); + if(OC_Group::inGroup($login, 'admin') or ($login==$user)) { + + if(OC_User::userExists($user)){ + // calculate the disc space + $txt='this is the private key of '.$user; + echo($txt); + }else{ + echo self::generateXml('', 'fail', 300, 'User does not exist'); + } + }else{ + echo self::generateXml('', 'fail', 300, 'You don´t have permission to access this ressource.'); + } + } + + } diff --git a/lib/ocsclient.php b/lib/ocsclient.php index 951d761d7e6..ae35470cff6 100644 --- a/lib/ocsclient.php +++ b/lib/ocsclient.php @@ -71,7 +71,7 @@ class OC_OCSClient{ $tmp=$data->data; $cats=array(); - foreach($tmp->category as $key=>$value) { + foreach($tmp->category as $value) { $id= (int) $value->id; $name= (string) $value->name; diff --git a/lib/preferences.php b/lib/preferences.php index f72378ce94f..c91423e69bc 100644 --- a/lib/preferences.php +++ b/lib/preferences.php @@ -165,7 +165,7 @@ class OC_Preferences{ public static function deleteKey( $user, $app, $key ){ // No need for more comments $query = OC_DB::prepare( 'DELETE FROM *PREFIX*preferences WHERE userid = ? AND appid = ? AND configkey = ?' ); - $result = $query->execute( array( $user, $app, $key )); + $query->execute( array( $user, $app, $key )); return true; } @@ -181,7 +181,7 @@ class OC_Preferences{ public static function deleteApp( $user, $app ){ // No need for more comments $query = OC_DB::prepare( 'DELETE FROM *PREFIX*preferences WHERE userid = ? AND appid = ?' ); - $result = $query->execute( array( $user, $app )); + $query->execute( array( $user, $app )); return true; } @@ -196,7 +196,7 @@ class OC_Preferences{ public static function deleteUser( $user ){ // No need for more comments $query = OC_DB::prepare( 'DELETE FROM *PREFIX*preferences WHERE userid = ?' ); - $result = $query->execute( array( $user )); + $query->execute( array( $user )); return true; } @@ -211,7 +211,7 @@ class OC_Preferences{ public static function deleteAppFromAllUsers( $app ){ // No need for more comments $query = OC_DB::prepare( 'DELETE FROM *PREFIX*preferences WHERE appid = ?' ); - $result = $query->execute( array( $app )); + $query->execute( array( $app )); return true; } diff --git a/lib/public/app.php b/lib/public/app.php index 9e2108818bf..28411933beb 100644 --- a/lib/public/app.php +++ b/lib/public/app.php @@ -34,28 +34,6 @@ namespace OCP; * This class provides functions to manage apps in ownCloud */ class App { - - /** - * @brief Makes owncloud aware of this app - * @brief This call is deprecated and not necessary to use. - * @param $data array with all information - * @returns true/false - * - * This function registers the application. $data is an associative array. - * The following keys are required: - * - id: id of the application, has to be unique ('addressbook') - * - name: Human readable name ('Addressbook') - * - version: array with Version (major, minor, bugfix) ( array(1, 0, 2)) - * - * The following keys are optional: - * - order: integer, that influences the position of your application in - * a list of applications. Lower values come first. - * - */ - public static function register( $data ){ - } - - /** * @brief adds an entry to the navigation * @param $data array containing the data @@ -158,6 +136,3 @@ class App { } - - -?> diff --git a/lib/public/config.php b/lib/public/config.php index 9f5abe672cb..ab01902ffe6 100644 --- a/lib/public/config.php +++ b/lib/public/config.php @@ -134,5 +134,3 @@ class Config { } - -?> diff --git a/lib/public/db.php b/lib/public/db.php index f7564c0bb6a..3a33f7674d8 100644 --- a/lib/public/db.php +++ b/lib/public/db.php @@ -91,5 +91,3 @@ class DB { } - -?> diff --git a/lib/public/files.php b/lib/public/files.php index fc3004434ba..32b3f036744 100644 --- a/lib/public/files.php +++ b/lib/public/files.php @@ -115,5 +115,3 @@ class Files { } - -?> diff --git a/lib/public/groupinterface.php b/lib/public/groupinterface.php new file mode 100644 index 00000000000..97833028118 --- /dev/null +++ b/lib/public/groupinterface.php @@ -0,0 +1,31 @@ +<?php +/** +* ownCloud +* +* @author Arthur Schiwon +* @copyright 2012 Arthur Schiwon blizzz@owncloud.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/>. +* +*/ + +/** + * Public interface of ownCloud for apps to use. + * Group Class. + * + */ + +namespace OCP; + +interface GroupInterface extends \OC_Group_Interface {}
\ No newline at end of file diff --git a/lib/public/json.php b/lib/public/json.php index b6edbd65bd5..99df79173eb 100644 --- a/lib/public/json.php +++ b/lib/public/json.php @@ -35,75 +35,140 @@ namespace OCP; */ class JSON { - /** * @brief Encode and print $data in JSON format * @param array $data The data to use * @param string $setContentType the optional content type + * @return string json formatted string. */ public static function encodedPrint( $data, $setContentType=true ){ return(\OC_JSON::encodedPrint( $data, $setContentType )); } - /** - * @brief Check if the user is logged in, send json error msg if not + * Check if the user is logged in, send json error msg if not. + * + * This method checks if a user is logged in. If not, a json error + * response will be return and the method will exit from execution + * of the script. + * The returned json will be in the format: + * + * {"status":"error","data":{"message":"Authentication error."}} + * + * Add this call to the start of all ajax method files that requires + * an authenticated user. + * + * @return string json formatted error string if not authenticated. */ public static function checkLoggedIn(){ return(\OC_JSON::checkLoggedIn()); } /** - * @brief Check an ajax get/post call if the request token is valid. - * @return json Error msg if not valid. - */ + * Check an ajax get/post call if the request token is valid. + * + * This method checks for a valid variable 'requesttoken' in $_GET, + * $_POST and $_SERVER. If a valid token is not found, a json error + * response will be return and the method will exit from execution + * of the script. + * The returned json will be in the format: + * + * {"status":"error","data":{"message":"Token expired. Please reload page."}} + * + * Add this call to the start of all ajax method files that creates, + * updates or deletes anything. + * In cases where you e.g. use an ajax call to load a dialog containing + * a submittable form, you will need to add the requesttoken first as a + * parameter to the ajax call, then assign it to the template and finally + * add a hidden input field also named 'requesttoken' containing the value. + * + * @return string json formatted error string if not valid. + */ public static function callCheck(){ return(\OC_JSON::callCheck()); } /** - * @brief Send json success msg + * Send json success msg + * + * Return a json success message with optional extra data. + * @see OCP\JSON::error() for the format to use. + * * @param array $data The data to use + * @return string json formatted string. */ public static function success( $data = array() ){ return(\OC_JSON::success( $data )); } - /** - * @brief Send json error msg + * Send json error msg + * + * Return a json error message with optional extra data for + * error message or app specific data. + * + * Example use: + * + * $id = [some value] + * OCP\JSON::error(array('data':array('message':'An error happened', 'id': $id))); + * + * Will return the json formatted string: + * + * {"status":"error","data":{"message":"An error happened", "id":[some value]}} + * * @param array $data The data to use + * @return string json formatted error string. */ public static function error( $data = array() ){ return(\OC_JSON::error( $data )); } - /** - * @brief set Content-Type header to jsonrequest - * @param array $type The contwnt type header - */ + * @brief set Content-Type header to jsonrequest + * @param array $type The contwnt type header + * @return string json formatted string. + */ public static function setContentTypeHeader( $type='application/json' ){ return(\OC_JSON::setContentTypeHeader( $type )); } - /** - * @brief Check if the App is enabled and send JSON error message instead - * @param string $app The app to check - */ + * Check if the App is enabled and send JSON error message instead + * + * This method checks if a specific app is enabled. If not, a json error + * response will be return and the method will exit from execution + * of the script. + * The returned json will be in the format: + * + * {"status":"error","data":{"message":"Application is not enabled."}} + * + * Add this call to the start of all ajax method files that requires + * a specific app to be enabled. + * + * @param string $app The app to check + * @return string json formatted string if not enabled. + */ public static function checkAppEnabled( $app ){ return(\OC_JSON::checkAppEnabled( $app )); } - /** - * @brief Check if the user is a admin, send json error msg if not + * Check if the user is a admin, send json error msg if not + * + * This method checks if the current user has admin rights. If not, a json error + * response will be return and the method will exit from execution + * of the script. + * The returned json will be in the format: + * + * {"status":"error","data":{"message":"Authentication error."}} + * + * Add this call to the start of all ajax method files that requires + * administrative rights. + * + * @return string json formatted string if not admin user. */ public static function checkAdminUser(){ return(\OC_JSON::checkAdminUser()); } } - -?> diff --git a/lib/public/response.php b/lib/public/response.php index cc2137c5cae..8dff3bcd354 100644 --- a/lib/public/response.php +++ b/lib/public/response.php @@ -105,5 +105,3 @@ class Response { } - -?> diff --git a/lib/public/template.php b/lib/public/template.php index b89088bdd06..a0ed618cb2c 100644 --- a/lib/public/template.php +++ b/lib/public/template.php @@ -104,6 +104,3 @@ function html_select_options($options, $selected, $params=array()) { class Template extends \OC_Template { } - - -?> diff --git a/lib/public/user.php b/lib/public/user.php index a0c069f7379..713e366b968 100644 --- a/lib/public/user.php +++ b/lib/public/user.php @@ -120,6 +120,3 @@ class User { } - - -?> diff --git a/lib/public/userinterface.php b/lib/public/userinterface.php new file mode 100644 index 00000000000..b73a8f8d8b0 --- /dev/null +++ b/lib/public/userinterface.php @@ -0,0 +1,31 @@ +<?php +/** +* ownCloud +* +* @author Arthur Schiwon +* @copyright 2012 Arthur Schiwon blizzz@owncloud.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/>. +* +*/ + +/** + * Public interface of ownCloud for apps to use. + * User Class. + * + */ + +namespace OCP; + +interface UserInterface extends \OC_User_Interface {}
\ No newline at end of file diff --git a/lib/public/util.php b/lib/public/util.php index 41121091544..75ca29f7129 100644 --- a/lib/public/util.php +++ b/lib/public/util.php @@ -320,6 +320,15 @@ class Util { public static function mb_str_replace($search, $replace, $subject, $encoding = 'UTF-8', &$count = null) { return(\OC_Helper::mb_str_replace($search, $replace, $subject, $encoding, $count)); } -} -?> + /** + * @brief performs a search in a nested array + * @param haystack the array to be searched + * @param needle the search string + * @param $index optional, only search this key name + * @return the key of the matching field, otherwise false + */ + public static function recursiveArraySearch($haystack, $needle, $index = null) { + return(\OC_Helper::recursiveArraySearch($haystack, $needle, $index)); + } +} diff --git a/lib/route.php b/lib/route.php new file mode 100644 index 00000000000..0d3339add6c --- /dev/null +++ b/lib/route.php @@ -0,0 +1,65 @@ +<?php +/** + * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +use Symfony\Component\Routing\Route; + +class OC_Route extends Route { + public function method($method) { + $this->setRequirement('_method', $method); + return $this; + } + + public function post() { + $this->method('post'); + return $this; + } + + public function get() { + $this->method('get'); + return $this; + } + + public function put() { + $this->method('put'); + return $this; + } + + public function delete() { + $this->method('delete'); + return $this; + } + + public function defaults($defaults) { + $action = $this->getDefault('action'); + $this->setDefaults($defaults); + if (isset($defaults['action'])) { + $action = $defaults['action']; + } + $this->action($action); + return $this; + } + + public function requirements($requirements) { + $method = $this->getRequirement('_method'); + $this->setRequirements($requirements); + if (isset($requirements['_method'])) { + $method = $requirements['_method']; + } + $this->method($method); + return $this; + } + + public function action($class, $function = null) { + $action = array($class, $function); + if (is_null($function)) { + $action = $class; + } + $this->setDefault('action', $action); + return $this; + } +} diff --git a/lib/router.php b/lib/router.php new file mode 100644 index 00000000000..f037ecdfef4 --- /dev/null +++ b/lib/router.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +use Symfony\Component\Routing\Matcher\UrlMatcher; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RouteCollection; +//use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\Exception\ResourceNotFoundException; + +class OC_Router { + protected $collections = array(); + protected $collection = null; + + public function useCollection($name) { + if (!isset($this->collections[$name])) { + $this->collections[$name] = new RouteCollection(); + } + $this->collection = $this->collections[$name]; + } + + public function create($name, $pattern, array $defaults = array(), array $requirements = array()) { + $route = new OC_Route($pattern, $defaults, $requirements); + $this->collection->add($name, $route); + return $route; + } + + public function match($url) { + $context = new RequestContext($_SERVER['REQUEST_URI'], $_SERVER['REQUEST_METHOD']); + $matcher = new UrlMatcher($this->collection, $context); + $parameters = $matcher->match($url); + if (isset($parameters['action'])) { + $action = $parameters['action']; + if (!is_callable($action)) { + var_dump($action); + throw new Exception('not a callable action'); + } + unset($parameters['action']); + call_user_func($action, $parameters); + } elseif (isset($parameters['file'])) { + include ($parameters['file']); + } else { + throw new Exception('no action available'); + } + } +} diff --git a/lib/search/provider.php b/lib/search/provider.php index 838ab696d04..b3ee79b4770 100644 --- a/lib/search/provider.php +++ b/lib/search/provider.php @@ -2,13 +2,17 @@ /** * provides search functionalty */ -class OC_Search_Provider { - public function __construct($options){} +abstract class OC_Search_Provider { + private $options; + + public function __construct($options){ + $this->options=$options; + } /** * search for $query * @param string $query * @return array An array of OC_Search_Result's */ - public function search($query){} + abstract public function search($query); } diff --git a/lib/setup.php b/lib/setup.php index bad0f5301c7..4d71bed86e2 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -102,7 +102,6 @@ class OC_Setup { } else { $oldUser=OC_Config::getValue('dbuser', false); - $oldPassword=OC_Config::getValue('dbpassword', false); $query="SELECT user FROM mysql.user WHERE user='$dbuser'"; //this should be enough to check for admin rights in mysql if(mysql_query($query, $connection)) { @@ -257,7 +256,7 @@ class OC_Setup { OC_Installer::installShippedApps(); //create htaccess files for apache hosts - if (strstr($_SERVER['SERVER_SOFTWARE'], 'Apache')) { + if (isset($_SERVER['SERVER_SOFTWARE']) && strstr($_SERVER['SERVER_SOFTWARE'], 'Apache')) { self::createHtaccess(); } @@ -380,5 +379,3 @@ class OC_Setup { file_put_contents(OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data').'/index.html', ''); } } - -?> diff --git a/lib/streamwrappers.php b/lib/streamwrappers.php index f1e0fa0e1d9..f502c6170bd 100644 --- a/lib/streamwrappers.php +++ b/lib/streamwrappers.php @@ -1,6 +1,4 @@ <?php -global $FAKEDIRS; -$FAKEDIRS=array(); class OC_FakeDirStream{ public static $dirs=array(); @@ -8,8 +6,6 @@ class OC_FakeDirStream{ private $index; public function dir_opendir($path,$options){ - global $FAKEDIRS; - $url=parse_url($path); $this->name=substr($path,strlen('fakedir://')); $this->index=0; if(!isset(self::$dirs[$this->name])){ @@ -161,7 +157,6 @@ class OC_StaticStreamWrapper { public function stream_write($data) { if (!$this->writable) return 0; $size = strlen($data); - $len = strlen(self::$data[$this->path]); if ($this->stream_eof()) { self::$data[$this->path] .= $data; } else { diff --git a/lib/template.php b/lib/template.php index 3b48c27b9b4..5b6999af533 100644 --- a/lib/template.php +++ b/lib/template.php @@ -82,7 +82,6 @@ function relative_modified_date($timestamp) { $diffhours = round($diffminutes/60); $diffdays = round($diffhours/24); $diffmonths = round($diffdays/31); - $diffyears = round($diffdays/365); if($timediff < 60) { return $l->t('seconds ago'); } else if($timediff < 120) { return $l->t('1 minute ago'); } diff --git a/lib/templatelayout.php b/lib/templatelayout.php index d33a87e9e4c..588a7845997 100644 --- a/lib/templatelayout.php +++ b/lib/templatelayout.php @@ -123,7 +123,7 @@ class OC_TemplateLayout extends OC_Template { elseif(self::appendIfExist($files, $apps_dir['path'], $apps_dir['url'], "$style.css")) { $append =true; break; } } if(! $append) { - echo('css file not found: style:'.$script.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); + echo('css file not found: style:'.$style.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); die(); } } diff --git a/lib/updater.php b/lib/updater.php index 5d97178c30e..332cea03bfc 100644 --- a/lib/updater.php +++ b/lib/updater.php @@ -84,4 +84,3 @@ class OC_Updater{ } } -?> diff --git a/lib/user.php b/lib/user.php index d02c1208a8d..e3c9c23effa 100644 --- a/lib/user.php +++ b/lib/user.php @@ -21,7 +21,7 @@ */ /** - * This class provides wrapper methods for user management. Multiple backends are + * This class provides wrapper methods for user management. Multiple backends are * supported. User management operations are delegated to the configured backend for * execution. * @@ -50,8 +50,8 @@ class OC_User { * * Makes a list of backends that can be used by other modules */ - public static function registerBackend( $name ){ - self::$_backends[] = $name; + public static function registerBackend( $backend ){ + self::$_backends[] = $backend; return true; } @@ -83,28 +83,38 @@ class OC_User { * Set the User Authentication Module */ public static function useBackend( $backend = 'database' ){ - // You'll never know what happens - if( null === $backend OR !is_string( $backend )){ - $backend = 'database'; - } + if($backend instanceof OC_User_Interface){ + self::$_usedBackends[get_class($backend)]=$backend; + }else{ + // You'll never know what happens + if( null === $backend OR !is_string( $backend )){ + $backend = 'database'; + } - // Load backend - switch( $backend ){ - case 'database': - case 'mysql': - case 'sqlite': - self::$_usedBackends[$backend] = new OC_User_Database(); - break; - default: - $className = 'OC_USER_' . strToUpper($backend); - self::$_usedBackends[$backend] = new $className(); - break; + // Load backend + switch( $backend ){ + case 'database': + case 'mysql': + case 'sqlite': + self::$_usedBackends[$backend] = new OC_User_Database(); + break; + default: + $className = 'OC_USER_' . strToUpper($backend); + self::$_usedBackends[$backend] = new $className(); + break; + } } - true; } /** + * remove all used backends + */ + public static function clearBackends(){ + self::$_usedBackends=array(); + } + + /** * @brief Create a new user * @param $uid The username of the user to create * @param $password The password of the new user @@ -200,7 +210,7 @@ class OC_User { if( $run ){ $uid=self::checkPassword( $uid, $password ); if($uid){ - session_regenerate_id(); + session_regenerate_id(true); self::setUserId($uid); OC_Hook::emit( "OC_User", "post_login", array( "uid" => $uid, 'password'=>$password )); return true; @@ -345,17 +355,13 @@ class OC_User { * @return boolean */ public static function userExists($uid){ - static $user_exists_checked = null;
- if (!is_null($user_exists_checked)) {
- return $user_exists_checked;
- } foreach(self::$_usedBackends as $backend){ $result=$backend->userExists($uid); if($result===true){ - return $user_exists_checked = true; + return true; } } - return $user_exists_checked = false; + return false; } /** diff --git a/lib/user/backend.php b/lib/user/backend.php index be068a63ce0..daa942d261c 100644 --- a/lib/user/backend.php +++ b/lib/user/backend.php @@ -42,7 +42,7 @@ define('OC_USER_BACKEND_CHECK_PASSWORD', 0x000100); * * Subclass this for your own backends, and see OC_User_Example for descriptions */ -abstract class OC_User_Backend { +abstract class OC_User_Backend implements OC_User_Interface { protected $possibleActions = array( OC_USER_BACKEND_CREATE_USER => 'createUser', diff --git a/lib/user/database.php b/lib/user/database.php index a48b8357d64..cc27b3ddbfd 100644 --- a/lib/user/database.php +++ b/lib/user/database.php @@ -39,7 +39,6 @@ require_once 'phpass/PasswordHash.php'; * Class for user management in a SQL Database (e.g. MySQL, SQLite) */ class OC_User_Database extends OC_User_Backend { - static private $userGroupCache=array(); /** * @var PasswordHash */ @@ -87,7 +86,7 @@ class OC_User_Database extends OC_User_Backend { public function deleteUser( $uid ){ // Delete user-group-relation $query = OC_DB::prepare( "DELETE FROM `*PREFIX*users` WHERE uid = ?" ); - $result = $query->execute( array( $uid )); + $query->execute( array( $uid )); return true; } @@ -104,11 +103,10 @@ class OC_User_Database extends OC_User_Backend { $hasher=$this->getHasher(); $hash = $hasher->HashPassword($password.OC_Config::getValue('passwordsalt', '')); $query = OC_DB::prepare( "UPDATE *PREFIX*users SET password = ? WHERE uid = ?" ); - $result = $query->execute( array( $hash, $uid )); + $query->execute( array( $hash, $uid )); return true; - } - else{ + }else{ return false; } } diff --git a/lib/user/example.php b/lib/user/example.php index 7f3fd1b8578..77246d8136c 100644 --- a/lib/user/example.php +++ b/lib/user/example.php @@ -35,9 +35,7 @@ abstract class OC_User_Example extends OC_User_Backend { * Creates a new user. Basic checking of username is done in OC_User * itself, not in its subclasses. */ - public function createUser($uid, $password){ - return OC_USER_BACKEND_NOT_IMPLEMENTED; - } + abstract public function createUser($uid, $password); /** * @brief Set password @@ -47,9 +45,7 @@ abstract class OC_User_Example extends OC_User_Backend { * * Change the password of a user */ - public function setPassword($uid, $password){ - return OC_USER_BACKEND_NOT_IMPLEMENTED; - } + abstract public function setPassword($uid, $password); /** * @brief Check if the password is correct @@ -60,7 +56,5 @@ abstract class OC_User_Example extends OC_User_Backend { * Check if the password is correct without logging in the user * returns the user id or false */ - public function checkPassword($uid, $password){ - return OC_USER_BACKEND_NOT_IMPLEMENTED; - } + abstract public function checkPassword($uid, $password); } diff --git a/lib/user/interface.php b/lib/user/interface.php new file mode 100644 index 00000000000..dc3685dc20d --- /dev/null +++ b/lib/user/interface.php @@ -0,0 +1,60 @@ +<?php + +/** + * ownCloud - user interface + * + * @author Arthur Schiwon + * @copyright 2012 Arthur Schiwon blizzz@owncloud.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/>. + * + */ + +interface OC_User_Interface { + + /** + * @brief Check if backend implements actions + * @param $actions bitwise-or'ed actions + * @returns boolean + * + * Returns the supported actions as int to be + * compared with OC_USER_BACKEND_CREATE_USER etc. + */ + public function implementsActions($actions); + + /** + * @brief delete a user + * @param $uid The username of the user to delete + * @returns true/false + * + * Deletes a user + */ + public function deleteUser($uid); + + /** + * @brief Get a list of all users + * @returns array with all uids + * + * Get a list of all users. + */ + public function getUsers(); + + /** + * @brief check if a user exists + * @param string $uid the username + * @return boolean + */ + public function userExists($uid); + +}
\ No newline at end of file diff --git a/lib/util.php b/lib/util.php index 2a7b8a922f9..0c563278cc5 100755 --- a/lib/util.php +++ b/lib/util.php @@ -77,13 +77,13 @@ class OC_Util { return '5 pre alpha'; } - /** - * get the current installed edition of ownCloud. There is the community edition that just returns an empty string and the enterprise edition that returns "Enterprise". - * @return string - */ - public static function getEditionString(){ - return ''; - } + /** + * get the current installed edition of ownCloud. There is the community edition that just returns an empty string and the enterprise edition that returns "Enterprise". + * @return string + */ + public static function getEditionString(){ + return ''; + } /** * add a javascript file @@ -131,12 +131,12 @@ class OC_Util { self::$headers[]=array('tag'=>$tag,'attributes'=>$attributes,'text'=>$text); } - /** - * formats a timestamp in the "right" way - * - * @param int timestamp $timestamp - * @param bool dateOnly option to ommit time from the result - */ + /** + * formats a timestamp in the "right" way + * + * @param int timestamp $timestamp + * @param bool dateOnly option to ommit time from the result + */ public static function formatDate( $timestamp,$dateOnly=false){ if(isset($_SESSION['timezone'])){//adjust to clients timezone if we know it $systemTimeZone = intval(date('O')); @@ -189,8 +189,6 @@ class OC_Util { if(!(is_callable('sqlite_open') or class_exists('SQLite3')) and !is_callable('mysql_connect') and !is_callable('pg_connect')){ $errors[]=array('error'=>'No database drivers (sqlite, mysql, or postgresql) installed.<br/>','hint'=>'');//TODO: sane hint } - $CONFIG_DBTYPE = OC_Config::getValue( "dbtype", "sqlite" ); - $CONFIG_DBNAME = OC_Config::getValue( "dbname", "owncloud" ); //common hint for all file permissons error messages $permissionsHint="Permissions can usually be fixed by giving the webserver write access to the ownCloud directory"; @@ -440,26 +438,25 @@ class OC_Util { } - /** - * Check if the htaccess file is working by creating a test file in the data directory and trying to access via http - */ - public static function ishtaccessworking() { - + /** + * Check if the htaccess file is working by creating a test file in the data directory and trying to access via http + */ + public static function ishtaccessworking() { // testdata $filename='/htaccesstest.txt'; $testcontent='testcontent'; // creating a test file - $testfile = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ).'/'.$filename; - $fp = @fopen($testfile, 'w'); - @fwrite($fp, $testcontent); - @fclose($fp); + $testfile = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ).'/'.$filename; + $fp = @fopen($testfile, 'w'); + @fwrite($fp, $testcontent); + @fclose($fp); // accessing the file via http - $url = OC_Helper::serverProtocol(). '://' . OC_Helper::serverHost() . OC::$WEBROOT.'/data'.$filename; - $fp = @fopen($url, 'r'); - $content=@fread($fp, 2048); - @fclose($fp); + $url = OC_Helper::serverProtocol(). '://' . OC_Helper::serverHost() . OC::$WEBROOT.'/data'.$filename; + $fp = @fopen($url, 'r'); + $content=@fread($fp, 2048); + @fclose($fp); // cleanup @unlink($testfile); @@ -469,13 +466,7 @@ class OC_Util { return(false); }else{ return(true); - } - - } - - - - + } } diff --git a/lib/vcategories.php b/lib/vcategories.php index 8157c343868..d15b7b166ea 100644 --- a/lib/vcategories.php +++ b/lib/vcategories.php @@ -131,8 +131,10 @@ class OC_VCategories { * } * $categories->rescan($objects); */ - public function rescan($objects, $sync=true) { - $this->categories = array(); + public function rescan($objects, $sync=true, $reset=true) { + if($reset === true) { + $this->categories = array(); + } foreach($objects as $object) { //OC_Log::write('core','OC_VCategories::rescan: '.substr($object, 0, 100).'(...)', OC_Log::DEBUG); $vobject = OC_VObject::parse($object); @@ -221,4 +223,3 @@ class OC_VCategories { } } -?> diff --git a/ocs/providers.php b/ocs/providers.php index adaa28db6cd..cc6de32266b 100644 --- a/ocs/providers.php +++ b/ocs/providers.php @@ -35,11 +35,10 @@ echo(' <termsofuse></termsofuse> <register></register> <services> - <activity ocsversion="1.5" /> + <config ocsversion="1.7" /> + <activity ocsversion="1.7" /> + <cloud ocsversion="1.7" /> </services> </provider> </providers> '); - - -?> diff --git a/ocs/v1.php b/ocs/v1.php index 77dd75b9fc2..ab0dc80f4ba 100644 --- a/ocs/v1.php +++ b/ocs/v1.php @@ -24,5 +24,3 @@ require_once('../lib/base.php'); @ob_clean(); OC_OCS::handle(); - -?> diff --git a/public.php b/public.php index 8846769f467..8383f36a246 100644 --- a/public.php +++ b/public.php @@ -10,6 +10,7 @@ if(is_null($file)){ $parts=explode('/',$file,2); $app=$parts[0]; + OC_Util::checkAppEnabled($app); OC_App::loadApp($app); diff --git a/remote.php b/remote.php index bdce867aaba..8461eea19ad 100644 --- a/remote.php +++ b/remote.php @@ -15,27 +15,27 @@ if (!$pos = strpos($path_info, '/', 1)) { $pos = strlen($path_info); } $service=substr($path_info, 1, $pos-1); + $file = OC_AppConfig::getValue('core', 'remote_' . $service); -$file = preg_replace('/apps\//','', $file); //Todo Remove after Multiappdir migration if(is_null($file)){ OC_Response::setStatus(OC_Response::STATUS_NOT_FOUND); exit; } -$file = ltrim ($file, '/'); +$file=ltrim($file,'/'); $parts=explode('/', $file, 2); $app=$parts[0]; switch ($app) { + case 'core': + $file = OC::$SERVERROOT .'/'. $file; + break; default: OC_Util::checkAppEnabled($app); OC_App::loadApp($app); $file = OC_App::getAppPath($app) .'/'. $parts[1]; break; - case 'core': - $file = OC::$SERVERROOT .'/'. $file; - break; } $baseuri = OC::$WEBROOT . '/remote.php/'.$service.'/'; require_once($file); diff --git a/search/ajax/search.php b/search/ajax/search.php index 326724d60c4..95ddfedf8ba 100644 --- a/search/ajax/search.php +++ b/search/ajax/search.php @@ -35,5 +35,3 @@ if($query){ }else{ echo 'false'; } - -?> diff --git a/search/index.php b/search/index.php index 518695c56d2..de55aec3999 100644 --- a/search/index.php +++ b/search/index.php @@ -49,5 +49,3 @@ foreach($results as $result){ $tmpl = new OC_Template( 'search', 'index', 'user' ); $tmpl->assign('resultTypes',$resultTypes); $tmpl->printPage(); - -?> diff --git a/settings/ajax/changepassword.php b/settings/ajax/changepassword.php index 860ea987871..4ba6813517b 100644 --- a/settings/ajax/changepassword.php +++ b/settings/ajax/changepassword.php @@ -9,6 +9,8 @@ $oldPassword=isset($_POST["oldpassword"])?$_POST["oldpassword"]:''; // Check if we are a user OC_JSON::checkLoggedIn(); +OCP\JSON::callCheck(); + if( (!OC_Group::inGroup( OC_User::getUser(), 'admin' ) && ($username!=OC_User::getUser() || !OC_User::checkPassword($username,$oldPassword)))) { OC_JSON::error( array( "data" => array( "message" => "Authentication error" ))); exit(); @@ -21,5 +23,3 @@ if( OC_User::setPassword( $username, $password )){ else{ OC_JSON::error(array("data" => array( "message" => "Unable to change password" ))); } - -?> diff --git a/settings/ajax/creategroup.php b/settings/ajax/creategroup.php index 57d82e7bd94..af8ad3dd8c0 100644 --- a/settings/ajax/creategroup.php +++ b/settings/ajax/creategroup.php @@ -9,6 +9,8 @@ if( !OC_User::isLoggedIn() || !OC_Group::inGroup( OC_User::getUser(), 'admin' )) exit(); } +OCP\JSON::callCheck(); + $groupname = $_POST["groupname"]; // Does the group exist? @@ -24,5 +26,3 @@ if( OC_Group::createGroup( $groupname )){ else{ OC_JSON::error(array("data" => array( "message" => "Unable to add group" ))); } - -?> diff --git a/settings/ajax/createuser.php b/settings/ajax/createuser.php index 6714711bc87..c56df4bc15a 100644 --- a/settings/ajax/createuser.php +++ b/settings/ajax/createuser.php @@ -8,6 +8,7 @@ if( !OC_User::isLoggedIn() || !OC_Group::inGroup( OC_User::getUser(), 'admin' )) OC_JSON::error(array("data" => array( "message" => "Authentication error" ))); exit(); } +OCP\JSON::callCheck(); $groups = array(); if( isset( $_POST["groups"] )){ @@ -35,5 +36,3 @@ try { } catch (Exception $exception) { OC_JSON::error(array("data" => array( "message" => $exception->getMessage()))); } - -?> diff --git a/settings/ajax/disableapp.php b/settings/ajax/disableapp.php index 53e9be379e1..cc006988707 100644 --- a/settings/ajax/disableapp.php +++ b/settings/ajax/disableapp.php @@ -2,6 +2,7 @@ // Init owncloud require_once('../../lib/base.php'); OC_JSON::checkAdminUser(); +OCP\JSON::callCheck(); OC_JSON::setContentTypeHeader(); OC_App::disable($_POST['appid']); diff --git a/settings/ajax/enableapp.php b/settings/ajax/enableapp.php index cb116ebe4e8..bd53a50210c 100644 --- a/settings/ajax/enableapp.php +++ b/settings/ajax/enableapp.php @@ -3,6 +3,7 @@ // Init owncloud require_once('../../lib/base.php'); OC_JSON::checkAdminUser(); +OCP\JSON::callCheck(); OC_JSON::setContentTypeHeader(); if(OC_App::enable($_POST['appid'])){ diff --git a/settings/ajax/lostpassword.php b/settings/ajax/lostpassword.php index c6df8551f52..803a424854c 100644 --- a/settings/ajax/lostpassword.php +++ b/settings/ajax/lostpassword.php @@ -2,8 +2,8 @@ // Init owncloud require_once('../../lib/base.php'); - OC_JSON::checkLoggedIn(); +OCP\JSON::callCheck(); $l=OC_L10N::get('core'); @@ -15,5 +15,3 @@ if( isset( $_POST['email'] ) && filter_var( $_POST['email'], FILTER_VALIDATE_EMA }else{ OC_JSON::error(array("data" => array( "message" => $l->t("Invalid email") ))); } - -?> diff --git a/settings/ajax/openid.php b/settings/ajax/openid.php index 58d071255c2..bf4ead06020 100644 --- a/settings/ajax/openid.php +++ b/settings/ajax/openid.php @@ -6,6 +6,7 @@ require_once('../../lib/base.php'); $l=OC_L10N::get('settings'); OC_JSON::checkLoggedIn(); +OCP\JSON::callCheck(); OC_JSON::checkAppEnabled('user_openid'); // Get data @@ -16,5 +17,3 @@ if( isset( $_POST['identity'] ) ){ }else{ OC_JSON::error(array("data" => array( "message" => $l->t("Invalid request") ))); } - -?> diff --git a/settings/ajax/removegroup.php b/settings/ajax/removegroup.php index 4d364781894..f8c2065956c 100644 --- a/settings/ajax/removegroup.php +++ b/settings/ajax/removegroup.php @@ -4,6 +4,7 @@ require_once('../../lib/base.php'); OC_JSON::checkAdminUser(); +OCP\JSON::callCheck(); $name = $_POST["groupname"]; @@ -14,5 +15,3 @@ if( OC_Group::deleteGroup( $name )){ else{ OC_JSON::error(array("data" => array( "message" => "Unable to delete group" ))); } - -?> diff --git a/settings/ajax/removeuser.php b/settings/ajax/removeuser.php index 2c288997a1f..230815217c3 100644 --- a/settings/ajax/removeuser.php +++ b/settings/ajax/removeuser.php @@ -4,6 +4,7 @@ require_once('../../lib/base.php'); OC_JSON::checkAdminUser(); +OCP\JSON::callCheck(); $username = $_POST["username"]; @@ -14,5 +15,3 @@ if( OC_User::deleteUser( $username )){ else{ OC_JSON::error(array("data" => array( "message" => "Unable to delete user" ))); } - -?> diff --git a/settings/ajax/setlanguage.php b/settings/ajax/setlanguage.php index e3b00c3bc80..54b103cd4fe 100644 --- a/settings/ajax/setlanguage.php +++ b/settings/ajax/setlanguage.php @@ -6,6 +6,7 @@ require_once('../../lib/base.php'); $l=OC_L10N::get('settings'); OC_JSON::checkLoggedIn(); +OCP\JSON::callCheck(); // Get data @@ -21,5 +22,3 @@ if( isset( $_POST['lang'] ) ){ }else{ OC_JSON::error(array("data" => array( "message" => $l->t("Invalid request") ))); } - -?> diff --git a/settings/ajax/setloglevel.php b/settings/ajax/setloglevel.php index 298cbd64738..4b97ba2aa32 100644 --- a/settings/ajax/setloglevel.php +++ b/settings/ajax/setloglevel.php @@ -7,6 +7,7 @@ require_once('../../lib/base.php'); OC_Util::checkAdminUser(); +OCP\JSON::callCheck(); OC_Config::setValue( 'loglevel', $_POST['level'] ); diff --git a/settings/ajax/setquota.php b/settings/ajax/setquota.php index f59017600ac..2b412c0f2fd 100644 --- a/settings/ajax/setquota.php +++ b/settings/ajax/setquota.php @@ -9,6 +9,7 @@ require_once('../../lib/base.php'); OC_JSON::checkAdminUser(); +OCP\JSON::callCheck(); $username = isset($_POST["username"])?$_POST["username"]:''; @@ -34,4 +35,3 @@ if($username){ } OC_JSON::success(array("data" => array( "username" => $username ,'quota'=>$quota))); -?> diff --git a/settings/ajax/togglegroups.php b/settings/ajax/togglegroups.php index 7773c1049c3..95338ed0267 100644 --- a/settings/ajax/togglegroups.php +++ b/settings/ajax/togglegroups.php @@ -4,6 +4,7 @@ require_once('../../lib/base.php'); OC_JSON::checkAdminUser(); +OCP\JSON::callCheck(); $success = true; $error = "add user to"; @@ -37,5 +38,3 @@ if( $success ){ else{ OC_JSON::error(array("data" => array( "message" => "Unable to $error group $group" ))); } - -?> diff --git a/settings/apps.php b/settings/apps.php index f4ae8b8d977..762395c031b 100644 --- a/settings/apps.php +++ b/settings/apps.php @@ -97,5 +97,3 @@ $appid = (isset($_GET['appid'])?strip_tags($_GET['appid']):''); $tmpl->assign('appid',$appid); $tmpl->printPage(); - -?> diff --git a/settings/help.php b/settings/help.php index f0abed8f558..b1dc1c5be77 100644 --- a/settings/help.php +++ b/settings/help.php @@ -25,5 +25,3 @@ $tmpl->assign( "kbe", $kbe ); $tmpl->assign( "pagecount", $pagecount ); $tmpl->assign( "page", $page ); $tmpl->printPage(); - -?> diff --git a/settings/js/users.js b/settings/js/users.js index dfa28e4c4cb..63ad426ecf4 100644 --- a/settings/js/users.js +++ b/settings/js/users.js @@ -47,25 +47,24 @@ UserList={ if( !UserList.deleteCanceled && UserList.deleteUid ){ // Delete user via ajax - $.post( - OC.filePath('settings','ajax','removeuser.php'), - {username:UserList.deleteUid}, - function(result){ - - // Remove undo option, & remove user from table - boolOperationFinished( - data, function(){ - $('#notification').fadeOut(); - $('tr').filterAttr( 'data-uid', username ).remove(); - UserList.deleteCanceled=true; - UserList.deleteFiles=null; - if( ready ){ - ready(); - } + $.ajax({ + type: 'POST', + url: OC.filePath('settings', 'ajax', 'removeuser.php'), + async: false, + data: { username: UserList.deleteUid }, + success: function(result) { + if (result.status == 'success') { + // Remove undo option, & remove user from table + $('#notification').fadeOut(); + $('tr').filterAttr('data-uid', UserList.deleteUid).remove(); + UserList.deleteCanceled = true; + UserList.deleteFiles = null; + if (ready) { + ready(); } - ); + } } - ); + }); } } } @@ -186,7 +185,7 @@ $(document).ready(function(){ }) $('input.quota-other').live('change',function(){ - var uid=$(this).parent().parent().data('uid'); + var uid=$(this).parent().parent().parent().data('uid'); var quota=$(this).val(); var select=$(this).prev(); var other=$(this); diff --git a/settings/personal.php b/settings/personal.php index 26a9f601d9a..d82db0d0e7e 100644 --- a/settings/personal.php +++ b/settings/personal.php @@ -17,7 +17,7 @@ OC_App::setActiveNavigationEntry( 'personal' ); // calculate the disc space $rootInfo=OC_FileCache::get(''); -$sharedInfo=OC_FileCache::get('/Shared');
+$sharedInfo=OC_FileCache::get('/Shared'); $used=$rootInfo['size']-$sharedInfo['size']; $free=OC_Filesystem::free_space(); $total=$free+$used; @@ -61,5 +61,3 @@ foreach($forms as $form){ $tmpl->append('forms',$form); } $tmpl->printPage(); - -?> diff --git a/settings/users.php b/settings/users.php index 026a30a750c..c3259d2a3f1 100644 --- a/settings/users.php +++ b/settings/users.php @@ -48,6 +48,3 @@ $tmpl->assign( 'quota_preset', $quotaPreset); $tmpl->assign( 'default_quota', $defaultQuota); $tmpl->assign( 'share_notice', $shareNotice); $tmpl->printPage(); - -?> - diff --git a/status.php b/status.php index 2d31702ecb3..f314a3a1c6f 100644 --- a/status.php +++ b/status.php @@ -29,6 +29,3 @@ if(OC_Config::getValue('installed')==1) $installed='true'; else $installed='fals $values=array('installed'=>$installed,'version'=>implode('.',OC_Util::getVersion()),'versionstring'=>OC_Util::getVersionString(),'edition'=>OC_Util::getEditionString()); echo(json_encode($values)); - - -?> diff --git a/tests/index.php b/tests/index.php index 691bf2a5d45..0be27ee3fd7 100644 --- a/tests/index.php +++ b/tests/index.php @@ -26,39 +26,64 @@ require_once 'simpletest/mock_objects.php'; require_once 'simpletest/collector.php'; require_once 'simpletest/default_reporter.php'; +$testSuiteName="ownCloud Unit Test Suite"; + +// prepare the reporter +if(OC::$CLI){ + $reporter=new TextReporter; + $test=isset($_SERVER['argv'][1])?$_SERVER['argv'][1]:false; + if($test=='xml'){ + $reporter= new XmlReporter; + $test=false; + + if(isset($_SERVER['argv'][2])){ + $testSuiteName=$testSuiteName." (".$_SERVER['argv'][2].")"; + } + } +}else{ + $reporter=new HtmlReporter; + $test=isset($_GET['test'])?$_GET['test']:false; +} + +// test suite instance +$testSuite=new TestSuite($testSuiteName); + //load core test cases -loadTests(dirname(__FILE__)); +loadTests(dirname(__FILE__), $testSuite, $test); //load app test cases + +// +// TODO: define a list of apps to be enabled + enable them +// + $apps=OC_App::getEnabledApps(); foreach($apps as $app){ if(is_dir(OC::$SERVERROOT.'/apps/'.$app.'/tests')){ - loadTests(OC::$SERVERROOT.'/apps/'.$app.'/tests'); + loadTests(OC::$SERVERROOT.'/apps/'.$app.'/tests', $testSuite, $test); } } -function loadTests($dir=''){ - if(OC::$CLI){ - $reporter='TextReporter'; - $test=isset($_SERVER['argv'][1])?$_SERVER['argv'][1]:false; - }else{ - $reporter='HtmlReporter'; - $test=isset($_GET['test'])?$_GET['test']:false; - } +// run the suite +if($testSuite->getSize()>0){ + $testSuite->run($reporter); +} + +// helper below +function loadTests($dir,$testSuite, $test){ if($dh=opendir($dir)){ while($name=readdir($dh)){ if($name[0]!='.'){//no hidden files, '.' or '..' $file=$dir.'/'.$name; if(is_dir($file)){ - loadTests($file); + loadTests($file, $testSuite, $test); }elseif(substr($file,-4)=='.php' and $file!=__FILE__){ $name=getTestName($file); if($test===false or $test==$name or substr($name,0,strlen($test))==$test){ - $testCase=new TestSuite($name); - $testCase->addFile($file); - if($testCase->getSize()>0){ - $testCase->run(new $reporter()); - } + $extractor = new SimpleFileLoader(); + $loadedSuite=$extractor->load($file); + if ($loadedSuite->getSize() > 0) + $testSuite->add($loadedSuite); } } } diff --git a/tests/lib/cache.php b/tests/lib/cache.php index bb5cfc6ee19..511999be956 100644 --- a/tests/lib/cache.php +++ b/tests/lib/cache.php @@ -42,6 +42,27 @@ abstract class Test_Cache extends UnitTestCase { $this->assertNull($this->instance->get('not_set'),'Unset value not equal to null'); $this->assertTrue($this->instance->remove('value1')); + $this->assertFalse($this->instance->hasKey('value1')); + } + + function testClear(){ + $value='ipsum lorum'; + $this->instance->set('1_value1',$value); + $this->instance->set('1_value2',$value); + $this->instance->set('2_value1',$value); + $this->instance->set('3_value1',$value); + + $this->assertTrue($this->instance->clear('1_')); + $this->assertFalse($this->instance->hasKey('1_value1')); + $this->assertFalse($this->instance->hasKey('1_value2')); + $this->assertTrue($this->instance->hasKey('2_value1')); + $this->assertTrue($this->instance->hasKey('3_value1')); + + $this->assertTrue($this->instance->clear()); + $this->assertFalse($this->instance->hasKey('1_value1')); + $this->assertFalse($this->instance->hasKey('1_value2')); + $this->assertFalse($this->instance->hasKey('2_value1')); + $this->assertFalse($this->instance->hasKey('3_value1')); } function testTTL(){ diff --git a/tests/lib/cache/file.php b/tests/lib/cache/file.php index 54e60e6569d..28778efb68c 100644 --- a/tests/lib/cache/file.php +++ b/tests/lib/cache/file.php @@ -21,8 +21,10 @@ */ class Test_Cache_File extends Test_Cache { + private $user; + function skip() { - $this->skipUnless(OC_User::isLoggedIn()); + //$this->skipUnless(OC_User::isLoggedIn()); } public function setUp(){ @@ -30,17 +32,32 @@ class Test_Cache_File extends Test_Cache { OC_FileProxy::clearProxies(); OC_Hook::clear('OC_Filesystem'); - //enable only the encryption hook - OC_FileProxy::register(new OC_FileProxy_Encryption()); + //enable only the encryption hook if needed + if(OC_App::isEnabled('files_encryption')){ + OC_FileProxy::register(new OC_FileProxy_Encryption()); + } //set up temporary storage OC_Filesystem::clearMounts(); OC_Filesystem::mount('OC_Filestorage_Temporary',array(),'/'); + OC_User::clearBackends(); + OC_User::useBackend(new OC_User_Dummy()); + + //login + OC_User::createUser('test', 'test'); + + $this->user=OC_User::getUser(); + OC_User::setUserId('test'); + //set up the users dir $rootView=new OC_FilesystemView(''); - $rootView->mkdir('/'.OC_User::getUser()); + $rootView->mkdir('/test'); $this->instance=new OC_Cache_File(); } + + public function tearDown(){ + OC_User::setUserId($this->user); + } } diff --git a/tests/lib/user/database.php b/tests/lib/user/database.php index b2fcce93c5b..f484ffa78f7 100644 --- a/tests/lib/user/database.php +++ b/tests/lib/user/database.php @@ -21,7 +21,6 @@ */ class Test_User_Database extends Test_User_Backend { - private $user=array(); /** * get a new unique user name * test cases can override this in order to clean up created user diff --git a/webapps.php b/webapps.php deleted file mode 100644 index b5fee9bf85f..00000000000 --- a/webapps.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -/** -* ownCloud status page. usefull if you want to check from the outside if an owncloud installation exists -* -* @author Frank Karlitschek -* @copyright 2012 Frank Karlitschek frank@owncloud.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/>. -* -*/ - -$RUNTIME_NOAPPS = TRUE; //no apps, yet - -require_once('lib/base.php'); - - -//valid user account -if(isset($_SERVER['PHP_AUTH_USER'])) $authuser=$_SERVER['PHP_AUTH_USER']; else $authuser=''; -if(isset($_SERVER['PHP_AUTH_PW'])) $authpw=$_SERVER['PHP_AUTH_PW']; else $authpw=''; - -if(!OC_User::login($authuser,$authpw)){ - header('WWW-Authenticate: Basic realm="your valid user account"'); - header('HTTP/1.0 401 Unauthorized'); - exit; -}else{ - - $apps=OC_App::getEnabledApps(); - $values=array(); - foreach($apps as $app) { - $info=OC_App::getAppInfo($app); - if(isset($info['standalone'])) { - $newvalue=array('name'=>$info['name'],'url'=>OC_Helper::linkToAbsolute($app,''),'icon'=>''); - $values[]=$newvalue; - } - - } - - echo(json_encode($values)); - exit; - - -} - -?> |