steffen: server/kolab-horde-fbview/kolab-horde-fbview/fbview/turba/lib/Driver imsp.php, NONE, 1.1 kolab.php, NONE, 1.1 ldap.php, NONE, 1.1 prefs.php, NONE, 1.1 sql.php, NONE, 1.1
cvs at intevation.de
cvs at intevation.de
Mon Oct 31 12:43:38 CET 2005
Author: steffen
Update of /kolabrepository/server/kolab-horde-fbview/kolab-horde-fbview/fbview/turba/lib/Driver
In directory doto:/tmp/cvs-serv18388/kolab-horde-fbview/kolab-horde-fbview/fbview/turba/lib/Driver
Added Files:
imsp.php kolab.php ldap.php prefs.php sql.php
Log Message:
Fbview in separate package
--- NEW FILE: imsp.php ---
<?php
/**
* Turba directory driver implementation for an IMSP server.
* For now, provides only for addressbooks named for the user.
*
* @author Michael Rubinsky<mike at theupstairsroom.com>
* @version 1.0
* @package Turba
*/
class Turba_Driver_imsp extends Turba_Driver {
/**
* Handle for the IMSP connection.
* @var object Net_IMSP $_imsp
*/
var $_imsp;
/**
* The name of the addressbook.
* @var string $_bookName
*/
var $_bookName = '';
/**
* Holds if we are authenticated.
* @var boolean $_authenticated
*/
var $_authenticated = '';
/**
* Holds name of the field indicating an IMSP group
* @var string $_groupField
*/
var $_groupField = '';
/**
* Holds value that $_groupField will have
* if entry is an IMSP group.
* @var string $_groupValue
*/
var $_groupValue = '';
/**
* Constructs a new Turba imsp driver object.
*
* @param array $params Hash containing additional configuration parameters.
*/
function Turba_Driver_imsp($params)
{
$this->type = 'imsp';
$this->params = $params;
$this->_groupField = $params['group_id_field'];
$this->_groupValue = $params['group_id_value'];
$this->_bookName = $params['name'];
}
/**
* Initialize the IMSP connection and check for error.
*/
function init()
{
global $prefs;
global $conf;
require_once 'Net/IMSP.php';
$this->_imsp = &Net_IMSP::singleton('Book', $this->params);
$result = $this->_imsp->init();
if (is_a($result, 'PEAR_Error')) {
$this->_authenticated = false;
return $result;
}
if (!empty($conf['log'])) {
$logParams = $conf['log'];
$result = $this->_imsp->setLogger($conf['log']);
if (is_a($result, 'PEAR_Error')) {
return $result;
}
}
$this->_authenticated = true;
return true;
}
/**
* Returns all entries matching $critera. (For now, only supports
* ONE search critera that will NOT match strictly. Currently,
* only supports searching * on one IMSP field (no AND or OR
* searches are supported yet).
*
* @param array $criteria Array containing the search criteria.
* @param array $fields List of fields to return.
*
* @return array Hash containing the search results.
*/
function search($criteria, $fields)
{
if (!$this->_authenticated) {
return array();
}
/* Ensure we have something to return. */
$results = array();
$noGroups = false;
/* Get the search criteria. */
$temp = array_values($criteria);
if (count($criteria)) {
$searchField = $temp[0][0]['field'];
$searchValue = $temp[0][0]['test'];
} else {
$searchField = 'name';
$searchValue = '';
}
/* Make sure the searchvalue isn't FullName, since fullname is
* created dynamically. */
if ($searchField == 'fullname') {
$searchField = 'name';
}
/**
* Are we searching for only Turba_Groups or Turba_Objects?
* This is needed so the 'Show Lists' and 'Show Contacts' links
* work correctly in Turba.
*/
if ($searchField == '__type') {
switch ($searchValue) {
case 'Group':
$searchField = $this->_groupField;
$searchValue = $this->_groupValue;
break;
case 'Object':
$searchField = 'name';
$searchValue = '';
$noGroups = true;
break;
}
}
/* If there is no searchValue than only use the wildcard. */
if (strlen($searchValue) > 0 ) {
$searchValue = $searchValue . '*';
} else {
$searchValue = '*';
}
$names = $this->_imsp->search($this->_bookName, $searchValue,
$searchField);
if (is_a($names, 'PEAR_Error')) {
$GLOBALS['notification']->push($names, 'horde.error');
} else {
$namesCount = count($names);
for ($i = 0; $i < $namesCount; $i++) {
$temp = $this->read('name', array($names[$i]), $fields);
$result = $temp[0];
if (is_a($result, 'PEAR_Error')) {
$GLOBALS['notification']->push($results, 'horde.error');
} elseif (($noGroups) && (isset($result[$this->_groupField])) &&
($result[$this->_groupField]) == $this->_groupValue) {
unset($result);
} else {
$results[] = $result;
}
}
Horde::logMessage(sprintf('IMSP returned %s results',
count($results)) ,__FILE__, __LINE__, LOG_DEBUG);
}
return array_values($results);
}
/**
* Read the given data from the imsp database and returns the
* result's fields.
*
* @param array $criteria (Ignored: Always 'name' for imsp) Search criteria.
* @param array $id Array of data identifiers.
* @param array $fields List of fields to return.
*
* @return array Hash containing the search results.
*/
function read($criteria, $id, $fields)
{
$results = array();
if (!$this->_authenticated) {
return $results;
}
$id = array_values($id);
$idCount = count($id);
for ($i = 0; $i < $idCount; $i++) {
$temp = $this->_imsp->getEntry($this->_bookName, $id[$i]);
if (is_a($temp, 'PEAR_Error')) {
$result = array();
} else {
$temp['fullname'] = $temp['name'];
$isIMSPGroup = false;
if ((isset($temp[$this->_groupField])) &&
($temp[$this->_groupField] == $this->_groupValue)) {
$isIMSPGroup = true;
}
if ($isIMSPGroup) {
//IMSP Group
if (isset($temp['email'])) {
$emailList = $this->_getGroupEmails($temp['email']);
$count = count($emailList);
for ($j = 0; $j < $count; $j++) {
$memberName = $this->_imsp->search
($this->_bookName,trim($emailList[$j]),'email');
if (count($memberName)) {
$members[] = $memberName[0];
}
}
$temp['__members'] = serialize($members);
}
$temp['__type'] = 'Group';
$temp['email'] = null;
$result = $temp;
} else {
//IMSP Contact
$count = count($fields);
for ($j = 0; $j < $count; $j++) {
if (isset($temp[$fields[$j]])) {
$result[$fields[$j]] = $temp[$fields[$j]];
}
}
}
}
$results[] = $result;
}
return $results;
}
/**
* Adds the specified object to the imsp database.
*/
function addObject($attributes)
{
/* We need to map out Turba_Groups back to IMSP groups before
* writing out to the server. We need to array_values() it in
* case an entry was deleted from the group. */
if ($attributes['__type'] == 'Group') {
/* We may have a newly created group. */
$attributes[$this->_groupField] = $this->_groupValue;
if (!isset($attributes['__members'])) {
$attributes['__members'] = '';
$attributes['email'] = ' ';
}
$temp = unserialize($attributes['__members']);
if (is_array($temp)) {
$members = array_values($temp);
} else {
$members = array();
}
if (count($members)) {
$result = $this->read('name', $members, array('email'));
$count = count($result);
for ($i = 0; $i < $count; $i++) {
$contact = sprintf("%s<%s>\n", $members[$i],
$result[$i]['email']);
$attributes['email'] .= $contact;
}
}
}
unset($attributes['__members']);
unset($attributes['__type']);
unset($attributes['fullname']);
return $this->_imsp->addEntry($this->_bookName, $attributes);
}
/**
* Deletes the specified object from the imsp database.
*/
function removeObject($object_key, $object_id)
{
return $this->_imsp->deleteEntry($this->_bookName, $object_id);
}
/**
* Saves the specified object in the imsp database.
*
* @param string $object_key (Ignored) name of the field
* in $attributes[] to treat as key.
* @param string $object_id (Ignored) the value of the key field.
* @param array $attributes Contains the field names and values of the entry.
*
* @return string The object id, possibly updated.
*/
function setObject($object_key, $object_id, $attributes)
{
// Should we check if the key changed, because IMSP will just
// write out a new entry without removing the previous one.
// This will change the key though and cause the entry not to
// display on the "success" screen.
/*if ($attributes['name'] != $this->makeKey($attributes)) {
$this->removeObject($object_key, $attributes['name']);
$attributes['name'] = $this->makeKey($attributes);
}*/
$result = $this->addObject($attributes);
return is_a($result, 'PEAR_Error') ? $result : $object_id;
}
/**
* Create an object key for a new object.
*
* @param array $attributes The attributes (in driver keys) of the
* object being added.
*
* @return string A unique ID for the new object.
*/
function makeKey($attributes)
{
return $attributes['fullname'];
}
/**
* Parses out $emailText into an array of pure email addresses
* suitable for searching the IMSP datastore with.
*
* @param $emailText string single string containing email addressses.
* @return array of pure email address.
*/
function _getGroupEmails($emailText)
{
$result = preg_match_all("(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3})",
$emailText, $matches);
return $matches[0];
}
}
--- NEW FILE: kolab.php ---
<?php
require_once 'Horde/Kolab.php';
require_once 'Horde/Data.php';
/**
* Horde Turba driver for the Kolab IMAP Server.
* Copyright (C) 2003, 2004 Code Fusion, cc.
*
* $Horde: turba/lib/Driver/kolab.php,v 1.1 2004/04/21 19:05:03 chuck Exp $
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Stuart Bingë <s.binge at codefusion.co.za>
* @version $Revision: 1.1 $
* @package Turba
*/
class Turba_Driver_kolab extends Turba_Driver {
/**
* Our Kolab Cyrus server connection.
*
* @var object Kolab_Cyrus $_kc
*/
var $_kc;
function init()
{
$this->_params['folder'] = array_key_exists('folder', $this->_params)
? $this->_params['folder'] : 'Contacts';
$this->_params['server'] = array_key_exists('server', $this->_params)
? $this->_params['server'] : $GLOBALS['conf']['kolab']['server'];
}
/**
* Opens a connection to the Kolab Cyrus Server.
*
* @return mixed True on success, PEAR_Error on failure.
*/
function _open()
{
$this->_kc = new Kolab_Cyrus($this->_params['server']);
$result = $this->_kc->openMailbox($this->_params['folder'], true);
if (is_a($result, 'PEAR_Error')) {
return $result;
}
return true;
}
/**
* Closes the Kolab Cyrus connection.
*/
function _close()
{
$this->_kc->disconnect();
}
/**
* Converts Turba search criteria into a comparable IMAP search string
*
* @param array $criteria The search criteria.
*
* @return string The IMAP search string corresponding to $criteria.
*/
function turbaToImap($criteria)
{
$values = array_values($criteria);
$values = $values[0];
$query = "";
for ($current = 0; $current < count($values); $current++) {
$temp = $values[$current];
while (!empty($temp) && !array_key_exists('field', $temp)) {
$temp = array_values($temp);
$temp = $temp[0];
}
if (empty($temp)) continue;
$searchkey = $temp['field'];
$searchval = $temp['test'];
switch ($searchkey) {
case 'owner':
$query .= 'FROM "' . $searchval . '" ';
break;
case 'name':
case 'firstname':
case 'lastname':
$query .= 'BODY "N:" ';
if (!empty($searchval))
$query .= 'BODY "' . $searchval . '" ';
break;
case 'email':
$query .= 'BODY "EMAIL:" ';
if (!empty($searchval))
$query .= 'BODY "' . $searchval . '" ';
break;
case 'title':
$query .= 'BODY "TITLE:" ';
if (!empty($searchval))
$query .= 'BODY "' . $searchval . '" ';
break;
case 'company':
$query .= 'BODY "ORG:" ';
if (!empty($searchval))
$query .= 'BODY "' . $searchval . '" ';
break;
case 'homeAddress':
case 'homeCity':
case 'homeProvince':
case 'homePostalCode':
case 'homeCountry':
$query .= 'BODY "ADR:" BODY "TYPE" BODY "HOME" ';
if (!empty($searchval))
$query .= 'BODY "' . $searchval . '" ';
break;
case 'workAddress':
case 'workCity':
case 'workProvince':
case 'workPostalCode':
case 'workCountry':
$query .= 'BODY "ADR:" BODY "TYPE" BODY "WORK" ';
if (!empty($searchval))
$query .= 'BODY "' . $searchval . '" ';
break;
case 'homePhone':
$query .= 'BODY "TEL:" BODY "TYPE" BODY "HOME" ';
if (!empty($searchval))
$query .= 'BODY "' . $searchval . '" ';
break;
case 'workPhone':
$query .= 'BODY "TEL:" BODY "TYPE" BODY "WORK" ';
if (!empty($searchval))
$query .= 'BODY "' . $searchval . '" ';
break;
case 'cellPhone':
$query .= 'BODY "TEL:" BODY "TYPE" BODY "CELL" ';
if (!empty($searchval))
$query .= 'BODY "' . $searchval . '" ';
break;
case 'fax':
$query .= 'BODY "TEL:" BODY "TYPE" BODY "FAX" ';
if (!empty($searchval))
$query .= 'BODY "' . $searchval . '" ';
break;
case 'notes':
$query .= 'BODY "NOTE:" ';
if (!empty($searchval))
$query .= 'BODY "' . $searchval . '" ';
break;
case 'website':
$query .= 'BODY "URL:" ';
if (!empty($searchval))
$query .= 'BODY "' . $searchval . '" ';
break;
case 'nickname':
$query .= 'BODY "NICKNAME:" ';
if (!empty($searchval))
$query .= 'BODY "' . $searchval . '" ';
break;
default:
if (!empty($searchkey))
$query .= 'BODY "' . $searchkey . '" ';
if (!empty($searchval))
$query .= 'BODY "' . $searchval . '" ';
}
}
return $query;
}
/**
* Searches the Kolab message store with the given criteria and returns a
* filtered list of results. If the criteria parameter is an empty
* array, all records will be returned.
*
* @param $criteria Array containing the search criteria.
* @param $fields List of fields to return.
*
* @return Hash containing the search results.
*/
function search($criteria, $fields)
{
$query = Turba_Driver_kolab::turbaToImap($criteria);
$result = $this->_open();
if (is_a($result, 'PEAR_Error')) {
return $result;
}
$results = array();
$msgs = $this->_kc->getMessageList(SORTDATE, false, $query);
foreach ($msgs as $msg) {
$object = $this->_kc->getObject($msg, "text/x-vcard");
if ($object === false) continue;
$contact = $this->loadVCard($object);
if ($contact === false) continue;
$card = array();
foreach ($fields as $field) {
$card[$field] = (isset($contact[$field]) ? $contact[$field] : '');
}
$results[] = $card;
}
$this->_close();
return $results;
}
/**
* Read the given data from the Kolab message store and returns the
* result's fields.
*
* @param $criteria Search criteria.
* @param $id Data identifier.
* @param $fields List of fields to return.
*
* @return Hash containing the search results.
*/
function read($criteria, $id, $fields)
{
if ($criteria != 'uid') return array();
$result = $this->_open();
if (is_a($result, 'PEAR_Error')) {
return $result;
}
$results = array();
if (!is_array($id)) $id = array($id);
foreach ($id as $i) {
$matches = $this->_kc->getMessageList(SORTDATE, false, "BODY \"UID:\" BODY \"$i\"");
foreach ($matches as $msg) {
$object = $this->_kc->getObject($msg, "text/x-vcard");
if ($object === false) continue;
$contact = $this->loadVCard($object);
if ($contact === false) continue;
$card = array();
foreach ($fields as $field) {
$card[$field] = (isset($contact[$field]) ? $contact[$field] : '');
}
$results[] = $card;
}
}
$this->_close();
return $results;
}
/**
* Adds the specified object to the Kolab message store.
*/
function addObject($attributes)
{
$result = $this->_open();
if (is_a($result, 'PEAR_Error')) {
return $result;
}
$result = $this->_kc->addObject(
$attributes['uid'],
$this->createVCard($attributes, NULL),
'text/x-vcard',
'kolab-contact-entry.vcard',
'Turba'
);
$this->_close();
return $result;
}
/**
* Removes the specified object from the Kolab message store.
*/
function removeObject($object_key, $object_id)
{
if ($object_key != 'uid') return false;
$result = $this->_open();
if (is_a($result, 'PEAR_Error')) {
return $result;
}
$matches = $this->_kc->getMessageList(SORTDATE, false, "BODY \"UID:\" BODY \"$object_id\"");
$this->_kc->deleteMessages($matches);
$this->_close();
return true;
}
/**
* Updates an existing object in the Kolab message store.
*
* @return string The object id, possibly updated.
*/
function setObject($object_key, $object_id, $attributes)
{
if ($object_key != 'uid') return false;
$result = $this->_open();
if (is_a($result, 'PEAR_Error')) {
return $result;
}
$matches = $this->_kc->getMessageList(SORTDATE, false, "BODY \"UID:\" BODY \"$object_id\"");
$vcard = '';
foreach ($matches as $msg) {
$vcard = $this->_kc->getObject($msg, "text/x-vcard");
if ($vcard === false) {
$vcard = '';
continue;
}
$this->_kc->deleteMessages($msg);
}
$result = $this->_kc->addObject(
$attributes['uid'],
$this->createVCard($attributes, $vcard),
'text/x-vcard',
'kolab-contact-entry.vcard',
'Turba'
);
$this->_close();
return is_a('PEAR_Error', $result) ? $result : $attributes['uid'];
}
/**
* Create an object key for a new object.
*
* @param array $attributes The attributes (in driver keys) of the
* object being added.
*
* @return string A unique ID for the new object.
*/
function makeKey($attributes)
{
return md5(uniqid(mt_rand(), true));
}
/**
* Converts a text VCARD representation into a Turba attribute hash
*
* @param string $text The text representation of the VCARD object.
*
* @return array A hash of turba attributes for the VCARD object.
*/
function loadVCard($text)
{
$vcard = &Horde_Data::singleton('vcard');
$data = $vcard->importData($text);
if (is_a('PEAR_Error', $data)) {
return $data;
}
$data = $data[0];
$contact = $vcard->toHash($data);
foreach ($data['params'] as $item) {
switch ($item['name']) {
case 'UID':
$contact['uid'] = $vcard->read($item);
}
}
$contact['owner'] = Kolab::getUser();
return $contact;
}
/**
* Converts a Turba attribute hash into a text VCARD representation.
*
* @param string $attributes The turba attribute hash.
* @param string $text (optional) If specified, this is used as the 'base'
* VCARD object, with the neccessary
* properties being overridden by $attributes.
*
* @return string The text VCARD representation.
*/
function createVCard($attributes, $text = '')
{
$vcard = &Horde_Data::singleton('vcard');
$data = array();
if (!empty($text)) {
$data = $vcard->importData($text);
if (is_a('PEAR_Error', $data)) {
return $data;
}
}
$hash = $vcard->fromHash($attributes);
$hash['AGENT'] = 'Horde/Turba/Kolab';
$hash['CLASS'] = 'PRIVATE';
$hash['PROFILE'] = 'VCARD';
$hash['UID'] = $attributes['uid'];
if (!empty($data)) {
$hash = array_merge($data, $hash);
}
return $vcard->exportData($hash);
}
}
--- NEW FILE: ldap.php ---
<?php
/**
* Turba directory driver implementation for PHP's LDAP extension.
*
* $Horde: turba/lib/Driver/ldap.php,v 1.49 2004/04/07 14:43:52 chuck Exp $
*
* @author Chuck Hagenbuch <chuck at horde.org>
* @author Jon Parise <jon at csh.rit.edu>
* @version $Revision: 1.1 $
* @since Turba 0.0.1
* @package Turba
*/
class Turba_Driver_ldap extends Turba_Driver {
/** Handle for the current LDAP connection. */
var $_ds = 0;
/**
* Constructs a new Turba LDAP driver object.
*
* @param $params Hash containing additional configuration parameters.
*/
function Turba_Driver_ldap($params)
{
if (!extension_loaded('ldap')) {
Horde::fatal(PEAR::raiseError(_("LDAP support is required but the LDAP module is not available or not loaded.")), __FILE__, __LINE__);
}
if (empty($params['server'])) {
$params['server'] = 'localhost';
}
if (empty($params['port'])) {
$params['port'] = 389;
}
if (empty($params['root'])) {
$params['root'] = '';
}
if (empty($params['multiple_entry_separator'])) {
$params['multiple_entry_separator'] = ', ';
}
if (empty($params['charset'])) {
$params['charset'] = '';
}
parent::Turba_Driver($params);
}
function init()
{
if (!($this->_ds = @ldap_connect($this->_params['server'], $this->_params['port']))) {
return PEAR::raiseError(_("Connection failure"));
}
// Set the LDAP protocol version.
if (!empty($this->_params['version'])) {
@ldap_set_option($this->_ds, LDAP_OPT_PROTOCOL_VERSION, $this->_params['version']);
}
if (isset($this->_params['bind_dn']) &&
isset($this->_params['bind_password'])) {
if (!@ldap_bind($this->_ds, $this->_params['bind_dn'], $this->_params['bind_password'])) {
return PEAR::raiseError(sprintf(_("Bind failed: (%s) %s"), ldap_errno($this->_ds), ldap_error($this->_ds)));
}
} else if (!(@ldap_bind($this->_ds))) {
return PEAR::raiseError(sprintf(_("Bind failed: (%s) %s"), ldap_errno($this->_ds), ldap_error($this->_ds)));
}
}
/**
* Searches the LDAP directory with the given criteria and returns
* a filtered list of results. If no criteria are specified, all
* records are returned.
*
* @param $criteria Array containing the search criteria.
* @param $fields List of fields to return.
*
* @return array Hash containing the search results.
*/
function search($criteria, $fields)
{
/* Build the LDAP filter. */
$filter = '';
if (count($criteria)) {
foreach ($criteria as $key => $vals) {
if ($key == 'OR') {
$filter .= '(|' . $this->_buildSearchQuery($vals) . ')';
} elseif ($key == 'AND') {
$filter .= '(&' . $this->_buildSearchQuery($vals) . ')';
}
}
} else {
// Filter on objectclass.
$filter = $this->_buildObjectclassFilter();
}
/* Add source-wide filters, which are _always_ AND-ed. */
if (!empty($this->_params['filter'])) {
$filter = '(&' . '(' . $this->_params['filter'] . ')' . $filter . ')';
}
/* Four11 (at least) doesn't seem to return 'cn' if you don't
* ask for 'sn' as well. Add 'sn' implicitly. */
$attr = $fields;
if (!in_array('sn', $attr)) {
$attr[] = 'sn';
}
/* Add a sizelimit, if specified. Default is 0, which means no
* limit. Note: You cannot override a server-side limit with
* this. */
$sizelimit = 0;
if (!empty($this->_params['sizelimit'])) {
$sizelimit = $this->_params['sizelimit'];
}
/* Log the query at a DEBUG log level. */
Horde::logMessage(sprintf('LDAP search by %s: root = %s (%s); filter = "%s"; attributes = "%s"; sizelimit = %d',
Auth::getAuth(), $this->_params['root'], $this->_params['server'], $filter, implode(', ', $attr), $sizelimit),
__FILE__, __LINE__, PEAR_LOG_DEBUG);
/* Send the query to the LDAP server and fetch the matching
* entries. */
if (!($res = @ldap_search($this->_ds, $this->_params['root'], $filter, $attr, 0, $sizelimit))) {
return PEAR::raiseError(sprintf(_("Query failed: (%s) %s"), ldap_errno($this->_ds), ldap_error($this->_ds)));
}
return $this->getResults($fields, $res);
}
/**
* Build a piece of a search query.
*
* @param array $criteria The array of criteria.
*
* @return string An LDAP query fragment.
*/
function _buildSearchQuery($criteria)
{
require_once 'Horde/LDAP.php';
$clause = '';
foreach ($criteria as $key => $vals) {
if (!empty($vals['OR'])) {
$clause .= '(|' . $this->_buildSearchQuery($vals) . ')';
} elseif (!empty($vals['AND'])) {
$clause .= '(&' . $this->_buildSearchQuery($vals) . ')';
} else {
if (isset($vals['field'])) {
$rhs = String::convertCharset($vals['test'], NLS::getCharset(), $this->_params['charset']);
$clause .= Horde_LDAP::buildClause($vals['field'], $vals['op'], $rhs);
} else {
foreach ($vals as $test) {
if (!empty($test['OR'])) {
$clause .= '(|' . $this->_buildSearchQuery($test) . ')';
} elseif (!empty($test['AND'])) {
$clause .= '(&' . $this->_buildSearchQuery($test) . ')';
} else {
$rhs = String::convertCharset($test['test'], NLS::getCharset(), $this->_params['charset']);
$clause .= Horde_LDAP::buildClause($test['field'], $test['op'], $rhs);
}
}
}
}
}
return $clause;
}
/**
* Reads the LDAP directory for a given element and returns
* the result's fields.
*
* @param string $criteria Search criteria (must be 'dn').
* @param mixed $dn The dn of the object to read.
* @param array $fields List of fields to return.
*
* @return array Hash containing the search results.
*/
function read($criteria, $dn, $fields)
{
// Only DN
if ($criteria != 'dn') {
return array();
}
$filter = $this->_buildObjectclassFilter();
/* Four11 (at least) doesn't seem to return 'cn' if you don't
* ask for 'sn' as well. Add 'sn' implicitly. */
$attr = $fields;
if (!in_array('sn', $attr)) {
$attr[] = 'sn';
}
// Handle a request for multiple records.
if (is_array($dn)) {
$results = array();
foreach ($dn as $d) {
$res = @ldap_read($this->_ds, $d, $filter, $attr);
if ($res) {
if (!is_a($result = $this->getResults($fields, $res), 'PEAR_Error')) {
$results += $result;
} else {
return $result;
}
} else {
return PEAR::raiseError(sprintf(_("Read failed: (%s) %s"), ldap_errno($this->_ds), ldap_error($this->_ds)));
}
}
return $results;
}
$res = @ldap_read($this->_ds, $dn, $filter, $attr);
if (!$res) {
return PEAR::raiseError(sprintf(_("Read failed: (%s) %s"), ldap_errno($this->_ds), ldap_error($this->_ds)));
}
return $this->getResults($fields, $res);
}
/**
* Get some results from a result identifier and clean them up.
*
* @param array $fields List of fields to return.
* @param resource $res Result identifier.
*
* @return array Hash containing the results.
*/
function getResults($fields, $res)
{
if (!($entries = @ldap_get_entries($this->_ds, $res))) {
return PEAR::raiseError(sprintf(_("Read failed: (%s) %s"), ldap_errno($this->_ds), ldap_error($this->_ds)));
}
/* Return only the requested fields (from $fields, above). */
$results = array();
for ($i = 0; $i < $entries['count']; $i++) {
$entry = $entries[$i];
$result = array();
foreach ($fields as $field) {
$field_l = String::lower($field);
if ($field == 'dn') {
$result[$field] = $entry[$field_l];
} else {
$result[$field] = '';
if (!empty($entry[$field_l])) {
for ($j = 0; $j < $entry[$field_l]['count']; $j++) {
if (!empty($result[$field])) {
$result[$field] .= $this->_params['multiple_entry_separator'];
}
$result[$field] .= String::convertCharset($entry[$field_l][$j], $this->_params['charset']);
}
}
}
}
$results[] = $result;
}
return $results;
}
/**
* Adds the specified entry to the LDAP directory.
*
* @param array $attributes The initial attributes for the new object.
*/
function addObject($attributes)
{
if (empty($attributes['dn'])) {
return PEAR::raiseError('Tried to add an object with no dn: [' . serialize($attributes) . '].');
} elseif (empty($this->_params['objectclass'])) {
return PEAR::raiseError('Tried to add an object with no objectclass: [' . serialize($attributes) . '].');
}
// Take the DN out of the attributes array
$dn = $attributes['dn'];
unset($attributes['dn']);
// Put the Objectclass into the attributes array
if (!is_array($this->_params['objectclass'])) {
$attributes['objectclass'] = $this->_params['objectclass'];
} else {
$i = 0;
foreach ($this->_params['objectclass'] as $objectclass) {
$attributes['objectclass'][$i] = $objectclass;
$i++;
}
}
// Don't add empty attributes.
$attributes = array_filter($attributes, array($this, '_emptyAttributeFilter'));
// Encode entries.
foreach ($attributes as $key => $val) {
if (!is_array($val)) {
$attributes[$key] = String::convertCharset($val, NLS::getCharset(), $this->_params['charset']);
}
}
if (!@ldap_add($this->_ds, $dn, $attributes)) {
return PEAR::raiseError('Failed to add an object: [' . ldap_errno($this->_ds) . '] "' . ldap_error($this->_ds) . '" (attributes: [' . serialize($attributes) . ']).' . "Charset:" . NLS::getCharset());
} else {
return true;
}
}
/**
* Deletes the specified entry from the LDAP directory.
*/
function removeObject($object_key, $object_id)
{
if ($object_key != 'dn') {
return PEAR::raiseError(_("Invalid key specified."));
}
if (!@ldap_delete($this->_ds, $object_id)) {
return PEAR::raiseError(sprintf(_("Delete failed: (%s) %s"), ldap_errno($this->_ds), ldap_error($this->_ds)));
} else {
return true;
}
}
/**
* Modifies the specified entry in the LDAP directory.
*
* @return string The object id, possibly updated.
*/
function setObject($object_key, $object_id, $attributes)
{
// Get the old entry so that we can access the old
// values. These are needed so that we can delete any
// attributes that have been removed by using ldap_mod_del.
$filter = $this->_buildObjectclassFilter();
$oldres = @ldap_read($this->_ds, $object_id, $filter, array_keys($attributes));
$info = ldap_get_attributes($this->_ds, ldap_first_entry($this->_ds, $oldres));
// Check if we need to rename the object.
if ($this->_params['version'] == 3 && $this->makeKey($attributes) != $object_id) {
if (isset($this->_params['dn']) && is_array($this->_params['dn']) && count($this->_params['dn'])) {
$newrdn = '';
foreach ($this->_params['dn'] as $param) {
if (isset($attributes[$param])) {
$newrdn .= $param . '=' . $attributes[$param] . ',';
}
}
$newrdn = substr($newrdn, 0, -1);
} else {
return PEAR::raiseError(_("Missing DN in LDAP source configuration."));
}
if (ldap_rename($this->_ds, $object_id, $newrdn, $this->_params['root'], true)) {
$object_id = $newrdn . ',' . $this->_params['root'];
} else {
return PEAR::raiseError( sprintf(_("Failed to change name: (%s) %s, %s"), ldap_errno($this->_ds), ldap_error($this->_ds), "$object_id,$newrdn,{$this->_params['root']}"));
}
}
// The attributes in the attributes array are all lower case
// while they are mixedCase in the search result. So convert
// the keys to lower.
$info = array_change_key_case($info, CASE_LOWER);
foreach ($info as $key => $value) {
$var = $info[$key];
$oldval = null;
// Check to see if the old value and the new value are
// different and that the new value is empty. If so then
// we use ldap_mod_del to delete the attribute.
if (isset($attributes[$key]) &&
($var[0] != $attributes[$key]) &&
$attributes[$key] == '') {
$oldval[$key] = $var[0];
if (!@ldap_mod_del($this->_ds, $object_id, $oldval)) {
return PEAR::raiseError(sprintf(_("Modify failed: (%s) %s"), ldap_errno($this->_ds), ldap_error($this->_ds)));
}
unset($attributes[$key]);
}
}
// Encode entries.
foreach ($attributes as $key => $val) {
if (!is_array($val)) {
$attributes[$key] = String::convertCharset($val, NLS::getCharset(), $this->_params['charset']);
}
}
unset($attributes[$object_key]);
$attributes = array_filter($attributes, array($this, '_emptyAttributeFilter'));
if (!@ldap_modify($this->_ds, $object_id, $attributes)) {
return PEAR::raiseError(sprintf(_("Modify failed: (%s) %s"), ldap_errno($this->_ds), ldap_error($this->_ds)));
} else {
return $object_id;
}
}
/**
* Build a DN based on a set of attributes and what attributes
* make a DN for the current source.
*
* @param array $attributes The attributes (in driver keys) of the
* object being added.
*
* @return string The DN for the new object.
*/
function makeKey($attributes)
{
$dn = '';
if (is_array($this->_params['dn'])) {
foreach ($this->_params['dn'] as $param) {
if (isset($attributes[$param])) {
$dn .= $param . '=' . $attributes[$param] . ',';
}
}
}
$dn .= $this->_params['root'];
return $dn;
}
/**
* Remove empty attributes from attributes array
*
* @param mixed $val Value from attributes array.
* @return bool Boolean used by array_filter.
*/
function _emptyAttributeFilter($var)
{
if (!is_array($var)) {
return ($var != '');
} else {
foreach ($var as $v) {
if ($v == '') {
return false;
}
}
return true;
}
}
/**
* Build an LDAP filter based on the objectclass parameter.
*
* @return string An LDAP filter.
*/
function _buildObjectclassFilter()
{
$filter = '';
if (!empty($this->_params['objectclass'])) {
if (!is_array($this->_params['objectclass'])) {
$filter = '(objectclass=' . $this->_params['objectclass'] . ')';
} else {
$filter = '(|';
foreach ($this->_params['objectclass'] as $objectclass) {
$filter .= '(objectclass=' . $objectclass . ')';
}
$filter .= ')';
}
}
return $filter;
}
}
--- NEW FILE: prefs.php ---
<?php
/**
* Turba directory driver implementation for Horde Preferences - very
* simple, lightweight container.
*
* $Horde: turba/lib/Driver/prefs.php,v 1.8 2004/04/05 03:11:41 chuck Exp $
*
* @author Chuck Hagenbuch <chuck at horde.org>
* @version $Revision: 1.1 $
* @since Turba 1.2
* @package Turba
*/
class Turba_Driver_prefs extends Turba_Driver {
/**
* Return all entries - searching isn't implemented here for
* now. The parameters are simply ignored.
*
* @param $criteria Array containing the search criteria.
* @param $fields List of fields to return.
*
* @return Hash containing the search results.
*/
function search($criteria, $fields)
{
return array_values($this->_getAddressBook());
}
/**
* Read the given data from the SQL database and returns
* the result's fields.
*
* @param $criteria Search criteria.
* @param $ids Data identifiers.
* @param $fields List of fields to return.
*
* @return Hash containing the search results.
*/
function read($criteria, $ids, $fields)
{
$book = $this->_getAddressBook();
$results = array();
if (!is_array($ids)) {
$ids = array($ids);
}
foreach ($ids as $id) {
if (isset($book[$id])) {
$results[] = $book[$id];
}
}
return $results;
}
/**
* Adds the specified object to the SQL database.
*/
function addObject($attributes)
{
$book = $this->_getAddressBook();
$book[$attributes['id']] = $attributes;
$this->_setAddressbook($book);
return true;
}
/**
* Deletes the specified object from the SQL database.
*/
function removeObject($object_key, $object_id)
{
$book = $this->_getAddressBook();
unset($book[$object_id]);
$this->_setAddressbook($book);
return true;
}
/**
* Saves the specified object in the SQL database.
*/
function setObject($object_key, $object_id, $attributes)
{
$book = $this->_getAddressBook();
$book[$object_id] = $attributes;
$this->_setAddressBook($book);
}
/**
* Create an object key for a new object.
*
* @param array $attributes The attributes (in driver keys) of the
* object being added.
*
* @return string A unique ID for the new object.
*/
function makeKey($attributes)
{
return md5(mt_rand());
}
function _getAddressBook()
{
global $prefs;
$val = $prefs->getValue('prefbooks');
if (!empty($val)) {
$prefbooks = unserialize($val);
return $prefbooks[$this->_params['name']];
} else {
return array();
}
}
function _setAddressBook($addressbook)
{
global $prefs;
$val = $prefs->getValue('prefbooks');
if (!empty($val)) {
$prefbooks = unserialize($val);
} else {
$prefbooks = array();
}
$prefbooks[$this->_params['name']] = $addressbook;
$prefs->setValue('prefbooks', serialize($prefbooks));
$prefs->store();
}
}
--- NEW FILE: sql.php ---
<?php
/**
* Turba directory driver implementation for PHP's PEAR database abstraction
* layer.
*
* $Horde: turba/lib/Driver/sql.php,v 1.50 2004/04/07 14:43:52 chuck Exp $
*
* @author Jon Parise <jon at csh.rit.edu>
* @version $Revision: 1.1 $
* @since Turba 0.0.1
* @package Turba
*/
class Turba_Driver_sql extends Turba_Driver {
/** Handle for the current database connection. */
var $_db = null;
function init()
{
include_once 'DB.php';
$this->_db = &DB::connect($this->_params,
array('persistent' => !empty($this->_params['persistent'])));
if (is_a($this->_db, 'PEAR_Error')) {
return $this->_db;
}
$this->_db->setOption('optimize', 'portability');
if ($this->_params['phptype'] == 'oci8') {
$this->_db->query('ALTER SESSION SET NLS_DATE_FORMAT = \'YYYY-MM-DD\'');
}
}
/**
* Searches the SQL database with the given criteria and returns a
* filtered list of results. If the criteria parameter is an empty
* array, all records will be returned.
*
* @param $criteria Array containing the search criteria.
* @param $fields List of fields to return.
*
* @return Hash containing the search results.
*/
function search($criteria, $fields)
{
/* Build the WHERE clause. */
$where = '';
if (count($criteria)) {
foreach ($criteria as $key => $vals) {
if ($key == 'OR' || $key == 'AND') {
if (!empty($where)) {
$where .= ' ' . $key . ' ';
}
$where .= '(' . $this->_buildSearchQuery($key, $vals) . ')';
}
}
$where = ' WHERE ' . $where;
}
/* Build up the full query. */
$query = 'SELECT ' . implode(', ', $fields) . ' FROM ' . $this->_params['table'] . $where;
/* Log the query at a DEBUG log level. */
Horde::logMessage(sprintf('SQL search by %s: table = %s; query = "%s"',
Auth::getAuth(), $this->_params['table'], $query),
__FILE__, __LINE__, PEAR_LOG_DEBUG);
/* Run query. */
$result = $this->_db->query($query);
if (is_a($result, 'PEAR_Error')) {
Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
return array();
}
$results = array();
$iMax = count($fields);
while ($row = $result->fetchRow()) {
if (is_a($row, 'PEAR_Error')) {
Horde::logMessage($row, __FILE__, __LINE__, PEAR_LOG_ERR);
return array();
}
$entry = array();
for ($i = 0; $i < $iMax; $i++) {
$field = $fields[$i];
$entry[$field] = $this->_convertFromDriver($row[$i]);
}
$results[] = $entry;
}
return $results;
}
/**
* Build a piece of a search query.
*
* @param string $glue The glue to join the criteria (OR/AND).
* @param array $criteria The array of criteria.
*
* @return string An SQL fragment.
*/
function _buildSearchQuery($glue, $criteria)
{
require_once 'Horde/SQL.php';
$clause = '';
foreach ($criteria as $key => $vals) {
if (!empty($vals['OR']) || !empty($vals['AND'])) {
if (!empty($clause)) {
$clause .= ' ' . $glue . ' ';
}
$clause .= '(' . $this->_buildSearchQuery($glue, $vals) . ')';
} else {
if (isset($vals['field'])) {
if (!empty($clause)) {
$clause .= ' ' . $glue . ' ';
}
$rhs = $this->_convertToDriver($vals['test']);
$clause .= Horde_SQL::buildClause($this->_db, $vals['field'], $vals['op'], $rhs);
} else {
foreach ($vals as $test) {
if (!empty($test['OR']) || !empty($test['AND'])) {
if (!empty($clause)) {
$clause .= ' ' . $glue . ' ';
}
$clause .= '(' . $this->_buildSearchQuery($glue, $test) . ')';
} else {
if (!empty($clause)) {
$clause .= ' ' . $key . ' ';
}
$rhs = $this->_convertToDriver($test['test']);
$clause .= Horde_SQL::buildClause($this->_db, $test['field'], $test['op'], $rhs);
}
}
}
}
}
return $clause;
}
/**
* Read the given data from the SQL database and returns the
* result's fields.
*
* @param $criteria Search criteria.
* @param $id Data identifier.
* @param $fields List of fields to return.
*
* @return Hash containing the search results.
*/
function read($criteria, $id, $fields)
{
$in = '';
if (is_array($id)) {
if (!count($id)) {
return array();
}
foreach ($id as $key) {
$in .= empty($in) ? $this->_db->quote($this->_convertToDriver($key))
: ', ' . $this->_db->quote($this->_convertToDriver($key));
}
$where = $criteria . ' IN (' . $in . ')';
} else {
$where = $criteria . ' = ' . $this->_db->quote($this->_convertToDriver($id));
}
$query = 'SELECT ' . implode(', ', $fields) . ' ';
$query .= 'FROM ' . $this->_params['table'] . ' WHERE ' . $where;
/* Log the query at a DEBUG log level. */
Horde::logMessage(sprintf('SQL read by %s: table = %s; query = "%s"',
Auth::getAuth(), $this->_params['table'], $query),
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$result = $this->_db->getAll($query);
if (is_a($result, 'PEAR_Error')) {
Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
}
$results = array();
$iMax = count($fields);
if (!is_a($result, 'PEAR_Error')) {
foreach ($result as $row) {
$entry = array();
for ($i=0; $i < $iMax; $i++) {
$field = $fields[$i];
$entry[$field] = $this->_convertFromDriver($row[$i]);
}
$results[] = $entry;
}
}
return $results;
}
/**
* Adds the specified object to the SQL database.
*/
function addObject($attributes)
{
$fields = array();
$values = array();
foreach ($attributes as $field => $value) {
$fields[] = $field;
$values[] = $this->_db->quote($this->_convertToDriver($value));
}
$query = 'INSERT INTO ' . $this->_params['table'] . ' (' . implode(', ', $fields) . ')';
$query .= ' VALUES (' . implode(', ', $values) . ')';
$result = $this->_db->query($query);
if (is_a($result, 'PEAR_Error')) {
Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
return $result;
}
return true;
}
/**
* Deletes the specified object from the SQL database.
*/
function removeObject($object_key, $object_id)
{
$where = $object_key . ' = ' . $this->_db->quote($object_id);
$query = 'DELETE FROM ' . $this->_params['table'] . ' WHERE ' . $where;
$result = $this->_db->query($query);
if (is_a($result, 'PEAR_Error')) {
Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
return $result;
}
return true;
}
/**
* Saves the specified object in the SQL database.
*
* @return string The object id, possibly updated.
*/
function setObject($object_key, $object_id, $attributes)
{
$where = $object_key . ' = ' . $this->_db->quote($object_id);
unset($attributes[$object_key]);
$set = array();
foreach ($attributes as $field => $value) {
$set[] = $field . ' = ' . $this->_db->quote($this->_convertToDriver($value));
}
$query = 'UPDATE ' . $this->_params['table'] . ' SET ' . implode(', ', $set) . ' ';
$query .= 'WHERE ' . $where;
/* Log the query at a DEBUG log level. */
Horde::logMessage(sprintf('SQL setObject by %s: table = %s; query = "%s"',
Auth::getAuth(), $this->_params['table'], $query),
__FILE__, __LINE__, PEAR_LOG_DEBUG);
$result = $this->_db->query($query);
if (is_a($result, 'PEAR_Error')) {
Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
}
return is_a($result, 'PEAR_Error') ? $result : $object_id;
}
/**
* Create an object key for a new object.
*
* @param array $attributes The attributes (in driver keys) of the
* object being added.
*
* @return string A unique ID for the new object.
*/
function makeKey($attributes)
{
return md5(uniqid(mt_rand(), true));
}
/**
* Converts a value from the driver's charset to the default charset.
*
* @param mixed $value A value to convert.
* @return mixed The converted value.
*/
function _convertFromDriver($value)
{
return String::convertCharset($value, $this->_params['charset']);
}
/**
* Converts a value from the default charset to the driver's charset.
*
* @param mixed $value A value to convert.
* @return mixed The converted value.
*/
function _convertToDriver($value)
{
return String::convertCharset($value, NLS::getCharset(), $this->_params['charset']);
}
}
More information about the commits
mailing list