TL;DR
- SmartProxy: scheme-prefixed entries (
http://,https://,socks5://,socks4://,socks4a://,socks://) are now accepted in the custom proxy list and in proxy-list URL bodies. Before 8.40 the parser only matched bareIP:PORT(optionally with*for SOCKS and@b64user:b64passfor auth); copying a line from a typical public proxy list and pasting it produced[SKIP] malformed. (#753) - SmartProxy: multiple
#PROXY_LIST_URLlines are aggregated. Before, only the FIRST^#http…line in the custom list textarea was used; any further URL sources were silently dropped. The manager now scans every#URLline, fetches each, merges the entries, and a single failing URL no longer kills the refresh — the status label shows[ok/total sources]when some succeed and some don't. (#753) - SmartProxy: list test is parallel with a configurable batch size. The test in
Edit -> Quota recovery & SmartProxy (509)used to probe every proxy sequentially with a 3 s TCP timeout, so a 300-entry pool took ~15 minutes. A newConcurrent probesspinner (1..100, default 20) cuts that to ~45 seconds. (#753) - SmartProxy: new
Save working proxies to custom listaction. After a test run, one click rewrites the inlineIP:PORTentries of the custom proxy list to only those that just passed the TCP probe.#URLsource lines and blank separators are preserved verbatim, so users who rely on auto-refreshed feeds can prune dead entries without losing the URLs that produced the list. Auth trailers and SOCKS markers are reconstructed from live state so the saved lines round-trip through the parser unchanged. (#753) - SmartProxy:
Settings -> SmartProxyrefresh-time label vsEdit -> Quota recovery509-window label disambiguated. The reporter on #753 flagged that the two spinners look like the same concept (60vs3600); they're not. Both labels were renamed and the tooltips now explicitly cross-reference each other. - MEGA
-9(ENOENT) is now FATAL, no retry loop on dead links. Before, when agetMegaFileMetadata/getMegaFileDownloadUrlreturned-9(the file no longer exists on MEGA), the cleanup path immediately re-armed the same request, producing an infinite loop that — with enough dead entries in a folder — eventually stalled the whole batch. (#688) - Everything that shipped in 8.39 is included; 8.40 is 8.39 + the changes above. No behaviour changes to anything outside SmartProxy and the dead-link path.
New in 8.40
Issue #753 — SmartProxy: accept scheme-prefixed entries
SmartMegaProxyManager.refreshProxyList() parsed entries against .+?:[0-9]{1,5} (after stripping an optional * for SOCKS and an optional @b64user:b64pass trailer for auth). Any line with an http://, https://, socks://, socks4://, socks4a:// or socks5:// prefix — i.e. the format public proxy lists actually ship — was rejected as [SKIP] malformed. The custom-list block and the URL-fetched block were near-duplicate parsers.
Both blocks are now collapsed into one parseProxyEntry helper that detects the scheme prefix case-insensitively, strips it, collapses all SOCKS variants to JDK Proxy.Type.SOCKS and HTTPS proxies to Proxy.Type.HTTP (since the JDK uses HTTP CONNECT for both), and drops any trailing path (http://host:port/ or http://host:port/list.txt). The legacy [*]IP:PORT[@b64u:b64p] shape continues to work unchanged. The * SOCKS marker can also precede a scheme prefix in case a user mixes conventions.
Audit follow-up (caught by scripts/SmartProxyParserSmoke.java):
- Base64 auth with
/was being truncated. The first cut applied a global path-strip before splitting on@; the legacyIP:PORT@b64u:b64pformat permits/in the base64 trailer, so an entry like1.2.3.4:8080@VGhpcw==:c2Vj/cmV0silently lost the trailing half of the password. The path-strip now runs only on the host:port half, after the@split. - URL-style
http://user:pass@host:portcredentials with numeric passwords (e.g.user:1234) were silently misparsed.user:1234matches the IP:PORT regex (port = 1234), so the parser would have storeduser:1234as the host andhost:portas the auth. Detected via the heuristic scheme prefix present AND parts[1] also looks like host:port and rejected with a pointed log line, since the legacy format on this codebase encodes auth as the trailer, not as the URL userinfo segment.
A reflection-based smoke test (SmartProxyParserSmoke.java) ships with the source under scripts/ (mirroring I18nSmoke.java) so any future parser tweak can be regression-tested in <1 s.
Issue #753 — SmartProxy: aggregate proxies from multiple #URL sources
MainPanel.java and MainPanelView.java extracted the SmartProxy list URL from the custom-list textarea via findFirstRegex("^#(http.+)$", custom_list, 1) — first match only. Any further #URL lines were silently dropped. With one feed sick or rate-limited, users had no way to aggregate from a second.
The #URL extraction now lives inside SmartMegaProxyManager.refreshProxyList(). The textarea is scanned line-by-line; lines starting with #http(s):// are collected as URL sources, the rest go through parseProxyEntry. Every URL is fetched, the entries are merged into a single working map, and a single failing URL is logged but does not invalidate the rest. The status label now appends [ok/total sources] when some URLs failed but the pool is still usable, so partial-success state is visible without trawling the DEBUG log. The SmartMegaProxyManager(String, MainPanel) constructor and the refreshProxyList(String) overload are gone (only two call sites; both updated).
Issue #753 — SmartProxy: parallel test with configurable batch size
QuotaRecoverySettingsDialog.testProxyList() probed entries sequentially with a 3 s TCP Socket.connect timeout each, so a 300-entry list took ~15 min. A safety_cap of 256 (raised to 4096 mid-development, then removed — see audit note below) capped the drain loop.
Replaced by a fixed-size ExecutorService whose size is taken from a new Concurrent probes spinner (1..100, default 20). Output stays in submission order (futures are walked in the order they were enqueued), malformed entries and bad-port entries are pre-classified on the spawning thread so worker slots aren't wasted on them, and the executor is shutdownNow()'d both on normal completion and on dispose() of the dialog (a user closing the dialog mid-test no longer leaves a thread per outstanding TCP connect attempt blocked inside the JVM). Default test wall time on a 300-entry pool drops from ~15 min to ~45 s. New i18n keys (ui.quota.batch_size_label, ui.quota.batch_size.tooltip, ui.quota.test.cancelled) and the updated ui.quota.test.testing_count placeholder land in every messages*.properties bundle (de, en, es, hu, it, tr, vi, zh).
Audit follow-up: the safety_cap was a chapuza for two reasons —
getProxy()filters out banned proxies (line 281 inSmartMegaProxyManager); the test, which was draining viagetProxy(), therefore never saw a proxy that was in its 5-minute ban window. A user who wanted to check whether their banned entries had recovered could not.- Any pool larger than the cap was silently truncated.
Both went away in one move: expose getProxySnapshot() on the manager (returns {address, type} for every entry regardless of ban state) and drive testProxyList() off that directly. No drain trick, no exclusion list, no cap. Banned proxies are now visible to the test — a banned entry that has actually recovered shows [OK], one that's still dead shows [FAIL], which is exactly the diagnostic value the action is supposed to provide.
Issue #753 — SmartProxy: Save working proxies to custom list action
A new button next to the Test SmartProxy list button. After a test run, one click rewrites the custom_proxy_list DB setting so that the only inline IP:PORT entries are those whose addresses just passed the TCP probe, in submission order. Lines starting with # (remote URL sources) and blank separators are preserved verbatim — so a user who relies on auto-refreshed feeds can prune dead entries without losing the URL feeds that produced the list. Auth trailers and SOCKS markers are looked up from live SmartMegaProxyManager state at save time, so each saved line round-trips through parseProxyEntry into an equivalent entry (an authenticated proxy doesn't lose its credentials). The save kicks an async refresh so the live pool tracks the new textarea immediately.
This replaces the more invasive "persist tested/working proxies" DB-schema proposal from the issue: it reuses the existing textarea as the sole proxy-list state, requires no new schema migration, lets the user re-test at any time, and the action is opt-in rather than implicit.
Issue #753 (reporter comment) — Settings -> SmartProxy refresh-time vs Edit -> Quota recovery 509-window label clarity
The reporter on #753 attached a screenshot of two spinners on different screens — Proxy list refresh (minutes): [60] in Settings -> SmartProxy, SmartProxy 509 recheck window (s): [3600] in Edit -> Quota recovery & SmartProxy (509) — and noted they look like the same concept with contradictory values. They are not: the first is how often the proxy list itself is re-downloaded from #URL feeds; the second is how long a download stays on SmartProxy after a 509 even if individual chunks succeed. Both labels were renamed (Re-download proxy list every (minutes): and Keep SmartProxy active after 509 for (s): respectively), and the tooltips now explicitly cross-reference each other so reading either one tells the user what the OTHER spinner does. The English literal change required updating both SettingsDialog.java's jLabel8.setText and SettingsDialog.form's text Property in lockstep so the LabelTranslatorSingleton English-literal->key lookup keeps working; a new settings.smartproxy.refresh.tooltip key was added and wired in via I18n.tr after initComponents. Translations landed in all 8 bundles.
Highlights (carried over from 8.39)
Issue #688 — MEGA -9 (ENOENT) no longer triggers an infinite retry loop on dead links
Reported by @yontank. When a getMegaFileMetadata or getMegaFileDownloadUrl request returned -9 (the link is dead — the file was removed from MEGA), the cleanup path treated it as a transient failure, re-queued the same request, hit -9 again, and so on. With a folder that contained enough dead entries the whole batch stalled inside that loop.
Fix: add -9 to FATAL_API_ERROR_CODES (the list that the cleanup path consults to decide fatal, do not retry, surface to user vs transient, retry). A dead link now lands once, shows the right error to the user, and the surrounding batch continues with the remaining entries.
Build artefact: MegaBasterd_8.40.jar is the full fat-JAR (-jar-with-dependencies), drop-in replacement for the 8.39 jar.
Translators: 9 new i18n keys + 4 updated literals — see #397