<?php

/*

Generalised database table editor.

Copyright © 2001 Nick Gammon.

  Author: Nick Gammon <nick@gammon.com.au>
  Web:    http://www.gammon.com.au/
  Date:   February 2001

  This program is free software; you can redistribute it and/or modify 
  it under the terms of the GNU General Public License as published by 
  the Free Software Foundation; either version 2 of the License, 
  or (at your option) any later version. 

  This program is distributed in the hope that it will be useful, 
  but WITHOUT ANY WARRANTY; without even the implied warranty of 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
  See the GNU General Public License for more details. 

  You should have received a copy of the GNU General Public License 
  along with this program; if not, write to 

  The Free Software Foundation, Inc., 
  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.


  The Free Software Foundation maintains a web page at: http://www.fsf.org

  See the file gpl.txt for the full GNU General Public License.

*/

require ("config.php");
require ($CONFIG_PATH . "general_config.php");
require ($INCLUDE_DIRECTORY . "common.php");

function CheckAccess ()
  {
  global $userid, $userinfo, $access, $table;
  
  Permission ("edittable");
  
  
  // now get their access levels for editing *this* table
  $userid = $userinfo ["userid"];
  $result = mysql_query ("SELECT * FROM access "
                       . "WHERE userid = $userid AND "
                       . "(tablename = '$table' OR tablename = '%')") 
    or Problem ("Select of access failed: " . mysql_error ());
  if (!$access = mysql_fetch_array ($result))
    Problem ("Permission denied for table '$table'");
  mysql_free_result ($result);  
  
  if (!$access ['can_select'])
    Problem ("Permission (select) denied");
  
  } // end of CheckAccess

function GetFieldNames ()
  {
  global $userid, $userinfo, $access, $table, 
         $field, $field_max_len, $field_type, $field_data,
         $metatable, $metarow;
  
  $result = mysql_query ("SHOW FIELDS FROM $table") 
      or Problem ("List fields failed: " . mysql_error ());
  
  // we'll put all that stuff into an array :) 
  while ($row = mysql_fetch_array ($result))
    $field [$row ['Field']] = $row;  
    
  mysql_free_result ($result);
  
  // get maximum lengths and types
  
  GetDatabaseName ($database);
  $result = mysql_list_fields ($database, $table)
      or Problem ("List fields (2) failed: " . mysql_error ());
  
  // get row data from mysql, and meta row data from database
   
  for ($i = 0; $i < mysql_num_fields ($result); $i++)
      {
      $name = mysql_field_name ($result, $i);
      $field_max_len [$name] = mysql_field_len ($result, $i);
      $field_type [$name] = mysql_field_type ($result, $i);
      // look for row metadata
      $metaresult = mysql_query ("SELECT * FROM metarow "
                           . "WHERE tablename = '$table' AND columnname = '$name'") 
        or Problem ("Select of metarow failed: " . mysql_error ());
      $metarow [$name] = mysql_fetch_array ($metaresult);
      mysql_free_result ($metaresult);  
      }

  mysql_free_result ($result);
  
  // get meta table data
  
  $metaresult = mysql_query ("SELECT * FROM metatable WHERE tablename = '$table'") 
       or Problem ("Select of metatable failed: " . mysql_error ());
  $metatable = mysql_fetch_array ($metaresult);
  mysql_free_result ($metaresult);  
  
  } // end of GetFieldNames

function GetPrimaryKey ()
  {
  global $userid, $userinfo, $access, $table, 
         $field, $field_max_len, $field_type, $field_data,
         $metatable, $metarow,
         $specials, $primary_key, $primary_key_name,
         $HTTP_GET_VARS;

  reset ($field);
  while (list ($name, $attr) = each ($field))
    if ($attr ['Key'] == "PRI")
      {
      $primary_key_name = $name;
      break;    // found it!
      } 
      
  if (!isset ($primary_key_name))
    Problem ("Cannot find the primary key");
  
  $specials [$primary_key_name] ['heading'] = true;

  // on searches the primary key is in the GET vars (ie. in the URL)  
  $primary_key = $HTTP_GET_VARS [$primary_key_name];
  
  } // end of GetPrimaryKey
  
function GetDisplayField ()
  {
  global $userid, $userinfo, $access, $table, 
         $field, $field_max_len, $field_type, $field_data,
         $metatable, $metarow,
         $specials, $primary_key, $primary_key_name,
         $display_field,
         $HTTP_GET_VARS;
  
  reset ($field);
  while (list ($name, $attr) = each ($field))
    if ($field_type [$name] == "string")
      {
      $display_field = $name;
      break;    // found it!
      } 
      
  if (!isset ($display_field))
    $display_field = $primary_key_name;
    
  
  }  // end of GetDisplayField 

  
function ValidateRecordNumber ()
  {
  global $userid, $userinfo, $access, $table, 
         $field, $field_max_len, $field_type,  $field_data,
         $metatable, $metarow,
         $specials, $primary_key, $primary_key_name,
         $display_field,
         $HTTP_GET_VARS, $HTTP_POST_VARS;

  // in this case the primary key is in the POST vars
  $primary_key = stripslashes ($HTTP_POST_VARS [$primary_key_name]);

  if (!strlen ($primary_key))   // nothing? oops
    Problem ("Primary key [$primary_key_name] not specified");

  // validate primary key
  $error = ValidateField ($primary_key, $field_type [$primary_key_name]);
    
  if ($error) 
    Problem ("Primary key [$primary_key_name] is invalid [$error]. You entered '"
             . htmlspecialchars ($primary_key) . "'"); 
  }  // end of  ValidateRecordNumber

function ValidateInputFields ()
  {
  global $userid, $userinfo, $access, $table, 
         $field, $field_max_len, $field_type, $field_data,
         $metatable, $metarow, $control,
         $specials, $primary_key, $primary_key_name,
         $display_field, $have_error,
         $HTTP_GET_VARS, $HTTP_POST_VARS;
  
  reset ($field);
  while (list ($name, $attr) = each ($field))
    {

    $error = "";
        
    // remove leading/trailing spaces
    $HTTP_POST_VARS [$name] = trim ($HTTP_POST_VARS [$name]);
    $value = stripslashes ($HTTP_POST_VARS [$name]); // get value
    $type = $field_type [$name];

    switch ($metarow [$name] ['displaytype'])
      {
      case 1: $type  = 'bool';  break;
      case 2: $type  = 'latitude';  break;
      case 3: $type  = 'longitude';  break;
    
      default:   // just use our default type
              break;
                
      } // end of switch
    
    
    // seed data array in case we redisplay this form
    $field_data [$name] = $value; 
    
    // special processing for latitude and longitude
    if ($type == 'latitude' || $type == 'longitude')
      {
      $deg = stripslashes ($HTTP_POST_VARS [$name . "_degrees"]);  
      $min = stripslashes ($HTTP_POST_VARS [$name . "_minutes"]);  
      $direction = trim ($HTTP_POST_VARS [$name . "_direction"]);
            
      if ($direction != 1 && $direction != -1)
        $error = "Latitude/longitude direction should be 1 or -1";  
      if (!$error)
        $error = ValidateField ($deg, 'int');
      if (!$error)
        $error = ValidateField ($min, 'float');
      if (!$error)
        {
        $value = ($deg + ($min / 60.0)) * $direction;
        $HTTP_POST_VARS [$name] = $value;  
        }     // end of converting back into degrees
           
      } // end of latitude/longitude

    // check for empty on NOT NULL fields
    if (!strlen ($value))
      {
        
      // auto_increment fields can be empty
      if (!strstr ($field [$name] ['Extra'], "auto_increment"))
        if ($attr ['Null'] != "YES")
          {
          $have_error = true;
          $specials [$name] ['error'] = "Field cannot be empty";
          }
        continue;   // enough validation, field is empty
      } // end of empty field
      
    // we will let them put "now" in a date or time field
    if (strtolower ($value) == "now")
      {
      switch ($type)
        {
        case "date": $value = strftime ("%Y-%m-%d", utctime()); break;
        case "datetime": $value = strftime ("%Y-%m-%d %H:%M:%S", utctime()); break;
        case "time": $value = strftime ("%H:%M:%S", utctime()); break;
        } // end of switch on type
      $HTTP_POST_VARS [$name] = $value;  
      } // end of word "now" in value
     
    if ($control ['extended_dates'])
      {
      switch ($type)
        {
        case "date": $error = DoExtendedDate ($value); break;
        case "datetime": $error = DoExtendedDateTime ($value); break;
        case "time": $error = DoExtendedTime ($value); break;
        } // end of switch on type
      $HTTP_POST_VARS [$name] = $value;  
      }  
     
    // passwords are entered by preceding with a "=" sign
    if (!$error)
      if ($metarow [$name] ['password'] && $value [0] == "=")
        {
        $value = md5 (trim (substr ($value, 1)));
        $HTTP_POST_VARS [$name] = $value;  
        }   // end of password
            
    // validate fields  

    if (!$error)
      $error = ValidateField ($value, $type);
    
    // ValidateField sets $error if there is an error      
    if (!$error)
      {
      $fktable = $metarow [$name] ['fktable'];
      $fkcolumn = $metarow [$name] ['fkcolumn'];
      
      // if we have a foreign key, check we are using a valid one
      if ($fktable)
        {
        
        $result = mysql_query ("SELECT $fkcolumn FROM $fktable WHERE $fkcolumn = '$value'")
                or Problem ("Select of foreign key table failed: " . mysql_error ());
        $row = mysql_fetch_array ($result);
        mysql_free_result ($result);  
        
        if (!$row)
          $error = "Related record does not exist in table '$fktable'";
          
        } // end of having a foreign key
      
      } // end of no error on field validation

      
    // now do user-specified validation - may set $error
    if (!$error)
      eval ($metarow [$name] ['validation']);

    if ($error)
      {
      $have_error = true;
      $specials [$name] ['error'] = $error;
      }
      
    } // end of checking each field

  } // end of ValidateInputFields
  
function AddRecord ()
  {
  global $userid, $userinfo, $access, $table, 
         $field, $field_max_len, $field_type, $field_data,
         $metatable, $metarow, $simple,
         $specials, $primary_key, $primary_key_name,
         $display_field, $have_error,
         $HTTP_GET_VARS, $HTTP_POST_VARS;

  if (!$simple)
    echo "<h1>Insert new record into '$table'</h1>\n";

  if (!$access ['can_insert'])
    Problem ("Permission to insert denied");

  $fieldnamelist = "";
  $valueslist = "";
  reset ($field);
  while (list ($name, $attr) = each ($field))
    {
    if (strstr ($field [$name] ['Extra'], "auto_increment"))
      continue;   // can't change auto_increment fields
            
    if (!empty ($fieldnamelist))
      {
      $fieldnamelist .= ", ";
      $valueslist .= ", ";
      }
    $fieldnamelist .= $name;
    $value = stripslashes ($HTTP_POST_VARS [$name]);
    if (!strlen ($value))
      $valueslist .= "NULL";
    else
      $valueslist .= "'" . addslashes ($value) . "'";
    }
    
   $query = "INSERT INTO $table ($fieldnamelist) VALUES ($valueslist)";
         
//      echo $query . "<br>";         
         
  $result = mysql_query ($query) 
      or Problem ("Insert failed: " . mysql_error ());
  
  if (mysql_affected_rows () == 0)
    Problem ("Could not insert record");
  else
    echo ("<p><b>Record inserted.</b></p>");
         
  // now find primary_key so we can re-read it
  if (strstr ($field [$primary_key_name] ['Extra'], "auto_increment"))
    $primary_key = mysql_insert_id ();
  else
    $primary_key = stripslashes ($HTTP_POST_VARS [$primary_key_name]);

  } // end of AddRecord
  
function ChangeRecord ()
  {
  global $userid, $userinfo, $access, $table, 
         $field, $field_max_len, $field_type,  $field_data,
         $metatable, $metarow, $simple,
         $specials, $primary_key, $primary_key_name,
         $display_field, $have_error,
         $HTTP_GET_VARS, $HTTP_POST_VARS;

  if (!$simple)
    echo "<h1>Amend record #" . htmlspecialchars ($primary_key) . " in '$table'</h1>\n";

  if (!$access ['can_update'])
    Problem ("Permission to change denied");

  $valueslist = "";
  reset ($field);
  while (list ($name, $attr) = each ($field))
    {
    if ($name == $primary_key_name)
      continue;   // can't modify primary key
    if (!empty ($valueslist))
      $valueslist .= ", ";
    $valueslist .= $name . " = ";
    $value = stripslashes ($HTTP_POST_VARS [$name]);
    if (!strlen ($value))
      $valueslist .= "NULL";
    else
      $valueslist .= "'" . addslashes ($value) . "'";
    }
  
  $query = "UPDATE $table SET $valueslist "
         . "WHERE $primary_key_name = '$primary_key'";
         
//      echo $query . "<br>";         
          
  $result = mysql_query ($query) 
      or Problem ("Update failed: " . mysql_error ());

  if (mysql_affected_rows () == 0)
    echo ("<p><b>Change did not affect any rows.</b></p>");
  else
    echo ("<p><b>Database updated.</b></p>");
    
  
  } // end of ChangeRecord
  
function DeleteRecord ()
  {
  global $userid, $userinfo, $access, $table, 
         $field, $field_max_len, $field_type,  $field_data,
         $metatable, $metarow, $simple,
         $specials, $primary_key, $primary_key_name,
         $display_field, $have_error,
         $HTTP_GET_VARS, $HTTP_POST_VARS;
         
  if (!$simple)
    echo "<h1>Delete record #" . htmlspecialchars ($primary_key) . " from '$table'</h1>\n";

  if (!$access ['can_delete'])
    Problem ("Permission to delete denied");

  // get record to be deleted (for foreign key checks)
  
  $result = mysql_query ("SELECT * from $table WHERE $primary_key_name = '$primary_key'") 
      or Problem ("Select of record to be deleted failed: " . mysql_error ());
  if (!$existingrow = mysql_fetch_array ($result))
    Problem ("Record $primary_key is not on file");
  mysql_free_result ($result);  
  
  // don't delete records that use this one
  $fkresult = mysql_query ("SELECT * FROM metarow WHERE fktable = '$table' "
                         . "AND fkcolumn IS NOT NULL "
                         . "AND fkdescription IS NOT NULL "
                          ) 
    or Problem ("Select of metarow failed: " . mysql_error ());
  $error = "";
  // for each entry, check we are not deleting one we use
  while (($fkrow = mysql_fetch_array ($fkresult)) && !$error)
    {
    $tabletocheck = $fkrow ['tablename'];
    $columntocheck = $fkrow ['columnname'];
    $valuetocheck = $existingrow [$fkrow ['fkcolumn']];
    $query = "SELECT * from $tabletocheck "
           . "WHERE $columntocheck = '$valuetocheck' LIMIT 1";
    $result = mysql_query ($query)
      or Problem ("Select of target table failed: " . mysql_error ());
    $targetrow = mysql_fetch_array ($result);
    mysql_free_result ($result);  
    if ($targetrow)
      $error = "Related record exists in table '$tabletocheck'";
    } // end of checking each row in the meta table
  
  mysql_free_result ($fkresult);  

  if ($error)
    Problem ($error);
  
  $query = "DELETE FROM $table "
         . "WHERE $primary_key_name = '$primary_key'";
  $result = mysql_query ($query) 
      or Problem ("Delete failed: " . mysql_error ());

  if (mysql_affected_rows () == 0)
    echo ("<p><b>No record was deleted.</b></p>");
  else
    echo ("<p><b>Record deleted.</b></p>");
    
  $primary_key = "";
  reset ($field);
  while (list ($name, $row) = each ($field))
    $field_data [$name] = "";
  
  } // end of DeleteRecord
  
function SearchRecord ()
  {
  global $userid, $userinfo, $access, $table, 
         $field, $field_max_len, $field_type,  $field_data,
         $metatable, $metarow,
         $specials, $primary_key, $primary_key_name,
         $display_field, $have_error,
         $searchfield,  $searchvalue,
         $HTTP_GET_VARS, $HTTP_POST_VARS;
  
  echo "<h1>Search for record in '$table'</h1>\n";
  $primary_key = "";

  $searchfield = trim (str_replace (";", " ", $searchfield));
  $searchvalue = trim (str_replace (";", " ", $searchvalue));

  if (!$searchfield)
    Problem ("No field to search on has been specified");
   
  $type = $field_type [$searchfield];
  
  if (!$type)
    Problem ("Search field '$searchfield' does not exist");
  
  if (!$searchvalue)
    {
    ShowError ("No search value specified, use NULL to search for empty fields");
    return;
    }

  if (strtolower ($searchvalue) == "null")
    $where = "WHERE $searchfield IS NULL";
  else 
   if (strtolower ($searchvalue) == "not null")
    $where = "WHERE $searchfield IS NOT NULL";
  else 
    {
    
    // validate search data
    $error = ValidateField ($searchvalue, $type);
      
    if ($error) 
      {
      ShowError ("Search data for '$searchfield' is invalid: $error");
      return;
      } // end of error in searchfield
      
    if ($field_type [$searchfield] == "string" ||
        $field_type [$searchfield] == "blob" )
      $where = "WHERE $searchfield LIKE '%$searchvalue%'";
    else
      $where = "WHERE $searchfield = '$searchvalue'";
    }   // end of not searching for NULL
    
  // what fields to show in the list?
  if (!($summary = $metatable ['summaryfields']))
    {
    // don't display primary key twice
    if ($display_field != $primary_key_name)
      $summary = "$display_field, ' [', $primary_key_name, ']'";
    else
      $summary = "$display_field";
    } // end of no user-specified summary field
  // what order to show them in?
  if (!($order = $metatable ['summaryorder']))
    $order = "$display_field";
    
  $query = "SELECT $primary_key_name, "
         . "CONCAT($summary) AS _summary "
         . "FROM $table $where ORDER BY $order LIMIT 100";

//      echo $query . "<br>";         

// show comments before a list here

  eval ($metatable ['beforelist']);
  
  ShowList ($query, 
            $primary_key_name, 
            "&table=$table&searchfield=$searchfield&searchvalue=" .
            stripslashes ($searchvalue),
            "_summary");

  echo ("<p><b>Search limited to maximum of 100 records.</b></p>");
  
  } // end of SearchRecord
  
function ListRecord ()
  {
  global $userid, $userinfo, $access, $table, 
         $field, $field_max_len, $field_type,  $field_data,
         $metatable, $metarow,
         $specials, $primary_key, $primary_key_name,
         $display_field, $have_error,
         $HTTP_GET_VARS, $HTTP_POST_VARS;

  echo "<h1>List all records in '$table'</h1>\n";
 
  // warn them of the WHERE clause
  if ($metatable ['whereclause'])
    {
    echo "<p><b>WHERE " . htmlspecialchars ($metatable ['whereclause']) . "</b></p>\n";
    $where = "WHERE " . $metatable ['whereclause'];
  }
  else
    $where = "";
    
  // what fields to show in the list?
  if (!($summary = $metatable ['summaryfields']))
    {
    // don't display primary key twice
    if ($display_field != $primary_key_name)
      $summary = "$display_field, ' [', $primary_key_name, ']'";
    else
      $summary = "$display_field";
     } // end of no user-specified summary field
  // what order to show them in?
  if (!($order = $metatable ['summaryorder']))
    $order = "$display_field";
  
  $query = "SELECT $primary_key_name, "
         . "CONCAT($summary) AS _summary "
         . "FROM $table "
         . "$where "
         . "ORDER BY $order LIMIT 100";

  // show comments before a list here
  
  eval ($metatable ['beforelist']);

  ShowList ($query, 
            $primary_key_name, 
            "&table=$table",
            "_summary");

  echo ("<p><b>List limited to maximum of 100 records.</b></p>");

  $primary_key = "";

  } // end of ListRecord
  
function NewRecord ()
  {
  global $userid, $userinfo, $access, $table, 
         $field, $field_max_len, $field_type,  $field_data,
         $metatable, $metarow, $simple, $desc,
         $specials, $primary_key, $primary_key_name,
         $display_field, $have_error,
         $HTTP_GET_VARS, $HTTP_POST_VARS;

  if ($simple)
    {
    if ($desc)  
      echo "<h1>" . htmlspecialchars ($desc) . "</h1>\n";
    } // end of simple
  else
    echo "<h1>New record in '$table'</h1>\n";
    
  $primary_key = "";
  reset ($field);
  while (list ($name, $attr) = each ($field))
    {
       
    if (strstr ($field [$name] ['Extra'], "auto_increment"))
      $field_data [$name] = "(auto)";
    else
      $field_data [$name] = $HTTP_GET_VARS [$name];   // initial values might be supplied in URL
      
    if ($attr ['Null'] != "YES")
      $specials [$name] ['error'] = "*";    // hint this needs completing
    }
  echo ("<p><b>Fields marked \"*\" are required.<br>"
        . "Press the &quot;Add&quot; button to add this record.</b></p>");

  } // end of NewRecord

function DuplicateRecord ()
  {
  global $userid, $userinfo, $access, $table, 
         $field, $field_max_len, $field_type,  $field_data,
         $metatable, $metarow, $simple, $desc,
         $specials, $primary_key, $primary_key_name,
         $display_field, $have_error,
         $HTTP_GET_VARS, $HTTP_POST_VARS;

  if ($simple)
    {
    if ($desc)  
      echo "<h1>" . htmlspecialchars ($desc) . "</h1>\n";
    } // end of simple
  else
    echo "<h1>Duplicate record in '$table'</h1>\n";
                                                                        
  // in this case the primary key is in the POST vars      
  $primary_key = stripslashes ($HTTP_POST_VARS [$primary_key_name]);      
             
  reset ($field);
  while (list ($name, $attr) = each ($field))
    {
       
    if (strstr ($field [$name] ['Extra'], "auto_increment"))
      $field_data [$name] = "(auto)";
      
    if ($attr ['Null'] != "YES")
      $specials [$name] ['error'] = "*";    // hint this needs completing
    }
  echo ("<p><b>Fields marked \"*\" are required.<br>"
        . "Press the &quot;Add&quot; button to add this record.</b></p>");

} // end of DuplicateRecord
  
function ReadRecord ()
  {
  global $userid, $userinfo, $access, $table, 
         $field, $field_max_len, $field_type,  $field_data,
         $metatable, $metarow,
         $specials, $primary_key, $primary_key_name,
         $display_field, $have_error,
         $HTTP_GET_VARS, $HTTP_POST_VARS;

  $query = "SELECT * "
         . "FROM $table "
         . "WHERE $primary_key_name = '$primary_key'";
                        
  $result = mysql_query ($query) 
      or Problem ("Select failed: " . mysql_error ());
  
  if (!($row = mysql_fetch_array ($result)))
    Problem ("Record $primary_key is not on file");
  
  reset ($field);
  while (list ($name, $attr) = each ($field))
    $field_data [$name] = $row [$name];
  
  mysql_free_result ($result);
  
  } // end of ReadRecord    

function ShowRecord ()
  {
  global $userid, $userinfo, $access, $table, 
         $field, $field_max_len, $field_type,  $field_data,
         $metatable, $metarow, $simple, $control,
         $specials, $primary_key, $primary_key_name,
         $display_field, $have_error, $action,
         $HTTP_GET_VARS, $HTTP_POST_VARS;

  // show comments before a form here
  
  eval ($metatable ['beforeform']);
  
  $params = array
    (
    'LH' => 'valign=top bgcolor="#ADD8E6" align=right',
    'RH' => 'bgcolor="#FAF0E6" align=left'
    );
  
  // do the specials
 
  reset ($field);
  while (list ($name, $attr) = each ($field))
    {
    
    // can't edit primary key unless adding
    if ($name == $primary_key_name &&     // check primary key
        $action != "new" &&               // must enter on a new
        $action != "duplicate" &&         // or duplicate
        !($action == "add" && $have_error))   // or an erroneous add
        continue;

    // can't edit auto_increment fields anyway      
    if (strstr ($field [$name] ['Extra'], "auto_increment"))
        continue; 
               
    $type = $field_type [$name];        

    $specials [$name] ['input'] = $name;    // field name for posting modification
    $specials [$name] ['maxlength'] = $field_max_len [$name];
    
    if ($control ['extended_dates'])
      $extra_size = 7;  // need to allow for "14 september 2002";
    else
      $extra_size = 0;
    
    if ($type == 'date')
      $specials [$name] ['maxlength'] = 11 + $extra_size;  // dates allow for 2002-15-02 - Netscape seems to need one more
    else if ($type == 'time')
      $specials [$name] ['maxlength'] = 9;  // dates allow for 23:55:55 - Netscape seems to need one more
    else if ($type == 'datetime')
      $specials [$name] ['maxlength'] = 20 + $extra_size;  // datetime
      
      
    $specials [$name] ['size'] = min (80, $specials [$name] ['maxlength']);
    if ($field_type [$name] == "blob")  // text and blobs are multiline fields
      $specials [$name] ['type']  = 'multiline';
    $specials [$name] ['cols'] = 80;  // for multiline
    $specials [$name] ['rows'] = 20;  // ditto
    $specials [$name] ['comment'] = $metarow [$name] ['comment'];
    
    $fktable = $metarow [$name] ['fktable'];

    // use override field description, if supplied 
    $specials [$name] ['description'] = $metarow [$name] ['label'];
      
    if ($metarow [$name] ['cols'])
      $specials [$name] ['cols'] = $metarow [$name] ['cols'];  // override columns
    if ($metarow [$name] ['rows'])
      $specials [$name] ['rows'] = $metarow [$name] ['rows'];  // override rows
    if ($metarow [$name] ['size'])
      $specials [$name] ['size'] = $metarow [$name] ['size'];  // override field size
      
    // they might override the display method 
    
    switch ($metarow [$name] ['displaytype'])
      {
      case 1: $specials [$name] ['type']  = 'bool';  break;
      case 2: $specials [$name] ['type']  = 'latitude';  break;
      case 3: $specials [$name] ['type']  = 'longitude';  break;
      case 4: $specials [$name] ['type']  = 'multiline';  break;
    
      default:   // just use our default type
              break;
                
      } // end of switch
    
    // if foreign key, make combo box
    if ($fktable)
      {
      // combo box with values from target table
      $specials [$name] ['type'] = 'combo';
  
      $fkcolumn = $metarow [$name] ['fkcolumn'];
      $fkdescription = $metarow [$name] ['fkdescription'];
  
      $result = mysql_query ("SELECT $fkcolumn, $fkdescription FROM $fktable "
                           . "ORDER BY $fkdescription") 
        or Problem ("Select of foreign key data failed: " . mysql_error ());
  
      while ($row = mysql_fetch_array ($result))
        $specials [$name] ['values'] [$row [$fkcolumn]] = $row [$fkdescription];  
  
      mysql_free_result ($result);  
      } // end of foreign key
    } // end of doing each field

  // don't show the primary key  
  if ($simple && strstr ($field [$primary_key_name] ['Extra'], "auto_increment"))
    unset ($field_data [$primary_key_name]);
  
  // now show the table 
  ShowTable ($field_data, $params, $specials);
  
  } // end of ShowRecord

function ShowButtons ()
  {
  global $userid, $userinfo, $access, $table, 
         $field, $field_max_len, $field_type,  $field_data,
         $metatable, $metarow, $simple,
         $specials, $primary_key, $primary_key_name,
         $display_field, $have_error,
         $searchfield,  $searchvalue, $action,
         $HTTP_GET_VARS, $HTTP_POST_VARS;
  
if (!$simple)
  {  
  ?>
  
  <p>
  <p>Search: &nbsp;
  <?php
  echo "<select name=searchfield size=1>\n";
  reset ($field);
  while (list ($name, $attr) = each ($field))
    {
    echo "<option value=\"$name\" ";
    if ($name == $searchfield)
      echo "selected ";
    echo ">$name\n";
    } // end of each item
  echo "</select>\n";
  ?>
  &nbsp; for match on: &nbsp;
  <input type=text name=searchvalue size=30 maxlength=255 value="<?php 
        echo stripslashes (($searchvalue)); 
  ?>">
  <input Type=submit Name=search Value="Search"> &nbsp;
  <input Type=submit Name=list Value="List All"> &nbsp;
  </p>
  <?php  
}   // end of not simple

echo "<p>";

if ($access ['can_insert'] && $action != "new")
  echo "<input Type=submit Name=new Value=\"New\"> &nbsp;\n";

// we can only add if we started with a blank record, or a faulty add

if (
		(!strlen ($primary_key) && 
	    ($action == "new" ||
	    ($action == "add" && $have_error))
	   )
    || ( 
        strlen ($primary_key) &&  
        $action == "duplicate" 
        )
   )
  {
  if ($access ['can_insert'])
    echo "<input Type=submit Name=add Value=\"Add\"> &nbsp;\n";
  }  // end of no primary key
  
// we can only change or delete if we have a key to do it to
  
if (strlen ($primary_key) && $action != "duplicate")
  {
  if ($access ['can_update'])
    echo "<input Type=submit Name=amend Value=\"Change\"> &nbsp;\n";
  if ($access ['can_delete'])
    echo "<input Type=submit Name=delete Value=\"Delete\"> &nbsp;\n";
  if ($access ['can_insert'])
    echo "<input Type=submit Name=duplicate Value=\"Duplicate\"> &nbsp;\n";

  // put primary key into form as a hidden field for updating or deleting purposes
  echo "<input type=hidden name=$primary_key_name value=\"$primary_key\">\n";

  }  // end of having primary key

// <-- how useful is reset really? --> echo "<input Type=reset> &nbsp;";

?></p>

<input type=hidden name=table value=<?php echo ($table); ?>>
<?php FormSession (); ?>

<?php  
  
  } // end of ShowButtons      

// ---------------- start of main section -------------------


if (empty ($table))
  MajorProblem ("Table name not specified");
    
Init ("Table maintenance - $table", "maintenance"); 

// make sure some fields are empty

unset ($primary_key);
unset ($specials);
unset ($have_error);
unset ($display_field);
unset ($metarow);

// check some turkey isn't running my web page

CheckAccess ();  

// get field names, types, lengths from database,
// get metadata from metarow, metatable tables

GetFieldNames ();
    
// Now, what is the primary key?
 
GetPrimaryKey ();
  
// Find a displayable field for summaries

GetDisplayField ();

if ($add)
  $action = "add";
else if ($amend)
  $action = "amend";
else if ($delete)
  $action = "delete";
else if ($search)
  $action = "search";
else if ($list)
  $action = "list";
else if ($new)
  $action = "new";
else if ($duplicate)
  $action = "duplicate";
else
  $action = "";


/*

// debugging

 DebugVars ();

 ShowArray ("field", $field);
 ShowArray ("field_max_len", $field_max_len);
 ShowArray ("field_type", $field_type);

*/

// do form preamble now

eval ($metatable ['preamble']);
  
// validate record number except on add, duplicate, search, list or new

if ($action != "add" && 
    $action != "search" && 
    $action != "list" && 
    $action != "new" && 
    $action != "duplicate" && 
    !empty ($action))
  ValidateRecordNumber ();

// validate fields on an add or amend
if ($action == "add" || 
    $action == "amend")
  ValidateInputFields ();
     
// process various actions
     
if ($have_error)   // skip add/change if validation error
  ShowError (sprintf ("%s not done", ucwords ($action)));
else
  switch ($action)
    {  
    case "add":     AddRecord (); break;
    case "amend":   ChangeRecord (); break;
    case "delete":  DeleteRecord (); break;
    case "search":  SearchRecord (); break; 
    case "list":    ListRecord (); break;    
    case "new":   NewRecord (); break;              
    case "duplicate":   DuplicateRecord (); break;              
    default:
       if ($simple)
         {
         if ($desc)
           echo "<h1>" . htmlspecialchars ($desc) . "</h1>\n";
         }
       else
        echo "<h1>Table maintenance - '$table'</h1>\n";
       break;
  
  } // end of switch on action

// lookup record
 
if (strlen ($primary_key) && !$have_error)
  ReadRecord ();

echo "<form METHOD=post ACTION=\"$PHP_SELF\">";

// when doing a search, or after a delete, don't display the record 
if (($action || strlen ($primary_key)) 
    && $action != "search" 
    && $action != "list"
    && $action != "delete")  
    ShowRecord ();

// show add/change/delete buttons, as appropriate

ShowButtons ();

echo "<input type=hidden name=simple value=\"$simple\">\n";
 
echo "</form>\n";

// do form postamble now
eval ($metatable ['postamble']);
    
    
if (!$simple)
  {
  echo "<hr><p>";
  ShowTablesToEdit ();
  
  if ($userinfo ['executesql'])
    hLink ("Execute SQL command", "executesql.php");
  
  echo "</p>";
  } // end of not simple 

MessageTail (false);
?>
    
