diff --git a/apps/dav/appinfo/register_command.php b/apps/dav/appinfo/register_command.php
index 1f0df054110cf5f7f1575dd8c0b050b5dba5c078..af41036cddcd37a02249f86457bf4ec17c1c7dae 100644
--- a/apps/dav/appinfo/register_command.php
+++ b/apps/dav/appinfo/register_command.php
@@ -2,7 +2,9 @@
 
 use OCA\DAV\Command\CreateAddressBook;
 use OCA\DAV\Command\CreateCalendar;
+use OCA\DAV\Command\SyncSystemAddressBook;
 
+$config = \OC::$server->getConfig();
 $dbConnection = \OC::$server->getDatabaseConnection();
 $userManager = OC::$server->getUserManager();
 $config = \OC::$server->getConfig();
@@ -10,3 +12,4 @@ $config = \OC::$server->getConfig();
 /** @var Symfony\Component\Console\Application $application */
 $application->add(new CreateAddressBook($userManager, $dbConnection, $config));
 $application->add(new CreateCalendar($userManager, $dbConnection));
+$application->add(new SyncSystemAddressBook($userManager, $dbConnection, $config));
diff --git a/apps/dav/command/syncsystemaddressbook.php b/apps/dav/command/syncsystemaddressbook.php
new file mode 100644
index 0000000000000000000000000000000000000000..bb2896abc60facfab2bc6de9fc8b60a254a53a6d
--- /dev/null
+++ b/apps/dav/command/syncsystemaddressbook.php
@@ -0,0 +1,107 @@
+<?php
+
+namespace OCA\DAV\Command;
+
+use OCA\DAV\CardDAV\CardDavBackend;
+use OCA\DAV\CardDAV\Converter;
+use OCA\DAV\Connector\Sabre\Principal;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\IUser;
+use OCP\IUserManager;
+use Sabre\CardDAV\Plugin;
+use Sabre\VObject\Component\VCard;
+use Sabre\VObject\Property\Text;
+use Sabre\VObject\Reader;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Helper\ProgressBar;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class SyncSystemAddressBook extends Command {
+
+	/** @var IUserManager */
+	protected $userManager;
+
+	/** @var \OCP\IDBConnection */
+	protected $dbConnection;
+
+	/** @var IConfig */
+	protected $config;
+
+	/** @var CardDavBackend */
+	private $backend;
+
+	/**
+	 * @param IUserManager $userManager
+	 * @param IDBConnection $dbConnection
+	 * @param IConfig $config
+	 */
+	function __construct(IUserManager $userManager, IDBConnection $dbConnection, IConfig $config) {
+		parent::__construct();
+		$this->userManager = $userManager;
+		$this->dbConnection = $dbConnection;
+		$this->config = $config;
+	}
+
+	protected function configure() {
+		$this
+			->setName('dav:sync-system-addressbook')
+			->setDescription('Synchronizes users to the system addressbook');
+	}
+
+	/**
+	 * @param InputInterface $input
+	 * @param OutputInterface $output
+	 */
+	protected function execute(InputInterface $input, OutputInterface $output) {
+		$principalBackend = new Principal(
+				$this->config,
+				$this->userManager
+		);
+
+		$this->backend = new CardDavBackend($this->dbConnection, $principalBackend);
+
+		// ensure system addressbook exists
+		$systemAddressBook = $this->ensureSystemAddressBookExists();
+		$converter = new Converter();
+
+		$output->writeln('Syncing users ...');
+		$progress = new ProgressBar($output);
+		$progress->start();
+		$this->userManager->callForAllUsers(function($user) use ($systemAddressBook, $converter, $progress) {
+			/** @var IUser $user */
+			$name = $user->getBackendClassName();
+			$userId = $user->getUID();
+
+			$cardId = "$name:$userId.vcf";
+			$card = $this->backend->getCard($systemAddressBook['id'], $cardId);
+			if ($card === false) {
+				$vCard = $converter->createCardFromUser($user);
+				$this->backend->createCard($systemAddressBook['id'], $cardId, $vCard->serialize());
+			} else {
+				$vCard = Reader::read($card['carddata']);
+				if ($converter->updateCard($vCard, $user)) {
+					$this->backend->updateCard($systemAddressBook['id'], $cardId, $vCard->serialize());
+				}
+			}
+			$progress->advance();
+		});
+		$progress->finish();
+		$output->writeln('');
+	}
+
+	protected function ensureSystemAddressBookExists() {
+		$book = $this->backend->getAddressBooksByUri('system');
+		if (!is_null($book)) {
+			return $book;
+		}
+		$systemPrincipal = "principals/system/system";
+		$this->backend->createAddressBook($systemPrincipal, 'system', [
+			'{' . Plugin::NS_CARDDAV . '}addressbook-description' => 'System addressbook which holds all users of this instance'
+		]);
+
+		return $this->backend->getAddressBooksByUri('system');
+	}
+}
diff --git a/apps/dav/lib/carddav/addressbook.php b/apps/dav/lib/carddav/addressbook.php
index eff1ad321e5d4a9bef943d94cc613753020fbaf4..507657e968219c2302c1f0bef7d76a907fba5598 100644
--- a/apps/dav/lib/carddav/addressbook.php
+++ b/apps/dav/lib/carddav/addressbook.php
@@ -3,6 +3,7 @@
 namespace OCA\DAV\CardDAV;
 
 use OCA\DAV\CardDAV\Sharing\IShareableAddressBook;
+use Sabre\DAV\Exception\NotFound;
 
 class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareableAddressBook {
 
@@ -51,4 +52,39 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareableAddres
 		$carddavBackend = $this->carddavBackend;
 		$carddavBackend->getShares($this->getName());
 	}
+
+	function getACL() {
+		$acl = parent::getACL();
+		if ($this->getOwner() === 'principals/system/system') {
+			$acl[] = [
+					'privilege' => '{DAV:}read',
+					'principal' => '{DAV:}authenticated',
+					'protected' => true,
+			];
+		}
+
+		return $acl;
+	}
+
+	function getChildACL() {
+		$acl = parent::getChildACL();
+		if ($this->getOwner() === 'principals/system/system') {
+			$acl[] = [
+					'privilege' => '{DAV:}read',
+					'principal' => '{DAV:}authenticated',
+					'protected' => true,
+			];
+		}
+
+		return $acl;
+	}
+
+	function getChild($name) {
+		$obj = $this->carddavBackend->getCard($this->addressBookInfo['id'], $name);
+		if (!$obj) {
+			throw new NotFound('Card not found');
+		}
+		return new Card($this->carddavBackend, $this->addressBookInfo, $obj);
+	}
+
 }
diff --git a/apps/dav/lib/carddav/addressbookroot.php b/apps/dav/lib/carddav/addressbookroot.php
index ee99ac8d7989dd19b53d70d07ca04ec44a706464..8c78d0245562dcec37302ea693da711449207dbf 100644
--- a/apps/dav/lib/carddav/addressbookroot.php
+++ b/apps/dav/lib/carddav/addressbookroot.php
@@ -20,4 +20,14 @@ class AddressBookRoot extends \Sabre\CardDAV\AddressBookRoot {
 
 	}
 
-}
\ No newline at end of file
+	function getName() {
+
+		// Grabbing all the components of the principal path.
+		$parts = explode('/', $this->principalPrefix);
+
+		// We are only interested in the second part.
+		return $parts[1];
+
+	}
+
+}
diff --git a/apps/dav/lib/carddav/card.php b/apps/dav/lib/carddav/card.php
new file mode 100644
index 0000000000000000000000000000000000000000..cea0b1e41c747132e9d73a82857bc63890067909
--- /dev/null
+++ b/apps/dav/lib/carddav/card.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\DAV\CardDAV;
+
+class Card extends \Sabre\CardDAV\Card {
+
+	function getACL() {
+		$acl = parent::getACL();
+		if ($this->getOwner() === 'principals/system/system') {
+			$acl[] = [
+				'privilege' => '{DAV:}read',
+				'principal' => '{DAV:}authenticated',
+				'protected' => true,
+			];
+		}
+
+		return $acl;
+	}
+
+}
diff --git a/apps/dav/lib/carddav/carddavbackend.php b/apps/dav/lib/carddav/carddavbackend.php
index daa31725fa1db37c767dfb68bbece4a4b3bf73a0..29b056672b4ebde520649428b17452e1bb84bba8 100644
--- a/apps/dav/lib/carddav/carddavbackend.php
+++ b/apps/dav/lib/carddav/carddavbackend.php
@@ -108,7 +108,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
 		return $addressBooks;
 	}
 
-	private function getAddressBooksByUri($addressBookUri) {
+	public function getAddressBooksByUri($addressBookUri) {
 		$query = $this->db->getQueryBuilder();
 		$result = $query->select(['id', 'uri', 'displayname', 'principaluri', 'description', 'synctoken'])
 			->from('addressbooks')
@@ -117,10 +117,10 @@ class CardDavBackend implements BackendInterface, SyncSupport {
 			->execute();
 
 		$row = $result->fetch();
-		if (is_null($row)) {
+		$result->closeCursor();
+		if ($row === false) {
 			return null;
 		}
-		$result->closeCursor();
 
 		return [
 				'id'  => $row['id'],
diff --git a/apps/dav/lib/carddav/converter.php b/apps/dav/lib/carddav/converter.php
new file mode 100644
index 0000000000000000000000000000000000000000..56b73eba4c0eb6d017375a61228c216e460b601b
--- /dev/null
+++ b/apps/dav/lib/carddav/converter.php
@@ -0,0 +1,158 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\DAV\CardDAV;
+
+use OCP\IImage;
+use OCP\IUser;
+use Sabre\VObject\Component\VCard;
+use Sabre\VObject\Property\Text;
+
+class Converter {
+
+	/**
+	 * @param IUser $user
+	 * @return VCard
+	 */
+	public function createCardFromUser(IUser $user) {
+
+		$uid = $user->getUID();
+		$displayName = $user->getDisplayName();
+		$displayName = empty($displayName ) ? $uid : $displayName;
+		$emailAddress = $user->getEMailAddress();
+		$cloudId = $user->getCloudId();
+		$image = $user->getAvatarImage(-1);
+
+		$vCard = new VCard();
+		$vCard->add(new Text($vCard, 'UID', $uid));
+		if (!empty($displayName)) {
+			$vCard->add(new Text($vCard, 'FN', $displayName));
+			$vCard->add(new Text($vCard, 'N', $this->splitFullName($displayName)));
+		}
+		if (!empty($emailAddress)) {
+			$vCard->add(new Text($vCard, 'EMAIL', $emailAddress, ['TYPE' => 'OTHER']));
+		}
+		if (!empty($cloudId)) {
+			$vCard->add(new Text($vCard, 'CLOUD', $cloudId));
+		}
+		if ($image) {
+			$vCard->add('PHOTO', $image->data(), ['ENCODING' => 'b', 'TYPE' => $image->mimeType()]);
+		}
+		$vCard->validate();
+
+		return $vCard;
+	}
+
+	/**
+	 * @param VCard $vCard
+	 * @param IUser $user
+	 * @return bool
+	 */
+	public function updateCard(VCard $vCard, IUser $user) {
+		$uid = $user->getUID();
+		$displayName = $user->getDisplayName();
+		$displayName = empty($displayName ) ? $uid : $displayName;
+		$emailAddress = $user->getEMailAddress();
+		$cloudId = $user->getCloudId();
+		$image = $user->getAvatarImage(-1);
+
+		$updated = false;
+		if($this->propertyNeedsUpdate($vCard, 'FN', $displayName)) {
+			$vCard->FN = new Text($vCard, 'FN', $displayName);
+			unset($vCard->N);
+			$vCard->add(new Text($vCard, 'N', $this->splitFullName($displayName)));
+			$updated = true;
+		}
+		if($this->propertyNeedsUpdate($vCard, 'EMAIL', $emailAddress)) {
+			$vCard->EMAIL = new Text($vCard, 'EMAIL', $emailAddress);
+			$updated = true;
+		}
+		if($this->propertyNeedsUpdate($vCard, 'CLOUD', $cloudId)) {
+			$vCard->CLOUD = new Text($vCard, 'CLOUD', $cloudId);
+			$updated = true;
+		}
+
+		if($this->propertyNeedsUpdate($vCard, 'PHOTO', $image)) {
+			$vCard->add('PHOTO', $image->data(), ['ENCODING' => 'b', 'TYPE' => $image->mimeType()]);
+			$updated = true;
+		}
+
+		if (empty($emailAddress) && !is_null($vCard->EMAIL)) {
+			unset($vCard->EMAIL);
+			$updated = true;
+		}
+		if (empty($cloudId) && !is_null($vCard->CLOUD)) {
+			unset($vCard->CLOUD);
+			$updated = true;
+		}
+		if (empty($image) && !is_null($vCard->PHOTO)) {
+			unset($vCard->PHOTO);
+			$updated = true;
+		}
+
+		return $updated;
+	}
+
+	/**
+	 * @param VCard $vCard
+	 * @param string $name
+	 * @param string|IImage $newValue
+	 * @return bool
+	 */
+	private function propertyNeedsUpdate(VCard $vCard, $name, $newValue) {
+		if (is_null($newValue)) {
+			return false;
+		}
+		$value = $vCard->__get($name);
+		if (!is_null($value)) {
+			$value = $value->getValue();
+			$newValue = $newValue instanceof IImage ? $newValue->data() : $newValue;
+
+			return $value !== $newValue;
+		}
+		return true;
+	}
+
+	/**
+	 * @param string $fullName
+	 * @return string[]
+	 */
+	public function splitFullName($fullName) {
+		// Very basic western style parsing. I'm not gonna implement
+		// https://github.com/android/platform_packages_providers_contactsprovider/blob/master/src/com/android/providers/contacts/NameSplitter.java ;)
+
+		$elements = explode(' ', $fullName);
+		$result = ['', '', '', '', ''];
+		if (count($elements) > 2) {
+			$result[0] = implode(' ', array_slice($elements, count($elements)-1));
+			$result[1] = $elements[0];
+			$result[2] = implode(' ', array_slice($elements, 1, count($elements)-2));
+		} elseif (count($elements) === 2) {
+			$result[0] = $elements[1];
+			$result[1] = $elements[0];
+		} else {
+			$result[0] = $elements[0];
+		}
+
+		return $result;
+	}
+
+}
diff --git a/apps/dav/lib/carddav/plugin.php b/apps/dav/lib/carddav/plugin.php
new file mode 100644
index 0000000000000000000000000000000000000000..f2b3dcbfda9faf494430deecfbc3fa1c7c92dde0
--- /dev/null
+++ b/apps/dav/lib/carddav/plugin.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\DAV\CardDAV;
+
+use Sabre\HTTP\URLUtil;
+
+class Plugin extends \Sabre\CardDAV\Plugin {
+
+	/**
+	 * Returns the addressbook home for a given principal
+	 *
+	 * @param string $principal
+	 * @return string
+	 */
+	protected function getAddressbookHomeForPrincipal($principal) {
+
+		if (strrpos($principal, 'principals/users', -strlen($principal)) !== FALSE) {
+			list(, $principalId) = URLUtil::splitPath($principal);
+			return self::ADDRESSBOOK_ROOT . '/users/' . $principalId;
+		}
+		if (strrpos($principal, 'principals/system', -strlen($principal)) !== FALSE) {
+			list(, $principalId) = URLUtil::splitPath($principal);
+			return self::ADDRESSBOOK_ROOT . '/system/' . $principalId;
+		}
+
+		throw new \LogicException('This is not supposed to happen');
+	}
+}
diff --git a/apps/dav/lib/carddav/useraddressbooks.php b/apps/dav/lib/carddav/useraddressbooks.php
index 5f618a0ece3f3107e2f24db13ce5410126f0fe5d..093cee0e1b2c8665e6e199729271574d09732c2e 100644
--- a/apps/dav/lib/carddav/useraddressbooks.php
+++ b/apps/dav/lib/carddav/useraddressbooks.php
@@ -11,13 +11,39 @@ class UserAddressBooks extends \Sabre\CardDAV\AddressBookHome {
 	 */
 	function getChildren() {
 
-		$addressbooks = $this->carddavBackend->getAddressBooksForUser($this->principalUri);
-		$objs = [];
-		foreach($addressbooks as $addressbook) {
-			$objs[] = new AddressBook($this->carddavBackend, $addressbook);
+		$addressBooks = $this->carddavBackend->getAddressBooksForUser($this->principalUri);
+		$objects = [];
+		foreach($addressBooks as $addressBook) {
+			$objects[] = new AddressBook($this->carddavBackend, $addressBook);
 		}
-		return $objs;
+		return $objects;
 
 	}
 
+	/**
+	 * Returns a list of ACE's for this node.
+	 *
+	 * Each ACE has the following properties:
+	 *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
+	 *     currently the only supported privileges
+	 *   * 'principal', a url to the principal who owns the node
+	 *   * 'protected' (optional), indicating that this ACE is not allowed to
+	 *      be updated.
+	 *
+	 * @return array
+	 */
+	function getACL() {
+
+		$acl = parent::getACL();
+		if ($this->principalUri === 'principals/system/system') {
+			$acl[] = [
+					'privilege' => '{DAV:}read',
+					'principal' => '{DAV:}authenticated',
+					'protected' => true,
+			];
+		}
+
+		return $acl;
+	}
+
 }
diff --git a/apps/dav/lib/dav/systemprincipalbackend.php b/apps/dav/lib/dav/systemprincipalbackend.php
new file mode 100644
index 0000000000000000000000000000000000000000..2c2049ace60091901efbfa5525d0e4a7ea011c4b
--- /dev/null
+++ b/apps/dav/lib/dav/systemprincipalbackend.php
@@ -0,0 +1,183 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\DAV\DAV;
+
+use Sabre\DAVACL\PrincipalBackend\AbstractBackend;
+use Sabre\HTTP\URLUtil;
+
+class SystemPrincipalBackend extends AbstractBackend {
+
+	/**
+	 * Returns a list of principals based on a prefix.
+	 *
+	 * This prefix will often contain something like 'principals'. You are only
+	 * expected to return principals that are in this base path.
+	 *
+	 * You are expected to return at least a 'uri' for every user, you can
+	 * return any additional properties if you wish so. Common properties are:
+	 *   {DAV:}displayname
+	 *   {http://sabredav.org/ns}email-address - This is a custom SabreDAV
+	 *     field that's actually injected in a number of other properties. If
+	 *     you have an email address, use this property.
+	 *
+	 * @param string $prefixPath
+	 * @return array
+	 */
+	function getPrincipalsByPrefix($prefixPath) {
+		$principals = [];
+
+		if ($prefixPath === 'principals/system') {
+			$principals[] = [
+				'uri' => 'principals/system/system',
+				'{DAV:}displayname' => 'system',
+			];
+		}
+
+		return $principals;
+	}
+
+	/**
+	 * Returns a specific principal, specified by it's path.
+	 * The returned structure should be the exact same as from
+	 * getPrincipalsByPrefix.
+	 *
+	 * @param string $path
+	 * @return array
+	 */
+	function getPrincipalByPath($path) {
+
+		$elements = explode('/', $path);
+		if ($elements[0] !== 'principals') {
+			return null;
+		}
+		if ($elements[1] === 'system') {
+			$principal = [
+				'uri' => 'principals/system/system',
+				'{DAV:}displayname' => 'system',
+			];
+			return $principal;
+		}
+
+		return null;
+	}
+
+	/**
+	 * Updates one ore more webdav properties on a principal.
+	 *
+	 * The list of mutations is stored in a Sabre\DAV\PropPatch object.
+	 * To do the actual updates, you must tell this object which properties
+	 * you're going to process with the handle() method.
+	 *
+	 * Calling the handle method is like telling the PropPatch object "I
+	 * promise I can handle updating this property".
+	 *
+	 * Read the PropPatch documentation for more info and examples.
+	 *
+	 * @param string $path
+	 * @param \Sabre\DAV\PropPatch $propPatch
+	 * @return void
+	 */
+	function updatePrincipal($path, \Sabre\DAV\PropPatch $propPatch) {
+	}
+
+	/**
+	 * This method is used to search for principals matching a set of
+	 * properties.
+	 *
+	 * This search is specifically used by RFC3744's principal-property-search
+	 * REPORT.
+	 *
+	 * The actual search should be a unicode-non-case-sensitive search. The
+	 * keys in searchProperties are the WebDAV property names, while the values
+	 * are the property values to search on.
+	 *
+	 * By default, if multiple properties are submitted to this method, the
+	 * various properties should be combined with 'AND'. If $test is set to
+	 * 'anyof', it should be combined using 'OR'.
+	 *
+	 * This method should simply return an array with full principal uri's.
+	 *
+	 * If somebody attempted to search on a property the backend does not
+	 * support, you should simply return 0 results.
+	 *
+	 * You can also just return 0 results if you choose to not support
+	 * searching at all, but keep in mind that this may stop certain features
+	 * from working.
+	 *
+	 * @param string $prefixPath
+	 * @param array $searchProperties
+	 * @param string $test
+	 * @return array
+	 */
+	function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
+		return [];
+	}
+
+	/**
+	 * Returns the list of members for a group-principal
+	 *
+	 * @param string $principal
+	 * @return array
+	 */
+	function getGroupMemberSet($principal) {
+		// TODO: for now the group principal has only one member, the user itself
+		$principal = $this->getPrincipalByPath($principal);
+		if (!$principal) {
+			throw new \Sabre\DAV\Exception('Principal not found');
+		}
+
+		return [$principal['uri']];
+	}
+
+	/**
+	 * Returns the list of groups a principal is a member of
+	 *
+	 * @param string $principal
+	 * @return array
+	 */
+	function getGroupMembership($principal) {
+		list($prefix, $name) = URLUtil::splitPath($principal);
+
+		if ($prefix === 'principals/system') {
+			$principal = $this->getPrincipalByPath($principal);
+			if (!$principal) {
+				throw new \Sabre\DAV\Exception('Principal not found');
+			}
+
+			return [];
+		}
+		return [];
+	}
+
+	/**
+	 * Updates the list of group members for a group principal.
+	 *
+	 * The principals should be passed as a list of uri's.
+	 *
+	 * @param string $principal
+	 * @param array $members
+	 * @return void
+	 */
+	function setGroupMemberSet($principal, array $members) {
+		throw new \Sabre\DAV\Exception('Setting members of the group is not supported yet');
+	}
+}
diff --git a/apps/dav/lib/rootcollection.php b/apps/dav/lib/rootcollection.php
index 3e349fa31c91b03ef112d593983860dfff21ccbc..c1635c9cde5a5985d2e91434eb9d1f4803c344cf 100644
--- a/apps/dav/lib/rootcollection.php
+++ b/apps/dav/lib/rootcollection.php
@@ -6,6 +6,7 @@ use OCA\DAV\CalDAV\CalDavBackend;
 use OCA\DAV\CardDAV\AddressBookRoot;
 use OCA\DAV\CardDAV\CardDavBackend;
 use OCA\DAV\Connector\Sabre\Principal;
+use OCA\DAV\DAV\SystemPrincipalBackend;
 use Sabre\CalDAV\CalendarRoot;
 use Sabre\CalDAV\Principal\Collection;
 use Sabre\DAV\SimpleCollection;
@@ -23,24 +24,33 @@ class RootCollection extends SimpleCollection {
 		$disableListing = !$config->getSystemValue('debug', false);
 
 		// setup the first level of the dav tree
-		$principalCollection = new Collection($principalBackend, 'principals/users');
-		$principalCollection->disableListing = $disableListing;
+		$userPrincipals = new Collection($principalBackend, 'principals/users');
+		$userPrincipals->disableListing = $disableListing;
+		$systemPrincipals = new Collection(new SystemPrincipalBackend(), 'principals/system');
+		$systemPrincipals->disableListing = $disableListing;
 		$filesCollection = new Files\RootCollection($principalBackend, 'principals/users');
 		$filesCollection->disableListing = $disableListing;
 		$caldavBackend = new CalDavBackend($db);
 		$calendarRoot = new CalendarRoot($principalBackend, $caldavBackend, 'principals/users');
 		$calendarRoot->disableListing = $disableListing;
 
-		$cardDavBackend = new CardDavBackend(\OC::$server->getDatabaseConnection(), $principalBackend);
+		$usersCardDavBackend = new CardDavBackend($db, $principalBackend);
+		$usersAddressBookRoot = new AddressBookRoot($principalBackend, $usersCardDavBackend, 'principals/users');
+		$usersAddressBookRoot->disableListing = $disableListing;
 
-		$addressBookRoot = new AddressBookRoot($principalBackend, $cardDavBackend, 'principals/users');
-		$addressBookRoot->disableListing = $disableListing;
+		$systemCardDavBackend = new CardDavBackend($db, $principalBackend);
+		$systemAddressBookRoot = new AddressBookRoot(new SystemPrincipalBackend(), $systemCardDavBackend, 'principals/system');
+		$systemAddressBookRoot->disableListing = $disableListing;
 
 		$children = [
-				new SimpleCollection('principals', [$principalCollection]),
+				new SimpleCollection('principals', [
+						$userPrincipals,
+						$systemPrincipals]),
 				$filesCollection,
 				$calendarRoot,
-				$addressBookRoot,
+				new SimpleCollection('addressbooks', [
+						$usersAddressBookRoot,
+						$systemAddressBookRoot]),
 		];
 
 		parent::__construct('root', $children);
diff --git a/apps/dav/lib/server.php b/apps/dav/lib/server.php
index ffdb917085e118d8680aabe715754542d5532aad..a031f2c442bbf60ac5848a6ed9ba788c35237ba6 100644
--- a/apps/dav/lib/server.php
+++ b/apps/dav/lib/server.php
@@ -58,7 +58,7 @@ class Server {
 		$this->server->addPlugin(new CardDAV\Sharing\Plugin($authBackend, \OC::$server->getRequest()));
 
 		// addressbook plugins
-		$this->server->addPlugin(new \Sabre\CardDAV\Plugin());
+		$this->server->addPlugin(new \OCA\DAV\CardDAV\Plugin());
 
 		// Finder on OS X requires Class 2 WebDAV support (locking), since we do
 		// not provide locking we emulate it using a fake locking plugin.
diff --git a/apps/dav/tests/travis/caldavtest/config/serverinfo.xml b/apps/dav/tests/travis/caldavtest/config/serverinfo.xml
index a474bb7135c61f0687f23efdea5ce0024595b85e..c80e47f94818486c01d50d4742701d3a17ee827f 100644
--- a/apps/dav/tests/travis/caldavtest/config/serverinfo.xml
+++ b/apps/dav/tests/travis/caldavtest/config/serverinfo.xml
@@ -569,7 +569,7 @@
 			<!-- relative path to user addressbook home-->
 			<substitution>
 				<key>$addressbookhome%d:</key>
-				<value>$addressbooks:$userid%d:</value>
+				<value>$addressbooks:users/$userid%d:</value>
 			</substitution>
 			<!-- relative path to user addressbook-->
 			<substitution>
diff --git a/apps/dav/tests/travis/caldavtest/tests/CardDAV/sync-report.xml b/apps/dav/tests/travis/caldavtest/tests/CardDAV/sync-report.xml
index 0321e61edbcef279fe059e4810a2ba5cbd396d5c..ffa6662981c76ef6af112a5424cb17e635fc775f 100644
--- a/apps/dav/tests/travis/caldavtest/tests/CardDAV/sync-report.xml
+++ b/apps/dav/tests/travis/caldavtest/tests/CardDAV/sync-report.xml
@@ -181,8 +181,7 @@
 				</verify>
 			</request>
 		</test>
-		<!--
-		<test name='6'>
+		<!-- test name='6'>
 			<require-feature>
 				<feature>sync-report-home</feature>
 			</require-feature>
@@ -236,7 +235,7 @@
 					</arg>
 				</verify>
 			</request>
-		</test>
+		</test -->
 		<test name='8'>
 			<description>remove new resource</description>
 			<request>
@@ -264,14 +263,15 @@
 					<callback>multistatusItems</callback>
 					<arg>
 						<name>okhrefs</name>
-						<value>$calendar_sync_extra_items:</value>
+						<!-- no sync on addressbook level -->
+						<!--<value>$calendar_sync_extra_items:</value>-->
 						<value>1.vcf</value>
 						<value>2.vcf</value>
 					</arg>
 				</verify>
 			</request>
 		</test>
-		<test name='10'>
+		<!--test name='10'>
 			<require-feature>
 				<feature>sync-report-home</feature>
 			</require-feature>
diff --git a/apps/dav/tests/unit/carddav/convertertest.php b/apps/dav/tests/unit/carddav/convertertest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f4e2ea3f0023d635bf8eb75e60dd58a910ea98c9
--- /dev/null
+++ b/apps/dav/tests/unit/carddav/convertertest.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\DAV\Tests\Unit;
+
+use OCA\DAV\CardDAV\Converter;
+use Test\TestCase;
+
+class ConverterTests extends  TestCase {
+
+	/**
+	 * @dataProvider providesNewUsers
+	 */
+	public function testCreation($expectedVCard, $displayName = null, $eMailAddress = null, $cloudId = null) {
+		$user = $this->getUserMock($displayName, $eMailAddress, $cloudId);
+
+		$converter = new Converter();
+		$vCard = $converter->createCardFromUser($user);
+		$cardData = $vCard->serialize();
+
+		$this->assertEquals($expectedVCard, $cardData);
+	}
+
+	public function providesNewUsers() {
+		return [
+				["BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.4.7//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nPHOTO;ENCODING=b;TYPE=JPEG:MTIzNDU2Nzg5\r\nEND:VCARD\r\n"],
+				["BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.4.7//EN\r\nUID:12345\r\nFN:Dr. Foo Bar\r\nN:Bar;Dr.;Foo;;\r\nPHOTO;ENCODING=b;TYPE=JPEG:MTIzNDU2Nzg5\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
+				["BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.4.7//EN\r\nUID:12345\r\nFN:Dr. Foo Bar\r\nN:Bar;Dr.;Foo;;\r\nEMAIL;TYPE=OTHER:foo@bar.net\r\nPHOTO;ENCODING=b;TYPE=JPEG:MTIzNDU2Nzg5\r\nEND:VCARD\r\n", "Dr. Foo Bar", "foo@bar.net"],
+				["BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.4.7//EN\r\nUID:12345\r\nFN:Dr. Foo Bar\r\nN:Bar;Dr.;Foo;;\r\nCLOUD:foo@bar.net\r\nPHOTO;ENCODING=b;TYPE=JPEG:MTIzNDU2Nzg5\r\nEND:VCARD\r\n", "Dr. Foo Bar", null, "foo@bar.net"],
+		];
+	}
+
+	/**
+	 * @dataProvider providesNewUsers
+	 */
+	public function testUpdateOfUnchangedUser($expectedVCard, $displayName = null, $eMailAddress = null, $cloudId = null) {
+		$user = $this->getUserMock($displayName, $eMailAddress, $cloudId);
+
+		$converter = new Converter();
+		$vCard = $converter->createCardFromUser($user);
+		$updated = $converter->updateCard($vCard, $user);
+		$this->assertFalse($updated);
+		$cardData = $vCard->serialize();
+
+		$this->assertEquals($expectedVCard, $cardData);
+	}
+
+	/**
+	 * @dataProvider providesUsersForUpdateOfRemovedElement
+	 */
+	public function testUpdateOfRemovedElement($expectedVCard, $displayName = null, $eMailAddress = null, $cloudId = null) {
+		$user = $this->getUserMock($displayName, $eMailAddress, $cloudId);
+
+		$converter = new Converter();
+		$vCard = $converter->createCardFromUser($user);
+
+		$user1 = $this->getMockBuilder('OCP\IUser')->disableOriginalConstructor()->getMock();
+		$user1->method('getUID')->willReturn('12345');
+		$user1->method('getDisplayName')->willReturn(null);
+		$user1->method('getEMailAddress')->willReturn(null);
+		$user1->method('getCloudId')->willReturn(null);
+		$user1->method('getAvatarImage')->willReturn(null);
+
+		$updated = $converter->updateCard($vCard, $user1);
+		$this->assertTrue($updated);
+		$cardData = $vCard->serialize();
+
+		$this->assertEquals($expectedVCard, $cardData);
+	}
+
+	public function providesUsersForUpdateOfRemovedElement() {
+		return [
+				["BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.4.7//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
+				["BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.4.7//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n", "Dr. Foo Bar", "foo@bar.net"],
+				["BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.4.7//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n", "Dr. Foo Bar", null, "foo@bar.net"],
+		];
+	}
+
+	/**
+	 * @dataProvider providesNames
+	 * @param $expected
+	 * @param $fullName
+	 */
+	public function testNameSplitter($expected, $fullName) {
+
+		$converter = new Converter();
+		$r = $converter->splitFullName($fullName);
+		$r = implode(';', $r);
+		$this->assertEquals($expected, $r);
+	}
+
+	public function providesNames() {
+		return [
+				['Sauron;;;;', 'Sauron'],
+				['Baggins;Bilbo;;;', 'Bilbo Baggins'],
+				['Tolkien;John;Ronald Reuel;;', 'John Ronald Reuel Tolkien'],
+		];
+	}
+
+	/**
+	 * @param $displayName
+	 * @param $eMailAddress
+	 * @param $cloudId
+	 * @return \PHPUnit_Framework_MockObject_MockObject
+	 */
+	protected function getUserMock($displayName, $eMailAddress, $cloudId) {
+		$image0 = $this->getMockBuilder('OCP\IImage')->disableOriginalConstructor()->getMock();
+		$image0->method('mimeType')->willReturn('JPEG');
+		$image0->method('data')->willReturn('123456789');
+		$user = $this->getMockBuilder('OCP\IUser')->disableOriginalConstructor()->getMock();
+		$user->method('getUID')->willReturn('12345');
+		$user->method('getDisplayName')->willReturn($displayName);
+		$user->method('getEMailAddress')->willReturn($eMailAddress);
+		$user->method('getCloudId')->willReturn($cloudId);
+		$user->method('getAvatarImage')->willReturn($image0);
+		return $user;
+	}
+}
diff --git a/apps/files_sharing/lib/helper.php b/apps/files_sharing/lib/helper.php
index a804737c490f849df03d8da1897514564ccd23c5..391b491e1ff9caed2c914b6ba7d440fb7794b211 100644
--- a/apps/files_sharing/lib/helper.php
+++ b/apps/files_sharing/lib/helper.php
@@ -310,20 +310,4 @@ class Helper {
 		\OC::$server->getConfig()->setSystemValue('share_folder', $shareFolder);
 	}
 
-	/**
-	 * remove protocol from URL
-	 *
-	 * @param string $url
-	 * @return string
-	 */
-	public static function removeProtocolFromUrl($url) {
-		if (strpos($url, 'https://') === 0) {
-			return substr($url, strlen('https://'));
-		} else if (strpos($url, 'http://') === 0) {
-			return substr($url, strlen('http://'));
-		}
-
-		return $url;
-	}
-
 }
diff --git a/apps/files_sharing/settings-personal.php b/apps/files_sharing/settings-personal.php
index deaa7b92ac75ab91cc25b4fff75707b255bbc771..85fad9c3eaf8ab72fb887a974336728c54d573c4 100644
--- a/apps/files_sharing/settings-personal.php
+++ b/apps/files_sharing/settings-personal.php
@@ -32,9 +32,7 @@ if (count($matches) > 0 && $matches[1] <= 9) {
 	$isIE8 = true;
 }
 
-$uid = \OC::$server->getUserSession()->getUser()->getUID();
-$server = \OC::$server->getURLGenerator()->getAbsoluteURL('/');
-$cloudID = $uid . '@' . rtrim(\OCA\Files_Sharing\Helper::removeProtocolFromUrl($server), '/');
+$cloudID = \OC::$server->getUserSession()->getUser()->getCloudId();
 $url = 'https://owncloud.org/federation#' . $cloudID;
 $ownCloudLogoPath = \OC::$server->getURLGenerator()->imagePath('core', 'logo-icon.svg');
 
diff --git a/lib/private/avatar.php b/lib/private/avatar.php
index 872da35f94745d36a7cd9635b6b545035e4ffcb6..37a813f3ff8f3dcef3405efbed44c5118249cfaa 100644
--- a/lib/private/avatar.php
+++ b/lib/private/avatar.php
@@ -79,7 +79,9 @@ class Avatar implements \OCP\IAvatar {
 			/** @var File $node */
 			$node = $this->folder->get('avatar.' . $ext);
 			$avatar->loadFromData($node->getContent());
-			$avatar->resize($size);
+			if ($size > 0) {
+				$avatar->resize($size);
+			}
 			$this->folder->newFile('avatar.' . $size . '.' . $ext)->putContent($avatar->data());
 		}
 		return $avatar;
diff --git a/lib/private/user/manager.php b/lib/private/user/manager.php
index 109f08f47a0e77d3042b1e51b8ac03c9f46d00ab..2cb866d00564f65d8520e709b74c00f00bcfc10b 100644
--- a/lib/private/user/manager.php
+++ b/lib/private/user/manager.php
@@ -294,21 +294,47 @@ class Manager extends PublicEmitter implements IUserManager {
 		$userCountStatistics = array();
 		foreach ($this->backends as $backend) {
 			if ($backend->implementsActions(\OC_User_Backend::COUNT_USERS)) {
-				$backendusers = $backend->countUsers();
-				if($backendusers !== false) {
+				$backendUsers = $backend->countUsers();
+				if($backendUsers !== false) {
 					if($backend instanceof \OCP\IUserBackend) {
 						$name = $backend->getBackendName();
 					} else {
 						$name = get_class($backend);
 					}
 					if(isset($userCountStatistics[$name])) {
-						$userCountStatistics[$name] += $backendusers;
+						$userCountStatistics[$name] += $backendUsers;
 					} else {
-						$userCountStatistics[$name] = $backendusers;
+						$userCountStatistics[$name] = $backendUsers;
 					}
 				}
 			}
 		}
 		return $userCountStatistics;
 	}
+
+	/**
+	 * The callback is executed for each user on each backend.
+	 * If the callback returns false no further users will be retrieved.
+	 *
+	 * @param \Closure $callback
+	 * @return void
+	 * @since 9.0.0
+	 */
+	public function callForAllUsers(\Closure $callback, $search = '') {
+		foreach($this->getBackends() as $backend) {
+			$limit = 500;
+			$offset = 0;
+			do {
+				$users = $backend->getUsers($search, $limit, $offset);
+				foreach ($users as $user) {
+					$user = $this->get($user);
+					$return = $callback($user);
+					if ($return === false) {
+						break;
+					}
+				}
+				$offset += $limit;
+			} while (count($users) >= $limit);
+		}
+	}
 }
diff --git a/lib/private/user/user.php b/lib/private/user/user.php
index 2740b25d5d36162a340e9b3aec1da65fc658e936..d1fa641504cecd94cf46f4e58044edb4df7c5cde 100644
--- a/lib/private/user/user.php
+++ b/lib/private/user/user.php
@@ -30,61 +30,56 @@
 namespace OC\User;
 
 use OC\Hooks\Emitter;
+use OCP\IAvatarManager;
+use OCP\IImage;
+use OCP\IURLGenerator;
 use OCP\IUser;
 use OCP\IConfig;
 
 class User implements IUser {
-	/**
-	 * @var string $uid
-	 */
+	/** @var string $uid */
 	private $uid;
 
-	/**
-	 * @var string $displayName
-	 */
+	/** @var string $displayName */
 	private $displayName;
 
-	/**
-	 * @var \OC_User_Interface $backend
-	 */
+	/** @var \OC_User_Interface $backend */
 	private $backend;
 
-	/**
-	 * @var bool $enabled
-	 */
+	/** @var bool $enabled */
 	private $enabled;
 
-	/**
-	 * @var Emitter|Manager $emitter
-	 */
+	/** @var Emitter|Manager $emitter */
 	private $emitter;
 
-	/**
-	 * @var string $home
-	 */
+	/** @var string $home */
 	private $home;
 
-	/**
-	 * @var int $lastLogin
-	 */
+	/** @var int $lastLogin */
 	private $lastLogin;
 
-	/**
-	 * @var \OCP\IConfig $config
-	 */
+	/** @var \OCP\IConfig $config */
 	private $config;
 
+	/** @var IAvatarManager */
+	private $avatarManager;
+
+	/** @var IURLGenerator */
+	private $urlGenerator;
+
 	/**
 	 * @param string $uid
 	 * @param \OC_User_Interface $backend
 	 * @param \OC\Hooks\Emitter $emitter
-	 * @param \OCP\IConfig $config
+	 * @param IConfig|null $config
+	 * @param IURLGenerator $urlGenerator
 	 */
-	public function __construct($uid, $backend, $emitter = null, IConfig $config = null) {
+	public function __construct($uid, $backend, $emitter = null, IConfig $config = null, $urlGenerator = null) {
 		$this->uid = $uid;
 		$this->backend = $backend;
 		$this->emitter = $emitter;
 		$this->config = $config;
+		$this->urlGenerator = $urlGenerator;
 		if ($this->config) {
 			$enabled = $this->config->getUserValue($uid, 'core', 'enabled', 'true');
 			$this->enabled = ($enabled === 'true');
@@ -93,6 +88,9 @@ class User implements IUser {
 			$this->enabled = true;
 			$this->lastLogin = \OC::$server->getConfig()->getUserValue($uid, 'login', 'lastLogin', 0);
 		}
+		if (is_null($this->urlGenerator)) {
+			$this->urlGenerator = \OC::$server->getURLGenerator();
+		}
 	}
 
 	/**
@@ -105,7 +103,7 @@ class User implements IUser {
 	}
 
 	/**
-	 * get the displayname for the user, if no specific displayname is set it will fallback to the user id
+	 * get the display name for the user, if no specific display name is set it will fallback to the user id
 	 *
 	 * @return string
 	 */
@@ -316,4 +314,52 @@ class User implements IUser {
 	public function getEMailAddress() {
 		return $this->config->getUserValue($this->uid, 'settings', 'email');
 	}
+
+	/**
+	 * get the avatar image if it exists
+	 *
+	 * @param int $size
+	 * @return IImage|null
+	 * @since 9.0.0
+	 */
+	public function getAvatarImage($size) {
+		// delay the initialization
+		if (is_null($this->avatarManager)) {
+			$this->avatarManager = \OC::$server->getAvatarManager();
+		}
+
+		$avatar = $this->avatarManager->getAvatar($this->uid);
+		$image = $avatar->get(-1);
+		if ($image) {
+			return $image;
+		}
+
+		return null;
+	}
+
+	/**
+	 * get the federation cloud id
+	 *
+	 * @return string
+	 * @since 9.0.0
+	 */
+	public function getCloudId() {
+		$uid = $this->getUID();
+		$server = $this->urlGenerator->getAbsoluteURL('/');
+		return $uid . '@' . rtrim( $this->removeProtocolFromUrl($server), '/');
+	}
+
+	/**
+	 * @param string $url
+	 * @return string
+	 */
+	private function removeProtocolFromUrl($url) {
+		if (strpos($url, 'https://') === 0) {
+			return substr($url, strlen('https://'));
+		} else if (strpos($url, 'http://') === 0) {
+			return substr($url, strlen('http://'));
+		}
+
+		return $url;
+	}
 }
diff --git a/lib/public/iuser.php b/lib/public/iuser.php
index 1e52cd590360f403e3ff442b68a08cc55c65ced1..67e2b107e0b27e790cff033c1d41028092cd71d2 100644
--- a/lib/public/iuser.php
+++ b/lib/public/iuser.php
@@ -152,4 +152,21 @@ interface IUser {
 	 * @since 9.0.0
 	 */
 	public function getEMailAddress();
+
+	/**
+	 * get the avatar image if it exists
+	 *
+	 * @param int $size
+	 * @return IImage|null
+	 * @since 9.0.0
+	 */
+	public function getAvatarImage($size);
+
+	/**
+	 * get the federation cloud id
+	 *
+	 * @return string
+	 * @since 9.0.0
+	 */
+	public function getCloudId();
 }
diff --git a/lib/public/iusermanager.php b/lib/public/iusermanager.php
index e3857d6231a68b8861c01e2f7a86e960cfbd5ffc..3a0abaca7b75bc0c92dfa97225f0ea8ab0310c26 100644
--- a/lib/public/iusermanager.php
+++ b/lib/public/iusermanager.php
@@ -134,4 +134,11 @@ interface IUserManager {
 	 * @since 8.0.0
 	 */
 	public function countUsers();
+
+	/**
+	 * @param \Closure $callback
+	 * @return void
+	 * @since 9.0.0
+	 */
+	public function callForAllUsers (\Closure $callback, $search = '');
 }
diff --git a/tests/lib/contacts/localadressbook.php b/tests/lib/contacts/localadressbook.php
index 6bfcf3d890a7f4dc3a81f7fbc71f19fb19d93df1..e5c43460835d80a199aec6e3096a6ecbd0942b7c 100644
--- a/tests/lib/contacts/localadressbook.php
+++ b/tests/lib/contacts/localadressbook.php
@@ -98,6 +98,11 @@ class SimpleUserForTesting implements IUser {
 	}
 
 	public function getEMailAddress() {
-		// TODO: Implement getEMailAddress() method.
+	}
+
+	public function getAvatarImage($size) {
+	}
+
+	public function getCloudId() {
 	}
 }
diff --git a/tests/lib/user/user.php b/tests/lib/user/user.php
index bc1365d35bf3211dbf109736eb013ecd83b06a63..1f613edc4e69e5a9b695a054e056d23a1f78d467 100644
--- a/tests/lib/user/user.php
+++ b/tests/lib/user/user.php
@@ -11,6 +11,13 @@ namespace Test\User;
 
 use OC\Hooks\PublicEmitter;
 
+/**
+ * Class User
+ *
+ * @group DB
+ *
+ * @package Test\User
+ */
 class User extends \Test\TestCase {
 	public function testDisplayName() {
 		/**
@@ -454,4 +461,21 @@ class User extends \Test\TestCase {
 		$this->assertTrue($user->delete());
 		$this->assertEquals(2, $hooksCalled);
 	}
+
+	public function testGetCloudId() {
+		/**
+		 * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend
+		 */
+		$backend = $this->getMock('\Test\Util\User\Dummy');
+		$urlGenerator = $this->getMockBuilder('\OC\URLGenerator')
+				->setMethods(['getAbsoluteURL'])
+				->disableOriginalConstructor()->getMock();
+		$urlGenerator
+				->expects($this->any())
+				->method('getAbsoluteURL')
+				->withAnyParameters()
+				->willReturn('http://localhost:8888/owncloud');
+		$user = new \OC\User\User('foo', $backend, null, null, $urlGenerator);
+		$this->assertEquals("foo@localhost:8888/owncloud", $user->getCloudId());
+	}
 }