* @brief Returns a canonical absolute path, optionally permitting non-existent files. */
| 63 | * @brief Returns a canonical absolute path, optionally permitting non-existent files. |
| 64 | */ |
| 65 | static QString normalizedPath(const QString& path, bool allowNonexistent) |
| 66 | { |
| 67 | QFileInfo info(path); |
| 68 | if (info.exists()) |
| 69 | return expandShortPath(QDir::cleanPath(info.canonicalFilePath())); |
| 70 | |
| 71 | if (!allowNonexistent) |
| 72 | return QString(); |
| 73 | |
| 74 | const QString absolute = QDir::cleanPath(info.absoluteFilePath()); |
| 75 | |
| 76 | QDir ancestor(absolute); |
| 77 | QStringList tail; |
| 78 | constexpr int kMaxDepth = 64; |
| 79 | for (int i = 0; i < kMaxDepth && !ancestor.exists() && !ancestor.isRoot(); ++i) { |
| 80 | tail.prepend(ancestor.dirName()); |
| 81 | if (!ancestor.cdUp()) |
| 82 | return expandShortPath(absolute); |
| 83 | } |
| 84 | |
| 85 | const QString canonicalRoot = ancestor.canonicalPath(); |
| 86 | if (canonicalRoot.isEmpty()) |
| 87 | return expandShortPath(absolute); |
| 88 | |
| 89 | tail.prepend(canonicalRoot); |
| 90 | return QDir::cleanPath(tail.join(QDir::separator())); |
| 91 | } |
| 92 | |
| 93 | /** |
| 94 | * @brief Validate a file path against the API allowlist, if configured. |
no test coverage detected