Skip to content

Android и Linux клиенты Sora - #8

Open
levvs-one wants to merge 25 commits into
mainfrom
feature/android-linux-clients
Open

Android и Linux клиенты Sora#8
levvs-one wants to merge 25 commits into
mainfrom
feature/android-linux-clients

Conversation

@levvs-one

@levvs-one levvs-one commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Что внутри

  • общий монохромный интерфейс Android/Linux
  • отдельные подписки, автообновление, Markdown-описание, защита от дублей и настоящий pingBatch
  • Android VpnService с TUN, foreground-службой, сохранением режима и восстановлением конфигурации
  • Linux системный прокси GNOME/KDE, закрытое XDG-хранилище и TUN только с реальными правами
  • проверочные sora_android.apk и sora_linux_amd64.deb только как CI-артефакты

Проверка

  • 7 JVM-регрессионных тестов прошли
  • Android SDK 36: APK собран, v2-подпись проверена apksigner
  • Linux: deb собран на Ubuntu 22.04 для совместимости с libasound2
  • Windows 7, 8.1, 10 и 11: сборка и регрессионные сценарии прошли

Релиз, тег, merge и публикация установщиков намеренно не выполняются до ручной проверки.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-01T08:39:07.965048Z 69b1e0d PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +94 to +95
throw failure
}.also { clearOperation() }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment on lines +60 to +61
val url = rawUrl.trim()
require(url.startsWith("https://", ignoreCase = true)) { "Подписка должна использовать HTTPS" }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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" }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment on lines +105 to +107
old.copy(
title = protocol.profileTitle(fetched.profileTitle, old.title),
xrayJson = xrayJson,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant