WebOrbiton

Code

FlatlyPage

A modern CMS for building landing pages.

Version history

Version 3.0.0.1 2026-09-26

Browse files
Files changed23
Lines added+23
Lines removed-61
.htaccess Modified +0 -1
⋮ 17 unchanged lines ⋮
  RewriteRule ^config\.php$ - [F,L]
  RewriteRule ^themes\.css$ - [F,L]
  
- # Extensions were removed: block leftovers from older versions
  RewriteRule ^extensions(/|$) - [F,L]
  RewriteRule ^(extensions-loader|admin/extensions|admin/popups)(\.php)?$ - [G,L]
  
⋮ 95 unchanged lines ⋮
admin/ai-helper-lib.php Modified +0 -1
⋮ 235 unchanged lines ⋮
                  if ($index >= $currentCount) {
                      $item = array_merge($itemSchema['base'], $item);
                  }
-                 // An unchanged item must stay a JSON object ({}), not [], or the editor would replace the whole list.
                  $items[] = $item === [] ? new stdClass() : $item;
              }
              if ($items !== []) {
⋮ 724 unchanged lines ⋮
admin/dashboard.php Modified +0 -1
⋮ 1397 unchanged lines ⋮
                                          el.classList.toggle('is-error', !ok);
                                      }
  
-                                     // Saves the consent settings together with the given script list; nothing else on the page is submitted.
                                      function persist(next, statusEl) {
                                          if (busy) return Promise.resolve(false);
                                          busy = true;
⋮ 999 unchanged lines ⋮
admin/login_tracking.php Modified +13 -1
⋮ 153 unchanged lines ⋮
  
      public function updateActivity()
      {
-         if (!isset($_SESSION['login_token'])) {
+         if (!isset($_SESSION['login_token']) || !is_string($_SESSION['login_token']) || preg_match('/^[a-f0-9]{64}$/', $_SESSION['login_token']) !== 1) {
              return false;
          }
  
⋮ 64 unchanged lines ⋮
  
      public function logoutSession($loginId)
      {
+         if (!is_string($loginId) || preg_match('/^login_[a-f0-9]+\.[0-9]+$/', $loginId) !== 1) {
+             return false;
+         }
+ 
          $xml = new DOMDocument('1.0', 'UTF-8');
          $xml->formatOutput = true;
          $xml->preserveWhiteSpace = false;
⋮ 25 unchanged lines ⋮
  
      public function banIP($ip)
      {
+         if (!is_string($ip) || filter_var($ip, FILTER_VALIDATE_IP) === false) {
+             return false;
+         }
+ 
          $bannedFile = DATA_DIR . '/private/banned_ips.json';
  
          $banned = [];
⋮ 56 unchanged lines ⋮
  
      private function logoutByIP($ip)
      {
+         if (!is_string($ip) || filter_var($ip, FILTER_VALIDATE_IP) === false) {
+             return false;
+         }
+ 
          $xml = new DOMDocument('1.0', 'UTF-8');
          $xml->formatOutput = true;
          $xml->preserveWhiteSpace = false;
⋮ 55 unchanged lines ⋮
admin/system.php Modified +0 -1
⋮ 74 unchanged lines ⋮
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>System - FlatlyPage CMS</title>
-     <meta name="generator" content="FlatlyPage CMS">
      <link rel="icon" href="admin.ico?v=<?= filemtime(__DIR__ . '/../css/admin.css') ?>" type="image/x-icon">
      <?= admin_font_head() ?>
      <link rel="stylesheet" href="/css/admin.css?v=<?= filemtime(__DIR__ . '/../css/admin.css') ?>">
⋮ 138 unchanged lines ⋮
admin/theme-edit/index.php Modified +1 -2
⋮ 5 unchanged lines ⋮
  
  <!-- Powered by Renderion Engine -->
  <!DOCTYPE html>
- <html lang="en" data-cms="flatlypage">
+ <html lang="en">
  
  <head>
      <meta charset="UTF-8">
⋮ 2 unchanged lines ⋮
      $domain = preg_replace('/[^a-z0-9\.\-]/i', '', $domain);
      $domain = ucfirst(strtolower($domain)); ?>
      <title>Create your own Theme</title>
-     <meta name="generator" content="FlatlyPage CMS">
      <meta name="author" content="FlatlyPage Team">
      <meta name="robots" content="noindex, nofollow">
  
⋮ 112 unchanged lines ⋮
admin/themes.php Modified +0 -1
⋮ 277 unchanged lines ⋮
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Themes - FlatlyPage CMS</title>
-     <meta name="generator" content="FlatlyPage CMS">
      <link rel="icon" href="admin.ico?v=<?= filemtime(__DIR__ . '/../css/admin.css') ?>" type="image/x-icon">
      <?= admin_font_head() ?>
      <link rel="stylesheet" href="/css/admin.css?v=<?= filemtime(__DIR__ . '/../css/admin.css') ?>">
⋮ 170 unchanged lines ⋮
admin/updater-lib.php Modified

Not shown (binary file or too large to diff).

admin/updater.php Modified +0 -1
⋮ 135 unchanged lines ⋮
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Updater - FlatlyPage CMS</title>
-     <meta name="generator" content="FlatlyPage CMS">
      <link rel="icon" href="admin.ico?v=<?= filemtime(__DIR__ . '/../css/admin.css') ?>" type="image/x-icon">
      <?= admin_font_head() ?>
      <link rel="stylesheet" href="/css/admin.css?v=<?= filemtime(__DIR__ . '/../css/admin.css') ?>">
⋮ 319 unchanged lines ⋮
api/analytics.php Modified +0 -1
⋮ 30 unchanged lines ⋮
      analytics_respond(413, ['ok' => false, 'error' => 'The scripts are too large.']);
  }
  
- // The settings arrive base64-encoded so hosting firewalls don't block a body containing <script>.
  $input = json_decode((string) file_get_contents('php://input', false, null, 0, $maxBody + 1), true);
  $decoded = is_array($input) && is_string($input['payload'] ?? null) ? base64_decode($input['payload'], true) : false;
  $data = $decoded !== false ? json_decode($decoded, true) : null;
⋮ 12 unchanged lines ⋮
assets/js/admin-editor.js Modified +0 -3
⋮ 538 unchanged lines ⋮
  
      const settingsForm = document.getElementById('settingsForm');
      if (settingsForm) {
-         // A field in a hidden tab can't show its validation message, so the form would silently not submit.
          settingsForm.addEventListener('invalid', (event) => {
              const panel = event.target.closest('.settings-panel');
              if (panel && !panel.classList.contains('active')) activateSettingsTab(panel.id.replace(/^panel-/, ''));
          }, true);
  
-         // Code fields are sent base64-encoded so hosting firewalls don't block posts containing <script>.
          settingsForm.addEventListener('submit', () => {
              settingsForm.querySelectorAll('.flatly-encoded').forEach(input => input.remove());
              settingsForm.querySelectorAll('textarea[data-encode]').forEach(area => {
⋮ 10 unchanged lines ⋮
              });
          });
  
-         // Coming back to the page (bfcache) must give the fields their names back.
          window.addEventListener('pageshow', () => {
              settingsForm.querySelectorAll('.flatly-encoded').forEach(input => input.remove());
              settingsForm.querySelectorAll('textarea[data-encode-name]').forEach(area => { area.name = area.dataset.encodeName; });
⋮ 2204 unchanged lines ⋮
assets/js/consent.js Modified +0 -2
⋮ 24 unchanged lines ⋮
              const script = document.createElement('script');
              Array.from(old.attributes).forEach(attr => script.setAttribute(attr.name, attr.value));
              script.text = old.textContent;
-             // External scripts without async run in order: the next one waits for this one to load.
              const waits = script.src && !old.hasAttribute('async') && !old.hasAttribute('defer');
              if (waits) {
                  script.async = false;
⋮ 46 unchanged lines ⋮
          if (value === 'accepted') {
              activate();
          } else if (previous === 'accepted' && activated) {
-             // Scripts that already ran cannot be unloaded, so reload without them.
              location.reload();
          }
      }
⋮ 65 unchanged lines ⋮
config.php Modified +0 -15
⋮ 464 unchanged lines ⋮
  
  const CUSTOM_CODE_MAX_LENGTH = 100000;
  
- /**
-  * Reads a code field that the admin sends base64-encoded as "<field>_b64" (so hosting firewalls
-  * don't block posts containing <script>); falls back to the plain field. Works for arrays too.
-  */
  function flatly_posted_code(string $field): mixed
  {
      $decode = static function (mixed $value): string {
⋮ 18 unchanged lines ⋮
      return mb_substr(trim($code), 0, CUSTOM_CODE_MAX_LENGTH);
  }
  
- /**
-  * Custom JavaScript from Settings > Custom, printed at the end of <body> on public pages.
-  * Plain code is wrapped in a <script> tag; a snippet that already has its own <script> tags
-  * (e.g. an analytics embed) is printed as-is.
-  */
  function flatly_custom_js(): string
  {
      $code = (string) (get_system_settings()['custom_js'] ?? '');
⋮ 15 unchanged lines ⋮
  ];
  const CUSTOM_HTML_MAX_SNIPPETS = 20;
  
- /** Builds the Custom HTML list from the parallel custom_html_location[] / custom_html_code[] form fields. */
  function flatly_clean_custom_html(mixed $locations, mixed $codes): array
  {
      $locations = is_array($locations) ? array_values($locations) : [];
⋮ 14 unchanged lines ⋮
      return $snippets;
  }
  
- /** Custom HTML from Settings > Custom (and analytics scripts) for one location on public pages, printed as-is. */
  function flatly_custom_html(string $location): string
  {
      $out = flatly_analytics_html($location);
⋮ 79 unchanged lines ⋮
      ];
  }
  
- /**
-  * Analytics scripts for one placement. With the consent manager on, scripts that require consent
-  * are printed inside an inert <template>; assets/js/consent.js runs them after the visitor accepts.
-  */
  function flatly_analytics_html(string $location): string
  {
      $analytics = flatly_analytics_settings();
⋮ 256 unchanged lines ⋮
contact.php Modified +2 -4
⋮ 1 unchanged line ⋮
  error_reporting(E_ALL);
  ini_set('display_errors', 0);
  
- header("X-Powered-By: FlatlyPage CMS");
+ header_remove('X-Powered-By');
  header("X-Content-Type-Options: nosniff");
  header("X-Frame-Options: SAMEORIGIN");
  header("X-XSS-Protection: 1; mode=block");
⋮ 67 unchanged lines ⋮
      }
  }
  ?>
- <!-- Powered by FlatlyPage CMS -->
  <!DOCTYPE html>
- <html lang="<?php echo htmlspecialchars($lang); ?>" data-cms="flatlypage">
+ <html lang="<?php echo htmlspecialchars($lang); ?>">
  
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title><?= e($page_title) ?> - <?= e($site_settings['site_name']) ?></title>
      <meta name="description" content="<?= e($page_description) ?>">
-     <meta name="generator" content="FlatlyPage CMS">
      <?= flatly_canonical_link() ?>
      <?= flatly_hreflang_links() ?>
      <?= flatly_language_detect_script() ?>
⋮ 336 unchanged lines ⋮
cron-update.php Modified +0 -14
  <?php
- /*
-  * FlatlyPage CMS - automatic updates, run by a cron job.
-  *
-  *   php /path/to/site/cron-update.php
-  *
-  * or, when the host can only call a URL:
-  *
-  *   https://example.com/cron-update?token=SECRET
-  *
-  * It does nothing unless both the updater and automatic updates are turned on in Admin > Updater,
-  * where the exact command, URL and token are shown.
-  */
- 
  $isCli = PHP_SAPI === 'cli';
  if ($isCli) {
-     // config.php expects a web request; without these it would guess the site path from the file system.
      $_SERVER['HTTP_HOST'] ??= 'localhost';
      $_SERVER['SERVER_PORT'] ??= 80;
      $_SERVER['SCRIPT_NAME'] = '/cron-update.php';
⋮ 32 unchanged lines ⋮
css/styles.css Modified

Not shown (binary file or too large to diff).

engine/index.php Modified +1 -2
  <!-- Powered by Renderion Engine -->
  <!DOCTYPE html>
- <html lang="en" data-cms="flatlypage">
+ <html lang="en">
  
  <head>
      <meta charset="UTF-8">
⋮ 3 unchanged lines ⋮
      $domain = ucfirst(strtolower($domain)); ?>
      <title><?= htmlspecialchars($domain, ENT_QUOTES, 'UTF-8') ?>: Renderion Engine</title> <!-- Dynamically added -->
      <link rel="icon" href="renderion.ico?v=<?= filemtime(__DIR__ . '/../engine/renderion.ico') ?>" type="image/x-icon">
-     <meta name="generator" content="FlatlyPage CMS">
      <meta name="author" content="FlatlyPage Team">
      <meta name="robots" content="noindex, nofollow">
  
⋮ 110 unchanged lines ⋮
fonts/Orbit.ttf Added +0 -0

            
index.php Modified +2 -4
⋮ 1 unchanged line ⋮
  error_reporting(E_ALL);
  ini_set('display_errors', 0);
  
- header("X-Powered-By: FlatlyPage CMS");
+ header_remove('X-Powered-By');
  header("X-Content-Type-Options: nosniff");
  header("X-Frame-Options: SAMEORIGIN");
  header("X-XSS-Protection: 1; mode=block");
⋮ 50 unchanged lines ⋮
      }
  }
  ?>
- <!-- Powered by FlatlyPage CMS -->
  <!DOCTYPE html>
- <html lang="<?php echo htmlspecialchars($lang); ?>" data-cms="flatlypage">
+ <html lang="<?php echo htmlspecialchars($lang); ?>">
  
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title><?= e($page_title) ?></title>
      <meta name="description" content="<?= e($page_description) ?>">
-     <meta name="generator" content="FlatlyPage CMS">
      <?= flatly_canonical_link() ?>
      <?= flatly_hreflang_links() ?>
      <?= flatly_language_detect_script() ?>
⋮ 314 unchanged lines ⋮
newsletter/manager.php Modified

Not shown (binary file or too large to diff).

newsletter/newsletter-unavailable.php Modified +1 -2
  <!-- Powered by Renderion Engine -->
  <!DOCTYPE html>
- <html lang="en" data-cms="flatlypage">
+ <html lang="en">
  
  <head>
      <meta charset="UTF-8">
⋮ 1 unchanged line ⋮
      <?php $domain = $_SERVER['HTTP_HOST'] ?? 'localhost'; $domain = preg_replace('/[^a-z0-9\.\-]/i', '', $domain); $domain = ucfirst(strtolower($domain)); ?>
      <title><?= htmlspecialchars($domain, ENT_QUOTES, 'UTF-8') ?></title> <!-- Dynamically added -->
      <link rel="icon" href="nl.ico?v=<?= filemtime(__DIR__ . '/../newsletter/nl.ico') ?>" type="image/x-icon">
-     <meta name="generator" content="FlatlyPage CMS"> 
      <meta name="author" content="FlatlyPage Team">
      <meta name="robots" content="noindex, nofollow">
  
⋮ 110 unchanged lines ⋮
page.php Modified +2 -4
⋮ 1 unchanged line ⋮
  error_reporting(E_ALL);
  ini_set('display_errors', 0);
  
- header("X-Powered-By: FlatlyPage CMS");
+ header_remove('X-Powered-By');
  header("X-Content-Type-Options: nosniff");
  header("X-Frame-Options: SAMEORIGIN");
  header("X-XSS-Protection: 1; mode=block");
⋮ 74 unchanged lines ⋮
      }
  }
  ?>
- <!-- Powered by FlatlyPage CMS -->
  <!DOCTYPE html>
- <html lang="<?php echo htmlspecialchars($lang); ?>" data-cms="flatlypage">
+ <html lang="<?php echo htmlspecialchars($lang); ?>">
  
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title><?= e($page_title) ?> - <?= e($site_settings['site_name']) ?></title>
      <meta name="description" content="<?= e($page_description) ?>">
-     <meta name="generator" content="FlatlyPage CMS">
      <?= flatly_canonical_link() ?>
      <?= flatly_hreflang_links() ?>
      <?= flatly_language_detect_script() ?>
⋮ 253 unchanged lines ⋮
version.txt Modified +1 -1
- 3.0.0.0
+ 3.0.0.1