Skip to content

refactor(routing): rewire the setsites ajax route to an extension-free url - #32

Merged
DeepDiver1975 merged 1 commit into
masterfrom
fix/rewire-legacy-ajax-routes
Jul 28, 2026
Merged

refactor(routing): rewire the setsites ajax route to an extension-free url#32
DeepDiver1975 merged 1 commit into
masterfrom
fix/rewire-legacy-ajax-routes

Conversation

@DeepDiver1975

@DeepDiver1975 DeepDiver1975 commented Jul 27, 2026

Copy link
Copy Markdown
Member

Description

Hardening, in the same class as owncloud/core#41740 and rewired the same way as
owncloud/core#41742. No user-visible behaviour change — see Impact below.

appinfo/routes.php declared

$this->create('external_ajax_setsites', 'ajax/setsites.php')
    ->actionInclude('external/ajax/setsites.php');

The router prefixes app route urls with /apps/<appid>, so the declared url
becomes /apps/external/ajax/setsites.php — which is a real file. The front
controller rewrite generated by \OC\Setup::updateHtaccess() only forwards a
request to index.php when the requested path does not exist on disk:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [PT,E=PATH_INFO:$1]

The web server therefore executes the script directly, without the bootstrap
index.php would have performed, and the request dies with Class "OC" not found → HTTP 500. The route was unreachable at its own declared url.

Impact: latent, not a live bug

OC.filePath() unconditionally injects /index.php/ for non-core app .php
files (core/js/js.js, the file.substring(file.length - 3) === 'php' && !isCore
branch), so the admin panel always requested the routed
/index.php/apps/external/ajax/setsites.php form — which works. Verified against
a pristine owncloud/server:11.0.0-rc2. The setting is not broken today.

The value here is that a route is reachable at the url it declares, and the bug
class cannot resurface if a caller is ever written the obvious way.

What this changes

  • The route url loses its .php suffix so that it no longer resolves to a file
    on disk. The actionInclude() target and the route name are unchanged, so
    linkToRoute() callers keep working.
  • js/admin.js moves from OC.filePath() to OC.generateUrl(). Simply dropping
    the .php from the OC.filePath() call would not work: with a non-.php file
    name and a non-core app, OC.filePath() falls through to its
    OC.appswebroots[app] branch and yields a static url rather than a routed
    one.

No backwards-compatible .php alias is added — an alias would re-introduce
exactly the shadowed url this change removes, so it would be dead on arrival.

Release note

This app needs its own release before an ownCloud bundle picks the change up.

🤖 Generated with Claude Code

…e url

The route url 'ajax/setsites.php' is prefixed to /apps/external/ajax/setsites.php
by the router, which *is* a real file on disk, and the front controller rewrite
skips those paths:

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule . index.php [PT,E=PATH_INFO:$1]

The web server therefore executes the script directly, without the bootstrap
index.php would have performed, and such a request dies with `Class "OC" not
found` (HTTP 500). The route was unreachable at its own declared url.

This is hardening, not a user-visible bug fix. OC.filePath() unconditionally
injects /index.php/ for non-core app .php files, so the admin panel always
requested the routed /index.php/apps/external/ajax/setsites.php form, which
works. Verified against a pristine owncloud/server:11.0.0-rc2.

The url loses its .php suffix so that it no longer resolves to a file on disk.
The actionInclude() target and the route name are unchanged, so linkToRoute()
callers keep working. The js caller moves from OC.filePath() to
OC.generateUrl(): with a non-.php file name OC.filePath() falls through to the
OC.appswebroots[app] branch and would yield a static url instead of a routed one.

No backwards-compatible .php alias is added - an alias would re-introduce
exactly the shadowed url this change removes.

See owncloud/core#41740 and
owncloud/core#41742 for the same change in core.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
@DeepDiver1975
DeepDiver1975 force-pushed the fix/rewire-legacy-ajax-routes branch from 240b4ed to 188f357 Compare July 27, 2026 21:33
@DeepDiver1975 DeepDiver1975 changed the title fix(routing): rewire the setsites ajax route to an extension-free url refactor(routing): rewire the setsites ajax route to an extension-free url Jul 27, 2026

@phil-davis phil-davis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

seems reasonable

@DeepDiver1975
DeepDiver1975 merged commit 7a7b083 into master Jul 28, 2026
4 checks passed
@DeepDiver1975
DeepDiver1975 deleted the fix/rewire-legacy-ajax-routes branch July 28, 2026 09:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants