Android и Linux клиенты Sora - #8
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 69b1e0d6ca
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| throw failure | ||
| }.also { clearOperation() } |
There was a problem hiding this comment.
Clear the busy state when an import fails
When fetching, normalizing, validating, or persisting a subscription throws, this throw exits before the following .also { clearOperation() } executes. The import dialog therefore remains permanently busy and disables further attempts until the app is restarted; clear the operation from a finally block instead.
Useful? React with 👍 / 👎.
| val url = rawUrl.trim() | ||
| require(url.startsWith("https://", ignoreCase = true)) { "Подписка должна использовать HTTPS" } |
There was a problem hiding this comment.
Prevent HTTPS subscriptions from downgrading on redirects
This validates only the user-supplied URL, while the Android client explicitly follows redirects and fetch never checks the final response URL. An HTTPS endpoint returning a redirect to HTTP can therefore expose a subscription token and allow an on-path attacker to replace the downloaded Xray configuration, despite the UI promising HTTPS-only imports; reject downgrade redirects or validate the final URL before accepting the body.
Useful? React with 👍 / 👎.
| val outbound = element as? JsonObject ?: return@mapIndexedNotNull null | ||
| val protocol = outbound.string("protocol").lowercase() | ||
| if (protocol in setOf("freedom", "blackhole", "dns", "loopback")) return@mapIndexedNotNull null | ||
| val tag = outbound.string("tag").ifBlank { "sora-$index" } |
There was a problem hiding this comment.
Connect the selected untagged outbound
For a valid Xray configuration containing multiple non-service outbounds without explicit tags, nodes assigns synthetic values such as sora-0 and sora-1, but runtimeConfig searches the original JSON for those nonexistent tags and then always falls back to the first outbound. Selecting any later node consequently connects to the wrong server; retain enough identity to resolve the original outbound by index or inject the synthetic tag into the runtime copy.
Useful? React with 👍 / 👎.
| override suspend fun write(value: String) { | ||
| Files.createDirectories(stateFile.parent) | ||
| val temporary = stateFile.resolveSibling("state.json.tmp") | ||
| Files.writeString(temporary, value, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING) |
There was a problem hiding this comment.
Restrict permissions on the Linux state file
On Linux systems with a conventional 022 umask and a traversable home/config directory, this newly created temporary file is typically mode 0644, and moving it preserves that mode. Because the serialized state includes subscription URLs and complete Xray configurations with proxy credentials, other local users can read those secrets; create the temporary file with owner-only permissions before writing and moving it.
Useful? React with 👍 / 👎.
| old.copy( | ||
| title = protocol.profileTitle(fetched.profileTitle, old.title), | ||
| xrayJson = xrayJson, |
There was a problem hiding this comment.
Preserve user-assigned subscription titles
After a user supplies a preferred title during import or renames a subscription in settings, every successful manual or automatic refresh replaces it with the server's profile-title header. This makes the exposed rename feature nonpersistent for subscriptions that publish that header; keep the stored title unless the application separately tracks that it was never customized.
Useful? React with 👍 / 👎.
Что внутри
sora_android.apkиsora_linux_amd64.debтолько как CI-артефактыПроверка
apksignerdebсобран на Ubuntu 22.04 для совместимости сlibasound2Релиз, тег, merge и публикация установщиков намеренно не выполняются до ручной проверки.