From a66701fe35c0fc0bc489e959689e81cd165e9599 Mon Sep 17 00:00:00 2001 From: OzGav Date: Tue, 3 Feb 2026 00:12:55 +1100 Subject: [PATCH] Allow all special characters in passwords (#3072) * fix-commas-in-passwords * shorten comment --- .../providers/filesystem_smb/__init__.py | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/music_assistant/providers/filesystem_smb/__init__.py b/music_assistant/providers/filesystem_smb/__init__.py index c7d56e00..cdbd033e 100644 --- a/music_assistant/providers/filesystem_smb/__init__.py +++ b/music_assistant/providers/filesystem_smb/__init__.py @@ -236,8 +236,8 @@ class SMBFileSystemProvider(LocalFileSystemProvider): server, username, password_str, share, subfolder ) elif platform.system() == "Linux": - mount_cmd = self._build_linux_mount_cmd( - server, username, password_str, share, subfolder + mount_cmd, env_vars = self._build_linux_mount_cmd( + server, username, password_str, share, subfolder, env_vars ) else: msg = f"SMB provider is not supported on {platform.system()}" @@ -279,16 +279,35 @@ class SMBFileSystemProvider(LocalFileSystemProvider): ] def _build_linux_mount_cmd( - self, server: str, username: str, password: str | None, share: str, subfolder: str - ) -> list[str]: - """Build mount command for Linux.""" + self, + server: str, + username: str, + password: str | None, + share: str, + subfolder: str, + env_vars: dict[str, str], + ) -> tuple[list[str], dict[str, str]]: + """Build mount command for Linux. + + Uses the PASSWD environment variable to handle passwords with special characters + (commas, etc.) that cannot be escaped on the command line. + + :param server: The SMB server hostname or IP. + :param username: The username for authentication. + :param password: The password for authentication (can contain special chars). + :param share: The share name on the server. + :param subfolder: Optional subfolder path within the share. + :param env_vars: Environment variables dict to modify with PASSWD if needed. + :returns: Tuple of (mount command args, modified env vars). + """ options = ["rw"] # read-write access - # Handle username and password + # We pass the password via the PASSWD environment variable to avoid + # improperly escaped passwords with special characters. if username and username.lower() != "guest": options.append(f"username={username}") if password: - options.append(f"password={password}") + env_vars["PASSWD"] = password else: # Guest/anonymous access options.append("guest") @@ -320,7 +339,7 @@ class SMBFileSystemProvider(LocalFileSystemProvider): ] ) - return [ + mount_cmd = [ "mount", "-t", "cifs", @@ -329,6 +348,7 @@ class SMBFileSystemProvider(LocalFileSystemProvider): f"//{server}/{share}{subfolder}", self.base_path, ] + return mount_cmd, env_vars async def unmount(self, ignore_error: bool = False) -> None: """Unmount the remote share.""" -- 2.34.1