<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><title>Module HowTo - Account pages</title> <link rel="stylesheet" type="text/css" href="style/layout.css"></head> <link rel="shortcut icon" type="image/x-icon" href="images/favicon.ico"> <body> <div style="text-align: center;"> <h1>Module HowTo - Account pages<br> </h1> <br> <br> <div style="text-align: left;"><br> <h2>1. Loading the LDAP attributes<br> </h2> Every time the user selects an existing account to modify LAM will load the complete LDAP entry of it. Your module then should select the attributes which are useful for it.<br> There are two variables in <span style="font-style: italic;">baseModule</span> which should be used to store the attributes. The <span style="font-weight: bold;">$attributes</span> variable stores the current attributes including changes the user made. The <span style="font-weight: bold;">$orig</span> variable stores the attributes as they were originally when the account was loaded. This allows you to see what changes were made.<br> <br> The <span style="font-weight: bold;">load_attributes()</span> function in your module gets the complete attribute list from LDAP.<br> <br> <span style="font-weight: bold; text-decoration: underline;">Example:</span><br style="font-weight: bold; text-decoration: underline;"> <br> The <span style="font-style: italic;">ieee802Device</span> uses an object class and the <span style="font-style: italic;">'macAddress'</span> attribute. Therefore we will save these two values.<br> <br> <table style="width: 100%; text-align: left;" class="mod-code" border="0" cellpadding="2" cellspacing="2"> <tbody> <tr> <td style="vertical-align: top;"> /**<br> * This function loads all needed attributes into the object.<br> *<br> * @param array $attr an array as it is retured from ldap_get_attributes<br> */<br> <span style="font-weight: bold;">function</span> <span style="color: rgb(255, 0, 0);">load_attributes</span>($attr) {<br> $this->attributes['objectClass'] = array();<br> $this->attributes['macAddress'] = array();<br> $this->orig['objectClass'] = array();<br> $this->orig['macAddress'] = array();<br> if (isset($attr['objectClass'])) {<br> $this->attributes['objectClass'] = $attr['objectClass'];<br> $this->orig['objectClass'] = $attr['objectClass'];<br> }<br> if (isset($attr['macAddress'])) {<br> $this->attributes['macAddress'] = $attr['macAddress'];<br> $this->orig['macAddress'] = $attr['macAddress'];<br> }<br> return 0;<br> }<br> </td> </tr> </tbody> </table> <br> <br> <h2>2. Page display</h2> Now that you have defined your subpages you will need one function for each page to display it. The function must return <span style="font-style: italic;">meta HTML code</span> as defined in the <span style="font-style: italic;">modules specification</span>.<br> This function is called <span style="font-weight: bold;">display_html_<page name>()</span> where <span style="font-style: italic;"><page name></span> is the name of your subpage.<br> <br> <span style="font-weight: bold; text-decoration: underline;">Example:</span><br style="font-weight: bold; text-decoration: underline;"> <br> The <span style="font-style: italic;">ieee802Device</span> module has only one subpage called <span style="font-style: italic;">'attributes'</span>.<br> <br> The first half of the code displays the existing MAC addresses and the second an input field for new values.<br> The variable <span style="font-style: italic;">$this->attributes</span> contains the LDAP attributes which are useful for this module.<br> <br> <table style="width: 100%; text-align: left;" class="mod-code" border="0" cellpadding="2" cellspacing="2"> <tbody> <tr> <td style="vertical-align: top;"> /**<br> * This function will create the meta HTML code to show a page with all attributes.<br> *<br> * @param array $post HTTP-POST values<br> */<br> <span style="font-weight: bold;">function</span> <span style="color: rgb(255, 0, 0);">display_html_attributes</span>($post) {<br> $return = array();<br> // list current MACs<br> for ($i = 0; $i < sizeof($this->attributes['macAddress']); $i++) {<br> $return[] = array(<br> array('kind' => 'text', 'text' => _('MAC address')),<br> array('kind' => 'input', 'name' => 'macAddress' . $i, 'type' => 'text', 'size' => '17', 'maxlength' => '17', 'value' => $this->attributes['macAddress'][$i]),<br> array('kind' => 'input', 'type' => 'submit', 'name' => 'delMAC' . $i, 'value' => _("Remove")),<br> array('kind' => 'help', 'value' => 'mac'));<br> }<br> // input box for new MAC<br> $return[] = array(<br> array('kind' => 'text', 'text' => _('New MAC address')),<br> array('kind' => 'input', 'name' => 'macAddress', 'type' => 'text', 'size' => '17', 'maxlength' => '17', 'value' => ''),<br> array('kind' => 'input', 'type' => 'submit', 'name' => 'addMAC', 'value' => _("Add")),<br> array('kind' => 'help', 'value' => 'mac'),<br> array('kind' => 'input', 'type' => 'hidden', 'value' => sizeof($this->attributes['macAddress']), 'name' => 'mac_number'));<br> return $return;<br> }<br> </td> </tr> </tbody> </table> <br> <br> <h2>3. Processing input data<br> </h2> Every time the user clicks on a submit button while your page is displayed LAM will call a function in your module.<br> This function is called <span style="font-weight: bold;">process_<page name>()</span> where <span style="font-style: italic;"><page name></span> is the name of your subpage.<br> <br> If all input data is ok then return an empty array. If you return one or more error messages then the user will be redirected to your page.<br> <br> <span style="font-weight: bold; text-decoration: underline;">Example:</span><br style="font-weight: bold; text-decoration: underline;"> <br> The <span style="font-style: italic;">ieee802Device</span> module has only one subpage called <span style="font-style: italic;">'attributes'</span> and therefore only <span style="font-style: italic;">process_attributes()</span>.<br> <br> The function checks the input fields and fills the LDAP attributes. If all is ok it will enable the user to move to another module page.<br> <br> <table style="width: 100%; text-align: left;" class="mod-code" border="0" cellpadding="2" cellspacing="2"> <tbody> <tr> <td style="vertical-align: top;"> /**<br> * Write variables into object and do some regex checks<br> *<br> * @param array $post HTTP-POST values<br> */<br> <span style="font-weight: bold;">function</span> <span style="color: rgb(255, 0, 0);">process_attributes</span>($post) {<br> $errors = array();<br> $this->attributes['macAddress'] = array();<br> // check old MACs<br> if (isset($post['mac_number'])) {<br> for ($i = 0; $i < $post['mac_number']; $i++) {<br> if (isset($post['delMAC' . $i])) continue;<br> if (isset($post['macAddress' . $i]) && ($post['macAddress' . $i] != "")) {<br> // check if address has correct format<br> if (!get_preg($post['macAddress' . $i], 'macAddress')) {<br> $message = $this->messages['mac'][0];<br> $message[] = $post['macAddress' . $i];<br> $errors[] = $message;<br> }<br> $this->attributes['macAddress'][] = $post['macAddress' . $i];<br> }<br> }<br> }<br> // check new MAC<br> if (isset($post['macAddress']) && ($post['macAddress'] != "")) {<br> // check if address has correct format<br> if (get_preg($post['macAddress'], 'macAddress')) {<br> $this->attributes['macAddress'][] = $post['macAddress'];<br> }<br> else {<br> $message = $this->messages['mac'][0];<br> $message[] = $post['macAddress'];<br> $errors[] = $message;<br> }<br> }<br> $this->attributes['macAddress'] = array_unique($this->attributes['macAddress']);<br> return $errors;<br> }<br> </td> </tr> </tbody> </table> <br> <br> <h2>4. Defining that your module is ready for user input and LDAP add/modify</h2> In most cases you will not need to implement these functions. The <span style="font-style: italic;">baseModule</span> will return <span style="font-style: italic;">true</span> for both functions.<br> <br> <span style="text-decoration: underline;"><br> There are two functions which control the module status:</span><br style="text-decoration: underline;"> <br> The <span style="font-weight: bold;">module_ready()</span> function has to return <span style="font-style: italic;">true</span> if the user may move to your module page. If it is <span style="font-style: italic;">false</span> the user will be shown an error message that your module is not yet ready. You can use this if your module depends on input data from other modules (e.g. you need the user name from posixAccount first).<br> <br> The second function is <span style="font-weight: bold;">module_complete()</span>. The user cannot do the LDAP operation if one or more modules return <span style="font-style: italic;">false</span>. This defines if all needed input data for your module was entered.<br> Use this function if you want to check that all required attributes are set.<br> <br> <span style="font-weight: bold; text-decoration: underline;">Example:</span><br style="font-weight: bold; text-decoration: underline;"> <br> The <span style="font-style: italic;">sambaSamAccount</span> module needs the user's <span style="font-style: italic;">uidNumber</span> and <span style="font-style: italic;">gidNumber</span> before it can accept input and the account needs a <span style="font-style: italic;">sambaSID</span> before it can be saved.<br> <br> <table style="width: 100%; text-align: left;" class="mod-code" border="0" cellpadding="2" cellspacing="2"> <tbody> <tr> <td style="vertical-align: top;"> /**<br> * This function is used to check if this module page can be displayed.<br> * It returns false if a module depends on data from other modules which was not yet entered.<br> *<br> * @return boolean true, if page can be displayed<br> */<br> <span style="font-weight: bold;">function</span> <span style="color: rgb(255, 0, 0);">module_ready</span>() {<br> if ($_SESSION[$this->base]->module['posixAccount']->attributes['gidNumber'][0]=='') return false;<br> if ($_SESSION[$this->base]->module['posixAccount']->attributes['uidNumber'][0]=='') return false;<br> if ($this->attributes['uid'][0]=='') return false;<br> return true;<br> }<br> <br> /**<br> * This functions is used to check if all settings for this module have been made.<br> *<br> * @return boolean true, if settings are complete<br> */<br> <span style="font-weight: bold;">function</span> <span style="color: rgb(255, 0, 0);">module_complete</span>() {<br> if (!$this->module_ready()) return false;<br> if ($this->attributes['sambaSID'][0] == '') return false;<br> return true;<br> }<br> <br> </td> </tr> </tbody> </table> <br> <br> <h2>5. Saving the LDAP attributes<br> </h2> In most cases you will not have to implement this option if you use <span style="font-weight: bold;">$this->attributes</span> and <span style="font-weight: bold;">$this->orig</span> to manage the LDAP attributes. The <span style="font-style: italic;">baseModule</span> will generate the save comands for you.<br> <br> When all modules report that they are ready for LDAP add/modify and the user clicks on the add/modify button your module will be asked what changes have to be made.<br> This is done in the function <span style="font-weight: bold;">save_attributes()</span>.<br> <br> <span style="font-weight: bold; text-decoration: underline;">Example:</span><br style="font-weight: bold; text-decoration: underline;"> <br> The <span style="font-style: italic;">kolabUser</span> module uses this function to make sure that its object class is saved. Other modules (e.g. quota) use it build the lamdaemon commands.<br> <br> <table style="width: 100%; text-align: left;" class="mod-code" border="0" cellpadding="2" cellspacing="2"> <tbody> <tr> <td style="vertical-align: top;"> /**<br> * Returns a list of modifications which have to be made to the LDAP account.<br> *<br> * @return array list of modifications<br> * <br>This function returns an array with 3 entries:<br> * <br>array( DN1 ('add' => array($attr), 'remove' => array($attr), 'modify' => array($attr)), DN2 .... )<br> * <br>DN is the DN to change. It may be possible to change several DNs (e.g. create a new user and add him to some groups via attribute memberUid)<br> * <br>"add" are attributes which have to be added to LDAP entry<br> * <br>"remove" are attributes which have to be removed from LDAP entry<br> * <br>"modify" are attributes which have to been modified in LDAP entry<br> */<br> function save_attributes() {<br> // add object class if needed<br> if (!isset($this->attributes['objectClass']) || !in_array('kolabInetOrgPerson', $this->attributes['objectClass'])) {<br> $this->attributes['objectClass'][] = 'kolabInetOrgPerson';<br> }<br> return parent::save_attributes();<br> }<br> </td> </tr> </tbody> </table> <br> <br> <span style="font-weight: bold;"></span> <h2><span style="font-weight: bold;"></span></h2> </div> </div> </body></html>