Better handle of SMB mount with special characters in username/password (#1448)
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Fri, 5 Jul 2024 13:21:46 +0000 (15:21 +0200)
committerGitHub <noreply@github.com>
Fri, 5 Jul 2024 13:21:46 +0000 (15:21 +0200)
music_assistant/server/helpers/process.py
music_assistant/server/providers/filesystem_smb/__init__.py

index 492bca619ef11f6a5f3b176afb692dd017a9bdac..b64951867aaf5e9434b6bee6abaffc5b6e4da648 100644 (file)
@@ -257,12 +257,10 @@ class AsyncProcess:
         return self._returncode
 
 
-async def check_output(*args: str) -> tuple[int, bytes]:
+async def check_output(*args: str, env: dict[str, str] | None = None) -> tuple[int, bytes]:
     """Run subprocess and return returncode and output."""
     proc = await asyncio.create_subprocess_exec(
-        *args,
-        stderr=asyncio.subprocess.STDOUT,
-        stdout=asyncio.subprocess.PIPE,
+        *args, stderr=asyncio.subprocess.STDOUT, stdout=asyncio.subprocess.PIPE, env=env
     )
     stdout, _ = await proc.communicate()
     return (proc.returncode, stdout)
index 6a0c4759ce83e10cf6a079e04a65a8f6f88b46e6..4fb2cf15fcf3c0491e5f26345e9c4b17eb52202b 100644 (file)
@@ -185,22 +185,18 @@ class SMBFileSystemProvider(LocalFileSystemProvider):
                 subfolder = subfolder[:-1]
 
         if platform.system() == "Darwin":
+            # NOTE: MacOS does not support special characters in the username/password
             password_str = f":{password}" if password else ""
             mount_cmd = [
                 "mount",
                 "-t",
                 "smbfs",
-                f"//{username}:{password_str}@{server}/{share}{subfolder}",
+                f"//{username}{password_str}@{server}/{share}{subfolder}",
                 self.base_path,
             ]
 
         elif platform.system() == "Linux":
-            options = [
-                "rw",
-                f'username="{username}"',
-            ]
-            if password:
-                options.append(f'password="{password}"')
+            options = ["rw"]
             if mount_options := self.config.get_value(CONF_MOUNT_OPTIONS):
                 options += mount_options.split(",")
 
@@ -224,8 +220,13 @@ class SMBFileSystemProvider(LocalFileSystemProvider):
             "Using mount command: %s",
             [m.replace(password, "########") if password else m for m in mount_cmd],
         )
+        env_vars = {
+            "USER": username,
+        }
+        if password:
+            env_vars["PASSWD"] = password
 
-        returncode, output = await check_output(*mount_cmd)
+        returncode, output = await check_output(*mount_cmd, env=env_vars)
         if returncode != 0:
             msg = f"SMB mount failed with error: {output.decode()}"
             raise LoginFailed(msg)