Simple Website Framework

Uploading Files

Wednesday October 21st, 2026

Written by Scary le Poo

The editor can put files on the server for you, so an image for a page no longer means opening an FTP client. There are two ways in: the Files screen, for managing the site's media folders directly, and the picture button in the content editor, which uploads the image you pick and inserts it where the cursor is.

Both belong to the editor, so they are available when $editorEnabled is true.


The Files screen

Open Files from the editor toolbar. Across the top are the folders uploads may go into, and inside each you see its subfolders and files, newest first, with thumbnails for images. From here you can:

  • Upload by dropping files onto the dashed box or clicking Choose files. Several at once is fine. Each file reports success or the reason it was refused.
  • Create a subfolder, say images/projects/, and upload into it.
  • Copy path on any file, ready to paste into a page's <img src="…"> or its Image field. Paths are relative to the site root, which is how pages refer to files: images/kitchen.jpg.
  • Delete a file. It goes to a trash, not the bin, and can be brought back from the Backups screen.

Names are tidied on the way in: lowercase, letters and digits, hyphens for everything else. Kitchen Remodel (Final).JPG is stored as kitchen-remodel-final.jpg, so the path you paste into a page will never need quoting or escaping. Uploading a name that already exists gives the new file a numbered name, kitchen-2.jpg; tick replace a file that has the same name to overwrite instead, in which case the old file goes to the trash first.


Putting a file into a page

Once a file is on the server there are three ways to use it, from quickest to most manual:

  • The Files button in the content editor's toolbar (next to the picture button). It opens a dialog showing the same folders and thumbnails as the Files screen; click an image and it is inserted where the cursor was. Tick show all files to insert a link to a PDF or other non-image. Upload new… at the bottom uploads into the folder you are looking at without leaving the page.
  • Choose… beside the Image field, for the page's share and archive image. Same dialog; the chosen path goes into the field. Uploading a single new file here fills the field straight away.
  • Copy path on the Files screen, then paste it wherever you need it — into the code view, or an <img src="…"> in a Markdown page.

The picture button

In the content editor, the picture button's default behaviour (from the Summernote library it uses) is to embed the image inside the page as a huge block of text, which makes the page file enormous and the image uncacheable. The editor overrides that: the image is uploaded and its path inserted instead. Posts upload to pages/posts/images/, pages to pages/images/, and the status line says where it went.


Where files may go

Uploads are allowed only into the folders named in $uploadDirs, and their subfolders:

$uploadDirs = array('images', 'pages/images', 'pages/posts/images', 'videos');

That default is the set of places this framework keeps media. Add your own folders to the list if you keep files elsewhere. Some folders can never be upload targets whatever the list says: pages/ itself (an upload there would be a page), and every code folder, plugins/, required/, includes/, themes/, css/, config/, and the backup folder.

A folder that does not exist yet is created on the first upload into it.


What is accepted

Images (jpg, png, gif, webp, avif, svg, ico), video (mp4, m4v, webm, ogv, mov), audio (mp3, ogg, wav, m4a, flac), PDF, office documents (doc, docx, xls, xlsx, ppt, pptx, odt), text (txt, md, csv, json, vtt, srt), fonts (woff, woff2, ttf, otf) and zip.

A file has to pass two checks, not one. Its extension must be on that list, and what is actually inside must match: PHP looks at the content, and a file called photo.png that is really a script is refused with a message saying so. Images additionally have to decode as images. Anything that could run on the server, .php, .phtml, .phar, .cgi, .htaccess and the like, is refused outright and cannot be added to the list.

Each upload folder also receives a small .htaccess telling Apache never to execute scripts there, rewritten on every upload. So even a file that somehow got through could only ever be served as a download, not run.

Worth being clear about what this does and does not protect. The editor already lets anyone who is logged in write any HTML they like into a page, so these checks are not a boundary between trusted and untrusted people. They stop accidents, and they make sure a hijacked session cannot gain anything it did not already have. The password and two-factor are the boundary.

Size

$uploadMaxSize caps each file, 25 MB by default. It can never exceed PHP's own limits, upload_max_filesize and post_max_size, which are set by your host; the Files screen shows whichever is in force. A shared host often allows 8 to 64 MB. If an upload of several files fails as a whole, it is usually post_max_size, which applies to the total; send fewer at a time.


Settings

Both optional; an older config.php without them gets the defaults.

SettingDefaultWhat it does
$uploadDirsarray('images', 'pages/images', 'pages/posts/images', 'videos')Folders (and their subfolders) uploads may go into. Code folders and pages/ are never allowed.
$uploadMaxSize25 * 1048576Bytes per file, bounded by PHP's own limits.