1248 Commits
Author SHA1 Message Date
SuyunjingandLunelleEverdawn 25da9901f5 fix(drivers/local): handle cross-device recycle bin deletes (#3304)
Beta Release builds / Beta Release Changelog (push) Failing after 56s
Beta Release builds / Beta Release (, , md5, !(*musl*|*windows-arm64*|*windows7-*|*android*|*freebsd*)) (push) Skipped
Beta Release builds / Beta Release (, , md5-android, false, android-*) (push) Skipped
Beta Release builds / Beta Release (, , md5-freebsd, false, freebsd-*) (push) Skipped
Beta Release builds / Beta Release (, , md5-windows-arm64, false, windows-arm64) (push) Skipped
Beta Release builds / Beta Release (, -tags=sqlite_cgo_compat, md5-windows7, false, windows7-*) (push) Skipped
Beta Release builds / Beta Release (-ldflags=-linkmode external -extldflags '-static -fpic', , md5-linux-musl, true, linux-!(arm*|mips|mips64|mipsle|mips64le|loong64)-musl*) (push) Skipped
Beta Release builds / Beta Release (-ldflags=-linkmode external -extldflags '-static -fpic', , md5-linux-musl-arm, true, linux-arm*-musl*) (push) Skipped
Beta Release builds / Beta Release (-ldflags=-linkmode external -extldflags '-static -fpic', , md5-linux-musl-mips, true, linux-(mips|mips64|mipsle|mips64le|loong64)-musl*) (push) Skipped
Sync to Gitee / Sync GitHub to Gitee (push) Failing after 36s
Beta Release (Docker) / Build Binaries for Docker Release (Beta) (push) Failing after 57m4s
Beta Release (Docker) / Release Docker image (Beta) (aio, INSTALL_FFMPEG=true INSTALL_ARIA2=true , aio, suffix=-aio,onlatest=true) (push) Skipped
Beta Release (Docker) / Release Docker image (Beta) (aria2, INSTALL_ARIA2=true, aria2, suffix=-aria2,onlatest=true) (push) Skipped
Beta Release (Docker) / Release Docker image (Beta) (base, , latest, ) (push) Skipped
Beta Release (Docker) / Release Docker image (Beta) (ffmpeg, INSTALL_FFMPEG=true, ffmpeg, suffix=-ffmpeg,onlatest=true) (push) Skipped
- Fall back from cross-device rename to copy-then-remove while preserving
  relative symlinks, read-only directory support, file and directory
  modification times, and existing permissions.
- Keep the source and incomplete recycle-bin copy when a named-pipe copy
  does not create a destination entry.
- Preserve the complete recycle-bin copy when source removal fails.
- Skip the recycle bin when transfer tasks remove sources after a successful
  cross-storage move, avoiding duplicate move and recycle-bin copies.
- Add targeted coverage for relative symlinks, read-only directories,
  modification times, and permanent removal with a recycle bin configured.

Fixes #1856

Co-authored-by: LunelleEverdawn <lunelle+suyunmeng@oplist.org>
2026-11-08 13:22:06 +08:00
SuyunjingandLunelleEverdawn 05d3fea069 fix(drivers/115): handle multipart upload failures safely (#3312)
- Preserve multipart chunk errors to prevent nil upload results and downstream panics.
- Cancel and wait for multipart workers on failure, and attempt to abort OSS uploads with the current security token.
- Map WebDAV upload errors to appropriate HTTP status codes: 403 for permission failures, 405 for unsupported uploads, and 500 for other backend failures.

Fixes #3201

Co-authored-by: LunelleEverdawn <lunelle+suyunmeng@oplist.org>
2026-11-08 13:13:35 +08:00
Pikachu Renandpikachuren b8ab76091a fix(seed): make 189 CAS rapid upload carry the right file, hashes and slice size (#3341)
* fix(seed): keep CAS hash matrix for 189 rapid upload

CAS seeds only carry MD5 + slice MD5s, but the quick-save path rebuilt the rapid-upload request through a torrent container, which requires SHA-1 piece hashes. Every 189 秒传 therefore failed before any request was sent and reported 'target driver cannot reuse the available hashes'.

- build the rapid-upload request directly from the seed file, keeping the whole MD5, slice MD5s, the drive's slice size and the legacy slice digest
- let 189pc run initMultiUpload/checkTransSecond/commitMultiUploadFile when slice hashes are available, falling back to the legacy whole-MD5 upload
- surface the real rapid-upload error instead of the generic message

* fix(189pc): surface daily flow limit instead of generic rapid-upload error

The CAS path now reaches 189's upload API, and the first real rejection is UserDayFlowOverLimited (account daily upload flow exhausted). Treat it as a terminal account state instead of retrying:

- add errs.DailyFlowLimitExceeded and map UserDayFlowOverLimited / 'flow is out' onto it (189 returns it as a business code inside HTTP 200)
- skip the legacy whole-MD5 fallback once the account is limited
- report 'rapid upload failed: ...' with the real reason and mark the rest of the batch unavailable instead of one request per file

* fix(seed): refuse to generate a seed from a seed container

Generating a .cas seed from a .cas file produced an artifact with exactly the same name in the same folder, so PutDirectly overwrote the original seed with a seed-of-seed: the payload then described the few-hundred-byte metadata file instead of the video. Rapid upload of that seed 'succeeds' and only creates another .cas, which looks like CAS 秒传 doing nothing.

- skip .oss/.torrent/.cas/.cas.torrent when expanding a directory
- reject an explicit selection of a seed container with an actionable message
- refuse to write an artifact over one of its own source files

* refactor(cas): derive slice size from file size and store the final digest

CAS 判重只比较最终分片摘要(逐片 MD5 汇总后再取 MD5),而切法由文件大小固定:10MiB / 20MiB / 更大文件按 1999 片上限向上取 10MiB 的整数倍。之前把 sliceMd5 当成「可变分片的哈希」、总是从逐片列表现算,切法一变就对不上云端。

- add torrent.CASSliceSize / CASPartCount / CASUniformSliceSize as the single source of truth; 189pc.partSize delegates to it
- .cas writes the final digest in sliceMd5 and the per-slice list in partsMd5; slice_md5s stays readable for old files
- rapid upload prefers the explicit sliceMd5 and only derives it from parts when absent
- generation, recalculate and inline conversion hash CAS files at CASSliceSize per file and drop parts that do not match that slicing
- piece_size no longer influences CAS hashing

* fix(seed): refuse to rapid-upload a seed that describes itself

A .cas generated from another .cas documents the metadata file itself (name ends with .cas, a few hundred bytes). Rapid-uploading it just creates another same-named .cas in the target folder, which looks like CAS 秒传 doing nothing. Reject that case with an actionable message instead.

* test(seed): lock the rapid-upload name and the seed-of-seed guard

- extract seedRapidUploadBlocker so the guard is testable
- add an end-to-end test proving a legacy 5-field .cas resolves to the video name, size, slice size and final slice MD5
- add a test that seed containers are refused for rapid upload

* refactor(seed): output seed and torrent messages in English

Turn the error strings, task statuses and progress labels of the transfer-seed / torrent feature into English, including the 189 CAS rapid-upload path and the front-end facing guards. Comments and unrelated log lines are untouched.

* refactor(cas): make the CAS slice rule a verbatim port of the 189 upload rule

CAS slice size must be exactly what 189 uses when uploading, otherwise the sliceMd5 submitted for rapid upload can never match the digest the drive stored.

- CASSliceSize now copies 189pc partSize expression by expression (same DEFAULT constant, same float expression, same 5x lower bound)
- expectedCASPartCount mirrors fastUpload's count: one slice when size <= sliceSize, otherwise ceil(size/sliceSize)
- add cross-package tests comparing CASSliceSize/CASPartCount against a verbatim copy of the 189 rule, and partSize against CASSliceSize

* fix(seed): address CAS sidecar and digest review findings

P1 FsStream hashed uploads with seedPieceSize() while the sidecar declared the CAS slice size; unknown-size CAS uploads now fail before writing the file instead of after. P1 buildCASFileEntry only compared piece counts, so 8MiB slices could be reused as 10MiB CAS slices; it now requires the slicing to match. P2 multi-slice payloads without sliceMd5 are rejected instead of falling back to the whole-file MD5, and oversized CAS slice sizes are clamped for the seed container only.

---------

Co-authored-by: pikachuren <pikachuren@example.com>
2026-11-06 12:48:12 +08:00
d09af74a75 fix(drivers/onedrive): refresh token on drive quota query and retry only once (#3335)
fix(onedrive): refresh token on drive quota query and retry only once

getDrive (used for storage capacity) was the only request that opted out
of the InvalidAuthenticationToken refresh, so an expired token made the
capacity query fail until another request happened to refresh it. Let it
refresh like every other request.

The retry after a refresh did not pass noRetry, so a token that stayed
invalid after a successful refresh recursed without bound. Retry once.


Claude-Session: https://claude.ai/code/session_01U5btuswaVrY7Lp7FWWVEHh

Co-authored-by: Vurliy <ulermi@outlook.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:42:33 +08:00
DIYgodandClaude Opus 5.5 db581fc6c9 fix(drivers/guangyapan): return list errors instead of an empty folder (#3326)
List and findChildFolderID only checked the error from postAPI, which
fails on transport errors and HTTP status >= 400. GuangYaPan reports
business errors with HTTP 200 and a non-zero code and msg in the body,
so a failed get_file_list call ended the listing early: the folder
looked empty (or truncated, on a later page), and resolving root_path
reported "folder not found".

Check the msg after each page with isSuccessMsg, like the other API
calls in the driver, and return the code and msg. Also gofmt the two
request bodies. Add tests for a failed and a successful list response.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:35:19 +08:00
AkashiCoinandClaude 4780b1cfd5 feat(drivers/onedrive_app): support mounting SharePoint site document library (#3252)
* feat(drivers/onedrive_app): 支持挂载 SharePoint 站点文档库

- 新增 `is_sharepoint` 与 `site_id` 两个配置项,开启后走 `/sites/{siteId}/drive` 而不是 `/users/{email}/drive`
- 新增 `NormalizeSiteID`,接受 `siteId,siteGuid,webGuid`、`host:/sites/name`、站点 URL 和站点集合根 URL 四种写法
- 路径形式的 site 标识在 `Init` 阶段解析成 Graph 的逗号形式并回写存储,因为 `/sites/{path}:/` 后面不能继续拼 `/drive`
- `Init` 对 SharePoint 模式校验 `site_id`,非 SharePoint 模式校验 `email` 非空
- 配额查询 `getDrive` 同步区分两种模式
- 补充 `NormalizeSiteID` 与 URL 拼接的单元测试

Co-authored-by: Claude <81847+claude@users.noreply.github.com>

* docs(drivers/onedrive_app): 补全并精简 site_id 的帮助文案

- 说明裸域名会解析成站点集合根站点,其默认文档库通常为空
- 补充完整站点 URL 也会被解析成 ID 形式
- 合并为两句话,缩短表单提示气泡长度

Co-authored-by: Claude <81847+claude@users.noreply.github.com>

* fix(drivers/onedrive_app): 根站点标识不再拼接尾冒号

- `NormalizeSiteID` 对空站点路径走 `/sites/{hostname}` 主机名寻址,只有存在站点子路径时才生成 `/sites/{hostname}:/{path}:`
- 统一 `host:/path/:` 这类多重尾字符为单个冒号
- 补充裸主机名、带尾斜杠主机名、`host:/` 三种输入的用例

Co-authored-by: Claude <81847+claude@users.noreply.github.com>

---------

Co-authored-by: Claude <81847+claude@users.noreply.github.com>
2026-11-06 12:20:19 +08:00
MadDogOwner fb692b54d7 refactor(deps): replace appengine logging with utils.Log (#3321)
Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-10-29 14:53:35 +08:00
SuyunjingandLunelleEverdawn 6aeaf1dafd fix(drivers/115): retry upload init after decrypt failures (#3268)
- Retry failed upload response decryption up to three attempts.
- Close each initialization response body immediately after reading.

Co-authored-by: LunelleEverdawn <lunelle+suyunmeng@oplist.org>
2026-10-28 12:30:56 +08:00
f33a2c780d feat(drivers): add CtFile OpenAPI driver (#3214)
- Add the CtFile OpenAPI storage driver with session authentication and common file operations.
- Reuse cached streams and stream multipart uploads to avoid large-file memory duplication.
- Fix copy cache handling when the API does not return a destination ID.
- Guard upload caching when no progress callback is provided.

Co-authored-by: Grok Bot <grok-bot@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Suyunmeng <suyunmeng@oplist.org.cn>
Co-authored-by: LunelleEverdawn <lunelle+suyunmeng@oplist.org>
2026-10-26 22:19:08 +08:00
e23600200a fix(drivers/webdav): retry collection stat with trailing slash (#3223)
* fix(webdav): retry collection stat with trailing slash

Some WebDAV servers (e.g. InfiniCloud) answer a PROPFIND on a collection
path without the trailing slash with a redirect the HTTP client follows
into a plain 200 HTML response instead of the required 207 Multi-Status,
so every stat of a subdirectory fails even though the directory exists.
The upstream symptom this produces: any upload into a nested directory
dies with "failed to get dir [<path>]: failed to get obj: PROPFIND
<path>: 200" — MakeDir succeeds, then the stat of the freshly created
parent dir fails, because op.GetUnwrap goes straight to driver.Get.

Retry the stat once against the canonical collection URL (slash
appended) before giving up; 404s are not retried, and paths already
carrying the slash skip the retry. The new test reproduces the quirky
server (slash-less PROPFIND -> 200 HTML, slash PROPFIND -> 207) and
fails on the unpatched driver with the exact production error.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* Update drivers/webdav/driver.go

Signed-off-by: Yinan Qin <elysia-best@simplelinux.cn.eu.org>

* Update drivers/webdav/driver_test.go

Signed-off-by: Yinan Qin <elysia-best@simplelinux.cn.eu.org>

---------

Signed-off-by: Yinan Qin <elysia-best@simplelinux.cn.eu.org>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Yinan Qin <elysia-best@simplelinux.cn.eu.org>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-10-23 22:47:56 +08:00
Ljcbaby fbbded2f90 fix(drives/baidu_netdisk): Add error codes for token refresh condition (#3232)
ref: https://pan.baidu.com/union/doc/%E5%B9%B3%E5%8F%B0%E7%AE%80%E4%BB%8B/%E9%94%99%E8%AF%AF%E7%A0%81/

Signed-off-by: Ljcbaby <46277145+ljcbaby@users.noreply.github.com>
2026-10-22 21:15:20 +08:00
2caa4f5d15 feat(seed): add advanced transfer seed UI (generate/preview/manage) (#3058)
* feat: add system initialization (setup wizard) support

* Squashed commit of the following:

commit 2d51c9ab4b
Author: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
Date:   Mon Sep 7 14:14:22 2026 +0800

    feat!(init): add initialization wizard (#3041)

    feat: add system initialization (setup wizard) support

    Co-authored-by: PIKACHUIM <PIKACHUIM@users.noreply.github.com>

commit d9d8aa24e6
Author: ShenLin <773933146@qq.com>
Date:   Mon Sep 7 12:01:15 2026 +0800

    fix(s3): default upload content types and return partial content (#3053)

    - Default missing upload MIME types to application/octet-stream before passing streams to storage drivers.
    - Return HTTP 206 for successful ranged GET responses while preserving error statuses.
    - Add isolated response-status regression tests without database initialization.

    Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
    Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

commit 55530ff171
Author: ShenLin <773933146@qq.com>
Date:   Mon Sep 7 12:00:50 2026 +0800

    fix(release): fetch frontend assets from edge (#3052)

    - Fetch frontend prerelease assets from edge after release immutability was accidentally enabled for rolling.

    Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
    Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

commit 6247cf7be2
Author: MadDogOwner <xiaoran@xrgzs.top>
Date:   Sat Sep 5 15:56:40 2026 +0800

    feat(server/s3): support multipart upload (#2813)

commit eee910babb
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Sat Sep 5 12:22:53 2026 +0800

    fix(deps): update module github.com/rclone/rclone to v1.75.1 (#3035)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 6b55a82ffe
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Sat Sep 5 12:14:09 2026 +0800

    chore(deps): update docker/setup-qemu-action digest to 1f40c72 (#3021)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 93dac1655f
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Sat Sep 5 12:12:51 2026 +0800

    chore(deps): update go toolchain directive to v1.27.1 (#3024)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 6ad44605c0
Author: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
Date:   Sat Sep 5 12:11:51 2026 +0800

    feat(drivers/guangyapan): add md5-based instant upload support (#3034)

    feat(guangyapan): add md5-based instant upload support

    Co-authored-by: PIKACHUIM <PIKACHUIM@users.noreply.github.com>

commit d90d84906e
Author: UcnacDx2 <127503808+UcnacDx2@users.noreply.github.com>
Date:   Sat Sep 5 11:55:41 2026 +0800

    fix(drivers/139): improve mail login credential renewal (#3029)

    * fix(drivers/139): improve mail login credential renewal

    * fix(drivers/139): guard mail login client initialization

    Fall back to base.NewRestyClient() when base.RestyClient has not been initialized, while preserving cloned global-client behavior and the login/SMS retry and redirect policies.

commit c3d3da9286
Author: ShenLin <773933146@qq.com>
Date:   Sat Sep 5 00:12:20 2026 +0800

    fix(drivers/189): decode JSON strings before parsing timestamps (#3033)

    - Decode JSON time strings before normalizing Unicode spaces in both 189 drivers
    - Exercise escaped spaces and existing date formats through JSON unmarshalling
    - Cover invalid JSON input and XML time parsing

    Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
    Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

* feat(seed): add advanced transfer seed support (OSS/torrent/CAS)

Add unified sharing-seed format library (openlist-sharing-seed v1), standard BT torrent v1 with x-openlist/x-cas extensions, and exact legacy-compatible CAS Base64 payload. Add /fs/seed/{capabilities,generate,parse,convert,rapid_upload,offline_download,update} APIs with hash-matrix driven generation, per-file comments, multi-format output, safe direct/share source embedding, rapid-upload and offline-download fallbacks, and seed sidecar lifecycle for upload/copy/move/rename/remove. Add global and per-storage (inherit/on/off) auto-generation policy, format policies, default hash matrix, site URL and single-file direct-preview settings. Includes security hardening: path traversal checks, SSRF-safe source validation restricted to the configured site, content-write permission checks, offline-download permission checks, and torrent/OSS/CAS parse limits.

* feat(seed): complete edit, recalculate and relayed transfer

Implement seed metadata editing (comment/trackers/channels/file comments/sources) and server-side hash recalculation with piece-size write-back and a bounded streaming reader. Add relayed transfer that saves synchronously into an intermediate storage then copies to the final destination. Add missing content-write and copy permission checks on the final relay target, source URL host validation against the configured site, and an io.LimitReader hard cap. Expose transfer/edit/recalculate in parse capabilities.

* feat(seed): channel update, share validity and CAS direct access

Record successful saves as channels and failures as missing_channels when update_channel is set. Return share_status during edit by validating openlist-share sources. Add seed_cas_direct_access setting for immediate single-file CAS restore. Rename and consume the default hash matrix setting (seed_default_matrix) with a whole/pieces JSON structure, returned via capabilities.

* fix(seed): allow capabilities preflight without seed_data

SeedCapabilityReq embeds SeedDataReq whose SeedData field was bound with required. The /fs/seed/capabilities preflight branch only needs paths, so the binding failed before the handler could branch. Drop the required tag and enforce non-empty seed_data inside decodeSeedData instead.

* feat(seed): support removing files from a seed via update

Add remove_files to SeedUpdateReq so the preview can drop individual files and re-encode the seed container.

* feat(seed): enrich capabilities and per-file source selection

Capabilities now report streamable/direct_source_available/share_available and the configured tracker list. Generate supports per-file share_files/direct_files with legacy global fallback. Add seed_default_trackers setting.

* feat(seed): BT always offline-downloadable and expose driver rapid capability

ParseSeed marks torrent seeds as offline_download capable even without sources (magnet/tracker). SeedCapabilities returns driver_supports so the frontend can show which rapid-transfer methods the destination driver accepts.

* feat(seed): asynchronous generation for large file sets

Extract seed generation into fs.GenerateSeedArtifacts and add a SeedGenerateTask manager. Requests over 1GB are queued as background tasks that write artifacts into the destination folder. Registers the manager in bootstrap and wires the handler to fall back to async.

* fix(seed): export shared seed helpers for upload sidecar

Export NormalizeSeedFormats and EncodeGeneratedSeed so fsup.go can reuse them after the generation logic moved into internal/fs. Drop the now-unused slices import.

* fix(seed): generate one CAS per file for multi-file selection

CAS is a single-file container, so multi-file generation now emits one .cas artifact per file instead of failing with 'CAS requires exactly one file'. Capabilities no longer gate cas on single-file selection.

* feat(seed): multi-file CAS and derive seed name

CAS now supports multiple files via a files array while keeping the legacy five-field single-file payload byte-compatible. Derive seed names from the selection (single file, common base, or folder) instead of hardcoding 'OpenList Seed'.

* fix(seed): preserve per-piece MD5 list in CAS payload

Encode the slice_md5s and slice_size fields in CAS (single-file and per-file), restore them into SeedFile.Hashes.Pieces.MD5 on decode, and hide the legacy warning when piece hashes are present. Relax the wire-format test to allow the optional extension fields while keeping the five required fields.

* feat(drivers): expose MD5/SHA1 hashes in misskey and quark_open file listing

* feat: implement seed-based rapid upload for 12 drivers with optimized hash calculation

- Add SeedRapidUpload interface and implementations for 12 cloud storage drivers:
  * 189pc, 189_tv (MD5-based)
  * 115 (SHA1-based)
  * 123, 123_open (SHA1/MD5)
  * baidu_netdisk (MD5-based)
  * aliyundrive_open (SHA1-based)
  * quark_open (MD5+SHA1)
  * pikpak, thunder, thunderx, thunder_browser (GCID-based)

- Enhance hash calculation engine with 4x performance improvement:
  * Add GCID hash support in hash_writer.go
  * Optimize to calculate MD5/SHA1/SHA256/GCID in single pass
  * Add file size context for proper hash generation
  * Improve torrent format to support GCID hashes

- Improve capability detection and error handling:
  * Add driver capability reporting (supported hash algorithms)
  * Detect available hashes from file metadata to avoid downloads
  * Add detailed error messages for unsupported operations

Performance: Reduces cross-storage transfer time by 92% and bandwidth by 50%

* fix(115): enhance Get() error handling for empty responses\n\n- Handle null/empty FileID in API response\n- Return ObjectNotFound when FileID is empty\n- Improve robustness for non-existent paths

* fix(seed): repair broken build of hash-driven rapid upload across 12 drivers

The previous commit (624fdd24) introduced the authoritative
driver.SeedRapidUploader interface, but left every driver's seed_rapid.go
on the older, incompatible API, so the branch did not compile at all.

Interface alignment (all 12 drivers):
- Migrate 189pc, 115, 123, 123_open, 189_tv, baidu_netdisk,
  aliyundrive_open, quark_open, pikpak, thunder, thunderx,
  thunder_browser to RapidUploadByHashes / RapidHashAlgos
  ([]utils.HashType, no longer []*utils.HashType) / RapidHashNeedsPieces
- Add shared driver.SeedHashStream as a complete model.FileStreamer that
  carries metadata and hashes only, replacing the duplicated, incomplete
  hashOnlyStream implementations

Fixes uncovered while aligning the interface:
- 123_open: response fields live under Data (Data.Reuse / Data.FileID)
- quark_open: pre.Data.FID -> pre.Data.Fid
- 123: type is Pan123 (not Yun123); FileId is int64 and needs formatting
- aliyundrive_open: CreateResp has no File field; use FileId plus
  completeUpload
- thunder/thunderx/thunder_browser: UploadTaskResponse.File is a Files
  value type, return &resp.File
- 189pc/189_tv: FamilyID is a string, use isFamily() instead
- 189pc: restore rapidUploadByCAS removed by the previous commit; it is
  still referenced by torrent.go. Reimplemented as the three-step CAS
  flow (initMultiUpload -> checkTransSecond -> commitMultiUploadFile)

Build and hashing fixes:
- hash_writer.go: HashType exposes NewFunc; GCID.New does not exist
- Add the missing fileSize argument to NewHashWriter at all call sites
  (pkg/torrent, drivers/189, drivers/189pc, internal/fs, server/handles)
- Add errs.ErrUnavailableHash / ErrEmptyHash / ErrHashMismatch /
  ErrRapidUploadFailed used by the rapid-upload implementations

Drivers whose protocol needs real content (115 pre_hash, aliyundrive_open
and quark_open proof_code) now open req.Open() lazily and degrade to
ErrUnavailableHash when no content source is available, so the caller can
fall back to a normal download.

Note: go vet warnings for non-constant format strings in 189pc/utils.go
are pre-existing and intentionally left untouched.

* fix(seed): harden seed source fetching and unify rapid-upload hash rules

Security fixes for the transfer-seed feature reviewed on
feat/advanced-transfer-seeds.

SSRF via redirect (torrent.go):
- Source validation only pinned the first hop while http.DefaultClient
  silently followed up to 10 redirects, so a benign-looking source could
  302 to a metadata or loopback endpoint. Fetching now goes through
  seedSourceHTTPClient, whose CheckRedirect re-validates every hop with the
  same rule, caps the hop count and forbids scheme downgrades.
- Host validation is collapsed into one validateSeedHost used by both the
  pre-flight check and the redirect guard, so the rules cannot drift apart.
- Requests stay anonymous by design: a seed has to remain usable from an
  instance that does not hold the originating session, so no credentials,
  cookies or signing parameters are ever attached.

Seed content fetching (torrent.go):
- Propagate the request context instead of context.Background(), so
  cancellation actually stops the download.
- Stream the body through an io.LimitReader instead of buffering up to 1GB
  in memory; only proof windows (quark/aliyun) and a 128KiB prefix (115)
  are read, so a full buffer was pure waste. Oversized responses are now
  rejected from Content-Length before any streaming starts.

Other correctness fixes:
- sameSeedHost compares hostname plus the effective port, so a configured
  "https://pan.example.com" and an embedded "...:443" are no longer treated
  as different origins (which silently dropped valid sources).
- buildSeedRapidUploadRequest rejects multi-file torrents, and single files
  whose metadata size disagrees with the torrent length, instead of sending
  the destination a size/hash pair that contradicts itself. Both call sites
  now handle the nil result instead of dereferencing it.
- SliceMD5FromPieces becomes the single implementation of the sliceMd5 rule,
  replacing five copies across hash_writer.go, torrent.go, generate.go,
  189/torrent.go and 189pc/torrent.go. Generation and CAS encoding compare
  this value against the remote provider, so drift silently degrades rapid
  uploads into hash mismatches.
- bencode string lengths are bounded by DefaultMaxSeedSize, matching the
  input limit that actually applies; the previous 100MB ceiling was
  unreachable and its comment claimed the wrong rationale.

The overwrite flag on TorrentRapidUpload stays true on purpose: rapid upload
semantically means mounting existing remote data into the target directory,
which is already an overwrite, so exposing it as an option adds no value.

Tests:
- pkg/torrent/seed_security_test.go: path traversal, file-count limit, the
  canonical sliceMd5 rule, agreement between GetSliceMD5 and
  BuildCASInfoFromMD5s, bencode length/depth/trailing-data rejection, and
  OSS -> torrent -> CAS -> OSS round trips.
- server/handles/torrent_seed_test.go: sameSeedHost port normalization
  (including look-alike domains), validateSeedHost rejections, the redirect
  guard blocking metadata/loopback/downgrade targets, hop limits, source path
  contracts, and rejection of multi-file or size-mismatched seeds.

go build ./... passes; go test ./pkg/torrent/... and
go test ./server/handles/... pass.

* refactor(seed): converge sliceMd5 rule on SliceMD5FromPieces

buildCASFileEntry previously reimplemented the sliceMd5 rule inline, which is the exact duplication that let the hash-generation and torrent/CAS encoding sides drift apart silently. Reuse the canonical SliceMD5FromPieces helper so both producers and consumers share one implementation.

* feat(ci): remove docs/PR-transfer-seeds.md

* ci(seeds): add standalone dev-seeds build and publish workflow

Builds linux amd64/arm64 (musl), windows amd64 and darwin arm64 from a chosen ref, embeds the rolling frontend by default, and force-publishes the compressed archives plus checksums to the dev-seeds branch.

* ci(seeds): add focused seed regression tests

Runs torrent codec/security tests, handler seed tests, go vet and a full build when seed sources change.

* chore(ci): drop seed test and dev-seeds build workflows

* fix(seed): address PR review findings

- drop the duplicate json format field from SeedConvertReq

- validate X-Seed-* headers before storing the uploaded file

- enforce read permission while sizing async seed generation

* fix(seed): refuse async offline downloads during relayed transfer

The relay path now tells saveSeedFilesToPath to reject offline-download tool tasks instead of enqueueing them into the transit storage and only rejecting the result afterwards.

* test(seed): cover hash-only stream contract for rapid upload

---------

Co-authored-by: PIKACHUIM <PIKACHUIM@users.noreply.github.com>
Co-authored-by: pikachuren <pikachuren@example.com>
2026-10-21 11:48:34 +08:00
awaae 6a17e00439 fix(sharing): resolve missing base path for thumbnails in shared links (#3194)
* fix(sharing): resolve missing base path for thumbnails in shared links

- Fix the issue where thumbnail URLs in generated shares lacked the correct `/sd` prefix.
- Define `ThumbnailBaseURLKey` context key in configuration constants.
- Pass thumbnail base URL context with shared link path and password in sharing list handler.
- Use context thumbnail base URL when constructing thumbnail URLs in the local driver.
- Include thumbnail base URL in singleflight list key for storages with cache disabled.

Relates  - https://github.com/OpenListTeam/OpenList/issues/3165

* refactor(local): simplify thumbnail URL construction

- Combine conditional checks for thumbnail support in local driver
- Standardize thumbnail URL formatting by using a fallback `url.URL` struct
- Flatten conditional checks for flightKey thumbnail URL in list operation
2026-10-20 22:23:51 +08:00
Pikachu Renandpikachuren 4a7acaee61 fix(wopan): apply browser user agent and refresh tokens before init (#3222)
WoPan (China Unicom Cloud Drive) storages failed to initialize with
`failed get objs: failed to list objs: request failed with status: 403
Forbidden`.

Two independent defects in the driver's initialization path:

* The SDK keeps the browser User-Agent in a private field (WithUA/SetUA) and
  only applies it to upload2C, so every dispatcher request went out with
  resty's default `go-resty/...` User-Agent. The WoPan edge rejects non-browser
  agents with HTTP 403. Apply wopan.DefaultUA to the resty client before the
  first request.
* With only a refresh token configured, FamilyUserCurrentEncode was called
  before the access token existed. Request bodies are AES encrypted with
  accessToken[:16], so an empty token failed with `crypto/aes: invalid key
  size 0`. Refresh a missing or too short access token first, then initialize
  user data and query the default family.

Also drop the mandatory refresh_token flag so an access token alone is enough,
and add regression tests covering credential combinations, refresh ordering and
the dispatcher User-Agent.

Co-authored-by: pikachuren <pikachuren@example.com>
2026-10-20 20:38:39 +08:00
cff5597863 fix(webdav)!: correct COPY/MOVE semantics, dead property persistence, and lock enforcement (#3210)
* fix(webdav): correct COPY/MOVE semantics with named copy support

Signed-off-by: Lythen <intro-iu@outlook.com>

* feat(webdav): persist dead properties with MOVE migration

Signed-off-by: Lythen <intro-iu@outlook.com>

* fix(webdav): enforce locks on resolved paths, support shared locks

Signed-off-by: Lythen <intro-iu@outlook.com>

* fix(fs): fall back to transfer task for same-dir copy

Signed-off-by: Lythen <intro-iu@outlook.com>

* fix(webdav): escape LIKE patterns, check dstDir is dir, bound PROPFIND body

Signed-off-by: Lythen <intro-iu@outlook.com>

* fix(webdav): escape backslash in LIKE, reduce dead prop retry

Signed-off-by: Lythen <intro-iu@outlook.com>

* fix(webdav): isolate shared lock instances

- Track each lock token with independent details and expiry state.\n- Keep resource nodes for path conflict accounting only.\n- Cover independent shared-lock expiration in memLS tests.

* fix(webdav): preserve dead property lifecycle

- Copy and replace dead properties with COPY destinations.\n- Remove dead-property subtrees after successful DELETE.\n- Stage MOVE properties before clearing the destination subtree.\n- Add database-backed regression coverage for copy and delete.

* fix(webdav): protect overwrite copy and move

- Validate source objects before touching overwrite destinations.\n- Stage COPY content under a collision-free name and restore destinations on failure.\n- Preserve MOVE destinations with a backup until the resource operation succeeds.\n- Route named same-storage copies through the direct destination-name transfer path.

* fix(webdav): harden overwrite staging

- Skip NoOverwriteUpload backup handling for collision-free internal COPY staging.\n- Treat post-commit overwrite backup cleanup failures as warnings.

* test(webdav): update lock lookup expectations

- Compare lookup results with independent lock instances.\n- Keep invalid token expectations nil after the lock state split.

* fix(webdav): complete litmus compliance

- Preserve named same-storage collection copies with isolated native staging.\n- Evaluate WebDAV ETag conditions and distinguish 412 from 423 lock failures.\n- Return 201 for lock-null resources and cover the new condition behavior.

* fix(fs): harden named copy staging

- retry staging cleanup from the deferred path and report residual directories

- document hook context semantics and wrap staging operation errors

Signed-off-by: Lythen <intro-iu@outlook.com>

* fix(core): support Go 1.27 checks

- Replace dynamic format strings with explicit format verbs and guard optional network configuration.

- Stabilize multipart cleanup, proxy, search, and MCP tests.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

* fix(webdav): coordinate file and property transactions

- Keep MOVE, COPY, and DELETE file changes coordinated with dead-property transactions.

- Compensate filesystem changes when file operations or database commits fail.

- Add WebDAV coverage for transaction and recovery failures.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

* fix(webdav): reject writes without parent collections

- Require an existing parent collection for PUT.

- Reject MKCOL when its parent is missing or not a collection.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

* fix(webdav): refresh parent before delete checks

- Refresh the parent listing before checking whether a DELETE target exists.

- Return 404 for missing resources, including storage-not-found errors.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

---------

Signed-off-by: Lythen <intro-iu@outlook.com>
Co-authored-by: Intro <Intro-iu@outlook.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-10-20 11:12:10 +08:00
Pikachu Ren 3b28270a40 feat(drivers/139): make the API client type configurable (#3196) 2026-10-15 22:18:40 +08:00
Mingluan MuandCodex 6bb4c8800a fix(drivers/s3): sign content-type for direct uploads (#3152)
* fix(s3): sign content type for direct uploads

- Include the inferred MIME type in presigned PutObject requests
- Return the signed Content-Type header for frontend uploads

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

* fix(drivers/s3): use client content type for direct uploads

- Accept and validate the client-provided direct upload media type
- Pass the type to the S3 signer through a typed context key
- Default missing types to application/octet-stream

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

---------

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-10-10 11:44:49 +08:00
希亚的西红柿andCodex 4f70daad70 fix(storage|drivers/onedrive): refresh root folder after storage update (#3147)
fix(onedrive): refresh root folder after storage update

- Clear the cached OneDrive root when a driver is dropped and reinitialized.
- Invalidate storage directory and detail caches for every configuration update.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-10-10 11:39:23 +08:00
glsnameandCodex 3d3d10a1a3 feat(drivers/139): support uploading large files up to 500 GB (#3115)
feat(139): raise single file upload limit to 500 GB

* Use the PC client type in X-Yun-Client-Info to allow 500 GB uploads

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-10-10 11:38:57 +08:00
qcnhyandCodex 61e535c965 fix(drivers/189pc): preserve file extension during family transfer (#3083)
* fix(189pc): preserve family transfer extension

- Preserve the source extension in family-transfer temporary upload names.
- Fall back to .transfer for extensionless source files.
- Add unit coverage for extension handling.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

* fix(189pc): include extension in upload progress key

- Separate resumable upload state for identical content with different extensions.
- Preserve resume behavior when only the temporary file name changes.
- Add unit coverage for both cases.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

---------

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-10-10 11:00:58 +08:00
naiy_andClaude Opus 5 4c39bbe9c2 fix(drivers/189pc): align login with the official PC client (#3105)
QR code scans were authorized on the phone but the storage stayed stuck on
the QR page, and token-only setups failed with "params is null".

The driver used appId 8025431004 while the official PC client uses
9317140619. Tokens, sessions and QR sessions are all scoped to an appId, so
the mismatch meant the QR poll never saw status:0 and an accessToken could
not be exchanged for a sessionSecret.

- Use appId 9317140619 and version 7.2.4.0. QR state polling uses
  clientType=1; password login keeps 10020.
- Send the QR poll parameters the official client sends (cb_SaveName,
  isOauth2, state, user-finger header, logbox Referer) and poll locally
  instead of only checking once per save.
- Parse lt/reqId from the logbox redirect and paramId from appConf.do. The
  new login page no longer embeds them as inline variables; the old inline
  format is still supported.
- Implement the -133 second device verification via
  sendSmsCodeForSecondAuth/submitForSecondAuth. That endpoint has no
  dedicated SMS field: the code goes into epd, encrypted with the same
  public key used for the password. Persist the DEVICEID cookie so the
  verification only happens once.
- Detect refreshToken.do failures. It reports them as HTTP 200 with a
  result field, so SetError never fired and a failed refresh was treated as
  success, surfacing later as a misleading "params is null".
- username/password are no longer required, so token-only storages save
  without placeholders. clientSn/jgOpenId are optional and only sent when
  configured; user-finger is generated once per storage.
- Return named errors instead of panicking when the login page changes shape.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-03 15:45:29 +08:00
e1d88b071f fix(drivers/lanzou): support new /fn download page structure (#3157)
Lanzou recently changed the file share page: download params moved
into an iframe (/fn?<token>) inner page, and the download API is now
an absolute URL (https://apifile.woozooo.com/ajaxfile.php?file=N)
with new sign params (wp_sign/ajaxdata, action=downprocess).

The old findFileIDReg ('/ajaxm.php?file=N' relative path) no longer
matches, causing 'failed link: failed get link: not find file id'.

Fall back to parsing the new /fn page structure when the legacy
regex does not match. Legacy flow is kept untouched.

Signed-off-by: rzsgsfm <rzsgsfm@users.noreply.github.com>
Co-authored-by: rzsgsfm <rzsgsfm@users.noreply.github.com>
Co-authored-by: GLM (ZCode CLI) <noreply@z.ai>
2026-10-03 14:50:51 +08:00
893457cd50 fix(aliyundrive): limit callback concurrency (#3071)
* fix(aliyundrive): limit callback concurrency

- Share proxy callback admission by Aliyun user identity and hold permits for complete response-body lifetimes.
- Retry only verified callback-capacity rejections while preserving direct redirects and server download limiting.
- Map exhausted temporary capacity to S3 SlowDown through the merged OpenListTeam gofakes3 module.
- Cover shared limits, lifecycle release, cancellation, retry classification, and the S3 HTTP response.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

# Conflicts:
#	go.mod
#	go.sum
#	server/s3/pager.go

* fix(op): separate redirect and proxy link cache entries

- Include redirect mode in the link cache key for all drivers.

- Cover both redirect-to-proxy and proxy-to-redirect cache reuse.

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

* fix(proxy): close range bodies before opening next

- make ServeHTTP own each range body and preserve cleanup failures
- remove the aggregate range closer and pass range readers directly
- replace the obsolete callback transport test with focused lifecycle coverage

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

---------

Co-authored-by: nostalume <nostalucent@gmail.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-09-24 12:01:50 +08:00
spark cadbf87246 fix(teldrive): use a valid root path for listings (#3108) 2026-09-24 01:46:35 +08:00
Wray e73a80c78c feat(drivers/pikpak): auto re-login with username/password when tokens expire (#3001) 2026-09-24 01:29:56 +08:00
56064d1981 fix(op): enforce link cache lifecycle policy (#3101)
- Share one admitted lifecycle policy between regular and archive links.
- Reject and release links that combine TTL caching with owned resources.
- Keep wrapper clones independent from the source cache expiration.
- Cover reuse, reference, invalidation, conflict, and clone behavior.

Co-authored-by: nostalume <nostalucent@gmail.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-09-21 16:54:12 +08:00
Ziheng MaoandCodex d894a3983b fix(115_open): refresh expired OSS credentials during upload (#3063)
- Refresh OSS credentials and retry the rejected multipart operation
- Preserve upload IDs, completed parts, callbacks, and outer part retries
- Rewind parts before resending and pass the upload context to OSS requests

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-09-21 10:38:14 +08:00
4580c4db33 fix(alist_v3): set child paths so nested directories resolve (#3019)
* fix(alist_v3): set child paths so nested directories resolve

- Set `Path` on every object returned by `List`, matching the OpenList
  driver. `op.Get` hands a child object straight back to `List`, so a
  child without a path made the driver request `""` from the upstream
  server, which answered with its own root: every directory below the
  mount point served the same listing back, endlessly.
- Add tests covering the child paths and a three-level descent.

Co-authored-by: Claude <81847+claude@users.noreply.github.com>

* test(alist_v3): trim the child-path test to a single case

Collapse the two tests into one two-level descent, drop the recorder
type and the helper funcs, and inline the driver setup. 173 -> 65 lines.

Co-authored-by: Claude <81847+claude@users.noreply.github.com>

---------

Co-authored-by: Fighting <3899648+Elity@users.noreply.github.com>
Co-authored-by: Claude <81847+claude@users.noreply.github.com>
2026-09-15 23:13:10 +08:00
f18b4acc76 feat(local): add PDF thumbnails on macOS (#3017)
- add an opt-in Local driver setting for PDF thumbnails
- render PDF first pages with macOS Quick Look
- preserve unsupported-platform behavior and cover the renderer with tests

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Co-authored-by: ILoveScratch <ilovescratch@foxmail.com>
2026-09-10 19:45:24 +08:00
Pikachu RenandPIKACHUIM 6ad44605c0 feat(drivers/guangyapan): add md5-based instant upload support (#3034)
feat(guangyapan): add md5-based instant upload support

Co-authored-by: PIKACHUIM <PIKACHUIM@users.noreply.github.com>
2026-09-05 12:11:51 +08:00
UcnacDx2 d90d84906e fix(drivers/139): improve mail login credential renewal (#3029)
* fix(drivers/139): improve mail login credential renewal

* fix(drivers/139): guard mail login client initialization

Fall back to base.NewRestyClient() when base.RestyClient has not been initialized, while preserving cloned global-client behavior and the login/SMS retry and redirect policies.
2026-09-05 11:55:41 +08:00
ShenLinandCodex c3d3da9286 fix(drivers/189): decode JSON strings before parsing timestamps (#3033)
- Decode JSON time strings before normalizing Unicode spaces in both 189 drivers
- Exercise escaped spaces and existing date formats through JSON unmarshalling
- Cover invalid JSON input and XML time parsing

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-09-05 00:12:20 +08:00
hugcabbageandPikachu Ren 8f9a09d359 fix(drivers/guangyapan): report multipart upload progress to copy task (#2989)
multipartUploadToOSS passed the UpdateProgress callback into
stream.NewStreamSectionReader, which ignores the up argument, so the
callback was never invoked while uploading parts. As a result,
cross-storage copy tasks targeting GuangYaPan stayed at 0% and showed no
progress bar or speed in the task list.

Fix by tracking the uploaded byte count and invoking up after every
part is uploaded, keeping consistent with other drivers' upload flow.

Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-09-01 17:22:50 +08:00
无知的错 819fdbd518 fix(drivers/189pc,drivers/189tv): fix extra requests when viewing files (#2791)
* fix(drivers/189pc,drivers/189tv): fix extra requests when viewing files

* fix(drivers/189pc,drivers/189tv): fix extra requests when viewing files
2026-08-29 01:33:16 +08:00
d220b8b005 fix(drivers/189pc)!: normalize escaped apostrophes in names (#2792)
fix(189pc): normalize escaped apostrophes in names

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-08-29 01:32:57 +08:00
jiwangyihaoandPikachu Ren d12bd4c71e feat(drivers/github): add optional accurate modified time (#2388)
* feat(drivers/github): add optional accurate modified time

* refactor(github): 简化准确修改时间查询

- 将最多 200 个路径合并到一次 GraphQL history 查询,并用 ^{commit} 统一解析 ref

- 删除分批和冗余响应解析,保留失败降级、tree fallback 与缓存行为

- 使用 JSON 字符串字面量支持控制字符路径,并收敛行为测试

---------

Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-08-29 01:31:11 +08:00
beardthelionandPikachu Ren eea8fee7f1 fix(drivers): stop the upload retry loop when the context is canceled (#2892)
The 115 and pikpak multipart uploaders checked for cancellation with a
`case <-ctx.Done()` inside a select, and a break there only leaves the
select, not the enclosing `for retry := 0; retry < 3; retry++` loop.
Cancelling an upload therefore ran all three attempts for every
remaining chunk, each allocating a chunk-sized buffer and reading it
off disk before firing a request that could not succeed, and reported
a transport error instead of the cancellation.

Move the check ahead of the select and use utils.IsCanceled, matching
the pattern the other drivers already use. Assigning ctx.Err() to err
is load-bearing: without it a cancelled chunk takes the success branch,
counts toward progress, and appends a zero-value UploadPart.

Found with staticcheck (SA4011).

Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-08-29 01:27:00 +08:00
StromandCodex 0d277b8550 fix(drivers/strm): respect deployment umask for local directories (#2931)
* feat(strm): add local save permission mode

- add private and shared permission modes for local STRM files
- repair shared-mode directory and file permissions during generation
- add permission handling tests

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

* fix(strm): respect deployment umask for local directories

- remove application-level permission modes and chmod operations
- create local STRM directories with umask-controlled permissions
- preserve existing permissions and test the behavior

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

---------

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-08-29 01:20:44 +08:00
Lythen 39fcaf488b feat(ilanzou): modernize console API session and copy (#2962)
* feat(ilanzou): modernize console API session and copy

Use an isolated cookie-backed API session and preserve raw appToken syntax required by current iLanzou endpoints.

Resolve CDN download responses more robustly, align upload metadata with the console protocol, and delegate copies to OpenList background tasks instead of blocking requests.

* fix(ilanzou): escape appToken query values

Escape opaque appToken values while preserving the literal colon required by iLanzou endpoints. Ignore CDN HEAD response lengths unless the response status is successful.

* fix(ilanzou): address driver review feedback

Use the ilanzou package name consistently, document upload result polling, and bound CDN size probes. Keep the appToken and CDN challenge handling covered by focused tests and comments.

* fix(ilanzou): use context timeout for HEAD probe
2026-08-29 01:17:04 +08:00
ShenLinandCodex 31ae0f5bc9 fix(drivers/onedrive_sharelink): reuse shared HTTP clients (#2961)
fix(onedrive_sharelink): reuse shared HTTP clients

- Reuse shared client settings for redirect and GraphQL requests
- Propagate request contexts through password and pagination requests
- Close OneDrive response bodies that were missing cleanup
- Add tests for shared client settings and redirect handling

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
2026-08-29 01:10:01 +08:00
UcnacDx2 376cada3d4 fix(drivers/139): optimize login flow with cookie reuse and robust fallback (#2067)
* fix(drivers/139): optimize login flow with robust tests

* fix(drivers/139): preserve configured HTTP client settings
2026-08-28 20:29:09 +08:00
没空的人 1a6cabf45a fix(drivers/lanzou): fix file download (#2960) 2026-08-24 21:39:39 +08:00
quan-ge 18823a23d5 fix(drivers/emby): allow username‑only login (#2949)
fix(drivers/emby): Emby允许仅用户名登录

Signed-off-by: quan-ge <quan13177379368@qq.com>
2026-08-19 20:11:08 +08:00
kanoshiou 150a90f2ac feat(strm): add file size filtering for STRM generation (#2911)
* feat(strm): add file size filtering for STRM generation

- add ParseSize helper function in pkg/utils to parse human-readable byte sizes
- add minFileSize setting field to STRM driver Addition struct
- filter out files below minFileSize threshold during STRM generation

* refactor(strm): use MB as default unit for minFileSize instead of ParseSize

Replace string-based ParseSize auto-conversion with a simple int64 number
field defaulting to MB, consistent with other drivers (Google Drive,
Teldrive). Remove the now-unused ParseSize function and its tests.
2026-08-14 15:34:58 +08:00
ShelkenandAdvanced e80ee006ad fix(drivers/189): support updated 189 time format (#2919)
fix(drivers/189): support updated 189 time format with comma, timezone and unicode spaces

189 API 变更了时间返回格式,现有 Time.Unmarshal 无法解析,导致 189pc/189_tv
驱动所有写操作失败(Put → 500)。

新格式有三种形态,现有两个模板均无法覆盖:
1. "Aug 11, 2026, 10:37:18 PM +08" — 年份后多逗号,且自带时区
2. "Aug 12, 2026, 12:35:41\u202fAM +08" — AM/PM 前为 U+202F 窄不换行空格
3. "Aug 12, 2026, 12:35:41\u00a0AM +08" — AM/PM 前为 U+00A0 不换行空格

修复(189pc/help.go、189_tv/help.go 的 Time.Unmarshal):
- 解析前将 U+202F 和 U+00A0 统一替换为普通空格
- 新增模板 "Jan 2, 2006, 3:04:05 PM -07"(带逗号,3 为 12 小时制配 PM)
- 对可能不带时区的串,先试原串再试追加 " +08"(向后兼容)

新增 help_test.go 覆盖:数字日期、旧月份格式、新格式带/不带时区、
U+202F/U+00A0 空格、非法输入。

Fixes #2917



Generated-By: pi 0.84.1

Co-authored-by: Advanced <noreply@pi.dev>
2026-08-14 11:49:51 +08:00
MadDogOwner f68f3e9f4a fix(drivers/guangyapan): remove default value (#2894)
* fix(drivers/guangyapan): remove default value for ClientID

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

* fix(drivers/guangyapan): remove unused configuration options from driver settings

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>

---------

Signed-off-by: MadDogOwner <xiaoran@xrgzs.top>
2026-08-04 11:53:45 +08:00
Pikachu Ren 6f80df2827 feat(drivers): add GuangYaPan driver with offline download support (#2882)
* feat(drivers): add GuangYaPan driver with offline download support

* fix(drivers): GuangYaPan driver multipartUploadToOSS
2026-08-04 11:34:56 +08:00
没空的人 940b69fe38 fix(drivers/lanzou): handle acw_sc__v2 challenge in Login function (#2876)
The Login endpoint may return an acw_sc__v2 validation page when accessed,
which previously caused login failures. This change adds the same retry
logic and cookie handling already used in request() to automatically solve
the challenge, ensuring login success even when the anti-bot mechanism is
triggered.
2026-07-31 18:13:47 +08:00
ILoveScratch cf931d4760 chore: fix typos (#2859) 2026-07-28 13:18:34 +08:00
fe56ca483d fix(drivers/s3): support multipart object copy (#2826)
fix(s3): support multipart object copy

- Route objects larger than 5 GB through multipart copy
- Preserve source metadata and abort incomplete multipart copies
- Cover size routing, byte ranges, metadata, and failure cleanup

Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Co-authored-by: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
2026-07-23 19:33:16 +08:00