config= &$config; /* Check if there is a special ldap-sub-tree specified, instead of dc=addressbook, */ $aoc = $this->config->search("addressbook", "LDAP_OBJECT_CLASS",array('menu')); if ($aoc != ""){ $this->abobjectclass = $aoc; } /* Get global filter config */ if (!session::is_set("phonefilter")){ $ui = get_userinfo(); $base = get_base_from_people($ui->dn); $phonefilter= array( "search_base" => $base, "organizational" => "checked", "global" => "checked", "search_for" => "*", "object_type" => "*"); session::set("phonefilter", $phonefilter); } $this->ui = get_userinfo(); } function execute() { /* Call parent execute */ plugin::execute(); $smarty= get_smarty(); /* Prevent empty variables for smarty */ foreach($this->attributes as $atr) { $smarty->assign($atr,""); } /* Save formular information */ $phonefilter= session::get("phonefilter"); foreach( array("search_for", "search_base", "object_type") as $type){ if (isset($_POST[$type])){ $phonefilter[$type]= $_POST[$type]; } $this->$type= $phonefilter[$type]; } if (isset($_POST['search_base'])){ foreach( array("organizational", "global") as $type){ if (isset($_POST[$type])){ $phonefilter[$type]= "checked"; } else { $phonefilter[$type]= ""; } } } /* Search string */ $s= $phonefilter['search_for']; if ($s == "") { $s= "*"; } if (isset($_GET['search'])){ $s= validate(mb_substr($_GET['search'], 0, 1, "UTF8"))."*"; if ($s == "**"){ $s= "*"; } $this->search_for= $s; $phonefilter['search_for']= $s; } session::set("phonefilter", $phonefilter); /* Assign create acl */ $acl = $this->get_entry_acls($this->abobjectclass.",".$phonefilter['search_base']); $smarty->assign("internal_createable", preg_match("/c/",$acl)); $smarty->assign("internal_removeable", preg_match("/d/",$acl)); $smarty->assign("internal_editable", preg_match("/w/",$acl)); /* Perform actions with CTI hook */ if (isset($_GET['target']) && isset($_GET['dial']) && isset($this->config->current['CTIHOOK'])){ $dialmode= $_GET['dial']; if ($dialmode == "telephoneNumber" || $dialmode == "mobile" || $dialmode == "homePhone"){ /* Get target */ $ldap= $this->config->get_ldap_link(); $ldap->cat(base64_decode($_GET['target']), array('telephoneNumber', 'mobile', 'homePhone')); $attrs= $ldap->fetch(); if (isset($attrs["$dialmode"])){ $target= $attrs[$dialmode][0]; } else { $target= ""; } /* Get source */ $ui= get_userinfo(); $ldap->cat($ui->dn, array('telephoneNumber')); $attrs= $ldap->fetch(); if (isset($attrs["telephoneNumber"])){ $source= $attrs['telephoneNumber'][0]; } else { $source= ""; } /* Save to session */ session::set('source',$source); session::set('target',$target); /* Perform call */ if ($target != "" && $source != ""){ $smarty->assign("phone_image", get_template_path('images/phone.png')); $smarty->assign("dial_info", sprintf(_("Dial from %s to %s now?"), "".$source."", "".$target."")); return($smarty->fetch(get_template_path('dial.tpl', TRUE))); return; } else { msg_dialog::display(_("Error"), _("You need to set your personal phone number in order to perform direct dials."), ERROR_DIALOG); } } } /* Finally dial */ if (isset($_POST['dial']) && session::is_set('source') && session::is_set('target')){ exec ($this->config->current['CTIHOOK']." '".session::get('source')."' '".session::get('target')."'", $dummy, $retval); session::un_set('source'); session::un_set('target'); } /* Delete entry? */ if (isset($_POST['delete_entry_confirm'])){ /* Some nice guy may send this as POST, so we've to check for the permissions again. */ $acl = $this->get_entry_acls($this->dn); if(preg_match("/d/",$acl)){ /* Delete request is permitted, perform LDAP action */ $ldap= $this->config->get_ldap_link(); $ldap->rmdir ($this->dn); new log("remove","addressbook/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error()); if (!$ldap->success()){ msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class())); } new log("remove","addressbook/".get_class($this),$this->dn,array(),"Addressbook object'".$this->dn."' has been removed"); } else { /* Normally this shouldn't be reached, send some extra logs to notify the administrator */ msg_dialog::permDelete($this->dn); new log("remove","addressbook/".get_class($this),$this->dn,array(),"Warning: '".$this->ui->uid."' tried to trick address book deletion."); } /* Remove lock file after successfull deletion */ del_lock ($this->dn); /* Clean up */ if (session::is_set('saved_start')){ $_GET['start']= session::get('saved_start'); } session::un_set('show_info'); session::un_set('saved_start'); } /* Delete entry? */ if (isset($_POST['delete_cancel'])){ del_lock ($this->dn); } /* Save address entry? */ if (isset($_POST['save'])){ $this->save_object(); $this->storage_base= $_POST['storage_base']; /* Perform checks */ $message= $this->check (); /* No errors, save object */ if (count ($message) == 0){ $this->save(); /* Clean up */ if (session::is_set('saved_start')){ $_GET['start']= session::get('saved_start'); } session::set('show_info',$this->dn); session::un_set('saved_start'); } else { /* Errors found, show message */ msg_dialog::displayChecks($message); } } /* Close info window */ if (isset($_GET['close']) || isset($_POST['cancel'])){ if (session::is_set('saved_start')){ $_GET['start']= session::get('saved_start'); } session::un_set('show_info'); session::un_set('saved_start'); } /* Start address book edit mode? */ if (isset($_GET['global'])){ if (!session::is_set('saved_start') && isset($_GET['start'])){ session::set('saved_start',$_GET['start']); } switch ($_GET['global']){ case "add": $this->dn= "new"; $this->orig_cn= ""; /* Clean values */ foreach ($this->attributes as $name){ $this->$name= ""; } $this->saved_attributes= array(); $this->storage_base= $this->config->current["BASE"]; break; case "edit": /* Clean values */ foreach ($this->attributes as $name){ $this->$name= ""; } $this->dn= session::get('show_info'); $this->load(); $this->orig_cn= $this->cn; break; case "remove": $this->dn= session::get('show_info'); $this->load(); /* Load permissions for selected 'dn' and check if we're allowed to remove this 'dn' */ $acl = $this->get_entry_acls($this->dn); if(preg_match("/d/",$acl)){ /* Check locking, save current plugin in 'back_plugin', so the dialog knows where to return. */ if (($user= get_lock($this->dn)) != ""){ return(gen_locked_message ($user, $this->dn)); } /* Lock the current entry, so nobody will edit it during deletion */ $ui= get_userinfo(); add_lock ($this->dn, $ui->dn); $smarty->assign("info", msgPool::deleteInfo($this->dn)); return($smarty->fetch(get_template_path('remove.tpl', TRUE))); } else { /* Obviously the user isn't allowed to delete. Show message and clean session. */ msg_dialog::permDelete($this->dn); } } session::set('show_info',"ADD"); } /* Open info window */ if (isset($_GET['show'])){ if (!session::is_set('saved_start')){ session::set('saved_start',$_GET['start']); } $this->dn = base64_decode($_GET['show']); $this->view_logged =FALSE; if(!$this->view_logged){ $this->view_logged = TRUE; new log("view","addressbook/".get_class($this),$this->dn); } session::set('show_info',base64_decode($_GET['show'])); } /* Get ldap link / build filter */ $ldap= $this->config->get_ldap_link(); $this->telephone_list= array (); /* Assemble bases (Depending on checkboxes, we search for organisational entries or seperated adressbook entries within dc=adressbook, ) */ $bases= array(); $filter= ""; if ($phonefilter['global'] == "checked"){ $bases[]= preg_replace("/".$this->config->current['BASE']."/", $this->abobjectclass.",".$this->config->current['BASE'], $this->search_base); } else { $filter= '(objectClass=gosaAccount)'; } if ($phonefilter['organizational'] == "checked"){ $bases[]= $this->search_base; } /* Only display those entries that have at least on of this attributes set */ $must_have_this = array("telephoneNumber","facsimileTelephoneNumber","mobile","homePhone","mail"); /* Requested attributes in ldap search */ $attributes = array("sn", "givenName", "telephoneNumber", "facsimileTelephoneNumber", "mobile", "homePhone", "uid", "mail", "cn"); /* Create attribute filter part */ $attribute_filter = ""; foreach($attributes as $att){ $attribute_filter .= "(".$att."=".$s.")"; } /* Walk through bases an check for usable entries */ foreach ($bases as $base){ $ldap->cd ($base); if ($phonefilter['object_type'] == '*'){ $ldap->search ( "(&(objectClass=person)$filter(!(objectClass=gosaUserTemplate))". // Skip templates etc .. "(!(uid=*$))". // Skip entries with ...$ as uid "(|".$attribute_filter."))" ,$attributes); } else { $ldap->search ("(&$filter(!(uid=*$))(!(objectClass=gosaUserTemplate))". //array "(".$phonefilter['object_type']."=$s))", $attributes); } /* Walk through LDAP results */ while ($attrs= $ldap->fetch()){ /* prevent empty vaiables */ foreach($this->attributes as $atr) { if(!isset($attrs[$atr][0])) { $attrs[$atr][0] = ""; } } /* Check if page number was posted */ if(!isset($_GET['start'])) { $_GET['start']=""; } /* Check if at least one attribute is specified */ $skip = false; foreach($must_have_this as $attr) { if(isset($attrs[$attr][0]) && !empty($attrs[$attr][0])){ $skip =false; break; } } /* Skip all attributes that we are not allowed to read */ $any = false; foreach($attributes as $attr){ $acls = $this->get_entry_acls($attrs['dn'],$attr); if(!preg_match("/r/",$acls)){ $attrs[$attr][0] = ""; }else{ $any = true; } } /* Only show lines that have set any mail or phone informations */ if(!$skip && $any){ $this->telephone_list[$attrs['sn'][0].$attrs['dn']]= " ". $attrs['sn'][0].", ".$attrs['givenName'][0]. "   ".$attrs['telephoneNumber'][0]."   ".$attrs['facsimileTelephoneNumber'][0]."   ".$attrs['mobile'][0]."   ".$attrs['homePhone'][0]."   \"vcf\" "; if(preg_match("/r/",$this->get_entry_acls($attrs['dn'],"mail"))){ if (isset($attrs['mail'][0]) && !empty($attrs['mail'][0])){ $dest= sprintf(_("Send mail to %s"), $attrs['mail'][0]); $this->telephone_list[$attrs['sn'][0].$attrs['dn']].= "". "\"vcf\""; } } $this->telephone_list[$attrs['sn'][0].$attrs['dn']].= " "; } } error_reporting(E_ALL | E_STRICT); } /* Sort up list */ ksort ($this->telephone_list); reset ($this->telephone_list); /* Fill template variables */ $smarty->assign("search_for", $this->search_for); $smarty->assign("object_type", $this->object_type); $this->base = $phonefilter['search_base']; $smarty->assign("deplist", $this->get_allowed_bases()); $smarty->assign("depselect", $this->search_base); $smarty->assign("global", $phonefilter['global']); $smarty->assign("organizational", $phonefilter['organizational']); $smarty->assign("search_image", get_template_path('images/search.png')); $smarty->assign("obj_image", get_template_path('images/list_ogroup.png')); $smarty->assign("tree_image", get_template_path('images/tree.png')); $smarty->assign("infoimage", get_template_path('images/info.png')); $smarty->assign("actionimage", get_template_path('images/action.png')); $smarty->assign("launchimage", get_template_path('images/launch.png')); /* Generate alphabet */ $alphabet= generate_alphabet(); /* Build list output */ $output= ""; $mod= 0; /* View detailed infos */ $smarty->assign("show_info", ""); if (session::is_set('show_info')){ $range= 4; $smarty->assign("show_info", "1"); $smarty->assign("url", "main.php?plug=".validate($_GET['plug'])."&close=1"); $tmp = $this->plInfo(); if(isset($_POST['storage_base'])){ $this->storage_base = $_POST['storage_base']; } switch (session::get('show_info')){ case "ADD": $a_bases = $this->get_allowed_bases(); if(!isset($a_bases[$this->storage_base])){ $base = key($this->get_allowed_bases()); $this->storage_base = $base; } $smarty->assign ('storage_base', $this->storage_base); $smarty->assign ('address_info', get_template_path('address_edit.tpl', TRUE)); foreach($tmp['plProvidedAcls'] as $name => $translated){ $smarty->assign($name."ACL",$this->get_entry_acls($this->abobjectclass.",".$base,$name)); } break; default: $smarty->assign ('address_info', get_template_path('address_info.tpl', TRUE)); foreach($tmp['plProvidedAcls'] as $name => $translated){ $smarty->assign($name."ACL",$this->get_entry_acls($this->dn,$name)); } break; } /* Fill variables from LDAP */ if (session::get('show_info') != "ADD"){ $ldap->cat(session::get('show_info'), $this->attributes); $info= $ldap->fetch(); } foreach ($this->attributes as $name){ /* Skip entries we are not allowed to read */ if(!preg_match("/r/",$this->get_entry_acls($this->dn,$name))){ $smarty->assign("info_$name", ""); }else if (session::get('show_info') != "ADD" && isset($info["$name"][0])){ error_reporting(0); /* Special treatment for phone attributes */ if ($name == "mobile" || $name == "homePhone" || $name == "telephoneNumber"){ $smarty->assign("info_$name", "".$info["$name"][0].""); } else { $smarty->assign("info_$name", preg_replace("/\n/", "
", $info["$name"][0])); } error_reporting(E_ALL | E_STRICT); } elseif (session::get('show_info') == "ADD" && isset($this->$name)) { $smarty->assign("info_$name", $this->$name); } else { $smarty->assign("info_$name", "-"); } } if (preg_match("/,".$this->abobjectclass.",/", session::get('show_info'))){ $storage= _("global addressbook"); $smarty->assign("internal", 0); } else { $storage= _("user database"); $smarty->assign("internal", 1); } if (session::get('show_info') != "ADD"){ $smarty->assign("storage_info", sprintf(_("Contact stored in '%s'"), $storage)); } else { $smarty->assign("storage_info", _("Creating new entry in")); } } else { if(isset($_POST['EntryPerPage'])){ $this->range = $_POST['EntryPerPage']; } $range = $this->range; $smarty->assign("internal", 1); } if (isset($_GET['start'])){ $this->start= validate($_GET['start']); } foreach ($this->telephone_list as $val){ if ($mod < $this->start) { $mod++; continue; } if ($mod >= ($this->start + $range)){ $mod++; break; } if ( ($mod++) & 1){ $col= "style=\"background-color: #ECECEC;\""; } else { $col= "style=\"background-color: #F5F5F5;\""; } $output.= "\n$val\n"; } $smarty->assign("search_result", $output); $smarty->assign("apply", apply_filter()); $smarty->assign("alphabet", $alphabet); if($range < 20){ $smarty->assign("range_selector", range_selector(count($this->telephone_list), $this->start, $range)); }else{ $smarty->assign("range_selector", range_selector(count($this->telephone_list), $this->start, $range, "EntryPerPage")); } $tmp= array("*" => _("All"), "sn" => _("Name"), "givenName" => _("Given name"), "telephoneNumber" => _("Work phone"), "mobile" => _("Cell phone"), "homePhone" => _("Home phone"), "uid" => _("User ID")); natsort($tmp); $smarty->assign("objlist", $tmp); /* Show main page */ $smarty->assign ('personal_image', get_template_path('images/addr_personal.png')); $smarty->assign ('home_image', get_template_path('images/addr_home.png')); $smarty->assign ('company_image', get_template_path('images/addr_company.png')); $smarty->assign ('add_image', get_template_path('images/lists/paste.png')); $smarty->assign ('edit_image', get_template_path('images/edit.png')); $smarty->assign ('delete_image', get_template_path('images/lists/delete.png')); return($smarty->fetch(get_template_path('contents.tpl', TRUE))); } function save_object() { plugin::save_object(); foreach($this->attributes as $attr){ /* save attributes depending on acls */ $acl = $this->get_entry_acls($this->dn,$attr); if(preg_match("/w/",$acl)){ if(isset($_POST[$attr])){ $this->$attr = $_POST[$attr]; } } } } function check() { /* Call common method to give check the hook */ $message= plugin::check(); /* must: sn, givenName */ if ($this->sn == ""){ $message[] = msgPool::required(_("Name")); return ($message); } if ($this->givenName == ""){ $message[] = msgPool::required(_("Given name")); return ($message); } /* Check for valid name definition */ if (preg_match ("/[\\\\]/", $this->sn)){ $message[] = msgPool::invalid(_("Name"),$this->sn,"/[\\\\]"); } if (preg_match ("/[\\\\]/", $this->givenName)){ $message[] = msgPool::invalid(_("Given name"),$this->givenName,"/[\\\\]"); } /* Check phone numbers */ if (!tests::is_phone_nr($this->homePhone)){ $message[] = msgPool::invalid(_("Phone"),$this->homePhone); } if (!tests::is_phone_nr($this->telephoneNumber)){ $message[] = msgPool::invalid(_("Telephone number"),$this->telephoneNumber); } if (!tests::is_phone_nr($this->facsimileTelephoneNumber)){ $message[] = msgPool::invalid(_("Fax"),$this->facsimileTelephoneNumber); } if (!tests::is_phone_nr($this->mobile)){ $message[] = msgPool::invalid(_("Mobile"),$this->mobile); } if (!tests::is_phone_nr($this->pager)){ $message[] = msgPool::invalid(_("Pager"),$this->pager); } /* Check for reserved characers */ if (preg_match ('/[,+"<>;]/', $this->givenName)){ $message[] = msgPool::invalid(_("Given name"),$this->givenName,'/[,+"<>;]/'); } if (preg_match ('/[,+"<>;]/', $this->sn)){ $message[] = msgPool::invalid(_("Name"),$this->sn,'/[,+"<>;]/'); } /* Check mail */ if (!tests::is_email($this->mail)){ $message[] = msgPool::invalid(_("Email"),"","","your-domain@your-domain.com"); } /* Assemble cn/dn */ $this->cn= $this->givenName." ".$this->sn; if ($this->orig_cn != $this->cn || $this->storage_base != $this->orig_storage_base){ $this->new_dn= $this->create_unique_dn("cn", preg_replace("/,*".$this->config->current['BASE']."$/", "", $this->storage_base).",".$this->abobjectclass.",".$this->config->current['BASE']); if ($this->new_dn == "none"){ $message[]= _("Cannot create a unique DN for your entry. Please fill more formular fields."); return ($message); } } else { $this->new_dn= $this->dn; } return ($message); } function load() { /* Load base attributes */ plugin::plugin ($this->config, $this->dn); $this->view_logged = FALSE; $this->storage_base= preg_replace('/^[^,]+,/', '', preg_replace('/'.$this->abobjectclass.',/', '', $this->dn)); } function save() { /* First use parents methods to do some basic fillup in $this->attrs */ plugin::save (); $this->attrs['cn']= $this->cn; $this->attrs['displayName']= $this->givenName." ".$this->sn; /* Move entry if it got another name... */ if ($this->dn != "new" && $this->dn != $this->new_dn){ $this->move($this->dn, $this->new_dn); } $this->dn= $this->new_dn; /* Save data. Using 'modify' implies that the entry is already present, use 'add' for new entries. So do a check first... */ $ldap= $this->config->get_ldap_link(); $ldap->cat ($this->dn,array('dn')); if ($ldap->fetch()){ $mode= "modify"; } else { $mode= "add"; $ldap->cd($this->config->current['BASE']); $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $this->dn)); } /* Finally write data with selected 'mode' */ $ldap->cd ($this->dn); $this->cleanup(); $ldap->$mode ($this->attrs); if (!$ldap->success()){ msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class())); return (1); } if($mode == "add"){ new log("create","addressbook/".get_class($this),$this->dn, array_keys($this->attrs),$ldap->get_error()); }else{ new log("modify","addressbook/".get_class($this),$this->dn, array_keys($this->attrs),$ldap->get_error()); } } /* Return entry acls */ function get_entry_acls($dn,$attr = "") { $acls = ""; /* Use addressbook acls */ if(preg_match("/".normalizePreg($this->abobjectclass)."/",$dn)) { $dn = preg_replace("/".normalizePreg($this->abobjectclass).",/","",$dn); $acls = $this->ui->get_permissions($dn,"addressbook/addressbook",$attr); } /* Use Organizational Person acls */ else{ $acls = $this->ui->get_permissions($dn,"users/user",$attr); } return($acls); } /* Return plugin informations for acl handling */ static function plInfo() { return (array( "plShortName" => _("Addressbook"), "plDescription" => _("Addressbook entry acls"), "plSelfModify" => FALSE, "plDepends" => array(), "plPriority" => 0, "plSection" => array("addons" => _("Addons")), "plCategory" => array("addressbook" => array("objectClass" => "inetOrgPerson", "description" => _("Addressbook"))), "plProvidedAcls" => array( "sn" => _("Surename"), "givenName" => _("Given name"), "telephoneNumber" => _("Telefon number"), "facsimileTelephoneNumber" => _("Fax number"), "mobile" => _("Mobile number"), "homePhone" => _("Home phone number"), "uid" => _("User identification"), "mail" => _("Mail address"), "pager" => _("Pager"), "o" => _("Organization"), "ou" => _("Department"), "l" => _("Location"), "postalAddress" => _("Postal address"), "postalCode" => _("Postal address"), "st" => _("State"), "initials" => _("Initials"), "title" => _("Title"), "homePostalAddress" => _("Home postal address"), "cn" => _("Common name")) )); } } // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: ?>