diff --git a/apps/files/index.php b/apps/files/index.php
index 9ae378d7a1..8f6838aa0d 100644
--- a/apps/files/index.php
+++ b/apps/files/index.php
@@ -108,7 +108,6 @@ if ($needUpgrade) {
// if the encryption app is disabled, than everything is fine (INIT_SUCCESSFUL status code)
$encryptionInitStatus = 2;
if (OC_App::isEnabled('files_encryption')) {
- $publicUploadEnabled = 'no';
$session = new \OCA\Encryption\Session(new \OC\Files\View('/'));
$encryptionInitStatus = $session->getInitialized();
}
diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php
index 0ac6fcf403..17bcac5c58 100755
--- a/apps/files_encryption/lib/helper.php
+++ b/apps/files_encryption/lib/helper.php
@@ -225,10 +225,7 @@ class Helper {
* @return bool
*/
public static function isPublicAccess() {
- if (\OCP\USER::getUser() === false
- || (isset($_GET['service']) && $_GET['service'] == 'files'
- && isset($_GET['t']))
- ) {
+ if (\OCP\User::getUser() === false) {
return true;
} else {
return false;
@@ -256,10 +253,45 @@ class Helper {
}
/**
- * @brief get path to the correspondig file in data/user/files if path points
+ * @brief try to get the user from the path if no user is logged in
+ * @param string $path
+ * @return mixed user or false if we couldn't determine a user
+ */
+ public static function getUser($path) {
+
+ $user = \OCP\User::getUser();
+
+
+ // if we are logged in, then we return the userid
+ if ($user) {
+ return $user;
+ }
+
+ // if no user is logged in we try to access a publicly shared files.
+ // In this case we need to try to get the user from the path
+
+ $trimmed = ltrim($path, '/');
+ $split = explode('/', $trimmed);
+
+ // it is not a file relative to data/user/files
+ if (count($split) < 2 || $split[1] !== 'files') {
+ return false;
+ }
+
+ $user = $split[0];
+
+ if (\OCP\User::userExists($user)) {
+ return $user;
+ }
+
+ return false;
+ }
+
+ /**
+ * @brief get path to the corresponding file in data/user/files if path points
* to a version or to a file in cache
* @param string $path path to a version or a file in the trash
- * @return string path to correspondig file relative to data/user/files
+ * @return string path to corresponding file relative to data/user/files
*/
public static function getPathToRealFile($path) {
$trimmed = ltrim($path, '/');
diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php
index 3427e8a963..b2c756894b 100755
--- a/apps/files_encryption/lib/keymanager.php
+++ b/apps/files_encryption/lib/keymanager.php
@@ -112,21 +112,18 @@ class Keymanager {
* @brief store file encryption key
*
* @param \OC_FilesystemView $view
+ * @param \OCA\Encryption\Util $util
* @param string $path relative path of the file, including filename
- * @param $userId
- * @param $catfile
- * @internal param string $key
+ * @param string $catfile keyfile content
* @return bool true/false
* @note The keyfile is not encrypted here. Client code must
* asymmetrically encrypt the keyfile before passing it to this method
*/
- public static function setFileKey(\OC_FilesystemView $view, $path, $userId, $catfile) {
+ public static function setFileKey(\OC_FilesystemView $view, $util, $path, $catfile) {
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
- //here we need the currently logged in user, while userId can be a different user
- $util = new Util($view, \OCP\User::getUser());
list($owner, $filename) = $util->getUidAndFilename($path);
// in case of system wide mount points the keys are stored directly in the data directory
@@ -172,15 +169,15 @@ class Keymanager {
/**
* @brief retrieve keyfile for an encrypted file
* @param \OC_FilesystemView $view
+ * @param \OCA\Encryption\Util $util
* @param $filePath
* @internal param \OCA\Encryption\file $string name
* @return string file key or false
* @note The keyfile returned is asymmetrically encrypted. Decryption
* of the keyfile must be performed by client code
*/
- public static function getFileKey(\OC_FilesystemView $view, $filePath) {
+ public static function getFileKey($view, $util, $filePath) {
- $util = new Util($view, \OCP\User::getUser());
list($owner, $filename) = $util->getUidAndFilename($filePath);
$filename = Helper::stripPartialFileExtension($filename);
@@ -216,17 +213,17 @@ class Keymanager {
* @brief Delete a keyfile
*
* @param \OC_FilesystemView $view
- * @param string $userId username
* @param string $path path of the file the key belongs to
* @return bool Outcome of unlink operation
* @note $path must be relative to data/user/files. e.g. mydoc.txt NOT
* /data/admin/files/mydoc.txt
*/
- public static function deleteFileKey(\OC_FilesystemView $view, $userId, $path) {
+ public static function deleteFileKey(\OC_FilesystemView $view, $path) {
$trimmed = ltrim($path, '/');
- $util = new Util($view, \OCP\User::getUser());
+ $userId = Helper::getUser($path);
+ $util = new Util($view, $userId);
if($util->isSystemWideMountPoint($path)) {
$keyPath = '/files_encryption/keyfiles/' . $trimmed;
@@ -315,16 +312,15 @@ class Keymanager {
/**
* @brief store multiple share keys for a single file
* @param \OC_FilesystemView $view
- * @param $path
+ * @param \OCA\Encryption\Util $util
+ * @param string $path
* @param array $shareKeys
* @return bool
*/
- public static function setShareKeys(\OC_FilesystemView $view, $path, array $shareKeys) {
+ public static function setShareKeys(\OC_FilesystemView $view, $util, $path, array $shareKeys) {
// $shareKeys must be an array with the following format:
// [userId] => [encrypted key]
- // Here we need the currently logged in user, while userId can be a different user
- $util = new Util($view, \OCP\User::getUser());
list($owner, $filename) = $util->getUidAndFilename($path);
@@ -363,21 +359,18 @@ class Keymanager {
* @brief retrieve shareKey for an encrypted file
* @param \OC_FilesystemView $view
* @param string $userId
+ * @param \OCA\Encryption\Util $util
* @param string $filePath
- * @internal param \OCA\Encryption\file $string name
* @return string file key or false
* @note The sharekey returned is encrypted. Decryption
* of the keyfile must be performed by client code
*/
- public static function getShareKey(\OC_FilesystemView $view, $userId, $filePath) {
+ public static function getShareKey(\OC_FilesystemView $view, $userId, $util, $filePath) {
// try reusing key file if part file
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
- //here we need the currently logged in user, while userId can be a different user
- $util = new Util($view, \OCP\User::getUser());
-
list($owner, $filename) = $util->getUidAndFilename($filePath);
$filename = Helper::stripPartialFileExtension($filename);
// in case of system wide mount points the keys are stored directly in the data directory
@@ -444,8 +437,9 @@ class Keymanager {
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
- //here we need the currently logged in user, while userId can be a different user
- $util = new Util($view, \OCP\User::getUser());
+ $userId = Helper::getUser($filePath);
+
+ $util = new Util($view, $userId);
list($owner, $filename) = $util->getUidAndFilename($filePath);
diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php
index a8c74bd9dd..5ba3bfa784 100644
--- a/apps/files_encryption/lib/proxy.php
+++ b/apps/files_encryption/lib/proxy.php
@@ -47,8 +47,10 @@ class Proxy extends \OC_FileProxy {
*/
private static function shouldEncrypt($path) {
+ $userId = Helper::getUser($path);
+
if (\OCP\App::isEnabled('files_encryption') === false || Crypt::mode() !== 'server' ||
- strpos($path, '/' . \OCP\User::getUser() . '/files') !== 0) {
+ strpos($path, '/' . $userId . '/files') !== 0) {
return false;
}
@@ -201,7 +203,7 @@ class Proxy extends \OC_FileProxy {
list($owner, $ownerPath) = $util->getUidAndFilename($relativePath);
// Delete keyfile & shareKey so it isn't orphaned
- if (!Keymanager::deleteFileKey($view, $owner, $ownerPath)) {
+ if (!Keymanager::deleteFileKey($view, $ownerPath)) {
\OCP\Util::writeLog('Encryption library',
'Keyfile or shareKey could not be deleted for file "' . $ownerPath . '"', \OCP\Util::ERROR);
}
@@ -244,9 +246,6 @@ class Proxy extends \OC_FileProxy {
// split the path parts
$pathParts = explode('/', $path);
- // get relative path
- $relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path);
-
// FIXME: handling for /userId/cache used by webdav for chunking. The cache chunks are NOT encrypted
if (isset($pathParts[2]) && $pathParts[2] === 'cache') {
return $result;
@@ -260,7 +259,8 @@ class Proxy extends \OC_FileProxy {
$view = new \OC_FilesystemView('');
- $util = new Util($view, \OCP\USER::getUser());
+ $userId = Helper::getUser($path);
+ $util = new Util($view, $userId);
// If file is already encrypted, decrypt using crypto protocol
if (
@@ -323,7 +323,7 @@ class Proxy extends \OC_FileProxy {
$view = new \OC_FilesystemView('/');
- $userId = \OCP\User::getUser();
+ $userId = Helper::getUser($path);
$util = new Util($view, $userId);
// if encryption is no longer enabled or if the files aren't migrated yet
@@ -401,7 +401,7 @@ class Proxy extends \OC_FileProxy {
$view = new \OC_FilesystemView('/');
$session = new \OCA\Encryption\Session($view);
- $userId = \OCP\User::getUser();
+ $userId = Helper::getUser($path);
$util = new Util($view, $userId);
// split the path parts
diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php
index 1186a5f1d8..7a37d2200a 100644
--- a/apps/files_encryption/lib/stream.php
+++ b/apps/files_encryption/lib/stream.php
@@ -55,6 +55,7 @@ class Stream {
private $rawPath; // The raw path relative to the data dir
private $relPath; // rel path to users file dir
private $userId;
+ private $keyId;
private $handle; // Resource returned by fopen
private $meta = array(); // Header / meta for source stream
private $writeCache;
@@ -90,17 +91,22 @@ class Stream {
$this->rootView = new \OC_FilesystemView('/');
}
+
$this->session = new \OCA\Encryption\Session($this->rootView);
- $this->privateKey = $this->session->getPrivateKey($this->userId);
-
- $util = new Util($this->rootView, \OCP\USER::getUser());
-
- $this->userId = $util->getUserId();
+ $this->privateKey = $this->session->getPrivateKey();
// rawPath is relative to the data directory
$this->rawPath = \OC\Files\Filesystem::normalizePath(str_replace('crypt://', '', $path));
+ $this->userId = Helper::getUser($this->rawPath);
+
+ $util = new Util($this->rootView, $this->userId);
+
+ // get the key ID which we want to use, can be the users key or the
+ // public share key
+ $this->keyId = $util->getKeyId();
+
// Strip identifier text from path, this gives us the path relative to data/',
+ filterModeAssisted: 0,
+ filterModeRaw: 1,
ajax: function(param, fnOnSuccess, fnOnError) {
$.post(
@@ -160,10 +162,7 @@ var LdapWizard = {
applyChanges: function (result) {
for (id in result.changes) {
- if(!$.isArray(result.changes[id])) {
- //no need to blacklist multiselect
- LdapWizard.saveBlacklist[id] = true;
- }
+ LdapWizard.blacklistAdd(id);
if(id.indexOf('count') > 0) {
$('#'+id).text(result.changes[id]);
} else {
@@ -195,6 +194,25 @@ var LdapWizard = {
}
},
+
+ blacklistAdd: function(id) {
+ obj = $('#'+id);
+ if(!(obj[0].hasOwnProperty('multiple') && obj[0]['multiple'] == true)) {
+ //no need to blacklist multiselect
+ LdapWizard.saveBlacklist[id] = true;
+ return true;
+ }
+ return false;
+ },
+
+ blacklistRemove: function(id) {
+ if(LdapWizard.saveBlacklist.hasOwnProperty(id)) {
+ delete LdapWizard.saveBlacklist[id];
+ return true;
+ }
+ return false;
+ },
+
checkBaseDN: function() {
host = $('#ldap_host').val();
port = $('#ldap_port').val();
@@ -204,7 +222,8 @@ var LdapWizard = {
//FIXME: determine base dn with anonymous access
if(host && port && user && pass) {
param = 'action=guessBaseDN'+
- '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val();
+ '&ldap_serverconfig_chooser='+
+ encodeURIComponent($('#ldap_serverconfig_chooser').val());
LdapWizard.showSpinner('#ldap_base');
$('#ldap_base').prop('disabled', 'disabled');
@@ -232,7 +251,8 @@ var LdapWizard = {
if(host && !port) {
param = 'action=guessPortAndTLS'+
- '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val();
+ '&ldap_serverconfig_chooser='+
+ encodeURIComponent($('#ldap_serverconfig_chooser').val());
LdapWizard.showSpinner('#ldap_port');
$('#ldap_port').prop('disabled', 'disabled');
@@ -256,6 +276,12 @@ var LdapWizard = {
},
composeFilter: function(type) {
+ subject = type.charAt(0).toUpperCase() + type.substr(1);
+ if(!$('#raw'+subject+'FilterContainer').hasClass('invisible')) {
+ //Raw filter editing, i.e. user defined filter, don't compose
+ return;
+ }
+
if(type == 'user') {
action = 'getUserListFilter';
} else if(type == 'login') {
@@ -265,7 +291,8 @@ var LdapWizard = {
}
param = 'action='+action+
- '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val();
+ '&ldap_serverconfig_chooser='+
+ encodeURIComponent($('#ldap_serverconfig_chooser').val());
LdapWizard.ajax(param,
function(result) {
@@ -323,7 +350,8 @@ var LdapWizard = {
_countThings: function(method) {
param = 'action='+method+
- '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val();
+ '&ldap_serverconfig_chooser='+
+ encodeURIComponent($('#ldap_serverconfig_chooser').val());
LdapWizard.ajax(param,
function(result) {
@@ -345,7 +373,8 @@ var LdapWizard = {
detectGroupMemberAssoc: function() {
param = 'action=determineGroupMemberAssoc'+
- '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val();
+ '&ldap_serverconfig_chooser='+
+ encodeURIComponent($('#ldap_serverconfig_chooser').val());
LdapWizard.ajax(param,
function(result) {
@@ -359,7 +388,8 @@ var LdapWizard = {
findAttributes: function() {
param = 'action=determineAttributes'+
- '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val();
+ '&ldap_serverconfig_chooser='+
+ encodeURIComponent($('#ldap_serverconfig_chooser').val());
LdapWizard.showSpinner('#ldap_loginfilter_attributes');
LdapWizard.ajax(param,
@@ -374,7 +404,9 @@ var LdapWizard = {
LdapWizard.hideSpinner('#ldap_loginfilter_attributes');
LdapWizard.applyChanges(result);
$('#ldap_loginfilter_attributes').multiselect('refresh');
- $('#ldap_loginfilter_attributes').multiselect('enable');
+ if($('#rawLoginFilterContainer').hasClass('invisible')) {
+ $('#ldap_loginfilter_attributes').multiselect('enable');
+ }
},
function (result) {
//deactivate if no attributes found
@@ -390,8 +422,9 @@ var LdapWizard = {
if(type != 'Users' && type != 'Groups') {
return false;
}
- param = 'action=determineGroupsFor'+type+
- '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val();
+ param = 'action=determineGroupsFor'+encodeURIComponent(type)+
+ '&ldap_serverconfig_chooser='+
+ encodeURIComponent($('#ldap_serverconfig_chooser').val());
LdapWizard.showSpinner('#'+multisel);
LdapWizard.ajax(param,
@@ -405,7 +438,11 @@ var LdapWizard = {
LdapWizard.hideSpinner('#'+multisel);
LdapWizard.applyChanges(result);
$('#'+multisel).multiselect('refresh');
- $('#'+multisel).multiselect('enable');
+ part = type.slice(0, -1);
+ if($('#raw' + part + 'FilterContainer').hasClass('invisible')) {
+ //enable only when raw filter editing is not turned on
+ $('#'+multisel).multiselect('enable');
+ }
},
function (result) {
LdapWizard.hideSpinner('#'+multisel);
@@ -418,8 +455,9 @@ var LdapWizard = {
if(type != 'User' && type != 'Group') {
return false;
}
- param = 'action=determine'+type+'ObjectClasses'+
- '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val();
+ param = 'action=determine'+encodeURIComponent(type)+'ObjectClasses'+
+ '&ldap_serverconfig_chooser='+
+ encodeURIComponent($('#ldap_serverconfig_chooser').val());
LdapWizard.showSpinner('#'+multisel);
LdapWizard.ajax(param,
@@ -485,15 +523,15 @@ var LdapWizard = {
},
initGroupFilter: function() {
+ LdapWizard.regardFilterMode('Group');
LdapWizard.findObjectClasses('ldap_groupfilter_objectclass', 'Group');
LdapWizard.findAvailableGroups('ldap_groupfilter_groups', 'Groups');
- LdapWizard.composeFilter('group');
LdapWizard.countGroups();
},
initLoginFilter: function() {
+ LdapWizard.regardFilterMode('Login');
LdapWizard.findAttributes();
- LdapWizard.composeFilter('login');
},
initMultiSelect: function(object, id, caption) {
@@ -509,9 +547,9 @@ var LdapWizard = {
},
initUserFilter: function() {
+ LdapWizard.regardFilterMode('User');
LdapWizard.findObjectClasses('ldap_userfilter_objectclass', 'User');
LdapWizard.findAvailableGroups('ldap_userfilter_groups', 'Users');
- LdapWizard.composeFilter('user');
LdapWizard.countUsers();
},
@@ -566,9 +604,36 @@ var LdapWizard = {
}
},
+ regardFilterMode: function(subject) {
+ param = 'action=get'+encodeURIComponent(subject)+'FilterMode'+
+ '&ldap_serverconfig_chooser='+
+ encodeURIComponent($('#ldap_serverconfig_chooser').val());
+
+ LdapWizard.ajax(param,
+ function(result) {
+ property = 'ldap' + subject + 'FilterMode';
+ mode = result.changes[property];
+ if(mode == LdapWizard.filterModeRaw
+ && $('#raw'+subject+'FilterContainer').hasClass('invisible')) {
+ LdapWizard['toggleRaw'+subject+'Filter']();
+ } else if(mode == LdapWizard.filterModeAssisted
+ && !$('#raw'+subject+'FilterContainer').hasClass('invisible')) {
+ LdapWizard['toggleRaw'+subject+'Filter']();
+ } else {
+ c = $('#raw'+subject+'FilterContainer').hasClass('invisible');
+ }
+ },
+ function (result) {
+ //on error case get back to default i.e. Assisted
+ if(!$('#raw'+subject+'FilterContainer').hasClass('invisible')) {
+ LdapWizard['toggleRaw'+subject+'Filter']();
+ }
+ }
+ );
+ },
+
save: function(inputObj) {
- if(LdapWizard.saveBlacklist.hasOwnProperty(inputObj.id)) {
- delete LdapWizard.saveBlacklist[inputObj.id];
+ if(LdapWizard.blacklistRemove(inputObj.id)) {
return;
}
if($(inputObj).is('input[type=checkbox]')
@@ -601,8 +666,8 @@ var LdapWizard = {
},
_save: function(object, value) {
- param = 'cfgkey='+object.id+
- '&cfgval='+value+
+ param = 'cfgkey='+encodeURIComponent(object.id)+
+ '&cfgval='+encodeURIComponent(value)+
'&action=save'+
'&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val();
@@ -632,7 +697,9 @@ var LdapWizard = {
}
},
- toggleRawFilter: function(container, moc, mg, stateVar) {
+ toggleRawFilter: function(container, moc, mg, stateVar, modeKey) {
+ //moc = multiselect objectclass
+ //mg = mutliselect groups
if($(container).hasClass('invisible')) {
$(container).removeClass('invisible');
$(moc).multiselect('disable');
@@ -642,26 +709,62 @@ var LdapWizard = {
LdapWizard[stateVar] = 'enable';
}
$(mg).multiselect('disable');
+ LdapWizard._save({ id: modeKey }, LdapWizard.filterModeRaw);
} else {
$(container).addClass('invisible');
$(mg).multiselect(LdapWizard[stateVar]);
$(moc).multiselect('enable');
+ LdapWizard._save({ id: modeKey }, LdapWizard.filterModeAssisted);
+ if(moc.indexOf('user') >= 0) {
+ LdapWizard.blacklistRemove('ldap_userlist_filter');
+ LdapWizard.composeFilter('user');
+ } else {
+ LdapWizard.blacklistRemove('ldap_group_filter');
+ LdapWizard.composeFilter('group');
+ }
}
},
toggleRawGroupFilter: function() {
+ LdapWizard.blacklistRemove('ldap_group_filter');
LdapWizard.toggleRawFilter('#rawGroupFilterContainer',
'#ldap_groupfilter_objectclass',
'#ldap_groupfilter_groups',
- 'groupFilterGroupSelectState'
+ 'groupFilterGroupSelectState',
+ 'ldapGroupFilterMode'
);
},
+ toggleRawLoginFilter: function() {
+ LdapWizard.blacklistRemove('ldap_login_filter');
+ container = '#rawLoginFilterContainer';
+ if($(container).hasClass('invisible')) {
+ $(container).removeClass('invisible');
+ action = 'disable';
+ property = 'disabled';
+ mode = LdapWizard.filterModeRaw;
+ } else {
+ $(container).addClass('invisible');
+ action = 'enable';
+ property = false;
+ mode = LdapWizard.filterModeAssisted;
+ }
+ $('#ldap_loginfilter_attributes').multiselect(action);
+ $('#ldap_loginfilter_email').prop('disabled', property);
+ $('#ldap_loginfilter_username').prop('disabled', property);
+ LdapWizard._save({ id: 'ldapLoginFilterMode' }, mode);
+ if(action == 'enable') {
+ LdapWizard.composeFilter('login');
+ }
+ },
+
toggleRawUserFilter: function() {
+ LdapWizard.blacklistRemove('ldap_userlist_filter');
LdapWizard.toggleRawFilter('#rawUserFilterContainer',
'#ldap_userfilter_objectclass',
'#ldap_userfilter_groups',
- 'userFilterGroupSelectState'
+ 'userFilterGroupSelectState',
+ 'ldapUserFilterMode'
);
},
@@ -722,6 +825,7 @@ $(document).ready(function() {
$('.lwautosave').change(function() { LdapWizard.save(this); });
$('#toggleRawUserFilter').click(LdapWizard.toggleRawUserFilter);
$('#toggleRawGroupFilter').click(LdapWizard.toggleRawGroupFilter);
+ $('#toggleRawLoginFilter').click(LdapWizard.toggleRawLoginFilter);
LdapConfiguration.refreshConfig();
$('.ldap_action_continue').click(function(event) {
event.preventDefault();
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..c396d5b4bf 100644
--- a/apps/user_ldap/lib/configuration.php
+++ b/apps/user_ldap/lib/configuration.php
@@ -47,12 +47,15 @@ class Configuration {
'ldapUserFilterObjectclass' => null,
'ldapUserFilterGroups' => null,
'ldapUserFilter' => null,
+ 'ldapUserFilterMode' => null,
'ldapGroupFilter' => null,
+ 'ldapGroupFilterMode' => null,
'ldapGroupFilterObjectclass' => null,
'ldapGroupFilterGroups' => null,
'ldapGroupDisplayName' => null,
'ldapGroupMemberAssocAttr' => null,
'ldapLoginFilter' => null,
+ 'ldapLoginFilterMode' => null,
'ldapLoginFilterEmail' => null,
'ldapLoginFilterUsername' => null,
'ldapLoginFilterAttributes' => null,
@@ -72,6 +75,7 @@ class Configuration {
'ldapExpertUsernameAttr' => null,
'ldapExpertUUIDUserAttr' => null,
'ldapExpertUUIDGroupAttr' => null,
+ 'lastJpegPhotoLookup' => null,
);
public function __construct($configPrefix, $autoread = true) {
@@ -301,13 +305,16 @@ class Configuration {
'ldap_base_users' => '',
'ldap_base_groups' => '',
'ldap_userlist_filter' => '',
+ 'ldap_user_filter_mode' => 0,
'ldap_userfilter_objectclass' => '',
'ldap_userfilter_groups' => '',
'ldap_login_filter' => 'uid=%uid',
+ 'ldap_login_filter_mode' => 0,
'ldap_loginfilter_email' => 0,
'ldap_loginfilter_username' => 1,
'ldap_loginfilter_attributes' => '',
'ldap_group_filter' => '',
+ 'ldap_group_filter_mode' => 0,
'ldap_groupfilter_objectclass' => '',
'ldap_groupfilter_groups' => '',
'ldap_display_name' => 'displayName',
@@ -330,6 +337,7 @@ class Configuration {
'ldap_expert_uuid_user_attr' => '',
'ldap_expert_uuid_group_attr' => '',
'has_memberof_filter_support' => 0,
+ 'last_jpegPhoto_lookup' => 0,
);
}
@@ -352,11 +360,14 @@ class Configuration {
'ldap_userfilter_objectclass' => 'ldapUserFilterObjectclass',
'ldap_userfilter_groups' => 'ldapUserFilterGroups',
'ldap_userlist_filter' => 'ldapUserFilter',
+ 'ldap_user_filter_mode' => 'ldapUserFilterMode',
'ldap_login_filter' => 'ldapLoginFilter',
+ 'ldap_login_filter_mode' => 'ldapLoginFilterMode',
'ldap_loginfilter_email' => 'ldapLoginFilterEmail',
'ldap_loginfilter_username' => 'ldapLoginFilterUsername',
'ldap_loginfilter_attributes' => 'ldapLoginFilterAttributes',
'ldap_group_filter' => 'ldapGroupFilter',
+ 'ldap_group_filter_mode' => 'ldapGroupFilterMode',
'ldap_groupfilter_objectclass' => 'ldapGroupFilterObjectclass',
'ldap_groupfilter_groups' => 'ldapGroupFilterGroups',
'ldap_display_name' => 'ldapUserDisplayName',
@@ -377,6 +388,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/lib/wizard.php b/apps/user_ldap/lib/wizard.php
index 9286af46be..84b397cf5e 100644
--- a/apps/user_ldap/lib/wizard.php
+++ b/apps/user_ldap/lib/wizard.php
@@ -38,6 +38,9 @@ class Wizard extends LDAPUtility {
const LFILTER_USER_LIST = 3;
const LFILTER_GROUP_LIST = 4;
+ const LFILTER_MODE_ASSISTED = 2;
+ const LFILTER_MODE_RAW = 1;
+
const LDAP_NW_TIMEOUT = 4;
/**
@@ -147,6 +150,42 @@ class Wizard extends LDAPUtility {
return $this->result;
}
+ /**
+ * @brief return the state of the Group Filter Mode
+ */
+ public function getGroupFilterMode() {
+ $this->getFilterMode('ldapGroupFilterMode');
+ return $this->result;
+ }
+
+ /**
+ * @brief return the state of the Login Filter Mode
+ */
+ public function getLoginFilterMode() {
+ $this->getFilterMode('ldapLoginFilterMode');
+ return $this->result;
+ }
+
+ /**
+ * @brief return the state of the User Filter Mode
+ */
+ public function getUserFilterMode() {
+ $this->getFilterMode('ldapUserFilterMode');
+ return $this->result;
+ }
+
+ /**
+ * @brief return the state of the mode of the specified filter
+ * @param $confkey string, contains the access key of the Configuration
+ */
+ private function getFilterMode($confkey) {
+ $mode = $this->configuration->$confkey;
+ if(is_null($mode)) {
+ $mode = $this->LFILTER_MODE_ASSISTED;
+ }
+ $this->result->addChange($confkey, $mode);
+ }
+
/**
* @brief detects the available LDAP attributes
* @returns the instance's WizardResult instance
diff --git a/apps/user_ldap/templates/part.wizard-loginfilter.php b/apps/user_ldap/templates/part.wizard-loginfilter.php
index d4a36eb0cb..dc5d61e9f7 100644
--- a/apps/user_ldap/templates/part.wizard-loginfilter.php
+++ b/apps/user_ldap/templates/part.wizard-loginfilter.php
@@ -28,6 +28,16 @@
name="ldap_loginfilter_attributes">
+ +
++ " + /> +
" />
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'