Source for file abook_database.php

Documentation is available at abook_database.php

  1. <?php
  2.  
  3. /**
  4.  * abook_database.php
  5.  *
  6.  * @copyright &copy; 1999-2006 The SquirrelMail Project Team
  7.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  8.  * @version $Id: abook_database.php,v 1.15.2.17 2006/10/07 11:58:42 tokul Exp $
  9.  * @package squirrelmail
  10.  * @subpackage addressbook
  11.  */
  12.  
  13. /** Needs the DB functions */
  14. if (!include_once('DB.php')) {
  15.     // same error also in db_prefs.php
  16.         require_once(SM_PATH 'functions/display_messages.php');
  17.     $error  _("Could not include PEAR database functions required for the database backend.""<br />\n";
  18.     $error .= sprintf(_("Is PEAR installed, and is the include path set correctly to find %s?"),
  19.                         '<tt>DB.php</tt>'"<br />\n";
  20.     $error .= _("Please contact your system administrator and report this error.");
  21.     error_box($error$color);
  22.     exit;
  23. }
  24.  
  25. /**
  26.  * Address book in a database backend
  27.  *
  28.  * Backend for personal/shared address book stored in a database,
  29.  * accessed using the DB-classes in PEAR.
  30.  *
  31.  * IMPORTANT:  The PEAR modules must be in the include path
  32.  * for this class to work.
  33.  *
  34.  * An array with the following elements must be passed to
  35.  * the class constructor (elements marked ? are optional):
  36.  * <pre>
  37.  *   dsn       => database DNS (see PEAR for syntax)
  38.  *   table     => table to store addresses in (must exist)
  39.  *   owner     => current user (owner of address data)
  40.  * ? name      => name of address book
  41.  * ? writeable => set writeable flag (true/false)
  42.  * ? listing   => enable/disable listing
  43.  * </pre>
  44.  * The table used should have the following columns:
  45.  * owner, nickname, firstname, lastname, email, label
  46.  * The pair (owner,nickname) should be unique (primary key).
  47.  *
  48.  *  NOTE. This class should not be used directly. Use the
  49.  *        "AddressBook" class instead.
  50.  * @package squirrelmail
  51.  * @subpackage addressbook
  52.  */
  53.     /**
  54.      * Backend type
  55.      * @var string 
  56.      */
  57.     var $btype = 'local';
  58.     /**
  59.      * Backend name
  60.      * @var string 
  61.      */
  62.     var $bname = 'database';
  63.  
  64.     /**
  65.      * Data Source Name (connection description)
  66.      * @var string 
  67.      */
  68.     var $dsn       = '';
  69.     /**
  70.      * Table that stores addresses
  71.      * @var string 
  72.      */
  73.     var $table     = '';
  74.     /**
  75.      * Owner name
  76.      *
  77.      * Limits list of database entries visible to end user
  78.      * @var string 
  79.      */
  80.     var $owner     = '';
  81.     /**
  82.      * Database Handle
  83.      * @var resource 
  84.      */
  85.     var $dbh       = false;
  86.     /**
  87.      * Enable/disable writing into address book
  88.      * @var bool 
  89.      */
  90.     var $writeable = true;
  91.     /**
  92.      * Enable/disable address book listing
  93.      * @var bool 
  94.      */
  95.     var $listing = true;
  96.  
  97.     /* ========================== Private ======================= */
  98.  
  99.     /**
  100.      * Constructor
  101.      * @param array $param address book backend options
  102.      */
  103.     function abook_database($param{
  104.         $this->sname = _("Personal address book");
  105.  
  106.         if (is_array($param)) {
  107.             if (empty($param['dsn']||
  108.                 empty($param['table']||
  109.                 empty($param['owner'])) {
  110.                 return $this->set_error('Invalid parameters');
  111.             }
  112.  
  113.             $this->dsn   = $param['dsn'];
  114.             $this->table = $param['table'];
  115.             $this->owner = $param['owner'];
  116.  
  117.             if (!empty($param['name'])) {
  118.                $this->sname = $param['name'];
  119.             }
  120.  
  121.             if (isset($param['writeable'])) {
  122.                $this->writeable = $param['writeable'];
  123.             }
  124.  
  125.             if (isset($param['listing'])) {
  126.                $this->listing = $param['listing'];
  127.             }
  128.  
  129.             $this->open(true);
  130.         }
  131.         else {
  132.             return $this->set_error('Invalid argument to constructor');
  133.         }
  134.     }
  135.  
  136.  
  137.     /**
  138.      * Open the database.
  139.      * @param bool $new new connection if it is true
  140.      * @return bool 
  141.      */
  142.     function open($new false{
  143.         $this->error = '';
  144.  
  145.         /* Return true is file is open and $new is unset */
  146.         if ($this->dbh && !$new{
  147.             return true;
  148.         }
  149.  
  150.         /* Close old file, if any */
  151.         if ($this->dbh{
  152.             $this->close();
  153.         }
  154.  
  155.         $dbh DB::connect($this->dsntrue);
  156.  
  157.         if (DB::isError($dbh)) {
  158.             return $this->set_error(sprintf(_("Database error: %s"),
  159.                                             DB::errorMessage($dbh)));
  160.         }
  161.  
  162.         $this->dbh = $dbh;
  163.  
  164.         /**
  165.          * field names are lowercased.
  166.          * We use unquoted identifiers and they use upper case in Oracle
  167.          */
  168.         $this->dbh->setOption('portability'DB_PORTABILITY_LOWERCASE);
  169.  
  170.         return true;
  171.     }
  172.  
  173.     /**
  174.      * Close the file and forget the filehandle
  175.      */
  176.     function close({
  177.         $this->dbh->disconnect();
  178.         $this->dbh = false;
  179.     }
  180.  
  181.     /* ========================== Public ======================== */
  182.  
  183.     /**
  184.      * Search the database
  185.      * @param string $expr search expression
  186.      * @return array search results
  187.      */
  188.     function search($expr{
  189.         $ret array();
  190.         if(!$this->open()) {
  191.             return false;
  192.         }
  193.  
  194.         /* To be replaced by advanded search expression parsing */
  195.         if (is_array($expr)) {
  196.             return;
  197.         }
  198.  
  199.         // don't allow wide search when listing is disabled.
  200.         if ($expr=='*' && $this->listing{
  201.             return array();
  202.         }
  203.  
  204.         /* lowercase expression in order to make it case insensitive */
  205.         $expr strtolower($expr);
  206.  
  207.         /* escape SQL wildcards */
  208.         $expr str_replace('_''\\_'$expr);
  209.         $expr str_replace('%''\\%'$expr);
  210.  
  211.         /* Convert wildcards to SQL syntax  */
  212.         $expr str_replace('?''_'$expr);
  213.         $expr str_replace('*''%'$expr);
  214.         $expr $this->dbh->quoteString($expr);
  215.         $expr "%$expr%";
  216.  
  217.         /* create escape expression */
  218.         $escape 'ESCAPE \'' $this->dbh->quoteString('\\''\'';
  219.  
  220.         $query sprintf("SELECT * FROM %s WHERE owner='%s' AND " .
  221.                          "(LOWER(firstname) LIKE '%s' %s OR LOWER(lastname) LIKE '%s' %s)",
  222.                          $this->table$this->owner$expr$escape$expr$escape);
  223.         $res $this->dbh->query($query);
  224.  
  225.         if (DB::isError($res)) {
  226.             return $this->set_error(sprintf(_("Database error: %s"),
  227.                                             DB::errorMessage($res)));
  228.         }
  229.  
  230.         while ($row $res->fetchRow(DB_FETCHMODE_ASSOC)) {
  231.             array_push($retarray('nickname'  => $row['nickname'],
  232.                                    'name'      => "$row[firstname] $row[lastname]",
  233.                                    'firstname' => $row['firstname'],
  234.                                    'lastname'  => $row['lastname'],
  235.                                    'email'     => $row['email'],
  236.                                    'label'     => $row['label'],
  237.                                    'backend'   => $this->bnum,
  238.                                    'source'    => &$this->sname));
  239.         }
  240.         return $ret;
  241.     }
  242.  
  243.     /**
  244.      * Lookup alias
  245.      * @param string $alias alias
  246.      * @return array search results
  247.      */
  248.     function lookup($alias{
  249.         if (empty($alias)) {
  250.             return array();
  251.         }
  252.  
  253.         $alias strtolower($alias);
  254.  
  255.         if (!$this->open()) {
  256.             return false;
  257.         }
  258.  
  259.         $query sprintf("SELECT * FROM %s WHERE owner='%s' AND LOWER(nickname)='%s'",
  260.                          $this->table$this->owner$this->dbh->quoteString($alias));
  261.  
  262.         $res $this->dbh->query($query);
  263.  
  264.         if (DB::isError($res)) {
  265.             return $this->set_error(sprintf(_("Database error: %s"),
  266.                                             DB::errorMessage($res)));
  267.         }
  268.  
  269.         if ($row $res->fetchRow(DB_FETCHMODE_ASSOC)) {
  270.             return array('nickname'  => $row['nickname'],
  271.                          'name'      => "$row[firstname] $row[lastname]",
  272.                          'firstname' => $row['firstname'],
  273.                          'lastname'  => $row['lastname'],
  274.                          'email'     => $row['email'],
  275.                          'label'     => $row['label'],
  276.                          'backend'   => $this->bnum,
  277.                          'source'    => &$this->sname);
  278.         }
  279.         return array();
  280.     }
  281.  
  282.     /**
  283.      * List all addresses
  284.      * @return array search results
  285.      */
  286.     function list_addr({
  287.         $ret array();
  288.         if (!$this->open()) {
  289.             return false;
  290.         }
  291.  
  292.         if(isset($this->listing&& !$this->listing{
  293.             return array();
  294.         }
  295.  
  296.  
  297.         $query sprintf("SELECT * FROM %s WHERE owner='%s'",
  298.                          $this->table$this->owner);
  299.  
  300.         $res $this->dbh->query($query);
  301.  
  302.         if (DB::isError($res)) {
  303.             return $this->set_error(sprintf(_("Database error: %s"),
  304.                                             DB::errorMessage($res)));
  305.         }
  306.  
  307.         while ($row $res->fetchRow(DB_FETCHMODE_ASSOC)) {
  308.             array_push($retarray('nickname'  => $row['nickname'],
  309.                                    'name'      => "$row[firstname] $row[lastname]",
  310.                                    'firstname' => $row['firstname'],
  311.                                    'lastname'  => $row['lastname'],
  312.                                    'email'     => $row['email'],
  313.                                    'label'     => $row['label'],
  314.                                    'backend'   => $this->bnum,
  315.                                    'source'    => &$this->sname));
  316.         }
  317.         return $ret;
  318.     }
  319.  
  320.     /**
  321.      * Add address
  322.      * @param array $userdata added data
  323.      * @return bool 
  324.      */
  325.     function add($userdata{
  326.         if (!$this->writeable{
  327.             return $this->set_error(_("Address book is read-only"));
  328.         }
  329.  
  330.         if (!$this->open()) {
  331.             return false;
  332.         }
  333.  
  334.         /* See if user exist already */
  335.         $ret $this->lookup($userdata['nickname']);
  336.         if (!empty($ret)) {
  337.             return $this->set_error(sprintf(_("User \"%s\" already exists")$ret['nickname']));
  338.         }
  339.  
  340.         /* Create query */
  341.         $query sprintf("INSERT INTO %s (owner, nickname, firstname, " .
  342.                          "lastname, email, label) VALUES('%s','%s','%s'," .
  343.                          "'%s','%s','%s')",
  344.                          $this->table$this->owner,
  345.                          $this->dbh->quoteString($userdata['nickname']),
  346.                          $this->dbh->quoteString($userdata['firstname']),
  347.                          $this->dbh->quoteString((!empty($userdata['lastname'])?$userdata['lastname']:'')),
  348.                          $this->dbh->quoteString($userdata['email']),
  349.                          $this->dbh->quoteString((!empty($userdata['label'])?$userdata['label']:'')) );
  350.  
  351.          /* Do the insert */
  352.          $r $this->dbh->simpleQuery($query);
  353.  
  354.          /* Check for errors */
  355.          if (DB::isError($r)) {
  356.              return $this->set_error(sprintf(_("Database error: %s"),
  357.                                              DB::errorMessage($r)));
  358.          }
  359.  
  360.          return true;
  361.     }
  362.  
  363.     /**
  364.      * Delete address
  365.      * @param string $alias alias that has to be deleted
  366.      * @return bool 
  367.      */
  368.     function remove($alias{
  369.         if (!$this->writeable{
  370.             return $this->set_error(_("Address book is read-only"));
  371.         }
  372.  
  373.         if (!$this->open()) {
  374.             return false;
  375.         }
  376.  
  377.         /* Create query */
  378.         $query sprintf("DELETE FROM %s WHERE owner='%s' AND (",
  379.                          $this->table$this->owner);
  380.  
  381.         $sepstr '';
  382.         while (list($undef$nicknameeach($alias)) {
  383.             $query .= sprintf("%s nickname='%s' "$sepstr,
  384.                               $this->dbh->quoteString($nickname));
  385.             $sepstr 'OR';
  386.         }
  387.         $query .= ')';
  388.  
  389.         /* Delete entry */
  390.         $r $this->dbh->simpleQuery($query);
  391.  
  392.         /* Check for errors */
  393.         if (DB::isError($r)) {
  394.             return $this->set_error(sprintf(_("Database error: %s"),
  395.                                             DB::errorMessage($r)));
  396.         }
  397.         return true;
  398.     }
  399.  
  400.     /**
  401.      * Modify address
  402.      * @param string $alias modified alias
  403.      * @param array $userdata new data
  404.      * @return bool 
  405.      */
  406.     function modify($alias$userdata{
  407.         if (!$this->writeable{
  408.             return $this->set_error(_("Address book is read-only"));
  409.         }
  410.  
  411.         if (!$this->open()) {
  412.             return false;
  413.         }
  414.  
  415.          /* See if user exist */
  416.         $ret $this->lookup($alias);
  417.         if (empty($ret)) {
  418.             return $this->set_error(sprintf(_("User \"%s\" does not exist")$alias));
  419.         }
  420.  
  421.         /* make sure that new nickname is not used */
  422.         if (strtolower($alias!= strtolower($userdata['nickname'])) {
  423.             /* same check as in add() */
  424.             $ret $this->lookup($userdata['nickname']);
  425.             if (!empty($ret)) {
  426.                 $error sprintf(_("User '%s' already exist.")$ret['nickname']);
  427.                 return $this->set_error($error);
  428.             }
  429.         }
  430.  
  431.         /* Create query */
  432.         $query sprintf("UPDATE %s SET nickname='%s', firstname='%s', ".
  433.                          "lastname='%s', email='%s', label='%s' ".
  434.                          "WHERE owner='%s' AND nickname='%s'",
  435.                          $this->table,
  436.                          $this->dbh->quoteString($userdata['nickname']),
  437.                          $this->dbh->quoteString($userdata['firstname']),
  438.                          $this->dbh->quoteString((!empty($userdata['lastname'])?$userdata['lastname']:'')),
  439.                          $this->dbh->quoteString($userdata['email']),
  440.                          $this->dbh->quoteString((!empty($userdata['label'])?$userdata['label']:'')),
  441.                          $this->owner,
  442.                          $this->dbh->quoteString($alias) );
  443.  
  444.         /* Do the insert */
  445.         $r $this->dbh->simpleQuery($query);
  446.  
  447.         /* Check for errors */
  448.         if (DB::isError($r)) {
  449.             return $this->set_error(sprintf(_("Database error: %s"),
  450.                                             DB::errorMessage($r)));
  451.         }
  452.         return true;
  453.     }
  454. /* End of class abook_database */
  455.  
  456. // vim: et ts=4

Documentation generated on Sat, 07 Oct 2006 16:29:33 +0300 by phpDocumentor 1.3.0RC6