GAzie PHP Cross Reference Customer Relationship Management

Source: /modules/gazpme/phpMyEdit.class.php - 3396 lines - 152376 bytes - Summary - Text - Print

   1  <?php
   2  
   3  /*

   4   * phpMyEdit - instant MySQL table editor and code generator

   5   *

   6   * phpMyEdit.class.php - main table editor class definition file

   7   * ____________________________________________________________

   8   *

   9   * Copyright (c) 1999-2002 John McCreesh <jpmcc@users.sourceforge.net>

  10   * Copyright (c) 2001-2002 Jim Kraai <jkraai@users.sourceforge.net>

  11   * Versions 5.0 and higher developed by Ondrej Jombik <nepto@php.net>

  12   * Copyright (c) 2002-2006 Platon Group, http://platon.sk/

  13   * All rights reserved.

  14   *

  15   * See README file for more information about this software.

  16   * See COPYING file for license information.

  17   *

  18   * Download the latest version from

  19   * http://platon.sk/projects/phpMyEdit/

  20   */
  21  
  22  /* $Platon: phpMyEdit/phpMyEdit.class.php,v 1.204 2007-09-16 12:57:07 nepto Exp $ */

  23  
  24  /*  This is a generic table editing program. The table and fields to be

  25      edited are defined in the calling program.

  26  

  27      This program works in three passes.

  28      * Pass 1 (the last part of the program) displays the selected SQL

  29        table in a scrolling table on the screen. Radio buttons are used to

  30        select a record for editing or deletion. If the user chooses Add,

  31        Change, Copy, View or Delete buttons.

  32      * Pass 2 starts, displaying the selected record. If the user chooses

  33        the Save button from this screen.

  34      * Pass 3 processes the update and the display returns to the

  35        original table view (Pass 1).

  36  */
  37  
  38  class phpMyEdit_timer /* {{{ */
  39  {
  40      var $startTime;
  41      var $started;
  42  
  43      function phpMyEdit_timer($start = true)
  44      {
  45          $this->started = false;
  46          if ($start) {
  47              $this->start();
  48          }
  49      }
  50  
  51      function start()
  52      {
  53          $startMtime      = explode(' ', microtime());
  54          $this->startTime = (double) $startMtime[0] + (double) $startMtime[1];
  55          $this->started   = true;
  56      }
  57  
  58      function end($iterations = 1)
  59      {
  60          // get the time, check whether the timer was started later

  61          $endMtime = explode(' ', microtime());
  62          if ($this->started) {
  63              $endTime = (double)($endMtime[0])+(double)($endMtime[1]);
  64              $dur = $endTime - $this->startTime;
  65              $avg = 1000 * $dur / $iterations;
  66              $avg = round(1000 * $avg) / 1000;
  67              return $avg;
  68          } else {
  69              return 'phpMyEdit_timer ERROR: timer not started';
  70          }
  71      }
  72  } /* }}} */
  73  
  74  if (! function_exists('array_search')) { /* {{{ */
  75      function array_search($needle, $haystack)
  76      {
  77          foreach ($haystack as $key => $value) {
  78              if ($needle == $value)
  79                  return $key;
  80          }
  81          return false;
  82      }
  83  } /* }}} */
  84  
  85  if (! function_exists('realpath')) { /* {{{ */
  86      function realpath($path)
  87      {
  88          return $path;
  89      }
  90  } /* }}} */
  91  
  92  class phpMyEdit
  93  {
  94      // Class variables {{{

  95  
  96      // Database handling

  97      var $hn;        // hostname

  98      var $un;        // user name

  99      var $pw;        // password

 100      var $tb;        // table

 101      var $db;        // database

 102      var $dbp;       // database with point and delimiters

 103      var $dbh;       // database handle

 104      var $close_dbh; // if database handle should be closed

 105  
 106      // Record manipulation

 107      var $key;       // name of field which is the unique key

 108      var $key_num;   // number of field which is the unique key

 109      var $key_type;  // type of key field (int/real/string/date etc.)

 110      var $key_delim; // character used for key value quoting

 111      var $rec;       // number of record selected for editing

 112      var $inc;       // number of records to display

 113      var $fm;        // first record to display

 114      var $fl;        // is the filter row displayed (boolean)

 115      var $fds;       // sql field names

 116      var $fdn;       // sql field names => $k

 117      var $num_fds;   // number of fields

 118      var $options;   // options for users: ACDFVPI

 119      var $fdd;       // field definitions

 120      var $qfn;       // value of all filters used during the last pass

 121      var $sfn;       // sort field number (- = descending sort order)

 122      var $cur_tab;   // current selected tab

 123  
 124      // Operation

 125      var $navop;     // navigation buttons/operations

 126      var $sw;        // filter display/hide/clear button

 127      var $operation; // operation to do: Add, Change, Delete

 128      var $saveadd;
 129      var $moreadd;
 130      var $canceladd;
 131      var $savechange;
 132      var $morechange;
 133      var $cancelchange;
 134      var $savecopy;
 135      var $cancelcopy;
 136      var $savedelete;
 137      var $canceldelete;
 138      var $cancelview;
 139  
 140      // Additional features

 141      var $labels;        // multilingual labels

 142      var $cgi;           // CGI variable features array

 143      var $js;            // JS configuration array

 144      var $dhtml;         // DHTML configuration array

 145      var $url;           // URL array

 146      var $message;       // informational message to print

 147      var $notify;        // change notification e-mail adresses

 148      var $logtable;      // name of optional logtable

 149      var $navigation;    // navigation style

 150      var $tabs;          // TAB names

 151      var $timer = null;  // phpMyEdit_timer object

 152      var $sd; var $ed;   // sql start and end delimiters '`' in case of MySQL

 153  
 154      // Predefined variables

 155      var $comp_ops  = array('<'=>'<','<='=>'<=','='=>'=','>='=>'>=','>'=>'>');
 156      var $sql_aggrs = array(
 157              'sum'   => 'Total',
 158              'avg'   => 'Average',
 159              'min'   => 'Minimum',
 160              'max'   => 'Maximum',
 161              'count' => 'Count');
 162      var $page_types = array(
 163              'L' => 'list',
 164              'F' => 'filter',
 165              'A' => 'add',
 166              'V' => 'view',
 167              'C' => 'change',
 168              'P' => 'copy',
 169              'D' => 'delete'
 170              );
 171      var $default_buttons = array(
 172              'L' => array('<<','<','add','view','change','copy','delete','>','>>','goto','goto_combo'),
 173              'F' => array('<<','<','add','view','change','copy','delete','>','>>','goto','goto_combo'),
 174              'A' => array('save','more','cancel'),
 175              'C' => array('save','more','cancel'),
 176              'P' => array('save', 'cancel'),
 177              'D' => array('save','cancel'),
 178              'V' => array('change','cancel')
 179              );
 180      // }}}

 181  
 182      /*

 183       * column specific functions

 184       */
 185  
 186      function col_has_sql($k)    { return isset($this->fdd[$k]['sql']); }
 187      function col_has_sqlw($k)   { return isset($this->fdd[$k]['sqlw']) && !$this->virtual($k); }
 188      function col_has_values($k) { return isset($this->fdd[$k]['values']) || isset($this->fdd[$k]['values2']); }
 189      function col_has_php($k)    { return isset($this->fdd[$k]['php']); }
 190      function col_has_URL($k)    { return isset($this->fdd[$k]['URL'])
 191          || isset($this->fdd[$k]['URLprefix']) || isset($this->fdd[$k]['URLpostfix']); }
 192      function col_has_multiple($k)
 193      { return $this->col_has_multiple_select($k) || $this->col_has_checkboxes($k); }
 194      function col_has_multiple_select($k)
 195      { return $this->fdd[$k]['select'] == 'M' && ! $this->fdd[$k]['values']['table']; }
 196      function col_has_checkboxes($k)
 197      { return $this->fdd[$k]['select'] == 'C' && ! $this->fdd[$k]['values']['table']; }
 198      function col_has_radio_buttons($k)
 199      { return $this->fdd[$k]['select'] == 'O' && ! $this->fdd[$k]['values']['table']; }
 200      function col_has_datemask($k)
 201      { return isset($this->fdd[$k]['datemask']) || isset($this->fdd[$k]['strftimemask']); }
 202  
 203      /*

 204       * functions for indicating whether navigation style is enabled

 205       */
 206  
 207      function nav_buttons()       { return stristr($this->navigation, 'B'); }
 208      function nav_text_links()    { return stristr($this->navigation, 'T'); }
 209      function nav_graphic_links() { return stristr($this->navigation, 'G'); }
 210      function nav_up()            { return (stristr($this->navigation, 'U') && !($this->buttons[$this->page_type]['up'] === false)); }
 211      function nav_down()          { return (stristr($this->navigation, 'D') && !($this->buttons[$this->page_type]['down'] === false)); }
 212  
 213      /*

 214       * functions for indicating whether operations are enabled

 215       */
 216  
 217      function add_enabled()    { return stristr($this->options, 'A'); }
 218      function change_enabled() { return stristr($this->options, 'C'); }
 219      function delete_enabled() { return stristr($this->options, 'D'); }
 220      function filter_enabled() { return stristr($this->options, 'F'); }
 221      function view_enabled()   { return stristr($this->options, 'V'); }
 222      function copy_enabled()   { return stristr($this->options, 'P') && $this->add_enabled(); }
 223      function tabs_enabled()   { return $this->display['tabs'] && count($this->tabs) > 0; }
 224      function hidden($k)       { return stristr($this->fdd[$k]['input'],'H'); }
 225      function password($k)     { return stristr($this->fdd[$k]['input'],'W'); }
 226      function readonly($k)     { return stristr($this->fdd[$k]['input'],'R') || $this->virtual($k);     }
 227      function virtual($k)      { return stristr($this->fdd[$k]['input'],'V') && $this->col_has_sql($k); }
 228  
 229      function add_operation()    { return $this->operation == $this->labels['Add']    && $this->add_enabled();    }
 230      function change_operation() { return $this->operation == $this->labels['Change'] && $this->change_enabled(); }
 231      function copy_operation()   { return $this->operation == $this->labels['Copy']   && $this->copy_enabled();   }
 232      function delete_operation() { return $this->operation == $this->labels['Delete'] && $this->delete_enabled(); }
 233      function view_operation()   { return $this->operation == $this->labels['View']   && $this->view_enabled();   }
 234      function filter_operation() { return $this->fl && $this->filter_enabled() && $this->list_operation(); }
 235      function list_operation()   { /* covers also filtering page */ return ! $this->change_operation()
 236                                          && ! $this->add_operation()    && ! $this->copy_operation()
 237                                          && ! $this->delete_operation() && ! $this->view_operation(); }
 238      function next_operation()   { return ($this->navop == $this->labels['Next']) || ($this->navop == '>'); }
 239      function prev_operation()   { return ($this->navop == $this->labels['Prev']) || ($this->navop == '<'); }
 240      function first_operation()  { return ($this->navop == $this->labels['First']) || ($this->navop == '<<'); }
 241      function last_operation()   { return ($this->navop == $this->labels['Last']) || ($this->navop == '>>'); }
 242      function clear_operation()  { return $this->sw == $this->labels['Clear'];  }
 243  
 244      function add_canceled()    { return $this->canceladd    == $this->labels['Cancel']; }
 245      function view_canceled()   { return $this->cancelview   == $this->labels['Cancel']; }
 246      function change_canceled() { return $this->cancelchange == $this->labels['Cancel']; }
 247      function copy_canceled()   { return $this->cancelcopy   == $this->labels['Cancel']; }
 248      function delete_canceled() { return $this->canceldelete == $this->labels['Cancel']; }
 249  
 250      function is_values2($k, $val = 'X') /* {{{ */
 251      {
 252          return $val === null ||
 253              (isset($this->fdd[$k]['values2']) && !isset($this->fdd[$k]['values']['table']));
 254      } /* }}} */
 255  
 256      function processed($k) /* {{{ */
 257      {
 258          if ($this->virtual($k)) {
 259              return false;
 260          }
 261          $options = @$this->fdd[$k]['options'];
 262          if (! isset($options)) {
 263              return true;
 264          }
 265          return
 266              ($this->saveadd    == $this->labels['Save']  && stristr($options, 'A')) ||
 267              ($this->moreadd    == $this->labels['More']  && stristr($options, 'A')) ||
 268              ($this->savechange == $this->labels['Save']  && stristr($options, 'C')) ||
 269              ($this->morechange == $this->labels['Apply'] && stristr($options, 'C')) ||
 270              ($this->savecopy   == $this->labels['Save']  && stristr($options, 'P')) ||
 271              ($this->savedelete == $this->labels['Save']  && stristr($options, 'D'));
 272      } /* }}} */
 273  
 274      function displayed($k) /* {{{ */
 275      {
 276          if (is_numeric($k)) {
 277              $k = $this->fds[$k];
 278          }
 279          $options = @$this->fdd[$k]['options'];
 280          if (! isset($options)) {
 281              return true;
 282          }
 283          return
 284              ($this->add_operation()    && stristr($options, 'A')) ||
 285              ($this->view_operation()   && stristr($options, 'V')) ||
 286              ($this->change_operation() && stristr($options, 'C')) ||
 287              ($this->copy_operation()   && stristr($options, 'P')) ||
 288              ($this->delete_operation() && stristr($options, 'D')) ||
 289              ($this->filter_operation() && stristr($options, 'F')) ||
 290              ($this->list_operation()   && stristr($options, 'L'));
 291      } /* }}} */
 292  
 293      function debug_var($name, $val) /* {{{ */
 294      {
 295          if (is_array($val) || is_object($val)) {
 296              echo "<pre>$name\n";
 297              ob_start();
 298              //print_r($val);

 299              var_dump($val);
 300              $content = ob_get_contents();
 301              ob_end_clean();
 302              echo htmlspecialchars($content);
 303              echo "</pre>\n";
 304          } else {
 305              echo 'debug_var()::<i>',htmlspecialchars($name),'</i>';
 306              echo '::<b>',htmlspecialchars($val),'</b>::',"<br />\n";
 307          }
 308      } /* }}} */
 309  
 310      /*

 311       * sql functions

 312       */
 313      function sql_connect() /* {{{ */
 314      {
 315          $this->dbh = @ini_get('allow_persistent')
 316              ? @mysql_pconnect($this->hn, $this->un, $this->pw)
 317              : @mysql_connect($this->hn, $this->un, $this->pw);
 318      } /* }}} */
 319  
 320  
 321      function sql_disconnect() /* {{{ */
 322      {
 323          if ($this->close_dbh) {
 324              @mysql_close($this->dbh);
 325              $this->dbh = null;
 326          }
 327      } /* }}} */
 328  
 329      function sql_fetch(&$res, $type = 'a') /* {{{ */
 330      {
 331          if($type == 'n') $type = MYSQL_NUM;
 332          else $type = MYSQL_ASSOC;
 333          return @mysql_fetch_array($res, $type);
 334      } /* }}} */
 335  
 336      function sql_free_result(&$res) /* {{{ */
 337      {
 338          return @mysql_free_result($res);
 339      } /* }}} */
 340  
 341      function sql_affected_rows(&$dbh) /* {{{ */
 342      {
 343          return @mysql_affected_rows($dbh);
 344      } /* }}} */
 345  
 346      function sql_field_len(&$res,$field) /* {{{ */
 347      {
 348          return @mysql_field_len($res, $field);
 349      } /* }}} */
 350  
 351      function sql_insert_id() /* {{{ */
 352      {
 353          return mysql_insert_id($this->dbh);
 354      } /* }}} */
 355  
 356      function sql_limit($start, $more) /* {{{ */
 357      {
 358          return ' LIMIT '.$start.', '.$more.' ';
 359      } /* }}} */
 360  
 361      function sql_delimiter() /* {{{ */
 362      {
 363          $this->sd = '`'; $this->ed='`';
 364          return $this->sd;
 365      } /* }}} */
 366  
 367  
 368      function myquery($qry, $line = 0, $debug = 0) /* {{{ */
 369      {
 370          global $debug_query;
 371          if ($debug_query || $debug) {
 372              $line = intval($line);
 373              echo '<h4>MySQL query at line ',$line,'</h4>',htmlspecialchars($qry),'<hr size="1" />',"\n";
 374          }
 375          if (isset($this->db)) {
 376              $ret = @mysql_db_query($this->db, $qry, $this->dbh);
 377          } else {
 378              $ret = @mysql_query($qry, $this->dbh);
 379          }
 380          if (! $ret) {
 381              echo '<h4>MySQL error ',mysql_errno($this->dbh),'</h4>';
 382              echo htmlspecialchars(mysql_error($this->dbh)),'<hr size="1" />',"\n";
 383          }
 384          return $ret;
 385      } /* }}} */
 386  
 387      /* end of sql functions */

 388  
 389      function make_language_labels($language) /* {{{ */
 390      {
 391          // just try the first language and variant

 392          // this isn't content-negotiation rfc compliant

 393          $language = strtoupper($language);
 394  
 395          // try the full language w/ variant

 396          $file = $this->dir['lang'].'PME.lang.'.$language.'.inc';
 397          while (! file_exists($file)) {
 398              $pos = strrpos($language, '-');
 399              if ($pos === false) {
 400                  $file = $this->dir['lang'].'PME.lang.EN.inc';
 401                  break;
 402              }
 403              $language = substr($language, 0, $pos);
 404              $file = $this->dir['lang'].'PME.lang.'.$language.'.inc';
 405          }
 406          $ret = @include($file);
 407          if (! is_array($ret)) {
 408              return $ret;
 409          }
 410          $small = array(
 411                  'Search' => 'v',
 412                  'Hide'   => '^',
 413                  'Clear'  => 'X',
 414                  'Query'  => htmlspecialchars('>'));
 415          if ((!$this->nav_text_links() && !$this->nav_graphic_links())
 416                  || !isset($ret['Search']) || !isset($ret['Query'])
 417                  || !isset($ret['Hide'])   || !isset($ret['Clear'])) {
 418              foreach ($small as $key => $val) {
 419                  $ret[$key] = $val;
 420              }
 421          }
 422          return $ret;
 423      } /* }}} */
 424  
 425      function set_values($field_num, $prepend = null, $append = null, $strict = false) /* {{{ */
 426      {
 427          return (array) $prepend + (array) $this->fdd[$field_num]['values2']
 428              + (isset($this->fdd[$field_num]['values']['table']) || $strict
 429                      ? $this->set_values_from_table($field_num, $strict)
 430                      : array())
 431              + (array) $append;
 432      } /* }}} */
 433  
 434      function set_values_from_table($field_num, $strict = false) /* {{{ */
 435      {
 436          $db    = &$this->fdd[$field_num]['values']['db'];
 437          $table = $this->sd.$this->fdd[$field_num]['values']['table'].$this->ed;
 438          $key   = &$this->fdd[$field_num]['values']['column'];
 439          $desc  = &$this->fdd[$field_num]['values']['description'];
 440          $dbp   = isset($db) ? $this->sd.$db.$this->ed.'.' : $this->dbp;
 441          $qparts['type'] = 'select';
 442          if ($table != $this->sd.$this->ed) {
 443              $qparts['select'] = 'DISTINCT '.$table.'.'.$this->sd.$key.$this->ed;
 444              if ($desc && is_array($desc) && is_array($desc['columns'])) {
 445                  $qparts['select'] .= ',CONCAT('; // )

 446                  $num_cols = sizeof($desc['columns']);
 447                  if (isset($desc['divs'][-1])) {
 448                      $qparts['select'] .= '"'.addslashes($desc['divs'][-1]).'",';
 449                  }
 450                  foreach ($desc['columns'] as $key => $val) {
 451                      if ($val) {
 452                          $qparts['select'] .= 'IFNULL(CAST('.$this->sd.$val.$this->ed.' AS CHAR),"")';
 453                          if ($desc['divs'][$key]) {
 454                              $qparts['select'] .= ',"'.addslashes($desc['divs'][$key]).'"';
 455                          }
 456                          $qparts['select'] .= ',';
 457                      }
 458                  }
 459                  $qparts['select']{strlen($qparts['select']) - 1} = ')';
 460                  $qparts['select'] .= ' AS '.$this->sd.'PMEalias'.$field_num.$this->ed;
 461                  $qparts['orderby'] = $this->sd.'PMEalias'.$field_num.$this->ed;
 462              } else if ($desc && is_array($desc)) {
 463                  // TODO

 464              } else if ($desc) {
 465                  $qparts['select'] .= ','.$table.'.'.$this->sd.$desc.$this->ed;
 466                  $qparts['orderby'] = $this->sd.$desc.$this->ed;
 467              } else if ($key) {
 468                  $qparts['orderby'] = $this->sd.$key.$this->ed;
 469              }
 470              $qparts['from'] = $dbp.$table;
 471              $ar = array(
 472                      'table'       => $table,
 473                      'column'      => $column,
 474                      'description' => $desc);
 475              $qparts['where'] = $this->substituteVars($this->fdd[$field_num]['values']['filters'], $ar);
 476              if ($this->fdd[$field_num]['values']['orderby']) {
 477                  $qparts['orderby'] = $this->substituteVars($this->fdd[$field_num]['values']['orderby'], $ar);
 478              }
 479          } else { /* simple value extraction */
 480              $key = &$this->fds[$field_num];
 481              $this->virtual($field_num) && $key = $this->fqn($field_num);
 482              $qparts['select']  = 'DISTINCT '.$this->sd.$key.$this->ed.' AS PMEkey';
 483              $qparts['orderby'] = 'PMEkey';
 484              $qparts['from']    = $this->dbp.$this->sd.$this->tb.$this->ed;
 485          }
 486          $values = array();
 487          $res    = $this->myquery($this->get_SQL_query($qparts), __LINE__);
 488          while ($row = $this->sql_fetch($res, 'n')) {
 489              $values[$row[0]] = $desc ? $row[1] : $row[0];
 490          }
 491          return $values;
 492      } /* }}} */
 493  
 494      function fqn($field, $dont_desc = false, $dont_cols = false) /* {{{ */
 495      {
 496          is_numeric($field) || $field = array_search($field, $this->fds);
 497          // if read SQL expression exists use it

 498          if ($this->col_has_sql($field) && !$this->col_has_values($field))
 499              return $this->fdd[$field]['sql'];
 500          // on copy/change always use simple key retrieving

 501          if ($this->add_operation()
 502                  || $this->copy_operation()
 503                  || $this->change_operation()) {
 504                  $ret = $this->sd.'PMEtable0'.$this->ed.'.'.$this->sd.$this->fds[$field].$this->ed;
 505          } else {
 506              if ($this->fdd[$this->fds[$field]]['values']['description'] && ! $dont_desc) {
 507                  $desc = &$this->fdd[$this->fds[$field]]['values']['description'];
 508                  if (is_array($desc) && is_array($desc['columns'])) {
 509                      $ret      = 'CONCAT('; // )

 510                      $num_cols = sizeof($desc['columns']);
 511                      if (isset($desc['divs'][-1])) {
 512                          $ret .= '"'.addslashes($desc['divs'][-1]).'",';
 513                      }
 514                      foreach ($desc['columns'] as $key => $val) {
 515                          if ($val) {
 516                              $ret .= 'IFNULL(CAST('.$this->sd.'PMEjoin'.$field.$this->ed.'.'.$this->sd.$val.$this->ed.' AS CHAR),"")';
 517                              if ($desc['divs'][$key]) {
 518                                  $ret .= ',"'.addslashes($desc['divs'][$key]).'"';
 519                              }
 520                              $ret .= ',';
 521                          }
 522                      }
 523                      $ret{strlen($ret) - 1} = ')';
 524                  } else if (is_array($desc)) {
 525                      // TODO

 526                  } else {
 527                      $ret = $this->sd.'PMEjoin'.$field.$this->ed.'.'.$this->sd.$this->fdd[$this->fds[$field]]['values']['description'].$this->ed;
 528                  }
 529              // TODO: remove me

 530              } elseif (0 && $this->fdd[$this->fds[$field]]['values']['column'] && ! $dont_cols) {
 531                  $ret = $this->sd.'PMEjoin'.$field.$this->ed.'.'.$this->fdd[$this->fds[$field]]['values']['column'];
 532              } else {
 533                  $ret = $this->sd.'PMEtable0'.$this->ed.'.'.$this->sd.$this->fds[$field].$this->ed;
 534              }
 535              // TODO: not neccessary, remove me!

 536              if (is_array($this->fdd[$this->fds[$field]]['values2'])) {
 537              }
 538          }
 539          return $ret;
 540      } /* }}} */
 541  
 542      function get_SQL_main_list_query($qparts) /* {{{ */
 543      {
 544          return $this->get_SQL_query($qparts);
 545      } /* }}} */
 546  
 547  
 548  
 549      function get_SQL_query($parts) /* {{{ */
 550      {
 551          foreach ($parts as $k => $v) {
 552              $parts[$k] = trim($parts[$k]);
 553          }
 554          switch ($parts['type']) {
 555              case 'select':
 556                  $ret  = 'SELECT ';
 557                  if ($parts['DISTINCT'])
 558                      $ret .= 'DISTINCT ';
 559                  $ret .= $parts['select'];
 560                  $ret .= ' FROM '.$parts['from'];
 561                  if ($parts['where'] != '')
 562                      $ret .= ' WHERE '.$parts['where'];
 563                  if ($parts['groupby'] != '')
 564                      $ret .= ' GROUP BY '.$parts['groupby'];
 565                  if ($parts['having'] != '')
 566                      $ret .= ' HAVING '.$parts['having'];
 567                  if ($parts['orderby'] != '')
 568                      $ret .= ' ORDER BY '.$parts['orderby'];
 569                  if ($parts['limit'] != '')
 570                      $ret .= ' '.$parts['limit'];
 571                  if ($parts['procedure'] != '')
 572                      $ret .= ' PROCEDURE '.$parts['procedure'];
 573                  break;
 574              case 'update':
 575                  $ret  = 'UPDATE '.$parts['table'];
 576                  $ret .= ' SET '.$parts['fields'];
 577                  if ($parts['where'] != '')
 578                      $ret .= ' WHERE '.$parts['where'];
 579                  break;
 580              case 'insert':
 581                  $ret  = 'INSERT INTO '.$parts['table'];
 582                  $ret .= ' VALUES '.$parts['values'];
 583                  break;
 584              case 'delete':
 585                  $ret  = 'DELETE FROM '.$parts['table'];
 586                  if ($parts['where'] != '')
 587                      $ret .= ' WHERE '.$parts['where'];
 588                  break;
 589              default:
 590                  die('unknown query type');
 591                  break;
 592          }
 593          return $ret;
 594      } /* }}} */
 595  
 596      function get_SQL_column_list() /* {{{ */
 597      {
 598          $fields = array();
 599          for ($k = 0; $k < $this->num_fds; $k++) {
 600              if (! $this->displayed[$k] && $k != $this->key_num) {
 601                  continue;
 602              }
 603              $fields[] = $this->fqn($k).' AS '.$this->sd.'qf'.$k.$this->ed; // no delimiters here, or maybe some yes

 604              if ($this->col_has_values($k)) {
 605                  if($this->col_has_sql($k)) $fields[] = $this->fdd[$k]['sql'].' AS '.$this->sd.'qf'.$k.'_idx'.$this->ed;
 606                  else $fields[] = $this->fqn($k, true, true).' AS '.$this->sd.'qf'.$k.'_idx'.$this->ed;
 607              }
 608              if ($this->col_has_datemask($k)) {
 609                  $fields[] = 'UNIX_TIMESTAMP('.$this->fqn($k).') AS '.$this->sd.'qf'.$k.'_timestamp'.$this->ed;
 610              }
 611          }
 612          return join(',', $fields);
 613      } /* }}} */
 614  
 615      function get_SQL_join_clause() /* {{{ */
 616      {
 617          $main_table  = $this->sd.'PMEtable0'.$this->ed;
 618          $join_clause = $this->sd.$this->tb.$this->ed." AS $main_table";
 619          for ($k = 0, $numfds = sizeof($this->fds); $k < $numfds; $k++) {
 620              $main_column = $this->fds[$k];
 621              if($this->fdd[$main_column]['values']['db']) {
 622                  $dbp = $this->sd.$this->fdd[$main_column]['values']['db'].$this->ed.'.';
 623              } else {
 624                  //$dbp = $this->dbp;

 625              }
 626              $table       = $this->sd.$this->fdd[$main_column]['values']['table'].$this->ed;
 627              $join_column = $this->sd.$this->fdd[$main_column]['values']['column'].$this->ed;
 628              $join_desc   = $this->sd.$this->fdd[$main_column]['values']['description'].$this->ed;
 629              if ($join_desc != $this->sd.$this->ed && $join_column != $this->sd.$this->ed) {
 630                  $join_table = $this->sd.'PMEjoin'.$k.$this->ed;
 631                  $ar = array(
 632                          'main_table'       => $main_table,
 633                          'main_column'      => $this->sd.$main_column.$this->ed,
 634                          'join_table'       => $join_table,
 635                          'join_column'      => $join_column,
 636                          'join_description' => $join_desc);
 637                  $join_clause .= " LEFT OUTER JOIN $dbp".$table." AS $join_table ON (";
 638                  $join_clause .= isset($this->fdd[$main_column]['values']['join'])
 639                      ? $this->substituteVars($this->fdd[$main_column]['values']['join'], $ar)
 640                      : "$join_table.$join_column = $main_table.".$this->sd.$main_column.$this->ed;
 641                  $join_clause .= ')';
 642              }
 643          }
 644          return $join_clause;
 645      } /* }}} */
 646  
 647      function get_SQL_where_from_query_opts($qp = null, $text = 0) /* {{{ */
 648      {
 649          if ($qp == null) {
 650              $qp = $this->query_opts;
 651          }
 652          $where = array();
 653          foreach ($qp as $field => $ov) {
 654              if (is_numeric($field)) {
 655                  $tmp_where = array();
 656                  foreach ($ov as $field2 => $ov2) {
 657                      $tmp_where[] = sprintf('%s %s %s', $field2, $ov2['oper'], $ov2['value']);
 658                  }
 659                  $where[] = '('.join(' OR ', $tmp_where).')';
 660              } else {
 661                  if (is_array($ov['value'])) {
 662                      $tmp_ov_val = '';
 663                      foreach ($ov['value'] as $ov_val) {
 664                          strlen($tmp_ov_val) > 0 && $tmp_ov_val .= ' OR ';
 665                          $tmp_ov_val .= sprintf('FIND_IN_SET("%s",%s)', $ov_val, $field);
 666                      }
 667                      $where[] = "($tmp_ov_val)";
 668                  } else {
 669                      $where[] = sprintf('%s %s %s', $field, $ov['oper'], $ov['value']);
 670                  }
 671              }
 672          }
 673          // Add any coder specified filters

 674          if (! $text && $this->filters) {
 675              $where[] = '('.$this->filters.')';
 676          }
 677          if (count($where) > 0) {
 678              if ($text) {
 679                  return str_replace('%', '*', join(' AND ',$where));
 680              } else {
 681                  return join(' AND ',$where);
 682              }
 683          }
 684          return ''; /* empty string */
 685      } /* }}} */
 686  
 687      function gather_query_opts() /* {{{ */
 688      {
 689          $this->query_opts = array();
 690          $this->prev_qfn   = $this->qfn;
 691          $this->qfn        = '';
 692          if ($this->clear_operation()) {
 693              return;
 694          }
 695          // gathers query options into an array, $this->query_opts

 696          $qo = array();
 697          for ($k = 0; $k < $this->num_fds; $k++) {
 698              $l    = 'qf'.$k;
 699              $lc   = 'qf'.$k.'_comp';
 700              $li   = 'qf'.$k.'_id';
 701              $m    = $this->get_sys_cgi_var($l);
 702              $mc   = $this->get_sys_cgi_var($lc);
 703              $mi   = $this->get_sys_cgi_var($li);
 704              if (! isset($m) && ! isset($mi)) {
 705                  continue;
 706              }
 707              if (is_array($m) || is_array($mi)) {
 708                  if (is_array($mi)) {
 709                      $m = $mi;
 710                      $l = $li;
 711                  }
 712                  if (in_array('*', $m)) {
 713                      continue;
 714                  }
 715                  if ($this->col_has_values($k) && $this->col_has_multiple($k)) {
 716                      foreach (array_keys($m) as $key) {
 717                          $m[$key] = addslashes($m[$key]);
 718                      }
 719                      $qo[$this->fqn($k)] = array('value' => $m);
 720                  } else {
 721                      $qf_op = '';
 722                      foreach (array_keys($m) as $key) {
 723                          if ($qf_op == '') {
 724                              $qf_op   = 'IN';
 725                              $qf_val  = '"'.addslashes($m[$key]).'"';
 726                              $afilter = ' IN ("'.addslashes($m[$key]).'"'; // )

 727                          } else {
 728                              $afilter = $afilter.',"'.addslashes($m[$key]).'"';
 729                              $qf_val .= ',"'.addslashes($m[$key]).'"';
 730                          }
 731                          $this->qfn .= '&'.$this->cgi['prefix']['sys'].$l.'['.rawurlencode($key).']='.rawurlencode($m[$key]);
 732                      }
 733                      $afilter = $afilter.')';
 734                      // XXX: $dont_desc and $dont_cols hack

 735                      $dont_desc = isset($this->fdd[$k]['values']['description']);
 736                      $dont_cols = isset($this->fdd[$k]['values']['column']);
 737                      $qo[$this->fqn($k, $dont_desc, $dont_cols)] =
 738                          array('oper'  => $qf_op, 'value' => "($qf_val)"); // )

 739                  }
 740              } else if (isset($mi)) {
 741                  if ($mi == '*') {
 742                      continue;
 743                  }
 744                  if ($this->fdd[$k]['select'] != 'M' && $this->fdd[$k]['select'] != 'D' && $mi == '') {
 745                      continue;
 746                  }
 747                  $afilter = addslashes($mi);
 748                  $qo[$this->fqn($k, true, true)] = array('oper'  => '=', 'value' => "'$afilter'");
 749                  $this->qfn .= '&'.$this->cgi['prefix']['sys'].$li.'='.rawurlencode($mi);
 750              } else if (isset($m)) {
 751                  if ($m == '*') {
 752                      continue;
 753                  }
 754                  if ($this->fdd[$k]['select'] != 'M' && $this->fdd[$k]['select'] != 'D' && $m == '') {
 755                      continue;
 756                  }
 757                  $afilter = addslashes($m);
 758                  if ($this->fdd[$k]['select'] == 'N') {
 759                      $mc = in_array($mc, $this->comp_ops) ? $mc : '=';
 760                      $qo[$this->fqn($k)] = array('oper' => $mc, 'value' => "'$afilter'");
 761                      $this->qfn .= '&'.$this->cgi['prefix']['sys'].$l .'='.rawurlencode($m);
 762                      $this->qfn .= '&'.$this->cgi['prefix']['sys'].$lc.'='.rawurlencode($mc);
 763                  } else {
 764                      $afilter = '%'.str_replace('*', '%', $afilter).'%';
 765                      $ids  = array();
 766                      $ar   = array();
 767                      $ar[$this->fqn($k)] = array('oper' => 'LIKE', 'value' => "'$afilter'");
 768                      if (is_array($this->fdd[$k]['values2'])) {
 769                          foreach ($this->fdd[$k]['values2'] as $key => $val) {
 770                              if (strlen($m) > 0 && stristr($val, $m)) {
 771                                  $ids[] = '"'.addslashes($key).'"';
 772                              }
 773                          }
 774                          if (count($ids) > 0) {
 775                              $ar[$this->fqn($k, true, true)]
 776                                  = array('oper'  => 'IN', 'value' => '('.join(',', $ids).')');
 777                          }
 778                      }
 779                      $qo[] = $ar;
 780                      $this->qfn .= '&'.$this->cgi['prefix']['sys'].$l.'='.rawurlencode($m);
 781                  }
 782              }
 783          }
 784          $this->query_opts = $qo;
 785      } /* }}} */
 786  
 787      /*

 788       * Create JavaScripts

 789       */
 790  
 791      function form_begin() /* {{{ */
 792      {
 793          $page_name = htmlspecialchars($this->page_name);
 794          if ($this->add_operation() || $this->change_operation() || $this->copy_operation()
 795                  || $this->view_operation() || $this->delete_operation()) {
 796              $field_to_tab = array();
 797              for ($tab = $k = $this->cur_tab = 0; $k < $this->num_fds; $k++) {
 798                  if (isset($this->fdd[$k]['tab'])) {
 799                      if ($tab == 0 && $k > 0) {
 800                          $this->tabs[0] = 'PMEtab0';
 801                          $this->cur_tab = 1;
 802                          $tab++;
 803                      }
 804                      if (is_array($this->fdd[$k]['tab'])) {
 805                          $this->tabs[$tab] = @$this->fdd[$k]['tab']['name'];
 806                          $this->fdd[$k]['tab']['default'] && $this->cur_tab = $tab;
 807                      } else {
 808                          $this->tabs[$tab] = @$this->fdd[$k]['tab'];
 809                      }
 810                      $tab++;
 811                  }
 812                  $field_to_tab[$k] = max(0, $tab - 1);
 813              }
 814              if (preg_match('/^'.$this->dhtml['prefix'].'tab(\d+)$/', $this->get_sys_cgi_var('cur_tab'), $parts)) {
 815                  $this->cur_tab = $parts[1];
 816              }
 817              if ($this->tabs_enabled()) {
 818                  // initial TAB styles

 819                  echo '<style type="text/css" media="screen">',"\n";
 820                  for ($i = 0; $i < count($this->tabs); $i++) {
 821                      echo '  #'.$this->dhtml['prefix'].'tab',$i,' { display: ';
 822                      echo (($i == $this->cur_tab || $this->tabs[$i] == 'PMEtab0' ) ? 'block' : 'none') ,'; }',"\n";
 823                  }
 824                  echo '</style>',"\n";
 825                  // TAB javascripts

 826                  echo '<script type="text/javascript"><!--',"\n\n";
 827                  $css_class_name1 = $this->getCSSclass('tab', $position);
 828                  $css_class_name2 = $this->getCSSclass('tab-selected', $position);
 829                  echo 'var '.$this->js['prefix'].'cur_tab  = "'.$this->dhtml['prefix'].'tab',$this->cur_tab,'";
 830  
 831  function '.$this->js['prefix'].'show_tab(tab_name)
 832  {';
 833                  if ($this->nav_up()) {
 834                      echo '
 835      document.getElementById('.$this->js['prefix'].'cur_tab+"_up_label").className = "',$css_class_name1,'";
 836      document.getElementById('.$this->js['prefix'].'cur_tab+"_up_link").className = "',$css_class_name1,'";
 837      document.getElementById(tab_name+"_up_label").className = "',$css_class_name2,'";
 838      document.getElementById(tab_name+"_up_link").className = "',$css_class_name2,'";';
 839                  }
 840                  if ($this->nav_down()) {
 841                      echo '
 842      document.getElementById('.$this->js['prefix'].'cur_tab+"_down_label").className = "',$css_class_name1,'";
 843      document.getElementById('.$this->js['prefix'].'cur_tab+"_down_link").className = "',$css_class_name1,'";
 844      document.getElementById(tab_name+"_down_label").className = "',$css_class_name2,'";
 845      document.getElementById(tab_name+"_down_link").className = "',$css_class_name2,'";';
 846                  }
 847                  echo '
 848      document.getElementById('.$this->js['prefix'].'cur_tab).style.display = "none";
 849      document.getElementById(tab_name).style.display = "block";
 850      '.$this->js['prefix'].'cur_tab = tab_name;
 851      document.'.$this->cgi['prefix']['sys'].'form.'.$this->cgi['prefix']['sys'].'cur_tab.value = tab_name;
 852  }',"\n\n";
 853                  echo '// --></script>', "\n";
 854              }
 855          }
 856  
 857          if ($this->add_operation() || $this->change_operation() || $this->copy_operation()) {
 858              $first_required = true;
 859              for ($k = 0; $k < $this->num_fds; $k++) {
 860                  if ($this->displayed[$k] && ! $this->readonly($k) && ! $this->hidden($k)
 861                          && ($this->fdd[$k]['js']['required'] || isset($this->fdd[$k]['js']['regexp']))) {
 862                      if ($first_required) {
 863                          $first_required = false;
 864                          echo '<script type="text/javascript"><!--',"\n";
 865                          echo '
 866  function '.$this->js['prefix'].'trim(str)
 867  {
 868      while (str.substring(0, 1) == " "
 869              || str.substring(0, 1) == "\\n"
 870              || str.substring(0, 1) == "\\r")
 871      {
 872          str = str.substring(1, str.length);
 873      }
 874      while (str.substring(str.length - 1, str.length) == " "
 875              || str.substring(str.length - 1, str.length) == "\\n"
 876              || str.substring(str.length - 1, str.length) == "\\r")
 877      {
 878          str = str.substring(0, str.length - 1);
 879      }
 880      return str;
 881  }
 882  
 883  function '.$this->js['prefix'].'form_control(theForm)
 884  {',"\n";
 885                      }
 886                      if ($this->col_has_values($k)) {
 887                          $condition = 'theForm.'.$this->cgi['prefix']['data'].$this->fds[$k].'.selectedIndex == -1';
 888                          $multiple  = $this->col_has_multiple_select($k);
 889                      } else {
 890                          $condition = '';
 891                          $multiple  = false;
 892                          if ($this->fdd[$k]['js']['required']) {
 893                              $condition = $this->js['prefix'].'trim(theForm.'.$this->cgi['prefix']['data'].$this->fds[$k].'.value) == ""';
 894                          }
 895                          if (isset($this->fdd[$k]['js']['regexp'])) {
 896                              $condition .= (strlen($condition) > 0 ? ' || ' : '');
 897                              $condition .= sprintf('!(%s.test('.$this->js['prefix'].'trim(theForm.%s.value)))',
 898                                      $this->fdd[$k]['js']['regexp'], $this->cgi['prefix']['data'].$this->fds[$k]);
 899                          }
 900                      }
 901  
 902                      /* Multiple selects have their name like ''name[]''.

 903                         It is not possible to work with them directly, because

 904                         theForm.name[].something will result into JavaScript

 905                         syntax error. Following search algorithm is provided

 906                         as a workaround for this.

 907                       */
 908                      if ($multiple) {
 909                          echo '
 910      multiple_select = null;
 911      for (i = 0; i < theForm.length; i++) {
 912          if (theForm.elements[i].name == "',$this->cgi['prefix']['data'].$this->fds[$k],'[]") {
 913              multiple_select = theForm.elements[i];
 914              break;
 915          }
 916      }
 917      if (multiple_select != null && multiple_select.selectedIndex == -1) {';
 918                      } else {
 919                          echo '
 920      if (',$condition,') {';
 921                      }
 922                      echo '
 923          alert("';
 924                      if (isset($this->fdd[$k]['js']['hint'])) {
 925                          echo htmlspecialchars($this->fdd[$k]['js']['hint']);
 926                      } else {
 927                          echo $this->labels['Please enter'],' ',$this->fdd[$k]['name'],'.';
 928                      }
 929                      echo '");';
 930                      if ($this->tabs_enabled() && $field_to_tab[$k] >= $this->cur_tab) {
 931                          echo '
 932          '.$this->js['prefix'].'show_tab("'.$this->dhtml['prefix'].'tab',$field_to_tab[$k],'");';
 933                      }
 934                      echo '
 935          theForm.',$this->cgi['prefix']['data'].$this->fds[$k],'.focus();
 936          return false;
 937      }',"\n";
 938                  }
 939              }
 940              if (! $first_required) {
 941                  echo '
 942      return true;
 943  }',"\n\n";
 944                  echo '// --></script>', "\n";
 945              }
 946          }
 947  
 948          if ($this->filter_operation()) {
 949                  echo '<script type="text/javascript"><!--',"\n";
 950                  echo '
 951  function '.$this->js['prefix'].'filter_handler(theForm, theEvent)
 952  {
 953      var pressed_key = null;
 954      if (theEvent.which) {
 955          pressed_key = theEvent.which;
 956      } else {
 957          pressed_key = theEvent.keyCode;
 958      }
 959      if (pressed_key == 13) { // enter pressed
 960          theForm.submit();
 961          return false;
 962      }
 963      return true;
 964  }',"\n\n";
 965                  echo '// --></script>', "\n";
 966          }
 967  
 968          if ($this->display['form']) {
 969              echo '<form class="',$this->getCSSclass('form'),'" method="post"';
 970              echo ' action="',$page_name,'" name="'.$this->cgi['prefix']['sys'].'form">',"\n";
 971          }
 972          return true;
 973      } /* }}} */
 974  
 975      function form_end() /* {{{ */
 976      {
 977          if ($this->display['form']) {
 978              echo '</form>',"\n";
 979          }
 980      } /* }}} */
 981  
 982      function display_tab_labels($position) /* {{{ */
 983      {
 984          if (! is_array($this->tabs)) {
 985              return false;
 986          }
 987          echo '<table summary="labels" class="',$this->getCSSclass('tab', $position),'">',"\n";
 988          echo '<tr class="',$this->getCSSclass('tab', $position),'">',"\n";
 989          for ($i = ($this->tabs[0] == 'PMEtab0' ? 1 : 0); $i < count($this->tabs); $i++) {
 990              $css_class_name = $this->getCSSclass($i != $this->cur_tab ? 'tab' : 'tab-selected', $position);
 991              echo '<td class="',$css_class_name,'" id="'.$this->dhtml['prefix'].'tab',$i,'_',$position,'_label">';
 992              echo '<a class="',$css_class_name,'" id="'.$this->dhtml['prefix'].'tab',$i,'_',$position,'_link';
 993              echo '" href="javascript:'.$this->js['prefix'].'show_tab(\''.$this->dhtml['prefix'].'tab',$i,'\')">';
 994              echo $this->tabs[$i],'</a></td>',"\n";
 995          }
 996          echo '<td class="',$this->getCSSclass('tab-end', $position),'">&nbsp;</td>',"\n";
 997          echo '</tr>',"\n";
 998          echo '</table>',"\n";
 999      } /* }}} */
1000  
1001      /*

1002       * Display functions

1003       */
1004  
1005      function display_add_record() /* {{{ */
1006      {
1007          for ($tab = 0, $k = 0; $k < $this->num_fds; $k++) {
1008              if (isset($this->fdd[$k]['tab']) && $this->tabs_enabled() && $k > 0) {
1009                  $tab++;
1010                  echo '</table>',"\n";
1011                  echo '</div>',"\n";
1012                  echo '<div id="'.$this->dhtml['prefix'].'tab',$tab,'">',"\n";
1013                  echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n";
1014              }
1015              if (! $this->displayed[$k]) {
1016                  continue;
1017              }
1018              if ($this->hidden($k)) {
1019                  echo $this->htmlHiddenData($this->fds[$k], $this->fdd[$k]['default']);
1020                  continue;
1021              }
1022              $css_postfix    = @$this->fdd[$k]['css']['postfix'];
1023              $css_class_name = $this->getCSSclass('input', null, 'next', $css_postfix);
1024              $escape         = isset($this->fdd[$k]['escape']) ? $this->fdd[$k]['escape'] : true;
1025              echo '<tr class="',$this->getCSSclass('row', null, true, $css_postfix),'">',"\n";
1026              echo '<td class="',$this->getCSSclass('key', null, true, $css_postfix),'">';
1027              echo $this->fdd[$k]['name'],'</td>',"\n";
1028              echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"';
1029              echo $this->getColAttributes($k),">\n";
1030              if ($this->col_has_values($k)) {
1031                  $vals       = $this->set_values($k);
1032                  $selected   = @$this->fdd[$k]['default'];
1033                  $multiple   = $this->col_has_multiple($k);
1034                  $readonly   = $this->readonly($k);
1035                  $strip_tags = true;
1036                  //$escape     = true;

1037                  if ($this->col_has_checkboxes($k) || $this->col_has_radio_buttons($k)) {
1038                      echo $this->htmlRadioCheck($this->cgi['prefix']['data'].$this->fds[$k],
1039                              $css_class_name, $vals, $selected, $multiple, $readonly,
1040                              $strip_tags, $escape);
1041                  } else {
1042                      echo $this->htmlSelect($this->cgi['prefix']['data'].$this->fds[$k],
1043                              $css_class_name, $vals, $selected, $multiple, $readonly,
1044                              $strip_tags, $escape);
1045                  }
1046              } elseif (isset ($this->fdd[$k]['textarea'])) {
1047                  echo '<textarea class="',$css_class_name,'" name="',$this->cgi['prefix']['data'].$this->fds[$k],'"';
1048                  echo ($this->readonly($k) ? ' disabled' : '');
1049                  if (intval($this->fdd[$k]['textarea']['rows']) > 0) {
1050                      echo ' rows="',$this->fdd[$k]['textarea']['rows'],'"';
1051                  }
1052                  if (intval($this->fdd[$k]['textarea']['cols']) > 0) {
1053                      echo ' cols="',$this->fdd[$k]['textarea']['cols'],'"';
1054                  }
1055                  if (isset($this->fdd[$k]['textarea']['wrap'])) {
1056                      echo ' wrap="',$this->fdd[$k]['textarea']['wrap'],'"';
1057                  } else {
1058                      echo ' wrap="virtual"';
1059                  }
1060                  echo '>';
1061                  if($escape) echo htmlspecialchars($this->fdd[$k]['default']);
1062                  else echo $this->fdd[$k]['default'];
1063                  echo '</textarea>',"\n";
1064              } elseif ($this->col_has_php($k)) {
1065                  echo include($this->fdd[$k]['php']);
1066              } else {
1067                  // Simple edit box required

1068                  $len_props = '';
1069                  $maxlen = intval($this->fdd[$k]['maxlen']);
1070                  $size   = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size'] : min($maxlen, 60);
1071                  if ($size > 0) {
1072                      $len_props .= ' size="'.$size.'"';
1073                  }
1074                  if ($maxlen > 0) {
1075                      $len_props .= ' maxlength="'.$maxlen.'"';
1076                  }
1077                  echo '<input class="',$css_class_name,'" ';
1078                  echo ($this->password($k) ? 'type="password"' : 'type="text"');
1079                  echo ($this->readonly($k) ? ' disabled' : '');
1080                  echo ' name="',$this->cgi['prefix']['data'].$this->fds[$k],'"';
1081                  echo $len_props,' value="';
1082                  if($escape) echo htmlspecialchars($this->fdd[$k]['default']);
1083                  else echo $this->fdd[$k]['default'];
1084                  echo '" />';
1085              }
1086              echo '</td>',"\n";
1087              if ($this->guidance) {
1088                  $css_class_name = $this->getCSSclass('help', null, true, $css_postfix);
1089                  $cell_value     = $this->fdd[$k]['help'] ? $this->fdd[$k]['help'] : '&nbsp;';
1090                  echo '<td class="',$css_class_name,'">',$cell_value,'</td>',"\n";
1091              }
1092              echo '</tr>',"\n";
1093          }
1094      } /* }}} */
1095  
1096      function display_copy_change_delete_record() /* {{{ */
1097      {
1098          /*

1099           * For delete or change: SQL SELECT to retrieve the selected record

1100           */
1101  
1102          $qparts['type']   = 'select';
1103          $qparts['select'] = $this->get_SQL_column_list();
1104          $qparts['from']   = $this->get_SQL_join_clause();
1105          $qparts['where']  = '('.$this->fqn($this->key).'='
1106              .$this->key_delim.$this->rec.$this->key_delim.')';
1107  
1108          $res = $this->myquery($this->get_SQL_query($qparts),__LINE__);
1109          if (! ($row = $this->sql_fetch($res))) {
1110              return false;
1111          }
1112          for ($tab = 0, $k = 0; $k < $this->num_fds; $k++) {
1113              if (isset($this->fdd[$k]['tab']) && $this->tabs_enabled() && $k > 0) {
1114                  $tab++;
1115                  echo '</table>',"\n";
1116                  echo '</div>',"\n";
1117                  echo '<div id="'.$this->dhtml['prefix'].'tab',$tab,'">',"\n";
1118                  echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n";
1119              }
1120              if (! $this->displayed[$k]) {
1121                  continue;
1122              }
1123              if ($this->copy_operation() || $this->change_operation()) {
1124                  if ($this->hidden($k)) {
1125                      if ($k != $this->key_num) {
1126                          echo $this->htmlHiddenData($this->fds[$k], $row["qf$k"]);
1127                      }
1128                      continue;
1129                  }
1130                  $css_postfix = @$this->fdd[$k]['css']['postfix'];
1131                  echo '<tr class="',$this->getCSSclass('row', null, 'next', $css_postfix),'">',"\n";
1132                  echo '<td class="',$this->getCSSclass('key', null, true, $css_postfix),'">';
1133                  echo $this->fdd[$k]['name'],'</td>',"\n";
1134                  /* There are two possibilities of readonly fields handling:

1135                     1. Display plain text for readonly timestamps, dates and URLs.

1136                     2. Display disabled input field

1137                     In all cases particular readonly field will NOT be saved. */
1138                  if ($this->readonly($k) && ($this->col_has_datemask($k) || $this->col_has_URL($k))) {
1139                      echo $this->display_delete_field($row, $k);
1140                  } elseif ($this->password($k)) {
1141                      echo $this->display_password_field($row, $k);
1142                  } else {
1143                      echo $this->display_change_field($row, $k);
1144                  }
1145                  if ($this->guidance) {
1146                      $css_class_name = $this->getCSSclass('help', null, true, $css_postfix);
1147                      $cell_value     = $this->fdd[$k]['help'] ? $this->fdd[$k]['help'] : '&nbsp;';
1148                      echo '<td class="',$css_class_name,'">',$cell_value,'</td>',"\n";
1149                  }
1150                  echo '</tr>',"\n";
1151              } elseif ($this->delete_operation() || $this->view_operation()) {
1152                  $css_postfix = @$this->fdd[$k]['css']['postfix'];
1153                  echo '<tr class="',$this->getCSSclass('row', null, 'next', $css_postfix),'">',"\n";
1154                  echo '<td class="',$this->getCSSclass('key', null, true, $css_postfix),'">';
1155                  echo $this->fdd[$k]['name'],'</td>',"\n";
1156                  if ($this->password($k)) {
1157                      echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"';
1158                      echo $this->getColAttributes($k),'>',$this->labels['hidden'],'</td>',"\n";
1159                  } else {
1160                      $this->display_delete_field($row, $k);
1161                  }
1162                  if ($this->guidance) {
1163                      $css_class_name = $this->getCSSclass('help', null, true, $css_postfix);
1164                      $cell_value     = $this->fdd[$k]['help'] ? $this->fdd[$k]['help'] : '&nbsp;';
1165                      echo '<td class="',$css_class_name,'">',$cell_value,'</td>',"\n";
1166                  }
1167                  echo '</tr>',"\n";
1168              }
1169          }
1170      } /* }}} */
1171  
1172      function display_change_field($row, $k) /* {{{ */
1173      {
1174          $css_postfix    = @$this->fdd[$k]['css']['postfix'];
1175          $css_class_name = $this->getCSSclass('input', null, true, $css_postfix);
1176          $escape         = isset($this->fdd[$k]['escape']) ? $this->fdd[$k]['escape'] : true;
1177          echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"';
1178          echo $this->getColAttributes($k),">\n";
1179          if ($this->col_has_values($k)) {
1180              $vals       = $this->set_values($k);
1181              $multiple   = $this->col_has_multiple($k);
1182              $readonly   = $this->readonly($k);
1183              $strip_tags = true;
1184              //$escape     = true;

1185              if ($this->col_has_checkboxes($k) || $this->col_has_radio_buttons($k)) {
1186                  echo $this->htmlRadioCheck($this->cgi['prefix']['data'].$this->fds[$k],
1187                          $css_class_name, $vals, $row["qf$k"], $multiple, $readonly,
1188                          $strip_tags, $escape);
1189              } else {
1190                  echo $this->htmlSelect($this->cgi['prefix']['data'].$this->fds[$k],
1191                          $css_class_name, $vals, $row["qf$k"], $multiple, $readonly,
1192                          $strip_tags, $escape);
1193              }
1194          } elseif (isset($this->fdd[$k]['textarea'])) {
1195              echo '<textarea class="',$css_class_name,'" name="',$this->cgi['prefix']['data'].$this->fds[$k],'"';
1196              echo ($this->readonly($k) ? ' disabled' : '');
1197              if (intval($this->fdd[$k]['textarea']['rows']) > 0) {
1198                  echo ' rows="',$this->fdd[$k]['textarea']['rows'],'"';
1199              }
1200              if (intval($this->fdd[$k]['textarea']['cols']) > 0) {
1201                  echo ' cols="',$this->fdd[$k]['textarea']['cols'],'"';
1202              }
1203              if (isset($this->fdd[$k]['textarea']['wrap'])) {
1204                  echo ' wrap="',$this->fdd[$k]['textarea']['wrap'],'"';
1205              } else {
1206                  echo ' wrap="virtual"';
1207              }
1208              echo '>';
1209              if($escape) echo htmlspecialchars($row["qf$k"]);
1210              else echo $row["qf$k"];
1211              echo '</textarea>',"\n";
1212          } elseif ($this->col_has_php($k)) {
1213              echo include($this->fdd[$k]['php']);
1214          } else {
1215              $len_props = '';
1216              $maxlen = intval($this->fdd[$k]['maxlen']);
1217              $size   = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size'] : min($maxlen, 60);
1218              if ($size > 0) {
1219                  $len_props .= ' size="'.$size.'"';
1220              }
1221              if ($maxlen > 0) {
1222                  $len_props .= ' maxlength="'.$maxlen.'"';
1223              }
1224              echo '<input class="',$css_class_name,'" type="text"';
1225              echo ($this->readonly($k) ? ' disabled' : '');
1226              echo ' name="',$this->cgi['prefix']['data'].$this->fds[$k],'" value="';
1227              if($escape) echo htmlspecialchars($row["qf$k"]);
1228              else echo $row["qf$k"];
1229              echo '"',$len_props,' />',"\n";
1230          }
1231          echo '</td>',"\n";
1232      } /* }}} */
1233  
1234      function display_password_field($row, $k) /* {{{ */
1235      {
1236          $css_postfix = @$this->fdd[$k]['css']['postfix'];
1237          echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"';
1238          echo $this->getColAttributes($k),">\n";
1239          $len_props = '';
1240          $maxlen = intval($this->fdd[$k]['maxlen']);
1241          $size   = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size'] : min($maxlen, 60);
1242          if ($size > 0) {
1243              $len_props .= ' size="'.$size.'"';
1244          }
1245          if ($maxlen > 0) {
1246              $len_props .= ' maxlength="'.$maxlen.'"';
1247          }
1248          echo '<input class="',$this->getCSSclass('value', null, true, $css_postfix),'" type="password"';
1249          echo ($this->readonly($k) ? ' disabled' : '');
1250          echo ' name="',$this->cgi['prefix']['data'].$this->fds[$k],'" value="';
1251          echo htmlspecialchars($row["qf$k"]),'"',$len_props,' />',"\n";
1252          echo '</td>',"\n";
1253      } /* }}} */
1254  
1255      function display_delete_field($row, $k) /* {{{ */
1256      {
1257          $css_postfix    = @$this->fdd[$k]['css']['postfix'];
1258          $css_class_name = $this->getCSSclass('value', null, true, $css_postfix);
1259          echo '<td class="',$css_class_name,'"',$this->getColAttributes($k),">\n";
1260          echo $this->cellDisplay($k, $row, $css_class_name);
1261          echo '</td>',"\n";
1262      } /* }}} */
1263  
1264      /**

1265       * Returns CSS class name

1266       */
1267      function getCSSclass($name, $position  = null, $divider = null, $postfix = null) /* {{{ */
1268      {
1269          static $div_idx = -1;
1270          $elements = array($this->css['prefix'], $name);
1271          if ($this->page_type && $this->css['page_type']) {
1272              if ($this->page_type != 'L' && $this->page_type != 'F') {
1273                  $elements[] = $this->page_types[$this->page_type];
1274              }
1275          }
1276          if ($position && $this->css['position']) {
1277              $elements[] = $position;
1278          }
1279          if ($divider && $this->css['divider']) {
1280              if ($divider === 'next') {
1281                  $div_idx++;
1282                  if ($this->css['divider'] > 0 && $div_idx >= $this->css['divider']) {
1283                      $div_idx = 0;
1284                  }
1285              }
1286              $elements[] = $div_idx;
1287          }
1288          if ($postfix) {
1289              $elements[] = $postfix;
1290          }
1291          return join($this->css['separator'], $elements);
1292      } /* }}} */
1293  
1294      /**

1295       * Returns field cell HTML attributes

1296       */
1297      function getColAttributes($k) /* {{{ */
1298      {
1299          $colattrs = '';
1300          if (isset($this->fdd[$k]['colattrs'])) {
1301              $colattrs .= ' ';
1302              $colattrs .= trim($this->fdd[$k]['colattrs']);
1303          }
1304          if (isset($this->fdd[$k]['nowrap'])) {
1305              $colattrs .= ' nowrap';
1306          }
1307          return $colattrs;
1308      } /* }}} */
1309  
1310      /**

1311       * Substitutes variables in string

1312       * (this is very simple but secure eval() replacement)

1313       */
1314      function substituteVars($str, $subst_ar) /* {{{ */
1315      {
1316          $array = preg_split('/(\\$\w+)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE);
1317          $count = count($array);
1318          for ($i = 1; $i < $count; $i += 2) {
1319              $key = substr($array[$i], 1);
1320              if (isset($subst_ar[$key])) {
1321                  $array[$i] = $subst_ar[$key];
1322              }
1323          }
1324          return join('', $array);
1325      } /* }}} */
1326  
1327      /**

1328       * Print URL

1329       */
1330      function urlDisplay($k, $link_val, $disp_val, $css, $key) /* {{{ */
1331      {
1332          $escape = isset($this->fdd[$k]['escape']) ? $this->fdd[$k]['escape'] : true;
1333          $ret  = '';
1334          $name = $this->fds[$k];
1335          $page = $this->page_name;
1336          $url  = $this->cgi['prefix']['sys'].'rec'.'='.$key.'&'.$this->cgi['prefix']['sys'].'fm'
1337              .'='.$this->fm.'&'.$this->cgi['prefix']['sys'].'fl'.'='.$this->fl;
1338          $url .= '&'.$this->cgi['prefix']['sys'].'qfn'.'='.rawurlencode($this->qfn).$this->qfn;
1339          $url .= '&'.$this->get_sfn_cgi_vars().$this->cgi['persist'];
1340          $ar   = array(
1341                  'key'   => $key,
1342                  'name'  => $name,
1343                  'link'  => $link_val,
1344                  'value' => $disp_val,
1345                  'css'   => $css,
1346                  'page'  => $page,
1347                  'url'   => $url
1348                  );
1349          $urllink = isset($this->fdd[$k]['URL'])
1350              ?  $this->substituteVars($this->fdd[$k]['URL'], $ar)
1351              : $link_val;
1352          $urldisp = isset($this->fdd[$k]['URLdisp'])
1353              ?  $this->substituteVars($this->fdd[$k]['URLdisp'], $ar)
1354              : $disp_val;
1355          $target = isset($this->fdd[$k]['URLtarget'])
1356              ? 'target="'.htmlspecialchars($this->fdd[$k]['URLtarget']).'" '
1357              : '';
1358          $prefix_found  = false;
1359          $postfix_found = false;
1360          $prefix_ar     = @$this->fdd[$k]['URLprefix'];
1361          $postfix_ar    = @$this->fdd[$k]['URLpostfix'];
1362          is_array($prefix_ar)  || $prefix_ar  = array($prefix_ar);
1363          is_array($postfix_ar) || $postfix_ar = array($postfix_ar);
1364          foreach ($prefix_ar as $prefix) {
1365              if (! strncmp($prefix, $urllink, strlen($prefix))) {
1366                  $prefix_found = true;
1367                  break;
1368              }
1369          }
1370          foreach ($postfix_ar as $postfix) {
1371              if (! strncmp($postfix, $urllink, strlen($postfix))) {
1372                  $postfix_found = true;
1373                  break;
1374              }
1375          }
1376          $prefix_found  || $urllink = array_shift($prefix_ar).$urllink;
1377          $postfix_found || $urllink = $urllink.array_shift($postfix_ar);
1378          if (strlen($urllink) <= 0 || strlen($urldisp) <= 0) {
1379              $ret = '&nbsp;';
1380          } else {
1381              if ($escape) {
1382                  $urldisp = htmlspecialchars($urldisp);
1383              }
1384              $urllink = htmlspecialchars($urllink);
1385              $ret = '<a '.$target.'class="'.$css.'" href="'.$urllink.'">'.$urldisp.'</a>';
1386          }
1387          return $ret;
1388      } /* }}} */
1389  
1390      function cellDisplay($k, $row, $css) /* {{{ */
1391      {
1392          $escape  = isset($this->fdd[$k]['escape']) ? $this->fdd[$k]['escape'] : true;
1393          $key_rec = $row['qf'.$this->key_num];
1394          if (@$this->fdd[$k]['datemask']) {
1395              $value = intval($row["qf$k".'_timestamp']);
1396              $value = $value ? @date($this->fdd[$k]['datemask'], $value) : '';
1397          } else if (@$this->fdd[$k]['strftimemask']) {
1398              $value = intval($row["qf$k".'_timestamp']);
1399              $value = $value ? @strftime($this->fdd[$k]['strftimemask'], $value) : '';
1400          } else if ($this->is_values2($k, $row["qf$k"])) {
1401              $value = $row['qf'.$k.'_idx'];
1402              if ($this->fdd[$k]['select'] == 'M') {
1403                  $value_ar  = explode(',', $value);
1404                  $value_ar2 = array();
1405                  foreach ($value_ar as $value_key) {
1406                      if (isset($this->fdd[$k]['values2'][$value_key])) {
1407                          $value_ar2[$value_key] = $this->fdd[$k]['values2'][$value_key];
1408                          $escape = false;
1409                      }
1410                  }
1411                  $value = join(', ', $value_ar2);
1412              } else {
1413                  if (isset($this->fdd[$k]['values2'][$value])) {
1414                      $value  = $this->fdd[$k]['values2'][$value];
1415                      $escape = false;
1416                  }
1417              }
1418          } elseif (isset($this->fdd[$k]['values2'][$row["qf$k"]])) {
1419              $value = $this->fdd[$k]['values2'][$row["qf$k"]];
1420          } else {
1421              $value = $row["qf$k"];
1422          }
1423          $original_value = $value;
1424          if (@$this->fdd[$k]['strip_tags']) {
1425              $value = strip_tags($value);
1426          }
1427          if ($num_ar = @$this->fdd[$k]['number_format']) {
1428              if (! is_array($num_ar)) {
1429                  $num_ar = array($num_ar);
1430              }
1431              if (count($num_ar) == 1) {
1432                  list($nbDec) = $num_ar;
1433                  $value = number_format($value, $nbDec);
1434              } else if (count($num_ar) == 3) {
1435                  list($nbDec, $decPoint, $thSep) = $num_ar;
1436                  $value = number_format($value, $nbDec, $decPoint, $thSep);
1437              }
1438          }
1439          if (intval($this->fdd[$k]['trimlen']) > 0 && strlen($value) > $this->fdd[$k]['trimlen']) {
1440              $value = ereg_replace("[\r\n\t ]+",' ',$value);
1441              $value = substr($value, 0, $this->fdd[$k]['trimlen'] - 3).'...';
1442          }
1443          if (@$this->fdd[$k]['mask']) {
1444              $value = sprintf($this->fdd[$k]['mask'], $value);
1445          }
1446          if ($this->col_has_php($k)) {
1447              return include($this->fdd[$k]['php']);
1448          }
1449          if ($this->col_has_URL($k)) {
1450              return $this->urlDisplay($k, $original_value, $value, $css, $key_rec);
1451          }
1452          if (strlen($value) <= 0) {
1453              return '&nbsp;';
1454          }
1455          if ($escape) {
1456              $value = htmlspecialchars($value);
1457          }
1458          return nl2br($value);
1459      } /* }}} */
1460  
1461      /**

1462       * Creates HTML submit input element

1463       *

1464       * @param   name            element name

1465       * @param   label           key in the language hash used as label

1466       * @param   css_class_name  CSS class name

1467       * @param   js_validation   if add JavaScript validation subroutine to button

1468       * @param   disabled        if mark the button as disabled

1469       * @param   js      any extra text in tags

1470       */
1471      function htmlSubmit($name, $label, $css_class_name, $js_validation = true, $disabled = false, $js = NULL) /* {{{ */
1472      {
1473          // Note that <input disabled> isn't valid HTML, but most browsers support it

1474          if($disabled == -1) return;
1475          $markdisabled = $disabled ? ' disabled' : '';
1476          $ret = '<input'.$markdisabled.' type="submit" class="'.$css_class_name
1477              .'" name="'.$this->cgi['prefix']['sys'].ltrim($markdisabled).$name
1478              .'" value="'.(isset($this->labels[$label]) ? $this->labels[$label] : $label);
1479          if ($js_validation) {
1480              $ret .= '" onclick="return '.$this->js['prefix'].'form_control(this.form);';
1481          }
1482          $ret .='"';
1483          if(isset($js)) $ret .= ' '.$js;
1484          $ret .= ' />';
1485          return $ret;
1486      } /* }}} */
1487  
1488      /**

1489       * Creates HTML hidden input element

1490       *

1491       * @param   name    element name

1492       * @param   value   value

1493       */
1494  
1495      function htmlHiddenSys($name, $value) /* {{{ */
1496      {
1497          return $this->htmlHidden($this->cgi['prefix']['sys'].$name, $value);
1498      } /* }}} */
1499  
1500      function htmlHiddenData($name, $value) /* {{{ */
1501      {
1502          return $this->htmlHidden($this->cgi['prefix']['data'].$name, $value);
1503      } /* }}} */
1504  
1505      function htmlHidden($name, $value) /* {{{ */
1506      {
1507          return '<input type="hidden" name="'.htmlspecialchars($name)
1508              .'" value="'.htmlspecialchars($value).'" />'."\n";
1509      } /* }}} */
1510  
1511      /**

1512       * Creates HTML select element (tag)

1513       *

1514       * @param   name        element name

1515       * @param   css         CSS class name

1516       * @param   kv_array    key => value array

1517       * @param   selected    selected key (it can be single string, array of

1518       *                      keys or multiple values separated by comma)

1519       * @param   multiple    bool for multiple selection

1520       * @param   readonly    bool for readonly/disabled selection

1521       * @param   strip_tags  bool for stripping tags from values

1522       * @param   escape      bool for HTML escaping values

1523       * @param   js      string to be in the <select >, ususally onchange='..';

1524       */
1525      function htmlSelect($name, $css, $kv_array, $selected = null, /* ...) {{{ */
1526              /* booleans: */ $multiple = false, $readonly = false, $strip_tags = false, $escape = true, $js = NULL)
1527      {
1528          $ret = '<select class="'.htmlspecialchars($css).'" name="'.htmlspecialchars($name);
1529          if ($multiple) {
1530              $ret  .= '[]" multiple size="'.$this->multiple;
1531              if (! is_array($selected) && $selected !== null) {
1532                  $selected = explode(',', $selected);
1533              }
1534          }
1535          $ret .= '"'.($readonly ? ' disabled ' : ' ').$js.">\n";
1536          if (! is_array($selected)) {
1537              $selected = $selected === null ? array() : array((string)$selected);
1538          } else {
1539              foreach($selected as $val) $selecte2[]=(string)$val;
1540              $selected = $selected2;
1541          }
1542          $found = false;
1543          foreach ($kv_array as $key => $value) {
1544              $ret .= '<option value="'.htmlspecialchars($key).'"';
1545              if ((! $found || $multiple) && in_array((string)$key, $selected, 1)
1546                      || (count($selected) == 0 && ! $found && ! $multiple)) {
1547                  $ret  .= ' selected="selected"';
1548                  $found = true;
1549              }
1550              $strip_tags && $value = strip_tags($value);
1551              $escape     && $value = htmlspecialchars($value);
1552              $ret .= '>'.$value.'</option>'."\n";
1553          }
1554          $ret .= '</select>';
1555          return $ret;
1556      } /* }}} */
1557  
1558      /**

1559       * Creates HTML checkboxes or radio buttons

1560       *

1561       * @param   name        element name

1562       * @param   css         CSS class name

1563       * @param   kv_array    key => value array

1564       * @param   selected    selected key (it can be single string, array of

1565       *                      keys or multiple values separated by comma)

1566       * @param   multiple    bool for multiple selection (checkboxes)

1567       * @param   readonly    bool for readonly/disabled selection

1568       * @param   strip_tags  bool for stripping tags from values

1569       * @param   escape      bool for HTML escaping values

1570       * @param   js      string to be in the <select >, ususally onchange='..';

1571       */
1572      function htmlRadioCheck($name, $css, $kv_array, $selected = null, /* ...) {{{ */
1573              /* booleans: */ $multiple = false, $readonly = false, $strip_tags = false, $escape = true, $js = NULL)
1574      {
1575          $ret = '';
1576          if ($multiple) {
1577              if (! is_array($selected) && $selected !== null) {
1578                  $selected = explode(',', $selected);
1579              }
1580          }
1581          if (! is_array($selected)) {
1582              $selected = $selected === null ? array() : array($selected);
1583          }
1584          $found = false;
1585          foreach ($kv_array as $key => $value) {
1586              $ret .= '<input type="'.($multiple ? 'checkbox' : 'radio').'" name="';
1587              $ret .= htmlspecialchars($name).'[]" value="'.htmlspecialchars($key).'"';
1588              if ((! $found || $multiple) && in_array((string) $key, $selected, 1)
1589                      || (count($selected) == 0 && ! $found && ! $multiple)) {
1590                  $ret  .= ' checked';
1591                  $found = true;
1592              }
1593              if ($readonly) {
1594                  $ret .= ' disabled';
1595              }
1596              $strip_tags && $value = strip_tags($value);
1597              $escape     && $value = htmlspecialchars($value);
1598              $ret .= '>'.$value.'<br>'."\n";
1599          }
1600          return $ret;
1601      } /* }}} */
1602  
1603      /**

1604       * Returns original variables HTML code for use in forms or links.

1605       *

1606       * @param   mixed   $origvars       string or array of original varaibles

1607       * @param   string  $method         type of method ("POST" or "GET")

1608       * @param   mixed   $default_value  default value of variables

1609       *                                  if null, empty values will be skipped

1610       * @return                          get HTML code of original varaibles

1611       */
1612      function get_origvars_html($origvars, $method = 'post', $default_value = '') /* {{{ */
1613      {
1614          $ret    = '';
1615          $method = strtoupper($method);
1616          if ($method == 'POST') {
1617              if (! is_array($origvars)) {
1618                  $new_origvars = array();
1619                  foreach (explode('&', $origvars) as $param) {
1620                      $parts = explode('=', $param, 2);
1621                      if (! isset($parts[1])) {
1622                          $parts[1] = $default_value;
1623                      }
1624                      if (strlen($parts[0]) <= 0) {
1625                          continue;
1626                      }
1627                      $new_origvars[$parts[0]] = $parts[1];
1628                  }
1629                  $origvars =& $new_origvars;
1630              }
1631              foreach ($origvars as $key => $val) {
1632                  if (strlen($val) <= 0 && $default_value === null) {
1633                      continue;
1634                  }
1635                  $key = rawurldecode($key);
1636                  $val = rawurldecode($val);
1637                  $ret .= $this->htmlHidden($key, $val);
1638              }
1639          } else if (! strncmp('GET', $method, 3)) {
1640              if (! is_array($origvars)) {
1641                  $ret .= $origvars;
1642              } else {
1643                  foreach ($origvars as $key => $val) {
1644                      if (strlen($val) <= 0 && $default_value === null) {
1645                          continue;
1646                      }
1647                      $ret == '' || $ret .= '&amp;';
1648                      $ret .= htmlspecialchars(rawurlencode($key));
1649                      $ret .= '=';
1650                      $ret .= htmlspecialchars(rawurlencode($val));
1651                  }
1652              }
1653              if ($method[strlen($method) - 1] == '+') {
1654                  $ret = "?$ret";
1655              }
1656          } else {
1657              trigger_error('Unsupported Platon::get_origvars_html() method: '
1658                      .$method, E_USER_ERROR);
1659          }
1660          return $ret;
1661      } /* }}} */
1662  
1663      function get_sfn_cgi_vars($alternative_sfn = null) /* {{{ */
1664      {
1665          if ($alternative_sfn === null) { // FAST! (cached return value)
1666              static $ret = null;
1667              $ret == null && $ret = $this->get_sfn_cgi_vars($this->sfn);
1668              return $ret;
1669          }
1670          $ret = '';
1671          $i   = 0;
1672          foreach ($alternative_sfn as $val) {
1673              $ret != '' && $ret .= '&';
1674              $ret .= rawurlencode($this->cgi['prefix']['sys'].'sfn')."[$i]=".rawurlencode($val);
1675              $i++;
1676          }
1677          return $ret;
1678      } /* }}} */
1679  
1680      function get_default_cgi_prefix($type) /* {{{ */
1681      {
1682          switch ($type) {
1683              case 'operation':   return 'PME_op_';
1684              case 'sys':         return 'PME_sys_';
1685              case 'data':        return 'PME_data_';
1686          }
1687          return '';
1688      } /* }}} */
1689  
1690      function get_sys_cgi_var($name, $default_value = null) /* {{{ */
1691      {
1692          if (isset($this)) {
1693              return $this->get_cgi_var($this->cgi['prefix']['sys'].$name, $default_value);
1694          }
1695          return phpMyEdit::get_cgi_var(phpMyEdit::get_default_cgi_prefix('sys').$name, $default_value);
1696      } /* }}} */
1697  
1698      function get_data_cgi_var($name, $default_value = null) /* {{{ */
1699      {
1700          if (isset($this)) {
1701              return $this->get_cgi_var($this->cgi['prefix']['data'].$name, $default_value);
1702          }
1703          return phpMyEdit::get_cgi_var(phpMyEdit::get_default_cgi_prefix('data').$name, $default_value);
1704      } /* }}} */
1705  
1706      function get_cgi_var($name, $default_value = null) /* {{{ */
1707      {
1708          if (isset($this) && isset($this->cgi['overwrite'][$name])) {
1709              return $this->cgi['overwrite'][$name];
1710          }
1711  
1712          static $magic_quotes_gpc = null;
1713          if ($magic_quotes_gpc === null) {
1714              $magic_quotes_gpc = get_magic_quotes_gpc();
1715          }
1716          $var = @$_GET[$name];
1717          if (! isset($var)) {
1718              $var = @$_POST[$name];
1719          }
1720          if (isset($var)) {
1721              if ($magic_quotes_gpc) {
1722                  if (is_array($var)) {
1723                      foreach (array_keys($var) as $key) {
1724                          $var[$key] = stripslashes($var[$key]);
1725                      }
1726                  } else {
1727                      $var = stripslashes($var);
1728                  }
1729              }
1730          } else {
1731              $var = @$default_value;
1732          }
1733          if (isset($this) && $var === null && isset($this->cgi['append'][$name])) {
1734              return $this->cgi['append'][$name];
1735          }
1736          return $var;
1737      } /* }}} */
1738  
1739      function get_server_var($name) /* {{{ */
1740      {
1741          if (isset($_SERVER[$name])) {
1742              return $_SERVER[$name];
1743          }
1744          global $HTTP_SERVER_VARS;
1745          if (isset($HTTP_SERVER_VARS[$name])) {
1746              return $HTTP_SERVER_VARS[$name];
1747          }
1748          global $$name;
1749          if (isset($$name)) {
1750              return $$name;
1751          }
1752          return null;
1753      } /* }}} */
1754  
1755      /*

1756       * Debug functions

1757       */
1758  
1759      function print_get_vars ($miss = 'No GET variables found') // debug only /* {{{ */
1760      {
1761          // we parse form GET variables

1762          if (is_array($_GET)) {
1763              echo "<p> Variables per GET ";
1764              foreach ($_GET as $k => $v) {
1765                  if (is_array($v)) {
1766                      foreach ($v as $akey => $aval) {
1767                          // $_GET[$k][$akey] = strip_tags($aval);

1768                          // $$k[$akey] = strip_tags($aval);

1769                          echo "$k\[$akey\]=$aval   ";
1770                      }
1771                  } else {
1772                      // $_GET[$k] = strip_tags($val);

1773                      // $$k = strip_tags($val);

1774                      echo "$k=$v   ";
1775                  }
1776              }
1777              echo '</p>';
1778          } else {
1779              echo '<p>';
1780              echo $miss;
1781              echo '</p>';
1782          }
1783      } /* }}} */
1784  
1785      function print_post_vars($miss = 'No POST variables found')  // debug only /* {{{ */
1786      {
1787          global $_POST;
1788          // we parse form POST variables

1789          if (is_array($_POST)) {
1790              echo "<p>Variables per POST ";
1791              foreach ($_POST as $k => $v) {
1792                  if (is_array($v)) {
1793                      foreach ($v as $akey => $aval) {
1794                          // $_POST[$k][$akey] = strip_tags($aval);

1795                          // $$k[$akey] = strip_tags($aval);

1796                          echo "$k\[$akey\]=$aval   ";
1797                      }
1798                  } else {
1799                      // $_POST[$k] = strip_tags($val);

1800                      // $$k = strip_tags($val);

1801                      echo "$k=$v   ";
1802                  }
1803              }
1804              echo '</p>';
1805          } else {
1806              echo '<p>';
1807              echo $miss;
1808              echo '</p>';
1809          }
1810      } /* }}} */
1811  
1812      function print_vars ($miss = 'Current instance variables')  // debug only /* {{{ */
1813      {
1814          echo "$miss   ";
1815          echo 'page_name=',$this->page_name,'   ';
1816          echo 'hn=',$this->hn,'   ';
1817          echo 'un=',$this->un,'   ';
1818          echo 'pw=',$this->pw,'   ';
1819          echo 'db=',$this->db,'   ';
1820          echo 'dbp=',$this->dbp,'   ';
1821          echo 'dbh=',$this->dbh,'   ';
1822          echo 'tb=',$this->tb,'   ';
1823          echo 'key=',$this->key,'   ';
1824          echo 'key_type=',$this->key_type,'   ';
1825          echo 'inc=',$this->inc,'   ';
1826          echo 'options=',$this->options,'   ';
1827          echo 'fdd=',$this->fdd,'   ';
1828          echo 'fl=',$this->fl,'   ';
1829          echo 'fm=',$this->fm,'   ';
1830          echo 'sfn=',htmlspecialchars($this->get_sfn_cgi_vars()),'   ';
1831          echo 'qfn=',$this->qfn,'   ';
1832          echo 'sw=',$this->sw,'   ';
1833          echo 'rec=',$this->rec,'   ';
1834          echo 'navop=',$this->navop,'   ';
1835          echo 'saveadd=',$this->saveadd,'   ';
1836          echo 'moreadd=',$this->moreadd,'   ';
1837          echo 'canceladd=',$this->canceladd,'   ';
1838          echo 'savechange=',$this->savechange,'   ';
1839          echo 'morechange=',$this->morechange,'   ';
1840          echo 'cancelchange=',$this->cancelchange,'   ';
1841          echo 'savecopy=',$this->savecopy,'   ';
1842          echo 'cancelcopy=',$this->cancelcopy,'   ';
1843          echo 'savedelete=',$this->savedelete,'   ';
1844          echo 'canceldelete=',$this->canceldelete,'   ';
1845          echo 'cancelview=',$this->cancelview,'   ';
1846          echo 'operation=',$this->operation,'   ';
1847          echo "\n";
1848      } /* }}} */
1849  
1850      /*

1851       * Display buttons at top and bottom of page

1852       */
1853      function display_list_table_buttons($position, $listall = false) /* {{{ */
1854      {
1855          if (($but_str = $this->display_buttons($position)) === null)
1856              return;
1857          if($position == 'down') echo '<hr size="1" class="'.$this->getCSSclass('hr', 'down').'" />'."\n";
1858          echo '<table summary="navigation" class="',$this->getCSSclass('navigation', $position),'">',"\n";
1859          echo '<tr class="',$this->getCSSclass('navigation', $position),'">',"\n";
1860          echo '<td class="',$this->getCSSclass('buttons', $position),'">',"\n";
1861          echo $but_str,'</td>',"\n";
1862          // Message is now written here

1863          if (strlen(@$this->message) > 0) {
1864              echo '<td class="',$this->getCSSclass('message', $position),'">',$this->message,'</td>',"\n";
1865          }
1866          if($this->display['num_pages'] || $this->display['num_records'])
1867              echo '<td class="',$this->getCSSclass('stats', $position),'">',"\n";
1868          if($this->display['num_pages']) {
1869              if ($listall) {
1870                  echo $this->labels['Page'],':&nbsp;1&nbsp;',$this->labels['of'],'&nbsp;1';
1871              } else {
1872                  $current_page = intval($this->fm / $this->inc) + 1;
1873                  $total_pages  = max(1, ceil($this->total_recs / abs($this->inc)));
1874                  echo $this->labels['Page'],':&nbsp;',$current_page;
1875                  echo '&nbsp;',$this->labels['of'],'&nbsp;',$total_pages;
1876              }
1877          }
1878          if($this->display['num_records'])
1879              echo '&nbsp; ',$this->labels['Records'],':&nbsp;',$this->total_recs;
1880          if($this->display['num_pages'] || $this->display['num_records']) echo '</td>';
1881          echo '</tr></table>',"\n";
1882          if($position == 'up') echo '<hr size="1" class="'.$this->getCSSclass('hr', 'up').'" />'."\n";
1883      } /* }}} */
1884  
1885      /*

1886       * Display buttons at top and bottom of page

1887       */
1888      function display_record_buttons($position) /* {{{ */
1889      {
1890          if (($but_str = $this->display_buttons($position)) === null)
1891              return;
1892          if ($position == 'down') {
1893              if ($this->tabs_enabled()) $this->display_tab_labels('down');
1894              echo '<hr size="1" class="',$this->getCSSclass('hr', 'down'),'" />',"\n";
1895          }
1896          echo '<table summary="navigation" class="',$this->getCSSclass('navigation', $position),'">',"\n";
1897          echo '<tr class="',$this->getCSSclass('navigation', $position),'">',"\n";
1898          echo '<td class="',$this->getCSSclass('buttons', $position),'">',"\n";
1899          echo $but_str,'</td>',"\n";
1900          // Message is now written here

1901          //echo '</td>',"\n";

1902          if (strlen(@$this->message) > 0) {
1903              echo '<td class="',$this->getCSSclass('message', $position),'">',$this->message,'</td>',"\n";
1904          }
1905          echo '</tr></table>',"\n";
1906          if ($position == 'up') {
1907              if ($this->tabs_enabled()) $this->display_tab_labels('up');
1908              echo '<hr size="1" class="',$this->getCSSclass('hr', 'up'),'" />',"\n";
1909          }
1910      } /* }}} */
1911  
1912      function display_buttons($position) /* {{{ */
1913      {
1914          $nav_fnc = 'nav_'.$position;
1915          if(! $this->$nav_fnc())
1916              return;
1917          $buttons = (is_array($this->buttons[$this->page_type][$position]))
1918              ? $this->buttons[$this->page_type][$position]
1919              : $this->default_buttons[$this->page_type];
1920          foreach ($buttons as $name) {
1921              $ret .= $this->display_button($name, $position)."\n";
1922          }
1923          return $ret;
1924      } /* }}} */
1925  
1926      function display_button($name, $position = 'up') /* {{{ */
1927      {
1928          if (is_array($name)) {
1929              if (isset($name['code'])) return $name['code'];
1930              return $this->htmlSubmit($name['name'], $name['value'], $name['css'], $name['js_validation'], $name['disabled'], $name['js']);
1931          }
1932          $disabled = 1; // show disabled by default

1933          if ($name[0] == '+') { $name = substr($name, 1); $disabled =  0; } // always show disabled as enabled

1934          if ($name[0] == '-') { $name = substr($name, 1); $disabled = -1; } // don't show disabled

1935          if ($name == 'cancel') {
1936              return $this->htmlSubmit('cancel'.$this->page_types[$this->page_type], 'Cancel',
1937                      $this->getCSSclass('cancel', $position), false);
1938          }
1939          if (in_array($name, array('add','view','change','copy','delete'))) {
1940              $enabled_fnc = $name.'_enabled';
1941              $enabled     = $this->$enabled_fnc();
1942              if ($name != 'add' && ! $this->total_recs && strstr('LF', $this->page_type))
1943                  $enabled = false;
1944              return $this->htmlSubmit('operation', ucfirst($name),
1945                      $this->getCSSclass($name, $position), false, $enabled ? 0 : $disabled);
1946          }
1947          if ($name == 'savedelete') {
1948              $enabled     = $this->delete_enabled();
1949              $js = 'onclick="return confirm(\''.$this->labels['Delete'].' ?\');"';
1950              return $this->htmlSubmit('savedelete', 'Delete',
1951                      $this->getCSSclass('save', $position), false, $enabled ? 0 : $disabled, $js);
1952          }
1953          if (in_array($name, array('save','more'))) {
1954              $validation = true; // if js validation

1955              if     ($this->page_type == 'D' && $name == 'save' ) { $value = 'Delete'; $validation = false; }
1956              elseif ($this->page_type == 'C' && $name == 'more' ) { $value = 'Apply'; }
1957              else $value = ucfirst($name);
1958              return $this->htmlSubmit($name.$this->page_types[$this->page_type], $value,
1959                      $this->getCSSclass($name, $position), $validation);
1960          }
1961          $listall = $this->inc <= 0;
1962          if ($listall) {
1963              $disabledprev = true;
1964              $disablednext = true;
1965              $total_pages  = 1;
1966              $current_page = 1;
1967          } else {
1968              $disabledprev = $this->fm <= 0;
1969              $disablednext =  $this->fm + $this->inc >= $this->total_recs;
1970              $total_pages  = max(1, ceil($this->total_recs / abs($this->inc)));
1971              $current_page = ceil($this->fm / abs($this->inc)); // must + 1

1972          }
1973          $disabledfirst = $disabledprev;
1974          $disabledlast  = $disablednext;
1975          // some statistics first

1976          if ($name == 'total_pages') return $total_pages;
1977          if ($name == 'current_page') return ($current_page+1);
1978          if ($name == 'total_recs') return ($this->total_recs);
1979          // now some goto buttons/dropdowns/inputs...

1980          if ($name == 'goto_text') {
1981              $ret = '<input type="text" class="'.$this->getCSSclass('gotopn', $position).'"';
1982              $ret .= ' name="'.$this->cgi['prefix']['sys'].'navpn'.$position.'" value="'.($current_page+1).'"';
1983              $ret .= ' size="'.(strlen($total_pages)+1).'" maxlength="'.(strlen($total_pages)+1).'"';
1984              // TODO some js here.... on enter submit, on click erase ?...

1985              $ret .=' oneypress="return PE_filter_handler(this.form, event);" />';
1986              return $ret;
1987          }
1988          if ($name == 'goto_combo') {
1989              $disabledgoto = !($listall || ($disablednext && $disabledprev)) ? '' : ' disabled';
1990              if ($disablegoto != '' && $disabled < 0) return;
1991              $kv_array = array();
1992              for ($i = 0; $i < $total_pages; $i++) {
1993                  $kv_array[$this->inc * $i] = $i + 1;
1994              }
1995              // TODO: add onchange="return this.form.submit();" DONE ???

1996              return $this->htmlSelect($this->cgi['prefix']['sys'].ltrim($disabledgoto).'navfm'.$position,
1997                      $this->getCSSclass('goto', $position), $kv_array, (string)$this->fm, false, $disabledgoto,
1998                      false, true, 'onchange="return this.form.submit();"');
1999          }
2000          if ($name == 'goto') {
2001              return $this->htmlSubmit('navop', 'Go to', $this->getCSSclass('goto', $position),
2002                      false, ($listall || ($disablednext && $disabledprev)) ? $disabled : 0);
2003          }
2004          if (in_array($name, array('first','prev','next','last','<<','<','>','>>'))) {
2005              $disabled_var = 'disabled'.$name;
2006              $name2 = $name;
2007              if (strlen($name) <= 2) {
2008                  $nav_values = array('<<' => 'first', '<' => 'prev', '>' => 'next', '>>' => 'last');
2009                  $disabled_var = 'disabled'.$nav_values[$name];
2010                  $name2 = $nav_values[$name];
2011              }
2012              return $this->htmlSubmit('navop', ucfirst($name),
2013                      $this->getCSSclass($name2, $position), false, $$disabled_var ? $disabled : 0);
2014          }
2015          if(isset($this->labels[$name])) return $this->labels[$name];
2016          return $name;
2017      } /* }}} */
2018  
2019      function number_of_recs() /* {{{ */
2020      {
2021          $count_parts = array(
2022                  'type'   => 'select',
2023                  'select' => 'count(*)',
2024                  'from'   => $this->get_SQL_join_clause(),
2025                  'where'  => $this->get_SQL_where_from_query_opts());
2026          $res = $this->myquery($this->get_SQL_main_list_query($count_parts), __LINE__);
2027          $row = $this->sql_fetch($res, 'n');
2028          $this->total_recs = $row[0];
2029      } /* }}} */
2030  
2031      /*

2032       * Table Page Listing

2033       */
2034      function list_table() /* {{{ */
2035      {
2036          if ($this->fm == '') {
2037              $this->fm = 0;
2038          }
2039          $this->fm = $this->navfm;
2040          if ($this->prev_operation()) {
2041              $this->fm = $this->fm - $this->inc;
2042              if ($this->fm < 0) {
2043                  $this->fm = 0;
2044              }
2045          }
2046          if ($this->first_operation()) {
2047              $this->fm = 0;
2048          } // last operation must be performed below, after retrieving total_recs

2049          if ($this->next_operation()) {
2050              $this->fm += $this->inc;
2051          }
2052          $this->number_of_recs();
2053          if ($this->last_operation() || $this->fm > $this->total_recs) { // if goto_text is badly set
2054              $this->fm = (int)(($this->total_recs - 1)/$this->inc)*$this->inc;
2055          }
2056          // If sort sequence has changed, restart listing

2057          $this->qfn != $this->prev_qfn && $this->fm = 0;
2058          if (0) { // DEBUG
2059              echo 'qfn vs. prev_qfn comparsion ';
2060              echo '[<b>',htmlspecialchars($this->qfn),'</b>]';
2061              echo '[<b>',htmlspecialchars($this->prev_qfn),'</b>]<br />';
2062              echo 'comparsion <u>',($this->qfn == $this->prev_qfn ? 'proved' : 'failed'),'</u>';
2063              echo '<hr size="1" />';
2064          }
2065          /*

2066           * If user is allowed to Change/Delete records, we need an extra column

2067           * to allow users to select a record

2068           */
2069          $select_recs = $this->key != '' &&
2070              ($this->change_enabled() || $this->delete_enabled() || $this->view_enabled());
2071          // Are we doing a listall?

2072          $listall = $this->inc <= 0;
2073          /*

2074           * Display the SQL table in an HTML table

2075           */
2076          $this->form_begin();
2077          echo $this->get_origvars_html($this->get_sfn_cgi_vars());
2078          echo $this->htmlHiddenSys('fl', $this->fl);
2079          // Display buttons at top and/or bottom of page.

2080          $this->display_list_table_buttons('up', $listall);
2081          if ($this->cgi['persist'] != '') {
2082              echo $this->get_origvars_html($this->cgi['persist']);
2083          }
2084          if (! $this->filter_operation()) {
2085              echo $this->get_origvars_html($this->qfn);
2086          }
2087          echo $this->htmlHiddenSys('qfn', $this->qfn);
2088          echo $this->htmlHiddenSys('fm', $this->fm);
2089          echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n";
2090          echo '<tr class="',$this->getCSSclass('header'),'">',"\n";
2091          /*

2092           * System (navigation, selection) columns counting

2093           */
2094          $sys_cols  = 0;
2095          $sys_cols += intval($this->filter_enabled() || $select_recs);
2096          if ($sys_cols > 0) {
2097              $sys_cols += intval($this->nav_buttons()
2098                      && ($this->nav_text_links() || $this->nav_graphic_links()));
2099          }
2100          /*

2101           * We need an initial column(s) (sys columns)

2102           * if we have filters, Changes or Deletes enabled

2103           */
2104          if ($sys_cols) {
2105              echo '<th class="',$this->getCSSclass('header'),'" colspan="',$sys_cols,'">';
2106              if ($this->filter_enabled()) {
2107                  if ($this->filter_operation()) {
2108                      echo $this->htmlSubmit('sw', 'Hide', $this->getCSSclass('hide'), false);
2109                      echo $this->htmlSubmit('sw', 'Clear', $this->getCSSclass('clear'), false);
2110                  } else {
2111                      echo $this->htmlSubmit('sw', 'Search', $this->getCSSclass('search'), false);
2112                  }
2113              } else {
2114                  echo '&nbsp;';
2115              }
2116              echo '</th>',"\n";
2117          }
2118          for ($k = 0; $k < $this->num_fds; $k++) {
2119              $fd = $this->fds[$k];
2120              if (! $this->displayed[$k]) {
2121                  continue;
2122              }
2123              $css_postfix    = @$this->fdd[$k]['css']['postfix'];
2124              $css_class_name = $this->getCSSclass('header', null, null, $css_postfix);
2125              $fdn = $this->fdd[$fd]['name'];
2126              if (! $this->fdd[$fd]['sort'] || $this->password($fd)) {
2127                  echo '<th class="',$css_class_name,'">',$fdn,'</th>',"\n";
2128              } else {
2129                  // Clicking on the current sort field reverses the sort order

2130                  $new_sfn = $this->sfn;
2131                  array_unshift($new_sfn, in_array("$k", $new_sfn, 1) ? "-$k" : $k);
2132                  echo '<th class="',$css_class_name,'">';
2133  
2134                  // INIZIO patch per GAzie

2135                  echo '<div onclick="GAz_sys_form.'.$this->cgi['prefix']['sys'].'fm.value=0; '.
2136                                     'GAz_sys_form.'.$this->cgi['prefix']['sys'].'fl.value='.$this->fl.'; '.
2137                                     'GAz_sys_form.elements[\''.$this->cgi['prefix']['sys'].'sfn[0]\'].value='.$new_sfn[0].'; '.
2138                                     'GAz_sys_form.submit();'.'" class="',$css_class_name,'" style="cursor:pointer;">';
2139                  echo $fdn;
2140                  echo '</div>';
2141                  // FINE patch per GAzie

2142  
2143  
2144  /*              --- VECCHIO METODO CESTINATO

2145                      FRANCAMENTE NON CAPISCO L'UTILITA' DI CREARE UN FILE php PER OGNI TABELLA!

2146  

2147                  echo '<a class="',$css_class_name,'" href="';

2148                  echo htmlspecialchars($this->page_name.'?'.$this->cgi['prefix']['sys'].'fm'.'=0'

2149                          .'&'.$this->cgi['prefix']['sys'].'fl'.'='.$this->fl

2150                          .'&'.$this->cgi['prefix']['sys'].'qfn'.'='.rawurlencode($this->qfn).$this->qfn

2151                          .'&'.$this->get_sfn_cgi_vars($new_sfn).$this->cgi['persist']);

2152                  echo '">',$fdn,'</a>

2153  */
2154                  echo '</th>',"\n";
2155              }
2156          }
2157          echo '</tr>',"\n";
2158  
2159          /*

2160           * Prepare the SQL Query from the data definition file

2161           */
2162          $qparts['type']   = 'select';
2163          $qparts['select'] = $this->get_SQL_column_list();
2164          // Even if the key field isn't displayed, we still need its value

2165          if ($select_recs) {
2166              if (!in_array ($this->key, $this->fds)) {
2167                  $qparts['select'] .= ','.$this->fqn($this->key);
2168              }
2169          }
2170          $qparts['from']  = $this->get_SQL_join_clause();
2171          $qparts['where'] = $this->get_SQL_where_from_query_opts();
2172          // build up the ORDER BY clause

2173          if (isset($this->sfn)) {
2174              $sort_fields   = array();
2175              $sort_fields_w = array();
2176              foreach ($this->sfn as $field) {
2177                  if ($field[0] == '-') {
2178                      $field = substr($field, 1);
2179                      $desc  = true;
2180                  } else {
2181                      $field = $field;
2182                      $desc  = false;
2183                  }
2184                  $sort_field   = $this->fqn($field);
2185                  $sort_field_w = $this->fdd[$field]['name'];
2186                  $this->col_has_sql($field) && $sort_field_w .= ' (sql)';
2187                  if ($desc) {
2188                      $sort_field   .= ' DESC';
2189                      $sort_field_w .= ' '.$this->labels['descending'];
2190                  } else {
2191                      $sort_field_w .= ' '.$this->labels['ascending'];
2192                  }
2193                  $sort_fields[]   = $sort_field;
2194                  $sort_fields_w[] = $sort_field_w;
2195              }
2196              if (count($sort_fields) > 0) {
2197                  $qparts['orderby'] = join(',', $sort_fields);
2198              }
2199          }
2200          $qparts['limit'] = $listall ? '' : $this->sql_limit($this->fm,$this->inc);
2201  
2202          /*

2203           * Main list_table() query

2204           *

2205           * Each row of the HTML table is one record from the SQL query. We must

2206           * perform this query before filter printing, because we want to use

2207           * $this->sql_field_len() function. We will also fetch the first row to get

2208           * the field names.

2209           */
2210          $query = $this->get_SQL_main_list_query($qparts);
2211          $res   = $this->myquery($query, __LINE__);
2212          if ($res == false) {
2213              $this->error('invalid SQL query', $query);
2214              return false;
2215          }
2216          $row = $this->sql_fetch($res);
2217  
2218          /* FILTER {{{

2219           *

2220           * Draw the filter and fill it with any data typed in last pass and stored

2221           * in the array parameter keyword 'filter'. Prepare the SQL WHERE clause.

2222           */
2223          if ($this->filter_operation()) {
2224              // Filter row retrieval

2225              $fields     = false;
2226              $filter_row = $row;
2227              if (! is_array($filter_row)) {
2228                  unset($qparts['where']);
2229                  $query = $this->get_SQL_query($qparts);
2230                  $res   = $this->myquery($query, __LINE__);
2231                  if ($res == false) {
2232                      $this->error('invalid SQL query', $query);
2233                      return false;
2234                  }
2235                  $filter_row = $this->sql_fetch($res);
2236              }
2237              /* Variable $fields is used to get index of particular field in

2238                 result. That index can be passed in example to $this->sql_field_len()

2239                 function. Use field names as indexes to $fields array. */
2240              if (is_array($filter_row)) {
2241                  $fields = array_flip(array_keys($filter_row));
2242              }
2243              if ($fields != false) {
2244                  $css_class_name = $this->getCSSclass('filter');
2245                  echo '<tr class="',$css_class_name,'">',"\n";
2246                  echo '<td class="',$css_class_name,'" colspan="',$sys_cols,'">';
2247                  echo $this->htmlSubmit('filter', 'Query', $this->getCSSclass('query'), false);
2248                  echo '</td>', "\n";
2249                  for ($k = 0; $k < $this->num_fds; $k++) {
2250                      if (! $this->displayed[$k]) {
2251                          continue;
2252                      }
2253                      $css_postfix      = @$this->fdd[$k]['css']['postfix'];
2254                      $css_class_name   = $this->getCSSclass('filter', null, null, $css_postfix);
2255                      $this->field_name = $this->fds[$k];
2256                      $fd               = $this->field_name;
2257                      $this->field      = $this->fdd[$fd];
2258                      $l  = 'qf'.$k;
2259                      $lc = 'qf'.$k.'_comp';
2260                      $li = 'qf'.$k.'_id';
2261                      if ($this->clear_operation()) {
2262                          $m  = null;
2263                          $mc = null;
2264                          $mi = null;
2265                      } else {
2266                          $m  = $this->get_sys_cgi_var($l);
2267                          $mc = $this->get_sys_cgi_var($lc);
2268                          $mi = $this->get_sys_cgi_var($li);
2269                      }
2270                      echo '<td class="',$css_class_name,'">';
2271                      if ($this->password($k)) {
2272                          echo '&nbsp;';
2273                      } else if ($this->fdd[$fd]['select'] == 'D' || $this->fdd[$fd]['select'] == 'M') {
2274                          // Multiple fields processing

2275                          // Default size is 2 and array required for values.

2276                          $from_table = ! $this->col_has_values($k) || isset($this->fdd[$k]['values']['table']);
2277                          $vals       = $this->set_values($k, array('*' => '*'), null, $from_table);
2278                          $selected   = $mi;
2279                          $multiple   = $this->col_has_multiple_select($k);
2280                          $multiple  |= $this->fdd[$fd]['select'] == 'M';
2281                          $readonly   = false;
2282                          $strip_tags = true;
2283                          $escape     = true;
2284                          echo $this->htmlSelect($this->cgi['prefix']['sys'].$l.'_id', $css_class_name,
2285                                  $vals, $selected, $multiple, $readonly, $strip_tags, $escape);
2286                      } elseif ($this->fdd[$fd]['select'] == 'N' || $this->fdd[$fd]['select'] == 'T') {
2287                          $len_props = '';
2288                          $maxlen = intval($this->fdd[$k]['maxlen']);
2289                          $maxlen > 0 || $maxlen = intval($this->sql_field_len($res, $fields["qf$k"]));
2290                          $size = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size']
2291                              : ($maxlen < 30 ? min($maxlen, 8) : 12);
2292                          $len_props .= ' size="'.$size.'"';
2293                          $len_props .= ' maxlength="'.$maxlen.'"';
2294                          if ($this->fdd[$fd]['select'] == 'N') {
2295                              $mc = in_array($mc, $this->comp_ops) ? $mc : '=';
2296                              echo $this->htmlSelect($this->cgi['prefix']['sys'].$l.'_comp',
2297                                      $css_class_name, $this->comp_ops, $mc);
2298                          }
2299                          echo '<input class="',$css_class_name,'" value="',htmlspecialchars(@$m);
2300                          echo '" type="text" name="'.$this->cgi['prefix']['sys'].'qf'.$k.'"',$len_props;
2301                          echo ' onkeypress="return '.$this->js['prefix'].'filter_handler(this.form, event);" />';
2302                      } else {
2303                          echo '&nbsp;';
2304                      }
2305                      echo '</td>',"\n";
2306                  }
2307                  echo '</tr>',"\n";
2308              }
2309          } // }}}

2310  
2311          /*

2312           * Display sorting sequence

2313           */
2314          if ($qparts['orderby'] && $this->display['sort']) {
2315              $css_class_name = $this->getCSSclass('sortinfo');
2316              echo '<tr class="',$css_class_name,'">',"\n";
2317              echo '<td class="',$css_class_name,'" colspan="',$sys_cols,'">';
2318              echo '<a class="',$css_class_name,'" href="';
2319              echo htmlspecialchars($this->page_name
2320                      .'?'.$this->cgi['prefix']['sys'].'fl'.'='.$this->fl
2321                      .'&'.$this->cgi['prefix']['sys'].'fm'.'='.$this->fm
2322                      .'&'.$this->cgi['prefix']['sys'].'qfn'.'='.rawurlencode($this->qfn)
2323                      .$this->qfn.$this->cgi['persist']);
2324              echo '">',$this->labels['Clear'],'</a></td>',"\n";
2325              echo '<td class="',$css_class_name,'" colspan="',$this->num_fields_displayed,'">';
2326              echo $this->labels['Sorted By'],': ',join(', ', $sort_fields_w),'</td></tr>',"\n";
2327          }
2328  
2329          /*

2330           * Display the current query

2331           */
2332          $text_query = $this->get_SQL_where_from_query_opts(null, true);
2333          if ($text_query != '' && $this->display['query']) {
2334              $css_class_name = $this->getCSSclass('queryinfo');
2335              echo '<tr class="',$css_class_name,'">',"\n";
2336              echo '<td class="',$css_class_name,'" colspan="',$sys_cols,'">';
2337              echo '<a class="',$css_class_name,'" href="';
2338              echo htmlspecialchars($this->get_server_var('PHP_SELF')
2339                      .'?'.$this->cgi['prefix']['sys'].'fl'.'='.$this->fl
2340                      .'&'.$this->cgi['prefix']['sys'].'fm'.'='.$this->fm
2341                      .'&'.$this->cgi['prefix']['sys'].'qfn'.'='.rawurlencode($this->qfn)
2342                      .'&'.$this->get_sfn_cgi_vars().$this->cgi['persist']);
2343              echo '">',$this->labels['Clear'],'</a></td>',"\n";
2344              echo '<td class="',$css_class_name,'" colspan="',$this->num_fields_displayed,'">';
2345              echo $this->labels['Current Query'],': ',htmlspecialchars($text_query),'</td></tr>',"\n";
2346          }
2347  
2348          if ($this->nav_text_links() || $this->nav_graphic_links()) {
2349              $qstrparts = array();
2350              strlen($this->fl)             > 0 && $qstrparts[] = $this->cgi['prefix']['sys'].'fl'.'='.$this->fl;
2351              strlen($this->fm)             > 0 && $qstrparts[] = $this->cgi['prefix']['sys'].'fm'.'='.$this->fm;
2352              count($this->sfn)             > 0 && $qstrparts[] = $this->get_sfn_cgi_vars();
2353              strlen($this->cgi['persist']) > 0 && $qstrparts[] = $this->cgi['persist'];
2354              $qpview      = $qstrparts;
2355              $qpcopy      = $qstrparts;
2356              $qpchange    = $qstrparts;
2357              $qpdelete    = $qstrparts;
2358              $qp_prefix   = $this->cgi['prefix']['sys'].'operation'.'='.$this->cgi['prefix']['operation'];
2359              $qpview[]    = $qp_prefix.'View';
2360              $qpcopy[]    = $qp_prefix.'Copy';
2361              $qpchange[]  = $qp_prefix.'Change';
2362              $qpdelete[]  = $qp_prefix.'Delete';
2363              $qpviewStr   = htmlspecialchars($this->page_name.'?'.join('&',$qpview).$this->qfn);
2364              $qpcopyStr   = htmlspecialchars($this->page_name.'?'.join('&',$qpcopy).$this->qfn);
2365              $qpchangeStr = htmlspecialchars($this->page_name.'?'.join('&',$qpchange).$this->qfn);
2366              $qpdeleteStr = htmlspecialchars($this->page_name.'?'.join('&',$qpdelete).$this->qfn);
2367          }
2368  
2369          $fetched  = true;
2370          $first    = true;
2371          $rowCount = 0;
2372          while ((!$fetched && ($row = $this->sql_fetch($res)) != false)
2373                  || ($fetched && $row != false)) {
2374              $fetched = false;
2375              echo '<tr class="',$this->getCSSclass('row', null, 'next'),'">',"\n";
2376              if ($sys_cols) { /* {{{ */
2377                  $key_rec     = $row['qf'.$this->key_num];
2378                  $queryAppend = htmlspecialchars('&'.$this->cgi['prefix']['sys'].'rec'.'='.$key_rec);
2379                  $viewQuery   = $qpviewStr   . $queryAppend;
2380                  $copyQuery   = $qpcopyStr   . $queryAppend;
2381                  $changeQuery = $qpchangeStr . $queryAppend;
2382                  $deleteQuery = $qpdeleteStr . $queryAppend;
2383                  $viewTitle   = htmlspecialchars($this->labels['View']);
2384                  $changeTitle = htmlspecialchars($this->labels['Change']);
2385                  $copyTitle   = htmlspecialchars($this->labels['Copy']);
2386                  $deleteTitle = htmlspecialchars($this->labels['Delete']);
2387                  $css_class_name = $this->getCSSclass('navigation', null, true);
2388                  if ($select_recs) {
2389                      if (! $this->nav_buttons() || $sys_cols > 1) {
2390                          echo '<td class="',$css_class_name,'">';
2391                      }
2392                      if ($this->nav_graphic_links()) {
2393                          $printed_out = false;
2394                          if ($this->view_enabled()) {
2395                              $printed_out = true;
2396                              echo '<a class="',$css_class_name,'" href="',$viewQuery,'"><img class="';
2397                              echo $css_class_name,'" src="',$this->url['images'];
2398                              echo 'pme-view.png" height="15" width="16" border="0" ';
2399                              echo 'alt="',$viewTitle,'" title="',$viewTitle,'" /></a>';
2400                          }
2401                          if ($this->change_enabled()) {
2402                              $printed_out && print('&nbsp;');
2403                              $printed_out = true;
2404                              echo '<a class="',$css_class_name,'" href="',$changeQuery,'"><img class="';
2405                              echo $css_class_name,'" src="',$this->url['images'];
2406                              echo 'pme-change.png" height="15" width="16" border="0" ';
2407                              echo 'alt="',$changeTitle,'" title="',$changeTitle,'" /></a>';
2408                          }
2409                          if ($this->copy_enabled()) {
2410                              $printed_out && print('&nbsp;');
2411                              $printed_out = true;
2412                              echo '<a class="',$css_class_name,'" href="',$copyQuery,'"><img class="';
2413                              echo $css_class_name,'" src="',$this->url['images'];
2414                              echo 'pme-copy.png" height="15" width="16" border="0" ';
2415                              echo 'alt="',$copyTitle,'" title="',$copyTitle,'" /></a>';
2416                          }
2417                          if ($this->delete_enabled()) {
2418                              $printed_out && print('&nbsp;');
2419                              $printed_out = true;
2420                              echo '<a class="',$css_class_name,'" href="',$deleteQuery,'"><img class="';
2421                              echo $css_class_name,'" src="',$this->url['images'];
2422                              echo 'pme-delete.png" height="15" width="16" border="0" ';
2423                              echo 'alt="',$deleteTitle,'" title="',$deleteTitle,'" /></a>';
2424                          }
2425                      }
2426                      if ($this->nav_text_links()) {
2427                          if ($this->nav_graphic_links()) {
2428                              echo '<br class="',$css_class_name,'">';
2429                          }
2430                          $printed_out = false;
2431                          if ($this->view_enabled()) {
2432                              $printed_out = true;
2433                              echo '<a href="',$viewQuery,'" title="',$viewTitle,'" class="',$css_class_name,'">V</a>';
2434                          }
2435                          if ($this->change_enabled()) {
2436                              $printed_out && print('&nbsp;');
2437                              $printed_out = true;
2438                              echo '<a href="',$changeQuery,'" title="',$changeTitle,'" class="',$css_class_name,'">C</a>';
2439                          }
2440                          if ($this->copy_enabled()) {
2441                              $printed_out && print('&nbsp;');
2442                              $printed_out = true;
2443                              echo '<a href="',$copyQuery,'" title="',$copyTitle,'" class="',$css_class_name,'">P</a>';
2444                          }
2445                          if ($this->delete_enabled()) {
2446                              $printed_out && print('&nbsp;');
2447                              $printed_out = true;
2448                              echo '<a href="',$deleteQuery,'" title="',$deleteTitle,'" class="',$css_class_name,'">D</a>';
2449                          }
2450                      }
2451                      if (! $this->nav_buttons() || $sys_cols > 1) {
2452                          echo '</td>',"\n";
2453                      }
2454                      if ($this->nav_buttons()) {
2455                          echo '<td class="',$css_class_name,'"><input class="',$css_class_name;
2456                          echo '" type="radio" name="'.$this->cgi['prefix']['sys'].'rec';
2457                          echo '" value="',htmlspecialchars($key_rec),'"';
2458                          if (($this->rec == '' && $first) || ($this->rec == $key_rec)) {
2459                              echo ' checked';
2460                              $first = false;
2461                          }
2462                          echo ' /></td>',"\n";
2463                      }
2464                  } elseif ($this->filter_enabled()) {
2465                      echo '<td class="',$css_class_name,'" colspan="',$sys_cols,'">&nbsp;</td>',"\n";
2466                  }
2467              } /* }}} */
2468              for ($k = 0; $k < $this->num_fds; $k++) { /* {{{ */
2469                  $fd = $this->fds[$k];
2470                  if (! $this->displayed[$k]) {
2471                      continue;
2472                  }
2473                  $css_postfix    = @$this->fdd[$k]['css']['postfix'];
2474                  $css_class_name = $this->getCSSclass('cell', null, true, $css_postfix);
2475                  if ($this->password($k)) {
2476                      echo '<td class="',$css_class_name,'">',$this->labels['hidden'],'</td>',"\n";
2477                      continue;
2478                  }
2479                  echo '<td class="',$css_class_name,'"',$this->getColAttributes($fd),'>';
2480                  echo $this->cellDisplay($k, $row, $css_class_name);
2481                  echo '</td>',"\n";
2482              } /* }}} */
2483              echo '</tr>',"\n";
2484          }
2485  
2486          /*

2487           * Display and accumulate column aggregation info, do totalling query

2488           * XXX this feature does not work yet!!!

2489           */
2490          // aggregates listing (if any)

2491          if ($$var_to_total) {
2492              // do the aggregate query if necessary

2493              //if ($vars_to_total) {

2494                  $qp = array();
2495                  $qp['type'] = 'select';
2496                  $qp['select'] = $aggr_from_clause;
2497                  $qp['from']   = $this->get_SQL_join_clause();
2498                  $qp['where']  = $this->get_SQL_where_from_query_opts();
2499                  $tot_query    = $this->get_SQL_query($qp);
2500                  $totals_result = $this->myquery($tot_query,__LINE__);
2501                  $tot_row       = $this->sql_fetch($totals_result);
2502              //}

2503              $qp_aggr = $qp;
2504              echo "\n",'<tr class="TODO-class">',"\n",'<td class="TODO-class">&nbsp;</td>',"\n";
2505              /*

2506              echo '<td>';

2507              echo printarray($qp_aggr);

2508              echo printarray($vars_to_total);

2509              echo '</td>';

2510              echo '<td colspan="'.($this->num_fds-1).'">'.$var_to_total.' '.$$var_to_total.'</td>';

2511              */
2512              // display the results

2513              for ($k=0;$k<$this->num_fds;$k++) {
2514                  $fd = $this->fds[$k];
2515                  if (stristr($this->fdd[$fd]['options'],'L') or !isset($this->fdd[$fd]['options'])) {
2516                      echo '<td>';
2517                      $aggr_var  = 'qf'.$k.'_aggr';
2518                      $$aggr_var = $this->get_sys_cgi_var($aggr_var);
2519                      if ($$aggr_var) {
2520                          echo $this->sql_aggrs[$$aggr_var],': ',$tot_row[$aggr_var];
2521                      } else {
2522                          echo '&nbsp;';
2523                      }
2524                      echo '</td>',"\n";
2525                  }
2526              }
2527              echo '</tr>',"\n";
2528          }
2529          echo '</table>',"\n"; // end of table rows listing

2530          $this->display_list_table_buttons('down', $listall);
2531          $this->form_end();
2532      } /* }}} */
2533  
2534      function display_record() /* {{{ */
2535      {
2536          // PRE Triggers

2537          $ret = true;
2538          if ($this->change_operation()) {
2539              $ret &= $this->exec_triggers_simple('update', 'pre');
2540              // if PRE update fails, then back to view operation

2541              if (! $ret) {
2542                  $this->operation = $this->labels['View'];
2543                  $ret = true;
2544              }
2545          }
2546          if ($this->add_operation() || $this->copy_operation()) {
2547              $ret &= $this->exec_triggers_simple('insert', 'pre');
2548          }
2549          if ($this->view_operation()) {
2550              $ret &= $this->exec_triggers_simple('select', 'pre');
2551          }
2552          if ($this->delete_operation()) {
2553              $ret &= $this->exec_triggers_simple('delete', 'pre');
2554          }
2555          // if PRE insert/view/delete fail, then back to the list

2556          if ($ret == false) {
2557              $this->operation = '';
2558              $this->list_table();
2559              return;
2560          }
2561          $this->form_begin();
2562          if ($this->cgi['persist'] != '') {
2563              echo $this->get_origvars_html($this->cgi['persist']);
2564          }
2565          echo $this->get_origvars_html($this->get_sfn_cgi_vars());
2566          echo $this->get_origvars_html($this->qfn);
2567          echo $this->htmlHiddenSys('cur_tab', $this->dhtml['prefix'].'tab'.$this->cur_tab);
2568          echo $this->htmlHiddenSys('qfn', $this->qfn);
2569          echo $this->htmlHiddenSys('rec', $this->copy_operation() ? '' : $this->rec);
2570          echo $this->htmlHiddenSys('fm', $this->fm);
2571          echo $this->htmlHiddenSys('fl', $this->fl);
2572          $this->display_record_buttons('up');
2573          if ($this->tabs_enabled()) {
2574              echo '<div id="'.$this->dhtml['prefix'].'tab0">',"\n";
2575          }
2576          echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n";
2577          if ($this->add_operation()) {
2578              $this->display_add_record();
2579          } else {
2580              $this->display_copy_change_delete_record();
2581          }
2582          echo '</table>',"\n";
2583          if ($this->tabs_enabled()) {
2584          echo '</div>',"\n";
2585          }
2586          $this->display_record_buttons('down');
2587  
2588          $this->form_end();
2589      } /* }}} */
2590  
2591      /*

2592       * Action functions

2593       */
2594  
2595      function do_add_record() /* {{{ */
2596      {
2597          // Preparing query

2598          $query       = '';
2599          $key_col_val = '';
2600          $newvals     = array();
2601          for ($k = 0; $k < $this->num_fds; $k++) {
2602              if ($this->processed($k)) {
2603                  $fd = $this->fds[$k];
2604                  if ($this->readonly($k)) {
2605                      $fn = (string) @$this->fdd[$k]['default'];
2606                  } else {
2607                      $fn = $this->get_data_cgi_var($fd);
2608                  }
2609                  if ($fd == $this->key) {
2610                      $key_col_val = $fn;
2611                  }
2612                  $newvals[$fd] = is_array($fn) ? join(',',$fn) : $fn;
2613              }
2614          }
2615          // Creating array of changed keys ($changed)

2616          $changed = array_keys($newvals);
2617          // Before trigger, newvals can be efectively changed

2618          if ($this->exec_triggers('insert', 'before', $oldvals, $changed, $newvals) == false) {
2619              return false;
2620          }
2621          // Real query (no additional query in this method)

2622          foreach ($newvals as $fd => $val) {
2623              if ($fd == '') continue;
2624              if ($this->col_has_sqlw($this->fdn[$fd])) {
2625                  $val_as  = addslashes($val);
2626                  $val_qas = '"'.addslashes($val).'"';
2627                  $value = $this->substituteVars(
2628                          $this->fdd[$this->fdn[$fd]]['sqlw'], array(
2629                              'val_qas' => $val_qas,
2630                              'val_as'  => $val_as,
2631                              'val'     => $val
2632                              ));
2633              } else {
2634                  $value = "'".addslashes($val)."'";
2635              }
2636              if ($query == '') {
2637                  $query = 'INSERT INTO '.$this->sd.$this->tb.$this->ed.' ('.$this->sd.$fd.$this->ed.''; // )

2638                  $query2 = ') VALUES ('.$value.'';
2639              } else {
2640                  $query  .= ', '.$this->sd.$fd.$this->ed.'';
2641                  $query2 .= ', '.$value.'';
2642              }
2643          }
2644          $query .= $query2.')';
2645          $res    = $this->myquery($query, __LINE__);
2646          $this->message = $this->sql_affected_rows($this->dbh).' '.$this->labels['record added'];
2647          if (! $res) {
2648              return false;
2649          }
2650          $this->rec = $this->sql_insert_id();
2651          // Notify list

2652          if (@$this->notify['insert'] || @$this->notify['all']) {
2653              $this->email_notify(false, $newvals);
2654          }
2655          // Note change in log table

2656          if ($this->logtable) {
2657              $query = sprintf('INSERT INTO %s'
2658                      .' (updated, user, host, operation, tab, rowkey, col, oldval, newval)'
2659                      .' VALUES (NOW(), "%s", "%s", "insert", "%s", "%s", "", "", "%s")',
2660                      $this->logtable, addslashes($this->get_server_var('REMOTE_USER')),
2661                      addslashes($this->get_server_var('REMOTE_ADDR')), addslashes($this->tb),
2662                      addslashes($key_col_val), addslashes(serialize($newvals)));
2663              $this->myquery($query, __LINE__);
2664          }
2665          // After trigger

2666          if ($this->exec_triggers('insert', 'after', $oldvals, $changed, $newvals) == false) {
2667              return false;
2668          }
2669          return true;
2670      } /* }}} */
2671  
2672      function do_change_record() /* {{{ */
2673      {
2674          // Preparing queries

2675          $query_real   = '';
2676          $query_oldrec = '';
2677          $newvals      = array();
2678          $oldvals      = array();
2679          $changed      = array();
2680          // Prepare query to retrieve oldvals

2681          for ($k = 0; $k < $this->num_fds; $k++) {
2682              if ($this->processed($k) && !$this->readonly($k)) {
2683                  $fd = $this->fds[$k];
2684                  $fn = $this->get_data_cgi_var($fd);
2685                  $newvals[$this->fds[$k]] = is_array($fn) ? join(',',$fn) : $fn;
2686                  if ($query_oldrec == '') {
2687                      $query_oldrec = 'SELECT '.$this->sd.$fd.$this->ed;
2688                  } else {
2689                      $query_oldrec .= ','.$this->sd.$fd.$this->ed;
2690                  }
2691              }
2692          }
2693          $where_part = " WHERE (".$this->sd.$this->key.$this->ed.'='.$this->key_delim.$this->rec.$this->key_delim.')';
2694          $query_newrec  = $query_oldrec.' FROM ' . $this->tb;
2695          $query_oldrec .= ' FROM ' . $this->sd.$this->tb.$this->ed . $where_part;
2696          // Additional query (must go before real query)

2697          $res     = $this->myquery($query_oldrec, __LINE__);
2698          $oldvals = $this->sql_fetch($res);
2699          $this->sql_free_result($res);
2700          // Creating array of changed keys ($changed)

2701          foreach ($newvals as $fd => $value) {
2702              if ($value != $oldvals[$fd])
2703                  $changed[] = $fd;
2704          }
2705          // Before trigger

2706          if ($this->exec_triggers('update', 'before', $oldvals, $changed, $newvals) == false) {
2707              return false;
2708          }
2709          // Build the real query respecting changes to the newvals array

2710          foreach ($newvals as $fd => $val) {
2711              if ($fd == '') continue;
2712              if ($this->col_has_sqlw($this->fdn[$fd])) {
2713                  $val_as  = addslashes($val);
2714                  $val_qas = '"'.addslashes($val).'"';
2715                  $value = $this->substituteVars(
2716                          $this->fdd[$this->fdn[$fd]]['sqlw'], array(
2717                              'val_qas' => $val_qas,
2718                              'val_as'  => $val_as,
2719                              'val'     => $val
2720                              ));
2721              } else {
2722                  $value = "'".addslashes($val)."'";
2723              }
2724              if ($query_real == '') {
2725                  $query_real   = 'UPDATE '.$this->sd.$this->tb.$this->ed.' SET '.$this->sd.$fd.$this->ed.'='.$value;
2726              } else {
2727                  $query_real   .= ','.$this->sd.$fd.$this->ed.'='.$value;
2728              }
2729          }
2730          $query_real .= $where_part;
2731          // Real query

2732          $res = $this->myquery($query_real, __LINE__);
2733          $this->message = $this->sql_affected_rows($this->dbh).' '.$this->labels['record changed'];
2734          if (! $res) {
2735              return false;
2736          }
2737          // Another additional query (must go after real query)

2738          if (in_array($this->key, $changed)) {
2739              $this->rec = $newvals[$this->key]; // key has changed

2740          }
2741          $query_newrec .= ' WHERE ('.$this->key.'='.$this->key_delim.$this->rec.$this->key_delim.')';
2742          $res     = $this->myquery($query_newrec, __LINE__);
2743          $newvals = $this->sql_fetch($res);
2744          $this->sql_free_result($res);
2745          // Creating array of changed keys ($changed)

2746          $changed = array();
2747          foreach ($newvals as $fd => $value) {
2748              if ($value != $oldvals[$fd])
2749                  $changed[] = $fd;
2750          }
2751          // Notify list

2752          if (@$this->notify['update'] || @$this->notify['all']) {
2753              if (count($changed) > 0) {
2754                  $this->email_notify($oldvals, $newvals);
2755              }
2756          }
2757          // Note change in log table

2758          if ($this->logtable) {
2759              foreach ($changed as $key) {
2760                  $qry = sprintf('INSERT INTO %s'
2761                          .' (updated, user, host, operation, tab, rowkey, col, oldval, newval)'
2762                          .' VALUES (NOW(), "%s", "%s", "update", "%s", "%s", "%s", "%s", "%s")',
2763                          $this->logtable, addslashes($this->get_server_var('REMOTE_USER')),
2764                          addslashes($this->get_server_var('REMOTE_ADDR')), addslashes($this->tb),
2765                          addsl