DIR : /home/kozerus/public_html/konet/ko_center_sysadm.html

/home/kozerus/public_html/konet

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>ko_center System Administrator Documentation</title>
  <style type="text/css">
    body { font-family: Arial, sans-serif; margin: 20px; background-color: #fafafa; }
    h1 { color: #222; border-bottom: 3px solid #900; padding-bottom: 8px; }
    h2 { color: #900; margin-top: 35px; border-bottom: 1px solid #ddd; padding-bottom: 4px; }
    h3 { color: #333; margin-top: 25px; }
    h4 { color: #555; }
    code { background-color: #eee; padding: 1px 5px; border-radius: 3px; font-size: 13px; }
    pre { background-color: #2d2d2d; color: #f8f8f2; padding: 12px; border-radius: 4px; overflow-x: auto; font-size: 13px; }
    pre code { background: none; padding: 0; }
    table { border-collapse: collapse; margin: 12px 0; width: 100%; }
    th, td { border: 1px solid #ccc; padding: 5px 8px; text-align: left; font-size: 13px; }
    th { background-color: #900; color: white; }
    tr:nth-child(even) { background-color: #f2f2f2; }
    .note { background-color: #fff8e1; border-left: 4px solid #ffc107; padding: 8px 12px; margin: 12px 0; }
    .warning { background-color: #fce4e4; border-left: 4px solid #dc3545; padding: 8px 12px; margin: 12px 0; }
    .info { background-color: #e3f2fd; border-left: 4px solid #1976d2; padding: 8px 12px; margin: 12px 0; }
    .admin-box { background-color: #f5f5f5; border: 1px solid #ddd; padding: 12px; margin: 12px 0; border-radius: 4px; }
    a { color: #900; text-decoration: none; }
    a:hover { text-decoration: underline; }
    .toc { margin: 20px 0; padding: 15px 20px; background: white; border: 1px solid #ddd; border-radius: 4px; }
    .toc h2 { margin-top: 0; border: none; }
    .toc ul { list-style-type: none; padding-left: 5px; columns: 2; }
    .toc li { margin: 3px 0; font-size: 14px; }
    .toc ul ul { padding-left: 15px; columns: 1; }
    .toc ul ul li { font-size: 13px; }
    .file-path { font-family: monospace; background: #f0f0f0; padding: 1px 4px; border-radius: 2px; font-size: 12px; }
    .cmd-block { background: #2d2d2d; color: #f8f8f2; padding: 10px 14px; border-radius: 4px; margin: 8px 0; }
    .tag { display: inline-block; background: #900; color: white; padding: 1px 6px; border-radius: 3px; font-size: 11px; font-weight: bold; }
    .tag-green { background: #2e7d32; }
    .tag-blue { background: #1565c0; }
    .tag-orange { background: #e65100; }
  </style>
</head>
<body>

<h1>ko_center System Administrator Documentation</h1>

<table>
<tr><td><strong>Application:</strong></td><td>ko_center — Centralized LED Dashboard &amp; System Management</td></tr>
<tr><td><strong>Version:</strong></td><td>v0.70 (2026-08-01)</td></tr>
<tr><td><strong>Primary File:</strong></td><td><span class="file-path">/os/ai/io/ko_center.php</span> (16,322 lines, 205 functions)</td></tr>
<tr><td><strong>Database:</strong></td><td>SQLite 3 — <span class="file-path">/os/ai/io/ko_center.db3</span> (~39.6 MB, 30+ tables)</td></tr>
<tr><td><strong>Web Server:</strong></td><td>Apache + mod_php (primary) / Python Flask (equivalent: <span class="file-path">ko_center.py</span>)</td></tr>
<tr><td><strong>Language:</strong></td><td>PHP 5.3+ (procedural, single-file architecture)</td></tr>
<tr><td><strong>Last Modified:</strong></td><td>2026-08-01 06:47 (server time)</td></tr>
</table>

<div class="toc">
<h2>Table of Contents</h2>
<ul>
  <li><a href="#1">1. System Architecture &amp; Design</a></li>
  <li><a href="#2">2. Installation &amp; Initial Setup</a></li>
  <li><a href="#3">3. Configuration Reference</a></li>
  <li><a href="#4">4. Database Administration</a></li>
  <li><a href="#5">5. User &amp; Role Management</a></li>
  <li><a href="#6">6. Security Assessment</a></li>
  <li><a href="#7">7. Logging, Debugging &amp; Monitoring</a></li>
  <li><a href="#8">8. Backup &amp; Recovery Procedures</a></li>
  <li><a href="#9">9. Routine Maintenance</a></li>
  <li><a href="#10">10. Troubleshooting Guide</a></li>
  <li><a href="#11">11. File Structure &amp; Asset Inventory</a></li>
  <li><a href="#12">12. PHP Function Reference (205 Functions)</a></li>
  <li><a href="#13">13. Deployment &amp; Server Configuration</a></li>
  <li><a href="#14">14. Python Flask Equivalent</a></li>
  <li><a href="#15">15. API &amp; URL Routing Reference</a></li>
  <li><a href="#16">16. Version History</a></li>
</ul>
</div>

<!-- ================================================================== -->
<h2 id="1">1. System Architecture &amp; Design</h2>
<!-- ================================================================== -->

<h3>1.1 Architectural Overview</h3>
<p>ko_center is a <strong>single-file PHP web application</strong> — all 205 functions and the entire routing logic reside in one file. It follows a traditional LAMP stack pattern with no external framework dependencies.</p>

<div class="admin-box">
<strong>Key Design Characteristics:</strong>
<ul>
  <li><strong>Single-file architecture:</strong> No MVC separation, no separate controller/model/view files</li>
  <li><strong>Procedural programming:</strong> All functions are global; no classes or objects</li>
  <li><strong>Global state management:</strong> <code>$GLOBALS</code> for database paths, table names, log files, user info</li>
  <li><strong>Session-based authentication:</strong> <code>$_SESSION['user']</code>, <code>$_SESSION['role']</code></li>
  <li><strong>URL-based routing:</strong> <code>?q=page/action/id</code> parsed into <code>$options[]</code> array by splitting on <code>/</code></li>
  <li><strong>Inline HTML generation:</strong> Functions return HTML strings concatenated and printed</li>
  <li><strong>SQLite backend:</strong> Single-file database, no separate database server required</li>
</ul>
</div>

<h3>1.2 Request Lifecycle</h3>
<pre>
HTTP Request → Apache/PHP → startup() → Parse ?q= → Route to handler → Generate HTML → Response

startup() does:
  1. session_start()
  2. Set error_reporting(0)
  3. Initialize $progid, $dttm, $dttm_ip
  4. Set $GLOBALS paths (dbfile, kbfile, hosts_allow, logfil, etc.)
  5. Detect host OS (win/linux)
  6. Parse $_REQUEST['q'] into $options[] array
  7. Check if database exists (auto-install if not)
  8. Route to appropriate handler based on $options[0]
</pre>

<h3>1.3 Core Global Variables</h3>
<table>
<tr><th>Variable</th><th>Type</th><th>Description</th></tr>
<tr><td><code>$progid</code></td><td>string</td><td>Program identifier: <code>"ko_center"</code></td></tr>
<tr><td><code>$dttm</code></td><td>string</td><td>Current datetime: <code>YYYYMMDD_HHMMSS</code></td></tr>
<tr><td><code>$dttm_ip</code></td><td>string</code></td><td>IP-formatted datetime: <code>YY.MM.DD.HH</code></td></tr>
<tr><td><code>$hostos</code></td><td>string</td><td>Operating system: <code>"win"</code> or <code>""</code> (linux)</td></tr>
<tr><td><code>$allowflag</code></td><td>string</td><td>Contents of <code>hosts.allow</code> file</td></tr>
<tr><td><code>$kb_user</code></td><td>string</td><td>KB user extracted from hosts.allow field 2</td></tr>
<tr><td><code>$user</code></td><td>string</td><td>Current user from hosts.allow field 2</td></tr>
<tr><td><code>$pass</code></td><td>string</td><td>Password from hosts.allow field 3</td></tr>
<tr><td><code>$step</code></td><td>string</td><td>Login step indicator</td></tr>
<tr><td><code>$leds_context</code></td><td>string</td><td>LED context: <code>"racks randomus default"</code></td></tr>
<tr><td><code>$led_context</code></td><td>string</td><td>LED context details</td></tr>
</table>

<h3>1.4 $GLOBALS Registry</h3>
<table>
<tr><th>Key</th><th>Value</th><th>Purpose</th></tr>
<tr><td><code>hosts_allow</code></td><td><code>$document_root/../safer/hosts.allow</code></td><td>Authentication file path</td></tr>
<tr><td><code>kbfile</code></td><td><code>$document_root/ko_center/db3/koaac_kb.db3</code></td><td>Knowledge Base database</td></tr>
<tr><td><code>kb_rootpath</code></td><td><code>$document_root/ko_center/kb</code></td><td>KB file storage root</td></tr>
<tr><td><code>kbpath</code></td><td><code>$document_root/ko_center/kb</code></td><td>KB path (alias)</td></tr>
<tr><td><code>ko_center_certsfile</code></td><td><code>$document_root/ko_center/db3/ko_center_certs.db3</code></td><td>Certificates database</td></tr>
<tr><td><code>logfil</code></td><td><code>$logfil_rootpath/ko_center_YYYYMM.log</code></td><td>Monthly log file</td></tr>
<tr><td><code>progid</code></td><td><code>"ko_center"</code></td><td>Program name</td></tr>
<tr><td><code>screenshots_pcharts</code></td><td><code>""</code></td><td>pChart screenshot path (empty = disabled)</td></tr>
<tr><td><code>dbs</code></td><td>Associative array</td><td>Multi-database registry keyed by role</td></tr>
<tr><td><code>roles</code></td><td>Array</td><td><code>['admin', 'local', 'users', 'anon']</code></td></tr>
<tr><td><code>themes</code></td><td>Array</td><td>jQuery UI theme names</td></tr>
<tr><td><code>tblname</code></td><td>string</td><td>Default table: <code>"leds"</code></td></tr>
<tr><td><code>js_output</code></td><td>boolean</td><td>JavaScript output flag (default false)</td></tr>
</table>

<!-- ================================================================== -->
<h2 id="2">2. Installation &amp; Initial Setup</h2>
<!-- ================================================================== -->

<h3>2.1 Prerequisites</h3>
<table>
<tr><th>Component</th><th>Minimum Version</th><th>Notes</th></tr>
<tr><td>Web Server</td><td>Apache 2.4+ or Python 3.6+</td><td>Apache with mod_php for PHP version; Flask for Python</td></tr>
<tr><td>PHP</td><td>5.3+</td><td>Requires PDO SQLite extension</td></tr>
<tr><td>SQLite</td><td>3.x</td><td>Bundled with PHP PDO</td></tr>
<tr><td>ImageMagick</td><td>Any version</td><td>Required only for LED GIF generation (cr_leds.py)</td></tr>
<tr><td>Perl</td><td>Any version</td><td>Required for iperms utility functions</td></tr>
<tr><td>Disk Space</td><td>~50 MB</td><td>Database (39.6 MB) + images + logs</td></tr>
<tr><td>PHP Memory</td><td>256 MB</td><td><code>memory_limit</code> in php.ini</td></tr>
</table>

<h3>2.2 Installation Steps</h3>

<div class="admin-box">
<h4>Step 1: Deploy Application Files</h4>
<pre>
mkdir -p /var/www/html/ko_center
mkdir -p /var/www/html/ko_center/db3
mkdir -p /var/www/html/ko_center/kb
mkdir -p /var/www/html/ko_center/images/btn
mkdir -p /var/www/html/ko_center/images/ani
mkdir -p /var/www/html/ko_center/images/fpb
cp ko_center.php /var/www/html/ko_center/
cp ko_center.db3 /var/www/html/ko_center/db3/
</pre>
</div>

<div class="admin-box">
<h4>Step 2: Configure hosts.allow</h4>
<p>Create or edit <span class="file-path">/var/www/html/../safer/hosts.allow</span>:</p>
<pre>
allow all
# Format: allow &lt;user&gt; &lt;role&gt; &lt;username&gt;
# Example: allow admin user joachim
</pre>
</div>

<div class="admin-box">
<h4>Step 3: Set File Permissions</h4>
<pre>
chown -R www-data:www-data /var/www/html/ko_center/
chmod 666 /var/www/html/ko_center/db3/ko_center.db3
chmod 755 /var/www/html/ko_center/
chmod 666 /var/www/html/ko_center/ko_trigger.dat  # if using trigger feature
</pre>
</div>

<div class="admin-box">
<h4>Step 4: First-Time Initialization</h4>
<p>Access the application in a browser:</p>
<pre>http://&lt;server&gt;/ko_center/ko_center.php</pre>
<p>If the database file doesn't exist, <code>leds_install("new")</code> is called automatically (line 421), which creates all core tables and inserts default data.</p>
</div>

<div class="admin-box">
<h4>Step 5: Verify Installation</h4>
<ul>
  <li><code>?q=about</code> — About page</li>
  <li><code>?q=pdo</code> — Lists all database tables</li>
  <li><code>?q=leds</code> — LED display (requires login)</li>
</ul>
</div>

<h3>2.3 leds_install() Function Details</h3>
<p>The <code>leds_install()</code> function (line 9707) supports two modes:</p>
<table>
<tr><th>Mode</th><th>Behavior</th></tr>
<tr><td><code>"new"</code></td><td>Creates database if it doesn't exist. If file already exists, returns error.</td></tr>
<tr><td><code>"old"</code></td><td>Renames existing database to <code>ko_center_YYYYMMDD_HHMMSS.db3</code> before creating a fresh one.</td></tr>
</table>

<p>Tables created during install:</p>
<table>
<tr><th>Function Call</th><th>Table Created</th><th>Default Data Inserted</th></tr>
<tr><td><code>pdo_cr_leds()</code> + <code>pdo_insert_leds()</code></td><td>leds</td><td>Yes</td></tr>
<tr><td><code>pdo_cr_nodes()</code> + <code>pdo_insert_nodes()</code></td><td>nodes</td><td>Yes</td></tr>
<tr><td><code>pdo_cr_roles()</code> + <code>pdo_insert_roles()</code></td><td>roles</td><td>Yes</td></tr>
<tr><td><code>pdo_cr_users()</code> + <code>pdo_insert_users()</code></td><td>users</td><td>Yes</td></tr>
<tr><td><code>pdo_cr_fp()</code> + <code>pdo_insert_fp()</code></td><td>fp</td><td>Yes</td></tr>
<tr><td><code>pdo_cr_grid()</code> + <code>pdo_insert_grid()</code></td><td>grid</td><td>Yes</td></tr>
<tr><td><code>pdo_cr_us()</code> + <code>pdo_insert_us()</code></td><td>us</td><td>Yes</td></tr>
<tr><td><code>pdo_cr_hw()</code> + <code>pdo_insert_hw()</code></td><td>hw</td><td>Yes</td></tr>
<tr><td><code>pdo_cr_n11()</code> + <code>pdo_insert_n11()</code></td><td>n11</td><td>Yes</td></tr>
<tr><td><code>pdo_cr_dbs()</code> + <code>pdo_insert_dbs()</code></td><td>dbs</td><td>Yes</td></tr>
<tr><td><code>pdo_cr_fgmenu()</code> + <code>pdo_insert_fgmenu()</code></td><td>fgmenu</td><td>Yes</td></tr>
<tr><td><code>pdo_cr_obj()</code> + <code>pdo_insert_obj()</code></td><td>obj</td><td>Yes</td></tr>
<tr><td><code>pdo_cr_pano()</code> + <code>pdo_insert_pano()</code></td><td>pano</td><td>Yes</td></tr>
<tr><td><code>pdo_cr_kb()</code></td><td>koaac_kb</td><td>No (created empty)</td></tr>
</table>

<!-- ================================================================== -->
<h2 id="3">3. Configuration Reference</h2>
<!-- ================================================================== -->

<h3>3.1 Path Configuration (startup() lines 130-151)</h3>
<table>
<tr><th>Setting</th><th>Default Path</th><th>Description</th></tr>
<tr><td><code>$path_btn</code></td><td><code>/ko_center/images/btn</code></td><td>Button image directory</td></tr>
<tr><td><code>$path_ani</code></td><td><code>/ko_center/images/ani</code></td><td>Animated LED GIF directory</td></tr>
<tr><td><code>$path_fpb</code></td><td><code>/ko_center/images/fpb</code></td><td>Floor plan button images</td></tr>
<tr><td><code>$logfil_rootpath</code></td><td><code>$document_root/../ko_safer</code></td><td>Log file directory</td></tr>
<tr><td><code>$logfil_basename</code></td><td><code>ko_center_YYYYMM.log</code></td><td>Monthly log file name</td></tr>
<tr><td><code>$hosts_allow</code></td><td><code>$document_root/../safer/hosts.allow</code></td><td>Authentication file</td></tr>
<tr><td><code>$kb_rootpath</code></td><td><code>$document_root/ko_center/kb</code></td><td>KB file storage</td></tr>
</table>

<h3>3.2 Theme Configuration</h3>
<p>Available jQuery UI themes (set via <code>$_SESSION['theme']</code>):</p>
<table>
<tr><th>Theme</th><th>CSS File</th><th>Image Path</th></tr>
<tr><td>redmond</td><td>js/themes/redmond/jquery-ui-1.7.2.custom.css</td><td>js/themes/redmond/images/</td></tr>
<tr><td>humanity</td><td>js/themes/humanity/jquery-ui-1.7.2.custom.css</td><td>js/themes/humanity/images/</td></tr>
<tr><td>frog</td><td>js/themes/le-frog/jquery-ui-1.7.2.custom.css</td><td>js/themes/le-frog/images/</td></tr>
<tr><td>swanky</td><td>js/themes/swanky-purse/jquery-ui-1.7.2.custom.css</td><td>js/themes/swanky-purse/images/</td></tr>
<tr><td>darkness</td><td>js/themes/ui-darkness/jquery-ui-1.7.2.custom.css</td><td>js/themes/ui-darkness/images/</td></tr>
<tr><td>lightness</td><td>js/themes/ui-lightness/jquery-ui-1.7.2.custom.css</td><td>js/themes/ui-lightness/images/</td></tr>
<tr><td>sunny</td><td>js/themes/sunny/jquery-ui-1.7.2.custom.css</td><td>js/themes/sunny/images/</td></tr>
<tr><td>mint</td><td>js/themes/mint-choc/jquery-ui-1.7.2.custom.css</td><td>js/themes/mint-choc/images/</td></tr>
</table>

<h3>3.3 Session Variables</h3>
<table>
<tr><th>Variable</th><th>Set By</th><th>Values</th><th>Purpose</th></tr>
<tr><td><code>$_SESSION['user']</code></td><td>leds_login_validate()</td><td>Username string</td><td>Authenticated user identity</td></tr>
<tr><td><code>$_SESSION['role']</code></td><td>leds_login_validate()</td><td>admin, local, users, anon</td><td>Access control level</td></tr>
<tr><td><code>$_SESSION['preview']</code></td><td>User toggle</td><td>"on" / "" (empty)</td><td>Enable/disable image preview on LED clicks</td></tr>
<tr><td><code>$_SESSION['theme']</code></td><td>User selection</td><td>Theme name</td><td>UI color theme</td></tr>
<tr><td><code>$_SESSION['grid_zoom']</code></td><td>User toggle</td><td>true / "" / false</td><td>Grid zoom state</td></tr>
<tr><td><code>$_SESSION['hs_type']</code></td><td>User selection</td><td>all, grid, us, hw, n11, none</td><td>Hotspot type filter for zoom viewer</td></tr>
<tr><td><code>$_SESSION['org_type']</code></td><td>User selection</td><td>a, e, h, o, p, t</td><td>Organization type filter</td></tr>
<tr><td><code>$_SESSION['gridimgpath']</code></td><td>js_scripts()</td><td>Theme image path</td><td>jQuery UI theme images</td></tr>
</table>

<!-- ================================================================== -->
<h2 id="4">4. Database Administration</h2>
<!-- ================================================================== -->

<h3>4.1 Database File</h3>
<table>
<tr><th>Property</th><th>Value</th></tr>
<tr><td>Path</td><td><span class="file-path">/os/ai/io/ko_center.db3</span></td></tr>
<tr><td>Type</td><td>SQLite 3</td></tr>
<tr><td>Size</td><td>~39.6 MB</td></tr>
<tr><td>Tables</td><td>30+</td></tr>
<tr><td>Access Method</td><td>PHP PDO via <code>newpdo()</code> function</td></tr>
<tr><td>Connection String</td><td><code>sqlite:/os/ai/io/ko_center.db3</code></td></tr>
</table>

<h3>4.2 Database Connection Function</h3>
<pre>
function newpdo( $dbfile ) {
    $pdo = new PDO("sqlite:$dbfile");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
    return $pdo;
}
</pre>

<h3>4.3 Complete Table Inventory</h3>
<table>
<tr><th>Table</th><th>Rows</th><th>Description</th></tr>
<tr><td><code>leds</code></td><td>262</td><td>LED indicator records (primary display table)</td></tr>
<tr><td><code>randomus</code></td><td>101</td><td>Random user/person data</td></tr>
<tr><td><code>leds_randomus</code></td><td>101</td><td>Combined LED schema + randomus data</td></tr>
<tr><td><code>ko_plans</code></td><td>—</td><td>Project plans with steps and items</td></tr>
<tr><td><code>ko_hw</code></td><td>—</td><td>Hardware inventory details</td></tr>
<tr><td><code>koaac_kb</code></td><td>—</td><td>Knowledge Base articles</td></tr>
<tr><td><code>nodes</code></td><td>—</td><td>Network nodes and devices</td></tr>
<tr><td><code>roles</code></td><td>—</td><td>User role definitions</td></tr>
<tr><td><code>users</code></td><td>—</td><td>User account records</td></tr>
<tr><td><code>cabs</code></td><td>—</td><td>Cabinet/rack data</td></tr>
<tr><td><code>kocab</code></td><td>—</td><td>Cabinet details</td></tr>
<tr><td><code>kohw</code></td><td>—</td><td>Hardware records</td></tr>
<tr><td><code>koplans</code></td><td>—</td><td>Plan records</td></tr>
<tr><td><code>cfg</code></td><td>—</td><td>Configuration key-value pairs</td></tr>
<tr><td><code>dbs</code></td><td>—</td><td>Database registry (multi-DB support)</td></tr>
<tr><td><code>menus</code></td><td>—</td><td>Navigation menu definitions</td></tr>
<tr><td><code>fp</code></td><td>—</td><td>Floor plan references</td></tr>
<tr><td><code>grid</code></td><td>—</td><td>Grid view configuration</td></tr>
<tr><td><code>us</code></td><td>—</td><td>User-specific data/preferences</td></tr>
<tr><td><code>n11</code></td><td>—</td><td>N11 monitoring alert data</td></tr>
<tr><td><code>pano</code></td><td>—</td><td>Panorama/tour data</td></tr>
<tr><td><code>obj</code></td><td>—</td><td>Object references</td></tr>
<tr><td><code>zoom</code></td><td>—</td><td>Zoom viewer configuration</td></tr>
<tr><td><code>zoomxml</code></td><td>—</td><td>Zoom XML hotspot data</td></tr>
<tr><td><code>shelves</code></td><td>—</td><td>Shelf/rack shelf data</td></tr>
<tr><td><code>hallo</code></td><td>—</td><td>Hallo records</td></tr>
<tr><td><code>halo</code></td><td>—</td><td>Halo records</td></tr>
<tr><td><code>nimbus</code></td><td>—</td><td>Nimbus records</td></tr>
<tr><td><code>aureole</code></td><td>—</td><td>Aureole records</td></tr>
<tr><td><code>leds_defaults</code></td><td>—</td><td>Default LED settings</td></tr>
<tr><td><code>leds_racks</code></td><td>—</td><td>LED-to-rack mappings</td></tr>
<tr><td><code>periods</code></td><td>—</td><td>Reporting time periods</td></tr>
<tr><td><code>rpts</code></td><td>—</td><td>Report definitions and SQL</td></tr>
<tr><td><code>hrc_datacenters_equipment</code></td><td>—</td><td>Datacenter equipment inventory</td></tr>
<tr><td><code>hrc_dc_*</code></td><td>—</td><td>Various datacenter tables (1307comm, unix, win, btu, etc.)</td></tr>
<tr><td><code>defrag_plan</code></td><td>—</td><td>Defragmentation plans</td></tr>
<tr><td><code>defrag_plansum</code></td><td>—</td><td>Defrag plan summaries</td></tr>
<tr><td><code>moveplan_details</code></td><td>—</td><td>Move plan details</td></tr>
<tr><td><code>es_ip</code></td><td>—</td><td>IP address tracking</td></tr>
<tr><td><code>es_hw</code></td><td>—</td><td>Extended hardware info</td></tr>
<tr><td><code>kohw_*</code></td><td>—</td><td>Hardware table variants (win, hrc, unix, etc.)</td></tr>
<tr><td><code>kohw_hrc_defrag</code></td><td>—</td><td>HRC defrag hardware</td></tr>
<tr><td><code>kohw_cabs_defrag</code></td><td>—</td><td>Cabinet defrag hardware</td></tr>
</table>

<h3>4.4 Database Maintenance Commands</h3>
<pre>
# Integrity check
sqlite3 /os/ai/io/ko_center.db3 "PRAGMA integrity_check;"

# List all tables
sqlite3 /os/ai/io/ko_center.db3 ".tables"

# Row counts for all tables
sqlite3 /os/ai/io/ko_center.db3 "SELECT name, (SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=m.name) FROM sqlite_master m WHERE type='table';"

# Vacuum (reclaim space, rebuild database)
sqlite3 /os/ai/io/ko_center.db3 "VACUUM;"

# Analyze (update query planner statistics)
sqlite3 /os/ai/io/ko_center.db3 "ANALYZE;"

# Backup
cp /os/ai/io/ko_center.db3 /os/ai/io/ko_center.db3.backup.$(date +%Y%m%d_%H%M%S)

# Export table to CSV
sqlite3 -header -csv /os/ai/io/ko_center.db3 "SELECT * FROM leds LIMIT 100;" > leds_export.csv

# Check database size
ls -lh /os/ai/io/ko_center.db3

# Check freelist (fragmentation indicator)
sqlite3 /os/ai/io/ko_center.db3 "PRAGMA freelist_count;"
</pre>

<!-- ================================================================== -->
<h2 id="5">5. User &amp; Role Management</h2>
<!-- ================================================================== -->

<h3>5.1 Authentication Flow</h3>
<ol>
  <li>User accesses application → <code>leds_login_form()</code> (line 8450) displays login form</li>
  <li>User submits credentials → <code>leds_login_validate()</code> (line 8568) processes</li>
  <li>Credentials validated against <code>hosts.allow</code> file contents</li>
  <li>On success: <code>$_SESSION['user']</code> and <code>$_SESSION['role']</code> are set</li>
  <li>On failure: Login form redisplayed with error</li>
  <li>Logout: <code>leds_logout()</code> (line 8739) clears session and redirects</li>
</ol>

<h3>5.2 Role Definitions</h3>
<table>
<tr><th>Role</th><th>Description</th><th>Access Level</th></tr>
<tr><td><code>anon</code></td><td>Unauthenticated / anonymous</td><td>Read-only, minimal features</td></tr>
<tr><td><code>users</code></td><td>Standard authenticated user</td><td>View LED status, basic navigation, grid views</td></tr>
<tr><td><code>local</code></td><td>Local/system user</td><td>Extended access including config</td></tr>
<tr><td><code>op</code></td><td>Operator</td><td>Operational features, LED management</td></tr>
<tr><td><code>mgrs</code></td><td>Manager</td><td>Management features, reports, KB</td></tr>
<tr><td><code>admin</code></td><td>Administrator</td><td>Full access, all features, database management</td></tr>
</table>

<h3>5.3 Role-Based Database Access</h3>
<p>The <code>dbs_init()</code> function (line 15441) defines multi-database access by role:</p>
<pre>
$dbfiles['admin']['ko_center']['dbfile'] = "$document_root/ko_center/ko_center.db3";
$dbfiles['admin']['ko_center']['tables'] = array('fp', 'leds', 'rpts', 'roles', 'users', ...);
</pre>
<p>Each role has access to specific databases and tables, enabling data isolation between user groups.</p>

<!-- ================================================================== -->
<h2 id="6">6. Security Assessment</h2>
<!-- ================================================================== -->

<div class="warning">
<strong>Critical Security Notice:</strong> ko_center.php is a legacy application with several known security vulnerabilities. Review and remediate before deploying in any production or exposed environment.
</div>

<h3>6.1 Vulnerability Summary</h3>
<table>
<tr><th>#</th><th>Vulnerability</th><th>Severity</th><th>Location</th><th>Description</th></tr>
<tr>
  <td>V1</td>
  <td><strong>SQL Injection</strong></td>
  <td><span class="tag">Critical</span></td>
  <td>leds_show() L6939, pdo_grid() L10686, multiple grid functions</td>
  <td>User input interpolated directly into SQL queries via string concatenation. Example: <code>$sql = "select * from $tblname where led_dttm == 'current' and led_type == '$led_type'"</code></td>
</tr>
<tr>
  <td>V2</td>
  <td><strong>Shell Command Injection</strong></td>
  <td><span class="tag">Critical</span></td>
  <td>leds_process() L6485, iperms() L6425, localcmds() L15887</td>
  <td>User-controlled values passed to <code>system()</code>, <code>exec()</code>, <code>passthru()</code>, and <code>proc_open()</code> without sanitization</td>
</tr>
<tr>
  <td>V3</td>
  <td><strong>Cross-Site Scripting (XSS)</strong></td>
  <td><span class="tag">High</span></td>
  <td>All functions that output user data</td>
  <td>No <code>htmlspecialchars()</code> or output encoding applied to user-supplied data displayed in HTML</td>
</tr>
<tr>
  <td>V4</td>
  <td><strong>Plain Text Passwords</strong></td>
  <td><span class="tag">High</span></td>
  <td>randomus table (login_pass column)</td>
  <td>Passwords stored in plain text, no hashing or salting</td>
</tr>
<tr>
  <td>V5</td>
  <td><strong>No CSRF Protection</strong></td>
  <td><span class="tag">Medium</span></td>
  <td>All form submissions</td>
  <td>No anti-CSRF tokens on any forms</td>
</tr>
<tr>
  <td>V6</td>
  <td><strong>No Rate Limiting</strong></td>
  <td><span class="tag">Medium</span></td>
  <td>Login form, all endpoints</td>
  <td>No brute-force protection or request throttling</td>
</tr>
<tr>
  <td>V7</td>
  <td><strong>Directory Traversal</strong></td>
  <td><span class="tag">High</span></td>
  <td>File operations in KB, upload, scrub</td>
  <td>File paths constructed from user input without path sanitization</td>
</tr>
<tr>
  <td>V8</td>
  <td><strong>Error Information Leakage</strong></td>
  <td><span class="tag">Low</span></td>
  <td>startup() L107</td>
  <td><code>error_reporting(0)</code> suppresses errors but may hide issues; however, custom error messages may leak path info</td>
</tr>
<tr>
  <td>V9</td>
  <td><strong>Weak Session Management</strong></td>
  <td><span class="tag">Medium</span></td>
  <td>startup() L105</td>
  <td>No session regeneration after login, no session timeout, no secure cookie flags</td>
</tr>
<tr>
  <td>V10</td>
  <td><strong>No HTTPS Enforcement</strong></td>
  <td><span class="tag">Medium</span></td>
  <td>All endpoints</td>
  <td>No HSTS, no redirect to HTTPS</td>
</tr>
</table>

<h3>6.2 Recommended Remediations</h3>
<table>
<tr><th>Vulnerability</th><th>Priority</th><th>Recommended Fix</th></tr>
<tr>
  <td>SQL Injection</td>
  <td>P0</td>
  <td>Replace all string-interpolated SQL with prepared statements using PDO <code>prepare()</code> / <code>execute()</code></td>
</tr>
<tr>
  <td>Shell Injection</td>
  <td>P0</td>
  <td>Use <code>escapeshellarg()</code> on all user input passed to shell commands; consider replacing shell calls with PHP native functions</td>
</tr>
<tr>
  <td>XSS</td>
  <td>P1</td>
  <td>Apply <code>htmlspecialchars()</code> to all user-supplied data before output in HTML</td>
</tr>
<tr>
  <td>Plain Text Passwords</td>
  <td>P0</td>
  <td>Hash passwords with <code>password_hash()</code> (bcrypt) and verify with <code>password_verify()</code></td>
</tr>
<tr>
  <td>CSRF</td>
  <td>P1</td>
  <td>Add CSRF token generation and validation to all state-changing forms</td>
</tr>
<tr>
  <td>Rate Limiting</td>
  <td>P2</td>
  <td>Implement login attempt throttling; consider Apache mod_evasive or application-level rate limiting</td>
</tr>
<tr>
  <td>Directory Traversal</td>
  <td>P0</td>
  <td>Sanitize all file paths with <code>basename()</code> and restrict to allowed directories</td>
</tr>
<tr>
  <td>Session Management</td>
  <td>P1</td>
  <td>Add <code>session_regenerate_id(true)</code> after login; set session timeout; configure secure cookie flags</td>
</tr>
</table>

<!-- ================================================================== -->
<h2 id="7">7. Logging, Debugging &amp; Monitoring</h2>
<!-- ================================================================== -->

<h3>7.1 Log File Configuration</h3>
<p>Log files are created in the <code>ko_safer</code> directory with monthly rotation:</p>
<pre>
Log directory: /os/ai/io/../ko_safer/
Log pattern:  ko_center_YYYYMM.log
Example:      /os/ai/io/../ko_safer/ko_center_202608.log
</pre>

<p>Log file path construction (startup() lines 144-148):</p>
<pre>
$yyyymm = date('Ym');
$logfil_basename = $progid . "_" . $yyyymm . ".log";
$logfil_rootpath = $document_root . "/../ko_safer";
$logfil = $logfil_rootpath . "/" . $logfil_basename;
$GLOBALS['logfil'] = $logfil;
</pre>

<h3>7.2 Logging Functions</h3>
<table>
<tr><th>Function</th><th>Line</th><th>Description</th></tr>
<tr><td><code>logwrite($logfil, $logrec)</code></td><td>4673</td><td>Append a record to the log file</td></tr>
<tr><td><code>logdump($logfil)</code></td><td>4683</td><td>Read and display entire log file contents</td></tr>
<tr><td><code>bugfile($options)</code></td><td>10993</td><td>Write comprehensive debug info to <code>fp_bugs.txt</code> (database file, URL table, page, POST data, GET data, session data)</td></tr>
</table>

<h3>7.3 Debug Mode</h3>
<p>Debug output is currently disabled (<code>error_reporting(0)</code> at line 107). To enable debugging:</p>
<ol>
  <li>Change <code>error_reporting(0)</code> to <code>error_reporting(E_ALL)</code> in <code>startup()</code></li>
  <li>Uncomment debug <code>print()</code> statements throughout the code (prefixed with <code>//</code>)</li>
  <li>Check log files in <code>/os/ai/io/../ko_safer/</code></li>
  <li>Use <code>?q=about</code> or <code>?q=pdo</code> for basic diagnostics</li>
</ol>

<h3>7.4 Monitoring Checklist</h3>
<ul>
  <li>Monitor disk space: <code>df -h /os/ai/io/</code></li>
  <li>Monitor log file sizes: <code>ls -lh /os/ai/io/../ko_safer/</code></li>
  <li>Monitor database file size: <code>ls -lh /os/ai/io/ko_center.db3</code></li>
  <li>Check web server error log: <code>tail -f /var/log/apache2/error.log</code></li>
  <li>Verify database integrity weekly: <code>sqlite3 ko_center.db3 "PRAGMA integrity_check;"</code></li>
</ul>

<!-- ================================================================== -->
<h2 id="8">8. Backup &amp; Recovery Procedures</h2>
<!-- ================================================================== -->

<h3>8.1 Backup Script</h3>
<pre>
#!/bin/bash
# ko_center_backup.sh — Daily backup script

DB="/os/ai/io/ko_center.db3"
KB="/os/ai/io/ko_center/kb"
CERTS="/os/ai/io/ko_center/db3/ko_center_certs.db3"
KB_DB="/os/ai/io/ko_center/db3/koaac_kb.db3"
BACKUP_DIR="/os/ai/io/backups"
HOSTS_ALLOW="/os/ai/io/../safer/hosts.allow"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p "$BACKUP_DIR"

# Backup database
cp "$DB" "$BACKUP_DIR/ko_center_$DATE.db3"
gzip "$BACKUP_DIR/ko_center_$DATE.db3"

# Backup certificates DB
cp "$CERTS" "$BACKUP_DIR/ko_center_certs_$DATE.db3"
gzip "$BACKUP_DIR/ko_center_certs_$DATE.db3"

# Backup KB database
cp "$KB_DB" "$BACKUP_DIR/koaac_kb_$DATE.db3"
gzip "$BACKUP_DIR/koaac_kb_$DATE.db3"

# Backup hosts.allow
cp "$HOSTS_ALLOW" "$BACKUP_DIR/hosts.allow_$DATE"

# Backup KB file attachments
tar -czf "$BACKUP_DIR/ko_kb_attachments_$DATE.tar.gz" -C "$(dirname $KB)" "$(basename $KB)"

# Keep only last 30 days of backups
find "$BACKUP_DIR" -name "ko_center_*.db3.gz" -mtime +30 -delete
find "$BACKUP_DIR" -name "hosts.allow_*" -mtime +30 -delete
find "$BACKUP_DIR" -name "ko_kb_attachments_*.tar.gz" -mtime +30 -delete

echo "Backup completed: $DATE"
</pre>

<h3>8.2 Recovery Procedure</h3>
<ol>
  <li><strong>Stop the web server:</strong> <code>systemctl stop apache2</code> (or <code>service apache2 stop</code>)</li>
  <li><strong>Copy backup to database location:</strong>
    <pre>gunzip -c /os/ai/io/backups/ko_center_YYYYMMDD_HHMMSS.db3.gz > /os/ai/io/ko_center.db3</pre></li>
  <li><strong>Verify integrity:</strong>
    <pre>sqlite3 /os/ai/io/ko_center.db3 "PRAGMA integrity_check;"</pre></li>
  <li><strong>Set correct permissions:</strong>
    <pre>chown www-data:www-data /os/ai/io/ko_center.db3
chmod 666 /os/ai/io/ko_center.db3</pre></li>
  <li><strong>Start the web server:</strong> <code>systemctl start apache2</code></li>
  <li><strong>Verify:</strong> Browse to <code>?q=about</code> and <code>?q=pdo</code></li>
</ol>

<h3>8.3 Files to Backup</h3>
<table>
<tr><th>File/Directory</th><th>Criticality</th><th>Backup Frequency</th></tr>
<tr><td><code>/os/ai/io/ko_center.db3</code></td><td><span class="tag">Critical</span></td><td>Daily</td></tr>
<tr><td><code>/os/ai/io/ko_center/db3/ko_center_certs.db3</code></td><td><span class="tag">Critical</span></td><td>Daily</td></tr>
<tr><td><code>/os/ai/io/ko_center/db3/koaac_kb.db3</code></td><td><span class="tag">Critical</span></td><td>Daily</td></tr>
<tr><td><code>/os/ai/io/safer/hosts.allow</code></td><td><span class="tag">Critical</span></td><td>Daily</td></tr>
<tr><td><code>/os/ai/io/ko_center.php</code></td><td><span class="tag">Critical</span></td><td>On every code change</td></tr>
<tr><td><code>/os/ai/io/images/</code></td><td><span class="tag">High</span></td><td>Weekly</td></tr>
<tr><td><code>/os/ai/io/ko_center/kb/</code></td><td><span class="tag">High</span></td><td>Daily</td></tr>
<tr><td><code>/os/ai/io/../ko_safer/</code></td><td><span class="tag">Medium</span></td><td>Monthly (archived)</td></tr>
</table>

<!-- ================================================================== -->
<h2 id="9">9. Routine Maintenance</h2>
<!-- ================================================================== -->

<h3>9.1 Scheduled Maintenance Tasks</h3>
<table>
<tr><th>Task</th><th>Frequency</th><th>Command / Action</th></tr>
<tr><td>Database backup</td><td>Daily</td><td>Run backup script (see Section 8.1)</td></tr>
<tr><td>Log rotation</td><td>Monthly</td><td>Compress old logs, delete logs older than 90 days</td></tr>
<tr><td>Database vacuum</td><td>Monthly</td><td><code>sqlite3 ko_center.db3 "VACUUM;"</code></td></tr>
<tr><td>Database analyze</td><td>Monthly</td><td><code>sqlite3 ko_center.db3 "ANALYZE;"</code></td></tr>
<tr><td>Disk space check</td><td>Weekly</td><td><code>df -h /os/ai/io/</code></td></tr>
<tr><td>File permissions audit</td><td>Weekly</td><td>Verify db3 file is writable by web server user</td></tr>
<tr><td>Image asset verification</td><td>Monthly</td><td>Verify <code>images/btn/</code>, <code>images/ani/</code>, <code>images/fpb/</code> have expected files</td></tr>
<tr><td>LED record cleanup</td><td>Monthly</td><td>Archive or delete old LED records (<code>led_dttm != 'current'</code>)</td></tr>
<tr><td>KB article review</td><td>Monthly</td><td>Remove outdated or unused KB entries</td></tr>
<tr><td>Database integrity check</td><td>Weekly</td><td><code>sqlite3 ko_center.db3 "PRAGMA integrity_check;"</code></td></tr>
<tr><td>Free space check</td><td>Weekly</td><td><code>sqlite3 ko_center.db3 "PRAGMA freelist_count;"</code></td></tr>
<tr><td>Trigger file check</td><td>Weekly</td><td>Verify <code>ko_trigger.dat</code> exists and is writable</td></tr>
</table>

<h3>9.2 LED Record Management</h3>
<p>LED records use <code>led_dttm = 'current'</code> to mark active records. Historical records should be archived:</p>
<pre>
-- Archive old LED records to a separate table
CREATE TABLE IF NOT EXISTS leds_archive AS SELECT * FROM leds WHERE 1=0;
INSERT INTO leds_archive SELECT * FROM leds WHERE led_dttm != 'current';
DELETE FROM leds WHERE led_dttm != 'current';
</pre>

<h3>9.3 Database Optimization</h3>
<pre>
# Rebuild all indexes
sqlite3 /os/ai/io/ko_center.db3 "REINDEX;"

# Update query planner statistics
sqlite3 /os/ai/io/ko_center.db3 "ANALYZE;"

# Check database size
ls -lh /os/ai/io/ko_center.db3

# Check for fragmentation
sqlite3 /os/ai/io/ko_center.db3 "PRAGMA freelist_count;"

# If freelist_count > 0, vacuum is recommended
sqlite3 /os/ai/io/ko_center.db3 "VACUUM;"
</pre>

<!-- ================================================================== -->
<h2 id="10">10. Troubleshooting Guide</h2>
<!-- ================================================================== -->

<h3>10.1 Common Issues &amp; Solutions</h3>
<table>
<tr><th>Symptom</th><th>Probable Cause</th><th>Solution</th></tr>
<tr>
  <td>Blank white page</td>
  <td>PHP error suppressed by <code>error_reporting(0)</code></td>
  <td>Temporarily change <code>error_reporting(0)</code> to <code>error_reporting(E_ALL)</code> in <code>startup()</code> at line 107</td>
</tr>
<tr>
  <td>"Database not found" error</td>
  <td><code>ko_center.db3</code> missing or incorrect path in <code>$GLOBALS['dbfile']</code></td>
  <td>Verify path in <code>startup()</code> (line 138); run <code>leds_install("new")</code> by accessing the URL in a browser</td>
</tr>
<tr>
  <td>"Permission denied" errors</td>
  <td>Web server user cannot write to database file or directories</td>
  <td><code>chown www-data:www-data /os/ai/io/ko_center.db3</code>; <code>chmod 666 /os/ai/io/ko_center.db3</code></td>
</tr>
<tr>
  <td>LED images not displaying</td>
  <td>Missing <code>ani_*.gif</code> files in <code>images/ani/</code></td>
  <td>Run <code>python3 /os/ai/io/cr_leds.py &lt;static.png&gt; &lt;dynamic.png&gt;</code></td>
</tr>
<tr>
  <td>Button images broken</td>
  <td>Missing <code>btn_*.gif</code> files in <code>images/btn/</code></td>
  <td>Verify button images exist in <code>/os/ai/io/images/btn/</code></td>
</tr>
<tr>
  <td>Login fails for all users</td>
  <td><code>hosts.allow</code> missing, wrong path, or wrong format</td>
  <td>Check <code>/os/ai/io/../safer/hosts.allow</code> exists and contains <code>allow all</code> or properly formatted entries</td>
</tr>
<tr>
  <td>Trigger not refreshing other browsers</td>
  <td><code>ko_trigger.dat</code> not writable or missing</td>
  <td><code>touch /os/ai/io/ko_trigger.dat &amp;&amp; chmod 666 /os/ai/io/ko_trigger.dat</code></td>
</tr>
<tr>
  <td>Grid view shows empty or error</td>
  <td>Table doesn't exist or has no data; SQL error</td>
  <td>Verify table exists: <code>sqlite3 ko_center.db3 ".tables"</code>; check SQL in query</td>
</tr>
<tr>
  <td>Report export fails</td>
  <td>File write permission issues in output directory</td>
  <td>Verify web server user has write permission to output directory</td>
</tr>
<tr>
  <td>Slow page loads</td>
  <td>Large database (39.6 MB), complex queries, missing indexes</td>
  <td>Run <code>VACUUM</code> and <code>ANALYZE</code>; add indexes to frequently queried columns</td>
</tr>
<tr>
  <td>KB file uploads fail</td>
  <td>PHP <code>upload_max_filesize</code> or <code>post_max_size</code> too small</td>
  <td>Increase in php.ini: <code>upload_max_filesize = 50M</code>, <code>post_max_size = 50M</code></td>
</tr>
<tr>
  <td>Theme not applying</td>
  <td>jQuery UI theme CSS files missing</td>
  <td>Verify theme CSS files exist in <code>js/themes/&lt;theme&gt;/</code></td>
</tr>
</table>

<h3>10.2 Debugging Checklist</h3>
<ol>
  <li><strong>Check PHP is running:</strong> <code>php -v</code></li>
  <li><strong>Check database exists:</strong> <code>ls -la /os/ai/io/ko_center.db3</code></li>
  <li><strong>Check database integrity:</strong> <code>sqlite3 /os/ai/io/ko_center.db3 "PRAGMA integrity_check;"</code></li>
  <li><strong>Check web server error log:</strong> <code>tail -f /var/log/apache2/error.log</code></li>
  <li><strong>Check application logs:</strong> <code>ls -la /os/ai/io/../ko_safer/</code></li>
  <li><strong>Verify file permissions:</strong> <code>namei -l /os/ai/io/ko_center.db3</code></li>
  <li><strong>Test basic functionality:</strong> Browse to <code>?q=about</code></li>
  <li><strong>Test database connectivity:</strong> Browse to <code>?q=pdo</code></li>
  <li><strong>Check PHP error log:</strong> <code>tail -f /var/log/php_errors.log</code></li>
  <li><strong>Enable error reporting:</strong> Temporarily set <code>error_reporting(E_ALL)</code> in startup()</li>
</ol>

<h3>10.3 Performance Tuning</h3>
<table>
<tr><th>Area</th><th>Setting</th><th>Recommendation</th></tr>
<tr><td>PHP Memory</td><td><code>memory_limit</code></td><td>Set to 256M or higher for large grid views</td></tr>
<tr><td>PHP Execution Time</td><td><code>max_execution_time</code></td><td>Set to 300 for long-running reports</td></tr>
<tr><td>PHP Upload Size</td><td><code>upload_max_filesize</code></td><td>Set to 50M for KB file uploads</td></tr>
<tr><td>SQLite Cache Size</td><td><code>PRAGMA cache_size</code></td><td>Set to -64000 (64MB) for better query performance</td></tr>
<tr><td>SQLite Journal Mode</td><td><code>PRAGMA journal_mode</code></td><td>Set to <code>WAL</code> for better concurrent read performance</td></tr>
<tr><td>Apache KeepAlive</td><td><code>KeepAlive On</code></td><td>Enable for better performance with multiple AJAX requests</td></tr>
<tr><td>Apache MaxClients</td><td><code>MaxClients</code></td><td>Adjust based on expected concurrent users</td></tr>
</table>

<!-- ================================================================== -->
<h2 id="11">11. File Structure &amp; Asset Inventory</h2>
<!-- ================================================================== -->

<h3>11.1 Complete Directory Layout</h3>
<pre>
/os/ai/io/
├── ko_center.php          [16,322 lines]  Main PHP application
├── ko_center.py            [Python Flask]  Python equivalent
├── ko_center.db3           [39.6 MB]      SQLite database
├── ko_center.html          [User doc]      System user documentation
├── ko_center_admin.html    [Admin doc]     Administrator documentation (previous)
├── ko_center_sysadm.html   [This file]    System administrator documentation
├── new_leds.py             [Script]       Create leds_randomus table
├── new_leds_tbl.py         [Script]       Generalized table creation
├── cr_leds.py              [Script]       LED GIF generation with ImageMagick
├── response_trigger_plan.txt       [Doc]    Trigger mechanism design
├── prompt_*.txt            [Prompts]      Original task prompts
├── response_*.txt          [Docs]         Response documents
├── ko_trigger.dat          [Runtime]      Trigger timestamp (created at runtime)
├── led_red_flashing.jpg    [Asset]        LED image asset
├── images/
│   ├── btn/                 Button GIF images (btn_black.gif, btn_white.gif, etc.)
│   ├── ani/                 Animated LED GIFs (ani_red0.gif through ani_trans3.gif)
│   ├── fpb/                 Floor plan button images
│   └── cab/                 Cabinet images
├── ko_center/
│   ├── db3/                 Additional database files
│   │   ├── ko_center_certs.db3
│   │   └── koaac_kb.db3
│   └── kb/                  Knowledge Base file storage
├── js/
│   ├── jquery-1.7.2.min.js
│   ├── jquery-ui-1.7.2.custom.min.js
│   ├── fg-menu/             fg-menu JavaScript and CSS
│   ├── jqgrid-4.4.0/       jqGrid library (JS, CSS, images, i18n)
│   └── tooltip/             Tooltip JavaScript
├── css/                     Theme CSS files (jQuery UI themes)
├── ../safer/
│   └── hosts.allow          Authentication/authorization file
└── ../ko_safer/
    └── ko_center_YYYYMM.log  Monthly application logs
</pre>

<h3>11.2 Key File Sizes</h3>
<table>
<tr><th>File</th><th>Size</th><th>Lines</th><th>Description</th></tr>
<tr><td><code>ko_center.php</code></td><td>~635 KB</td><td>16,322</td><td>Main application (all functionality)</td></tr>
<tr><td><code>ko_center.db3</code></td><td>~39.6 MB</td><td>—</td><td>SQLite database</td></tr>
<tr><td><code>ko_center.py</code></td><td>—</td><td>—</td><td>Python Flask equivalent</td></tr>
<tr><td><code>new_leds.py</code></td><td>—</td><td>—</td><td>Create leds_randomus table</td></tr>
<tr><td><code>new_leds_tbl.py</code></td><td>—</td><td>—</td><td>Generalized table creation</td></tr>
<tr><td><code>cr_leds.py</code></td><td>—</td><td>—</td><td>LED GIF generation</td></tr>
</table>

<!-- ================================================================== -->
<h2 id="12">12. PHP Function Reference (205 Functions)</h2>
<!-- ================================================================== -->

<h3>12.1 Core Application Functions</h3>
<table>
<tr><th>Function</th><th>Line</th><th>Purpose</th></tr>
<tr><td><code>startup()</code></td><td>101</td><td>Application initialization: session, globals, paths, config, routing</td></tr>
<tr><td><code>html_header()</code></td><td>8395</td><td>Generate HTML <code>&lt;head&gt;</code> section with CSS/JS includes</td></tr>
<tr><td><code>html_footer()</code></td><td>10987</td><td>Generate HTML <code>&lt;/body&gt;&lt;/html&gt;</code> closing tags</td></tr>
<tr><td><code>html_page()</code></td><td>6635</td><td>Generate complete HTML page (header + buttons + content + footer)</td></tr>
<tr><td><code>html_btn_squares()</code></td><td>7331</td><td>Generate navigation button squares</td></tr>
<tr><td><code>js_scripts()</code></td><td>14337</td><td>Generate JavaScript includes (jQuery, jqGrid, fg-menu)</td></tr>
<tr><td><code>leds_show()</code></td><td>6895</td><td>Main LED display — queries DB, renders LED grid with blinking GIFs</td></tr>
<tr><td><code>leds_detail()</code></td><td>7759</td><td>LED detail view with associated hardware items and images</td></tr>
<tr><td><code>leds_about()</code></td><td>6323</td><td>About page</td></tr>
<tr><td><code>leds_login_form()</code></td><td>8450</td><td>Login form HTML generation</td></tr>
<tr><td><code>leds_login_validate()</code></td><td>8568</td><td>Login credential validation against hosts.allow</td></tr>
<tr><td><code>leds_logout()</code></td><td>8739</td><td>Session cleanup and redirect to main page</td></tr>
<tr><td><code>leds_config()</code></td><td>6653</td><td>Configuration page with theme/org/role/preview/hotspot buttons</td></tr>
<tr><td><code>leds_install()</code></td><td>9707</td><td>Database initialization — creates all tables and inserts default data</td></tr>
</table>

<h3>12.2 Database Functions</h3>
<table>
<tr><th>Function</th><th>Line</th><th>Purpose</th></tr>
<tr><td><code>newpdo($dbfile)</code></td><td>6595</td><td>Create SQLite PDO connection</td></tr>
<tr><td><code>pdo_create($dbfile, $tblname, $sql)</code></td><td>9785</td><td>Create a new database table (drop + create)</td></tr>
<tr><td><code>pdo_insert($dbfile, $tblname, $data)</code></td><td>9799</td><td>Insert a row into a table from CSV/PSV file</td></tr>
<tr><td><code>pdo_cr_leds()</code></td><td>9929</td><td>Create the leds table</td></tr>
<tr><td><code>pdo_cr_kb()</code></td><td>9981</td><td>Create the KB (koaac_kb) table</td></tr>
<tr><td><code>pdo_cr_nodes()</code></td><td>10132</td><td>Create the nodes table</td></tr>
<tr><td><code>pdo_cr_roles()</code></td><td>10166</td><td>Create the roles table</td></tr>
<tr><td><code>pdo_cr_users()</code></td><td>10178</td><td>Create the users table</td></tr>
<tr><td><code>pdo_cr_fp()</code></td><td>10200</td><td>Create the floor plan (fp) table</td></tr>
<tr><td><code>pdo_cr_grid()</code></td><td>10220</td><td>Create the grid table</td></tr>
<tr><td><code>pdo_cr_us()</code></td><td>10240</td><td>Create the us (user-specific) table</td></tr>
<tr><td><code>pdo_cr_hw()</code></td><td>10261</td><td>Create the hw table</td></tr>
<tr><td><code>pdo_cr_n11()</code></td><td>10282</td><td>Create the n11 table</td></tr>
<tr><td><code>pdo_cr_dbs()</code></td><td>15641</td><td>Create the dbs (database registry) table</td></tr>
<tr><td><code>pdo_cr_flds()</code></td><td>15728</td><td>Create the flds (fields) table</td></tr>
<tr><td><code>pdo_cr_menus()</code></td><td>9981</td><td>Create the menus table</td></tr>
<tr><td><code>pdo_insert_leds()</code></td><td>10305</td><td>Insert default LED records</td></tr>
<tr><td><code>pdo_insert_nodes()</code></td><td>10423</td><td>Insert default node records</td></tr>
<tr><td><code>pdo_insert_roles()</code></td><td>10474</td><td>Insert default role records</td></tr>
<tr><td><code>pdo_insert_users()</code></td><td>10491</td><td>Insert default user records</td></tr>
<tr><td><code>pdo_insert_fp()</code></td><td>10516</td><td>Insert default floor plan records</td></tr>
<tr><td><code>pdo_insert_grid()</code></td><td>10538</td><td>Insert default grid records</td></tr>
<tr><td><code>pdo_insert_us()</code></td><td>10552</td><td>Insert default user-specific records</td></tr>
<tr><td><code>pdo_insert_hw()</code></td><td>10570</td><td>Insert default hardware records</td></tr>
<tr><td><code>pdo_insert_n11()</code></td><td>10586</td><td>Insert default n11 records</td></tr>
<tr><td><code>pdo_insert_obj()</code></td><td>10600</td><td>Insert default object records</td></tr>
<tr><td><code>pdo_insert_pano()</code></td><td>10621</td><td>Insert default panorama records</td></tr>
<tr><td><code>pdo_insert_dbs()</code></td><td>15754</td><td>Insert default database registry records</td></tr>
<tr><td><code>pdo_cr_fgmenu()</code></td><td>9981</td><td>Create the fgmenu table</td></tr>
<tr><td><code>pdo_insert_fgmenu()</code></td><td>9994</td><td>Insert default fgmenu records</td></tr>
</table>

<h3>12.3 Grid &amp; Data Display Functions</h3>
<table>
<tr><th>Function</th><th>Line</th><th>Purpose</th></tr>
<tr><td><code>pdo_grid($options)</code></td><td>10686</td><td>Generate sortable/filterable database grid view</td></tr>
<tr><td><code>pdo_gridxml($options)</code></td><td>11021</td><td>Export grid data as XML</td></tr>
<tr><td><code>pdo_unload($options)</code></td><td>11693</td><td>Unload/export table data</td></tr>
<tr><td><code>pdo_list($options)</code></td><td>11786</td><td>List all database tables</td></tr>
<tr><td><code>pdo_update($options)</code></td><td>11790</td><td>Update table data (inline editing)</td></tr>
<tr><td><code>pdo_load($options)</code></td><td>11794</td><td>Load table data for editing</td></tr>
<tr><td><code>sql_view($options)</code></td><td>9645</td><td>SQL query interface</td></tr>
<tr><td><code>leds_view($options)</code></td><td>9685</td><td>Generic data view</td></tr>
<tr><td><code>leds_list($options)</code></td><td>9689</td><td>Generic data listing</td></tr>
<tr><td><code>leds_test($options)</code></td><td>9694</td><td>Test/diagnostic view</td></tr>
</table>

<h3>12.4 Report Functions</h3>
<table>
<tr><th>Function</th><th>Line</th><th>Purpose</th></tr>
<tr><td><code>leds_reports_sql($options)</code></td><td>3681</td><td>SQL query interface for custom reports</td></tr>
<tr><td><code>leds_reports_csv($dbfile, $sql, $csvfil)</code></td><td>3841</td><td>Export report data as CSV</td></tr>
<tr><td><code>leds_reports_rpt($options)</code></td><td>3931</td><td>Generate formatted report with print/export options</td></tr>
<tr><td><code>rptsxml($options)</code></td><td>16043</td><td>XML report generation</td></tr>
<tr><td><code>rpts($options)</code></td><td>16134</td><td>Report listing and management</td></tr>
<tr><td><code>reports_menu($code)</code></td><td>3377</td><td>Generate report navigation menu</td></tr>
</table>

<h3>12.5 KB (Knowledge Base) Functions</h3>
<table>
<tr><th>Function</th><th>Line</th><th>Purpose</th></tr>
<tr><td><code>leds_kb($options)</code></td><td>12401</td><td>Knowledge Base listing</td></tr>
<tr><td><code>leds_kb_rpts($options)</code></td><td>12594</td><td>KB reports</td></tr>
<tr><td><code>koaac_kb_new_form($options)</code></td><td>4844</td><td>New KB entry form</td></tr>
<tr><td><code>koaac_kb_add_form($options)</code></td><td>5436</td><td>Add KB entry form</td></tr>
<tr><td><code>koaac_kb_upload($kbid)</code></td><td>5690</td><td>KB file upload handler</td></tr>
<tr><td><code>kbwrite($kbfil, $kbrec)</code></td><td>4661</td><td>Write KB record to file</td></tr>
<tr><td><code>kb_ls($options, $path)</code></td><td>4701</td><td>List KB files in directory</td></tr>
<tr><td><code>kb_mkdir($kbpath, $kbid)</code></td><td>6031</td><td>Create KB directory structure</td></tr>
</table>

<h3>12.6 Utility Functions</h3>
<table>
<tr><th>Function</th><th>Line</th><th>Purpose</th></tr>
<tr><td><code>logwrite($logfil, $logrec)</code></td><td>4673</td><td>Write a record to the log file</td></tr>
<tr><td><code>logdump($logfil)</code></td><td>4683</td><td>Dump entire log file contents</td></tr>
<tr><td><code>bugfile($options)</code></td><td>10993</td><td>Write comprehensive debug info to fp_bugs.txt</td></tr>
<tr><td><code>ko_unique()</code></td><td>14904</td><td>Generate UUID</td></tr>
<tr><td><code>ko_unique1()</code></td><td>14909</td><td>Generate short unique ID (8 chars)</td></tr>
<tr><td><code>pc_encode($data)</code></td><td>14918</td><td>PC encoding (obfuscation/encoding)</td></tr>
<tr><td><code>pc_decode($data, $hash)</code></td><td>14923</td><td>PC decoding</td></tr>
<tr><td><code>datediff($interval, $date1, $date2)</code></td><td>14939</td><td>Calculate difference between two dates</td></tr>
<tr><td><code>datediff_leds($diffdays)</code></td><td>14951</td><td>LED-specific date difference (returns color, speed, days)</td></tr>
<tr><td><code>iperms($options)</code></td><td>6425</td><td>System permissions/utility functions (periods, job2db)</td></tr>
<tr><td><code>localcmds($options)</code></td><td>15887</td><td>Local command execution interface</td></tr>
<tr><td><code>telnet($options)</code></td><td>15939</td><td>Telnet connection utility</td></tr>
<tr><td><code>ko_imap($options)</code></td><td>14700</td><td>IMAP email functions</td></tr>
<tr><td><code>email_headers()</code></td><td>16117</td><td>Email header generation</td></tr>
<tr><td><code>leds_process($title, $cmd, $cwd)</code></td><td>6485</td><td>Execute shell process and display formatted output</td></tr>
<tr><td><code>leds_process_psv($title, $cmd, $cwd)</code></td><td>6519</td><td>Execute Perl script process and display output</td></tr>
<tr><td><code>leds_process_value($title, $cmd, $cwd)</code></td><td>6560</td><td>Execute command and return value</td></tr>
</table>

<h3>12.7 AJAX Functions</h3>
<table>
<tr><th>Function</th><th>Line</th><th>Purpose</th></tr>
<tr><td><code>ko_ajax($options)</code></td><td>2508</td><td>AJAX request handler (test1: login simulation with refreshPage event)</td></tr>
<tr><td><code>ko_ajax_controller($options)</code></td><td>2532</td><td>Generate AJAX controller JavaScript (LoginController)</td></tr>
<tr><td><code>ko_ajax_listener($options)</code></td><td>2555</td><td>Generate AJAX listener JavaScript (event handling)</td></tr>
<tr><td><code>ko_ajax_app($options)</code></td><td>2580</td><td>Generate AJAX app JavaScript (includes refreshPage → window.location.reload)</td></tr>
<tr><td><code>ko_ajax_complete($options)</code></td><td>2599</td><td>Generate AJAX complete handler (global AJAX event dispatcher)</td></tr>
<tr><td><code>ko_ajax_result($options)</code></td><td>2616</td><td>Generate ServiceResult JavaScript class</td></tr>
</table>

<h3>12.8 View/Page Functions</h3>
<table>
<tr><th>Function</th><th>Line</th><th>Purpose</th></tr>
<tr><td><code>leds_zm5($options)</code></td><td>7271</td><td>Zoom level 5 viewer</td></tr>
<tr><td><code>leds_zoom($options)</code></td><td>13443</td><td>Zoom viewer with hotspot navigation</td></tr>
<tr><td><code>html_zoom_detail($options)</code></td><td>8072</td><td>Zoom detail view with XML hotspot config</td></tr>
<tr><td><code>leds_ptviewer($options)</code></td><td>13368</td><td>Panorama/tour viewer</td></tr>
<tr><td><code>leds_ptobject($options)</code></td><td>13835</td><td>Individual panorama object viewer</td></tr>
<tr><td><code>leds_zview($options)</code></td><td>13835</td><td>ZView display</td></tr>
<tr><td><code>leds_zview_xml($options)</code></td><td>13952</td><td>ZView XML generation</td></tr>
<tr><td><code>leds_zview_details($options)</code></td><td>13999</td><td>ZView detail rendering</td></tr>
<tr><td><code>leds_zview_xmlnew($options)</code></td><td>14057</td><td>Create new ZView XML configuration</td></tr>
<tr><td><code>leds_zoomxml($options)</code></td><td>14181</td><td>Zoom XML export</td></tr>
<tr><td><code>html_links($options)</code></td><td>13434</td><td>Links page</td></tr>
<tr><td><code>pchart_pie($options)</code></td><td>4470</td><td>pChart pie chart display</td></tr>
<tr><td><code>scrub_view($options)</code></td><td>6108</td><td>Scrub/data cleanup view</td></tr>
<tr><td><code>scrub_show($options)</code></td><td>6859</td><td>Scrub display with file listing</td></tr>
<tr><td><code>scrub_upload_form($options)</code></td><td>9085</td><td>Scrub file upload form</td></tr>
<tr><td><code>scrub_upload($user)</code></td><td>9154</td><td>Process scrub file upload</td></tr>
<tr><td><code>ko_upload2()</code></td><td>9422</td><td>File upload handler</td></tr>
<tr><td><code>ko_uploads()</code></td><td>9466</td><td>List uploaded files</td></tr>
<tr><td><code>leds_update_form($options)</code></td><td>8776</td><td>LED update form</td></tr>
<tr><td><code>leds_update($options)</code></td><td>8992</td><td>Process LED update</td></tr>
</table>

<h3>12.9 Special-Purpose Functions</h3>
<table>
<tr><th>Function</th><th>Line</th><th>Purpose</th></tr>
<tr><td><code>im_identify($filemask)</code></td><td>4300</td><td>ImageMagick file identification</td></tr>
<tr><td><code>key2png($key, $val)</code></td><td>4339</td><td>Key-value to PNG conversion</td></tr>
<tr><td><code>sqlq($dbfile, $sql, $fld)</code></td><td>2801</td><td>Execute SQL query and return field value</td></tr>
<tr><td><code>sql_updform(...)</code></td><td>4410</td><td>SQL update form generation</td></tr>
<tr><td><code>csv2db3($csvfil, $delimiter)</code></td><td>3619</td><td>Import CSV file into database</td></tr>
<tr><td><code>getfiles($path, $mask)</code></td><td>6075</td><td>List files matching a mask in a directory</td></tr>
<tr><td><code>fgmenu_head($options)</code></td><td>14976</td><td>Generate fg-menu head HTML</td></tr>
<tr><td><code>fgmenu_js($options)</code></td><td>15032</td><td>Generate fg-menu JavaScript</td></tr>
<tr><td><code>fgmenu_htm($options)</code></td><td>15075</td><td>Generate fg-menu HTML</td></tr>
<tr><td><code>fgmenu_dyn($options)</code></td><td>15129</td><td>Generate dynamic fg-menu</td></tr>
<tr><td><code>menutree(...)</code></td><td>15313</td><td>Recursive menu tree builder</td></tr>
<tr><td><code>head_jqui_css($options)</code></td><td>14518</td><td>Generate jQuery UI CSS includes</td></tr>
<tr><td><code>jqui($jqui)</code></td><td>16260</td><td>jQuery UI component generator</td></tr>
<tr><td><code>css_rollovers_head($options)</code></td><td>14644</td><td>Generate CSS rollover styles</td></tr>
<tr><td><code>js_rollover($options)</code></td><td>14633</td><td>Generate JavaScript rollover code</td></tr>
<tr><td><code>html_btn_hotspots($options, $callback)</code></td><td>6673</td><td>Generate hotspot type buttons</td></tr>
<tr><td><code>html_btn_orgs($options, $callback)</code></td><td>6729</td><td>Generate organization type buttons</td></tr>
<tr><td><code>html_btn_preview($options, $callback)</code></td><td>6756</td><td>Generate preview mode toggle button</td></tr>
<tr><td><code>html_btn_roles($options, $callback)</code></td><td>6783</td><td>Generate role type buttons</td></tr>
<tr><td><code>html_btn_themes($options, $callback)</code></td><td>6812</td><td>Generate theme selection buttons</td></tr>
<tr><td><code>html_btn_footer($options)</code></td><td>7431</td><td>Generate footer button row</td></tr>
<tr><td><code>html_dc_links($option)</code></td><td>7664</td><td>Generate datacenter links</td></tr>
<tr><td><code>html_kb_links($options)</code></td><td>7687</td><td>Generate KB navigation links</td></tr>
<tr><td><code>html_nodes_links($options)</code></td><td>7707</td><td>Generate node navigation links</td></tr>
<tr><td><code>html_scrub($options)</code></td><td>7728</td><td>Generate scrub navigation</td></tr>
<tr><td><code>ko_sessions_start()</code></td><td>14823</td><td>Session initialization</td></tr>
<tr><td><code>ko_sessions()</code></td><td>14833</td><td>Session management</td></tr>
<tr><td><code>ko_validata()</code></td><td>14842</td><td>Validation function</td></tr>
<tr><td><code>ko_validate_form()</code></td><td>14862</td><td>Form validation</td></tr>
<tr><td><code>ko_validate_form_user($user)</code></td><td>14872</td><td>Validate username</td></tr>
<tr><td><code>ko_validate_form_pass($pass)</code></td><td>14874</td><td>Validate password</td></tr>
<tr><td><code>ko_print_form($errors)</code></td><td>14877</td><td>Print form with error messages</td></tr>
<tr><td><code>leds_login_form($options)</code></td><td>8450</td><td>Login form with jqGrid integration</td></tr>
<tr><td><code>ldap_authenticate()</code></td><td>8525</td><td>LDAP authentication (commented out)</td></tr>
<tr><td><code>ko_dragdrop_redirect($options)</code></td><td>2630</td><td>Drag-and-drop redirect handler</td></tr>
<tr><td><code>ko_dragdrop($options)</code></td><td>2646</td><td>Drag-and-drop interface</td></tr>
<tr><td><code>dragdrop_test1($options)</code></td><td>2697</td><td>Drag-and-drop test page</td></tr>
<tr><td><code>ko_im($options)</code></td><td>2778</td><td>Image manipulation interface</td></tr>
<tr><td><code>leds_leds($options)</code></td><td>3428</td><td>LED management interface</td></tr>
<tr><td><code>leds_ko_centerd_rpts($options)</code></td><td>13137</td><td>ko_centerd reports</td></tr>
<tr><td><code>leds_nodes_rpts($options)</code></td><td>13252</td><td>Node reports</td></tr>
<tr><td><code>leds_certs_rpts($options)</code></td><td>12801</td><td>Certificate reports</td></tr>
<tr><td><code>leds_cons_rpts($options)</code></td><td>12907</td><td>Console reports</td></tr>
<tr><td><code>leds_hosts_rpts($options)</code></td><td>13013</td><td>Host reports</td></tr>
<tr><td><code>leds_dc_rpts($options)</code></td><td>12696</td><td>Datacenter reports</td></tr>
<tr><td><code>leds_plans($options)</code></td><td>—</td><td>Plan listing and management</td></tr>
<tr><td><code>leds_hw($options)</code></td><td>4560</td><td>Hardware inventory view</td></tr>
<tr><td><code>leds_certs($options)</code></td><td>12164</td><td>Certificate listing</td></tr>
<tr><td><code>leds_cons($options)</code></td><td>12282</td><td>Console listing</td></tr>
<tr><td><code>leds_hosts($options)</code></td><td>12401</td><td>Host listing</td></tr>
<tr><td><code>leds_ko_centerd_rpts($options)</code></td><td>13137</td><td>ko_centerd reports</td></tr>
<tr><td><code>leds_reports_sql($options)</code></td><td>3681</td><td>SQL report interface</td></tr>
<tr><td><code>leds_reports_csv($dbfile, $sql, $csvfil)</code></td><td>3841</td><td>CSV report export</td></tr>
<tr><td><code>leds_reports_rpt($options)</code></td><td>3931</td><td>Formatted report generator</td></tr>
<tr><td><code>leds_menu($options)</code></td><td>9645</td><td>Navigation menu generator</td></tr>
<tr><td><code>ko_plans_items($options)</code></td><td>2819</td><td>Plan items view</td></tr>
<tr><td><code>ko_plans_steps($options)</code></td><td>2920</td><td>Plan steps view</td></tr>
<tr><td><code>ko_plans1($options)</code></td><td>3132</td><td>Plan view v1</td></tr>
<tr><td><code>ko_plans_save($options)</code></td><td>3138</td><td>Plan save handler</td></tr>
<tr><td><code>ko_co($options)</code></td><td>—</td><td>ko_center main page handler</td></tr>
<tr><td><code>anonymous_option1/2/3($options)</code></td><td>6402-6404</td><td>Guest anonymous role options</td></tr>
<tr><td><code>guest_option1/2/3($options)</code></td><td>6405-6407</td><td>Guest role options</td></tr>
<tr><td><code>user_option1/2/3($options)</code></td><td>6408-6410</td><td>User role options</td></tr>
<tr><td><code>qc_option1/2/3($options)</code></td><td>6411-6413</td><td>QC role options</td></tr>
<tr><td><code>manager_option1/2/3($options)</code></td><td>6414-6416</td><td>Manager role options</td></tr>
<tr><td><code>operator_option1/2/3($options)</code></td><td>6417-6419</td><td>Operator role options</td></tr>
<tr><td><code>admin_option1/2/3($options)</code></td><td>6420-6422</td><td>Admin role options</td></tr>
<tr><td><code>iperms($options)</code></td><td>6425</td><td>System permissions (periods_p, periods_pp, job2db)</td></tr>
<tr><td><code>datediff($interval, $date1, $date2)</code></td><td>14939</td><td>Date difference calculator</td></tr>
<tr><td><code>datediff_leds($diffdays)</code></td><td>14951</td><td>LED date difference (returns color/speed for LED status)</td></tr>
<tr><td><code>sql3_select_hallo($db3file, $db3tbl, $ip)</code></td><td>6108</td><td>SQLite3 select for hallo table</td></tr>
<tr><td><code>sql3_insert_hallo($db3file, $db3tbl)</code></td><td>6131</td><td>SQLite3 insert for hallo table</td></tr>
</table>

<!-- ================================================================== -->
<h2 id="13">13. Deployment &amp; Server Configuration</h2>
<!-- ================================================================== -->

<h3>13.1 Apache Virtual Host Configuration</h3>
<pre>
&lt;VirtualHost *:80&gt;
    ServerName ko_center.example.com
    DocumentRoot /os/ai/io

    &lt;Directory /os/ai/io&gt;
        Options +FollowSymLinks
        AllowOverride None
        Require all granted
    &lt;/Directory&gt;

    # PHP configuration
    php_value upload_max_filesize 50M
    php_value post_max_size 50M
    php_value max_execution_time 300
    php_value memory_limit 256M

    # SQLite configuration
    php_value sqlite.assoc_case 0

    # Logging
    ErrorLog /var/log/apache2/ko_center_error.log
    CustomLog /var/log/apache2/ko_center_access.log combined

    # Security headers
    Header set X-Content-Type-Options "nosniff"
    Header set X-Frame-Options "SAMEORIGIN"
&lt;/VirtualHost&gt;
</pre>

<h3>13.2 Environment Variables</h3>
<table>
<tr><th>Variable</th><th>Default</th><th>Description</th></tr>
<tr><td><code>KO_THEME</code></td><td><code>redmond</code></td><td>jQuery UI theme name</td></tr>
<tr><td><code>KO_DB_FILE</code></td><td><code>/os/ai/io/ko_center.db3</code></td><td>Database file path</td></tr>
<tr><td><code>KO_HOSTS_ALLOW</code></td><td><code>/os/ai/io/../safer/hosts.allow</code></td><td>Authentication file path</td></tr>
<tr><td><code>KO_LOG_DIR</code></td><td><code>/os/ai/io/../ko_safer</code></td><td>Log file directory</td></tr>
<tr><td><code>KO_TRIGGER_FILE</code></td><td><code>/os/ai/io/ko_trigger.dat</code></td><td>Trigger timestamp file</td></tr>
</table>

<h3>13.3 PHP Configuration Recommendations</h3>
<pre>
; php.ini or .htaccess settings for ko_center

memory_limit = 256M
max_execution_time = 300
upload_max_filesize = 50M
post_max_size = 50M

; SQLite
sqlite3.extension_dir = ""

; Session
session.gc_maxlifetime = 1440
session.cookie_httponly = 1
session.cookie_samesite = "Lax"

; Error reporting (production)
display_errors = Off
log_errors = On
error_log = /var/log/php_errors.log
</pre>

<!-- ================================================================== -->
<h2 id="14">14. Python Flask Equivalent</h2>
<!-- ================================================================== -->

<p>A Python Flask equivalent of ko_center.php has been created at <span class="file-path">/os/ai/io/ko_center.py</span>. Key differences:</p>

<table>
<tr><th>Aspect</th><th>PHP Version</th><th>Python Version</th></tr>
<tr><td>Web Framework</td><td>Apache + mod_php</td><td>Flask (built-in dev server)</td></tr>
<tr><td>Routing</td><td><code>?q=page/action/id</code> parsed manually in startup()</td><td>Flask <code>@app.route</code> decorators</td></tr>
<tr><td>Database</td><td>PDO SQLite</td><td>Python <code>sqlite3</code> module</td></tr>
<tr><td>Sessions</td><td><code>$_SESSION</code></td><td>Flask <code>session</code></td></tr>
<tr><td>HTML Generation</td><td>String concatenation in functions</td><td>String concatenation in functions</td></tr>
<tr><td>Authentication</td><td>hosts.allow file check</td><td>Same hosts.allow file check</td></tr>
<tr><td>AJAX</td><td>jQuery AJAX + custom ko_ajax functions</td><td>Flask <code>jsonify()</code> + jQuery AJAX</td></tr>
<tr><td>File Upload</td><td><code>$_FILES</code> superglobal</td><td>Flask <code>request.files</code></td></tr>
<tr><td>Process Execution</td><td><code>system()</code>, <code>exec()</code>, <code>passthru()</code></td><td><code>subprocess</code> module</td></tr>
<tr><td>Trigger Endpoint</td><td><code>?q=trigger</code> (file-based)</td><td><code>/trigger</code> route (file-based)</td></tr>
</table>

<p><strong>Running the Python version:</strong></p>
<pre>python3 /os/ai/io/ko_center.py</pre>
<p>Then browse to <code>http://localhost:5000</code></p>

<!-- ================================================================== -->
<h2 id="15">15. API &amp; URL Routing Reference</h2>
<!-- ================================================================== -->

<h3>15.1 Complete Route Reference</h3>
<table>
<tr><th>Route Pattern</th><th>Method</th><th>Handler Function</th><th>Description</th></tr>
<tr><td><code>?q=leds</code></td><td>GET</td><td>leds_show()</td><td>Display LED indicators</td></tr>
<tr><td><code>?q=leds/detail/&lt;name&gt;</code></td><td>GET</td><td>leds_detail()</td><td>LED detail view</td></tr>
<tr><td><code>?q=about</code></td><td>GET</td><td>leds_about()</td><td>About page</td></tr>
<tr><td><code>?q=login</code></td><td>GET</td><td>leds_login_form()</td><td>Login form</td></tr>
<tr><td><code>?q=login_validate</code></td><td>POST</td><td>leds_login_validate()</td><td>Process login</td></tr>
<tr><td><code>?q=logout</code></td><td>GET</td><td>leds_logout()</td><td>Logout</td></tr>
<tr><td><code>?q=config</code></td><td>GET</td><td>leds_config()</td><td>Configuration page</td></tr>
<tr><td><code>?q=trigger</code></td><td>GET</td><td>handle_trigger()</td><td>Broadcast trigger (JSON)</td></tr>
<tr><td><code>?q=ko_ajax</code></td><td>GET</td><td>ko_ajax()</td><td>AJAX handler</td></tr>
<tr><td><code>?q=ko_dragdrop</code></td><td>GET</td><td>ko_dragdrop()</td><td>Drag and drop interface</td></tr>
<tr><td><code>?q=ko_im</code></td><td>GET</td><td>ko_im()</td><td>Image manipulation</td></tr>
<tr><td><code>?q=grid?dbcode=&lt;db&gt;&amp;table=&lt;tbl&gt;</code></td><td>GET</td><td>pdo_grid()</td><td>Database grid view</td></tr>
<tr><td><code>?q=reports/sql</code></td><td>GET</td><td>leds_reports_sql()</td><td>SQL query interface</td></tr>
<tr><td><code>?q=reports/rpt/&lt;code&gt;</code></td><td>GET</td><td>leds_reports_rpt()</td><td>Run named report</td></tr>
<tr><td><code>?q=kb</code></td><td>GET</td><td>leds_kb()</td><td>KB listing</td></tr>
<tr><td><code>?q=kb/new</code></td><td>GET</td><td>koaac_kb_new_form()</td><td>New KB entry form</td></tr>
<tr><td><code>?q=kb/view/&lt;id&gt;</code></td><td>GET</td><td>leds_kb()</td><td>View KB entry</td></tr>
<tr><td><code>?q=certs</code></td><td>GET</td><td>leds_certs()</td><td>Certificate listing</td></tr>
<tr><td><code>?q=nodes</code></td><td>GET</td><td>leds_hosts()</td><td>Node listing</td></tr>
<tr><td><code>?q=hw</code></td><td>GET</td><td>leds_hw()</td><td>Hardware inventory</td></tr>
<tr><td><code>?q=hw?cab=&lt;cab&gt;</code></td><td>GET</td><td>leds_hw()</td><td>Hardware filtered by cabinet</td></tr>
<tr><td><code>?q=hw?sn=&lt;sn&gt;</code></td><td>GET</td><td>leds_hw()</td><td>Hardware filtered by serial number</td></tr>
<tr><td><code>?q=hw?ip=&lt;ip&gt;</code></td><td>GET</td><td>leds_hw()</td><td>Hardware filtered by IP</td></tr>
<tr><td><code>?q=hw?hrctag=&lt;tag&gt;</code></td><td>GET</td><td>leds_hw()</td><td>Hardware filtered by HRC tag</td></tr>
<tr><td><code>?q=plans</code></td><td>GET</td><td>leds_plans()</td><td>Plan listing</td></tr>
<tr><td><code>?q=sql</code></td><td>GET</td><td>sql_view()</td><td>SQL query interface</td></tr>
<tr><td><code>?q=zoom/&lt;code&gt;/&lt;type&gt;/&lt;rowid&gt;</code></td><td>GET</td><td>leds_zoom()</td><td>Zoom viewer</td></tr>
<tr><td><code>?q=zview/&lt;file&gt;/&lt;xml&gt;</code></td><td>GET</td><td>leds_zview()</td><td>Full-screen zoom view</td></tr>
<tr><td><code>?q=ptviewer</code></td><td>GET</td><td>leds_ptviewer()</td><td>Panorama viewer</td></tr>
<tr><td><code>?q=ptobject</code></td><td>GET</td><td>leds_ptobject()</td><td>Panorama object viewer</td></tr>
<tr><td><code>?q=scrub</code></td><td>GET</td><td>scrub_view()</td><td>Scrub/data cleanup</td></tr>
<tr><td><code>?q=upload</code></td><td>GET/POST</td><td>ko_upload2()</td><td>File upload</td></tr>
<tr><td><code>?q=pdo_cr_kb</code></td><td>GET</td><td>pdo_cr_kb()</td><td>Create KB table</td></tr>
<tr><td><code>?q=pdo_cr_leds</code></td><td>GET</td><td>pdo_cr_leds()</td><td>Create leds table</td></tr>
<tr><td><code>?q=pdo_insert_leds</code></td><td>GET</td><td>pdo_insert_leds()</td><td>Insert LED record</td></tr>
<tr><td><code>?q=pdo_list</code></td><td>GET</td><td>pdo_list()</td><td>List database tables</td></tr>
<tr><td><code>?q=pdo_unload?dbcode=&lt;db&gt;&amp;table=&lt;tbl&gt;</code></td><td>GET</td><td>pdo_unload()</td><td>Unload/export table</td></tr>
<tr><td><code>?q=pdo_update</code></td><td>GET</td><td>pdo_update()</td><td>Update table data</td></tr>
<tr><td><code>?q=pdo_load</code></td><td>GET</td><td>pdo_load()</td><td>Load table data</td></tr>
<tr><td><code>?q=pdo_gridxml?dbcode=&lt;db&gt;&amp;table=&lt;tbl&gt;</code></td><td>GET</td><td>pdo_gridxml()</td><td>Grid XML export</td></tr>
<tr><td><code>?q=dc_rpts</code></td><td>GET</td><td>leds_dc_rpts()</td><td>Datacenter reports</td></tr>
<tr><td><code>?q=kb_rpts</code></td><td>GET</td><td>leds_kb_rpts()</td><td>KB reports</td></tr>
<tr><td><code>?q=certs_rpts</code></td><td>GET</td><td>leds_certs_rpts()</td><td>Certificate reports</td></tr>
<tr><td><code>?q=cons_rpts</code></td><td>GET</td><td>leds_cons_rpts()</td><td>Console reports</td></tr>
<tr><td><code>?q=hosts_rpts</code></td><td>GET</td><td>leds_hosts_rpts()</td><td>Host reports</td></tr>
<tr><td><code>?q=ko_centerd_rpts</code></td><td>GET</td><td>leds_ko_centerd_rpts()</td><td>ko_centerd reports</td></tr>
<tr><td><code>?q=nodes_rpts</code></td><td>GET</td><td>leds_nodes_rpts()</td><td>Node reports</td></tr>
<tr><td><code>?q=form_request_access</code></td><td>GET</td><td>inline HTML</td><td>Access request form</td></tr>
<tr><td><code>?q=konet</code></td><td>GET</td><td>inline HTML</td><td>Contact information</td></tr>
<tr><td><code>?q=pdo</code></td><td>GET</td><td>inline HTML</td><td>Database table listing</td></tr>
<tr><td><code>?q=tools</code></td><td>GET</td><td>inline HTML</td><td>Tools page</td></tr>
<tr><td><code>?q=update/&lt;name&gt;</code></td><td>GET</td><td>leds_update_form()</td><td>LED update form</td></tr>
<tr><td><code>?q=iperms</code></td><td>GET</td><td>iperms()</td><td>System permissions utility</td></tr>
<tr><td><code>?q=iperms/periods_p</code></td><td>GET</td><td>iperms()</td><td>Run periods_p Perl script</td></tr>
<tr><td><code>?q=iperms/job2db/mkwl</code></td><td>GET</td><td>iperms()</td><td>Run mkwl job</td></tr>
<tr><td><code>?q=links</code></td><td>GET</td><td>html_links()</td><td>Links page</td></tr>
</table>

<h3>15.2 Trigger API</h3>
<p>The trigger endpoint provides a JSON API for browser refresh coordination across multiple clients:</p>

<h4>Request</h4>
<pre>GET /ko_center/ko_center.php?q=trigger[&amp;last_check=&lt;timestamp&gt;]</pre>

<h4>Response</h4>
<pre>{
  "triggered": true|false,
  "timestamp": "2026-08-01 07:05:00",
  "since": "2026-08-01 07:00:00"
}</pre>

<h4>Workflow</h4>
<ol>
  <li>Browser A polls <code>?q=trigger</code> every 3 seconds</li>
  <li>Browser B calls <code>?q=trigger</code> (writes timestamp to <code>ko_trigger.dat</code>)</li>
  <li>Browser A's next poll detects the new timestamp</li>
  <li>Browser A calls <code>window.location.reload()</code></li>
</ol>

<!-- ================================================================== -->
<h2 id="16">16. Version History</h2>
<!-- ================================================================== -->

<table>
<tr><th>Version</th><th>Date</th><th>Changes</th></tr>
<tr><td>v0.70</td><td>2026-08-01</td><td>Current: q=leds_context, ranks, randomus, actions</td></tr>
<tr><td>v0.67</td><td>2025-03-25</td><td>q=login debug</td></tr>
<tr><td>v0.66</td><td>2025-03-25</td><td>ERR_210 /etc/hosts.allow fix</td></tr>
<tr><td>v0.65</td><td>2020-10-14</td><td>fpbimg support</td></tr>
<tr><td>v0.64</td><td>2020-09-25</td><td>sql3_insert_hallo, sql3_select_hallo</td></tr>
<tr><td>v0.64</td><td>2020-09-23</td><td>Bug fixes, blank page fixes</td></tr>
<tr><td>v0.64</td><td>2019-08-27</td><td>leds_dragdrop support</td></tr>
<tr><td>v0.64</td><td>2012-12-10</td><td>leds_dragdrop initial</td></tr>
<tr><td>v0.64</td><td>2012-12-07</td><td>ko_ajax, ko_dragdrop, ko_im added</td></tr>
<tr><td>v0.64</td><td>2012-12-02</td><td>reports/rpts img, cab/cab1/cab2, leds/set/ledcode</td></tr>
<tr><td>v0.63</td><td>2012-12-02</td><td>reports/sql</td></tr>
<tr><td>v0.62</td><td>2012-12-02</td><td>reports/sql</td></tr>
<tr><td>v0.61</td><td>2012-11-09</td><td>defrag/report</td></tr>
<tr><td>v0.60</td><td>2012-10-27</td><td>passthru() support</td></tr>
<tr><td>v0.59</td><td>2012-10-27</td><td>hostos win logic</td></tr>
<tr><td>v0.57</td><td>2012-09-27</td><td>gui mods/allow</td></tr>
<tr><td>v0.56</td><td>2012-09-26</td><td>datacall support</td></tr>
<tr><td>v0.55</td><td>2012-09-18</td><td>ko_center_hosts.db3 datacall</td></tr>
<tr><td>v0.54</td><td>2012-09-18</td><td>ko_center_cons.db3</td></tr>
<tr><td>v0.53</td><td>2012-08-29</td><td>new /pat url, /nap</td></tr>
<tr><td>v0.52</td><td>2012-08-29</td><td>?q=kb/rpts/rpt_id&fmt=xml &amp; fmt=csv</td></tr>
<tr><td>v0.51</td><td>2012-08-28</td><td>rptsxml</td></tr>
<tr><td>v0.50</td><td>2012-08-28</td><td>jqgrid-4.4.0 integration</td></tr>
<tr><td>v0.49</td><td>2012-08-24</td><td>errtxt, fixtxt to files, fmt4search</td></tr>
<tr><td>v0.48</td><td>2012-08-24</td><td>ko_center.db3 nodes tables &amp; reports</td></tr>
<tr><td>v0.47</td><td>2012-08-23</td><td>ko_center_certs</td></tr>
<tr><td>v0.46</td><td>2012-08-23</td><td>kb upload size increase</td></tr>
<tr><td>v0.45</td><td>2012-08-22</td><td>ko_centerd rpts view grids</td></tr>
<tr><td>v0.44</td><td>2012-08-22</td><td>mod views</td></tr>
<tr><td>v0.43</td><td>2012-08-17</td><td>mod views</td></tr>
<tr><td>v0.42</td><td>2012-08-16</td><td>logins for led tweets</td></tr>
<tr><td>v0.41</td><td>2012-08-16</td><td>?q=certs/rpts</td></tr>
<tr><td>v0.40</td><td>2012-08-16</td><td>?q=kb/rpts</td></tr>
<tr><td>v0.39</td><td>2012-08-14</td><td>ko_center main page org</td></tr>
<tr><td>v0.38</td><td>2012-08-13</td><td>?q=kb/view kb/mod dbgrid links for kb certs</td></tr>
<tr><td>v0.37</td><td>2012-08-09</td><td>links reorg + certs</td></tr>
<tr><td>v0.36</td><td>2012-08-09</td><td>?q=kb</td></tr>
<tr><td>v0.35</td><td>2012-08-09</td><td>itil to links</td></tr>
<tr><td>v0.35</td><td>2012-08-08</td><td>ko_center_certs.dbe</td></tr>
<tr><td>v0.34</td><td>2012-08-03</td><td>dyn pchart example link &amp; debug</td></tr>
<tr><td>v0.33</td><td>2012-08-01</td><td>pchart link</td></tr>
<tr><td>v0.32</td><td>2012-07-30</td><td>pdo_cr_kb, pdo_cr_flds, new/add/mod/upd/view</td></tr>
<tr><td>v0.31</td><td>2012-07-30</td><td>pdo_cr_kb, pdo_cr_flds</td></tr>
<tr><td>v0.30</td><td>2012-07-27</td><td>pdo_cr_kb</td></tr>
<tr><td>v0.29</td><td>2012-07-27</td><td>newpass1 newpass2</td></tr>
<tr><td>v0.28</td><td>2012-07-27</td><td>user=hosts.allow[2]</td></tr>
<tr><td>v0.27</td><td>—</td><td>q=sql/cr/kb</td></tr>
<tr><td>v0.26</td><td>—</td><td>newpass1 newpass2</td></tr>
<tr><td>v0.25</td><td>—</td><td>user info from hosts.allow</td></tr>
<tr><td>v0.24</td><td>2012-07-20</td><td>session role check</td></tr>
<tr><td>v0.23</td><td>2012-07-20</td><td>es/hs,vg,bp/ ...</td></tr>
<tr><td>v0.22</td><td>2012-07-20</td><td>es/us/koSYS_us.php ko_center/us/koSYS_us.php</td></tr>
<tr><td>v0.21</td><td>2012-06-27</td><td>rename scrub update to scrub</td></tr>
<tr><td>v0.20</td><td>2012-06-19</td><td>korhe_us.db3</td></tr>
<tr><td>v0.19</td><td>2012-06-19</td><td>koaix_us.db3</td></tr>
<tr><td>v0.18</td><td>2012-06-18</td><td>add kb, bp tables</td></tr>
<tr><td>v0.17</td><td>2012-06-08</td><td>add kb, bp tables</td></tr>
<tr><td>v0.16</td><td>2012-06-05</td><td>add ko_center tables</td></tr>
<tr><td>v0.15</td><td>2012-06-01</td><td>add hs tables</td></tr>
<tr><td>v0.14</td><td>2012-05-31</td><td>add grid tables users us</td></tr>
<tr><td>v0.13</td><td>2012-05-31</td><td>$files=getfilko_center( $path, $mask )</td></tr>
<tr><td>v0.12</td><td>2012-05-31</td><td>gunzip scrubfile accommodation</td></tr>
<tr><td>v0.11</td><td>2012-05-31</td><td>add serena link</td></tr>
<tr><td>v0.10</td><td>2012-05-16</td><td>refresh to kohpx_vg.php kohpx_us.php kohpx_sw.php</td></tr>
<tr><td>v0.09</td><td>2012-04-25</td><td>db3 grid from /home/ko/vg/kohpx_vg.db3</td></tr>
<tr><td>v0.08</td><td>2012-03-13</td><td>q=links, sw reports pending</td></tr>
<tr><td>v0.07</td><td>2012-03-13</td><td>btn_footers</td></tr>
<tr><td>v0.06</td><td>2012-03-13</td><td>q=scrub consolidate upload examples</td></tr>
<tr><td>v0.05</td><td>2012-02-16</td><td>ko_upload scrub2</td></tr>
<tr><td>v0.04</td><td>2012-02-16</td><td>ko_upload scrub</td></tr>
<tr><td>v0.03</td><td>2012-02-07</td><td>Initial development</td></tr>
<tr><td>v0.02</td><td>2012-02-07</td><td>Initial version</td></tr>
<tr><td>v0.01</td><td>2012-02-05</td><td>First release</td></tr>
</table>

</body>
</html>
//


koh5_pano



Your browser does not support the HTML5 canvas element.


Drag mouse to navigate.

Navigation





17.Aug.2010, Martin Wengenmayer