LDIF export
This commit is contained in:
parent
f2d77dc851
commit
1d7db3794b
|
@ -342,6 +342,14 @@ $helpArray = array (
|
|||
// import/export
|
||||
"750" => array ("Headline" => _('LDIF data'),
|
||||
"Text" => _('The input data must be formatted in LDIF format.')),
|
||||
"751" => array ("Headline" => _('Base DN'),
|
||||
"Text" => _('The export will read entries of this DN.')),
|
||||
"752" => array ("Headline" => _('Search filter'),
|
||||
"Text" => _('Please enter an LDAP filter to specifiy the exported entries.')),
|
||||
"753" => array ("Headline" => _('Attributes'),
|
||||
"Text" => _('Please enter a comma separated list of attributes to export. Using "*" will export all attributes.')),
|
||||
"754" => array ("Headline" => _('Include system attributes'),
|
||||
"Text" => _('Activate this option to export internal attributes that are not visible by default.')),
|
||||
// 800 - 899
|
||||
// jobs
|
||||
'800' => array(
|
||||
|
|
|
@ -854,6 +854,32 @@ function ldapGetDN($dn, $attributes = array('dn'), $handle = null) {
|
|||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DN and children of a given DN.
|
||||
*
|
||||
* @param String $dn DN
|
||||
* @param String $filter LDAP filter
|
||||
* @param array $attributes list of attributes to fetch
|
||||
* @param handle $handle LDAP handle (optional for admin interface pages)
|
||||
* @return array attributes or null if not found
|
||||
*/
|
||||
function ldapListDN($dn, $filter = '(objectclass=*)', $attributes = array('dn'), $handle = null) {
|
||||
if ($handle == null) {
|
||||
$handle = $_SESSION['ldap']->server();
|
||||
}
|
||||
$return = null;
|
||||
$sr = @ldap_list($handle, escapeDN($dn), $filter, $attributes, 0, 0, 0, LDAP_DEREF_NEVER);
|
||||
if ($sr) {
|
||||
$entries = ldap_get_entries($handle, $sr);
|
||||
if ($entries) {
|
||||
cleanLDAPResult($entries);
|
||||
$return = $entries;
|
||||
}
|
||||
@ldap_free_result($sr);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a DN and all child entries.
|
||||
*
|
||||
|
|
|
@ -43,6 +43,8 @@ class Exporter {
|
|||
|
||||
const DATA = 'data';
|
||||
const STATUS = 'status';
|
||||
const FILE = 'file';
|
||||
const OUTPUT = 'output';
|
||||
|
||||
private $baseDn = null;
|
||||
private $searchScope = null;
|
||||
|
@ -84,6 +86,8 @@ class Exporter {
|
|||
public function doExport() {
|
||||
try {
|
||||
$this->checkParameters();
|
||||
$results = $this->getLDAPData();
|
||||
return $this->writeDataAndReturnJson($results);
|
||||
}
|
||||
catch (LAMException $e) {
|
||||
$data = Exporter::formatMessage('ERROR', $e->getTitle(), $e->getMessage());
|
||||
|
@ -124,4 +128,151 @@ class Exporter {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the LDAP entries
|
||||
*
|
||||
* @return array[] LDAP entries
|
||||
*/
|
||||
private function getLDAPData() {
|
||||
$attributes = preg_split('/,[ ]*/', $this->attributes);
|
||||
if ($this->includeSystem) {
|
||||
$attributes = array_merge($attributes, array('+', 'passwordRetryCount', 'accountUnlockTime', 'nsAccountLock',
|
||||
'nsRoleDN', 'passwordExpirationTime', 'pwdChangedTime'));
|
||||
}
|
||||
$attributes = array_unique($attributes);
|
||||
switch ($this->searchScope) {
|
||||
case 'base':
|
||||
return array(ldapGetDN($this->baseDn, $attributes));
|
||||
break;
|
||||
case 'one':
|
||||
return ldapListDN($this->baseDn, $this->filter, $attributes);
|
||||
break;
|
||||
case 'sub':
|
||||
return searchLDAP($this->baseDn, $this->filter, $attributes);
|
||||
break;
|
||||
default:
|
||||
throw new LAMException('Invalid scope');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the entries to file/response and prints JSON.
|
||||
*
|
||||
* @param array $entries LDAP entries
|
||||
*/
|
||||
private function writeDataAndReturnJson(&$entries) {
|
||||
$lineEnding = ($this->ending === 'windows') ? "\r\n" : "\n";
|
||||
if ($this->format === 'csv') {
|
||||
$output = $this->getCsvOutput($entries, $lineEnding);
|
||||
}
|
||||
elseif ($this->format === 'ldif') {
|
||||
$output = $this->getLdifOutput($entries, $lineEnding);
|
||||
}
|
||||
else {
|
||||
throw new LAMException('Invalid format');
|
||||
}
|
||||
if ($this->saveAsFile) {
|
||||
$filename = '../../tmp/' . getRandomNumber() . time() .'.' . $this->format;
|
||||
$handle = fopen($filename, 'w');
|
||||
chmod($filename, 0640);
|
||||
fwrite($handle, $output);
|
||||
fclose($handle);
|
||||
return json_encode(array(
|
||||
Exporter::FILE => $filename,
|
||||
Exporter::STATUS => 'done'
|
||||
));
|
||||
}
|
||||
return json_encode(array(
|
||||
Exporter::OUTPUT => htmlspecialchars($output),
|
||||
Exporter::STATUS => 'done'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given LDAP entries to CSV format.
|
||||
*
|
||||
* @param string $entries entries
|
||||
* @param string $lineEnding line ending
|
||||
*/
|
||||
private function getCsvOutput(&$entries, $lineEnding) {
|
||||
return 'CSV';
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given LDAP entries to LDIF format.
|
||||
*
|
||||
* @param string $entries entries
|
||||
* @param string $lineEnding line ending
|
||||
*/
|
||||
private function getLdifOutput(&$entries, $lineEnding) {
|
||||
$output = '';
|
||||
$output .= '#' . $lineEnding;
|
||||
$output .= '# ' . _('Base DN') . ': ' . $this->baseDn . $lineEnding;
|
||||
$output .= '# ' . _('Search scope') . ': ' . $this->searchScope . $lineEnding;
|
||||
$output .= '# ' . _('Search filter') . ': ' . $this->filter . $lineEnding;
|
||||
$output .= '# ' . _('Total entries') . ': ' . sizeof($entries) . $lineEnding;
|
||||
$output .= '#' . $lineEnding;
|
||||
$output .= '# Generated by LDAP Account Manager on ' . date('Y-m-d H:i:s') . $lineEnding;
|
||||
$output .= $lineEnding;
|
||||
$output .= $lineEnding;
|
||||
$output .= 'version: 1';
|
||||
$output .= $lineEnding;
|
||||
$output .= $lineEnding;
|
||||
foreach ($entries as $entry) {
|
||||
$output .= 'dn: ' . $entry['dn'] . $lineEnding;
|
||||
unset($entry['dn']);
|
||||
ksort($entry);
|
||||
foreach ($entry as $attributeName => $values) {
|
||||
foreach ($values as $value) {
|
||||
if ($this->isPlainAscii($value)) {
|
||||
$output .= $this->wrapLdif($attributeName . ': ' . $value, $lineEnding) . $lineEnding;
|
||||
}
|
||||
else {
|
||||
$output .= $this->wrapLdif($attributeName . ':: ' . base64_encode($value), $lineEnding) . $lineEnding;
|
||||
}
|
||||
}
|
||||
}
|
||||
$output .= $lineEnding;
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the LDIF line if needed.
|
||||
*
|
||||
* @param string $content line content
|
||||
* @param string $lineEnding line ending
|
||||
*/
|
||||
private function wrapLdif($content, $lineEnding) {
|
||||
$line_length = 76;
|
||||
if (strlen($content) <= $line_length) {
|
||||
return $content;
|
||||
}
|
||||
$wrappedContent = substr($content, 0, $line_length) . $lineEnding;
|
||||
$contentLeft = substr($content, $line_length);
|
||||
$line_length = $line_length - 1;
|
||||
$lines = str_split($contentLeft, $line_length);
|
||||
foreach ($lines as $line) {
|
||||
$wrappedContent .= ' ' . $line . $lineEnding;
|
||||
}
|
||||
return trim($wrappedContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is plain ASCII.
|
||||
*
|
||||
* @param string $content content to check
|
||||
* @return bool is plain ASCII
|
||||
*/
|
||||
private function isPlainAscii($content) {
|
||||
for ($i=0; $i < strlen($content); $i++) {
|
||||
if (ord($content[$i]) < 32 || ord($content[$i]) > 127) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -986,6 +986,12 @@ window.lam.importexport.startExport = function(tokenName, tokenValue) {
|
|||
jQuery('#statusExportInprogress').hide();
|
||||
jQuery('#statusExportDone').show();
|
||||
jQuery('.newexport').show();
|
||||
if (jsonData.output) {
|
||||
jQuery('#exportResults > pre').text(jsonData.output);
|
||||
}
|
||||
else if (jsonData.file) {
|
||||
window.open(jsonData.file, '_blank');
|
||||
}
|
||||
}
|
||||
else {
|
||||
jQuery('#progressbarExport').hide();
|
||||
|
@ -994,6 +1000,13 @@ window.lam.importexport.startExport = function(tokenName, tokenValue) {
|
|||
jQuery('#statusExportFailed').show();
|
||||
jQuery('.newexport').show();
|
||||
}
|
||||
})
|
||||
.fail(function() {
|
||||
jQuery('#progressbarExport').hide();
|
||||
jQuery('#btn_submitExportCancel').hide();
|
||||
jQuery('#statusExportInprogress').hide();
|
||||
jQuery('#statusExportFailed').show();
|
||||
jQuery('.newexport').show();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -262,12 +262,7 @@ function printExportTabContent(&$tabindex) {
|
|||
$container = new htmlResponsiveRow();
|
||||
$container->add(new htmlTitle(_("Export")), 12);
|
||||
|
||||
$container->addLabel(new htmlOutputText(_('Base DN'), true, true));
|
||||
$baseDnGroup = new htmlGroup();
|
||||
$baseDnInput = new htmlInputField('baseDn', getDefaultBaseDn());
|
||||
$baseDnInput->setRequired(true);
|
||||
$baseDnGroup->addElement($baseDnInput);
|
||||
$container->addField($baseDnGroup);
|
||||
$container->add(new htmlResponsiveInputField(_('Base DN'), 'baseDn', getDefaultBaseDn(), '751', true), 12);
|
||||
|
||||
$searchScopes = array(
|
||||
_('Base (base dn only)') => 'base',
|
||||
|
@ -278,9 +273,9 @@ function printExportTabContent(&$tabindex) {
|
|||
$searchScopeSelect->setHasDescriptiveElements(true);
|
||||
$searchScopeSelect->setSortElements(false);
|
||||
$container->add($searchScopeSelect, 12);
|
||||
$container->add(new htmlResponsiveInputField(_('Search filter'), 'filter', '(objectClass=*)'), 12);
|
||||
$container->add(new htmlResponsiveInputField(_('Attributes'), 'attributes', '*'), 12);
|
||||
$container->add(new htmlResponsiveInputCheckbox('includeSystem', false, _('Include system attributes')), 12);
|
||||
$container->add(new htmlResponsiveInputField(_('Search filter'), 'filter', '(objectClass=*)', '752'), 12);
|
||||
$container->add(new htmlResponsiveInputField(_('Attributes'), 'attributes', '*', '753'), 12);
|
||||
$container->add(new htmlResponsiveInputCheckbox('includeSystem', false, _('Include system attributes'), '754'), 12);
|
||||
$container->add(new htmlResponsiveInputCheckbox('saveAsFile', false, _('Save as file')), 12);
|
||||
|
||||
$formats = array(
|
||||
|
@ -375,7 +370,9 @@ function printExportTabProcessing(&$tabindex) {
|
|||
|
||||
$container->addVerticalSpacer('3rem');
|
||||
|
||||
$container->add(new htmlDiv('exportResults', new htmlOutputText('')), 12);
|
||||
$exportText = new htmlOutputText('');
|
||||
$exportText->setPreformatted(true);
|
||||
$container->add(new htmlDiv('exportResults', $exportText), 12);
|
||||
$container->add(new htmlJavaScript(
|
||||
'window.lam.importexport.startExport(\'' . getSecurityTokenName() . '\', \'' . getSecurityTokenValue() . '\');'
|
||||
), 12);
|
||||
|
|
Loading…
Reference in New Issue