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