Commit Graph

59299 Commits

Author SHA1 Message Date
Wainui Witika-Park bd1514890b
Update release notes for 25.05.14 release
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-24 15:10:31 +12:00
Wainui Witika-Park 33f0b2ecca
Increment version for 25.05.14 release
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-24 15:07:07 +12:00
Sanjar Tulkinov Anvar o'g'li 1880e0f6f6
Bug 42736: Prevent SQL injection in reports/cat_issues_top.pl
The "Most-circulated items" report built its SQL by concatenating the
Criteria and Filter request parameters directly into the query, with no
bind placeholders and no whitelist on the Criteria identifier. An
authenticated staff user with the reports permission could inject
arbitrary SQL and read any data reachable by the Koha database user.

This validates the Criteria parameter against a fixed allow-list of the
report's own column options (matching reports/cat_issues_top.tt) so it
is safe to use as a SQL identifier, and binds every Filter value with a
placeholder in both the column-header query and the main calculation
query. The Limit parameter is validated as a plain integer.

This mirrors the fix already applied to the sibling
reports/bor_issues_top.pl (bug 42369).

Test plan:
0. Apply the patch
1. koha-plack --restart kohadev
2. Go to Reports > Most-circulated items (reports/cat_issues_top.pl)
3. Run the report with various Criteria and Filter values, confirm the
   output is correct and no errors appear
4. Before the patch, a Filter value or the Criteria containing SQL (a
   single quote followed by a subquery) broke out of the query. After
   the patch, confirm such input is treated as a literal value: you get
   normal output or an empty result, with no SQL error, no delay, and no
   data leak

Signed-off-by: Sanjar Tulkinov Anvar o'g'li <sanjarbiy11@gmail.com>
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Aleisha Amohia <aleisha@catalyst.net.nz>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-19 12:30:41 +12:00
Baptiste Wojtkowski 34fa9f2a7c
Bug 8127: Fix filters use in 'Most-circulated items report'
Filters are broken for many reasons. Previous patch contains some
(little) tidying.
There are 3 parts in this patch:
1 - The column name is incorrectly named in the dropdown for "branch",
  it is added in this patch
2 - There is a definition for 'Day' and 'Month', but not for 'Week', it
is also added in this patch
3 - Dbh variables are passed in the string definition AND in the call. I
removed them from the string definition since it violates the coding
guidelines.

Test plan:

1. On an fresh ktd db, run the script provided here (https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=8127#c3)  to fill the database with checkins/checkouts:

Visit http://your_koha:8081/cgi-bin/koha/reports/cat_issues_top.pl
2. Run a baseline test with following params:
Checkout date from 01/01/2020
Checkout date to: tomorrow
Library: Any library
Fill nothing else

Notice it is works

3. Test with some limits (Library, Week, and any other), notice you encounter errors on Library and Week, and that any other is empty, without error.

4. Apply patch
5. Rerun 2-3 and notice you now have results. Check with each possible limit, limiting to 5. Test once with 10 as a limit.

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-19 12:30:36 +12:00
Baptiste Wojtkowski 6a37415774
Bug 8127: Remove useless commented warns
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-19 12:30:28 +12:00
Amit Gupta b0def4443d
Bug 42904: Prevent XSS in patron restriction comments
Test plan

1. Search for a patron and open the patron details page.
2. Under "Patron restrictions", add a manual restriction with the following comment:
   <img src=x onerror="alert(document.domain)">
3. Save the restriction.
4. Navigate to the patron checkouts page:
   /cgi-bin/koha/circ/circulation.pl?borrowernumber=xxx
   Verify that the JavaScript payload executes.
5. Edit the patron record:
   /cgi-bin/koha/members/memberentry.pl?op=edit_form&destination=circ&borrowernumber=xxx
   Verify that the JavaScript payload executes.
6. For OPAC - Go to OPAC Verify that the JavaScript payload executes - /cgi-bin/koha/opac-user.pl
7. Apply the patch.
8. Repeat steps 4, 5 and 6.
9. Verify that:
   1. No JavaScript is executed.
   2. The page loads normally without any alert dialog. Applicable for both the staff and opac.

Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-18 16:34:23 +12:00
Martin Renvoize 787343b8d9
Bug 42800: (QA follow-up) Fix backslash breaking the shelf list script block
erm.tt built the logged_in_user_lists JS array by manually
interpolating each shelf's id/name into a JS string literal, escaped
with the TT html filter:

    id: "[% shelf.shelfnumber | html %]",
    name: "[% shelf.shelfname | html %]",

The html filter escapes <, >, &, and " -- enough to stop the
<script>-tag and </script>-breakout scenario from the original bug --
but it does not escape backslashes. A list name ending in a backslash
(e.g. "foo\") escapes the closing quote of the JS string literal,
unbalancing it and throwing a JS syntax error that breaks the whole
inline <script> block on every ERM page (including the unrelated
`const logged_in_user = ...` a few lines below), reproducing the
"broken UI" half of the original bug via a different character.

Build the id/name pairs as an actual array of hashes and JSON-encode
them with To.json(), after escaping each value with the html
vmethod. JSON encoding (via the JSON module) correctly escapes
backslashes and quotes for use inside a JS string, while keeping the
values HTML-escaped so they stay inert if ever written into the DOM
via innerHTML (as the DataTables render callback in
EHoldingsLocalTitlesFormImport.vue does).

Test plan:
1. Enable the ERMModule system preference.
2. Create a list named: backslash test \
3. Go to /cgi-bin/koha/erm/eholdings/local/titles/import (or any
   other ERM page).
   => Without this patch: the page's inline script throws a syntax
      error ("Invalid or unexpected token") and
      "logged_in_user_lists is not defined", breaking the Vue
      component.
   => With this patch: the page loads without errors and the list is
      shown correctly in the table.
4. Also verify the original bug's script-tag scenario still works:
   create a list named <script>alert("booh!");</script> and confirm
   it displays as inert text, not executing, on the same pages.

Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-18 16:12:41 +12:00
Jonathan Druart cabee467b8
Bug 42800: Fix XSS in shelf list in the ERM module
const logged_in_user_lists = [% To.json(logged_in_user.virtualshelves.unblessed) | $raw %];

If you have a script tag in a list name the UI will be broken, and there
is potentially a XSS vulnerability

Test plan:
Create a new list with name="<script>alert("booh!");</script>"
Go to /cgi-bin/koha/erm/eholdings/local/titles/import
or any ERM views
=> Without this patch the UI is broken
=> With this patch applied it's not and the table is correctly populated
with the lists

Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-18 16:09:45 +12:00
Wainui Witika-Park 133ca5e4a5
RMAINT followup for Bug 42847 - remove extra parentheses
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-18 16:00:18 +12:00
Martin Renvoize 5f57b6d6f8
Bug 30233: (follow-up) Fix POD formatting codes in _apply_substitution
The angle-bracket delimiter notation in the POD prose (e.g.
PATTERN<DELIM>) caused the POD parser to treat the trailing letter of
each word as an unknown formatting code (N<>, T<>). Replace with
C<s/PATTERN/REPLACEMENT/FLAGS> and a parenthetical note that any
non-space delimiter is accepted.

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Baptiste Wojtkowski <baptiste.wojtkowski@biblibre.com>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-14 13:32:59 +12:00
Martin Renvoize dc5b1e140b
Bug 30233: (follow-up) Add tests for _apply_substitution and combined modifiers
- t/C4/ClassSplitRoutine/RegEx.t (new): exercises _apply_substitution via
  the public split_callnumber interface — basic substitution, alternate
  delimiters, \n/$n backrefs, /gi combined flag, /e rejection, and malformed
  or uncompilable rules (including the new logger warn path).
- t/Koha/Regex/Replacement.t: extend the subst() helper to handle the ig/gi
  combined modifier and add a subtest that confirms case-insensitive global
  replacement and backref case preservation.

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Baptiste Wojtkowski <baptiste.wojtkowski@biblibre.com>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-14 13:32:54 +12:00
wainuiwitikapark e3bfd193c3
RMAINT perltidy C4/SIP/Sip/MsgType.pm and t/db_dependent/SIP/MsgType.t from Bug 42847
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-14 12:53:35 +12:00
Marcel de Rooy a34e362d6d
Bug 43085: Fix typo in data/marc21_field_006.xml
It reads position 12-18 and "six positions". Since the length is
18, the final position is 17.

Test plan:
Test 006 plugin in basic editor.
Switch type of material to CF (computer files).
Check length of 006 in editor when saving the 006 form.

Note: this patch is cherry-picked from Bug 40284

Sponsored-by: Toi Ohomai Institute of Technology
Signed-off-by: Lawrence O'Regan-Lloyd
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-12 13:04:05 +12:00
Wainui Witika-Park 28f672102f
Update release notes for 25.05.13 release
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-05 16:38:06 +12:00
Wainui Witika-Park c40999f7d8
Increment version for 25.05.13 release
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-05 16:33:35 +12:00
Wainui Witika-Park 0dff1745ae
Merge remote-tracking branch 'upstream/25.05.x' into HEAD 2026-08-05 16:20:01 +12:00
Martin Renvoize 41f07ab8a4
Bug 42471: [25.05] (follow-up) prevent XSS in suggestion status
The custom/authorized-value status branch concatenated row.status
directly into a class="..." attribute string. escape_str() only
escapes &, <, > (not quotes), so a status code containing a double
quote could still break out of the attribute.

Build the status <span> via DOM APIs instead, the same way the
reason field was fixed: fixed statuses get a hardcoded class, and
the free-form status code goes into a data-status attribute via
dataset, which the DOM escapes safely regardless of content.

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-05 15:56:36 +12:00
David Cook c80ddfab7a
Bug 42471: [25.05] (follow-up) prevent XSS in suggestion reason
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-05 15:56:32 +12:00
Jonathan Druart c0ce4d57cd
Bug 42471: [25.05] Prevent XSS in suggestion.tt
escape_str all the things

Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-05 15:56:26 +12:00
Martin Renvoize d413403825
Bug 42746: (QA follow-up) Sanitize agefield and substitution field at the sink too
The original fix only whitelisted agefield, condition_field, and
substitution_field at the point they're saved in
tools/automatic_item_modification_by_age.pl, leaving the actual
consumer of the stored syspref, C4::Items::ToggleNewStatus, trusting
agefield and substitution field unchecked. agefield is spliced
directly into raw SQL (TO_DAYS($agefield)) and so can't be
parameterized like an ordinary value; substitution field reaches a
dynamic method call ($item->$field($value)). Any future or
alternate writer of the automatic_item_modification_by_age_configuration
syspref would have reopened both holes without touching the form at
all.

This adds the same allow-list validation directly in ToggleNewStatus
(falling back to the safe default agefield, or skipping the
substitution/condition, exactly as before for missing values), shares
the age-field allow-list between the two files via a new
GetAutomaticItemModificationAgeFields() in C4::Items so it can't drift
between them, and logs rejected values via Koha::Logger instead of
silently discarding them so tampering leaves an audit trail.

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-05 15:41:06 +12:00
Jonathan Druart 1d419a33c0
Bug 42746: Sanitize condition and substitution fields
Signed-off-by: Sanjar Tulkinov Anvar o'g'li <sanjarbiy11@gmail.com>

Amended-by: Jonathan Druart:
Replace , with ;

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-05 15:41:02 +12:00
Jonathan Druart 2b52eb2bcb
Bug 42746: Sanitize age_field
Signed-off-by: Sanjar Tulkinov Anvar o'g'li <sanjarbiy11@gmail.com>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-05 15:40:57 +12:00
Martin Renvoize 5e3741d0e5
Bug 42747: (QA follow-up) Parameterize query, dedupe, and log rejections
The original fix only whitelisted image_name at the point it's saved
in edit-layout.pl, leaving the actual injection sink in create-pdf.pl
unparameterized. This adds defense-in-depth by fixing the query itself,
avoids a redundant duplicate call to get_all_image_names() (already
fetched earlier in the script as $image_names), and logs rejected
image_name values instead of silently discarding them so tampering
attempts leave an audit trail.

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-05 15:18:23 +12:00
Jonathan Druart 32b9364b06
Bug 42747: Prevent SQL injection via image_name in edit-layout
Signed-off-by: Sanjar Tulkinov Anvar o'g'li <sanjarbiy11@gmail.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-05 15:18:15 +12:00
Jonathan Druart 4117fdd35a
Bug 42866: Prevent SQL injection in Koha::AddtionalContents->search_for_display
Signed-off-by: Sanjar Tulkinov Anvar o'g'li <sanjarbiy11@gmail.com>

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-05 14:40:41 +12:00
Jonathan Druart e8d39513ea
Bug 42749: Prevent SQL injection from GetInvoices (order_by)
Signed-off-by: Sanjar Tulkinov Anvar o'g'li <sanjarbiy11@gmail.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-05 14:24:13 +12:00
David Cook bc07155f03
Bug 42847: [24.11] Fix unit test
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-05 14:16:39 +12:00
Kyle M Hall 498c85b62a
Bug 42847: [24.11] Prevent previously authenticated user (squashed)
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-05 14:16:32 +12:00
Laura_Escamilla afdbbd117e
Bug 43019: Prevent access to pages belonging to another library (staff side)
To test:
1. Create two patron accounts:
    * One patron whose home library matches the library assigned to the page.
    * One patron whose home library is different from the library assigned to the page.
2. Create a new page with the following settings:
    * Display location = OPAC
    * Library = a specific library
    * Publication date = Today
    * Title and Content = minimally necessary content
3. Save the page.
4. Right-click the OPAC link and copy the link address.
5. Open the link in an incognito or private browser window without signing in.
    * Confirm that the library-specific page is not displayed.
    * Confirm that a 404 page is shown.
6. In the incognito window, sign in using the patron account whose home library matches the page library.
7. Open the copied OPAC link again.
    * Confirm that the page is displayed.
8. Sign out and sign in using the patron account whose home library does not match the page library.
9. Open the copied OPAC link again.
    * Confirm that the page is not displayed.
    * Confirm that a 404 page is shown.
10. Edit the page and change Library to All libraries.
11. Open the OPAC link in an incognito or private browser window without signing in.
    * Confirm that the page is displayed.
12. While signed in as each patron account, open the OPAC link again.
    * Confirm that the page is displayed for patrons from both libraries.
13. Create or edit a page with the following settings:
    * Display location = Staff interface
    * Library = a specific library
    * Publication date = Today
    * Title and Content = minimally necessary content
14. Sign in to the staff interface using a staff account whose library matches the page library.
15. Open the page from the staff interface.
    * Confirm that the page is displayed.
16. Sign out and sign in using a staff account whose library does not match the page library.
17. Open the staff page link directly.
    * Confirm that the page is not displayed.
    * Confirm that a 404 page is shown.
18. Edit the staff page and change Library to All libraries.
19. Open the page while signed in with staff accounts from both libraries.
    * Confirm that the page is displayed for both accounts.
20. Repeat the OPAC and staff interface checks using Display location = Staff interface and OPAC.
    * Confirm that the page is displayed in both interfaces for users from the matching library.
    * Confirm that users from a different library receive a 404 page.
    * Confirm that pages assigned to All libraries are available in both interfaces.

Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-04 14:01:22 +12:00
David Cook fad32519c1
Bug 43019: Fix branch comparison
This change fixes the branch comparison between the Page
and the user. Previously, it was doing a numeric "!=" and now it
does the string comparison "ne". Also, if no environmental variable
is set for the default branch, it defaults to an empty string
for anonymous (ie non-authenticated) users.

Test plan:
0. Apply the patch
1. restart_all
2. Log into the staff interface
3. Go to Tools
4. Click on "Pages"
5. Create a Page for All Libraries for the OPAC
6. Copy the "OPAC" link in the "Page URL" table cell and open it
in a private window or a separate browser
7. Note that the page appears
8. Now change the "Page" to a specific library
9. Revisit the URL in the private window
10. Note that it now gives a 404 error
11. Log into the OPAC with a user whose library matches the libary
of the Page
12. Note that now you can view the URL again
13. Change the library of the user or the Page
14. Note that you cannot see the Page now

Signed-off-by: Phil Ringnalda <phil@chetcolibrary.org>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-08-04 13:45:36 +12:00
Martin Renvoize 9474e9e359
Bug 30233: (follow-up) Log a warning when _apply_substitution discards a bad pattern
When eval { qr/$pattern/ } fails (e.g. the admin-configured s/// contains
an invalid regex), _apply_substitution previously returned silently with no
indication of why the rule was skipped. Add a Koha::Logger warn so the
failure appears in the log and is diagnosable without a debugger.

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Baptiste Wojtkowski <baptiste.wojtkowski@biblibre.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-30 15:54:03 +12:00
David Cook cc6af33c1b
Bug 30233: (follow-up) fix some errors reported by QA tools
Note: While the methodology in Koha::Regex::Replacement may seem
bespoke, it's similar to how Python's re.sub(pattern, repl, string)
regex substitution works.

Unit tests:
prove -v t/Koha/Regex/Replacement.t \
    t/SimpleMARC.t \
    t/db_dependent/MarcModificationTemplates.t \
    t/Labels_split_Regex.t

Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Baptiste Wojtkowski <baptiste.wojtkowski@biblibre.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-30 15:53:54 +12:00
Sanjar Tulkinov Anvar o'g'li 0c718157be
Bug 30233: Stop running call number split regexes as code
C4::ClassSplitRoutine::RegEx::split_callnumber ran the admin-configured rule
through eval "\$cn_item =~ $regex", executing arbitrary Perl. Parse the
rule as s<DELIM>PATTERN<DELIM>REPLACEMENT<DELIM>FLAGS, reject the /e flag,
compile the pattern with qr// and expand the replacement as data via
Koha::Regex::Replacement::expand_template, so the rule is applied without
eval.

Signed-off-by: Sanjar Tulkinov Anvar o'g'li <sanjarbiy11@gmail.com>
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Baptiste Wojtkowski <baptiste.wojtkowski@biblibre.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-30 15:53:48 +12:00
Sanjar Tulkinov Anvar o'g'li 82a117c87b
Bug 30233: Stop running MARC modification replacements as code
Koha::SimpleMARC::_modify_values and Koha::Items::apply_regex wrapped the
user replacement in a string and ran it through s///ee, so an interpolation
block such as \@{[ system(...) ]} executed arbitrary Perl. Expand the
replacement as data via Koha::Regex::Replacement::expand_template under a
single /e instead, which keeps capture-group replacements working but never
runs the input as code.

Signed-off-by: Sanjar Tulkinov Anvar o'g'li <sanjarbiy11@gmail.com>
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Baptiste Wojtkowski <baptiste.wojtkowski@biblibre.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-30 15:53:43 +12:00
Sanjar Tulkinov Anvar o'g'li b0298e02ca
Bug 30233: Add Koha::Regex::Replacement to expand replacements as data
Add a small single-pass helper, Koha::Regex::Replacement::expand_template,
that expands a user-supplied regex replacement string as data: numbered
backreferences ($1..$n, ${n}, the legacy \1..\9 form), named captures
($+{name}, ${name}) and the \n \r \t escapes. Every other character is
copied through literally, so \@{...}/${...} interpolation blocks end up as
text rather than being run. This is used to replace the s///ee double-eval.

The routine is fully qualified at the call sites rather than exported, and
case folding is left out to keep it small.

Signed-off-by: Sanjar Tulkinov Anvar o'g'li <sanjarbiy11@gmail.com>
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Baptiste Wojtkowski <baptiste.wojtkowski@biblibre.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-30 15:53:18 +12:00
wainuiwitikapark 9ec3a6bb7e
RMAINT perltidy Koha/Suggestion.pm from Bug 42723
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-23 15:16:41 +12:00
Owen Leonard e8fffb0535
Bug 42441: Remove event attributes from authority merge template
This patch moves a couple of "onclick" event attributes from the
authority merge template, moving the event handling to the JS block.

This patch also fixes the behavior that I assume the click handlers are
meant to have, changing the framework selection. A mismatch of IDs in
the code meant that clicking the radio buttons didn't do anything.

To test, apply the patch and go to Authorities.

- Perform a search for authority records which will return multiple
  results, including records with different heading types (e.g. Personal
  Name, Topical Term, etc.)
- In the "Actions" menu for one of the search results, click "Merge"
- Do the same with another result which has a different heading type.
- On the "Merging records" page you should see a frameowrk dropdown.
- When you click the radio buttons next to your two records to merge the
  framework selection should change to match your selection.

Sponsored-by: Athens County Public Libraries
Signed-off-by: Phil Ringnalda <phil@chetcolibrary.org>

Amended-by: Jonathan Druart
Tidy

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
(cherry picked from commit 71559d0909)
Signed-off-by: Baptiste Wojtkowski <baptiste.wojtkowski@biblibre.com>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-22 12:46:19 +12:00
Owen Leonard 9c685ef0eb
Bug 42154: Bug 38714 hid the "New match check" link in record matching rules
This patch corrects the logic used to determine whether to show the "New
match check" link. I mistakenly changed it to check for the matchpoints
variable instead of the matchchecks variable.

To test, apply the patch and go to Administration -> Record matching
rules.

- Click "New record matching rule" in the toolbar.
- Scroll down to the "Required match checks" section.
- You should see a "New match check" link alongside a "Remove this match
  check" link.
- Go back to the record matching rules main page.
- If necessary, create a rule which doesn't have any match checks.
- In the "Required match checks" section of the edit form you should see
  a "New match check" link, previously hidden by Bug 388714.

Sponsored-by: Athens County Public Libraries
Signed-off-by: David Nind <david@davidnind.com>

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
(cherry picked from commit d27639707f)
Signed-off-by: Baptiste Wojtkowski <baptiste.wojtkowski@biblibre.com>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-22 12:19:03 +12:00
Emmi Takkinen fd20081429
Bug 29768: Do not hide guarantor name from memberentry.pl
Syspref "hidepatronname" currently hides guarantors
name on memberentry.pl. This is inconsistent since name isn't hidden e.g. on moremember.pl and staff
can already see patrons other personal information
during edit.

To test:
1) Disable syspref "hidepatronname"
2) Edit guarantee patrons information
=> Field "Guarantor" only shows guarantors cardnumber (or
is empty if guarantor has no cardnumber)
3) Apply patch
=> Guarantors name is now displayed (as a hyperlink)

Also confirm  hidepatronname still works as expected
on other pages (holds table, items detail page etc.).

Sponsored-by: Koha-Suomi Oy
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
(cherry picked from commit 4e6e7bd914)
Signed-off-by: Jacob O'Mara <Jacob.omara@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-21 15:13:26 +12:00
Emily Lamancusa 8f720fc813
Bug 41999: Search all data in suggestion column
Include all displayed fields in the DataTables-searchable data for the
Suggestion column of the suggestions table

To test:
1. Go to Acquisitions > suggestions
2. Create a new suggestion for your logged-in library. Be sure fill out
   all of the following fields:
   Title
   Author
   Copyright date
   ISBN or ISSN
   Publisher
   Publication place
   Collection title
   Document type
   Notes
3. Save the suggestion. Confirm that you see the new suggestion in the
   purchase suggestions table.
4. Using the "search" field above the table, search for a word in the
   title
--> Confirm that the purchase suggestion from step 2 is still shown
5. Clear the "search" field and search for the author's first or last
   name
--> Confirm that the suggestion from step 2 is still shown
6. Use the "search" field to search for each of the other pieces of
   information filled out in step 2
--> Confirm that the suggestion is still shown for each search

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
(cherry picked from commit bf7522b67c)
Signed-off-by: Jacob O'Mara <Jacob.omara@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-21 15:06:02 +12:00
Casey Conlin a6960bf097
Bug 42359: Fix Guided.t update_sql test input
The test was feeding update_sql object field names instead of the parameter names it actually expects.
This let savedsql get cleared during the update.
The test was updated to pass the expected inputs so it still checks cache_expiry without creating the warning in the delete log path.

Test plan:
1. Confirm the issue by enabling the ReportsLog preference in Koha UI andin ktd shell running prove t/db_dependent/Reports/Guided.t
2. Apply the patch.
3. Run the tests again with prove t/db_dependent/Reports/Guided.t
4. The tests should pass.
5. Disable the preference and run again.
6. Tests should pass.
7. Sign off if steps above check out.

Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
(cherry picked from commit d09c65d047)
Signed-off-by: Jacob O'Mara <Jacob.omara@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-21 14:31:06 +12:00
Kevin Carnes 8d6bcefd46
Bug 21941: Fix GROUP BY in circ/reserveratios.pl
When using strict_sql_modes, the Hold ratios page causes an Incorrect
GROUP BY error and returns an Error 500.

This patch removes uncessary columns from the database query and adds
the biblio columns to the GROUP BY statement, so they can be selected.
Since it's already grouped by biblionumber, it should not cause any
additional rows to be created.

Test plan:
1. Make sure that strict_sql_modes is enabled in the koha-conf.xml
   file.
2. Place at least one hold on a book.
3. Go to Circulation and select Hold ratios.
4. Observe that you get an Error 500.
5. Apply patch.
6. Repeat step 3.
7. Observe that you can view the page.
8. If the table is empty, change the ratio to 1.
9. Sign off.

Sponsored-by: Lund University Library
Signed-off-by: Owen Leonard <oleonard@myacpl.org>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
(cherry picked from commit ea4600476e)
Signed-off-by: Jacob O'Mara <Jacob.omara@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-21 14:26:09 +12:00
Andrew Fuerste Henry be019f4f92
Bug 41292: Rename whitelist to allowlist and add force_password_reset_when_set_by_staff
To test:
1 - Attempt to save a report containing "select force_password_reset_when_set_by_staff from categories"
2 - observe koha prevents this save
3 - apply patch, restart services
4 - repeat step 1
5 - observe your report now saves and runs successfully

While adding this new field to the list of allowed fields, I changed "whitelist" to "allowlist" as suggested by the terminology guide: https://wiki.koha-community.org/wiki/Terminology

Signed-off-by: David Nind <david@davidnind.com>

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
(cherry picked from commit fdc57489a1)
Signed-off-by: Jacob O'Mara <jacob.omara@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-21 14:20:17 +12:00
Ayoub Glizi-Vicioso 129cc9054b
Bug 41967: Ensure --cards argument accepts an integer in cleanup_database.pl
Test plan (for --cards arguments) :

1. Initial Setup:
    a) Go to Tools > Patron card creator > New > Card batch
    b) Create two different batches (Batch 1 and Batch 2) using the 'Add by borrowernumber(s):' option.
        If using **KTD** you can use the following borrowernumbers for both batches:
            15
            29
            47
        else you will need to create your own patrons and enter their borrowernumber.
    c) In your terminal, set the timestamps manually:
        --OPTION A (KTD users):
            ktd --shell
            koha-mysql kohadev

        --OPTION B:
            Access your database

        Then:
            UPDATE creator_batches SET timestamp = DATE_SUB(NOW(), INTERVAL 30 DAY) WHERE batch_id = '1';
            UPDATE creator_batches SET timestamp = DATE_SUB(NOW(), INTERVAL 5 DAY) WHERE batch_id = '2';

    Note: your batch_id may differ.

2. Before Applying the Patch:
    a) Run the following cleanup script:
        ./misc/cronjobs/cleanup_database.pl --cards 15 --confirm --verbose
    b) Error in console output
    c) Nothing is deleted even though one batch was older than 15 days
        SELECT * FROM creator_batches;

3. Apply The Patch

4. After Applying The Patch:
    a) Redo step 1 (Initial Setup).
    b) Run again the following cleanup script:
        ./misc/cronjobs/cleanup_database.pl --cards 15 --confirm --verbose
    c) Check that the console output says: "Purging ... more than 15 days ago"
    d) Batch 1 is deleted, but Batch 2 (5 days old) is STILL PRESENT. Success!
        SELECT * FROM creator_batches;

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Thomas Klausner <domm@plix.at>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
(cherry picked from commit 0c2ef0e6b4)
Signed-off-by: Jacob O'Mara <Jacob.omara@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-21 14:14:31 +12:00
Ayoub Glizi-Vicioso 6261325bbd
Bug 41967: Ensure --labels argument accepts an integer in cleanup_database.pl
Test plan :

1. Initial Setup:
    a) Go to Cataloging > Label creator > New > Label batch
    b) Create two different batches (Batch 1 and Batch 2) using the 'Add by barcodes or itemnumbers' option.
        If using **KTD** you can use those barcodes for the two batches:
            39999000010114
            39999000010138
            39999000010152
        else you will need to create your own records with items and enter their barcodes.
    c) In your terminal (in a ktd --shell), set the timestamps manually:
        --OPTION A (KTD users):
            ktd --shell
            koha-mysql kohadev

        --OPTION B:
            Access your database

        Then:
            UPDATE creator_batches SET timestamp = DATE_SUB(NOW(), INTERVAL 30 DAY) WHERE batch_id = '1';
            UPDATE creator_batches SET timestamp = DATE_SUB(NOW(), INTERVAL 5 DAY) WHERE batch_id = '2';

    Note: your batch_id may differ.

2. Before Applying the Patch:
    a) Run the following cleanup script:
        ./misc/cronjobs/cleanup_database.pl --labels 15 --confirm --verbose
    b) Check that the console output says: "Purging ... more than 1 days ago"
    c) Check database and notice that it is now empty, even though one set was less than 15 days old.
        SELECT * FROM creator_batches;

3. Apply The Patch

4. After Applying The Patch:
    a) Redo step 1 (Initial Setup).
    b) Run again the following cleanup script:
        ./misc/cronjobs/cleanup_database.pl --labels 15 --confirm --verbose
    c) Check that the console output says: "Purging ... more than 15 days ago"
    d) Batch 1 is deleted, but Batch 2 (5 days old) is STILL PRESENT. Success!
        SELECT * FROM creator_batches;

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Thomas Klausner <domm@plix.at>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
(cherry picked from commit 9e05ca0e19)
Signed-off-by: Jacob O'Mara <Jacob.omara@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-21 14:08:17 +12:00
Pedro Amorim 4e83b669a5
Bug 41861: Update how cost and price_paid show
1) Enabled ILLModule
2) Create a new ILL request, set a title, '42' for cardnumber and any library:
<staff_url>/cgi-bin/koha/ill/ill-requests.pl?method=create&backend=Standard
3) (k-t-d required, cost is not editable in UI, but backends may set it) Run the following query:
koha-mysql kohadev
update illrequests set cost = 1;
4) Notice cost shows, now run the same but set to 0:
update illrequests set cost = 1;
5) Notice it doesn't show.
6) Apply patch. Refresh. Notice is shows '0' now.

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Edith Speller <edith.speller@ukhsa.gov.uk>
Signed-off-by: Baptiste Wojtkowski <baptiste.wojtkowski@biblibre.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
(cherry picked from commit 041fa90a0d)
Signed-off-by: Jacob O'Mara <Jacob.omara@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-21 13:57:01 +12:00
Martin Renvoize fd9be777fb
Bug 41510: (RM follow-up) Perltidy a missed file at merge time
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
(cherry picked from commit 7fd796d8f8)
Signed-off-by: Jacob O'Mara <Jacob.omara@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-21 13:43:17 +12:00
Paul Derscheid 327cb59546
Bug 41510: Handle undefined itemtype in item->effective_bookable
- Guard against undefined itemtype before calling ->bookable on it
- Return 0 (not bookable) when no itemtype is found and item-level
  bookable is not defined

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
(cherry picked from commit 99410bc27c)
Signed-off-by: Jacob O'Mara <Jacob.omara@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-21 13:43:13 +12:00
Paul Derscheid 00457f7e73
Bug 41510: Add test for effective_bookable with missing itemtype
- Add test case for the scenario where an item has no itemtype
  because both items.itype and biblioitems.itemtype are NULL
- Note: We must set biblioitems.itemtype to NULL before creating the
  item because Koha::Item->store() automatically populates itype from
  biblioitems.itemtype when itype is not set

Test plan:
- Apply this patch only
- Run: prove t/db_dependent/Koha/Item.t :: effective_bookable
- Verify test 6 FAILS with "Can't call method 'bookable' on an
  undefined value"
- Apply the follow-up patch
- Run the test again
- Verify all tests PASS

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
(cherry picked from commit 26ffc16c38)
Signed-off-by: Jacob O'Mara <Jacob.omara@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-21 13:43:07 +12:00
Emily Lamancusa b3f525497b
Bug 41386: (QA follow-up) Make sure charge is defined
Check that $charge is defined before comparing, to avoid "argument isn't
numeric" error if no charge is defined.

Signed-off-by: Emily Lamancusa <emily.lamancusa@montgomerycountymd.gov>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
(cherry picked from commit 699ba06eb7)
Signed-off-by: Jacob O'Mara <Jacob.omara@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
2026-07-21 12:56:39 +12:00