'; echo "
\n"; echo ''; include __DIR__ . '/../../lib/adminFooter.inc'; } /** * Runs the dry run and change actions. * * @param htmlResponsiveRow $container container */ function runActions(htmlResponsiveRow &$container) { // LDAP suffix if ($_POST['suffix'] == '-') { $suffix = trim($_POST['otherSuffix']); } else { $suffix = $_POST['suffix']; } if (empty($suffix)) { $error = new htmlStatusMessage('ERROR', _('LDAP Suffix is invalid!')); $error->colspan = 5; $container->add($error, 12); return; } // LDAP filter $filter = trim($_POST['filter']); // operations $operations = array(); for ($i = 0; $i < $_POST['opcount']; $i++) { if (!empty($_POST['attr_' . $i])) { $operations[] = array($_POST['op_' . $i], strtolower(trim($_POST['attr_' . $i])), trim($_POST['val_' . $i])); } } if (sizeof($operations) == 0) { $error = new htmlStatusMessage('ERROR', _('Please specify at least one operation.')); $error->colspan = 5; $container->add($error, 12); return; } $_SESSION['multiEdit_suffix'] = $suffix; $_SESSION['multiEdit_filter'] = $filter; $_SESSION['multiEdit_operations'] = $operations; $_SESSION['multiEdit_status'] = array('stage' => STAGE_START); $_SESSION['multiEdit_dryRun'] = isset($_POST['dryRun']); // disable all input elements $jsContent = ' jQuery(\'input\').attr(\'disabled\', true); jQuery(\'select\').attr(\'disabled\', true); jQuery(\'button\').attr(\'disabled\', true); '; $container->add(new htmlJavaScript($jsContent), 12); // progress area $container->add(new htmlSubTitle(_('Progress')), 12); $progressBarDiv = new htmlDiv('progressBar', ''); $progressBarDiv->colspan = 5; $container->add($progressBarDiv, 12); $progressDiv = new htmlDiv('progressArea', ''); $progressDiv->colspan = 5; $container->add($progressDiv, 12); // JS block for AJAX status update $ajaxBlock = ' jQuery.get(\'multiEdit.php?ajaxStatus\', null, function(data) {handleReply(data);}, \'json\'); function handleReply(data) { jQuery(\'#progressBar\').progressbar({value: data.progress, max: 120}); jQuery(\'#progressArea\').html(data.content); if (data.status != "finished") { jQuery.get(\'multiEdit.php?ajaxStatus\', null, function(data) {handleReply(data);}, \'json\'); } else { jQuery(\'input\').removeAttr(\'disabled\'); jQuery(\'select\').removeAttr(\'disabled\'); jQuery(\'button\').removeAttr(\'disabled\'); jQuery(\'#progressBar\').hide(); } } '; $container->add(new htmlJavaScript($ajaxBlock), 12); } /** * Performs the modify operations. */ function runAjaxActions() { $jsonReturn = array( 'status' => STAGE_START, 'progress' => 0, 'content' => '' ); switch ($_SESSION['multiEdit_status']['stage']) { case STAGE_START: $jsonReturn = readLDAPData(); break; case STAGE_READ_FINISHED: $jsonReturn = generateActions(); break; case STAGE_ACTIONS_CALCULATED: case STAGE_WRITING: if ($_SESSION['multiEdit_dryRun']) { $jsonReturn = dryRun(); } else { $jsonReturn = doModify(); } break; } echo json_encode($jsonReturn); } /** * Reads the LDAP entries from the directory. * * @return array status */ function readLDAPData() { $suffix = $_SESSION['multiEdit_suffix']; $filter = $_SESSION['multiEdit_filter']; if (empty($filter)) { $filter = '(objectClass=*)'; } $operations = $_SESSION['multiEdit_operations']; $attributes = array(); foreach ($operations as $op) { if (!in_array(strtolower($op[1]), $attributes)) { $attributes[] = strtolower($op[1]); } } // run LDAP query $results = searchLDAP($suffix, $filter, $attributes); // print error message if no data returned if (empty($results)) { $code = ldap_errno($_SESSION['ldap']->server()); if ($code !== 0) { $msg = new htmlStatusMessage('ERROR', _('Encountered an error while performing search.'), getDefaultLDAPErrorString($_SESSION['ldap']->server())); } else { $msg = new htmlStatusMessage('ERROR', _('No objects found!')); } $content = getMessageHTML($msg); return array( 'status' => STAGE_FINISHED, 'progress' => 120, 'content' => $content ); } // save LDAP data $_SESSION['multiEdit_status']['entries'] = $results; $_SESSION['multiEdit_status']['stage'] = STAGE_READ_FINISHED; return array( 'status' => STAGE_READ_FINISHED, 'progress' => 10, 'content' => '' ); } /** * Generates the required actions based on the read LDAP data. * * @return array status */ function generateActions() { $actions = array(); foreach ($_SESSION['multiEdit_status']['entries'] as $entry) { $dn = $entry['dn']; foreach ($_SESSION['multiEdit_operations'] as $op) { $opType = $op[0]; $attr = $op[1]; $val = $op[2]; switch ($opType) { case ADD: if (empty($entry[$attr]) || !in_array_ignore_case($val, $entry[$attr])) { $actions[] = array(ADD, $dn, $attr, $val); } break; case MOD: if (empty($entry[$attr])) { // attribute not yet exists, add it $actions[] = array(ADD, $dn, $attr, $val); } elseif (!empty($entry[$attr]) && !in_array_ignore_case($val, $entry[$attr])) { // attribute exists and value is not included, replace old values $actions[] = array(MOD, $dn, $attr, $val); } break; case DEL: if (empty($val) && !empty($entry[$attr])) { $actions[] = array(DEL, $dn, $attr, null); } elseif (!empty($val) && isset($entry[$attr]) && in_array($val, $entry[$attr])) { $actions[] = array(DEL, $dn, $attr, $val); } break; } } } // save actions $_SESSION['multiEdit_status']['actions'] = $actions; $_SESSION['multiEdit_status']['stage'] = STAGE_ACTIONS_CALCULATED; return array( 'status' => STAGE_ACTIONS_CALCULATED, 'progress' => 20, 'content' => '' ); } /** * Prints the dryRun output. * * @return array status */ function dryRun() { $pro = isLAMProVersion() ? ' Pro' : ''; $ldif = '# LDAP Account Manager' . $pro . ' ' . LAMVersion() . "\n\nversion: 1\n\n"; $log = ''; // fill LDIF and log file $lastDN = ''; foreach ($_SESSION['multiEdit_status']['actions'] as $action) { $opType = $action[0]; $dn = $action[1]; $attr = $action[2]; $val = $action[3]; if ($lastDN != $dn) { if ($lastDN != '') { $log .= "\r\n"; } $lastDN = $dn; $log .= $dn . "\r\n"; } if ($lastDN != '') { $ldif .= "\n"; } $ldif .= 'dn: ' . $dn . "\n"; $ldif .= 'changetype: modify' . "\n"; switch ($opType) { case ADD: $log .= '+' . $attr . '=' . $val . "\r\n"; $ldif .= 'add: ' . $attr . "\n"; $ldif .= $attr . ': ' . $val . "\n"; break; case DEL: $ldif .= 'delete: ' . $attr . "\n"; if (empty($val)) { $log .= '-' . $attr . "\r\n"; } else { $log .= '-' . $attr . '=' . $val . "\r\n"; $ldif .= $attr . ': ' . $val . "\n"; } break; case MOD: $log .= '*' . $attr . '=' . $val . "\r\n"; $ldif .= 'replace: ' . $attr . "\n"; $ldif .= $attr . ': ' . $val . "\n"; break; } } // build meta HTML $container = new htmlTable(); $container->addElement(new htmlOutputText(_('Dry run finished.')), true); $container->addVerticalSpace('20px'); // store LDIF $filename = 'ldif' . getRandomNumber() . '.ldif'; $out = @fopen(dirname(__FILE__) . '/../../tmp/' . $filename, "wb"); fwrite($out, $ldif); $container->addElement(new htmlOutputText(_('LDIF file')), true); $ldifLink = new htmlLink($filename, '../../tmp/' . $filename); $ldifLink->setTargetWindow('_blank'); $container->addElement($ldifLink, true); $container->addVerticalSpace('20px'); $container->addElement(new htmlOutputText(_('Log output')), true); $container->addElement(new htmlInputTextarea('log', $log, 100, 30), true); // generate HTML fclose ($out); ob_start(); $tabindex = 1; parseHtml(null, $container, array(), true, $tabindex, 'user'); $content = ob_get_contents(); ob_end_clean(); return array( 'status' => STAGE_FINISHED, 'progress' => 120, 'content' => $content ); } /** * Error handler * * @param int $errno error number * @param string $errstr error message * @param string $errfile error file * @param int $errline error line */ function multiEditLdapErrorHandler($errno, $errstr, $errfile, $errline) { switch ($errno) { case E_USER_ERROR: logNewMessage(LOG_ERR, 'Error occured: ' . $errstr . " ($errfile: $errline)"); $_REQUEST['multiEdit_error'] = true; break; case E_USER_WARNING: logNewMessage(LOG_WARNING, 'Error occured: ' . $errstr . " ($errfile: $errline)"); $_REQUEST['multiEdit_error'] = true; break; } } /** * Runs the actual modifications. * * @return array status */ function doModify() { set_error_handler('\LAM\TOOLS\MULTI_EDIT\multiEditLdapErrorHandler'); // initial action index if (!isset($_SESSION['multiEdit_status']['index'])) { $_SESSION['multiEdit_status']['index'] = 0; } // initial content if (!isset($_SESSION['multiEdit_status']['modContent'])) { $_SESSION['multiEdit_status']['modContent'] = ''; } // run 10 modifications in each call $localCount = 0; while (($localCount < 10) && ($_SESSION['multiEdit_status']['index'] < sizeof($_SESSION['multiEdit_status']['actions']))) { $action = $_SESSION['multiEdit_status']['actions'][$_SESSION['multiEdit_status']['index']]; $opType = $action[0]; $dn = $action[1]; $attr = $action[2]; $val = $action[3]; $_SESSION['multiEdit_status']['modContent'] .= htmlspecialchars($dn) . "