2018-08-31 18:59:05 +00:00
|
|
|
<?php
|
|
|
|
namespace LAM\TOOLS\IMPORT_EXPORT;
|
2018-09-01 11:36:04 +00:00
|
|
|
use \htmlStatusMessage;
|
|
|
|
use \LAMException;
|
2018-08-31 18:59:05 +00:00
|
|
|
/*
|
|
|
|
|
|
|
|
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
2019-01-02 20:10:32 +00:00
|
|
|
Copyright (C) 2018 - 2019 Roland Gruber
|
2018-08-31 18:59:05 +00:00
|
|
|
|
|
|
|
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');
|
|
|
|
|
|
|
|
/**
|
2018-09-23 18:12:27 +00:00
|
|
|
* Imports LDIF files.
|
2018-08-31 18:59:05 +00:00
|
|
|
*
|
|
|
|
* @author Roland Gruber
|
|
|
|
* @package tools
|
|
|
|
*/
|
|
|
|
class Importer {
|
|
|
|
|
2018-09-01 11:36:04 +00:00
|
|
|
const SESSION_KEY_TASKS = 'import_tasks';
|
2018-08-31 18:59:05 +00:00
|
|
|
const SESSION_KEY_COUNT = 'import_count';
|
2018-09-15 16:25:53 +00:00
|
|
|
const SESSION_KEY_STOP_ON_ERROR = 'import_stop_on_error';
|
2018-08-31 18:59:05 +00:00
|
|
|
const STATUS = 'status';
|
|
|
|
const PROGRESS = 'progress';
|
|
|
|
const DATA = 'data';
|
|
|
|
const TIME_LIMIT = 10;
|
2018-09-01 11:36:04 +00:00
|
|
|
const KEY = 0;
|
|
|
|
const VALUE = 1;
|
|
|
|
const CHANGETYPE = 'changeType';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extracts the single entries in the file.
|
|
|
|
*
|
|
|
|
* @param string[] $lines LDIF lines
|
|
|
|
* @return string|array array of string[]
|
|
|
|
* @throws LAMException invalid format
|
|
|
|
*/
|
|
|
|
private function extractImportChunks($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)) {
|
|
|
|
throw new LAMException(_('Invalid data'), htmlspecialchars($line));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$currentEntry[sizeof($currentEntry) - 1] .= substr($line, 1);
|
|
|
|
}
|
|
|
|
}
|
2018-09-15 13:03:47 +00:00
|
|
|
elseif ($line === '-') {
|
|
|
|
$currentEntry[] = $line;
|
|
|
|
}
|
2018-09-01 11:36:04 +00:00
|
|
|
else {
|
|
|
|
$parts = explode(':', $line, 2);
|
|
|
|
if (sizeof($parts) < 2) {
|
|
|
|
throw new LAMException(_('Invalid data'), htmlspecialchars($line));
|
|
|
|
}
|
|
|
|
$currentEntry[] = $line;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!empty($currentEntry)) {
|
|
|
|
$entries[] = $currentEntry;
|
|
|
|
}
|
|
|
|
return $entries;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts the lines to LDAP import tasks.
|
|
|
|
*
|
|
|
|
* @param string[] $lines import lines
|
|
|
|
* @throws LAMException if invalid format was found
|
|
|
|
* @return ImporterTask[] tasks
|
|
|
|
*/
|
|
|
|
public function getTasks($lines) {
|
|
|
|
$chunks = $this->extractImportChunks($lines);
|
2019-01-02 20:10:32 +00:00
|
|
|
return $this->convertToTasks($chunks);
|
2018-09-01 11:36:04 +00:00
|
|
|
}
|
2018-08-31 18:59:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Processes the import data stored in session.
|
|
|
|
*/
|
|
|
|
public function doImport() {
|
2018-09-01 11:36:04 +00:00
|
|
|
$data = '';
|
|
|
|
$tasks = &$_SESSION[Importer::SESSION_KEY_TASKS];
|
2018-09-15 16:25:53 +00:00
|
|
|
$stopOnError = $_SESSION[Importer::SESSION_KEY_STOP_ON_ERROR];
|
2018-08-31 18:59:05 +00:00
|
|
|
// check if any actions are needed at all
|
2018-09-01 11:36:04 +00:00
|
|
|
if (empty($tasks)) {
|
|
|
|
return $this->getStatus($data);
|
2018-08-31 18:59:05 +00:00
|
|
|
}
|
|
|
|
$endTime = $this->getEndTime();
|
2018-09-01 11:36:04 +00:00
|
|
|
while ((!empty($tasks)) && ($endTime > time())) {
|
|
|
|
$task = array_shift($tasks);
|
|
|
|
try {
|
|
|
|
$data .= $task->run();
|
|
|
|
}
|
|
|
|
catch (LAMException $e) {
|
2018-09-15 16:25:53 +00:00
|
|
|
if ($stopOnError) {
|
|
|
|
return $this->stopImport($data, $e);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$data .= Importer::formatMessage('ERROR', $e->getTitle(), $e->getMessage());
|
|
|
|
}
|
2018-09-01 11:36:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return $this->getStatus($data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stops the import process because of an exception.
|
|
|
|
*
|
|
|
|
* @param string $data HTML output
|
|
|
|
* @param LAMException $e exception
|
|
|
|
* @return string JSON status
|
|
|
|
*/
|
|
|
|
private function stopImport($data, LAMException $e) {
|
|
|
|
$data .= Importer::formatMessage('ERROR', $e->getTitle(), $e->getMessage());
|
|
|
|
if (isset($_SESSION[Importer::SESSION_KEY_TASKS])) {
|
|
|
|
unset($_SESSION[Importer::SESSION_KEY_TASKS]);
|
2018-08-31 18:59:05 +00:00
|
|
|
}
|
2018-09-01 11:36:04 +00:00
|
|
|
$status = array(
|
|
|
|
Importer::STATUS => 'failed',
|
|
|
|
Importer::DATA => $data
|
|
|
|
);
|
|
|
|
return json_encode($status);
|
2018-08-31 18:59:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the current status as JSON.
|
|
|
|
*
|
2018-09-01 11:36:04 +00:00
|
|
|
* @param string $data HTML output to display
|
2018-08-31 18:59:05 +00:00
|
|
|
* @return string JSON status
|
|
|
|
*/
|
2018-09-01 11:36:04 +00:00
|
|
|
private function getStatus($data) {
|
|
|
|
if (empty($_SESSION[Importer::SESSION_KEY_TASKS])) {
|
|
|
|
if (isset($_SESSION[Importer::SESSION_KEY_TASKS])) {
|
|
|
|
unset($_SESSION[Importer::SESSION_KEY_TASKS]);
|
2018-08-31 18:59:05 +00:00
|
|
|
}
|
|
|
|
$status = array(
|
2018-09-01 11:36:04 +00:00
|
|
|
Importer::STATUS => 'done',
|
|
|
|
Importer::DATA => $data
|
2018-08-31 18:59:05 +00:00
|
|
|
);
|
|
|
|
return json_encode($status);
|
|
|
|
}
|
2018-09-01 11:36:04 +00:00
|
|
|
$progress = (sizeof($_SESSION[Importer::SESSION_KEY_TASKS]) / $_SESSION[Importer::SESSION_KEY_COUNT]) * 100.0;
|
2018-08-31 18:59:05 +00:00
|
|
|
$progress = floor(100 - $progress);
|
|
|
|
$status = array(
|
|
|
|
Importer::STATUS => 'inProgress',
|
|
|
|
Importer::PROGRESS => $progress,
|
2018-09-01 11:36:04 +00:00
|
|
|
Importer::DATA => $data
|
2018-08-31 18:59:05 +00:00
|
|
|
);
|
|
|
|
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
|
2018-09-01 11:36:04 +00:00
|
|
|
* @return ImporterTask[] tasks
|
|
|
|
*/
|
|
|
|
private function convertToTasks($entries) {
|
|
|
|
$tasks = array();
|
|
|
|
$count = sizeof($entries);
|
|
|
|
for ($i = 0; $i < $count; $i++) {
|
|
|
|
$entry = $entries[$i];
|
|
|
|
$firstParts = explode(':', $entry[0], 2);
|
|
|
|
if ($firstParts[Importer::KEY] == 'version') {
|
|
|
|
if ($i > 0) {
|
|
|
|
// allow version only as first chunk
|
|
|
|
throw new LAMException(_('Invalid data'), _('Duplicate version entry found.'));
|
|
|
|
}
|
|
|
|
$this->processVersion($entry);
|
|
|
|
}
|
|
|
|
elseif ($firstParts[Importer::KEY] == 'dn') {
|
|
|
|
$tasks[] = $this->processDnEntry($entry);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
throw new LAMException(_('A valid dn line is required'), htmlspecialchars($entry[0]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $tasks;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks a version entry.
|
|
|
|
*
|
|
|
|
* @param string[] $entry entry
|
|
|
|
* @throws LAMException if version is invalid
|
|
|
|
*/
|
|
|
|
private function processVersion($entry) {
|
|
|
|
$keyValue = $this->getLineKeyValue($entry[0]);
|
|
|
|
if (($keyValue[Importer::VALUE] != '1') || (sizeof($entry) > 1)) {
|
|
|
|
$escapedLines = array_map('htmlspecialchars', $entry);
|
2018-12-09 18:56:34 +00:00
|
|
|
throw new LAMException(_('LDIF import only supports version 1'), implode('<br>', $escapedLines));
|
2018-09-01 11:36:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks a dn entry.
|
|
|
|
*
|
|
|
|
* @param string[] $entry entry
|
|
|
|
* @return ImporterTask task
|
|
|
|
* @throws LAMException if invalid format
|
|
|
|
*/
|
|
|
|
private function processDnEntry($entry) {
|
|
|
|
$dnLine = array_shift($entry);
|
|
|
|
$keyValue = $this->getLineKeyValue($dnLine);
|
|
|
|
$dn = $keyValue[Importer::VALUE];
|
|
|
|
if (empty($entry)) {
|
|
|
|
throw new LAMException(_('Invalid data'), htmlspecialchars($dnLine));
|
|
|
|
}
|
|
|
|
$firstAttributeLine = array_shift($entry);
|
|
|
|
$firstAttribute = $this->getLineKeyValue($firstAttributeLine);
|
|
|
|
if ($firstAttribute[Importer::KEY] != Importer::CHANGETYPE) {
|
|
|
|
// complete DN
|
|
|
|
$attributes = array(
|
|
|
|
$firstAttribute[Importer::KEY] => array($firstAttribute[Importer::VALUE])
|
|
|
|
);
|
|
|
|
foreach ($entry as $attributeLine) {
|
|
|
|
$attribute = $this->getLineKeyValue($attributeLine);
|
|
|
|
$attributes[$attribute[Importer::KEY]][] = $attribute[Importer::VALUE];
|
|
|
|
}
|
|
|
|
return new AddEntryTask($dn, $attributes);
|
|
|
|
}
|
2018-09-04 17:34:03 +00:00
|
|
|
else {
|
|
|
|
$type = $firstAttribute[Importer::VALUE];
|
2018-09-06 18:53:22 +00:00
|
|
|
if ($type === 'add') {
|
|
|
|
$attributes = array();
|
|
|
|
foreach ($entry as $line) {
|
|
|
|
$lineData = $this->getLineKeyValue($line);
|
|
|
|
$attributes[$lineData[Importer::KEY]][] = $lineData[Importer::VALUE];
|
|
|
|
}
|
|
|
|
return new AddEntryTask($dn, $attributes);
|
|
|
|
}
|
2018-09-06 19:19:07 +00:00
|
|
|
elseif ($type === 'modrdn') {
|
|
|
|
return $this->createModRdnTask($dn, $entry);
|
|
|
|
}
|
2018-09-06 19:30:05 +00:00
|
|
|
elseif ($type === 'delete') {
|
|
|
|
if (!empty($entry)) {
|
|
|
|
throw new LAMException(_('Invalid data'), htmlspecialchars($dn));
|
|
|
|
}
|
|
|
|
return new DeleteEntryTask($dn);
|
|
|
|
}
|
2018-09-15 13:03:47 +00:00
|
|
|
elseif ($type !== 'modify') {
|
|
|
|
throw new LAMException(_('Invalid data'), htmlspecialchars($dn) . ' - changeType: ' . htmlspecialchars($type));
|
|
|
|
}
|
2018-09-04 17:34:03 +00:00
|
|
|
$subtasks = array();
|
|
|
|
$currentLines = array();
|
|
|
|
$linesCount = sizeof($entry);
|
|
|
|
for ($i = 0; $i < $linesCount; $i++) {
|
|
|
|
$line = $entry[$i];
|
|
|
|
if ($line === '-') {
|
2018-09-15 13:03:47 +00:00
|
|
|
$subtasks[] = $this->getChangeTypeTask($dn, $currentLines);
|
2018-09-04 17:34:03 +00:00
|
|
|
$currentLines = array();
|
|
|
|
}
|
2018-09-15 13:03:47 +00:00
|
|
|
else {
|
|
|
|
$currentLines[] = $line;
|
|
|
|
}
|
2018-09-04 17:34:03 +00:00
|
|
|
}
|
2018-09-15 13:03:47 +00:00
|
|
|
$subtasks[] = $this->getChangeTypeTask($dn, $currentLines);
|
2018-09-06 18:53:22 +00:00
|
|
|
return new MultiTask($subtasks, $dn);
|
2018-09-04 17:34:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-06 19:19:07 +00:00
|
|
|
/**
|
|
|
|
* Returns a modrdn task.
|
|
|
|
*
|
|
|
|
* @param string $dn DN
|
|
|
|
* @param string[] $entry entry lines
|
|
|
|
* @return
|
|
|
|
* @throws LAMException syntax error
|
|
|
|
*/
|
|
|
|
private function createModRdnTask($dn, $entry) {
|
|
|
|
if (sizeof($entry) !== 2) {
|
|
|
|
throw new LAMException(_('Invalid data'), htmlspecialchars($dn));
|
|
|
|
}
|
|
|
|
$newRdnData = $this->getLineKeyValue($entry[0]);
|
|
|
|
if ($newRdnData[Importer::KEY] !== 'newrdn') {
|
|
|
|
throw new LAMException(_('Invalid data'), htmlspecialchars($dn) . '<br>' . $newRdnData);
|
|
|
|
}
|
|
|
|
$newRdn = $newRdnData[Importer::VALUE];
|
|
|
|
$delOldRdnData = $this->getLineKeyValue($entry[1]);
|
|
|
|
if (($delOldRdnData[Importer::KEY] !== 'deleteoldrdn') || !in_array($delOldRdnData[Importer::VALUE], array('0', '1'), true)) {
|
2018-09-15 13:03:47 +00:00
|
|
|
throw new LAMException(_('Invalid data'), htmlspecialchars($dn) . '<br>' . $entry[1]);
|
2018-09-06 19:19:07 +00:00
|
|
|
}
|
2019-01-02 20:10:32 +00:00
|
|
|
$delOldRdn = ($delOldRdnData[Importer::VALUE] !== '0');
|
2018-09-06 19:19:07 +00:00
|
|
|
return new RenameEntryTask($dn, $newRdn, $delOldRdn);
|
|
|
|
}
|
|
|
|
|
2018-09-04 17:34:03 +00:00
|
|
|
/**
|
|
|
|
* Returns a task for LDIF changeType entry.
|
|
|
|
*
|
|
|
|
* @param string $dn DN
|
|
|
|
* @param string $lines lines
|
|
|
|
* @return ImporterTask task
|
|
|
|
*/
|
2018-09-15 13:03:47 +00:00
|
|
|
private function getChangeTypeTask($dn, $lines) {
|
|
|
|
$firstLine = array_shift($lines);
|
|
|
|
$firstLineData = $this->getLineKeyValue($firstLine);
|
|
|
|
$type = $firstLineData[Importer::KEY];
|
|
|
|
$attributeName = $firstLineData[Importer::VALUE];
|
2018-09-04 17:34:03 +00:00
|
|
|
$attributes = array();
|
|
|
|
foreach ($lines as $line) {
|
|
|
|
$lineData = $this->getLineKeyValue($line);
|
2018-09-15 13:03:47 +00:00
|
|
|
if ($lineData[Importer::KEY] !== $attributeName) {
|
|
|
|
throw new LAMException(_('Invalid data'), htmlspecialchars($dn) . ' - ' . htmlspecialchars($type));
|
|
|
|
}
|
|
|
|
$attributes[$attributeName][] = $lineData[Importer::VALUE];
|
2018-09-04 17:34:03 +00:00
|
|
|
}
|
|
|
|
if ($type === 'add') {
|
2018-09-15 13:03:47 +00:00
|
|
|
return new AddAttributesTask($dn, $attributes);
|
|
|
|
}
|
|
|
|
elseif ($type === 'delete') {
|
|
|
|
return new DeleteAttributesTask($dn, $attributeName, $attributes);
|
2018-09-04 17:34:03 +00:00
|
|
|
}
|
2018-09-15 13:03:47 +00:00
|
|
|
elseif ($type === 'replace') {
|
|
|
|
return new ReplaceAttributesTask($dn, $attributes);
|
|
|
|
}
|
|
|
|
throw new LAMException(_('Invalid data'), htmlspecialchars($dn) . ' - ' . htmlspecialchars($type));
|
2018-09-01 11:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the HTML for an error message.
|
|
|
|
*
|
|
|
|
* @param string $type message type (e.g. INFO)
|
|
|
|
* @param string $title title
|
|
|
|
* @param string $message message
|
|
|
|
* @return string HTML
|
|
|
|
*/
|
|
|
|
public static function formatMessage($type, $title, $message) {
|
|
|
|
$msg = new htmlStatusMessage($type, $title, $message);
|
|
|
|
$tabindex = 0;
|
|
|
|
ob_start();
|
|
|
|
$msg->generateHTML(null, array($msg), array(), true, $tabindex, 'user');
|
|
|
|
$data = ob_get_contents();
|
|
|
|
ob_clean();
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the key and value part of the line.
|
|
|
|
*
|
|
|
|
* @param string $line line
|
|
|
|
* @return string[] array(key, value)
|
|
|
|
*/
|
|
|
|
private function getLineKeyValue($line) {
|
|
|
|
$parts = explode(':', $line, 2);
|
2018-09-04 17:34:03 +00:00
|
|
|
if (sizeof($parts) !== 2) {
|
|
|
|
throw new LAMException(_('Invalid data'), htmlspecialchars($line));
|
|
|
|
}
|
2018-09-01 11:36:04 +00:00
|
|
|
if (substr($parts[Importer::VALUE], 0, 1) == ':') {
|
|
|
|
$value = base64_decode(trim(substr($parts[Importer::VALUE], 1)));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$value = trim($parts[Importer::VALUE]);
|
|
|
|
}
|
|
|
|
return array($parts[Importer::KEY], $value);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A single import task.
|
|
|
|
*
|
|
|
|
* @author Roland Gruber
|
|
|
|
*/
|
|
|
|
interface ImporterTask {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Runs the task.
|
|
|
|
*
|
|
|
|
* @return string HTML output or LAMException if error occured
|
|
|
|
*/
|
|
|
|
public function run();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a complete LDAP entry.
|
|
|
|
*
|
|
|
|
* @author Roland Gruber
|
|
|
|
*/
|
|
|
|
class AddEntryTask implements ImporterTask {
|
|
|
|
|
|
|
|
private $dn = '';
|
|
|
|
private $attributes = array();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* @param string $dn DN
|
|
|
|
* @param array[string[]] $attributes list of attributes
|
2018-08-31 18:59:05 +00:00
|
|
|
*/
|
2018-09-01 11:36:04 +00:00
|
|
|
public function __construct($dn, $attributes) {
|
|
|
|
$this->dn = $dn;
|
|
|
|
$this->attributes = $attributes;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* {@inheritDoc}
|
|
|
|
* @see \LAM\TOOLS\IMPORT_EXPORT\ImporterTask::run()
|
|
|
|
*/
|
|
|
|
public function run() {
|
|
|
|
$ldap = $_SESSION['ldap']->server();
|
|
|
|
$success = @ldap_add($ldap, $this->dn, $this->attributes);
|
|
|
|
if ($success) {
|
|
|
|
return Importer::formatMessage('INFO', _('Entry created'), htmlspecialchars($this->dn));
|
|
|
|
}
|
|
|
|
throw new LAMException(sprintf(_('Was unable to create DN: %s.'), $this->dn), getExtendedLDAPErrorMessage($ldap));
|
2018-08-31 18:59:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-09-06 19:19:07 +00:00
|
|
|
/**
|
|
|
|
* Renames an LDAP entry.
|
|
|
|
*
|
|
|
|
* @author Roland Gruber
|
|
|
|
*/
|
|
|
|
class RenameEntryTask implements ImporterTask {
|
|
|
|
|
|
|
|
private $dn = '';
|
|
|
|
private $newRdn = '';
|
|
|
|
private $deleteOldRdn = true;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* @param string $dn DN
|
|
|
|
* @param string $newRdn new RDN value
|
|
|
|
* @param bool $deleteOldRdn delete old RDN value
|
|
|
|
*/
|
|
|
|
public function __construct($dn, $newRdn, $deleteOldRdn) {
|
|
|
|
$this->dn = $dn;
|
|
|
|
$this->newRdn = $newRdn;
|
|
|
|
$this->deleteOldRdn = $deleteOldRdn;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* {@inheritDoc}
|
|
|
|
* @see \LAM\TOOLS\IMPORT_EXPORT\ImporterTask::run()
|
|
|
|
*/
|
|
|
|
public function run() {
|
|
|
|
$ldap = $_SESSION['ldap']->server();
|
|
|
|
$success = @ldap_rename($ldap, $this->dn, $this->newRdn, null, $this->deleteOldRdn);
|
|
|
|
if ($success) {
|
|
|
|
return Importer::formatMessage('INFO', _('Rename successful!'), htmlspecialchars($this->dn));
|
|
|
|
}
|
|
|
|
throw new LAMException(_('Could not rename the entry.') . '<br>' . $this->dn, getExtendedLDAPErrorMessage($ldap));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-09-06 19:30:05 +00:00
|
|
|
/**
|
|
|
|
* Deletes an LDAP entry.
|
|
|
|
*
|
|
|
|
* @author Roland Gruber
|
|
|
|
*/
|
|
|
|
class DeleteEntryTask implements ImporterTask {
|
|
|
|
|
|
|
|
private $dn = '';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* @param string $dn DN
|
|
|
|
*/
|
|
|
|
public function __construct($dn) {
|
|
|
|
$this->dn = $dn;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* {@inheritDoc}
|
|
|
|
* @see \LAM\TOOLS\IMPORT_EXPORT\ImporterTask::run()
|
|
|
|
*/
|
|
|
|
public function run() {
|
|
|
|
$ldap = $_SESSION['ldap']->server();
|
|
|
|
$success = @ldap_delete($ldap, $this->dn);
|
|
|
|
if ($success) {
|
|
|
|
return Importer::formatMessage('INFO', sprintf(_('Successfully deleted DN %s'), $this->dn), '');
|
|
|
|
}
|
|
|
|
throw new LAMException(_('Could not delete the entry.') . '<br>' . $this->dn, getExtendedLDAPErrorMessage($ldap));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-09-04 17:34:03 +00:00
|
|
|
/**
|
|
|
|
* Combines multiple import tasks.
|
|
|
|
*
|
|
|
|
* @author Roland Gruber
|
|
|
|
*/
|
|
|
|
class MultiTask implements ImporterTask {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var ImporterTask[] tasks
|
|
|
|
*/
|
|
|
|
private $tasks = array();
|
|
|
|
|
2018-09-06 18:53:22 +00:00
|
|
|
/**
|
|
|
|
* @var string DN
|
|
|
|
*/
|
|
|
|
private $dn = null;
|
|
|
|
|
2018-09-04 17:34:03 +00:00
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* @param ImporterTask[] $tasks tasks
|
|
|
|
*/
|
2018-09-06 18:53:22 +00:00
|
|
|
public function __construct($tasks, $dn) {
|
2018-09-04 17:34:03 +00:00
|
|
|
$this->tasks = $tasks;
|
2018-09-06 18:53:22 +00:00
|
|
|
$this->dn = $dn;
|
2018-09-04 17:34:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* {@inheritDoc}
|
|
|
|
* @see \LAM\TOOLS\IMPORT_EXPORT\ImporterTask::run()
|
|
|
|
*/
|
|
|
|
public function run() {
|
|
|
|
foreach ($this->tasks as $task) {
|
|
|
|
$task->run();
|
|
|
|
}
|
|
|
|
return Importer::formatMessage('INFO', _('LDAP operation successful.'), htmlspecialchars($this->dn));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the list of subtasks.
|
|
|
|
*
|
|
|
|
* @return ImporterTask[]
|
|
|
|
*/
|
|
|
|
public function getTasks() {
|
|
|
|
return $this->tasks;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds attributes to an existing LDAP entry.
|
|
|
|
*
|
|
|
|
* @author Roland Gruber
|
|
|
|
*/
|
|
|
|
class AddAttributesTask implements ImporterTask {
|
|
|
|
|
|
|
|
private $dn = '';
|
|
|
|
private $attributes = array();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* @param string $dn DN
|
|
|
|
* @param array[string[]] $attributes list of attributes
|
|
|
|
*/
|
|
|
|
public function __construct($dn, $attributes) {
|
|
|
|
$this->dn = $dn;
|
|
|
|
$this->attributes = $attributes;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* {@inheritDoc}
|
|
|
|
* @see \LAM\TOOLS\IMPORT_EXPORT\ImporterTask::run()
|
|
|
|
*/
|
|
|
|
public function run() {
|
|
|
|
$ldap = $_SESSION['ldap']->server();
|
|
|
|
$success = @ldap_mod_add($ldap, $this->dn, $this->attributes);
|
|
|
|
if ($success) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
throw new LAMException(sprintf(_('Was unable to create DN: %s.'), $this->dn), getExtendedLDAPErrorMessage($ldap));
|
|
|
|
}
|
|
|
|
|
2018-09-15 13:03:47 +00:00
|
|
|
/**
|
|
|
|
* Returns the DN.
|
|
|
|
*
|
|
|
|
* @return string DN
|
|
|
|
*/
|
|
|
|
public function getDn() {
|
|
|
|
return $this->dn;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the attributes to add.
|
|
|
|
*
|
|
|
|
* @return string[] attributes (array('attr' => array('val1', 'val2')))
|
|
|
|
*/
|
|
|
|
public function getAttributes() {
|
|
|
|
return $this->attributes;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deletes attributes from an existing LDAP entry.
|
|
|
|
*
|
|
|
|
* @author Roland Gruber
|
|
|
|
*/
|
|
|
|
class DeleteAttributesTask implements ImporterTask {
|
|
|
|
|
|
|
|
private $dn = '';
|
|
|
|
private $attributes = array();
|
|
|
|
private $attributeName = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* @param string $dn DN
|
|
|
|
* @param string $attributeName attribute name
|
|
|
|
* @param array[string[]] $attributes list of attributes
|
|
|
|
*/
|
|
|
|
public function __construct($dn, $attributeName, $attributes) {
|
|
|
|
$this->dn = $dn;
|
|
|
|
$this->attributeName = $attributeName;
|
|
|
|
$this->attributes = $attributes;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* {@inheritDoc}
|
|
|
|
* @see \LAM\TOOLS\IMPORT_EXPORT\ImporterTask::run()
|
|
|
|
*/
|
|
|
|
public function run() {
|
|
|
|
$ldap = $_SESSION['ldap']->server();
|
|
|
|
if (!empty($this->attributes)) {
|
|
|
|
$success = @ldap_mod_del($ldap, $this->dn, $this->attributes);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$success = @ldap_modify($ldap, $this->dn, array($this->attributeName => array()));
|
|
|
|
}
|
|
|
|
if ($success) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
throw new LAMException(sprintf(_('Was unable to create DN: %s.'), $this->dn), getExtendedLDAPErrorMessage($ldap));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the DN.
|
|
|
|
*
|
|
|
|
* @return string DN
|
|
|
|
*/
|
|
|
|
public function getDn() {
|
|
|
|
return $this->dn;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the attributes to add.
|
|
|
|
*
|
|
|
|
* @return string[] attributes (array('attr' => array('val1', 'val2')))
|
|
|
|
*/
|
|
|
|
public function getAttributes() {
|
|
|
|
return $this->attributes;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the attributes name.
|
|
|
|
*
|
|
|
|
* @return string name
|
|
|
|
*/
|
|
|
|
public function getAttributeName() {
|
|
|
|
return $this->attributeName;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replaces attributes in an existing LDAP entry.
|
|
|
|
*
|
|
|
|
* @author Roland Gruber
|
|
|
|
*/
|
|
|
|
class ReplaceAttributesTask implements ImporterTask {
|
|
|
|
|
|
|
|
private $dn = '';
|
|
|
|
private $attributes = array();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* @param string $dn DN
|
|
|
|
* @param array[string[]] $attributes list of attributes
|
|
|
|
*/
|
|
|
|
public function __construct($dn, $attributes) {
|
|
|
|
$this->dn = $dn;
|
|
|
|
$this->attributes = $attributes;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* {@inheritDoc}
|
|
|
|
* @see \LAM\TOOLS\IMPORT_EXPORT\ImporterTask::run()
|
|
|
|
*/
|
|
|
|
public function run() {
|
|
|
|
$ldap = $_SESSION['ldap']->server();
|
|
|
|
$success = @ldap_modify($ldap, $this->dn, $this->attributes);
|
|
|
|
if ($success) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
throw new LAMException(sprintf(_('Was unable to create DN: %s.'), $this->dn), getExtendedLDAPErrorMessage($ldap));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the DN.
|
|
|
|
*
|
|
|
|
* @return string DN
|
|
|
|
*/
|
|
|
|
public function getDn() {
|
|
|
|
return $this->dn;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the attributes to add.
|
|
|
|
*
|
|
|
|
* @return string[] attributes (array('attr' => array('val1', 'val2')))
|
|
|
|
*/
|
|
|
|
public function getAttributes() {
|
|
|
|
return $this->attributes;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the attributes name.
|
|
|
|
*
|
|
|
|
* @return string name
|
|
|
|
*/
|
|
|
|
public function getAttributeName() {
|
|
|
|
return $this->attributeName;
|
|
|
|
}
|
|
|
|
|
2018-09-04 17:34:03 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:59:05 +00:00
|
|
|
?>
|