Source for file db_prefs.php

Documentation is available at db_prefs.php

  1. <?php
  2.  
  3. /**
  4.  * db_prefs.php
  5.  *
  6.  * This contains functions for manipulating user preferences
  7.  * stored in a database, accessed though the Pear DB layer.
  8.  *
  9.  * Database:
  10.  *
  11.  * The preferences table should have three columns:
  12.  *    user       char  \  primary
  13.  *    prefkey    char  /  key
  14.  *    prefval    blob
  15.  *
  16.  *   CREATE TABLE userprefs (user CHAR(128) NOT NULL DEFAULT '',
  17.  *                           prefkey CHAR(64) NOT NULL DEFAULT '',
  18.  *                           prefval BLOB NOT NULL DEFAULT '',
  19.  *                           primary key (user,prefkey));
  20.  *
  21.  * Configuration of databasename, username and password is done
  22.  * by using conf.pl or the administrator plugin
  23.  *
  24.  * @copyright 1999-2014 The SquirrelMail Project Team
  25.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  26.  * @version $Id: db_prefs.php 14420 2014-01-01 20:33:20Z pdontthink $
  27.  * @package squirrelmail
  28.  * @subpackage prefs
  29.  * @since 1.1.3
  30.  */
  31.  
  32. /** @ignore */
  33. if (!defined('SM_PATH')) define('SM_PATH','../');
  34.  
  35. /** Unknown database */
  36. define('SMDB_UNKNOWN'0);
  37. /** MySQL */
  38. define('SMDB_MYSQL'1);
  39. /** PostgreSQL */
  40. define('SMDB_PGSQL'2);
  41.  
  42. /**
  43.  * don't display errors (no code execution in functions/*.php).
  44.  * will handle error in dbPrefs class.
  45.  */
  46. @include_once('DB.php');
  47.  
  48. global $prefs_are_cached$prefs_cache;
  49.  
  50. /**
  51.  * @ignore
  52.  */
  53. function cachePrefValues($username{
  54.     global $prefs_are_cached$prefs_cache;
  55.  
  56.     sqgetGlobalVar('prefs_are_cached'$prefs_are_cachedSQ_SESSION );
  57.     if ($prefs_are_cached{
  58.         sqgetGlobalVar('prefs_cache'$prefs_cacheSQ_SESSION );
  59.         return;
  60.     }
  61.  
  62.     sqsession_unregister('prefs_cache');
  63.     sqsession_unregister('prefs_are_cached');
  64.  
  65.     $db new dbPrefs;
  66.     if(isset($db->error)) {
  67.         printf_("Preference database error (%s). Exiting abnormally"),
  68.               $db->error);
  69.         exit;
  70.     }
  71.  
  72.     $db->fillPrefsCache($username);
  73.     if (isset($db->error)) {
  74.         printf_("Preference database error (%s). Exiting abnormally"),
  75.               $db->error);
  76.         exit;
  77.     }
  78.  
  79.     $prefs_are_cached true;
  80.  
  81.     sqsession_register($prefs_cache'prefs_cache');
  82.     sqsession_register($prefs_are_cached'prefs_are_cached');
  83. }
  84.  
  85. /**
  86.  * Class used to handle connections to prefs database and operations with preferences
  87.  *
  88.  * @package squirrelmail
  89.  * @subpackage prefs
  90.  * @since 1.1.3
  91.  *
  92.  */
  93. class dbPrefs {
  94.     /**
  95.      * Table used to store preferences
  96.      * @var string 
  97.      */
  98.     var $table = 'userprefs';
  99.  
  100.     /**
  101.      * Field used to store owner of preference
  102.      * @var string 
  103.      */
  104.     var $user_field = 'user';
  105.  
  106.     /**
  107.      * Field used to store preference name
  108.      * @var string 
  109.      */
  110.     var $key_field = 'prefkey';
  111.  
  112.     /**
  113.      * Field used to store preference value
  114.      * @var string 
  115.      */
  116.     var $val_field = 'prefval';
  117.  
  118.     /**
  119.      * Database connection object
  120.      * @var object 
  121.      */
  122.     var $dbh   = NULL;
  123.  
  124.     /**
  125.      * Error messages
  126.      * @var string 
  127.      */
  128.     var $error = NULL;
  129.  
  130.     /**
  131.      * Database type (SMDB_* constants)
  132.      * Is used in setKey().
  133.      * @var integer 
  134.      */
  135.     var $db_type = SMDB_UNKNOWN;
  136.  
  137.     /**
  138.      * Default preferences
  139.      * @var array 
  140.      */
  141.     var $default = Array('theme_default' => 0,
  142.                          'show_html_default' => '0');
  143.  
  144.     /**
  145.      * Preference owner field size
  146.      * @var integer 
  147.      * @since 1.5.1
  148.      */
  149.     var $user_size = 128;
  150.  
  151.     /**
  152.      * Preference key field size
  153.      * @var integer 
  154.      * @since 1.5.1
  155.      */
  156.     var $key_size = 64;
  157.  
  158.     /**
  159.      * Preference value field size
  160.      * @var integer 
  161.      * @since 1.5.1
  162.      */
  163.     var $val_size = 65536;
  164.  
  165.  
  166.  
  167.     /**
  168.      * initialize the default preferences array.
  169.      *
  170.      */
  171.     function dbPrefs({
  172.         // Try and read the default preferences file.
  173.         $default_pref SM_PATH 'config/default_pref';
  174.         if (@file_exists($default_pref)) {
  175.             if ($file @fopen($default_pref'r')) {
  176.                 while (!feof($file)) {
  177.                     $pref fgets($file1024);
  178.                     $i strpos($pref'=');
  179.                     if ($i 0{
  180.                         $this->default[trim(substr($pref0$i))trim(substr($pref$i 1));
  181.                     }
  182.                 }
  183.                 fclose($file);
  184.             }
  185.         }
  186.     }
  187.  
  188.     /**
  189.      * initialize DB connection object
  190.      *
  191.      * @return boolean true, if object is initialized
  192.      *
  193.      */
  194.     function open({
  195.         global $prefs_dsn$prefs_table;
  196.         global $prefs_user_size$prefs_key_size$prefs_val_size;
  197.  
  198.         /* test if Pear DB class is available and freak out if it is not */
  199.         if (class_exists('DB')) {
  200.             // same error also in abook_database.php
  201.             $this->error  = _("Could not include PEAR database functions required for the database backend.""\n";
  202.             $this->error .= sprintf(_("Is PEAR installed, and is the include path set correctly to find %s?"),
  203.                               'DB.php'"\n";
  204.             $this->error .= _("Please contact your system administrator and report this error.");
  205.             return false;
  206.         }
  207.  
  208.         if(isset($this->dbh)) {
  209.             return true;
  210.         }
  211.  
  212.         if (preg_match('/^mysql/'$prefs_dsn)) {
  213.             $this->db_type = SMDB_MYSQL;
  214.         elseif (preg_match('/^pgsql/'$prefs_dsn)) {
  215.             $this->db_type = SMDB_PGSQL;
  216.         }
  217.  
  218.         if (!empty($prefs_table)) {
  219.             $this->table = $prefs_table;
  220.         }
  221.         if (!empty($prefs_user_field)) {
  222.             $this->user_field = $prefs_user_field;
  223.         }
  224.  
  225.         // the default user field is "user", which in PostgreSQL
  226.         // is an identifier and causes errors if not escaped
  227.         //
  228.         if ($this->db_type == SMDB_PGSQL{
  229.            $this->user_field = '"' $this->user_field . '"';
  230.         }
  231.  
  232.         if (!empty($prefs_key_field)) {
  233.             $this->key_field = $prefs_key_field;
  234.         }
  235.         if (!empty($prefs_val_field)) {
  236.             $this->val_field = $prefs_val_field;
  237.         }
  238.         if (!empty($prefs_user_size)) {
  239.             $this->user_size = (int) $prefs_user_size;
  240.         }
  241.         if (!empty($prefs_key_size)) {
  242.             $this->key_size = (int) $prefs_key_size;
  243.         }
  244.         if (!empty($prefs_val_size)) {
  245.             $this->val_size = (int) $prefs_val_size;
  246.         }
  247.         $dbh DB::connect($prefs_dsntrue);
  248.  
  249.         if(DB::isError($dbh)) {
  250.             $this->error = DB::errorMessage($dbh);
  251.             return false;
  252.         }
  253.  
  254.         $this->dbh = $dbh;
  255.         return true;
  256.     }
  257.  
  258.     /**
  259.      * Function used to handle database connection errors
  260.      *
  261.      * @param object PEAR Error object
  262.      *
  263.      */
  264.     function failQuery($res NULL{
  265.         if($res == NULL{
  266.             printf(_("Preference database error (%s). Exiting abnormally"),
  267.                   $this->error);
  268.         else {
  269.             printf(_("Preference database error (%s). Exiting abnormally"),
  270.                   DB::errorMessage($res));
  271.         }
  272.         exit;
  273.     }
  274.  
  275.     /**
  276.      * Get user's prefs setting
  277.      *
  278.      * @param string $user user name
  279.      * @param string $key preference name
  280.      * @param mixed $default (since 1.2.5) default value
  281.      *
  282.      * @return mixed preference value
  283.      *
  284.      */
  285.     function getKey($user$key$default ''{
  286.         global $prefs_cache;
  287.  
  288.         $temp array(&$user&$key);
  289.         $result do_hook('get_pref_override'$temp);
  290.         if (is_null($result)) {
  291.             cachePrefValues($user);
  292.  
  293.             if (isset($prefs_cache[$key])) {
  294.                 $result $prefs_cache[$key];
  295.             else {
  296. //FIXME: is there a justification for having two prefs hooks so close?  who uses them?
  297.                 $temp array(&$user&$key);
  298.                 $result do_hook('get_pref'$temp);
  299.                 if (is_null($result)) {
  300.                     if (isset($this->default[$key])) {
  301.                         $result $this->default[$key];
  302.                     else {
  303.                         $result $default;
  304.                     }
  305.                 }
  306.             }
  307.         }
  308.         return $result;
  309.     }
  310.  
  311.     /**
  312.      * Delete user's prefs setting
  313.      *
  314.      * @param string $user user name
  315.      * @param string $key  preference name
  316.      *
  317.      * @return boolean 
  318.      *
  319.      */
  320.     function deleteKey($user$key{
  321.         global $prefs_cache;
  322.  
  323.         if (!$this->open()) {
  324.             return false;
  325.         }
  326.         $query sprintf("DELETE FROM %s WHERE %s='%s' AND %s='%s'",
  327.                          $this->table,
  328.                          $this->user_field,
  329.                          $this->dbh->quoteString($user),
  330.                          $this->key_field,
  331.                          $this->dbh->quoteString($key));
  332.  
  333.         $res $this->dbh->simpleQuery($query);
  334.         if(DB::isError($res)) {
  335.             $this->failQuery($res);
  336.         }
  337.  
  338.         unset($prefs_cache[$key]);
  339.  
  340.         return true;
  341.     }
  342.  
  343.     /**
  344.      * Set user's preference
  345.      *
  346.      * @param string $user  user name
  347.      * @param string $key   preference name
  348.      * @param mixed  $value preference value
  349.      *
  350.      * @return boolean 
  351.      *
  352.      */
  353.     function setKey($user$key$value{
  354.         if (!$this->open()) {
  355.             return false;
  356.         }
  357.  
  358.         /**
  359.          * Check if username fits into db field
  360.          */
  361.         if (strlen($user$this->user_size{
  362.             $this->error = "Oversized username value."
  363.                 ." Your preferences can't be saved."
  364.                 ." See the administrator's manual or contact your system administrator.";
  365.  
  366.             /**
  367.              * Debugging function. Can be used to log all issues that trigger
  368.              * oversized field errors. Function should be enabled in all three
  369.              * strlen checks. See http://www.php.net/error-log
  370.              */
  371.             // error_log($user.'|'.$key.'|'.$value."\n",3,'/tmp/oversized_log');
  372.  
  373.             // error is fatal
  374.             $this->failQuery(null);
  375.         }
  376.         /**
  377.          * Check if preference key fits into db field
  378.          */
  379.         if (strlen($key$this->key_size{
  380.             $err_msg "Oversized user's preference key."
  381.                 ." Some preferences were not saved."
  382.                 ." See the administrator's manual or contact your system administrator.";
  383.             // error is not fatal. Only some preference is not saved.
  384.             trigger_error($err_msg,E_USER_WARNING);
  385.             return false;
  386.         }
  387.         /**
  388.          * Check if preference value fits into db field
  389.          */
  390.         if (strlen($value$this->val_size{
  391.             $err_msg "Oversized user's preference value."
  392.                 ." Some preferences were not saved."
  393.                 ." See the administrator's manual or contact your system administrator.";
  394.             // error is not fatal. Only some preference is not saved.
  395.             trigger_error($err_msg,E_USER_WARNING);
  396.             return false;
  397.         }
  398.  
  399.  
  400.         if ($this->db_type == SMDB_MYSQL{
  401.             $query sprintf("REPLACE INTO %s (%s, %s, %s) ".
  402.                              "VALUES('%s','%s','%s')",
  403.                              $this->table,
  404.                              $this->user_field,
  405.                              $this->key_field,
  406.                              $this->val_field,
  407.                              $this->dbh->quoteString($user),
  408.                              $this->dbh->quoteString($key),
  409.                              $this->dbh->quoteString($value));
  410.  
  411.             $res $this->dbh->simpleQuery($query);
  412.             if(DB::isError($res)) {
  413.                 $this->failQuery($res);
  414.             }
  415.         elseif ($this->db_type == SMDB_PGSQL{
  416.             $this->dbh->simpleQuery("BEGIN TRANSACTION");
  417.             $query sprintf("DELETE FROM %s WHERE %s='%s' AND %s='%s'",
  418.                              $this->table,
  419.                              $this->user_field,
  420.                              $this->dbh->quoteString($user),
  421.                              $this->key_field,
  422.                              $this->dbh->quoteString($key));
  423.             $res $this->dbh->simpleQuery($query);
  424.             if (DB::isError($res)) {
  425.                 $this->dbh->simpleQuery("ROLLBACK TRANSACTION");
  426.                 $this->failQuery($res);
  427.             }
  428.             $query sprintf("INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s')",
  429.                              $this->table,
  430.                              $this->user_field,
  431.                              $this->key_field,
  432.                              $this->val_field,
  433.                              $this->dbh->quoteString($user),
  434.                              $this->dbh->quoteString($key),
  435.                              $this->dbh->quoteString($value));
  436.             $res $this->dbh->simpleQuery($query);
  437.             if (DB::isError($res)) {
  438.                 $this->dbh->simpleQuery("ROLLBACK TRANSACTION");
  439.                 $this->failQuery($res);
  440.             }
  441.             $this->dbh->simpleQuery("COMMIT TRANSACTION");
  442.         else {
  443.             $query sprintf("DELETE FROM %s WHERE %s='%s' AND %s='%s'",
  444.                              $this->table,
  445.                              $this->user_field,
  446.                              $this->dbh->quoteString($user),
  447.                              $this->key_field,
  448.                              $this->dbh->quoteString($key));
  449.             $res $this->dbh->simpleQuery($query);
  450.             if (DB::isError($res)) {
  451.                 $this->failQuery($res);
  452.             }
  453.             $query sprintf("INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s')",
  454.                              $this->table,
  455.                              $this->user_field,
  456.                              $this->key_field,
  457.                              $this->val_field,
  458.                              $this->dbh->quoteString($user),
  459.                              $this->dbh->quoteString($key),
  460.                              $this->dbh->quoteString($value));
  461.             $res $this->dbh->simpleQuery($query);
  462.             if (DB::isError($res)) {
  463.                 $this->failQuery($res);
  464.             }
  465.         }
  466.  
  467.         return true;
  468.     }
  469.  
  470.     /**
  471.      * Fill preference cache array
  472.      *
  473.      * @param string $user user name
  474.      *
  475.      * @since 1.2.3
  476.      *
  477.      */
  478.     function fillPrefsCache($user{
  479.         global $prefs_cache;
  480.  
  481.         if (!$this->open()) {
  482.             return;
  483.         }
  484.  
  485.         $prefs_cache array();
  486.         $query sprintf("SELECT %s as prefkey, %s as prefval FROM %s ".
  487.                          "WHERE %s = '%s'",
  488.                          $this->key_field,
  489.                          $this->val_field,
  490.                          $this->table,
  491.                          $this->user_field,
  492.                          $this->dbh->quoteString($user));
  493.         $res $this->dbh->query($query);
  494.         if (DB::isError($res)) {
  495.             $this->failQuery($res);
  496.         }
  497.  
  498.         while ($row $res->fetchRow(DB_FETCHMODE_ASSOC)) {
  499.             $prefs_cache[$row['prefkey']] $row['prefval'];
  500.         }
  501.     }
  502.  
  503. /* end class dbPrefs */
  504.  
  505.  
  506. /**
  507.  * Returns the value for the requested preference
  508.  * @ignore
  509.  */
  510. function getPref($data_dir$username$pref_name$default ''{
  511.     $db new dbPrefs;
  512.     if(isset($db->error)) {
  513.         printf_("Preference database error (%s). Exiting abnormally"),
  514.               $db->error);
  515.         exit;
  516.     }
  517.  
  518.     return $db->getKey($username$pref_name$default);
  519. }
  520.  
  521. /**
  522.  * Remove the desired preference setting ($pref_name)
  523.  * @ignore
  524.  */
  525. function removePref($data_dir$username$pref_name{
  526.     global $prefs_cache;
  527.     $db new dbPrefs;
  528.     if(isset($db->error)) {
  529.         $db->failQuery();
  530.     }
  531.  
  532.     $db->deleteKey($username$pref_name);
  533.  
  534.     if (isset($prefs_cache[$pref_name])) {
  535.         unset($prefs_cache[$pref_name]);
  536.     }
  537.  
  538.     sqsession_register($prefs_cache 'prefs_cache');
  539.     return;
  540. }
  541.  
  542. /**
  543.  * Sets the desired preference setting ($pref_name) to whatever is in $value
  544.  * @ignore
  545.  */
  546. function setPref($data_dir$username$pref_name$value{
  547.     global $prefs_cache;
  548.  
  549.     if (isset($prefs_cache[$pref_name]&& ($prefs_cache[$pref_name== $value)) {
  550.         return;
  551.     }
  552.  
  553.     if ($value === ''{
  554.         removePref($data_dir$username$pref_name);
  555.         return;
  556.     }
  557.  
  558.     $db new dbPrefs;
  559.     if(isset($db->error)) {
  560.         $db->failQuery();
  561.     }
  562.  
  563.     $db->setKey($username$pref_name$value);
  564.     $prefs_cache[$pref_name$value;
  565.     assert_options(ASSERT_ACTIVE1);
  566.     assert_options(ASSERT_BAIL1);
  567.     assert ('$value == $prefs_cache[$pref_name]');
  568.     sqsession_register($prefs_cache 'prefs_cache');
  569.     return;
  570. }
  571.  
  572. /**
  573.  * This checks if the prefs are available
  574.  * @ignore
  575.  */
  576. function checkForPrefs($data_dir$username{
  577.     $db new dbPrefs;
  578.     if(isset($db->error)) {
  579.         $db->failQuery();
  580.     }
  581. }
  582.  
  583. /**
  584.  * Writes the Signature
  585.  * @ignore
  586.  */
  587. function setSig($data_dir$username$number$value{
  588.     if ($number == "g"{
  589.         $key '___signature___';
  590.     else {
  591.         $key sprintf('___sig%s___'$number);
  592.     }
  593.     setPref($data_dir$username$key$value);
  594.     return;
  595. }
  596.  
  597. /**
  598.  * Gets the signature
  599.  * @ignore
  600.  */
  601. function getSig($data_dir$username$number{
  602.     if ($number == "g"{
  603.         $key '___signature___';
  604.     else {
  605.         $key sprintf('___sig%d___'$number);
  606.     }
  607.     return getPref($data_dir$username$key);
  608. }

Documentation generated on Sun, 26 Oct 2014 04:17:39 +0100 by phpDocumentor 1.4.3