Source for file abook_database.php

Documentation is available at abook_database.php

  1. <?php
  2.  
  3. /**
  4.  * abook_database.php
  5.  *
  6.  * Supported database schema
  7.  * <pre>
  8.  *  owner varchar(128) NOT NULL
  9.  *  nickname varchar(16) NOT NULL
  10.  *  firstname varchar(128)
  11.  *  lastname varchar(128)
  12.  *  email varchar(128) NOT NULL
  13.  *  label varchar(255)
  14.  *  PRIMARY KEY (owner,nickname)
  15.  * </pre>
  16.  *
  17.  * @copyright 1999-2016 The SquirrelMail Project Team
  18.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  19.  * @version $Id: abook_database.php 14601 2016-10-29 21:52:49Z pdontthink $
  20.  * @package squirrelmail
  21.  * @subpackage addressbook
  22.  */
  23.  
  24. /**
  25.  * Needs either PDO or the DB functions
  26.  * Don't display errors here. Error will be set in class constructor function.
  27.  */
  28. global $use_pdo$disable_pdo;
  29. if (empty($disable_pdo&& class_exists('PDO'))
  30.     $use_pdo TRUE;
  31. else
  32.     $use_pdo FALSE;
  33.  
  34. if (!$use_pdo)
  35.     @include_once('DB.php');
  36.  
  37. /**
  38.  * Address book in a database backend
  39.  *
  40.  * Backend for personal/shared address book stored in a database,
  41.  * accessed using the DB-classes in PEAR or PDO, the latter taking
  42.  * precedence if available..
  43.  *
  44.  * IMPORTANT:  If PDO is not available (it should be installed by
  45.  *             default since PHP 5.1), then the PEAR modules must
  46.  *             be in the include path for this class to work.
  47.  *
  48.  * An array with the following elements must be passed to
  49.  * the class constructor (elements marked ? are optional):
  50.  * <pre>
  51.  *   dsn       => database DNS (see PEAR for syntax, but more or
  52.  *                less it is:  mysql://user:pass@hostname/dbname)
  53.  *   table     => table to store addresses in (must exist)
  54.  *   owner     => current user (owner of address data)
  55.  * ? name      => name of address book
  56.  * ? writeable => set writeable flag (true/false)
  57.  * ? listing   => enable/disable listing
  58.  * </pre>
  59.  * The table used should have the following columns:
  60.  * owner, nickname, firstname, lastname, email, label
  61.  * The pair (owner,nickname) should be unique (primary key).
  62.  *
  63.  *  NOTE. This class should not be used directly. Use the
  64.  *        "AddressBook" class instead.
  65.  *
  66.  * Three settings that control PDO behavior can be specified in
  67.  * config/config_local.php if needed:
  68.  *    boolean $disable_pdo SquirrelMail uses PDO by default to access the
  69.  *                         user preferences and address book databases, but
  70.  *                         setting this to TRUE will cause SquirrelMail to
  71.  *                         fall back to using Pear DB instead.
  72.  *    boolean $pdo_show_sql_errors When database errors are encountered,
  73.  *                                 setting this to TRUE causes the actual
  74.  *                                 database error to be displayed, otherwise
  75.  *                                 generic errors are displayed, preventing
  76.  *                                 internal database information from being
  77.  *                                 exposed. This should be enabled only for
  78.  *                                 debugging purposes.
  79.  *    string $pdo_identifier_quote_char By default, SquirrelMail will quote
  80.  *                                      table and field names in database
  81.  *                                      queries with what it thinks is the
  82.  *                                      appropriate quote character for the
  83.  *                                      database type being used (backtick
  84.  *                                      for MySQL (and thus MariaDB), double
  85.  *                                      quotes for all others), but you can
  86.  *                                      override the character used by
  87.  *                                      putting it here, or tell SquirrelMail
  88.  *                                      NOT to quote identifiers by setting
  89.  *                                      this to "none"
  90.  *
  91.  * @package squirrelmail
  92.  * @subpackage addressbook
  93.  */
  94.     /**
  95.      * Backend type
  96.      * @var string 
  97.      */
  98.     var $btype = 'local';
  99.     /**
  100.      * Backend name
  101.      * @var string 
  102.      */
  103.     var $bname = 'database';
  104.  
  105.     /**
  106.      * Data Source Name (connection description)
  107.      * @var string 
  108.      */
  109.     var $dsn       = '';
  110.  
  111.     /**
  112.      * Character used to quote database table
  113.      * and field names
  114.      * @var string 
  115.      */
  116.     var $identifier_quote_char = '';
  117.  
  118.     /**
  119.      * Table that stores addresses
  120.      * @var string 
  121.      */
  122.     var $table     = '';
  123.     /**
  124.      * Owner name
  125.      *
  126.      * Limits list of database entries visible to end user
  127.      * @var string 
  128.      */
  129.     var $owner     = '';
  130.     /**
  131.      * Database Handle
  132.      * @var resource 
  133.      */
  134.     var $dbh       = false;
  135.     /**
  136.      * Enable/disable writing into address book
  137.      * @var bool 
  138.      */
  139.     var $writeable = true;
  140.     /**
  141.      * Enable/disable address book listing
  142.      * @var bool 
  143.      */
  144.     var $listing = true;
  145.  
  146.     /* ========================== Private ======================= */
  147.  
  148.     /**
  149.      * Constructor
  150.      * @param array $param address book backend options
  151.      */
  152.     function abook_database($param{
  153.         $this->sname = _("Personal Address Book");
  154.  
  155.         /* test if PDO or Pear DB classes are available and freak out if necessary */
  156.         global $use_pdo;
  157.         if (!$use_pdo && !class_exists('DB')) {
  158.             // same error also in db_prefs.php
  159.             $error  _("Could not find or include PHP PDO or PEAR database functions required for the database backend.""\n";
  160.             $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";
  161.             $error .= _("Please contact your system administrator and report this error.");
  162.             return $this->set_error($error);
  163.         }
  164.  
  165.         if (is_array($param)) {
  166.             if (empty($param['dsn']||
  167.                 empty($param['table']||
  168.                 empty($param['owner'])) {
  169.                 return $this->set_error('Invalid parameters');
  170.             }
  171.  
  172.             $this->dsn   = $param['dsn'];
  173.             $this->table = $param['table'];
  174.             $this->owner = $param['owner'];
  175.  
  176.             if (!empty($param['name'])) {
  177.                $this->sname = $param['name'];
  178.             }
  179.  
  180.             if (isset($param['writeable'])) {
  181.                $this->writeable = $param['writeable'];
  182.             }
  183.  
  184.             if (isset($param['listing'])) {
  185.                $this->listing = $param['listing'];
  186.             }
  187.  
  188.             // figure out identifier quoting (only used for PDO, though we could change that)
  189.             global $pdo_identifier_quote_char;
  190.             if (empty($pdo_identifier_quote_char)) {
  191.                 if (strpos($this->dsn'mysql'=== 0)
  192.                     $this->identifier_quote_char = '`';
  193.                 else
  194.                     $this->identifier_quote_char = '"';
  195.             else if ($pdo_identifier_quote_char === 'none')
  196.                 $this->identifier_quote_char = '';
  197.             else
  198.                 $this->identifier_quote_char = $pdo_identifier_quote_char;
  199.  
  200.  
  201.             $this->open(true);
  202.         }
  203.         else {
  204.             return $this->set_error('Invalid argument to constructor');
  205.         }
  206.     }
  207.  
  208.  
  209.     /**
  210.      * Open the database.
  211.      * @param bool $new new connection if it is true
  212.      * @return bool 
  213.      */
  214.     function open($new false{
  215.         global $use_pdo;
  216.         $this->error = '';
  217.  
  218.         /* Return true is file is open and $new is unset */
  219.         if ($this->dbh && !$new{
  220.             return true;
  221.         }
  222.  
  223.         /* Close old file, if any */
  224.         if ($this->dbh{
  225.             $this->close();
  226.         }
  227.  
  228.         if ($use_pdo{
  229.             // parse and convert DSN to PDO style
  230.             // Pear's full DSN syntax is one of the following:
  231.             //    phptype(dbsyntax)://username:password@protocol+hostspec/database?option=value
  232.             //    phptype(syntax)://user:pass@protocol(proto_opts)/database
  233.             //
  234.             // $matches will contain:
  235.             // 1: database type
  236.             // 2: username
  237.             // 3: password
  238.             // 4: hostname (and possible port number) OR protocol (and possible protocol options)
  239.             // 5: database name (and possible options)
  240.             // 6: port number (moved from match number 4)
  241.             // 7: options (moved from match number 5)
  242.             // 8: protocol (instead of hostname)
  243.             // 9: protocol options (moved from match number 4/8)
  244. //TODO: do we care about supporting cases where no password is given? (this is a legal DSN, but causes an error below)
  245.             if (!preg_match('|^(.+)://(.+):(.+)@(.+)/(.+)$|i'$this->dsn$matches)) {
  246.                 return $this->set_error(_("Could not parse prefs DSN"));
  247.             }
  248.             $matches[6NULL;
  249.             $matches[7NULL;
  250.             $matches[8NULL;
  251.             $matches[9NULL;
  252.             if (preg_match('|^(.+):(\d+)$|'$matches[4]$host_port_matches)) {
  253.                 $matches[4$host_port_matches[1];
  254.                 $matches[6$host_port_matches[2];
  255.             }
  256.             if (preg_match('|^(.+?)\((.+)\)$|'$matches[4]$protocol_matches)) {
  257.                 $matches[8$protocol_matches[1];
  258.                 $matches[9$protocol_matches[2];
  259.                 $matches[4NULL;
  260.                 $matches[6NULL;
  261.             }
  262. //TODO: currently we just ignore options specified on the end of the DSN
  263.             if (preg_match('|^(.+?)\?(.+)$|'$matches[5]$database_name_options_matches)) {
  264.                 $matches[5$database_name_options_matches[1];
  265.                 $matches[7$database_name_options_matches[2];
  266.             }
  267.             if ($matches[8=== 'unix' && !empty($matches[9]))
  268.                 $pdo_prefs_dsn $matches[1':unix_socket=' $matches[9';dbname=' $matches[5];
  269.             else
  270.                 $pdo_prefs_dsn $matches[1':host=' $matches[4(!empty($matches[6]';port=' $matches[6''';dbname=' $matches[5];
  271.             try {
  272.                 $dbh new PDO($pdo_prefs_dsn$matches[2]$matches[3]);
  273.             catch (Exception $e{
  274.                 return $this->set_error(sprintf(_("Database error: %s")$e->getMessage()));
  275.             }
  276.  
  277.             $dbh->setAttribute(PDO::ATTR_CASEPDO::CASE_LOWER);
  278.  
  279.         else {
  280.             $dbh DB::connect($this->dsntrue);
  281.  
  282.             if (DB::isError($dbh)) {
  283.                 return $this->set_error(sprintf(_("Database error: %s"),
  284.                                                 DB::errorMessage($dbh)));
  285.             }
  286.  
  287.             /**
  288.              * field names are lowercased.
  289.              * We use unquoted identifiers and they use upper case in Oracle
  290.              */
  291.             $dbh->setOption('portability'DB_PORTABILITY_LOWERCASE);
  292.         }
  293.  
  294.         $this->dbh = $dbh;
  295.         return true;
  296.     }
  297.  
  298.     /**
  299.      * Close the file and forget the filehandle
  300.      */
  301.     function close({
  302.         global $use_pdo;
  303.         if ($use_pdo{
  304.             $this->dbh = NULL;
  305.         else {
  306.             $this->dbh->disconnect();
  307.             $this->dbh = false;
  308.         }
  309.     }
  310.  
  311.     /**
  312.      * Determine internal database field name given one of
  313.      * the SquirrelMail SM_ABOOK_FIELD_* constants
  314.      *
  315.      * @param integer $field The SM_ABOOK_FIELD_* contant to look up
  316.      *
  317.      * @return string The desired field name, or the string "ERROR"
  318.      *                 if the $field is not understood (the caller
  319.      *                 is responsible for handing errors)
  320.      *
  321.      */
  322.     function get_field_name($field{
  323.         switch ($field{
  324.             case SM_ABOOK_FIELD_NICKNAME:
  325.                 return 'nickname';
  326.             case SM_ABOOK_FIELD_FIRSTNAME:
  327.                 return 'firstname';
  328.             case SM_ABOOK_FIELD_LASTNAME:
  329.                 return 'lastname';
  330.             case SM_ABOOK_FIELD_EMAIL:
  331.                 return 'email';
  332.             case SM_ABOOK_FIELD_LABEL:
  333.                 return 'label';
  334.             default:
  335.                 return 'ERROR';
  336.         }
  337.     }
  338.  
  339.     /* ========================== Public ======================== */
  340.  
  341.     /**
  342.      * Search the database
  343.      *
  344.      * Backend supports only * and ? wildcards. Complex eregs are not supported.
  345.      * Search is case insensitive.
  346.      * @param string $expr search expression
  347.      * @return array search results. boolean false on error
  348.      */
  349.     function search($expr{
  350.         $ret array();
  351.         if(!$this->open()) {
  352.             return false;
  353.         }
  354.  
  355.         /* To be replaced by advanded search expression parsing */
  356.         if (is_array($expr)) {
  357.             return;
  358.         }
  359.  
  360.         // don't allow wide search when listing is disabled.
  361.         if ($expr=='*' && $this->listing)
  362.             return array();
  363.  
  364.         /* lowercase expression in order to make it case insensitive */
  365.         $expr strtolower($expr);
  366.  
  367.         /* escape SQL wildcards */
  368.         $expr str_replace('_''\\_'$expr);
  369.         $expr str_replace('%''\\%'$expr);
  370.  
  371.         /* Convert wildcards to SQL syntax  */
  372.         $expr str_replace('?''_'$expr);
  373.         $expr str_replace('*''%'$expr);
  374.  
  375.         $expr "%$expr%";
  376.  
  377.         global $use_pdo$pdo_show_sql_errors;
  378.         if ($use_pdo{
  379.             if (!($sth $this->dbh->prepare('SELECT * FROM ' $this->identifier_quote_char . $this->table . $this->identifier_quote_char . ' WHERE ' $this->identifier_quote_char . 'owner' $this->identifier_quote_char . ' = ? AND (LOWER(' $this->identifier_quote_char . 'firstname' $this->identifier_quote_char . ') LIKE ? ESCAPE ? OR LOWER(' $this->identifier_quote_char . 'lastname' $this->identifier_quote_char . ') LIKE ? ESCAPE ? OR LOWER(' $this->identifier_quote_char . 'email' $this->identifier_quote_char . ') LIKE ? ESCAPE ? OR LOWER(' $this->identifier_quote_char . 'nickname' $this->identifier_quote_char . ') LIKE ? ESCAPE ?)'))) {
  380.                 if ($pdo_show_sql_errors)
  381.                     return $this->set_error(sprintf(_("Database error: %s")implode(' - '$this->dbh->errorInfo())));
  382.                 else
  383.                     return $this->set_error(sprintf(_("Database error: %s")_("Could not prepare query")));
  384.             }
  385.             if (!($res $sth->execute(array($this->owner$expr'\\'$expr'\\'$expr'\\'$expr'\\')))) {
  386.                 if ($pdo_show_sql_errors)
  387.                     return $this->set_error(sprintf(_("Database error: %s")implode(' - '$sth->errorInfo())));
  388.                 else
  389.                     return $this->set_error(sprintf(_("Database error: %s")_("Could not execute query")));
  390.             }
  391.  
  392.             while ($row $sth->fetch(PDO::FETCH_ASSOC)) {
  393.                 array_push($retarray('nickname'  => $row['nickname'],
  394.                                        'name'      => $this->fullname($row['firstname']$row['lastname']),
  395.                                        'firstname' => $row['firstname'],
  396.                                        'lastname'  => $row['lastname'],
  397.                                        'email'     => $row['email'],
  398.                                        'label'     => $row['label'],
  399.                                        'backend'   => $this->bnum,
  400.                                        'source'    => &$this->sname));
  401.             }
  402.  
  403.         else {
  404.             $expr $this->dbh->quoteString($expr);
  405.  
  406.             /* create escape expression */
  407.             $escape 'ESCAPE \'' $this->dbh->quoteString('\\''\'';
  408.  
  409.             $query sprintf("SELECT * FROM %s WHERE owner='%s' AND " .
  410.                              "(LOWER(firstname) LIKE '%s' %s " .
  411.                              "OR LOWER(lastname) LIKE '%s' %s " .
  412.                              "OR LOWER(email) LIKE '%s' %s " .
  413.                              "OR LOWER(nickname) LIKE '%s' %s)",
  414.                              $this->table$this->owner$expr$escape$expr$escape,
  415.                                                          $expr$escape$expr$escape);
  416.             $res $this->dbh->query($query);
  417.  
  418.             if (DB::isError($res)) {
  419.                 return $this->set_error(sprintf(_("Database error: %s"),
  420.                                                 DB::errorMessage($res)));
  421.             }
  422.  
  423.             while ($row $res->fetchRow(DB_FETCHMODE_ASSOC)) {
  424.                 array_push($retarray('nickname'  => $row['nickname'],
  425.                                        'name'      => $this->fullname($row['firstname']$row['lastname']),
  426.                                        'firstname' => $row['firstname'],
  427.                                        'lastname'  => $row['lastname'],
  428.                                        'email'     => $row['email'],
  429.                                        'label'     => $row['label'],
  430.                                        'backend'   => $this->bnum,
  431.                                        'source'    => &$this->sname));
  432.             }
  433.         }
  434.         return $ret;
  435.     }
  436.  
  437.     /**
  438.      * Lookup an address by the indicated field.
  439.      *
  440.      * @param string  $value The value to look up
  441.      * @param integer $field The field to look in, should be one
  442.      *                        of the SM_ABOOK_FIELD_* constants
  443.      *                        defined in include/constants.php
  444.      *                        (OPTIONAL; defaults to nickname field)
  445.      *                        NOTE: uniqueness is only guaranteed
  446.      *                        when the nickname field is used here;
  447.      *                        otherwise, the first matching address
  448.      *                        is returned.
  449.      *
  450.      * @return array Array with lookup results when the value
  451.      *                was found, an empty array if the value was
  452.      *                not found.
  453.      *
  454.      */
  455.     function lookup($value$field=SM_ABOOK_FIELD_NICKNAME{
  456.         if (empty($value)) {
  457.             return array();
  458.         }
  459.  
  460.         $value strtolower($value);
  461.  
  462.         if (!$this->open()) {
  463.             return false;
  464.         }
  465.  
  466.         $db_field $this->get_field_name($field);
  467.         if ($db_field == 'ERROR'{
  468.             return $this->set_error(sprintf(_("Unknown field name: %s")$field));
  469.         }
  470.  
  471.         global $use_pdo$pdo_show_sql_errors;
  472.         if ($use_pdo{
  473.             if (!($sth $this->dbh->prepare('SELECT * FROM ' $this->identifier_quote_char . $this->table . $this->identifier_quote_char . ' WHERE ' $this->identifier_quote_char . 'owner' $this->identifier_quote_char . ' = ? AND LOWER(' $this->identifier_quote_char . $db_field $this->identifier_quote_char . ') = ?'))) {
  474.                 if ($pdo_show_sql_errors)
  475.                     return $this->set_error(sprintf(_("Database error: %s")implode(' - '$this->dbh->errorInfo())));
  476.                 else
  477.                     return $this->set_error(sprintf(_("Database error: %s")_("Could not prepare query")));
  478.             }
  479.             if (!($res $sth->execute(array($this->owner$value)))) {
  480.                 if ($pdo_show_sql_errors)
  481.                     return $this->set_error(sprintf(_("Database error: %s")implode(' - '$sth->errorInfo())));
  482.                 else
  483.                     return $this->set_error(sprintf(_("Database error: %s")_("Could not execute query")));
  484.             }
  485.  
  486.             if ($row $sth->fetch(PDO::FETCH_ASSOC)) {
  487.                 return array('nickname'  => $row['nickname'],
  488.                              'name'      => $this->fullname($row['firstname']$row['lastname']),
  489.                              'firstname' => $row['firstname'],
  490.                              'lastname'  => $row['lastname'],
  491.                              'email'     => $row['email'],
  492.                              'label'     => $row['label'],
  493.                              'backend'   => $this->bnum,
  494.                              'source'    => &$this->sname);
  495.             }
  496.  
  497.         else {
  498.             $query sprintf("SELECT * FROM %s WHERE owner = '%s' AND LOWER(%s) = '%s'",
  499.                              $this->table$this->owner$db_field
  500.                              $this->dbh->quoteString($value));
  501.  
  502.             $res $this->dbh->query($query);
  503.  
  504.             if (DB::isError($res)) {
  505.                 return $this->set_error(sprintf(_("Database error: %s"),
  506.                                                 DB::errorMessage($res)));
  507.             }
  508.  
  509.             if ($row $res->fetchRow(DB_FETCHMODE_ASSOC)) {
  510.                 return array('nickname'  => $row['nickname'],
  511.                              'name'      => $this->fullname($row['firstname']$row['lastname']),
  512.                              'firstname' => $row['firstname'],
  513.                              'lastname'  => $row['lastname'],
  514.                              'email'     => $row['email'],
  515.                              'label'     => $row['label'],
  516.                              'backend'   => $this->bnum,
  517.                              'source'    => &$this->sname);
  518.             }
  519.         }
  520.  
  521.         return array();
  522.     }
  523.  
  524.     /**
  525.      * List all addresses
  526.      * @return array search results
  527.      */
  528.     function list_addr({
  529.         $ret array();
  530.         if (!$this->open()) {
  531.             return false;
  532.         }
  533.  
  534.         if(isset($this->listing&& !$this->listing{
  535.             return array();
  536.         }
  537.  
  538.  
  539.         global $use_pdo$pdo_show_sql_errors;
  540.         if ($use_pdo{
  541.             if (!($sth $this->dbh->prepare('SELECT * FROM ' $this->identifier_quote_char . $this->table . $this->identifier_quote_char . ' WHERE ' $this->identifier_quote_char . 'owner' $this->identifier_quote_char . ' = ?'))) {
  542.                 if ($pdo_show_sql_errors)
  543.                     return $this->set_error(sprintf(_("Database error: %s")implode(' - '$this->dbh->errorInfo())));
  544.                 else
  545.                     return $this->set_error(sprintf(_("Database error: %s")_("Could not prepare query")));
  546.             }
  547.             if (!($res $sth->execute(array($this->owner)))) {
  548.                 if ($pdo_show_sql_errors)
  549.                     return $this->set_error(sprintf(_("Database error: %s")implode(' - '$sth->errorInfo())));
  550.                 else
  551.                     return $this->set_error(sprintf(_("Database error: %s")_("Could not execute query")));
  552.             }
  553.  
  554.             while ($row $sth->fetch(PDO::FETCH_ASSOC)) {
  555.                 array_push($retarray('nickname'  => $row['nickname'],
  556.                                        'name'      => $this->fullname($row['firstname']$row['lastname']),
  557.                                        'firstname' => $row['firstname'],
  558.                                        'lastname'  => $row['lastname'],
  559.                                        'email'     => $row['email'],
  560.                                        'label'     => $row['label'],
  561.                                        'backend'   => $this->bnum,
  562.                                        'source'    => &$this->sname));
  563.             }
  564.         else {
  565.             $query sprintf("SELECT * FROM %s WHERE owner='%s'",
  566.                              $this->table$this->owner);
  567.  
  568.             $res $this->dbh->query($query);
  569.  
  570.             if (DB::isError($res)) {
  571.                 return $this->set_error(sprintf(_("Database error: %s"),
  572.                                                 DB::errorMessage($res)));
  573.             }
  574.  
  575.             while ($row $res->fetchRow(DB_FETCHMODE_ASSOC)) {
  576.                 array_push($retarray('nickname'  => $row['nickname'],
  577.                                        'name'      => $this->fullname($row['firstname']$row['lastname']),
  578.                                        'firstname' => $row['firstname'],
  579.                                        'lastname'  => $row['lastname'],
  580.                                        'email'     => $row['email'],
  581.                                        'label'     => $row['label'],
  582.                                        'backend'   => $this->bnum,
  583.                                        'source'    => &$this->sname));
  584.             }
  585.         }
  586.  
  587.         return $ret;
  588.     }
  589.  
  590.     /**
  591.      * Add address
  592.      * @param array $userdata added data
  593.      * @return bool 
  594.      */
  595.     function add($userdata{
  596.         if (!$this->writeable{
  597.             return $this->set_error(_("Address book is read-only"));
  598.         }
  599.  
  600.         if (!$this->open()) {
  601.             return false;
  602.         }
  603.  
  604.         // NB: if you want to check for some unwanted characters
  605.         //     or other problems, do so here like this:
  606.         // TODO: Should pull all validation code out into a separate function
  607.         //if (strpos($userdata['nickname'], ' ')) {
  608.         //    return $this->set_error(_("Nickname contains illegal characters"));
  609.         //}
  610.  
  611.         /* See if user exist already */
  612.         $ret $this->lookup($userdata['nickname']);
  613.         if (!empty($ret)) {
  614.             return $this->set_error(sprintf(_("User \"%s\" already exists")$ret['nickname']));
  615.         }
  616.  
  617.         global $use_pdo$pdo_show_sql_errors;
  618.         if ($use_pdo{
  619.             if (!($sth $this->dbh->prepare('INSERT INTO ' $this->identifier_quote_char . $this->table . $this->identifier_quote_char . ' (' $this->identifier_quote_char . 'owner' $this->identifier_quote_char . ', ' $this->identifier_quote_char . 'nickname' $this->identifier_quote_char . ', ' $this->identifier_quote_char . 'firstname' $this->identifier_quote_char . ', ' $this->identifier_quote_char . 'lastname' $this->identifier_quote_char . ', ' $this->identifier_quote_char . 'email' $this->identifier_quote_char . ', ' $this->identifier_quote_char . 'label' $this->identifier_quote_char . ') VALUES (?, ?, ?, ?, ?, ?)'))) {
  620.                 if ($pdo_show_sql_errors)
  621.                     return $this->set_error(sprintf(_("Database error: %s")implode(' - '$this->dbh->errorInfo())));
  622.                 else
  623.                     return $this->set_error(sprintf(_("Database error: %s")_("Could not prepare query")));
  624.             }
  625.             if (!($res $sth->execute(array($this->owner$userdata['nickname']$userdata['firstname'](!empty($userdata['lastname']$userdata['lastname''')$userdata['email'](!empty($userdata['label']$userdata['label'''))))) {
  626.                 if ($pdo_show_sql_errors)
  627.                     return $this->set_error(sprintf(_("Database error: %s")implode(' - '$sth->errorInfo())));
  628.                 else
  629.                     return $this->set_error(sprintf(_("Database error: %s")_("Could not execute query")));
  630.             }
  631.         else {
  632.             /* Create query */
  633.             $query sprintf("INSERT INTO %s (owner, nickname, firstname, " .
  634.                              "lastname, email, label) VALUES('%s','%s','%s'," .
  635.                              "'%s','%s','%s')",
  636.                              $this->table$this->owner,
  637.                              $this->dbh->quoteString($userdata['nickname']),
  638.                              $this->dbh->quoteString($userdata['firstname']),
  639.                              $this->dbh->quoteString((!empty($userdata['lastname'])?$userdata['lastname']:'')),
  640.                              $this->dbh->quoteString($userdata['email']),
  641.                              $this->dbh->quoteString((!empty($userdata['label'])?$userdata['label']:'')) );
  642.  
  643.             /* Do the insert */
  644.             $r $this->dbh->simpleQuery($query);
  645.  
  646.             /* Check for errors */
  647.             if (DB::isError($r)) {
  648.                 return $this->set_error(sprintf(_("Database error: %s"),
  649.                                                 DB::errorMessage($r)));
  650.             }
  651.         }
  652.  
  653.          return true;
  654.     }
  655.  
  656.     /**
  657.      * Deletes address book entries
  658.      * @param array $alias aliases that have to be deleted. numerical
  659.      *   array with nickname values
  660.      * @return bool 
  661.      */
  662.     function remove($alias{
  663.         if (!$this->writeable{
  664.             return $this->set_error(_("Address book is read-only"));
  665.         }
  666.  
  667.         if (!$this->open()) {
  668.             return false;
  669.         }
  670.  
  671.         global $use_pdo$pdo_show_sql_errors;
  672.         if ($use_pdo{
  673.             $sepstr '';
  674.             $where_clause '';
  675.             $where_clause_args array();
  676.             while (list($undef$nicknameeach($alias)) {
  677.                 $where_clause .= $sepstr $this->identifier_quote_char . 'nickname' $this->identifier_quote_char . ' = ?';
  678.                 $where_clause_args[$nickname;
  679.                 $sepstr ' OR ';
  680.             }
  681.             if (!($sth $this->dbh->prepare('DELETE FROM ' $this->identifier_quote_char . $this->table . $this->identifier_quote_char . ' WHERE ' $this->identifier_quote_char . 'owner' $this->identifier_quote_char . ' = ? AND (' $where_clause ')'))) {
  682.                 if ($pdo_show_sql_errors)
  683.                     return $this->set_error(sprintf(_("Database error: %s")implode(' - '$this->dbh->errorInfo())));
  684.                 else
  685.                     return $this->set_error(sprintf(_("Database error: %s")_("Could not prepare query")));
  686.             }
  687.             array_unshift($where_clause_args$this->owner);
  688.             if (!($res $sth->execute($where_clause_args))) {
  689.                 if ($pdo_show_sql_errors)
  690.                     return $this->set_error(sprintf(_("Database error: %s")implode(' - '$sth->errorInfo())));
  691.                 else
  692.                     return $this->set_error(sprintf(_("Database error: %s")_("Could not execute query")));
  693.             }
  694.         else {
  695.             /* Create query */
  696.             $query sprintf("DELETE FROM %s WHERE owner='%s' AND (",
  697.                              $this->table$this->owner);
  698.  
  699.             $sepstr '';
  700.             while (list($undef$nicknameeach($alias)) {
  701.                 $query .= sprintf("%s nickname='%s' "$sepstr,
  702.                                   $this->dbh->quoteString($nickname));
  703.                 $sepstr 'OR';
  704.             }
  705.             $query .= ')';
  706.  
  707.             /* Delete entry */
  708.             $r $this->dbh->simpleQuery($query);
  709.  
  710.             /* Check for errors */
  711.             if (DB::isError($r)) {
  712.                 return $this->set_error(sprintf(_("Database error: %s"),
  713.                                                 DB::errorMessage($r)));
  714.             }
  715.         }
  716.  
  717.         return true;
  718.     }
  719.  
  720.     /**
  721.      * Modify address
  722.      * @param string $alias modified alias
  723.      * @param array $userdata new data
  724.      * @return bool 
  725.      */
  726.     function modify($alias$userdata{
  727.         if (!$this->writeable{
  728.             return $this->set_error(_("Address book is read-only"));
  729.         }
  730.  
  731.         if (!$this->open()) {
  732.             return false;
  733.         }
  734.  
  735.         // NB: if you want to check for some unwanted characters
  736.         //     or other problems, do so here like this:
  737.         // TODO: Should pull all validation code out into a separate function
  738.         //if (strpos($userdata['nickname'], ' ')) {
  739.         //    return $this->set_error(_("Nickname contains illegal characters"));
  740.         //}
  741.  
  742.          /* See if user exist */
  743.         $ret $this->lookup($alias);
  744.         if (empty($ret)) {
  745.             return $this->set_error(sprintf(_("User \"%s\" does not exist"),$alias));
  746.         }
  747.  
  748.         /* make sure that new nickname is not used */
  749.         if (strtolower($alias!= strtolower($userdata['nickname'])) {
  750.             /* same check as in add() */
  751.             $ret $this->lookup($userdata['nickname']);
  752.             if (!empty($ret)) {
  753.                 $error sprintf(_("User '%s' already exist.")$ret['nickname']);
  754.                 return $this->set_error($error);
  755.             }
  756.         }
  757.  
  758.         global $use_pdo$pdo_show_sql_errors;
  759.         if ($use_pdo{
  760.             if (!($sth $this->dbh->prepare('UPDATE ' $this->identifier_quote_char . $this->table . $this->identifier_quote_char . ' SET ' $this->identifier_quote_char . 'nickname' $this->identifier_quote_char . ' = ?, ' $this->identifier_quote_char . 'firstname' $this->identifier_quote_char . ' = ?, ' $this->identifier_quote_char . 'lastname' $this->identifier_quote_char . ' = ?, ' $this->identifier_quote_char . 'email' $this->identifier_quote_char . ' = ?, ' $this->identifier_quote_char . 'label' $this->identifier_quote_char . ' = ? WHERE ' $this->identifier_quote_char . 'owner' $this->identifier_quote_char . ' = ? AND ' $this->identifier_quote_char . 'nickname' $this->identifier_quote_char . ' = ?'))) {
  761.                 if ($pdo_show_sql_errors)
  762.                     return $this->set_error(sprintf(_("Database error: %s")implode(' - '$this->dbh->errorInfo())));
  763.                 else
  764.                     return $this->set_error(sprintf(_("Database error: %s")_("Could not prepare query")));
  765.             }
  766.             if (!($res $sth->execute(array($userdata['nickname']$userdata['firstname'](!empty($userdata['lastname']$userdata['lastname''')$userdata['email'](!empty($userdata['label']$userdata['label''')$this->owner$alias)))) {
  767.                 if ($pdo_show_sql_errors)
  768.                     return $this->set_error(sprintf(_("Database error: %s")implode(' - '$sth->errorInfo())));
  769.                 else
  770.                     return $this->set_error(sprintf(_("Database error: %s")_("Could not execute query")));
  771.             }
  772.         else {
  773.             /* Create query */
  774.             $query sprintf("UPDATE %s SET nickname='%s', firstname='%s', ".
  775.                              "lastname='%s', email='%s', label='%s' ".
  776.                              "WHERE owner='%s' AND nickname='%s'",
  777.                              $this->table,
  778.                              $this->dbh->quoteString($userdata['nickname']),
  779.                              $this->dbh->quoteString($userdata['firstname']),
  780.                              $this->dbh->quoteString((!empty($userdata['lastname'])?$userdata['lastname']:'')),
  781.                              $this->dbh->quoteString($userdata['email']),
  782.                              $this->dbh->quoteString((!empty($userdata['label'])?$userdata['label']:'')),
  783.                              $this->owner,
  784.                              $this->dbh->quoteString($alias) );
  785.  
  786.             /* Do the insert */
  787.             $r $this->dbh->simpleQuery($query);
  788.  
  789.             /* Check for errors */
  790.             if (DB::isError($r)) {
  791.                 return $this->set_error(sprintf(_("Database error: %s"),
  792.                                                 DB::errorMessage($r)));
  793.             }
  794.         }
  795.  
  796.         return true;
  797.     }
  798. /* End of class abook_database */
  799.  
  800. // vim: et ts=4

Documentation generated on Sun, 11 Dec 2016 04:21:02 +0100 by phpDocumentor 1.4.3