diff --git a/phpgwapi/inc/class.ldap.inc.php b/phpgwapi/inc/class.ldap.inc.php
new file mode 100644
index 0000000000..96d12e90da
--- /dev/null
+++ b/phpgwapi/inc/class.ldap.inc.php
@@ -0,0 +1,251 @@
+ *
+ * View and manipulate contact records using LDAP *
+ * ------------------------------------------------------------------------ *
+ * This library is part of the eGroupWare API *
+ * http://www.egroupware.org/api *
+ * -------------------------------------------- *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU General Public License as published by the *
+ * Free Software Foundation; version 2 of the License. *
+ \**************************************************************************/
+
+ /* $Id$ */
+
+ include_once(EGW_INCLUDE_ROOT.'/phpgwapi/inc/class.ldapserverinfo.inc.php');
+
+ /*!
+ @class contacts
+ @abstract Contact List System
+ @discussion Author: jengo/Milosch
+ This class provides a contact database scheme.
+ It attempts to be based on the vcard 2.1 standard, with mods as needed to make for more reasonable sql storage.
+ The LDAP schema used here may require installation of schema files available in the phpgwapi/doc/ldap dir.
+ Please see the README file there.
+ Syntax: CreateObject('phpgwapi.contacts');
+ Example1: $contacts = CreateObject('phpgwapi.contacts');
+ */
+ class ldap
+ {
+ /**
+ * @var resource $ds holds the LDAP link identifier
+ */
+ var $ds;
+
+ /**
+ * @var array $ldapServerInfo holds the detected information about the different ldap servers
+ */
+ var $ldapServerInfo;
+
+ /**
+ * the constructor for this class
+ */
+ function ldap() {
+ $this->restoreSessionData();
+ }
+
+ /**
+ * escapes a string for use in searchfilters meant for ldap_search.
+ *
+ * Escaped Characters are: '*', '(', ')', ' ', '\', NUL
+ * It's actually a PHP-Bug, that we have to escape space.
+ * For all other Characters, refer to RFC2254.
+ * @param $string either a string to be escaped, or an array of values to be escaped
+ */
+ function getLDAPServerInfo($_host)
+ {
+ if(is_a($this->ldapServerInfo[$_host], 'ldapserverinfo')) {
+ return $this->ldapServerInfo[$_host];
+ }
+
+ return false;
+ }
+
+ /**
+ * escapes a string for use in searchfilters meant for ldap_search.
+ *
+ * Escaped Characters are: '*', '(', ')', ' ', '\', NUL
+ * It's actually a PHP-Bug, that we have to escape space.
+ * For all other Characters, refer to RFC2254.
+ * @param $string either a string to be escaped, or an array of values to be escaped
+ */
+ function ldapAddslashes($string='')
+ {
+ return str_replace(array('\\','*','(',')','\0',' '),array('\\\\','\*','\(','\)','\\0','\20'),$string);
+ }
+
+ /**
+ * connect to the ldap server and return a handle
+ *
+ * @param $host ldap host
+ * @param $dn ldap dn
+ * @param $passwd ldap pw
+ */
+ function ldapConnect($host='', $dn='', $passwd='')
+ {
+ if(!function_exists('ldap_connect'))
+ {
+ /* log does not exist in setup(, yet) */
+ if(is_object($GLOBALS['egw']->log))
+ {
+ $GLOBALS['egw']->log->message('F-Abort, LDAP support unavailable');
+ $GLOBALS['egw']->log->commit();
+ }
+
+ printf('Error: LDAP support unavailable
',$host);
+ return False;
+ }
+
+ if(!$host)
+ {
+ $host = $GLOBALS['egw_info']['server']['ldap_host'];
+ }
+
+ if(!$dn)
+ {
+ $dn = $GLOBALS['egw_info']['server']['ldap_root_dn'];
+ }
+
+ if(!$passwd)
+ {
+ $passwd = $GLOBALS['egw_info']['server']['ldap_root_pw'];
+ }
+
+ // connects to ldap server
+ if(!$this->ds = ldap_connect("ldap://$host", 389))
+ {
+ /* log does not exist in setup(, yet) */
+ if(is_object($GLOBALS['egw']->log))
+ {
+ $GLOBALS['egw']->log->message('F-Abort, Failed connecting to LDAP server');
+ $GLOBALS['egw']->log->commit();
+ }
+
+ printf("Error: Can't connect to LDAP server %s!
",$host);
+ echo function_backtrace(1);
+ return False;
+ }
+
+ if(!isset($this->ldapServerInfo[$host])) {
+ //print "no ldap server info found
";
+ $ldapbind = ldap_bind($this->ds, '', '');
+ $filter='(objectclass=*)';
+ $justthese = array('structuralObjectClass','namingContexts','supportedLDAPVersion','subschemaSubentry');
+
+ if($sr=ldap_read($this->ds, '', $filter, $justthese)) {
+ if($info = ldap_get_entries($this->ds, $sr)) {
+
+ $ldapServerInfo = new ldapserverinfo();
+
+ // check for supported ldap version
+ if($info[0]['supportedldapversion']) {
+ for($i=0; $i<$info[0]['supportedldapversion']['count']; $i++) {
+ $supportedVersion = ($supportedVersion < $info[0]['supportedldapversion'][$i] ? $info[0]['supportedldapversion'][$i] : $supportedVersion);
+ }
+ $ldapServerInfo->setVersion($supportedVersion);
+ }
+
+ // check for naming contexts
+ if($info[0]['namingcontexts']) {
+ for($i=0; $i<$info[0]['namingcontexts']['count']; $i++) {
+ $namingcontexts[] = $info[0]['namingcontexts'][$i];
+ }
+ $ldapServerInfo->setNamingContexts($namingcontexts);
+ }
+
+ // check for ldap server type
+ if($info[0]['structuralobjectclass']) {
+ switch($info[0]['structuralobjectclass'][0]) {
+ case 'OpenLDAProotDSE':
+ $ldapServerType = OPENLDAP_LDAPSERVER;
+ break;
+ default:
+ $ldapServerType = UNKNOWN_LDAPSERVER;
+ break;
+ }
+ $ldapServerInfo->setServerType($ldapServerType);
+ }
+
+ // check for subschema entry dn
+ if($info[0]['subschemasubentry']) {
+ $subschemasubentry = $info[0]['subschemasubentry'][0];
+ $ldapServerInfo->setSubSchemaEntry($subschemasubentry);
+ }
+
+ // create list of supported objetclasses
+ if(!empty($subschemasubentry)) {
+ $filter='(objectclass=*)';
+ $justthese = array('objectClasses');
+
+ if($sr=ldap_read($this->ds, $subschemasubentry, $filter, $justthese)) {
+ if($info = ldap_get_entries($this->ds, $sr)) {
+ if($info[0]['objectclasses']) {
+ for($i=0; $i<$info[0]['objectclasses']['count']; $i++) {
+ $pattern = '/^\( (.*) NAME \'(\w*)\' /';
+ if(preg_match($pattern, $info[0]['objectclasses'][$i], $matches)) {
+ if(count($matches) == 3) {
+ $supportedObjectClasses[$matches[1]] = strtolower($matches[2]);
+ }
+ }
+ }
+ $ldapServerInfo->setSupportedObjectClasses($supportedObjectClasses);
+ }
+ }
+ }
+ }
+ $this->ldapServerInfo[$host] = $ldapServerInfo;
+ }
+ } else {
+ $this->ldapServerInfo[$host] = false;
+ }
+ $this->saveSessionData();
+ } else {
+ $ldapServerInfo = $this->ldapServerInfo[$host];
+ }
+
+ if(is_a($ldapServerInfo, 'ldapserverinfo') && $ldapServerInfo->getVersion() > 2) {
+ ldap_set_option($this->ds, LDAP_OPT_PROTOCOL_VERSION, 3);
+ }
+
+ if(!ldap_bind($this->ds,$dn,$passwd))
+ {
+ if(is_object($GLOBALS['egw']->log))
+ {
+ $GLOBALS['egw']->log->message('F-Abort, Failed binding to LDAP server');
+ $GLOBALS['egw']->log->commit();
+ }
+
+ printf("Error: Can't bind to LDAP server: %s!
",$dn);
+ echo function_backtrace(1);
+ return False;
+ }
+
+ return $this->ds;
+ }
+
+ /**
+ * disconnect from the ldap server
+ */
+ function ldapDisconnect() {
+ if(is_resource($this->ds)) {
+ ldap_unbind($this->ds);
+ }
+ }
+
+ /**
+ * restore the session data
+ */
+ function restoreSessionData() {
+ $this->ldapServerInfo = $GLOBALS['egw']->session->appsession('ldapServerInfo');
+ }
+ /**
+ * save the session data
+ */
+ function saveSessionData() {
+ $GLOBALS['egw']->session->appsession('ldapServerInfo','',$this->ldapServerInfo);
+ }
+
+ }
+?>
diff --git a/phpgwapi/inc/class.ldapserverinfo.inc.php b/phpgwapi/inc/class.ldapserverinfo.inc.php
new file mode 100644
index 0000000000..1983a320b0
--- /dev/null
+++ b/phpgwapi/inc/class.ldapserverinfo.inc.php
@@ -0,0 +1,137 @@
+ *
+ * View and manipulate contact records using LDAP *
+ * ------------------------------------------------------------------------ *
+ * This library is part of the eGroupWare API *
+ * http://www.egroupware.org/api *
+ * -------------------------------------------- *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU General Public License as published by the *
+ * Free Software Foundation; version 2 of the License. *
+ \**************************************************************************/
+
+ /* $Id$ */
+
+ define('UNKNOWN_LDAPSERVER',0);
+ define('OPENLDAP_LDAPSERVER',1);
+
+ /*!
+ @class contacts
+ @abstract Contact List System
+ @discussion Author: jengo/Milosch
+ This class provides a contact database scheme.
+ It attempts to be based on the vcard 2.1 standard, with mods as needed to make for more reasonable sql storage.
+ The LDAP schema used here may require installation of schema files available in the phpgwapi/doc/ldap dir.
+ Please see the README file there.
+ Syntax: CreateObject('phpgwapi.contacts');
+ Example1: $contacts = CreateObject('phpgwapi.contacts');
+ */
+ class ldapserverinfo
+ {
+ /**
+ * @var array $namingContext holds the supported namingcontexts
+ */
+ var $namingContext = array();
+
+ /**
+ * @var string $version holds the LDAP server version
+ */
+ var $version = 2;
+
+ /**
+ * @var integer $serverType holds the type of LDAP server(OpenLDAP, ADS, NDS, ...)
+ */
+ var $serverType = 0;
+
+ /**
+ * @var string $_subSchemaEntry the subschema entry DN
+ */
+ var $subSchemaEntry = '';
+
+ /**
+ * @var array $supportedObjectClasses the supported objectclasses
+ */
+ var $supportedObjectClasses = array();
+
+ /**
+ * @var array $supportedOIDs the supported OIDs
+ */
+ var $supportedOIDs = array();
+
+ /**
+ * the constructor for this class
+ */
+ /*function ldapserverinfo() {
+ }*/
+
+ /**
+ * gets the version
+ *
+ * @return integer the supported ldap version
+ */
+ function getVersion() {
+ return $this->version;
+ }
+
+ /**
+ * sets the namingcontexts
+ *
+ * @param array $_namingContext the supported namingcontexts
+ */
+ function setNamingContexts($_namingContext) {
+ $this->namingContext = $_namingContext;
+ }
+
+ /**
+ * sets the type of the ldap server(OpenLDAP, ADS, NDS, ...)
+ *
+ * @param integer $_serverType the type of ldap server
+ */
+ function setServerType($_serverType) {
+ $this->serverType = $_serverType;
+ }
+
+ /**
+ * sets the DN for the subschema entry
+ *
+ * @param string $_subSchemaEntry the subschema entry DN
+ */
+ function setSubSchemaEntry($_subSchemaEntry) {
+ $this->subSchemaEntry = $_subSchemaEntry;
+ }
+
+ /**
+ * sets the supported objectclasses
+ *
+ * @param array $_supportedObjectClasses the supported objectclasses
+ */
+ function setSupportedObjectClasses($_supportedObjectClasses) {
+ $this->supportedOIDs = $_supportedObjectClasses;
+ $this->supportedObjectClasses = array_flip($_supportedObjectClasses);
+ }
+
+ /**
+ * sets the version
+ *
+ * @param integer $_version the supported ldap version
+ */
+ function setVersion($_version) {
+ $this->version = $_version;
+ }
+
+ /**
+ * checks for supported objectclasses
+ *
+ * @return bool returns true if the ldap server supports this objectclass
+ */
+ function supportsObjectClass($_objectClass) {
+ if($this->supportedObjectClasses[strtolower($_objectClass)]) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+?>