Markdown Reader
Beamreactor Includes
BeamReactor – Global Includes #
> Version: 1.0
> Audience: BeamReactor core developers and integrators
> Scope: Include system architecture, authoring rules, installation discipline
> Version: 1.0
> Audience: BeamReactor core developers and integrators
> Scope: Include system architecture, authoring rules, installation discipline
Global includes are lightweight PHP files that run on every single request, regardless of which page or plugin is being loaded. They are not plugins. They have no URL, no UI, and no plugin lifecycle. They are pure execution hooks — tasks the engine must carry out unconditionally as it processes any incoming request.
Typical responsibilities:
rand())When a request enters the XDP engine (index.php), the engine starts by loading configuration (user/conf/cog.php), which defines all global variables including $cfg, $headdata, $footdata, and the $inc_allowed whitelist. The engine then iterates through $inc_allowed in declaration order:
// index.php
if(isset($inc_allowed))
{
foreach($inc_allowed as $objINC)
{
$incfile = 'inc/'.$objINC;
if(is_file($incfile)) include($incfile);
}
unset($objINC, $incfile);
}
This loop completes before any plugin, page, or HTML output is produced. At this point, no <html> has been echoed. Includes that append to $headdata, $footdata, or $cfg['body'] do so safely because those buffers are rendered later by HeaderHandler.
Order matters. Includes that depend on a function set by an earlier include (e.g. isBanned(), defined by ban.inc.php) must appear after it in $inc_allowed. The canonical boot order is:
$inc_allowed = [
'ban.inc.php', // 1. IP ban gate — must be first
'geos.inc.php', // 2. Geolocation (depends on IP being clean)
'hax.inc.php', // 3. Intrusion heuristics
'stats.inc.php', // 4. Request statistics
// ... subsequent includes may depend on all of the above
];
> � ️ This rule is mandatory and non-negotiable.
An include file that exists on disk but is not listed in $inc_allowed is never executed. Dropping a file into inc/ does not activate it. Only the whitelist in user/conf/cog.php grants execution rights.
The required installation sequence is therefore:
Step 1 — Authorize (edit user/conf/cog.php):
$inc_allowed = [
'ban.inc.php', 'geos.inc.php', /* ... existing entries ... */
'my_include.inc.php' // ← add the entry FIRST
];
Step 2 — Deploy (create inc/my_include.inc.php):
<?php
if(!function_exists('isBanned')) return;
// ... logic
?>
This order enforces a deliberate review step before any code runs. Authoring the file first and hoping the engine picks it up is not acceptable — it bypasses the authorization layer and makes the inclusion accidental rather than intentional.
If the file does not exist when the engine reaches its entry in $inc_allowed, it is silently skipped (is_file() check). This is a safety net, not the intended workflow.
Every include must open with a dependency guard. Because includes run before most of the engine is initialized, a direct call (e.g. via the filesystem) would have no defined functions. The guard ensures the include is running inside the engine:
if(!function_exists('isBanned')) die('forbidden');
Use die('forbidden') for this specific guard — not return. On a shared hosting environment, a direct HTTP or filesystem call to an inc/ file would silently pass through a return, potentially exposing partial logic or globals. die() makes out-of-context execution impossible.
return is correct for conditional early exits further down in the include, where the engine context is confirmed and you simply have nothing to do (e.g. wrong page type, user not authenticated, condition not met).
Includes that have side effects on the UI or database should skip error pages:
if(stripos($cfg['obj'] ?? '', '.err') !== false) return;
Return as early as possible. Condition-based early exit keeps execution fast for the majority of requests where the include has nothing to do:
// Example: only run for authenticated users
if(!secure(0)) return;
// Example: only run 1 in 40 requests (probabilistic housekeeping)
if(rand(0, 40) !== 0) return;
<?php
/**
* XDP [name] include
*
* [One-line description of what this include does.]
*
* @subpackage Includes
* @author [Author]
* @copyright [Year] [Author]
* @version 1.0.0
* @since [Year]
* @date [Date]
*/
// Security gate — die() is mandatory here, not return.
// Prevents any execution if the file is called directly (shared hosting, misconfiguration).
if(!function_exists('isBanned')) die('forbidden');
// Early exit conditions — return is correct from here on (engine context is confirmed).
// Skip error pages
if(stripos($cfg['obj'] ?? '', '.err') !== false) return;
// Early exit condition (example)
if(empty($cfg['dbtable'])) return;
// Logic
// ...
?>
Includes have access to the three global output buffers that HeaderHandler will render later in the request. All three are plain strings — append with .=.
| Buffer | Rendered location | Typical use |
|---|---|---|
| $headdata | Inside <head> | <style>, <script>, <link> |
| $cfg['body'] | Immediately after <body> | Visible HTML (banners, overlays) |
| $footdata | End of <body> | <script src="...">, deferred JS |
// Inject a stylesheet
$headdata .= '<link rel="stylesheet" href="path/to/style.css">';
// Inject a top-of-page banner
$cfg['body'] = ($cfg['body'] ?? '') . '<div id="my-banner">...</div>';
// Inject a deferred script
$footdata .= '<script src="javascript/my_module.js"></script>';
Note: $cfg['body'] may not be initialized at the point the include runs. Always use the null-coalescing concatenation pattern shown above.
At the time includes run, the following are guaranteed to be available:
| Variable | Description |
|---|---|
| $cfg | Full engine configuration array |
| $cfg['obj'] | Requested object identifier (e.g. home.php, 403.err) |
| $cfg[0] | Base URL |
| $cfg[1] | Site name |
| $cfg['dbtable'] | Member table name (empty if membership disabled) |
| $headdata | HTML head buffer (string) |
| $footdata | HTML foot buffer (string) |
| $cfg['skin'] | Active skin name |
| $_SESSION | PHP session |
| $_COOKIE | PHP cookies |
| ipCheck() | Returns the verified client IP |
| isBanned() | Checks whether an IP is banned |
| secure() | Checks user permission level by string constant name |
| File | Purpose | Runs when |
|---|---|---|
| ban.inc.php | Enforces IP ban list; redirects to 403 | Always (first) |
| geos.inc.php | Geolocation lookup and logging | Always |
| hax.inc.php | Intrusion heuristics and attack detection | Always |
| stats.inc.php | Records request to stats table (deferred INSERT) | Always |
| botsniffer.inc.php | Bot and crawler identification | Always |
| currentUsers.inc.php | Active user count tracking | Always |
| tidy.inc.php | Probabilistic cleanup of unactivated accounts | ~1/40 requests |
| defense_logs.inc.php | Security event logging | Always |
| rss_gc.inc.php | RSS cache garbage collection | Probabilistic |
| displayWarnings.inc.php | Toast system injection (authenticated users) | Authenticated |
| scattags.inc.php | Tag scatter/scatter-cache operations | Always |
| session_warning.inc.php | Session timeout warning JS injection | Authenticated |
| ip_notice.inc.php | Top-of-page IP storage notice banner | Until cookie set |
die('forbidden') for the security guard at the top (out-of-context protection)return for all conditional early exits below the guarddie() for anything other than the security guard$cfg['body'] is initialized — always use ?? or isset()echo, print) — use $headdata, $footdata, $cfg['body']$inc_allowedif(!function_exists(...)) return;.err check when appropriate$inc_allowed (dependencies first)Includes are not plugins. They are responsibilities the engine carries on every request. That is why they require explicit authorization.