Completed
Push — master ( ae6394...970eb8 )
by John
31:32 queued 02:08
created
lib/private/Security/TrustedDomainHelper.php 2 patches
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -70,7 +70,7 @@  discard block
 block discarded – undo
70 70
 		}
71 71
 
72 72
 		if (isset($parsedUrl['port']) && $parsedUrl['port']) {
73
-			return $this->isTrustedDomain($parsedUrl['host'] . ':' . $parsedUrl['port']);
73
+			return $this->isTrustedDomain($parsedUrl['host'].':'.$parsedUrl['port']);
74 74
 		}
75 75
 
76 76
 		return $this->isTrustedDomain($parsedUrl['host']);
@@ -106,9 +106,9 @@  discard block
 block discarded – undo
106 106
 			if (gettype($trusted) !== 'string') {
107 107
 				break;
108 108
 			}
109
-			$regex = '/^' . implode('[-\.a-zA-Z0-9]*', array_map(function ($v) {
109
+			$regex = '/^'.implode('[-\.a-zA-Z0-9]*', array_map(function($v) {
110 110
 				return preg_quote($v, '/');
111
-			}, explode('*', $trusted))) . '$/i';
111
+			}, explode('*', $trusted))).'$/i';
112 112
 			if (preg_match($regex, $domain) || preg_match($regex, $domainWithPort)) {
113 113
 				return true;
114 114
 			}
Please login to merge, or discard this patch.
Indentation   +67 added lines, -67 removed lines patch added patch discarded remove patch
@@ -13,79 +13,79 @@
 block discarded – undo
13 13
 use OCP\Security\ITrustedDomainHelper;
14 14
 
15 15
 class TrustedDomainHelper implements ITrustedDomainHelper {
16
-	public function __construct(
17
-		private IConfig $config,
18
-	) {
19
-	}
16
+    public function __construct(
17
+        private IConfig $config,
18
+    ) {
19
+    }
20 20
 
21
-	/**
22
-	 * Strips a potential port from a domain (in format domain:port)
23
-	 * @return string $host without appended port
24
-	 */
25
-	private function getDomainWithoutPort(string $host): string {
26
-		$pos = strrpos($host, ':');
27
-		if ($pos !== false) {
28
-			$port = substr($host, $pos + 1);
29
-			if (is_numeric($port)) {
30
-				$host = substr($host, 0, $pos);
31
-			}
32
-		}
33
-		return $host;
34
-	}
21
+    /**
22
+     * Strips a potential port from a domain (in format domain:port)
23
+     * @return string $host without appended port
24
+     */
25
+    private function getDomainWithoutPort(string $host): string {
26
+        $pos = strrpos($host, ':');
27
+        if ($pos !== false) {
28
+            $port = substr($host, $pos + 1);
29
+            if (is_numeric($port)) {
30
+                $host = substr($host, 0, $pos);
31
+            }
32
+        }
33
+        return $host;
34
+    }
35 35
 
36
-	/**
37
-	 * {@inheritDoc}
38
-	 */
39
-	public function isTrustedUrl(string $url): bool {
40
-		$parsedUrl = parse_url($url);
41
-		if (empty($parsedUrl['host'])) {
42
-			return false;
43
-		}
36
+    /**
37
+     * {@inheritDoc}
38
+     */
39
+    public function isTrustedUrl(string $url): bool {
40
+        $parsedUrl = parse_url($url);
41
+        if (empty($parsedUrl['host'])) {
42
+            return false;
43
+        }
44 44
 
45
-		if (isset($parsedUrl['port']) && $parsedUrl['port']) {
46
-			return $this->isTrustedDomain($parsedUrl['host'] . ':' . $parsedUrl['port']);
47
-		}
45
+        if (isset($parsedUrl['port']) && $parsedUrl['port']) {
46
+            return $this->isTrustedDomain($parsedUrl['host'] . ':' . $parsedUrl['port']);
47
+        }
48 48
 
49
-		return $this->isTrustedDomain($parsedUrl['host']);
50
-	}
49
+        return $this->isTrustedDomain($parsedUrl['host']);
50
+    }
51 51
 
52
-	/**
53
-	 * {@inheritDoc}
54
-	 */
55
-	public function isTrustedDomain(string $domainWithPort): bool {
56
-		// overwritehost is always trusted
57
-		if ($this->config->getSystemValue('overwritehost') !== '') {
58
-			return true;
59
-		}
52
+    /**
53
+     * {@inheritDoc}
54
+     */
55
+    public function isTrustedDomain(string $domainWithPort): bool {
56
+        // overwritehost is always trusted
57
+        if ($this->config->getSystemValue('overwritehost') !== '') {
58
+            return true;
59
+        }
60 60
 
61
-		$domain = $this->getDomainWithoutPort($domainWithPort);
61
+        $domain = $this->getDomainWithoutPort($domainWithPort);
62 62
 
63
-		// Read trusted domains from config
64
-		$trustedList = $this->config->getSystemValue('trusted_domains', []);
65
-		if (!is_array($trustedList)) {
66
-			return false;
67
-		}
63
+        // Read trusted domains from config
64
+        $trustedList = $this->config->getSystemValue('trusted_domains', []);
65
+        if (!is_array($trustedList)) {
66
+            return false;
67
+        }
68 68
 
69
-		// Always allow access from localhost
70
-		if (preg_match(Request::REGEX_LOCALHOST, $domain) === 1) {
71
-			return true;
72
-		}
73
-		// Reject malformed domains in any case
74
-		if (str_starts_with($domain, '-') || str_contains($domain, '..')) {
75
-			return false;
76
-		}
77
-		// Match, allowing for * wildcards
78
-		foreach ($trustedList as $trusted) {
79
-			if (gettype($trusted) !== 'string') {
80
-				break;
81
-			}
82
-			$regex = '/^' . implode('[-\.a-zA-Z0-9]*', array_map(function ($v) {
83
-				return preg_quote($v, '/');
84
-			}, explode('*', $trusted))) . '$/i';
85
-			if (preg_match($regex, $domain) || preg_match($regex, $domainWithPort)) {
86
-				return true;
87
-			}
88
-		}
89
-		return false;
90
-	}
69
+        // Always allow access from localhost
70
+        if (preg_match(Request::REGEX_LOCALHOST, $domain) === 1) {
71
+            return true;
72
+        }
73
+        // Reject malformed domains in any case
74
+        if (str_starts_with($domain, '-') || str_contains($domain, '..')) {
75
+            return false;
76
+        }
77
+        // Match, allowing for * wildcards
78
+        foreach ($trustedList as $trusted) {
79
+            if (gettype($trusted) !== 'string') {
80
+                break;
81
+            }
82
+            $regex = '/^' . implode('[-\.a-zA-Z0-9]*', array_map(function ($v) {
83
+                return preg_quote($v, '/');
84
+            }, explode('*', $trusted))) . '$/i';
85
+            if (preg_match($regex, $domain) || preg_match($regex, $domainWithPort)) {
86
+                return true;
87
+            }
88
+        }
89
+        return false;
90
+    }
91 91
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/Migration/Version1130Date20220110154719.php 1 patch
Indentation   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -32,25 +32,25 @@
 block discarded – undo
32 32
 use OCP\Migration\SimpleMigrationStep;
33 33
 
34 34
 class Version1130Date20220110154719 extends SimpleMigrationStep {
35
-	public function getName() {
36
-		return 'Drop ldap_group_mapping_backup';
37
-	}
38
-
39
-	/**
40
-	 * @param IOutput $output
41
-	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
42
-	 * @param array $options
43
-	 * @return null|ISchemaWrapper
44
-	 */
45
-	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
46
-		/** @var ISchemaWrapper $schema */
47
-		$schema = $schemaClosure();
48
-
49
-		if ($schema->hasTable('ldap_group_mapping_backup')) {
50
-			$schema->dropTable('ldap_group_mapping_backup');
51
-			return $schema;
52
-		}
53
-
54
-		return null;
55
-	}
35
+    public function getName() {
36
+        return 'Drop ldap_group_mapping_backup';
37
+    }
38
+
39
+    /**
40
+     * @param IOutput $output
41
+     * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
42
+     * @param array $options
43
+     * @return null|ISchemaWrapper
44
+     */
45
+    public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
46
+        /** @var ISchemaWrapper $schema */
47
+        $schema = $schemaClosure();
48
+
49
+        if ($schema->hasTable('ldap_group_mapping_backup')) {
50
+            $schema->dropTable('ldap_group_mapping_backup');
51
+            return $schema;
52
+        }
53
+
54
+        return null;
55
+    }
56 56
 }
Please login to merge, or discard this patch.
apps/testing/lib/Controller/LockingController.php 2 patches
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -94,7 +94,7 @@  discard block
 block discarded – undo
94 94
 	 */
95 95
 	protected function getPath(string $user, string $path): string {
96 96
 		$node = $this->rootFolder->getUserFolder($user)->get($path);
97
-		return 'files/' . md5($node->getStorage()->getId() . '::' . trim($node->getInternalPath(), '/'));
97
+		return 'files/'.md5($node->getStorage()->getId().'::'.trim($node->getInternalPath(), '/'));
98 98
 	}
99 99
 
100 100
 	/**
@@ -125,7 +125,7 @@  discard block
 block discarded – undo
125 125
 
126 126
 		try {
127 127
 			$lockingProvider->acquireLock($path, $type);
128
-			$this->config->setAppValue('testing', 'locking_' . $path, (string)$type);
128
+			$this->config->setAppValue('testing', 'locking_'.$path, (string) $type);
129 129
 			return new DataResponse();
130 130
 		} catch (LockedException $e) {
131 131
 			throw new OCSException('', Http::STATUS_LOCKED, $e);
@@ -148,7 +148,7 @@  discard block
 block discarded – undo
148 148
 
149 149
 		try {
150 150
 			$lockingProvider->changeLock($path, $type);
151
-			$this->config->setAppValue('testing', 'locking_' . $path, (string)$type);
151
+			$this->config->setAppValue('testing', 'locking_'.$path, (string) $type);
152 152
 			return new DataResponse();
153 153
 		} catch (LockedException $e) {
154 154
 			throw new OCSException('', Http::STATUS_LOCKED, $e);
@@ -171,7 +171,7 @@  discard block
 block discarded – undo
171 171
 
172 172
 		try {
173 173
 			$lockingProvider->releaseLock($path, $type);
174
-			$this->config->deleteAppValue('testing', 'locking_' . $path);
174
+			$this->config->deleteAppValue('testing', 'locking_'.$path);
175 175
 			return new DataResponse();
176 176
 		} catch (LockedException $e) {
177 177
 			throw new OCSException('', Http::STATUS_LOCKED, $e);
@@ -206,12 +206,12 @@  discard block
 block discarded – undo
206 206
 			if (strpos($lock, 'locking_') === 0) {
207 207
 				$path = substr($lock, strlen('locking_'));
208 208
 
209
-				if ($type === ILockingProvider::LOCK_EXCLUSIVE && (int)$this->config->getAppValue('testing', $lock) === ILockingProvider::LOCK_EXCLUSIVE) {
210
-					$lockingProvider->releaseLock($path, (int)$this->config->getAppValue('testing', $lock));
211
-				} elseif ($type === ILockingProvider::LOCK_SHARED && (int)$this->config->getAppValue('testing', $lock) === ILockingProvider::LOCK_SHARED) {
212
-					$lockingProvider->releaseLock($path, (int)$this->config->getAppValue('testing', $lock));
209
+				if ($type === ILockingProvider::LOCK_EXCLUSIVE && (int) $this->config->getAppValue('testing', $lock) === ILockingProvider::LOCK_EXCLUSIVE) {
210
+					$lockingProvider->releaseLock($path, (int) $this->config->getAppValue('testing', $lock));
211
+				} elseif ($type === ILockingProvider::LOCK_SHARED && (int) $this->config->getAppValue('testing', $lock) === ILockingProvider::LOCK_SHARED) {
212
+					$lockingProvider->releaseLock($path, (int) $this->config->getAppValue('testing', $lock));
213 213
 				} else {
214
-					$lockingProvider->releaseLock($path, (int)$this->config->getAppValue('testing', $lock));
214
+					$lockingProvider->releaseLock($path, (int) $this->config->getAppValue('testing', $lock));
215 215
 				}
216 216
 			}
217 217
 		}
Please login to merge, or discard this patch.
Indentation   +160 added lines, -160 removed lines patch added patch discarded remove patch
@@ -23,164 +23,164 @@
 block discarded – undo
23 23
 
24 24
 class LockingController extends OCSController {
25 25
 
26
-	/**
27
-	 * @param string $appName
28
-	 * @param IRequest $request
29
-	 * @param ILockingProvider $lockingProvider
30
-	 * @param FakeDBLockingProvider $fakeDBLockingProvider
31
-	 * @param IDBConnection $connection
32
-	 * @param IConfig $config
33
-	 * @param IRootFolder $rootFolder
34
-	 */
35
-	public function __construct(
36
-		$appName,
37
-		IRequest $request,
38
-		protected ILockingProvider $lockingProvider,
39
-		protected FakeDBLockingProvider $fakeDBLockingProvider,
40
-		protected IDBConnection $connection,
41
-		protected IConfig $config,
42
-		protected IRootFolder $rootFolder,
43
-	) {
44
-		parent::__construct($appName, $request);
45
-	}
46
-
47
-	/**
48
-	 * @throws \RuntimeException
49
-	 */
50
-	protected function getLockingProvider(): ILockingProvider {
51
-		if ($this->lockingProvider instanceof DBLockingProvider) {
52
-			return $this->fakeDBLockingProvider;
53
-		}
54
-		throw new \RuntimeException('Lock provisioning is only possible using the DBLockingProvider');
55
-	}
56
-
57
-	/**
58
-	 * @throws NotFoundException
59
-	 */
60
-	protected function getPath(string $user, string $path): string {
61
-		$node = $this->rootFolder->getUserFolder($user)->get($path);
62
-		return 'files/' . md5($node->getStorage()->getId() . '::' . trim($node->getInternalPath(), '/'));
63
-	}
64
-
65
-	/**
66
-	 * @throws OCSException
67
-	 */
68
-	public function isLockingEnabled(): DataResponse {
69
-		try {
70
-			$this->getLockingProvider();
71
-			return new DataResponse();
72
-		} catch (\RuntimeException $e) {
73
-			throw new OCSException($e->getMessage(), Http::STATUS_NOT_IMPLEMENTED, $e);
74
-		}
75
-	}
76
-
77
-	/**
78
-	 * @throws OCSException
79
-	 */
80
-	public function acquireLock(int $type, string $user, string $path): DataResponse {
81
-		try {
82
-			$path = $this->getPath($user, $path);
83
-		} catch (NoUserException $e) {
84
-			throw new OCSException('User not found', Http::STATUS_NOT_FOUND, $e);
85
-		} catch (NotFoundException $e) {
86
-			throw new OCSException('Path not found', Http::STATUS_NOT_FOUND, $e);
87
-		}
88
-
89
-		$lockingProvider = $this->getLockingProvider();
90
-
91
-		try {
92
-			$lockingProvider->acquireLock($path, $type);
93
-			$this->config->setAppValue('testing', 'locking_' . $path, (string)$type);
94
-			return new DataResponse();
95
-		} catch (LockedException $e) {
96
-			throw new OCSException('', Http::STATUS_LOCKED, $e);
97
-		}
98
-	}
99
-
100
-	/**
101
-	 * @throws OCSException
102
-	 */
103
-	public function changeLock(int $type, string $user, string $path): DataResponse {
104
-		try {
105
-			$path = $this->getPath($user, $path);
106
-		} catch (NoUserException $e) {
107
-			throw new OCSException('User not found', Http::STATUS_NOT_FOUND, $e);
108
-		} catch (NotFoundException $e) {
109
-			throw new OCSException('Path not found', Http::STATUS_NOT_FOUND, $e);
110
-		}
111
-
112
-		$lockingProvider = $this->getLockingProvider();
113
-
114
-		try {
115
-			$lockingProvider->changeLock($path, $type);
116
-			$this->config->setAppValue('testing', 'locking_' . $path, (string)$type);
117
-			return new DataResponse();
118
-		} catch (LockedException $e) {
119
-			throw new OCSException('', Http::STATUS_LOCKED, $e);
120
-		}
121
-	}
122
-
123
-	/**
124
-	 * @throws OCSException
125
-	 */
126
-	public function releaseLock(int $type, string $user, string $path): DataResponse {
127
-		try {
128
-			$path = $this->getPath($user, $path);
129
-		} catch (NoUserException $e) {
130
-			throw new OCSException('User not found', Http::STATUS_NOT_FOUND, $e);
131
-		} catch (NotFoundException $e) {
132
-			throw new OCSException('Path not found', Http::STATUS_NOT_FOUND, $e);
133
-		}
134
-
135
-		$lockingProvider = $this->getLockingProvider();
136
-
137
-		try {
138
-			$lockingProvider->releaseLock($path, $type);
139
-			$this->config->deleteAppValue('testing', 'locking_' . $path);
140
-			return new DataResponse();
141
-		} catch (LockedException $e) {
142
-			throw new OCSException('', Http::STATUS_LOCKED, $e);
143
-		}
144
-	}
145
-
146
-	/**
147
-	 * @throws OCSException
148
-	 */
149
-	public function isLocked(int $type, string $user, string $path): DataResponse {
150
-		try {
151
-			$path = $this->getPath($user, $path);
152
-		} catch (NoUserException $e) {
153
-			throw new OCSException('User not found', Http::STATUS_NOT_FOUND, $e);
154
-		} catch (NotFoundException $e) {
155
-			throw new OCSException('Path not found', Http::STATUS_NOT_FOUND, $e);
156
-		}
157
-
158
-		$lockingProvider = $this->getLockingProvider();
159
-
160
-		if ($lockingProvider->isLocked($path, $type)) {
161
-			return new DataResponse();
162
-		}
163
-
164
-		throw new OCSException('', Http::STATUS_LOCKED);
165
-	}
166
-
167
-	public function releaseAll(?int $type = null): DataResponse {
168
-		$lockingProvider = $this->getLockingProvider();
169
-
170
-		foreach ($this->config->getAppKeys('testing') as $lock) {
171
-			if (strpos($lock, 'locking_') === 0) {
172
-				$path = substr($lock, strlen('locking_'));
173
-
174
-				if ($type === ILockingProvider::LOCK_EXCLUSIVE && (int)$this->config->getAppValue('testing', $lock) === ILockingProvider::LOCK_EXCLUSIVE) {
175
-					$lockingProvider->releaseLock($path, (int)$this->config->getAppValue('testing', $lock));
176
-				} elseif ($type === ILockingProvider::LOCK_SHARED && (int)$this->config->getAppValue('testing', $lock) === ILockingProvider::LOCK_SHARED) {
177
-					$lockingProvider->releaseLock($path, (int)$this->config->getAppValue('testing', $lock));
178
-				} else {
179
-					$lockingProvider->releaseLock($path, (int)$this->config->getAppValue('testing', $lock));
180
-				}
181
-			}
182
-		}
183
-
184
-		return new DataResponse();
185
-	}
26
+    /**
27
+     * @param string $appName
28
+     * @param IRequest $request
29
+     * @param ILockingProvider $lockingProvider
30
+     * @param FakeDBLockingProvider $fakeDBLockingProvider
31
+     * @param IDBConnection $connection
32
+     * @param IConfig $config
33
+     * @param IRootFolder $rootFolder
34
+     */
35
+    public function __construct(
36
+        $appName,
37
+        IRequest $request,
38
+        protected ILockingProvider $lockingProvider,
39
+        protected FakeDBLockingProvider $fakeDBLockingProvider,
40
+        protected IDBConnection $connection,
41
+        protected IConfig $config,
42
+        protected IRootFolder $rootFolder,
43
+    ) {
44
+        parent::__construct($appName, $request);
45
+    }
46
+
47
+    /**
48
+     * @throws \RuntimeException
49
+     */
50
+    protected function getLockingProvider(): ILockingProvider {
51
+        if ($this->lockingProvider instanceof DBLockingProvider) {
52
+            return $this->fakeDBLockingProvider;
53
+        }
54
+        throw new \RuntimeException('Lock provisioning is only possible using the DBLockingProvider');
55
+    }
56
+
57
+    /**
58
+     * @throws NotFoundException
59
+     */
60
+    protected function getPath(string $user, string $path): string {
61
+        $node = $this->rootFolder->getUserFolder($user)->get($path);
62
+        return 'files/' . md5($node->getStorage()->getId() . '::' . trim($node->getInternalPath(), '/'));
63
+    }
64
+
65
+    /**
66
+     * @throws OCSException
67
+     */
68
+    public function isLockingEnabled(): DataResponse {
69
+        try {
70
+            $this->getLockingProvider();
71
+            return new DataResponse();
72
+        } catch (\RuntimeException $e) {
73
+            throw new OCSException($e->getMessage(), Http::STATUS_NOT_IMPLEMENTED, $e);
74
+        }
75
+    }
76
+
77
+    /**
78
+     * @throws OCSException
79
+     */
80
+    public function acquireLock(int $type, string $user, string $path): DataResponse {
81
+        try {
82
+            $path = $this->getPath($user, $path);
83
+        } catch (NoUserException $e) {
84
+            throw new OCSException('User not found', Http::STATUS_NOT_FOUND, $e);
85
+        } catch (NotFoundException $e) {
86
+            throw new OCSException('Path not found', Http::STATUS_NOT_FOUND, $e);
87
+        }
88
+
89
+        $lockingProvider = $this->getLockingProvider();
90
+
91
+        try {
92
+            $lockingProvider->acquireLock($path, $type);
93
+            $this->config->setAppValue('testing', 'locking_' . $path, (string)$type);
94
+            return new DataResponse();
95
+        } catch (LockedException $e) {
96
+            throw new OCSException('', Http::STATUS_LOCKED, $e);
97
+        }
98
+    }
99
+
100
+    /**
101
+     * @throws OCSException
102
+     */
103
+    public function changeLock(int $type, string $user, string $path): DataResponse {
104
+        try {
105
+            $path = $this->getPath($user, $path);
106
+        } catch (NoUserException $e) {
107
+            throw new OCSException('User not found', Http::STATUS_NOT_FOUND, $e);
108
+        } catch (NotFoundException $e) {
109
+            throw new OCSException('Path not found', Http::STATUS_NOT_FOUND, $e);
110
+        }
111
+
112
+        $lockingProvider = $this->getLockingProvider();
113
+
114
+        try {
115
+            $lockingProvider->changeLock($path, $type);
116
+            $this->config->setAppValue('testing', 'locking_' . $path, (string)$type);
117
+            return new DataResponse();
118
+        } catch (LockedException $e) {
119
+            throw new OCSException('', Http::STATUS_LOCKED, $e);
120
+        }
121
+    }
122
+
123
+    /**
124
+     * @throws OCSException
125
+     */
126
+    public function releaseLock(int $type, string $user, string $path): DataResponse {
127
+        try {
128
+            $path = $this->getPath($user, $path);
129
+        } catch (NoUserException $e) {
130
+            throw new OCSException('User not found', Http::STATUS_NOT_FOUND, $e);
131
+        } catch (NotFoundException $e) {
132
+            throw new OCSException('Path not found', Http::STATUS_NOT_FOUND, $e);
133
+        }
134
+
135
+        $lockingProvider = $this->getLockingProvider();
136
+
137
+        try {
138
+            $lockingProvider->releaseLock($path, $type);
139
+            $this->config->deleteAppValue('testing', 'locking_' . $path);
140
+            return new DataResponse();
141
+        } catch (LockedException $e) {
142
+            throw new OCSException('', Http::STATUS_LOCKED, $e);
143
+        }
144
+    }
145
+
146
+    /**
147
+     * @throws OCSException
148
+     */
149
+    public function isLocked(int $type, string $user, string $path): DataResponse {
150
+        try {
151
+            $path = $this->getPath($user, $path);
152
+        } catch (NoUserException $e) {
153
+            throw new OCSException('User not found', Http::STATUS_NOT_FOUND, $e);
154
+        } catch (NotFoundException $e) {
155
+            throw new OCSException('Path not found', Http::STATUS_NOT_FOUND, $e);
156
+        }
157
+
158
+        $lockingProvider = $this->getLockingProvider();
159
+
160
+        if ($lockingProvider->isLocked($path, $type)) {
161
+            return new DataResponse();
162
+        }
163
+
164
+        throw new OCSException('', Http::STATUS_LOCKED);
165
+    }
166
+
167
+    public function releaseAll(?int $type = null): DataResponse {
168
+        $lockingProvider = $this->getLockingProvider();
169
+
170
+        foreach ($this->config->getAppKeys('testing') as $lock) {
171
+            if (strpos($lock, 'locking_') === 0) {
172
+                $path = substr($lock, strlen('locking_'));
173
+
174
+                if ($type === ILockingProvider::LOCK_EXCLUSIVE && (int)$this->config->getAppValue('testing', $lock) === ILockingProvider::LOCK_EXCLUSIVE) {
175
+                    $lockingProvider->releaseLock($path, (int)$this->config->getAppValue('testing', $lock));
176
+                } elseif ($type === ILockingProvider::LOCK_SHARED && (int)$this->config->getAppValue('testing', $lock) === ILockingProvider::LOCK_SHARED) {
177
+                    $lockingProvider->releaseLock($path, (int)$this->config->getAppValue('testing', $lock));
178
+                } else {
179
+                    $lockingProvider->releaseLock($path, (int)$this->config->getAppValue('testing', $lock));
180
+                }
181
+            }
182
+        }
183
+
184
+        return new DataResponse();
185
+    }
186 186
 }
Please login to merge, or discard this patch.
core/Migrations/Version24000Date20211213081604.php 1 patch
Indentation   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -30,37 +30,37 @@
 block discarded – undo
30 30
 use OCP\Migration\SimpleMigrationStep;
31 31
 
32 32
 class Version24000Date20211213081604 extends SimpleMigrationStep {
33
-	/**
34
-	 * @param IOutput $output
35
-	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
36
-	 * @param array $options
37
-	 * @return null|ISchemaWrapper
38
-	 */
39
-	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
40
-		/** @var ISchemaWrapper $schema */
41
-		$schema = $schemaClosure();
33
+    /**
34
+     * @param IOutput $output
35
+     * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
36
+     * @param array $options
37
+     * @return null|ISchemaWrapper
38
+     */
39
+    public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
40
+        /** @var ISchemaWrapper $schema */
41
+        $schema = $schemaClosure();
42 42
 
43
-		$hasTable = $schema->hasTable('ratelimit_entries');
43
+        $hasTable = $schema->hasTable('ratelimit_entries');
44 44
 
45
-		if (!$hasTable) {
46
-			$table = $schema->createTable('ratelimit_entries');
47
-			$table->addColumn('id', Types::BIGINT, [
48
-				'autoincrement' => true,
49
-				'notnull' => true,
50
-			]);
51
-			$table->addColumn('hash', Types::STRING, [
52
-				'notnull' => true,
53
-				'length' => 128,
54
-			]);
55
-			$table->addColumn('delete_after', Types::DATETIME, [
56
-				'notnull' => true,
57
-			]);
58
-			$table->setPrimaryKey(['id']);
59
-			$table->addIndex(['hash'], 'ratelimit_hash');
60
-			$table->addIndex(['delete_after'], 'ratelimit_delete_after');
61
-			return $schema;
62
-		}
45
+        if (!$hasTable) {
46
+            $table = $schema->createTable('ratelimit_entries');
47
+            $table->addColumn('id', Types::BIGINT, [
48
+                'autoincrement' => true,
49
+                'notnull' => true,
50
+            ]);
51
+            $table->addColumn('hash', Types::STRING, [
52
+                'notnull' => true,
53
+                'length' => 128,
54
+            ]);
55
+            $table->addColumn('delete_after', Types::DATETIME, [
56
+                'notnull' => true,
57
+            ]);
58
+            $table->setPrimaryKey(['id']);
59
+            $table->addIndex(['hash'], 'ratelimit_hash');
60
+            $table->addIndex(['delete_after'], 'ratelimit_delete_after');
61
+            return $schema;
62
+        }
63 63
 
64
-		return null;
65
-	}
64
+        return null;
65
+    }
66 66
 }
Please login to merge, or discard this patch.
core/Migrations/Version24000Date20211213081506.php 1 patch
Indentation   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -29,22 +29,22 @@
 block discarded – undo
29 29
 use OCP\Migration\SimpleMigrationStep;
30 30
 
31 31
 class Version24000Date20211213081506 extends SimpleMigrationStep {
32
-	/**
33
-	 * @param IOutput $output
34
-	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
35
-	 * @param array $options
36
-	 * @return null|ISchemaWrapper
37
-	 */
38
-	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
39
-		/** @var ISchemaWrapper $schema */
40
-		$schema = $schemaClosure();
32
+    /**
33
+     * @param IOutput $output
34
+     * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
35
+     * @param array $options
36
+     * @return null|ISchemaWrapper
37
+     */
38
+    public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
39
+        /** @var ISchemaWrapper $schema */
40
+        $schema = $schemaClosure();
41 41
 
42
-		$hasTable = $schema->hasTable('ratelimit_entries');
43
-		if ($hasTable) {
44
-			$schema->dropTable('ratelimit_entries');
45
-			return $schema;
46
-		}
42
+        $hasTable = $schema->hasTable('ratelimit_entries');
43
+        if ($hasTable) {
44
+            $schema->dropTable('ratelimit_entries');
45
+            return $schema;
46
+        }
47 47
 
48
-		return null;
49
-	}
48
+        return null;
49
+    }
50 50
 }
Please login to merge, or discard this patch.
lib/private/Talk/ConversationOptions.php 1 patch
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -28,22 +28,22 @@
 block discarded – undo
28 28
 use OCP\Talk\IConversationOptions;
29 29
 
30 30
 class ConversationOptions implements IConversationOptions {
31
-	private bool $isPublic;
31
+    private bool $isPublic;
32 32
 
33
-	private function __construct(bool $isPublic) {
34
-		$this->isPublic = $isPublic;
35
-	}
33
+    private function __construct(bool $isPublic) {
34
+        $this->isPublic = $isPublic;
35
+    }
36 36
 
37
-	public static function default(): self {
38
-		return new self(false);
39
-	}
37
+    public static function default(): self {
38
+        return new self(false);
39
+    }
40 40
 
41
-	public function setPublic(bool $isPublic = true): IConversationOptions {
42
-		$this->isPublic = $isPublic;
43
-		return $this;
44
-	}
41
+    public function setPublic(bool $isPublic = true): IConversationOptions {
42
+        $this->isPublic = $isPublic;
43
+        return $this;
44
+    }
45 45
 
46
-	public function isPublic(): bool {
47
-		return $this->isPublic;
48
-	}
46
+    public function isPublic(): bool {
47
+        return $this->isPublic;
48
+    }
49 49
 }
Please login to merge, or discard this patch.
core/Migrations/Version24000Date20220131153041.php 1 patch
Indentation   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -32,24 +32,24 @@
 block discarded – undo
32 32
 use OCP\Migration\SimpleMigrationStep;
33 33
 
34 34
 class Version24000Date20220131153041 extends SimpleMigrationStep {
35
-	/**
36
-	 * @param IOutput $output
37
-	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
38
-	 * @param array $options
39
-	 * @return null|ISchemaWrapper
40
-	 */
41
-	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
42
-		/** @var ISchemaWrapper $schema */
43
-		$schema = $schemaClosure();
35
+    /**
36
+     * @param IOutput $output
37
+     * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
38
+     * @param array $options
39
+     * @return null|ISchemaWrapper
40
+     */
41
+    public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
42
+        /** @var ISchemaWrapper $schema */
43
+        $schema = $schemaClosure();
44 44
 
45
-		$table = $schema->getTable('jobs');
46
-		if (!$table->hasColumn('time_sensitive')) {
47
-			$table->addColumn('time_sensitive', Types::SMALLINT, [
48
-				'default' => 1,
49
-			]);
50
-			$table->addIndex(['time_sensitive'], 'jobs_time_sensitive');
51
-			return $schema;
52
-		}
53
-		return null;
54
-	}
45
+        $table = $schema->getTable('jobs');
46
+        if (!$table->hasColumn('time_sensitive')) {
47
+            $table->addColumn('time_sensitive', Types::SMALLINT, [
48
+                'default' => 1,
49
+            ]);
50
+            $table->addIndex(['time_sensitive'], 'jobs_time_sensitive');
51
+            return $schema;
52
+        }
53
+        return null;
54
+    }
55 55
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/Migration/Version1130Date20211102154716.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -214,7 +214,7 @@
 block discarded – undo
214 214
 
215 215
 		while ($nextcloudId = array_shift($idList)) {
216 216
 			$update->setParameter('nextcloudId', $nextcloudId);
217
-			$update->setParameter('invalidatedUuid', 'invalidated_' . \bin2hex(\random_bytes(6)));
217
+			$update->setParameter('invalidatedUuid', 'invalidated_'.\bin2hex(\random_bytes(6)));
218 218
 			try {
219 219
 				$update->executeStatement();
220 220
 				$this->logger->warning(
Please login to merge, or discard this patch.
Indentation   +219 added lines, -219 removed lines patch added patch discarded remove patch
@@ -22,245 +22,245 @@
 block discarded – undo
22 22
 
23 23
 class Version1130Date20211102154716 extends SimpleMigrationStep {
24 24
 
25
-	/** @var string[] */
26
-	private $hashColumnAddedToTables = [];
25
+    /** @var string[] */
26
+    private $hashColumnAddedToTables = [];
27 27
 
28
-	public function __construct(
29
-		private IDBConnection $dbc,
30
-		private LoggerInterface $logger,
31
-	) {
32
-	}
28
+    public function __construct(
29
+        private IDBConnection $dbc,
30
+        private LoggerInterface $logger,
31
+    ) {
32
+    }
33 33
 
34
-	public function getName() {
35
-		return 'Adjust LDAP user and group ldap_dn column lengths and add ldap_dn_hash columns';
36
-	}
34
+    public function getName() {
35
+        return 'Adjust LDAP user and group ldap_dn column lengths and add ldap_dn_hash columns';
36
+    }
37 37
 
38
-	public function preSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
39
-		foreach (['ldap_user_mapping', 'ldap_group_mapping'] as $tableName) {
40
-			$this->processDuplicateUUIDs($tableName);
41
-		}
38
+    public function preSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
39
+        foreach (['ldap_user_mapping', 'ldap_group_mapping'] as $tableName) {
40
+            $this->processDuplicateUUIDs($tableName);
41
+        }
42 42
 
43
-		/** @var ISchemaWrapper $schema */
44
-		$schema = $schemaClosure();
45
-		if ($schema->hasTable('ldap_group_mapping_backup')) {
46
-			// Previous upgrades of a broken release might have left an incomplete
47
-			// ldap_group_mapping_backup table. No need to recreate, but it
48
-			// should be empty.
49
-			// TRUNCATE is not available from Query Builder, but faster than DELETE FROM.
50
-			$sql = $this->dbc->getDatabasePlatform()->getTruncateTableSQL('`*PREFIX*ldap_group_mapping_backup`', false);
51
-			$this->dbc->executeStatement($sql);
52
-		}
53
-	}
43
+        /** @var ISchemaWrapper $schema */
44
+        $schema = $schemaClosure();
45
+        if ($schema->hasTable('ldap_group_mapping_backup')) {
46
+            // Previous upgrades of a broken release might have left an incomplete
47
+            // ldap_group_mapping_backup table. No need to recreate, but it
48
+            // should be empty.
49
+            // TRUNCATE is not available from Query Builder, but faster than DELETE FROM.
50
+            $sql = $this->dbc->getDatabasePlatform()->getTruncateTableSQL('`*PREFIX*ldap_group_mapping_backup`', false);
51
+            $this->dbc->executeStatement($sql);
52
+        }
53
+    }
54 54
 
55
-	/**
56
-	 * @param IOutput $output
57
-	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
58
-	 * @param array $options
59
-	 * @return null|ISchemaWrapper
60
-	 */
61
-	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
62
-		/** @var ISchemaWrapper $schema */
63
-		$schema = $schemaClosure();
55
+    /**
56
+     * @param IOutput $output
57
+     * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
58
+     * @param array $options
59
+     * @return null|ISchemaWrapper
60
+     */
61
+    public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
62
+        /** @var ISchemaWrapper $schema */
63
+        $schema = $schemaClosure();
64 64
 
65
-		$changeSchema = false;
66
-		foreach (['ldap_user_mapping', 'ldap_group_mapping'] as $tableName) {
67
-			$table = $schema->getTable($tableName);
68
-			if (!$table->hasColumn('ldap_dn_hash')) {
69
-				$table->addColumn('ldap_dn_hash', Types::STRING, [
70
-					'notnull' => false,
71
-					'length' => 64,
72
-				]);
73
-				$changeSchema = true;
74
-				$this->hashColumnAddedToTables[] = $tableName;
75
-			}
76
-			$column = $table->getColumn('ldap_dn');
77
-			if ($tableName === 'ldap_user_mapping') {
78
-				if ($column->getLength() < 4000) {
79
-					$column->setLength(4000);
80
-					$changeSchema = true;
81
-				}
65
+        $changeSchema = false;
66
+        foreach (['ldap_user_mapping', 'ldap_group_mapping'] as $tableName) {
67
+            $table = $schema->getTable($tableName);
68
+            if (!$table->hasColumn('ldap_dn_hash')) {
69
+                $table->addColumn('ldap_dn_hash', Types::STRING, [
70
+                    'notnull' => false,
71
+                    'length' => 64,
72
+                ]);
73
+                $changeSchema = true;
74
+                $this->hashColumnAddedToTables[] = $tableName;
75
+            }
76
+            $column = $table->getColumn('ldap_dn');
77
+            if ($tableName === 'ldap_user_mapping') {
78
+                if ($column->getLength() < 4000) {
79
+                    $column->setLength(4000);
80
+                    $changeSchema = true;
81
+                }
82 82
 
83
-				if ($table->hasIndex('ldap_dn_users')) {
84
-					$table->dropIndex('ldap_dn_users');
85
-					$changeSchema = true;
86
-				}
87
-				if (!$table->hasIndex('ldap_user_dn_hashes')) {
88
-					$table->addUniqueIndex(['ldap_dn_hash'], 'ldap_user_dn_hashes');
89
-					$changeSchema = true;
90
-				}
91
-				if (!$table->hasIndex('ldap_user_directory_uuid')) {
92
-					$table->addUniqueIndex(['directory_uuid'], 'ldap_user_directory_uuid');
93
-					$changeSchema = true;
94
-				}
95
-			} elseif (!$schema->hasTable('ldap_group_mapping_backup')) {
96
-				// We need to copy the table twice to be able to change primary key, prepare the backup table
97
-				$table2 = $schema->createTable('ldap_group_mapping_backup');
98
-				$table2->addColumn('ldap_dn', Types::STRING, [
99
-					'notnull' => true,
100
-					'length' => 4000,
101
-					'default' => '',
102
-				]);
103
-				$table2->addColumn('owncloud_name', Types::STRING, [
104
-					'notnull' => true,
105
-					'length' => 64,
106
-					'default' => '',
107
-				]);
108
-				$table2->addColumn('directory_uuid', Types::STRING, [
109
-					'notnull' => true,
110
-					'length' => 255,
111
-					'default' => '',
112
-				]);
113
-				$table2->addColumn('ldap_dn_hash', Types::STRING, [
114
-					'notnull' => false,
115
-					'length' => 64,
116
-				]);
117
-				$table2->setPrimaryKey(['owncloud_name'], 'lgm_backup_primary');
118
-				$changeSchema = true;
119
-			}
120
-		}
83
+                if ($table->hasIndex('ldap_dn_users')) {
84
+                    $table->dropIndex('ldap_dn_users');
85
+                    $changeSchema = true;
86
+                }
87
+                if (!$table->hasIndex('ldap_user_dn_hashes')) {
88
+                    $table->addUniqueIndex(['ldap_dn_hash'], 'ldap_user_dn_hashes');
89
+                    $changeSchema = true;
90
+                }
91
+                if (!$table->hasIndex('ldap_user_directory_uuid')) {
92
+                    $table->addUniqueIndex(['directory_uuid'], 'ldap_user_directory_uuid');
93
+                    $changeSchema = true;
94
+                }
95
+            } elseif (!$schema->hasTable('ldap_group_mapping_backup')) {
96
+                // We need to copy the table twice to be able to change primary key, prepare the backup table
97
+                $table2 = $schema->createTable('ldap_group_mapping_backup');
98
+                $table2->addColumn('ldap_dn', Types::STRING, [
99
+                    'notnull' => true,
100
+                    'length' => 4000,
101
+                    'default' => '',
102
+                ]);
103
+                $table2->addColumn('owncloud_name', Types::STRING, [
104
+                    'notnull' => true,
105
+                    'length' => 64,
106
+                    'default' => '',
107
+                ]);
108
+                $table2->addColumn('directory_uuid', Types::STRING, [
109
+                    'notnull' => true,
110
+                    'length' => 255,
111
+                    'default' => '',
112
+                ]);
113
+                $table2->addColumn('ldap_dn_hash', Types::STRING, [
114
+                    'notnull' => false,
115
+                    'length' => 64,
116
+                ]);
117
+                $table2->setPrimaryKey(['owncloud_name'], 'lgm_backup_primary');
118
+                $changeSchema = true;
119
+            }
120
+        }
121 121
 
122
-		return $changeSchema ? $schema : null;
123
-	}
122
+        return $changeSchema ? $schema : null;
123
+    }
124 124
 
125
-	/**
126
-	 * @param IOutput $output
127
-	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
128
-	 * @param array $options
129
-	 */
130
-	public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
131
-		$this->handleDNHashes('ldap_group_mapping');
132
-		$this->handleDNHashes('ldap_user_mapping');
133
-	}
125
+    /**
126
+     * @param IOutput $output
127
+     * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
128
+     * @param array $options
129
+     */
130
+    public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
131
+        $this->handleDNHashes('ldap_group_mapping');
132
+        $this->handleDNHashes('ldap_user_mapping');
133
+    }
134 134
 
135
-	protected function handleDNHashes(string $table): void {
136
-		$select = $this->getSelectQuery($table);
137
-		$update = $this->getUpdateQuery($table);
135
+    protected function handleDNHashes(string $table): void {
136
+        $select = $this->getSelectQuery($table);
137
+        $update = $this->getUpdateQuery($table);
138 138
 
139
-		$result = $select->executeQuery();
140
-		while ($row = $result->fetch()) {
141
-			$dnHash = hash('sha256', $row['ldap_dn'], false);
142
-			$update->setParameter('name', $row['owncloud_name']);
143
-			$update->setParameter('dn_hash', $dnHash);
144
-			try {
145
-				$update->executeStatement();
146
-			} catch (Exception $e) {
147
-				$this->logger->error('Failed to add hash "{dnHash}" ("{name}" of {table})',
148
-					[
149
-						'app' => 'user_ldap',
150
-						'name' => $row['owncloud_name'],
151
-						'dnHash' => $dnHash,
152
-						'table' => $table,
153
-						'exception' => $e,
154
-					]
155
-				);
156
-			}
157
-		}
158
-		$result->closeCursor();
159
-	}
139
+        $result = $select->executeQuery();
140
+        while ($row = $result->fetch()) {
141
+            $dnHash = hash('sha256', $row['ldap_dn'], false);
142
+            $update->setParameter('name', $row['owncloud_name']);
143
+            $update->setParameter('dn_hash', $dnHash);
144
+            try {
145
+                $update->executeStatement();
146
+            } catch (Exception $e) {
147
+                $this->logger->error('Failed to add hash "{dnHash}" ("{name}" of {table})',
148
+                    [
149
+                        'app' => 'user_ldap',
150
+                        'name' => $row['owncloud_name'],
151
+                        'dnHash' => $dnHash,
152
+                        'table' => $table,
153
+                        'exception' => $e,
154
+                    ]
155
+                );
156
+            }
157
+        }
158
+        $result->closeCursor();
159
+    }
160 160
 
161
-	protected function getSelectQuery(string $table): IQueryBuilder {
162
-		$qb = $this->dbc->getQueryBuilder();
163
-		$qb->select('owncloud_name', 'ldap_dn')
164
-			->from($table);
161
+    protected function getSelectQuery(string $table): IQueryBuilder {
162
+        $qb = $this->dbc->getQueryBuilder();
163
+        $qb->select('owncloud_name', 'ldap_dn')
164
+            ->from($table);
165 165
 
166
-		// when added we may run into risk that it's read from a DB node
167
-		// where the column is not present. Then the where clause is also
168
-		// not necessary since all rows qualify.
169
-		if (!in_array($table, $this->hashColumnAddedToTables, true)) {
170
-			$qb->where($qb->expr()->isNull('ldap_dn_hash'));
171
-		}
166
+        // when added we may run into risk that it's read from a DB node
167
+        // where the column is not present. Then the where clause is also
168
+        // not necessary since all rows qualify.
169
+        if (!in_array($table, $this->hashColumnAddedToTables, true)) {
170
+            $qb->where($qb->expr()->isNull('ldap_dn_hash'));
171
+        }
172 172
 
173
-		return $qb;
174
-	}
173
+        return $qb;
174
+    }
175 175
 
176
-	protected function getUpdateQuery(string $table): IQueryBuilder {
177
-		$qb = $this->dbc->getQueryBuilder();
178
-		$qb->update($table)
179
-			->set('ldap_dn_hash', $qb->createParameter('dn_hash'))
180
-			->where($qb->expr()->eq('owncloud_name', $qb->createParameter('name')));
181
-		return $qb;
182
-	}
176
+    protected function getUpdateQuery(string $table): IQueryBuilder {
177
+        $qb = $this->dbc->getQueryBuilder();
178
+        $qb->update($table)
179
+            ->set('ldap_dn_hash', $qb->createParameter('dn_hash'))
180
+            ->where($qb->expr()->eq('owncloud_name', $qb->createParameter('name')));
181
+        return $qb;
182
+    }
183 183
 
184
-	/**
185
-	 * @throws Exception
186
-	 */
187
-	protected function processDuplicateUUIDs(string $table): void {
188
-		$uuids = $this->getDuplicatedUuids($table);
189
-		$idsWithUuidToInvalidate = [];
190
-		foreach ($uuids as $uuid) {
191
-			array_push($idsWithUuidToInvalidate, ...$this->getNextcloudIdsByUuid($table, $uuid));
192
-		}
193
-		$this->invalidateUuids($table, $idsWithUuidToInvalidate);
194
-	}
184
+    /**
185
+     * @throws Exception
186
+     */
187
+    protected function processDuplicateUUIDs(string $table): void {
188
+        $uuids = $this->getDuplicatedUuids($table);
189
+        $idsWithUuidToInvalidate = [];
190
+        foreach ($uuids as $uuid) {
191
+            array_push($idsWithUuidToInvalidate, ...$this->getNextcloudIdsByUuid($table, $uuid));
192
+        }
193
+        $this->invalidateUuids($table, $idsWithUuidToInvalidate);
194
+    }
195 195
 
196
-	/**
197
-	 * @throws Exception
198
-	 */
199
-	protected function invalidateUuids(string $table, array $idList): void {
200
-		$update = $this->dbc->getQueryBuilder();
201
-		$update->update($table)
202
-			->set('directory_uuid', $update->createParameter('invalidatedUuid'))
203
-			->where($update->expr()->eq('owncloud_name', $update->createParameter('nextcloudId')));
196
+    /**
197
+     * @throws Exception
198
+     */
199
+    protected function invalidateUuids(string $table, array $idList): void {
200
+        $update = $this->dbc->getQueryBuilder();
201
+        $update->update($table)
202
+            ->set('directory_uuid', $update->createParameter('invalidatedUuid'))
203
+            ->where($update->expr()->eq('owncloud_name', $update->createParameter('nextcloudId')));
204 204
 
205
-		while ($nextcloudId = array_shift($idList)) {
206
-			$update->setParameter('nextcloudId', $nextcloudId);
207
-			$update->setParameter('invalidatedUuid', 'invalidated_' . \bin2hex(\random_bytes(6)));
208
-			try {
209
-				$update->executeStatement();
210
-				$this->logger->warning(
211
-					'LDAP user or group with ID {nid} has a duplicated UUID value which therefore was invalidated. You may double-check your LDAP configuration and trigger an update of the UUID.',
212
-					[
213
-						'app' => 'user_ldap',
214
-						'nid' => $nextcloudId,
215
-					]
216
-				);
217
-			} catch (Exception $e) {
218
-				// Catch possible, but unlikely duplications if new invalidated errors.
219
-				// There is the theoretical chance of an infinity loop is, when
220
-				// the constraint violation has a different background. I cannot
221
-				// think of one at the moment.
222
-				if ($e->getReason() !== Exception::REASON_CONSTRAINT_VIOLATION) {
223
-					throw $e;
224
-				}
225
-				$idList[] = $nextcloudId;
226
-			}
227
-		}
228
-	}
205
+        while ($nextcloudId = array_shift($idList)) {
206
+            $update->setParameter('nextcloudId', $nextcloudId);
207
+            $update->setParameter('invalidatedUuid', 'invalidated_' . \bin2hex(\random_bytes(6)));
208
+            try {
209
+                $update->executeStatement();
210
+                $this->logger->warning(
211
+                    'LDAP user or group with ID {nid} has a duplicated UUID value which therefore was invalidated. You may double-check your LDAP configuration and trigger an update of the UUID.',
212
+                    [
213
+                        'app' => 'user_ldap',
214
+                        'nid' => $nextcloudId,
215
+                    ]
216
+                );
217
+            } catch (Exception $e) {
218
+                // Catch possible, but unlikely duplications if new invalidated errors.
219
+                // There is the theoretical chance of an infinity loop is, when
220
+                // the constraint violation has a different background. I cannot
221
+                // think of one at the moment.
222
+                if ($e->getReason() !== Exception::REASON_CONSTRAINT_VIOLATION) {
223
+                    throw $e;
224
+                }
225
+                $idList[] = $nextcloudId;
226
+            }
227
+        }
228
+    }
229 229
 
230
-	/**
231
-	 * @throws \OCP\DB\Exception
232
-	 * @return array<string>
233
-	 */
234
-	protected function getNextcloudIdsByUuid(string $table, string $uuid): array {
235
-		$select = $this->dbc->getQueryBuilder();
236
-		$select->select('owncloud_name')
237
-			->from($table)
238
-			->where($select->expr()->eq('directory_uuid', $select->createNamedParameter($uuid)));
230
+    /**
231
+     * @throws \OCP\DB\Exception
232
+     * @return array<string>
233
+     */
234
+    protected function getNextcloudIdsByUuid(string $table, string $uuid): array {
235
+        $select = $this->dbc->getQueryBuilder();
236
+        $select->select('owncloud_name')
237
+            ->from($table)
238
+            ->where($select->expr()->eq('directory_uuid', $select->createNamedParameter($uuid)));
239 239
 
240
-		$result = $select->executeQuery();
241
-		$idList = [];
242
-		while (($id = $result->fetchOne()) !== false) {
243
-			$idList[] = $id;
244
-		}
245
-		$result->closeCursor();
246
-		return $idList;
247
-	}
240
+        $result = $select->executeQuery();
241
+        $idList = [];
242
+        while (($id = $result->fetchOne()) !== false) {
243
+            $idList[] = $id;
244
+        }
245
+        $result->closeCursor();
246
+        return $idList;
247
+    }
248 248
 
249
-	/**
250
-	 * @return Generator<string>
251
-	 * @throws \OCP\DB\Exception
252
-	 */
253
-	protected function getDuplicatedUuids(string $table): Generator {
254
-		$select = $this->dbc->getQueryBuilder();
255
-		$select->select('directory_uuid')
256
-			->from($table)
257
-			->groupBy('directory_uuid')
258
-			->having($select->expr()->gt($select->func()->count('owncloud_name'), $select->createNamedParameter(1)));
249
+    /**
250
+     * @return Generator<string>
251
+     * @throws \OCP\DB\Exception
252
+     */
253
+    protected function getDuplicatedUuids(string $table): Generator {
254
+        $select = $this->dbc->getQueryBuilder();
255
+        $select->select('directory_uuid')
256
+            ->from($table)
257
+            ->groupBy('directory_uuid')
258
+            ->having($select->expr()->gt($select->func()->count('owncloud_name'), $select->createNamedParameter(1)));
259 259
 
260
-		$result = $select->executeQuery();
261
-		while (($uuid = $result->fetchOne()) !== false) {
262
-			yield $uuid;
263
-		}
264
-		$result->closeCursor();
265
-	}
260
+        $result = $select->executeQuery();
261
+        while (($uuid = $result->fetchOne()) !== false) {
262
+            yield $uuid;
263
+        }
264
+        $result->closeCursor();
265
+    }
266 266
 }
Please login to merge, or discard this patch.
apps/user_ldap/lib/Helper.php 2 patches
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -128,12 +128,12 @@  discard block
 block discarded – undo
128 128
 
129 129
 		sort($serverConnections);
130 130
 		$lastKey = array_pop($serverConnections);
131
-		$lastNumber = (int)str_replace('s', '', $lastKey);
132
-		return 's' . str_pad((string)($lastNumber + 1), 2, '0', STR_PAD_LEFT);
131
+		$lastNumber = (int) str_replace('s', '', $lastKey);
132
+		return 's'.str_pad((string) ($lastNumber + 1), 2, '0', STR_PAD_LEFT);
133 133
 	}
134 134
 
135 135
 	private function getServersConfig(string $value): array {
136
-		$regex = '/' . $value . '$/S';
136
+		$regex = '/'.$value.'$/S';
137 137
 
138 138
 		$keys = $this->config->getAppKeys('user_ldap');
139 139
 		$result = [];
@@ -160,7 +160,7 @@  discard block
 block discarded – undo
160 160
 		$query = $this->connection->getQueryBuilder();
161 161
 		$query->delete('appconfig')
162 162
 			->where($query->expr()->eq('appid', $query->createNamedParameter('user_ldap')))
163
-			->andWhere($query->expr()->like('configkey', $query->createNamedParameter((string)$prefix . '%')))
163
+			->andWhere($query->expr()->like('configkey', $query->createNamedParameter((string) $prefix.'%')))
164 164
 			->andWhere($query->expr()->notIn('configkey', $query->createNamedParameter([
165 165
 				'enabled',
166 166
 				'installed_version',
@@ -225,7 +225,7 @@  discard block
 block discarded – undo
225 225
 		}
226 226
 
227 227
 		if (!is_string($dn)) {
228
-			throw new \LogicException('String expected ' . \gettype($dn) . ' given');
228
+			throw new \LogicException('String expected '.\gettype($dn).' given');
229 229
 		}
230 230
 
231 231
 		if (($sanitizedDn = $this->sanitizeDnCache->get($dn)) !== null) {
Please login to merge, or discard this patch.
Indentation   +262 added lines, -262 removed lines patch added patch discarded remove patch
@@ -14,266 +14,266 @@
 block discarded – undo
14 14
 use OCP\Server;
15 15
 
16 16
 class Helper {
17
-	/** @var CappedMemoryCache<string> */
18
-	protected CappedMemoryCache $sanitizeDnCache;
19
-
20
-	public function __construct(
21
-		private IConfig $config,
22
-		private IDBConnection $connection,
23
-	) {
24
-		$this->sanitizeDnCache = new CappedMemoryCache(10000);
25
-	}
26
-
27
-	/**
28
-	 * returns prefixes for each saved LDAP/AD server configuration.
29
-	 *
30
-	 * @param bool $activeConfigurations optional, whether only active configuration shall be
31
-	 *                                   retrieved, defaults to false
32
-	 * @return array with a list of the available prefixes
33
-	 *
34
-	 * Configuration prefixes are used to set up configurations for n LDAP or
35
-	 * AD servers. Since configuration is stored in the database, table
36
-	 * appconfig under appid user_ldap, the common identifiers in column
37
-	 * 'configkey' have a prefix. The prefix for the very first server
38
-	 * configuration is empty.
39
-	 * Configkey Examples:
40
-	 * Server 1: ldap_login_filter
41
-	 * Server 2: s1_ldap_login_filter
42
-	 * Server 3: s2_ldap_login_filter
43
-	 *
44
-	 * The prefix needs to be passed to the constructor of Connection class,
45
-	 * except the default (first) server shall be connected to.
46
-	 *
47
-	 */
48
-	public function getServerConfigurationPrefixes($activeConfigurations = false): array {
49
-		$referenceConfigkey = 'ldap_configuration_active';
50
-
51
-		$keys = $this->getServersConfig($referenceConfigkey);
52
-
53
-		$prefixes = [];
54
-		foreach ($keys as $key) {
55
-			if ($activeConfigurations && $this->config->getAppValue('user_ldap', $key, '0') !== '1') {
56
-				continue;
57
-			}
58
-
59
-			$len = strlen($key) - strlen($referenceConfigkey);
60
-			$prefixes[] = substr($key, 0, $len);
61
-		}
62
-		asort($prefixes);
63
-
64
-		return $prefixes;
65
-	}
66
-
67
-	/**
68
-	 *
69
-	 * determines the host for every configured connection
70
-	 *
71
-	 * @return array an array with configprefix as keys
72
-	 *
73
-	 */
74
-	public function getServerConfigurationHosts() {
75
-		$referenceConfigkey = 'ldap_host';
76
-
77
-		$keys = $this->getServersConfig($referenceConfigkey);
78
-
79
-		$result = [];
80
-		foreach ($keys as $key) {
81
-			$len = strlen($key) - strlen($referenceConfigkey);
82
-			$prefix = substr($key, 0, $len);
83
-			$result[$prefix] = $this->config->getAppValue('user_ldap', $key);
84
-		}
85
-
86
-		return $result;
87
-	}
88
-
89
-	/**
90
-	 * return the next available configuration prefix
91
-	 *
92
-	 * @return string
93
-	 */
94
-	public function getNextServerConfigurationPrefix() {
95
-		$serverConnections = $this->getServerConfigurationPrefixes();
96
-
97
-		if (count($serverConnections) === 0) {
98
-			return 's01';
99
-		}
100
-
101
-		sort($serverConnections);
102
-		$lastKey = array_pop($serverConnections);
103
-		$lastNumber = (int)str_replace('s', '', $lastKey);
104
-		return 's' . str_pad((string)($lastNumber + 1), 2, '0', STR_PAD_LEFT);
105
-	}
106
-
107
-	private function getServersConfig(string $value): array {
108
-		$regex = '/' . $value . '$/S';
109
-
110
-		$keys = $this->config->getAppKeys('user_ldap');
111
-		$result = [];
112
-		foreach ($keys as $key) {
113
-			if (preg_match($regex, $key) === 1) {
114
-				$result[] = $key;
115
-			}
116
-		}
117
-
118
-		return $result;
119
-	}
120
-
121
-	/**
122
-	 * deletes a given saved LDAP/AD server configuration.
123
-	 *
124
-	 * @param string $prefix the configuration prefix of the config to delete
125
-	 * @return bool true on success, false otherwise
126
-	 */
127
-	public function deleteServerConfiguration($prefix) {
128
-		if (!in_array($prefix, self::getServerConfigurationPrefixes())) {
129
-			return false;
130
-		}
131
-
132
-		$query = $this->connection->getQueryBuilder();
133
-		$query->delete('appconfig')
134
-			->where($query->expr()->eq('appid', $query->createNamedParameter('user_ldap')))
135
-			->andWhere($query->expr()->like('configkey', $query->createNamedParameter((string)$prefix . '%')))
136
-			->andWhere($query->expr()->notIn('configkey', $query->createNamedParameter([
137
-				'enabled',
138
-				'installed_version',
139
-				'types',
140
-				'bgjUpdateGroupsLastRun',
141
-			], IQueryBuilder::PARAM_STR_ARRAY)));
142
-
143
-		if (empty($prefix)) {
144
-			$query->andWhere($query->expr()->notLike('configkey', $query->createNamedParameter('s%')));
145
-		}
146
-
147
-		$deletedRows = $query->execute();
148
-		return $deletedRows !== 0;
149
-	}
150
-
151
-	/**
152
-	 * checks whether there is one or more disabled LDAP configurations
153
-	 */
154
-	public function haveDisabledConfigurations(): bool {
155
-		$all = $this->getServerConfigurationPrefixes(false);
156
-		$active = $this->getServerConfigurationPrefixes(true);
157
-
158
-		return count($all) !== count($active) || count($all) === 0;
159
-	}
160
-
161
-	/**
162
-	 * extracts the domain from a given URL
163
-	 *
164
-	 * @param string $url the URL
165
-	 * @return string|false domain as string on success, false otherwise
166
-	 */
167
-	public function getDomainFromURL($url) {
168
-		$uinfo = parse_url($url);
169
-		if (!is_array($uinfo)) {
170
-			return false;
171
-		}
172
-
173
-		$domain = false;
174
-		if (isset($uinfo['host'])) {
175
-			$domain = $uinfo['host'];
176
-		} elseif (isset($uinfo['path'])) {
177
-			$domain = $uinfo['path'];
178
-		}
179
-
180
-		return $domain;
181
-	}
182
-
183
-	/**
184
-	 * sanitizes a DN received from the LDAP server
185
-	 *
186
-	 * This is used and done to have a stable format of DNs that can be compared
187
-	 * and identified again. The input DN value is modified as following:
188
-	 *
189
-	 * 1) whitespaces after commas are removed
190
-	 * 2) the DN is turned to lower-case
191
-	 * 3) the DN is escaped according to RFC 2253
192
-	 *
193
-	 * When a future DN is supposed to be used as a base parameter, it has to be
194
-	 * run through DNasBaseParameter() first, to recode \5c into a backslash
195
-	 * again, otherwise the search or read operation will fail with LDAP error
196
-	 * 32, NO_SUCH_OBJECT. Regular usage in LDAP filters requires the backslash
197
-	 * being escaped, however.
198
-	 *
199
-	 * Internally, DNs are stored in their sanitized form.
200
-	 *
201
-	 * @param array|string $dn the DN in question
202
-	 * @return array|string the sanitized DN
203
-	 */
204
-	public function sanitizeDN($dn) {
205
-		//treating multiple base DNs
206
-		if (is_array($dn)) {
207
-			$result = [];
208
-			foreach ($dn as $singleDN) {
209
-				$result[] = $this->sanitizeDN($singleDN);
210
-			}
211
-			return $result;
212
-		}
213
-
214
-		if (!is_string($dn)) {
215
-			throw new \LogicException('String expected ' . \gettype($dn) . ' given');
216
-		}
217
-
218
-		if (($sanitizedDn = $this->sanitizeDnCache->get($dn)) !== null) {
219
-			return $sanitizedDn;
220
-		}
221
-
222
-		//OID sometimes gives back DNs with whitespace after the comma
223
-		// a la "uid=foo, cn=bar, dn=..." We need to tackle this!
224
-		$sanitizedDn = preg_replace('/([^\\\]),(\s+)/u', '\1,', $dn);
225
-
226
-		//make comparisons and everything work
227
-		$sanitizedDn = mb_strtolower($sanitizedDn, 'UTF-8');
228
-
229
-		//escape DN values according to RFC 2253 – this is already done by ldap_explode_dn
230
-		//to use the DN in search filters, \ needs to be escaped to \5c additionally
231
-		//to use them in bases, we convert them back to simple backslashes in readAttribute()
232
-		$replacements = [
233
-			'\,' => '\5c2C',
234
-			'\=' => '\5c3D',
235
-			'\+' => '\5c2B',
236
-			'\<' => '\5c3C',
237
-			'\>' => '\5c3E',
238
-			'\;' => '\5c3B',
239
-			'\"' => '\5c22',
240
-			'\#' => '\5c23',
241
-			'(' => '\28',
242
-			')' => '\29',
243
-			'*' => '\2A',
244
-		];
245
-		$sanitizedDn = str_replace(array_keys($replacements), array_values($replacements), $sanitizedDn);
246
-		$this->sanitizeDnCache->set($dn, $sanitizedDn);
247
-
248
-		return $sanitizedDn;
249
-	}
250
-
251
-	/**
252
-	 * converts a stored DN so it can be used as base parameter for LDAP queries, internally we store them for usage in LDAP filters
253
-	 *
254
-	 * @param string $dn the DN
255
-	 * @return string
256
-	 */
257
-	public function DNasBaseParameter($dn) {
258
-		return str_ireplace('\\5c', '\\', $dn);
259
-	}
260
-
261
-	/**
262
-	 * listens to a hook thrown by server2server sharing and replaces the given
263
-	 * login name by a username, if it matches an LDAP user.
264
-	 *
265
-	 * @param array $param contains a reference to a $uid var under 'uid' key
266
-	 * @throws \Exception
267
-	 */
268
-	public static function loginName2UserName($param): void {
269
-		if (!isset($param['uid'])) {
270
-			throw new \Exception('key uid is expected to be set in $param');
271
-		}
272
-
273
-		$userBackend = Server::get(User_Proxy::class);
274
-		$uid = $userBackend->loginName2UserName($param['uid']);
275
-		if ($uid !== false) {
276
-			$param['uid'] = $uid;
277
-		}
278
-	}
17
+    /** @var CappedMemoryCache<string> */
18
+    protected CappedMemoryCache $sanitizeDnCache;
19
+
20
+    public function __construct(
21
+        private IConfig $config,
22
+        private IDBConnection $connection,
23
+    ) {
24
+        $this->sanitizeDnCache = new CappedMemoryCache(10000);
25
+    }
26
+
27
+    /**
28
+     * returns prefixes for each saved LDAP/AD server configuration.
29
+     *
30
+     * @param bool $activeConfigurations optional, whether only active configuration shall be
31
+     *                                   retrieved, defaults to false
32
+     * @return array with a list of the available prefixes
33
+     *
34
+     * Configuration prefixes are used to set up configurations for n LDAP or
35
+     * AD servers. Since configuration is stored in the database, table
36
+     * appconfig under appid user_ldap, the common identifiers in column
37
+     * 'configkey' have a prefix. The prefix for the very first server
38
+     * configuration is empty.
39
+     * Configkey Examples:
40
+     * Server 1: ldap_login_filter
41
+     * Server 2: s1_ldap_login_filter
42
+     * Server 3: s2_ldap_login_filter
43
+     *
44
+     * The prefix needs to be passed to the constructor of Connection class,
45
+     * except the default (first) server shall be connected to.
46
+     *
47
+     */
48
+    public function getServerConfigurationPrefixes($activeConfigurations = false): array {
49
+        $referenceConfigkey = 'ldap_configuration_active';
50
+
51
+        $keys = $this->getServersConfig($referenceConfigkey);
52
+
53
+        $prefixes = [];
54
+        foreach ($keys as $key) {
55
+            if ($activeConfigurations && $this->config->getAppValue('user_ldap', $key, '0') !== '1') {
56
+                continue;
57
+            }
58
+
59
+            $len = strlen($key) - strlen($referenceConfigkey);
60
+            $prefixes[] = substr($key, 0, $len);
61
+        }
62
+        asort($prefixes);
63
+
64
+        return $prefixes;
65
+    }
66
+
67
+    /**
68
+     *
69
+     * determines the host for every configured connection
70
+     *
71
+     * @return array an array with configprefix as keys
72
+     *
73
+     */
74
+    public function getServerConfigurationHosts() {
75
+        $referenceConfigkey = 'ldap_host';
76
+
77
+        $keys = $this->getServersConfig($referenceConfigkey);
78
+
79
+        $result = [];
80
+        foreach ($keys as $key) {
81
+            $len = strlen($key) - strlen($referenceConfigkey);
82
+            $prefix = substr($key, 0, $len);
83
+            $result[$prefix] = $this->config->getAppValue('user_ldap', $key);
84
+        }
85
+
86
+        return $result;
87
+    }
88
+
89
+    /**
90
+     * return the next available configuration prefix
91
+     *
92
+     * @return string
93
+     */
94
+    public function getNextServerConfigurationPrefix() {
95
+        $serverConnections = $this->getServerConfigurationPrefixes();
96
+
97
+        if (count($serverConnections) === 0) {
98
+            return 's01';
99
+        }
100
+
101
+        sort($serverConnections);
102
+        $lastKey = array_pop($serverConnections);
103
+        $lastNumber = (int)str_replace('s', '', $lastKey);
104
+        return 's' . str_pad((string)($lastNumber + 1), 2, '0', STR_PAD_LEFT);
105
+    }
106
+
107
+    private function getServersConfig(string $value): array {
108
+        $regex = '/' . $value . '$/S';
109
+
110
+        $keys = $this->config->getAppKeys('user_ldap');
111
+        $result = [];
112
+        foreach ($keys as $key) {
113
+            if (preg_match($regex, $key) === 1) {
114
+                $result[] = $key;
115
+            }
116
+        }
117
+
118
+        return $result;
119
+    }
120
+
121
+    /**
122
+     * deletes a given saved LDAP/AD server configuration.
123
+     *
124
+     * @param string $prefix the configuration prefix of the config to delete
125
+     * @return bool true on success, false otherwise
126
+     */
127
+    public function deleteServerConfiguration($prefix) {
128
+        if (!in_array($prefix, self::getServerConfigurationPrefixes())) {
129
+            return false;
130
+        }
131
+
132
+        $query = $this->connection->getQueryBuilder();
133
+        $query->delete('appconfig')
134
+            ->where($query->expr()->eq('appid', $query->createNamedParameter('user_ldap')))
135
+            ->andWhere($query->expr()->like('configkey', $query->createNamedParameter((string)$prefix . '%')))
136
+            ->andWhere($query->expr()->notIn('configkey', $query->createNamedParameter([
137
+                'enabled',
138
+                'installed_version',
139
+                'types',
140
+                'bgjUpdateGroupsLastRun',
141
+            ], IQueryBuilder::PARAM_STR_ARRAY)));
142
+
143
+        if (empty($prefix)) {
144
+            $query->andWhere($query->expr()->notLike('configkey', $query->createNamedParameter('s%')));
145
+        }
146
+
147
+        $deletedRows = $query->execute();
148
+        return $deletedRows !== 0;
149
+    }
150
+
151
+    /**
152
+     * checks whether there is one or more disabled LDAP configurations
153
+     */
154
+    public function haveDisabledConfigurations(): bool {
155
+        $all = $this->getServerConfigurationPrefixes(false);
156
+        $active = $this->getServerConfigurationPrefixes(true);
157
+
158
+        return count($all) !== count($active) || count($all) === 0;
159
+    }
160
+
161
+    /**
162
+     * extracts the domain from a given URL
163
+     *
164
+     * @param string $url the URL
165
+     * @return string|false domain as string on success, false otherwise
166
+     */
167
+    public function getDomainFromURL($url) {
168
+        $uinfo = parse_url($url);
169
+        if (!is_array($uinfo)) {
170
+            return false;
171
+        }
172
+
173
+        $domain = false;
174
+        if (isset($uinfo['host'])) {
175
+            $domain = $uinfo['host'];
176
+        } elseif (isset($uinfo['path'])) {
177
+            $domain = $uinfo['path'];
178
+        }
179
+
180
+        return $domain;
181
+    }
182
+
183
+    /**
184
+     * sanitizes a DN received from the LDAP server
185
+     *
186
+     * This is used and done to have a stable format of DNs that can be compared
187
+     * and identified again. The input DN value is modified as following:
188
+     *
189
+     * 1) whitespaces after commas are removed
190
+     * 2) the DN is turned to lower-case
191
+     * 3) the DN is escaped according to RFC 2253
192
+     *
193
+     * When a future DN is supposed to be used as a base parameter, it has to be
194
+     * run through DNasBaseParameter() first, to recode \5c into a backslash
195
+     * again, otherwise the search or read operation will fail with LDAP error
196
+     * 32, NO_SUCH_OBJECT. Regular usage in LDAP filters requires the backslash
197
+     * being escaped, however.
198
+     *
199
+     * Internally, DNs are stored in their sanitized form.
200
+     *
201
+     * @param array|string $dn the DN in question
202
+     * @return array|string the sanitized DN
203
+     */
204
+    public function sanitizeDN($dn) {
205
+        //treating multiple base DNs
206
+        if (is_array($dn)) {
207
+            $result = [];
208
+            foreach ($dn as $singleDN) {
209
+                $result[] = $this->sanitizeDN($singleDN);
210
+            }
211
+            return $result;
212
+        }
213
+
214
+        if (!is_string($dn)) {
215
+            throw new \LogicException('String expected ' . \gettype($dn) . ' given');
216
+        }
217
+
218
+        if (($sanitizedDn = $this->sanitizeDnCache->get($dn)) !== null) {
219
+            return $sanitizedDn;
220
+        }
221
+
222
+        //OID sometimes gives back DNs with whitespace after the comma
223
+        // a la "uid=foo, cn=bar, dn=..." We need to tackle this!
224
+        $sanitizedDn = preg_replace('/([^\\\]),(\s+)/u', '\1,', $dn);
225
+
226
+        //make comparisons and everything work
227
+        $sanitizedDn = mb_strtolower($sanitizedDn, 'UTF-8');
228
+
229
+        //escape DN values according to RFC 2253 – this is already done by ldap_explode_dn
230
+        //to use the DN in search filters, \ needs to be escaped to \5c additionally
231
+        //to use them in bases, we convert them back to simple backslashes in readAttribute()
232
+        $replacements = [
233
+            '\,' => '\5c2C',
234
+            '\=' => '\5c3D',
235
+            '\+' => '\5c2B',
236
+            '\<' => '\5c3C',
237
+            '\>' => '\5c3E',
238
+            '\;' => '\5c3B',
239
+            '\"' => '\5c22',
240
+            '\#' => '\5c23',
241
+            '(' => '\28',
242
+            ')' => '\29',
243
+            '*' => '\2A',
244
+        ];
245
+        $sanitizedDn = str_replace(array_keys($replacements), array_values($replacements), $sanitizedDn);
246
+        $this->sanitizeDnCache->set($dn, $sanitizedDn);
247
+
248
+        return $sanitizedDn;
249
+    }
250
+
251
+    /**
252
+     * converts a stored DN so it can be used as base parameter for LDAP queries, internally we store them for usage in LDAP filters
253
+     *
254
+     * @param string $dn the DN
255
+     * @return string
256
+     */
257
+    public function DNasBaseParameter($dn) {
258
+        return str_ireplace('\\5c', '\\', $dn);
259
+    }
260
+
261
+    /**
262
+     * listens to a hook thrown by server2server sharing and replaces the given
263
+     * login name by a username, if it matches an LDAP user.
264
+     *
265
+     * @param array $param contains a reference to a $uid var under 'uid' key
266
+     * @throws \Exception
267
+     */
268
+    public static function loginName2UserName($param): void {
269
+        if (!isset($param['uid'])) {
270
+            throw new \Exception('key uid is expected to be set in $param');
271
+        }
272
+
273
+        $userBackend = Server::get(User_Proxy::class);
274
+        $uid = $userBackend->loginName2UserName($param['uid']);
275
+        if ($uid !== false) {
276
+            $param['uid'] = $uid;
277
+        }
278
+    }
279 279
 }
Please login to merge, or discard this patch.