Журнал изменений

Официальный сайт SLAED CMS

Журнал изменений

Фильтр и поиск

Всего: 1230 Доступных коммитов | Отфильтровано: 1230 Коммиты | Страница: 1 из 123
Сегодня (07.10.2026)
Fix: The rehearsal of update.php on the production dump runs through, a forum file outside the forum reaches its post, and the folders move after the migration
Автор: Eduard Laas | Дата: 00:44 07.10.2026

Roadmap step 15, the rehearsal of docs/1-FILES-2026.md: update.php of the tree ran both stages over HTTP on a copy of the production dump of 2026-09-30 with the production files, in a scratch tree outside the stand. It found four faults, each fixed here, and that a clean 6.2 site is not migrated; every file address of the stored texts was compared before and after, and the pages that show them were crawled.

Core changes:

  1. First stage (public/update.php):
  2. The first stage defines UPLOADS_DIR, which setUpdateAttach() reads for the forum and the private messages

    • Without it the first forum post with a direct address stopped the update with a fatal error
  3. setUpdateConfig() drops a 6.2 global key that names a configuration area (forum, newsletter, search)

    • getConfig() merges the files in name order, so 'forum' => '0' of global.php replaced the whole forum area and
every topic answered a TypeError
  1. Foreign addresses (public/update.php):
  2. getMigrateForeign() takes the owner of the file route
  3. setMigrateForeign() points a direct address of uploads/forum/ in any text but a forum post at the go=file address of the first published post that carries the name

    • The news #468 and the private message #1665 of production reach their forum files through posts #6235 and #14824
  4. Order of the operator (UPGRADING.md, docs/NODE.md, lang/*.php):
  5. The upload folders move into uploads/node/<type>/ after the migration and before the site opens

    • addNodeType() refuses a type whose folder already holds a file, so a folder moved before the run stopped it
  6. _NODE_MIGINFO says so in the six locales
  7. NODE.md records the foreign address step, the path constants of the first stage, the dropped global keys and that the migration reads the 6.3 shape of the module tables, which a clean 6.2 site does not have

  8. Tests and probes (tests/Unit/UpdateSiteTest.php, tests/Unit/UpdateConfigTest.php, tests/Unit/UpdateAttachTest.php, tests/Support/install_probe.php, tests/Support/update_probe.php, tests/Fixtures/update62/site.sql):

  9. The update62 fixture seeds a forum post and a private message with direct addresses; the probe reports both texts

    • The forum post is one more rating target, so the expected count is 4
  10. The configuration probe ships forum.php and carries the 6.2 key forum, which must not reach global.php
  11. UpdateAttachTest covers the forum owner of getMigrateForeign()
  12. Documentation and plans (docs/1-FILES-2026.md, docs/ROADMAP-2026.md):
  13. The files plan records the rehearsal and the decisions "The rehearsal data", "The folders move after the migration" and "A forum file outside the forum"; the roadmap ticks step 15

Benefits:

  • update.php runs through on the production data of slaed.net without a stop
  • Of 721 file addresses in the stored texts none is lost; the guest crawl of 231 pages saw 1049 file references, all answering 200, and the 12 addresses no guest reads answered 200 to the panel

Technical notes:

  • Breaking for the operator: the folder moves of UPGRADING.md now come after update.php, not before
  • A clean 6.2 site with sid, hometext and bodytext is not migrated; update.php serves slaed.net alone
  • The stand database still carries the two forum addresses of news #3895 and private message #1665 unconverted
  • No schema change
Вчера (06.10.2026)
Feature: The archive folder answers 410, and an address into the folder of another type reaches the material that carries the file
Автор: Eduard Laas | Дата: 23:13 06.10.2026

Batch 8 of docs/1-FILES-2026.md (step 14 of docs/ROADMAP-2026.md). uploads/archive/ leaves the public list of the light path, and update.php points a direct address a text keeps into the 6.2 folder of a type it does not belong to at the go=file address of a published material of that type which carries the name: one owner and one route per file.

Core changes:

  1. The archive retired (core/stream.php):
  2. archive is off getUploadPublic(), so every address under uploads/archive/ answers 410, an existing file included
  3. Addresses of another owner (public/update.php):
  4. getMigrateForeign() rewrites uploads/<dir>/<name> and its thumb into ./index.php?go=file&own=node&id=<id>&key=<name>

    • [code] and [php] keep their examples, another host and a name outside the attachment grammar stay
    • A name no material carries keeps its address, which answers 410
  5. setMigrateForeign() runs after the data step on every run of the migration over Node texts, comments, the forum, private messages, site messages, newsletters, blocks, signatures, own blocks and polls

    • The material is the first published one of the type whose text, [usehtml] address or published comment carries
the name; the own folder of a material and of its comments stays with batch 3
  • A text the longer address would push past its column keeps its addresses and is named in the notes of the run
  1. Tests and probes (tests/Unit/UpdateAttachTest.php, tests/Unit/PublicTreeTest.php, tests/Unit/UploadFormatTest.php, tests/Support/format_probe.php):

  2. UpdateAttachTest covers the pointing, the thumb, the kept example, the other host and the name no material carries
  3. PublicTreeTest refuses uploads/archive/ and gives it no address; the format probe renders through presentation
  4. Documentation and plans (docs/*, UPGRADING.md):
  5. The files plan records batch 8, the stand run and the decisions "A file of another owner" and "The stand texts of batch 3"; the roadmap ticks step 14

  6. UPGRADING.md drops archive from the public folders and describes the pointing of foreign addresses

Benefits:

  • No file of the archive is readable by its address any more
  • A forum post, a message or a newsletter that showed a file of a news or files material keeps showing it to the reader of that material, without a copy

Technical notes:

  • Breaking: uploads/archive/<name> answers 410
  • On the stand the conversion of batch 3 ran again (122 materials, 4 comments) and the pointing reached message #16, newsletter #11 and forum post #2791; no stored text addresses uploads/archive/

  • No schema change
Feature: The files of a comment on a poll or a profile leave only to a reader of its target, and every comment binds only a name it may carry
Автор: Eduard Laas | Дата: 22:05 06.10.2026

Batch 7 of docs/1-FILES-2026.md (step 13 of docs/ROADMAP-2026.md). uploads/voting/ leaves the public list of the light path and the owner comment gets its adapter in FileAccess: a comment grants the [attach] names its body carries to a reader of its poll or profile while it is published, and the comment layer refuses a new name the writer may not bind on every target, Node included.

Core changes:

  1. The comment adapter (core/stream.php, core/system.php, core/classes/access.php, core/user.php):
  2. voting is off getUploadPublic(); getUploadOwner() names comment for it
  3. getFileService() wires comment: its target is the id of the comment, its folder the one the comment form of its target uploads into (getCommentPlace(): uploads/voting/, uploads/profile/)

  4. checkCommentFile() serves a name of a published comment whose module page is open to the reader and whose target shows its discussion (Comment::getTargetMode()); a moderator of the module reads every comment

    • A comment of a Node material is refused here and keeps its route through the material
  5. FileAccess::PREVIEW gains comment; own=comment&name=voting serves the own upload of the poll comments
  6. getCommentBody() renders a comment in ['comment', $id] against the folder of getCommentPlace()
  7. The profile owner (core/user.php):
  8. checkProfileFile() grants the names of the own block to its owner alone, beside the signature for every reader of the profile

  9. Writers of a comment (core/classes/comment.php):
  10. Comment::checkAttachNames() refuses the first new [attach] name that is no own upload of the folder, no file for a moderator of it and no name the same target already serves

    • A published comment of the target, and for Node NodeService::getNodeFile() of the material
  11. The new comment, the author edit and the moderator edit (updateBody()) ask it
  12. Tests and probes (tests/Unit/FileAccessTest.php, tests/Unit/PublicTreeTest.php, tests/Support/route_probe.php):
  13. getRouteComment() covers a published and a pending comment of a poll and of a profile, a hidden poll, a guest, the author, a moderator, closed profiles, the preview, both pages, the own block and the three writers of a poll, a profile and a Node comment

  14. FileAccessTest the preview address of comment; PublicTreeTest the closed folder of voting
  15. Documentation and plans (docs/*, UPGRADING.md):
  16. The files plan records batch 7 and the decisions "The poll folder" and "A name in a comment"; the roadmap ticks step 13

  17. UPGRADING.md and PARSER.md describe the closed poll folder and the file context ['comment', $id]

Benefits:

  • A file of a hidden poll or of an unpublished comment is no longer readable by anyone who knows its address
  • A comment can no longer publish a file of another account's own block or of an unpublished Node material

Technical notes:

  • Breaking: uploads/voting/<name> answers 410; no comment of a poll or a profile carries a file on the stand, so nothing was converted

  • A comment on a profile of a 6.2 site with an [attach] of a file in uploads/account/ needs that file copied into uploads/profile/ (UPGRADING.md)

  • No schema change
Feature: The files of a private message leave only to its two sides, and the account texts get a closed folder of their own
Автор: Eduard Laas | Дата: 21:20 06.10.2026

Batch 6 of docs/1-FILES-2026.md (step 12 of docs/ROADMAP-2026.md). uploads/account/ leaves the public list of the light path and holds the files of the private messages alone; the signature, the own block and the comments on a profile upload into the new closed folder uploads/profile/, and every page renders a signature in the file context of its account.

Core changes:

  1. The private message adapter (core/stream.php, core/system.php, core/classes/access.php, core/classes/privat.php, core/user.php, core/admin.php):

  2. account is off getUploadPublic(); getFileService() wires privat to uploads/account/ and checkPrivatFile()

    • A name a message carries goes to a side that still holds it (Privat::getMessageBody())
    • A moderator of account reads every message; the panel list renders a body in ['privat', $id]
  3. checkPrivatNames() lets a writer bind an own upload or a name a message they still read carries, so a reply quotes and a forward carries its files; addPrivateMessage() refuses any other name (Privat::getAttachBodies())

  4. The profile owner (config/uploads.php, core/system.php, core/user.php, modules/account/*):
  5. A new owner profile with its rule in config/uploads.php, moderated as account through checkUploadModer()
  6. checkProfileFile() grants the names of a signature to whoever may open the profile; checkProfileNames() refuses a foreign name in the signature and the own block on savehome

  7. The signature, the own block and the comments on a profile upload into profile (getCommentPlace())
  8. getUserSign() renders a signature in ['profile', $uid] on the forum, the profile, the private message and the comments, which printed the stored source unparsed until now; getUserBlock() renders in ['profile', $uid]

  9. The mail texts of the panel render against the public folder all
  10. One set of upload helpers (core/system.php, core/user.php, core/classes/node/service.php):
  11. getUploadOwner() names the closed owner of an upload module for the editor window and every renderer
  12. checkUploadPreview() and checkUploadNames() replace the copies inside the forum adapter and serve all three owners
  13. FileAccess::PREVIEW gains privat and profile
  14. The grant of a stored text no longer asks the extensions of the upload rule, Node included: the rule decides the upload, the preview and a new binding, not whether a stored name is served

  15. Migration (public/update.php):
  16. setUpdateAttach() replaces setUpdateForum() and runs over the forum and the private messages

    • The stand ran it once over the messages: the three addresses of brandbook.pdf (#1690, #1691, #1694) became [attach]
  17. Tests and probes (tests/Unit/*, tests/Support/route_probe.php):
  18. FileAccessTest and getRouteAccount() cover both sides, a deleted side, a third account, a guest, a moderator, the previews, a forward, a foreign and a deleted name, the signature on three pages, closed profiles and the profile form

  19. NodeServiceTest the moderator of profile; PublicTreeTest the two closed folders; UpdateAttachTest a labelled link of a private message

  20. Browser tooling (package.json, tools/browser-audit.mjs):
  21. playwright ^1.63.0; chrome-remote-interface leaves the dev dependencies
  22. browser-audit.mjs prefers the Chromium build pinned by the installed playwright over older revisions on disk
  23. Documentation and plans (docs/*, UPGRADING.md):
  24. The files plan records batch 6 and the decisions "The profile folder", "A name in a private message", "The administrator and private files" and "The rule governs the upload"; the roadmap ticks step 12

  25. UPGRADING.md, ARCHITECTURE.md and PARSER.md describe the closed account folder, the profile folder and the file contexts ['privat', $id] and ['profile', $uid]

Benefits:

  • A file sent in a private message is no longer readable by anyone who knows its address
  • Narrowing an upload rule no longer cuts off what was uploaded under it

Technical notes:

  • Breaking: uploads/account/<name> and uploads/profile/<name> answer 410; update.php rewrites the addresses of the private messages to [attach]

  • config/uploads.php gains the rule profile; a 6.2 signature, own block or mail text with an [attach] of a file in uploads/account/ needs that file copied into uploads/profile/ or uploads/all/ (UPGRADING.md)

  • Until batch 7 an attachment of the own block or of a profile comment has no address; neither carries one today
  • No schema change
Feature: The files of the forum leave only through go=file to a reader of the post that names them
Автор: Eduard Laas | Дата: 19:01 06.10.2026

Batch 5 of docs/1-FILES-2026.md (step 11 of docs/ROADMAP-2026.md). uploads/forum/ leaves the public list of the light path and gets its own adapter in FileAccess: a post grants the [attach] names its text carries to whom its topic page shows it, the preview form grants the visitor's own upload, and a writer can bind only a name they may carry.

Core changes:

  1. The forum adapter (core/stream.php, core/system.php, core/classes/access.php, core/user.php):
  2. forum is off getUploadPublic(); getFileService() wires its folder and checkForumFile() as its grant

    • The gate of the module page first, then the reader of the category while the post and its topic are published
    • A moderator of the forum reads every post, a moderator of the category the published posts of any topic
  3. FileAccess::PREVIEW lists the owners with a preview form; the forum joins Node with name=forum
  4. setFileRoute() and getFileUrl() accept the preview of every owner on that list
  5. getEditorFileData() gives a file of the forum the preview address and inserts it as [attach] alone
  6. Writers of a post (core/user.php, modules/forum/index.php, lang/*):
  7. checkForumNames() refuses a new [attach] name that is no own upload, no file for a forum moderator and no name a published post of the same topic carries; the full form and the quick edit ask it

  8. _FILE_FOREIGN in all six locales names the refused file
  9. Rendering in the file context (core/user.php, core/helpers.php, core/classes/parser.php, modules/forum/index.php):
  10. getForumBody() renders a post in ['forum', $id], the preview of an unsaved post in ['forum', 0]
  11. The parser accepts target 0 as an unsaved text; getTplPreviewContent() passes own on
  12. getImgText() takes a file context, so the og:image of a topic is the file route of its first post
  13. The signature on a forum page renders against account, the folder its editor uploads into
  14. Migration (public/update.php):
  15. setUpdateForum() turns a direct address of a file uploads/forum/ holds into [attach] of the same name
  16. getMigrateAttach() also reads a Markdown image and drops a link label that is its own address

    • The stand ran it once: 121 of 124 posts; three images inside a foreign link and one example inside [code] stay
  17. Tests and probes (tests/Unit/*, tests/Support/route_probe.php):
  18. FileAccessTest and the route probe cover a closed category, a hidden topic, an unpublished reply, a guest, a member, a moderator, the preview and the three writers

  19. QuickEditTest the refused foreign name; UpdateAttachTest the Markdown image and the labelled link
  20. ParserFixturesTest the preview address of an unsaved text; PublicTreeTest and FileManagerPathTest the closed folder
  21. Documentation and plans (docs/*, UPGRADING.md):
  22. The files plan records batch 5 and the decisions "A preview of the forum", "A quoted attachment" and "The signature on the forum"; the roadmap ticks step 11

  23. UPGRADING.md and PARSER.md describe the closed forum folder and the file context of a post

Benefits:

  • A file attached in a closed category is no longer readable by anyone who knows its address
  • A quote carries an attachment within its topic without opening a file of another category

Technical notes:

  • Breaking: uploads/forum/<name> answers 410; update.php rewrites the addresses of posts to [attach]
  • The signature keeps the public account folder until batch 6 closes it
  • No schema change
Feature: Every uploaded file leaves through one route that asks its owner, attachments gain a full-size form, and retired addresses answer 404, 410 or 301
Автор: Eduard Laas | Дата: 16:09 06.10.2026

Roadmap steps 7 to 10 land together: item 1 of the production findings, and batches 2, 3 and 4 of the files plan. FileAccess now owns the delivery decision of every file through one adapter per owner, the parser asks it for each address instead of building one, and go=file is the single file address of the site, Node included.

Core changes:

  1. One route for every file (core/classes/access.php, core/system.php, public/index.php, modules/node/index.php):
  2. FileAccess takes one adapter per owner of the closed set FileAccess::OWNERS as two closures, folder and grant

    • getFilePath() adds the shared checks: a bare name of a supported type, the file inside the folder of its owner,
a thumb only when its copy exists; every refusal is an empty answer
  • getFileUrl() answers the go=file address of a closed owner, the Node preview of a type, the direct link of a
public folder
  • getFileService() wires node (grant through NodeService::getNodeFile(), the type of a material read from its row, nothing while a configuration journal holds the type) and public (no route)

  • setFileRoute() serves go=file: the query is exactly an owner with its target or the preview of a Node type, GET and HEAD only, every refusal the same 404

  • op=attach and setNodeAttach() are retired; getNodeQuery() moved to the core as getStrictQuery()
  • setErrorOut() treats go=file as a non-HTML answer
  • Parser file context (core/classes/parser.php, core/user.php, core/classes/node/view.php, modules/search/index.php):
  • filterContent() and filterDoc() take array $own (['node', $nid]) in place of int $nid; the cache key carries it
  • filterAttach() asks FileAccess for the folder and every address, and makes a thumb only where the owner has a folder
  • The editor file list and the preview of an unsaved resource take their address from getFileUrl()
  • Inline attachment (config/filetype.php, admin/modules/uploads.php, window-body-insert.html, filemanager.js, lang/*):
  • [attach ... size=full] renders the template full at the own size of the image and makes no thumb, falling back to the template of its extension when full is empty

  • The uploads screen edits full beside the extensions; the insert window offers Thumbnail or Full size
  • Node texts off the archive (public/update.php, core/classes/node/service.php, core/classes/parser.php):
  • update.php moves, copies and renames no file; getMigrateAttach() turns a direct address of the own folder into [attach] with the name unchanged, and a source inside [usehtml] into the go=file address of its material

  • getNodeFile() grants the names such an address carries and no longer needs a managed name for a stored material
  • checkImageSource() keeps the query of a local source, so an attachment image no longer renders as index.php
  • Retired addresses (core/security.php, core/stream.php, nginx.conf.example):
  • A path that is no address answers 404, a missing upload 410, and /index.php/... a 301 to the clean address
  • Tests and probes (tests/Unit/, tests/Support/, tools/*):
  • FileAccessTest: closed owners, every address form, a carried name whatever its form, refusals of every other name
  • UpdateAttachTest for the migration of 6.2 texts; ParserFixturesTest for the file context and the full-size form
  • The route probes follow go=file: 20 crafted queries refused, POST 405, the retired op=attach 404
  • Documentation and plans (docs/*, UPGRADING.md, README.md, admin and module help):
  • NODE.md, PARSER.md, ARCHITECTURE.md describe the file route and the file context
  • The files plan records batches 2 to 4 and the decision "One file address"; the roadmap ticks steps 7 to 10
  • docs/4-EDITOR-2026.md, the plan of the editor work, joins the roadmap
  • Design demos (public/demo/*):
  • The editor variants ed-plain-01..08 and ed-code-01..09 with their CodeMirror bundle, and the Node header variants nh-01..10

Benefits:

  • One decision and one sender for every uploaded file, so closing the forum, private messages and comments in the next batches is one adapter each

  • No address of a file is spelled outside FileAccess

Technical notes:

  • Breaking: op=attach answers 404; the stand rewrote its 184 [usehtml] addresses to go=file, and production never carried op=attach

  • Breaking: Parser::filterContent() and filterDoc() take array $own instead of int $nid as the sixth argument
  • No closed owner but Node is wired yet; forum follows in batch 5
Chore: The old installer leaves the tree, so no guard file and no SQL dump lies outside public/
Автор: Eduard Laas | Дата: 09:07 06.10.2026

Batch 4 of docs/0-PRIVATE-DATA-2026.md (step 6 of docs/ROADMAP-2026.md). setup_old/ was the last folder of the project that carried its own .htaccess and index.html guards and kept ignored .sql files beside them; the new installer in public/setup.php replaced it, so the folder goes whole and the tree test stops exempting it.

Core changes:

  1. The old installer (setup_old/*):
  2. setup_old/ is deleted with its language files, templates, images and guards

    • Its ignored .sql files went with it; they stay in history before b2973ad4, the schema lives in storage/update/sql
  3. Tests (tests/Unit/PublicTreeTest.php):
  4. The check for guard files outside the document root no longer skips setup_old/
  5. Documentation (docs/0-PRIVATE-DATA-2026.md, docs/ROADMAP-2026.md):
  6. The plan records batch 4 as done; the roadmap ticks step 6

Benefits:

  • No guard file is left that a server misconfiguration could rely on outside public/
  • One installer remains, the one that is tested and shipped

Technical notes:

  • No schema change, no address change
  • nginx.conf.example, the other half of the batch, landed with step 4
Feature: The installation proves from inside the panel that only public/ is reachable, and a Node type goes public only on that proof
Автор: Eduard Laas | Дата: 08:56 06.10.2026

Batch 3 of docs/0-PRIVATE-DATA-2026.md (step 5 of docs/ROADMAP-2026.md). A random marker check.txt lies in the project and in storage/, config/, uploads/ and admin/info; an hourly scheduler job asks each at the address it would have under the site address and judges by the body, never by the status. The panel warns when a root is open, unknown or not checked within a day, and switching a Node type on asks the same check for the upload root.

Core changes:

  1. The self-check (core/system.php, config/scheduler.php, .gitignore):
  2. getPrivateRoots() names the project and the four folders that hold the secrets
  3. setPrivateMark() keeps a random 32-hex marker per folder, written again under a lock when missing or damaged
  4. checkPrivateRoots() asks every marker over getSchedulerFetch() with the transport as a seam for tests

    • open: the marker is in the body, whatever the status; closed: any other answer; unknown: no answer or no http(s) site address
  5. addSelfCheckTask() is the system job selfcheck, every hour at minute 20; it keeps the verdict of every root in its scheduler state and fails on a root that is not closed

  6. The markers are ignored by git, so a shipped copy cannot let a copy of the delivery pass for the site
  7. Panel (admin/index.php, admin/modules/security.php, admin/lang/*.php):
  8. getSelfCheckAlert() warns on the home of the panel about an open or unknown root, with its addresses, and about a verdict older than a day; the security section adds the all-clear with the time of the last run

  9. _SEC_CHECK_DONE, _SEC_CHECK_NONE, _SEC_CHECK_OPEN and _SEC_CHECK_UNK in all six locales
  10. Node types (core/classes/node/service.php):
  11. checkTypeGuard() asks checkPrivateRoots() for the upload root alone instead of a request to the type folder; only closed lets a type go public

  12. Installer and update (public/setup.php, public/update.php):
  13. The last part of setup.php, the one that runs with the core, writes the markers
  14. update.php adds the job selfcheck to a scheduler that does not carry it; two long comments are shortened
  15. Documentation and help (docs/*, admin/info/scheduler/ru.md, modules/node/admin/info/ru.md, .gitmessage):
  16. The plan records batch 3 and the project as the fifth watched root; the roadmap ticks step 5
  17. NODE.md, the scheduler help and the Node help describe the check behind switching a type on
  18. .gitmessage states one task, one commit
  19. Tests (tests/Unit/SelfCheckTest.php, tests/Support/check_probe.php, tests/Unit/NodeConfigTest.php, tests/Support/node_probe.php):
  20. New SelfCheckTest: every root at its own address with its own marker, three verdicts, the body decides and not the status, a missing marker written again, the job state shown by the panel, a stale verdict counted as none

  21. The gate of the Node probe runs on the marker of the upload root instead of a served file of the type folder

Benefits:

  • An operator learns from the panel, not from a leak, that a document root or a server alias exposes the project
  • One check serves the panel, the scheduler and the switch of a Node type

Technical notes:

  • New scheduler job selfcheck; existing sites gain it through update.php
  • check.txt markers are written per installation and never shipped
  • No schema change
Эта неделя (05.10.2026)
Refactor: The document root is public/, every upload leaves through one light path outside it, and nginx ships its own server block
Автор: Eduard Laas | Дата: 23:01 05.10.2026

Batch 2 of docs/0-PRIVATE-DATA-2026.md (step 4 of docs/ROADMAP-2026.md), with the server half of batch 4. The browser now reaches public/ and nothing else: the code, config/, storage/ and the whole uploads/ lie at the project level, so no server misconfiguration can serve a journal, a backup or a closed upload folder. Public upload addresses keep working through a light path of the front controller that answers before the core boots.

Core changes:

  1. The public/ tree (public/*, .htaccess, nginx.conf.example):
  2. templates/, plugins/, sound/, demo/, .htaccess, favicon.ico, robots.txt, error.html and sitemap.xml move into public/
  3. index.php, setup.php and update.php move into public/ whole and define BASE_DIR and PUBLIC_DIR themselves; public/admin.php stays the short file that runs admin/index.php

  4. public/.htaccess drops RewriteBase and refuses the PHP and the markup of the themes; a project-level .htaccess rewrites every request into public/ and refuses everything without mod_rewrite

  5. nginx.conf.example: root on public/, location ^~ /uploads/ to index.php, the theme refusals and the error pages
  6. One upload root and the light path (core/stream.php, core/system.php, core/classes/*):
  7. core/stream.php: UPLOADS_DIR, getUploadPublic(), getUploadUrl(), getUploadRequest(), setUploadStream() and getFileStream()

    • The light path serves a public folder with nosniff, a sandbox policy, a day of public cache, ETag, 304 and ranges
    • Every other folder, a dot segment, a traversal or a missing file answers 404 without loading the core
  8. getFileStream() takes a cache mode (none, private, public) and sends the sandbox policy on every answer
  9. No caller spells 'uploads/' into an address: the parser, getImgText(), the upload rules, avatars, presentation and the file layer ask getUploadUrl(); a private folder has no direct address

  10. The upload service creates a missing folder of its owner on the first write; a missing folder is no refusal of a rule
  11. addEditorUpload() builds the file context after the write, so the first upload into a new folder reports its file
  12. Guards and paths (core/, admin/, modules/, blocks/):
  13. Every .htaccess and guard index.html outside public/ goes, with their writers in FileManager, NodeService, CaptchaStore and update.php; the counters create storage/counter themselves

  14. Every path that relied on the working directory reads BASE_DIR or PUBLIC_DIR: language files, module scans, theme assets, logos, ranks, flags, the sitemap, the file scan, the template editor and the .htaccess and robots.txt editor

  15. The critical files of the file manager follow PUBLIC_DIR, so a document root named public_html keeps them
  16. The installer records the mode of the document root as webroot in config/global.php and shows it as a check row; the avatar folder ships as avatars below uploads/ with its own settings label

  17. Documentation and help (README.md, UPGRADING.md, docs/, admin/info/, modules/*/admin/info/ru.md):
  18. README and the help of the security section explain both modes, Apache, LiteSpeed, nginx and three variants for shared hosting; UPGRADING.md and the help point at nginx.conf.example

  19. The plans record the decisions of the batch, the real entries in public/ and the writer that creates a folder
  20. Tests and tools (tests/, tools/):
  21. New PublicTreeTest: the light path over real HTTP without the core, nothing of the project on public/, both .htaccess files, getUploadUrl() and no guard outside public/

  22. New NginxConfigTest: nginx.conf.example refuses exactly what public/.htaccess refuses, file by file, and passes nginx -t where a binary is set in SLAED_NGINX

  23. The probe servers serve public/ and run the real light path; the probes write no guards
  24. ui-contract, ui-audit and the pre-commit hook watch public/templates and public/plugins

Benefits:

  • No server rule is needed to keep config/, storage/ or a closed upload folder private
  • One sender and one list decide every upload address and its delivery; closing an owner is one line of the list
  • nginx gets a tested server block instead of rules copied from the documentation

Technical notes:

  • Breaking change: the document root of a site must point at public/, or the project-level .htaccess must rewrite into it on Apache or LiteSpeed; a server without .htaccess support needs nginx.conf.example

  • Upload addresses uploads/<folder>/<name> of public folders do not change; files of Node types have no direct address
  • NodeProfileTest fails 11 of 14 on the stand as on the clean HEAD before this change; the installer of the probe does not reach the database there

Refactor: Every Node type keeps its files in uploads/node/<type>, one function names the folder of an owner, and the files plan records its decisions and inventory
Автор: Eduard Laas | Дата: 18:06 05.10.2026

Batches 0 and 1 of docs/1-FILES-2026.md. Node types no longer share the upload root with the modules: they live below one root of their own, so a type can only meet another type there, and every builder of an upload path asks one function instead of spelling 'uploads/'.$mod. The plan carries the owner's decisions and the inventory of the stand database that the later batches rely on.

Core changes:

  1. One root for the types (core/system.php, core/classes/parser.php, modules/node/index.php, update.php):
  2. NODE_DIR is UPLOADS_DIR.'/node'; getUploadFolder($mod, $node) answers node/<type> for a type, the own name for a module

    • The flag names a type the registry does not carry yet or no longer, as type operations and update.php do
  3. getUploadRuleData(), getUploadPlaceRule() (store), getImgText(), Parser::filterAttach() and getNodeAssetPath() ask it
  4. Node service and locks (core/classes/node/service.php, core/classes/filemanager.php):
  5. setTypeRoot(), checkTypeGuard(), setTypeWrite(), updateNodeTypeStatus(), deleteNodeType(), checkNodeFiles(), setNodeWrite() and getNodeFile() build the type folder through getUploadFolder()

  6. checkNewName() drops its scan of the upload root; a module name and a key of config/uploads.php stay refused
  7. FileManager::getPathLock() takes uploads/node/<type> as the root of an upload area, so two types never wait for each other
  8. Administration (core/admin.php, admin/modules/uploads.php):
  9. getAdminUploadRule() reads the type out of a path below uploads/node and hands the owner on as mod
  10. getUploadsFolders() lists the folders of the upload root with the type folders below uploads/node

    • The default folder setting keeps an owner name, its label shows the path
  11. The tree and the documents (uploads/, UPGRADING.md, docs/, modules/node/admin/info/ru.md, admin/info/config/ru.md):
  12. uploads/{content,docs,faq,files,help,links,news} move to uploads/node/, which carries index.html and .htaccess
  13. UPGRADING.md gives the operator the folder move; NODE.md and the help name uploads/node/<type>
  14. docs/1-FILES-2026.md records the decisions of batches 0 and 1 and the inventory; docs/ROADMAP-2026.md ticks steps 2 and 3
  15. Tests and tools (tests/*, tools/node-profile.php, tools/upload-route-check.php):
  16. The probe routers follow the nginx rule below a folder of the upload root instead of one level only
  17. Route, node, install, upload and image probes build their type folders below uploads/node
  18. New: the folder of a type through every rule builder, two types as two lock areas, names a folder of the root carries

Benefits:

  • A type can no longer collide with a module folder, and the type check no longer scans the upload root
  • The place of the types is decided once, which batch 2 of 0-PRIVATE-DATA-2026.md needs to take uploads/node out of public/

Technical notes:

  • Breaking: a site whose type folders sit at uploads/<type>/ moves each to uploads/node/<type>/ before the new files serve
  • No public address changes: texts reach type files through op=attach and op=asset by name, no stored row carries the folder
  • NodeProfileTest fails 11 of 14 as on a clean HEAD (the installer copy never gets config/db.php); not caused by this change

Страница 1 из 123. Всего: 1230

1 2 3 4 5 6 7 8 9 10 … 123
Хотите опробовать SLAED CMS в действии?
Идеи и предложения
Обратная связь
Подтверждение

Поделиться
QR-код

Предварительный просмотр