LDIF export
This commit is contained in:
parent
f2d77dc851
commit
1d7db3794b
|
@ -342,6 +342,14 @@ $helpArray = array (
|
||||||
// import/export
|
// import/export
|
||||||
"750" => array ("Headline" => _('LDIF data'),
|
"750" => array ("Headline" => _('LDIF data'),
|
||||||
"Text" => _('The input data must be formatted in LDIF format.')),
|
"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
|
// 800 - 899
|
||||||
// jobs
|
// jobs
|
||||||
'800' => array(
|
'800' => array(
|
||||||
|
|
|
@ -854,6 +854,32 @@ function ldapGetDN($dn, $attributes = array('dn'), $handle = null) {
|
||||||
return $return;
|
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.
|
* Deletes a DN and all child entries.
|
||||||
*
|
*
|
||||||
|
|
|
@ -43,6 +43,8 @@ class Exporter {
|
||||||
|
|
||||||
const DATA = 'data';
|
const DATA = 'data';
|
||||||
const STATUS = 'status';
|
const STATUS = 'status';
|
||||||
|
const FILE = 'file';
|
||||||
|
const OUTPUT = 'output';
|
||||||
|
|
||||||
private $baseDn = null;
|
private $baseDn = null;
|
||||||
private $searchScope = null;
|
private $searchScope = null;
|
||||||
|
@ -84,6 +86,8 @@ class Exporter {
|
||||||
public function doExport() {
|
public function doExport() {
|
||||||
try {
|
try {
|
||||||
$this->checkParameters();
|
$this->checkParameters();
|
||||||
|
$results = $this->getLDAPData();
|
||||||
|
return $this->writeDataAndReturnJson($results);
|
||||||
}
|
}
|
||||||
catch (LAMException $e) {
|
catch (LAMException $e) {
|
||||||
$data = Exporter::formatMessage('ERROR', $e->getTitle(), $e->getMessage());
|
$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('#statusExportInprogress').hide();
|
||||||
jQuery('#statusExportDone').show();
|
jQuery('#statusExportDone').show();
|
||||||
jQuery('.newexport').show();
|
jQuery('.newexport').show();
|
||||||
|
if (jsonData.output) {
|
||||||
|
jQuery('#exportResults > pre').text(jsonData.output);
|
||||||
|
}
|
||||||
|
else if (jsonData.file) {
|
||||||
|
window.open(jsonData.file, '_blank');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
jQuery('#progressbarExport').hide();
|
jQuery('#progressbarExport').hide();
|
||||||
|
@ -994,6 +1000,13 @@ window.lam.importexport.startExport = function(tokenName, tokenValue) {
|
||||||
jQuery('#statusExportFailed').show();
|
jQuery('#statusExportFailed').show();
|
||||||
jQuery('.newexport').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 = new htmlResponsiveRow();
|
||||||
$container->add(new htmlTitle(_("Export")), 12);
|
$container->add(new htmlTitle(_("Export")), 12);
|
||||||
|
|
||||||
$container->addLabel(new htmlOutputText(_('Base DN'), true, true));
|
$container->add(new htmlResponsiveInputField(_('Base DN'), 'baseDn', getDefaultBaseDn(), '751', true), 12);
|
||||||
$baseDnGroup = new htmlGroup();
|
|
||||||
$baseDnInput = new htmlInputField('baseDn', getDefaultBaseDn());
|
|
||||||
$baseDnInput->setRequired(true);
|
|
||||||
$baseDnGroup->addElement($baseDnInput);
|
|
||||||
$container->addField($baseDnGroup);
|
|
||||||
|
|
||||||
$searchScopes = array(
|
$searchScopes = array(
|
||||||
_('Base (base dn only)') => 'base',
|
_('Base (base dn only)') => 'base',
|
||||||
|
@ -278,9 +273,9 @@ function printExportTabContent(&$tabindex) {
|
||||||
$searchScopeSelect->setHasDescriptiveElements(true);
|
$searchScopeSelect->setHasDescriptiveElements(true);
|
||||||
$searchScopeSelect->setSortElements(false);
|
$searchScopeSelect->setSortElements(false);
|
||||||
$container->add($searchScopeSelect, 12);
|
$container->add($searchScopeSelect, 12);
|
||||||
$container->add(new htmlResponsiveInputField(_('Search filter'), 'filter', '(objectClass=*)'), 12);
|
$container->add(new htmlResponsiveInputField(_('Search filter'), 'filter', '(objectClass=*)', '752'), 12);
|
||||||
$container->add(new htmlResponsiveInputField(_('Attributes'), 'attributes', '*'), 12);
|
$container->add(new htmlResponsiveInputField(_('Attributes'), 'attributes', '*', '753'), 12);
|
||||||
$container->add(new htmlResponsiveInputCheckbox('includeSystem', false, _('Include system attributes')), 12);
|
$container->add(new htmlResponsiveInputCheckbox('includeSystem', false, _('Include system attributes'), '754'), 12);
|
||||||
$container->add(new htmlResponsiveInputCheckbox('saveAsFile', false, _('Save as file')), 12);
|
$container->add(new htmlResponsiveInputCheckbox('saveAsFile', false, _('Save as file')), 12);
|
||||||
|
|
||||||
$formats = array(
|
$formats = array(
|
||||||
|
@ -375,7 +370,9 @@ function printExportTabProcessing(&$tabindex) {
|
||||||
|
|
||||||
$container->addVerticalSpacer('3rem');
|
$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(
|
$container->add(new htmlJavaScript(
|
||||||
'window.lam.importexport.startExport(\'' . getSecurityTokenName() . '\', \'' . getSecurityTokenValue() . '\');'
|
'window.lam.importexport.startExport(\'' . getSecurityTokenName() . '\', \'' . getSecurityTokenValue() . '\');'
|
||||||
), 12);
|
), 12);
|
||||||
|
|
Loading…
Reference in New Issue