Signed-off-by: Joas Schilling <coding@schilljs.com>tags/v24.0.0beta1
); | ); | ||||
}); | }); | ||||
$container->registerService(ILDAPWrapper::class, function () { | |||||
return new LDAP(); | |||||
$container->registerService(ILDAPWrapper::class, function (IAppContainer $appContainer) { | |||||
/** @var IServerContainer $server */ | |||||
$server = $appContainer->get(IServerContainer::class); | |||||
return new LDAP( | |||||
$server->getConfig()->getSystemValueString('ldap_log_file') | |||||
); | |||||
}); | }); | ||||
} | } | ||||
if (isset($argument['ldapWrapper'])) { | if (isset($argument['ldapWrapper'])) { | ||||
$this->ldap = $argument['ldapWrapper']; | $this->ldap = $argument['ldapWrapper']; | ||||
} else { | } else { | ||||
$this->ldap = new LDAP(); | |||||
$this->ldap = new LDAP($this->config->getSystemValueString('ldap_log_file')); | |||||
} | } | ||||
if (isset($argument['avatarManager'])) { | if (isset($argument['avatarManager'])) { |
use OCA\User_LDAP\PagedResults\Php73; | use OCA\User_LDAP\PagedResults\Php73; | ||||
class LDAP implements ILDAPWrapper { | class LDAP implements ILDAPWrapper { | ||||
protected $logFile = ''; | |||||
protected $curFunc = ''; | protected $curFunc = ''; | ||||
protected $curArgs = []; | protected $curArgs = []; | ||||
/** @var IAdapter */ | /** @var IAdapter */ | ||||
protected $pagedResultsAdapter; | protected $pagedResultsAdapter; | ||||
public function __construct() { | |||||
public function __construct(string $logFile = '') { | |||||
$this->pagedResultsAdapter = new Php73(); | $this->pagedResultsAdapter = new Php73(); | ||||
$this->logFile = $logFile; | |||||
} | } | ||||
/** | /** | ||||
private function preFunctionCall($functionName, $args) { | private function preFunctionCall($functionName, $args) { | ||||
$this->curFunc = $functionName; | $this->curFunc = $functionName; | ||||
$this->curArgs = $args; | $this->curArgs = $args; | ||||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||||
$args = array_reduce($this->curArgs, static function (array $carry, $item): array { | |||||
$carry[] = !is_resource($item) ? $item : '(resource)'; | |||||
return $carry; | |||||
}, []); | |||||
file_put_contents( | |||||
$this->logFile, | |||||
$this->curFunc . '::' . json_encode($args) . "\n", | |||||
FILE_APPEND | |||||
); | |||||
} | |||||
} | } | ||||
/** | /** |
* Defaults to ``true`` | * Defaults to ``true`` | ||||
*/ | */ | ||||
'files_no_background_scan' => false, | 'files_no_background_scan' => false, | ||||
/** | |||||
* Log all queries into a file | |||||
* | |||||
* Warning: This heavily decreases the performance of the server and is only | |||||
* meant to debug/profile the query interaction manually. | |||||
* Also, it might log sensitive data into a plain text file. | |||||
*/ | |||||
'query_log_file' => '', | |||||
/** | |||||
* Log all redis requests into a file | |||||
* | |||||
* Warning: This heavily decreases the performance of the server and is only | |||||
* meant to debug/profile the redis interaction manually. | |||||
* Also, it might log sensitive data into a plain text file. | |||||
*/ | |||||
'redis_log_file' => '', | |||||
/** | |||||
* Log all LDAP requests into a file | |||||
* | |||||
* Warning: This heavily decreases the performance of the server and is only | |||||
* meant to debug/profile the LDAP interaction manually. | |||||
* Also, it might log sensitive data into a plain text file. | |||||
*/ | |||||
'ldap_log_file' => '', | |||||
]; | ]; |
$sql = $this->replaceTablePrefix($sql); | $sql = $this->replaceTablePrefix($sql); | ||||
$sql = $this->adapter->fixupStatement($sql); | $sql = $this->adapter->fixupStatement($sql); | ||||
$this->queriesExecuted++; | $this->queriesExecuted++; | ||||
$this->logQueryToFile($sql); | |||||
return parent::executeQuery($sql, $params, $types, $qcp); | return parent::executeQuery($sql, $params, $types, $qcp); | ||||
} | } | ||||
$sql = $this->replaceTablePrefix($sql); | $sql = $this->replaceTablePrefix($sql); | ||||
$sql = $this->adapter->fixupStatement($sql); | $sql = $this->adapter->fixupStatement($sql); | ||||
$this->queriesExecuted++; | $this->queriesExecuted++; | ||||
$this->logQueryToFile($sql); | |||||
return parent::executeUpdate($sql, $params, $types); | return parent::executeUpdate($sql, $params, $types); | ||||
} | } | ||||
$sql = $this->replaceTablePrefix($sql); | $sql = $this->replaceTablePrefix($sql); | ||||
$sql = $this->adapter->fixupStatement($sql); | $sql = $this->adapter->fixupStatement($sql); | ||||
$this->queriesExecuted++; | $this->queriesExecuted++; | ||||
$this->logQueryToFile($sql); | |||||
return parent::executeStatement($sql, $params, $types); | return parent::executeStatement($sql, $params, $types); | ||||
} | } | ||||
protected function logQueryToFile(string $sql): void { | |||||
$logFile = $this->systemConfig->getValue('query_log_file', ''); | |||||
if ($logFile !== '' && is_writable($logFile)) { | |||||
file_put_contents( | |||||
$this->systemConfig->getValue('query_log_file', ''), | |||||
$sql . "\n", | |||||
FILE_APPEND | |||||
); | |||||
} | |||||
} | |||||
/** | /** | ||||
* Returns the ID of the last inserted row, or the last value from a sequence object, | * Returns the ID of the last inserted row, or the last value from a sequence object, | ||||
* depending on the underlying driver. | * depending on the underlying driver. |
*/ | */ | ||||
private $lockingCacheClass; | private $lockingCacheClass; | ||||
/** @var string */ | |||||
private $logFile; | |||||
/** | /** | ||||
* @param string $globalPrefix | * @param string $globalPrefix | ||||
* @param ILogger $logger | * @param ILogger $logger | ||||
* @param string|null $localCacheClass | * @param string|null $localCacheClass | ||||
* @param string|null $distributedCacheClass | * @param string|null $distributedCacheClass | ||||
* @param string|null $lockingCacheClass | * @param string|null $lockingCacheClass | ||||
* @param string $logFile | |||||
*/ | */ | ||||
public function __construct(string $globalPrefix, ILogger $logger, | public function __construct(string $globalPrefix, ILogger $logger, | ||||
$localCacheClass = null, $distributedCacheClass = null, $lockingCacheClass = null) { | |||||
$localCacheClass = null, $distributedCacheClass = null, $lockingCacheClass = null, string $logFile = '') { | |||||
$this->logger = $logger; | $this->logger = $logger; | ||||
$this->logFile = $logFile; | |||||
$this->globalPrefix = $globalPrefix; | $this->globalPrefix = $globalPrefix; | ||||
if (!$localCacheClass) { | if (!$localCacheClass) { | ||||
* @return IMemcache | * @return IMemcache | ||||
*/ | */ | ||||
public function createLocking(string $prefix = ''): IMemcache { | public function createLocking(string $prefix = ''): IMemcache { | ||||
return new $this->lockingCacheClass($this->globalPrefix . '/' . $prefix); | |||||
return new $this->lockingCacheClass($this->globalPrefix . '/' . $prefix, $this->logFile); | |||||
} | } | ||||
/** | /** | ||||
* @return ICache | * @return ICache | ||||
*/ | */ | ||||
public function createDistributed(string $prefix = ''): ICache { | public function createDistributed(string $prefix = ''): ICache { | ||||
return new $this->distributedCacheClass($this->globalPrefix . '/' . $prefix); | |||||
return new $this->distributedCacheClass($this->globalPrefix . '/' . $prefix, $this->logFile); | |||||
} | } | ||||
/** | /** | ||||
* @return ICache | * @return ICache | ||||
*/ | */ | ||||
public function createLocal(string $prefix = ''): ICache { | public function createLocal(string $prefix = ''): ICache { | ||||
return new $this->localCacheClass($this->globalPrefix . '/' . $prefix); | |||||
return new $this->localCacheClass($this->globalPrefix . '/' . $prefix, $this->logFile); | |||||
} | } | ||||
/** | /** |
*/ | */ | ||||
private static $cache = null; | private static $cache = null; | ||||
public function __construct($prefix = '') { | |||||
private $logFile; | |||||
public function __construct($prefix = '', string $logFile = '') { | |||||
parent::__construct($prefix); | parent::__construct($prefix); | ||||
$this->logFile = $logFile; | |||||
if (is_null(self::$cache)) { | if (is_null(self::$cache)) { | ||||
self::$cache = \OC::$server->getGetRedisFactory()->getInstance(); | self::$cache = \OC::$server->getGetRedisFactory()->getInstance(); | ||||
} | } | ||||
} | } | ||||
public function get($key) { | public function get($key) { | ||||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||||
file_put_contents( | |||||
$this->logFile, | |||||
$this->getNameSpace() . '::get::' . $key . "\n", | |||||
FILE_APPEND | |||||
); | |||||
} | |||||
$result = self::$cache->get($this->getNameSpace() . $key); | $result = self::$cache->get($this->getNameSpace() . $key); | ||||
if ($result === false && !self::$cache->exists($this->getNameSpace() . $key)) { | if ($result === false && !self::$cache->exists($this->getNameSpace() . $key)) { | ||||
return null; | return null; | ||||
} | } | ||||
public function set($key, $value, $ttl = 0) { | public function set($key, $value, $ttl = 0) { | ||||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||||
file_put_contents( | |||||
$this->logFile, | |||||
$this->getNameSpace() . '::set::' . $key . '::' . $ttl . '::' . json_encode($value) . "\n", | |||||
FILE_APPEND | |||||
); | |||||
} | |||||
if ($ttl > 0) { | if ($ttl > 0) { | ||||
return self::$cache->setex($this->getNameSpace() . $key, $ttl, json_encode($value)); | return self::$cache->setex($this->getNameSpace() . $key, $ttl, json_encode($value)); | ||||
} else { | } else { | ||||
} | } | ||||
public function hasKey($key) { | public function hasKey($key) { | ||||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||||
file_put_contents( | |||||
$this->logFile, | |||||
$this->getNameSpace() . '::hasKey::' . $key . "\n", | |||||
FILE_APPEND | |||||
); | |||||
} | |||||
return (bool)self::$cache->exists($this->getNameSpace() . $key); | return (bool)self::$cache->exists($this->getNameSpace() . $key); | ||||
} | } | ||||
public function remove($key) { | public function remove($key) { | ||||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||||
file_put_contents( | |||||
$this->logFile, | |||||
$this->getNameSpace() . '::remove::' . $key . "\n", | |||||
FILE_APPEND | |||||
); | |||||
} | |||||
if (self::$cache->del($this->getNameSpace() . $key)) { | if (self::$cache->del($this->getNameSpace() . $key)) { | ||||
return true; | return true; | ||||
} else { | } else { | ||||
} | } | ||||
public function clear($prefix = '') { | public function clear($prefix = '') { | ||||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||||
file_put_contents( | |||||
$this->logFile, | |||||
$this->getNameSpace() . '::clear::' . $prefix . "\n", | |||||
FILE_APPEND | |||||
); | |||||
} | |||||
$prefix = $this->getNameSpace() . $prefix . '*'; | $prefix = $this->getNameSpace() . $prefix . '*'; | ||||
$keys = self::$cache->keys($prefix); | $keys = self::$cache->keys($prefix); | ||||
$deleted = self::$cache->del($keys); | $deleted = self::$cache->del($keys); | ||||
if ($ttl !== 0 && is_int($ttl)) { | if ($ttl !== 0 && is_int($ttl)) { | ||||
$args['ex'] = $ttl; | $args['ex'] = $ttl; | ||||
} | } | ||||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||||
file_put_contents( | |||||
$this->logFile, | |||||
$this->getNameSpace() . '::add::' . $key . '::' . $value . "\n", | |||||
FILE_APPEND | |||||
); | |||||
} | |||||
return self::$cache->set($this->getPrefix() . $key, $value, $args); | return self::$cache->set($this->getPrefix() . $key, $value, $args); | ||||
} | } | ||||
* @return int | bool | * @return int | bool | ||||
*/ | */ | ||||
public function inc($key, $step = 1) { | public function inc($key, $step = 1) { | ||||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||||
file_put_contents( | |||||
$this->logFile, | |||||
$this->getNameSpace() . '::inc::' . $key . "\n", | |||||
FILE_APPEND | |||||
); | |||||
} | |||||
return self::$cache->incrBy($this->getNameSpace() . $key, $step); | return self::$cache->incrBy($this->getNameSpace() . $key, $step); | ||||
} | } | ||||
* @return int | bool | * @return int | bool | ||||
*/ | */ | ||||
public function dec($key, $step = 1) { | public function dec($key, $step = 1) { | ||||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||||
file_put_contents( | |||||
$this->logFile, | |||||
$this->getNameSpace() . '::dec::' . $key . "\n", | |||||
FILE_APPEND | |||||
); | |||||
} | |||||
if (!$this->hasKey($key)) { | if (!$this->hasKey($key)) { | ||||
return false; | return false; | ||||
} | } | ||||
* @return bool | * @return bool | ||||
*/ | */ | ||||
public function cas($key, $old, $new) { | public function cas($key, $old, $new) { | ||||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||||
file_put_contents( | |||||
$this->logFile, | |||||
$this->getNameSpace() . '::cas::' . $key . "\n", | |||||
FILE_APPEND | |||||
); | |||||
} | |||||
if (!is_int($new)) { | if (!is_int($new)) { | ||||
$new = json_encode($new); | $new = json_encode($new); | ||||
} | } | ||||
* @return bool | * @return bool | ||||
*/ | */ | ||||
public function cad($key, $old) { | public function cad($key, $old) { | ||||
if ($this->logFile !== '' && is_writable($this->logFile)) { | |||||
file_put_contents( | |||||
$this->logFile, | |||||
$this->getNameSpace() . '::cad::' . $key . "\n", | |||||
FILE_APPEND | |||||
); | |||||
} | |||||
self::$cache->watch($this->getNameSpace() . $key); | self::$cache->watch($this->getNameSpace() . $key); | ||||
if ($this->get($key) === $old) { | if ($this->get($key) === $old) { | ||||
$result = self::$cache->multi() | $result = self::$cache->multi() |
return new \OC\Memcache\Factory($prefix, $c->get(ILogger::class), | return new \OC\Memcache\Factory($prefix, $c->get(ILogger::class), | ||||
$config->getSystemValue('memcache.local', null), | $config->getSystemValue('memcache.local', null), | ||||
$config->getSystemValue('memcache.distributed', null), | $config->getSystemValue('memcache.distributed', null), | ||||
$config->getSystemValue('memcache.locking', null) | |||||
$config->getSystemValue('memcache.locking', null), | |||||
$config->getSystemValueString('redis_log_file') | |||||
); | ); | ||||
} | } | ||||
return $arrayCacheFactory; | return $arrayCacheFactory; |