[Pkg-owncloud-commits] [owncloud] 29/32: Imported Upstream version 6.0.3~rc1+dfsg

David Prévot taffit at moszumanska.debian.org
Wed Apr 23 18:59:02 UTC 2014


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository owncloud.

commit 61eba845ee81c057f24fe191e2817a703362b7d5
Merge: e84bf62 53df9c9
Author: David Prévot <taffit at debian.org>
Date:   Wed Apr 23 13:04:41 2014 -0400

    Imported Upstream version 6.0.3~rc1+dfsg

 3rdparty/doctrine/common/bin/travis-setup.php      | 141 ---------------
 apps/activity/lib/data.php                         |   2 +-
 apps/activity/lib/search.php                       |   2 +-
 apps/calendar/lib/export.php                       |  10 --
 apps/contacts/lib/backend/database.php             |   6 +-
 apps/contacts/lib/backend/shared.php               |  14 +-
 apps/contacts/lib/dispatcher.php                   |   6 +-
 apps/contacts/lib/share/addressbook.php            |   5 +-
 apps/files_external/ajax/addMountPoint.php         |   7 +-
 .../3rdparty/Zend/Search/Lucene/Document/Docx.php  |   1 +
 .../Zend/Search/Lucene/Document/OpenXml.php        |   1 +
 .../3rdparty/Zend/Search/Lucene/Document/Xlsx.php  |   1 +
 apps/search_lucene/document/Ods.php                |   1 +
 apps/search_lucene/document/Odt.php                |   1 +
 apps/search_lucene/document/OpenDocument.php       |   1 +
 apps/user_ldap/group_ldap.php                      |  21 +--
 apps/user_ldap/group_proxy.php                     |  16 --
 apps/user_ldap/js/ldapFilter.js                    | 100 +++++++++++
 apps/user_ldap/js/settings.js                      | 100 +++--------
 apps/user_ldap/lib/access.php                      |  15 ++
 apps/user_ldap/settings.php                        |   1 +
 .../doc/admin/_sources/configuration/auth_ldap.txt |  65 ++++---
 core/doc/admin/configuration/auth_ldap.html        |  65 ++++---
 core/skeleton/ownCloudUserManual.pdf               | Bin 1572014 -> 1571999 bytes
 lib/base.php                                       |  29 ++++
 .../dependencyinjection/dicontainer.php            |  12 +-
 lib/private/appframework/http/request.php          |  87 ++++------
 lib/private/connector/sabre/file.php               |   7 +-
 lib/private/eventsource.php                        |   3 +-
 lib/private/files/type/detection.php               |  36 +++-
 lib/private/group.php                              |  12 +-
 lib/private/group/backend.php                      |  22 +--
 lib/private/group/database.php                     |  26 ---
 lib/private/group/group.php                        |   6 +-
 lib/private/group/manager.php                      |  34 ++++
 lib/private/helper.php                             |  10 ++
 lib/private/json.php                               |   2 -
 lib/private/mimetypes.list.php                     | 192 ++++++++++++---------
 lib/private/server.php                             |   9 +-
 lib/private/template.php                           |  23 ---
 lib/private/user/manager.php                       |   4 +-
 lib/public/appframework/iappcontainer.php          |   4 +-
 version.php                                        |   8 +-
 43 files changed, 517 insertions(+), 591 deletions(-)

diff --cc apps/activity/lib/data.php
index 409be24,0000000..4bfa5d8
mode 100644,000000..100644
--- a/apps/activity/lib/data.php
+++ b/apps/activity/lib/data.php
@@@ -1,286 -1,0 +1,286 @@@
 +<?php
 +
 +/**
 + * ownCloud - Activity App
 + *
 + * @author Frank Karlitschek
 + * @copyright 2013 Frank Karlitschek frank at 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 Lesser General Public
 + * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +
 +
 +namespace OCA\Activity;
 +
 +
 +/**
 + * @brief Class for managing the data in the activities
 + */
 +class Data
 +{
 +	const PRIORITY_VERYLOW 	= 10;
 +	const PRIORITY_LOW	= 20;
 +	const PRIORITY_MEDIUM	= 30;
 +	const PRIORITY_HIGH	= 40;
 +	const PRIORITY_VERYHIGH	= 50;
 +
 +	/**
 +	 * @brief Send an event into the activity stream
 +	 * @param string $app The app where this event is associated with
 +	 * @param string $subject A short description of the event
 +	 * @param string $message A longer description of the event
 +	 * @param string $file The file including path where this event is associated with. (optional)
 +	 * @param string $link A link where this event is associated with (optional)
 +	 * @return boolean
 +	 */
 +	public static function send($app, $subject, $subjectparams = array(), $message = '', $messageparams = array(), $file = '', $link = '', $affecteduser = '', $type = 0, $prio = Data::PRIORITY_MEDIUM)
 +	{
 +
 +		$timestamp = time();
 +		$user = \OCP\User::getUser();
 +		
 +		if($affecteduser === '') {
 +			$auser = \OCP\User::getUser();
 +		} else{
 +			$auser = $affecteduser;
 +		}
 +
 +		// store in DB
 +		$query = \OCP\DB::prepare('INSERT INTO `*PREFIX*activity`(`app`, `subject`, `subjectparams`, `message`, `messageparams`, `file`, `link`, `user`, `affecteduser`, `timestamp`, `priority`, `type`)' . ' VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )');
 +		$query->execute(array($app, $subject, serialize($subjectparams), $message, serialize($messageparams), $file, $link, $user, $auser, $timestamp, $prio, $type));
 +
 +		// call the expire function only every 1000x time to preserve performance.
 +		if (rand(0, 1000) == 0) {
 +			Data::expire();
 +		}
 +
 +		// fire a hook so that other apps like notification systems can connect
 +		// todo translations
 +		\OCP\Util::emitHook('OC_Activity', 'post_event', array('app' => $app, 'subject' => $subject, 'user' => $user, 'affecteduser' => $affecteduser, 'message' => $message, 'file' => $file, 'link'=> $link, 'prio' => $prio, 'type' => $type));
 +
 +		return true;
 +	}
 +
 +	/**
 +	 * @brief Translate an event string with the translations from the app where it was send from
 +	 * @param string $app The app where this event comes from
 +	 * @param string $text The text including placeholders
 +	 * @param array $params The parameter for the placeholder
 +	 * @return string translated
 +	 */
 +	public static function translation($app, $text, $params)
 +	{
 +		$l = \OCP\Util::getL10N($app);
 +		$result = $l->t($text, $params);
 +		unset($l);
 +		return($result);
 +	}
 +
 +	/**
 +	 * @brief Read a list of events from the activity stream
 +	 * @param int $start The start entry
 +	 * @param int $count The number of statements to read
 +	 * @return array
 +	 */
 +	public static function read($start, $count)
 +	{
 +		// get current user
 +		$user = \OCP\User::getUser();
 +
 +		// fetch from DB
 +		$query = \OCP\DB::prepare('SELECT `activity_id`, `app`, `subject`, `subjectparams`, `message`, `messageparams`, `file`, `link`, `timestamp`, `priority`, `type`, `user`, `affecteduser`  FROM `*PREFIX*activity` WHERE `affecteduser` = ? ORDER BY `timestamp` desc', $count, $start);
 +		$result = $query->execute(array($user));
 +
 +		$activity = array();
 +		while ($row = $result->fetchRow()) {
 +			$row['subject'] = Data::translation($row['app'],$row['subject'],unserialize($row['subjectparams']));
 +			$row['message'] = Data::translation($row['app'],$row['message'],unserialize($row['messageparams']));
 +			$activity[] = $row;
 +		}
 +		return $activity;
 +
 +	}
 +
 +	/**
 +	 * @brief Get a list of events which contain the query string
 +	 * @param string $txt The query string
 +	 * @param int $count The number of statements to read
 +	 * @return array
 +	 */
 +	public static function search($txt, $count)
 +	{
 +
 +		// get current user
 +		$user = \OCP\User::getUser();
 +
 +		// search in DB
- 		$query = \OCP\DB::prepare('SELECT `activity_id`, `app`, `subject`, `message`, `file`, `link`, `timestamp`, `priority`, `type`, `user`, `affecteduser` FROM `*PREFIX*activity` WHERE `affecteduser` = ? AND ((`subject` LIKE ?) OR (`message` LIKE ?) OR (`file` LIKE ?)) ORDER BY `timestamp` desc', $count);
++		$query = \OCP\DB::prepare('SELECT `activity_id`, `app`, `subject`, `subjectparams`, `message`, `messageparams`, `file`, `link`, `timestamp`, `priority`, `type`, `user`, `affecteduser` FROM `*PREFIX*activity` WHERE `affecteduser` = ? AND ((`subject` LIKE ?) OR (`message` LIKE ?) OR (`file` LIKE ?)) ORDER BY `timestamp` desc', $count);
 +		$result = $query->execute(array($user, '%' . $txt . '%', '%' . $txt . '%', '%' . $txt . '%')); //$result = $query->execute(array($user,'%'.$txt.''));
 +
 +		$activity = array();
 +		while ($row = $result->fetchRow()) {
 +			$row['subject'] = Data::translation($row['app'],$row['subject'],unserialize($row['subjectparams']));
 +			$row['message'] = Data::translation($row['app'],$row['message'],unserialize($row['messageparams']));
 +			$activity[] = $row;
 +		}
 +		return $activity;
 +
 +	}
 +
 +	/**
 +	 * @brief Show a specific event in the activities
 +	 * @param array $event An array with all the event data in it
 +	 */
 +	public static function show($event)
 +	{
 +		$l = \OC_L10N::get('lib');
 +		$user = $event['user'];
 +		if (!isset($event['isGrouped'])){
 +			$event['isGrouped'] = false;
 +		}
 +
 +		$formattedDate = \OCP\Util::formatDate($event['timestamp']);
 +		$formattedTimestamp = \OCP\relative_modified_date($event['timestamp']);
 +		$displayName = \OCP\User::getDisplayName($user);
 +
 +		// TODO: move into template?
 +		echo('<div class="box">');
 +
 +		echo('<div class="header">');
 +		echo('<span class="avatar" data-user="' . \OC_Util::sanitizeHTML($user) . '"></span>');
 +		echo('<span>');
 +		echo('<span class="user">' . \OC_Util::sanitizeHTML($displayName) . '</span>');
 +		echo('<span class="activitytime tooltip" title="' . \OC_Util::sanitizeHTML($formattedDate) . '">' . \OC_Util::sanitizeHTML($formattedTimestamp) . '</span>');
 +		echo('<span class="appname">' . \OC_Util::sanitizeHTML($event['app']) . '</span>');
 +		echo('</span>');
 +		echo('</div>');
 +		echo('<div class="messagecontainer">');
 +
 +		if ($event['isGrouped']){
 +			$count = 0;
 +			echo('<ul class="activitysubject grouped">');
 +			foreach($event['events'] as $subEvent){
 +				echo('<li>');
 +				if ($subEvent['link'] <> '') echo('<a href="' . $subEvent['link'] . '">');
 +				echo(\OC_Util::sanitizeHTML($subEvent['subject']));
 +				if ($subEvent['link'] <> '') echo('</a>');
 +				echo('</li>');
 +				$count++;
 +				if ($count > 5){
 +					echo('<li class="more">' . $l->n('%n more...', '%n more...', count($event['events']) - $count) . '</li>');
 +					break;
 +				}
 +			}
 +			echo('</ul>');
 +		}
 +		else{
 +			if ($event['link'] <> '') echo('<a href="' . $event['link'] . '">');
 +			echo('<div class="activitysubject">' . \OC_Util::sanitizeHTML($event['subject']) . '</div>');
 +			echo('<div class="activitymessage">' . \OC_Util::sanitizeHTML($event['message']) . '</div>');
 +		}
 +
 +		$rootView = new \OC\Files\View('');
 +		if ($event['file'] !== null){
 +			$exist = $rootView->file_exists('/' . $user . '/files' . $event['file']);
 +			unset($rootView);
 +			// show a preview image if the file still exists
 +			if ($exist) {
 +				echo('<img class="preview" src="' . \OCP\Util::linkToRoute('core_ajax_preview', array('file' => $event['file'], 'x' => 150, 'y' => 150)) . '" />');
 +			}
 +		}
 +
 +		if (!$event['isGrouped'] && $event['link'] <> '') echo('</a>');
 +		echo('</div>'); // end messagecontainer
 +		echo('</div>'); // end box
 +
 +	}
 +
 +
 +	/**
 +	 * @brief Expire old events
 +	 */
 +	public static function expire()
 +	{
 +		// keep activity feed entries for one year
 +		$ttl = (60 * 60 * 24 * 365);
 +
 +		$timelimit = time() - $ttl;
 +		$query = \OCP\DB::prepare('DELETE FROM `*PREFIX*activity` where `timestamp`<?');
 +		$query->execute(array($timelimit));
 +	}
 +
 +
 +	/**
 +	 * @brief Generate an RSS feed
 +	 * @param string $link
 +	 * @param string $content
 +	 */
 +	public static function generaterss($link, $content)
 +	{
 +
 +		$writer = xmlwriter_open_memory();
 +		xmlwriter_set_indent($writer, 4);
 +		xmlwriter_start_document($writer, '1.0', 'utf-8');
 +
 +		xmlwriter_start_element($writer, 'rss');
 +		xmlwriter_write_attribute($writer, 'version', '2.0');
 +		xmlwriter_write_attribute($writer, 'xmlns:atom', 'http://www.w3.org/2005/Atom');
 +		xmlwriter_start_element($writer, 'channel');
 +
 +		xmlwriter_write_element($writer, 'title', 'my ownCloud');
 +		xmlwriter_write_element($writer, 'language', 'en-us');
 +		xmlwriter_write_element($writer, 'link', $link);
 +		xmlwriter_write_element($writer, 'description', 'A personal ownCloud activities');
 +		xmlwriter_write_element($writer, 'pubDate', date('r'));
 +		xmlwriter_write_element($writer, 'lastBuildDate', date('r'));
 +
 +		xmlwriter_start_element($writer, 'atom:link');
 +		xmlwriter_write_attribute($writer, 'href', $link);
 +		xmlwriter_write_attribute($writer, 'rel', 'self');
 +		xmlwriter_write_attribute($writer, 'type', 'application/rss+xml');
 +		xmlwriter_end_element($writer);
 +
 +		// items
 +		for ($i = 0; $i < count($content); $i++) {
 +			xmlwriter_start_element($writer, 'item');
 +			if (isset($content[$i]['subject'])) {
 +				xmlwriter_write_element($writer, 'title', $content[$i]['subject']);
 +			}
 +
 +			if (isset($content[$i]['link'])) xmlwriter_write_element($writer, 'link', $content[$i]['link']);
 +			if (isset($content[$i]['link'])) xmlwriter_write_element($writer, 'guid', $content[$i]['link']);
 +			if (isset($content[$i]['timestamp'])) xmlwriter_write_element($writer, 'pubDate', date('r', $content[$i]['timestamp']));
 +
 +			if (isset($content[$i]['message'])) {
 +				xmlwriter_start_element($writer, 'description');
 +				xmlwriter_start_cdata($writer);
 +				xmlwriter_text($writer, $content[$i]['message']);
 +				xmlwriter_end_cdata($writer);
 +				xmlwriter_end_element($writer);
 +			}
 +			xmlwriter_end_element($writer);
 +		}
 +
 +		xmlwriter_end_element($writer);
 +		xmlwriter_end_element($writer);
 +
 +		xmlwriter_end_document($writer);
 +		$entry = xmlwriter_output_memory($writer);
 +		unset($writer);
 +		return ($entry);
 +	}
 +
 +
 +}
diff --cc apps/activity/lib/search.php
index 70ba2c1,0000000..f4003ac
mode 100644,000000..100644
--- a/apps/activity/lib/search.php
+++ b/apps/activity/lib/search.php
@@@ -1,54 -1,0 +1,54 @@@
 +<?php
 +
 +/**
 + * ownCloud - Activities App
 + *
 + * @author Frank Karlitschek
 + * @copyright 2013 Frank Karlitschek frank at 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 Lesser General Public
 + * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +
 +
 +namespace OCA\Activity;
 +
 +
 +/**
 +* @brief Class for provide search results for the system search
 +*/
 +class Search extends \OC_Search_Provider{
 +	
 +	/**
 +	* @brief Search in the activities and return search results
 +	* @param $query
 +	* @return search results
 +	*/
 +	function search($query){
 +
 +		$data = Data::search($query, 100);
 +
 +		$results = array();
 +		foreach($data as $d){
 +			$file = $d['file'];
 +			$results[] = new \OC_Search_Result(
 +				basename($file),
 +				$d['subject'].' ('.\OCP\Util::formatDate($d['timestamp']).')',
- 				\OC_Helper::linkTo( 'activity', 'index.php' ), 'Activity');
++				\OC_Helper::linkTo( 'activity', 'index.php' ), 'Activity', dirname($file));
 +		}
 +
 +		return $results;
 +	}
 +
 +}
diff --cc apps/calendar/lib/export.php
index 9797498,0000000..0db9e5b
mode 100644,000000..100644
--- a/apps/calendar/lib/export.php
+++ b/apps/calendar/lib/export.php
@@@ -1,115 -1,0 +1,105 @@@
 +<?php
 +/**
 + * Copyright (c) 2012 Georg Ehrke <ownclouddev at georgswebsite.de>
 + * This file is licensed under the Affero General Public License version 3 or
 + * later.
 + * See the COPYING-README file.
 + */
 +/**
 + * This class does export and converts all times to UTC
 + */
 +class OC_Calendar_Export{
 +	/**
 +	 * @brief Use one of these constants as second parameter if you call OC_Calendar_Export::export()
 +	 */
 +	const CALENDAR = 'calendar';
 +	const EVENT = 'event';
 +
 +	/**
 +	 * @brief export a calendar or an event
 +	 * @param integer $id id of calendar / event
 +	 * @param string $type use OC_Calendar_Export constants
 +	 * @return string
 +	 */
 +	public static function export($id, $type) {
 +		if($type == self::EVENT) {
 +			$return = self::event($id);
 +		}else{
 +			$return = self::calendar($id);
 +		}
 +		return self::fixLineBreaks($return);
 +	}
 +
 +	/**
 +	 * @brief exports a calendar and convert all times to UTC
 +	 * @param integer $id id of the calendar
 +	 * @return string
 +	 */
 +	private static function calendar($id) {
 +		$events = OC_Calendar_Object::all($id);
 +		$calendar = OC_Calendar_Calendar::find($id);
 +		$return = "BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:ownCloud Calendar " . OCP\App::getAppVersion('calendar') . "\nX-WR-CALNAME:" . $calendar['displayname'] . "\n";
 +		foreach($events as $event) {
 +			$return .= self::generateEvent($event);
 +		}
 +		$return .= "END:VCALENDAR";
 +		return $return;
 +	}
 +
 +	/**
 +	 * @brief exports an event and convert all times to UTC
 +	 * @param integer $id id of the event
 +	 * @return string
 +	 */
 +	private static function event($id) {
 +		$event = OC_Calendar_Object::find($id);
 +		$return = "BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:ownCloud Calendar " . OCP\App::getAppVersion('calendar') . "\nX-WR-CALNAME:" . $event['summary'] . "\n";
 +		$return .= self::generateEvent($event);
 +		$return .= "END:VCALENDAR";
 +		return $return;
 +	 }
 +
 +	 /**
 +	  * @brief generates the VEVENT/VTODO/VJOURNAL with UTC dates
 +	  * @param array $event
 +	  * @return string
 +	  */
 +	 private static function generateEvent($event) {
 +	 	$object = OC_VObject::parse($event['calendardata']);
 +		if(!$object){
 +			return false;
 +		}
 +
 +		$sharedAccessClassPermissions = OC_Calendar_Object::getAccessClassPermissions($object);
 +		if(OC_Calendar_Object::getowner($event['id']) !== OCP\User::getUser()){
 +			if (!($sharedAccessClassPermissions & OCP\PERMISSION_READ)) {
 +				return '';
 +			}
 +		}
 +		$object = OC_Calendar_Object::cleanByAccessClass($event['id'], $object);
 +
 +		if($object->VEVENT){
- 			$dtstart = $object->VEVENT->DTSTART;
- 			$start_dt = $dtstart->getDateTime();
- 			$dtend = OC_Calendar_Object::getDTEndFromVEvent($object->VEVENT);
- 			$end_dt = $dtend->getDateTime();
- 			if($dtstart->getDateType() !== Sabre\VObject\Property\DateTime::DATE) {
- 				$start_dt->setTimezone(new DateTimeZone('UTC'));
- 				$end_dt->setTimezone(new DateTimeZone('UTC'));
- 				$object->VEVENT->setDateTime('DTSTART', $start_dt, Sabre\VObject\Property\DateTime::UTC);
- 				$object->VEVENT->setDateTime('DTEND', $end_dt, Sabre\VObject\Property\DateTime::UTC);
- 			}
 +			return $object->VEVENT->serialize();
 +		}
 +		if($object->VTODO){
 +			return $object->VTODO->serialize();
 +		}
 +		if($object->VJOURNAL){
 +			return $object->VJOURNAL->serialize();
 +		}
 +		return '';
 +	}
 +
 +	/**
 +	 * @brief fixes new line breaks
 +	 * (fixes problems with Apple iCal)
 +	 * @param string $string to fix
 +	 * @return string
 +	 */
 +	private static function fixLineBreaks($string) {
 +		$string = str_replace("\r\n", "\n", $string);
 +		$string = str_replace("\r", "\n", $string);
 +		$string = str_replace("\n", "\r\n", $string);
 +		return $string;
 +	}
 +}
diff --cc apps/contacts/lib/backend/database.php
index a890169,0000000..1283cdc
mode 100644,000000..100644
--- a/apps/contacts/lib/backend/database.php
+++ b/apps/contacts/lib/backend/database.php
@@@ -1,812 -1,0 +1,812 @@@
 +<?php
 +/**
 + * ownCloud - Database backend for Contacts
 + *
 + * @author Thomas Tanghus
 + * @copyright 2013 Thomas Tanghus (thomas at 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/>.
 + *
 + */
 +
 +namespace OCA\Contacts\Backend;
 +
 +use OCA\Contacts\Contact,
 +	OCA\Contacts\VObject\VCard,
 +	OCA\Contacts\Utils\Properties,
 +	Sabre\VObject\Reader;
 +
 +/**
 + * Subclass this class for Cantacts backends
 + */
 +
 +class Database extends AbstractBackend {
 +
 +	public $name = 'local';
 +	static private $preparedQueries = array();
 +
 +	/**
 +	* Sets up the backend
 +	*
 +	* @param string $addressBooksTableName
 +	* @param string $cardsTableName
 +	*/
 +	public function __construct(
 +		$userid = null,
 +		$options = array(
 +			'addressBooksTableName' => '*PREFIX*contacts_addressbooks',
 +			'cardsTableName' => '*PREFIX*contacts_cards',
 +			'indexTableName' => '*PREFIX*contacts_cards_properties'
 +		)
 +	) {
 +		$this->userid = $userid ? $userid : \OCP\User::getUser();
 +		$this->addressBooksTableName = $options['addressBooksTableName'];
 +		$this->cardsTableName = $options['cardsTableName'];
 +		$this->indexTableName = $options['indexTableName'];
 +		$this->addressbooks = array();
 +	}
 +
 +	/**
 +	 * Returns the list of addressbooks for a specific user.
 +	 *
 +	 * @see AbstractBackend::getAddressBooksForUser
 +	 * @return array
 +	 */
 +	public function getAddressBooksForUser(array $options = array()) {
 +
 +		try {
 +			if(!isset(self::$preparedQueries['addressbooksforuser'])) {
 +				$sql = 'SELECT `id`, `displayname`, `description`, `ctag` AS `lastmodified`, `userid` AS `owner`, `uri` FROM `'
 +					. $this->addressBooksTableName
 +					. '` WHERE `userid` = ? ORDER BY `displayname`';
 +				self::$preparedQueries['addressbooksforuser'] = \OCP\DB::prepare($sql);
 +			}
 +			$result = self::$preparedQueries['addressbooksforuser']->execute(array($this->userid));
 +			if (\OCP\DB::isError($result)) {
 +				\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: ' . \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
 +				return $this->addressbooks;
 +			}
 +		} catch(\Exception $e) {
 +			\OCP\Util::writeLog('contacts', __METHOD__.' exception: ' . $e->getMessage(), \OCP\Util::ERROR);
 +			return $this->addressbooks;
 +		}
 +
 +		while($row = $result->fetchRow()) {
 +			$row['permissions'] = \OCP\PERMISSION_ALL;
 +			$this->addressbooks[$row['id']] = $row;
 +		}
 +		return $this->addressbooks;
 +	}
 +
 +	public function getAddressBook($addressbookid, array $options = array()) {
- 		//\OCP\Util::writeLog('contacts', __METHOD__.' id: '
- 		//	. $addressbookid, \OCP\Util::DEBUG);
++		\OCP\Util::writeLog('contacts', __METHOD__.' id: ' . $addressbookid, \OCP\Util::DEBUG);
++		$owner = isset($options['shared_by']) ? $options['shared_by'] : $this->userid;
 +		if($this->addressbooks && isset($this->addressbooks[$addressbookid])) {
 +			//print(__METHOD__ . ' ' . __LINE__ .' addressBookInfo: ' . print_r($this->addressbooks[$addressbookid], true));
 +			return $this->addressbooks[$addressbookid];
 +		}
 +		// Hmm, not found. Lets query the db.
 +		try {
 +			$query = 'SELECT `id`, `displayname`, `description`, `userid` AS `owner`, `ctag` AS `lastmodified`, `uri` FROM `'
 +				. $this->addressBooksTableName
 +				. '` WHERE `id` = ? AND `userid` = ?';
 +			if(!isset(self::$preparedQueries['getaddressbook'])) {
 +				self::$preparedQueries['getaddressbook'] = \OCP\DB::prepare($query);
 +			}
- 			$result = self::$preparedQueries['getaddressbook']->execute(array($addressbookid, $this->userid));
++			$result = self::$preparedQueries['getaddressbook']->execute(array($addressbookid, $owner));
 +			if (\OCP\DB::isError($result)) {
 +				\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: '
 +					. \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
 +				return null;
 +			}
 +			if((int)$result->numRows() === 0) {
 +				return null;
 +			}
 +			$row = $result->fetchRow();
 +			$row['permissions'] = \OCP\PERMISSION_ALL;
 +			$row['backend'] = $this->name;
 +			$this->addressbooks[$addressbookid] = $row;
 +			return $row;
 +		} catch(\Exception $e) {
 +			\OCP\Util::writeLog('contacts', __METHOD__.' exception: '
 +				. $e->getMessage(), \OCP\Util::ERROR);
 +			return null;
 +		}
 +		return null;
 +	}
 +
 +	public function hasAddressBook($addressbookid, array $options = array()) {
 +		// First check if it's already cached
 +		if($this->addressbooks && isset($this->addressbooks[$addressbookid])) {
 +			return true;
 +		}
 +		return count($this->getAddressBook($addressbookid)) > 0;
 +	}
 +
 +	/**
 +	 * Updates an addressbook's properties
 +	 *
 +	 * @param string $addressbookid
 +	 * @param array $changes
 +	 * @return bool
 +	 */
 +	public function updateAddressBook($addressbookid, array $changes, array $options = array()) {
 +		if(count($changes) === 0) {
 +			return false;
 +		}
 +
 +		$query = 'UPDATE `' . $this->addressBooksTableName . '` SET ';
 +
 +		$updates = array();
 +
 +		if(isset($changes['displayname'])) {
 +			$query .= '`displayname` = ?, ';
 +			$updates[] = $changes['displayname'];
 +			if($this->addressbooks && isset($this->addressbooks[$addressbookid])) {
 +				$this->addressbooks[$addressbookid]['displayname'] = $changes['displayname'];
 +			}
 +		}
 +
 +		if(isset($changes['description'])) {
 +			$query .= '`description` = ?, ';
 +			$updates[] = $changes['description'];
 +			if($this->addressbooks && isset($this->addressbooks[$addressbookid])) {
 +				$this->addressbooks[$addressbookid]['description'] = $changes['description'];
 +			}
 +		}
 +
 +		$query .= '`ctag` = ? + 1 WHERE `id` = ?';
 +		$updates[] = time();
 +		$updates[] = $addressbookid;
 +
 +		try {
 +			$stmt = \OCP\DB::prepare($query);
 +			$result = $stmt->execute($updates);
 +			if (\OCP\DB::isError($result)) {
 +				\OCP\Util::writeLog('contacts',
 +					__METHOD__. 'DB error: '
 +					. \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
 +				return false;
 +			}
 +		} catch(\Exception $e) {
 +			\OCP\Util::writeLog('contacts',
 +				__METHOD__ . ', exception: '
 +				. $e->getMessage(), \OCP\Util::ERROR);
 +			return false;
 +		}
 +
 +		return true;
 +	}
 +
 +	/**
 +	 * Creates a new address book
 +	 *
 +	 * Supported properties are 'displayname', 'description' and 'uri'.
 +	 * 'uri' is supported to allow to add from CardDAV requests, and MUST
 +	 * be used for the 'uri' database field if present.
 +	 * 'displayname' MUST be present.
 +	 *
 +	 * @param array $properties
 +	 * @param array $options - Optional (backend specific options)
 +	 * @return string|false The ID if the newly created AddressBook or false on error.
 +	 */
 +	public function createAddressBook(array $properties, array $options = array()) {
 +
 +		if(count($properties) === 0 || !isset($properties['displayname'])) {
 +			return false;
 +		}
 +
 +		$query = 'INSERT INTO `' . $this->addressBooksTableName . '` '
 +			. '(`userid`,`displayname`,`uri`,`description`,`ctag`) VALUES(?,?,?,?,?)';
 +
 +		$updates = array($this->userid, $properties['displayname']);
 +		$updates[] = isset($properties['uri'])
 +			? $properties['uri']
 +			: $this->createAddressBookURI($properties['displayname']);
 +		$updates[] = isset($properties['description']) ? $properties['description'] : '';
 +		$ctag = time();
 +		$updates[] = $ctag;
 +
 +		try {
 +			if(!isset(self::$preparedQueries['createaddressbook'])) {
 +				self::$preparedQueries['createaddressbook'] = \OCP\DB::prepare($query);
 +			}
 +			$result = self::$preparedQueries['createaddressbook']->execute($updates);
 +			if (\OCP\DB::isError($result)) {
 +				\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: ' . \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
 +				return false;
 +			}
 +		} catch(\Exception $e) {
 +			\OCP\Util::writeLog('contacts', __METHOD__ . ', exception: ' . $e->getMessage(), \OCP\Util::ERROR);
 +			return false;
 +		}
 +
 +		$newid = \OCP\DB::insertid($this->addressBooksTableName);
 +		if($this->addressbooks) {
 +			$updates['id'] = $newid;
 +			$updates['ctag'] = $ctag;
 +			$updates['lastmodified'] = $ctag;
 +			$updates['permissions'] = \OCP\PERMISSION_ALL;
 +			$this->addressbooks[$newid] = $updates;
 +		}
 +		return $newid;
 +	}
 +
 +	/**
 +	 * Deletes an entire addressbook and all its contents
 +	 *
 +	 * NOTE: For efficience this method bypasses the cleanup hooks and deletes
 +	 * property indexes and category/group relations by itself.
 +	 *
 +	 * @param string $addressbookid
 +	 * @param array $options - Optional (backend specific options)
 +	 * @return bool
 +	 */
 +	public function deleteAddressBook($addressbookid, array $options = array()) {
 +
 +		// Get all contact ids for this address book
 +		$ids = array();
 +		$result = null;
 +		$stmt = \OCP\DB::prepare('SELECT `id` FROM `' . $this->cardsTableName . '`'
 +					. ' WHERE `addressbookid` = ?');
 +		try {
 +			$result = $stmt->execute(array($addressbookid));
 +			if (\OCP\DB::isError($result)) {
 +				\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: '
 +					. \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
 +				return false;
 +			}
 +		} catch(\Exception $e) {
 +			\OCP\Util::writeLog('contacts', __METHOD__.
 +				', exception: ' . $e->getMessage(), \OCP\Util::ERROR);
 +			return false;
 +		}
 +
 +		if(!is_null($result)) {
 +			while($id = $result->fetchOne()) {
 +				$ids[] = $id;
 +			}
 +		}
 +
 +		\OCP\Util::emitHook('OCA\Contacts', 'pre_deleteAddressBook',
 +			array('addressbookid' => $addressbookid, 'contactids' => $ids)
 +		);
 +
 +		// Delete contacts in address book.
 +		if(!isset(self::$preparedQueries['deleteaddressbookcontacts'])) {
 +			self::$preparedQueries['deleteaddressbookcontacts'] =
 +				\OCP\DB::prepare('DELETE FROM `' . $this->cardsTableName
 +					. '` WHERE `addressbookid` = ?');
 +		}
 +		try {
 +			self::$preparedQueries['deleteaddressbookcontacts']
 +				->execute(array($addressbookid));
 +		} catch(\Exception $e) {
 +			\OCP\Util::writeLog('contacts', __METHOD__.
 +				', exception: ' . $e->getMessage(), \OCP\Util::ERROR);
 +			return false;
 +		}
 +
 +		// Delete the address book.
 +		if(!isset(self::$preparedQueries['deleteaddressbook'])) {
 +			self::$preparedQueries['deleteaddressbook'] =
 +				\OCP\DB::prepare('DELETE FROM `'
 +					. $this->addressBooksTableName . '` WHERE `id` = ?');
 +		}
 +		try {
 +			self::$preparedQueries['deleteaddressbook']
 +				->execute(array($addressbookid));
 +		} catch(\Exception $e) {
 +			\OCP\Util::writeLog('contacts', __METHOD__.
 +				', exception: ' . $e->getMessage(), \OCP\Util::ERROR);
 +			return false;
 +		}
 +
 +		if($this->addressbooks && isset($this->addressbooks[$addressbookid])) {
 +			unset($this->addressbooks[$addressbookid]);
 +		}
 +
 +		return true;
 +	}
 +
 +	/**
 +	 * @brief Updates ctag for addressbook
 +	 * @param integer $id
 +	 * @return boolean
 +	 */
 +	public function setModifiedAddressBook($id) {
 +		$query = 'UPDATE `' . $this->addressBooksTableName
 +			. '` SET `ctag` = ? + 1 WHERE `id` = ?';
 +		if(!isset(self::$preparedQueries['touchaddressbook'])) {
 +			self::$preparedQueries['touchaddressbook'] = \OCP\DB::prepare($query);
 +		}
 +		$ctag = time();
 +		self::$preparedQueries['touchaddressbook']->execute(array($ctag, $id));
 +
 +		return true;
 +	}
 +
 +	public function lastModifiedAddressBook($addressbookid) {
 +		if($this->addressbooks && isset($this->addressbooks[$addressbookid])) {
 +			return $this->addressbooks[$addressbookid]['lastmodified'];
 +		}
 +		$addressBook = $this->getAddressBook($addressbookid);
 +		return $addressBook ? $addressBook['lastmodified'] : null;
 +	}
 +
 +	/**
 +	 * Returns the number of contacts in a specific address book.
 +	 *
 +	 * @param string $addressbookid
 +	 * @param bool $omitdata Don't fetch the entire carddata or vcard.
 +	 * @return array
 +	 */
 +	public function numContacts($addressbookid) {
 +		$query = 'SELECT COUNT(*) AS `count` FROM `' . $this->cardsTableName . '` WHERE '
 +			. '`addressbookid` = ?';
 +
 +		if(!isset(self::$preparedQueries['count'])) {
 +			self::$preparedQueries['count'] = \OCP\DB::prepare($query);
 +		}
 +		$result = self::$preparedQueries['count']->execute(array($addressbookid));
 +		if (\OCP\DB::isError($result)) {
 +			\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: ' . \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
 +			return null;
 +		}
 +		return (int)$result->fetchOne();
 +	}
 +
 +	/**
 +	 * Returns all contacts for a specific addressbook id.
 +	 *
 +	 * @param string $addressbookid
 +	 * @param array $options - Optional (backend specific options)
 +	 * @param bool $omitdata Don't fetch the entire carddata or vcard.
 +	 * @return array
 +	 */
 +	public function getContacts($addressbookid, array $options = array() ) {
 +		//\OCP\Util::writeLog('contacts', __METHOD__.' addressbookid: ' . $addressbookid, \OCP\Util::DEBUG);
 +		$cards = array();
 +		try {
 +			$omitdata = isset($options['omitdata']) ? $options['omitdata'] : false;
 +			$qfields = $omitdata ? '`id`, `fullname` AS `displayname`' : '*';
 +			$query = 'SELECT ' . $qfields . ' FROM `' . $this->cardsTableName
 +				. '` WHERE `addressbookid` = ? ORDER BY `fullname`';
 +			$stmt = \OCP\DB::prepare(
 +				$query,
 +				isset($options['limit']) ? $options['limit'] : null,
 +				isset($options['offset']) ? $options['offset'] : null
 +			);
 +			$result = $stmt->execute(array($addressbookid));
 +			if (\OCP\DB::isError($result)) {
 +				\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: ' . \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
 +				return $cards;
 +			}
 +		} catch(\Exception $e) {
 +			\OCP\Util::writeLog('contacts', __METHOD__.', exception: '.$e->getMessage(), \OCP\Util::ERROR);
 +			return $cards;
 +		}
 +
 +		if(!is_null($result)) {
 +			while($row = $result->fetchRow()) {
 +				$row['permissions'] = \OCP\PERMISSION_ALL;
 +				$cards[] = $row;
 +			}
 +		}
 +
 +		return $cards;
 +	}
 +
 +	/**
 +	 * Returns a specific contact.
 +	 *
 +	 * The $id for Database and Shared backends can be an array containing
 +	 * either 'id' or 'uri' to be able to play seamlessly with the
 +	 * CardDAV backend.
 +	 * FIXME: $addressbookid isn't used in the query, so there's no access control.
 +	 * 	OTOH the groups backend - OC_VCategories - doesn't no about parent collections
 +	 * 	only object IDs. Hmm.
 +	 * 	I could make a hack and add an optional, not documented 'nostrict' argument
 +	 * 	so it doesn't look for addressbookid.
 +	 *
 +	 * @param string $addressbookid
 +	 * @param mixed $id Contact ID
 +	 * @param array $options - Optional (backend specific options)
 +	 * @return array|null
 +	 */
 +	public function getContact($addressbookid, $id, array $options = array()) {
 +		//\OCP\Util::writeLog('contacts', __METHOD__.' identifier: ' . $addressbookid . ' ' . $id['uri'], \OCP\Util::DEBUG);
 +
 +		$noCollection = isset($options['noCollection']) ? $options['noCollection'] : false;
 +
 +		$where_query = '`id` = ?';
 +		if(is_array($id)) {
 +			$where_query = '';
 +			if(isset($id['id'])) {
 +				$id = $id['id'];
 +			} elseif(isset($id['uri'])) {
 +				$where_query = '`uri` = ?';
 +				$id = $id['uri'];
 +			} else {
 +				throw new \Exception(
 +					__METHOD__ . ' If second argument is an array, either \'id\' or \'uri\' has to be set.'
 +				);
 +				return null;
 +			}
 +		}
 +		$ids = array($id);
 +
 +		if(!$noCollection) {
 +			$where_query .= ' AND `addressbookid` = ?';
 +			$ids[] = $addressbookid;
 +		}
 +
 +		try {
 +			$query =  'SELECT `id`, `uri`, `carddata`, `lastmodified`, `addressbookid` AS `parent`, `fullname` AS `displayname` FROM `'
 +				. $this->cardsTableName . '` WHERE ' . $where_query;
 +			$stmt = \OCP\DB::prepare($query);
 +			$result = $stmt->execute($ids);
 +			if (\OCP\DB::isError($result)) {
 +				\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: ' . \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
 +				return null;
 +			}
 +		} catch(\Exception $e) {
 +			\OCP\Util::writeLog('contacts', __METHOD__.', exception: '.$e->getMessage(), \OCP\Util::ERROR);
 +			\OCP\Util::writeLog('contacts', __METHOD__.', id: '. $id, \OCP\Util::DEBUG);
 +			return null;
 +		}
 +
 +		$row = $result->fetchRow();
 +		if(!$row) {
 +			\OCP\Util::writeLog('contacts', __METHOD__.', Not found, id: '. $id, \OCP\Util::DEBUG);
 +			return null;
 +		}
 +		$row['permissions'] = \OCP\PERMISSION_ALL;
 +		return $row;
 +	}
 +
 +	public function hasContact($addressbookid, $id) {
 +		return $this->getContact($addressbookid, $id) !== false;
 +	}
 +
 +	/**
 +	 * Creates a new contact
 +	 *
 +	 * In the Database and Shared backends contact be either a Contact object or a string
 +	 * with carddata to be able to play seamlessly with the CardDAV backend.
 +	 * If this method is called by the CardDAV backend, the carddata is already validated.
 +	 * NOTE: It's assumed that this method is called either from the CardDAV backend, the
 +	 * import script, or from the ownCloud web UI in which case either the uri parameter is
 +	 * set, or the contact has a UID. If neither is set, it will fail.
 +	 *
 +	 * @param string $addressbookid
 +	 * @param VCard|string $contact
 +	 * @param array $options - Optional (backend specific options)
 +	 * @return string|bool The identifier for the new contact or false on error.
 +	 */
 +	public function createContact($addressbookid, $contact, array $options = array()) {
 +
 +		$qname = 'createcontact';
 +		$uri = isset($options['uri']) ? $options['uri'] : null;
 +
 +		if(!$contact instanceof VCard) {
 +			try {
 +				$contact = Reader::read($contact);
 +			} catch(\Exception $e) {
 +				\OCP\Util::writeLog('contacts', __METHOD__.', exception: '.$e->getMessage(), \OCP\Util::ERROR);
 +				return false;
 +			}
 +		}
 +
 +		try {
 +			$contact->validate(VCard::REPAIR|VCard::UPGRADE);
 +		} catch (\Exception $e) {
 +			OCP\Util::writeLog('contacts', __METHOD__ . ' ' .
 +				'Error validating vcard: ' . $e->getMessage(), \OCP\Util::ERROR);
 +			return false;
 +		}
 +
 +		$uri = is_null($uri) ? $this->uniqueURI($addressbookid, $contact->UID . '.vcf') : $uri;
 +		$now = new \DateTime;
 +		$contact->REV = $now->format(\DateTime::W3C);
 +
 +		$appinfo = \OCP\App::getAppInfo('contacts');
 +		$appversion = \OCP\App::getAppVersion('contacts');
 +		$prodid = '-//ownCloud//NONSGML '.$appinfo['name'].' '.$appversion.'//EN';
 +		$contact->PRODID = $prodid;
 +
 +		$data = $contact->serialize();
 +		if(!isset(self::$preparedQueries[$qname])) {
 +		self::$preparedQueries[$qname] = \OCP\DB::prepare('INSERT INTO `'
 +			. $this->cardsTableName
 +			. '` (`addressbookid`,`fullname`,`carddata`,`uri`,`lastmodified`) VALUES(?,?,?,?,?)' );
 +		}
 +		try {
 +			$result = self::$preparedQueries[$qname]
 +				->execute(
 +					array(
 +						$addressbookid,
 +						(string)$contact->FN,
 +						$contact->serialize(),
 +						$uri,
 +						time()
 +					)
 +				);
 +			if (\OCP\DB::isError($result)) {
 +				\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: ' . \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
 +				return false;
 +			}
 +		} catch(\Exception $e) {
 +			\OCP\Util::writeLog('contacts', __METHOD__.', exception: '.$e->getMessage(), \OCP\Util::ERROR);
 +			return false;
 +		}
 +		$newid = \OCP\DB::insertid($this->cardsTableName);
 +
 +		$this->setModifiedAddressBook($addressbookid);
 +		\OCP\Util::emitHook('OCA\Contacts', 'post_createContact',
 +			array('id' => $newid, 'parent' => $addressbookid, 'backend' => $this->name, 'contact' => $contact)
 +		);
 +		return (string)$newid;
 +	}
 +
 +	/**
 +	 * Updates a contact
 +	 *
 +	 * @param string $addressbookid
 +	 * @param mixed $id Contact ID
 +	 * @param VCard|string $contact
 +	 * @param array $options - Optional (backend specific options)
 +	 * @see getContact
 +	 * @return bool
 +	 */
 +	public function updateContact($addressbookid, $id, $contact, array $options = array()) {
 +		$noCollection = isset($options['noCollection']) ? $options['noCollection'] : false;
 +		$isBatch = isset($options['isBatch']) ? $options['isBatch'] : false;
 +		$qname = 'updatecontact';
 +
 +		$updateRevision = true;
 +		$isCardDAV = false;
 +		if(!$contact instanceof VCard) {
 +			try {
 +				$contact = Reader::read($contact);
 +			} catch(\Exception $e) {
 +				\OCP\Util::writeLog('contacts', __METHOD__.', exception: '.$e->getMessage(), \OCP\Util::ERROR);
 +				return false;
 +			}
 +		}
 +
 +		if(is_array($id)) {
 +			$where_query = '';
 +			if(isset($id['id'])) {
 +				$id = $id['id'];
 +			} elseif(isset($id['uri'])) {
 +				$updateRevision = false;
 +				$isCardDAV = true;
 +				$id = $this->getIdFromUri($id['uri']);
 +				if(is_null($id)) {
 +					\OCP\Util::writeLog('contacts', __METHOD__ . ' Couldn\'t find contact', \OCP\Util::ERROR);
 +					return false;
 +				}
 +			} else {
 +				throw new \Exception(
 +					__METHOD__ . ' If second argument is an array, either \'id\' or \'uri\' has to be set.'
 +				);
 +			}
 +		}
 +
 +		if($updateRevision || !isset($contact->REV)) {
 +			$now = new \DateTime;
 +			$contact->REV = $now->format(\DateTime::W3C);
 +		}
 +
 +		$data = $contact->serialize();
 +
 +		if($noCollection) {
 +			$me = $this->getContact(null, $id, $options);
 +			$addressbookid = $me['parent'];
 +		}
 +
 +		$updates = array($contact->FN, $data, time(), $id, $addressbookid);
 +
 +		$query = 'UPDATE `' . $this->cardsTableName
 +				. '` SET `fullname` = ?,`carddata` = ?, `lastmodified` = ? WHERE `id` = ? AND `addressbookid` = ?';
 +		if(!isset(self::$preparedQueries[$qname])) {
 +			self::$preparedQueries[$qname] = \OCP\DB::prepare($query);
 +		}
 +		try {
 +			$result = self::$preparedQueries[$qname]->execute($updates);
 +			if (\OCP\DB::isError($result)) {
 +				\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: ' . \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
 +				return false;
 +			}
 +		} catch(\Exception $e) {
 +			\OCP\Util::writeLog('contacts', __METHOD__.', exception: '
 +				. $e->getMessage(), \OCP\Util::ERROR);
 +			\OCP\Util::writeLog('contacts', __METHOD__.', id' . $id, \OCP\Util::DEBUG);
 +			return false;
 +		}
 +
 +		$this->setModifiedAddressBook($addressbookid);
 +		if(!$isBatch) {
 +			\OCP\Util::emitHook('OCA\Contacts', 'post_updateContact',
 +				array(
 +					'backend' => $this->name,
 +					'addressBookId' => $addressbookid,
 +					'contactId' => $id,
 +					'contact' => $contact,
 +					'carddav' => $isCardDAV
 +				)
 +			);
 +		}
 +		return true;
 +	}
 +
 +	/**
 +	 * Deletes a contact
 +	 *
 +	 * @param string $addressbookid
 +	 * @param string $id
 +	 * @param array $options - Optional (backend specific options)
 +	 * @see getContact
 +	 * @return bool
 +	 */
 +	public function deleteContact($addressbookid, $id, array $options = array()) {
 +		// TODO: pass the uri in $options instead.
 +
 +		$qname = 'deletecontact';
 +		$noCollection = isset($options['noCollection']) ? $options['noCollection'] : false;
 +		$isBatch = isset($options['isBatch']) ? $options['isBatch'] : false;
 +
 +		if(is_array($id)) {
 +			if(isset($id['id'])) {
 +				$id = $id['id'];
 +			} elseif(isset($id['uri'])) {
 +				$id = $this->getIdFromUri($id['uri']);
 +				if(is_null($id)) {
 +					\OCP\Util::writeLog('contacts', __METHOD__ . ' Couldn\'t find contact', \OCP\Util::ERROR);
 +					return false;
 +				}
 +			} else {
 +				throw new Exception(
 +					__METHOD__ . ' If second argument is an array, either \'id\' or \'uri\' has to be set.'
 +				);
 +			}
 +		}
 +
 +		if(!$isBatch) {
 +			\OCP\Util::emitHook('OCA\Contacts', 'pre_deleteContact',
 +				array('id' => $id)
 +			);
 +		}
 +
 +		if($noCollection) {
 +			$me = $this->getContact(null, $id, $options);
 +			$addressbookid = $me['parent'];
 +		}
 +
 +		if(!isset(self::$preparedQueries[$qname])) {
 +			self::$preparedQueries[$qname] = \OCP\DB::prepare('DELETE FROM `'
 +				. $this->cardsTableName
 +				. '` WHERE `id` = ? AND `addressbookid` = ?');
 +		}
 +		\OCP\Util::writeLog('contacts', __METHOD__ . ' updates: ' . $id . '/' . $addressbookid, \OCP\Util::DEBUG);
 +		try {
 +			$result = self::$preparedQueries[$qname]->execute(array($id, $addressbookid));
 +			if (\OCP\DB::isError($result)) {
 +				\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: '
 +					. \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
 +				return false;
 +			}
 +		} catch(\Exception $e) {
 +			\OCP\Util::writeLog('contacts', __METHOD__.
 +				', exception: ' . $e->getMessage(), \OCP\Util::ERROR);
 +			\OCP\Util::writeLog('contacts', __METHOD__.', id: '
 +				. $id, \OCP\Util::DEBUG);
 +			return false;
 +		}
 +		$this->setModifiedAddressBook($addressbookid);
 +		return true;
 +	}
 +
 +	/**
 +	 * @brief Get the last modification time for a contact.
 +	 *
 +	 * Must return a UNIX time stamp or null if the backend
 +	 * doesn't support it.
 +	 *
 +	 * @param string $addressbookid
 +	 * @param mixed $id
 +	 * @returns int | null
 +	 */
 +	public function lastModifiedContact($addressbookid, $id) {
 +		$contact = $this->getContact($addressbookid, $id);
 +		return ($contact ? $contact['lastmodified'] : null);
 +	}
 +
 +	/**
 +	 * @brief Get the contact id from the uri.
 +	 *
 +	 * @param mixed $id
 +	 * @returns int | null
 +	 */
 +	public function getIdFromUri($uri) {
 +		$query =  'SELECT `id` FROM `'. $this->cardsTableName . '` WHERE `uri` = ?';
 +		$stmt = \OCP\DB::prepare($query);
 +		$result = $stmt->execute(array($uri));
 +		if (\OCP\DB::isError($result)) {
 +			\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: ' . \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
 +			return null;
 +		}
 +		$one = $result->fetchOne();
 +		if(!$one) {
 +			\OCP\Util::writeLog('contacts', __METHOD__.', Not found, uri: '. $uri, \OCP\Util::DEBUG);
 +			return null;
 +		}
 +		return $one;
 +	}
 +
 +	private function createAddressBookURI($displayname, $userid = null) {
 +		$userid = $userid ? $userid : \OCP\User::getUser();
 +		$name = str_replace(' ', '_', strtolower($displayname));
 +		try {
 +			$stmt = \OCP\DB::prepare('SELECT `uri` FROM `' . $this->addressBooksTableName . '` WHERE `userid` = ? ');
 +			$result = $stmt->execute(array($userid));
 +			if (\OCP\DB::isError($result)) {
 +				\OCP\Util::writeLog('contacts', __METHOD__. 'DB error: ' . \OC_DB::getErrorMessage($result), \OCP\Util::ERROR);
 +				return $name;
 +			}
 +		} catch(\Exception $e) {
 +			\OCP\Util::writeLog('contacts', __METHOD__ . ' exception: ' . $e->getMessage(), \OCP\Util::ERROR);
 +			return $name;
 +		}
 +		$uris = array();
 +		while($row = $result->fetchRow()) {
 +			$uris[] = $row['uri'];
 +		}
 +
 +		$newname = $name;
 +		$i = 1;
 +		while(in_array($newname, $uris)) {
 +			$newname = $name.$i;
 +			$i = $i + 1;
 +		}
 +		return $newname;
 +	}
 +
 +	/**
 +	* @brief Checks if a contact with the same URI already exist in the address book.
 +	* @param string $addressBookId Address book ID.
 +	* @param string $uri
 +	* @returns string Unique URI
 +	*/
 +	protected function uniqueURI($addressBookId, $uri) {
 +		$stmt = \OCP\DB::prepare( 'SELECT * FROM `' . $this->cardsTableName . '` WHERE `addressbookid` = ? AND `uri` = ?' );
 +
 +		$result = $stmt->execute(array($addressBookId, $uri));
 +
 +		if($result->numRows() > 0) {
 +			while(true) {
 +				$uri = Properties::generateUID() . '.vcf';
 +				$result = $stmt->execute(array($addressBookId, $uri));
 +				if($result->numRows() > 0) {
 +					continue;
 +				} else {
 +					return $uri;
 +				}
 +			}
 +		} else {
 +			return $uri;
 +		}
 +	}
 +}
diff --cc apps/contacts/lib/backend/shared.php
index 4896405,0000000..e4213b0
mode 100644,000000..100644
--- a/apps/contacts/lib/backend/shared.php
+++ b/apps/contacts/lib/backend/shared.php
@@@ -1,131 -1,0 +1,131 @@@
 +<?php
 +/**
 + * ownCloud - Backend for Shared contacts
 + *
 + * @author Thomas Tanghus
 + * @copyright 2013 Thomas Tanghus (thomas at 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/>.
 + *
 + */
 +
 +namespace OCA\Contacts\Backend;
 +
 +use OCA\Contacts;
 +
 +/**
 + * Subclass this class for Cantacts backends
 + */
 +
 +class Shared extends Database {
 +
 +	public $name = 'shared';
 +	public $addressbooks = array();
 +
 +	/**
 +	 * Returns the list of addressbooks for a specific user.
 +	 *
 +	 * @param string $principaluri
 +	 * @return array
 +	 */
 +	public function getAddressBooksForUser(array $options = array()) {
 +
 +		// workaround for https://github.com/owncloud/core/issues/2814
 +		$maybeSharedAddressBook = \OCP\Share::getItemsSharedWith(
 +			'addressbook',
 +			Contacts\Share\Addressbook::FORMAT_ADDRESSBOOKS
 +		);
- 		foreach($maybeSharedAddressBook as $sharedAddressbook) {
- 			if(isset($sharedAddressbook['id'])) {
- 				$this->addressbooks[] = $this->getAddressBook($sharedAddressbook['id']);
++
++		foreach ($maybeSharedAddressBook as $sharedAddressbook) {
++
++			if (isset($sharedAddressbook['id'])) {
++				$this->addressBooks[$sharedAddressbook['id']] = $sharedAddressbook;
++				$this->addressBooks[$sharedAddressbook['id']]['backend'] = $this->name;
 +			}
 +		}
 +
- 		foreach($this->addressbooks as &$addressBook) {
- 			$addressBook['backend'] = $this->name;
- 		}
- 		return $this->addressbooks;
++		return $this->addressBooks;
 +	}
 +
 +	/**
 +	 * Returns a specific address book.
 +	 *
 +	 * @param string $addressbookid
 +	 * @param mixed $id Contact ID
 +	 * @return mixed
 +	 */
 +	public function getAddressBook($addressbookid, array $options = array()) {
 +		$addressBook = \OCP\Share::getItemSharedWithBySource(
 +			'addressbook',
 +			$addressbookid,
 +			Contacts\Share\Addressbook::FORMAT_ADDRESSBOOKS
 +		);
 +		// Not sure if I'm doing it wrongly, or if its supposed to return
 +		// the info in an array?
 +		$addressBook = (isset($addressBook['permissions']) ? $addressBook : $addressBook[0]);
 +		$addressBook['backend'] = $this->name;
 +		return $addressBook;
 +	}
 +
 +	/**
 +	 * Returns all contacts for a specific addressbook id.
 +	 *
 +	 * @param string $addressbookid
 +	 * @param bool $omitdata Don't fetch the entire carddata or vcard.
 +	 * @return array
 +	 */
 +	public function getContacts($addressbookid, array $options = array()) {
 +
 +		$addressBook = $this->getAddressBook($addressbookid);
 +		if(!$addressBook) {
 +			throw new \Exception('Shared Address Book not found: ' . $addressbookid, 404);
 +		}
 +		$permissions = $addressBook['permissions'];
 +
 +		$cards = parent::getContacts($addressbookid, $options);
 +
 +		foreach($cards as &$card) {
 +			$card['permissions'] = $permissions;
 +		}
 +
 +		return $cards;
 +	}
 +
 +	/**
 +	 * Returns a specific contact.
 +	 *
 +	 * The $id for Database and Shared backends can be an array containing
 +	 * either 'id' or 'uri' to be able to play seamlessly with the
 +	 * CardDAV backend.
 +	 * @see \Database\getContact
 +	 *
 +	 * @param string $addressbookid
 +	 * @param mixed $id Contact ID
 +	 * @return array|false
 +	 */
 +	public function getContact($addressbookid, $id, array $options = array()) {
 +		$addressBook = $this->getAddressBook($addressbookid);
 +		if(!$addressBook) {
 +			throw new \Exception('Shared Address Book not found: ' . $addressbookid, 404);
 +		}
 +		$permissions = $addressBook['permissions'];
 +
 +		$card = parent::getContact($addressbookid, $id, $options);
 +		if(!$card) {
 +			throw new \Exception('Shared Contact not found: ' . implode(',', $id), 404);
 +		}
 +		$card['permissions'] = $permissions;
 +		return $card;
 +	}
 +}
diff --cc apps/contacts/lib/dispatcher.php
index a85432e,0000000..021256b
mode 100644,000000..100644
--- a/apps/contacts/lib/dispatcher.php
+++ b/apps/contacts/lib/dispatcher.php
@@@ -1,72 -1,0 +1,76 @@@
 +<?php
 +/**
 + * Copyright (c) 2013 Thomas Tanghus (thomas at tanghus.net)
 + * This file is licensed under the Affero General Public License version 3 or
 + * later.
 + * See the COPYING-README file.
 + */
 +
 +namespace OCA\Contacts;
 +
 +use OCP\AppFramework\App as MainApp,
 +	OCP\AppFramework\IAppContainer,
 +	OCA\Contacts\App,
 +	OCA\Contacts\Middleware\Http as HttpMiddleware,
 +	OCA\Contacts\Controller\PageController,
 +	OCA\Contacts\Controller\AddressBookController,
 +	OCA\Contacts\Controller\GroupController,
 +	OCA\Contacts\Controller\ContactController,
 +	OCA\Contacts\Controller\ContactPhotoController,
 +	OCA\Contacts\Controller\SettingsController,
 +	OCA\Contacts\Controller\ImportController,
 +	OCA\Contacts\Controller\ExportController;
 +
 +/**
 + * This class manages our app actions
 + *
 + * TODO: Merge with App
 + */
 +
 +class Dispatcher extends MainApp {
 +	/**
 +	* @var App
 +	*/
 +	protected $app;
 +
 +	public function __construct($params) {
 +		parent::__construct('contacts', $params);
 +		$this->container = $this->getContainer();
- 		$this->container->registerMiddleware(new HttpMiddleware($this->container));
 +		$this->app = new App($this->container->query('API')->getUserId());
 +		$this->registerServices();
++		$this->container->registerMiddleware('HttpMiddleware');
 +	}
 +
++
 +	public function registerServices() {
 +		$app = $this->app;
++		$this->container->registerService('HttpMiddleware', function(IAppContainer $container) use($app) {
++			return new HttpMiddleware($container);
++		});
 +		$this->container->registerService('PageController', function(IAppContainer $container) use($app) {
 +			return new PageController($container, $app);
 +		});
 +		$this->container->registerService('AddressBookController', function(IAppContainer $container) use($app) {
 +			return new AddressBookController($container, $app);
 +		});
 +		$this->container->registerService('GroupController', function(IAppContainer $container) use($app) {
 +			return new GroupController($container, $app);
 +		});
 +		$this->container->registerService('ContactController', function(IAppContainer $container) use($app) {
 +			return new ContactController($container, $app);
 +		});
 +		$this->container->registerService('ContactPhotoController', function(IAppContainer $container) use($app) {
 +			return new ContactPhotoController($container, $app);
 +		});
 +		$this->container->registerService('SettingsController', function(IAppContainer $container) use($app) {
 +			return new SettingsController($container, $app);
 +		});
 +		$this->container->registerService('ImportController', function(IAppContainer $container) use($app) {
 +			return new ImportController($container, $app);
 +		});
 +		$this->container->registerService('ExportController', function(IAppContainer $container) use($app) {
 +			return new ExportController($container, $app);
 +		});
 +	}
 +
 +}
diff --cc apps/contacts/lib/share/addressbook.php
index 6a5ddf0,0000000..0de637f
mode 100644,000000..100644
--- a/apps/contacts/lib/share/addressbook.php
+++ b/apps/contacts/lib/share/addressbook.php
@@@ -1,127 -1,0 +1,126 @@@
 +<?php
 +/**
 + * Copyright (c) 2012 Bart Visscher <bartv at thisnet.nl>
 + * This file is licensed under the Affero General Public License version 3 or
 + * later.
 + * See the COPYING-README file.
 + */
 +
 +namespace OCA\Contacts\Share;
 +use OCA\Contacts\App;
 +
 +class Addressbook implements \OCP\Share_Backend_Collection {
 +	const FORMAT_ADDRESSBOOKS = 1;
 +	const FORMAT_COLLECTION = 2;
 +
 +	/**
 +	 * @var \OCA\Contacts\App;
 +	 */
 +	public $app;
 +
 +	public function __construct() {
 +		$this->app = new App(\OCP\User::getUser());
 +	}
 +
 +	/**
 +	* @brief Get the source of the item to be stored in the database
 +	* @param string Item
 +	* @param string Owner of the item
 +	* @return mixed|array|false Source
 +	*
 +	* Return an array if the item is file dependent, the array needs two keys: 'item' and 'file'
 +	* Return false if the item does not exist for the user
 +	*
 +	* The formatItems() function will translate the source returned back into the item
 +	*/
 +	public function isValidSource($itemSource, $uidOwner) {
 +		$app = new App($uidOwner);
 +
 +		try {
 +			$app->getAddressBook('local', $itemSource);
 +		} catch(\Exception $e) {
 +			return false;
 +		}
 +		return true;
 +	}
 +
 +	/**
 +	* @brief Get a unique name of the item for the specified user
 +	* @param string Item
 +	* @param string|false User the item is being shared with
 +	* @param array|null List of similar item names already existing as shared items
 +	* @return string Target name
 +	*
 +	* This function needs to verify that the user does not already have an item with this name.
 +	* If it does generate a new name e.g. name_#
 +	*/
 +	public function generateTarget($itemSource, $shareWith, $exclude = null) {
 +		// Get app for the sharee
 +		$app = new App($shareWith);
 +		$backend = $app->getBackend('local');
 +
 +		// Get address book for the owner
 +		$addressBook = $this->app->getBackend('local')->getAddressBook($itemSource);
 +
 +		$userAddressBooks = array();
 +
 +		foreach($backend->getAddressBooksForUser() as $userAddressBook) {
 +			$userAddressBooks[] = $userAddressBook['displayname'];
 +		}
 +		$name = $addressBook['displayname'] . '(' . $addressBook['owner'] . ')';
 +		$suffix = '';
 +		while (in_array($name.$suffix, $userAddressBooks)) {
 +			$suffix++;
 +		}
 +
 +		$suffix = $suffix ? ' ' . $suffix : '';
 +		return $name.$suffix;
 +	}
 +
 +	/**
 +	* @brief Converts the shared item sources back into the item in the specified format
 +	* @param array Shared items
 +	* @param int Format
 +	* @return ?
 +	*
 +	* The items array is a 3-dimensional array with the item_source as the first key and the share id as the second key to an array with the share info.
 +	* The key/value pairs included in the share info depend on the function originally called:
 +	* If called by getItem(s)Shared: id, item_type, item, item_source, share_type, share_with, permissions, stime, file_source
 +	* If called by getItem(s)SharedWith: id, item_type, item, item_source, item_target, share_type, share_with, permissions, stime, file_source, file_target
 +	* This function allows the backend to control the output of shared items with custom formats.
 +	* It is only called through calls to the public getItem(s)Shared(With) functions.
 +	*/
 +	public function formatItems($items, $format, $parameters = null, $include = false) {
 +		//\OCP\Util::writeLog('contacts', __METHOD__
 +		//	. ' ' . $include . ' ' . print_r($items, true), \OCP\Util::DEBUG);
 +		$addressBooks = array();
 +		$backend = $this->app->getBackend('local');
 +
 +		if ($format === self::FORMAT_ADDRESSBOOKS) {
 +			foreach ($items as $item) {
- 				//\OCP\Util::writeLog('contacts', __METHOD__.' item_source: ' . $item['item_source'] . ' include: '
- 				//	. (int)$include, \OCP\Util::DEBUG);
- 				$addressBook = $backend->getAddressBook($item['item_source']);
++				//\OCP\Util::writeLog('contacts', __METHOD__.' item owner: ' . print_r($item['uid_owner'], true) , \OCP\Util::DEBUG);
++				$addressBook = $backend->getAddressBook($item['item_source'], array('shared_by' => $item['uid_owner']));
 +				if ($addressBook) {
 +					$addressBook['displayname'] = $addressBook['displayname'] . ' (' . $addressBook['owner'] . ')';
 +					$addressBook['permissions'] = $item['permissions'];
 +					$addressBooks[] = $addressBook;
 +				}
 +			}
 +		} elseif ($format === self::FORMAT_COLLECTION) {
 +			foreach ($items as $item) {
 +			}
 +		}
 +		return $addressBooks;
 +	}
 +
 +	public function getChildren($itemSource) {
 +		\OCP\Util::writeLog('contacts', __METHOD__.' item_source: ' . $itemSource, \OCP\Util::DEBUG);
 +		$contacts = $this->app->getBackend('local')->getContacts($itemSource);
 +		$children = array();
 +		foreach($contacts as $contact) {
 +			$children[] = array('source' => $contact['id'], 'target' => $contact['displayname']);
 +		}
 +		return $children;
 +	}
 +
 +}
diff --cc apps/search_lucene/3rdparty/Zend/Search/Lucene/Document/Docx.php
index f3c3e11,0000000..f5d74a6
mode 100644,000000..100644
--- a/apps/search_lucene/3rdparty/Zend/Search/Lucene/Document/Docx.php
+++ b/apps/search_lucene/3rdparty/Zend/Search/Lucene/Document/Docx.php
@@@ -1,151 -1,0 +1,152 @@@
 +<?php
 +/**
 + * Zend Framework
 + *
 + * LICENSE
 + *
 + * This source file is subject to the new BSD license that is bundled
 + * with this package in the file LICENSE.txt.
 + * It is also available through the world-wide-web at this URL:
 + * http://framework.zend.com/license/new-bsd
 + * If you did not receive a copy of the license and are unable to
 + * obtain it through the world-wide-web, please send an email
 + * to license at zend.com so we can send you a copy immediately.
 + *
 + * @category   Zend
 + * @package    Zend_Search_Lucene
 + * @subpackage Document
 + * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 + * @license    http://framework.zend.com/license/new-bsd     New BSD License
 + * @version    $Id: Docx.php 24593 2012-01-05 20:35:02Z matthew $
 + */
 +
 +/** Zend_Search_Lucene_Document_OpenXml */
 +require_once 'Zend/Search/Lucene/Document/OpenXml.php';
 +
 +/**
 + * Docx document.
 + *
 + * @category   Zend
 + * @package    Zend_Search_Lucene
 + * @subpackage Document
 + * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 + * @license    http://framework.zend.com/license/new-bsd     New BSD License
 + */
 +class Zend_Search_Lucene_Document_Docx extends Zend_Search_Lucene_Document_OpenXml {
 +    /**
 +     * Xml Schema - WordprocessingML
 +     *
 +     * @var string
 +     */
 +    const SCHEMA_WORDPROCESSINGML = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
 +
 +    /**
 +     * Object constructor
 +     *
 +     * @param string  $fileName
 +     * @param boolean $storeContent
 +     * @throws Zend_Search_Lucene_Exception
 +     */
 +    private function __construct($fileName, $storeContent) {
 +        if (!class_exists('ZipArchive', false)) {
 +            require_once 'Zend/Search/Lucene/Exception.php';
 +            throw new Zend_Search_Lucene_Exception('MS Office documents processing functionality requires Zip extension to be loaded');
 +        }
 +
 +        // Document data holders
 +        $documentBody = array();
 +        $coreProperties = array();
 +
 +        // Open OpenXML package
 +        $package = new ZipArchive();
 +        $package->open($fileName);
 +
 +        // Read relations and search for officeDocument
 +        $relationsXml = $package->getFromName('_rels/.rels');
 +        if ($relationsXml === false) {
 +            require_once 'Zend/Search/Lucene/Exception.php';
 +            throw new Zend_Search_Lucene_Exception('Invalid archive or corrupted .docx file.');
 +        }
++        libxml_disable_entity_loader(true);
 +        $relations = simplexml_load_string($relationsXml);
 +        foreach($relations->Relationship as $rel) {
 +            if ($rel ["Type"] == Zend_Search_Lucene_Document_OpenXml::SCHEMA_OFFICEDOCUMENT) {
 +                // Found office document! Read in contents...
 +                $contents = simplexml_load_string($package->getFromName(
 +                                                                $this->absoluteZipPath(dirname($rel['Target'])
 +                                                              . '/'
 +                                                              . basename($rel['Target']))
 +                                                                       ));
 +
 +                $contents->registerXPathNamespace('w', Zend_Search_Lucene_Document_Docx::SCHEMA_WORDPROCESSINGML);
 +                $paragraphs = $contents->xpath('//w:body/w:p');
 +
 +                foreach ($paragraphs as $paragraph) {
 +                    $runs = $paragraph->xpath('.//w:r/*[name() = "w:t" or name() = "w:br"]');
 +
 +                    if ($runs === false) {
 +                        // Paragraph doesn't contain any text or breaks
 +                        continue;
 +                    }
 +
 +                    foreach ($runs as $run) {
 +                     if ($run->getName() == 'br') {
 +                         // Break element
 +                         $documentBody[] = ' ';
 +                     } else {
 +                         $documentBody[] = (string)$run;
 +                     }
 +                    }
 +
 +                    // Add space after each paragraph. So they are not bound together.
 +                    $documentBody[] = ' ';
 +                }
 +
 +                break;
 +            }
 +        }
 +
 +        // Read core properties
 +        $coreProperties = $this->extractMetaData($package);
 +
 +        // Close file
 +        $package->close();
 +
 +        // Store filename
 +        $this->addField(Zend_Search_Lucene_Field::Text('filename', $fileName, 'UTF-8'));
 +
 +        // Store contents
 +        if ($storeContent) {
 +            $this->addField(Zend_Search_Lucene_Field::Text('body', implode('', $documentBody), 'UTF-8'));
 +        } else {
 +            $this->addField(Zend_Search_Lucene_Field::UnStored('body', implode('', $documentBody), 'UTF-8'));
 +        }
 +
 +        // Store meta data properties
 +        foreach ($coreProperties as $key => $value) {
 +            $this->addField(Zend_Search_Lucene_Field::Text($key, $value, 'UTF-8'));
 +        }
 +
 +        // Store title (if not present in meta data)
 +        if (! isset($coreProperties['title'])) {
 +            $this->addField(Zend_Search_Lucene_Field::Text('title', $fileName, 'UTF-8'));
 +        }
 +    }
 +
 +    /**
 +     * Load Docx document from a file
 +     *
 +     * @param string  $fileName
 +     * @param boolean $storeContent
 +     * @return Zend_Search_Lucene_Document_Docx
 +     * @throws Zend_Search_Lucene_Document_Exception
 +     */
 +    public static function loadDocxFile($fileName, $storeContent = false) {
 +        if (!is_readable($fileName)) {
 +            require_once 'Zend/Search/Lucene/Document/Exception.php';
 +            throw new Zend_Search_Lucene_Document_Exception('Provided file \'' . $fileName . '\' is not readable.');
 +        }
 +
 +        return new Zend_Search_Lucene_Document_Docx($fileName, $storeContent);
 +    }
 +}
diff --cc apps/search_lucene/3rdparty/Zend/Search/Lucene/Document/OpenXml.php
index 89772f1,0000000..871b75e
mode 100644,000000..100644
--- a/apps/search_lucene/3rdparty/Zend/Search/Lucene/Document/OpenXml.php
+++ b/apps/search_lucene/3rdparty/Zend/Search/Lucene/Document/OpenXml.php
@@@ -1,129 -1,0 +1,130 @@@
 +<?php
 +/**
 + * Zend Framework
 + *
 + * LICENSE
 + *
 + * This source file is subject to the new BSD license that is bundled
 + * with this package in the file LICENSE.txt.
 + * It is also available through the world-wide-web at this URL:
 + * http://framework.zend.com/license/new-bsd
 + * If you did not receive a copy of the license and are unable to
 + * obtain it through the world-wide-web, please send an email
 + * to license at zend.com so we can send you a copy immediately.
 + *
 + * @category   Zend
 + * @package    Zend_Search_Lucene
 + * @subpackage Document
 + * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 + * @license    http://framework.zend.com/license/new-bsd     New BSD License
 + * @version    $Id: OpenXml.php 24593 2012-01-05 20:35:02Z matthew $
 + */
 +
 +
 +/** Zend_Search_Lucene_Document */
 +require_once 'Zend/Search/Lucene/Document.php';
 +
 +
 +/**
 + * OpenXML document.
 + *
 + * @category   Zend
 + * @package    Zend_Search_Lucene
 + * @subpackage Document
 + * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 + * @license    http://framework.zend.com/license/new-bsd     New BSD License
 + */
 +abstract class Zend_Search_Lucene_Document_OpenXml extends Zend_Search_Lucene_Document
 +{
 +    /**
 +     * Xml Schema - Relationships
 +     *
 +     * @var string
 +     */
 +    const SCHEMA_RELATIONSHIP = 'http://schemas.openxmlformats.org/package/2006/relationships';
 +
 +    /**
 +     * Xml Schema - Office document
 +     *
 +     * @var string
 +     */
 +    const SCHEMA_OFFICEDOCUMENT = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument';
 +
 +    /**
 +     * Xml Schema - Core properties
 +     *
 +     * @var string
 +     */
 +    const SCHEMA_COREPROPERTIES = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';
 +
 +    /**
 +     * Xml Schema - Dublin Core
 +     *
 +     * @var string
 +     */
 +    const SCHEMA_DUBLINCORE = 'http://purl.org/dc/elements/1.1/';
 +
 +    /**
 +     * Xml Schema - Dublin Core Terms
 +     *
 +     * @var string
 +     */
 +    const SCHEMA_DUBLINCORETERMS = 'http://purl.org/dc/terms/';
 +
 +    /**
 +     * Extract metadata from document
 +     *
 +     * @param ZipArchive $package    ZipArchive OpenXML package
 +     * @return array    Key-value pairs containing document meta data
 +     */
 +    protected function extractMetaData(ZipArchive $package)
 +    {
 +        // Data holders
 +        $coreProperties = array();
 +
 +        // Read relations and search for core properties
++        libxml_disable_entity_loader(true);
 +        $relations = simplexml_load_string($package->getFromName("_rels/.rels"));
 +        foreach ($relations->Relationship as $rel) {
 +            if ($rel["Type"] == Zend_Search_Lucene_Document_OpenXml::SCHEMA_COREPROPERTIES) {
 +                // Found core properties! Read in contents...
 +                $contents = simplexml_load_string(
 +                    $package->getFromName(dirname($rel["Target"]) . "/" . basename($rel["Target"]))
 +                );
 +
 +                foreach ($contents->children(Zend_Search_Lucene_Document_OpenXml::SCHEMA_DUBLINCORE) as $child) {
 +                    $coreProperties[$child->getName()] = (string)$child;
 +                }
 +                foreach ($contents->children(Zend_Search_Lucene_Document_OpenXml::SCHEMA_COREPROPERTIES) as $child) {
 +                    $coreProperties[$child->getName()] = (string)$child;
 +                }
 +                foreach ($contents->children(Zend_Search_Lucene_Document_OpenXml::SCHEMA_DUBLINCORETERMS) as $child) {
 +                    $coreProperties[$child->getName()] = (string)$child;
 +                }
 +            }
 +        }
 +
 +        return $coreProperties;
 +    }
 +
 +    /**
 +     * Determine absolute zip path
 +     *
 +     * @param string $path
 +     * @return string
 +     */
 +    protected function absoluteZipPath($path) {
 +        $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
 +        $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
 +        $absolutes = array();
 +        foreach ($parts as $part) {
 +            if ('.' == $part) continue;
 +            if ('..' == $part) {
 +                array_pop($absolutes);
 +            } else {
 +                $absolutes[] = $part;
 +            }
 +        }
 +        return implode('/', $absolutes);
 +    }
 +}
diff --cc apps/search_lucene/3rdparty/Zend/Search/Lucene/Document/Xlsx.php
index 4bccb13,0000000..dcdd14f
mode 100644,000000..100644
--- a/apps/search_lucene/3rdparty/Zend/Search/Lucene/Document/Xlsx.php
+++ b/apps/search_lucene/3rdparty/Zend/Search/Lucene/Document/Xlsx.php
@@@ -1,263 -1,0 +1,264 @@@
 +<?php
 +/**
 + * Zend Framework
 + *
 + * LICENSE
 + *
 + * This source file is subject to the new BSD license that is bundled
 + * with this package in the file LICENSE.txt.
 + * It is also available through the world-wide-web at this URL:
 + * http://framework.zend.com/license/new-bsd
 + * If you did not receive a copy of the license and are unable to
 + * obtain it through the world-wide-web, please send an email
 + * to license at zend.com so we can send you a copy immediately.
 + *
 + * @category   Zend
 + * @package    Zend_Search_Lucene
 + * @subpackage Document
 + * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 + * @license    http://framework.zend.com/license/new-bsd     New BSD License
 + * @version    $Id: Xlsx.php 24593 2012-01-05 20:35:02Z matthew $
 + */
 +
 +
 +/** Zend_Search_Lucene_Document_OpenXml */
 +require_once 'Zend/Search/Lucene/Document/OpenXml.php';
 +
 +/**
 + * Xlsx document.
 + *
 + * @category   Zend
 + * @package    Zend_Search_Lucene
 + * @subpackage Document
 + * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 + * @license    http://framework.zend.com/license/new-bsd     New BSD License
 + */
 +class Zend_Search_Lucene_Document_Xlsx extends Zend_Search_Lucene_Document_OpenXml
 +{
 +    /**
 +     * Xml Schema - SpreadsheetML
 +     *
 +     * @var string
 +     */
 +    const SCHEMA_SPREADSHEETML = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main';
 +
 +    /**
 +     * Xml Schema - DrawingML
 +     *
 +     * @var string
 +     */
 +    const SCHEMA_DRAWINGML = 'http://schemas.openxmlformats.org/drawingml/2006/main';
 +
 +    /**
 +     * Xml Schema - Shared Strings
 +     *
 +     * @var string
 +     */
 +    const SCHEMA_SHAREDSTRINGS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings';
 +
 +    /**
 +     * Xml Schema - Worksheet relation
 +     *
 +     * @var string
 +     */
 +    const SCHEMA_WORKSHEETRELATION = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet';
 +
 +    /**
 +     * Xml Schema - Slide notes relation
 +     *
 +     * @var string
 +     */
 +    const SCHEMA_SLIDENOTESRELATION = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide';
 +
 +    /**
 +     * Object constructor
 +     *
 +     * @param string  $fileName
 +     * @param boolean $storeContent
 +     * @throws Zend_Search_Lucene_Exception
 +     */
 +    private function __construct($fileName, $storeContent)
 +    {
 +        if (!class_exists('ZipArchive', false)) {
 +            require_once 'Zend/Search/Lucene/Exception.php';
 +            throw new Zend_Search_Lucene_Exception('MS Office documents processing functionality requires Zip extension to be loaded');
 +        }
 +
 +        // Document data holders
 +        $sharedStrings = array();
 +        $worksheets = array();
 +        $documentBody = array();
 +        $coreProperties = array();
 +
 +        // Open OpenXML package
 +        $package = new ZipArchive();
 +        $package->open($fileName);
 +
 +        // Read relations and search for officeDocument
 +        $relationsXml = $package->getFromName('_rels/.rels');
 +        if ($relationsXml === false) {
 +            require_once 'Zend/Search/Lucene/Exception.php';
 +            throw new Zend_Search_Lucene_Exception('Invalid archive or corrupted .xlsx file.');
 +        }
++        libxml_disable_entity_loader(true);
 +        $relations = simplexml_load_string($relationsXml);
 +        foreach ($relations->Relationship as $rel) {
 +            if ($rel["Type"] == Zend_Search_Lucene_Document_OpenXml::SCHEMA_OFFICEDOCUMENT) {
 +                // Found office document! Read relations for workbook...
 +                $workbookRelations = simplexml_load_string($package->getFromName( $this->absoluteZipPath(dirname($rel["Target"]) . "/_rels/" . basename($rel["Target"]) . ".rels")) );
 +                $workbookRelations->registerXPathNamespace("rel", Zend_Search_Lucene_Document_OpenXml::SCHEMA_RELATIONSHIP);
 +
 +                // Read shared strings
 +                $sharedStringsPath = $workbookRelations->xpath("rel:Relationship[@Type='" . Zend_Search_Lucene_Document_Xlsx::SCHEMA_SHAREDSTRINGS . "']");
 +                $sharedStringsPath = (string)$sharedStringsPath[0]['Target'];
 +                $xmlStrings = simplexml_load_string($package->getFromName( $this->absoluteZipPath(dirname($rel["Target"]) . "/" . $sharedStringsPath)) );
 +                if (isset($xmlStrings) && isset($xmlStrings->si)) {
 +                    foreach ($xmlStrings->si as $val) {
 +                        if (isset($val->t)) {
 +                            $sharedStrings[] = (string)$val->t;
 +                        } elseif (isset($val->r)) {
 +                            $sharedStrings[] = $this->_parseRichText($val);
 +                        }
 +                    }
 +                }
 +
 +                // Loop relations for workbook and extract worksheets...
 +                foreach ($workbookRelations->Relationship as $workbookRelation) {
 +                    if ($workbookRelation["Type"] == Zend_Search_Lucene_Document_Xlsx::SCHEMA_WORKSHEETRELATION) {
 +                        $worksheets[ str_replace( 'rId', '', (string)$workbookRelation["Id"]) ] = simplexml_load_string(
 +                            $package->getFromName( $this->absoluteZipPath(dirname($rel["Target"]) . "/" . dirname($workbookRelation["Target"]) . "/" . basename($workbookRelation["Target"])) )
 +                        );
 +                    }
 +                }
 +
 +                break;
 +            }
 +        }
 +
 +        // Sort worksheets
 +        ksort($worksheets);
 +
 +        // Extract contents from worksheets
 +        foreach ($worksheets as $sheetKey => $worksheet) {
 +            foreach ($worksheet->sheetData->row as $row) {
 +                foreach ($row->c as $c) {
 +                    // Determine data type
 +                    $dataType = (string)$c["t"];
 +                    switch ($dataType) {
 +                        case "s":
 +                            // Value is a shared string
 +                            if ((string)$c->v != '') {
 +                                $value = $sharedStrings[intval($c->v)];
 +                            } else {
 +                                $value = '';
 +                            }
 +
 +                            break;
 +
 +                        case "b":
 +                            // Value is boolean
 +                            $value = (string)$c->v;
 +                            if ($value == '0') {
 +                                $value = false;
 +                            } else if ($value == '1') {
 +                                $value = true;
 +                            } else {
 +                                $value = (bool)$c->v;
 +                            }
 +
 +                            break;
 +
 +                        case "inlineStr":
 +                            // Value is rich text inline
 +                            $value = $this->_parseRichText($c->is);
 +
 +                            break;
 +
 +                        case "e":
 +                            // Value is an error message
 +                            if ((string)$c->v != '') {
 +                                $value = (string)$c->v;
 +                            } else {
 +                                $value = '';
 +                            }
 +
 +                            break;
 +
 +                        default:
 +                            // Value is a string
 +                            $value = (string)$c->v;
 +
 +                            // Check for numeric values
 +                            if (is_numeric($value) && $dataType != 's') {
 +                                if ($value == (int)$value) $value = (int)$value;
 +                                elseif ($value == (float)$value) $value = (float)$value;
 +                                elseif ($value == (double)$value) $value = (double)$value;
 +                            }
 +                    }
 +
 +                    $documentBody[] = $value;
 +                }
 +            }
 +        }
 +
 +        // Read core properties
 +        $coreProperties = $this->extractMetaData($package);
 +
 +        // Close file
 +        $package->close();
 +
 +        // Store filename
 +        $this->addField(Zend_Search_Lucene_Field::Text('filename', $fileName, 'UTF-8'));
 +
 +        // Store contents
 +        if ($storeContent) {
 +            $this->addField(Zend_Search_Lucene_Field::Text('body', implode(' ', $documentBody), 'UTF-8'));
 +        } else {
 +            $this->addField(Zend_Search_Lucene_Field::UnStored('body', implode(' ', $documentBody), 'UTF-8'));
 +        }
 +
 +        // Store meta data properties
 +        foreach ($coreProperties as $key => $value)
 +        {
 +            $this->addField(Zend_Search_Lucene_Field::Text($key, $value, 'UTF-8'));
 +        }
 +
 +        // Store title (if not present in meta data)
 +        if (!isset($coreProperties['title']))
 +        {
 +            $this->addField(Zend_Search_Lucene_Field::Text('title', $fileName, 'UTF-8'));
 +        }
 +    }
 +
 +    /**
 +     * Parse rich text XML
 +     *
 +     * @param SimpleXMLElement $is
 +     * @return string
 +     */
 +    private function _parseRichText($is = null) {
 +        $value = array();
 +
 +        if (isset($is->t)) {
 +            $value[] = (string)$is->t;
 +        } else {
 +            foreach ($is->r as $run) {
 +                $value[] = (string)$run->t;
 +            }
 +        }
 +
 +        return implode('', $value);
 +    }
 +
 +    /**
 +     * Load Xlsx document from a file
 +     *
 +     * @param string  $fileName
 +     * @param boolean $storeContent
 +     * @return Zend_Search_Lucene_Document_Xlsx
 +     */
 +    public static function loadXlsxFile($fileName, $storeContent = false)
 +    {
 +        return new Zend_Search_Lucene_Document_Xlsx($fileName, $storeContent);
 +    }
 +}
diff --cc apps/search_lucene/document/Ods.php
index e5419f2,0000000..8ba3c1a
mode 100644,000000..100644
--- a/apps/search_lucene/document/Ods.php
+++ b/apps/search_lucene/document/Ods.php
@@@ -1,87 -1,0 +1,88 @@@
 +<?php
 +
 +namespace OCA\Search_Lucene\Document;
 +/**
 + * Ods document.
 + * @see http://en.wikipedia.org/wiki/OpenDocument_technical_specification
 + */
 +class Ods extends OpenDocument {
 +
 +	const SCHEMA_ODTABLE = 'urn:oasis:names:tc:opendocument:xmlns:table:1.0';
 +
 +    /**
 +     * Object constructor
 +     *
 +     * @param string  $fileName
 +     * @param boolean $storeContent
 +     * @throws \Zend_Search_Lucene_Exception
 +     */
 +    private function __construct($fileName, $storeContent) {
 +        if (!class_exists('ZipArchive', false)) {
 +            throw new \Zend_Search_Lucene_Exception('Open Document Spreadsheet processing functionality requires Zip extension to be loaded');
 +        }
 +
 +        // Document data holders
 +		$documentTables = array();
 +		$documentCells = array();
 +
 +        // Open OpenXML package
 +        $package = new \ZipArchive();
 +        $package->open($fileName);
 +
 +        // Read relations and search for officeDocument
 +        $content = $package->getFromName('content.xml');
 +        if ($content === false) {
 +            throw new \Zend_Search_Lucene_Exception('Invalid archive or corrupted .ods file.');
 +        }
++        	libxml_disable_entity_loader(true);
 +		$sxe = simplexml_load_string($content, 'SimpleXMLElement', LIBXML_NOBLANKS | LIBXML_COMPACT);
 +
 +		foreach ($sxe->xpath('//table:table[@table:name]') as $table) {
 +			$documentTables[] = (string)$table->attributes($this::SCHEMA_ODTABLE)->name;
 +		}
 +		foreach ($sxe->xpath('//text:p') as $cell) {
 +			$documentCells[] = (string)$cell;
 +		}
 +
 +        // Read core properties
 +        $coreProperties = $this->extractMetaData($package);
 +
 +        // Close file
 +        $package->close();
 +
 +        // Store contents
 +        if ($storeContent) {
 +			$this->addField(\Zend_Search_Lucene_Field::Text('sheets', implode(' ', $documentTables), 'UTF-8'));
 +			$this->addField(\Zend_Search_Lucene_Field::Text('body', implode(' ', $documentCells), 'UTF-8'));
 +        } else {
 +			$this->addField(\Zend_Search_Lucene_Field::UnStored('sheets', implode(' ', $documentTables), 'UTF-8'));
 +			$this->addField(\Zend_Search_Lucene_Field::UnStored('body', implode(' ', $documentCells), 'UTF-8'));
 +        }
 +
 +        // Store meta data properties
 +        foreach ($coreProperties as $key => $value) {
 +            $this->addField(\Zend_Search_Lucene_Field::Text($key, $value, 'UTF-8'));
 +        }
 +
 +        // Store title (if not present in meta data)
 +        if (! isset($coreProperties['title'])) {
 +            $this->addField(\Zend_Search_Lucene_Field::Text('title', $fileName, 'UTF-8'));
 +        }
 +    }
 +
 +    /**
 +     * Load Ods document from a file
 +     *
 +     * @param string  $fileName
 +     * @param boolean $storeContent
 +     * @return Ods
 +     * @throws \Zend_Search_Lucene_Document_Exception
 +     */
 +    public static function loadOdsFile($fileName, $storeContent = false) {
 +        if (!is_readable($fileName)) {
 +            throw new \Zend_Search_Lucene_Document_Exception('Provided file \'' . $fileName . '\' is not readable.');
 +        }
 +
 +        return new Ods($fileName, $storeContent);
 +    }
 +}
diff --cc apps/search_lucene/document/Odt.php
index ea36313,0000000..c850c71
mode 100644,000000..100644
--- a/apps/search_lucene/document/Odt.php
+++ b/apps/search_lucene/document/Odt.php
@@@ -1,85 -1,0 +1,86 @@@
 +<?php
 +
 +namespace OCA\Search_Lucene\Document;
 +/**
 + * Odt document.
 + * @see http://en.wikipedia.org/wiki/OpenDocument_technical_specification
 + */
 +class Odt extends OpenDocument {
 +    /**
 +     * Object constructor
 +     *
 +     * @param string  $fileName
 +     * @param boolean $storeContent
 +     * @throws \Zend_Search_Lucene_Exception
 +     */
 +    private function __construct($fileName, $storeContent) {
 +        if (!class_exists('ZipArchive', false)) {
 +            throw new \Zend_Search_Lucene_Exception('Open Document Text processing functionality requires Zip extension to be loaded');
 +        }
 +
 +        // Document data holders
 +		$documentHeadlines = array();
 +		$documentParagraphs = array();
 +
 +        // Open OpenXML package
 +        $package = new \ZipArchive();
 +        $package->open($fileName);
 +
 +        // Read relations and search for officeDocument
 +        $content = $package->getFromName('content.xml');
 +        if ($content === false) {
 +            throw new \Zend_Search_Lucene_Exception('Invalid archive or corrupted .odt file.');
 +        }
++			libxml_disable_entity_loader(true);
 +		$sxe = simplexml_load_string($content, 'SimpleXMLElement', LIBXML_NOBLANKS | LIBXML_COMPACT);
 +
 +		foreach ($sxe->xpath('//text:h') as $headline) {
 +			$documentHeadlines[] = (string)$headline;
 +		}
 +
 +		foreach ($sxe->xpath('//text:p') as $paragraph) {
 +			$documentParagraphs[] = (string)$paragraph;
 +		}
 +
 +        // Read core properties
 +        $coreProperties = $this->extractMetaData($package);
 +
 +        // Close file
 +        $package->close();
 +
 +        // Store contents
 +        if ($storeContent) {
 +			$this->addField(\Zend_Search_Lucene_Field::Text('headlines', implode(' ', $documentHeadlines), 'UTF-8'));
 +			$this->addField(\Zend_Search_Lucene_Field::Text('body', implode(' ', $documentParagraphs), 'UTF-8'));
 +        } else {
 +			$this->addField(\Zend_Search_Lucene_Field::UnStored('headlines', implode(' ', $documentHeadlines), 'UTF-8'));
 +			$this->addField(\Zend_Search_Lucene_Field::UnStored('body', implode(' ', $documentParagraphs), 'UTF-8'));
 +        }
 +
 +        // Store meta data properties
 +        foreach ($coreProperties as $key => $value) {
 +            $this->addField(\Zend_Search_Lucene_Field::Text($key, $value, 'UTF-8'));
 +        }
 +
 +        // Store title (if not present in meta data)
 +        if (! isset($coreProperties['title'])) {
 +            $this->addField(\Zend_Search_Lucene_Field::Text('title', $fileName, 'UTF-8'));
 +        }
 +    }
 +
 +    /**
 +     * Load Odt document from a file
 +     *
 +     * @param string  $fileName
 +     * @param boolean $storeContent
 +     * @return Odt
 +     * @throws \Zend_Search_Lucene_Document_Exception
 +     */
 +    public static function loadOdtFile($fileName, $storeContent = false) {
 +        if (!is_readable($fileName)) {
 +            throw new \Zend_Search_Lucene_Document_Exception('Provided file \'' . $fileName . '\' is not readable.');
 +        }
 +
 +        return new Odt($fileName, $storeContent);
 +    }
 +}
diff --cc apps/search_lucene/document/OpenDocument.php
index d944902,0000000..d2a14d3
mode 100644,000000..100644
--- a/apps/search_lucene/document/OpenDocument.php
+++ b/apps/search_lucene/document/OpenDocument.php
@@@ -1,81 -1,0 +1,82 @@@
 +<?php
 +
 +namespace OCA\Search_Lucene\Document;
 +/**
 + * OpenDocument document.
 + */
 +abstract class OpenDocument extends \Zend_Search_Lucene_Document
 +{
 +	const OASIS_XPATH_TITLE    = '//dc:title';
 +	const OASIS_XPATH_SUBJECT  = '//dc:subject';
 +	const OASIS_XPATH_CREATOR  = '//meta:initial-creator';
 +	const OASIS_XPATH_KEYWORDS = '//meta:keyword';
 +	const OASIS_XPATH_CREATED  = '//meta:creation-date';
 +	const OASIS_XPATH_MODIFIED = '//dc:date';
 +
 +    /**
 +     * Extract metadata from document
 +     *
 +     * @param ZipArchive $package ZipArchive OpenDocument package
 +     * @return array Key-value pairs containing document meta data
 +     */
 +    protected function extractMetaData(\ZipArchive $package)
 +    {
 +        // Data holders
 +        $coreProperties = array();
 +
 +        // Read relations and search for core properties
++		libxml_disable_entity_loader(true);
 +		$sxe = simplexml_load_string($package->getFromName("meta.xml"));
 +
 +		if (is_object($sxe) && $sxe instanceof \SimpleXMLElement) {
 +
 +			$coreProperties['title'] = $this->extractTermsFromMetadata($sxe, $this::OASIS_XPATH_TITLE);
 +
 +			$coreProperties['subject'] = $this->extractTermsFromMetadata($sxe, $this::OASIS_XPATH_SUBJECT);
 +
 +			$coreProperties['creator'] = $this->extractTermsFromMetadata($sxe, $this::OASIS_XPATH_CREATOR);
 +
 +			$coreProperties['keywords'] = $this->extractTermsFromMetadata($sxe, $this::OASIS_XPATH_KEYWORDS);
 +
 +			//replace T in date string with ' '
 +			$coreProperties['created'] = str_replace('T', ' ', $this->extractTermsFromMetadata($sxe, $this::OASIS_XPATH_CREATED));
 +
 +			$coreProperties['modified'] = str_replace('T', ' ', $this->extractTermsFromMetadata($sxe, $this::OASIS_XPATH_MODIFIED));
 +		}
 +
 +        return $coreProperties;
 +    }
 +
 +	private function extractTermsFromMetadata(\SimpleXMLElement $sxe, $path) {
 +
 +		$terms = array();
 +
 +		foreach ($sxe->xpath($path) as $value) {
 +			$terms[] = (string)$value;
 +		}
 +
 +		return (implode(' ', $terms));
 +
 +	}
 +
 +    /**
 +     * Determine absolute zip path
 +     *
 +     * @param string $path
 +     * @return string
 +     */
 +    protected function absoluteZipPath($path) {
 +        $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
 +        $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
 +        $absolutes = array();
 +        foreach ($parts as $part) {
 +            if ('.' == $part) continue;
 +            if ('..' == $part) {
 +                array_pop($absolutes);
 +            } else {
 +                $absolutes[] = $part;
 +            }
 +        }
 +        return implode('/', $absolutes);
 +    }
 +}
diff --cc core/doc/admin/_sources/configuration/auth_ldap.txt
index 06af732,0000000..fac83b3
mode 100644,000000..100644
--- a/core/doc/admin/_sources/configuration/auth_ldap.txt
+++ b/core/doc/admin/_sources/configuration/auth_ldap.txt
@@@ -1,616 -1,0 +1,615 @@@
 +LDAP Authentication
 +===================
 +
- ownCloud ships an LDAP backend, which allows full use of ownCloud for user
++ownCloud ships an LDAP backend, which allows full use of ownCloud for users
 +logging in with LDAP credentials including:
 +
 +* LDAP group support
 +* File sharing with users and groups
 +* Access via WebDAV and of course ownCloud Desktop Client
 +* Versioning, external Storages and all other ownCloud goodies
 +
 +To connect to an LDAP server the configuration needs to be set up properly.
 +Once the LDAP backend is activated (Apps Sidebar→Apps, choose **LDAP user and
 +group backend**, click on **Enable**) the configuration can be found on
 +Settings→Admin. Read on for a detailed description of the configuration fields.
 +
 +Configuration
 +-------------
 +
- The LDAP backend follows a wizard-like approach, splitted into four tabs. A
++The LDAP backend configuration follows a wizard-like approach, split into four tabs. A
 +correctly completed first tab ("Server") is mandatory to access the other tabs.
- Also, the other tabs need to be reviewed by the admin, however the necessary
- settings are detected automatically. An indicator will show whether the
- configuration is incomplete, incorrect or OK.
++The settings in the other tabs are detected automatically, but should be reviewed by the
++admin. An indicator will show whether the configuration is incomplete, incorrect or OK.
 +
- The settings are changed automatically, as soon as a input element looses the
++The settings are changed automatically, as soon as a input element loses the
 +focus, i.e. the cursor is taken away by clicking somewhere else or pressing the
- tabulator key.
++Tab key.
 +
 +The other tabs can be navigated by clicking the tabs or by using the *Continue*
 +and *Back* buttons. They are located on the lower right, next to the status
 +indicator.
 +
 +Server
 +~~~~~~
 +
- The server tab contains the basic information on the LDAP server. They make sure
++The Server tab contains the basic information on the LDAP server. They make sure
 +that ownCloud will be able to connect to LDAP and be able to read data from
 +there. The admin at least needs to provide a hostname. If anonymous access is
 +not possible he will need to provide an account DN and a password, too. ownCloud
 +attempts to auto-detect the port and the base DN.
 +
 +.. figure:: ../images/ldap-wizard-1-server.png
 +
 +Server configuration:
 +  ownCloud can be configured to connect to multiple LDAP servers. Using this
 +  control you can pick a configuration you want to edit or add a new one. The
 +  button **Delete Configuration** deletes the current configuration.
 +
 +Host:
 +  The host name of the LDAP server. It can also be a **ldaps://** URI, for
 +  instance.
 +
 +  It is also possible to pass a port number, which speeds up port detection. It
 +  is especially useful, if a custom port is used. ownCloud will move the value
 +  to the port field subsequently.
 +
 +  Examples:
 +
 +  * *directory.my-company.com*
 +  * *ldaps://directory.my-company.com*
 +  * *directory.my-company.com:9876*
 +
 +Port:
 +  The port on which to connect to the LDAP server. The field is disabled in the
 +  beginning of a new configuration. The port will be detected automatically,
 +  if the LDAP server is running on a standard port. After ownCloud attempted to
 +  determine the port, the field will be enabled for user input. A successfully
 +  found port will be inserted by ownCloud, of course.
 +
 +  Example:
 +
 +  * *389*
 +
 +User DN:
 +  The name as DN of a user who is able to do searches in the LDAP
 +  directory. Leave it empty for anonymous access. It is recommended to have a
 +  special system user for ownCloud.
 +
 +  Example:
 +
 +  * *uid=owncloudsystemuser,cn=sysusers,dc=my-company,dc=com*
 +
 +Password:
 +  The password for the user given above. Empty for anonymous access.
 +
 +Base DN:
 +  The base DN of LDAP, from where all users and groups can be reached. Separated
 +  Base DNs for users and groups can be set in the Advanced tab. Nevertheless,
 +  this field is mandatory. ownCloud attempts to determine the Base DN according
 +  to the provided User DN or the provided Host.
 +
 +  Example:
 +
 +  * *dc=my-company,dc=com*
 +
 +User Filter
 +~~~~~~~~~~~
 +
- The settings in the user filter tab determine which LDAP users will appear and
++The settings in the User Filter tab determine which LDAP users will appear and
 +are allowed to log in into ownCloud. It is also possible to enter a raw LDAP
 +filter.
 +
 +.. figure:: ../images/ldap-wizard-2-user.png
 +
 +only those object classes:
-   ownCloud will determine the object classes that are typically availalble for
++  ownCloud will determine the object classes that are typically available for
 +  (ideally only) user objects in your LDAP. ownCloud will automatically select
 +  the object class that returns the highest amount of users. You can select
 +  multiple object classes.
 +
 +only from those groups:
 +  If your LDAP server supports the member-of-overlay in LDAP filters, you can
 +  define that only users from one or more certain groups are allowed to
 +  appear and log in into ownCloud. By default, no value will be selected. You
 +  can select multiple groups.
 +
 +  If your LDAP server does not support the member-of-overlay in LDAP filters,
 +  the input field is disabled. Please contact your LDAP administrator.
 +
 +Edit raw filter instead:
 +  Clicking on this text will toggle the filter mode. Instead of the assisted
 +  approach, you can enter the raw LDAP filter directly in the appearing field.
 +
 +  Example:
 +
 +  * *objectClass=inetOrgPerson*
 +
 +x users found:
 +  This is an indicator that tells you approximately how many users will be
 +  allowed to access ownCloud. The number will update after any change you do.
 +
 +Login Filter
 +~~~~~~~~~~~~
 +
- The settings in the login filter tab determine which user detail will be
++The settings in the Login Filter tab determine which user detail will be
 +compared to the login value entered by the user. It is possible to allow
 +multiple user details. It is also possible to enter a raw LDAP filter.
 +
 +The user limitation as set up in the previous tab is in effect, unless you
 +manually configure the filter in raw mode.
 +
 +.. figure:: ../images/ldap-wizard-3-login.png
 +
 +LDAP Username:
 +  If this value is checked, the login value will be compared to the username in
 +  the LDAP directory. The corresponding attribute, usually *uid* or
 +  *samaccountname* will be detected automatically by ownCloud.
 +
 +LDAP Email Address:
 +  If this value is checked, the login value will be compared to an email address
 +  in the LDAP directory. The email address will be looked for in the
 +  *mailPrimaryAddress* and *mail* attributes.
 +
 +Other Attributes:
 +  This multiselect box allows you to select other attributes for the comparison.
 +  The list is generated automatically based on the attributes that a user object
 +  contains in your LDAP server.
 +
 +Edit raw filter instead:
 +  Clicking on this text will toggle the filter mode. Instead of the assisted
 +  approach, you can enter the raw LDAP filter directly in the appearing field.
 +
 +  The **%uid** placeholder will be replaced with the login name entered by the user
 +  upon login. When you enter the filter manually.
 +
 +  Examples:
 +
 +  * only username: *uid=%uid*
 +  * username or email address: *(|(uid=%uid)(mail=$uid))*
 +
 +Group Filter
 +~~~~~~~~~~~~
 +
- The settings in the group filter tab determine which groups will be availalble
- in ownCloud. It does not have any restrictions on logins, this has been dealed
++The settings in the Group Filter tab determine which groups will be available
++in ownCloud. It does not have any restrictions on logins, this has been dealt
 +with in the prior tabs.  It is also possible to enter a raw LDAP
 +filter.
 +
- By default, no groups will be availalble in ownCloud. You actively need to
++By default, no groups will be available in ownCloud. You actively need to
 +enable groups.
 +
 +.. figure:: ../images/ldap-wizard-4-group.png
 +
 +only those object classes:
-   ownCloud will determine the object classes that are typically availalble for
++  ownCloud will determine the object classes that are typically available for
 +  (ideally only) group objects in your LDAP. ownCloud will only list object
 +  classes that return at least one group object. You can select multiple
 +  object classes. A typical object class is "group", or "posixGroup".
 +
 +only from those groups:
-   This setting lets you pick certain groups that shall be availalble in
++  This setting lets you pick certain groups that shall be available in
 +  ownCloud. This field follows a whitelist approach. ownCloud will generate a
 +  list of available groups found in your LDAP server. You can select multiple
 +  groups.
 +
 +Edit raw filter instead:
 +  Clicking on this text will toggle the filter mode. Instead of the assisted
 +  approach, you can enter the raw LDAP filter directly in the appearing field.
 +
 +  Example:
 +
 +  * *objectClass=group*
 +  * *objectClass=posixGroup*
 +
 +y groups found:
 +  This is an indicator that tells you approximately how many groups will be
 +  available in  ownCloud. The number will update after any change you do.
 +
 +
 +Advanced Settings
 +-----------------
 +
- In the LDAP Advanced settings section you can define options, that are less
++In the LDAP Advanced Settings section you can define options, that are less
 +common to set. They are not needed for a working connection. It can also have a
 +positive effect on the performance to specify distinguished bases for user and
 +group searches.
 +
 +The Advanced Settings are structured into three parts:
 +
 +* Connection Settings
 +* Directory Settings
 +* Special Attributes
 +
 +Connection Settings
 +~~~~~~~~~~~~~~~~~~~
 +
 +.. figure:: ../images/ldap-advanced-1-connection.png
 +
 +   LDAP Advanced Settings, section Connection Settings
 +
 +Configuration Active:
 +  Enables or Disables the current configuration. Disabled configuration will not
 +  connect to the LDAP server.
 +
 +  By default, it is turned off. It will be automatically turned on, when using
 +  the wizard and the configuration is OK and a test connection successful.
 +
 +Backup (Replica) Host:
 +  A backup server can be defined here. ownCloud tries to connect to the backup
 +  server automatically, when the main host (as specified in basic settings)
-   cannot be reached. It is import that the backup server is a replica of the
++  cannot be reached. It is important that the backup server is a replica of the
 +  main server, because the object UUIDs must match.
 +
 +  Example:
 +
 +  * *directory2.my-company.com*
 +
 +Backup (Replica) Port:
 +  The port on which to connect to the backup LDAP server. If no port is given,
 +  but a host, then the main port (as specified above) will be used.
 +
 +  Example:
 +
 +  * *389*
 +
 +Disable Main Server:
 +  You can manually override the main server and make ownCloud only connect to
-   the backup server. It may be handy for planned downtimes.
++  the backup server. This may be handy for planned downtimes.
 +
 +Case insensitive LDAP server (Windows):
-   Whether the LDAP server is running on a Windows Host. Usually, it is not
++  Whether the LDAP server is running on a Windows host. Usually, it is not
 +  necessary to check it, however.
 +
 +Turn off SSL certificate validation:
-   Turns of check of valid SSL certificates. Use it – if needed –
++  Turns off check of valid SSL certificates. Use it – if needed –
 +  for testing, only!
 +
 +Cache Time-To-Live:
 +  A cache is introduced to avoid unnecessary LDAP traffic,
-   for example lookups check whether the users exists on every page request or
++  for example lookups check whether the users exist on every page request or
 +  WebDAV interaction. It is also supposed to speed up the Admin → User page or
 +  list of users to share with, once it is populated. Saving the configuration
 +  empties the cache (changes are not necessary). The time is given in seconds.
 +
 +  Note that almost every PHP request would require to build up a new connection
-   to the LDAP server. If you require a most up-to-dateness it is recommended not
++  to the LDAP server. If you require most up-to-dateness it is recommended not
 +  to totally switch off the cache, but define a minimum life time of 15s.
 +
 +  Examples:
 +
 +  * ten minutes: *600*
 +  * one hour: *3600*
 +
 +Directory Settings
 +~~~~~~~~~~~~~~~~~~~
 +
 +.. figure:: ../images/ldap-advanced-2-directory.png
 +
 +   LDAP Advanced Settings, section Directory Settings
 +
 +User Display Name Field:
 +  The attribute that should be used as display name in ownCloud.
 +
 +  *  Example: *displayName*
 +
 +Base User Tree:
 +  The base DN of LDAP, from where all users can be reached. It needs to be given
 +  completely despite to the Base DN from the Basic settings. You can specify
 +  multiple base trees, one in each line.
 +
 +  * Example:
 +
 +    | *cn=programmers,dc=my-company,dc=com*
 +    | *cn=designers,dc=my-company,dc=com*
 +
 +User Search Attributes:
 +  These attributes are used when a search for users is done. This happens, for
 +  instance, in the share dialogue. By default the user display name attribute as
 +  specified above is being used. Multiple attributes can be given, one in each
 +  line.
 +
 +  Beware that if an attribute is not available on a user object, the user will
 +  neither be listed (e.g. in the share dialogue) nor be able to login. This also
 +  affects the display name attribute as specified above. If you override the
 +  default, the display name attribute will not be taken into account, unless you
 +  specify it as well.
 +
 +  * Example:
 +
 +    | *displayName*
 +    | *mail*
 +
 +Group Display Name Field:
 +  The attribute that should be used as ownCloud group name. ownCloud allows a
 +  limited set of characters (a-zA-Z0-9.-_@), every other character will be
 +  replaced in ownCloud. Once a group name is assigned, it will not be changed,
 +  i.e. changing this value will only have effect to new LDAP groups.
 +
 +  * Example: *cn*
 +
 +Base Group Tree:
 +  The base DN of LDAP, from where all groups can be reached.
 +  It needs to be given completely despite to the Base DN from the Basic
 +  settings. You can specify multiple base trees, one in each line.
 +
 +  * Example:
 +
 +    | *cn=barcelona,dc=my-company,dc=com*
 +    | *cn=madrid,dc=my-company,dc=com*
 +
 +Group Search Attributes:
 +  These attributes are used when a search for groups is done. This happens, for
 +  instance, in the share dialogue. By default the group display name attribute
 +  as specified above is being used. Multiple attributes can be given, one in
 +  each line.
 +
 +  If you override the default, the group display name attribute will not be
 +  taken into account, unless you specify it as well.
 +
 +  * Example:
 +
 +    | *cn*
 +    | *description*
 +
 +Group Member association:
 +  The attribute that is used to indicate group memberships, i.e. the attribute
 +  used by LDAP groups to refer to their users.
 +
-   ownCloud detects the value automatically, you should only change it, if you
++  ownCloud detects the value automatically. You should only change it if you
 +  have a very valid reason and know what you are doing.
 +
 +  * Example: *uniquemember*
 +
 +Special Attributes
 +~~~~~~~~~~~~~~~~~~
 +
 +.. figure:: ../images/ldap-advanced-3-attributes.png
 +
 +   LDAP Advanced Settings, section Special Attributes
 +
 +Quota Field:
 +  ownCloud can read an LDAP attribute and set the user quota according to its
 +  value. Specify the attribute here, otherwise keep it empty. The attribute
 +  shall return human readable values, e.g. "2 GB".
 +
 +  * Example: *ownCloudQuota*
 +
 +Quota Default:
 +  Override ownCloud default quota for LDAP users who do not
 +  have a quota set in the attribute given above.
 +
 +  * Example: *15 GB*
 +
 +Email Field:
 +  ownCloud can read an LDAP attribute and set the user email
 +  there from. Specify the attribute here, otherwise keep it empty.
 +
 +  Although the wizard offers you to check login by email, the correct email
 +  attribute is not detected and you need to specify it manually.
 +
 +  * Example: *mail*
 +
 +User Home Folder Naming Rule:
 +  By default, the ownCloud creates the user
 +  directory, where all files and meta data are kept, according to the ownCloud
 +  user name. You may want to override this setting and name it after an
 +  attribute value. The attribute given can also return an absolute path, e.g.
 +  ``/mnt/storage43/alice``. Leave it empty for default behavior.
 +
 +  * Example: *cn*
 +
 +Expert Settings
 +---------------
 +
 +.. figure:: ../images/ldap-expert.png
 +
 +In the Expert Settings fundamental behavior can be adjusted to your needs. The
 +configuration should be done before starting production use or when testing the
 +installation.
 +
 +Internal Username:
 +  The internal username is the identifier in ownCloud for LDAP users. By default
 +  it will be created from the UUID attribute. By using the UUID attribute it is
 +  made sure that the username is unique and characters do not need to be
 +  converted. The internal username has the restriction that only these
 +  characters are allowed: [\a-\zA-\Z0-\9_. at -]. Other characters are replaced with
 +  their ASCII correspondence or are simply omitted.
 +
 +  The LDAP backend ensures that there are no duplicate internal usernames in
 +  ownCloud, i.e. that it is checking all other activated user backends
 +  (including local ownCloud users). On collisions a random number (between 1000
 +  and 9999) will be attached to the retrieved value. For example, if "alice"
 +  exists, the next username may be "alice_1337".
 +
 +  The internal username is also the default name for the user home folder in
 +  ownCloud. It is also a part of remote URLs, for instance for all \*DAV services.
 +  With this setting the default behaviour can be overridden.
 +
 +  Leave it empty for default behaviour. Changes will have effect only on newly
 +  mapped (added) LDAP users.
 +
 +  * Example: *uid*
 +
 +Override UUID detection
 +  By default, ownCloud auto-detects the UUID attribute. The UUID attribute is
 +  used to doubtlessly identify LDAP users and groups. Also, the internal
 +  username will be created based on the UUID, if not specified otherwise above.
 +
 +  You can override the setting and pass an attribute of your choice. You must
 +  make sure that the attribute of your choice can be fetched for both users and
 +  groups and it is unique. Leave it empty for default behaviour. Changes will
 +  have effect only on newly mapped (added) LDAP users and groups. It also will
-   have effect when a user's or group's DN changes and an old UUID was cached: It
++  have effect when a user's or group's DN changes and an old UUID was cached: it
 +  will result in a new user. Because of this, the setting should be applied
 +  before putting ownCloud in production use and cleaning the bindings
 +  (see below).
 +
 +  * Example: *cn*
 +
 +Username-LDAP User Mapping
 +  ownCloud uses the usernames as key to store and assign data. In order to
 +  precisely identify and recognize users, each LDAP user will have a internal
 +  username in ownCloud. This requires a mapping from ownCloud username to LDAP
 +  user. The created username is mapped to the UUID of the LDAP user.
 +  Additionally the DN is cached as well to reduce LDAP interaction, but it is
 +  not used for identification. If the DN changes, the change will be detected by
 +  ownCloud by checking the UUID value.
 +
 +  The same is valid for groups.
 +
 +  The internal ownCloud name is used all over in ownCloud. Clearing the Mappings
-   will have leftovers everywhere. Do never clear the mappings
++  will have leftovers everywhere. Never clear the mappings
 +  in a production environment. Only clear mappings in a testing or experimental
 +  stage.
 +
 +  **Clearing the Mappings is not configuration sensitive, it affects all LDAP
 +  configurations!**
 +
 +Testing the configuration
 +-------------------------
 +
- In this version we introduced the **Test Configuration** button on the bottom
- of the LDAP settings section. It will always check the values as currently
++The **Test Configuration** button on the bottom
++of the LDAP settings section will always check the values as currently
 +given in the input fields. You do not need to save before testing. By clicking
 +on the button, ownCloud will try to bind to the ownCloud server with the
 +settings currently given in the input fields. The response will look like this:
 +
 +.. figure:: ../images/ldap-settings-invalid-oc45.png
 +
 +   Failure
 +
 +In case the configuration fails, you can see details in ownCloud's log, which
 +is in the data directory and called **owncloud.log** or on the bottom the
 +**Settings →  Admin page**. Unfortunately it requires a reload – sorry for the
 +inconvenience.
 +
 +.. figure:: ../images/ldap-settings-valid-oc45.png
 +
 +   Success
 +
 +In this case, Save the settings. You can check if the users and groups are
 +fetched correctly on the Settings → Users page.
 +
 +ownCloud Avatar integration
 +---------------------------
 +
 +ownCloud 6 incorporates a user profile picture feature, called Avatar. If a user
 +has a photo stored in the *jpegPhoto* or, since 6.0.2, *thumbnailPhoto*
 +attribute, it will be used as Avatar. The user then is not able to change his
 +avatar in the personal settings. It must be done within LDAP. *jpegPhoto* is
 +preferred over *thumbnailPhoto*.
 +
 +.. figure:: ../images/ldap-fetched-avatar.png
 +
 +   Profile picture fetched from LDAP, Personal Settings
 +
 +If the *jpegPhoto* or *thumbnailPhoto* attribute is not set or empty, the
 +default ownCloud behaviour is active, i.e. the user will be able to set and
 +change his profile picture in the personal settings. If the user sets a profile
 +picture within ownCloud it will _not_ be stored in LDAP.
 +
 +The *jpegPhoto* or *thumbnailPhoto* attribute will be fetched once a day to make
 +sure the current photo from LDAP is used in ownCloud. If a picture is added
 +later, a possibly set profile picture will be overridden with the LDAP one. If a
 +photo stored in the *jpegPhoto* and/or *thumbnailPhoto* attribute is deleted
 +later, the last profile picture in ownCloud will still be used.
 +
 +The photo taken from LDAP will be adjusted to the requirements of the ownCloud
- avatar automatically. I.e. it will be transformed into a square. If the photo
++avatar automatically, i.e. it will be transformed into a square. If the photo
 +needs to be cut, it will be done equally from both affected sides. The original
 +photo stored in LDAP will stay the same, of course.
 +
 +Troubleshooting, Tips and Tricks
 +--------------------------------
 +
 +SSL Certificate Verification (LDAPS, TLS)
 +-----------------------------------------
 +
 +A common mistake with SSL certificates is that they may not be known to PHP.
 +If you have trouble with certificate validation make sure that
 +
 +* you have the certificate of the server installed on the ownCloud server
 +* the certificate is announced in the system's LDAP configuration file (usually
 +  */etc/ldap/ldap.conf* on Linux, *C:\\openldap\\sysconf\\ldap.conf* or
 +  *C:\\ldap.conf* on Windows) using a **TLS_CACERT /path/to/cert** line.
 +* Using LDAPS, also make sure that the port is correctly configured (by default
 +  686)
 +
 +Microsoft Active Directory
 +--------------------------
 +
 +Compared to earlier ownCloud versions, no further tweaks need to be done to
 +make ownCloud work with Active Directory. ownCloud will automatically find the
 +correct configuration in the wizard-like set up process.
 +
 +Duplicating Server Configurations
 +---------------------------------
 +
 +In case you have a working configuration and want to create a similar one or
 +"snapshot" configurations before modifying them you can do the following:
 +
 +#. Go to the **Server** tab
 +#. On **Server Configuration** choose *Add Server Configuration*
 +#. Answer the question *Take over settings from recent server configuration?*
 +   with *yes*.
 +#. (optional) Switch to **Advanced** tab and uncheck **Configuration Active**
 +   in the *Connection Settings*, so the new configuration is not used on Save
 +#. Click on **Save**
 +
 +Now you can modify the configuration and enable it if you wish.
 +
 +ownCloud LDAP Internals
 +-----------------------
 +
 +Some parts of how the LDAP backend works are described here. May it be helpful.
 +
 +Groups
 +------
 +
 +At the moment, only secondary groups are read. That means that only the groups
 +are retrieved, which are returned by the attribute auto-detected (or manually
- chosen) in Group-Member association. Primary groups are not being taken into
++chosen) in Group-Member association. Primary groups are not taken into
 +account.
 +
 +User and Group Mapping
 +----------------------
 +
 +In ownCloud the user or group name is used to have all relevant information in
 +the database assigned. To work reliably a permanent internal user name and
 +group name is created and mapped to the LDAP DN and UUID. If the DN changes in
 +LDAP it will be detected, there will be no conflicts.
 +
 +Those mappings are done in the database table ldap_user_mapping and
 +ldap_group_mapping. The user name is also used for the user's folder (except
 +something else is specified in *User Home Folder Naming Rule*), which
 +contains files and meta data.
 +
 +As of ownCloud 5 internal user name and a visible display name are separated.
 +This is not the case for group names, yet, i.e. group cannot be altered.
 +
 +That means that your LDAP configuration should be good and ready before putting
 +it into production. The mapping tables are filled early, but as long as you are
 +testing, you can empty the tables any time. Do not do this in production. If you
 +want to rename a group, be very careful. Do not rename the user's internal name.
 +
 +Caching
 +-------
 +
- For performance reasons a cache has been introduced to ownCloud. He we store
++For performance reasons a cache has been introduced to ownCloud. The cache stores
 +all users and groups, group memberships or internal userExists-requests. Since
 +ownCloud is written in PHP and each and every page request (also done by Ajax)
 +loads ownCloud and would execute one or more LDAP queries again, you do want to
 +have some of those queries cached and save those requests and traffic. It is
 +highly recommended to have the cache filled for a small amount of time, which
 +comes also very handy when using the sync client, as it is yet another request
 +for PHP.
 +
 +Handling with Backup Server
 +---------------------------
 +
- When ownCloud is not able to contact the main server, he will be treated as
++When ownCloud is not able to contact the main server, it will be treated as
 +offline and no connection attempts will be done for the time specified in
 +**Cache Time-To-Live**. If a backup server is configured, it will be connected
- instead. If you plan a maintained downtime, check **Disable Main Server** for
++instead. For planned downtime, check **Disable Main Server** for
 +the time being to avoid unnecessary connection attempts every now and then.
diff --cc core/doc/admin/configuration/auth_ldap.html
index abd280e,0000000..6bac9db
mode 100644,000000..100644
--- a/core/doc/admin/configuration/auth_ldap.html
+++ b/core/doc/admin/configuration/auth_ldap.html
@@@ -1,785 -1,0 +1,784 @@@
 +
 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 +  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 +
 +
 +<html xmlns="http://www.w3.org/1999/xhtml">
 +  <head>
 +    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 +    
 +    <title>LDAP Authentication — ownCloud Administrators Manual 6.0 documentation</title>
 +    
 +    <link rel="stylesheet" href="../_static/style.css" type="text/css" />
 +    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
 +    <link rel="stylesheet" href="../_static/style.css" type="text/css" />
 +    <link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
 +    
 +    <script type="text/javascript">
 +      var DOCUMENTATION_OPTIONS = {
 +        URL_ROOT:    '../',
 +        VERSION:     '6.0',
 +        COLLAPSE_INDEX: false,
 +        FILE_SUFFIX: '.html',
 +        HAS_SOURCE:  true
 +      };
 +    </script>
 +    <script type="text/javascript" src="../_static/jquery.js"></script>
 +    <script type="text/javascript" src="../_static/underscore.js"></script>
 +    <script type="text/javascript" src="../_static/doctools.js"></script>
 +    <script type="text/javascript" src="../_static/bootstrap.js"></script>
 +    <link rel="top" title="ownCloud Administrators Manual 6.0 documentation" href="../index.html" />
 +    <link rel="up" title="Configuration" href="index.html" />
 +    <link rel="next" title="Background Jobs" href="background_jobs.html" />
 +    <link rel="prev" title="User Management" href="configuration_users.html" />
 +<script type="text/javascript">
 +(function () {
 +  /**
 +   * Patch TOC list.
 +   *
 +   * Will mutate the underlying span to have a correct ul for nav.
 +   *
 +   * @param $span: Span containing nested UL's to mutate.
 +   * @param minLevel: Starting level for nested lists. (1: global, 2: local).
 +   */
 +  var patchToc = function ($ul, minLevel) {
 +    var findA;
 +
 +    // Find all a "internal" tags, traversing recursively.
 +    findA = function ($elem, level) {
 +      var level = level || 0,
 +        $items = $elem.find("> li > a.internal, > ul, > li > ul");
 +
 +      // Iterate everything in order.
 +      $items.each(function (index, item) {
 +        var $item = $(item),
 +          tag = item.tagName.toLowerCase(),
 +          pad = 15 + ((level - minLevel) * 10);
 +
 +        if (tag === 'a' && level >= minLevel) {
 +          // Add to existing padding.
 +          $item.css('padding-left', pad + "px");
 +          console.log(level, $item, 'padding-left', pad + "px");
 +        } else if (tag === 'ul') {
 +          // Recurse.
 +          findA($item, level + 1);
 +        }
 +      });
 +    };
 +
 +    console.log("HERE");
 +    findA($ul);
 +  };
 +
 +  $(document).ready(function () {
 +    // Add styling, structure to TOC's.
 +    $(".dropdown-menu").each(function () {
 +      $(this).find("ul").each(function (index, item){
 +        var $item = $(item);
 +        $item.addClass('unstyled');
 +      });
 +      $(this).find("li").each(function () {
 +        $(this).parent().append(this);
 +      });
 +    });
 +
 +    // Patch in level.
 +    patchToc($("ul.globaltoc"), 2);
 +    patchToc($("ul.localtoc"), 2);
 +
 +    // Enable dropdown.
 +    $('.dropdown-toggle').dropdown();
 +  });
 +}());
 +</script>
 +
 +  </head>
 +  <body>
 +  
 +
 +<div class="container">
 +  <div class="content">
 +    <div class="page-header">
 +      <h1><a href="../contents.html">ownCloud Administrators Manual</a></h1>
 +
 +    </div>
 +    
 +			<div class="row">
 +				<div class="span3">
 +					<div class="sidebar">
 +						<div class="well">
 +							<div class="menu-support-container">
 +								<ul id="menu-support" class="menu">
 +									<ul>
 +										<li><a href="../contents.html">Overview</a></li>
 +									</ul>
 +                  <ul>
 +<li class="toctree-l1"><a class="reference internal" href="../index.html">ownCloud 6.0 Admin Documentation</a></li>
 +</ul>
 +<ul class="current">
 +<li class="toctree-l1"><a class="reference internal" href="../installation/index.html">Installation</a></li>
 +<li class="toctree-l1 current"><a class="reference internal" href="index.html">Configuration</a><ul class="current">
 +<li class="toctree-l2"><a class="reference internal" href="configuration_apps.html">Managing Apps</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="configuration_users.html">User Management</a></li>
 +<li class="toctree-l2 current"><a class="current reference internal" href="">LDAP Authentication</a><ul>
 +<li class="toctree-l3"><a class="reference internal" href="#configuration">Configuration</a></li>
 +<li class="toctree-l3"><a class="reference internal" href="#advanced-settings">Advanced Settings</a></li>
 +<li class="toctree-l3"><a class="reference internal" href="#expert-settings">Expert Settings</a></li>
 +<li class="toctree-l3"><a class="reference internal" href="#testing-the-configuration">Testing the configuration</a></li>
 +<li class="toctree-l3"><a class="reference internal" href="#owncloud-avatar-integration">ownCloud Avatar integration</a></li>
 +<li class="toctree-l3"><a class="reference internal" href="#troubleshooting-tips-and-tricks">Troubleshooting, Tips and Tricks</a></li>
 +<li class="toctree-l3"><a class="reference internal" href="#ssl-certificate-verification-ldaps-tls">SSL Certificate Verification (LDAPS, TLS)</a></li>
 +<li class="toctree-l3"><a class="reference internal" href="#microsoft-active-directory">Microsoft Active Directory</a></li>
 +<li class="toctree-l3"><a class="reference internal" href="#duplicating-server-configurations">Duplicating Server Configurations</a></li>
 +<li class="toctree-l3"><a class="reference internal" href="#owncloud-ldap-internals">ownCloud LDAP Internals</a></li>
 +<li class="toctree-l3"><a class="reference internal" href="#groups">Groups</a></li>
 +<li class="toctree-l3"><a class="reference internal" href="#user-and-group-mapping">User and Group Mapping</a></li>
 +<li class="toctree-l3"><a class="reference internal" href="#caching">Caching</a></li>
 +<li class="toctree-l3"><a class="reference internal" href="#handling-with-backup-server">Handling with Backup Server</a></li>
 +</ul>
 +</li>
 +<li class="toctree-l2"><a class="reference internal" href="background_jobs.html">Background Jobs</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="configuration_3rdparty.html">Find Third-Party Libraries</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="configuration_automation.html">Automatic Configuration</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="configuration_custom_clients.html">Customizing Client Download Links</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="configuration_database.html">MySQL/Postgres/SQLite Support</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="configuration_encryption.html">Using Server-Side Encryption</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="configuration_knowledgebase.html">Disable Knowledge Base</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="configuration_language.html">Setting the Default Language</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="configuration_logging.html">Configure Logging</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="configuration_mail.html">Sending Mail Notifications</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="configuration_maintenance.html">Enable Maintenance Mode</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="configuration_preview.html">Enabling File Previews</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="configuration_reverseproxy.html">Reverse Proxy Configuration</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="configuring_big_file_upload.html">Dealing with Big File Uploads</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="custom_mount_config_gui.html">Custom Mount Configuration Web-GUI</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="custom_mount_config.html">Custom Mount Configuration</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="custom_user_backend.html">Custom User Backend Configuration</a></li>
 +<li class="toctree-l2"><a class="reference internal" href="xsendfile.html">Serving static files via web server</a></li>
 +</ul>
 +</li>
 +<li class="toctree-l1"><a class="reference internal" href="../apps/index.html">Apps</a></li>
 +<li class="toctree-l1"><a class="reference internal" href="../maintenance/index.html">Maintenance</a></li>
 +<li class="toctree-l1"><a class="reference internal" href="../config/index.html">The Configuration File</a></li>
 +<li class="toctree-l1"><a class="reference internal" href="../issues/index.html">Issues</a></li>
 +</ul>
 +
 +								</ul>
 +							</div>
 +						</div>
 +					</div>
 +				</div>
 +        
 +
 +				<div class="span9">
 +					<div class="page-content">
 +						
 +  <div class="section" id="ldap-authentication">
 +<h1>LDAP Authentication<a class="headerlink" href="#ldap-authentication" title="Permalink to this headline">¶</a></h1>
- <p>ownCloud ships an LDAP backend, which allows full use of ownCloud for user
++<p>ownCloud ships an LDAP backend, which allows full use of ownCloud for users
 +logging in with LDAP credentials including:</p>
 +<ul class="simple">
 +<li>LDAP group support</li>
 +<li>File sharing with users and groups</li>
 +<li>Access via WebDAV and of course ownCloud Desktop Client</li>
 +<li>Versioning, external Storages and all other ownCloud goodies</li>
 +</ul>
 +<p>To connect to an LDAP server the configuration needs to be set up properly.
 +Once the LDAP backend is activated (Apps Sidebar→Apps, choose <strong>LDAP user and
 +group backend</strong>, click on <strong>Enable</strong>) the configuration can be found on
 +Settings→Admin. Read on for a detailed description of the configuration fields.</p>
 +<div class="section" id="configuration">
 +<h2>Configuration<a class="headerlink" href="#configuration" title="Permalink to this headline">¶</a></h2>
- <p>The LDAP backend follows a wizard-like approach, splitted into four tabs. A
++<p>The LDAP backend configuration follows a wizard-like approach, split into four tabs. A
 +correctly completed first tab (“Server”) is mandatory to access the other tabs.
- Also, the other tabs need to be reviewed by the admin, however the necessary
- settings are detected automatically. An indicator will show whether the
- configuration is incomplete, incorrect or OK.</p>
- <p>The settings are changed automatically, as soon as a input element looses the
++The settings in the other tabs are detected automatically, but should be reviewed by the
++admin. An indicator will show whether the configuration is incomplete, incorrect or OK.</p>
++<p>The settings are changed automatically, as soon as a input element loses the
 +focus, i.e. the cursor is taken away by clicking somewhere else or pressing the
- tabulator key.</p>
++Tab key.</p>
 +<p>The other tabs can be navigated by clicking the tabs or by using the <em>Continue</em>
 +and <em>Back</em> buttons. They are located on the lower right, next to the status
 +indicator.</p>
 +<div class="section" id="server">
 +<h3>Server<a class="headerlink" href="#server" title="Permalink to this headline">¶</a></h3>
- <p>The server tab contains the basic information on the LDAP server. They make sure
++<p>The Server tab contains the basic information on the LDAP server. They make sure
 +that ownCloud will be able to connect to LDAP and be able to read data from
 +there. The admin at least needs to provide a hostname. If anonymous access is
 +not possible he will need to provide an account DN and a password, too. ownCloud
 +attempts to auto-detect the port and the base DN.</p>
 +<div class="figure">
 +<img alt="../_images/ldap-wizard-1-server.png" src="../_images/ldap-wizard-1-server.png" />
 +</div>
 +<dl class="docutils">
 +<dt>Server configuration:</dt>
 +<dd>ownCloud can be configured to connect to multiple LDAP servers. Using this
 +control you can pick a configuration you want to edit or add a new one. The
 +button <strong>Delete Configuration</strong> deletes the current configuration.</dd>
 +<dt>Host:</dt>
 +<dd><p class="first">The host name of the LDAP server. It can also be a <strong>ldaps://</strong> URI, for
 +instance.</p>
 +<p>It is also possible to pass a port number, which speeds up port detection. It
 +is especially useful, if a custom port is used. ownCloud will move the value
 +to the port field subsequently.</p>
 +<p>Examples:</p>
 +<ul class="last simple">
 +<li><em>directory.my-company.com</em></li>
 +<li><em>ldaps://directory.my-company.com</em></li>
 +<li><em>directory.my-company.com:9876</em></li>
 +</ul>
 +</dd>
 +<dt>Port:</dt>
 +<dd><p class="first">The port on which to connect to the LDAP server. The field is disabled in the
 +beginning of a new configuration. The port will be detected automatically,
 +if the LDAP server is running on a standard port. After ownCloud attempted to
 +determine the port, the field will be enabled for user input. A successfully
 +found port will be inserted by ownCloud, of course.</p>
 +<p>Example:</p>
 +<ul class="last simple">
 +<li><em>389</em></li>
 +</ul>
 +</dd>
 +<dt>User DN:</dt>
 +<dd><p class="first">The name as DN of a user who is able to do searches in the LDAP
 +directory. Leave it empty for anonymous access. It is recommended to have a
 +special system user for ownCloud.</p>
 +<p>Example:</p>
 +<ul class="last simple">
 +<li><em>uid=owncloudsystemuser,cn=sysusers,dc=my-company,dc=com</em></li>
 +</ul>
 +</dd>
 +<dt>Password:</dt>
 +<dd>The password for the user given above. Empty for anonymous access.</dd>
 +<dt>Base DN:</dt>
 +<dd><p class="first">The base DN of LDAP, from where all users and groups can be reached. Separated
 +Base DNs for users and groups can be set in the Advanced tab. Nevertheless,
 +this field is mandatory. ownCloud attempts to determine the Base DN according
 +to the provided User DN or the provided Host.</p>
 +<p>Example:</p>
 +<ul class="last simple">
 +<li><em>dc=my-company,dc=com</em></li>
 +</ul>
 +</dd>
 +</dl>
 +</div>
 +<div class="section" id="user-filter">
 +<h3>User Filter<a class="headerlink" href="#user-filter" title="Permalink to this headline">¶</a></h3>
- <p>The settings in the user filter tab determine which LDAP users will appear and
++<p>The settings in the User Filter tab determine which LDAP users will appear and
 +are allowed to log in into ownCloud. It is also possible to enter a raw LDAP
 +filter.</p>
 +<div class="figure">
 +<img alt="../_images/ldap-wizard-2-user.png" src="../_images/ldap-wizard-2-user.png" />
 +</div>
 +<dl class="docutils">
 +<dt>only those object classes:</dt>
- <dd>ownCloud will determine the object classes that are typically availalble for
++<dd>ownCloud will determine the object classes that are typically available for
 +(ideally only) user objects in your LDAP. ownCloud will automatically select
 +the object class that returns the highest amount of users. You can select
 +multiple object classes.</dd>
 +<dt>only from those groups:</dt>
 +<dd><p class="first">If your LDAP server supports the member-of-overlay in LDAP filters, you can
 +define that only users from one or more certain groups are allowed to
 +appear and log in into ownCloud. By default, no value will be selected. You
 +can select multiple groups.</p>
 +<p class="last">If your LDAP server does not support the member-of-overlay in LDAP filters,
 +the input field is disabled. Please contact your LDAP administrator.</p>
 +</dd>
 +<dt>Edit raw filter instead:</dt>
 +<dd><p class="first">Clicking on this text will toggle the filter mode. Instead of the assisted
 +approach, you can enter the raw LDAP filter directly in the appearing field.</p>
 +<p>Example:</p>
 +<ul class="last simple">
 +<li><em>objectClass=inetOrgPerson</em></li>
 +</ul>
 +</dd>
 +<dt>x users found:</dt>
 +<dd>This is an indicator that tells you approximately how many users will be
 +allowed to access ownCloud. The number will update after any change you do.</dd>
 +</dl>
 +</div>
 +<div class="section" id="login-filter">
 +<h3>Login Filter<a class="headerlink" href="#login-filter" title="Permalink to this headline">¶</a></h3>
- <p>The settings in the login filter tab determine which user detail will be
++<p>The settings in the Login Filter tab determine which user detail will be
 +compared to the login value entered by the user. It is possible to allow
 +multiple user details. It is also possible to enter a raw LDAP filter.</p>
 +<p>The user limitation as set up in the previous tab is in effect, unless you
 +manually configure the filter in raw mode.</p>
 +<div class="figure">
 +<img alt="../_images/ldap-wizard-3-login.png" src="../_images/ldap-wizard-3-login.png" />
 +</div>
 +<dl class="docutils">
 +<dt>LDAP Username:</dt>
 +<dd>If this value is checked, the login value will be compared to the username in
 +the LDAP directory. The corresponding attribute, usually <em>uid</em> or
 +<em>samaccountname</em> will be detected automatically by ownCloud.</dd>
 +<dt>LDAP Email Address:</dt>
 +<dd>If this value is checked, the login value will be compared to an email address
 +in the LDAP directory. The email address will be looked for in the
 +<em>mailPrimaryAddress</em> and <em>mail</em> attributes.</dd>
 +<dt>Other Attributes:</dt>
 +<dd>This multiselect box allows you to select other attributes for the comparison.
 +The list is generated automatically based on the attributes that a user object
 +contains in your LDAP server.</dd>
 +<dt>Edit raw filter instead:</dt>
 +<dd><p class="first">Clicking on this text will toggle the filter mode. Instead of the assisted
 +approach, you can enter the raw LDAP filter directly in the appearing field.</p>
 +<p>The <strong>%uid</strong> placeholder will be replaced with the login name entered by the user
 +upon login. When you enter the filter manually.</p>
 +<p>Examples:</p>
 +<ul class="last simple">
 +<li>only username: <em>uid=%uid</em></li>
 +<li>username or email address: <em>(|(uid=%uid)(mail=$uid))</em></li>
 +</ul>
 +</dd>
 +</dl>
 +</div>
 +<div class="section" id="group-filter">
 +<h3>Group Filter<a class="headerlink" href="#group-filter" title="Permalink to this headline">¶</a></h3>
- <p>The settings in the group filter tab determine which groups will be availalble
- in ownCloud. It does not have any restrictions on logins, this has been dealed
++<p>The settings in the Group Filter tab determine which groups will be available
++in ownCloud. It does not have any restrictions on logins, this has been dealt
 +with in the prior tabs.  It is also possible to enter a raw LDAP
 +filter.</p>
- <p>By default, no groups will be availalble in ownCloud. You actively need to
++<p>By default, no groups will be available in ownCloud. You actively need to
 +enable groups.</p>
 +<div class="figure">
 +<img alt="../_images/ldap-wizard-4-group.png" src="../_images/ldap-wizard-4-group.png" />
 +</div>
 +<dl class="docutils">
 +<dt>only those object classes:</dt>
- <dd>ownCloud will determine the object classes that are typically availalble for
++<dd>ownCloud will determine the object classes that are typically available for
 +(ideally only) group objects in your LDAP. ownCloud will only list object
 +classes that return at least one group object. You can select multiple
 +object classes. A typical object class is “group”, or “posixGroup”.</dd>
 +<dt>only from those groups:</dt>
- <dd>This setting lets you pick certain groups that shall be availalble in
++<dd>This setting lets you pick certain groups that shall be available in
 +ownCloud. This field follows a whitelist approach. ownCloud will generate a
 +list of available groups found in your LDAP server. You can select multiple
 +groups.</dd>
 +<dt>Edit raw filter instead:</dt>
 +<dd><p class="first">Clicking on this text will toggle the filter mode. Instead of the assisted
 +approach, you can enter the raw LDAP filter directly in the appearing field.</p>
 +<p>Example:</p>
 +<ul class="last simple">
 +<li><em>objectClass=group</em></li>
 +<li><em>objectClass=posixGroup</em></li>
 +</ul>
 +</dd>
 +<dt>y groups found:</dt>
 +<dd>This is an indicator that tells you approximately how many groups will be
 +available in  ownCloud. The number will update after any change you do.</dd>
 +</dl>
 +</div>
 +</div>
 +<div class="section" id="advanced-settings">
 +<h2>Advanced Settings<a class="headerlink" href="#advanced-settings" title="Permalink to this headline">¶</a></h2>
- <p>In the LDAP Advanced settings section you can define options, that are less
++<p>In the LDAP Advanced Settings section you can define options, that are less
 +common to set. They are not needed for a working connection. It can also have a
 +positive effect on the performance to specify distinguished bases for user and
 +group searches.</p>
 +<p>The Advanced Settings are structured into three parts:</p>
 +<ul class="simple">
 +<li>Connection Settings</li>
 +<li>Directory Settings</li>
 +<li>Special Attributes</li>
 +</ul>
 +<div class="section" id="connection-settings">
 +<h3>Connection Settings<a class="headerlink" href="#connection-settings" title="Permalink to this headline">¶</a></h3>
 +<div class="figure">
 +<img alt="../_images/ldap-advanced-1-connection.png" src="../_images/ldap-advanced-1-connection.png" />
 +<p class="caption">LDAP Advanced Settings, section Connection Settings</p>
 +</div>
 +<dl class="docutils">
 +<dt>Configuration Active:</dt>
 +<dd><p class="first">Enables or Disables the current configuration. Disabled configuration will not
 +connect to the LDAP server.</p>
 +<p class="last">By default, it is turned off. It will be automatically turned on, when using
 +the wizard and the configuration is OK and a test connection successful.</p>
 +</dd>
 +<dt>Backup (Replica) Host:</dt>
 +<dd><p class="first">A backup server can be defined here. ownCloud tries to connect to the backup
 +server automatically, when the main host (as specified in basic settings)
- cannot be reached. It is import that the backup server is a replica of the
++cannot be reached. It is important that the backup server is a replica of the
 +main server, because the object UUIDs must match.</p>
 +<p>Example:</p>
 +<ul class="last simple">
 +<li><em>directory2.my-company.com</em></li>
 +</ul>
 +</dd>
 +<dt>Backup (Replica) Port:</dt>
 +<dd><p class="first">The port on which to connect to the backup LDAP server. If no port is given,
 +but a host, then the main port (as specified above) will be used.</p>
 +<p>Example:</p>
 +<ul class="last simple">
 +<li><em>389</em></li>
 +</ul>
 +</dd>
 +<dt>Disable Main Server:</dt>
 +<dd>You can manually override the main server and make ownCloud only connect to
- the backup server. It may be handy for planned downtimes.</dd>
++the backup server. This may be handy for planned downtimes.</dd>
 +<dt>Case insensitive LDAP server (Windows):</dt>
- <dd>Whether the LDAP server is running on a Windows Host. Usually, it is not
++<dd>Whether the LDAP server is running on a Windows host. Usually, it is not
 +necessary to check it, however.</dd>
 +<dt>Turn off SSL certificate validation:</dt>
- <dd>Turns of check of valid SSL certificates. Use it – if needed –
++<dd>Turns off check of valid SSL certificates. Use it – if needed –
 +for testing, only!</dd>
 +<dt>Cache Time-To-Live:</dt>
 +<dd><p class="first">A cache is introduced to avoid unnecessary LDAP traffic,
- for example lookups check whether the users exists on every page request or
++for example lookups check whether the users exist on every page request or
 +WebDAV interaction. It is also supposed to speed up the Admin → User page or
 +list of users to share with, once it is populated. Saving the configuration
 +empties the cache (changes are not necessary). The time is given in seconds.</p>
 +<p>Note that almost every PHP request would require to build up a new connection
- to the LDAP server. If you require a most up-to-dateness it is recommended not
++to the LDAP server. If you require most up-to-dateness it is recommended not
 +to totally switch off the cache, but define a minimum life time of 15s.</p>
 +<p>Examples:</p>
 +<ul class="last simple">
 +<li>ten minutes: <em>600</em></li>
 +<li>one hour: <em>3600</em></li>
 +</ul>
 +</dd>
 +</dl>
 +</div>
 +<div class="section" id="directory-settings">
 +<h3>Directory Settings<a class="headerlink" href="#directory-settings" title="Permalink to this headline">¶</a></h3>
 +<div class="figure">
 +<img alt="../_images/ldap-advanced-2-directory.png" src="../_images/ldap-advanced-2-directory.png" />
 +<p class="caption">LDAP Advanced Settings, section Directory Settings</p>
 +</div>
 +<dl class="docutils">
 +<dt>User Display Name Field:</dt>
 +<dd><p class="first">The attribute that should be used as display name in ownCloud.</p>
 +<ul class="last simple">
 +<li>Example: <em>displayName</em></li>
 +</ul>
 +</dd>
 +<dt>Base User Tree:</dt>
 +<dd><p class="first">The base DN of LDAP, from where all users can be reached. It needs to be given
 +completely despite to the Base DN from the Basic settings. You can specify
 +multiple base trees, one in each line.</p>
 +<ul class="last">
 +<li><p class="first">Example:</p>
 +<div class="line-block">
 +<div class="line"><em>cn=programmers,dc=my-company,dc=com</em></div>
 +<div class="line"><em>cn=designers,dc=my-company,dc=com</em></div>
 +</div>
 +</li>
 +</ul>
 +</dd>
 +<dt>User Search Attributes:</dt>
 +<dd><p class="first">These attributes are used when a search for users is done. This happens, for
 +instance, in the share dialogue. By default the user display name attribute as
 +specified above is being used. Multiple attributes can be given, one in each
 +line.</p>
 +<p>Beware that if an attribute is not available on a user object, the user will
 +neither be listed (e.g. in the share dialogue) nor be able to login. This also
 +affects the display name attribute as specified above. If you override the
 +default, the display name attribute will not be taken into account, unless you
 +specify it as well.</p>
 +<ul class="last">
 +<li><p class="first">Example:</p>
 +<div class="line-block">
 +<div class="line"><em>displayName</em></div>
 +<div class="line"><em>mail</em></div>
 +</div>
 +</li>
 +</ul>
 +</dd>
 +<dt>Group Display Name Field:</dt>
 +<dd><p class="first">The attribute that should be used as ownCloud group name. ownCloud allows a
 +limited set of characters (a-zA-Z0-9.-_@), every other character will be
 +replaced in ownCloud. Once a group name is assigned, it will not be changed,
 +i.e. changing this value will only have effect to new LDAP groups.</p>
 +<ul class="last simple">
 +<li>Example: <em>cn</em></li>
 +</ul>
 +</dd>
 +<dt>Base Group Tree:</dt>
 +<dd><p class="first">The base DN of LDAP, from where all groups can be reached.
 +It needs to be given completely despite to the Base DN from the Basic
 +settings. You can specify multiple base trees, one in each line.</p>
 +<ul class="last">
 +<li><p class="first">Example:</p>
 +<div class="line-block">
 +<div class="line"><em>cn=barcelona,dc=my-company,dc=com</em></div>
 +<div class="line"><em>cn=madrid,dc=my-company,dc=com</em></div>
 +</div>
 +</li>
 +</ul>
 +</dd>
 +<dt>Group Search Attributes:</dt>
 +<dd><p class="first">These attributes are used when a search for groups is done. This happens, for
 +instance, in the share dialogue. By default the group display name attribute
 +as specified above is being used. Multiple attributes can be given, one in
 +each line.</p>
 +<p>If you override the default, the group display name attribute will not be
 +taken into account, unless you specify it as well.</p>
 +<ul class="last">
 +<li><p class="first">Example:</p>
 +<div class="line-block">
 +<div class="line"><em>cn</em></div>
 +<div class="line"><em>description</em></div>
 +</div>
 +</li>
 +</ul>
 +</dd>
 +<dt>Group Member association:</dt>
 +<dd><p class="first">The attribute that is used to indicate group memberships, i.e. the attribute
 +used by LDAP groups to refer to their users.</p>
- <p>ownCloud detects the value automatically, you should only change it, if you
++<p>ownCloud detects the value automatically. You should only change it if you
 +have a very valid reason and know what you are doing.</p>
 +<ul class="last simple">
 +<li>Example: <em>uniquemember</em></li>
 +</ul>
 +</dd>
 +</dl>
 +</div>
 +<div class="section" id="special-attributes">
 +<h3>Special Attributes<a class="headerlink" href="#special-attributes" title="Permalink to this headline">¶</a></h3>
 +<div class="figure">
 +<img alt="../_images/ldap-advanced-3-attributes.png" src="../_images/ldap-advanced-3-attributes.png" />
 +<p class="caption">LDAP Advanced Settings, section Special Attributes</p>
 +</div>
 +<dl class="docutils">
 +<dt>Quota Field:</dt>
 +<dd><p class="first">ownCloud can read an LDAP attribute and set the user quota according to its
 +value. Specify the attribute here, otherwise keep it empty. The attribute
 +shall return human readable values, e.g. “2 GB”.</p>
 +<ul class="last simple">
 +<li>Example: <em>ownCloudQuota</em></li>
 +</ul>
 +</dd>
 +<dt>Quota Default:</dt>
 +<dd><p class="first">Override ownCloud default quota for LDAP users who do not
 +have a quota set in the attribute given above.</p>
 +<ul class="last simple">
 +<li>Example: <em>15 GB</em></li>
 +</ul>
 +</dd>
 +<dt>Email Field:</dt>
 +<dd><p class="first">ownCloud can read an LDAP attribute and set the user email
 +there from. Specify the attribute here, otherwise keep it empty.</p>
 +<p>Although the wizard offers you to check login by email, the correct email
 +attribute is not detected and you need to specify it manually.</p>
 +<ul class="last simple">
 +<li>Example: <em>mail</em></li>
 +</ul>
 +</dd>
 +<dt>User Home Folder Naming Rule:</dt>
 +<dd><p class="first">By default, the ownCloud creates the user
 +directory, where all files and meta data are kept, according to the ownCloud
 +user name. You may want to override this setting and name it after an
 +attribute value. The attribute given can also return an absolute path, e.g.
 +<tt class="docutils literal"><span class="pre">/mnt/storage43/alice</span></tt>. Leave it empty for default behavior.</p>
 +<ul class="last simple">
 +<li>Example: <em>cn</em></li>
 +</ul>
 +</dd>
 +</dl>
 +</div>
 +</div>
 +<div class="section" id="expert-settings">
 +<h2>Expert Settings<a class="headerlink" href="#expert-settings" title="Permalink to this headline">¶</a></h2>
 +<div class="figure">
 +<img alt="../_images/ldap-expert.png" src="../_images/ldap-expert.png" />
 +</div>
 +<p>In the Expert Settings fundamental behavior can be adjusted to your needs. The
 +configuration should be done before starting production use or when testing the
 +installation.</p>
 +<dl class="docutils">
 +<dt>Internal Username:</dt>
 +<dd><p class="first">The internal username is the identifier in ownCloud for LDAP users. By default
 +it will be created from the UUID attribute. By using the UUID attribute it is
 +made sure that the username is unique and characters do not need to be
 +converted. The internal username has the restriction that only these
 +characters are allowed: [a-zA-Z0-9_.@-]. Other characters are replaced with
 +their ASCII correspondence or are simply omitted.</p>
 +<p>The LDAP backend ensures that there are no duplicate internal usernames in
 +ownCloud, i.e. that it is checking all other activated user backends
 +(including local ownCloud users). On collisions a random number (between 1000
 +and 9999) will be attached to the retrieved value. For example, if “alice”
 +exists, the next username may be “alice_1337”.</p>
 +<p>The internal username is also the default name for the user home folder in
 +ownCloud. It is also a part of remote URLs, for instance for all *DAV services.
 +With this setting the default behaviour can be overridden.</p>
 +<p>Leave it empty for default behaviour. Changes will have effect only on newly
 +mapped (added) LDAP users.</p>
 +<ul class="last simple">
 +<li>Example: <em>uid</em></li>
 +</ul>
 +</dd>
 +<dt>Override UUID detection</dt>
 +<dd><p class="first">By default, ownCloud auto-detects the UUID attribute. The UUID attribute is
 +used to doubtlessly identify LDAP users and groups. Also, the internal
 +username will be created based on the UUID, if not specified otherwise above.</p>
 +<p>You can override the setting and pass an attribute of your choice. You must
 +make sure that the attribute of your choice can be fetched for both users and
 +groups and it is unique. Leave it empty for default behaviour. Changes will
 +have effect only on newly mapped (added) LDAP users and groups. It also will
- have effect when a user’s or group’s DN changes and an old UUID was cached: It
++have effect when a user’s or group’s DN changes and an old UUID was cached: it
 +will result in a new user. Because of this, the setting should be applied
 +before putting ownCloud in production use and cleaning the bindings
 +(see below).</p>
 +<ul class="last simple">
 +<li>Example: <em>cn</em></li>
 +</ul>
 +</dd>
 +<dt>Username-LDAP User Mapping</dt>
 +<dd><p class="first">ownCloud uses the usernames as key to store and assign data. In order to
 +precisely identify and recognize users, each LDAP user will have a internal
 +username in ownCloud. This requires a mapping from ownCloud username to LDAP
 +user. The created username is mapped to the UUID of the LDAP user.
 +Additionally the DN is cached as well to reduce LDAP interaction, but it is
 +not used for identification. If the DN changes, the change will be detected by
 +ownCloud by checking the UUID value.</p>
 +<p>The same is valid for groups.</p>
 +<p>The internal ownCloud name is used all over in ownCloud. Clearing the Mappings
- will have leftovers everywhere. Do never clear the mappings
++will have leftovers everywhere. Never clear the mappings
 +in a production environment. Only clear mappings in a testing or experimental
 +stage.</p>
 +<p class="last"><strong>Clearing the Mappings is not configuration sensitive, it affects all LDAP
 +configurations!</strong></p>
 +</dd>
 +</dl>
 +</div>
 +<div class="section" id="testing-the-configuration">
 +<h2>Testing the configuration<a class="headerlink" href="#testing-the-configuration" title="Permalink to this headline">¶</a></h2>
- <p>In this version we introduced the <strong>Test Configuration</strong> button on the bottom
- of the LDAP settings section. It will always check the values as currently
++<p>The <strong>Test Configuration</strong> button on the bottom
++of the LDAP settings section will always check the values as currently
 +given in the input fields. You do not need to save before testing. By clicking
 +on the button, ownCloud will try to bind to the ownCloud server with the
 +settings currently given in the input fields. The response will look like this:</p>
 +<div class="figure">
 +<img alt="../_images/ldap-settings-invalid-oc45.png" src="../_images/ldap-settings-invalid-oc45.png" />
 +<p class="caption">Failure</p>
 +</div>
 +<p>In case the configuration fails, you can see details in ownCloud’s log, which
 +is in the data directory and called <strong>owncloud.log</strong> or on the bottom the
 +<strong>Settings →  Admin page</strong>. Unfortunately it requires a reload – sorry for the
 +inconvenience.</p>
 +<div class="figure">
 +<img alt="../_images/ldap-settings-valid-oc45.png" src="../_images/ldap-settings-valid-oc45.png" />
 +<p class="caption">Success</p>
 +</div>
 +<p>In this case, Save the settings. You can check if the users and groups are
 +fetched correctly on the Settings → Users page.</p>
 +</div>
 +<div class="section" id="owncloud-avatar-integration">
 +<h2>ownCloud Avatar integration<a class="headerlink" href="#owncloud-avatar-integration" title="Permalink to this headline">¶</a></h2>
 +<p>ownCloud 6 incorporates a user profile picture feature, called Avatar. If a user
 +has a photo stored in the <em>jpegPhoto</em> or, since 6.0.2, <em>thumbnailPhoto</em>
 +attribute, it will be used as Avatar. The user then is not able to change his
 +avatar in the personal settings. It must be done within LDAP. <em>jpegPhoto</em> is
 +preferred over <em>thumbnailPhoto</em>.</p>
 +<div class="figure">
 +<img alt="../_images/ldap-fetched-avatar.png" src="../_images/ldap-fetched-avatar.png" />
 +<p class="caption">Profile picture fetched from LDAP, Personal Settings</p>
 +</div>
 +<p>If the <em>jpegPhoto</em> or <em>thumbnailPhoto</em> attribute is not set or empty, the
 +default ownCloud behaviour is active, i.e. the user will be able to set and
 +change his profile picture in the personal settings. If the user sets a profile
 +picture within ownCloud it will _not_ be stored in LDAP.</p>
 +<p>The <em>jpegPhoto</em> or <em>thumbnailPhoto</em> attribute will be fetched once a day to make
 +sure the current photo from LDAP is used in ownCloud. If a picture is added
 +later, a possibly set profile picture will be overridden with the LDAP one. If a
 +photo stored in the <em>jpegPhoto</em> and/or <em>thumbnailPhoto</em> attribute is deleted
 +later, the last profile picture in ownCloud will still be used.</p>
 +<p>The photo taken from LDAP will be adjusted to the requirements of the ownCloud
- avatar automatically. I.e. it will be transformed into a square. If the photo
++avatar automatically, i.e. it will be transformed into a square. If the photo
 +needs to be cut, it will be done equally from both affected sides. The original
 +photo stored in LDAP will stay the same, of course.</p>
 +</div>
 +<div class="section" id="troubleshooting-tips-and-tricks">
 +<h2>Troubleshooting, Tips and Tricks<a class="headerlink" href="#troubleshooting-tips-and-tricks" title="Permalink to this headline">¶</a></h2>
 +</div>
 +<div class="section" id="ssl-certificate-verification-ldaps-tls">
 +<h2>SSL Certificate Verification (LDAPS, TLS)<a class="headerlink" href="#ssl-certificate-verification-ldaps-tls" title="Permalink to this headline">¶</a></h2>
 +<p>A common mistake with SSL certificates is that they may not be known to PHP.
 +If you have trouble with certificate validation make sure that</p>
 +<ul class="simple">
 +<li>you have the certificate of the server installed on the ownCloud server</li>
 +<li>the certificate is announced in the system’s LDAP configuration file (usually
 +<em>/etc/ldap/ldap.conf</em> on Linux, <em>C:\openldap\sysconf\ldap.conf</em> or
 +<em>C:\ldap.conf</em> on Windows) using a <strong>TLS_CACERT /path/to/cert</strong> line.</li>
 +<li>Using LDAPS, also make sure that the port is correctly configured (by default
 +686)</li>
 +</ul>
 +</div>
 +<div class="section" id="microsoft-active-directory">
 +<h2>Microsoft Active Directory<a class="headerlink" href="#microsoft-active-directory" title="Permalink to this headline">¶</a></h2>
 +<p>Compared to earlier ownCloud versions, no further tweaks need to be done to
 +make ownCloud work with Active Directory. ownCloud will automatically find the
 +correct configuration in the wizard-like set up process.</p>
 +</div>
 +<div class="section" id="duplicating-server-configurations">
 +<h2>Duplicating Server Configurations<a class="headerlink" href="#duplicating-server-configurations" title="Permalink to this headline">¶</a></h2>
 +<p>In case you have a working configuration and want to create a similar one or
 +“snapshot” configurations before modifying them you can do the following:</p>
 +<ol class="arabic simple">
 +<li>Go to the <strong>Server</strong> tab</li>
 +<li>On <strong>Server Configuration</strong> choose <em>Add Server Configuration</em></li>
 +<li>Answer the question <em>Take over settings from recent server configuration?</em>
 +with <em>yes</em>.</li>
 +<li>(optional) Switch to <strong>Advanced</strong> tab and uncheck <strong>Configuration Active</strong>
 +in the <em>Connection Settings</em>, so the new configuration is not used on Save</li>
 +<li>Click on <strong>Save</strong></li>
 +</ol>
 +<p>Now you can modify the configuration and enable it if you wish.</p>
 +</div>
 +<div class="section" id="owncloud-ldap-internals">
 +<h2>ownCloud LDAP Internals<a class="headerlink" href="#owncloud-ldap-internals" title="Permalink to this headline">¶</a></h2>
 +<p>Some parts of how the LDAP backend works are described here. May it be helpful.</p>
 +</div>
 +<div class="section" id="groups">
 +<h2>Groups<a class="headerlink" href="#groups" title="Permalink to this headline">¶</a></h2>
 +<p>At the moment, only secondary groups are read. That means that only the groups
 +are retrieved, which are returned by the attribute auto-detected (or manually
- chosen) in Group-Member association. Primary groups are not being taken into
++chosen) in Group-Member association. Primary groups are not taken into
 +account.</p>
 +</div>
 +<div class="section" id="user-and-group-mapping">
 +<h2>User and Group Mapping<a class="headerlink" href="#user-and-group-mapping" title="Permalink to this headline">¶</a></h2>
 +<p>In ownCloud the user or group name is used to have all relevant information in
 +the database assigned. To work reliably a permanent internal user name and
 +group name is created and mapped to the LDAP DN and UUID. If the DN changes in
 +LDAP it will be detected, there will be no conflicts.</p>
 +<p>Those mappings are done in the database table ldap_user_mapping and
 +ldap_group_mapping. The user name is also used for the user’s folder (except
 +something else is specified in <em>User Home Folder Naming Rule</em>), which
 +contains files and meta data.</p>
 +<p>As of ownCloud 5 internal user name and a visible display name are separated.
 +This is not the case for group names, yet, i.e. group cannot be altered.</p>
 +<p>That means that your LDAP configuration should be good and ready before putting
 +it into production. The mapping tables are filled early, but as long as you are
 +testing, you can empty the tables any time. Do not do this in production. If you
 +want to rename a group, be very careful. Do not rename the user’s internal name.</p>
 +</div>
 +<div class="section" id="caching">
 +<h2>Caching<a class="headerlink" href="#caching" title="Permalink to this headline">¶</a></h2>
- <p>For performance reasons a cache has been introduced to ownCloud. He we store
++<p>For performance reasons a cache has been introduced to ownCloud. The cache stores
 +all users and groups, group memberships or internal userExists-requests. Since
 +ownCloud is written in PHP and each and every page request (also done by Ajax)
 +loads ownCloud and would execute one or more LDAP queries again, you do want to
 +have some of those queries cached and save those requests and traffic. It is
 +highly recommended to have the cache filled for a small amount of time, which
 +comes also very handy when using the sync client, as it is yet another request
 +for PHP.</p>
 +</div>
 +<div class="section" id="handling-with-backup-server">
 +<h2>Handling with Backup Server<a class="headerlink" href="#handling-with-backup-server" title="Permalink to this headline">¶</a></h2>
- <p>When ownCloud is not able to contact the main server, he will be treated as
++<p>When ownCloud is not able to contact the main server, it will be treated as
 +offline and no connection attempts will be done for the time specified in
 +<strong>Cache Time-To-Live</strong>. If a backup server is configured, it will be connected
- instead. If you plan a maintained downtime, check <strong>Disable Main Server</strong> for
++instead. For planned downtime, check <strong>Disable Main Server</strong> for
 +the time being to avoid unnecessary connection attempts every now and then.</p>
 +</div>
 +</div>
 +
 +
 +					</div>
 +				</div>
 +			</div>
 +    
 +  </div>
 +</div>
 +  </body>
 +</html>
diff --cc core/skeleton/ownCloudUserManual.pdf
index f883ee7,0000000..628f538
mode 100644,000000..100644
Binary files differ
diff --cc version.php
index 31c9a1b,6a900f8..d55a56e
--- a/version.php
+++ b/version.php
@@@ -1,6 -1,17 +1,6 @@@
 -<?php
 -
 -// We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel when updating major/minor version number.
 -$OC_Version=array(6, 0, 3, 0);
 -
 -// The human readable string
 -$OC_VersionString='6.0.3 RC1';
 -
 -// The ownCloud edition
 -$OC_Edition='';
 -
 -// The ownCloud channel
 -$OC_Channel='git';
 -
 -// The build number
 -$OC_Build='';
 -
 +<?php 
- $OC_Version = array(6,0,2,5);
- $OC_VersionString = '6.0.2';
++$OC_Version = array(6,0,3,0);
++$OC_VersionString = '6.0.3 RC1';
 +$OC_Edition = '';
- $OC_Channel = 'daily';
- $OC_Build = '2014-04-18T03:13:40+00:00';
++$OC_Channel = 'testing';
++$OC_Build = '2014-04-23T16:23:29+00:00';

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud.git



More information about the Pkg-owncloud-commits mailing list