commit 329665c14241c7bd8f03fbc4cd3dd352f2c0ae5c Author: Lucas Gass Date: Wed Aug 12 22:55:18 2026 +0000 Bug 43283: Change event handler to work on all dT pages To test: 1. Have 25+ patron lists w/ at least 1 borrower 2. On the list of patron lists page ( lists.tt ) use the Actions button to choose 'Print patron cards' 3. On the first dT page it should open in modal ( good ) 4. On any subsquent pages it will not open in a modal and you cannot export the file ( bad ) 5. APPLY PATCH 6. Try again. The 'Print patron cards' should open in a modal on every page Signed-off-by: George Williams commit 662020e21b7c70c4d93a96c0abb2ae89ef5f3302 Author: Pedro Amorim Date: Thu Aug 13 10:07:41 2026 +0000 Bug 42714: RM follow-up: Fix tests prove t/00-load.t prove xt/author/pod_coverage.t Signed-off-by: Pedro Amorim commit 55bc6f01e0f3500496e4493fac257e638f0e758e Author: Owen Leonard Date: Thu Aug 6 13:07:26 2026 -0400 Bug 41842: (follow-up) Ensure that tidy doesn't trim wanted whitespace Signed-off-by: Owen Leonard Signed-off-by: Pedro Amorim commit 1b00485b275d26d7e22607babf9ac403071359e0 Author: Owen Leonard Date: Thu Jun 25 06:53:57 2026 -0400 Bug 41842: (follow-up) Make sure this space doesn't get tidied Signed-off-by: Owen Leonard Signed-off-by: Pedro Amorim commit 3cd648d52f714bc26fb60eff1daf8c11bd489bdf Author: Martin Renvoize Date: Thu Jun 25 10:55:05 2026 +0100 Bug 41842: Use space-dash-space separator between course name and section The staff interface templates were using a bare hyphen with no spaces when displaying course name and section together, while the OPAC templates (Bug 42654) use ' - ' (space-dash-space). This brings the staff interface into alignment with the OPAC convention for consistency and readability. Signed-off-by: Martin Renvoize Signed-off-by: Owen Leonard Signed-off-by: Pedro Amorim commit 303ba57409de25250f6951e79c6ed36ebdb2f788 Author: Owen Leonard Date: Fri Feb 13 08:40:24 2026 -0500 Bug 41842: Improve translation of course reserves headings This patch adds some use of I18N functions to course reserves templates in order to improve the process of translation by adding context and placeholders. The patch also rewords some headings for clarity and consistency. To test, apply the patch and go to course reserves. - Add a course if necessary. - Click the course to view it. - On the course details page, confirm that the page title, breadcrumbs, and heading look correct. - Click "Edit" in the toolbar. - Check the page title, breadcrumbs, and heading again. - Return to the course details and click "Add reserves" and check that page. - Submit a barcode or biblionumber and check that page. - Test the "Batch add reserves" page. To test the improved I18N, apply the patch and test that the correct strings are translatable. In this example I'm testing fr-FR: - Update a translation: > gulp po:update > cd misc/translator > perl translate update fr-FR - Open the corresponding .po file for the modified strings, e.g. fr-FR-messages.po. - Locate strings pulled from course reserves templates for translation, e.g.: #: koha-tmpl/intranet-tmpl/prog/en/modules/course_reserves/course.tt:10 #: koha-tmpl/intranet-tmpl/prog/en/modules/course_reserves/course.tt:42 #: koha-tmpl/intranet-tmpl/prog/en/modules/course_reserves/course.tt:56 #, fuzzy, perl-brace-format msgid "Edit course {course_name}" msgstr "Modifier {course_name}" - Remove the "fuzzy," - Edit the "msgstr" string however you want (it's just for testing) - Install the updated translation: > perl translate install fr-FR Switch to the translation you updated. Walk through the process of editing a course and adding course reserves to confirm that your translated strings show up. Sponsored-by: Athens County Public Libraries Signed-off-by: David Nind Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit 4960d6987d839e5364b4c4c61712354500b87fef Author: Pedro Amorim Date: Wed Aug 12 14:59:20 2026 +0000 Bug 42973: (RM follow-up) Update tests number Because of bug 42866 prove t/db_dependent/Koha/AdditionalContents.t Signed-off-by: Pedro Amorim commit 89f6fcc4cd1403a3653286e4bb78a7060a3a7285 Author: Laura Escamilla Date: Wed Jul 1 17:17:45 2026 +0000 Bug 42973: Unit test Added a unit test to confirm that search_for_display orders manually positioned news first, followed by unnumbered news by publication date descending. Test passes: prove t/db_dependent/Koha/AdditionalContents.t Signed-off-by: Gretchen Maxeiner Signed-off-by: David Cook Signed-off-by: Pedro Amorim commit 70caff963ab22380e6609162814a748d0ceeabf9 Author: Laura Escamilla Date: Wed Jul 1 16:25:56 2026 +0000 Bug 42973: Restore manual ordering for news To test: 1. Create four OPAC news items: - "Pinned news item" with "Appear in position" = 1 and an older publication date. - "Newest unnumbered news item" with no position and the newest publication date. - "Middle unnumbered news item" with no position and an intermediate publication date. - "Oldest unnumbered news item" with no position and the oldest publication date. 2. View the OPAC main page. 3. Confirm the news items are ordered by publication date, with the newest item first. Apply the patch. 4. Reload the OPAC main page. 5. Confirm the manually positioned news item appears first. 6. Confirm the remaining news items are ordered by publication date descending. 7. Confirm news items without an "Appear in position" value continue to display newest first. 8. Sign off and have a wonderful day! Signed-off-by: Gretchen Maxeiner Signed-off-by: David Cook Signed-off-by: Pedro Amorim commit bb53e653f3d37f1a5e86724ed036a060889d80f2 Author: Katrin Fischer Date: Sun Aug 9 14:15:17 2026 +0000 Bug 43239: (QA follow-up) Rephrase hint on subscription form This is to clarify that the item's current item type will not be changed, no matter what settings have been used in the subscription. Signed-off-by: Katrin Fischer Signed-off-by: Pedro Amorim commit 5005019b5d4367a8e8ae3b22d5ea1116fea900d3 Author: David Nind Date: Sat Aug 8 20:57:22 2026 +0000 Bug 43239: (follow-up) Update wording for hint Signed-off-by: David Nind Signed-off-by: Katrin Fischer Signed-off-by: Pedro Amorim commit 02515ebcc764345d0c7705dbada97d7755e97291 Author: Emmi Takkinen Date: Thu Aug 6 13:37:13 2026 +0300 Bug 43239: Preserve item item type if previousitemtype column is undefined It is possible to create serial item with wrong itemtype if syspreference makePreviousSerialAvailable is enabled and field "item type for older issues" isn't filled when creating a subscription for biblio record. This happens when multiple items are created. In installations where itemtypes differ between items and biblios, this causes data inconsistencies and leads to errors in biblios Holdings table. This patch changes behaviour of serials-edit.pl so that if makePreviousSerialAvailable is enabled and subscriptions previousitemtype column is NULL, previous serial items itype column is preserved. It also adds a hint text to subscription form about this change. To test: 1. Enable systempreference makePreviousSerialAvailable. 2. Create new biblio record. 3. Create a new subscription for biblio record you made, select option "Create an item record", select different item type from "Item type" selection than biblio record has but leave selection "item type for older issues" empty. 4. Receive a serial item for subscription. Check from biblio records Holdings table that its item type matches item type selected in step 3. 5. Now receive 3 serial items. After creating them check Holdings table again. => Note that first item created now has same item type as biblio record. 6. Apply this patch, restart services. 7. Create new subscription, fill needed fields as in step 3. => Note that there is a new hint text after field "item type for older issues". 8. Repeat steps 4. and 5. => Note that now all items have same item type. Sponsored-by: Koha-Suomi Oy Signed-off-by: David Nind Signed-off-by: Katrin Fischer Signed-off-by: Pedro Amorim commit a0ac15d8b361108119c1ed294304ee06cd4c97fd Author: Pedro Amorim Date: Wed Aug 12 15:48:59 2026 +0000 Bug 35104: DBRev 26.06.00.013 Signed-off-by: Pedro Amorim commit 1b4373eea332d8de62eac8b75176fa0288f50829 Author: Martin Renvoize Date: Wed Jul 8 12:27:47 2026 +0100 Bug 35104: Update Exporter/Record.t fixture for the new store() validation This test built a "bad" biblio by storing invalid MARCXML directly via Koha::Biblio::Metadata->store(), which now rejects it. Simulate legacy corrupt data already in the database by writing it straight to the DBIC row, bypassing the new validation, instead. Signed-off-by: Baptiste Bayche Signed-off-by: Baptiste Wojtkowski Sponsored-by: OpenFifth Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 6726b1a2544bd31a67a31d7c52c98384fdf5f867 Author: Martin Renvoize Date: Wed Jul 8 12:40:23 2026 +0100 Bug 35104: Catch invalid metadata and surface repair warnings in AddBiblio/ModBiblio AddBiblio/ModBiblio/ModBiblioMarc gain an optional warnings arrayref option: any repair messages recorded by Koha::Biblio::Metadata->store() (see previous commit) are appended to it via object_messages, so a caller can show the cataloguer what was automatically fixed instead of the fix happening invisibly. AddBiblio also now distinguishes Koha::Exceptions::Metadata::Invalid from other errors in its catch block and rethrows it, so a caller can tell "this record is unrecoverable" apart from an unexpected internal error and react accordingly (see following bugs for callers doing so). The inline StripNonXmlChars calls in TransformHtmlToMarc are removed, since stripping is now handled centrally and consistently by Koha::Biblio::Metadata->store() rather than ad-hoc at every call site. Signed-off-by: Baptiste Bayche Signed-off-by: Baptiste Wojtkowski Sponsored-by: OpenFifth Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 112712e31cd7462533b8cb64bedfc21f04f76978 Author: Martin Renvoize Date: Wed Jul 8 12:25:23 2026 +0100 Bug 35104: Recover MARCXML that fails to decode, or throw when unrecoverable Koha::Biblio::Metadata->store() now validates that MARCXML round-trips through MARC::Record before saving it, rather than saving whatever was given and letting corruption surface later as an opaque failure somewhere downstream. Two faults are recovered automatically, and either or both may apply to the same record: - non-XML characters (recorded as nonxml_stripped, recovered via StripNonXmlChars) - datafields with no subfields at all, which MARC::File::XML refuses to parse (recorded as empty_datafield_stripped, recovered by removing the empty datafield) Each recovered fault is logged, reported via object_messages for the caller to act on, and recorded as a biblio_metadata_errors row (tag and subfield included where identifiable) for later review - except where an identical row already exists for the same metadata_id, so a source record that stays dirty across repeated saves (e.g. re-harvested from an external repository) doesn't pile up duplicate rows for the same fault. Existing rows are otherwise left alone on a clean save, since they're review flags requiring explicit resolution, not a cache to invalidate. If the MARCXML cannot be recovered at all, Koha::Exceptions::Metadata::Invalid is thrown. The recovery logic is exposed as a repair_marcxml class method so other callers that parse MARCXML ahead of a store() (see following bugs) can reuse it instead of re-implementing it. Signed-off-by: Baptiste Bayche Signed-off-by: Baptiste Wojtkowski Sponsored-by: OpenFifth Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit b80a26eb51506cd381b82fbceab6b4f6ada1f1e2 Author: Martin Renvoize Date: Wed Jul 8 12:25:05 2026 +0100 Bug 35104: Add Koha::Biblio::Metadata::Error(s) object classes Thin Koha::Object(s) wrappers around biblio_metadata_errors. error_type is restricted to a known set of constants, validated on store(), so a typo'd or unknown value fails loudly rather than writing an unrecognised value into the database. Errors::by_type() gives callers a named filter instead of hand-rolling the same search(). Signed-off-by: Baptiste Bayche Signed-off-by: Baptiste Wojtkowski Sponsored-by: OpenFifth Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 50b0ba401b1ee72c654be271eeeb67faaed19055 Author: Martin Renvoize Date: Wed Jul 8 12:24:24 2026 +0100 Bug 35104: Guard Koha::Exceptions::Metadata::Invalid::full_message against undef fields full_message() interpolated id/biblionumber/format/schema/decoding_error directly into a sprintf without checking definedness, producing Perl warnings whenever one of them is unset (e.g. a new, not-yet-stored metadata object with no id yet). Signed-off-by: Baptiste Bayche Signed-off-by: Baptiste Wojtkowski Sponsored-by: OpenFifth Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 0490204f7b7221bbc6b1e163edff2bd7c1ebd922 Author: Martin Renvoize Date: Wed Jul 8 12:24:18 2026 +0100 Bug 35104: Add koha_object_class to BiblioMetadataError schema result Signed-off-by: Baptiste Bayche Signed-off-by: Baptiste Wojtkowski Sponsored-by: OpenFifth Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 7d9562c1b668b8a9521cb38a1d88e161293bb3c8 Author: Martin Renvoize Date: Wed Jul 8 12:24:09 2026 +0100 Bug 35104: Automated Schema Update Signed-off-by: Baptiste Bayche Signed-off-by: Baptiste Wojtkowski Sponsored-by: OpenFifth Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 22b4acf8d21eefc7d1b0af8091278321907dbb4c Author: Martin Renvoize Date: Wed Jul 8 12:23:42 2026 +0100 Bug 35104: Add biblio_metadata_errors table for per-fault error tracking Adds biblio_metadata_errors to record individual faults (non-XML characters, empty datafields, ...) found and recovered when saving a bibliographic record's MARCXML, so they can be surfaced to cataloguers and explicitly resolved once reviewed. Signed-off-by: Baptiste Bayche Signed-off-by: Baptiste Wojtkowski Sponsored-by: OpenFifth Signed-off-by: Nick Clemens Signed-off-by: Pedro Amorim commit 1ffbc32ad27e00ea6d447437c250a653fcaf868f Author: Laura Escamilla Date: Mon Jul 27 19:15:22 2026 +0000 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 Signed-off-by: Pedro Amorim commit e50267072f8cfd9225fcfe283a6b1246242dd273 Author: David Cook Date: Wed Jul 8 05:35:04 2026 +0000 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 Signed-off-by: Jonathan Druart Signed-off-by: Pedro Amorim commit a45638d8fca95fca07352b5acba5d8cd4772b6c8 Author: Jonathan Druart Date: Thu Jun 18 11:21:38 2026 +0200 Bug 42866: Prevent SQL injection in Koha::AddtionalContents->search_for_display Signed-off-by: Sanjar Tulkinov Anvar o'g'li Signed-off-by: Marcel de Rooy Signed-off-by: Pedro Amorim commit f3f6f159389842f74beade61e868067e06e8e58b Author: Martin Renvoize Date: Fri Jun 19 10:29:55 2026 +0100 Bug 42847: (QA follow-up) Clear session state on all login_core exit paths login_core only cleared leftover session state on the failed-auth branch. The earlier 'SIP access not authorized' return (unknown terminal id) left any account/ils/institution/policy/credentials from a prior connection on a reused prefork worker in place. Move the reset to the top of login_core so every non-success exit path leaves clean state, and only a successful api_auth re-establishes the session. This keeps the no-authenticated-state-until-auth invariant in a single place rather than duplicating the key list per branch. Also extend the unit test to cover the unknown-terminal path on a reused worker. Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit 50a43898133ef887c1cc837c7eeb69f3d45041b1 Author: Kyle M Hall Date: Tue Jun 16 10:12:07 2026 -0400 Bug 42847: Prevent previously authenticated user After a SIP terminal logs in successfully, a later connection handled by the same worker could bypass authentication entirely. login_core() stores the account in the session before calling api_auth(), and left it in place when authentication failed. The check in raw_transport() that is meant to drop unauthenticated connections only looks at $self->{account}->{id}, which is now populated straight from the SIP config, so the connection is treated as logged in. Test Plan: 1) Create a SIP user with the username and password "term1" 2) Restart the SIP server 3) Apply the first patch 4) prove t/db_dependent/SIP/MsgType.t 5) Note the new test fails 6) Telnet to the SIP server port ( 6001 for ktd ) 5) Send a successful login: 9300CNterm1|COterm1 6) Note you get a 941 back 7) Disconnect, then telnet to localhost 6001 again 8) Send a bad login: 9300CNterm1|COterm2 9) Note you get a 940 back, but the connection stays open 10) Send a patron information request, using a real patron cardnumber: 6300120260615 110310 AOCPL|AA23529001000463 11) Note you get a 64 patron information response with the patron's data back, even though the login failed! 12) Apply the second patch 13) prove t/db_dependent/SIP/MsgType.t 14) Note the subtest now passes! 15) Restart all the things! 16) Repeat steps 4 to 10 17) Note the the patron info request returns no patron data and the connection is dropped! Signed-off-by: Nick Clemens Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit d56dc2bfa850ca991eb27ac68473114a277afdcb Author: Kyle M Hall Date: Tue Jun 16 10:12:07 2026 -0400 Bug 42847: Add unit tests Signed-off-by: Nick Clemens Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit 887b163652c7db9a3cc220df1b8ab2df15383355 Author: Jonathan Druart Date: Mon Jun 8 12:21:17 2026 +0200 Bug 42749: Prevent SQL injection from GetInvoices (order_by) Signed-off-by: Sanjar Tulkinov Anvar o'g'li Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit 5aa86845f50a1c306220a2f2b340f02b2a72fd42 Author: Martin Renvoize Date: Tue Jul 7 14:35:47 2026 +0100 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 Signed-off-by: Pedro Amorim commit bbbaa83c1cb0600a097954cc89a037f12b8e1742 Author: Jonathan Druart Date: Tue Jul 7 14:23:44 2026 +0100 Bug 42747: Prevent SQL injection via image_name in edit-layout Signed-off-by: Sanjar Tulkinov Anvar o'g'li Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit b0c86b0fcf15b30bf412071e7502f774c9f78323 Author: Martin Renvoize Date: Tue Jul 7 15:17:09 2026 +0100 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 Signed-off-by: Pedro Amorim commit 52f4b17b0f61c91d84df34fb3c633a1c2c6d17f1 Author: Jonathan Druart Date: Tue Jun 2 14:14:34 2026 +0200 Bug 42746: Sanitize condition and substitution fields Signed-off-by: Sanjar Tulkinov Anvar o'g'li Amended-by: Jonathan Druart: Replace , with ; Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit 2b09e846bcafb33fba547a4c18ec4b762192be8c Author: Jonathan Druart Date: Tue Jun 2 14:08:10 2026 +0200 Bug 42746: Sanitize age_field Signed-off-by: Sanjar Tulkinov Anvar o'g'li Signed-off-by: Pedro Amorim commit 8145e26a93cbc72d64e2331314cc4b89af2ff127 Author: Martin Renvoize Date: Tue Jul 7 15:45:45 2026 +0100 Bug 42471: (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 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 Signed-off-by: Pedro Amorim commit 222dac6c3c542f77d6ba1b2df84100625e5b9608 Author: David Cook Date: Tue May 5 01:56:49 2026 +0000 Bug 42471: (follow-up) prevent XSS in suggestion reason Signed-off-by: David Cook Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit acf118443663bc80bfc5e8b34c5298efed472132 Author: Jonathan Druart Date: Mon May 4 14:15:34 2026 +0200 Bug 42471: Prevent XSS in suggestion.tt escape_str all the things Signed-off-by: David Cook Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim commit da595ca8d5d5d1144b9c6db64f46148c517b1203 Author: Martin Renvoize Date: Wed Jul 1 09:21:40 2026 +0100 Bug 30233: (follow-up) Fix POD formatting codes in _apply_substitution The angle-bracket delimiter notation in the POD prose (e.g. PATTERN) caused the POD parser to treat the trailing letter of each word as an unknown formatting code (N<>, T<>). Replace with C and a parenthetical note that any non-space delimiter is accepted. Signed-off-by: Martin Renvoize Signed-off-by: Baptiste Wojtkowski Signed-off-by: Pedro Amorim commit 8a06056143ac793f88436e2dc053e2e575d12cf5 Author: Martin Renvoize Date: Wed Jul 1 09:21:40 2026 +0100 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 Signed-off-by: Baptiste Wojtkowski Signed-off-by: Pedro Amorim commit 45852aa193cbc6a3b70b793d641ca9935bc8f1f5 Author: Martin Renvoize Date: Wed Jul 1 08:18:13 2026 +0100 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 Signed-off-by: Baptiste Wojtkowski Signed-off-by: Pedro Amorim commit b9e797364929f55067c3ac5ba53f797650b6bf2b Author: David Cook Date: Thu Jun 25 13:38:11 2026 +0000 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 Signed-off-by: Martin Renvoize Signed-off-by: Baptiste Wojtkowski Signed-off-by: Pedro Amorim commit 1043dfeda71d66a3e9a3aae0da226cc9de312763 Author: Sanjar Tulkinov Anvar o'g'li Date: Wed Jun 24 22:56:19 2026 -0400 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 sPATTERNREPLACEMENTFLAGS, 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 Signed-off-by: David Cook Signed-off-by: Martin Renvoize Signed-off-by: Baptiste Wojtkowski Signed-off-by: Pedro Amorim commit d7c1e19b495d854d0c17ad65fdb5e339edba40fc Author: Sanjar Tulkinov Anvar o'g'li Date: Wed Jun 24 22:56:19 2026 -0400 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 Signed-off-by: David Cook Signed-off-by: Martin Renvoize Signed-off-by: Baptiste Wojtkowski Signed-off-by: Pedro Amorim commit cda91ee42c56348363eab08a7480892e66da7ad6 Author: Sanjar Tulkinov Anvar o'g'li Date: Wed Jun 24 22:56:19 2026 -0400 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 Signed-off-by: David Cook Signed-off-by: Martin Renvoize Signed-off-by: Baptiste Wojtkowski Signed-off-by: Pedro Amorim commit 3b5f16adc654c3348481ebc4e1f76600972e2fa6 Author: Owen Leonard Date: Thu Jul 24 17:11:12 2025 +0000 Bug 40498: Improve style of list transfer form This patch makes some style changes to the list transfer form. Since it needs the same CSS that is used on the circulation page, the CSS block is moved from circulation.tt to staff-global.scss. The patch also changes the behavior of the form so that the "New owner" line doesn't appear until after a patron has been selected. To test, apply the patch and rebuild the staff interface CSS. - If necessary, create a public list. - From the list of public lists, click the "Transfer" button. - Verify that the form looks correct. The patron search field should match the search field shown when you navigate directly to circulation.pl - Search for a patron who has permission to manage public lists. - After you select a patron, a new line should appear: "New owner: [name]" - Click "Transfer" and confirm that the process works correctly. Sponsored-by: Athens County Public Libraries Signed-off-by: Laura_Escamilla Signed-off-by: Pedro Amorim commit 4110bcf3bf98b81d2ed7ca48d8151c138fa26b28 Author: Jennifer Sutton Date: Mon Jun 22 00:31:54 2026 +0000 Bug 30759: Add hint about the data that is sent via the Google Books API to OPACSuggestionAutoFill Add information about the data that is sent to Google if the OPACSuggestionAutoFill system preference is enabled. Test plan: 1. Go to Administration > System preferences. 2. Search for the OPACSuggestionAutoFill system preference. 3. Note that there is no note about the data that is sent to Google if the system prference is enabled. 4. Apply the patch. 5. Refresh the page. 6. There is now a note about the data that is sent to Google. 7. Check that it reads well and makes ense. Sponsored-by: Catalyst IT Signed-off-by: David Nind Signed-off-by: Laura_Escamilla Signed-off-by: Pedro Amorim commit 9e90ca26f7d682bea29c16c460234a84268d24ad Author: Martin Renvoize Date: Fri Sep 12 15:08:54 2025 +0100 Bug 40800: SIP checkin incorrectly triggering alerts on successful transfer completion When an item is checked in via SIP2 at the correct target branch after a transfer, the system was incorrectly triggering an alert flag. This occurred because the TransferArrived message was not being filtered out for accounts with checked_in_ok="1", causing the alert logic to treat successful transfer completion as a failure condition. The TransferArrived message indicates successful transfer completion and is purely informational - it should not trigger SIP alerts. This fix ensures that TransferArrived messages are filtered out before alert evaluation, preventing false positive alerts on successful operations. Test Plan: 1. Set up a SIP2 account with checked_in_ok="1" in SIPconfig.xml 2. Via staff client, check out an item to a patron 3. Return the item to a different branch to trigger a transfer 4. Use misc/sip_cli_emulator.pl to check in the item at the target branch 5. Verify SIP response shows alert flag 'N' (no alert) instead of 'Y' 6. Test wrong branch checkin still shows alert flag 'Y' with CV04 type Before: Transfer completion at correct branch incorrectly shows alert='Y' After: Transfer completion at correct branch correctly shows alert='N' Sponsored-by: OpenFifth Signed-off-by: Jackie Usher Signed-off-by: Kyle M Hall Signed-off-by: Pedro Amorim commit c6e52fe82b4fcb333147fe47efbbbdf9733dab7c Author: Pedro Amorim Date: Thu Aug 6 15:34:50 2026 +0000 Bug 41649: DBRev 26.06.00.012 Signed-off-by: Pedro Amorim commit 4475df36bfcd77bbad674e4cf1454b62db7ac90e Author: Martin Renvoize Date: Tue Jan 20 12:21:19 2026 +0000 Bug 41649: DBIC Schema boolean update Sponsored-by: OpenFifth Signed-off-by: Marcus Michel Signed-off-by: Kyle M Hall Signed-off-by: Pedro Amorim commit c6798323cd16c9243b8c832d1f757bcba4d4342d Author: Martin Renvoize Date: Mon Jan 19 14:26:14 2026 +0000 Bug 41649: Fix SIP Message tests for magnetic media The tests for desensitize and alert flags were failing because items were created with random itemtypes that could have sip_magnetic=1. This caused unexpected behavior since magnetic media items don't get desensitized and trigger alert flags. Fix by explicitly creating itemtypes with sip_magnetic=0 in: - test_checkout_desensitize - test_renew_desensitize - test_checkin_v2 Sponsored-by: OpenFifth Signed-off-by: Marcus Michel Signed-off-by: Kyle M Hall Signed-off-by: Pedro Amorim commit cd728e5bb28d9227ce24732fb727b68be0019c20 Author: Martin Renvoize Date: Fri Jan 16 08:13:35 2026 +0000 Bug 41649: Unit tests for magnetic media Add unit tests for SIP magnetic media support. Test plan 1) Run t/db_dependent/SIP/Transaction.t in ktd and confirm it passes Sponsored-by: OpenFifth Signed-off-by: Marcus Michel Signed-off-by: Kyle M Hall Signed-off-by: Pedro Amorim