* @brief Validate a file path against the API allowlist, if configured. */
| 94 | * @brief Validate a file path against the API allowlist, if configured. |
| 95 | */ |
| 96 | bool API::isPathAllowed(const QString& filePath, const bool allowNonexistent) |
| 97 | { |
| 98 | QStringList roots; |
| 99 | if (qEnvironmentVariableIsSet("SERIAL_STUDIO_API_ALLOWED_PATHS")) { |
| 100 | const QString envValue = QString::fromLocal8Bit(qgetenv("SERIAL_STUDIO_API_ALLOWED_PATHS")); |
| 101 | if (envValue.trimmed().isEmpty()) |
| 102 | return false; |
| 103 | |
| 104 | roots = envValue.split(QDir::listSeparator(), Qt::SkipEmptyParts); |
| 105 | } |
| 106 | |
| 107 | else |
| 108 | roots = {QDir::homePath(), QDir::tempPath()}; |
| 109 | |
| 110 | const QString targetPath = normalizedPath(filePath, allowNonexistent); |
| 111 | if (targetPath.isEmpty()) |
| 112 | return false; |
| 113 | |
| 114 | for (const auto& root : std::as_const(roots)) { |
| 115 | const QString rootPath = normalizedPath(root.trimmed(), true); |
| 116 | if (rootPath.isEmpty()) |
| 117 | continue; |
| 118 | |
| 119 | #ifdef Q_OS_WIN |
| 120 | const Qt::CaseSensitivity sensitivity = Qt::CaseInsensitive; |
| 121 | #else |
| 122 | const Qt::CaseSensitivity sensitivity = Qt::CaseSensitive; |
| 123 | #endif |
| 124 | |
| 125 | if (targetPath.compare(rootPath, sensitivity) == 0) |
| 126 | return true; |
| 127 | |
| 128 | const QString prefix = rootPath + QLatin1Char('/'); |
| 129 | if (targetPath.startsWith(prefix, sensitivity)) |
| 130 | return true; |
| 131 | } |
| 132 | |
| 133 | return false; |
| 134 | } |
nothing calls this directly
no test coverage detected