PageRenderTime 60ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/htdocs/default/admin/phpMyEdit.class.php

http://epicnms.googlecode.com/
PHP | 1882 lines | 1613 code | 94 blank | 175 comment | 488 complexity | f0481e2623d1103512ce40a491fc4db9 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0, MIT, AGPL-1.0, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. * phpMyEdit - instant MySQL table editor and code generator
  4. *
  5. * phpMyEdit.class.php - main table editor class definition file
  6. * ____________________________________________________________
  7. *
  8. * Copyright (c) 1999-2002 John McCreesh <jpmcc@users.sourceforge.net>
  9. * Copyright (c) 2001-2002 Jim Kraai <jkraai@users.sourceforge.net>
  10. * Versions 5.0 and higher developed by Ondrej Jombik <nepto@php.net>
  11. * Copyright (c) 2002-2006 Platon Group, http://platon.sk/
  12. * All rights reserved.
  13. *
  14. * See README file for more information about this software.
  15. * See COPYING file for license information.
  16. *
  17. * Download the latest version from
  18. * http://platon.sk/projects/phpMyEdit/
  19. */
  20. /* $Platon: phpMyEdit/phpMyEdit.class.php,v 1.204 2007-09-16 12:57:07 nepto Exp $ */
  21. /* This is a generic table editing program. The table and fields to be
  22. edited are defined in the calling program.
  23. This program works in three passes.
  24. * Pass 1 (the last part of the program) displays the selected SQL
  25. table in a scrolling table on the screen. Radio buttons are used to
  26. select a record for editing or deletion. If the user chooses Add,
  27. Change, Copy, View or Delete buttons.
  28. * Pass 2 starts, displaying the selected record. If the user chooses
  29. the Save button from this screen.
  30. * Pass 3 processes the update and the display returns to the
  31. original table view (Pass 1).
  32. */
  33. class phpMyEdit_timer /* {{{ */
  34. {
  35. var $startTime;
  36. var $started;
  37. function phpMyEdit_timer($start = true)
  38. {
  39. $this->started = false;
  40. if ($start) {
  41. $this->start();
  42. }
  43. }
  44. function start()
  45. {
  46. $startMtime = explode(' ', microtime());
  47. $this->startTime = (double) $startMtime[0] + (double) $startMtime[1];
  48. $this->started = true;
  49. }
  50. function end($iterations = 1)
  51. {
  52. // get the time, check whether the timer was started later
  53. $endMtime = explode(' ', microtime());
  54. if ($this->started) {
  55. $endTime = (double)($endMtime[0])+(double)($endMtime[1]);
  56. $dur = $endTime - $this->startTime;
  57. $avg = 1000 * $dur / $iterations;
  58. $avg = round(1000 * $avg) / 1000;
  59. return $avg;
  60. } else {
  61. return 'phpMyEdit_timer ERROR: timer not started';
  62. }
  63. }
  64. } /* }}} */
  65. if (! function_exists('array_search')) { /* {{{ */
  66. function array_search($needle, $haystack)
  67. {
  68. foreach ($haystack as $key => $value) {
  69. if ($needle == $value)
  70. return $key;
  71. }
  72. return false;
  73. }
  74. } /* }}} */
  75. if (! function_exists('realpath')) { /* {{{ */
  76. function realpath($path)
  77. {
  78. return $path;
  79. }
  80. } /* }}} */
  81. class phpMyEdit
  82. {
  83. // Class variables {{{
  84. // Database handling
  85. var $hn; // hostname
  86. var $un; // user name
  87. var $pw; // password
  88. var $tb; // table
  89. var $db; // database
  90. var $dbp; // database with point and delimiters
  91. var $dbh; // database handle
  92. var $close_dbh; // if database handle should be closed
  93. // Record manipulation
  94. var $key; // name of field which is the unique key
  95. var $key_num; // number of field which is the unique key
  96. var $key_type; // type of key field (int/real/string/date etc.)
  97. var $key_delim; // character used for key value quoting
  98. var $rec; // number of record selected for editing
  99. var $inc; // number of records to display
  100. var $fm; // first record to display
  101. var $fl; // is the filter row displayed (boolean)
  102. var $fds; // sql field names
  103. var $fdn; // sql field names => $k
  104. var $num_fds; // number of fields
  105. var $options; // options for users: ACDFVPI
  106. var $fdd; // field definitions
  107. var $qfn; // value of all filters used during the last pass
  108. var $sfn; // sort field number (- = descending sort order)
  109. var $cur_tab; // current selected tab
  110. // Operation
  111. var $navop; // navigation buttons/operations
  112. var $sw; // filter display/hide/clear button
  113. var $operation; // operation to do: Add, Change, Delete
  114. var $saveadd;
  115. var $moreadd;
  116. var $canceladd;
  117. var $savechange;
  118. var $morechange;
  119. var $cancelchange;
  120. var $savecopy;
  121. var $cancelcopy;
  122. var $savedelete;
  123. var $canceldelete;
  124. var $cancelview;
  125. // Additional features
  126. var $labels; // multilingual labels
  127. var $cgi; // CGI variable features array
  128. var $js; // JS configuration array
  129. var $dhtml; // DHTML configuration array
  130. var $url; // URL array
  131. var $message; // informational message to print
  132. var $notify; // change notification e-mail adresses
  133. var $logtable; // name of optional logtable
  134. var $navigation; // navigation style
  135. var $tabs; // TAB names
  136. var $timer = null; // phpMyEdit_timer object
  137. var $sd; var $ed; // sql start and end delimiters '`' in case of MySQL
  138. // Predefined variables
  139. var $comp_ops = array('<'=>'<','<='=>'<=','='=>'=','>='=>'>=','>'=>'>');
  140. var $sql_aggrs = array(
  141. 'sum' => 'Total',
  142. 'avg' => 'Average',
  143. 'min' => 'Minimum',
  144. 'max' => 'Maximum',
  145. 'count' => 'Count');
  146. var $page_types = array(
  147. 'L' => 'list',
  148. 'F' => 'filter',
  149. 'A' => 'add',
  150. 'V' => 'view',
  151. 'C' => 'change',
  152. 'P' => 'copy',
  153. 'D' => 'delete'
  154. );
  155. var $default_buttons = array(
  156. 'L' => array('<<','<','add','view','change','copy','delete','>','>>','goto','goto_combo'),
  157. 'F' => array('<<','<','add','view','change','copy','delete','>','>>','goto','goto_combo'),
  158. 'A' => array('save','more','cancel'),
  159. 'C' => array('save','more','cancel'),
  160. 'P' => array('save', 'cancel'),
  161. 'D' => array('save','cancel'),
  162. 'V' => array('change','cancel')
  163. );
  164. // }}}
  165. /*
  166. * column specific functions
  167. */
  168. function col_has_sql($k) { return isset($this->fdd[$k]['sql']); }
  169. function col_has_sqlw($k) { return isset($this->fdd[$k]['sqlw']) && !$this->virtual($k); }
  170. function col_has_values($k) { return isset($this->fdd[$k]['values']) || isset($this->fdd[$k]['values2']); }
  171. function col_has_php($k) { return isset($this->fdd[$k]['php']); }
  172. function col_has_URL($k) { return isset($this->fdd[$k]['URL'])
  173. || isset($this->fdd[$k]['URLprefix']) || isset($this->fdd[$k]['URLpostfix']); }
  174. function col_has_multiple($k)
  175. { return $this->col_has_multiple_select($k) || $this->col_has_checkboxes($k); }
  176. function col_has_multiple_select($k)
  177. { return $this->fdd[$k]['select'] == 'M' && ! $this->fdd[$k]['values']['table']; }
  178. function col_has_checkboxes($k)
  179. { return $this->fdd[$k]['select'] == 'C' && ! $this->fdd[$k]['values']['table']; }
  180. function col_has_radio_buttons($k)
  181. { return $this->fdd[$k]['select'] == 'O' && ! $this->fdd[$k]['values']['table']; }
  182. function col_has_datemask($k)
  183. { return isset($this->fdd[$k]['datemask']) || isset($this->fdd[$k]['strftimemask']); }
  184. /*
  185. * functions for indicating whether navigation style is enabled
  186. */
  187. function nav_buttons() { return stristr($this->navigation, 'B'); }
  188. function nav_text_links() { return stristr($this->navigation, 'T'); }
  189. function nav_graphic_links() { return stristr($this->navigation, 'G'); }
  190. function nav_up() { return (stristr($this->navigation, 'U') && !($this->buttons[$this->page_type]['up'] === false)); }
  191. function nav_down() { return (stristr($this->navigation, 'D') && !($this->buttons[$this->page_type]['down'] === false)); }
  192. /*
  193. * functions for indicating whether operations are enabled
  194. */
  195. function add_enabled() { return stristr($this->options, 'A'); }
  196. function change_enabled() { return stristr($this->options, 'C'); }
  197. function delete_enabled() { return stristr($this->options, 'D'); }
  198. function filter_enabled() { return stristr($this->options, 'F'); }
  199. function view_enabled() { return stristr($this->options, 'V'); }
  200. function copy_enabled() { return stristr($this->options, 'P') && $this->add_enabled(); }
  201. function tabs_enabled() { return $this->display['tabs'] && count($this->tabs) > 0; }
  202. function hidden($k) { return stristr($this->fdd[$k]['input'],'H'); }
  203. function password($k) { return stristr($this->fdd[$k]['input'],'W'); }
  204. function readonly($k) { return stristr($this->fdd[$k]['input'],'R') || $this->virtual($k); }
  205. function virtual($k) { return stristr($this->fdd[$k]['input'],'V') && $this->col_has_sql($k); }
  206. function add_operation() { return $this->operation == $this->labels['Add'] && $this->add_enabled(); }
  207. function change_operation() { return $this->operation == $this->labels['Change'] && $this->change_enabled(); }
  208. function copy_operation() { return $this->operation == $this->labels['Copy'] && $this->copy_enabled(); }
  209. function delete_operation() { return $this->operation == $this->labels['Delete'] && $this->delete_enabled(); }
  210. function view_operation() { return $this->operation == $this->labels['View'] && $this->view_enabled(); }
  211. function filter_operation() { return $this->fl && $this->filter_enabled() && $this->list_operation(); }
  212. function list_operation() { /* covers also filtering page */ return ! $this->change_operation()
  213. && ! $this->add_operation() && ! $this->copy_operation()
  214. && ! $this->delete_operation() && ! $this->view_operation(); }
  215. function next_operation() { return ($this->navop == $this->labels['Next']) || ($this->navop == '>'); }
  216. function prev_operation() { return ($this->navop == $this->labels['Prev']) || ($this->navop == '<'); }
  217. function first_operation() { return ($this->navop == $this->labels['First']) || ($this->navop == '<<'); }
  218. function last_operation() { return ($this->navop == $this->labels['Last']) || ($this->navop == '>>'); }
  219. function clear_operation() { return $this->sw == $this->labels['Clear']; }
  220. function add_canceled() { return $this->canceladd == $this->labels['Cancel']; }
  221. function view_canceled() { return $this->cancelview == $this->labels['Cancel']; }
  222. function change_canceled() { return $this->cancelchange == $this->labels['Cancel']; }
  223. function copy_canceled() { return $this->cancelcopy == $this->labels['Cancel']; }
  224. function delete_canceled() { return $this->canceldelete == $this->labels['Cancel']; }
  225. function is_values2($k, $val = 'X') /* {{{ */
  226. {
  227. return $val === null ||
  228. (isset($this->fdd[$k]['values2']) && !isset($this->fdd[$k]['values']['table']));
  229. } /* }}} */
  230. function processed($k) /* {{{ */
  231. {
  232. if ($this->virtual($k)) {
  233. return false;
  234. }
  235. $options = @$this->fdd[$k]['options'];
  236. if (! isset($options)) {
  237. return true;
  238. }
  239. return
  240. ($this->saveadd == $this->labels['Save'] && stristr($options, 'A')) ||
  241. ($this->moreadd == $this->labels['More'] && stristr($options, 'A')) ||
  242. ($this->savechange == $this->labels['Save'] && stristr($options, 'C')) ||
  243. ($this->morechange == $this->labels['Apply'] && stristr($options, 'C')) ||
  244. ($this->savecopy == $this->labels['Save'] && stristr($options, 'P')) ||
  245. ($this->savedelete == $this->labels['Save'] && stristr($options, 'D'));
  246. } /* }}} */
  247. function displayed($k) /* {{{ */
  248. {
  249. if (is_numeric($k)) {
  250. $k = $this->fds[$k];
  251. }
  252. $options = @$this->fdd[$k]['options'];
  253. if (! isset($options)) {
  254. return true;
  255. }
  256. return
  257. ($this->add_operation() && stristr($options, 'A')) ||
  258. ($this->view_operation() && stristr($options, 'V')) ||
  259. ($this->change_operation() && stristr($options, 'C')) ||
  260. ($this->copy_operation() && stristr($options, 'P')) ||
  261. ($this->delete_operation() && stristr($options, 'D')) ||
  262. ($this->filter_operation() && stristr($options, 'F')) ||
  263. ($this->list_operation() && stristr($options, 'L'));
  264. } /* }}} */
  265. function debug_var($name, $val) /* {{{ */
  266. {
  267. if (is_array($val) || is_object($val)) {
  268. echo "<pre>$name\n";
  269. ob_start();
  270. //print_r($val);
  271. var_dump($val);
  272. $content = ob_get_contents();
  273. ob_end_clean();
  274. echo htmlspecialchars($content);
  275. echo "</pre>\n";
  276. } else {
  277. echo 'debug_var()::<i>',htmlspecialchars($name),'</i>';
  278. echo '::<b>',htmlspecialchars($val),'</b>::',"<br />\n";
  279. }
  280. } /* }}} */
  281. /*
  282. * sql functions
  283. */
  284. function sql_connect() /* {{{ */
  285. {
  286. $this->dbh = @ini_get('allow_persistent')
  287. ? @mysql_pconnect($this->hn, $this->un, $this->pw)
  288. : @mysql_connect($this->hn, $this->un, $this->pw);
  289. } /* }}} */
  290. function sql_disconnect() /* {{{ */
  291. {
  292. if ($this->close_dbh) {
  293. @mysql_close($this->dbh);
  294. $this->dbh = null;
  295. }
  296. } /* }}} */
  297. function sql_fetch(&$res, $type = 'a') /* {{{ */
  298. {
  299. if($type == 'n') $type = MYSQL_NUM;
  300. else $type = MYSQL_ASSOC;
  301. return @mysql_fetch_array($res, $type);
  302. } /* }}} */
  303. function sql_free_result(&$res) /* {{{ */
  304. {
  305. return @mysql_free_result($res);
  306. } /* }}} */
  307. function sql_affected_rows(&$dbh) /* {{{ */
  308. {
  309. return @mysql_affected_rows($dbh);
  310. } /* }}} */
  311. function sql_field_len(&$res,$field) /* {{{ */
  312. {
  313. return @mysql_field_len($res, $field);
  314. } /* }}} */
  315. function sql_insert_id() /* {{{ */
  316. {
  317. return mysql_insert_id($this->dbh);
  318. } /* }}} */
  319. function sql_limit($start, $more) /* {{{ */
  320. {
  321. return ' LIMIT '.$start.', '.$more.' ';
  322. } /* }}} */
  323. function sql_delimiter() /* {{{ */
  324. {
  325. $this->sd = '`'; $this->ed='`';
  326. return $this->sd;
  327. } /* }}} */
  328. function myquery($qry, $line = 0, $debug = 0) /* {{{ */
  329. {
  330. global $debug_query;
  331. if ($debug_query || $debug) {
  332. $line = intval($line);
  333. echo '<h4>MySQL query at line ',$line,'</h4>',htmlspecialchars($qry),'<hr size="1" />',"\n";
  334. }
  335. if (isset($this->db)) {
  336. $ret = @mysql_db_query($this->db, $qry, $this->dbh);
  337. } else {
  338. $ret = @mysql_query($qry, $this->dbh);
  339. }
  340. if (! $ret) {
  341. echo '<h4>MySQL error ',mysql_errno($this->dbh),'</h4>';
  342. echo htmlspecialchars(mysql_error($this->dbh)),'<hr size="1" />',"\n";
  343. }
  344. return $ret;
  345. } /* }}} */
  346. /* end of sql functions */
  347. function make_language_labels($language) /* {{{ */
  348. {
  349. // just try the first language and variant
  350. // this isn't content-negotiation rfc compliant
  351. $language = strtoupper($language);
  352. // try the full language w/ variant
  353. $file = $this->dir['lang'].'PME.lang.'.$language.'.inc';
  354. while (! file_exists($file)) {
  355. $pos = strrpos($language, '-');
  356. if ($pos === false) {
  357. $file = $this->dir['lang'].'PME.lang.EN.inc';
  358. break;
  359. }
  360. $language = substr($language, 0, $pos);
  361. $file = $this->dir['lang'].'PME.lang.'.$language.'.inc';
  362. }
  363. $ret = @include($file);
  364. if (! is_array($ret)) {
  365. return $ret;
  366. }
  367. $small = array(
  368. 'Search' => 'v',
  369. 'Hide' => '^',
  370. 'Clear' => 'X',
  371. 'Query' => htmlspecialchars('>'));
  372. if ((!$this->nav_text_links() && !$this->nav_graphic_links())
  373. || !isset($ret['Search']) || !isset($ret['Query'])
  374. || !isset($ret['Hide']) || !isset($ret['Clear'])) {
  375. foreach ($small as $key => $val) {
  376. $ret[$key] = $val;
  377. }
  378. }
  379. return $ret;
  380. } /* }}} */
  381. function set_values($field_num, $prepend = null, $append = null, $strict = false) /* {{{ */
  382. {
  383. return (array) $prepend + (array) $this->fdd[$field_num]['values2']
  384. + (isset($this->fdd[$field_num]['values']['table']) || $strict
  385. ? $this->set_values_from_table($field_num, $strict)
  386. : array())
  387. + (array) $append;
  388. } /* }}} */
  389. function set_values_from_table($field_num, $strict = false) /* {{{ */
  390. {
  391. $db = &$this->fdd[$field_num]['values']['db'];
  392. $table = $this->sd.$this->fdd[$field_num]['values']['table'].$this->ed;
  393. $key = &$this->fdd[$field_num]['values']['column'];
  394. $desc = &$this->fdd[$field_num]['values']['description'];
  395. $dbp = isset($db) ? $this->sd.$db.$this->ed.'.' : $this->dbp;
  396. $qparts['type'] = 'select';
  397. if ($table != $this->sd.$this->ed) {
  398. $qparts['select'] = 'DISTINCT '.$table.'.'.$this->sd.$key.$this->ed;
  399. if ($desc && is_array($desc) && is_array($desc['columns'])) {
  400. $qparts['select'] .= ',CONCAT('; // )
  401. $num_cols = sizeof($desc['columns']);
  402. if (isset($desc['divs'][-1])) {
  403. $qparts['select'] .= '"'.addslashes($desc['divs'][-1]).'",';
  404. }
  405. foreach ($desc['columns'] as $key => $val) {
  406. if ($val) {
  407. $qparts['select'] .= 'IFNULL(CAST('.$this->sd.$val.$this->ed.' AS CHAR),"")';
  408. if ($desc['divs'][$key]) {
  409. $qparts['select'] .= ',"'.addslashes($desc['divs'][$key]).'"';
  410. }
  411. $qparts['select'] .= ',';
  412. }
  413. }
  414. $qparts['select']{strlen($qparts['select']) - 1} = ')';
  415. $qparts['select'] .= ' AS '.$this->sd.'PMEalias'.$field_num.$this->ed;
  416. $qparts['orderby'] = $this->sd.'PMEalias'.$field_num.$this->ed;
  417. } else if ($desc && is_array($desc)) {
  418. // TODO
  419. } else if ($desc) {
  420. $qparts['select'] .= ','.$table.'.'.$this->sd.$desc.$this->ed;
  421. $qparts['orderby'] = $this->sd.$desc.$this->ed;
  422. } else if ($key) {
  423. $qparts['orderby'] = $this->sd.$key.$this->ed;
  424. }
  425. $qparts['from'] = $dbp.$table;
  426. $ar = array(
  427. 'table' => $table,
  428. 'column' => $column,
  429. 'description' => $desc);
  430. $qparts['where'] = $this->substituteVars($this->fdd[$field_num]['values']['filters'], $ar);
  431. if ($this->fdd[$field_num]['values']['orderby']) {
  432. $qparts['orderby'] = $this->substituteVars($this->fdd[$field_num]['values']['orderby'], $ar);
  433. }
  434. } else { /* simple value extraction */
  435. $key = &$this->fds[$field_num];
  436. $this->virtual($field_num) && $key = $this->fqn($field_num);
  437. $qparts['select'] = 'DISTINCT '.$this->sd.$key.$this->ed.' AS PMEkey';
  438. $qparts['orderby'] = 'PMEkey';
  439. $qparts['from'] = $this->dbp.$this->sd.$this->tb.$this->ed;
  440. }
  441. $values = array();
  442. $res = $this->myquery($this->get_SQL_query($qparts), __LINE__);
  443. while ($row = $this->sql_fetch($res, 'n')) {
  444. $values[$row[0]] = $desc ? $row[1] : $row[0];
  445. }
  446. return $values;
  447. } /* }}} */
  448. function fqn($field, $dont_desc = false, $dont_cols = false) /* {{{ */
  449. {
  450. is_numeric($field) || $field = array_search($field, $this->fds);
  451. // if read SQL expression exists use it
  452. if ($this->col_has_sql($field) && !$this->col_has_values($field))
  453. return $this->fdd[$field]['sql'];
  454. // on copy/change always use simple key retrieving
  455. if ($this->add_operation()
  456. || $this->copy_operation()
  457. || $this->change_operation()) {
  458. $ret = $this->sd.'PMEtable0'.$this->ed.'.'.$this->sd.$this->fds[$field].$this->ed;
  459. } else {
  460. if ($this->fdd[$this->fds[$field]]['values']['description'] && ! $dont_desc) {
  461. $desc = &$this->fdd[$this->fds[$field]]['values']['description'];
  462. if (is_array($desc) && is_array($desc['columns'])) {
  463. $ret = 'CONCAT('; // )
  464. $num_cols = sizeof($desc['columns']);
  465. if (isset($desc['divs'][-1])) {
  466. $ret .= '"'.addslashes($desc['divs'][-1]).'",';
  467. }
  468. foreach ($desc['columns'] as $key => $val) {
  469. if ($val) {
  470. $ret .= 'IFNULL(CAST('.$this->sd.'PMEjoin'.$field.$this->ed.'.'.$this->sd.$val.$this->ed.' AS CHAR),"")';
  471. if ($desc['divs'][$key]) {
  472. $ret .= ',"'.addslashes($desc['divs'][$key]).'"';
  473. }
  474. $ret .= ',';
  475. }
  476. }
  477. $ret{strlen($ret) - 1} = ')';
  478. } else if (is_array($desc)) {
  479. // TODO
  480. } else {
  481. $ret = $this->sd.'PMEjoin'.$field.$this->ed.'.'.$this->sd.$this->fdd[$this->fds[$field]]['values']['description'].$this->ed;
  482. }
  483. // TODO: remove me
  484. } elseif (0 && $this->fdd[$this->fds[$field]]['values']['column'] && ! $dont_cols) {
  485. $ret = $this->sd.'PMEjoin'.$field.$this->ed.'.'.$this->fdd[$this->fds[$field]]['values']['column'];
  486. } else {
  487. $ret = $this->sd.'PMEtable0'.$this->ed.'.'.$this->sd.$this->fds[$field].$this->ed;
  488. }
  489. // TODO: not neccessary, remove me!
  490. if (is_array($this->fdd[$this->fds[$field]]['values2'])) {
  491. }
  492. }
  493. return $ret;
  494. } /* }}} */
  495. function get_SQL_main_list_query($qparts) /* {{{ */
  496. {
  497. return $this->get_SQL_query($qparts);
  498. } /* }}} */
  499. function get_SQL_query($parts) /* {{{ */
  500. {
  501. foreach ($parts as $k => $v) {
  502. $parts[$k] = trim($parts[$k]);
  503. }
  504. switch ($parts['type']) {
  505. case 'select':
  506. $ret = 'SELECT ';
  507. if ($parts['DISTINCT'])
  508. $ret .= 'DISTINCT ';
  509. $ret .= $parts['select'];
  510. $ret .= ' FROM '.$parts['from'];
  511. if ($parts['where'] != '')
  512. $ret .= ' WHERE '.$parts['where'];
  513. if ($parts['groupby'] != '')
  514. $ret .= ' GROUP BY '.$parts['groupby'];
  515. if ($parts['having'] != '')
  516. $ret .= ' HAVING '.$parts['having'];
  517. if ($parts['orderby'] != '')
  518. $ret .= ' ORDER BY '.$parts['orderby'];
  519. if ($parts['limit'] != '')
  520. $ret .= ' '.$parts['limit'];
  521. if ($parts['procedure'] != '')
  522. $ret .= ' PROCEDURE '.$parts['procedure'];
  523. break;
  524. case 'update':
  525. $ret = 'UPDATE '.$parts['table'];
  526. $ret .= ' SET '.$parts['fields'];
  527. if ($parts['where'] != '')
  528. $ret .= ' WHERE '.$parts['where'];
  529. break;
  530. case 'insert':
  531. $ret = 'INSERT INTO '.$parts['table'];
  532. $ret .= ' VALUES '.$parts['values'];
  533. break;
  534. case 'delete':
  535. $ret = 'DELETE FROM '.$parts['table'];
  536. if ($parts['where'] != '')
  537. $ret .= ' WHERE '.$parts['where'];
  538. break;
  539. default:
  540. die('unknown query type');
  541. break;
  542. }
  543. return $ret;
  544. } /* }}} */
  545. function get_SQL_column_list() /* {{{ */
  546. {
  547. $fields = array();
  548. for ($k = 0; $k < $this->num_fds; $k++) {
  549. if (! $this->displayed[$k] && $k != $this->key_num) {
  550. continue;
  551. }
  552. $fields[] = $this->fqn($k).' AS '.$this->sd.'qf'.$k.$this->ed; // no delimiters here, or maybe some yes
  553. if ($this->col_has_values($k)) {
  554. if($this->col_has_sql($k)) $fields[] = $this->fdd[$k]['sql'].' AS '.$this->sd.'qf'.$k.'_idx'.$this->ed;
  555. else $fields[] = $this->fqn($k, true, true).' AS '.$this->sd.'qf'.$k.'_idx'.$this->ed;
  556. }
  557. if ($this->col_has_datemask($k)) {
  558. $fields[] = 'UNIX_TIMESTAMP('.$this->fqn($k).') AS '.$this->sd.'qf'.$k.'_timestamp'.$this->ed;
  559. }
  560. }
  561. return join(',', $fields);
  562. } /* }}} */
  563. function get_SQL_join_clause() /* {{{ */
  564. {
  565. $main_table = $this->sd.'PMEtable0'.$this->ed;
  566. $join_clause = $this->sd.$this->tb.$this->ed." AS $main_table";
  567. for ($k = 0, $numfds = sizeof($this->fds); $k < $numfds; $k++) {
  568. $main_column = $this->fds[$k];
  569. if($this->fdd[$main_column]['values']['db']) {
  570. $dbp = $this->sd.$this->fdd[$main_column]['values']['db'].$this->ed.'.';
  571. } else {
  572. //$dbp = $this->dbp;
  573. }
  574. $table = $this->sd.$this->fdd[$main_column]['values']['table'].$this->ed;
  575. $join_column = $this->sd.$this->fdd[$main_column]['values']['column'].$this->ed;
  576. $join_desc = $this->sd.$this->fdd[$main_column]['values']['description'].$this->ed;
  577. if ($join_desc != $this->sd.$this->ed && $join_column != $this->sd.$this->ed) {
  578. $join_table = $this->sd.'PMEjoin'.$k.$this->ed;
  579. $ar = array(
  580. 'main_table' => $main_table,
  581. 'main_column' => $this->sd.$main_column.$this->ed,
  582. 'join_table' => $join_table,
  583. 'join_column' => $join_column,
  584. 'join_description' => $join_desc);
  585. $join_clause .= " LEFT OUTER JOIN $dbp".$table." AS $join_table ON (";
  586. $join_clause .= isset($this->fdd[$main_column]['values']['join'])
  587. ? $this->substituteVars($this->fdd[$main_column]['values']['join'], $ar)
  588. : "$join_table.$join_column = $main_table.".$this->sd.$main_column.$this->ed;
  589. $join_clause .= ')';
  590. }
  591. }
  592. return $join_clause;
  593. } /* }}} */
  594. function get_SQL_where_from_query_opts($qp = null, $text = 0) /* {{{ */
  595. {
  596. if ($qp == null) {
  597. $qp = $this->query_opts;
  598. }
  599. $where = array();
  600. foreach ($qp as $field => $ov) {
  601. if (is_numeric($field)) {
  602. $tmp_where = array();
  603. foreach ($ov as $field2 => $ov2) {
  604. $tmp_where[] = sprintf('%s %s %s', $field2, $ov2['oper'], $ov2['value']);
  605. }
  606. $where[] = '('.join(' OR ', $tmp_where).')';
  607. } else {
  608. if (is_array($ov['value'])) {
  609. $tmp_ov_val = '';
  610. foreach ($ov['value'] as $ov_val) {
  611. strlen($tmp_ov_val) > 0 && $tmp_ov_val .= ' OR ';
  612. $tmp_ov_val .= sprintf('FIND_IN_SET("%s",%s)', $ov_val, $field);
  613. }
  614. $where[] = "($tmp_ov_val)";
  615. } else {
  616. $where[] = sprintf('%s %s %s', $field, $ov['oper'], $ov['value']);
  617. }
  618. }
  619. }
  620. // Add any coder specified filters
  621. if (! $text && $this->filters) {
  622. $where[] = '('.$this->filters.')';
  623. }
  624. if (count($where) > 0) {
  625. if ($text) {
  626. return str_replace('%', '*', join(' AND ',$where));
  627. } else {
  628. return join(' AND ',$where);
  629. }
  630. }
  631. return ''; /* empty string */
  632. } /* }}} */
  633. function gather_query_opts() /* {{{ */
  634. {
  635. $this->query_opts = array();
  636. $this->prev_qfn = $this->qfn;
  637. $this->qfn = '';
  638. if ($this->clear_operation()) {
  639. return;
  640. }
  641. // gathers query options into an array, $this->query_opts
  642. $qo = array();
  643. for ($k = 0; $k < $this->num_fds; $k++) {
  644. $l = 'qf'.$k;
  645. $lc = 'qf'.$k.'_comp';
  646. $li = 'qf'.$k.'_id';
  647. $m = $this->get_sys_cgi_var($l);
  648. $mc = $this->get_sys_cgi_var($lc);
  649. $mi = $this->get_sys_cgi_var($li);
  650. if (! isset($m) && ! isset($mi)) {
  651. continue;
  652. }
  653. if (is_array($m) || is_array($mi)) {
  654. if (is_array($mi)) {
  655. $m = $mi;
  656. $l = $li;
  657. }
  658. if (in_array('*', $m)) {
  659. continue;
  660. }
  661. if ($this->col_has_values($k) && $this->col_has_multiple($k)) {
  662. foreach (array_keys($m) as $key) {
  663. $m[$key] = addslashes($m[$key]);
  664. }
  665. $qo[$this->fqn($k)] = array('value' => $m);
  666. } else {
  667. $qf_op = '';
  668. foreach (array_keys($m) as $key) {
  669. if ($qf_op == '') {
  670. $qf_op = 'IN';
  671. $qf_val = '"'.addslashes($m[$key]).'"';
  672. $afilter = ' IN ("'.addslashes($m[$key]).'"'; // )
  673. } else {
  674. $afilter = $afilter.',"'.addslashes($m[$key]).'"';
  675. $qf_val .= ',"'.addslashes($m[$key]).'"';
  676. }
  677. $this->qfn .= '&'.$this->cgi['prefix']['sys'].$l.'['.rawurlencode($key).']='.rawurlencode($m[$key]);
  678. }
  679. $afilter = $afilter.')';
  680. // XXX: $dont_desc and $dont_cols hack
  681. $dont_desc = isset($this->fdd[$k]['values']['description']);
  682. $dont_cols = isset($this->fdd[$k]['values']['column']);
  683. $qo[$this->fqn($k, $dont_desc, $dont_cols)] =
  684. array('oper' => $qf_op, 'value' => "($qf_val)"); // )
  685. }
  686. } else if (isset($mi)) {
  687. if ($mi == '*') {
  688. continue;
  689. }
  690. if ($this->fdd[$k]['select'] != 'M' && $this->fdd[$k]['select'] != 'D' && $mi == '') {
  691. continue;
  692. }
  693. $afilter = addslashes($mi);
  694. $qo[$this->fqn($k, true, true)] = array('oper' => '=', 'value' => "'$afilter'");
  695. $this->qfn .= '&'.$this->cgi['prefix']['sys'].$li.'='.rawurlencode($mi);
  696. } else if (isset($m)) {
  697. if ($m == '*') {
  698. continue;
  699. }
  700. if ($this->fdd[$k]['select'] != 'M' && $this->fdd[$k]['select'] != 'D' && $m == '') {
  701. continue;
  702. }
  703. $afilter = addslashes($m);
  704. if ($this->fdd[$k]['select'] == 'N') {
  705. $mc = in_array($mc, $this->comp_ops) ? $mc : '=';
  706. $qo[$this->fqn($k)] = array('oper' => $mc, 'value' => "'$afilter'");
  707. $this->qfn .= '&'.$this->cgi['prefix']['sys'].$l .'='.rawurlencode($m);
  708. $this->qfn .= '&'.$this->cgi['prefix']['sys'].$lc.'='.rawurlencode($mc);
  709. } else {
  710. $afilter = '%'.str_replace('*', '%', $afilter).'%';
  711. $ids = array();
  712. $ar = array();
  713. $ar[$this->fqn($k)] = array('oper' => 'LIKE', 'value' => "'$afilter'");
  714. if (is_array($this->fdd[$k]['values2'])) {
  715. foreach ($this->fdd[$k]['values2'] as $key => $val) {
  716. if (strlen($m) > 0 && stristr($val, $m)) {
  717. $ids[] = '"'.addslashes($key).'"';
  718. }
  719. }
  720. if (count($ids) > 0) {
  721. $ar[$this->fqn($k, true, true)]
  722. = array('oper' => 'IN', 'value' => '('.join(',', $ids).')');
  723. }
  724. }
  725. $qo[] = $ar;
  726. $this->qfn .= '&'.$this->cgi['prefix']['sys'].$l.'='.rawurlencode($m);
  727. }
  728. }
  729. }
  730. $this->query_opts = $qo;
  731. } /* }}} */
  732. /*
  733. * Create JavaScripts
  734. */
  735. function form_begin() /* {{{ */
  736. {
  737. $page_name = htmlspecialchars($this->page_name);
  738. if ($this->add_operation() || $this->change_operation() || $this->copy_operation()
  739. || $this->view_operation() || $this->delete_operation()) {
  740. $field_to_tab = array();
  741. for ($tab = $k = $this->cur_tab = 0; $k < $this->num_fds; $k++) {
  742. if (isset($this->fdd[$k]['tab'])) {
  743. if ($tab == 0 && $k > 0) {
  744. $this->tabs[0] = 'PMEtab0';
  745. $this->cur_tab = 1;
  746. $tab++;
  747. }
  748. if (is_array($this->fdd[$k]['tab'])) {
  749. $this->tabs[$tab] = @$this->fdd[$k]['tab']['name'];
  750. $this->fdd[$k]['tab']['default'] && $this->cur_tab = $tab;
  751. } else {
  752. $this->tabs[$tab] = @$this->fdd[$k]['tab'];
  753. }
  754. $tab++;
  755. }
  756. $field_to_tab[$k] = max(0, $tab - 1);
  757. }
  758. if (preg_match('/^'.$this->dhtml['prefix'].'tab(\d+)$/', $this->get_sys_cgi_var('cur_tab'), $parts)) {
  759. $this->cur_tab = $parts[1];
  760. }
  761. if ($this->tabs_enabled()) {
  762. // initial TAB styles
  763. echo '<style type="text/css" media="screen">',"\n";
  764. for ($i = 0; $i < count($this->tabs); $i++) {
  765. echo ' #'.$this->dhtml['prefix'].'tab',$i,' { display: ';
  766. echo (($i == $this->cur_tab || $this->tabs[$i] == 'PMEtab0' ) ? 'block' : 'none') ,'; }',"\n";
  767. }
  768. echo '</style>',"\n";
  769. // TAB javascripts
  770. echo '<script type="text/javascript"><!--',"\n\n";
  771. $css_class_name1 = $this->getCSSclass('tab', $position);
  772. $css_class_name2 = $this->getCSSclass('tab-selected', $position);
  773. echo 'var '.$this->js['prefix'].'cur_tab = "'.$this->dhtml['prefix'].'tab',$this->cur_tab,'";
  774. function '.$this->js['prefix'].'show_tab(tab_name)
  775. {';
  776. if ($this->nav_up()) {
  777. echo '
  778. document.getElementById('.$this->js['prefix'].'cur_tab+"_up_label").className = "',$css_class_name1,'";
  779. document.getElementById('.$this->js['prefix'].'cur_tab+"_up_link").className = "',$css_class_name1,'";
  780. document.getElementById(tab_name+"_up_label").className = "',$css_class_name2,'";
  781. document.getElementById(tab_name+"_up_link").className = "',$css_class_name2,'";';
  782. }
  783. if ($this->nav_down()) {
  784. echo '
  785. document.getElementById('.$this->js['prefix'].'cur_tab+"_down_label").className = "',$css_class_name1,'";
  786. document.getElementById('.$this->js['prefix'].'cur_tab+"_down_link").className = "',$css_class_name1,'";
  787. document.getElementById(tab_name+"_down_label").className = "',$css_class_name2,'";
  788. document.getElementById(tab_name+"_down_link").className = "',$css_class_name2,'";';
  789. }
  790. echo '
  791. document.getElementById('.$this->js['prefix'].'cur_tab).style.display = "none";
  792. document.getElementById(tab_name).style.display = "block";
  793. '.$this->js['prefix'].'cur_tab = tab_name;
  794. document.'.$this->cgi['prefix']['sys'].'form.'.$this->cgi['prefix']['sys'].'cur_tab.value = tab_name;
  795. }',"\n\n";
  796. echo '// --></script>', "\n";
  797. }
  798. }
  799. if ($this->add_operation() || $this->change_operation() || $this->copy_operation()) {
  800. $first_required = true;
  801. for ($k = 0; $k < $this->num_fds; $k++) {
  802. if ($this->displayed[$k] && ! $this->readonly($k) && ! $this->hidden($k)
  803. && ($this->fdd[$k]['js']['required'] || isset($this->fdd[$k]['js']['regexp']))) {
  804. if ($first_required) {
  805. $first_required = false;
  806. echo '<script type="text/javascript"><!--',"\n";
  807. echo '
  808. function '.$this->js['prefix'].'trim(str)
  809. {
  810. while (str.substring(0, 1) == " "
  811. || str.substring(0, 1) == "\\n"
  812. || str.substring(0, 1) == "\\r")
  813. {
  814. str = str.substring(1, str.length);
  815. }
  816. while (str.substring(str.length - 1, str.length) == " "
  817. || str.substring(str.length - 1, str.length) == "\\n"
  818. || str.substring(str.length - 1, str.length) == "\\r")
  819. {
  820. str = str.substring(0, str.length - 1);
  821. }
  822. return str;
  823. }
  824. function '.$this->js['prefix'].'form_control(theForm)
  825. {',"\n";
  826. }
  827. if ($this->col_has_values($k)) {
  828. $condition = 'theForm.'.$this->cgi['prefix']['data'].$this->fds[$k].'.selectedIndex == -1';
  829. $multiple = $this->col_has_multiple_select($k);
  830. } else {
  831. $condition = '';
  832. $multiple = false;
  833. if ($this->fdd[$k]['js']['required']) {
  834. $condition = $this->js['prefix'].'trim(theForm.'.$this->cgi['prefix']['data'].$this->fds[$k].'.value) == ""';
  835. }
  836. if (isset($this->fdd[$k]['js']['regexp'])) {
  837. $condition .= (strlen($condition) > 0 ? ' || ' : '');
  838. $condition .= sprintf('!(%s.test('.$this->js['prefix'].'trim(theForm.%s.value)))',
  839. $this->fdd[$k]['js']['regexp'], $this->cgi['prefix']['data'].$this->fds[$k]);
  840. }
  841. }
  842. /* Multiple selects have their name like ''name[]''.
  843. It is not possible to work with them directly, because
  844. theForm.name[].something will result into JavaScript
  845. syntax error. Following search algorithm is provided
  846. as a workaround for this.
  847. */
  848. if ($multiple) {
  849. echo '
  850. multiple_select = null;
  851. for (i = 0; i < theForm.length; i++) {
  852. if (theForm.elements[i].name == "',$this->cgi['prefix']['data'].$this->fds[$k],'[]") {
  853. multiple_select = theForm.elements[i];
  854. break;
  855. }
  856. }
  857. if (multiple_select != null && multiple_select.selectedIndex == -1) {';
  858. } else {
  859. echo '
  860. if (',$condition,') {';
  861. }
  862. echo '
  863. alert("';
  864. if (isset($this->fdd[$k]['js']['hint'])) {
  865. echo htmlspecialchars($this->fdd[$k]['js']['hint']);
  866. } else {
  867. echo $this->labels['Please enter'],' ',$this->fdd[$k]['name'],'.';
  868. }
  869. echo '");';
  870. if ($this->tabs_enabled() && $field_to_tab[$k] >= $this->cur_tab) {
  871. echo '
  872. '.$this->js['prefix'].'show_tab("'.$this->dhtml['prefix'].'tab',$field_to_tab[$k],'");';
  873. }
  874. echo '
  875. theForm.',$this->cgi['prefix']['data'].$this->fds[$k],'.focus();
  876. return false;
  877. }',"\n";
  878. }
  879. }
  880. if (! $first_required) {
  881. echo '
  882. return true;
  883. }',"\n\n";
  884. echo '// --></script>', "\n";
  885. }
  886. }
  887. if ($this->filter_operation()) {
  888. echo '<script type="text/javascript"><!--',"\n";
  889. echo '
  890. function '.$this->js['prefix'].'filter_handler(theForm, theEvent)
  891. {
  892. var pressed_key = null;
  893. if (theEvent.which) {
  894. pressed_key = theEvent.which;
  895. } else {
  896. pressed_key = theEvent.keyCode;
  897. }
  898. if (pressed_key == 13) { // enter pressed
  899. theForm.submit();
  900. return false;
  901. }
  902. return true;
  903. }',"\n\n";
  904. echo '// --></script>', "\n";
  905. }
  906. if ($this->display['form']) {
  907. echo '<form class="',$this->getCSSclass('form'),'" method="post"';
  908. echo ' action="',$page_name,'" name="'.$this->cgi['prefix']['sys'].'form">',"\n";
  909. }
  910. return true;
  911. } /* }}} */
  912. function form_end() /* {{{ */
  913. {
  914. if ($this->display['form']) {
  915. echo '</form>',"\n";
  916. }
  917. } /* }}} */
  918. function display_tab_labels($position) /* {{{ */
  919. {
  920. if (! is_array($this->tabs)) {
  921. return false;
  922. }
  923. echo '<table summary="labels" class="',$this->getCSSclass('tab', $position),'">',"\n";
  924. echo '<tr class="',$this->getCSSclass('tab', $position),'">',"\n";
  925. for ($i = ($this->tabs[0] == 'PMEtab0' ? 1 : 0); $i < count($this->tabs); $i++) {
  926. $css_class_name = $this->getCSSclass($i != $this->cur_tab ? 'tab' : 'tab-selected', $position);
  927. echo '<td class="',$css_class_name,'" id="'.$this->dhtml['prefix'].'tab',$i,'_',$position,'_label">';
  928. echo '<a class="',$css_class_name,'" id="'.$this->dhtml['prefix'].'tab',$i,'_',$position,'_link';
  929. echo '" href="javascript:'.$this->js['prefix'].'show_tab(\''.$this->dhtml['prefix'].'tab',$i,'\')">';
  930. echo $this->tabs[$i],'</a></td>',"\n";
  931. }
  932. echo '<td class="',$this->getCSSclass('tab-end', $position),'">&nbsp;</td>',"\n";
  933. echo '</tr>',"\n";
  934. echo '</table>',"\n";
  935. } /* }}} */
  936. /*
  937. * Display functions
  938. */
  939. function display_add_record() /* {{{ */
  940. {
  941. for ($tab = 0, $k = 0; $k < $this->num_fds; $k++) {
  942. if (isset($this->fdd[$k]['tab']) && $this->tabs_enabled() && $k > 0) {
  943. $tab++;
  944. echo '</table>',"\n";
  945. echo '</div>',"\n";
  946. echo '<div id="'.$this->dhtml['prefix'].'tab',$tab,'">',"\n";
  947. echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n";
  948. }
  949. if (! $this->displayed[$k]) {
  950. continue;
  951. }
  952. if ($this->hidden($k)) {
  953. echo $this->htmlHiddenData($this->fds[$k], $this->fdd[$k]['default']);
  954. continue;
  955. }
  956. $css_postfix = @$this->fdd[$k]['css']['postfix'];
  957. $css_class_name = $this->getCSSclass('input', null, 'next', $css_postfix);
  958. $escape = isset($this->fdd[$k]['escape']) ? $this->fdd[$k]['escape'] : true;
  959. echo '<tr class="',$this->getCSSclass('row', null, true, $css_postfix),'">',"\n";
  960. echo '<td class="',$this->getCSSclass('key', null, true, $css_postfix),'">';
  961. echo $this->fdd[$k]['name'],'</td>',"\n";
  962. echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"';
  963. echo $this->getColAttributes($k),">\n";
  964. if ($this->col_has_values($k)) {
  965. $vals = $this->set_values($k);
  966. $selected = @$this->fdd[$k]['default'];
  967. $multiple = $this->col_has_multiple($k);
  968. $readonly = $this->readonly($k);
  969. $strip_tags = true;
  970. //$escape = true;
  971. if ($this->col_has_checkboxes($k) || $this->col_has_radio_buttons($k)) {
  972. echo $this->htmlRadioCheck($this->cgi['prefix']['data'].$this->fds[$k],
  973. $css_class_name, $vals, $selected, $multiple, $readonly,
  974. $strip_tags, $escape);
  975. } else {
  976. echo $this->htmlSelect($this->cgi['prefix']['data'].$this->fds[$k],
  977. $css_class_name, $vals, $selected, $multiple, $readonly,
  978. $strip_tags, $escape);
  979. }
  980. } elseif (isset ($this->fdd[$k]['textarea'])) {
  981. echo '<textarea class="',$css_class_name,'" name="',$this->cgi['prefix']['data'].$this->fds[$k],'"';
  982. echo ($this->readonly($k) ? ' disabled' : '');
  983. if (intval($this->fdd[$k]['textarea']['rows']) > 0) {
  984. echo ' rows="',$this->fdd[$k]['textarea']['rows'],'"';
  985. }
  986. if (intval($this->fdd[$k]['textarea']['cols']) > 0) {
  987. echo ' cols="',$this->fdd[$k]['textarea']['cols'],'"';
  988. }
  989. if (isset($this->fdd[$k]['textarea']['wrap'])) {
  990. echo ' wrap="',$this->fdd[$k]['textarea']['wrap'],'"';
  991. } else {
  992. echo ' wrap="virtual"';
  993. }
  994. echo '>';
  995. if($escape) echo htmlspecialchars($this->fdd[$k]['default']);
  996. else echo $this->fdd[$k]['default'];
  997. echo '</textarea>',"\n";
  998. } elseif ($this->col_has_php($k)) {
  999. echo include($this->fdd[$k]['php']);
  1000. } else {
  1001. // Simple edit box required
  1002. $len_props = '';
  1003. $maxlen = intval($this->fdd[$k]['maxlen']);
  1004. $size = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size'] : min($maxlen, 60);
  1005. if ($size > 0) {
  1006. $len_props .= ' size="'.$size.'"';
  1007. }
  1008. if ($maxlen > 0) {
  1009. $len_props .= ' maxlength="'.$maxlen.'"';
  1010. }
  1011. echo '<input class="',$css_class_name,'" ';
  1012. echo ($this->password($k) ? 'type="password"' : 'type="text"');
  1013. echo ($this->readonly($k) ? ' disabled' : '');
  1014. echo ' name="',$this->cgi['prefix']['data'].$this->fds[$k],'"';
  1015. echo $len_props,' value="';
  1016. if($escape) echo htmlspecialchars($this->fdd[$k]['default']);
  1017. else echo $this->fdd[$k]['default'];
  1018. echo '" />';
  1019. }
  1020. echo '</td>',"\n";
  1021. if ($this->guidance) {
  1022. $css_class_name = $this->getCSSclass('help', null, true, $css_postfix);
  1023. $cell_value = $this->fdd[$k]['help'] ? $this->fdd[$k]['help'] : '&nbsp;';
  1024. echo '<td class="',$css_class_name,'">',$cell_value,'</td>',"\n";
  1025. }
  1026. echo '</tr>',"\n";
  1027. }
  1028. } /* }}} */
  1029. function display_copy_change_delete_record() /* {{{ */
  1030. {
  1031. /*
  1032. * For delete or change: SQL SELECT to retrieve the selected record
  1033. */
  1034. $qparts['type'] = 'select';
  1035. $qparts['select'] = $this->get_SQL_column_list();
  1036. $qparts['from'] = $this->get_SQL_join_clause();
  1037. $qparts['where'] = '('.$this->fqn($this->key).'='
  1038. .$this->key_delim.$this->rec.$this->key_delim.')';
  1039. $res = $this->myquery($this->get_SQL_query($qparts),__LINE__);
  1040. if (! ($row = $this->sql_fetch($res))) {
  1041. return false;
  1042. }
  1043. for ($tab = 0, $k = 0; $k < $this->num_fds; $k++) {
  1044. if (isset($this->fdd[$k]['tab']) && $this->tabs_enabled() && $k > 0) {
  1045. $tab++;
  1046. echo '</table>',"\n";
  1047. echo '</div>',"\n";
  1048. echo '<div id="'.$this->dhtml['prefix'].'tab',$tab,'">',"\n";
  1049. echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n";
  1050. }
  1051. if (! $this->displayed[$k]) {
  1052. continue;
  1053. }
  1054. if ($this->copy_operation() || $this->change_operation()) {
  1055. if ($this->hidden($k)) {
  1056. if ($k != $this->key_num) {
  1057. echo $this->htmlHiddenData($this->fds[$k], $row["qf$k"]);
  1058. }
  1059. continue;
  1060. }
  1061. $css_postfix = @$this->fdd[$k]['css']['postfix'];
  1062. echo '<tr class="',$this->getCSSclass('row', null, 'next', $css_postfix),'">',"\n";
  1063. echo '<td class="',$this->getCSSclass('key', null, true, $css_postfix),'">';
  1064. echo $this->fdd[$k]['name'],'</td>',"\n";
  1065. /* There are two possibilities of readonly fields handling:
  1066. 1. Display plain text for readonly timestamps, dates and URLs.
  1067. 2. Display disabled input field
  1068. In all cases particular readonly field will NOT be saved. */
  1069. if ($this->readonly($k) && ($this->col_has_datemask($k) || $this->col_has_URL($k))) {
  1070. echo $this->display_delete_field($row, $k);
  1071. } elseif ($this->password($k)) {
  1072. echo $this->display_password_field($row, $k);
  1073. } else {
  1074. echo $this->display_change_field($row, $k);
  1075. }
  1076. if ($this->guidance) {
  1077. $css_class_name = $this->getCSSclass('help', null, true, $css_postfix);
  1078. $cell_value = $this->fdd[$k]['help'] ? $this->fdd[$k]['help'] : '&nbsp;';
  1079. echo '<td class="',$css_class_name,'">',$cell_value,'</td>',"\n";
  1080. }
  1081. echo '</tr>',"\n";
  1082. } elseif ($this->delete_operation() || $this->view_operation()) {
  1083. $css_postfix = @$this->fdd[$k]['css']['postfix'];
  1084. echo '<tr class="',$this->getCSSclass('row', null, 'next', $css_postfix),'">',"\n";
  1085. echo '<td class="',$this->getCSSclass('key', null, true, $css_postfix),'">';
  1086. echo $this->fdd[$k]['name'],'</td>',"\n";
  1087. if ($this->password($k)) {
  1088. echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"';
  1089. echo $this->getColAttributes($k),'>',$this->labels['hidden'],'</td>',"\n";
  1090. } else {
  1091. $this->display_delete_field($row, $k);
  1092. }
  1093. if ($this->guidance) {
  1094. $css_class_name = $this->getCSSclass('help', null, true, $css_postfix);
  1095. $cell_value = $this->fdd[$k]['help'] ? $this->fdd[$k]['help'] : '&nbsp;';
  1096. echo '<td class="',$css_class_name,'">',$cell_value,'</td>',"\n";
  1097. }
  1098. echo '</tr>',"\n";
  1099. }
  1100. }
  1101. } /* }}} */
  1102. function display_change_field($row, $k) /* {{{ */
  1103. {
  1104. $css_postfix = @$this->fdd[$k]['css']['postfix'];
  1105. $css_class_name = $this->getCSSclass('input', null, true, $css_postfix);
  1106. $escape = isset($this->fdd[$k]['escape']) ? $this->fdd[$k]['escape'] : true;
  1107. echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"';
  1108. echo $this->getColAttributes($k),">\n";
  1109. if ($this->col_has_values($k)) {
  1110. $vals = $this->set_values($k);
  1111. $multiple = $this->col_has_multiple($k);
  1112. $readonly = $this->readonly($k);
  1113. $strip_tags = true;
  1114. //$escape = true;
  1115. if ($this->col_has_checkboxes($k) || $this->col_has_radio_buttons($k)) {
  1116. echo $this->htmlRadioCheck($this->cgi['prefix']['data'].$this->fds[$k],
  1117. $css_class_name, $vals, $row["qf$k"], $multiple, $readonly,
  1118. $strip_tags, $escape);
  1119. } else {
  1120. echo $this->htmlSelect($this->cgi['prefix']['data'].$this->fds[$k],
  1121. $css_class_name, $vals, $row["qf$k"], $multiple, $readonly,
  1122. $strip_tags, $escape);
  1123. }
  1124. } elseif (isset($this->fdd[$k]['textarea'])) {
  1125. echo '<textarea class="',$css_class_name,'" name="',$this->cgi['prefix']['data'].$this->fds[$k],'"';
  1126. echo ($this->readonly($k) ? ' disabled' : '');
  1127. if (intval($this->fdd[$k]['textarea']['rows']) > 0) {
  1128. echo ' rows="',$this->fdd[$k]['textarea']['rows'],'"';
  1129. }
  1130. if (intval($this->fdd[$k]['textarea']['cols']) > 0) {
  1131. echo ' cols="',$this->fdd[$k]['textarea']['cols'],'"';
  1132. }
  1133. if (isset($this->fdd[$k]['textarea']['wrap'])) {
  1134. echo ' wrap="',$this->fdd[$k]['textarea']['wrap'],'"';
  1135. } else {
  1136. echo ' wrap="virtual"';
  1137. }
  1138. echo '>';
  1139. if($escape) echo htmlspecialchars($row["qf$k"]);
  1140. else echo $row["qf$k"];
  1141. echo '</textarea>',"\n";
  1142. } elseif ($this->col_has_php($k)) {
  1143. echo include($this->fdd[$k]['php']);
  1144. } else {
  1145. $len_props = '';
  1146. $maxlen = intval($this->fdd[$k]['maxlen']);
  1147. $size = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size'] : min($maxlen, 60);
  1148. if ($size > 0) {
  1149. $len_props .= ' size="'.$size.'"';
  1150. }
  1151. if ($maxlen > 0) {
  1152. $len_props .= ' maxlength="'.$maxlen.'"';
  1153. }
  1154. echo '<input class="',$css_class_name,'" type="text"';
  1155. echo ($this->readonly($k) ? ' disabled' : '');
  1156. echo ' name="',$this->cgi['prefix']['data'].$this->fds[$k],'" value="';
  1157. if($escape) echo htmlspecialchars($row["qf$k"]);
  1158. else echo $row["qf$k"];
  1159. echo '"',$len_props,' />',"\n";
  1160. }
  1161. echo '</td>',"\n";
  1162. } /* }}} */
  1163. function display_password_field($row, $k) /* {{{ */
  1164. {
  1165. $css_postfix = @$this->fdd[$k]['css']['postfix'];
  1166. echo '<td class="',$this->getCSSclass('value', null, true, $css_postfix),'"';
  1167. echo $this->getColAttributes($k),">\n";
  1168. $len_props = '';
  1169. $maxlen = intval($this->fdd[$k]['maxlen']);
  1170. $size = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size'] : min($maxlen, 60);
  1171. if ($size > 0) {
  1172. $len_props .= ' size="'.$size.'"';
  1173. }
  1174. if ($maxlen > 0) {
  1175. $len_props .= ' maxlength="'.$maxlen.'"';
  1176. }
  1177. echo '<input class="',$this->getCSSclass('value', null, true, $css_postfix),'" type="password"';
  1178. echo ($this->readonly($k) ? ' disabled' : '');
  1179. echo ' name="',$this->cgi['prefix']['data'].$this->fds[$k],'" value="';
  1180. echo htmlspecialchars($row["qf$k"]),'"',$len_props,' />',"\n";
  1181. echo '</td>',"\n";
  1182. } /* }}} */
  1183. function display_delete_field($row, $k) /* {{{ */
  1184. {
  1185. $css_postfix = @$this->fdd[$k]['css']['postfix'];
  1186. $css_class_name = $this->getCSSclass('value', null, true, $css_postfix);
  1187. echo '<td class="',$css_class_name,'"',$this->getColAttributes($k),">\n";
  1188. echo $this->cellDisplay($k, $row, $css_class_name);
  1189. echo '</td>',"\n";
  1190. } /* }}} */
  1191. /**
  1192. * Returns CSS class name
  1193. */
  1194. function getCSSclass($name, $position = null, $divider = null, $postfix = null) /* {{{ */
  1195. {
  1196. static $div_idx = -1;
  1197. $elements = array($this->css['prefix'], $name);
  1198. if ($this->page_type && $this->css['page_type']) {
  1199. if ($this->page_type != 'L' && $this->page_type != 'F') {
  1200. $elements[] = $this->page_types[$this->page_type];
  1201. }
  1202. }
  1203. if ($position && $this->css['position']) {
  1204. $elements[] = $position;
  1205. }
  1206. if ($divider && $this->css['divider']) {
  1207. if ($divider === 'next') {
  1208. $div_idx++;
  1209. if ($this->css['divider'] > 0 && $div_idx >= $this->css['divider']) {
  1210. $div_idx = 0;
  1211. }
  1212. }
  1213. $elements[] = $div_idx;
  1214. }
  1215. if ($postfix) {
  1216. $elements[] = $postfix;
  1217. }
  1218. return join($this->css['separator'], $elements);
  1219. } /* }}} */
  1220. /**
  1221. * Returns field cell HTML attributes
  1222. */
  1223. function getColAttributes($k) /* {{{ */
  1224. {
  1225. $colattrs = '';
  1226. if (isset($this->fdd[$k]['colattrs'])) {
  1227. $colattrs .= ' ';
  1228. $colattrs .= trim($this->fdd[$k]['colattrs']);
  1229. }
  1230. if (isset($this->fdd[$k]['nowrap'])) {
  1231. $colattrs .= ' nowrap';
  1232. }
  1233. return $colattrs;
  1234. } /* }}} */
  1235. /**
  1236. * Substitutes variables in string
  1237. * (this is very simple but secure eval() replacement)
  1238. */
  1239. function substituteVars($str, $subst_ar) /* {{{ */
  1240. {
  1241. $array = preg_split('/(\\$\w+)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE);
  1242. $count = count($array);
  1243. for ($i = 1; $i < $count; $i += 2) {
  1244. $key = substr($array[$i], 1);
  1245. if (isset($subst_ar[$key])) {
  1246. $array[$i] = $subst_ar[$key];
  1247. }
  1248. }
  1249. return join('', $array);
  1250. } /* }}} */
  1251. /**
  1252. * Print URL
  1253. */
  1254. function urlDisplay($k, $link_val, $disp_val, $css, $key) /* {{{ */
  1255. {
  1256. $escape = isset($this->fdd[$k]['escape']) ? $this->fdd[$k]['escape'] : true;
  1257. $ret = '';
  1258. $name = $this->fds[$k];
  1259. $page = $this->page_name;
  1260. $url = $this->cgi['prefix']['sys'].'rec'.'='.$key.'&'.$this->cgi['prefix']['sys'].'fm'
  1261. .'='.$this->fm.'&'.$this->cgi['prefix']['sys'].'fl'.'='.$this->fl;
  1262. $url .= '&'.$this->cgi['prefix']['sys'].'qfn'.'='.rawurlencode($this->qfn).$this->qfn;
  1263. $url .= '&'.$this->get_sfn_cgi_vars().$this->cgi['persist'];
  1264. $ar = array(
  1265. 'key' => $key,
  1266. 'name' => $name,
  1267. 'link' => $link_val,
  1268. 'value' => $disp_val,
  1269. 'css' => $css,
  1270. 'page' => $page,
  1271. 'url' => $url
  1272. );
  1273. $urllink = isset($this->fdd[$k]['URL'])
  1274. ? $this->substituteVars($this->fdd[$k]['URL'], $ar)
  1275. : $link_val;
  1276. $urldisp = isset($this->fdd[$k]['URLdisp'])
  1277. ? $this->substituteVars($this->fdd[$k]['URLdisp'], $ar)
  1278. : $disp_val;
  1279. $target = isset($this->fdd[$k]['URLtarget'])
  1280. ? 'target="'.htmlspecialchars($this->fdd[$k]['URLtarget']).'" '
  1281. : '';
  1282. $prefix_found = false;
  1283. $postfix_found = false;
  1284. $prefix_ar = @$this->fdd[$k]['URLprefix'];
  1285. $postfix_ar = @$this->fdd[$k]['URLpostfix'];
  1286. is_array($prefix_ar) || $prefix_ar = array($prefix_ar);
  1287. is_array($postfix_ar) || $postfix_ar = array($postfix_ar);
  1288. foreach ($prefix_ar as $prefix) {
  1289. if (! strncmp($prefix, $urllink, strlen($prefix))) {
  1290. $prefix_found = true;
  1291. break;
  1292. }
  1293. }
  1294. foreach ($postfix_ar as $postfix) {
  1295. if (! strncmp($postfix, $urllink, strlen($postfix))) {
  1296. $postfix_found = true;
  1297. break;
  1298. }
  1299. }
  1300. $prefix_found || $urllink = array_shift($prefix_ar).$urllink;
  1301. $postfix_found || $urllink = $urllink.array_shift($postfix_ar);
  1302. if (strlen($urllink) <= 0 || strlen($urldisp) <= 0) {
  1303. $ret = '&nbsp;';
  1304. } else {
  1305. if ($escape) {
  1306. $urldisp = htmlspecialchars($urldisp);
  1307. }
  1308. $urllink = htmlspecialchars($urllink);
  1309. $ret = '<a '.$target.'class="'.$css.'" href="'.$urllink.'">'.$urldisp.'</a>';
  1310. }
  1311. return $ret;
  1312. } /* }}} */
  1313. function cellDisplay($k, $row, $css) /* {{{ */
  1314. {
  1315. $escape = isset($this->fdd[$k]['escape']) ? $this->fdd[$k]['escape'] : true;
  1316. $key_rec = $row['qf'.$this->key_num];
  1317. if (@$this->fdd[$k]['datemask']) {
  1318. $value = intval($row["qf$k".'_timestamp']);
  1319. $value = $value ? @date($this->fdd[$k]['datemask'], $value) : '';
  1320. } else if (@$this->fdd[$k]['strftimemask']) {
  1321. $value = intval($row["qf$k".'_timestamp']);
  1322. $value = $value ? @strftime($this->fdd[$k]['strftimemask'], $value) : '';
  1323. } else if ($this->is_values2($k, $row["qf$k"])) {
  1324. $value = $row['qf'.$k.'_idx'];
  1325. if ($this->fdd[$k]['select'] == 'M') {
  1326. $value_ar = explode(',', $value);
  1327. $value_ar2 = array();
  1328. foreach ($value_ar as $value_key) {
  1329. if (isset($this->fdd[$k]['values2'][$value_key])) {
  1330. $value_ar2[$value_key] = $this->fdd[$k]['values2'][$value_key];
  1331. $escape = false;
  1332. }
  1333. }
  1334. $value = join(', ', $value_ar2);
  1335. } else {
  1336. if (isset($this->fdd[$k][

Large files files are truncated, but you can click here to view the full file