94 Commits
Author SHA1 Message Date
Isaac ConnorandClaude Opus 5 9c06eb6ba2 refactor: connect to the database on first use, not on include
database.php called dbConnect() at file scope, so including it opened a socket,
and on failure rendered views/no_database_connection.php and exit()ed from
inside a library include. Every model in web/includes requires this file, so
merely loading a class did both.

Connect on first use instead. $dbConn becomes tri-state - false for "not
attempted", null for "attempt failed", a PDO for connected - and two accessors
sit on top of it:

  zmDbConn()        opens if needed; on failure renders the error view and
                    stops, which is what the include used to do, just at the
                    point a query is actually attempted.
  zmDbConnOrNull()  opens if needed but returns null instead of ending the
                    request, for callers with a fallback.

dbQuery() is the funnel every fetch helper goes through, so routing it plus
dbEscape(), dbError() and dbInsertId() through the accessors covers the library.
The five callers that reached for the raw global are updated: config.php.in,
Event.php and ajax/console.php need a connection and take zmDbConn(); logger.php
takes zmDbConnOrNull() and falls through to its error_log target, so a logging
call can no longer end the request or open a connection by itself.

ZMSessionHandler captured $dbConn in its constructor. It is constructed while
session.php is being included, before anything has needed the database, so with
a lazy connection that captured false. It now resolves per call and its methods
return "no session" rather than dereferencing a bool.

Two smaller fixes fall out. The error view was included by a relative path that
only resolved when the cwd was web/, so it never worked for requests served out
of web/api/; it is now anchored with __DIR__. And dbDisconnect() set $dbConn to
null, which in the new tri-state means "connecting failed" and would send the
next query to the error page; it sets false so a later query can reconnect.
Nothing calls dbDisconnect() today.

This does NOT make database.php includable without a database. It requires
logger.php, which requires config.php, which reads ZoneMinder's configuration
out of the Config table at include time. Until that cycle is broken the
connection still happens during bootstrap, just from config.php rather than from
here.

Tests: tests/php/test_database_lazy_connect.php, 7 assertions, all pass. It
tokenises database.php and asserts nothing runs at include time, that dbQuery()
goes through the accessor, and that only the connection plumbing touches the
global. Verified it reports the pre-refactor file's `if ( !dbConnect() )` - an
earlier version of the check skipped tokens inside parentheses and so passed on
exactly the code it exists to reject.

Not covered by tests: behaviour when the database is genuinely unreachable, and
the session handler against a live database. Needs manual testing on an
installed tree, including stopping mysql to confirm the error view still renders
for both a web request and an API request.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01477mR97vfnK6zczbHgzq6T
2026-08-17 20:52:10 -04:00
Isaac ConnorandClaude Opus 4.8 48fadaebbf feat: customizable menu entries with links, icons and delete on options menu tab
Port the menu customization work from the ai_server branch onto master:
- Add/edit/delete custom navbar/sidebar menu entries via Options > Menu
- Per-entry Link column (new Menu_Items.Link) with ?view= fallback derived
  the same way as built-in items; custom entries render via buildMenuItem
- Live icon preview (material/font awesome) with fixed-width preview cell
- Per-row delete icon; add/reset buttons with tooltips
- Surface DB errors when saving options config: capture the swallowed PDO
  error via dbLastError() and show it in the page error banner instead of
  redirecting past it

Menu_Items.Link is added to zm_create.sql.in and as an idempotent ALTER in
zm_update-1.39.16.sql.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 12:13:49 -04:00
SteveGilvarry 8801c42064 fix: address review feedback on DB SSL verify option
- API (database.php.default): only set the PDO verify flag when SSL is
  actually configured (ZM_DB_SSL_CA_CERT set), matching the web/Perl/C++
  layers. Previously a fresh install's default (1) would set the flag on a
  non-SSL connection, since the CakePHP datasource merges 'flags' uncondi-
  tionally.
- Both PHP layers: cast to string and trim before parsing the value, and use
  strict in_array, to avoid type-juggling and stray-whitespace edge cases.
- zm_db.cpp: use my_bool (not char) for the MYSQL_OPT_SSL_VERIFY_SERVER_CERT
  fallback argument, the type libmysqlclient expects. That branch only
  compiles on older clients without MYSQL_OPT_SSL_MODE, where my_bool exists.

refs #3816
2026-06-14 15:57:09 +10:00
SteveGilvarry e60bdc67b2 feat: add ZM_DB_SSL_VERIFY_SERVER_CERT option (portable across MySQL/MariaDB)
Add a ZM_DB_SSL_VERIFY_SERVER_CERT setting so a database connection that uses
ZM_DB_SSL_CA_CERT can talk to a server with a self-signed or otherwise
non-matching certificate. When enabled, verification is by identity (the cert
must chain to the CA and its CN/SAN must match ZM_DB_HOST), consistent across
the C++ daemons, the PHP web interface, the CakePHP API and the Perl scripts.

This re-does the reverted #3817. That PR broke the build because it called
mysql_options(MYSQL_OPT_SSL_VERIFY_SERVER_CERT, ...), and that enum was removed
from the MySQL 8.0 C client in favour of MYSQL_OPT_SSL_MODE; it also passed a
c_str() where a my_bool* was expected, and referenced the PHP constant
unconditionally (fatal on PHP 8 for an upgraded install whose zm.conf predates
the option).

The option that controls server-cert verification differs by client library and
the symbols are enum values, not macros, so CMake feature-detects them by
compiling:
  - HAVE_MYSQL_OPT_SSL_MODE  (MySQL 5.7.11+/8.0, MariaDB Connector/C 3.1+)
  - HAVE_MYSQL_OPT_SSL_VERIFY_SERVER_CERT  (older MariaDB/MySQL)
zm_db.cpp uses SSL_MODE_VERIFY_IDENTITY / SSL_MODE_REQUIRED when the former is
available, else falls back to the latter with a proper my_bool.

Value handling is three-way in every layer: a truthy value verifies, a false-y
value (0/false/no/off) skips verification, and an empty/unset value leaves the
client default in place so existing installs are unchanged on upgrade. PHP, the
API datasource (via PDO flags) and the Perl DSN are all guarded with defined()
checks. Fresh installs default to 1.

Documents the full ZM_DB_* connection and SSL settings, including the hostname
verification gotcha when connecting by IP, in docs/userguide/configfiles.rst.

refs #3816
2026-06-14 13:20:00 +10:00
Isaac Connor 16a5f9e0a2 Merge dbUpdate and dbInsert from another branch 2024-11-18 10:47:07 -05:00
Simpler1 18d74ed7ac (feat): Tags
fix(tag): Create tags on mobile

chore(tags): Change TagName to Name

chore(tags): eslint

chore(tags): dbFetchAll to dbQuery for removetag

chore(events): eslint (attempt 2)

feat(tags): Better handling of keyboard

fix(tags): Enter key for creating new tag

fix(tags): Don't allow space as a tag name

feat(tags): Delete tag if last assignment removed

fix(tags): Increase height of dropdown

in progress

fix(Tags): Use T.Id on the events page dropdown

fix(Tags): Remove $availableTags from events.php

chore(sql): Formatting sql statements

feat(Tags): Working OR on filters and events pages

fix(filter): Populate availableTags

chore(Tags): code formatting

fix(tag): Add tag on create tag

Fix(tags): Remove tag from available if last

feat(tags): Add zm_update.sql

fix(chosen): Undo css width

fix(chosen): tags dropdown width

fix(tags): dropdown over timeline

fix(tags): Full width input

fix(events): Refresh table on page show

chore(filter): Clean up availableTags

chore(event): Clean up available & selected Tags

fix(event): Update available tags on remove

fix(event): Remove hack for selected tags

feat(tags): Blur input after adding tag

doc(tags): Initial tags documentation

fix(tags): Dark theme dropdown

fix(tags): Dark theme for tags on input

fix(tags): Dark theme for highlight in dropdown

fix(tags): Populate filter tags droplist

chore(): Bump zm_update to 1.37.42

chore(tags): Move mobile check to skin.js

chore(tags): Comment debug statements

fix(tags): Enter key to create tag on mobile Chome

chore(tags): Space in 'All Tags' for translation

Temporary commit to handle cookie expiration times

chore(tags): Remove unnecessary Tag(s) from en_gb

chore(): Cleanup unnecessary Error and Debug

chore(): Resolve merge conflicts

chore(): Address merge conflicts with master
2023-08-31 15:50:08 -04:00
Isaac Connor 4959d83751 Switch from utf8 to utf8mb4 so that collate works 2023-05-25 17:31:30 -04:00
Isaac Connor fc90d7bc2b Remove debug 2023-05-15 16:08:51 -04:00
Isaac Connor 39de76e989 add a db_version and a feature check function to determine if we support skip locks in the query. Use it to disable the feature in filter view. 2023-02-25 11:44:50 -05:00
Michael 0d6b8d1de3 Set web backend db connection to utf8 2022-11-10 18:57:35 +01:00
Isaac Connor e617eb8615 Whitespace 2021-11-09 13:59:14 -05:00
Isaac Connor 284b9f963f Merge branch 'master' into zma_to_thread 2020-12-29 12:18:26 -05:00
Isaac Connor 4d33667a85 Merge branch 'release-1.34' 2020-12-05 16:51:42 -05:00
Isaac Connor fdbca4760f dbFetchAll should always return an array. Not null on error 2020-12-05 16:38:25 -05:00
Isaac Connor 8397ec3b9d Merge branch 'release-1.34' 2020-12-01 14:28:10 -05:00
Isaac Connor baeb1dbd5b Take an optional debug param in dbQuery 2020-12-01 14:07:23 -05:00
Isaac Connor 10c0a6617c Return Debug to a regular function to match other logging functions. Since we switched to using namespaces we no longer clash with cake_php. 2020-10-14 10:39:25 -04:00
Isaac Connor 861ebedcae Implement a crude view for a failed db connection with a 30 second reload interval. 2020-09-21 11:15:34 -04:00
Isaac Connor 2d05fbda8d simplify debug line 2020-08-24 14:36:36 -04:00
Isaac Connor 198790796d Merge branch 'release-1.34'
plus cleanups in dbConnect
2020-06-05 19:02:43 -04:00
Isaac Connor 8802447b10 Handle no DB_HOST specifed so default to localhost 2020-06-04 11:36:10 -04:00
Isaac Connor c4b2aa4a85 Handle no DB_HOST specifed so default to localhost 2020-06-04 11:34:16 -04:00
Isaac Connor 689956bba7 Merge branch 'master' of github.com:zoneminder/ZoneMinder 2019-12-13 17:49:00 -05:00
Isaac Connor bedc61a347 handle dbFetchNext on null result more gracefully 2019-12-13 11:49:55 -05:00
Isaac Connor 4632bbd124 Apply relevant changes to deal with php7,4 deprecations 2019-12-07 11:45:32 -05:00
Isaac Connor 393f0a369c Revamp timeline. Make it handle being full browser width. remove onclicks. 2019-09-28 14:23:23 -04:00
Isaac Connor daa9f646fb fix error printing 2019-09-19 14:56:34 -04:00
Isaac Connor d5aa95e45f cpplint fixes 2019-09-09 16:13:32 -04:00
Isaac Connor 4140d51e9f database.php cleanup. remove dbFetchMonitor and dbFetchGroup. Their usage has been replaced with the Object::find_one usage. Also more quoting of table and colume names to fix #2659 2019-08-13 11:45:50 -04:00
Isaac Connor 4765b9d936 Don't generate php errors when returned row doesn't have the specified column 2019-05-24 14:52:04 -04:00
Isaac Connor 8dd8888975 Php namespace (#2537)
* experiment with namespaces on the Server class

* experiment with namespaces on the Server class

* Implement the ZM namespace on objects

* Implement the ZM namespace on objects

* Implement the ZM namespace on objects
2019-02-22 09:19:07 -05:00
Isaac Connor a066968aca fix dbError and cause it to return the error string instead of just logging it. Add error logging of db errors that don't throw exceptions. 2018-11-07 12:33:18 -05:00
Isaac Connor 7ee80e7cca Debug lines should be debug, not warning 2018-08-31 11:58:03 -04:00
Isaac Connor 00e82fb751 Implement MonitoServerId,StorageServerId,FilterServerID in Filters 2018-04-25 13:05:19 -07:00
Isaac Connor 117555a857 Merge branch 'storageareas' of github.com:/connortechnology/ZoneMinder into storageareas 2018-04-25 09:39:10 -04:00
Isaac Connor 161fc94496 remove useless () 2018-04-25 09:33:12 -04:00
Isaac Connor 9fd2c12765 DB Logging is a Debug level 2018-04-24 08:42:52 -04:00
Isaac Connor bbee7fd0f2 fix array_key_exists 2018-04-18 14:17:41 -07:00
Isaac Connor 75248e7465 use array_key_exists instead of isset so that we can return nulls 2018-04-18 14:21:27 -04:00
Isaac Connor 6b6fdc7cee Log the sql before running it 2018-02-09 07:29:10 -08:00
Isaac Connor 929e49c301 early return if there is no rows returned. Improve debug when there is a row but the specified column isn't present 2018-02-02 10:27:30 -05:00
Isaac Connor 212882efb9 db errors should NOT BE FATAL! 2018-02-01 11:31:25 -05:00
Isaac Connor 31b7deb101 Return NULL on error in dbQuery 2018-01-29 10:41:24 -08:00
Isaac Connor 97595051ce whitespace 2018-01-22 11:42:19 -05:00
Isaac Connor 0171d532fc fix the test for DB_DEBUG 2017-12-04 16:50:56 -05:00
Isaac Connor 1ccd344bf5 implement Storage Area move 2017-12-04 11:05:50 -05:00
Isaac Connor cb70a3627f Fixes to montagereview and only load event data when in History mode 2017-11-28 14:50:21 -05:00
Isaac Connor b1bb0020d3 turn off database debug 2017-11-24 15:42:44 -05:00
Isaac Connor 9dd0f29e88 Merge branch 'storageareas' into tesla 2017-11-22 11:41:11 -08:00
Isaac Connor 59a87c14d3 fix error message 2017-11-08 11:17:46 -05:00