DB
[ class tree: DB ] [ index: DB ] [ all elements ]

Source for file ldap.php

Documentation is available at ldap.php

  1. <?php
  2. //
  3. // Pear DB LDAP - Database independent query interface definition
  4. // for PHP's LDAP extension.
  5. //
  6. // Copyright (c) 2002-2003 Ludovico Magnocavallo <ludo@sumatrasolutions.com>
  7. //
  8. //  This library is free software; you can redistribute it and/or
  9. //  modify it under the terms of the GNU Lesser General Public
  10. //  License as published by the Free Software Foundation; either
  11. //  version 2.1 of the License, or (at your option) any later version.
  12. //
  13. //  This library is distributed in the hope that it will be useful,
  14. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. //  Lesser General Public License for more details.
  17. //
  18. //  You should have received a copy of the GNU Lesser General Public
  19. //  License along with this library; if not, write to the Free Software
  20. //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  21. //
  22. // Contributors
  23. // - Piotr Roszatycki <dexter@debian.org>
  24. //   DB_ldap::base() method, support for LDAP sequences, various fixes
  25. // - Aaron Spencer Hawley <aaron dot hawley at uvm dot edu>
  26. //   fix to use port number if present in DB_ldap->connect()
  27. //
  28. // $Id$
  29. //
  30.  
  31. require_once 'DB.php';
  32. require_once 'DB/common.php';
  33.  
  34. define("DB_ERROR_BIND_FAILED",     -26);
  35. define("DB_ERROR_UNKNOWN_LDAP_ACTION",     -27);
  36.  
  37. /**
  38.  * LDAP result class
  39.  *
  40.  * LDAP_result extends DB_result to provide specific LDAP
  41.  * result methods.
  42.  *
  43.  * @version 1.0
  44.  * @author Ludovico Magnocavallo <ludo@sumatrasolutions.com>
  45.  * @package DB
  46.  */
  47.  
  48. class LDAP_result extends DB_result
  49. {
  50.  
  51.     // {{{ properties
  52.  
  53.     /**
  54.      * data returned from ldap_entries()
  55.      * @access private
  56.      */
  57.     var $_entries   = null;
  58.     /**
  59.      * result rows as hash of records
  60.      * @access private
  61.      */
  62.     var $_recordset = null;
  63.     /**
  64.      * current record as hash
  65.      * @access private
  66.      */
  67.     var $_record    = null;
  68.  
  69.     // }}}
  70.     // {{{ constructor
  71.  
  72.     /**
  73.      * class constructor, calls DB_result constructor
  74.      * @param ref $dbh reference to the db instance
  75.      * @param resource $result ldap command result
  76.      */
  77.     function LDAP_result(&$dbh$result)
  78.     {
  79.         $this->DB_result($dbh$result);
  80.     }
  81.  
  82.     /**
  83.      * fetch rows of data into $this->_recordset
  84.      *
  85.      * called once as soon as something needs to be returned
  86.      * @access private
  87.      * @param resource $result ldap command result
  88.      * @return boolean true
  89.      */
  90.     function getRows({
  91.         if ($this->_recordset === null{
  92.             // begin processing result into recordset
  93.             $this->_entries = ldap_get_entries($this->dbh->connection$this->result);
  94.             $this->row_counter $this->_entries['count'];
  95.             $i = 1;
  96.             $rs_template = array();
  97.             if (count($this->dbh->attributes> 0{
  98.                 reset($this->dbh->attributes);
  99.                 while (list($a_index$a_nameeach($this->dbh->attributes)) $rs_template[$a_name'';
  100.             }
  101.             while (list($entry_idx$entryeach($this->_entries)) {
  102.                 // begin first loop, iterate through entries
  103.                 if (!empty($this->dbh->limit_from&& ($i $this->dbh->limit_from)) continue;
  104.                 if (!empty($this->dbh->limit_count&& ($i $this->dbh->limit_count)) break;
  105.                 $rs $rs_template;
  106.                 if (!is_array($entry)) continue;
  107.                 while (list($attr$attr_valueseach($entry)) {
  108.                     // begin second loop, iterate through attributes
  109.                     if (is_int($attr|| $attr == 'count'continue;
  110.                     if (is_string($attr_values)) $rs[$attr$attr_values;
  111.                     else {
  112.                         $value '';
  113.                         while (list($value_idx$attr_valueeach($attr_values)) {
  114.                             // begin third loop, iterate through attribute values
  115.                             if (!is_int($value_idx)) continue;
  116.                             if (empty($value)) $value $attr_value;
  117.                             else {
  118.                                 if (is_array($value)) $value[$attr_value;
  119.                                 else $value = array($value$attr_value);
  120.                             }
  121. //                          else $value .= "\n$attr_value";
  122.                             // end third loop
  123.                         }
  124.                         $rs[$attr$value;
  125.                     }
  126.                     // end second loop
  127.                 }
  128.                 reset($rs);
  129.                 $this->_recordset[$entry_idx$rs;
  130.                 $i++;
  131.                 // end first loop
  132.             }
  133.             $this->_entries = null;
  134.             if (!is_array($this->_recordset))
  135.                 $this->_recordset = array();
  136.             if (!empty($this->dbh->sorting)) {
  137.                 $sorting_method (!empty($this->dbh->sorting_method$this->dbh->sorting_method : 'cmp');
  138.                 uksort($this->_recordsetarray(&$this$sorting_method));
  139.             }
  140.             reset($this->_recordset);
  141.             // end processing result into recordset
  142.         }
  143.         return DB_OK;
  144.     }
  145.  
  146.  
  147.     /**
  148.      * Fetch and return a row of data (it uses driver->fetchInto for that)
  149.      * @param int $fetchmode  format of fetched row
  150.      * @param int $rownum     the row number to fetch
  151.      *
  152.      * @return  array a row of data, NULL on no more rows or PEAR_Error on error
  153.      *
  154.      * @access public
  155.      */
  156.     function &fetchRow($fetchmode = DB_FETCHMODE_DEFAULT$rownum = null)
  157.     {
  158.         $this->getRows();
  159.         if (count($this->_recordset=== 0 {
  160.             return null;
  161.         }
  162.  
  163.         if ($this->_record !== null{
  164.             $this->_record next($this->_recordset);
  165.         else {
  166.             $this->_record current($this->_recordset);
  167.         }
  168.         $row $this->_record;
  169.         if ($row === false{
  170.             return null;
  171.         }
  172.  
  173.         return $row;
  174.     }
  175.  
  176.  
  177.     /**
  178.      * Fetch a row of data into an existing variable.
  179.      *
  180.      * @param  mixed     $arr        reference to data containing the row
  181.      * @param  integer   $fetchmode  format of fetched row
  182.      * @param  integer   $rownum     the row number to fetch
  183.      *
  184.      * @return  mixed  DB_OK on success, NULL on no more rows or
  185.      *                  a DB_Error object on error
  186.      *
  187.      * @access public
  188.      */
  189.  
  190.     function fetchInto(&$ar$fetchmode = DB_FETCHMODE_DEFAULT$rownum = null)
  191.     {
  192.         $this->getRows();
  193.         if ($this->_record !== null$this->_record next($this->_recordset);
  194.         else $this->_record current($this->_recordset);
  195.         $ar $this->_record;
  196.         if (!$ar{
  197.             return null;
  198.         }
  199.         return DB_OK;
  200.     }
  201.  
  202.     /**
  203.      * return all records
  204.      *
  205.      * returns a hash of all records, basically returning
  206.      * a copy of $this->_recordset
  207.      * @param  integer   $fetchmode  format of fetched row
  208.      * @param  integer   $rownum     the row number to fetch (not used, here for interface compatibility)
  209.      *
  210.      * @return  mixed  DB_OK on success, NULL on no more rows or
  211.      *                  a DB_Error object on error
  212.      *
  213.      * @access public
  214.      */
  215.     function fetchAll($fetchmode = DB_FETCHMODE_DEFAULT$rownum = null)
  216.     {
  217.         $this->getRows();
  218.         return($this->_recordset);
  219.     }
  220.  
  221.     /**
  222.      * Get the the number of columns in a result set.
  223.      *
  224.      * @return int the number of columns, or a DB error
  225.      *
  226.      * @access public
  227.      */
  228.     function numCols($result)
  229.     {
  230.         $this->getRows();
  231.         return(count(array_keys($this->_record)));
  232.     }
  233.  
  234.     function cmp($a$b)
  235.     {
  236.         return(strcmp(strtolower($this->_recordset[$a][$this->dbh->sorting])strtolower($this->_recordset[$b][$this->dbh->sorting])));
  237.     }
  238.  
  239.     /**
  240.      * Get the number of rows in a result set.
  241.      *
  242.      * @return int the number of rows, or a DB error
  243.      *
  244.      * @access public
  245.      */
  246.     function numRows()
  247.     {
  248.         $this->getRows();
  249.         return $this->row_counter;
  250.     }
  251.  
  252.     /**
  253.      * Get the next result if a batch of queries was executed.
  254.      *
  255.      * @return bool true if a new result is available or false if not.
  256.      *
  257.      * @access public
  258.      */
  259.     function nextResult()
  260.     {
  261.         return $this->dbh->nextResult($this->result);
  262.     }
  263.  
  264.     /**
  265.      * Frees the resources allocated for this result set.
  266.      * @return  int     error code
  267.      *
  268.      * @access public
  269.      */
  270.     function free()
  271.     {
  272.         $this->_recordset = null;
  273.         $this->_record = null;
  274.         ldap_free_result($this->result);
  275.         $this->result = null;
  276.         return true;
  277.     }
  278.  
  279.     /**
  280.     * @deprecated
  281.     */
  282.     function tableInfo($mode = null)
  283.     {
  284.         return $this->dbh->tableInfo($this->result$mode);
  285.     }
  286.  
  287.     /**
  288.     * returns the actual rows number
  289.     * @return integer 
  290.     */
  291.     function getRowCounter()
  292.     {
  293.         $this->getRows();
  294.         return $this->row_counter;
  295.     }
  296. }
  297.  
  298. /**
  299.  * LDAP DB interface class
  300.  *
  301.  * LDAP extends DB_common to provide DB compliant
  302.  * access to LDAP servers
  303.  *
  304.  * @version 1.0
  305.  * @author Ludovico Magnocavallo <ludo@sumatrasolutions.com>
  306.  * @package DB
  307.  */
  308.  
  309. class DB_ldap extends DB_common
  310. {
  311.     // {{{ properties
  312.  
  313.     /**
  314.      * LDAP connection
  315.      * @access private
  316.      */
  317.     var $connection;
  318.     /**
  319.      * base dn
  320.      * @access private
  321.      */
  322.     var $base           '';
  323.     /**
  324.      * default base dn
  325.      * @access private
  326.      */
  327.     var $d_base           '';
  328.     /**
  329.      * query base dn
  330.      * @access private
  331.      */
  332.     var $q_base           '';
  333.     /**
  334.      * array of LDAP actions that only manipulate data
  335.      * returning a true/false value
  336.      * @access private
  337.      */
  338.     var $manip          = array('add''compare''delete''modify''mod_add''mod_del''mod_replace''rename');
  339.     /**
  340.      * store the default real LDAP action to perform
  341.      * @access private
  342.      */
  343.     var $action         'search';
  344.     /**
  345.      * store the real LDAP action to perform
  346.      * (ie PHP ldap function to call) for a query
  347.      * @access private
  348.      */
  349.     var $q_action       '';
  350.     /**
  351.      * store optional parameters passed
  352.      *  to the real LDAP action
  353.      * @access private
  354.      */
  355.     var $q_params       = array();
  356.  
  357.     // }}}
  358.  
  359.     /**
  360.      * Constructor, calls DB_common constructor
  361.      *
  362.      * @see DB_common::DB_common()
  363.      */
  364.     function DB_ldap()
  365.     {
  366.         $this->DB_common();
  367.         $this->phptype 'ldap';
  368.         $this->dbsyntax 'ldap';
  369.         $this->features = array(
  370.             'prepare'       => false,
  371.             'pconnect'      => false,
  372.             'transactions'  => false,
  373.             'limit'         => false
  374.         );
  375.         $this->errorcode_map = array(
  376.             0x10 => DB_ERROR_NOSUCHFIELD,               // LDAP_NO_SUCH_ATTRIBUTE
  377.             0x11 => DB_ERROR_INVALID,                   // LDAP_UNDEFINED_TYPE
  378.             0x12 => DB_ERROR_INVALID,                   // LDAP_INAPPROPRIATE_MATCHING
  379.             0x13 => DB_ERROR_INVALID,                   // LDAP_CONSTRAINT_VIOLATION
  380.             0x14 => DB_ERROR_ALREADY_EXISTS,            // LDAP_TYPE_OR_VALUE_EXISTS
  381.             0x15 => DB_ERROR_INVALID,                   // LDAP_INVALID_SYNTAX
  382.             0x20 => DB_ERROR_NOT_FOUND,                 // LDAP_NO_SUCH_OBJECT
  383.             0x21 => DB_ERROR_NOT_FOUND,                 // LDAP_ALIAS_PROBLEM
  384.             0x22 => DB_ERROR_INVALID,                   // LDAP_INVALID_DN_SYNTAX
  385.             0x23 => DB_ERROR_INVALID,                   // LDAP_IS_LEAF
  386.             0x24 => DB_ERROR_INVALID,                   // LDAP_ALIAS_DEREF_PROBLEM
  387.             0x30 => DB_ERROR_ACCESS_VIOLATION,          // LDAP_INAPPROPRIATE_AUTH
  388.             0x31 => DB_ERROR_ACCESS_VIOLATION,          // LDAP_INVALID_CREDENTIALS
  389.             0x32 => DB_ERROR_ACCESS_VIOLATION,          // LDAP_INSUFFICIENT_ACCESS
  390.             0x40 => DB_ERROR_MISMATCH,                  // LDAP_NAMING_VIOLATION
  391.             0x41 => DB_ERROR_MISMATCH,                  // LDAP_OBJECT_CLASS_VIOLATION
  392.             0x44 => DB_ERROR_ALREADY_EXISTS,            // LDAP_ALREADY_EXISTS
  393.             0x51 => DB_ERROR_CONNECT_FAILED,            // LDAP_SERVER_DOWN
  394.             0x57 => DB_ERROR_SYNTAX                     // LDAP_FILTER_ERROR
  395.         );
  396.     }
  397.  
  398.     /**
  399.      * Connect and bind to LDAP server with either anonymous or authenticated bind depending on dsn info
  400.      *
  401.      * @param array $dsninfo dsn info as passed by DB::connect()
  402.      * @param boolean $persistent kept for interface compatibility
  403.      * @return DB_OK if successfully connected. A DB error code is returned on failure.
  404.      */
  405.     function connect($dsninfo$persistent = false)
  406.     {
  407.         if (!PEAR::loadExtension('ldap'))
  408.             return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
  409.  
  410.         $this->dsn    $dsninfo;
  411.         $user         $dsninfo['username'];
  412.         $pw           $dsninfo['password'];
  413.         $host         $dsninfo['hostspec'];
  414.         $port         $dsninfo['port'];
  415.         $this->base   $dsninfo['database'];
  416.         $this->d_base $this->base;
  417.         $version      $dsninfo['protocol'];
  418.  
  419.         if (empty($host)) {
  420.             return $this->raiseError("no host specified $host");
  421.         // else ...
  422.  
  423.         if (isset($port)) {
  424.             $conn = ldap_connect($host$port);
  425.         else {
  426.             $conn = ldap_connect($host);
  427.         }
  428.         if (!$conn{
  429.             return $this->raiseError(DB_ERROR_CONNECT_FAILED);
  430.         }
  431.  
  432.         if (isset($version)) {
  433.             ldap_set_option($connLDAP_OPT_PROTOCOL_VERSION$version);
  434.         else {
  435.             // Use 3 by default
  436.             $res = ldap_set_option($connLDAP_OPT_PROTOCOL_VERSION3);
  437.             // If 3 fails then we can try 2
  438.             if (!$res{
  439.                 ldap_set_option($connLDAP_OPT_PROTOCOL_VERSION2);
  440.             }
  441.         }
  442.  
  443.         if ($user && $pw{
  444.             $bind @ldap_bind($conn$user$pw);
  445.         else {
  446.             $bind @ldap_bind($conn);
  447.         }
  448.         if (!$bind{
  449.             return $this->raiseError(DB_ERROR_BIND_FAILED);
  450.         }
  451.         $this->connection $conn;
  452.         return DB_OK;
  453.     }
  454.  
  455.     /**
  456.      * Unbinds from LDAP server
  457.      *
  458.      * @return int ldap_unbind() return value
  459.      */
  460.     function disconnect()
  461.     {
  462.         $ret @ldap_unbind($this->connection);
  463.         $this->connection = null;
  464.         return $ret;
  465.     }
  466.  
  467.  
  468.     /**
  469.      * Performs a request against the LDAP server
  470.      *
  471.      * The type of request (and the corresponding PHP ldap function called)
  472.      * depend on two additional parameters, added in respect to the
  473.      * DB_common interface.
  474.      *
  475.      * @param string $filter text of the request to send to the LDAP server
  476.      * @param string $action type of request to perform, defaults to search (ldap_search())
  477.      * @param array $params array of additional parameters to pass to the PHP ldap function requested
  478.      * @return result from ldap function or DB Error object if no result
  479.      */
  480.     function simpleQuery($filter$action = null$params = null)
  481.     {
  482.         if ($action === null{
  483.             $action (!empty($this->q_action$this->q_action $this->action);
  484.         }
  485.         if ($params === null{
  486.             $params (count($this->q_params> 0 ? $this->q_params : array());
  487.         }
  488.         if (!$this->isManip($action)) {
  489.             $base $this->q_base $this->q_base $this->base;
  490.             $attributes = array();
  491.             $attrsonly = 0;
  492.             $sizelimit = 0;
  493.             $timelimit = 0;
  494.             $deref = LDAP_DEREF_NEVER;
  495.             $sorting '';
  496.             $sorting_method '';
  497.             reset($params);
  498.             while (list($k$veach($params)) {
  499.                 if (isset(${$k})) ${$k$v;
  500.             }
  501.             $this->sorting $sorting;
  502.             $this->sorting_method $sorting_method;
  503.             $this->attributes $attributes;
  504.             # double escape char for filter: '(o=Przedsi\C4\99biorstwo)' => '(o=Przedsi\\C4\\99biorstwo)'
  505.             $filter str_replace('\\''\\\\'$filter);
  506.             $this->last_query $filter;
  507.             if ($action == 'search')
  508.                 $result @ldap_search($this->connection$base$filter$attributes$attrsonly$sizelimit$timelimit$deref);
  509.             else if ($action == 'list')
  510.                 $result @ldap_list($this->connection$base$filter$attributes$attrsonly$sizelimit$timelimit$deref);
  511.             else if ($action == 'read')
  512.                 $result @ldap_read($this->connection$base$filter$attributes$attrsonly$sizelimit$timelimit$deref);
  513.             else
  514.                 return $this->ldapRaiseError(DB_ERROR_UNKNOWN_LDAP_ACTION);
  515.             if (!$result{
  516.                 return $this->ldapRaiseError();
  517.             }
  518.         else {
  519.             # If first argument is an array, it contains the entry with DN.
  520.             if (is_array($filter)) {
  521.                 $entry $filter;
  522.                 $filter $entry["dn"];
  523.             else {
  524.                 $entry = array();
  525.             }
  526.             unset($entry["dn"]);
  527.             $attribute      '';
  528.             $value          '';
  529.             $newrdn         '';
  530.             $newparent      '';
  531.             $deleteoldrdn   = false;
  532.             reset($params);
  533.             while (list($k$veach($params)) {
  534.                 if (isset(${$k})) ${$k$v;
  535.             }
  536.             $this->last_query $filter;
  537.             if ($action == 'add')
  538.                 $result @ldap_add($this->connection$filter$entry);
  539.             else if ($action == 'compare')
  540.                 $result @ldap_add($this->connection$filter$attribute$value);
  541.             else if ($action == 'delete')
  542.                 $result @ldap_delete($this->connection$filter);
  543.             else if ($action == 'modify')
  544.                 $result @ldap_modify($this->connection$filter$entry);
  545.             else if ($action == 'mod_add')
  546.                 $result @ldap_mod_add($this->connection$filter$entry);
  547.             else if ($action == 'mod_del')
  548.                 $result @ldap_mod_del($this->connection$filter$entry);
  549.             else if ($action == 'mod_replace')
  550.                 $result @ldap_mod_replace($this->connection$filter$entry);
  551.             else if ($action == 'rename')
  552.                 $result @ldap_rename($this->connection$filter$newrdn$newparent$deleteoldrdn);
  553.             else
  554.                 return $this->ldapRaiseError(DB_ERROR_UNKNOWN_LDAP_ACTION);
  555.             if (!$result{
  556.                 return $this->ldapRaiseError();
  557.             }
  558.         }
  559.         $this->freeQuery();
  560.         return $result;
  561.     }
  562.  
  563.     /**
  564.      * Executes a query performing variables substitution in the query text
  565.      *
  566.      * @param string $stmt text of the request to send to the LDAP server
  567.      * @param array $data query variables values to substitute
  568.      * @param string $action type of request to perform, defaults to search (ldap_search())
  569.      * @param array $params array of additional parameters to pass to the PHP ldap function requested
  570.      * @return LDAP_result object or DB Error object if no result
  571.      * @see DB_common::executeEmulateQuery $this->simpleQuery()
  572.      */
  573.     function execute($stmt$data = false$action = null$params = array())
  574.     {
  575.         $this->q_params $params;
  576.         $realquery $this->executeEmulateQuery($stmt$data);
  577.         if (DB::isError($realquery)) {
  578.             return $realquery;
  579.         }
  580.         $result $this->simpleQuery($realquery$action$params);
  581.         if (DB::isError($result|| $result === DB_OK{
  582.             return $result;
  583.         }
  584.  
  585.         $obj = new LDAP_result($this$result);
  586.         return $obj;
  587.     }
  588.  
  589.     /**
  590.      * Executes multiple queries performing variables substitution for each query
  591.      *
  592.      * @param string $stmt text of the request to send to the LDAP server
  593.      * @param array $data query variables values to substitute
  594.      * @param string $action type of request to perform, defaults to search (ldap_search())
  595.      * @param array $params array of additional parameters to pass to the PHP ldap function requested
  596.      * @return LDAP_result object or DB Error object if no result
  597.      * @see DB_common::executeMultiple
  598.      */
  599.     function executeMultiple($stmt&$data$action = null$params = array())
  600.     {
  601.         $this->q_action $action $action $this->action;
  602.         $this->q_params $params;
  603.         return(parent::executeMultiple($stmt$data));
  604.     }
  605.  
  606.     /**
  607.      * Executes a query substituting variables if any are present
  608.      *
  609.      * @param string $query text of the request to send to the LDAP server
  610.      * @param array $data query variables values to substitute
  611.      * @param string $action type of request to perform, defaults to search (ldap_search())
  612.      * @param array $params array of additional parameters to pass to the PHP ldap function requested
  613.      * @return LDAP_result object or DB Error object if no result
  614.      * @see DB_common::prepare() $this->execute()$this->simpleQuery()
  615.      */
  616.     function &query($query$data = array()$action = null$params = array())
  617.     {
  618.         // $this->q_action = $action ? $action : $this->action;
  619.         // $this->q_params = $params;
  620.         if (sizeof($data> 0{
  621.             $sth $this->prepare($query);
  622.             if (DB::isError($sth)) {
  623.                 return $sth;
  624.             }
  625.             return $this->execute($sth$data);
  626.         }
  627.  
  628.         $result $this->simpleQuery($query$action$params);
  629.         if (DB::isError($result|| $result === DB_OK{
  630.             return $result;
  631.         }
  632.  
  633.         $obj = new LDAP_result($this$result);
  634.         return $obj;
  635.     }
  636.  
  637.     /**
  638.      * Modifies a query to return only a set of rows, stores $from and $count for LDAP_result
  639.      *
  640.      * @param string $query text of the request to send to the LDAP server
  641.      * @param int $from record position from which to start returning data
  642.      * @param int $count number of records to return
  643.      * @return modified query text (no modifications are made, see above)
  644.      */
  645.     function modifyLimitQuery($query$from$count)
  646.     {
  647.         $this->limit_from $from;
  648.         $this->limit_count $count;
  649.         return $query;
  650.     }
  651.  
  652.     /**
  653.      * Executes a query returning only a specified number of rows
  654.      *
  655.      * This method only saves the $from and $count parameters for LDAP_result
  656.      * where the actual records processing takes place
  657.      *
  658.      * @param string $query text of the request to send to the LDAP server
  659.      * @param int $from record position from which to start returning data
  660.      * @param int $count number of records to return
  661.      * @param string $action type of request to perform, defaults to search (ldap_search())
  662.      * @param array $params array of additional parameters to pass to the PHP ldap function requested
  663.      * @return LDAP_result object or DB Error object if no result
  664.      */
  665.     function limitQuery($query$from$count$action = null$params = array())
  666.     {
  667.         $query $this->modifyLimitQuery($query$from$count);
  668.         $this->q_action $action $action $this->action;
  669.         $this->q_params $params;
  670.         return $this->query($query$action$params);
  671.     }
  672.  
  673.     /**
  674.      * Fetch the first column of the first row of data returned from
  675.      * a query.  Takes care of doing the query and freeing the results
  676.      * when finished.
  677.      *
  678.      * @param $query the SQL query
  679.      * @param $data if supplied, prepare/execute will be used
  680.      *         with this array as execute parameters
  681.      * @param string $action type of request to perform, defaults to search (ldap_search())
  682.      * @param array $params array of additional parameters to pass to the PHP ldap function requested
  683.      * @return array 
  684.      * @see DB_common::getOne()
  685.      * @access public
  686.      */
  687.     function &getOne($query$data = array()$action = null$params = array())
  688.     {
  689.         $this->q_action $action $action $this->action;
  690.         $this->q_params $params;
  691.         return(parent::getOne($query$data));
  692.     }
  693.  
  694.     /**
  695.      * Fetch the first row of data returned from a query.  Takes care
  696.      * of doing the query and freeing the results when finished.
  697.      *
  698.      * @param $query the SQL query
  699.      * @param $fetchmode the fetch mode to use
  700.      * @param $data array if supplied, prepare/execute will be used
  701.      *         with this array as execute parameters
  702.      * @param string $action type of request to perform, defaults to search (ldap_search())
  703.      * @param array $params array of additional parameters to pass to the PHP ldap function requested
  704.      * @access public
  705.      * @return array the first row of results as an array indexed from
  706.      *  0, or a DB error code.
  707.      * @see DB_common::getRow()
  708.      * @access public
  709.      */
  710.     function &getRow($query,
  711.                      $data = null,
  712.                      $fetchmode = DB_FETCHMODE_DEFAULT,
  713.                      $action = null$params = array())
  714.     {
  715.         $this->q_action $action $action $this->action;
  716.         $this->q_params $params;
  717.         return(parent::getRow($query$data$fetchmode));
  718.     }
  719.  
  720.     /**
  721.      * Fetch the first column of data returned from a query.  Takes care
  722.      * of doing the query and freeing the results when finished.
  723.      *
  724.      * @param $query the SQL query
  725.      * @param $col which column to return (integer [column number,
  726.      *  starting at 0] or string [column name])
  727.      * @param $data array if supplied, prepare/execute will be used
  728.      *         with this array as execute parameters
  729.      * @param string $action type of request to perform, defaults to search (ldap_search())
  730.      * @param array $params array of additional parameters to pass to the PHP ldap function requested
  731.      * @access public
  732.      * @return array an indexed array with the data from the first
  733.      *  row at index 0, or a DB error code.
  734.      * @see DB_common::getCol()
  735.      * @access public
  736.      */
  737.     function &getCol($query$col = 0$data = array()$action = null$params = array())
  738.     {
  739.         $this->q_action $action $action $this->action;
  740.         $this->q_params $params;
  741.         return(parent::getCol($query$col$data));
  742.     }
  743.  
  744.     /**
  745.      * Calls DB_common::getAssoc()
  746.      *
  747.      * @param $query the SQL query
  748.      * @param $force_array (optional) used only when the query returns
  749.      *  exactly two columns.  If true, the values of the returned array
  750.      *  will be one-element arrays instead of scalars.
  751.      *  starting at 0] or string [column name])
  752.      * @param array $data if supplied, prepare/execute will be used
  753.      *         with this array as execute parameters
  754.      * @param $fetchmode the fetch mode to use
  755.      * @param boolean $group see DB_Common::getAssoc()
  756.      * @param string $action type of request to perform, defaults to search (ldap_search())
  757.      * @param array $params array of additional parameters to pass to the PHP ldap function requested
  758.      * @access public
  759.      * @return array an indexed array with the data from the first
  760.      *  row at index 0, or a DB error code.
  761.      * @see DB_common::getAssoc()
  762.      * @access public
  763.      */
  764.     function &getAssoc($query$force_array = false$data = array(),
  765.                        $fetchmode = DB_FETCHMODE_ORDERED$group = false,
  766.                        $action = null$params = array())
  767.     {
  768.         $this->q_action $action $action $this->action;
  769.         $this->q_params $params;
  770.         $result = parent::getAssoc($query$force_array$data$fetchmode$group);
  771.         return $result;
  772.     }
  773.  
  774.     /**
  775.      * Fetch all the rows returned from a query.
  776.      *
  777.      * @param $query the SQL query
  778.      * @param array $data if supplied, prepare/execute will be used
  779.      *         with this array as execute parameters
  780.      * @param $fetchmode the fetch mode to use
  781.      * @param string $action type of request to perform, defaults to search (ldap_search())
  782.      * @param array $params array of additional parameters to pass to the PHP ldap function requested
  783.      * @access public
  784.      * @return array an nested array, or a DB error
  785.      * @see DB_common::getAll()
  786.      */
  787.     function &getAll($query,
  788.                      $data = null,
  789.                      $fetchmode = DB_FETCHMODE_DEFAULT,
  790.                      $action = null$params = array())
  791.     {
  792.         $this->q_action $action $action $this->action;
  793.         $this->q_params $params;
  794.         $result = parent::getAll($query$data$fetchmode);
  795.         return $result;
  796.     }
  797.  
  798.     function numRows($result)
  799.     {
  800.         return $result->numRows();
  801.     }
  802.  
  803.     function getTables()
  804.     {
  805.         return $this->ldapRaiseError(DB_ERROR_NOT_CAPABLE);
  806.     }
  807.  
  808.     function getListOf($type)
  809.     {
  810.         return $this->ldapRaiseError(DB_ERROR_NOT_CAPABLE);
  811.     }
  812.  
  813.     function isManip($action)
  814.     {
  815.         return(in_array($action$this->manip));
  816.     }
  817.  
  818.     function freeResult()
  819.     {
  820.         return true;
  821.     }
  822.  
  823.     function freeQuery($query '')
  824.     {
  825.         $this->q_action '';
  826.         $this->q_base   '';
  827.         $this->q_params = array();
  828.         $this->attributes = null;
  829.         $this->sorting '';
  830.         return true;
  831.     }
  832.  
  833.     // Deprecated, will be removed in future releases.
  834.     function base($base = null)
  835.     {
  836.         $this->q_base ($base !== null$base : null;
  837.         return true;
  838.     }
  839.  
  840.     function ldapSetBase($base = null)
  841.     {
  842.         $this->base ($base !== null$base $this->d_base;
  843.         $this->q_base '';
  844.         return true;
  845.     }
  846.  
  847.     function ldapSetAction($action 'search')
  848.     {
  849.         if ($action != 'search' && $action != 'list' && $action != 'read'{
  850.             return $this->ldapRaiseError(DB_ERROR_UNKNOWN_LDAP_ACTION);
  851.         }
  852.         $this->action $action;
  853.         $this->q_action '';
  854.         return true;
  855.     }
  856.  
  857.     /**
  858.      * Get the next value in a sequence.
  859.      *
  860.      * LDAP provides transactions for only one entry and we need to
  861.      * prevent race condition. If unique value before and after modify
  862.      * aren't equal then wait and try again.
  863.      *
  864.      * The name of sequence is LDAP DN of entry.
  865.      *
  866.      * @access public
  867.      * @param string $seq_name the DN of the sequence
  868.      * @param bool $ondemand whether to create the sequence on demand
  869.      * @return sequence integer, or a DB error
  870.      */
  871.     function nextId($seq_name$ondemand = true)
  872.     {
  873.         $repeat = 0;
  874.         do {
  875.             // Get the sequence entry
  876.             $this->base($seq_name);
  877.             $this->pushErrorHandling(PEAR_ERROR_RETURN);
  878.             $data $this->getRow("objectClass=*");
  879.             $this->popErrorHandling();
  880.  
  881.             if (DB::isError($data)) {
  882.                 // DB_ldap doesn't use DB_ERROR_NOT_FOUND
  883.                 if ($ondemand && $repeat == 0
  884.                 && $data->getCode(== DB_ERROR{
  885.                 // Try to create sequence and repeat
  886.                     $repeat = 1;
  887.                     $data $this->createSequence($seq_name);
  888.                     if (DB::isError($data)) {
  889.                         return $this->ldapRaiseError($data);
  890.                     }
  891.                 else {
  892.                     // Other error
  893.                     return $this->ldapRaiseError($data);
  894.                 }
  895.             else {
  896.                 // Increment sequence value
  897.                 $data["cn"]++;
  898.                 // Unique identificator of transaction
  899.                 $seq_unique mt_rand();
  900.                 $data["uid"$seq_unique;
  901.                 // Modify the LDAP entry
  902.                 $this->pushErrorHandling(PEAR_ERROR_RETURN);
  903.                 $data $this->simpleQuery($data'modify');
  904.                 $this->popErrorHandling();
  905.                 if (DB::isError($data)) {
  906.                     return $this->ldapRaiseError($data);
  907.                 }
  908.                 // Get the entry and check if it contains our unique value
  909.                 $this->base($seq_name);
  910.                 $data $this->getRow("objectClass=*");
  911.                 if (DB::isError($data)) {
  912.                     return $this->ldapRaiseError($data);
  913.                 }
  914.                 if ($data["uid"!= $seq_unique{
  915.                     // It is not our entry. Wait a little time and repeat
  916.                     sleep(1);
  917.                     $repeat = 1;
  918.                 else {
  919.                     $repeat = 0;
  920.                 }
  921.             }
  922.         while ($repeat);
  923.  
  924.         if (DB::isError($data)) {
  925.             return $data;
  926.         }
  927.         return $data["cn"];
  928.     }
  929.  
  930.     /**
  931.      * Create the sequence
  932.      *
  933.      * The sequence entry is based on core schema with extensibleObject,
  934.      * so it should work with any LDAP server which doesn't check schema
  935.      * or supports extensibleObject object class.
  936.      *
  937.      * Sequence name have to be DN started with "sn=$seq_id,", i.e.:
  938.      *
  939.      * $seq_name = "sn=uidNumber,ou=sequences,dc=php,dc=net";
  940.      *
  941.      * dn: $seq_name
  942.      * objectClass: top
  943.      * objectClass: extensibleObject
  944.      * sn: $seq_id
  945.      * cn: $seq_value
  946.      * uid: $seq_uniq
  947.      *
  948.      * @param string $seq_name the DN of the sequence
  949.      * @return mixed DB_OK on success or DB error on error
  950.      * @access public
  951.      */
  952.     function createSequence($seq_name)
  953.     {
  954.         // Extract $seq_id from DN
  955.         list($seq_id$_explode(","seq_name2);
  956.  
  957.         // Create the sequence entry
  958.         $data = array(
  959.             'dn' => $seq_name,
  960.             'objectclass' => array("top""extensibleObject"),
  961.             'sn' => $seq_id,
  962.             'cn' => 0,
  963.             'uid' => 0
  964.         );
  965.  
  966.         // Add the LDAP entry
  967.         $this->pushErrorHandling(PEAR_ERROR_RETURN);
  968.         $data $this->simpleQuery($data'add');
  969.         $this->popErrorHandling();
  970.         return $data;
  971.     }
  972.  
  973.     /**
  974.      * Drop a sequence
  975.      *
  976.      * @param string $seq_name the DN of the sequence
  977.      * @return mixed DB_OK on success or DB error on error
  978.      * @access public
  979.      */
  980.     function dropSequence($seq_name)
  981.     {
  982.         // Delete the sequence entry
  983.         $data = array(
  984.             'dn' => $seq_name,
  985.         );
  986.         $this->pushErrorHandling(PEAR_ERROR_RETURN);
  987.         $data $this->simpleQuery($data'delete');
  988.         $this->popErrorHandling();
  989.         return $data;
  990.     }
  991.  
  992.     // {{{ ldapRaiseError()
  993.  
  994.     function ldapRaiseError($errno = null)
  995.     {
  996.         if ($errno === null{
  997.             $errno $this->errorCode(ldap_errno($this->connection));
  998.         }
  999.         if ($this->q_action !== null{
  1000.             return $this->raiseError($errnonullnull,
  1001.                 sprintf('%s base="%s" filter="%s"',
  1002.                     $this->q_action$this->q_base$this->last_query
  1003.                 ),
  1004.                 $errno == DB_ERROR_UNKNOWN_LDAP_ACTION ? null : @ldap_error($this->connection));
  1005.         else {
  1006.             return $this->raiseError($errnonullnull"???",
  1007.                 @ldap_error($this->connection));
  1008.         }
  1009.     }
  1010.  
  1011.     // }}}
  1012.  
  1013. }
  1014.  
  1015. /*
  1016.  * Local variables:
  1017.  * tab-width: 4
  1018.  * c-basic-offset: 4
  1019.  * End:
  1020.  */
  1021. ?>

Documentation generated on Mon, 11 Mar 2019 15:46:33 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.