import tool

This commit is contained in:
Roland Gruber 2018-08-31 20:59:05 +02:00
parent a4c867d6b3
commit c9cff54937
5 changed files with 433 additions and 2 deletions

View File

@ -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(

118
lam/lib/import.inc Normal file
View File

@ -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);
}
}
?>

View File

@ -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();

View File

@ -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']));

View File

@ -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';