r1202 + all options have moved into the database
authorDenis Ovsienko <infrastation@yandex.ru>
Sat, 13 Oct 2007 13:47:30 +0000 (13:47 +0000)
committerDenis Ovsienko <infrastation@yandex.ru>
Sat, 13 Oct 2007 13:47:30 +0000 (13:47 +0000)
+ render_rack_object.php minor speedup
+ flexible NAMEFUL_OBJTYPES replaces hardcoded TYPE_SERVER, TYPE_SWITCH and TYPE_ROUTER
+ docs update

13 files changed:
ChangeLog
INSTALL
TODO
inc/auth.php
inc/config.php
inc/database.php
inc/functions.php
inc/init.php
inc/interface.php
inc/navigation.php
index.php
logout.php
render_rack_thumb.php

index 61330f4..6c727a8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,6 +9,7 @@
        update: new stock values in dictionary chapters: server OS type,
                PortType, switch models
        update: make GigE default port type
+       update: configuration is now stored in the database
 0.14.5 2007-03-08
        bugfix: lots of adjustments to allow database be MySQL 4.0
 0.14.4 2007-02-21
diff --git a/INSTALL b/INSTALL
index 74fd82f..fa405af 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -14,7 +14,7 @@ II. Layout
 or http://racktables.mysite.org.
 2. Go into 'inc' directory, copy secret-sample.php to secret.php and modify accordingly.
 3. Edit install/init-auth.sql and change admin password
-4. Change $enterprise in inc/config.php
+4. [FIXME: this isn't true anymore] Change $enterprise in inc/config.php
 
 III. Database setup
 mysql> create database_name;
diff --git a/TODO b/TODO
index f4ccad5..8517efa 100644 (file)
--- a/TODO
+++ b/TODO
@@ -13,7 +13,7 @@
 - bug: can't view/click on remote side in port list, if remote side is nameless
 - bug: cannot update port 'e4/4', if port 'e 4/4' exists
 - use user ID instead of username where possible
-- eliminate default_port_type
++ eliminate default_port_type
 - keep all configuration variables in a single array
 - check words usage before deletion from a chapter
 - bug: search function is called 4 times per 1 search (see functions.php)
index e7b141f..1bdffd9 100644 (file)
@@ -14,7 +14,6 @@ function authenticate ()
                showError ('Password hash not supported, authentication impossible.');
                die();
        }
-       global $enterprise;
        if
        (
                !isset ($_SERVER['PHP_AUTH_USER']) or
@@ -22,7 +21,7 @@ function authenticate ()
                !authenticated ($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])
        )
        {
-               header ("WWW-Authenticate: Basic realm=\"${enterprise} RackTables access\"");
+               header ('WWW-Authenticate: Basic realm="' . getConfigVar ('enterprise') . ' RackTables access"');
                header ('HTTP/1.0 401 Unauthorized');
                showError ('This system requires authentication. You should use a username and a password.');
                die();
index e342e7c..9e74ac3 100644 (file)
@@ -1,89 +1,75 @@
 <?
 /*
-*
-*  This is RackTables public configuration file.
-*
-*/
-
-
-/* The following parameters/constants are necessary, although they are unlikely
- * to change (at least in the current release). They just have to be stored
- * somewhere and this is the place.
- */
-
-define ('VERSION', '0.14.6');
-
-// This is the name of hash used to store account password hashes in the database.
-define ('PASSWORD_HASH', 'sha1');
-$rtwidth[0] = 9;
-$rtwidth[1] = 21;
-$rtwidth[2] = 9;
-
-// Free atoms. They are available for allocation to objects.
-// They are not stored in the database.
-// HSV: 180-25-75
-$color['F'] = '8fbfbf';
-
-// Absent atoms.
-// HSV: 0-0-75
-$color['A'] = 'bfbfbf';
-
-// Unusable atoms. Some problems keep them to be 'F'.
-// HSV: 0-25-75
-$color['U'] = 'bf8f8f';
-
-// Taken atoms. object_id should be present then.
-// HSV: 180-50-50
-$color['T'] = '408080';
-
-// Taken atoms with highlight. They are not stored in the database and
-// are only used for highlighting.
-// HSV: 180-50-100
-$color['Th'] = '80ffff';
-
-// Taken atoms with object problem. This is detected at runtime.
-// HSV: 0-50-50
-$color['Tw'] = '804040';
-
-// An object can be both current and problematic. We run highlightObject() first
-// and markupObjectProblems() second.
-// HSV: 0-50-100
-$color['Thw'] = 'ff8080';
-
-$nextorder['odd'] = 'even';
-$nextorder['even'] = 'odd';
-
-
-
-/*******************************************************************************
- * The following parameters are likely to be changed by user, thus they
- * are listed below until we implement a configuration storage to move
- * them there.
+ *
+ * This file used to hold a collection of constants, variables and arrays,
+ * which drived the way misc RackTables functions performed. Now most of
+ * then have gone into the database, and there is perhaps a user interface
+ * for changing them. This file now provides a couple of functions to
+ * access the new config storage.
+ *
  */
 
-$enterprise = 'MyCompanyName';
 
-// Taken from the database, RJ-45/100Base-TX
-$default_port_type = 11;
+// Current code version is subject to change with each new release.
+define ('CODE_VERSION', '0.14.6');
 
-// Number of lines in object mass-adding form.
-define ('MASSCOUNT', 15);
-define ('MAXSELSIZE', 30);
-
-// These are the object types, which assume a common name to be normally
-// configured. If a name is absent for an object of one of such types,
-// HTML output is corrected to accent this misconfiguration.
-define ('NAMEFUL_OBJTYPES', '4,7,8');
-
-// Row-scope picture scale factor.
-define ('ROW_SCALE', 2);
-
-// Max switch port per one row on the switchvlans dynamic tab.
-define ('PORTS_PER_ROW', 12);
+// The name of hash used to store account password hashes
+// in the database. I think, we are happy with this one forever.
+define ('PASSWORD_HASH', 'sha1');
 
-/*******************************************************************************
- * And finally there are some things that we'd still like to see in the
- * configuration storage, but not changeable by user.
- */
+function getConfigVar ($varname = '')
+{
+       global $configCache;
+       // We assume the only point of cache init, and it is init.php. If it
+       // has failed, we don't retry loading.
+       if (!isset ($configCache))
+       {
+               showError ("Configuration cache is unavailable in getConfigVar()");
+               die;
+       }
+       if ($varname == '')
+       {
+               showError ("Missing argument to getConfigVar()");
+               die;
+       }
+       if (isset ($configCache[$varname]))
+       {
+               // Try casting to int, if possible.
+               if ($configCache[$varname]['vartype'] == 'unit')
+                       return 0 + $configCache[$varname]['varvalue'];
+               else
+                       return $configCache[$varname]['varvalue'];
+       }
+       return NULL;
+}
+
+function setConfigVar ($varname = '', $varvalue = '')
+{
+       global $configCache;
+       if (!isset ($configCache))
+       {
+               showError ('Configuration cache is unavailable in setConfigVar()');
+               die;
+       }
+       if (empty ($varname))
+       {
+               showError ("Empty argument to setConfigVar()");
+               die;
+       }
+       // We don't operate on unknown data.
+       if (!isset ($configCache[$varname]))
+       {
+               showError ("setConfigVar() doesn't know how to handle '${varname}'");
+               die;
+       }
+       if (empty ($varvalue) && $configCache[$varname]['emptyok'] != 'yes')
+       {
+               showError ("'${varname}' is configured to take non-empty value. Perhaps there was a reason to do so.");
+               die;
+       }
+       // Update cache only if the changes went into DB.
+       if (storeConfigVar ($varname, $varvalue))
+               $configCache[$varname]['varvalue'] = $varvalue;
+}
 
 ?>
index 80fcc32..a9a1815 100644 (file)
@@ -1799,4 +1799,45 @@ function useDeleteBlade ($tablename, $keyname, $keyvalue, $quotekey = TRUE)
                return TRUE;
 }
 
+function loadConfigCache ()
+{
+       global $dbxlink;
+       $query = 'select varname, varvalue, vartype, is_hidden, emptyok, description from Config';
+       $result = $dbxlink->query ($query);
+       if ($result == NULL)
+       {
+               $errorInfo = $dbxlink->errorInfo();
+               showError ("SQL query '${query}'\nwith message '${errorInfo[2]}'\nfailed in getAttrValues()");
+               return NULL;
+       }
+       $cache = array();
+       while ($row = $result->fetch (PDO::FETCH_ASSOC))
+               $cache[$row['varname']] = $row;
+       $result->closeCursor();
+       return $cache;
+}
+
+// setConfigVar() is expected to perform all necessary filtering
+function storeConfigVar ($varname = NULL, $varvalue = NULL)
+{
+       if ($varname == NULL || $varvalue == NULL)
+       {
+               showError ('Invalid arguments to storeConfigVar()');
+               return FALSE;
+       }
+       $query = "update Config set varvalue='${varvalue}' where varname='${varname}' limit 1";
+       $result = $dbxlink->query ($query);
+       if ($result == NULL)
+       {
+               showError ("SQL query '${query}' failed in storeConfigVar()");
+               return FALSE;
+       }
+       $rc = $result->rowCount();
+       $result->closeCursor();
+       if ($rc == 1)
+               return TRUE;
+       showError ("Something went wrong in storeConfigVar() when updatating '${varname}'");
+       return FALSE;
+}
+
 ?>
index 39da5ef..101b98a 100644 (file)
@@ -31,7 +31,7 @@ function displayedName ($objectData)
 {
        if ($objectData['name'] != '')
                return $objectData['name'];
-       elseif (in_array ($objectData['objtype_id'], explode (',', NAMEFUL_OBJTYPES)))
+       elseif (in_array ($objectData['objtype_id'], explode (',', getConfigVar ('NAMEFUL_OBJTYPES'))))
                return "ANONYMOUS " . $objectData['objtype_name'];
        else
                return "[${objectData['objtype_name']}]";
index f09a748..e6afefe 100644 (file)
@@ -71,6 +71,14 @@ authenticate();
 // Note that we don't perform autorization here, so each 1st level page
 // has to do it in its way, e.g. to call authorize().
 
+$configCache = loadConfigCache();
+if (!count ($configCache))
+{
+       showError ('Failed to load configuration from the database.');
+       die();
+}
+
+
 $remote_username = $_SERVER['PHP_AUTH_USER'];
 $pageno = (isset ($_REQUEST['page'])) ? $_REQUEST['page'] : 'index';
 $tabno = (isset ($_REQUEST['tab'])) ? $_REQUEST['tab'] : 'default';
index 1fb7057..a088a9a 100644 (file)
@@ -5,6 +5,10 @@
 *
 */
 
+// Interface function's special.
+$nextorder['odd'] = 'even';
+$nextorder['even'] = 'odd';
+
 // Main menu.
 function renderIndex ()
 {
@@ -60,8 +64,8 @@ function renderRackspace ()
 <?
        // generate thumb gallery
        $rackrowList = getRackRowInfo();
-       global $rtwidth, $root, $nextorder;
-       $rackwidth = $rtwidth[0] + $rtwidth[1] + $rtwidth[2];
+       global $root, $nextorder;
+       $rackwidth = getConfigVar ('rtwidth_0') + getConfigVar ('rtwidth_1') + getConfigVar ('rtwidth_2');
        $order = 'odd';
        foreach ($rackrowList as $rackrow)
        {
@@ -110,8 +114,8 @@ function renderRow ($row_id)
 
        echo "</td><td class=pcright>";
 
-       global $rtwidth, $root, $nextorder;
-       $rackwidth = $rtwidth[0] + $rtwidth[1] + $rtwidth[2];
+       global $root, $nextorder;
+       $rackwidth = getConfigVar ('rtwidth_0') + getConfigVar ('rtwidth_1') + getConfigVar ('rtwidth_2');
        $rackList = getRacksForRow ($row_id);
        $order = 'odd';
        startPortlet ('Racks');
@@ -119,8 +123,8 @@ function renderRow ($row_id)
        foreach ($rackList as $dummy => $rack)
        {
                echo "<td align=center class=row_${order}><a href='${root}?page=rack&rack_id=${rack['id']}'>";
-               echo "<img border=0 width=" . $rackwidth * ROW_SCALE . " height=";
-               echo (3 + 3 + $rack['height'] * 2) * ROW_SCALE;
+               echo "<img border=0 width=" . $rackwidth * getConfigVar ('ROW_SCALE') . " height=";
+               echo (3 + 3 + $rack['height'] * 2) * getConfigVar ('ROW_SCALE');
                echo " title='${rack['height']} units'";
                echo "src='render_rack_thumb.php?rack_id=${rack['id']}'>";
                echo "<br>${rack['name']}</a></td>";
@@ -612,12 +616,12 @@ function renderRackObject ($object_id = 0)
        echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
        if (!empty ($info['name']))
                echo "<tr><th width='50%' class=tdright>Common name:</th><td class=tdleft>${info['name']}</td></tr>\n";
-       elseif (in_array ($info['objtype_id'], explode (',', NAMEFUL_OBJTYPES)))
+       elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('NAMEFUL_OBJTYPES'))))
                echo "<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>\n";
        echo "<tr><th width='50%' class=tdright>Object type:</th><td class=tdleft>${info['objtype_name']}</td></tr>\n";
        if (!empty ($info['asset_no']))
                echo "<tr><th width='50%' class=tdright>Asset tag:</th><td class=tdleft>${info['asset_no']}</td></tr>\n";
-       elseif (in_array ($info['objtype_id'], explode (',', NAMEFUL_OBJTYPES)))
+       elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('NAMEFUL_OBJTYPES'))))
                echo "<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>\n";
        if (!empty ($info['label']))
                echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
@@ -848,7 +852,7 @@ function renderRackObject ($object_id = 0)
 
 function renderRackMultiSelect ($sname, $racks, $selected)
 {
-       echo "<select name=${sname} multiple size=" . MAXSELSIZE . " onchange='getElementById(\"racks\").submit()'>\n";
+       echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementById(\"racks\").submit()'>\n";
        foreach ($racks as $rack)
        {
                echo "<option value=${rack['id']}";
@@ -939,7 +943,7 @@ function renderPortsForObject ($object_id = 0)
        echo "<input type=hidden name=tab value='${tabno}'>\n";
        echo "<td><select name='port_type_id' tabindex=102>\n";
        $types = getPortTypes();
-       global $default_port_type;
+       $default_port_type = getConfigVar ('default_port_type');
        foreach ($types as $typeid => $typename)
        {
                echo "<option value='${typeid}'";
@@ -2009,7 +2013,8 @@ function renderAddMultipleObjectsForm ()
        if (isset ($_REQUEST['got_fast_data']))
        {
                $keepvalues = TRUE;
-               for ($i=0; $i < MASSCOUNT; $i++)
+               $max = getConfigVar ('MASSCOUNT');
+               for ($i = 0; $i < $max; $i++)
                {
                        if (!isset ($_REQUEST["${i}_object_type_id"]))
                        {
@@ -2086,7 +2091,8 @@ function renderAddMultipleObjectsForm ()
        echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th></tr>\n";
        // If a user forgot to select object type on input, we keep his
        // previous input in the form.
-       for ($i = 0; $i < MASSCOUNT; $i++)
+       $max = getConfigVar ('MASSCOUNT');
+       for ($i = 0; $i < $max; $i++)
        {
                echo '<tr><td>';
                printSelect ($typelist, "${i}_object_type_id", 0);
@@ -2131,7 +2137,7 @@ function printGreeting ()
 {
        global $remote_username, $accounts;
        $account = $accounts[$remote_username];
-       echo "Hello, ${account['user_realname']}. This is RackTables " . VERSION . ". Click <a href=logout.php>here</a> to logout.";
+       echo "Hello, ${account['user_realname']}. This is RackTables " . CODE_VERSION . ". Click <a href=logout.php>here</a> to logout.";
 }
 
 function renderSearchResults ()
@@ -2420,14 +2426,17 @@ function renderPermissionsEditForm ()
 
 function renderReadonlyParameters ()
 {
-       global $color, $default_port_type;
+       $default_port_type = getConfigVar ('default_port_type');
        startPortlet ('config.php');
        echo '<table border=0 align=center>';
-       echo "<tr><th class=tdright>version:</th><td class=tdleft>" . VERSION . "</td></tr>\n";
+       echo "<tr><th class=tdright>Code version:</th><td class=tdleft>" . CODE_VERSION . "</td></tr>\n";
        echo "<tr><th class=tdright>password hash:</th><td class=tdleft>" . PASSWORD_HASH . "</td></tr>\n";
        echo "<tr><th class=tdright>default port type:</th><td class=tdleft>${default_port_type}</td></tr>\n";
-       foreach ($color as $class => $value)
-               echo "<tr><th class=tdright bgcolor='#${value}'>color for class ${class}</th><td class=tdleft>${value}</td></tr>\n";
+       foreach (array ('F', 'A', 'U', 'T', 'Th', 'Tw', 'Thw') as $class)
+               echo
+                       "<tr><th class=tdright bgcolor='#" . getConfigVar ('color_' . $class) .
+                       "'>color for class ${class}</th><td class=tdleft>" .
+                       getConfigVar ('color_' . $class) . "</td></tr>\n";
        echo "</table>\n";
        finishPortlet();
 }
@@ -3083,14 +3092,15 @@ function renderVLANMembership ($object_id = 0)
        echo "<input type=hidden name=object_id value=${object_id}>";
        echo "<input type=hidden name=portcount value=" . count ($portlist) . ">\n";
        $portno = 0;
+       $ports_per_row = getConfigVar ('PORTS_PER_ROW');
        foreach ($portlist as $port)
        {
                // Don't let wide forms break our fancy pages.
-               if ($portno % PORTS_PER_ROW == 0)
+               if ($portno % $ports_per_row == 0)
                {
                        if ($portno > 0)
                                echo "</tr>\n";
-                       echo "<tr><th>" . ($portno + 1) . "-" . ($portno + PORTS_PER_ROW) . "</th>";
+                       echo "<tr><th>" . ($portno + 1) . "-" . ($portno + $ports_per_row) . "</th>";
                }
                echo '<td>' . $port['portname'] . '<br>';
                echo "<input type=hidden name=portname_${portno} value=" . $port['portname'] . '>';
@@ -3114,7 +3124,7 @@ function renderVLANMembership ($object_id = 0)
                $portno++;
                echo "</td>";
        }
-       echo "</tr><tr><td colspan=" . (PORTS_PER_ROW + 1) . "><input type=submit value='Save changes'></form></td></tr></table>";
+       echo "</tr><tr><td colspan=" . ($ports_per_row + 1) . "><input type=submit value='Save changes'></form></td></tr></table>";
        finishPortlet();
 
        echo '</td></tr></table>'; // -------------------------------------
index bbae69e..d0726dd 100644 (file)
@@ -224,9 +224,9 @@ function getPath ($targetno)
 
 function showPathAndSearch ($pageno)
 {
-       global $root, $page, $enterprise;
+       global $root, $page;
        // Path.
-       echo "<td class=activemenuitem width='99%'>${enterprise} RackTables";
+       echo "<td class=activemenuitem width='99%'>" . getConfigVar ('enterprise') . " RackTables";
        if (isset ($page[$pageno]['title']))
        {
                $path = getPath ($pageno);
@@ -250,15 +250,11 @@ function showPathAndSearch ($pageno)
 
 function getTitle ($pageno, $tabno)
 {
-       global $page, $enterprise;
-       if (isset ($page[$pageno]['title']))
-       {
-               $ret = $page[$pageno]['title']($pageno);
-               $ret = $ret['name'];
-       }
-       else
-               $ret = $enterprise;
-       return $ret;
+       global $page;
+       if (!isset ($page[$pageno]['title']))
+               return getConfigVar ('enterprise');
+       $tmp = $page[$pageno]['title']($pageno);
+       return $tmp['name'];
 }
 
 function showTabs ($pageno, $tabno)
index 566898e..18f9f58 100644 (file)
--- a/index.php
+++ b/index.php
@@ -10,11 +10,11 @@ echo "<link rel=stylesheet type='text/css' href=pi.css />\n";
 echo "<link rel=icon href='" . getFaviconURL() . "' type='image/x-icon' />";
 echo "<style type='text/css'>\n";
 // Print style information
-foreach ($color as $statecode => $colorcode)
+foreach (array ('F', 'A', 'U', 'T', 'Th', 'Tw', 'Thw') as $statecode)
 {
        echo "td.state_${statecode} {\n";
        echo "\ttext-align: center;\n";
-       echo "\tbackground-color: #${colorcode};\n";
+       echo "\tbackground-color: #" . (getConfigVar ('color_' . $statecode)) . ";\n";
        echo "\tfont: bold 10px Verdana, sans-serif;\n";
        echo "}\n\n";
 }
index 458712b..40bae1e 100644 (file)
@@ -1,7 +1,6 @@
 <?
 require 'inc/init.php';
-global $enterprise;
-header ("WWW-Authenticate: Basic realm=\"${enterprise} RackTables access\"");
+header ('WWW-Authenticate: Basic realm="' . getConfigVar ('enterprise') . ' RackTables access"');
 header ('HTTP/1.0 401 Unauthorized');
 showError ('You are now logged out.');
 ?>
index ac759c3..0a0003f 100644 (file)
@@ -22,12 +22,18 @@ function renderError ()
        imagedestroy ($img);
 }
 
+// Having a local caching array speeds things up. A little.
 function colorFromHex ($image, $hex)
 {
+       static $colorcache = array ();
+       if (isset ($colorcache[$hex]))
+               return $colorcache[$hex];
        $r = hexdec ('0x' . substr ($hex, 0, 2));
        $g = hexdec ('0x' . substr ($hex, 2, 2));
        $b = hexdec ('0x' . substr ($hex, 4, 2));
-       return imagecolorallocate ($image, $r, $g, $b);
+       $c = imagecolorallocate ($image, $r, $g, $b);
+       $colorcache[$hex] = $c;
+       return $c;
 }
 
 function renderRackThumb ($rack_id = 0)
@@ -38,7 +44,13 @@ function renderRackThumb ($rack_id = 0)
                return;
        }
        markupObjectProblems ($rackData);
-       global $rtwidth;
+       // Cache in a local array, because we are going to use those values often.
+       $rtwidth = array
+       (
+               0 => getConfigVar ('rtwidth_0'),
+               1 => getConfigVar ('rtwidth_1'),
+               2 => getConfigVar ('rtwidth_2')
+       );
        $offset[0] = 3;
        $offset[1] = 3 + $rtwidth[0];
        $offset[2] = 3 + $rtwidth[0] + $rtwidth[1];
@@ -46,7 +58,10 @@ function renderRackThumb ($rack_id = 0)
        $totalwidth = $offset[2] + $rtwidth[2] + 3;
        $img = @imagecreatetruecolor ($totalwidth, $totalheight)
                or die("Cannot Initialize new GD image stream");
-       global $color;
+       // cache our palette as well
+       $color = array();
+       foreach (array ('F', 'A', 'U', 'T', 'Th', 'Tw', 'Thw') as $statecode)
+               $color[$statecode] = getConfigVar ('color_' . $statecode);
        imagerectangle ($img, 0, 0, $totalwidth - 1, $totalheight - 1, colorFromHex ($img, '000000'));
        imagerectangle ($img, 1, 1, $totalwidth - 2, $totalheight - 2, colorFromHex ($img, 'c0c0c0'));
        imagerectangle ($img, 2, 2, $totalwidth - 3, $totalheight - 3, colorFromHex ($img, '000000'));