?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~'; } /** * Ensure that parameters (database names, usernames, etc.) * only contain allowed characters before used in SQL statements * (or file names in the case of SQLiteDatabaseManager). * * By default, only the characters in static::allowedParameterCharacters() are allowed. * * Null parameters are skipped. * * @throws InvalidArgumentException */ protected function validateParameter(string|array|null $parameters, string|null $allowedCharacters = null): void { $allowedCharacters ??= static::allowedParameterCharacters(); foreach ((array) $parameters as $parameter) { if (is_null($parameter)) { // Skip if there's nothing to validate // (e.g. when $tenant->database()->getUsername() of an // improperly created tenant is null and it gets passed). continue; } if (! is_string($parameter)) { throw new InvalidArgumentException("Parameter has to be a string."); } foreach (str_split($parameter) as $character) { if (! str_contains($allowedCharacters, $character)) { throw new InvalidArgumentException("Forbidden character '{$character}' in parameter."); } } } } /** * Ensure password only contains allowed characters (static::allowedPasswordCharacters()) * before used in SQL statements. * * Used in permission controlled managers as a shorthand for calling validateParameter() * with the less strict allowlist to validate database user passwords. * * @throws InvalidArgumentException */ protected function validatePassword(string|null $password): void { $this->validateParameter($password, static::allowedPasswordCharacters()); } /** * Ensure filename only contains allowed characters (static::allowedFilenameCharacters()) * and is not a directory name before used in file paths (e.g. SQLite database names). * * @throws InvalidArgumentException * @see Stancl\Tenancy\Database\TenantDatabaseManagers\SQLiteDatabaseManager */ protected function validateFilename(string|null $filename): void { $this->validateParameter($filename, static::allowedFilenameCharacters()); if (is_string($filename) && is_dir($filename)) { throw new InvalidArgumentException("Filename '{$filename}' is a directory."); } } }