\version 2.00 \date 24.07.2003 This is the base class for all plugins. It can be used standalone or can be included by the tabs class. All management should be done within this class. Extend your plugins from this class. */ class plugin { /*! \brief Reference to parent object This variable is used when the plugin is included in tabs and keeps reference to the tab class. Communication to other tabs is possible by 'name'. So the 'fax' plugin can ask the 'userinfo' plugin for the fax number. \sa tab */ var $parent= NULL; /*! \brief Configuration container Access to global configuration */ var $config= NULL; /*! \brief Mark plugin as account Defines whether this plugin is defined as an account or not. This has consequences for the plugin to be saved from tab mode. If it is set to 'FALSE' the tab will call the delete function, else the save function. Should be set to 'TRUE' if the construtor detects a valid LDAP object. \sa plugin::plugin() */ var $is_account= FALSE; var $initially_was_account= FALSE; /*! \brief Mark plugin as template Defines whether we are creating a template or a normal object. Has conseqences on the way execute() shows the formular and how save() puts the data to LDAP. \sa plugin::save() plugin::execute() */ var $is_template= FALSE; var $ignore_account= FALSE; var $is_modified= FALSE; /*! \brief Represent temporary LDAP data This is only used internally. */ var $attrs= array(); /*! \brief Used standard values dn */ var $dn= ""; var $uid= ""; var $sn= ""; var $givenName= ""; var $acl= "*none*"; var $dialog= FALSE; /* attribute list for save action */ var $attributes= array(); var $objectclasses= array(); var $new= TRUE; /*! \brief plugin constructor If 'dn' is set, the node loads the given 'dn' from LDAP \param dn Distinguished name to initialize plugin from \sa plugin() */ function plugin ($config, $dn= NULL) { /* Configuration is fine, allways */ $this->config= $config; $this->dn= $dn; /* Handle new accounts, don't read information from LDAP */ if ($dn == "new"){ return; } /* Get LDAP descriptor */ $ldap= $this->config->get_ldap_link(); if ($dn != NULL){ /* Load data to 'attrs' and save 'dn' */ $ldap->cat ($dn); $this->attrs= $ldap->fetch(); /* Copy needed attributes */ foreach ($this->attributes as $val){ if (isset($this->attrs["$val"][0])){ $this->$val= $this->attrs["$val"][0]; } } /* Set the template flag according to the existence of objectClass gosaUserTemplate */ if (isset($this->attrs['objectClass'])){ if (in_array ("gosaUserTemplate", $this->attrs['objectClass'])){ $this->is_template= TRUE; @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "found", "Template check"); } } /* Is Account? */ error_reporting(0); $found= TRUE; foreach ($this->objectclasses as $obj){ if (preg_match('/top/i', $obj)){ continue; } if (!in_array_ics ($obj, $this->attrs['objectClass'])){ $found= FALSE; break; } } error_reporting(E_ALL); if ($found){ $this->is_account= TRUE; @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "found", "Object check"); } } /* Save initial account state */ $this->initially_was_account= $this->is_account; } /*! \brief execute plugin Generates the html output for this node */ function execute() { /* Do we represent a valid account? */ if (!$this->is_account){ echo " ". _("This 'dn' has no account extensions.").""; return; } /* Show dummy message */ echo _("This is an empty plugin."); } /* remove object from parent */ function remove_from_parent() { /* include global link_info */ $ldap= $this->config->get_ldap_link(); /* Get current objectClasses in order to add the required ones */ $ldap->cat($this->dn); $tmp= $ldap->fetch (); if (isset($tmp['objectClass'])){ $oc= $tmp['objectClass']; } else { $oc= array("count" => 0); } /* Remove objectClasses from entry */ $ldap->cd($this->dn); $this->attrs= array(); $this->attrs['objectClass']= array(); for ($i= 0; $i<$oc["count"]; $i++){ if (!in_array_ics($oc[$i], $this->objectclasses)){ $this->attrs['objectClass'][]= $oc[$i]; } } /* Unset attributes from entry */ foreach ($this->attributes as $val){ $this->attrs["$val"]= array(); } /* Unset account info */ $this->is_account= FALSE; /* Do not write in plugin base class, this must be done by children, since there are normally additional attribs, lists, etc. */ /* $ldap->modify($this->attrs); */ } /* Save data to object */ function save_object() { /* Save values to object */ foreach ($this->attributes as $val){ if (chkacl ($this->acl, "$val") == "" && isset ($_POST["$val"])){ /* Check for modifications */ if (get_magic_quotes_gpc()) { $data= stripcslashes($_POST["$val"]); } else { $data= $this->$val = $_POST["$val"]; } if ($this->$val != $data){ $this->is_modified= TRUE; } $this->$val= $data; } } } /* Save data to LDAP, depending on is_account we save or delete */ function save() { /* include global link_info */ $ldap= $this->config->get_ldap_link(); /* Start with empty array */ $this->attrs= array(); /* Get current objectClasses in order to add the required ones */ $ldap->cat($this->dn); $tmp= $ldap->fetch (); if (isset($tmp['objectClass'])){ $oc= $tmp["objectClass"]; $this->new= FALSE; } else { $oc= array("count" => 0); $this->new= TRUE; } /* Load (minimum) attributes, add missing ones */ $this->attrs['objectClass']= $this->objectclasses; for ($i= 0; $i<$oc["count"]; $i++){ if (!in_array_ics($oc[$i], $this->objectclasses)){ $this->attrs['objectClass'][]= $oc[$i]; } } /* Copy standard attributes */ foreach ($this->attributes as $val){ if ($this->$val != ""){ $this->attrs["$val"]= $this->$val; } elseif (!$this->new) { $this->attrs["$val"]= array(); } } } /* Check formular input */ function check() { $message= array(); return ($message); } /* Adapt from template, using 'dn' */ function adapt_from_template($dn) { /* Include global link_info */ $ldap= $this->config->get_ldap_link(); /* Load requested 'dn' to 'attrs' */ $ldap->cat ($dn); $this->attrs= $ldap->fetch(); /* Walk through attributes */ foreach ($this->attributes as $val){ if (isset($this->attrs["$val"][0])){ /* If attribute is set, replace dynamic parts: %sn, %givenName and %uid. Fill these in our local variables. */ $value= $this->attrs["$val"][0]; foreach (array("sn", "givenName", "uid") as $repl){ if (preg_match("/%$repl/i", $value)){ $value= preg_replace ("/%$repl/i", $this->parent->$repl, $value); } } $this->$val= $value; } } /* Is Account? */ $found= TRUE; foreach ($this->objectclasses as $obj){ if (preg_match('/top/i', $obj)){ continue; } if (!in_array_ics ($obj, $this->attrs['objectClass'])){ $found= FALSE; break; } } if ($found){ $this->is_account= TRUE; } } /* Indicate whether a password change is needed or not */ function password_change_needed() { return FALSE; } /* Show header message for tab dialogs */ function show_header($button_text, $text, $disabled= FALSE) { if ($disabled == TRUE){ $state= "disabled"; } else { $state= ""; } $display= "\n

$text

\n"; $display.= "acl, "all")." ".$state. ">

 

"; return($display); } function postcreate() { /* Find postcreate entries for this class */ $command= $this->search($this->config->data['MENU'], get_class($this), "POSTCREATE"); if ($command == ""){ $command= $this->search($this->config->data['SERVICE'], get_class($this), "POSTCREATE"); } if ($command != ""){ /* Walk through attribute list */ foreach ($this->attributes as $attr){ $command= preg_replace("/%$attr/", $this->$attr, $command); } $command= preg_replace("/%dn/", $this->dn, $command); if (check_command($command)){ @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Execute"); exec($command); } else { $message= sprintf(_("Command '%s', specified as POSTCREATE for plugin '%s' doesn't seem to exist."), $command, get_class($this)); print_red ($message); } } } function postmodify() { /* Find postcreate entries for this class */ $command= $this->search($this->config->data['MENU'], get_class($this), "POSTMODIFY"); if ($command == ""){ $command= $this->search($this->config->data['SERVICE'], get_class($this), "POSTMODIFY"); } if ($command != ""){ /* Walk through attribute list */ foreach ($this->attributes as $attr){ $command= preg_replace("/%$attr/", $this->$attr, $command); } $command= preg_replace("/%dn/", $this->dn, $command); if (check_command($command)){ @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Execute"); exec($command); } else { $message= sprintf(_("Command '%s', specified as POSTMODIFY for plugin '%s' doesn't seem to exist."), $command, get_class($this)); print_red ($message); } } } function postremove() { /* Find postremove entries for this class */ $command= $this->search($this->config->data['MENU'], get_class($this), "POSTREMOVE"); if ($command == ""){ $command= $this->search($this->config->data['SERVICE'], get_class($this), "POSTREMOVE"); } if ($command != ""){ /* Walk through attribute list */ foreach ($this->attributes as $attr){ $command= preg_replace("/%$attr/", $this->$attr, $command); } $command= preg_replace("/%dn/", $this->dn, $command); if (check_command($command)){ @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Execute"); exec($command); } else { $message= sprintf(_("Command '%s', specified as POSTREMOVE for plugin '%s' doesn't seem to exist."), $command, get_class($this)); print_red ($message); } } } function search($arr, $name, $return) { if (is_array($arr)){ foreach ($arr as $a){ if (isset($a['CLASS']) && strtolower($a['CLASS']) == strtolower($name)){ if (isset($a[$return])){ return ($a[$return]); } else { return (""); } } else { $res= $this->search ($a, $name, $return); if ($res != ""){ return $res; } } } } return (""); } /* Create unique DN */ function create_unique_dn($attribute, $base) { $ldap= $this->config->get_ldap_link(); $base= preg_replace("/^,*/", "", $base); /* Try to use plain entry first */ $dn= "$attribute=".$this->$attribute.",$base"; $ldap->cat ($dn); if (!$ldap->fetch()){ return ($dn); } /* Look for additional attributes */ foreach ($this->attributes as $attr){ if ($attr == $attribute || $this->$attr == ""){ continue; } $dn= "$attribute=".$this->$attribute."+$attr=".$this->$attr.",$base"; $ldap->cat ($dn); if (!$ldap->fetch()){ return ($dn); } } /* None found */ return ("none"); } function rebind($ldap, $referral) { $credentials= LDAP::get_credentials($referral, $this->config->current['REFERRAL']); if (ldap_bind($ldap, $credentials['ADMIN'], $credentials['PASSWORD'])) { $this->error = "Success"; $this->hascon=true; $this->reconnect= true; return (0); } else { $this->error = "Could not bind to " . $binddn; return NULL; } } /* This is a workaround function. */ function copy($src_dn, $dst_dn) { /* Rename dn in possible object groups */ $ldap= $this->config->get_ldap_link(); $ldap->search('(&(objectClass=gosaGroupOfNames)(member='.$src_dn.'))', array('cn')); while ($attrs= $ldap->fetch()){ $og= new ogroup($this->config, $ldap->getDN()); unset($og->member[$src_dn]); $og->member[$dst_dn]= $dst_dn; $og->save (); } $ldap->cat($dst_dn); $attrs= $ldap->fetch(); if (count($attrs)){ trigger_error("Trying to overwrite $dst_dn, which already exists.", E_USER_WARNING); return (FALSE); } $ldap->cat($src_dn); $attrs= array(); $attrs= $ldap->fetch(); if (!count($attrs)){ trigger_error("Trying to move $src_dn, which does not seem to exist.", E_USER_WARNING); return (FALSE); } /* Grummble. This really sucks. PHP ldap doesn't support rdn stuff. */ $ds= ldap_connect($this->config->current['SERVER']); ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); if (function_exists("ldap_set_rebind_proc") && isset($this->config->current['REFERRAL'])) { ldap_set_rebind_proc($ds, array(&$this, "rebind")); } $r=ldap_bind($ds,$this->config->current['ADMIN'], $this->config->current['PASSWORD']); error_reporting (0); $sr=ldap_read($ds, $src_dn, "objectClass=*"); /* Fill data from LDAP */ $new= array(); if ($sr) { $ei=ldap_first_entry($ds, $sr); if ($ei) { foreach($attrs as $attr => $val){ if ($info = ldap_get_values_len($ds, $ei, $attr)){ for ($i= 0; $i<$info['count']; $i++){ if ($info['count'] == 1){ $new[$attr]= $info[$i]; } else { $new[$attr][]= $info[$i]; } } } } } } /* close conncetion */ error_reporting (E_ALL); ldap_unbind($ds); /* Adapt naming attribute */ $dst_name= preg_replace("/^([^=]+)=.*$/", "\\1", $dst_dn); $dst_val = preg_replace("/^[^=]+=([^,+]+).*,.*$/", "\\1", $dst_dn); $new[$dst_name]= $dst_val; /* Save copy */ $ldap->connect(); $ldap->cd($this->config->current['BASE']); $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $dst_dn)); $ldap->cd($dst_dn); $ldap->add($new); if ($ldap->error != "Success"){ trigger_error("Trying to save $dst_dn failed.", E_USER_WARNING); return(FALSE); } return (TRUE); } function move($src_dn, $dst_dn) { /* Copy source to destination */ if (!$this->copy($src_dn, $dst_dn)){ return (FALSE); } /* Delete source */ $ldap= $this->config->get_ldap_link(); $ldap->rmdir($src_dn); if ($ldap->error != "Success"){ trigger_error("Trying to delete $src_dn failed.", E_USER_WARNING); return (FALSE); } return (TRUE); } /* Move/Rename complete trees */ function recursive_move($src_dn, $dst_dn) { /* Check if the destination entry exists */ $ldap= $this->config->get_ldap_link(); /* Check if destination exists - abort */ $ldap->cat($dst_dn); if ($ldap->fetch()){ trigger_error("recursive_move $dst_dn already exists.", E_USER_WARNING); return (FALSE); } /* Perform a search for all objects to be moved */ $objects= array(); $ldap->cd($src_dn); $ldap->search("(objectClass=*)", array("dn")); while($attrs= $ldap->fetch()){ $dn= $attrs['dn']; $objects[$dn]= strlen($dn); } /* Sort objects by indent level */ asort($objects); reset($objects); /* Copy objects from small to big indent levels by replacing src_dn by dst_dn */ foreach ($objects as $object => $len){ $src= $object; $dst= preg_replace("/$src_dn$/", "$dst_dn", $object); if (!$this->copy($src, $dst)){ return (FALSE); } } /* Remove src_dn */ $ldap->cd($src_dn); $ldap->recursive_remove(); return (TRUE); } function handle_post_events($mode) { switch ($mode){ case "add": $this->postcreate(); break; case "modify": $this->postmodify(); break; case "remove": $this->postremove(); break; } } } // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: ?>