diff --git a/apps/user_ldap/group_proxy.php b/apps/user_ldap/group_proxy.php
index acc563c953..4404bd7fe3 100644
--- a/apps/user_ldap/group_proxy.php
+++ b/apps/user_ldap/group_proxy.php
@@ -67,16 +67,17 @@ class Group_Proxy extends lib\Proxy implements \OCP\GroupInterface {
* @param $gid string, the gid connected to the request
* @param $method string, the method of the group backend that shall be called
* @param $parameters an array of parameters to be passed
+ * @param $passOnWhen the result matches this variable
* @return mixed, the result of the method or false
*/
- protected function callOnLastSeenOn($gid, $method, $parameters) {
+ protected function callOnLastSeenOn($gid, $method, $parameters, $passOnWhen) {
$cacheKey = $this->getGroupCacheKey($gid);;
$prefix = $this->getFromCache($cacheKey);
//in case the uid has been found in the past, try this stored connection first
if(!is_null($prefix)) {
if(isset($this->backends[$prefix])) {
$result = call_user_func_array(array($this->backends[$prefix], $method), $parameters);
- if(!$result) {
+ if($result === $passOnWhen) {
//not found here, reset cache to null if group vanished
//because sometimes methods return false with a reason
$groupExists = call_user_func_array(
diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php
index a07bd3fa11..ecc74b6cf5 100644
--- a/apps/user_ldap/lib/access.php
+++ b/apps/user_ldap/lib/access.php
@@ -199,7 +199,9 @@ class Access extends LDAPUtility {
*/
public function username2dn($name) {
$dn = $this->ocname2dn($name, true);
- if($dn) {
+ //Check whether the DN belongs to the Base, to avoid issues on multi-
+ //server setups
+ if($dn && $this->isDNPartOfBase($dn, $this->connection->ldapBaseUsers)) {
return $dn;
}
diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php
index e14ed824a7..58f4b11e69 100644
--- a/apps/user_ldap/lib/configuration.php
+++ b/apps/user_ldap/lib/configuration.php
@@ -72,6 +72,7 @@ class Configuration {
'ldapExpertUsernameAttr' => null,
'ldapExpertUUIDUserAttr' => null,
'ldapExpertUUIDGroupAttr' => null,
+ 'lastJpegPhotoLookup' => null,
);
public function __construct($configPrefix, $autoread = true) {
@@ -330,6 +331,7 @@ class Configuration {
'ldap_expert_uuid_user_attr' => '',
'ldap_expert_uuid_group_attr' => '',
'has_memberof_filter_support' => 0,
+ 'last_jpegPhoto_lookup' => 0,
);
}
@@ -377,6 +379,7 @@ class Configuration {
'ldap_expert_uuid_user_attr' => 'ldapExpertUUIDUserAttr',
'ldap_expert_uuid_group_attr' => 'ldapExpertUUIDGroupAttr',
'has_memberof_filter_support' => 'hasMemberOfFilterSupport',
+ 'last_jpegPhoto_lookup' => 'lastJpegPhotoLookup',
);
return $array;
}
diff --git a/apps/user_ldap/lib/proxy.php b/apps/user_ldap/lib/proxy.php
index c74b357bdd..30e1875901 100644
--- a/apps/user_ldap/lib/proxy.php
+++ b/apps/user_ldap/lib/proxy.php
@@ -54,7 +54,7 @@ abstract class Proxy {
return 'group-'.$gid.'-lastSeenOn';
}
- abstract protected function callOnLastSeenOn($id, $method, $parameters);
+ abstract protected function callOnLastSeenOn($id, $method, $parameters, $passOnWhen);
abstract protected function walkBackends($id, $method, $parameters);
/**
@@ -64,8 +64,9 @@ abstract class Proxy {
* @param $parameters an array of parameters to be passed
* @return mixed, the result of the specified method
*/
- protected function handleRequest($id, $method, $parameters) {
- if(!$result = $this->callOnLastSeenOn($id, $method, $parameters)) {
+ protected function handleRequest($id, $method, $parameters, $passOnWhen = false) {
+ $result = $this->callOnLastSeenOn($id, $method, $parameters, $passOnWhen);
+ if($result === $passOnWhen) {
$result = $this->walkBackends($id, $method, $parameters);
}
return $result;
diff --git a/apps/user_ldap/user_ldap.php b/apps/user_ldap/user_ldap.php
index 6f52bbdf23..527a5c10b8 100644
--- a/apps/user_ldap/user_ldap.php
+++ b/apps/user_ldap/user_ldap.php
@@ -69,6 +69,74 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface {
}
}
+ /**
+ * @brief reads jpegPhoto and set is as avatar if available
+ * @param $uid string ownCloud user name
+ * @param $dn string the user's LDAP DN
+ * @return void
+ */
+ private function updateAvatar($uid, $dn) {
+ $hasLoggedIn = \OCP\Config::getUserValue($uid, 'user_ldap',
+ 'firstLoginAccomplished', 0);
+ $lastChecked = \OCP\Config::getUserValue($uid, 'user_ldap',
+ 'lastJpegPhotoLookup', 0);
+ if(($hasLoggedIn !== '1') || (time() - intval($lastChecked)) < 86400 ) {
+ //update only once a day
+ return;
+ }
+
+ $jpegPhoto = $this->access->readAttribute($dn, 'jpegPhoto');
+ \OCP\Config::setUserValue($uid, 'user_ldap', 'lastJpegPhotoLookup', time());
+ if(!$jpegPhoto || !is_array($jpegPhoto) || !isset($jpegPhoto[0])) {
+ //not set, nothing left to do;
+ return;
+ }
+
+ $image = new \OCP\Image();
+ $image->loadFromBase64(base64_encode($jpegPhoto[0]));
+
+ if(!$image->valid()) {
+ \OCP\Util::writeLog('user_ldap', 'jpegPhoto data invalid for '.$dn,
+ \OCP\Util::ERROR);
+ return;
+ }
+ //make sure it is a square and not bigger than 128x128
+ $size = min(array($image->width(), $image->height(), 128));
+ if(!$image->centerCrop($size)) {
+ \OCP\Util::writeLog('user_ldap',
+ 'croping image for avatar failed for '.$dn,
+ \OCP\Util::ERROR);
+ return;
+ }
+
+ if(!\OC\Files\Filesystem::$loaded) {
+ \OC_Util::setupFS($uid);
+ }
+
+ $avatarManager = \OC::$server->getAvatarManager();
+ $avatar = $avatarManager->getAvatar($uid);
+ $avatar->set($image);
+ }
+
+ /**
+ * @brief checks whether the user is allowed to change his avatar in ownCloud
+ * @param $uid string the ownCloud user name
+ * @return boolean either the user can or cannot
+ */
+ public function canChangeAvatar($uid) {
+ $dn = $this->access->username2dn($uid);
+ if(!$dn) {
+ return false;
+ }
+ $jpegPhoto = $this->access->readAttribute($dn, 'jpegPhoto');
+ if(!$jpegPhoto || !is_array($jpegPhoto) || !isset($jpegPhoto[0])) {
+ //The user is allowed to change his avatar in ownCloud only if no
+ //avatar is provided by LDAP
+ return true;
+ }
+ return false;
+ }
+
/**
* @brief Check if the password is correct
* @param $uid The username
@@ -100,6 +168,10 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface {
return false;
}
+ \OCP\Config::setUserValue($ocname, 'user_ldap',
+ 'firstLoginAccomplished', 1);
+
+ $this->updateAvatar($ocname, $dn);
//give back the display name
return $ocname;
}
@@ -173,6 +245,7 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface {
$this->access->connection->writeToCache('userExists'.$uid, true);
$this->updateQuota($dn);
+ $this->updateAvatar($uid, $dn);
return true;
}
@@ -289,7 +362,8 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface {
public function implementsActions($actions) {
return (bool)((OC_USER_BACKEND_CHECK_PASSWORD
| OC_USER_BACKEND_GET_HOME
- | OC_USER_BACKEND_GET_DISPLAYNAME)
+ | OC_USER_BACKEND_GET_DISPLAYNAME
+ | OC_USER_BACKEND_PROVIDE_AVATAR)
& $actions);
}
diff --git a/apps/user_ldap/user_proxy.php b/apps/user_ldap/user_proxy.php
index 092fdbf7c7..b073b143e7 100644
--- a/apps/user_ldap/user_proxy.php
+++ b/apps/user_ldap/user_proxy.php
@@ -54,6 +54,7 @@ class User_Proxy extends lib\Proxy implements \OCP\UserInterface {
protected function walkBackends($uid, $method, $parameters) {
$cacheKey = $this->getUserCacheKey($uid);
foreach($this->backends as $configPrefix => $backend) {
+// print("walkBackend '$configPrefix'
");
if($result = call_user_func_array(array($backend, $method), $parameters)) {
$this->writeToCache($cacheKey, $configPrefix);
return $result;
@@ -67,16 +68,17 @@ class User_Proxy extends lib\Proxy implements \OCP\UserInterface {
* @param $uid string, the uid connected to the request
* @param $method string, the method of the user backend that shall be called
* @param $parameters an array of parameters to be passed
+ * @param $passOnWhen the result matches this variable
* @return mixed, the result of the method or false
*/
- protected function callOnLastSeenOn($uid, $method, $parameters) {
+ protected function callOnLastSeenOn($uid, $method, $parameters, $passOnWhen) {
$cacheKey = $this->getUserCacheKey($uid);
$prefix = $this->getFromCache($cacheKey);
//in case the uid has been found in the past, try this stored connection first
if(!is_null($prefix)) {
if(isset($this->backends[$prefix])) {
$result = call_user_func_array(array($this->backends[$prefix], $method), $parameters);
- if(!$result) {
+ if($result === $passOnWhen) {
//not found here, reset cache to null if user vanished
//because sometimes methods return false with a reason
$userExists = call_user_func_array(
@@ -163,6 +165,15 @@ class User_Proxy extends lib\Proxy implements \OCP\UserInterface {
return $this->handleRequest($uid, 'getDisplayName', array($uid));
}
+ /**
+ * @brief checks whether the user is allowed to change his avatar in ownCloud
+ * @param $uid string the ownCloud user name
+ * @return boolean either the user can or cannot
+ */
+ public function canChangeAvatar($uid) {
+ return $this->handleRequest($uid, 'canChangeAvatar', array($uid), true);
+ }
+
/**
* @brief Get a list of all display names
* @returns array with all displayNames (value) and the corresponding uids (key)
diff --git a/lib/private/avatar.php b/lib/private/avatar.php
index 814a9b22be..e97f55eeca 100644
--- a/lib/private/avatar.php
+++ b/lib/private/avatar.php
@@ -44,15 +44,19 @@ class OC_Avatar implements \OCP\IAvatar {
/**
* @brief sets the users avatar
- * @param $data mixed imagedata or path to set a new avatar
+ * @param $data mixed OC_Image, imagedata or path to set a new avatar
* @throws Exception if the provided file is not a jpg or png image
* @throws Exception if the provided image is not valid
* @throws \OC\NotSquareException if the image is not square
* @return void
*/
public function set ($data) {
-
- $img = new OC_Image($data);
+ if($data instanceOf OC_Image) {
+ $img = $data;
+ $data = $img->data();
+ } else {
+ $img = new OC_Image($data);
+ }
$type = substr($img->mimeType(), -3);
if ($type === 'peg') {
$type = 'jpg';
diff --git a/lib/private/user.php b/lib/private/user.php
index 5bd3600675..210e5ed3f0 100644
--- a/lib/private/user.php
+++ b/lib/private/user.php
@@ -424,6 +424,22 @@ class OC_User {
}
}
+ /**
+ * @brief Check whether user can change his avatar
+ * @param string $uid The username
+ * @return bool
+ *
+ * Check whether a specified user can change his avatar
+ */
+ public static function canUserChangeAvatar($uid) {
+ $user = self::getManager()->get($uid);
+ if ($user) {
+ return $user->canChangeAvatar();
+ } else {
+ return false;
+ }
+ }
+
/**
* @brief Check whether user can change his password
* @param string $uid The username
diff --git a/lib/private/user/backend.php b/lib/private/user/backend.php
index e9be08e429..02c93d13bd 100644
--- a/lib/private/user/backend.php
+++ b/lib/private/user/backend.php
@@ -31,13 +31,13 @@ define('OC_USER_BACKEND_NOT_IMPLEMENTED', -501);
/**
* actions that user backends can define
*/
-define('OC_USER_BACKEND_CREATE_USER', 0x000001);
-define('OC_USER_BACKEND_SET_PASSWORD', 0x000010);
-define('OC_USER_BACKEND_CHECK_PASSWORD', 0x000100);
-define('OC_USER_BACKEND_GET_HOME', 0x001000);
-define('OC_USER_BACKEND_GET_DISPLAYNAME', 0x010000);
-define('OC_USER_BACKEND_SET_DISPLAYNAME', 0x100000);
-
+define('OC_USER_BACKEND_CREATE_USER', 0x0000001);
+define('OC_USER_BACKEND_SET_PASSWORD', 0x0000010);
+define('OC_USER_BACKEND_CHECK_PASSWORD', 0x0000100);
+define('OC_USER_BACKEND_GET_HOME', 0x0001000);
+define('OC_USER_BACKEND_GET_DISPLAYNAME', 0x0010000);
+define('OC_USER_BACKEND_SET_DISPLAYNAME', 0x0100000);
+define('OC_USER_BACKEND_PROVIDE_AVATAR', 0x1000000);
/**
* Abstract base class for user management. Provides methods for querying backend
@@ -54,6 +54,7 @@ abstract class OC_User_Backend implements OC_User_Interface {
OC_USER_BACKEND_GET_HOME => 'getHome',
OC_USER_BACKEND_GET_DISPLAYNAME => 'getDisplayName',
OC_USER_BACKEND_SET_DISPLAYNAME => 'setDisplayName',
+ OC_USER_BACKEND_PROVIDE_AVATAR => 'canChangeAvatar',
);
/**
diff --git a/lib/private/user/user.php b/lib/private/user/user.php
index e5f842944f..e773473ec4 100644
--- a/lib/private/user/user.php
+++ b/lib/private/user/user.php
@@ -139,6 +139,18 @@ class User {
return \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data") . '/' . $this->uid; //TODO switch to Config object once implemented
}
+ /**
+ * check if the backend allows the user to change his avatar on Personal page
+ *
+ * @return bool
+ */
+ public function canChangeAvatar() {
+ if($this->backend->implementsActions(\OC_USER_BACKEND_PROVIDE_AVATAR)) {
+ return $this->backend->canChangeAvatar($this->uid);
+ }
+ return true;
+ }
+
/**
* check if the backend supports changing passwords
*
diff --git a/settings/personal.php b/settings/personal.php
index 670e18e20e..44e1048941 100644
--- a/settings/personal.php
+++ b/settings/personal.php
@@ -90,6 +90,7 @@ $tmpl->assign('displayNameChangeSupported', OC_User::canUserChangeDisplayName(OC
$tmpl->assign('displayName', OC_User::getDisplayName());
$tmpl->assign('enableDecryptAll' , $enableDecryptAll);
$tmpl->assign('enableAvatars', \OC_Config::getValue('enable_avatars', true));
+$tmpl->assign('avatarChangeSupported', OC_User::canUserChangeAvatar(OC_User::getUser()));
$forms=OC_App::getForms('personal');
$tmpl->assign('forms', array());
diff --git a/settings/templates/personal.php b/settings/templates/personal.php
index a79eeefa79..3eb864655b 100644
--- a/settings/templates/personal.php
+++ b/settings/templates/personal.php
@@ -87,11 +87,15 @@ if($_['passwordChangeSupported']) {