CallBackery

 view release on metacpan or  search on metacpan

CHANGES  view on Meta::CPAN

   "%2" standing in the result.

 - New trmJoin($sep,@parts) for a message whose number of parts is only
   known at run time -- a list of warnings, the flags on a table row.
   join() was the obvious thing to reach for and it stringified every part;
   the msgid trmJoin builds holds nothing but placeholders and the
   separator, so all the words stay in the parts.

0.60.1 2026-09-09 22:37:58 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - SECURITY: CallBackery::Plugin::Doc passed the client supplied document
   name to Pod::Simple::Search->find without validation. find() treats
   "::" as a path separator, so a name such as "..::..::..::etc::motd"
   escaped @INC and let an unauthenticated GET on /doc render the POD of
   any file readable by the server process. Because the traversal stays
   inside a single URL path segment, no browser, router or reverse proxy
   ever saw a ".." segment to normalise away. The document name is now
   required to be a plain module name (\w+ parts joined by "::") and
   anything else answers 404 without echoing the name back. Reported by
   CPANSec. (CWE-22)

 - CallBackery::Plugin::Doc now reads the documentation file with a three
   argument open instead of IO::File and a two argument "< $path", and
   checks that the open succeeded. Hardening only, as the path is built
   from the validated module name.

 - The test suite no longer drops a callbackery.db into the current
   directory. t/callbackery.cfg names its config database with a relative
   path, so every test built straight from it wrote into the checkout
   root. The new t/lib/CallBackeryTest.pm redirects cfg_db to a uniquely
   named database below the system temp directory, which is removed when
   the test process exits.

 - MANIFEST was missing five of the seven test files, so released
   tarballs shipped only t/basic.t. All tests are listed now.

0.60.0 2026-08-27 08:42:19 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - Excel export: new makeExportAction option "extraCols" adds generated
   columns to an XLSX export. The only type so far is "qrCode", which
   embeds the content of a selectable field as a QR code image. The
   content comes from a table key or a code reference, the column is
   placed after its source column or at an explicit insertAfter index,
   and label and size are configurable. Needs Text::QRCode, which is
   loaded only when such a column is exported. CSV exports ignore the
   option.

 - CallBackery::GuiPlugin::AbstractTable used Mojo::Asset::Memory
   without loading it, and only worked because Mojolicious happened to
   have loaded it already.
0.59.0 2026-08-20 08:58:50 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - New optional actionCfg property "noBusyIndicator" for download and
   display actions. When set, the modal busy indicator ("Preparing
   Download ...") is not shown while the download is being prepared, so
   the gui stays usable for actions which take a long time to produce
   their data. Default behaviour is unchanged.

0.58.4 2026-07-31 16:15:51 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - Frontend ui.Login: a login could be lost outright. The credentials
   were copied into the hidden iframe form that exists only to make the
   browser offer to save the password, and that copy ran before the
   login call, unguarded. The iframe reloads /login every time the login
   window appears, so whenever that fetch had not completed yet -- a
   busy server is enough -- getElementById returned null, the handler
   threw on it, and the login request was never sent. The form had
   already disabled itself, so it just sat there greyed out with nothing
   on screen to explain it, and only a reload got the user out of it.
   The password manager hand-off now happens after a successful login
   and is fully guarded, so it can miss the save prompt but can no
   longer come between the user and their session.

0.58.3 2026-07-30 16:11:29 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - Config: restoring a configuration blob replaced the configuration
   database file, giving it a new inode. Every connection open at the
   time stayed attached to the old, now unlinked file: it went on
   reading the pre-restore configuration and failed on its first write
   with SQLITE_READONLY_DBMOVED, which SQLite reports as "attempt to
   write a readonly database". With a prefork server and background
   helpers that is most of the processes on the machine. The
   replacement database is now built beside the live one and copied in
   with SQLite's online backup API, so the inode is preserved and open
   connections simply see the restored data. If the write lock cannot
   be had within 30 seconds the restore now gives up with an error and
   leaves the database untouched, rather than restoring it half way.

0.58.2 2026-07-20 12:54:27 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - Frontend ui.plugin.Form: make sure trigger load does not overwrite
   fix for automated testing which fills forms very quickly

0.58.1 2026-07-16 08:39:18 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - Frontend ui.plugin.Form: a trigger-field change made while form data
   was still loading parked its form reconfiguration in _reconfPending
   and never sent it — the affected form stayed in its stale layout
   (e.g. fields that the reset should reveal never appeared) until the
   user toggled the trigger field again. The pending queue is now
   drained when loading completes.

0.58.0 2026-07-15 17:23:33 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - Session expiry now surfaces as a dedicated RPC code 7 ("session
   expired"), distinct from code 6 ("login required"). allow_rpc_access
   guards plugin instantiation so an expired session no longer escapes as
   a generic error. CallBackery::User gains a per-request `sessionExpired`
   flag for subclasses that enforce a cookie max-age.

 - Frontend data.Server: session expiry shows a single deduplicated
   "Session Expired -> Reload" prompt instead of a storm of error popups.
   Communication failures (server unreachable / proxy returning garbage)
   now retry silently for idempotent reads, then show one "Connection
   problem" dialog with Retry / Reload. MsgBox gains reload/retry buttons.

0.57.0 2026-06-16 08:58:42 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - We are on JSON-RPC 2.0 now. callbackery.data.Server now uses
   qx.io.jsonrpc.Client (qooxdoo 7.x) instead of the deprecated
   qx.io.remote.Rpc. 



( run in 0.836 second using v1.01-cache-2.11-cpan-007c89162af )