Happy New Year
[squirrelmail.git] / functions / db_prefs.php
CommitLineData
82474746 1<?php
15e6162e 2
d6c32258 3/**
35586184 4 * db_prefs.php
5 *
35586184 6 * This contains functions for manipulating user preferences
21ddfbc3 7 * stored in a database, accessed through the Pear DB layer
8 * or PDO, the latter taking precedence if available.
35586184 9 *
35586184 10 * Database:
35586184 11 *
99a6c222 12 * The preferences table should have three columns:
13 * user char \ primary
35586184 14 * prefkey char / key
15 * prefval blob
16 *
4b7dd3d9 17 * CREATE TABLE userprefs (user CHAR(128) NOT NULL DEFAULT '',
35586184 18 * prefkey CHAR(64) NOT NULL DEFAULT '',
19 * prefval BLOB NOT NULL DEFAULT '',
20 * primary key (user,prefkey));
21 *
22 * Configuration of databasename, username and password is done
3499f99f 23 * by using conf.pl or the administrator plugin
35586184 24 *
21ddfbc3 25 * Three settings that control PDO behavior can be specified in
26 * config/config_local.php if needed:
27 * boolean $disable_pdo SquirrelMail uses PDO by default to access the
28 * user preferences and address book databases, but
29 * setting this to TRUE will cause SquirrelMail to
30 * fall back to using Pear DB instead.
31 * boolean $pdo_show_sql_errors When database errors are encountered,
32 * setting this to TRUE causes the actual
33 * database error to be displayed, otherwise
34 * generic errors are displayed, preventing
35 * internal database information from being
36 * exposed. This should be enabled only for
37 * debugging purposes.
65e468fa 38 * string $db_identifier_quote_char By default, SquirrelMail will quote
39 * table and field names in database
40 * queries with what it thinks is the
41 * appropriate quote character for the
42 * database type being used (backtick
43 * for MySQL (and thus MariaDB), double
44 * quotes for all others), but you can
45 * override the character used by
46 * putting it here, or tell SquirrelMail
47 * NOT to quote identifiers by setting
48 * this to "none"
21ddfbc3 49 *
b0392fa8 50 * If needed, you can also set $prefs_db_charset as a string
51 * (such as "utf8mb4") in config/config_local.php if your system
52 * does not default the SQL connection character set as expected
53 * (most sensible systems will do the right thing transparently).
54 *
33aab559 55 * @copyright 1999-2024 The SquirrelMail Project Team
4b4abf93 56 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
31841a9e 57 * @version $Id$
d6c32258 58 * @package squirrelmail
ace4c62c 59 * @subpackage prefs
60 * @since 1.1.3
35586184 61 */
62
ace4c62c 63/** @ignore */
64if (!defined('SM_PATH')) define('SM_PATH','../');
65
d6c32258 66/** Unknown database */
98749983 67define('SMDB_UNKNOWN', 0);
d6c32258 68/** MySQL */
98749983 69define('SMDB_MYSQL', 1);
d6c32258 70/** PostgreSQL */
98749983 71define('SMDB_PGSQL', 2);
72
099fea11 73/**
21ddfbc3 74 * Needs either PDO or the DB functions
75 * Don't display errors here. (no code execution in functions/*.php).
099fea11 76 * will handle error in dbPrefs class.
77 */
21ddfbc3 78global $use_pdo, $disable_pdo;
79if (empty($disable_pdo) && class_exists('PDO'))
80 $use_pdo = TRUE;
81else
82 $use_pdo = FALSE;
83
84if (!$use_pdo)
85 @include_once('DB.php');
35586184 86
370059dd 87global $prefs_are_cached, $prefs_cache;
2d367c68 88
4d30c1b7 89/**
90 * @ignore
91 */
370059dd 92function cachePrefValues($username) {
93 global $prefs_are_cached, $prefs_cache;
94
37d5278d 95 sqgetGlobalVar('prefs_are_cached', $prefs_are_cached, SQ_SESSION );
370059dd 96 if ($prefs_are_cached) {
37d5278d 97 sqgetGlobalVar('prefs_cache', $prefs_cache, SQ_SESSION );
370059dd 98 return;
99 }
2d367c68 100
9eb0fbd4 101 sqsession_unregister('prefs_cache');
102 sqsession_unregister('prefs_are_cached');
370059dd 103
104 $db = new dbPrefs;
105 if(isset($db->error)) {
106 printf( _("Preference database error (%s). Exiting abnormally"),
107 $db->error);
108 exit;
109 }
2d367c68 110
370059dd 111 $db->fillPrefsCache($username);
112 if (isset($db->error)) {
113 printf( _("Preference database error (%s). Exiting abnormally"),
114 $db->error);
115 exit;
116 }
117
118 $prefs_are_cached = true;
119
9eb0fbd4 120 sqsession_register($prefs_cache, 'prefs_cache');
121 sqsession_register($prefs_are_cached, 'prefs_are_cached');
370059dd 122}
123
d6c32258 124/**
ace4c62c 125 * Class used to handle connections to prefs database and operations with preferences
37b11ab0 126 *
d6c32258 127 * @package squirrelmail
ace4c62c 128 * @subpackage prefs
129 * @since 1.1.3
37b11ab0 130 *
d6c32258 131 */
370059dd 132class dbPrefs {
ace4c62c 133 /**
134 * Table used to store preferences
135 * @var string
136 */
370059dd 137 var $table = 'userprefs';
37b11ab0 138
ace4c62c 139 /**
140 * Field used to store owner of preference
141 * @var string
142 */
99a6c222 143 var $user_field = 'user';
37b11ab0 144
ace4c62c 145 /**
146 * Field used to store preference name
147 * @var string
148 */
99a6c222 149 var $key_field = 'prefkey';
37b11ab0 150
ace4c62c 151 /**
152 * Field used to store preference value
153 * @var string
154 */
99a6c222 155 var $val_field = 'prefval';
370059dd 156
ace4c62c 157 /**
158 * Database connection object
159 * @var object
160 */
370059dd 161 var $dbh = NULL;
37b11ab0 162
ace4c62c 163 /**
164 * Error messages
165 * @var string
166 */
370059dd 167 var $error = NULL;
37b11ab0 168
ace4c62c 169 /**
170 * Database type (SMDB_* constants)
171 * Is used in setKey().
172 * @var integer
173 */
98749983 174 var $db_type = SMDB_UNKNOWN;
370059dd 175
21ddfbc3 176 /**
177 * Character used to quote database table
178 * and field names
179 * @var string
180 */
181 var $identifier_quote_char = '';
182
ace4c62c 183 /**
184 * Default preferences
185 * @var array
186 */
2ea6df85 187 var $default = Array('theme_default' => 0,
102b278b 188 'include_self_reply_all' => '0',
189 'do_not_reply_to_self' => '1',
370059dd 190 'show_html_default' => '0');
191
06316c07 192 /**
193 * Preference owner field size
194 * @var integer
195 * @since 1.5.1
196 */
197 var $user_size = 128;
37b11ab0 198
06316c07 199 /**
200 * Preference key field size
201 * @var integer
202 * @since 1.5.1
203 */
204 var $key_size = 64;
37b11ab0 205
06316c07 206 /**
207 * Preference value field size
208 * @var integer
209 * @since 1.5.1
210 */
211 var $val_size = 65536;
212
37b11ab0 213
214
3ec364a4 215 /**
634f552a 216 * Constructor (PHP5 style, required in some future version of PHP)
3ec364a4 217 * initialize the default preferences array.
218 *
219 */
634f552a 220 function __construct() {
3ec364a4 221 // Try and read the default preferences file.
222 $default_pref = SM_PATH . 'config/default_pref';
223 if (@file_exists($default_pref)) {
224 if ($file = @fopen($default_pref, 'r')) {
225 while (!feof($file)) {
226 $pref = fgets($file, 1024);
227 $i = strpos($pref, '=');
228 if ($i > 0) {
229 $this->default[trim(substr($pref, 0, $i))] = trim(substr($pref, $i + 1));
230 }
231 }
232 fclose($file);
233 }
234 }
235 }
236
634f552a 237 /**
238 * Constructor (PHP4 style, kept for compatibility reasons)
239 * initialize the default preferences array.
240 *
241 */
242 function dbPrefs() {
243 self::__construct();
244 }
245
ace4c62c 246 /**
247 * initialize DB connection object
37b11ab0 248 *
ace4c62c 249 * @return boolean true, if object is initialized
37b11ab0 250 *
ace4c62c 251 */
370059dd 252 function open() {
b0392fa8 253 global $prefs_dsn, $prefs_db_charset, $prefs_table, $use_pdo, $db_identifier_quote_char;
98749983 254 global $prefs_user_field, $prefs_key_field, $prefs_val_field;
06316c07 255 global $prefs_user_size, $prefs_key_size, $prefs_val_size;
3499f99f 256
21ddfbc3 257 /* test if PDO or Pear DB classes are available and freak out if necessary */
258 if (!$use_pdo && !class_exists('DB')) {
099fea11 259 // same error also in abook_database.php
21ddfbc3 260 $error = _("Could not find or include PHP PDO or PEAR database functions required for the database backend.") . "\n";
261 $error .= sprintf(_("PDO should come preinstalled with PHP version 5.1 or higher. Otherwise, is PEAR installed, and is the include path set correctly to find %s?"), 'DB.php') . "\n";
262 $error .= _("Please contact your system administrator and report this error.");
099fea11 263 return false;
264 }
265
370059dd 266 if(isset($this->dbh)) {
267 return true;
268 }
3499f99f 269
21ddfbc3 270 if (strpos($prefs_dsn, 'mysql') === 0) {
98749983 271 $this->db_type = SMDB_MYSQL;
21ddfbc3 272 } else if (strpos($prefs_dsn, 'pgsql') === 0) {
98749983 273 $this->db_type = SMDB_PGSQL;
274 }
275
65e468fa 276 // figure out identifier quoting
277 if (empty($db_identifier_quote_char)) {
21ddfbc3 278 if ($this->db_type == SMDB_MYSQL)
279 $this->identifier_quote_char = '`';
280 else
281 $this->identifier_quote_char = '"';
65e468fa 282 } else if ($db_identifier_quote_char === 'none')
21ddfbc3 283 $this->identifier_quote_char = '';
284 else
65e468fa 285 $this->identifier_quote_char = $db_identifier_quote_char;
21ddfbc3 286
3499f99f 287 if (!empty($prefs_table)) {
288 $this->table = $prefs_table;
289 }
99a6c222 290 if (!empty($prefs_user_field)) {
291 $this->user_field = $prefs_user_field;
292 }
293 if (!empty($prefs_key_field)) {
294 $this->key_field = $prefs_key_field;
295 }
296 if (!empty($prefs_val_field)) {
297 $this->val_field = $prefs_val_field;
298 }
06316c07 299 if (!empty($prefs_user_size)) {
300 $this->user_size = (int) $prefs_user_size;
301 }
302 if (!empty($prefs_key_size)) {
303 $this->key_size = (int) $prefs_key_size;
304 }
305 if (!empty($prefs_val_size)) {
306 $this->val_size = (int) $prefs_val_size;
307 }
2d367c68 308
21ddfbc3 309 // connect, create database connection object
310 //
311 if ($use_pdo) {
312 // parse and convert DSN to PDO style
a95fae0b 313 // Pear's full DSN syntax is one of the following:
314 // phptype(dbsyntax)://username:password@protocol+hostspec/database?option=value
315 // phptype(syntax)://user:pass@protocol(proto_opts)/database
316 //
21ddfbc3 317 // $matches will contain:
318 // 1: database type
319 // 2: username
320 // 3: password
a95fae0b 321 // 4: hostname (and possible port number) OR protocol (and possible protocol options)
322 // 5: database name (and possible options)
323 // 6: port number (moved from match number 4)
324 // 7: options (moved from match number 5)
325 // 8: protocol (instead of hostname)
326 // 9: protocol options (moved from match number 4/8)
327//TODO: do we care about supporting cases where no password is given? (this is a legal DSN, but causes an error below)
21ddfbc3 328 if (!preg_match('|^(.+)://(.+):(.+)@(.+)/(.+)$|i', $prefs_dsn, $matches)) {
329 $this->error = _("Could not parse prefs DSN");
330 return false;
331 }
a95fae0b 332 $matches[6] = NULL;
333 $matches[7] = NULL;
334 $matches[8] = NULL;
335 $matches[9] = NULL;
21ddfbc3 336 if (preg_match('|^(.+):(\d+)$|', $matches[4], $host_port_matches)) {
337 $matches[4] = $host_port_matches[1];
338 $matches[6] = $host_port_matches[2];
a95fae0b 339 }
340 if (preg_match('|^(.+?)\((.+)\)$|', $matches[4], $protocol_matches)) {
341 $matches[8] = $protocol_matches[1];
342 $matches[9] = $protocol_matches[2];
343 $matches[4] = NULL;
21ddfbc3 344 $matches[6] = NULL;
a95fae0b 345 }
346//TODO: currently we just ignore options specified on the end of the DSN
347 if (preg_match('|^(.+?)\?(.+)$|', $matches[5], $database_name_options_matches)) {
348 $matches[5] = $database_name_options_matches[1];
349 $matches[7] = $database_name_options_matches[2];
350 }
351 if ($matches[8] === 'unix' && !empty($matches[9]))
352 $pdo_prefs_dsn = $matches[1] . ':unix_socket=' . $matches[9] . ';dbname=' . $matches[5];
353 else
354 $pdo_prefs_dsn = $matches[1] . ':host=' . $matches[4] . (!empty($matches[6]) ? ';port=' . $matches[6] : '') . ';dbname=' . $matches[5];
b0392fa8 355 if (!empty($prefs_db_charset))
356 $pdo_prefs_dsn .= ';charset=' . $prefs_db_charset;
21ddfbc3 357 try {
358 $dbh = new PDO($pdo_prefs_dsn, $matches[2], $matches[3]);
359 } catch (Exception $e) {
360 $this->error = $e->getMessage();
361 return false;
362 }
363 } else {
364 $dbh = DB::connect($prefs_dsn, true);
365
366 if(DB::isError($dbh)) {
367 $this->error = DB::errorMessage($dbh);
368 return false;
369 }
2d367c68 370 }
371
372 $this->dbh = $dbh;
b0392fa8 373
374 // Older versions of PHP are buggy with setting charset on the dsn so we also issue a SET NAMES
375 if (!empty($prefs_db_charset)) {
376 if ($use_pdo) {
377 $res = $dbh->exec('SET NAMES \'' . $prefs_db_charset . '\'');
378 /* Purposefully not checking for errors; some setups reportedly botch this on queries like this
379 if ($res === FALSE) {
380 if ($pdo_show_sql_errors)
381 $this->error = implode(' - ', $sth->errorInfo());
382 else
383 $this->error = _("Could not execute query");
384 }
385 $this->failQuery();
386 */
387 }
388 else {
389 $res = $this->dbh->simpleQuery('SET NAMES \'' . $prefs_db_charset . '\'');
390 /* Purposefully not checking for errors; some setups reportedly botch this on queries like this
391 if(DB::isError($res)) {
392 $this->failQuery($res);
393 }
394 */
395 }
396 }
397
2d367c68 398 return true;
370059dd 399 }
82474746 400
ace4c62c 401 /**
402 * Function used to handle database connection errors
37b11ab0 403 *
202bcbcc 404 * @param object PEAR Error object
37b11ab0 405 *
ace4c62c 406 */
370059dd 407 function failQuery($res = NULL) {
21ddfbc3 408 global $use_pdo;
2d367c68 409 if($res == NULL) {
410 printf(_("Preference database error (%s). Exiting abnormally"),
370059dd 411 $this->error);
2d367c68 412 } else {
413 printf(_("Preference database error (%s). Exiting abnormally"),
21ddfbc3 414 ($use_pdo ? implode(' - ', $res->errorInfo()) : DB::errorMessage($res)));
2d367c68 415 }
416 exit;
370059dd 417 }
82474746 418
ace4c62c 419 /**
420 * Get user's prefs setting
37b11ab0 421 *
ace4c62c 422 * @param string $user user name
423 * @param string $key preference name
424 * @param mixed $default (since 1.2.5) default value
37b11ab0 425 *
ace4c62c 426 * @return mixed preference value
37b11ab0 427 *
ace4c62c 428 */
370059dd 429 function getKey($user, $key, $default = '') {
430 global $prefs_cache;
2d367c68 431
971c7b1a 432 $temp = array(&$user, &$key);
433 $result = do_hook('get_pref_override', $temp);
434 if (is_null($result)) {
435 cachePrefValues($user);
2d367c68 436
971c7b1a 437 if (isset($prefs_cache[$key])) {
438 $result = $prefs_cache[$key];
62337234 439 } else {
971c7b1a 440//FIXME: is there a justification for having two prefs hooks so close? who uses them?
441 $temp = array(&$user, &$key);
442 $result = do_hook('get_pref', $temp);
443 if (is_null($result)) {
444 if (isset($this->default[$key])) {
445 $result = $this->default[$key];
446 } else {
447 $result = $default;
448 }
449 }
62337234 450 }
2d367c68 451 }
971c7b1a 452 return $result;
370059dd 453 }
2d367c68 454
ace4c62c 455 /**
456 * Delete user's prefs setting
37b11ab0 457 *
202bcbcc 458 * @param string $user user name
37b11ab0 459 * @param string $key preference name
460 *
ace4c62c 461 * @return boolean
37b11ab0 462 *
ace4c62c 463 */
370059dd 464 function deleteKey($user, $key) {
21ddfbc3 465 global $prefs_cache, $use_pdo, $pdo_show_sql_errors;
82474746 466
b279d7f4 467 if (!$this->open()) {
468 return false;
469 }
21ddfbc3 470 if ($use_pdo) {
471 if (!($sth = $this->dbh->prepare('DELETE FROM ' . $this->identifier_quote_char . $this->table . $this->identifier_quote_char . ' WHERE ' . $this->identifier_quote_char . $this->user_field . $this->identifier_quote_char . ' = ? AND ' . $this->identifier_quote_char . $this->key_field . $this->identifier_quote_char . ' = ?'))) {
472 if ($pdo_show_sql_errors)
473 $this->error = implode(' - ', $this->dbh->errorInfo());
474 else
475 $this->error = _("Could not prepare query");
476 $this->failQuery();
477 }
478 if (!($res = $sth->execute(array($user, $key)))) {
479 if ($pdo_show_sql_errors)
480 $this->error = implode(' - ', $sth->errorInfo());
481 else
482 $this->error = _("Could not execute query");
483 $this->failQuery();
484 }
485 } else {
65e468fa 486 $query = sprintf("DELETE FROM %s%s%s WHERE %s%s%s='%s' AND %s%s%s='%s'",
487 $this->identifier_quote_char,
21ddfbc3 488 $this->table,
65e468fa 489 $this->identifier_quote_char,
490 $this->identifier_quote_char,
21ddfbc3 491 $this->user_field,
65e468fa 492 $this->identifier_quote_char,
21ddfbc3 493 $this->dbh->quoteString($user),
65e468fa 494 $this->identifier_quote_char,
21ddfbc3 495 $this->key_field,
65e468fa 496 $this->identifier_quote_char,
21ddfbc3 497 $this->dbh->quoteString($key));
498
499 $res = $this->dbh->simpleQuery($query);
500 if(DB::isError($res)) {
501 $this->failQuery($res);
502 }
370059dd 503 }
504
505 unset($prefs_cache[$key]);
82474746 506
2d367c68 507 return true;
370059dd 508 }
82474746 509
ace4c62c 510 /**
511 * Set user's preference
37b11ab0 512 *
513 * @param string $user user name
514 * @param string $key preference name
515 * @param mixed $value preference value
516 *
ace4c62c 517 * @return boolean
37b11ab0 518 *
ace4c62c 519 */
370059dd 520 function setKey($user, $key, $value) {
21ddfbc3 521 global $use_pdo, $pdo_show_sql_errors;
b279d7f4 522 if (!$this->open()) {
523 return false;
524 }
06316c07 525
526 /**
527 * Check if username fits into db field
528 */
529 if (strlen($user) > $this->user_size) {
530 $this->error = "Oversized username value."
5e07597f 531 ." Your preferences can't be saved."
6f4c512c 532 ." See the administrator's manual or contact your system administrator.";
06316c07 533
534 /**
202bcbcc 535 * Debugging function. Can be used to log all issues that trigger
536 * oversized field errors. Function should be enabled in all three
06316c07 537 * strlen checks. See http://www.php.net/error-log
538 */
539 // error_log($user.'|'.$key.'|'.$value."\n",3,'/tmp/oversized_log');
540
541 // error is fatal
542 $this->failQuery(null);
543 }
544 /**
545 * Check if preference key fits into db field
546 */
547 if (strlen($key) > $this->key_size) {
548 $err_msg = "Oversized user's preference key."
5e07597f 549 ." Some preferences were not saved."
6f4c512c 550 ." See the administrator's manual or contact your system administrator.";
06316c07 551 // error is not fatal. Only some preference is not saved.
552 trigger_error($err_msg,E_USER_WARNING);
553 return false;
554 }
555 /**
556 * Check if preference value fits into db field
557 */
558 if (strlen($value) > $this->val_size) {
559 $err_msg = "Oversized user's preference value."
5e07597f 560 ." Some preferences were not saved."
6f4c512c 561 ." See the administrator's manual or contact your system administrator.";
06316c07 562 // error is not fatal. Only some preference is not saved.
563 trigger_error($err_msg,E_USER_WARNING);
564 return false;
565 }
566
567
98749983 568 if ($this->db_type == SMDB_MYSQL) {
21ddfbc3 569 if ($use_pdo) {
570 if (!($sth = $this->dbh->prepare('REPLACE INTO ' . $this->identifier_quote_char . $this->table . $this->identifier_quote_char . ' (' . $this->identifier_quote_char . $this->user_field . $this->identifier_quote_char . ', ' . $this->identifier_quote_char . $this->key_field . $this->identifier_quote_char . ', ' . $this->identifier_quote_char . $this->val_field . $this->identifier_quote_char . ') VALUES (?, ?, ?)'))) {
571 if ($pdo_show_sql_errors)
572 $this->error = implode(' - ', $this->dbh->errorInfo());
573 else
574 $this->error = _("Could not prepare query");
575 $this->failQuery();
576 }
577 if (!($res = $sth->execute(array($user, $key, $value)))) {
578 if ($pdo_show_sql_errors)
579 $this->error = implode(' - ', $sth->errorInfo());
580 else
581 $this->error = _("Could not execute query");
582 $this->failQuery();
583 }
584 } else {
65e468fa 585 $query = sprintf("REPLACE INTO %s%s%s (%s%s%s, %s%s%s, %s%s%s) ".
21ddfbc3 586 "VALUES('%s','%s','%s')",
65e468fa 587 $this->identifier_quote_char,
21ddfbc3 588 $this->table,
65e468fa 589 $this->identifier_quote_char,
590 $this->identifier_quote_char,
21ddfbc3 591 $this->user_field,
65e468fa 592 $this->identifier_quote_char,
593 $this->identifier_quote_char,
21ddfbc3 594 $this->key_field,
65e468fa 595 $this->identifier_quote_char,
596 $this->identifier_quote_char,
21ddfbc3 597 $this->val_field,
65e468fa 598 $this->identifier_quote_char,
21ddfbc3 599 $this->dbh->quoteString($user),
600 $this->dbh->quoteString($key),
601 $this->dbh->quoteString($value));
602
603 $res = $this->dbh->simpleQuery($query);
604 if(DB::isError($res)) {
605 $this->failQuery($res);
606 }
98749983 607 }
608 } elseif ($this->db_type == SMDB_PGSQL) {
21ddfbc3 609 if ($use_pdo) {
610 if ($this->dbh->exec('BEGIN TRANSACTION') === FALSE) {
611 if ($pdo_show_sql_errors)
612 $this->error = implode(' - ', $this->dbh->errorInfo());
613 else
614 $this->error = _("Could not execute query");
615 $this->failQuery();
616 }
617 if (!($sth = $this->dbh->prepare('DELETE FROM ' . $this->identifier_quote_char . $this->table . $this->identifier_quote_char . ' WHERE ' . $this->identifier_quote_char . $this->user_field . $this->identifier_quote_char . ' = ? AND ' . $this->identifier_quote_char . $this->key_field . $this->identifier_quote_char . ' = ?'))) {
618 if ($pdo_show_sql_errors)
619 $this->error = implode(' - ', $this->dbh->errorInfo());
620 else
621 $this->error = _("Could not prepare query");
622 $this->failQuery();
623 }
624 if (!($res = $sth->execute(array($user, $key)))) {
625 if ($pdo_show_sql_errors)
626 $this->error = implode(' - ', $sth->errorInfo());
627 else
628 $this->error = _("Could not execute query");
629 $this->dbh->exec('ROLLBACK TRANSACTION');
630 $this->failQuery();
631 }
632 if (!($sth = $this->dbh->prepare('INSERT INTO ' . $this->identifier_quote_char . $this->table . $this->identifier_quote_char . ' (' . $this->identifier_quote_char . $this->user_field . $this->identifier_quote_char . ', ' . $this->identifier_quote_char . $this->key_field . $this->identifier_quote_char . ', ' . $this->identifier_quote_char . $this->val_field . $this->identifier_quote_char . ') VALUES (?, ?, ?)'))) {
633 if ($pdo_show_sql_errors)
634 $this->error = implode(' - ', $this->dbh->errorInfo());
635 else
636 $this->error = _("Could not prepare query");
637 $this->failQuery();
638 }
639 if (!($res = $sth->execute(array($user, $key, $value)))) {
640 if ($pdo_show_sql_errors)
641 $this->error = implode(' - ', $sth->errorInfo());
642 else
643 $this->error = _("Could not execute query");
644 $this->dbh->exec('ROLLBACK TRANSACTION');
645 $this->failQuery();
646 }
647 if ($this->dbh->exec('COMMIT TRANSACTION') === FALSE) {
648 if ($pdo_show_sql_errors)
649 $this->error = implode(' - ', $this->dbh->errorInfo());
650 else
651 $this->error = _("Could not execute query");
652 $this->failQuery();
653 }
654 } else {
655 $this->dbh->simpleQuery("BEGIN TRANSACTION");
65e468fa 656 $query = sprintf("DELETE FROM %s%s%s WHERE %s%s%s='%s' AND %s%s%s='%s'",
657 $this->identifier_quote_char,
21ddfbc3 658 $this->table,
65e468fa 659 $this->identifier_quote_char,
660 $this->identifier_quote_char,
21ddfbc3 661 $this->user_field,
65e468fa 662 $this->identifier_quote_char,
21ddfbc3 663 $this->dbh->quoteString($user),
65e468fa 664 $this->identifier_quote_char,
21ddfbc3 665 $this->key_field,
65e468fa 666 $this->identifier_quote_char,
21ddfbc3 667 $this->dbh->quoteString($key));
668 $res = $this->dbh->simpleQuery($query);
669 if (DB::isError($res)) {
670 $this->dbh->simpleQuery("ROLLBACK TRANSACTION");
671 $this->failQuery($res);
672 }
65e468fa 673 $query = sprintf("INSERT INTO %s%s%s (%s%s%s, %s%s%s, %s%s%s) VALUES ('%s', '%s', '%s')",
674 $this->identifier_quote_char,
21ddfbc3 675 $this->table,
65e468fa 676 $this->identifier_quote_char,
677 $this->identifier_quote_char,
21ddfbc3 678 $this->user_field,
65e468fa 679 $this->identifier_quote_char,
680 $this->identifier_quote_char,
21ddfbc3 681 $this->key_field,
65e468fa 682 $this->identifier_quote_char,
683 $this->identifier_quote_char,
21ddfbc3 684 $this->val_field,
65e468fa 685 $this->identifier_quote_char,
21ddfbc3 686 $this->dbh->quoteString($user),
687 $this->dbh->quoteString($key),
688 $this->dbh->quoteString($value));
689 $res = $this->dbh->simpleQuery($query);
690 if (DB::isError($res)) {
691 $this->dbh->simpleQuery("ROLLBACK TRANSACTION");
692 $this->failQuery($res);
693 }
694 $this->dbh->simpleQuery("COMMIT TRANSACTION");
98749983 695 }
98749983 696 } else {
21ddfbc3 697 if ($use_pdo) {
698 if (!($sth = $this->dbh->prepare('DELETE FROM ' . $this->identifier_quote_char . $this->table . $this->identifier_quote_char . ' WHERE ' . $this->identifier_quote_char . $this->user_field . $this->identifier_quote_char . ' = ? AND ' . $this->identifier_quote_char . $this->key_field . $this->identifier_quote_char . ' = ?'))) {
699 if ($pdo_show_sql_errors)
700 $this->error = implode(' - ', $this->dbh->errorInfo());
701 else
702 $this->error = _("Could not prepare query");
703 $this->failQuery();
704 }
705 if (!($res = $sth->execute(array($user, $key)))) {
706 if ($pdo_show_sql_errors)
707 $this->error = implode(' - ', $sth->errorInfo());
708 else
709 $this->error = _("Could not execute query");
710 $this->failQuery();
711 }
712 if (!($sth = $this->dbh->prepare('INSERT INTO ' . $this->identifier_quote_char . $this->table . $this->identifier_quote_char . ' (' . $this->identifier_quote_char . $this->user_field . $this->identifier_quote_char . ', ' . $this->identifier_quote_char . $this->key_field . $this->identifier_quote_char . ', ' . $this->identifier_quote_char . $this->val_field . $this->identifier_quote_char . ') VALUES (?, ?, ?)'))) {
713 if ($pdo_show_sql_errors)
714 $this->error = implode(' - ', $this->dbh->errorInfo());
715 else
716 $this->error = _("Could not prepare query");
717 $this->failQuery();
718 }
719 if (!($res = $sth->execute(array($user, $key, $value)))) {
720 if ($pdo_show_sql_errors)
721 $this->error = implode(' - ', $sth->errorInfo());
722 else
723 $this->error = _("Could not execute query");
724 $this->failQuery();
725 }
726 } else {
65e468fa 727 $query = sprintf("DELETE FROM %s%s%s WHERE %s%s%s='%s' AND %s%s%s='%s'",
728 $this->identifier_quote_char,
21ddfbc3 729 $this->table,
65e468fa 730 $this->identifier_quote_char,
731 $this->identifier_quote_char,
21ddfbc3 732 $this->user_field,
65e468fa 733 $this->identifier_quote_char,
21ddfbc3 734 $this->dbh->quoteString($user),
65e468fa 735 $this->identifier_quote_char,
21ddfbc3 736 $this->key_field,
65e468fa 737 $this->identifier_quote_char,
21ddfbc3 738 $this->dbh->quoteString($key));
739 $res = $this->dbh->simpleQuery($query);
740 if (DB::isError($res)) {
741 $this->failQuery($res);
742 }
65e468fa 743 $query = sprintf("INSERT INTO %s%s%s (%s%s%s, %s%s%s, %s%s%s) VALUES ('%s', '%s', '%s')",
744 $this->identifier_quote_char,
21ddfbc3 745 $this->table,
65e468fa 746 $this->identifier_quote_char,
747 $this->identifier_quote_char,
21ddfbc3 748 $this->user_field,
65e468fa 749 $this->identifier_quote_char,
750 $this->identifier_quote_char,
21ddfbc3 751 $this->key_field,
65e468fa 752 $this->identifier_quote_char,
753 $this->identifier_quote_char,
21ddfbc3 754 $this->val_field,
65e468fa 755 $this->identifier_quote_char,
21ddfbc3 756 $this->dbh->quoteString($user),
757 $this->dbh->quoteString($key),
758 $this->dbh->quoteString($value));
759 $res = $this->dbh->simpleQuery($query);
760 if (DB::isError($res)) {
761 $this->failQuery($res);
762 }
98749983 763 }
370059dd 764 }
2d367c68 765
766 return true;
370059dd 767 }
82474746 768
ace4c62c 769 /**
770 * Fill preference cache array
37b11ab0 771 *
ace4c62c 772 * @param string $user user name
37b11ab0 773 *
ace4c62c 774 * @since 1.2.3
37b11ab0 775 *
ace4c62c 776 */
370059dd 777 function fillPrefsCache($user) {
21ddfbc3 778 global $prefs_cache, $use_pdo, $pdo_show_sql_errors;
2d367c68 779
b279d7f4 780 if (!$this->open()) {
781 return;
782 }
370059dd 783
784 $prefs_cache = array();
21ddfbc3 785 if ($use_pdo) {
786 if (!($sth = $this->dbh->prepare('SELECT ' . $this->identifier_quote_char . $this->key_field . $this->identifier_quote_char . ' AS prefkey, ' . $this->identifier_quote_char . $this->val_field . $this->identifier_quote_char . ' AS prefval FROM ' . $this->identifier_quote_char . $this->table . $this->identifier_quote_char . ' WHERE ' . $this->identifier_quote_char . $this->user_field . $this->identifier_quote_char . ' = ?'))) {
787 if ($pdo_show_sql_errors)
788 $this->error = implode(' - ', $this->dbh->errorInfo());
789 else
790 $this->error = _("Could not prepare query");
791 $this->failQuery();
792 }
793 if (!($res = $sth->execute(array($user)))) {
794 if ($pdo_show_sql_errors)
795 $this->error = implode(' - ', $sth->errorInfo());
796 else
797 $this->error = _("Could not execute query");
798 $this->failQuery();
799 }
370059dd 800
21ddfbc3 801 while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
802 $prefs_cache[$row['prefkey']] = $row['prefval'];
803 }
804 } else {
65e468fa 805 $query = sprintf("SELECT %s%s%s as prefkey, %s%s%s as prefval FROM %s%s%s ".
806 "WHERE %s%s%s = '%s'",
807 $this->identifier_quote_char,
21ddfbc3 808 $this->key_field,
65e468fa 809 $this->identifier_quote_char,
810 $this->identifier_quote_char,
21ddfbc3 811 $this->val_field,
65e468fa 812 $this->identifier_quote_char,
813 $this->identifier_quote_char,
21ddfbc3 814 $this->table,
65e468fa 815 $this->identifier_quote_char,
816 $this->identifier_quote_char,
21ddfbc3 817 $this->user_field,
65e468fa 818 $this->identifier_quote_char,
21ddfbc3 819 $this->dbh->quoteString($user));
820 $res = $this->dbh->query($query);
821 if (DB::isError($res)) {
822 $this->failQuery($res);
823 }
824
825 while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
826 $prefs_cache[$row['prefkey']] = $row['prefval'];
827 }
370059dd 828 }
829 }
830
370059dd 831} /* end class dbPrefs */
82474746 832
833
4d30c1b7 834/**
37b11ab0 835 * Returns the value for the requested preference
4d30c1b7 836 * @ignore
837 */
37b11ab0 838function getPref($data_dir, $username, $pref_name, $default = '') {
370059dd 839 $db = new dbPrefs;
840 if(isset($db->error)) {
2d367c68 841 printf( _("Preference database error (%s). Exiting abnormally"),
370059dd 842 $db->error);
2d367c68 843 exit;
370059dd 844 }
845
37b11ab0 846 return $db->getKey($username, $pref_name, $default);
370059dd 847}
848
4d30c1b7 849/**
37b11ab0 850 * Remove the desired preference setting ($pref_name)
4d30c1b7 851 * @ignore
852 */
37b11ab0 853function removePref($data_dir, $username, $pref_name) {
1fa62ab9 854 global $prefs_cache;
370059dd 855 $db = new dbPrefs;
856 if(isset($db->error)) {
857 $db->failQuery();
858 }
859
37b11ab0 860 $db->deleteKey($username, $pref_name);
88a99543 861
37b11ab0 862 if (isset($prefs_cache[$pref_name])) {
863 unset($prefs_cache[$pref_name]);
88a99543 864 }
865
866 sqsession_register($prefs_cache , 'prefs_cache');
370059dd 867 return;
868}
869
4d30c1b7 870/**
37b11ab0 871 * Sets the desired preference setting ($pref_name) to whatever is in $value
4d30c1b7 872 * @ignore
873 */
37b11ab0 874function setPref($data_dir, $username, $pref_name, $value) {
370059dd 875 global $prefs_cache;
876
37b11ab0 877 if (isset($prefs_cache[$pref_name]) && ($prefs_cache[$pref_name] == $value)) {
1fa62ab9 878 return;
370059dd 879 }
880
37b11ab0 881 if ($value === '') {
882 removePref($data_dir, $username, $pref_name);
370059dd 883 return;
884 }
885
886 $db = new dbPrefs;
887 if(isset($db->error)) {
888 $db->failQuery();
889 }
890
37b11ab0 891 $db->setKey($username, $pref_name, $value);
892 $prefs_cache[$pref_name] = $value;
370059dd 893 assert_options(ASSERT_ACTIVE, 1);
894 assert_options(ASSERT_BAIL, 1);
37b11ab0 895 assert ('$value == $prefs_cache[$pref_name]');
88a99543 896 sqsession_register($prefs_cache , 'prefs_cache');
370059dd 897 return;
898}
899
4d30c1b7 900/**
901 * This checks if the prefs are available
902 * @ignore
903 */
370059dd 904function checkForPrefs($data_dir, $username) {
905 $db = new dbPrefs;
906 if(isset($db->error)) {
907 $db->failQuery();
908 }
909}
910
4d30c1b7 911/**
912 * Writes the Signature
913 * @ignore
914 */
37b11ab0 915function setSig($data_dir, $username, $number, $value) {
16e5635d 916 if ($number == "g") {
917 $key = '___signature___';
918 } else {
919 $key = sprintf('___sig%s___', $number);
920 }
37b11ab0 921 setPref($data_dir, $username, $key, $value);
370059dd 922 return;
923}
924
4d30c1b7 925/**
926 * Gets the signature
927 * @ignore
928 */
16e5635d 929function getSig($data_dir, $username, $number) {
16e5635d 930 if ($number == "g") {
931 $key = '___signature___';
932 } else {
933 $key = sprintf('___sig%d___', $number);
934 }
57f1d1c1 935 return getPref($data_dir, $username, $key);
370059dd 936}