psalm fixes

This commit is contained in:
Robin Appelman 2025-10-24 17:31:24 +02:00
commit 4a93467905
12 changed files with 61 additions and 33 deletions

View file

@ -5,6 +5,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config" xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
findUnusedCode="false"
> >
<stubs> <stubs>
<file name="tests/krb.phpstub" preloadClasses="true"/> <file name="tests/krb.phpstub" preloadClasses="true"/>

View file

@ -33,7 +33,7 @@ class BasicAuth implements IAuth {
} }
public function getExtraCommandLineArguments(): string { public function getExtraCommandLineArguments(): string {
return ($this->workgroup) ? '-W ' . escapeshellarg($this->workgroup) : ''; return ($this->workgroup !== null) ? '-W ' . escapeshellarg($this->workgroup) : '';
} }
public function setExtraSmbClientOptions($smbClientState): void { public function setExtraSmbClientOptions($smbClientState): void {

View file

@ -23,7 +23,7 @@ class Exception extends \Exception {
*/ */
public static function unknown(?string $path, $error): Exception { public static function unknown(?string $path, $error): Exception {
$message = 'Unknown error (' . (string)$error . ')'; $message = 'Unknown error (' . (string)$error . ')';
if ($path) { if ($path !== null) {
$message .= ' for ' . $path; $message .= ' for ' . $path;
} }

View file

@ -12,6 +12,9 @@ class InvalidRequestException extends Exception {
*/ */
protected $path; protected $path;
/**
* @psalm-suppress ParamNameMismatch
*/
public function __construct(string $path = "", int $code = 0, ?\Throwable $previous = null) { public function __construct(string $path = "", int $code = 0, ?\Throwable $previous = null) {
$class = get_class($this); $class = get_class($this);
$parts = explode('\\', $class); $parts = explode('\\', $class);

View file

@ -47,7 +47,7 @@ class KerberosTicket {
*/ */
public static function fromEnv(): ?KerberosTicket { public static function fromEnv(): ?KerberosTicket {
$ticketName = getenv("KRB5CCNAME"); $ticketName = getenv("KRB5CCNAME");
if (!$ticketName) { if ($ticketName === false) {
return null; return null;
} }
$krb5 = new KRB5CCache(); $krb5 = new KRB5CCache();

View file

@ -129,9 +129,17 @@ class NativeFileInfo implements IFileInfo {
$attribute = $this->share->getAttribute($this->path, 'system.nt_sec_desc.acl.*+'); $attribute = $this->share->getAttribute($this->path, 'system.nt_sec_desc.acl.*+');
foreach (explode(',', $attribute) as $acl) { foreach (explode(',', $attribute) as $acl) {
list($user, $permissions) = explode(':', $acl, 2); $parts = explode(':', $acl, 2);
if (count($parts) !== 2) {
continue;
}
list($user, $permissions) = $parts;
$user = trim($user, '\\'); $user = trim($user, '\\');
list($type, $flags, $mask) = explode('/', $permissions); $parts = explode('/', $permissions);
if (count($parts) < 3) {
continue;
}
list($type, $flags, $mask) = $parts;
$mask = hexdec($mask); $mask = hexdec($mask);
$acls[$user] = new ACL((int)$type, (int)$flags, (int)$mask); $acls[$user] = new ACL((int)$type, (int)$flags, (int)$mask);

View file

@ -322,7 +322,7 @@ class NativeState {
if (!$this->state) { if (!$this->state) {
throw new ConnectionException("Not connected"); throw new ConnectionException("Not connected");
} }
if ($length) { if ($length !== null) {
$result = @smbclient_write($this->state, $file, $data, $length); $result = @smbclient_write($this->state, $file, $data, $length);
} else { } else {
$result = @smbclient_write($this->state, $file, $data); $result = @smbclient_write($this->state, $file, $data);

View file

@ -28,7 +28,7 @@ class TimeZoneProvider implements ITimeZoneProvider {
$timeZone = null; $timeZone = null;
$net = $this->system->getNetPath(); $net = $this->system->getNetPath();
// for local domain names we can assume same timezone // for local domain names we can assume same timezone
if ($net && $host && strpos($host, '.') !== false) { if ($net !== null && $host && strpos($host, '.') !== false) {
$command = sprintf( $command = sprintf(
'%s time zone -S %s', '%s time zone -S %s',
$net, $net,
@ -37,11 +37,12 @@ class TimeZoneProvider implements ITimeZoneProvider {
$timeZone = exec($command); $timeZone = exec($command);
} }
if (!$timeZone) { if (!is_string($timeZone)) {
$date = $this->system->getDatePath(); $date = $this->system->getDatePath();
if ($date) { if ($date !== null) {
$timeZone = exec($date . " +%z"); $timeZone = exec($date . " +%z");
} else { }
if (!is_string($timeZone)) {
$timeZone = date_default_timezone_get(); $timeZone = date_default_timezone_get();
} }
} }

View file

@ -93,11 +93,11 @@ class Connection extends RawConnection {
* @return no-return * @return no-return
*/ */
private function unknownError($promptLine = '') { private function unknownError($promptLine = '') {
if ($promptLine) { //maybe we have some error we missed on the previous line if ($promptLine !== false) { //maybe we have some error we missed on the previous line
throw new ConnectException('Unknown error (' . $promptLine . ')'); throw new ConnectException('Unknown error (' . $promptLine . ')');
} else { } else {
$error = $this->readError(); // maybe something on stderr $error = $this->readError(); // maybe something on stderr
if ($error) { if ($error !== false) {
throw new ConnectException('Unknown error (stderr: ' . $error . ')'); throw new ConnectException('Unknown error (stderr: ' . $error . ')');
} else { } else {
throw new ConnectException('Unknown error'); throw new ConnectException('Unknown error');

View file

@ -78,7 +78,9 @@ class Parser {
* @throws NotFoundException * @throws NotFoundException
*/ */
public function checkForError(array $output, string $path): void { public function checkForError(array $output, string $path): void {
if (strpos($output[0], 'does not exist')) { $error = '';
if (isset($output[0])) {
if (strpos($output[0], 'does not exist') > 0) {
throw new NotFoundException($path); throw new NotFoundException($path);
} }
$error = $this->getErrorCode($output[0]); $error = $this->getErrorCode($output[0]);
@ -87,6 +89,7 @@ class Parser {
$localPath = substr($output[0], strlen(self::MSG_NOT_FOUND)); $localPath = substr($output[0], strlen(self::MSG_NOT_FOUND));
throw new InvalidResourceException('Failed opening local file "' . $localPath . '" for writing'); throw new InvalidResourceException('Failed opening local file "' . $localPath . '" for writing');
} }
}
throw Exception::fromMap(self::EXCEPTION_MAP, $error, $path); throw Exception::fromMap(self::EXCEPTION_MAP, $error, $path);
} }
@ -197,12 +200,12 @@ class Parser {
public function parseListShares(array $output): array { public function parseListShares(array $output): array {
$shareNames = []; $shareNames = [];
foreach ($output as $line) { foreach ($output as $line) {
if (strpos($line, '|')) { if (strpos($line, '|') > 0) {
list($type, $name, $description) = explode('|', $line); list($type, $name, $description) = explode('|', $line);
if (strtolower($type) === 'disk') { if (strtolower($type) === 'disk') {
$shareNames[$name] = $description; $shareNames[$name] = $description;
} }
} elseif (strpos($line, 'Disk')) { } elseif (strpos($line, 'Disk') > 0) {
// new output format // new output format
list($name, $description) = explode('Disk', $line); list($name, $description) = explode('Disk', $line);
$shareNames[trim($name)] = trim($description); $shareNames[trim($name)] = trim($description);
@ -221,12 +224,24 @@ class Parser {
if (strpos($acl, ':') === false) { if (strpos($acl, ':') === false) {
continue; continue;
} }
[$type, $acl] = explode(':', $acl, 2); $parts = explode(':', $acl, 2);
if (count($parts) !== 2) {
continue;
}
[$type, $acl] = $parts;
if ($type !== 'ACL') { if ($type !== 'ACL') {
continue; continue;
} }
[$user, $permissions] = explode(':', $acl, 2); $parts = explode(':', $acl, 2);
[$type, $flags, $mask] = explode('/', $permissions); if (count($parts) !== 2) {
continue;
}
[$user, $permissions] = $parts;
$parts = explode('/', $permissions);
if (count($parts) < 3) {
continue;
}
[$type, $flags, $mask] = $parts;
$type = $type === 'ALLOWED' ? ACL::TYPE_ALLOW : ACL::TYPE_DENY; $type = $type === 'ALLOWED' ? ACL::TYPE_ALLOW : ACL::TYPE_DENY;

View file

@ -28,7 +28,7 @@ class Server extends AbstractServer {
} }
private function getAuthFileArgument(): string { private function getAuthFileArgument(): string {
if ($this->getAuth()->getUsername()) { if ($this->getAuth()->getUsername() !== null) {
return '--authentication-file=' . $this->system->getFD(3); return '--authentication-file=' . $this->system->getFD(3);
} else { } else {
return ''; return '';
@ -54,8 +54,8 @@ class Server extends AbstractServer {
$smbClient, $smbClient,
$this->getAuthFileArgument(), $this->getAuthFileArgument(),
$this->getAuth()->getExtraCommandLineArguments(), $this->getAuth()->getExtraCommandLineArguments(),
$maxProtocol ? "--option='client max protocol=" . $maxProtocol . "'" : "", ($maxProtocol !== null) ? "--option='client max protocol=" . $maxProtocol . "'" : "",
$minProtocol ? "--option='client min protocol=" . $minProtocol . "'" : "", ($minProtocol !== null) ? "--option='client min protocol=" . $minProtocol . "'" : "",
escapeshellarg('//' . $this->getHost()) escapeshellarg('//' . $this->getHost())
); );
$connection = new RawConnection($command); $connection = new RawConnection($command);

View file

@ -76,7 +76,7 @@ class Share extends AbstractShare {
} }
private function getAuthFileArgument(): string { private function getAuthFileArgument(): string {
if ($this->server->getAuth()->getUsername()) { if ($this->server->getAuth()->getUsername() !== null) {
return '--authentication-file=' . $this->system->getFD(3); return '--authentication-file=' . $this->system->getFD(3);
} else { } else {
return ''; return '';
@ -94,13 +94,13 @@ class Share extends AbstractShare {
$command = sprintf( $command = sprintf(
'%s %s%s -t %s %s %s %s %s %s', '%s %s%s -t %s %s %s %s %s %s',
self::EXEC_CMD, self::EXEC_CMD,
$stdBuf ? $stdBuf . ' -o0 ' : '', ($stdBuf !== null) ? $stdBuf . ' -o0 ' : '',
$smbClient, $smbClient,
$this->server->getOptions()->getTimeout(), $this->server->getOptions()->getTimeout(),
$this->getAuthFileArgument(), $this->getAuthFileArgument(),
$this->server->getAuth()->getExtraCommandLineArguments(), $this->server->getAuth()->getExtraCommandLineArguments(),
$maxProtocol ? "--option='client max protocol=" . $maxProtocol . "'" : "", ($maxProtocol !== null) ? "--option='client max protocol=" . $maxProtocol . "'" : "",
$minProtocol ? "--option='client min protocol=" . $minProtocol . "'" : "", ($minProtocol !== null) ? "--option='client min protocol=" . $minProtocol . "'" : "",
escapeshellarg('//' . $this->server->getHost() . '/' . $this->name) escapeshellarg('//' . $this->server->getHost() . '/' . $this->name)
); );
$connection = new Connection($command, $this->parser); $connection = new Connection($command, $this->parser);
@ -439,7 +439,7 @@ class Share extends AbstractShare {
* @throws DependencyException * @throws DependencyException
*/ */
public function notify(string $path): INotifyHandler { public function notify(string $path): INotifyHandler {
if (!$this->system->getStdBufPath()) { //stdbuf is required to disable smbclient's output buffering if ($this->system->getStdBufPath() == null) { //stdbuf is required to disable smbclient's output buffering
throw new DependencyException('stdbuf is required for usage of the notify command'); throw new DependencyException('stdbuf is required for usage of the notify command');
} }
$connection = $this->getConnection(); // use a fresh connection since the notify command blocks the process $connection = $this->getConnection(); // use a fresh connection since the notify command blocks the process
@ -519,7 +519,7 @@ class Share extends AbstractShare {
*/ */
protected function getAcls(string $path): array { protected function getAcls(string $path): array {
$commandPath = $this->system->getSmbcAclsPath(); $commandPath = $this->system->getSmbcAclsPath();
if (!$commandPath) { if ($commandPath === null) {
return []; return [];
} }