History log of /dokuwiki/lib/ (Results 1 – 25 of 4587)
Revision Date Author Comments
(<<< Hide modified files)
(Show modified files >>>)
fe58309e16-Jul-2026 Andreas Gohr <gohr@cosmocode.de>

extension: don't crash on malformed conflict/dependency ids

The conflicts and depends fields in the repository metadata are free
form text entered by extension authors and may contain values that ar

extension: don't crash on malformed conflict/dependency ids

The conflicts and depends fields in the repository metadata are free
form text entered by extension authors and may contain values that are
not valid extension ids, such as "sprintdoc template". Since 9af82229f
routed every Extension construction through the strict setBase()
validation, such a value made Extension::createFromId() throw an
uncaught RuntimeException while building the notices, taking down the
whole extension manager.

Skip entries that cannot be parsed into an extension id when checking
for missing dependencies and conflicts.

As an immeadiate fix this will also be fixed in the repository API to
avoid sending invalid extension IDs to the extension manager.

Fixes #4691

show more ...

1ed5d39808-Jul-2026 splitbrain <86426+splitbrain@users.noreply.github.com>

�� Rector and PHPCS fixes

2d05a06d08-Jul-2026 Andreas Gohr <gohr@cosmocode.de>

fix(info): read parser modes from the registry, not the deprecated global

The info plugin's ~~INFO:syntaxtypes~~ read the $PARSER_MODES global
directly. Since the mode taxonomy moved into ModeRegist

fix(info): read parser modes from the registry, not the deprecated global

The info plugin's ~~INFO:syntaxtypes~~ read the $PARSER_MODES global
directly. Since the mode taxonomy moved into ModeRegistry (c8dd1b9d2),
that global is only populated as a side effect of a parse, so on a warm
instruction cache with no parse in the request it is unset and the
syntax-types table renders empty. ~~INFO:syntaxmodes~~ used the
deprecated p_get_parsermodes(), logging a deprecation on every render.

Both now build a ModeRegistry and read the categories and modes from it
directly, independent of parse or cache state.

show more ...

18cdf10207-Jul-2026 Andreas Gohr <gohr@cosmocode.de>

fix(editor): give toolbar and picker buttons an explicit type

Toolbar and picker buttons are created as <button> elements with no type
attribute, so they default to type="submit". When a plugin rend

fix(editor): give toolbar and picker buttons an explicit type

Toolbar and picker buttons are created as <button> elements with no type
attribute, so they default to type="submit". When a plugin renders the
toolbar into a container inside its own form, clicking any button (e.g. a
smiley picker) submits that form. Set type="button" so the buttons never
trigger a submit.

show more ...

6a8e48ed07-Jul-2026 Andreas Gohr <gohr@cosmocode.de>

fix(extension): skip invalid directories when listing extensions

A leftover directory whose name is not a valid extension base (e.g.
"myplugin (copy)") made Extension::setBase() throw, which propaga

fix(extension): skip invalid directories when listing extensions

A leftover directory whose name is not a valid extension base (e.g.
"myplugin (copy)") made Extension::setBase() throw, which propagated
out of the unguarded getPlugins()/getTemplates() calls and fataled the
whole Extension Manager page and the extension list CLI.

Catch the exception per-directory in readExtensionsFromDirectory() so a
single stray directory is skipped and logged instead of breaking every
caller. The throw is kept for the install path.

show more ...

c3a14f6706-Jul-2026 Andreas Gohr <gohr@cosmocode.de>

fix(media): don't upscale small images in the detail previews

The detail page, media manager and media diff requested a bounding-box
resize at the full box size, so an image smaller than the box was

fix(media): don't upscale small images in the detail previews

The detail page, media manager and media diff requested a bounding-box
resize at the full box size, so an image smaller than the box was enlarged
and fetch.php generated and cached the upscaled copy.

slika 1.2 adds an $upscale option to resize/crop. getDisplayDimensions()
now takes a $fit flag mirroring fetch.php one to one and predicts the
matching no-upscale dimensions, media_resize_image()/media_mod_image()
forward $upscale, and fetch.php disables upscaling for fit=1 requests.
In-page image scaling is unchanged.

show more ...


/dokuwiki/_test/rector.php
/dokuwiki/_test/tests/File/MediaFileTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/AbstractModeTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/PreformattedTest.php
/dokuwiki/_test/tests/Search/Collection/CollectionSearchTest.php
/dokuwiki/_test/tests/Search/Collection/DirectCollectionTest.php
/dokuwiki/_test/tests/Search/Collection/FrequencyCollectionTest.php
/dokuwiki/_test/tests/Search/Collection/LookupCollectionTest.php
/dokuwiki/_test/tests/Search/Index/LockTest.php
/dokuwiki/_test/tests/Search/Index/MemoryIndexTest.php
/dokuwiki/_test/tests/Search/Index/TupleOpsTest.php
/dokuwiki/_test/tests/Search/Query/QueryEvaluatorTest.php
/dokuwiki/_test/tests/Search/Query/QueryParserTest.php
/dokuwiki/_test/tests/Ui/Media/DisplayTest.php
/dokuwiki/_test/tests/inc/media_resize.test.php
/dokuwiki/composer.json
/dokuwiki/composer.lock
/dokuwiki/inc/Cache/CacheImageMod.php
/dokuwiki/inc/File/MediaFile.php
/dokuwiki/inc/JpegMeta.php
/dokuwiki/inc/Parsing/Handler.php
/dokuwiki/inc/Parsing/Lexer/Lexer.php
/dokuwiki/inc/Parsing/Parser.php
/dokuwiki/inc/Parsing/ParserMode/AbstractMode.php
/dokuwiki/inc/Parsing/ParserMode/GfmQuote.php
/dokuwiki/inc/Parsing/ParserMode/Preformatted.php
/dokuwiki/inc/Search/Collection/AbstractCollection.php
/dokuwiki/inc/Search/Collection/DirectCollection.php
/dokuwiki/inc/Search/Index/AbstractIndex.php
/dokuwiki/inc/Search/Index/Lock.php
/dokuwiki/inc/Search/Index/TupleOps.php
/dokuwiki/inc/Search/LegacyIndexer.php
/dokuwiki/inc/Search/Query/QueryEvaluator.php
/dokuwiki/inc/Search/Tokenizer.php
/dokuwiki/inc/Ui/Media/Display.php
/dokuwiki/inc/Ui/MediaDiff.php
/dokuwiki/inc/legacy.php
/dokuwiki/inc/media.php
/dokuwiki/inc/template.php
exe/fetch.php
/dokuwiki/vendor/composer/installed.json
/dokuwiki/vendor/composer/installed.php
/dokuwiki/vendor/splitbrain/slika/README.md
/dokuwiki/vendor/splitbrain/slika/src/Adapter.php
/dokuwiki/vendor/splitbrain/slika/src/GdAdapter.php
/dokuwiki/vendor/splitbrain/slika/src/ImageInfo.php
/dokuwiki/vendor/splitbrain/slika/src/ImageMagickAdapter.php
10287e9925-Jun-2026 Andreas Gohr <andi@splitbrain.org>

Cache: key on resolved base URL instead of the raw Host header

The instruction (.i), render (.xhtml) and metadata cache keys embedded
the client-supplied HTTP_HOST and SERVER_PORT, as did the JS and

Cache: key on resolved base URL instead of the raw Host header

The instruction (.i), render (.xhtml) and metadata cache keys embedded
the client-supplied HTTP_HOST and SERVER_PORT, as did the JS and CSS
dispatchers. A crawler varying the Host header - or a wiki reachable
under several names - thus multiplied every cached artifact per host
value, growing the cache directory without bound.

Instructions and metadata never embed resolved URLs, so they drop the
host component entirely. Rendered output and the JS/CSS bundles key
on DOKU_BASE (plus the SSL flag for JS) instead: fixed when baseurl is
configured, and only varying for genuine multi-domain canonical setups.
Feeds keep host/port keying since their links are always absolute.

This should address the obvious cases mentioned in #4574

show more ...

3e37eccf03-Jul-2026 Andreas Gohr <andi@splitbrain.org>

Harden media manager select callback (defense-in-depth)

The media manager popup derives the select callback name and the target
edit-field id from URL parameters (onselect, edid) and calls
opener[cb

Harden media manager select callback (defense-in-depth)

The media manager popup derives the select callback name and the target
edit-field id from URL parameters (onselect, edid) and calls
opener[cb](edid, ...). Tighten this handling:

- sanitize edid to word characters and hyphens
- strip all non-word characters from the callback name (global replace,
not just the first run)
- refuse to call anything that is not a page-script function, rejecting
browser/JS built-ins such as eval, Function, setTimeout and open

This is a precaution, not a fix for an exploitable vulnerability. In core
the popup is only ever opened by the trusted, same-origin editor, which
builds the URL itself and never sets onselect; a directly loaded popup has
no opener and a cross-origin opener is blocked by the same-origin policy,
so an attacker cannot reach the sink. The change removes the reliance on
that ambient browser protection and guards plugins that open the popup
with their own callback.

show more ...

aa331cf229-Jun-2026 Martin Růžička <martinr@post.cz>

Translation update (cs)

946266a326-Jun-2026 Schplurtz le Déboulonné <Schplurtz@laposte.net>

Translation update (fr)

2848662b25-Jun-2026 splitbrain <86426+splitbrain@users.noreply.github.com>

�� Rector and PHPCS fixes

9af8222925-Jun-2026 Andreas Gohr <gohr@cosmocode.de>

extension: validate base name to prevent path traversal on install

The extension base name flowed unsanitized from an uploaded archive's
plugin.info.txt (or an extension id) into getInstallDir(), wh

extension: validate base name to prevent path traversal on install

The extension base name flowed unsanitized from an uploaded archive's
plugin.info.txt (or an extension id) into getInstallDir(), where
fullpath() collapses '..' segments. A crafted base such as
'../../../../evil' therefore resolved outside lib/plugins/, letting
dircopy() write the archive contents to an arbitrary web-writable path.

Route every base assignment through a new setBase() that rejects
anything other than a bare extension name.

Note: this is not really a security concern since plugins can execute
arbitrary code by design. The is mostly to make sure, plugin code is not
installed accidentally at the wrong location.

show more ...

15751e1825-Jun-2026 Andreas Gohr <gohr@cosmocode.de>

Preserve edid and onselect across media manager search (#4608)

The media manager popup search reloads the whole page, dropping the
edid and onselect parameters that plugins (e.g. struct, prosemirror

Preserve edid and onselect across media manager search (#4608)

The media manager popup search reloads the whole page, dropping the
edid and onselect parameters that plugins (e.g. struct, prosemirror)
rely on to insert media and run their callback. Carry them over in the
search form action URL so they survive the reload, and match them in
media.js regardless of their position in the query string.

show more ...

195a3a7f25-Jun-2026 Andreas Gohr <gohr@cosmocode.de>

make getUserData() fail safely on non-string input

When removing multiple users at once, plugins listening on the
AUTH_USER_CHANGE event may pass the array of user names (params[0]
for 'delete') to

make getUserData() fail safely on non-string input

When removing multiple users at once, plugins listening on the
AUTH_USER_CHANGE event may pass the array of user names (params[0]
for 'delete') to getUserData(), which crashed authplain with an
"Array to string conversion" / illegal offset error.

Guard the bundled auth backends so a non-string user fails safely
by returning false, and document that AUTH_USER_CHANGE params[0] is
a string for create/modify but a string[] for delete.

Fixes #4567

show more ...

6436b0ab25-Jun-2026 Schplurtz le Déboulonné <Schplurtz@laposte.net>

Translation update (fr)

75364f1325-Jun-2026 Marek Adamski <fevbew@wp.pl>

Translation update (pl)

5d71952d16-Jun-2026 Andreas Gohr <andi@splitbrain.org>

Translation update (de)

17acbd0f06-Jun-2026 Andreas Gohr <andi@splitbrain.org>

Cast the ACL permission to an integer when saving the rule table

The bulk update path pulled the permission map straight from input and
wrote each value verbatim into a tab-separated ACL line, while

Cast the ACL permission to an integer when saving the rule table

The bulk update path pulled the permission map straight from input and
wrote each value verbatim into a tab-separated ACL line, while the
single-rule path already read it through an integer filter. A non-integer
value could carry a newline or tab and inject extra rules into the file.
Cast to int so the value can only ever be a single permission number.

This was not exploitable: the rule table is reachable only through the
ACL admin plugin, which is superuser-only and CSRF-protected, and a
superuser can already edit the ACL file directly. The cast is hardening
for consistency with the single-rule path.

show more ...

fa03edf306-Jun-2026 Andreas Gohr <andi@splitbrain.org>

(security) Enforce per-page edit permission in the revert plugin

The revert manager is accessible to managers, not just admins. Its
reversion loop called saveWikiText() for every submitted page id w

(security) Enforce per-page edit permission in the revert plugin

The revert manager is accessible to managers, not just admins. Its
reversion loop called saveWikiText() for every submitted page id without
checking the per-page ACL, relying only on the manager role. A manager
denied edit on a namespace could therefore revert those pages to an
older revision or blank them entirely (low severity).

The page listing already hid unreadable pages, but offered every
readable page for reversion, including ones the manager could not edit.
A hand-crafted POST could also target arbitrary ids regardless of what
the listing showed.

Each id is now cleaned and checked for edit permission before it is
reverted; ids that fail the check are silently skipped. The listing
additionally only offers pages the manager actually has edit permission
on, so the form and the action agree.

show more ...

5d8c9d4206-Jun-2026 Andreas Gohr <andi@splitbrain.org>

(security) Require a security token for the lock AJAX call

The lock AJAX call refreshes the edit lock and saves a draft, both of
which change server state. It was gated only by the write ACL and,
un

(security) Require a security token for the lock AJAX call

The lock AJAX call refreshes the edit lock and saves a draft, both of
which change server state. It was gated only by the write ACL and,
unlike the sibling draft-delete call, did not verify a security token
(low severity).

A cross-site forged POST against a logged-in user could, within that
user's own write permissions, take or hold an edit lock and store
attacker-controlled draft content under their name.

The call now verifies the security token before taking the lock or
saving the draft. Logged out users are unaffected, as no token is
issued or checked for them. The edit lock timer now always sends the
token with its refresh request, including when draft saving is
disabled.

show more ...

aabc478206-Jun-2026 Andreas Gohr <andi@splitbrain.org>

(security) Add CSRF protection and use Form class in popularity plugin

The plugin is accessible to managers, not just admins, and had two
separate issues.

1. Missing CSRF token (low severity)
Th

(security) Add CSRF protection and use Form class in popularity plugin

The plugin is accessible to managers, not just admins, and had two
separate issues.

1. Missing CSRF token (low severity)
The handler accepted the posted data and toggled autosubmit without
checking a security token. A cross-site forged POST against a logged-in
manager could enable autosubmit and trigger a submission of the wiki's
data to the popularity server.
2. Reflected XSS (low severity)
When a submission failed, the posted data was reflected back into a
readonly textarea without escaping. A value closing the textarea early
(eg. </textarea><script>...) could inject script into the manager's
browser.
To exploit this, not only a CSRF attack against an authenticated
manager was needed, also the connection to the DokuWiki popularity
server needed to fail.

The popularity plugin now verifies the security token before it sends
data or toggles the autosubmit option.

The form is now built via the the Form API so the textarea value is
escaped automatically. The security token is emitted automatically.
The fallback browser-submission form posts to an external server and is
built without the security token.

show more ...

3e42782802-Jun-2026 Wizzard <wizzardsk@gmail.com>

Translation update (sk)

7e687fd829-May-2026 Andreas Gohr <andi@splitbrain.org>

fix(auth): scope media ACL checks to the namespace

Media files have no per-file ACLs; permissions must be evaluated against
the namespace they live in. Several call sites passed the raw media ID
to

fix(auth): scope media ACL checks to the namespace

Media files have no per-file ACLs; permissions must be evaluated against
the namespace they live in. Several call sites passed the raw media ID
to auth_quickaclcheck(), so a page-intended exact-ID rule (e.g. on
wiki:secret.png) could silently apply to a media file sharing that ID.

Introduce mediaAclPath() that builds the correct namespace wildcard
path (handling root-namespace media) and route all media-related ACL
checks through it. Also normalize the lone `:X` sentinel variant in
fetch.functions.php to the standard `:*` form.

fixes: #4647

show more ...

1dbc46ac27-May-2026 Tzipirigu <tzipirigu.radu25683@gmail.com>

Translation update (ro)

1536bca224-May-2026 Kishore D Rajegowda <kishore328@gmail.com>

fix(locktimer): reset lock timer on paste and other input events

The lock-timer handler was bound only to `keypress`, which fires for
character key presses but not for paste via right-click menu,
dr

fix(locktimer): reset lock timer on paste and other input events

The lock-timer handler was bound only to `keypress`, which fires for
character key presses but not for paste via right-click menu,
drag-and-drop, or other non-keyboard input methods. Users editing a
page solely by pasting could therefore lose their page lock after the
configured timeout despite active editing.

Switch the binding to the `input` event, which fires on every value
change of the textarea regardless of source (typing, paste via any
method, cut, drag-drop, undo/redo). This is a superset of the previous
behaviour, so no editing action regresses.

Fixes #3714

show more ...

12345678910>>...184