a68a4bd8eee5891f319f4756859f0176001e0a22
1 <?php
3 class phonequeue extends plugin
4 {
5 /* plugin specific values */
6 var $mail= "";
7 var $cn= "";
10 var $goFonTimeOut ="20";
11 var $goFonMaxLen ="20"; //
12 var $goFonAnnounceFrequency ="60"; // Annouce Frequency in seconds
13 var $goFonDialOption_t ="";
14 var $goFonDialOption_T ="";
15 var $goFonDialOption_h ="";
16 var $goFonDialOption_r ="";
17 var $goFonQueueAnnounce ="gonicus-berlin-welcome";
18 var $goFonDialOption_H ="";
19 var $goFonMusiconHold ="default";
20 var $goFonWelcomeMusic ="gonicus-berlin-welcome";
21 var $goFonQueueReportHold ="yes";
22 var $goFonQueueYouAreNext ="queue-youarenext";
23 var $goFonQueueThereAre ="queue-thereare";
24 var $goFonQueueCallsWaiting ="queue-callswaiting";
25 var $goFonQueueThankYou ="queue-thankyou";
26 var $goFonQueueMinutes ="queue-minutes";
27 var $goFonQueueSeconds ="queue-seconds";
28 var $goFonQueueLanguage ="queue-holdtime";
29 var $goFonQueueStrategy ="ringall";
30 var $goFonQueueAnnounceHoldtime="yes";
31 var $telephoneNumber =array();
32 var $goFonQueueMember =array();
33 var $goFonDialOption ="tThH";
34 var $goFonQueueRetry =5;
36 var $old_phone_numbers =array();
38 /* attribute list for save action */
39 var $attributes= array( "goFonTimeOut","goFonMaxLen","goFonAnnounceFrequency","goFonDialOption_t","goFonDialOption_T",
40 "goFonDialOption_h","goFonDialOption_r",
41 "goFonDialOption_H","goFonMusiconHold","goFonWelcomeMusic","goFonQueueReportHold","goFonQueueYouAreNext",
42 "goFonQueueThereAre","goFonQueueCallsWaiting","goFonQueueThankYou","goFonQueueMinutes","goFonQueueSeconds",
43 "telephoneNumber","goFonQueueLanguage","goFonQueueStrategy","goFonQueueAnnounceHoldtime","goFonQueueAnnounce","goFonDialOption","goFonQueueRetry");
44 /* ObjectClass */
45 var $objectclasses= array("goFonQueue");
47 function phonequeue ($config, $dn= NULL)
48 {
49 plugin::plugin($config, $dn);
51 /* Include config object */
52 $this->config= $config;
54 /* Save initial account state */
55 $this->initially_was_account= $this->is_account;
57 if($this->is_account){
58 if(isset($this->attrs['telephoneNumber'])){
59 $this->telephoneNumber=$this->attrs['telephoneNumber'];
60 unset($this->telephoneNumber['count']);
61 }
63 for($i = 0; $i < strlen($this->goFonDialOption); $i++){
64 $name = "goFonDialOption_".$this->goFonDialOption[$i];
65 $this->$name=$this->goFonDialOption[$i];
66 }
67 }
69 $this->old_phone_numbers = $this->telephoneNumber;
70 }
73 function execute()
74 {
75 /* Do we need to flip is_account state? */
76 if (isset($_POST['modify_state'])){
77 $this->is_account= !$this->is_account;
78 }
80 /* Show tab dialog headers */
81 if ($this->parent != NULL){
82 if ($this->is_account){
83 $display= $this->show_header(_("Remove the phone queue from this Account"),
84 _("Phone queue is enabled for this group. You can disable it by clicking below."));
85 } else {
86 $display= $this->show_header(_("Create phone queue"), _("For this group the phone queues are disabled. You can enable them by clicking below."));
87 return ($display);
88 }
89 }
91 /* Add queue number */
92 if(isset($_POST['add_phonenumber'])&&(isset($_POST['phonenumber']))&&(!empty($_POST['phonenumber']))){
93 if((!in_array($_POST['phonenumber'],$this->telephoneNumber))&&(is_numeric($_POST['phonenumber']))){
94 $this->telephoneNumber[]=$_POST['phonenumber'];
95 }
96 }
98 /* Delete queue number */
99 if(isset($_POST['delete_phonenumber'])&&(isset($_POST['goFonQueueNumber_List']))){
100 unset($this->telephoneNumber[$_POST['goFonQueueNumber_List']]);
101 }
103 $tmp = array();
104 foreach($this->telephoneNumber as $val){
105 if(!empty($val)){
106 $tmp[]= $val;
107 }
108 }
109 $this->telephoneNumber=$tmp;
111 /* queue number up */
112 if(isset($_POST['up_phonenumber'])&&(isset($_POST['goFonQueueNumber_List']))){
113 if($_POST['goFonQueueNumber_List']>0){
114 $up = $this->telephoneNumber[$_POST['goFonQueueNumber_List']];
115 $down = $this->telephoneNumber[$_POST['goFonQueueNumber_List']-1];
116 $this->telephoneNumber[$_POST['goFonQueueNumber_List']] = $down;
117 $this->telephoneNumber[$_POST['goFonQueueNumber_List']-1] = $up;
118 }
119 }
121 /* Queuenumber down */
122 if(isset($_POST['down_phonenumber'])&&(isset($_POST['goFonQueueNumber_List']))){
123 if(isset($this->telephoneNumber[($_POST['goFonQueueNumber_List']+1)])){
124 $up = $this->telephoneNumber[$_POST['goFonQueueNumber_List']+1];
125 $down = $this->telephoneNumber[$_POST['goFonQueueNumber_List']];
126 $this->telephoneNumber[$_POST['goFonQueueNumber_List']+1] = $down;
127 $this->telephoneNumber[$_POST['goFonQueueNumber_List']] = $up;
128 }
129 }
132 $smarty= get_smarty();
134 $smarty->assign("goFonQueueLanguageOptions",array('de'=>_('German'),'ur'=>_('Uruguai')));
135 $smarty->assign("goFonQueueAnnounceHoldtimeOptions",array('no'=>_("No"),'yes'=>_('Yes')));
136 $smarty->assign("goFonQueueStrategyOptions",array('ringall' =>_("ring all available channels until one answers"),
137 'roundrobin' =>_("take turns ringing each available interface"),
138 'leastrecent'=>_("ring interface which was least recently called by this queue"),
139 'fewestcalls'=>_("ring the one with fewest completed calls from this queue"),
140 'random' =>_("ring random interface"),
141 'rrmemory' =>_("round robin with memory, remember where we left off last ring pass")));
143 foreach($this->attributes as $key => $val){
144 $smarty->assign($val,$this->$val);
146 if($this->$val == false){
147 $smarty->assign($val."CHK","");
148 }else{
149 $smarty->assign($val."CHK"," checked ");
150 }
152 if(chkacl($this->acl,$key)==""){
153 $smarty->assign($val."ACL","");
154 }else{
155 $smarty->assign($val."ACL"," disabled ");
156 }
157 }
158 return ($display.$smarty->fetch (get_template_path('phonequeue.tpl', TRUE)));
159 }
162 /* Check formular input */
163 function check()
164 {
165 $message= array();
166 #fixme workaround : Tab is not initialised correct
167 if(!$this->is_account) return($message);
169 if($this->is_number_used()){
170 $message[] = $this->is_number_used();
171 }
173 if($this->generate_mysql_entension_entries()){
174 $message[] = $this->generate_mysql_entension_entries();
175 }
177 if(!((is_numeric($this->goFonTimeOut))||(empty($this->goFonTimeOut)))){
178 $message[] = _("Timeout must be numeric");
179 }
180 if(!((is_numeric($this->goFonQueueRetry))||(empty($this->goFonQueueRetry)))){
181 $message[] = _("Retry must be numeric");
182 }
183 if(!((is_numeric($this->goFonMaxLen))||(empty($this->goFonMaxLen)))){
184 $message[] = _("Max queue length must be numeric");
185 }
186 if(!((is_numeric($this->goFonAnnounceFrequency))||(empty($this->goFonAnnounceFrequency)))){
187 $message[] = _("Announce frequency must be numeric");
188 }
189 if(count($this->telephoneNumber)==0){
190 $message[] = _("There must be least one queue number defined.");
191 }
193 return $message;
194 }
198 function generate_mysql_entension_entries($save = false)
199 {
201 $SQL = array();
203 // Get Configuration for Mysql database Server
204 $a_SETUP = $_SESSION['config']->data['SERVERS']['FON'];
205 $s_parameter ="";
207 // Connect to DB server
208 $r_con = @mysql_pconnect($a_SETUP['SERVER'],$a_SETUP['LOGIN'],$a_SETUP['PASSWORD']);
210 // Check if we are connected correctly
211 if(!$r_con){
212 gosa_log(mysql_error());
213 return (sprintf(_("The MySQL Server '%s' isn't reachable as user '%s', check GOsa log for mysql error."),
214 $a_SETUP['SERVER'],$a_SETUP['LOGIN']));
215 }
217 // Select database for Extensions
218 $db = @mysql_select_db($a_SETUP['DB'],$r_con);
220 // Test if we have the database selected correctly
221 if(!$db){
222 gosa_log(mysql_error());
223 return( sprintf(_("Can't select database %s on %s."),$a_SETUP['DB'],$a_SETUP['SERVER']));
224 }
226 if($save){
227 $i = 0;
228 $prio = 11;
230 if(empty($this->cn)){
231 $this->cn = $this->parent->by_object['ogroup']->cn;
232 $this->attrs['cn'][0] = $this->parent->by_object['ogroup']->cn;
233 }
235 // Delete old Entries
236 $delete = array();
237 if(is_array($this->old_phone_numbers)){
238 foreach($this->old_phone_numbers as $phone){
239 $delete[]= "DELETE FROM ".$a_SETUP['EXT_TABLE']." WHERE exten='".$phone."';\n";
240 }
241 }
242 $delete[]= "DELETE FROM ".$a_SETUP['EXT_TABLE']." WHERE exten='".$this->attrs['cn'][0]."';\n";
243 $delete[]= "DELETE FROM ".$a_SETUP['QUEUE_TABLE']." WHERE name=\"".$this->attrs['cn'][0]."\"; \n";
244 $delete[]= "DELETE FROM ".$a_SETUP['QUEUE_MEMBER_TABLE']." WHERE queue_name=\"".$this->attrs['cn'][0]."\";\n";
246 /* Perform queries to delte old entries */
247 foreach($delete as $query){
248 if(!mysql_query($query)){
249 gosa_log(mysql_error());
250 return(mysql_error(). sprintf(_("Can't delete in Database %s, on Server %s."),$a_SETUP['DB'],$a_SETUP['SERVER']));
251 }
252 }
254 /* Append new Member for this queue */
255 $i = 0;
256 $queueuser =array();
257 foreach($this->parent->by_object['ogroup']->memberList as $member){
258 if(in_array("goFonAccount",$member['objectClass'])){
259 $i ++ ;
260 $queueuser[$i]['queue_name'] = $this->attrs['cn'][0];
261 $queueuser[$i]['interface'] = "SIP/".$member['uid'][0];
262 $queueuser[$i]['penalty'] = 1;
263 }
264 }
266 /* Parse and Add members to query Array */
267 if(is_array($queueuser)){
268 foreach($queueuser as $user){
269 $entries = "";
270 $values = "";
271 foreach($user as $attr => $val){
272 $entries.= "`".$attr."`,";
273 $values .= "'".$val."',";
274 }
275 $values = preg_replace("/,$/","",$values);
276 $entries = preg_replace("/,$/","",$entries );
278 $SQL[]="INSERT INTO ".$a_SETUP['QUEUE_MEMBER_TABLE']." (".$entries.") VALUES (".$values.")";
279 }
280 }
283 /* generate Extension entries, with priority */
285 $queueusers=0;
286 foreach($this->parent->by_object['ogroup']->memberList as $member){
287 if(in_array("goFonAccount",$member['objectClass'])){
288 $queueusers++;
289 }
290 }
293 $i = 0;
294 foreach($this->telephoneNumber as $num){
296 // If there are no member in a Queue
297 // Play sound an quit
299 // A Queue is not deleted directly, it is stored until the o group is deleted
301 $a_ext[$i]['context'] = 'GOsa';
302 $a_ext[$i]['exten'] = $this->attrs['cn'][0];
303 $a_ext[$i]['priority'] = 1;
304 $a_ext[$i]['app'] = "Goto";
305 $a_ext[$i]['appdata'] = $num."|1";
306 $i ++ ;
308 if($queueusers == 0){
309 $a_ext[$i]['context'] = 'GOsa';
310 $a_ext[$i]['exten'] = $num;
311 $a_ext[$i]['priority'] = 1;
312 $a_ext[$i]['app'] = "SetLanguage";
313 $a_ext[$i]['appdata'] = "de";
314 $i ++ ;
316 $a_ext[$i]['context'] = 'GOsa';
317 $a_ext[$i]['exten'] = $num;
318 $a_ext[$i]['priority'] = 2;
319 $a_ext[$i]['app'] = "Playback";
320 $a_ext[$i]['appdata'] = "ss-noservice";
321 $i ++ ;
323 $a_ext[$i]['context'] = 'GOsa';
324 $a_ext[$i]['exten'] = $num;
325 $a_ext[$i]['priority'] = 3;
326 $a_ext[$i]['app'] = "Goto";
327 $a_ext[$i]['appdata'] = "default";
328 $i ++ ;
329 }else{
330 $prio --;
331 $a_ext[$i]['context'] = 'GOsa';
332 $a_ext[$i]['exten'] = $num;
333 $a_ext[$i]['priority'] = 1;
334 $a_ext[$i]['app'] = "Wait";
335 $a_ext[$i]['appdata'] = "2";
336 $i ++ ;
337 $a_ext[$i]['context'] = 'GOsa';
338 $a_ext[$i]['exten'] = $num;
339 $a_ext[$i]['priority'] = 2;
340 $a_ext[$i]['app'] = "SetLanguage";
341 $a_ext[$i]['appdata'] = $this->goFonQueueLanguage;
342 $i ++ ;
343 $a_ext[$i]['context'] = 'GOsa';
344 $a_ext[$i]['exten'] = $num;
345 $a_ext[$i]['priority'] = 3;
346 $a_ext[$i]['app'] = "Playback";
347 $a_ext[$i]['appdata'] = $this->goFonWelcomeMusic;
348 $i ++ ;
349 $a_ext[$i]['context'] = 'GOsa';
350 $a_ext[$i]['exten'] = $num;
351 $a_ext[$i]['priority'] = 4;
352 $a_ext[$i]['app'] = "SetCIDName";
353 if(!empty($this->parent->by_object['ogroup']->description)){
354 $a_ext[$i]['appdata'] = $this->parent->by_object['ogroup']->description;
355 }else{
356 $a_ext[$i]['appdata'] = $this->attrs['cn'][0]." - ".$num;
357 }
358 $i ++ ;
359 $a_ext[$i]['context'] = 'GOsa';
360 $a_ext[$i]['exten'] = $num;
361 $a_ext[$i]['priority'] = 5;
362 $a_ext[$i]['app'] = "SetVar";
363 $a_ext[$i]['appdata'] = $prio;
364 $i ++ ;
365 $a_ext[$i]['context'] = 'GOsa';
366 $a_ext[$i]['exten'] = $num;
367 $a_ext[$i]['priority'] = 6;
368 $a_ext[$i]['app'] = "Queue";
369 $a_ext[$i]['appdata'] = $this->attrs['cn'][0].
370 "|".
371 $this->goFonDialOption_t.
372 $this->goFonDialOption_T.
373 $this->goFonDialOption_h.
374 $this->goFonDialOption_H.
375 $this->goFonDialOption_r;
376 }
378 /* Generate Priority Entry */
379 $queue["announce"] = "";
380 $queue["monitor_join"] = "";
381 $queue["monitor_format"] = "";
382 $queue["queue_holdtime"] = $this->goFonQueueAnnounce;
383 $queue["queue_lessthan"] = "";
384 $queue["announce_round_seconds"]= "";
385 $queue["retry"] = $this->goFonQueueRetry;
386 $queue["wrapuptime"] = "";
387 $queue["servicelevel"] = "";
388 $queue["joinempty"] = "no";
389 $queue["leavewhenempty"] = "yes";
390 $queue["eventmemberstatus"] = "";
391 $queue["eventwhencalled"] = "";
392 $queue["reportholdtime"] = "yes";
393 $queue["memberdelay"] = "";
394 $queue["weight"] = "";
395 $queue["timeoutrestart"] = "";
397 $queue["context"] = "default";
398 $queue["name"] = $this->attrs['cn'][0];
399 $queue["timeout"] = $this->goFonTimeOut;
400 $queue["maxlen"] = $this->goFonMaxLen;
401 $queue["strategy" ] = $this->goFonQueueStrategy;
402 $queue["queue_thankyou"] = $this->goFonQueueThankYou;
403 $queue["queue_reporthold"] = $this->goFonQueueReportHold;
404 $queue["announce_frequency"] = $this->goFonAnnounceFrequency;
405 $queue["queue_youarenext"] = $this->goFonQueueYouAreNext;
406 $queue["queue_thereare"] = $this->goFonQueueThereAre;
407 $queue["queue_callswaiting"] = $this->goFonQueueCallsWaiting;
408 $queue["queue_minutes"] = $this->goFonQueueMinutes;
409 $queue["queue_seconds"] = $this->goFonQueueSeconds;
410 $queue["announce_holdtime"] = $this->goFonQueueAnnounceHoldtime;
411 $queue["musiconhold"] = $this->goFonMusiconHold;
413 $i++;
414 }
416 /* Parse and Add Extension entries */
417 foreach($a_ext as $ext){
418 $entries = "";
419 $values = "";
420 foreach($ext as $attr => $val){
421 $entries.= "`".$attr."`,";
422 $values .= "'".$val."',";
423 }
424 $values = preg_replace("/,$/","",$values);
425 $entries = preg_replace("/,$/","",$entries );
426 $SQL[]="INSERT INTO ".$a_SETUP['EXT_TABLE']." (".$entries.") VALUES (".$values.")";
427 }
430 /* Parse and Add Queue */
431 $entries = "";
432 $values = "";
433 foreach($queue as $attr=>$val){
434 if($val == "") continue;
435 $entries.= "`".$attr."`,";
436 $values .= "'".$val."',";
437 }
438 $values = preg_replace("/,$/","",$values);
439 $entries = preg_replace("/,$/","",$entries );
440 $SQL[]="INSERT INTO ".$a_SETUP['QUEUE_TABLE']." (".$entries.") VALUES (".$values.")";
442 foreach($SQL as $query){
443 if(!mysql_query($query)){
444 gosa_log(mysql_error());
445 print_red(mysql_error());
446 return(mysql_error(). sprintf(_("Can't delete in Database %s, on Server %s."),$a_SETUP['DB'],$a_SETUP['SERVER']));
447 }
448 }
450 }
451 return(false);
452 }
456 /* This function checks if the given phonenumbers are available or already in use*/
458 function is_number_used()
459 {
460 $ldap= $this->config->get_ldap_link();
461 $ldap->cd($this->config->current['BASE']);
462 $ldap->search("(|(objectClass=goFonAccount)(objectClass=goFonQueue))", array("telephoneNumber","cn","uid"));
463 while($attrs = $ldap->fetch()) {
464 unset($attrs['telephoneNumber']['count']);
465 foreach($attrs['telephoneNumber'] as $tele){
466 if(!isset($attrs['cn'][0])) $attrs['cn'][0]=$attrs['dn'];
467 if(!isset($attrs['uid'][0])) $attrs['uid'][0]=$attrs['dn'];
468 $numbers[$tele]=$attrs;
469 }
470 }
472 foreach($this->telephoneNumber as $num){
473 if((isset($numbers[$num]))&&(($numbers[$num]['cn'][0]!= $this->attrs['cn'][0]))){
474 if(isset($numbers[$num]['uid'][0])){
475 return sprintf(_("The specified telephonenumber '%s' is already assigned to '%s'."),$num,$numbers[$num]['uid'][0]);
476 }else{
477 return sprintf(_("The specified telephonenumber '%s' is already assigned to '%s'."),$num,$numbers[$num]['cn'][0]);
478 }
479 }
480 }
481 }
487 function save_object()
488 {
489 plugin::save_object();
490 if(isset($_POST['phonenumber'])){
491 foreach(array("goFonDialOption_t","goFonDialOption_T","goFonDialOption_h","goFonDialOption_r","goFonDialOption_H","goFonMusiconHold") as $val){
492 if(isset($_POST[$val])){
493 $this->$val = $_POST[$val];
494 }else{
495 $this->$val = false;
496 }
497 }
498 }
500 }
502 function save()
503 {
504 #fixme workaround : Tab is not initialised correct
505 if(!$this->is_account) return;
506 $ldap= $this->config->get_ldap_link();
508 plugin::save();
509 $this->attrs['goFonDialOption'] = "";
510 foreach(array("goFonDialOption_t","goFonDialOption_T","goFonDialOption_r","goFonDialOption_h","goFonDialOption_H") as $val){
511 $this->attrs['goFonDialOption'].=$this->$val;
512 unset($this->attrs[$val]);
513 }
514 $this->generate_mysql_entension_entries(true);
515 if($this->attrs['goFonDialOption']=="") $this->attrs['goFonDialOption']=array();
517 /* Save data to LDAP */
518 $ldap->cd($this->dn);
519 $ldap->modify($this->attrs);
521 show_ldap_error($ldap->get_error());
523 /* Optionally execute a command after we're done */
524 if ($this->initially_was_account == $this->is_account){
525 if ($this->is_modified){
526 $this->handle_post_events("mofify");
527 }
528 } else {
529 $this->handle_post_events("add");
530 }
531 }
534 /* remove object from parent */
535 function remove_from_parent()
536 {
537 $SQL = array();
539 // Get Configuration for Mysql database Server
540 $a_SETUP = $_SESSION['config']->data['SERVERS']['FON'];
541 $s_parameter ="";
543 // Connect to DB server
544 $r_con = @mysql_pconnect($a_SETUP['SERVER'],$a_SETUP['LOGIN'],$a_SETUP['PASSWORD']);
546 // Check if we are connected correctly
547 if(!$r_con){
548 gosa_log(mysql_error());
549 return (sprintf(_("The MySQL Server '%s' isn't reachable as user '%s', check GOsa log for mysql error."),
550 $a_SETUP['SERVER'],$a_SETUP['LOGIN']));
551 }
553 // Select database for Extensions
554 $db = @mysql_select_db($a_SETUP['DB'],$r_con);
556 // Test if we have the database selected correctly
557 if(!$db){
558 gosa_log(mysql_error());
559 return( sprintf(_("Can't select database %s on %s."),$a_SETUP['DB'],$a_SETUP['SERVER']));
560 }
562 $tmp = array_flip($this->attributes);
563 foreach(array("goFonDialOption_t","goFonDialOption_T","goFonDialOption_r","goFonDialOption_h","goFonDialOption_H") as $val){
564 unset($this->$val);
565 unset($this->attrs[$val]);
566 unset($tmp[$val]);
567 }
568 foreach(array_flip($tmp) as $key => $val){
569 $tmp2[]=$val;
570 }
571 $this->attributes = $tmp2;
573 $i = 0;
574 $prio = 11;
576 if(empty($this->cn)){
577 $this->cn = $this->parent->by_object['ogroup']->cn;
578 $this->attrs['cn'][0] = $this->parent->by_object['ogroup']->cn;
579 }
581 // Delete old Entries
582 $delete = array();
583 foreach($this->old_phone_numbers as $phone){
584 $delete[]= "DELETE FROM ".$a_SETUP['EXT_TABLE']." WHERE exten='".$phone."';\n";
585 }
586 $delete[]= "DELETE FROM ".$a_SETUP['EXT_TABLE']." WHERE exten='".$this->attrs['cn'][0]."';\n";
587 $delete[]= "DELETE FROM ".$a_SETUP['QUEUE_TABLE']." WHERE name=\"".$this->attrs['cn'][0]."\"; \n";
588 $delete[]= "DELETE FROM ".$a_SETUP['QUEUE_MEMBER_TABLE']." WHERE queue_name=\"".$this->attrs['cn'][0]."\";\n";
590 /* Perform queries to delte old entries */
591 foreach($delete as $query){
592 if(!mysql_query($query)){
593 gosa_log(mysql_error());
594 return(mysql_error(). sprintf(_("Can't delete in Database %s, on Server %s."),$a_SETUP['DB'],$a_SETUP['SERVER']));
595 }
596 }
600 /* Cancel if there's nothing to do here */
601 if (!$this->initially_was_account){
602 return;
603 }
605 /* include global link_info */
606 $ldap= $this->config->get_ldap_link();
608 /* Remove and write to LDAP */
609 plugin::remove_from_parent();
611 @DEBUG (DEBUG_LDAP, __LINE__, __FUNCTION__, __FILE__,
612 $this->attributes, "Save");
613 $ldap->cd($this->dn);
614 $ldap->modify($this->attrs);
615 show_ldap_error($ldap->get_error());
616 }
618 }
620 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
621 ?>