Warning: Undefined array key "skin" in /home/nizo0755/beamreactor.com/lib/functions.lib.php on line 194
Beamreactor · Le dernier CMS français indépendant: reprenez le contrôle!
En vous promenant sur Beamreactor, nous stockons votre IP 48h pour des raisons de sécurité.
FAQ · TICKETS · CONTACT · CHANGELOG

Un problème ?
On est .

Consultez la FAQ, ouvrez un ticket de support, ou contactez-nous directement. Pas de chatbot, pas de file d'attente — un développeur qui répond.

Avant d'écrire, la réponse est peut-être ici

Features and architecture

Technical questions about the XDP engine, plugins, security, the frame system and BeamReactor development conventions.

What is frameheader() for?+
frameheader() opens a visual section (frame) on the page. It displays the plugin or section title and creates the HTML container in which content will be rendered. Usage: frameheader('My title', 'h3', false). Title levels follow the HTML hierarchy: h1 for the page title (once only), h2 for main sections, h3 and beyond for frames and widgets. A directly called plugin must start with: if($obj=='my_plugin.php') frameheader($dialplugindisplay); — this condition prevents double header rendering when the plugin is included from another script.
When should I use framefooter()?+
framefooter() closes the frame opened by frameheader(). It is required before opening a new section with frameheader(). Never call framefooter() without a following frameheader(), except at the end of a page. The standard pattern for structuring a page into multiple blocks: frameheader('Section 1'); /* content */ framefooter(); frameheader('Section 2'); /* content */. The engine handles the final closing automatically.
How do I structure a page with multiple sections?+
Use the framefooter() / frameheader() pair to chain sections. Each section creates a distinct visual block with its own title. Example: after displaying a form and receiving an error, close the current frame with framefooter(), open a clean new frame with frameheader(''), include the form again, then return. This keeps the user on a valid, properly framed page without any HTTP redirect.
How does secure() work?+
secure() checks whether the logged-in user's level is sufficient to access a resource. It takes a level constant as parameter (BASE_LEVEL_ADMIN, PLUGIN_LEVEL_MODERATOR, etc.) and returns true or false. The standard pattern: frameheader($dialplugindisplay); if(!secure(PLUGIN_LEVEL_MODERATOR)) { forbids(); return; }. The frame is opened BEFORE the check — forbids() displays inside the frame, otherwise the layout breaks. The trick secure(0) simply checks whether the user is logged in at all.
Which includes should I use in a plugin?+
None for config and libraries — the XDP engine loads them automatically. The only permitted include is for the locale: include(getlocale('plugin_name'));. Files named .conf.inc.php and .lib.inc.php are detected and loaded by the engine. Manual require or include for config or libs will cause a warning and a broken path. Similarly, never include a module (.mod.php) — they are called exclusively via ?obj=name.mod.
How do translations work in a plugin?+
Each plugin has its translation files in /locale/plugin_name.XX.inc.php (XX = ISO language code). Loading is done via include(getlocale('plugin_name'));, which must be called BEFORE frameheader() to avoid missing variable errors. Translations use a $dialpluginname[] array. $dialplugindisplay contains the displayed plugin title, $dialplugincall the name shown in the control centre. getAvailableLanguages() returns the list of available languages.
How do I load plugin-specific CSS or JavaScript?+
Use the global variable $headdata to inject into <head>: $headdata .= '<link rel="stylesheet" type="text/css" href="plugins/my_plugin/css/my_plugin.css">'; For JavaScript, same approach: $headdata .= '<script src="plugins/my_plugin/js/my_plugin.js"></script>'; To execute JS after the DOM, use $footdata with a heredoc. CSS must use variables defined in core.css — never invent colours. If a variable is missing, suggest adding it to core.css.
How do I validate user input?+
Use the Sanitizer: use Beamreactor\Sanitizer\Parser; then Parser::sanitize($input, 'type'). Available types include: bool, date, email, name, html, xml, uuid, url, string, ip, float, int, path and others. sanitize() cleans and validates the data, returning false if invalid. check() verifies the format without cleaning. Always sanitize BEFORE any SQL operation. Never invent a datatype — propose one if needed.
How do I interact with the database?+
Use the SQL class: use Beamreactor\Database\SQL;. Main methods: SQL::query() for multiple rows, SQL::queryFirst() for a single row, SQL::queryValue() for a single value, SQL::insertRow() to insert, SQL::updateRow() to update, SQL::deleteRow() to delete. Always use prepared statements with ? parameters. Direct variable concatenation in SQL is strictly forbidden. Check database availability with isset($cfg['dbtable']) and table existence with SQL::tableExists().
How do I create an AJAX endpoint?+
Modules (.mod.php) are BeamReactor's AJAX endpoints. They respond with JSON, XML, HTML or text. They go in /handlers/plugin_name.mod.php and are called via ?obj=plugin_name.mod (without .php). Never call the full file path. Minimal structure: frameheader check, security via secure(), Content-Type header, action processing via Parser::sanitize(), JSON response with ['success' => !!1] or ['success' => !!0]. On the JavaScript side, calls use $.post(BEAM_BASE_URL + '?obj=plugin_name.mod', {...}).
How does page routing work?+
Everything in BeamReactor goes through index.php. The ?obj= parameter determines what gets loaded. A plugin: ?obj=my_plugin.php. An AJAX module: ?obj=my_plugin.mod. A document: ?obj=my_page.dta. The XDP engine resolves the path, loads config, libs and locale automatically, then executes the script in a secured environment. No PHP script can be called directly — everything goes through the engine.
How do I display notifications to the user?+
BeamReactor has a toast system with 6 levels: debug (0), info (1), success (2), warning (3), error (4), critical (5). Quick usage: Toast::info('Title', 'Message', 5000); or Toast::add(Toast::LEVEL_WARNING, 'Title', 'Message', BASE_LEVEL_USER, 0). The minUserLevel parameter targets notifications by access level. Duration is in milliseconds, 0 for persistent.
What is the structure of a BeamReactor plugin?+
A plugin is a self-contained folder in /plugins/plugin_name/ containing: plugin_name.php (main interface), /conf/ (auto-loaded config), /lib/ (auto-loaded libraries), /locale/ (per-language translations), /handlers/ (AJAX endpoints .mod.php), /css/, /js/, /images/, /sql/ (table installation), /tests/, /doc/ (documentation .md and help .help.json), and /data/cache/ for persistent data. Installation means dropping the folder in. Removal means taking it out.
How do I display JavaScript dialogs in BeamReactor?+
BeamReactor replaces native alert/confirm/prompt with custom dialogs defined in javascript/dialogs.js.php. Four functions: alertWindow('Title', 'message') for alerts, confirmWindow('Title', 'question?', {}, callback) for confirmations, promptWindow('Title', 'Label:', {}, callback) for input, infoWindow('Title', 'info') for information. Never use native alert(), confirm() or prompt().
How do I pass PHP translations to JavaScript?+
In the plugin locale file, define a $js_translations array and call setJavascriptLocale($js_translations). Example: $js_translations = ['my_plugin' => ['error_msg' => $dialmyplugin[5]], 'global' => ['error' => $dial[32]]]; setJavascriptLocale($js_translations);. On the JavaScript side, access translations via PLUGIN_TRANSLATION.my_plugin.error_msg. Translations are injected into the head as a global JavaScript object.
Can I use exit or die in a plugin?+
No. Plugins must never use exit or die. The only permitted die in all plugin code is if(!function_exists('frameheader')) die('forbidden'); on the first line, which verifies the BeamReactor context. To stop execution, use return. To handle an error, display the message inside the frame then return. If a plugin uses exit or die, the engine cannot determine what failed and diagnostics become impossible.
How do security levels work?+
BeamReactor uses a fixed hierarchy: OVERMIND > ADMIN > MODERATOR > HIGHUSER > USER. BASE_LEVEL_* constants are defined in cog.inc.php. Each plugin can define its own levels via PLUGIN_NAME_LEVEL_* in its configuration. $basedisplevel always uses BASE_LEVEL_*, never PLUGIN_LEVEL_*. Custom define() calls come after $basedisplevel. The system automatically fills in missing levels via base_user_levels().
How does automatic class loading work?+
Files named .lib.inc.php and .conf.inc.php are loaded automatically by the engine. For additional classes, register a PSR-4 autoloader in the plugin configuration using spl_autoload_register(). The namespace follows the convention Beamreactor\PluginName\. Class files go in /lib/ and are resolved by the path relative to the namespace. This allows multiple plugins to coexist without name collisions.

Two factors authentication

It adds an essential extra layer of protection by requiring additional identity verification. This ensures that even if your password is stolen, a third party cannot access your data. It is the most effective defense against identity theft and account hacking.

How to set up two-factor authentication?+
To secure your account, two steps are required. Registered users must log in to the main BeamReactor interface. Click the "profile" button at the top left to access your settings. At the bottom, you will find a 2FA QR code to scan with an app like Google Authenticator or Microsoft Authenticator. Special recovery codes will be provided: make sure to copy them down to recover your account in case of phone loss or theft.
How do I log in with two-factor authentication?+
Log in with your username and password on the BeamReactor website. The system will then ask you for a code, which you will find in the Authenticator app on your phone.
What are the requirements?+
Update your phone's operating system and the Google or Microsoft Authenticator app to their latest versions. If you cannot log in but still have access to your registered email, try changing your password. If you lack email access, contact us via the support form.
What if I forgot my password?+
You can reset it at any time by clicking the "inaccessible account" link on the login page.
What if my phone is lost or broken?+
Use one of the recovery codes provided during your 2FA registration. On the authentication page, click on "recovery code", enter it, and then update your 2FA settings in your profile once logged in.
What if I have a new phone number?+
The procedure is the same as for a lost phone: use your recovery codes to log in, then synchronize your new device via your user profile.
Why is two-factor authentication implemented?+
Two-factor authentication (2FA) adds an essential layer of protection by requiring additional proof of identity. It ensures that even if your password is stolen, your data remains inaccessible to third parties. It is the most effective defense against identity theft and account hacking.

Besoin d'aide personnalisée ?

Ticketing — Pour les utilisateurs enregistrés. Créez un ticket, suivez son avancement, échangez avec le support technique. Votre historique est conservé.

Contact direct — Pour les demandes commerciales, les partenariats ou les questions avant achat. Pas besoin de compte.
Formulaire de contact →

Changelog récent

- May 3, 2026, 2:06 pm: Enième mise à jour de Payment/PaymentStripe. Mise à jour du MCP pour permettre l'intervention sur le code, avec une fenêtre modale pour chaque intervention. Persona "system". Lien entre ContextHelper et MCP pour récuperer les profils, les historiques et stocker les interventions MCP dans l'environnement LLM général.
- April 27, 2026, 10:14 pm: class session, changement de isAuthenticated() (utilisé pour le chargement de classes JS) pour favoriser l'usage de la méthode secure() originale.
- April 27, 2026, 10:13 pm: Mise à jour des loaders, retrait des fonctions inutiles autoDiscoverAll() et discoverPlugins(). Correction du 2FA, implémentation du générateur de code QR et de l'endpoint correspondant pour éviter la dépendance externe. Correction de la classe TwoFA pour prendre en compte ces modifications. Retrait de TOCTOU dans la classe CMDB (createOwner(), register(), subscribe()). Changement du nom de cookie de session, changé un rand() par un random_bytes(
- April 26, 2026, 1:35 pm: Rectification de race conditions (TOCTOU DB) dans les modules stripe et paypal. Mise en place d'un upsert dans la classe SQL.
- April 22, 2026, 11:25 pm: Fix du flow et des valeurs TTC sur l'ensemble du système marketing. Mise à jour des pages d'accès BeamReactor
- April 19, 2026, 10:36 pm: Correction des affichages TTC, correctifs (multiples) de la structure d'abonnement stripe, des classes et des plugins y afférents (*order*, payment, products_order_check, products_order_confirm)... Ajout du JSON VIES à la table 'orders'.
- April 19, 2026, 10:33 pm: Remplacement de l'array des strings VIES par un module (endpoint) VIES approprié avec check du numéro de TVA intra à chaque étape.
- April 14, 2026, 12:59 pm: Mise en place de la facturation numérique. Meilleure prise en compte des abonnements liés a l'achat de produits via Stripe (avant partiellement manuel, maintenant entièrement automatisé).
- April 1, 2026, 9:19 pm: added the new invoice system, and the matching documentations. Added the orders_admin plugin (replaces commands.php) updated the stripe payment system, the mailform translations and default address, the mailbox, the products editor (-but broke the i18n functionality :c) the language_switcher, the lostpass and register files (removed debug in register), the functions.lib.php had erroneous skin variables, products_order_success.css, products_select
- March 29, 2026, 3:30 am: Fixed various UI bugs, broken language selector in the join_form, missing frameheader in the activate.php, missing frameheaders in the oneliner, added some white space nowrap in users.php
- March 29, 2026, 3:29 am: Fixed remaining $skinn references, added SL shapes parser plugin, fixed the comments, added the video_player, fixed a hardcoded structure in the parser/sanitizer, improved the sanitizer datatypes, added the video filetypes
- March 22, 2026, 8:27 pm: Infusé les webhooks Paypal et Stripe
- March 7, 2026, 10:14 pm: Hier: vérification du système stub MCP qui remplace le connecteur web original par Claude Opus 4.6. Derniers bugs fixés (accès non contrôlés aux classes). Vérification de la configuration stripe avant exposition dans les classes de paiement. rédaction par Claude du .md ContextGuardian.
- March 7, 2026, 10:13 pm: "Updated shop systems to fix small bugs. I've also introduced the bontanical anonimizer for unregistered website users"
- March 3, 2026, 1:53 am: Fix i18n sur le products_families. Fix sur les toasts des Javas.
- March 3, 2026, 1:05 am: Sight design changes to the BeamReactor website home pages. New BeamReactor shop website.
- February 28, 2026, 1:21 am: Fixed SDP redirection (optional user level would break). Fixed 404, translations wouldn't be applied correctly. converted dates systems to DateTimeImmutable especially for sensible ones (2038 plagued unix timestamp, for example). Fixed the gallery and gallery handlers, making use of the dedicated thumbnail generating endpoint. changed the faq, guestbook, oneliner and forums to use the userid
- February 18, 2026, 10:34 pm: Reverted systems ruined by Claude Desktop
- February 18, 2026, 10:33 pm: Converted the remaining missing DE translations, updated the audit to ignore libs, moved and updated the widgets functionality, Claude used the search_index table to make a new version of the search bar
- February 17, 2026, 2:08 am: Ancres automatiques: tous les titres Markdown (.md) (#) génèrent désormais un id HTML basé sur le texte du titre. Format: les espaces sont remplacés par des tirets et les caractères spéciaux sont simplifiés (ex: ## Mon Titre devient id="mon-titre"). Utilisation : on peut lier directement une section via l'URL ?obj=mdreader&file=NOM_FICHIER#id-du-titre.
- January 17, 2026: Emoji picker created for chat interface (~40 emojis). CSS layout fixed (div#middle margin issue). Flexbox alignment for attach/emoji/send buttons.
- January 17, 2026: SSE event ordering fixed (finished:true was sent before compression events). KoboldCPP response extraction corrected (results[0]['text']). Complete UserPreferencesMapper implemented (temperature, top_p, repetition penalties). Model-specific stop sequences via FormatFactory.
- January 18, 2026: Editorial plugin i18n system: language selector with color-coded indicators (green=complete, pulsing yellow=missing), AJAX translation checks, dynamic switching without reload. DatatypeIa created for LLM prompts (no XSS filtering for AI content).
- January 18, 2026: Robots.txt plugin fully rewritten (CSS variables, removed die()). Botlist and botsniffer modernized with gradient risk bars and category badges. Fixed product_zid bug in products_i18n table. New datatypes: SIREN (Luhn algorithm) and IBAN (MOD-97 validation).
- January 19, 2026: Abstract payment gateway architecture: pluggable providers (virement, chèque, Stripe, PayPal), unified Payment facade with modular handlers, webhook handling, success/cancel pages, cart restoration, anti-duplicate protection.
- January 19, 2026: Scroll position preservation for language switching using sessionStorage save/restore on page reload.
- January 23, 2026: Complete session management system migrated from JASSPR framework: Sessions class facade, session_warning.inc.php, session_manipulator.mod.php, session_monitor.js. Progressive timeout warnings (toasts then modals), 2FA integration, clean logout. Transparent migration across multiple sites.
- January 23, 2026: RAG source management pagination fix: deleteSource and reprocessSource now pass currentPage and currentSearch to loadSources() instead of resetting to page 1.
- January 24, 2026: LLM connector debugging session: fixed undefined variables before assignment, session handling after Sessions::unlock(), namespace mismatches. LLMPrompt class with intent detection. Locale system integration (getlocale()/$cfg[22]) for FR/EN prompt engineering. Persona selector with llm_personas SQL table.
- January 25, 2026: Update of the bidirectional LLM firewall (Aegis): SQL tables for encoding rules and trash tags, AegisEncodingHandler class, LLMFirewall v2. Detection of UTF-8 overlong sequences, homoglyph attacks, control characters. Trash tags per model family (Llama, Mistral, Qwen). Multilingual jailbreak patterns. Full integration with existing Aegis Corpus components.

Historique complet →

Pas trouvé votre réponse ?

Ouvrez un ticket ou contactez-nous.

de en fr