1
0
mirror of https://github.com/abraunegg/onedrive.git synced 2026-10-29 04:15:11 +03:00

72 Commits

Author SHA1 Message Date
abraunegg
245bbaab36 Clarify Microsoft object sync limits (#3924)
Clarify Microsoft object sync limits
2026-10-24 11:42:13 +11:00
mali
86272b1ba1 Escape regex metacharacters in 'skip_file' and 'skip_dir' patterns (#3922)
* Escape regex metacharacters in `skip_file` and `skip_dir` patterns

  Previously, `wild2regex()` only escaped `.`, `+`, `/`, `(` and `)`. The characters `[`, `]`, `{`, `}`, `^` and `$` are valid in OneDrive file and directory names but were passed directly to the regex engine.

  As a result, a rule such as `Photos [2023]` was interpreted as a character class, incorrectly matching `Photos 2` instead of the intended directory. Similarly, patterns such as `~$*` failed to match correctly, while unmatched `[` or `{` characters could trigger a `RegexException` during configuration processing.

  Update `wild2regex()` to escape these characters correctly while preserving existing `*` and `?` wildcard behaviour.

  Also correct sync-root-relative path handling for `skip_file` exclusions so that explicitly anchored file rules are consistently evaluated during local synchronisation.

* Expand E2E filtering validation in TC0011 and TC0012

  Significantly expand the existing E2E filtering testcases to validate literal-character matching, wildcard behaviour, path anchoring and configuration safety across real OneDrive synchronisation operations.

  - **TC0011 (`skip_file`):** Expand to 32 scenarios covering literal regex metacharacters, unmatched brackets and braces, wildcard combinations, case-insensitive matching, filename and sync-root-anchored path exclusions, configuration-change resync requirements, remote-content preservation and invalid-rule rejection.
  - **TC0012 (`skip_dir`):** Expand to 38 scenarios covering literal regex metacharacters, strict and non-strict directory matching, sync-root-anchored paths, multi-component directory exclusions, wildcard combinations, configuration-change resync requirements, remote-content preservation and invalid-rule rejection.
  - Add `sync_list` interaction scenarios that verify valid inclusion rules are not incorrectly classified as shadowed, while genuinely conflicting inclusion rules are rejected with explicit diagnostics.
  - Validate filtering behaviour in both upload and download directions using independent client instances and remote-content verification.
  - Update the configuration, usage and E2E documentation to reflect the corrected matching behaviour and expanded regression coverage.

  The expanded filtering suites have been validated successfully against OneDrive Personal, Personal with a 15-character drive ID, OneDrive for Business and SharePoint configurations.

  The filtering E2E coverage now comprises **70 scenarios per configuration**, with all 280 scenario executions passing.

Co-authored-by: abraunegg <alex.braunegg@gmail.com>
2026-10-24 06:46:07 +11:00
abraunegg
2bf2f9f4d1 Clarify systemd usage (#3915)
Clarify systemd usage
2026-10-16 15:27:11 +11:00
abraunegg
7c9a1c8ebf Update Microsoft Intune validation (#3910)
Update Microsoft Intune validation
2026-10-13 07:28:26 +11:00
abraunegg
47c9a3cabb Update sponsorship details (#3907)
Update sponsorship details
2026-10-12 06:14:07 +11:00
abraunegg
98752fd185 Align documentation, CLI help and shell completions with current client behaviour (#3903)
Align the user-facing documentation, CLI help, sample configuration, man page and shell completion definitions with the behaviour currently implemented in `master`.

This is a documentation and interface-consistency update only. It does not change synchronisation behaviour.

## Changes

- Add `monitor_status` to the supplied example `config`, reflecting the existing default-enabled monitor runtime status functionality.
- Update `monitor_fullscan_frequency` wording to consistently describe the **online full-scan true-up** cadence rather than implying a local filesystem scan.
- Update the `--display-sync-status` summary text in:
  - application CLI help
  - `docs/usage.md`
  - the man page

  The wording now reflects the current read-only, bidirectional synchronisation-state assessment rather than the previous remote-only pending-change behaviour.
- Update HTTP 429 documentation to reflect current logging behaviour:
  - successfully handled throttling is quiet during normal operation;
  - detailed 429 handling and retry information remains available in verbose/debug modes;
  - genuine unrecoverable failures continue to be reported.
- Add the missing `--disable-time-check` option to Bash, Fish and Zsh shell completions.
- Correct several shell-completion descriptions so they match the current CLI semantics, including:
  - `--monitor-fullscan-frequency`
  - `--get-file-link`
  - `--get-sharepoint-drive-id`

## Validation

The supported command-line option set was compared directly against the options implemented in `src/config.d`.

After these changes:

- Bash completion exposes the complete current long-option set.
- Fish completion exposes the complete current long-option set.
- Zsh completion exposes the complete current long-option set.
- All three completion implementations contain the same 68 supported long CLI options as the application.
- The man page contains the complete current CLI option set.
- Duplicate stale `--display-sync-status` wording has been removed.
- Documentation describing HTTP 429 handling now matches the behaviour implemented in `master`.
2026-10-10 20:26:54 +11:00
abraunegg
6415cb4e56 Add monitor runtime status JSON for external observability (#3896)
This PR adds a new machine-readable runtime status capability for long-running `--monitor` operation.

When the client is running in monitor mode, it now maintains:

```text
<configuration directory>/monitor-status.json
```

alongside the existing configuration and application state files.

The status file provides a lightweight external view of the running monitor without requiring log parsing, additional Microsoft Graph requests, database inspection or execution of `--display-sync-status`.

### Runtime information exposed

The JSON status includes:

- application PID and per-process instance identifier
- configured operating mode
- configured monitor interval
- current monitor state
- application runtime
- monitor loop count
- current cycle start time
- last completed loop time
- whether the current process has completed its first successful synchronisation
- successful synchronisation cycle count
- last successful synchronisation time
- result and duration of the most recent cycle
- failed download count
- failed upload count
- failed Recycle Bin operation count
- Microsoft OneDrive service reachability
- current system-time validation state

All timestamps are emitted in UTC using an ISO-8601/RFC-3339-style representation so that monitoring systems can consume them consistently and convert them to local time when presenting them to users.

### Behaviour

Monitor runtime status is enabled by default:

```text
monitor_status = "true"
```

and may be disabled explicitly:

```text
monitor_status = "false"
```

The status file is:

- written with restrictive permissions
- updated using temporary-file + atomic rename semantics
- updated only at meaningful monitor lifecycle points rather than for individual file operations or notification events
- removed during a clean application shutdown

An abnormal termination such as `SIGKILL` or system power loss may leave the last status snapshot behind. A new monitor process immediately replaces any previous state with a new process instance and resets initial synchronisation readiness.

Status publication is deliberately non-fatal. Failure to write the runtime status file does not alter or interrupt normal synchronisation behaviour.

### Purpose

This provides a stable visibility layer for external tooling such as:

- Docker / Podman health and readiness checks
- systemd monitoring
- shell automation
- monitoring and observability platforms
- future graphical or management interfaces

In particular, consumers can determine whether a newly started monitor process has completed at least one successful synchronisation cycle without parsing normal application log output.

### Relationship to `--display-sync-status`

This capability does **not** replace or change the semantics of `--display-sync-status`.

The two interfaces answer different questions:

```text
monitor-status.json
    -> What is the running monitor doing, and did its synchronisation
       processing complete successfully?

--display-sync-status
    -> Are the local filesystem and Microsoft OneDrive currently
       converged?
```

This distinction is important for one-way operating modes.

For example, a `--download-only` monitor may successfully complete all permitted download processing while local-only files remain present.

In that situation:

```text
monitor-status.json
    -> last cycle successful

--display-sync-status
    -> NOT IN SYNC
```

Both results are correct: the configured monitor operation completed successfully, while the local and remote data states are not identical.

### I/O impact

The runtime status file is intentionally small and is not used as a high-frequency heartbeat.

It is updated during monitor lifecycle/state transitions such as:

- monitor startup
- synchronisation cycle start
- synchronisation cycle completion
- relevant condition changes
- orderly shutdown cleanup

It is not rewritten for individual uploads, downloads, inotify events or WebSocket notifications.

This keeps the additional filesystem I/O negligible relative to the database, filesystem and network activity already performed by normal monitor operation.

### Documentation

Documentation has been updated to cover:

- the new `monitor_status` configuration option
- runtime status file location and lifecycle
- JSON fields and timestamp conventions
- Docker and Podman observability use
- relationship to `--display-sync-status`
- application architecture integration
2026-10-07 13:27:41 +11:00
abraunegg
5691477a72 Fix Bug #3885: Reduce Full Scan database I/O and improve monitor-loop memory reclamation (#3888)
This pull request addresses excessive database I/O and process memory growth observed during large-account Full Scan and generated `/children` enumeration workloads.

Testing and profiling were performed primarily against a fixed 101,494-object OneDrive dataset so that changes in database activity, allocation volume and retained process memory could be compared directly between implementations.

## Native Full Scan reconciliation

Native tokenless `/delta` Full Scan True Up no longer uses the database `syncStatus` field as a temporary mark-and-sweep presence flag.

Previously, the client:

1. materialised the applicable database subtree,
2. wrote existing records to `syncStatus = N`,
3. processed the authoritative online enumeration,
4. wrote observed records back to `syncStatus = Y`, and
5. treated records still marked `N` as absent online.

For a no-change 101,494-object Full Scan this generated approximately 3.15 GiB of database write activity.

The new implementation instead builds an in-memory presence candidate set containing only the IDs already present in the applicable database subtree. As authoritative `/delta` items are observed, their IDs are removed from that set. Any IDs remaining after a successfully completed enumeration are processed through the existing deletion/reconciliation logic.

This makes native Full Scan presence reconciliation read-only for unchanged objects and avoids using persistent database state for temporary bookkeeping.

Testing with the fixed 101,494-object dataset reduced no-change Full Scan database writes from approximately **3.15 GiB to 44 KiB**.

## Bounded native `/delta` processing

Authoritative native `/delta` enumeration no longer requires all accepted JSON items to remain retained until the complete response has been downloaded.

Accepted items are drained through the existing reconciliation path in bounded **500-item batches** while enumeration continues. The final partial batch is processed only after the authoritative enumeration has completed.

This preserves the existing database transaction, filtering, move/rename, deletion and deferred-download behaviour while placing an explicit lifetime boundary around processed JSON pages and batches.

A single strategic `GC.collect()` is performed after authoritative enumeration and reconciliation and before deferred download processing, allowing temporary enumeration state to be reclaimed before the next phase begins.

## Generated `/children` enumeration

The generated current-state `/children` path has also been changed from account-sized accumulation to bounded processing.

Previously, recursive `/children` traversal accumulated the complete remote object hierarchy before constructing and processing the generated response. On large accounts this created an unnecessarily large transient JSON working set.

The new path preserves the existing depth-first traversal and generated-response reconciliation semantics, but submits accepted objects directly into the same bounded 500-item processing pipeline as enumeration progresses.

The final partial batch is deliberately retained until traversal is complete so that absence reconciliation remains authoritative.

Generated `/children` reconciliation continues to use the existing `syncStatus` semantics, but its initial database subtree marking no longer materialises full `Item` records for the entire tree.

Instead, both generated subtree marking and native Full Scan presence enumeration use a minimal database projection containing only:

- `id`
- `type`

This avoids constructing and duplicating full database `Item` state — names, tags, hashes, remote metadata and other fields — when only object identity and directory recursion are required.

## Database allocation reductions

Several high-frequency database queries have been narrowed to return only the data actually required by their callers.

Notable changes include:

- subtree traversal uses `SELECT id, type` rather than full `Item` materialisation;
- `idInLocalDatabase()` now performs a `SELECT 1 ... LIMIT 1` existence check;
- `computePath()` retrieves only the seven fields required for path reconstruction rather than building a complete `Item`.

Existing timestamp validation and relocation handling are retained.

No database schema changes are introduced.

## Monitor-mode garbage collection and memory telemetry

Monitor mode now performs:

```text
GC.collect();
GC.minimize();
```

after every completed monitor loop rather than using the previous 24-hour cleanup interval.

`GC.collect()` and `GC.minimize()` are retained as separate operations because they address different aspects of the observed behaviour: reclaiming unreachable managed objects and returning unused managed heap capacity to the operating system.

When memory telemetry is enabled, memory state is recorded both before and after this collection/minimisation boundary.

The asynchronous logging subsystem now provides a drain barrier so that telemetry messages and logger-local buffers have been written and released before garbage collection is measured. This prevents the telemetry mechanism itself from changing the memory state being observed.

## Object and response lifetime cleanup

The investigation also identified a number of long-lived references whose useful lifetime had already ended.

The PR therefore explicitly releases temporary JSON responses, processed arrays and intermediate API state after their final use across sync, OneDrive API, webhook, Socket.IO, Intune and utility paths.

CurlEngine pool handling has also been tightened:

- popped pool slots are explicitly cleared;
- stopped engines are destroyed instead of abandoned;
- expired engines are deterministically destroyed after cleanup.

These changes are intended to make ownership boundaries explicit and prevent stale references from extending the lifetime of otherwise reclaimable state.

## Memory validation

The important measurement is retained memory after repeated large enumerations, not simply cumulative allocation volume.

A native `/delta` control run using the bounded processing and strategic collection path completed **222 monitor loops over more than 22 hours**, including repeated authoritative Full Scans. After establishing its initial working-set high-water, post-minimisation memory remained bounded at approximately:

```text
GC capacity: ~38.9 MiB
RSS:         ~77–78 MiB
```

The generated `/children` path was then tested with:

```text
force_children_scan = true
```

so that every monitor loop enumerated the same fixed 101,494-object account through `/children`.

An intermediate implementation that bounded JSON processing but still materialised the database subtree as full `Item` records continued to show retained-memory growth, reaching approximately:

```text
GC capacity: ~169 MiB
RSS:         ~209 MiB
```

by Loop 14.

After replacing that subtree materialisation with the minimal `id + type` traversal, the same workload remained around:

```text
GC capacity: ~25.6 MiB
RSS:         ~64 MiB
```

through Loop 14, with no GC-arena staircase. At Loop 15, heap minimisation returned additional pages to the operating system, reducing the post-minimisation state to approximately:

```text
GC capacity: ~18.4 MiB
RSS:         ~57 MiB
```

The long-duration `/children` soak is still being continued to confirm the same bounded behaviour over an overnight run.

## Functional validation

The bounded generated-response changes have also been exercised through the existing E2E coverage.

At the current PR revision:

- Personal Account Shared Folder E2E tests are green.
- Business Account Shared Folder E2E tests are green.

The implementation preserves the existing filtering, reconciliation, deletion, move/rename, Shared Folder and deferred-download processing paths.

## Scope

This PR changes the implementation of large authoritative enumeration and memory lifecycle management without changing the database schema or the externally visible synchronisation model.

The primary goals are:

- eliminate unnecessary Full Scan database writes;
- avoid account-sized transient JSON and database object graphs;
- process authoritative data using bounded working sets;
- make temporary object lifetimes explicit;
- reclaim managed heap capacity consistently during long-running monitor operation; and
- preserve existing reconciliation semantics and E2E behaviour.
2026-10-07 07:52:59 +11:00
abraunegg
6965af2b0b Add project sponsorship visibility to initial graphical authentication (#3867)
## Summary

This PR adds restrained GitHub Sponsors visibility to the OneDrive Client for Linux while deliberately avoiding recurring or intrusive sponsorship messaging.

Following a successful **initial graphical authentication**, the browser completion page now includes an optional invitation to help sustain the project through GitHub Sponsors.

The sponsorship message is not displayed during `--reauth`, authentication failures, application startup, monitor startup, normal synchronisation activity, terminal output or desktop notifications.

## Changes

- Enhances the graphical authentication completion page with a clearer responsive layout and application identity.
- Displays the sponsorship section only after successful initial graphical authentication.
- Does not display sponsorship content during explicit `--reauth`.
- Adds an attributable GitHub Sponsors link using GitHub Sponsors campaign metadata.
- Adds passive sponsorship information to the project README and graphical-authentication documentation.
- Adds browser response protections including `Referrer-Policy: no-referrer`, `Cache-Control: no-store`, a restrictive Content Security Policy and `X-Content-Type-Options: nosniff`.
- Does not add application telemetry, click tracking or any new configuration option.

## Sponsorship Behaviour

The graphical authentication page displays:

> Help sustain OneDrive Client for Linux

OneDrive Client for Linux is free, open-source software that is independently developed and maintained. If it is useful to you or your organisation, you can help sustain ongoing development, testing and maintenance through GitHub Sponsors.

The user must explicitly select **Sponsor on GitHub** before any connection to GitHub is made.

GitHub Sponsors campaign metadata is used only to attribute completed sponsorships to the relevant project surface.

## Privacy

The application does not report whether the sponsorship message was displayed or selected.

No application telemetry or analytics have been added.

The local OAuth completion response explicitly prevents the Microsoft OAuth callback URL from being supplied as a browser referrer when following the external sponsorship link.
2026-09-11 10:13:20 +10:00
abraunegg
e9c9f9f8ea Update docs - usage.md and manpage- #3858s (#3858)
Update docs - usage.md and manpage- #3858
2026-09-08 06:35:40 +10:00
Thomas Drake-Brockman
368bb572fd Add notify_monitor_start option to silence monitor-start notification (#3779)
Addresses discussion #3109

Running in `--monitor` mode sends a GUI notification on every startup confirming that filesystem monitoring has begun. There was previously no way to silence just this notification short of disabling all notifications via `disable_notifications`.

* Add `notify_monitor_start` config option (default `true`, preserving existing behaviour) that gates only the monitor-start GUI notification
* Document the option in `config`, `docs/application-config-options.md` and `docs/usage.md`

To disable just this notification, add this to your cofig:
```
notify_monitor_start = "false"
```

Checked to compile with LDC v1.20.1 (Debian) and LDC 1.42.0 (Fedora).
2026-09-05 06:24:18 +10:00
abraunegg
9e074dd310 Implement FR #3787: Use different browser with --reauth and friends (#3848)
## Overview

This pull request implements the feature request raised in #3787 to allow a user to explicitly select which browser is used for interactive Microsoft authentication.

The current GUI authentication path launches the Microsoft authorisation URL using `xdg-open`. This means the desktop environment's configured default browser is normally selected. In environments where a user intentionally uses a different browser for Microsoft 365 authentication, setting the standard `BROWSER` environment variable does not reliably override that desktop preference because `xdg-open` may successfully select the desktop-configured browser before consulting `BROWSER`.

For example, a user may use Firefox as their normal desktop browser while using Microsoft Edge exclusively for Microsoft 365 authentication and SSO.

This change allows that user to run:

```bash
BROWSER=/usr/bin/microsoft-edge-stable onedrive --reauth
```

and have the Microsoft authentication URL opened directly using Microsoft Edge.

## Changes

The browser launch logic in `src/localAuth.d` has been updated so that:

1. If the `BROWSER` environment variable is set, the client first attempts to launch the configured executable directly with the Microsoft authorisation URL.
2. If the configured browser cannot be launched, the failure is written to the debug log and the client falls back to the existing `xdg-open` behaviour.
3. If `BROWSER` is not set, behaviour remains unchanged and `xdg-open` is used as before.
4. If browser launch ultimately fails, the existing authentication fallback behaviour remains unchanged.

Both an explicit executable path:

```bash
BROWSER=/usr/bin/microsoft-edge-stable onedrive --reauth
```

and an executable available through `PATH`:

```bash
BROWSER=microsoft-edge-stable onedrive --reauth
```

are supported.

## Design Considerations

This change deliberately does not attempt to automatically detect Microsoft Edge or introduce a Microsoft Edge-specific configuration option.

`BROWSER` is treated as a user-selected browser executable, making the implementation browser-neutral and allowing the same mechanism to be used with Firefox, Chromium, Chrome, Edge or another browser.

The value is passed directly to `spawnProcess()` as an executable rather than being executed through a shell. This keeps the authentication path deterministic and avoids introducing shell command parsing into OAuth browser launching.

The existing behaviour remains the fallback path, so an invalid or stale `BROWSER` value does not prevent authentication from proceeding through the normal desktop browser.

## Behaviour

With no override configured:

```bash
unset BROWSER
onedrive --reauth
```

the existing desktop/default-browser behaviour is retained.

With an explicit browser configured:

```bash
BROWSER=/usr/bin/microsoft-edge-stable onedrive --reauth
```

the selected browser is used for Microsoft authentication.

If the configured browser does not exist or cannot be started:

```bash
BROWSER=/does/not/exist onedrive --reauth
```

the client falls back to `xdg-open`.

## Scope

This is intentionally a laser-focused change.

There are no changes to:

* OAuth request or response handling
* local loopback authentication
* GUI session detection
* authentication callback processing
* device authentication
* headless or SSH authentication behaviour
* application configuration options
* Microsoft Edge detection
* the existing manual authentication fallback

Only the browser-selection step of the existing GUI authentication workflow is changed.
2026-09-04 07:23:58 +10:00
abraunegg
bec9b20c0c Fix Bug #3806: Complete --display-sync-status redesign with documentation and E2E regression coverage (#3844)
This PR completes the redesign of `--display-sync-status` to provide a meaningful, read-only assessment of whether the configured OneDrive sync scope is currently in sync.

Previously, `--display-sync-status` was primarily based on pending Microsoft Graph `/delta` data. This meant it could identify some pending remote changes, but it did not provide a complete picture of synchronisation state and could miss important conditions such as local-only changes, zero-byte files, directory changes, moves or renames, and deletion tombstones.

The redesigned implementation now evaluates synchronisation state in **both directions**:

```text
Microsoft OneDrive -> Local filesystem
Local filesystem   -> Microsoft OneDrive
```

and reports an overall result of:

* `IN SYNC`
* `NOT IN SYNC`
* `INDETERMINATE`

This provides a safe way for users, monitoring systems and diagnostic workflows to answer:

> Is this client currently in sync?

without performing a sync or destroying/rebuilding application state.


---

## What has changed

### Remote state assessment

The Microsoft OneDrive → Local filesystem assessment now identifies pending remote changes including:

* new files
* new directories
* modified files
* moved or renamed items
* deleted items
* zero-byte files
* approximate download volume

Microsoft Graph deletion tombstones are explicitly recognised and handled rather than being incorrectly processed as malformed live objects.

The existing stored delta cursor is used only as the starting point for the assessment and is **not advanced or modified** by `--display-sync-status`.

### Local state assessment

The Local filesystem → Microsoft OneDrive assessment now compares the configured local filesystem against the client's stored sync database and identifies:

* new local files
* new local directories
* modified local files
* timestamp-only differences
* locally deleted or missing items
* file/directory type changes
* files requiring upload
* directories requiring creation online
* remote deletions that would be requested
* approximate upload volume

The implementation follows the same database hierarchy and relative-path semantics used by normal synchronisation processing.

### Overall sync state

The command now produces a clear overall state.

`IN SYNC` means that no pending local or remote changes were detected for the configured sync scope.

`NOT IN SYNC` means that one or more pending local or remote changes were positively identified.

`INDETERMINATE` is used where the command cannot safely prove that the configured scope is fully assessed.

The implementation deliberately prefers `INDETERMINATE` over incorrectly reporting `IN SYNC` where remote traversal completeness cannot be guaranteed.

---

## Read-only behaviour

`--display-sync-status` remains a query-only operation.

The command does **not**:

* upload files
* download files
* create or remove local files or directories
* modify the live sync database
* advance stored Microsoft Graph delta cursors
* perform reconciliation

The command operates against the existing copied/read-only application state used for no-sync operations.

The command also now establishes the configured `sync_dir` as its working directory before local filesystem assessment, consistent with normal sync and monitor operation.

The existing `.nosync` / `--check-nomount` protection is also applied so that an unavailable mounted filesystem cannot be incorrectly interpreted as mass local deletion.

---

## Scope and filtering

The status assessment honours the configured sync scope and applicable client-side filtering, including:

* `--single-directory`
* `sync_list`
* `skip_file`
* `skip_dir`
* `skip_dotfiles`
* `skip_size`
* root-file handling
* upload-only and download-only operating modes
* `--no-remote-delete`

Where configured operation requires a remote traversal mechanism that cannot be safely reproduced by the read-only status query, the result is reported as `INDETERMINATE` rather than returning a false clean result.

---

## Transfer estimates

Pending upload and download data is now displayed using a human-readable value while retaining the exact byte count.

For example:

```text
Approximate download data:   14.15 MB (14838177 bytes)
Approximate upload data:     2.09 KB (2144 bytes)
```

Values smaller than 1 KiB are displayed directly in bytes:

```text
Approximate upload data:     90 bytes
```

This avoids misleading output such as `0 KB` for small but non-zero files while retaining deterministic values useful for diagnostics and testing.

---

## Example output

A clean client now reports:

```text
Synchronization status for the configured sync scope:

Microsoft OneDrive -> Local filesystem
  No pending remote changes detected.

Local filesystem -> Microsoft OneDrive
  No pending local changes detected.

Overall status: IN SYNC
No pending local or remote changes were detected for the configured sync scope.
```

A client with changes in both directions may report:

```text
Microsoft OneDrive -> Local filesystem
  Pending remote items:        1
  New files:                   1
  Files requiring download:    1

Local filesystem -> Microsoft OneDrive
  Pending local items:         1
  Modified local files:        1
  Files requiring upload:      1

Overall status: NOT IN SYNC
```

When remote changes are also pending, locally inferred actions are reported as the current point-in-time assessment and may subsequently be reconciled or superseded when normal synchronisation processing occurs.

---

## End-to-end regression coverage

A new **TC0079** end-to-end test case has been added for the redesigned `--display-sync-status` behaviour.

TC0079 exercises the status command through multiple lifecycle states, including:

* established clean state → `IN SYNC`
* deterministic incomplete assessment → `INDETERMINATE`
* local-only pending changes
* same-size local content modification
* timestamp-only local differences
* new local files and directories
* local deletion
* filtered local content
* remote-only pending changes
* remote deletion tombstones
* remote rename
* remote modification
* zero-byte remote files
* new remote files and directories
* filtered remote content
* mixed local and remote pending changes
* repeated status queries proving that the command does not consume or advance the live delta cursor

TC0079 is registered in the standard E2E suite and therefore runs across the supported Personal, Personal 15-character `driveId`, Business and SharePoint account workflows.

---

## Documentation

Documentation has been updated to describe the redesigned capability and its intended use.

Updates include:

* `docs/usage.md`

  * explains why `--display-sync-status` should be used when a user wants to determine sync health without performing a sync or `--resync`
  * documents the bidirectional assessment and overall states

* `docs/application-config-options.md`

  * expands the CLI option documentation and behaviour

* `docs/end_to_end_testing.md`

  * documents TC0079 and its coverage

The documentation also makes clear that `NOT IN SYNC` is a reported synchronisation state rather than a command execution failure; consumers should evaluate the reported `Overall status` rather than treating the process exit code as the synchronisation result.

---

## Result

This change turns `--display-sync-status` from a limited remote-change check into a substantially more useful synchronisation-health diagnostic while preserving the most important property of the command:

**it determines sync state without performing a sync or modifying the client's existing synchronisation state.**
2026-09-02 12:42:10 +10:00
abraunegg
e286a56e61 Fix Bug #3834: Validate timestamp authority and detect time differences between host platform and Microsoft OneDrive (#3836)
## Summary

This PR implements the first stage of #3834 by introducing a system-time authority and safety gate before timestamp-sensitive OneDrive synchronisation is allowed to proceed.

The client now validates the host system clock against time returned by the Microsoft service and maintains a process-wide time-authority state that can be used to determine whether synchronisation is safe.

This PR intentionally **does not change how file or directory timestamps are applied during synchronisation**. The broader audit and correction of timestamp application logic described in #3834 will be handled in a separate follow-up PR.

## System Time Validation

The client uses Microsoft service time as the external reference and accounts for HTTP round-trip time and measurement uncertainty when calculating effective clock skew.

The current policy is:

* **0–15 seconds:** system time considered acceptable
* **>15 seconds to 120 seconds:** warning is generated, synchronisation continues
* **>120 seconds:** potentially unsafe; a second independent Microsoft time observation is performed before the condition is treated as blocking

A single anomalous observation therefore cannot immediately prevent synchronisation.

When significant drift is confirmed, the client enters `TIME_DRIFT_BLOCKING` and timestamp-sensitive synchronisation is not permitted until system time has been corrected and successfully revalidated.

System time is periodically revalidated while the application is running, and significant wall-clock discontinuities trigger revalidation of the previously established authority state.

## Behaviour

### `--sync`

If unsafe system clock drift is confirmed before synchronisation begins:

* synchronisation does not start
* the user is advised to correct the local system clock or time synchronisation service
* the application exits with failure

If system time becomes unsafe during synchronisation, further timestamp-sensitive processing is stopped and the application exits with failure.

### `--monitor`

If unsafe clock drift is present when monitor mode starts:

* the monitor process remains running
* synchronisation and event processing do not begin
* system time is periodically revalidated
* normal monitor startup automatically continues once system time is corrected

If system time becomes unsafe while monitor mode is already running:

* timestamp-sensitive synchronisation is suspended
* the monitor process remains running
* local filesystem observations may still be retained for later processing
* WebSocket/Webhook-triggered reconciliation is prevented while the safety gate is closed
* processing automatically resumes once system time has been corrected and revalidated

Important blocking and recovery state changes are emitted through normal application logging and notification paths and therefore do not require `--verbose`.

## Configuration

A `disable_time_check` configuration option / `--disable-time-check` command-line option is provided for users who explicitly need to bypass system-time validation.

## E2E Coverage

A new **TC0077 — Timestamp authority safety gating validation** test case has been added with three scenarios:

* **TA-0001:** `--monitor` starts with unsafe clock drift, remains suspended, and automatically starts synchronisation after time is corrected
* **TA-0002:** an already-running `--monitor` instance develops unsafe clock drift, suspends synchronisation, retains pending local work, and resumes processing after time recovery
* **TA-0003:** `--sync` starts with unsafe clock drift, performs no synchronisation and exits with failure
* **TA-0004:** unsafe clock drift with `--disable-time-check` validates that the explicit time-validation override bypasses the clock safety gate, permits normal synchronisation to proceed despite otherwise blocking clock drift, and confirms through independent remote verification that local content is successfully propagated to OneDrive

The E2E implementation uses process-local clock manipulation so the GitHub Actions runner, filesystem timestamps and Microsoft-side timestamps are not modified by the test.

## Scope

This PR establishes **whether the local system clock can safely participate in timestamp-sensitive synchronisation decisions**.

It does **not** yet alter:

* remote-to-local timestamp application
* local-to-remote timestamp propagation
* file or directory timestamp semantics
* move/rename timestamp handling
* timestamp-only reconciliation
* `lastModifiedDateTime` update behaviour
* `--local-first` timestamp authority semantics

Those areas will be reviewed separately once this timestamp-authority foundation has been merged.
2026-08-26 11:14:08 +10:00
abraunegg
81971a9c30 Fix Bug #3825: Fix safeBackup replacement handling to preserve canonical files transactionally (#3826)
This PR fixes a serious data-preservation flaw in the `safeBackup` conflict-resolution workflow and strengthens several related reconciliation paths where unique local file content could otherwise be lost or incorrectly classified.

When an existing local file needed to be preserved before being replaced by a newer or conflicting Microsoft OneDrive version, several code paths could rename the original canonical file to a `-safeBackup-` filename **before the replacement operation had successfully completed**.

If the subsequent replacement failed, the client could be left with only the `-safeBackup-` file and no file at the original canonical pathname.

This PR changes replacement-style safeBackup handling so that preservation and replacement are performed transactionally:

> **The existing canonical file remains present until a complete, validated replacement is ready to be committed and any required preservation has succeeded.**

The implementation has also been hardened following dedicated E2E regression testing, which exposed additional reconciliation paths where the same data-preservation rules were not being applied consistently.
2026-08-21 08:30:01 +10:00
abraunegg
778cc05d24 Fix Bug #3782: Change mandatory resync exit status from 126 to 78 (#3799)
The client currently exits with status `126` when it detects a condition that requires the user to perform a `--resync`.

Exit status `126` is conventionally used by shells to indicate that a command was found but could not be executed. This does not accurately represent the OneDrive client's behaviour: the application has executed successfully, but has detected a persistent configuration or state condition that requires user intervention before normal synchronisation can continue.

Change the mandatory resync exit status from `126` to `78`.

Exit status `78` corresponds to the traditional `EX_CONFIG` value and more accurately represents the condition being reported. It also avoids using the shell-reserved `126` exit status.

This change:

* changes `EXIT_RESYNC_REQUIRED` from `126` to `78`;
* updates both supplied systemd service templates to use `RestartPreventExitStatus=78`;
* preserves the existing systemd behaviour where a mandatory resync prevents automatic service restart while leaving the service in a failed state requiring operator action;
* improves the resync-required error message to make it clear that `--resync` must be appended to the normal invocation, for example:

  * `onedrive --sync --resync`
  * `onedrive --monitor --resync`
* documents the new exit status and the compatibility impact for scripts, monitoring systems and custom service definitions that currently test for exit status `126`.

No synchronisation or resync processing behaviour is otherwise changed.

Existing automation that explicitly checks for exit status `126` will need to be updated to check for exit status `78` instead.
2026-08-08 07:22:07 +10:00
abraunegg
0b7299adb1 Release files for 2.5.11 (#3764)
* Add the missing `remove_source_folders` entry to `--display-config` output.
* Release files for 2.5.11
2026-06-30 13:56:23 +10:00
abraunegg
fcf369c2b6 Update docs clarify monitor operations (#3760)
* Clarify 'monitor' configuration options
2026-06-29 08:27:53 +10:00
abraunegg
0efee85980 Implement GUI-based OAuth callback handling using local loopback listener (#3750)
This change improves the user authentication experience when running the client in a graphical desktop environment.

Previously, browser-based authentication relied on the user manually copying and pasting the final redirect URL from the browser back into the client. Due to Microsoft authentication workflow changes and automatic browser redirection behaviour, this process has become increasingly unreliable and has generated ongoing user support requests.

**Changes included:**

- Added a dedicated local authentication listener implementation (localAuth.d)
- Automatically detects when the client is running in a GUI session
- Opens the Microsoft authentication URL in the user's default browser
- Uses a local loopback HTTP listener to capture the OAuth authorisation response directly
- Eliminates the need for manual copy-and-paste of the redirect URL when using a desktop environment
- Returns a simple browser success/failure page after authentication completes
- Uses a fixed loopback callback endpoint of:
  http://127.0.0.1:53100/
- Falls back to the existing nativeclient copy-and-paste authentication workflow when:
  - no GUI environment is detected
  - the local listener cannot be started
  - browser launch fails
  - local callback authentication cannot be completed

This change is fully backwards compatible for headless, SSH and server deployments while providing a significantly improved authentication experience for desktop users.
2026-06-15 14:54:36 +10:00
abraunegg
77938303d4 Fix single-tenant authentication redirect URI handling and add administrator consent support (#3745)
Fix authentication URL generation when `azure_tenant_id` is configured and the default OneDrive Client for Linux application registration is being used.

Changes include:

* Fix redirect URI generation for single-tenant authentication when using the default application registration
* Retain the registered Microsoft Identity Platform native-client redirect URI:
  `https://login.microsoftonline.com/common/oauth2/nativeclient`
* Add the `--display-admin-consent-url` CLI option
* Generate tenant-specific Microsoft Entra ID administrator consent URLs
* Improve documentation for `azure_tenant_id`
* Add documentation covering Microsoft Entra ID administrator consent workflows and tenant-wide application approval

These changes resolve Microsoft Entra ID authentication failures reporting `AADSTS50011` when using `azure_tenant_id` with the default application registration and provide a documented workflow for administrator consent in managed Microsoft 365 and Microsoft Entra ID environments.
2026-06-10 08:26:28 +10:00
abraunegg
0bcc08bd51 Implement FR #3738: Implement capability to display the Admin Consent URL via --display-admin-consent-url (#3739)
* Add CLI option to generate an Admin Consent URL
* Document new capability
2026-06-09 04:06:48 +10:00
abraunegg
a62c4a45e0 Add push-triggered E2E testing across Personal, Business and SharePoint accounts (#3644)
* Add push-triggered E2E testing across Personal, Business and SharePoint accounts + Shared Folder Testing
2026-05-06 18:17:05 +10:00
abraunegg
8e953e51be Implement FR #3685: Support Microsoft Identity Broker 3.0.1 (#3686)
* Implement full support for Microsoft Identity Broker 3.x behaviour, ensuring compatibility while maintaining backward support for broker 2.x.
* Update usage.md to add RHEL Intune package versions and Ubuntu Intune package versions
2026-04-10 13:22:25 +10:00
abraunegg
db42574a01 Add Server Side Filtering Documentation (#3663)
* Add Server Side Filtering Documentation
2026-03-18 06:12:06 +11:00
abraunegg
881218238a Update usage.md and known-issues.md regarding AADSTS70000 errors (#3615)
* Add detailed guidance to usage and known-issues documentation explaining
AADSTS70000 errors during authentication. Clarifies that these failures are
caused by invalid or expired authorisation codes, commonly due to browser
extensions or privacy features modifying the redirect URI, and documents
recommended remediation steps.
* Fix 'OneDrive Free Client' as this should read 'OneDrive Client for Linux'
2026-01-24 08:04:40 +11:00
abraunegg
19b050fa79 Improve --resync warning prompt for clarity and safer operation (#3562)
This update refines the --resync user warning prompt to provide clearer,
more accurate guidance on the behaviour and risks associated with performing a
resynchronisation operation.

Key improvements include:

Explicitly explaining that --resync deletes the client’s local state
database and rebuilds it entirely from the current OneDrive contents.

Accurately describing possible outcomes, including overwrite scenarios,
conflict-driven renames or duplications, increased upload/download activity,
and potential Microsoft Graph API throttling (HTTP 429).

Removing incorrect implications that local-only files may be deleted during
--resync (they will instead be uploaded, unless destructive cleanup modes
are explicitly used).

Strengthening safety guidance by recommending:

Maintaining a current backup of the sync_dir

Running the same command with --dry-run before executing a real --resync

Enabling use_recycle_bin so locally triggered online deletions are preserved

Improved formatting and readability for terminal output.

This change enhances user understanding, reduces the likelihood of accidental
data loss, and aligns runtime messaging with the client’s actual synchronisation
logic and documented behaviour.
2025-12-12 12:47:29 +11:00
abraunegg
bbe3f40a0b Clarify what is enabled with 'display_manager_integration' (#3554)
* Clarify what is enabled with 'display_manager_integration' to avoid the misconception this need to be enabled to use the recycle bin feature
2025-12-11 09:51:55 +11:00
abraunegg
a4598fe358 Clarify 'sync_list' rules in documentation (#3551)
* Clarify 'sync_list' rules and clearly articulate which rules are computationally expensive.
2025-11-28 08:38:58 +11:00
abraunegg
bdf3a77dbe Update broken link for FreeDesktop.org Trash Specification (#3550)
* Update broken link for FreeDesktop.org Trash Specification and add graphic
2025-11-27 18:46:41 +11:00
abraunegg
4f634b8340 Update OAuth2 Authentication Process Diagrams (#3537)
* Update OAuth2 Authentication Process Diagrams
2025-11-17 06:50:48 +11:00
abraunegg
7bb509c749 Fix Bug #3512: Unexpected deletion of empty nested folders during first sync with 'sync_list' (#3513)
* Fix unexpected deletion of empty nested folders during first sync with sync_list
* Add missing line breaks in usage.md
2025-11-06 10:39:44 +11:00
abraunegg
3082e7a4bd Update Documentation (#3510)
* Update Documentation
2025-11-05 10:35:42 +11:00
abraunegg
40e0ca4462 Implement Desktop Manager Integration for GNOME and KDE (#3500)
Implement full “Display Manager Integration” support for both GNOME and KDE desktop environments. This new feature allows the OneDrive Client for Linux to detect the active desktop session and automatically:

* Register the configured sync_dir as a “special place” or sidebar entry within the file manager (Nautilus on GNOME; Dolphin on KDE).
* Apply a custom “onedrive” folder icon to the synchronisation directory when the installed icon theme supports it.
* Cleanly install and uninstall required resources (icons, bookmarks, file manager integration) via the Makefile’s install and uninstall targets, thereby supporting system-wide installations, packaging workflows, and per-user installs.
* Introduce a new configuration option display_manager_integration (boolean) to enable or disable this integration behaviour at runtime.
* Update documentation and usage guidance to clearly explain what “Display Manager Integration” means, what this client implements (sidebar entry + icon) and what features remain out-of-scope (context menus, overlay badges, tray icons).
* Ensure safe, idempotent integration logic for both GNOME and KDE (bookmark manipulation, icon theme detection, cache refresh) with fallbacks and minimal dependencies.

With this merge, users installing via make install or system packages will benefit from enhanced desktop usability: the OneDrive folder appears visibly and intuitively within their standard file manager sidebar, making access and identification simpler. At the same time, the core sync engine remains focused on reliable file synchronisation, with the desktop integration layer remaining optional and disabled by default unless explicitly enabled via configuration.
2025-11-03 14:26:49 +11:00
abraunegg
defada7daf Update Documentation for v2.5.8 (#3507)
* Update Documentation for v2.5.8 release
2025-11-03 10:31:14 +11:00
abraunegg
1321ae6306 Implement FR #2576: Implement resumable downloads (#3354)
* Implement resumable downloads (FR #2576) by using a state JSON file to track download progress and resuming the download from that offset, post validation of:
  * offset point is where the local point is at
  * hash has not changed online, thus file has not changed online in-between failed download
2025-08-01 06:33:33 +10:00
abraunegg
f89cfaa6fc Update usage.md (#3399)
* Clarify caution message about using bad curl versions to remove ambiguity and clarify that other bugs, not related to HTTP/2 will still impact operational use of this client
2025-07-27 10:15:19 +10:00
abraunegg
4301c2ee67 Update wording within first steps for clarity (#3391)
* Update wording within first steps for clarity
2025-07-22 08:23:28 +10:00
abraunegg
c3c5bf38bc Fix Bug #3336: Handle inconsistent OneDrive Personal driveId casing across multiple Microsoft Graph API Endpoints (#3347)
* Handle inconsistent OneDrive Personal driveId casing across multiple Microsoft Graph API Endpoints by ensuring that where ever there is a use of a driveId for a comparison, ensure the value to compare has been transformed to 'lowercase' to avoid the situation where Microsoft Graph API sends the driveId as 'lowercase' in one API response and 'UPPERCASE' in other responses.
2025-07-05 07:14:47 +10:00
abraunegg
a1a8b46673 Add curl 8.13.x and 8.14.0 to known bad curl versions (#3356)
* Add curl 8.13.x and 8.14.0 to known bad curl versions that when used, have operational impacts to this client
2025-06-25 08:06:44 +10:00
abraunegg
d8d695600a Update OAuth2 Interactive Authorisation Flow prompts (#3323)
* Update OAuth2 Interactive Authorisation Flow prompts to remove any ambiguity on what actions a user needs to take
2025-06-08 13:20:57 +10:00
abraunegg
810197cc05 Implement FR #2693: Implement OAuth2 Device Authorisation Flow (#3313)
Adds support for Microsoft’s OAuth2 Device Authorisation Flow, enabling the client to authenticate using device and user codes on a second device. This is particularly useful for headless or limited-input environments where interactive browser login is not possible.

Includes:
- Initiating device code requests and displaying user instructions
- Polling token endpoint until user authorises the device or the code expires
- Error handling for pending, declined, and expired authorisation states
- Countdown display showing remaining authorisation window

This feature is enabled via the `use_device_auth` config option
2025-06-03 07:47:56 +10:00
abraunegg
d9b8966fa4 Force rebuild post GitHub Actions outage (#3298)
* Force rebuild post GitHub Actions outage
2025-05-27 04:51:37 +10:00
abraunegg
61e5a1edb6 Implement FR #3209: Add native support for authentication via Intune dbus interface (#3274)
* Adds support for calling `acquireTokenInteractively` and `acquireTokenSilently` via D-Bus
* Parses and handles the full `brokerTokenResponse` object returned by the Intune broker
* Stores and reuses `account` data to enable silent token refresh without repeated interactive authentication
* Ensures the access token and its expiry time are properly calculated and stored for consistent token management
* Fallback to interactive authentication is triggered if silent authentication fails
2025-05-26 17:14:50 +10:00
abraunegg
b496c4e21f Update 'Client Side Filtering' documentation and handling (#3296)
* Fix documentation around missing 'check_nosync' needing a --resync when enabling / disabling
* Fix documentation around missing 'skip_size' needing a --resync when enabling / disabling
* Validate 'check_nosync' and 'skip_size' when used as part of a config file to trigger --resync
* Validate 'check_nosync' and 'skip_size' when used as part of CLI to trigger --resync
2025-05-26 15:25:04 +10:00
abraunegg
73194b0169 Implement FR #3234: Add configurable upload delay to support Obsidian (#3262)
* As of now, Obsidian on Linux does not provide a built-in way to disable atomic saves or switch to a backup-copy method via configuration. Obsidian uses Electron and relies on the default save behavior of its underlying libraries and editor components (like CodeMirror), which typically perform atomic writes for every keystroke. This FR implements a delay in uploading changes to Microsoft OneDrive that is user configurable to better handle how Obsidian works
* Add specific note regarding compatibility with Obsidian and the options that this PR introduces
* Enforce a minimum | maximum for 'inotify_delay'
* Update documentation for feature
* Update 'config' file with 'delay_inotify_processing' option
* Add Ubuntu 24.10 version of curl (8.9.1) to known bad curl versions
* Add Ubuntu version name for Ubuntu 24.10
2025-05-12 06:29:41 +10:00
abraunegg
ce1a47ded8 Add Ubuntu 24.10 curl version for compatibility and bug reference
* Add Ubuntu 24.10 curl version for compatibility and bug reference
2025-05-09 14:12:34 +10:00
abraunegg
4736b79f56 Update Client Architecture Documentation (#3261)
* Update Client Architecture Documentation
* Fix wording in 'usage.md'
2025-05-04 10:31:16 +10:00
abraunegg
acda30e3f6 Update usage.md
* Explicitly add 'Obsidian' as an editor that performs atomic saves.
2025-05-04 07:40:35 +10:00
abraunegg
5c9a055733 Update usage.md (#3260)
* Add links to additional documentation based on feedback in https://github.com/abraunegg/onedrive/issues/3257
2025-05-03 10:40:07 +10:00
abraunegg
831445f616 Update usage.md
* Add missing TOC link for 'Client Documentation'
2025-05-03 09:13:55 +10:00