Developers
Accessing files
Two different problems share this name: getting at a hub's files on the server, and reading and writing files from inside your code. This page covers the first and points at the chapter that covers the second.
Reaching the server
A hub runs on a Linux server and you work on it over SSH. From a terminal:
ssh username@hub.example.org
For file transfer, use sFTP, which runs over the same SSH connection and encrypts commands and data alike. An ordinary FTP client cannot talk to it.
sftp username@hub.example.org
Any current SSH client works. Windows ships OpenSSH, so ssh and sftp work
from PowerShell or the Command Prompt; PuTTY and
WinSCP are the long-standing graphical alternatives.
macOS and Linux have ssh and sftp installed already.
Inside an sftp session, get and put transfer a file, ls and cd work
on the remote side, lls and lcd on the local side, and help lists the
rest. scp -r and rsync -a are usually quicker for a whole directory.
Finding the hub
The web root is the hub's document root, conventionally /www/<hubname> on
a Hubzero server. Many sites keep a second, development copy alongside it,
often /www/dev. Both are ordinary directories; nothing in the CMS depends
on the name.
Underneath, the layout is the one described in
Structure: core/ holds the platform,
app/ holds this hub's configuration, extensions, cache, and uploads, and
index.php at the root is the only entry point.
Two things to know before you edit anything in place:
- Files must stay readable by the web server user,
apacheon Enterprise Linux. A file you create over sFTP is owned by you. - Everything under
app/is a running hub's state and is not in the repository. Everything undercore/is, so an edit there is a change you will have to carry forward or contribute back.
Reading and writing files from code
Do not use PHP's fopen and unlink directly. The CMS has a file API, so
that the same calls work whether the hub writes to local disk or over FTP,
and so uploads are virus-scanned and paths are normalised on the way
through.
The entry point is the Filesystem facade, which resolves to
Hubzero\Filesystem\Filesystem:
use Filesystem;
if (Filesystem::exists($path))
{
$contents = Filesystem::read($path);
}
Filesystem::write($path, $contents);
Filesystem::makeDirectory($dir);
Filesystem::delete($path);
exists(), read(), write(), append(), prepend(), copy(),
move(), rename(), delete(), upload(), makeDirectory(),
copyDirectory(), deleteDirectory(), isDirectory(), isFile(),
isWritable(), size(), mimetype(), lastModified() and
listContents() are all on the class, along with four macros —
files(), directories(), directoryTree() and emptyDirectory() —
registered by the service provider at boot.
Filesystem is the full chapter: the adapters, the macro mechanism, the safe-path rules, and the archive types.
What it looks like when it goes wrong: Filesystem::read() on a path that
is not there throws
FileNotFoundException,
so an unguarded read of a missing upload takes the whole page down. A file
that exists but that the web server user cannot read is worse: PHP's
file_get_contents() warns and returns false, which read() casts to a
string, so you get an empty string and a blank patch of page with nothing in
the log but a warning. Test exists() first, and check what write()
returns — it is a boolean, and a failed write is not an exception.
Rewritten and checked against 2.4-main @ 348f0057c2 on 2026-09-10.