import tool
This commit is contained in:
parent
a4c867d6b3
commit
c9cff54937
|
@ -330,7 +330,7 @@ $helpArray = array (
|
||||||
"Text" => _("This will create a new organisational unit under the selected one.")),
|
"Text" => _("This will create a new organisational unit under the selected one.")),
|
||||||
"602" => array ("Headline" => _("OU-Editor") . " - " . _("Delete organisational unit"),
|
"602" => array ("Headline" => _("OU-Editor") . " - " . _("Delete organisational unit"),
|
||||||
"Text" => _("This will delete the selected organisational unit. The OU has to be empty.")),
|
"Text" => _("This will delete the selected organisational unit. The OU has to be empty.")),
|
||||||
// 700 - 799
|
// 700 - 749
|
||||||
// multi edit tool
|
// multi edit tool
|
||||||
"700" => array ("Headline" => _('LDAP suffix'),
|
"700" => array ("Headline" => _('LDAP suffix'),
|
||||||
"Text" => _('Please select the suffix where changes should be done.')),
|
"Text" => _('Please select the suffix where changes should be done.')),
|
||||||
|
@ -338,6 +338,10 @@ $helpArray = array (
|
||||||
"Text" => _('Use this to enter an additional LDAP filter (e.g. "(cn!=admin)") to reduce the number of entries to modify.')),
|
"Text" => _('Use this to enter an additional LDAP filter (e.g. "(cn!=admin)") to reduce the number of entries to modify.')),
|
||||||
"702" => array ("Headline" => _('Operations'),
|
"702" => array ("Headline" => _('Operations'),
|
||||||
"Text" => _('Please specify which attributes should be changed. The modify operation will also add an value if the attribute does not yet exist. To delete all values of an attribute please leave the value field empty.')),
|
"Text" => _('Please specify which attributes should be changed. The modify operation will also add an value if the attribute does not yet exist. To delete all values of an attribute please leave the value field empty.')),
|
||||||
|
// 750 - 799
|
||||||
|
// import/export
|
||||||
|
"750" => array ("Headline" => _('LDIF data'),
|
||||||
|
"Text" => _('The input data must be formatted in LDIF format.')),
|
||||||
// 800 - 899
|
// 800 - 899
|
||||||
// jobs
|
// jobs
|
||||||
'800' => array(
|
'800' => array(
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
<?php
|
||||||
|
namespace LAM\TOOLS\IMPORT_EXPORT;
|
||||||
|
/*
|
||||||
|
|
||||||
|
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
|
Copyright (C) 2018 Roland Gruber
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LDIF import.
|
||||||
|
*
|
||||||
|
* @author Roland Gruber
|
||||||
|
* @package tools
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** LDAP handle */
|
||||||
|
include_once('ldap.inc');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates LDAP accounts for file upload.
|
||||||
|
*
|
||||||
|
* @author Roland Gruber
|
||||||
|
* @package tools
|
||||||
|
*/
|
||||||
|
class Importer {
|
||||||
|
|
||||||
|
const SESSION_KEY_ENTRIES = 'import_entries';
|
||||||
|
const SESSION_KEY_COUNT = 'import_count';
|
||||||
|
const STATUS = 'status';
|
||||||
|
const PROGRESS = 'progress';
|
||||||
|
const DATA = 'data';
|
||||||
|
const TIME_LIMIT = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes the import data stored in session.
|
||||||
|
*/
|
||||||
|
public function doImport() {
|
||||||
|
$entries = &$_SESSION[Importer::SESSION_KEY_ENTRIES];
|
||||||
|
// check if any actions are needed at all
|
||||||
|
if (empty($entries)) {
|
||||||
|
return $this->getStatus();
|
||||||
|
}
|
||||||
|
$endTime = $this->getEndTime();
|
||||||
|
while ((!empty($entries)) && ($endTime > time())) {
|
||||||
|
$this->continueImport($entries);
|
||||||
|
}
|
||||||
|
return $this->getStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current status as JSON.
|
||||||
|
*
|
||||||
|
* @return string JSON status
|
||||||
|
*/
|
||||||
|
private function getStatus() {
|
||||||
|
if (empty($entries)) {
|
||||||
|
if (isset($_SESSION[Importer::SESSION_KEY_ENTRIES])) {
|
||||||
|
unset($_SESSION[Importer::SESSION_KEY_ENTRIES]);
|
||||||
|
}
|
||||||
|
$status = array(
|
||||||
|
Importer::STATUS => 'done'
|
||||||
|
);
|
||||||
|
return json_encode($status);
|
||||||
|
}
|
||||||
|
$progress = (sizeof($_SESSION[Importer::SESSION_KEY_ENTRIES]) / $_SESSION[Importer::SESSION_KEY_COUNT]) * 100.0;
|
||||||
|
$progress = floor(100 - $progress);
|
||||||
|
$status = array(
|
||||||
|
Importer::STATUS => 'inProgress',
|
||||||
|
Importer::PROGRESS => $progress,
|
||||||
|
Importer::DATA => ''
|
||||||
|
);
|
||||||
|
return json_encode($status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the time when processing should end.
|
||||||
|
*
|
||||||
|
* @return number end time as Unix timestamp
|
||||||
|
*/
|
||||||
|
private function getEndTime() {
|
||||||
|
$startTime = time();
|
||||||
|
$maxTime = get_cfg_var('max_execution_time') - 10;
|
||||||
|
if ($maxTime > Importer::TIME_LIMIT) {
|
||||||
|
$maxTime = Importer::TIME_LIMIT;
|
||||||
|
}
|
||||||
|
if ($maxTime <= 0) {
|
||||||
|
$maxTime = Importer::TIME_LIMIT;
|
||||||
|
}
|
||||||
|
return $startTime + $maxTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Continues the import with processing of a single entry.
|
||||||
|
*
|
||||||
|
* @param array[] $entries import entries
|
||||||
|
*/
|
||||||
|
private function continueImport(&$entries) {
|
||||||
|
$entry = array_shift($entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
|
@ -901,6 +901,43 @@ window.lam.tools.schema.select = function() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.lam.import = window.lam.import || {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the import process.
|
||||||
|
*
|
||||||
|
* @param tokenName name of CSRF token
|
||||||
|
* @param tokenValue value of CSRF token
|
||||||
|
*/
|
||||||
|
window.lam.import.startImport = function(tokenName, tokenValue) {
|
||||||
|
jQuery(document).ready(function() {
|
||||||
|
var output = jQuery('#importResults');
|
||||||
|
var data = {
|
||||||
|
jsonInput: ''
|
||||||
|
};
|
||||||
|
data[tokenName] = tokenValue;
|
||||||
|
jQuery.ajax({
|
||||||
|
url: '../misc/ajax.php?function=import',
|
||||||
|
method: 'POST',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
.done(function(jsonData){
|
||||||
|
if (jsonData.status == 'done') {
|
||||||
|
jQuery('#progressbarImport').hide();
|
||||||
|
jQuery('#btn_submitImportCancel').hide();
|
||||||
|
jQuery('#statusImportInprogress').hide();
|
||||||
|
jQuery('#statusImportDone').show();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
jQuery('#progressbarImport').progressbar({
|
||||||
|
value: jsonData.progress
|
||||||
|
});
|
||||||
|
window.lam.import.startImport(tokenName, tokenValue);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
jQuery(document).ready(function() {
|
jQuery(document).ready(function() {
|
||||||
window.lam.gui.equalHeight();
|
window.lam.gui.equalHeight();
|
||||||
window.lam.form.autoTrim();
|
window.lam.form.autoTrim();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
namespace LAM\AJAX;
|
namespace LAM\AJAX;
|
||||||
|
use \LAM\TOOLS\IMPORT_EXPORT\Importer;
|
||||||
/*
|
/*
|
||||||
|
|
||||||
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
|
@ -91,7 +92,15 @@ class Ajax {
|
||||||
if ($function == 'passwordChange') {
|
if ($function == 'passwordChange') {
|
||||||
$this->managePasswordChange($jsonInput);
|
$this->managePasswordChange($jsonInput);
|
||||||
}
|
}
|
||||||
elseif ($function == 'upload') {
|
elseif ($function === 'import') {
|
||||||
|
include_once('../../lib/import.inc');
|
||||||
|
$importer = new Importer();
|
||||||
|
ob_start();
|
||||||
|
$jsonOut = $importer->doImport();
|
||||||
|
ob_end_clean();
|
||||||
|
echo $jsonOut;
|
||||||
|
}
|
||||||
|
elseif ($function === 'upload') {
|
||||||
include_once('../../lib/upload.inc');
|
include_once('../../lib/upload.inc');
|
||||||
$typeManager = new \LAM\TYPES\TypeManager();
|
$typeManager = new \LAM\TYPES\TypeManager();
|
||||||
$uploader = new \LAM\UPLOAD\Uploader($typeManager->getConfiguredType($_GET['typeId']));
|
$uploader = new \LAM\UPLOAD\Uploader($typeManager->getConfiguredType($_GET['typeId']));
|
||||||
|
|
|
@ -0,0 +1,263 @@
|
||||||
|
<?php
|
||||||
|
namespace LAM\TOOLS\IMPORT_EXPORT;
|
||||||
|
use \htmlTitle;
|
||||||
|
use \htmlResponsiveRadio;
|
||||||
|
use \htmlResponsiveRow;
|
||||||
|
use \htmlResponsiveInputFileUpload;
|
||||||
|
use \htmlResponsiveInputTextarea;
|
||||||
|
use \htmlButton;
|
||||||
|
use \htmlStatusMessage;
|
||||||
|
use \htmlDiv;
|
||||||
|
use \htmlOutputText;
|
||||||
|
use \htmlJavaScript;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
|
Copyright (C) 2018 Roland Gruber
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multi edit tool that allows LDAP operations on multiple entries.
|
||||||
|
*
|
||||||
|
* @author Roland Gruber
|
||||||
|
* @package tools
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** security functions */
|
||||||
|
include_once("../../lib/security.inc");
|
||||||
|
/** access to configuration data */
|
||||||
|
include_once("../../lib/config.inc");
|
||||||
|
/** access LDAP server */
|
||||||
|
include_once("../../lib/ldap.inc");
|
||||||
|
/** used to print status messages */
|
||||||
|
include_once("../../lib/status.inc");
|
||||||
|
/** import class */
|
||||||
|
include_once("../../lib/import.inc");
|
||||||
|
|
||||||
|
// start session
|
||||||
|
startSecureSession();
|
||||||
|
enforceUserIsLoggedIn();
|
||||||
|
|
||||||
|
// die if no write access
|
||||||
|
if (!checkIfWriteAccessIsAllowed()) die();
|
||||||
|
|
||||||
|
checkIfToolIsActive('ImportExport');
|
||||||
|
|
||||||
|
setlanguage();
|
||||||
|
|
||||||
|
if (!empty($_POST)) {
|
||||||
|
validateSecurityToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean old data
|
||||||
|
if (isset($_SESSION[Importer::SESSION_KEY_ENTRIES])) {
|
||||||
|
unset($_SESSION[Importer::SESSION_KEY_ENTRIES]);
|
||||||
|
}
|
||||||
|
if (isset($_SESSION[Importer::SESSION_KEY_COUNT])) {
|
||||||
|
unset($_SESSION[Importer::SESSION_KEY_COUNT]);
|
||||||
|
}
|
||||||
|
|
||||||
|
include '../../lib/adminHeader.inc';
|
||||||
|
$tabindex = 1;
|
||||||
|
?>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
$("#tabs").tabs();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="user-bright smallPaddingContent">
|
||||||
|
<div id="tabs">
|
||||||
|
<ul>
|
||||||
|
<li id="tab_import">
|
||||||
|
<a href="#tab-import"><img alt="import" src="../../graphics/import.png"> <?php echo _('Import') ?> </a>
|
||||||
|
</li>
|
||||||
|
<li id="tab_export">
|
||||||
|
<a href="#tab-export"><img alt="export" src="../../graphics/export.png"> <?php echo _('Export') ?> </a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div id="tab-import">
|
||||||
|
<?php
|
||||||
|
if (isset($_POST['submitImport'])) {
|
||||||
|
printImportTabProcessing($tabindex);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printImportTabContent($tabindex);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
<div id="tab-export">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the content area for the import tab.
|
||||||
|
*
|
||||||
|
* @param int $tabindex tabindex
|
||||||
|
*/
|
||||||
|
function printImportTabContent(&$tabindex) {
|
||||||
|
echo "<form enctype=\"multipart/form-data\" action=\"importexport.php\" method=\"post\">\n";
|
||||||
|
$container = new htmlResponsiveRow();
|
||||||
|
$container->add(new htmlTitle(_("Import")), 12);
|
||||||
|
$sources = array(
|
||||||
|
_('File') => 'file',
|
||||||
|
_('Text input') => 'text'
|
||||||
|
);
|
||||||
|
$sourceRadio = new htmlResponsiveRadio(_('Source'), 'source', $sources, 'text');
|
||||||
|
$sourceRadio->setTableRowsToHide(
|
||||||
|
array(
|
||||||
|
'file' => array('text'),
|
||||||
|
'text' => array('file')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$sourceRadio->setTableRowsToShow(
|
||||||
|
array(
|
||||||
|
'text' => array('text'),
|
||||||
|
'file' => array('file')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$container->add($sourceRadio, 12);
|
||||||
|
$container->addVerticalSpacer('1rem');
|
||||||
|
$container->add(new htmlResponsiveInputFileUpload('file', _('File'), '750'), 12);
|
||||||
|
$container->add(new htmlResponsiveInputTextarea('text', '', '60', '20', _('LDIF data'), '750'), 12);
|
||||||
|
|
||||||
|
$container->addVerticalSpacer('3rem');
|
||||||
|
$button = new htmlButton('submitImport', _('Submit'));
|
||||||
|
$container->add($button, 12, 12, 12, 'text-center');
|
||||||
|
|
||||||
|
addSecurityTokenToMetaHTML($container);
|
||||||
|
|
||||||
|
parseHtml(null, $container, array(), false, $tabindex, 'user');
|
||||||
|
echo ("</form>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the content area for the import tab during processing state.
|
||||||
|
*
|
||||||
|
* @param int $tabindex tabindex
|
||||||
|
*/
|
||||||
|
function printImportTabProcessing(&$tabindex) {
|
||||||
|
$message = checkImportData();
|
||||||
|
if (!empty($message)) {
|
||||||
|
$container = new htmlResponsiveRow();
|
||||||
|
$container->add(new htmlStatusMessage('ERROR', $message), 12);
|
||||||
|
parseHtml(null, $container, array(), false, $tabindex, 'user');
|
||||||
|
printImportTabContent($tabindex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
echo "<form enctype=\"multipart/form-data\" action=\"importexport.php\" method=\"post\">\n";
|
||||||
|
$container = new htmlResponsiveRow();
|
||||||
|
$container->add(new htmlTitle(_("Import")), 12);
|
||||||
|
|
||||||
|
$container->add(new htmlDiv('statusImportInprogress', new htmlOutputText(_('Status') . ': ' . _('in progress'))), 12);
|
||||||
|
$container->add(new htmlDiv('statusImportDone', new htmlOutputText(_('Status') . ': ' . _('done')), array('hidden')), 12);
|
||||||
|
$container->add(new htmlDiv('progressbarImport', new htmlOutputText('')), 12);
|
||||||
|
$container->add(new htmlDiv('importResults', new htmlOutputText('')), 12);
|
||||||
|
$container->add(new htmlJavaScript(
|
||||||
|
'window.lam.import.startImport(\'' . getSecurityTokenName() . '\', \'' . getSecurityTokenValue() . '\');'
|
||||||
|
), 12);
|
||||||
|
|
||||||
|
$container->addVerticalSpacer('3rem');
|
||||||
|
|
||||||
|
$button = new htmlButton('submitImportCancel', _('Cancel'));
|
||||||
|
$container->add($button, 12, 12, 12, 'text-center');
|
||||||
|
|
||||||
|
addSecurityTokenToMetaHTML($container);
|
||||||
|
|
||||||
|
parseHtml(null, $container, array(), false, $tabindex, 'user');
|
||||||
|
echo ("</form>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the import data is ok.
|
||||||
|
*
|
||||||
|
* @return string error message if not valid
|
||||||
|
*/
|
||||||
|
function checkImportData() {
|
||||||
|
$source = $_POST['source'];
|
||||||
|
$ldif = '';
|
||||||
|
if ($source == 'text') {
|
||||||
|
$ldif = $_POST['text'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$handle = fopen($_FILES['file']['tmp_name'], "r");
|
||||||
|
$ldif = fread($handle, 100000000);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
if (empty($ldif)) {
|
||||||
|
return _('You must either upload a file or provide an import in the text box.');
|
||||||
|
}
|
||||||
|
$lines = preg_split("/\n|\r\n|\r/", $ldif);
|
||||||
|
$entriesData = extractImportEntries($lines);
|
||||||
|
if (!is_array($entriesData)) {
|
||||||
|
return $entriesData;
|
||||||
|
}
|
||||||
|
$_SESSION[Importer::SESSION_KEY_ENTRIES] = $entriesData;
|
||||||
|
$_SESSION[Importer::SESSION_KEY_COUNT] = sizeof($entriesData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the single entries in the file.
|
||||||
|
*
|
||||||
|
* @param string[] $lines LDIF lines
|
||||||
|
* @return string|array array of string[]
|
||||||
|
*/
|
||||||
|
function extractImportEntries($lines) {
|
||||||
|
$entries = array();
|
||||||
|
$currentEntry = array();
|
||||||
|
foreach ($lines as $line) {
|
||||||
|
if (substr(trim($line), 0, 1) === '#') {
|
||||||
|
// skip comments
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (empty(trim($line))) {
|
||||||
|
// end of entry
|
||||||
|
if (!empty($currentEntry)) {
|
||||||
|
$entries[] = $currentEntry;
|
||||||
|
$currentEntry = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif (substr($line, 0, 1) === ' ') {
|
||||||
|
// append to last line if starting with a space
|
||||||
|
if (empty($currentEntry)) {
|
||||||
|
return _('Invalid data:') . ' ' . htmlspecialchars($line);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$currentEntry[sizeof($currentEntry) - 1] .= substr($line, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$parts = explode(':', $line, 2);
|
||||||
|
if (sizeof($parts) < 2) {
|
||||||
|
return _('Invalid data:') . ' ' . htmlspecialchars($line);
|
||||||
|
}
|
||||||
|
$currentEntry[] = $line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($currentEntry)) {
|
||||||
|
$entries[] = $currentEntry;
|
||||||
|
}
|
||||||
|
return $entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
include '../../lib/adminFooter.inc';
|
Loading…
Reference in New Issue