23 Commits

Author SHA1 Message Date
dillard 839572f1fb Only treat --full as the option when it is outside string literals
A value like 'value --full' in the query turned the full table view on.
Leave string literals and quoted identifiers out when looking for the
option.
2026-09-30 17:34:49 +02:00
dillard ec4b4a4ece Cut long values in SQL result tables to fit the terminal
One long value made every line of the table wider than the terminal,
so the whole table wrapped. Narrow the widest columns until the table
fits and end cut values with an ellipsis. Adding --full to the query,
which is an SQL comment, shows the values in full as before.
2026-09-30 17:26:16 +02:00
dillard f68b1658be Harden SQL mode checks and sanitize occ output
A security review found three issues:

- Comments were removed without a space before matching the forbidden
  patterns, so "TO/**/PROGRAM" became "TOPROGRAM" and passed the
  COPY ... PROGRAM check while PostgreSQL still ran it. Comments are
  now replaced by a space, and the COPY file check also covers E'...',
  U&'...' and dollar-quoted file names.
- Only statements starting with DELETE or UPDATE asked for
  confirmation, so a leading block comment, a data-modifying CTE
  (WITH x AS (DELETE ...)) or DROP/TRUNCATE/INSERT ran without it.
  Every statement that is not a plain read now needs confirmation,
  decided on the server.
- occ output could contain escape sequences, backspaces and URLs from
  user-controlled text (display names, file names) that rewrite or hide
  text or show a clickable link. Only color codes are kept now, and
  URLs are no longer turned into links.

The checks move to SqlGuard so they can be tested on their own. They
remain defense in depth: dynamic SQL can always get around a text
check, so the database role should not have superuser rights,
pg_execute_server_program or pg_read/write_server_files. A read that
starts with WITH now shows its rows like a SELECT.
2026-09-30 03:15:35 +02:00
dillard 3fc8601344 Keep occ output brackets escaped through the formatters
The overtyping and from_ansi formatters unescape brackets before they
parse the text, so escaping them beforehand was not enough: literal
brackets were still read as formatting. Enable
unixFormattingEscapeBrackets so both formatters escape the text again
after parsing. Verified in the browser: Symfony's "[alias]" in
`occ list` stays in place, ANSI colors still work, and formatting in
the output text (colors, links) is no longer applied.

Bump the version to 0.4.4 so browsers load the new script.
2026-09-30 02:25:13 +02:00
dillard 635cdd4b24 Escape brackets in occ output before rendering
jQuery Terminal reads "[" and "]" as its own formatting syntax. occ
output was echoed as is, so literal brackets, such as Symfony's
"[alias]" in `occ list`, closed the color formatting of the next line
early and moved text to the wrong place. Text from the output, like a
display name, could also inject terminal formatting.

Escape the brackets in the text and keep the ANSI sequences, so the
colors still work.
2026-09-30 02:07:46 +02:00
dillard a5f5c5cdb7 Fix code-review findings: ajax error handling, translated comment, docs
- js/index.js: the occ-command ajax call used the wrong jQuery .fail()
  signature ((response, code) instead of (jqXHR, textStatus,
  errorThrown)), so any failure printed the literal string
  "[object Object]" instead of a useful message.
- js/index.js: the initial bootstrap call that builds the terminal had
  no .fail() handler at all - a failure there (expired session/CSRF
  token, network error, rejected admin check) left #app-content
  permanently blank with zero diagnostic information. This is exactly
  what made today's NC34 debugging session harder than it needed to
  be; now it shows the actual HTTP status/reason in the page.
- OccController.php: translated a leftover Dutch comment (missed by
  the earlier Russian->English pass since it wasn't Russian), and
  documented why requireAdmin() is intentional defense-in-depth rather
  than a misunderstanding of the framework: verified against
  Nextcloud's own SecurityMiddleware source that any controller method
  without @NoAdminRequired already rejects non-admins by default, so
  this check (and the original "security fix" commit that added it)
  was addressing a non-issue for THIS controller specifically.
  DbController's equivalent check is still genuinely load-bearing -
  that controller originally shipped with @PublicPage, which does
  bypass the default protection - so it gets a note explaining the
  distinction instead.
- README: added compatibility matrix rows for 0.4.0 (app id rename to
  extended_occweb) and 0.4.1 (these fixes), both verified on NC 34.0.4.

Deferred to when a test instance exists (tracked, not fixed here): no
documented migration path from the old occweb id to extended_occweb
for existing installs, OccController's constructor doing expensive
work before the (redundant) admin check runs, and js/jquery.js loading
unconditionally on NC30-33 where core still provides jQuery.

Version bump to 0.4.1.
2026-09-26 16:04:14 +02:00
dillard 138ee88486 Rename app id from occweb to extended_occweb, prep for App Store
Nextcloud's app id "occweb" is effectively unavailable for a new store
listing: the original Adphi/occweb still owns that App Store slot
(stale, v0.2.3), and el-choco/occweb_v2 has since published a
same-lineage rewrite under its own id. Rather than fight over the
"occweb" name, publish this fork under its own id, matching the
<name> this app has always had: "Extended OCC Web".

Renames every place the literal app id is used: info.xml <id> and the
auto-generated navigation <route>, script()/style() registrations in
templates/index.php, the TemplateResponse app name in
OccController::index(), the /apps/... base URL in js/index.js, and the
'app' log context tag in DbController.php. The GitHub repo name and
its <website>/<bugs>/<repository>/<screenshot> links are unaffected -
those identify the repo, not the Nextcloud app.

Docs (README, INSTALL-AIO.md, install.sh) updated to clone into and
reference an "extended_occweb" directory, since Nextcloud requires the
app folder name to match its id - a plain `git clone` of this repo no
longer produces a correctly-named install directory on its own.

Version bump to 0.4.0 given the scope (breaking change for anyone who
already deployed under the old "occweb" id - requires disable+remove
of the old app and a fresh enable under the new id, not an in-place
upgrade).
2026-09-26 12:51:21 +02:00
dillard 2872d70653 Fix NC34 compatibility: vendor jQuery, send CSRF token explicitly on ajax calls
Live-tested against nc01 after its auto-update jumped to NC 34.0.4:

- Nextcloud's global jQuery has been deprecated since NC19 and is no
  longer reliably present/first-loaded on NC34 (other apps like
  serverinfo hit the same issue). occweb's index.js and the vendored
  jquery.terminal (term.js) both assume a global jQuery, so ship our
  own copy (js/jquery.js, 3.7.1 from code.jquery.com) and load it
  before them in templates/index.php. Fixes a hard "jQuery is not
  defined" crash that left the terminal blank (black screen).

- With that fixed, every ajax call started failing with HTTP 412
  "CSRF check failed": core only auto-attaches the requesttoken
  header to requests made through ITS OWN globally-loaded jQuery, and
  with occweb now vendoring a separate jQuery instance that no longer
  happens. A global $.ajaxSetup() call turned out unreliable (another
  app's later jQuery load can replace window.jQuery afterwards), so
  each of the three ajax calls (SQL query, initial completion list,
  occ command execution) now sets the requesttoken header explicitly
  via OC.requestToken.

Bump max-version to 34 - actually verified working on NC 34.0.4 now,
not inherited/guessed (see the policy comment in this same file).
Version bump to 0.3.5.
2026-09-26 12:23:28 +02:00
dillard 7d05643ee6 Translate Russian comments and user-facing strings to English
Covers OccOutput.php, DbController.php and js/index.js: docblocks,
inline comments, the forbidden-construct labels shown to admins in
error responses, and the SQL template descriptions shown in the
terminal (delete-user, list-user, rename-user).
2026-09-26 00:13:03 +02:00
Egor Bugaev 9e15c3b96c Add rename-user SQL template; make batch transaction handling robust against non-Postgres backends
- New 'rename-user' template (templates / template rename-user <old> <new>):
  best-effort uid rename across core tables (oc_users, oc_preferences,
  oc_group_user, oc_group_admin, oc_ldap_user_mapping, oc_share, oc_mounts,
  oc_storages). Explicitly NOT a supported Nextcloud operation - the
  generated script carries an in-line warning (as leading SQL comments)
  that app-specific tables (Talk, Calendar, Contacts, Mail, 2FA/WebAuthn...)
  are not covered and that the data directory must be renamed on disk
  manually, followed by occ files:scan --all. Documented the same caveat
  in both READMEs.
- Hardened the round-2 transaction wrapping: beginTransaction()/commit()/
  rollBack() are now wrapped in try/catch. PostgreSQL (our backend) has
  fully transactional DDL so this wasn't actually broken here, but
  Nextcloud also supports MySQL/MariaDB via the same IDBConnection, where
  DDL implicitly commits - on that backend a DDL statement in the batch
  would make a later commit()/rollBack() throw 'no active transaction'
  and previously that exception was unhandled (HTTP 500 instead of a
  clean JSON response). Now: if rollBack() itself fails after an error,
  we report rollbackFailed+warning instead of falsely claiming rolledBack,
  since earlier statements in that batch may already be permanently
  applied. If commit() fails with nothing to commit (already
  auto-committed), that's logged only, since the effects are already
  durably persisted.
2026-07-06 19:52:05 +03:00
Egor Bugaev ca0605706f Security hardening round 2: comment-aware forbidden-pattern check, UPDATE confirmation, transactional batches, quote-aware split (incl. double quotes), NULL-safe table rendering, AJAX timeout, request size limit
- removeAllComments() strips -- and /* */ comments before checking
  FORBIDDEN_PATTERNS, closing a bypass where a comment inserted between
  a function name and '(' hid it from the regex (e.g. pg_read_file/**/(...)).
- UPDATE now requires confirm=true just like DELETE (deleteCount/updateCount).
- Batches run inside a single DB transaction; a failing statement rolls back
  everything already applied in that batch instead of leaving partial writes.
- splitStatements() (PHP and JS) now tracks a single quoteChar instead of a
  bool, handling both '...' strings and "..." quoted identifiers symmetrically.
- Frontend TEMPLATES no longer rely on SET/current_setting: the escaped uid
  is inlined into every statement, so partial copy/paste still works.
- renderTable() renders NULL as [NULL] instead of an empty string, so it's
  no longer visually identical to an empty string value.
- Added MAX_SQL_BYTES (1MB) request size limit, returned as HTTP 413.
- Added a 120s client-side AJAX timeout with a distinct timeout message,
  so a hung request doesn't leave the terminal paused indefinitely.
2026-07-06 19:38:25 +03:00
Egor Bugaev 8aaab998a1 Harden SQL mode: block file/program access, audit log, row limit, quote-aware statement splitting 2026-07-06 17:54:36 +03:00
Egor Bugaev d402da8498 Add SQL query templates and psql-style table output for SELECT 2026-07-06 17:16:47 +03:00
Egor Bugaev 4d87deb176 Require explicit confirmation before running DELETE statements in SQL mode 2026-07-06 17:03:51 +03:00
fanategorius b6849053d2 Update index.js 2026-07-06 16:28:22 +03:00
fanategorius b6ea7b9d92 Update index.js 2026-07-06 16:27:52 +03:00
fanategorius b98df89971 Update index.js 2026-07-06 12:51:15 +03:00
Adphi 1745aa185a fix greetings not updating date on exit 2019-01-19 19:15:22 +01:00
Adphi e5a9f0142f add scroll down on key down 2019-01-19 18:09:39 +01:00
Adphi 5e7da4b5c7 added alias c to clear and exit command 2019-01-19 16:38:43 +01:00
Adphi c642ad90f9 fixed navigation 2019-01-19 16:16:04 +01:00
Adphi 32837fffa6 renamed app 'OCC Web' 2019-01-19 15:54:24 +01:00
Adphi c909a11420 init: term colors, completion, execution 2019-01-19 15:40:52 +01:00