вторник, 13 октября 2009 г.

WEB-интерфейс для адресной книги LDAP + генератор ldif

В компании, где я работаю, как и во многих других, в качестве единого хранилища e-mail адресов сотрудников используется адресная книга на базе LDAP. В качестве телефонной книги, так исторически сложилось, использовали отдельную электронную таблицу, что мне не очень нравилось, поскольку нужно было вести сразу два списка - отдельно адреса, отдельно телефоны. Между тем никто не мешает вести весь учет в адресной книге. Единственным препятствием является то, что большинство почтовых клиентов не отображают адресные книги LDAP целиком, позволяя лишь осуществлять поиск по ним, с подстановкой e-mail в адресную строку. По этому и возникла идея написать WEB-интерфейс для адресной книги. Однако заполнять ее телефонными номерами вручную тоже не очень хотелось, отсюда вторая идея, написать скрипт, который сделает это за меня.



Некоторые соглашения:
Используемое программное обеспечение:
  • Openldap
  • PHP
  • Apache2
  • Phpldapadmin.
Адрес адресной книги в каталоге LDAP - ou=addressbook, dc=domain, dc=local
Поле используемое для хранения номеров телефонов - telephonenumber
Для каждой записи храним два телефонных номера - внутренний и городской.

WEB-интерфейс


Определимся с внешним видом:
Как будет выглядеть страница - дело хозяйское, я решил, что у меня она будет состоять и трех фрэймов - в верхнем заголовок, левый для управления выводимой информацией, правый для вывода информации. Создаем файл index.html следующего содержания:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//RU">

<HTML>
<HEAD>
    <link rel="stylesheet" type="text/css" href="abook.css">
    <TITLE>Адресная книга</TITLE>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</HEAD>
 <BODY>  
       <frameset rows="80,*" cols="*">
       <frame src="top.html" name="topFrame" scrolling="no" noresize>
<frameset cols="280,*">
      <frame src="left.html" name="leftFrame" scrolling="no" noresize>
      <frame src="main.php" name="mainFrame">
      </frameset>
      </frameset></BODY>
</HTML>
Поскольку верхний фрэйм не несет функциональной нагрузки, то описывать top.html не буду, пишите сами, как сочтете нужным, можете вообще его убрать.

Левый фрэйм:
Тут у нас будет организована возможность переключения между двумя адресными книгами и форма поиска по ним.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//RU">

<HTML>
<HEAD>
    <link rel="stylesheet" type="text/css" href="abook.css">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</HEAD>   
<BODY>
    <H3 align=center>Адресная книга</H3>
    <ul>
<li><A href="main.php?ask=addressbook1" TARGET="mainFrame">"Офис"</A></li>
        <li><A href="main.php?ask=addressbook2" TARGET="mainFrame">"Филиал"</A></li>
<li>Поиск<br>
   <form action="main.php" TARGET="mainFrame">
   <input type="radio" name="ask" value="addressbook1">"Офис"<Br>
     <input type="radio" name="ask" value="addresbook2" checked>"Филиал"<Br>
   <div align=center><input type="text" name="sval" size=27>
   <input type="submit" value="Искать">
   </form>
</li>
    </ul>
<HR size=3 width=100% color=black>
</BODY>
</HTML>
 Правый фрэйм:
Файл main.php служит для создания и выполнения запросов к LDAP серверу и вывода результатов на экран. Подробно не расписываю, смотрим комментарии в тексте.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//RU">

<HTML>
<HEAD>
    <link rel="stylesheet" type="text/css" href="abook.css">
    <TITLE>Справочная</TITLE>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</HEAD>  
<BODY>
<?php
//Адрес LDAP сервера
$srv="localhost";

if(isset($_GET['ask'])){$ask=$_GET['ask'];}
else {$ask="addressbook1";}
if(isset($_GET['sval'])){$sval=$_GET['sval'];}
if ($ask=="addressbook1"){echo "<H3 align=center>Главный офис</H3>";}
elseif ($ask=="addressbook2"){if ($div==''){echo "<H3 align=center>Филиал</H3>";}}
if ($ds=ldap_connect($srv))
{
//Подключаемся к ldap серверу
$r=ldap_bind($ds);  // это "anonymous" связь, обычно доступ
// только для чтения, вывод "Результат связи.."
//Если задан параметр поиска, то ищем
//Если не задан выводим все подряд
if ($sval<>''){
$sr=ldap_search($ds,"ou=$ask, dc=domain, dc=local", "cn=*".$sval."*");}
else
{
$sr=ldap_search($ds,"ou=$ask, dc=domain, dc=local", "sn=*");
}
//Выполняем запрос
$info = ldap_get_entries($ds, $sr);
?>
//Выводим результаты в таблицу
<div align=center>
<table bgcolor=black><tr align=center bgcolor=orange><td>Имя</td><td>Электронная почта</td><td>Внутренний телефон</td><td>Городской телефон</td></tr>
<?php
for ($i=0; $i<$info["count"]; $i++)
{
#    echo "dn is: ". $info[$i]["dn"] ."<br>";
    $cn=$info[$i]["cn"][0];
    $last=$cn{strlen($cn)-1};
    if ($last<>')')
    {
        echo "<tr bgcolor=white><td>".$info[$i]["cn"][0] ."</td>";
   echo "<td><A href=\"mailto:".$info[$i]["mail"][0]."\">".$info[$i]["mail"][0]."</A></td>";
   echo "<td align=center>". $info[$i]["telephonenumber"][0]."</td><td align=center>". $info[$i]["telephonenumber"][1]."</td></tr>";
    }
}
 
echo "</table></div>";
ldap_close($ds);
}
else
//Ругаемся, если не получилось подключиться
{echo "<h4>Нет соединения с LDAP сервером</h4>";}
?>
</BODY>
</HTML>
Готово. Заходим, смотрим, радуемся. Осталось только внести телефонные номера.

Генератор LDIF


Подготовка:
Определимся с имеющимися источниками информации. У нас есть адресная книга LDAP, содержащая Ф.И.О. и e-mail сотрудников и электронная таблица содержащая Ф.И.О, внутренний и городской номера телефонов сотрудников. Нам необходимо объединить содержимое этих источников и на выходе получить файл формата LDIF, для последующего импорта на LDAP сервер. (Написание Ф.И.О. должно быть одинаково в обоих местах!)
Раз уж мы изначально стали использовать PHP, то продолжим дальше.
Для начала приведем электронную таблицу к виду
|Ф.И.О.|внутренний номер|городской номер|
и сохраним ее в формате csv. Получим файл содержащий строки вида:
Иванов Иван Иванович,101,555-55-55
Копируем полученный файл в папку на web сервере, где будет лежать наш скрипт.

convert.php
Создаем файл convert.php следующего содержания:
<HTML>
<HEAD>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</HEAD>  
<?php
//Ваш файл в формате csv
$file=file("file.csv");
//Адресная книга LDAP
$ask="addressbook1";
//ldap сервер
$srv="localhost";
if ($ds=ldap_connect($srv))
{
$r=ldap_bind($ds);
$sr=ldap_search($ds,"ou=$ask, dc=domain, dc=local", "sn=*");
$info = ldap_get_entries($ds, $sr);
print "dn: ou="."$ask".",dc=domain,dc=local<br>
ou: ".$ask."<br>
objectClass: top<br>
objectClass: organizationalUnit<br><br>";
for ($i=0; $i<$info["count"]; $i++) {
foreach($file as $line)
{
$parts=explode(',',$line);

if (eregi($info[$i]["cn"][0],$parts[0]))
{
    echo "dn: ". $info[$i]["dn"] ."<br>";
        echo "sn: ".$info[$i]["sn"][0] ."<br>";
echo "givenName: ".$info[$i]["givenname"][0]."<br>";
echo "mail: ". $info[$i]["mail"][0]."<br>";
echo "objectClass: top<br>
objectClass: person<br>
objectClass: organizationalPerson<br>
objectClass: inetOrgPerson<br>";
echo "cn: ".$info[$i]["cn"][0]."<br>";
     echo "telephoneNumber: ".$parts[1]."<br>";
     echo "telephoneNumber: ".$parts[2]."<br><br>";
}
}
   }
   ldap_close($ds);
   }
else {echo "<h4>Нет соединения с LDAP сервером</h4>";}
?>
</BODY>
</HTML>
Переходим по адресу http://ваш_сервер/папка/convert.php и видим нужный нам текст в формате LDIF
dn: ou=addressbook1,dc=domain,dc=local
ou: addressbook1
objectClass: top
objectClass: organizationalUnit

dn: cn=Иванов Иван Иванович,ou=addressbook1,dc=domain,dc=local
sn: Иванов
givenName: Иван Иванович
mail: ivanov@domain.ru
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
cn: Иванов Иван Иванович
telephoneNumber: 101
telephoneNumber: 555-55-55
 Сохраняем в файл любым удобным Вам способом, удаляем существующую адресную книгу и импортируем полученный файл. Рекомендую для этих целей использовать Phpldapadmin, но можно и из консоли.
Заходим по адресу Вашего WEB-интерфейса адресной книги и любуемся результатом проделанной работы.

Комментариев нет:

Отправить комментарий