PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/modules/gazpme/phpMyEdit.class.php

https://bitbucket.org/marcor/gazie
PHP | 3396 lines | 2863 code | 135 blank | 398 comment | 894 complexity | 5d7b1b1a3d78f1a7efa1e32b1f1b23e9 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0, GPL-2.0
  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]['values2'][$value])) {
  1337. $value = $this->fdd[$k]['values2'][$value];
  1338. $escape = false;
  1339. }
  1340. }
  1341. } elseif (isset($this->fdd[$k]['values2'][$row["qf$k"]])) {
  1342. $value = $this->fdd[$k]['values2'][$row["qf$k"]];
  1343. } else {
  1344. $value = $row["qf$k"];
  1345. }
  1346. $original_value = $value;
  1347. if (@$this->fdd[$k]['strip_tags']) {
  1348. $value = strip_tags($value);
  1349. }
  1350. if ($num_ar = @$this->fdd[$k]['number_format']) {
  1351. if (! is_array($num_ar)) {
  1352. $num_ar = array($num_ar);
  1353. }
  1354. if (count($num_ar) == 1) {
  1355. list($nbDec) = $num_ar;
  1356. $value = number_format($value, $nbDec);
  1357. } else if (count($num_ar) == 3) {
  1358. list($nbDec, $decPoint, $thSep) = $num_ar;
  1359. $value = number_format($value, $nbDec, $decPoint, $thSep);
  1360. }
  1361. }
  1362. if (intval($this->fdd[$k]['trimlen']) > 0 && strlen($value) > $this->fdd[$k]['trimlen']) {
  1363. $value = ereg_replace("[\r\n\t ]+",' ',$value);
  1364. $value = substr($value, 0, $this->fdd[$k]['trimlen'] - 3).'...';
  1365. }
  1366. if (@$this->fdd[$k]['mask']) {
  1367. $value = sprintf($this->fdd[$k]['mask'], $value);
  1368. }
  1369. if ($this->col_has_php($k)) {
  1370. return include($this->fdd[$k]['php']);
  1371. }
  1372. if ($this->col_has_URL($k)) {
  1373. return $this->urlDisplay($k, $original_value, $value, $css, $key_rec);
  1374. }
  1375. if (strlen($value) <= 0) {
  1376. return '&nbsp;';
  1377. }
  1378. if ($escape) {
  1379. $value = htmlspecialchars($value);
  1380. }
  1381. return nl2br($value);
  1382. } /* }}} */
  1383. /**
  1384. * Creates HTML submit input element
  1385. *
  1386. * @param name element name
  1387. * @param label key in the language hash used as label
  1388. * @param css_class_name CSS class name
  1389. * @param js_validation if add JavaScript validation subroutine to button
  1390. * @param disabled if mark the button as disabled
  1391. * @param js any extra text in tags
  1392. */
  1393. function htmlSubmit($name, $label, $css_class_name, $js_validation = true, $disabled = false, $js = NULL) /* {{{ */
  1394. {
  1395. // Note that <input disabled> isn't valid HTML, but most browsers support it
  1396. if($disabled == -1) return;
  1397. $markdisabled = $disabled ? ' disabled' : '';
  1398. $ret = '<input'.$markdisabled.' type="submit" class="'.$css_class_name
  1399. .'" name="'.$this->cgi['prefix']['sys'].ltrim($markdisabled).$name
  1400. .'" value="'.(isset($this->labels[$label]) ? $this->labels[$label] : $label);
  1401. if ($js_validation) {
  1402. $ret .= '" onclick="return '.$this->js['prefix'].'form_control(this.form);';
  1403. }
  1404. $ret .='"';
  1405. if(isset($js)) $ret .= ' '.$js;
  1406. $ret .= ' />';
  1407. return $ret;
  1408. } /* }}} */
  1409. /**
  1410. * Creates HTML hidden input element
  1411. *
  1412. * @param name element name
  1413. * @param value value
  1414. */
  1415. function htmlHiddenSys($name, $value) /* {{{ */
  1416. {
  1417. return $this->htmlHidden($this->cgi['prefix']['sys'].$name, $value);
  1418. } /* }}} */
  1419. function htmlHiddenData($name, $value) /* {{{ */
  1420. {
  1421. return $this->htmlHidden($this->cgi['prefix']['data'].$name, $value);
  1422. } /* }}} */
  1423. function htmlHidden($name, $value) /* {{{ */
  1424. {
  1425. return '<input type="hidden" name="'.htmlspecialchars($name)
  1426. .'" value="'.htmlspecialchars($value).'" />'."\n";
  1427. } /* }}} */
  1428. /**
  1429. * Creates HTML select element (tag)
  1430. *
  1431. * @param name element name
  1432. * @param css CSS class name
  1433. * @param kv_array key => value array
  1434. * @param selected selected key (it can be single string, array of
  1435. * keys or multiple values separated by comma)
  1436. * @param multiple bool for multiple selection
  1437. * @param readonly bool for readonly/disabled selection
  1438. * @param strip_tags bool for stripping tags from values
  1439. * @param escape bool for HTML escaping values
  1440. * @param js string to be in the <select >, ususally onchange='..';
  1441. */
  1442. function htmlSelect($name, $css, $kv_array, $selected = null, /* ...) {{{ */
  1443. /* booleans: */ $multiple = false, $readonly = false, $strip_tags = false, $escape = true, $js = NULL)
  1444. {
  1445. $ret = '<select class="'.htmlspecialchars($css).'" name="'.htmlspecialchars($name);
  1446. if ($multiple) {
  1447. $ret .= '[]" multiple size="'.$this->multiple;
  1448. if (! is_array($selected) && $selected !== null) {
  1449. $selected = explode(',', $selected);
  1450. }
  1451. }
  1452. $ret .= '"'.($readonly ? ' disabled ' : ' ').$js.">\n";
  1453. if (! is_array($selected)) {
  1454. $selected = $selected === null ? array() : array((string)$selected);
  1455. } else {
  1456. foreach($selected as $val) $selecte2[]=(string)$val;
  1457. $selected = $selected2;
  1458. }
  1459. $found = false;
  1460. foreach ($kv_array as $key => $value) {
  1461. $ret .= '<option value="'.htmlspecialchars($key).'"';
  1462. if ((! $found || $multiple) && in_array((string)$key, $selected, 1)
  1463. || (count($selected) == 0 && ! $found && ! $multiple)) {
  1464. $ret .= ' selected="selected"';
  1465. $found = true;
  1466. }
  1467. $strip_tags && $value = strip_tags($value);
  1468. $escape && $value = htmlspecialchars($value);
  1469. $ret .= '>'.$value.'</option>'."\n";
  1470. }
  1471. $ret .= '</select>';
  1472. return $ret;
  1473. } /* }}} */
  1474. /**
  1475. * Creates HTML checkboxes or radio buttons
  1476. *
  1477. * @param name element name
  1478. * @param css CSS class name
  1479. * @param kv_array key => value array
  1480. * @param selected selected key (it can be single string, array of
  1481. * keys or multiple values separated by comma)
  1482. * @param multiple bool for multiple selection (checkboxes)
  1483. * @param readonly bool for readonly/disabled selection
  1484. * @param strip_tags bool for stripping tags from values
  1485. * @param escape bool for HTML escaping values
  1486. * @param js string to be in the <select >, ususally onchange='..';
  1487. */
  1488. function htmlRadioCheck($name, $css, $kv_array, $selected = null, /* ...) {{{ */
  1489. /* booleans: */ $multiple = false, $readonly = false, $strip_tags = false, $escape = true, $js = NULL)
  1490. {
  1491. $ret = '';
  1492. if ($multiple) {
  1493. if (! is_array($selected) && $selected !== null) {
  1494. $selected = explode(',', $selected);
  1495. }
  1496. }
  1497. if (! is_array($selected)) {
  1498. $selected = $selected === null ? array() : array($selected);
  1499. }
  1500. $found = false;
  1501. foreach ($kv_array as $key => $value) {
  1502. $ret .= '<input type="'.($multiple ? 'checkbox' : 'radio').'" name="';
  1503. $ret .= htmlspecialchars($name).'[]" value="'.htmlspecialchars($key).'"';
  1504. if ((! $found || $multiple) && in_array((string) $key, $selected, 1)
  1505. || (count($selected) == 0 && ! $found && ! $multiple)) {
  1506. $ret .= ' checked';
  1507. $found = true;
  1508. }
  1509. if ($readonly) {
  1510. $ret .= ' disabled';
  1511. }
  1512. $strip_tags && $value = strip_tags($value);
  1513. $escape && $value = htmlspecialchars($value);
  1514. $ret .= '>'.$value.'<br>'."\n";
  1515. }
  1516. return $ret;
  1517. } /* }}} */
  1518. /**
  1519. * Returns original variables HTML code for use in forms or links.
  1520. *
  1521. * @param mixed $origvars string or array of original varaibles
  1522. * @param string $method type of method ("POST" or "GET")
  1523. * @param mixed $default_value default value of variables
  1524. * if null, empty values will be skipped
  1525. * @return get HTML code of original varaibles
  1526. */
  1527. function get_origvars_html($origvars, $method = 'post', $default_value = '') /* {{{ */
  1528. {
  1529. $ret = '';
  1530. $method = strtoupper($method);
  1531. if ($method == 'POST') {
  1532. if (! is_array($origvars)) {
  1533. $new_origvars = array();
  1534. foreach (explode('&', $origvars) as $param) {
  1535. $parts = explode('=', $param, 2);
  1536. if (! isset($parts[1])) {
  1537. $parts[1] = $default_value;
  1538. }
  1539. if (strlen($parts[0]) <= 0) {
  1540. continue;
  1541. }
  1542. $new_origvars[$parts[0]] = $parts[1];
  1543. }
  1544. $origvars =& $new_origvars;
  1545. }
  1546. foreach ($origvars as $key => $val) {
  1547. if (strlen($val) <= 0 && $default_value === null) {
  1548. continue;
  1549. }
  1550. $key = rawurldecode($key);
  1551. $val = rawurldecode($val);
  1552. $ret .= $this->htmlHidden($key, $val);
  1553. }
  1554. } else if (! strncmp('GET', $method, 3)) {
  1555. if (! is_array($origvars)) {
  1556. $ret .= $origvars;
  1557. } else {
  1558. foreach ($origvars as $key => $val) {
  1559. if (strlen($val) <= 0 && $default_value === null) {
  1560. continue;
  1561. }
  1562. $ret == '' || $ret .= '&amp;';
  1563. $ret .= htmlspecialchars(rawurlencode($key));
  1564. $ret .= '=';
  1565. $ret .= htmlspecialchars(rawurlencode($val));
  1566. }
  1567. }
  1568. if ($method[strlen($method) - 1] == '+') {
  1569. $ret = "?$ret";
  1570. }
  1571. } else {
  1572. trigger_error('Unsupported Platon::get_origvars_html() method: '
  1573. .$method, E_USER_ERROR);
  1574. }
  1575. return $ret;
  1576. } /* }}} */
  1577. function get_sfn_cgi_vars($alternative_sfn = null) /* {{{ */
  1578. {
  1579. if ($alternative_sfn === null) { // FAST! (cached return value)
  1580. static $ret = null;
  1581. $ret == null && $ret = $this->get_sfn_cgi_vars($this->sfn);
  1582. return $ret;
  1583. }
  1584. $ret = '';
  1585. $i = 0;
  1586. foreach ($alternative_sfn as $val) {
  1587. $ret != '' && $ret .= '&';
  1588. $ret .= rawurlencode($this->cgi['prefix']['sys'].'sfn')."[$i]=".rawurlencode($val);
  1589. $i++;
  1590. }
  1591. return $ret;
  1592. } /* }}} */
  1593. function get_default_cgi_prefix($type) /* {{{ */
  1594. {
  1595. switch ($type) {
  1596. case 'operation': return 'PME_op_';
  1597. case 'sys': return 'PME_sys_';
  1598. case 'data': return 'PME_data_';
  1599. }
  1600. return '';
  1601. } /* }}} */
  1602. function get_sys_cgi_var($name, $default_value = null) /* {{{ */
  1603. {
  1604. if (isset($this)) {
  1605. return $this->get_cgi_var($this->cgi['prefix']['sys'].$name, $default_value);
  1606. }
  1607. return phpMyEdit::get_cgi_var(phpMyEdit::get_default_cgi_prefix('sys').$name, $default_value);
  1608. } /* }}} */
  1609. function get_data_cgi_var($name, $default_value = null) /* {{{ */
  1610. {
  1611. if (isset($this)) {
  1612. return $this->get_cgi_var($this->cgi['prefix']['data'].$name, $default_value);
  1613. }
  1614. return phpMyEdit::get_cgi_var(phpMyEdit::get_default_cgi_prefix('data').$name, $default_value);
  1615. } /* }}} */
  1616. function get_cgi_var($name, $default_value = null) /* {{{ */
  1617. {
  1618. if (isset($this) && isset($this->cgi['overwrite'][$name])) {
  1619. return $this->cgi['overwrite'][$name];
  1620. }
  1621. static $magic_quotes_gpc = null;
  1622. if ($magic_quotes_gpc === null) {
  1623. $magic_quotes_gpc = get_magic_quotes_gpc();
  1624. }
  1625. $var = @$_GET[$name];
  1626. if (! isset($var)) {
  1627. $var = @$_POST[$name];
  1628. }
  1629. if (isset($var)) {
  1630. if ($magic_quotes_gpc) {
  1631. if (is_array($var)) {
  1632. foreach (array_keys($var) as $key) {
  1633. $var[$key] = stripslashes($var[$key]);
  1634. }
  1635. } else {
  1636. $var = stripslashes($var);
  1637. }
  1638. }
  1639. } else {
  1640. $var = @$default_value;
  1641. }
  1642. if (isset($this) && $var === null && isset($this->cgi['append'][$name])) {
  1643. return $this->cgi['append'][$name];
  1644. }
  1645. return $var;
  1646. } /* }}} */
  1647. function get_server_var($name) /* {{{ */
  1648. {
  1649. if (isset($_SERVER[$name])) {
  1650. return $_SERVER[$name];
  1651. }
  1652. global $HTTP_SERVER_VARS;
  1653. if (isset($HTTP_SERVER_VARS[$name])) {
  1654. return $HTTP_SERVER_VARS[$name];
  1655. }
  1656. global $$name;
  1657. if (isset($$name)) {
  1658. return $$name;
  1659. }
  1660. return null;
  1661. } /* }}} */
  1662. /*
  1663. * Debug functions
  1664. */
  1665. function print_get_vars ($miss = 'No GET variables found') // debug only /* {{{ */
  1666. {
  1667. // we parse form GET variables
  1668. if (is_array($_GET)) {
  1669. echo "<p> Variables per GET ";
  1670. foreach ($_GET as $k => $v) {
  1671. if (is_array($v)) {
  1672. foreach ($v as $akey => $aval) {
  1673. // $_GET[$k][$akey] = strip_tags($aval);
  1674. // $$k[$akey] = strip_tags($aval);
  1675. echo "$k\[$akey\]=$aval ";
  1676. }
  1677. } else {
  1678. // $_GET[$k] = strip_tags($val);
  1679. // $$k = strip_tags($val);
  1680. echo "$k=$v ";
  1681. }
  1682. }
  1683. echo '</p>';
  1684. } else {
  1685. echo '<p>';
  1686. echo $miss;
  1687. echo '</p>';
  1688. }
  1689. } /* }}} */
  1690. function print_post_vars($miss = 'No POST variables found') // debug only /* {{{ */
  1691. {
  1692. global $_POST;
  1693. // we parse form POST variables
  1694. if (is_array($_POST)) {
  1695. echo "<p>Variables per POST ";
  1696. foreach ($_POST as $k => $v) {
  1697. if (is_array($v)) {
  1698. foreach ($v as $akey => $aval) {
  1699. // $_POST[$k][$akey] = strip_tags($aval);
  1700. // $$k[$akey] = strip_tags($aval);
  1701. echo "$k\[$akey\]=$aval ";
  1702. }
  1703. } else {
  1704. // $_POST[$k] = strip_tags($val);
  1705. // $$k = strip_tags($val);
  1706. echo "$k=$v ";
  1707. }
  1708. }
  1709. echo '</p>';
  1710. } else {
  1711. echo '<p>';
  1712. echo $miss;
  1713. echo '</p>';
  1714. }
  1715. } /* }}} */
  1716. function print_vars ($miss = 'Current instance variables') // debug only /* {{{ */
  1717. {
  1718. echo "$miss ";
  1719. echo 'page_name=',$this->page_name,' ';
  1720. echo 'hn=',$this->hn,' ';
  1721. echo 'un=',$this->un,' ';
  1722. echo 'pw=',$this->pw,' ';
  1723. echo 'db=',$this->db,' ';
  1724. echo 'dbp=',$this->dbp,' ';
  1725. echo 'dbh=',$this->dbh,' ';
  1726. echo 'tb=',$this->tb,' ';
  1727. echo 'key=',$this->key,' ';
  1728. echo 'key_type=',$this->key_type,' ';
  1729. echo 'inc=',$this->inc,' ';
  1730. echo 'options=',$this->options,' ';
  1731. echo 'fdd=',$this->fdd,' ';
  1732. echo 'fl=',$this->fl,' ';
  1733. echo 'fm=',$this->fm,' ';
  1734. echo 'sfn=',htmlspecialchars($this->get_sfn_cgi_vars()),' ';
  1735. echo 'qfn=',$this->qfn,' ';
  1736. echo 'sw=',$this->sw,' ';
  1737. echo 'rec=',$this->rec,' ';
  1738. echo 'navop=',$this->navop,' ';
  1739. echo 'saveadd=',$this->saveadd,' ';
  1740. echo 'moreadd=',$this->moreadd,' ';
  1741. echo 'canceladd=',$this->canceladd,' ';
  1742. echo 'savechange=',$this->savechange,' ';
  1743. echo 'morechange=',$this->morechange,' ';
  1744. echo 'cancelchange=',$this->cancelchange,' ';
  1745. echo 'savecopy=',$this->savecopy,' ';
  1746. echo 'cancelcopy=',$this->cancelcopy,' ';
  1747. echo 'savedelete=',$this->savedelete,' ';
  1748. echo 'canceldelete=',$this->canceldelete,' ';
  1749. echo 'cancelview=',$this->cancelview,' ';
  1750. echo 'operation=',$this->operation,' ';
  1751. echo "\n";
  1752. } /* }}} */
  1753. /*
  1754. * Display buttons at top and bottom of page
  1755. */
  1756. function display_list_table_buttons($position, $listall = false) /* {{{ */
  1757. {
  1758. if (($but_str = $this->display_buttons($position)) === null)
  1759. return;
  1760. if($position == 'down') echo '<hr size="1" class="'.$this->getCSSclass('hr', 'down').'" />'."\n";
  1761. echo '<table summary="navigation" class="',$this->getCSSclass('navigation', $position),'">',"\n";
  1762. echo '<tr class="',$this->getCSSclass('navigation', $position),'">',"\n";
  1763. echo '<td class="',$this->getCSSclass('buttons', $position),'">',"\n";
  1764. echo $but_str,'</td>',"\n";
  1765. // Message is now written here
  1766. if (strlen(@$this->message) > 0) {
  1767. echo '<td class="',$this->getCSSclass('message', $position),'">',$this->message,'</td>',"\n";
  1768. }
  1769. if($this->display['num_pages'] || $this->display['num_records'])
  1770. echo '<td class="',$this->getCSSclass('stats', $position),'">',"\n";
  1771. if($this->display['num_pages']) {
  1772. if ($listall) {
  1773. echo $this->labels['Page'],':&nbsp;1&nbsp;',$this->labels['of'],'&nbsp;1';
  1774. } else {
  1775. $current_page = intval($this->fm / $this->inc) + 1;
  1776. $total_pages = max(1, ceil($this->total_recs / abs($this->inc)));
  1777. echo $this->labels['Page'],':&nbsp;',$current_page;
  1778. echo '&nbsp;',$this->labels['of'],'&nbsp;',$total_pages;
  1779. }
  1780. }
  1781. if($this->display['num_records'])
  1782. echo '&nbsp; ',$this->labels['Records'],':&nbsp;',$this->total_recs;
  1783. if($this->display['num_pages'] || $this->display['num_records']) echo '</td>';
  1784. echo '</tr></table>',"\n";
  1785. if($position == 'up') echo '<hr size="1" class="'.$this->getCSSclass('hr', 'up').'" />'."\n";
  1786. } /* }}} */
  1787. /*
  1788. * Display buttons at top and bottom of page
  1789. */
  1790. function display_record_buttons($position) /* {{{ */
  1791. {
  1792. if (($but_str = $this->display_buttons($position)) === null)
  1793. return;
  1794. if ($position == 'down') {
  1795. if ($this->tabs_enabled()) $this->display_tab_labels('down');
  1796. echo '<hr size="1" class="',$this->getCSSclass('hr', 'down'),'" />',"\n";
  1797. }
  1798. echo '<table summary="navigation" class="',$this->getCSSclass('navigation', $position),'">',"\n";
  1799. echo '<tr class="',$this->getCSSclass('navigation', $position),'">',"\n";
  1800. echo '<td class="',$this->getCSSclass('buttons', $position),'">',"\n";
  1801. echo $but_str,'</td>',"\n";
  1802. // Message is now written here
  1803. //echo '</td>',"\n";
  1804. if (strlen(@$this->message) > 0) {
  1805. echo '<td class="',$this->getCSSclass('message', $position),'">',$this->message,'</td>',"\n";
  1806. }
  1807. echo '</tr></table>',"\n";
  1808. if ($position == 'up') {
  1809. if ($this->tabs_enabled()) $this->display_tab_labels('up');
  1810. echo '<hr size="1" class="',$this->getCSSclass('hr', 'up'),'" />',"\n";
  1811. }
  1812. } /* }}} */
  1813. function display_buttons($position) /* {{{ */
  1814. {
  1815. $nav_fnc = 'nav_'.$position;
  1816. if(! $this->$nav_fnc())
  1817. return;
  1818. $buttons = (is_array($this->buttons[$this->page_type][$position]))
  1819. ? $this->buttons[$this->page_type][$position]
  1820. : $this->default_buttons[$this->page_type];
  1821. foreach ($buttons as $name) {
  1822. $ret .= $this->display_button($name, $position)."\n";
  1823. }
  1824. return $ret;
  1825. } /* }}} */
  1826. function display_button($name, $position = 'up') /* {{{ */
  1827. {
  1828. if (is_array($name)) {
  1829. if (isset($name['code'])) return $name['code'];
  1830. return $this->htmlSubmit($name['name'], $name['value'], $name['css'], $name['js_validation'], $name['disabled'], $name['js']);
  1831. }
  1832. $disabled = 1; // show disabled by default
  1833. if ($name[0] == '+') { $name = substr($name, 1); $disabled = 0; } // always show disabled as enabled
  1834. if ($name[0] == '-') { $name = substr($name, 1); $disabled = -1; } // don't show disabled
  1835. if ($name == 'cancel') {
  1836. return $this->htmlSubmit('cancel'.$this->page_types[$this->page_type], 'Cancel',
  1837. $this->getCSSclass('cancel', $position), false);
  1838. }
  1839. if (in_array($name, array('add','view','change','copy','delete'))) {
  1840. $enabled_fnc = $name.'_enabled';
  1841. $enabled = $this->$enabled_fnc();
  1842. if ($name != 'add' && ! $this->total_recs && strstr('LF', $this->page_type))
  1843. $enabled = false;
  1844. return $this->htmlSubmit('operation', ucfirst($name),
  1845. $this->getCSSclass($name, $position), false, $enabled ? 0 : $disabled);
  1846. }
  1847. if ($name == 'savedelete') {
  1848. $enabled = $this->delete_enabled();
  1849. $js = 'onclick="return confirm(\''.$this->labels['Delete'].' ?\');"';
  1850. return $this->htmlSubmit('savedelete', 'Delete',
  1851. $this->getCSSclass('save', $position), false, $enabled ? 0 : $disabled, $js);
  1852. }
  1853. if (in_array($name, array('save','more'))) {
  1854. $validation = true; // if js validation
  1855. if ($this->page_type == 'D' && $name == 'save' ) { $value = 'Delete'; $validation = false; }
  1856. elseif ($this->page_type == 'C' && $name == 'more' ) { $value = 'Apply'; }
  1857. else $value = ucfirst($name);
  1858. return $this->htmlSubmit($name.$this->page_types[$this->page_type], $value,
  1859. $this->getCSSclass($name, $position), $validation);
  1860. }
  1861. $listall = $this->inc <= 0;
  1862. if ($listall) {
  1863. $disabledprev = true;
  1864. $disablednext = true;
  1865. $total_pages = 1;
  1866. $current_page = 1;
  1867. } else {
  1868. $disabledprev = $this->fm <= 0;
  1869. $disablednext = $this->fm + $this->inc >= $this->total_recs;
  1870. $total_pages = max(1, ceil($this->total_recs / abs($this->inc)));
  1871. $current_page = ceil($this->fm / abs($this->inc)); // must + 1
  1872. }
  1873. $disabledfirst = $disabledprev;
  1874. $disabledlast = $disablednext;
  1875. // some statistics first
  1876. if ($name == 'total_pages') return $total_pages;
  1877. if ($name == 'current_page') return ($current_page+1);
  1878. if ($name == 'total_recs') return ($this->total_recs);
  1879. // now some goto buttons/dropdowns/inputs...
  1880. if ($name == 'goto_text') {
  1881. $ret = '<input type="text" class="'.$this->getCSSclass('gotopn', $position).'"';
  1882. $ret .= ' name="'.$this->cgi['prefix']['sys'].'navpn'.$position.'" value="'.($current_page+1).'"';
  1883. $ret .= ' size="'.(strlen($total_pages)+1).'" maxlength="'.(strlen($total_pages)+1).'"';
  1884. // TODO some js here.... on enter submit, on click erase ?...
  1885. $ret .=' oneypress="return PE_filter_handler(this.form, event);" />';
  1886. return $ret;
  1887. }
  1888. if ($name == 'goto_combo') {
  1889. $disabledgoto = !($listall || ($disablednext && $disabledprev)) ? '' : ' disabled';
  1890. if ($disablegoto != '' && $disabled < 0) return;
  1891. $kv_array = array();
  1892. for ($i = 0; $i < $total_pages; $i++) {
  1893. $kv_array[$this->inc * $i] = $i + 1;
  1894. }
  1895. // TODO: add onchange="return this.form.submit();" DONE ???
  1896. return $this->htmlSelect($this->cgi['prefix']['sys'].ltrim($disabledgoto).'navfm'.$position,
  1897. $this->getCSSclass('goto', $position), $kv_array, (string)$this->fm, false, $disabledgoto,
  1898. false, true, 'onchange="return this.form.submit();"');
  1899. }
  1900. if ($name == 'goto') {
  1901. return $this->htmlSubmit('navop', 'Go to', $this->getCSSclass('goto', $position),
  1902. false, ($listall || ($disablednext && $disabledprev)) ? $disabled : 0);
  1903. }
  1904. if (in_array($name, array('first','prev','next','last','<<','<','>','>>'))) {
  1905. $disabled_var = 'disabled'.$name;
  1906. $name2 = $name;
  1907. if (strlen($name) <= 2) {
  1908. $nav_values = array('<<' => 'first', '<' => 'prev', '>' => 'next', '>>' => 'last');
  1909. $disabled_var = 'disabled'.$nav_values[$name];
  1910. $name2 = $nav_values[$name];
  1911. }
  1912. return $this->htmlSubmit('navop', ucfirst($name),
  1913. $this->getCSSclass($name2, $position), false, $$disabled_var ? $disabled : 0);
  1914. }
  1915. if(isset($this->labels[$name])) return $this->labels[$name];
  1916. return $name;
  1917. } /* }}} */
  1918. function number_of_recs() /* {{{ */
  1919. {
  1920. $count_parts = array(
  1921. 'type' => 'select',
  1922. 'select' => 'count(*)',
  1923. 'from' => $this->get_SQL_join_clause(),
  1924. 'where' => $this->get_SQL_where_from_query_opts());
  1925. $res = $this->myquery($this->get_SQL_main_list_query($count_parts), __LINE__);
  1926. $row = $this->sql_fetch($res, 'n');
  1927. $this->total_recs = $row[0];
  1928. } /* }}} */
  1929. /*
  1930. * Table Page Listing
  1931. */
  1932. function list_table() /* {{{ */
  1933. {
  1934. if ($this->fm == '') {
  1935. $this->fm = 0;
  1936. }
  1937. $this->fm = $this->navfm;
  1938. if ($this->prev_operation()) {
  1939. $this->fm = $this->fm - $this->inc;
  1940. if ($this->fm < 0) {
  1941. $this->fm = 0;
  1942. }
  1943. }
  1944. if ($this->first_operation()) {
  1945. $this->fm = 0;
  1946. } // last operation must be performed below, after retrieving total_recs
  1947. if ($this->next_operation()) {
  1948. $this->fm += $this->inc;
  1949. }
  1950. $this->number_of_recs();
  1951. if ($this->last_operation() || $this->fm > $this->total_recs) { // if goto_text is badly set
  1952. $this->fm = (int)(($this->total_recs - 1)/$this->inc)*$this->inc;
  1953. }
  1954. // If sort sequence has changed, restart listing
  1955. $this->qfn != $this->prev_qfn && $this->fm = 0;
  1956. if (0) { // DEBUG
  1957. echo 'qfn vs. prev_qfn comparsion ';
  1958. echo '[<b>',htmlspecialchars($this->qfn),'</b>]';
  1959. echo '[<b>',htmlspecialchars($this->prev_qfn),'</b>]<br />';
  1960. echo 'comparsion <u>',($this->qfn == $this->prev_qfn ? 'proved' : 'failed'),'</u>';
  1961. echo '<hr size="1" />';
  1962. }
  1963. /*
  1964. * If user is allowed to Change/Delete records, we need an extra column
  1965. * to allow users to select a record
  1966. */
  1967. $select_recs = $this->key != '' &&
  1968. ($this->change_enabled() || $this->delete_enabled() || $this->view_enabled());
  1969. // Are we doing a listall?
  1970. $listall = $this->inc <= 0;
  1971. /*
  1972. * Display the SQL table in an HTML table
  1973. */
  1974. $this->form_begin();
  1975. echo $this->get_origvars_html($this->get_sfn_cgi_vars());
  1976. echo $this->htmlHiddenSys('fl', $this->fl);
  1977. // Display buttons at top and/or bottom of page.
  1978. $this->display_list_table_buttons('up', $listall);
  1979. if ($this->cgi['persist'] != '') {
  1980. echo $this->get_origvars_html($this->cgi['persist']);
  1981. }
  1982. if (! $this->filter_operation()) {
  1983. echo $this->get_origvars_html($this->qfn);
  1984. }
  1985. echo $this->htmlHiddenSys('qfn', $this->qfn);
  1986. echo $this->htmlHiddenSys('fm', $this->fm);
  1987. echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n";
  1988. echo '<tr class="',$this->getCSSclass('header'),'">',"\n";
  1989. /*
  1990. * System (navigation, selection) columns counting
  1991. */
  1992. $sys_cols = 0;
  1993. $sys_cols += intval($this->filter_enabled() || $select_recs);
  1994. if ($sys_cols > 0) {
  1995. $sys_cols += intval($this->nav_buttons()
  1996. && ($this->nav_text_links() || $this->nav_graphic_links()));
  1997. }
  1998. /*
  1999. * We need an initial column(s) (sys columns)
  2000. * if we have filters, Changes or Deletes enabled
  2001. */
  2002. if ($sys_cols) {
  2003. echo '<th class="',$this->getCSSclass('header'),'" colspan="',$sys_cols,'">';
  2004. if ($this->filter_enabled()) {
  2005. if ($this->filter_operation()) {
  2006. echo $this->htmlSubmit('sw', 'Hide', $this->getCSSclass('hide'), false);
  2007. echo $this->htmlSubmit('sw', 'Clear', $this->getCSSclass('clear'), false);
  2008. } else {
  2009. echo $this->htmlSubmit('sw', 'Search', $this->getCSSclass('search'), false);
  2010. }
  2011. } else {
  2012. echo '&nbsp;';
  2013. }
  2014. echo '</th>',"\n";
  2015. }
  2016. for ($k = 0; $k < $this->num_fds; $k++) {
  2017. $fd = $this->fds[$k];
  2018. if (! $this->displayed[$k]) {
  2019. continue;
  2020. }
  2021. $css_postfix = @$this->fdd[$k]['css']['postfix'];
  2022. $css_class_name = $this->getCSSclass('header', null, null, $css_postfix);
  2023. $fdn = $this->fdd[$fd]['name'];
  2024. if (! $this->fdd[$fd]['sort'] || $this->password($fd)) {
  2025. echo '<th class="',$css_class_name,'">',$fdn,'</th>',"\n";
  2026. } else {
  2027. // Clicking on the current sort field reverses the sort order
  2028. $new_sfn = $this->sfn;
  2029. array_unshift($new_sfn, in_array("$k", $new_sfn, 1) ? "-$k" : $k);
  2030. echo '<th class="',$css_class_name,'">';
  2031. // INIZIO patch per GAzie
  2032. echo '<div onclick="GAz_sys_form.'.$this->cgi['prefix']['sys'].'fm.value=0; '.
  2033. 'GAz_sys_form.'.$this->cgi['prefix']['sys'].'fl.value='.$this->fl.'; '.
  2034. 'GAz_sys_form.elements[\''.$this->cgi['prefix']['sys'].'sfn[0]\'].value='.$new_sfn[0].'; '.
  2035. 'GAz_sys_form.submit();'.'" class="',$css_class_name,'" style="cursor:pointer;">';
  2036. echo $fdn;
  2037. echo '</div>';
  2038. // FINE patch per GAzie
  2039. /* --- VECCHIO METODO CESTINATO
  2040. FRANCAMENTE NON CAPISCO L'UTILITA' DI CREARE UN FILE php PER OGNI TABELLA!
  2041. echo '<a class="',$css_class_name,'" href="';
  2042. echo htmlspecialchars($this->page_name.'?'.$this->cgi['prefix']['sys'].'fm'.'=0'
  2043. .'&'.$this->cgi['prefix']['sys'].'fl'.'='.$this->fl
  2044. .'&'.$this->cgi['prefix']['sys'].'qfn'.'='.rawurlencode($this->qfn).$this->qfn
  2045. .'&'.$this->get_sfn_cgi_vars($new_sfn).$this->cgi['persist']);
  2046. echo '">',$fdn,'</a>
  2047. */
  2048. echo '</th>',"\n";
  2049. }
  2050. }
  2051. echo '</tr>',"\n";
  2052. /*
  2053. * Prepare the SQL Query from the data definition file
  2054. */
  2055. $qparts['type'] = 'select';
  2056. $qparts['select'] = $this->get_SQL_column_list();
  2057. // Even if the key field isn't displayed, we still need its value
  2058. if ($select_recs) {
  2059. if (!in_array ($this->key, $this->fds)) {
  2060. $qparts['select'] .= ','.$this->fqn($this->key);
  2061. }
  2062. }
  2063. $qparts['from'] = $this->get_SQL_join_clause();
  2064. $qparts['where'] = $this->get_SQL_where_from_query_opts();
  2065. // build up the ORDER BY clause
  2066. if (isset($this->sfn)) {
  2067. $sort_fields = array();
  2068. $sort_fields_w = array();
  2069. foreach ($this->sfn as $field) {
  2070. if ($field[0] == '-') {
  2071. $field = substr($field, 1);
  2072. $desc = true;
  2073. } else {
  2074. $field = $field;
  2075. $desc = false;
  2076. }
  2077. $sort_field = $this->fqn($field);
  2078. $sort_field_w = $this->fdd[$field]['name'];
  2079. $this->col_has_sql($field) && $sort_field_w .= ' (sql)';
  2080. if ($desc) {
  2081. $sort_field .= ' DESC';
  2082. $sort_field_w .= ' '.$this->labels['descending'];
  2083. } else {
  2084. $sort_field_w .= ' '.$this->labels['ascending'];
  2085. }
  2086. $sort_fields[] = $sort_field;
  2087. $sort_fields_w[] = $sort_field_w;
  2088. }
  2089. if (count($sort_fields) > 0) {
  2090. $qparts['orderby'] = join(',', $sort_fields);
  2091. }
  2092. }
  2093. $qparts['limit'] = $listall ? '' : $this->sql_limit($this->fm,$this->inc);
  2094. /*
  2095. * Main list_table() query
  2096. *
  2097. * Each row of the HTML table is one record from the SQL query. We must
  2098. * perform this query before filter printing, because we want to use
  2099. * $this->sql_field_len() function. We will also fetch the first row to get
  2100. * the field names.
  2101. */
  2102. $query = $this->get_SQL_main_list_query($qparts);
  2103. $res = $this->myquery($query, __LINE__);
  2104. if ($res == false) {
  2105. $this->error('invalid SQL query', $query);
  2106. return false;
  2107. }
  2108. $row = $this->sql_fetch($res);
  2109. /* FILTER {{{
  2110. *
  2111. * Draw the filter and fill it with any data typed in last pass and stored
  2112. * in the array parameter keyword 'filter'. Prepare the SQL WHERE clause.
  2113. */
  2114. if ($this->filter_operation()) {
  2115. // Filter row retrieval
  2116. $fields = false;
  2117. $filter_row = $row;
  2118. if (! is_array($filter_row)) {
  2119. unset($qparts['where']);
  2120. $query = $this->get_SQL_query($qparts);
  2121. $res = $this->myquery($query, __LINE__);
  2122. if ($res == false) {
  2123. $this->error('invalid SQL query', $query);
  2124. return false;
  2125. }
  2126. $filter_row = $this->sql_fetch($res);
  2127. }
  2128. /* Variable $fields is used to get index of particular field in
  2129. result. That index can be passed in example to $this->sql_field_len()
  2130. function. Use field names as indexes to $fields array. */
  2131. if (is_array($filter_row)) {
  2132. $fields = array_flip(array_keys($filter_row));
  2133. }
  2134. if ($fields != false) {
  2135. $css_class_name = $this->getCSSclass('filter');
  2136. echo '<tr class="',$css_class_name,'">',"\n";
  2137. echo '<td class="',$css_class_name,'" colspan="',$sys_cols,'">';
  2138. echo $this->htmlSubmit('filter', 'Query', $this->getCSSclass('query'), false);
  2139. echo '</td>', "\n";
  2140. for ($k = 0; $k < $this->num_fds; $k++) {
  2141. if (! $this->displayed[$k]) {
  2142. continue;
  2143. }
  2144. $css_postfix = @$this->fdd[$k]['css']['postfix'];
  2145. $css_class_name = $this->getCSSclass('filter', null, null, $css_postfix);
  2146. $this->field_name = $this->fds[$k];
  2147. $fd = $this->field_name;
  2148. $this->field = $this->fdd[$fd];
  2149. $l = 'qf'.$k;
  2150. $lc = 'qf'.$k.'_comp';
  2151. $li = 'qf'.$k.'_id';
  2152. if ($this->clear_operation()) {
  2153. $m = null;
  2154. $mc = null;
  2155. $mi = null;
  2156. } else {
  2157. $m = $this->get_sys_cgi_var($l);
  2158. $mc = $this->get_sys_cgi_var($lc);
  2159. $mi = $this->get_sys_cgi_var($li);
  2160. }
  2161. echo '<td class="',$css_class_name,'">';
  2162. if ($this->password($k)) {
  2163. echo '&nbsp;';
  2164. } else if ($this->fdd[$fd]['select'] == 'D' || $this->fdd[$fd]['select'] == 'M') {
  2165. // Multiple fields processing
  2166. // Default size is 2 and array required for values.
  2167. $from_table = ! $this->col_has_values($k) || isset($this->fdd[$k]['values']['table']);
  2168. $vals = $this->set_values($k, array('*' => '*'), null, $from_table);
  2169. $selected = $mi;
  2170. $multiple = $this->col_has_multiple_select($k);
  2171. $multiple |= $this->fdd[$fd]['select'] == 'M';
  2172. $readonly = false;
  2173. $strip_tags = true;
  2174. $escape = true;
  2175. echo $this->htmlSelect($this->cgi['prefix']['sys'].$l.'_id', $css_class_name,
  2176. $vals, $selected, $multiple, $readonly, $strip_tags, $escape);
  2177. } elseif ($this->fdd[$fd]['select'] == 'N' || $this->fdd[$fd]['select'] == 'T') {
  2178. $len_props = '';
  2179. $maxlen = intval($this->fdd[$k]['maxlen']);
  2180. $maxlen > 0 || $maxlen = intval($this->sql_field_len($res, $fields["qf$k"]));
  2181. $size = isset($this->fdd[$k]['size']) ? $this->fdd[$k]['size']
  2182. : ($maxlen < 30 ? min($maxlen, 8) : 12);
  2183. $len_props .= ' size="'.$size.'"';
  2184. $len_props .= ' maxlength="'.$maxlen.'"';
  2185. if ($this->fdd[$fd]['select'] == 'N') {
  2186. $mc = in_array($mc, $this->comp_ops) ? $mc : '=';
  2187. echo $this->htmlSelect($this->cgi['prefix']['sys'].$l.'_comp',
  2188. $css_class_name, $this->comp_ops, $mc);
  2189. }
  2190. echo '<input class="',$css_class_name,'" value="',htmlspecialchars(@$m);
  2191. echo '" type="text" name="'.$this->cgi['prefix']['sys'].'qf'.$k.'"',$len_props;
  2192. echo ' onkeypress="return '.$this->js['prefix'].'filter_handler(this.form, event);" />';
  2193. } else {
  2194. echo '&nbsp;';
  2195. }
  2196. echo '</td>',"\n";
  2197. }
  2198. echo '</tr>',"\n";
  2199. }
  2200. } // }}}
  2201. /*
  2202. * Display sorting sequence
  2203. */
  2204. if ($qparts['orderby'] && $this->display['sort']) {
  2205. $css_class_name = $this->getCSSclass('sortinfo');
  2206. echo '<tr class="',$css_class_name,'">',"\n";
  2207. echo '<td class="',$css_class_name,'" colspan="',$sys_cols,'">';
  2208. echo '<a class="',$css_class_name,'" href="';
  2209. echo htmlspecialchars($this->page_name
  2210. .'?'.$this->cgi['prefix']['sys'].'fl'.'='.$this->fl
  2211. .'&'.$this->cgi['prefix']['sys'].'fm'.'='.$this->fm
  2212. .'&'.$this->cgi['prefix']['sys'].'qfn'.'='.rawurlencode($this->qfn)
  2213. .$this->qfn.$this->cgi['persist']);
  2214. echo '">',$this->labels['Clear'],'</a></td>',"\n";
  2215. echo '<td class="',$css_class_name,'" colspan="',$this->num_fields_displayed,'">';
  2216. echo $this->labels['Sorted By'],': ',join(', ', $sort_fields_w),'</td></tr>',"\n";
  2217. }
  2218. /*
  2219. * Display the current query
  2220. */
  2221. $text_query = $this->get_SQL_where_from_query_opts(null, true);
  2222. if ($text_query != '' && $this->display['query']) {
  2223. $css_class_name = $this->getCSSclass('queryinfo');
  2224. echo '<tr class="',$css_class_name,'">',"\n";
  2225. echo '<td class="',$css_class_name,'" colspan="',$sys_cols,'">';
  2226. echo '<a class="',$css_class_name,'" href="';
  2227. echo htmlspecialchars($this->get_server_var('PHP_SELF')
  2228. .'?'.$this->cgi['prefix']['sys'].'fl'.'='.$this->fl
  2229. .'&'.$this->cgi['prefix']['sys'].'fm'.'='.$this->fm
  2230. .'&'.$this->cgi['prefix']['sys'].'qfn'.'='.rawurlencode($this->qfn)
  2231. .'&'.$this->get_sfn_cgi_vars().$this->cgi['persist']);
  2232. echo '">',$this->labels['Clear'],'</a></td>',"\n";
  2233. echo '<td class="',$css_class_name,'" colspan="',$this->num_fields_displayed,'">';
  2234. echo $this->labels['Current Query'],': ',htmlspecialchars($text_query),'</td></tr>',"\n";
  2235. }
  2236. if ($this->nav_text_links() || $this->nav_graphic_links()) {
  2237. $qstrparts = array();
  2238. strlen($this->fl) > 0 && $qstrparts[] = $this->cgi['prefix']['sys'].'fl'.'='.$this->fl;
  2239. strlen($this->fm) > 0 && $qstrparts[] = $this->cgi['prefix']['sys'].'fm'.'='.$this->fm;
  2240. count($this->sfn) > 0 && $qstrparts[] = $this->get_sfn_cgi_vars();
  2241. strlen($this->cgi['persist']) > 0 && $qstrparts[] = $this->cgi['persist'];
  2242. $qpview = $qstrparts;
  2243. $qpcopy = $qstrparts;
  2244. $qpchange = $qstrparts;
  2245. $qpdelete = $qstrparts;
  2246. $qp_prefix = $this->cgi['prefix']['sys'].'operation'.'='.$this->cgi['prefix']['operation'];
  2247. $qpview[] = $qp_prefix.'View';
  2248. $qpcopy[] = $qp_prefix.'Copy';
  2249. $qpchange[] = $qp_prefix.'Change';
  2250. $qpdelete[] = $qp_prefix.'Delete';
  2251. $qpviewStr = htmlspecialchars($this->page_name.'?'.join('&',$qpview).$this->qfn);
  2252. $qpcopyStr = htmlspecialchars($this->page_name.'?'.join('&',$qpcopy).$this->qfn);
  2253. $qpchangeStr = htmlspecialchars($this->page_name.'?'.join('&',$qpchange).$this->qfn);
  2254. $qpdeleteStr = htmlspecialchars($this->page_name.'?'.join('&',$qpdelete).$this->qfn);
  2255. }
  2256. $fetched = true;
  2257. $first = true;
  2258. $rowCount = 0;
  2259. while ((!$fetched && ($row = $this->sql_fetch($res)) != false)
  2260. || ($fetched && $row != false)) {
  2261. $fetched = false;
  2262. echo '<tr class="',$this->getCSSclass('row', null, 'next'),'">',"\n";
  2263. if ($sys_cols) { /* {{{ */
  2264. $key_rec = $row['qf'.$this->key_num];
  2265. $queryAppend = htmlspecialchars('&'.$this->cgi['prefix']['sys'].'rec'.'='.$key_rec);
  2266. $viewQuery = $qpviewStr . $queryAppend;
  2267. $copyQuery = $qpcopyStr . $queryAppend;
  2268. $changeQuery = $qpchangeStr . $queryAppend;
  2269. $deleteQuery = $qpdeleteStr . $queryAppend;
  2270. $viewTitle = htmlspecialchars($this->labels['View']);
  2271. $changeTitle = htmlspecialchars($this->labels['Change']);
  2272. $copyTitle = htmlspecialchars($this->labels['Copy']);
  2273. $deleteTitle = htmlspecialchars($this->labels['Delete']);
  2274. $css_class_name = $this->getCSSclass('navigation', null, true);
  2275. if ($select_recs) {
  2276. if (! $this->nav_buttons() || $sys_cols > 1) {
  2277. echo '<td class="',$css_class_name,'">';
  2278. }
  2279. if ($this->nav_graphic_links()) {
  2280. $printed_out = false;
  2281. if ($this->view_enabled()) {
  2282. $printed_out = true;
  2283. echo '<a class="',$css_class_name,'" href="',$viewQuery,'"><img class="';
  2284. echo $css_class_name,'" src="',$this->url['images'];
  2285. echo 'pme-view.png" height="15" width="16" border="0" ';
  2286. echo 'alt="',$viewTitle,'" title="',$viewTitle,'" /></a>';
  2287. }
  2288. if ($this->change_enabled()) {
  2289. $printed_out && print('&nbsp;');
  2290. $printed_out = true;
  2291. echo '<a class="',$css_class_name,'" href="',$changeQuery,'"><img class="';
  2292. echo $css_class_name,'" src="',$this->url['images'];
  2293. echo 'pme-change.png" height="15" width="16" border="0" ';
  2294. echo 'alt="',$changeTitle,'" title="',$changeTitle,'" /></a>';
  2295. }
  2296. if ($this->copy_enabled()) {
  2297. $printed_out && print('&nbsp;');
  2298. $printed_out = true;
  2299. echo '<a class="',$css_class_name,'" href="',$copyQuery,'"><img class="';
  2300. echo $css_class_name,'" src="',$this->url['images'];
  2301. echo 'pme-copy.png" height="15" width="16" border="0" ';
  2302. echo 'alt="',$copyTitle,'" title="',$copyTitle,'" /></a>';
  2303. }
  2304. if ($this->delete_enabled()) {
  2305. $printed_out && print('&nbsp;');
  2306. $printed_out = true;
  2307. echo '<a class="',$css_class_name,'" href="',$deleteQuery,'"><img class="';
  2308. echo $css_class_name,'" src="',$this->url['images'];
  2309. echo 'pme-delete.png" height="15" width="16" border="0" ';
  2310. echo 'alt="',$deleteTitle,'" title="',$deleteTitle,'" /></a>';
  2311. }
  2312. }
  2313. if ($this->nav_text_links()) {
  2314. if ($this->nav_graphic_links()) {
  2315. echo '<br class="',$css_class_name,'">';
  2316. }
  2317. $printed_out = false;
  2318. if ($this->view_enabled()) {
  2319. $printed_out = true;
  2320. echo '<a href="',$viewQuery,'" title="',$viewTitle,'" class="',$css_class_name,'">V</a>';
  2321. }
  2322. if ($this->change_enabled()) {
  2323. $printed_out && print('&nbsp;');
  2324. $printed_out = true;
  2325. echo '<a href="',$changeQuery,'" title="',$changeTitle,'" class="',$css_class_name,'">C</a>';
  2326. }
  2327. if ($this->copy_enabled()) {
  2328. $printed_out && print('&nbsp;');
  2329. $printed_out = true;
  2330. echo '<a href="',$copyQuery,'" title="',$copyTitle,'" class="',$css_class_name,'">P</a>';
  2331. }
  2332. if ($this->delete_enabled()) {
  2333. $printed_out && print('&nbsp;');
  2334. $printed_out = true;
  2335. echo '<a href="',$deleteQuery,'" title="',$deleteTitle,'" class="',$css_class_name,'">D</a>';
  2336. }
  2337. }
  2338. if (! $this->nav_buttons() || $sys_cols > 1) {
  2339. echo '</td>',"\n";
  2340. }
  2341. if ($this->nav_buttons()) {
  2342. echo '<td class="',$css_class_name,'"><input class="',$css_class_name;
  2343. echo '" type="radio" name="'.$this->cgi['prefix']['sys'].'rec';
  2344. echo '" value="',htmlspecialchars($key_rec),'"';
  2345. if (($this->rec == '' && $first) || ($this->rec == $key_rec)) {
  2346. echo ' checked';
  2347. $first = false;
  2348. }
  2349. echo ' /></td>',"\n";
  2350. }
  2351. } elseif ($this->filter_enabled()) {
  2352. echo '<td class="',$css_class_name,'" colspan="',$sys_cols,'">&nbsp;</td>',"\n";
  2353. }
  2354. } /* }}} */
  2355. for ($k = 0; $k < $this->num_fds; $k++) { /* {{{ */
  2356. $fd = $this->fds[$k];
  2357. if (! $this->displayed[$k]) {
  2358. continue;
  2359. }
  2360. $css_postfix = @$this->fdd[$k]['css']['postfix'];
  2361. $css_class_name = $this->getCSSclass('cell', null, true, $css_postfix);
  2362. if ($this->password($k)) {
  2363. echo '<td class="',$css_class_name,'">',$this->labels['hidden'],'</td>',"\n";
  2364. continue;
  2365. }
  2366. echo '<td class="',$css_class_name,'"',$this->getColAttributes($fd),'>';
  2367. echo $this->cellDisplay($k, $row, $css_class_name);
  2368. echo '</td>',"\n";
  2369. } /* }}} */
  2370. echo '</tr>',"\n";
  2371. }
  2372. /*
  2373. * Display and accumulate column aggregation info, do totalling query
  2374. * XXX this feature does not work yet!!!
  2375. */
  2376. // aggregates listing (if any)
  2377. if ($$var_to_total) {
  2378. // do the aggregate query if necessary
  2379. //if ($vars_to_total) {
  2380. $qp = array();
  2381. $qp['type'] = 'select';
  2382. $qp['select'] = $aggr_from_clause;
  2383. $qp['from'] = $this->get_SQL_join_clause();
  2384. $qp['where'] = $this->get_SQL_where_from_query_opts();
  2385. $tot_query = $this->get_SQL_query($qp);
  2386. $totals_result = $this->myquery($tot_query,__LINE__);
  2387. $tot_row = $this->sql_fetch($totals_result);
  2388. //}
  2389. $qp_aggr = $qp;
  2390. echo "\n",'<tr class="TODO-class">',"\n",'<td class="TODO-class">&nbsp;</td>',"\n";
  2391. /*
  2392. echo '<td>';
  2393. echo printarray($qp_aggr);
  2394. echo printarray($vars_to_total);
  2395. echo '</td>';
  2396. echo '<td colspan="'.($this->num_fds-1).'">'.$var_to_total.' '.$$var_to_total.'</td>';
  2397. */
  2398. // display the results
  2399. for ($k=0;$k<$this->num_fds;$k++) {
  2400. $fd = $this->fds[$k];
  2401. if (stristr($this->fdd[$fd]['options'],'L') or !isset($this->fdd[$fd]['options'])) {
  2402. echo '<td>';
  2403. $aggr_var = 'qf'.$k.'_aggr';
  2404. $$aggr_var = $this->get_sys_cgi_var($aggr_var);
  2405. if ($$aggr_var) {
  2406. echo $this->sql_aggrs[$$aggr_var],': ',$tot_row[$aggr_var];
  2407. } else {
  2408. echo '&nbsp;';
  2409. }
  2410. echo '</td>',"\n";
  2411. }
  2412. }
  2413. echo '</tr>',"\n";
  2414. }
  2415. echo '</table>',"\n"; // end of table rows listing
  2416. $this->display_list_table_buttons('down', $listall);
  2417. $this->form_end();
  2418. } /* }}} */
  2419. function display_record() /* {{{ */
  2420. {
  2421. // PRE Triggers
  2422. $ret = true;
  2423. if ($this->change_operation()) {
  2424. $ret &= $this->exec_triggers_simple('update', 'pre');
  2425. // if PRE update fails, then back to view operation
  2426. if (! $ret) {
  2427. $this->operation = $this->labels['View'];
  2428. $ret = true;
  2429. }
  2430. }
  2431. if ($this->add_operation() || $this->copy_operation()) {
  2432. $ret &= $this->exec_triggers_simple('insert', 'pre');
  2433. }
  2434. if ($this->view_operation()) {
  2435. $ret &= $this->exec_triggers_simple('select', 'pre');
  2436. }
  2437. if ($this->delete_operation()) {
  2438. $ret &= $this->exec_triggers_simple('delete', 'pre');
  2439. }
  2440. // if PRE insert/view/delete fail, then back to the list
  2441. if ($ret == false) {
  2442. $this->operation = '';
  2443. $this->list_table();
  2444. return;
  2445. }
  2446. $this->form_begin();
  2447. if ($this->cgi['persist'] != '') {
  2448. echo $this->get_origvars_html($this->cgi['persist']);
  2449. }
  2450. echo $this->get_origvars_html($this->get_sfn_cgi_vars());
  2451. echo $this->get_origvars_html($this->qfn);
  2452. echo $this->htmlHiddenSys('cur_tab', $this->dhtml['prefix'].'tab'.$this->cur_tab);
  2453. echo $this->htmlHiddenSys('qfn', $this->qfn);
  2454. echo $this->htmlHiddenSys('rec', $this->copy_operation() ? '' : $this->rec);
  2455. echo $this->htmlHiddenSys('fm', $this->fm);
  2456. echo $this->htmlHiddenSys('fl', $this->fl);
  2457. $this->display_record_buttons('up');
  2458. if ($this->tabs_enabled()) {
  2459. echo '<div id="'.$this->dhtml['prefix'].'tab0">',"\n";
  2460. }
  2461. echo '<table class="',$this->getCSSclass('main'),'" summary="',$this->tb,'">',"\n";
  2462. if ($this->add_operation()) {
  2463. $this->display_add_record();
  2464. } else {
  2465. $this->display_copy_change_delete_record();
  2466. }
  2467. echo '</table>',"\n";
  2468. if ($this->tabs_enabled()) {
  2469. echo '</div>',"\n";
  2470. }
  2471. $this->display_record_buttons('down');
  2472. $this->form_end();
  2473. } /* }}} */
  2474. /*
  2475. * Action functions
  2476. */
  2477. function do_add_record() /* {{{ */
  2478. {
  2479. // Preparing query
  2480. $query = '';
  2481. $key_col_val = '';
  2482. $newvals = array();
  2483. for ($k = 0; $k < $this->num_fds; $k++) {
  2484. if ($this->processed($k)) {
  2485. $fd = $this->fds[$k];
  2486. if ($this->readonly($k)) {
  2487. $fn = (string) @$this->fdd[$k]['default'];
  2488. } else {
  2489. $fn = $this->get_data_cgi_var($fd);
  2490. }
  2491. if ($fd == $this->key) {
  2492. $key_col_val = $fn;
  2493. }
  2494. $newvals[$fd] = is_array($fn) ? join(',',$fn) : $fn;
  2495. }
  2496. }
  2497. // Creating array of changed keys ($changed)
  2498. $changed = array_keys($newvals);
  2499. // Before trigger, newvals can be efectively changed
  2500. if ($this->exec_triggers('insert', 'before', $oldvals, $changed, $newvals) == false) {
  2501. return false;
  2502. }
  2503. // Real query (no additional query in this method)
  2504. foreach ($newvals as $fd => $val) {
  2505. if ($fd == '') continue;
  2506. if ($this->col_has_sqlw($this->fdn[$fd])) {
  2507. $val_as = addslashes($val);
  2508. $val_qas = '"'.addslashes($val).'"';
  2509. $value = $this->substituteVars(
  2510. $this->fdd[$this->fdn[$fd]]['sqlw'], array(
  2511. 'val_qas' => $val_qas,
  2512. 'val_as' => $val_as,
  2513. 'val' => $val
  2514. ));
  2515. } else {
  2516. $value = "'".addslashes($val)."'";
  2517. }
  2518. if ($query == '') {
  2519. $query = 'INSERT INTO '.$this->sd.$this->tb.$this->ed.' ('.$this->sd.$fd.$this->ed.''; // )
  2520. $query2 = ') VALUES ('.$value.'';
  2521. } else {
  2522. $query .= ', '.$this->sd.$fd.$this->ed.'';
  2523. $query2 .= ', '.$value.'';
  2524. }
  2525. }
  2526. $query .= $query2.')';
  2527. $res = $this->myquery($query, __LINE__);
  2528. $this->message = $this->sql_affected_rows($this->dbh).' '.$this->labels['record added'];
  2529. if (! $res) {
  2530. return false;
  2531. }
  2532. $this->rec = $this->sql_insert_id();
  2533. // Notify list
  2534. if (@$this->notify['insert'] || @$this->notify['all']) {
  2535. $this->email_notify(false, $newvals);
  2536. }
  2537. // Note change in log table
  2538. if ($this->logtable) {
  2539. $query = sprintf('INSERT INTO %s'
  2540. .' (updated, user, host, operation, tab, rowkey, col, oldval, newval)'
  2541. .' VALUES (NOW(), "%s", "%s", "insert", "%s", "%s", "", "", "%s")',
  2542. $this->logtable, addslashes($this->get_server_var('REMOTE_USER')),
  2543. addslashes($this->get_server_var('REMOTE_ADDR')), addslashes($this->tb),
  2544. addslashes($key_col_val), addslashes(serialize($newvals)));
  2545. $this->myquery($query, __LINE__);
  2546. }
  2547. // After trigger
  2548. if ($this->exec_triggers('insert', 'after', $oldvals, $changed, $newvals) == false) {
  2549. return false;
  2550. }
  2551. return true;
  2552. } /* }}} */
  2553. function do_change_record() /* {{{ */
  2554. {
  2555. // Preparing queries
  2556. $query_real = '';
  2557. $query_oldrec = '';
  2558. $newvals = array();
  2559. $oldvals = array();
  2560. $changed = array();
  2561. // Prepare query to retrieve oldvals
  2562. for ($k = 0; $k < $this->num_fds; $k++) {
  2563. if ($this->processed($k) && !$this->readonly($k)) {
  2564. $fd = $this->fds[$k];
  2565. $fn = $this->get_data_cgi_var($fd);
  2566. $newvals[$this->fds[$k]] = is_array($fn) ? join(',',$fn) : $fn;
  2567. if ($query_oldrec == '') {
  2568. $query_oldrec = 'SELECT '.$this->sd.$fd.$this->ed;
  2569. } else {
  2570. $query_oldrec .= ','.$this->sd.$fd.$this->ed;
  2571. }
  2572. }
  2573. }
  2574. $where_part = " WHERE (".$this->sd.$this->key.$this->ed.'='.$this->key_delim.$this->rec.$this->key_delim.')';
  2575. $query_newrec = $query_oldrec.' FROM ' . $this->tb;
  2576. $query_oldrec .= ' FROM ' . $this->sd.$this->tb.$this->ed . $where_part;
  2577. // Additional query (must go before real query)
  2578. $res = $this->myquery($query_oldrec, __LINE__);
  2579. $oldvals = $this->sql_fetch($res);
  2580. $this->sql_free_result($res);
  2581. // Creating array of changed keys ($changed)
  2582. foreach ($newvals as $fd => $value) {
  2583. if ($value != $oldvals[$fd])
  2584. $changed[] = $fd;
  2585. }
  2586. // Before trigger
  2587. if ($this->exec_triggers('update', 'before', $oldvals, $changed, $newvals) == false) {
  2588. return false;
  2589. }
  2590. // Build the real query respecting changes to the newvals array
  2591. foreach ($newvals as $fd => $val) {
  2592. if ($fd == '') continue;
  2593. if ($this->col_has_sqlw($this->fdn[$fd])) {
  2594. $val_as = addslashes($val);
  2595. $val_qas = '"'.addslashes($val).'"';
  2596. $value = $this->substituteVars(
  2597. $this->fdd[$this->fdn[$fd]]['sqlw'], array(
  2598. 'val_qas' => $val_qas,
  2599. 'val_as' => $val_as,
  2600. 'val' => $val
  2601. ));
  2602. } else {
  2603. $value = "'".addslashes($val)."'";
  2604. }
  2605. if ($query_real == '') {
  2606. $query_real = 'UPDATE '.$this->sd.$this->tb.$this->ed.' SET '.$this->sd.$fd.$this->ed.'='.$value;
  2607. } else {
  2608. $query_real .= ','.$this->sd.$fd.$this->ed.'='.$value;
  2609. }
  2610. }
  2611. $query_real .= $where_part;
  2612. // Real query
  2613. $res = $this->myquery($query_real, __LINE__);
  2614. $this->message = $this->sql_affected_rows($this->dbh).' '.$this->labels['record changed'];
  2615. if (! $res) {
  2616. return false;
  2617. }
  2618. // Another additional query (must go after real query)
  2619. if (in_array($this->key, $changed)) {
  2620. $this->rec = $newvals[$this->key]; // key has changed
  2621. }
  2622. $query_newrec .= ' WHERE ('.$this->key.'='.$this->key_delim.$this->rec.$this->key_delim.')';
  2623. $res = $this->myquery($query_newrec, __LINE__);
  2624. $newvals = $this->sql_fetch($res);
  2625. $this->sql_free_result($res);
  2626. // Creating array of changed keys ($changed)
  2627. $changed = array();
  2628. foreach ($newvals as $fd => $value) {
  2629. if ($value != $oldvals[$fd])
  2630. $changed[] = $fd;
  2631. }
  2632. // Notify list
  2633. if (@$this->notify['update'] || @$this->notify['all']) {
  2634. if (count($changed) > 0) {
  2635. $this->email_notify($oldvals, $newvals);
  2636. }
  2637. }
  2638. // Note change in log table
  2639. if ($this->logtable) {
  2640. foreach ($changed as $key) {
  2641. $qry = sprintf('INSERT INTO %s'
  2642. .' (updated, user, host, operation, tab, rowkey, col, oldval, newval)'
  2643. .' VALUES (NOW(), "%s", "%s", "update", "%s", "%s", "%s", "%s", "%s")',
  2644. $this->logtable, addslashes($this->get_server_var('REMOTE_USER')),
  2645. addslashes($this->get_server_var('REMOTE_ADDR')), addslashes($this->tb),
  2646. addslashes($this->rec), addslashes($key),
  2647. addslashes($oldvals[$key]), addslashes($newvals[$key]));
  2648. $this->myquery($qry, __LINE__);
  2649. }
  2650. }
  2651. // After trigger
  2652. if ($this->exec_triggers('update', 'after', $oldvals, $changed, $newvals) == false) {
  2653. return false;
  2654. }
  2655. return true;
  2656. } /* }}} */
  2657. function do_delete_record() /* {{{ */
  2658. {
  2659. // Additional query
  2660. $query = 'SELECT * FROM '.$this->sd.$this->tb.$this->ed.' WHERE ('.$this->sd.$this->key.$this->ed.' = '
  2661. .$this->key_delim.$this->rec.$this->key_delim.')'; // )
  2662. $res = $this->myquery($query, __LINE__);
  2663. $oldvals = $this->sql_fetch($res);
  2664. $this->sql_free_result($res);
  2665. // Creating array of changed keys ($changed)
  2666. $changed = is_array($oldvals) ? array_keys($oldvals) : array();
  2667. $newvals = array();
  2668. // Before trigger
  2669. if ($this->exec_triggers('delete', 'before', $oldvals, $changed, $newvals) == false) {
  2670. return false;
  2671. }
  2672. // Real query
  2673. $query = 'DELETE FROM '.$this->tb.' WHERE ('.$this->key.' = '
  2674. .$this->key_delim.$this->rec.$this->key_delim.')'; // )
  2675. $res = $this->myquery($query, __LINE__);
  2676. $this->message = $this->sql_affected_rows($this->dbh).' '.$this->labels['record deleted'];
  2677. if (! $res) {
  2678. return false;
  2679. }
  2680. // Notify list
  2681. if (@$this->notify['delete'] || @$this->notify['all']) {
  2682. $this->email_notify($oldvals, false);
  2683. }
  2684. // Note change in log table
  2685. if ($this->logtable) {
  2686. $query = sprintf('INSERT INTO %s'
  2687. .' (updated, user, host, operation, tab, rowkey, col, oldval, newval)'
  2688. .' VALUES (NOW(), "%s", "%s", "delete", "%s", "%s", "%s", "%s", "")',
  2689. $this->logtable, addslashes($this->get_server_var('REMOTE_USER')),
  2690. addslashes($this->get_server_var('REMOTE_ADDR')), addslashes($this->tb),
  2691. addslashes($this->rec), addslashes($key), addslashes(serialize($oldvals)));
  2692. $this->myquery($query, __LINE__);
  2693. }
  2694. // After trigger
  2695. if ($this->exec_triggers('delete', 'after', $oldvals, $changed, $newvals) == false) {
  2696. return false;
  2697. }
  2698. return true;
  2699. } /* }}} */
  2700. function email_notify($old_vals, $new_vals) /* {{{ */
  2701. {
  2702. if (! function_exists('mail')) {
  2703. return false;
  2704. }
  2705. if ($old_vals != false && $new_vals != false) {
  2706. $action = 'update';
  2707. $subject = 'Record updated in';
  2708. $body = 'An item with '.$this->fdd[$this->key]['name'].' = '
  2709. .$this->key_delim.$this->rec.$this->key_delim .' was updated in';
  2710. $vals = $new_vals;
  2711. } elseif ($new_vals != false) {
  2712. $action = 'insert';
  2713. $subject = 'Record added to';
  2714. $body = 'A new item was added into';
  2715. $vals = $new_vals;
  2716. } elseif ($old_vals != false) {
  2717. $action = 'delete';
  2718. $subject = 'Record deleted from';
  2719. $body = 'An item was deleted from';
  2720. $vals = $old_vals;
  2721. } else {
  2722. return false;
  2723. }
  2724. $addr = $this->get_server_var('REMOTE_ADDR');
  2725. $user = $this->get_server_var('REMOTE_USER');
  2726. $body = 'This notification e-mail was automatically generated by phpMyEdit.'."\n\n".$body;
  2727. $body .= ' table '.$this->tb.' in SQL database '.$this->db.' on '.$this->page_name;
  2728. $body .= ' by '.($user == '' ? 'unknown user' : "user $user").' from '.$addr;
  2729. $body .= ' at '.date('d/M/Y H:i').' with the following fields:'."\n\n";
  2730. $i = 1;
  2731. foreach ($vals as $k => $text) {
  2732. $name = isset($this->fdd[$k]['name~'])
  2733. ? $this->fdd[$k]['name~'] : $this->fdd[$k]['name'];
  2734. if ($action == 'update') {
  2735. if ($old_vals[$k] == $new_vals[$k]) {
  2736. continue;
  2737. }
  2738. $body .= sprintf("[%02s] %s (%s)\n WAS: %s\n IS: %s\n",
  2739. $i, $name, $k, $old_vals[$k], $new_vals[$k]);
  2740. } else {
  2741. $body .= sprintf('[%02s] %s (%s): %s'."\n", $i, $name, $k, $text);
  2742. }
  2743. $i++;
  2744. }
  2745. $body .= "\n--\r\n"; // \r is needed for signature separating
  2746. $body .= "phpMyEdit\ninstant SQL table editor and code generator\n";
  2747. $body .= "http://platon.sk/projects/phpMyEdit/\n\n";
  2748. $subject = @$this->notify['prefix'].$subject.' '.$this->dbp.$this->tb;
  2749. $subject = trim($subject); // just for sure
  2750. $wrap_w = intval(@$this->notify['wrap']);
  2751. $wrap_w > 0 || $wrap_w = 72;
  2752. $from = (string) @$this->notify['from'];
  2753. $from != '' || $from = 'webmaster@'.strtolower($this->get_server_var('SERVER_NAME'));
  2754. $headers = 'From: '.$from."\n".'X-Mailer: PHP/'.phpversion().' (phpMyEdit)';
  2755. $body = wordwrap($body, $wrap_w, "\n", 1);
  2756. $emails = (array) $this->notify[$action] + (array) $this->notify['all'];
  2757. foreach ($emails as $email) {
  2758. if (! empty($email)) {
  2759. mail(trim($email), $subject, $body, $headers);
  2760. }
  2761. }
  2762. return true;
  2763. } /* }}} */
  2764. /*
  2765. * Apply triggers function
  2766. * Run a (set of) trigger(s). $trigger can be an Array or a filename
  2767. * Break and return false as soon as a trigger return false
  2768. * we need a reference on $newvals to be able to change value before insert/update
  2769. */
  2770. function exec_triggers($op, $step, $oldvals, &$changed, &$newvals) /* {{{ */
  2771. {
  2772. if (! isset($this->triggers[$op][$step])) {
  2773. return true;
  2774. }
  2775. $ret = true;
  2776. $trig = $this->triggers[$op][$step];
  2777. if (is_array($trig)) {
  2778. ksort($trig);
  2779. for ($t = reset($trig); $t !== false && $ret != false; $t = next($trig)) {
  2780. $ret = include($t);
  2781. }
  2782. } else {
  2783. $ret = include($trig);
  2784. }
  2785. return $ret;
  2786. } /* }}} */
  2787. function exec_triggers_simple($op, $step) /* {{{ */
  2788. {
  2789. $oldvals = $newvals = $changed = array();
  2790. return $this->exec_triggers($op, $step, $oldvals, $changed, $newvals);
  2791. } /* }}} */
  2792. /*
  2793. * Recreate functions
  2794. */
  2795. function recreate_fdd($default_page_type = 'L') /* {{{ */
  2796. {
  2797. // TODO: one level deeper browsing
  2798. $this->page_type = $default_page_type;
  2799. $this->filter_operation() && $this->page_type = 'F';
  2800. $this->view_operation() && $this->page_type = 'V';
  2801. if ($this->add_operation()
  2802. || $this->saveadd == $this->labels['Save']
  2803. || $this->moreadd == $this->labels['More']) {
  2804. $this->page_type = 'A';
  2805. }
  2806. if ($this->change_operation()
  2807. || $this->savechange == $this->labels['Save']
  2808. || $this->morechange == $this->labels['Apply']) {
  2809. $this->page_type = 'C';
  2810. }
  2811. if ($this->copy_operation() || $this->savecopy == $this->labels['Save']) {
  2812. $this->page_type = 'P';
  2813. }
  2814. if ($this->delete_operation() || $this->savedelete == $this->labels['Delete']) {
  2815. $this->page_type = 'D';
  2816. }
  2817. // Restore backups (if exists)
  2818. foreach (array_keys($this->fdd) as $column) {
  2819. foreach (array_keys($this->fdd[$column]) as $col_option) {
  2820. if ($col_option[strlen($col_option) - 1] != '~')
  2821. continue;
  2822. $this->fdd[$column][substr($col_option, 0, strlen($col_option) - 1)]
  2823. = $this->fdd[$column][$col_option];
  2824. unset($this->fdd[$column][$col_option]);
  2825. }
  2826. }
  2827. foreach (array_keys($this->fdd) as $column) {
  2828. foreach (array_keys($this->fdd[$column]) as $col_option) {
  2829. if (! strchr($col_option, '|')) {
  2830. continue;
  2831. }
  2832. $col_ar = explode('|', $col_option, 2);
  2833. if (! stristr($col_ar[1], $this->page_type)) {
  2834. continue;
  2835. }
  2836. // Make field backups
  2837. $this->fdd[$column][$col_ar[0] .'~'] = $this->fdd[$column][$col_ar[0]];
  2838. $this->fdd[$column][$col_option.'~'] = $this->fdd[$column][$col_option];
  2839. // Set particular field
  2840. $this->fdd[$column][$col_ar[0]] = $this->fdd[$column][$col_option];
  2841. unset($this->fdd[$column][$col_option]);
  2842. }
  2843. }
  2844. } /* }}} */
  2845. function recreate_displayed() /* {{{ */
  2846. {
  2847. $field_num = 0;
  2848. $num_fields_displayed = 0;
  2849. $this->fds = array();
  2850. $this->fdn = array();
  2851. $this->displayed = array();
  2852. $this->guidance = false;
  2853. foreach (array_keys($this->fdd) as $key) {
  2854. if (preg_match('/^\d+$/', $key)) { // skipping numeric keys
  2855. continue;
  2856. }
  2857. $this->fds[$field_num] = $key;
  2858. $this->fdn[$key] = $field_num;
  2859. /* We must use here displayed() function, because displayed[] array
  2860. is not created yet. We will simultaneously create that array as well. */
  2861. if ($this->displayed[$field_num] = $this->displayed($field_num)) {
  2862. $num_fields_displayed++;
  2863. }
  2864. if (is_array(@$this->fdd[$key]['values']) && ! isset($this->fdd[$key]['values']['table'])) {
  2865. foreach ($this->fdd[$key]['values'] as $val) {
  2866. $this->fdd[$key]['values2'][$val] = $val;
  2867. }
  2868. unset($this->fdd[$key]['values']);
  2869. }
  2870. isset($this->fdd[$key]['help']) && $this->guidance = true;
  2871. $this->fdd[$field_num] = $this->fdd[$key];
  2872. $field_num++;
  2873. }
  2874. $this->num_fds = $field_num;
  2875. $this->num_fields_displayed = $num_fields_displayed;
  2876. $this->key_num = array_search($this->key, $this->fds);
  2877. /* Adds first displayed column into sorting fields by replacing last
  2878. array entry. Also remove duplicite values and change column names to
  2879. their particular field numbers.
  2880. Note that entries like [0]=>'9' [1]=>'-9' are correct and they will
  2881. have desirable sorting behaviour. So there is no need to remove them.
  2882. */
  2883. $this->sfn = array_unique($this->sfn);
  2884. $check_ar = array();
  2885. foreach ($this->sfn as $key => $val) {
  2886. if (preg_match('/^[-]?\d+$/', $val)) { // skipping numeric keys
  2887. $val = abs($val);
  2888. if (in_array($val, $check_ar) || $this->password($val)) {
  2889. unset($this->sfn[$key]);
  2890. } else {
  2891. $check_ar[] = $val;
  2892. }
  2893. continue;
  2894. }
  2895. if ($val[0] == '-') {
  2896. $val = substr($val, 1);
  2897. $minus = '-';
  2898. } else {
  2899. $minus = '';
  2900. }
  2901. if (($val = array_search($val, $this->fds)) === false || $this->password($val)) {
  2902. unset($this->sfn[$key]);
  2903. } else {
  2904. $val = intval($val);
  2905. if (in_array($val, $check_ar)) {
  2906. unset($this->sfn[$key]);
  2907. } else {
  2908. $this->sfn[$key] = $minus.$val;
  2909. $check_ar[] = $val;
  2910. }
  2911. }
  2912. }
  2913. $this->sfn = array_unique($this->sfn);
  2914. return true;
  2915. } /* }}} */
  2916. function backward_compatibility() /* {{{ */
  2917. {
  2918. foreach (array_keys($this->fdd) as $column) {
  2919. // move ['required'] to ['js']['required']
  2920. if (! isset($this->fdd[$column]['js']['required']) && isset($this->fdd[$column]['required'])) {
  2921. $this->fdd[$column]['js']['required'] = $this->fdd[$column]['required'];
  2922. }
  2923. // move 'HWR' flags from ['options'] into ['input']
  2924. if (isset($this->fdd[$column]['options'])) {
  2925. stristr($this->fdd[$column]['options'], 'H') && $this->fdd[$column]['input'] .= 'H';
  2926. stristr($this->fdd[$column]['options'], 'W') && $this->fdd[$column]['input'] .= 'W';
  2927. stristr($this->fdd[$column]['options'], 'R') && $this->fdd[$column]['input'] .= 'R';
  2928. }
  2929. }
  2930. } /* }}} */
  2931. /*
  2932. * Error handling function
  2933. */
  2934. function error($message, $additional_info = '') /* {{{ */
  2935. {
  2936. echo '<h1>phpMyEdit error: ',htmlspecialchars($message),'</h1>',"\n";
  2937. if ($additional_info != '') {
  2938. echo '<hr size="1" />',htmlspecialchars($additional_info);
  2939. }
  2940. return false;
  2941. } /* }}} */
  2942. /*
  2943. * Database connection function
  2944. */
  2945. function connect() /* {{{ */
  2946. {
  2947. if (isset($this->dbh)) {
  2948. return true;
  2949. }
  2950. if (!isset($this->db)) {
  2951. $this->error('no database defined');
  2952. return false;
  2953. }
  2954. if (!isset ($this->tb)) {
  2955. $this->error('no table defined');
  2956. return false;
  2957. }
  2958. $this->sql_connect();
  2959. if (!$this->dbh) {
  2960. $this->error('could not connect to SQL');
  2961. return false;
  2962. }
  2963. return true;
  2964. } /* }}} */
  2965. /*
  2966. * The workhorse
  2967. */
  2968. function execute() /* {{{ */
  2969. {
  2970. // DEBUG - uncomment to enable
  2971. /*
  2972. //phpinfo();
  2973. $this->print_get_vars();
  2974. $this->print_post_vars();
  2975. $this->print_vars();
  2976. echo "<pre>query opts:\n";
  2977. echo print_r($this->query_opts);
  2978. echo "</pre>\n";
  2979. echo "<pre>get vars:\n";
  2980. echo print_r($this->get_opts);
  2981. echo "</pre>\n";
  2982. */
  2983. // Let's do explicit quoting - it's safer
  2984. @set_magic_quotes_runtime(0);
  2985. // Checking if language file inclusion was successful
  2986. if (! is_array($this->labels)) {
  2987. $this->error('could not locate language files', 'searched path: '.$this->dir['lang']);
  2988. return false;
  2989. }
  2990. // Database connection
  2991. if ($this->connect() == false) {
  2992. return false;
  2993. }
  2994. /*
  2995. * ======================================================================
  2996. * Pass 3: process any updates generated if the user has selected
  2997. * a save or cancel button during Pass 2
  2998. * ======================================================================
  2999. */
  3000. // Cancel button - Cancel Triggers
  3001. if ($this->add_canceled() || $this->copy_canceled()) {
  3002. $this->exec_triggers_simple('insert', 'cancel');
  3003. }
  3004. if ($this->view_canceled()) {
  3005. $this->exec_triggers_simple('select', 'cancel');
  3006. }
  3007. if ($this->change_canceled()) {
  3008. $this->exec_triggers_simple('update', 'cancel');
  3009. }
  3010. if ($this->delete_canceled()) {
  3011. $this->exec_triggers_simple('delete', 'cancel');
  3012. }
  3013. // Save/More Button - database operations
  3014. if ($this->saveadd == $this->labels['Save'] || $this->savecopy == $this->labels['Save']) {
  3015. $this->add_enabled() && $this->do_add_record();
  3016. unset($this->saveadd);
  3017. unset($this->savecopy);
  3018. $this->recreate_fdd();
  3019. }
  3020. elseif ($this->moreadd == $this->labels['More']) {
  3021. $this->add_enabled() && $this->do_add_record();
  3022. $this->operation = $this->labels['Add']; // to force add operation
  3023. $this->recreate_fdd();
  3024. $this->recreate_displayed();
  3025. $this->backward_compatibility();
  3026. }
  3027. elseif ($this->savechange == $this->labels['Save']) {
  3028. $this->change_enabled() && $this->do_change_record();
  3029. unset($this->savechange);
  3030. $this->recreate_fdd();
  3031. }
  3032. elseif ($this->morechange == $this->labels['Apply']) {
  3033. $this->change_enabled() && $this->do_change_record();
  3034. $this->operation = $this->labels['Change']; // to force change operation
  3035. $this->recreate_fdd();
  3036. $this->recreate_displayed();
  3037. $this->backward_compatibility();
  3038. }
  3039. elseif ($this->savedelete == $this->labels['Delete']) {
  3040. $this->delete_enabled() && $this->do_delete_record();
  3041. unset($this->savedelete);
  3042. $this->recreate_fdd();
  3043. }
  3044. /*
  3045. * ======================================================================
  3046. * Pass 2: display an input/edit/confirmation screen if the user has
  3047. * selected an editing button on Pass 1 through this page
  3048. * ======================================================================
  3049. */
  3050. if ($this->add_operation()
  3051. || $this->change_operation() || $this->delete_operation()
  3052. || $this->view_operation() || $this->copy_operation()) {
  3053. $this->display_record();
  3054. }
  3055. /*
  3056. * ======================================================================
  3057. * Pass 1 and Pass 3: display the SQL table in a scrolling window on
  3058. * the screen (skip this step in 'Add More' mode)
  3059. * ======================================================================
  3060. */
  3061. else {
  3062. $this->list_table();
  3063. }
  3064. $this->sql_disconnect();
  3065. if ($this->display['time'] && $this->timer != null) {
  3066. echo $this->timer->end(),' miliseconds';
  3067. }
  3068. } /* }}} */
  3069. /*
  3070. * Class constructor
  3071. */
  3072. function phpMyEdit($opts) /* {{{ */
  3073. {
  3074. // Set desirable error reporting level
  3075. $error_reporting = error_reporting(E_ALL & ~E_NOTICE);
  3076. // Database handle variables
  3077. $this->sql_delimiter();
  3078. if (isset($opts['dbh'])) {
  3079. $this->close_dbh = false;
  3080. $this->dbh = $opts['dbh'];
  3081. $this->dbp = '';
  3082. } else {
  3083. $this->close_dbh = true;
  3084. $this->dbh = null;
  3085. $this->dbp = $this->sd.$opts['db'].$this->ed.'.';
  3086. $this->hn = $opts['hn'];
  3087. $this->un = $opts['un'];
  3088. $this->pw = $opts['pw'];
  3089. $this->db = $opts['db'];
  3090. }
  3091. $this->tb = $opts['tb'];
  3092. // Other variables
  3093. $this->key = $opts['key'];
  3094. $this->key_type = $opts['key_type'];
  3095. $this->inc = $opts['inc'];
  3096. $this->options = $opts['options'];
  3097. $this->fdd = $opts['fdd'];
  3098. $this->multiple = intval($opts['multiple']);
  3099. $this->multiple <= 0 && $this->multiple = 2;
  3100. $this->filters = is_array(@$opts['filters']) ? join(' AND ', $opts['filters']) : @$opts['filters'];
  3101. $this->triggers = @$opts['triggers'];
  3102. $this->notify = @$opts['notify'];
  3103. $this->logtable = @$opts['logtable'];
  3104. $this->page_name = @$opts['page_name'];
  3105. if (! isset($this->page_name)) {
  3106. $this->page_name = basename($this->get_server_var('PHP_SELF'));
  3107. isset($this->page_name) || $this->page_name = $this->tb;
  3108. }
  3109. $this->display['query'] = @$opts['display']['query'];
  3110. $this->display['sort'] = @$opts['display']['sort'];
  3111. $this->display['time'] = @$opts['display']['time'];
  3112. if ($this->display['time']) {
  3113. $this->timer = new phpMyEdit_timer();
  3114. }
  3115. $this->display['tabs'] = isset($opts['display']['tabs'])
  3116. ? $opts['display']['tabs'] : true;
  3117. $this->display['form'] = isset($opts['display']['form'])
  3118. ? $opts['display']['form'] : true;
  3119. $this->display['num_records'] = isset($opts['display']['num_records'])
  3120. ? $opts['display']['num_records'] : true;
  3121. $this->display['num_pages'] = isset($opts['display']['num_pages'])
  3122. ? $opts['display']['num_pages'] : true;
  3123. // Creating directory variables
  3124. $this->dir['root'] = dirname(realpath(__FILE__))
  3125. . (strlen(dirname(realpath(__FILE__))) > 0 ? '/' : '');
  3126. $this->dir['lang'] = $this->dir['root'].'lang/';
  3127. // Creating URL variables
  3128. $this->url['images'] = 'images/';
  3129. isset($opts['url']['images']) && $this->url['images'] = $opts['url']['images'];
  3130. // CSS classes policy
  3131. $this->css = @$opts['css'];
  3132. !isset($this->css['separator']) && $this->css['separator'] = '-';
  3133. !isset($this->css['prefix']) && $this->css['prefix'] = 'pme';
  3134. !isset($this->css['page_type']) && $this->css['page_type'] = false;
  3135. !isset($this->css['position']) && $this->css['position'] = false;
  3136. !isset($this->css['divider']) && $this->css['divider'] = 2;
  3137. $this->css['divider'] = intval(@$this->css['divider']);
  3138. // JS overall configuration
  3139. $this->js = @$opts['js'];
  3140. !isset($this->js['prefix']) && $this->js['prefix'] = 'PME_js_';
  3141. // DHTML overall configuration
  3142. $this->dhtml = @$opts['dhtml'];
  3143. !isset($this->dhtml['prefix']) && $this->dhtml['prefix'] = 'PME_dhtml_';
  3144. // Navigation
  3145. $this->navigation = @$opts['navigation'];
  3146. if (! $this->nav_buttons() && ! $this->nav_text_links() && ! $this->nav_graphic_links()) {
  3147. $this->navigation .= 'B'; // buttons are default
  3148. }
  3149. if (! $this->nav_up() && ! $this->nav_down()) {
  3150. $this->navigation .= 'D'; // down position is default
  3151. }
  3152. $this->buttons = $opts['buttons'];
  3153. // Language labels (must go after navigation)
  3154. $this->labels = $this->make_language_labels(isset($opts['language'])
  3155. ? $opts['language'] : $this->get_server_var('HTTP_ACCEPT_LANGUAGE'));
  3156. // CGI variables
  3157. $this->cgi = @$opts['cgi'];
  3158. $this->cgi['persist'] = '';
  3159. if (@is_array($opts['cgi']['persist'])) {
  3160. foreach ($opts['cgi']['persist'] as $key => $val) {
  3161. if (is_array($val)) {
  3162. foreach($val as $key2 => $val2) {
  3163. $this->cgi['persist'] .= '&'.rawurlencode($key)
  3164. .'['.rawurlencode($key2).']='.rawurlencode($val2);
  3165. }
  3166. } else {
  3167. $this->cgi['persist'] .= '&'.rawurlencode($key).'='.rawurlencode($val);
  3168. }
  3169. }
  3170. }
  3171. foreach (array('operation', 'sys', 'data') as $type) {
  3172. if (! isset($this->cgi['prefix'][$type])) {
  3173. $this->cgi['prefix'][$type] = $this->get_default_cgi_prefix($type);
  3174. }
  3175. }
  3176. // Sorting variables
  3177. $this->sfn = $this->get_sys_cgi_var('sfn');
  3178. isset($this->sfn) || $this->sfn = array();
  3179. is_array($this->sfn) || $this->sfn = array($this->sfn);
  3180. isset($opts['sort_field']) || $opts['sort_field'] = array();
  3181. is_array($opts['sort_field']) || $opts['sort_field'] = array($opts['sort_field']);
  3182. $this->sfn = array_merge($this->sfn, $opts['sort_field']);
  3183. // Form variables all around
  3184. $this->fl = intval($this->get_sys_cgi_var('fl'));
  3185. $this->fm = intval($this->get_sys_cgi_var('fm'));
  3186. // $old_page = ceil($this->fm / abs($this->inc)) + 1;
  3187. $this->qfn = $this->get_sys_cgi_var('qfn');
  3188. $this->sw = $this->get_sys_cgi_var('sw');
  3189. $this->rec = $this->get_sys_cgi_var('rec', '');
  3190. $this->navop = $this->get_sys_cgi_var('navop');
  3191. $navfmup = $this->get_sys_cgi_var('navfmup');
  3192. $navfmdown = $this->get_sys_cgi_var('navfmdown');
  3193. $navpnup = $this->get_sys_cgi_var('navpnup');
  3194. $navpndown = $this->get_sys_cgi_var('navpndown');
  3195. if($navfmdown!=NULL && $navfmdown != $this->fm) $this->navfm = $navfmdown;
  3196. elseif($navfmup!=NULL && $navfmup != $this->fm) $this->navfm = $navfmup;
  3197. elseif($navpndown!=NULL && ($navpndown-1)*$this->inc != $this->fm) $this->navfm = ($navpndown-1)*$this->inc;
  3198. elseif($navpnup!=NULL && ($navpnup-1)*$this->inc != $this->fm) $this->navfm = ($navpnup-1)*$this->inc;
  3199. else $this->navfm = $this->fm;
  3200. $this->operation = $this->get_sys_cgi_var('operation');
  3201. $oper_prefix_len = strlen($this->cgi['prefix']['operation']);
  3202. if (! strncmp($this->cgi['prefix']['operation'], $this->operation, $oper_prefix_len)) {
  3203. $this->operation = $this->labels[substr($this->operation, $oper_prefix_len)];
  3204. }
  3205. $this->saveadd = $this->get_sys_cgi_var('saveadd');
  3206. $this->moreadd = $this->get_sys_cgi_var('moreadd');
  3207. $this->canceladd = $this->get_sys_cgi_var('canceladd');
  3208. $this->savechange = $this->get_sys_cgi_var('savechange');
  3209. $this->morechange = $this->get_sys_cgi_var('morechange');
  3210. $this->cancelchange = $this->get_sys_cgi_var('cancelchange');
  3211. $this->savecopy = $this->get_sys_cgi_var('savecopy');
  3212. $this->cancelcopy = $this->get_sys_cgi_var('cancelcopy');
  3213. $this->savedelete = $this->get_sys_cgi_var('savedelete');
  3214. $this->canceldelete = $this->get_sys_cgi_var('canceldelete');
  3215. $this->cancelview = $this->get_sys_cgi_var('cancelview');
  3216. // Filter setting
  3217. if (isset($this->sw)) {
  3218. $this->sw == $this->labels['Search'] && $this->fl = 1;
  3219. $this->sw == $this->labels['Hide'] && $this->fl = 0;
  3220. //$this->sw == $this->labels['Clear'] && $this->fl = 0;
  3221. }
  3222. // TAB names
  3223. $this->tabs = array();
  3224. // Setting key_delim according to key_type
  3225. if ($this->key_type == 'real') {
  3226. /* If 'real' key_type does not work,
  3227. try change MySQL datatype from float to double */
  3228. $this->rec = doubleval($this->rec);
  3229. $this->key_delim = '';
  3230. } elseif ($this->key_type == 'int') {
  3231. $this->rec = intval($this->rec);
  3232. $this->key_delim = '';
  3233. } else {
  3234. $this->key_delim = '"';
  3235. // $this->rec remains unmodified
  3236. }
  3237. // Specific $fdd modifications depending on performed action
  3238. $this->recreate_fdd();
  3239. // Extract SQL Field Names and number of fields
  3240. $this->recreate_displayed();
  3241. // Issue backward compatibility
  3242. $this->backward_compatibility();
  3243. // Gathering query options
  3244. $this->gather_query_opts();
  3245. // Call to action
  3246. !isset($opts['execute']) && $opts['execute'] = 1;
  3247. $opts['execute'] && $this->execute();
  3248. // Restore original error reporting level
  3249. error_reporting($error_reporting);
  3250. } /* }}} */
  3251. }
  3252. /* Modeline for ViM {{{
  3253. * vim:set ts=4:
  3254. * vim600:fdm=marker fdl=0 fdc=0:
  3255. * }}} */
  3256. ?>