diff --git a/lam/lib/import.inc b/lam/lib/import.inc
index 9110d089..d96475f1 100644
--- a/lam/lib/import.inc
+++ b/lam/lib/import.inc
@@ -82,6 +82,9 @@ class Importer {
$currentEntry[sizeof($currentEntry) - 1] .= substr($line, 1);
}
}
+ elseif ($line === '-') {
+ $currentEntry[] = $line;
+ }
else {
$parts = explode(':', $line, 2);
if (sizeof($parts) < 2) {
@@ -284,6 +287,9 @@ class Importer {
}
return new DeleteEntryTask($dn);
}
+ elseif ($type !== 'modify') {
+ throw new LAMException(_('Invalid data'), htmlspecialchars($dn) . ' - changeType: ' . htmlspecialchars($type));
+ }
$changes = array();
$subtasks = array();
$currentLines = array();
@@ -291,18 +297,14 @@ class Importer {
for ($i = 0; $i < $linesCount; $i++) {
$line = $entry[$i];
if ($line === '-') {
- $subtasks[] = $this->getChangeTypeTask($dn, $currentLines, $type);
+ $subtasks[] = $this->getChangeTypeTask($dn, $currentLines);
$currentLines = array();
- $i++;
- $line = $entry[$i];
- $lineTypeData = $this->getLineKeyValue($line);
- if ($lineTypeData[Importer::KEY] != Importer::CHANGETYPE) {
- throw new LAMException(_('Invalid data'), htmlspecialchars($line));
- }
}
- $currentLines[] = $line;
+ else {
+ $currentLines[] = $line;
+ }
}
- $subtasks[] = $this->getChangeTypeTask($dn, $currentLines, $type);
+ $subtasks[] = $this->getChangeTypeTask($dn, $currentLines);
return new MultiTask($subtasks, $dn);
}
}
@@ -326,7 +328,7 @@ class Importer {
$newRdn = $newRdnData[Importer::VALUE];
$delOldRdnData = $this->getLineKeyValue($entry[1]);
if (($delOldRdnData[Importer::KEY] !== 'deleteoldrdn') || !in_array($delOldRdnData[Importer::VALUE], array('0', '1'), true)) {
- throw new LAMException(_('Invalid data'), htmlspecialchars($dn) . '
' . $delOldRdnData);
+ throw new LAMException(_('Invalid data'), htmlspecialchars($dn) . '
' . $entry[1]);
}
$delOldRdn = ($delOldRdnData[Importer::VALUE] === '0') ? false : true;
return new RenameEntryTask($dn, $newRdn, $delOldRdn);
@@ -337,19 +339,31 @@ class Importer {
*
* @param string $dn DN
* @param string $lines lines
- * @param string $type change type
* @return ImporterTask task
*/
- private function getChangeTypeTask($dn, $lines, $type) {
+ private function getChangeTypeTask($dn, $lines) {
+ $firstLine = array_shift($lines);
+ $firstLineData = $this->getLineKeyValue($firstLine);
+ $type = $firstLineData[Importer::KEY];
+ $attributeName = $firstLineData[Importer::VALUE];
$attributes = array();
foreach ($lines as $line) {
$lineData = $this->getLineKeyValue($line);
- $attributes[$lineData[Importer::KEY]][] = $lineData[Importer::VALUE];
+ if ($lineData[Importer::KEY] !== $attributeName) {
+ throw new LAMException(_('Invalid data'), htmlspecialchars($dn) . ' - ' . htmlspecialchars($type));
+ }
+ $attributes[$attributeName][] = $lineData[Importer::VALUE];
}
if ($type === 'add') {
- return new AddEntryTask($dn, $attributes);
+ return new AddAttributesTask($dn, $attributes);
}
- throw new LAMException(_('Invalid data'), htmlspecialchars($dn) . ' - ' . Importer::CHANGETYPE . ': ' . htmlspecialchars($type));
+ elseif ($type === 'delete') {
+ return new DeleteAttributesTask($dn, $attributeName, $attributes);
+ }
+ elseif ($type === 'replace') {
+ return new ReplaceAttributesTask($dn, $attributes);
+ }
+ throw new LAMException(_('Invalid data'), htmlspecialchars($dn) . ' - ' . htmlspecialchars($type));
}
/**
@@ -599,6 +613,158 @@ class AddAttributesTask implements ImporterTask {
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;
+ }
+
+}
+
+/**
+ * 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;
+ }
+
}
?>
diff --git a/lam/tests/lib/importTest.php b/lam/tests/lib/importTest.php
index 9cfbcff9..991ce0ad 100644
--- a/lam/tests/lib/importTest.php
+++ b/lam/tests/lib/importTest.php
@@ -5,6 +5,8 @@ use LAM\TOOLS\IMPORT_EXPORT\AddAttributesTask;
use LAM\TOOLS\IMPORT_EXPORT\AddEntryTask;
use LAM\TOOLS\IMPORT_EXPORT\RenameEntryTask;
use LAM\TOOLS\IMPORT_EXPORT\DeleteEntryTask;
+use LAM\TOOLS\IMPORT_EXPORT\DeleteAttributesTask;
+use LAM\TOOLS\IMPORT_EXPORT\ReplaceAttributesTask;
/*
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
@@ -257,4 +259,184 @@ class ImporterTest extends PHPUnit_Framework_TestCase {
$this->assertEquals(DeleteEntryTask::class, get_class($task));
}
+ /**
+ * Change entry with modify changetype with invalid operation.
+ */
+ public function testChangeModifyInvalid() {
+ $lines = array(
+ "version: 1",
+ "",
+ "dn: uid=test,dc=example,dc=com",
+ "changeType: modify",
+ "invalid: test",
+ );
+
+ $this->setExpectedException(LAMException::class, 'uid=test,dc=example,dc=com');
+
+ $importer = new Importer();
+ $tasks = $importer->getTasks($lines);
+ }
+
+ /**
+ * Change entry with modify changetype and add operation.
+ */
+ public function testChangeModifyAdd() {
+ $lines = array(
+ "version: 1",
+ "",
+ "dn: uid=test,dc=example,dc=com",
+ "changeType: modify",
+ "add: uid",
+ "uid: uid1",
+ "uid: uid2"
+ );
+
+ $importer = new Importer();
+ $tasks = $importer->getTasks($lines);
+ $this->assertEquals(1, sizeof($tasks));
+ $task = $tasks[0];
+ $this->assertEquals(MultiTask::class, get_class($task));
+ $subtasks = $task->getTasks();
+ $this->assertEquals(1, sizeof($subtasks));
+ $subTask = $subtasks[0];
+ $this->assertEquals(AddAttributesTask::class, get_class($subTask));
+ $this->assertEquals($subTask->getDn(), 'uid=test,dc=example,dc=com');
+ $attributes = $subTask->getAttributes();
+ $this->assertEquals(1, sizeof($attributes));
+ $this->assertEquals(2, sizeof($attributes['uid']));
+ $this->assertTrue(in_array('uid1', $attributes['uid']));
+ $this->assertTrue(in_array('uid2', $attributes['uid']));
+ }
+
+ /**
+ * Change entry with modify changetype and two add operations.
+ */
+ public function testChangeModifyAddTwice() {
+ $lines = array(
+ "version: 1",
+ "",
+ "dn: uid=test,dc=example,dc=com",
+ "changeType: modify",
+ "add: uid",
+ "uid: uid1",
+ "uid: uid2",
+ "-",
+ "add: gn",
+ "gn: name1",
+ "gn: name2"
+ );
+
+ $importer = new Importer();
+ $tasks = $importer->getTasks($lines);
+ $this->assertEquals(1, sizeof($tasks));
+ $task = $tasks[0];
+ $this->assertEquals(MultiTask::class, get_class($task));
+ $subtasks = $task->getTasks();
+ $this->assertEquals(2, sizeof($subtasks));
+ $subTask = $subtasks[0];
+ $this->assertEquals(AddAttributesTask::class, get_class($subTask));
+ $this->assertEquals($subTask->getDn(), 'uid=test,dc=example,dc=com');
+ $attributes = $subTask->getAttributes();
+ $this->assertEquals(1, sizeof($attributes));
+ $this->assertEquals(2, sizeof($attributes['uid']));
+ $this->assertTrue(in_array('uid1', $attributes['uid']));
+ $this->assertTrue(in_array('uid2', $attributes['uid']));
+ $subTask = $subtasks[1];
+ $this->assertEquals(AddAttributesTask::class, get_class($subTask));
+ $this->assertEquals($subTask->getDn(), 'uid=test,dc=example,dc=com');
+ $attributes = $subTask->getAttributes();
+ $this->assertEquals(1, sizeof($attributes));
+ $this->assertEquals(2, sizeof($attributes['gn']));
+ $this->assertTrue(in_array('name1', $attributes['gn']));
+ $this->assertTrue(in_array('name2', $attributes['gn']));
+ }
+
+ /**
+ * Change entry with modify changetype and delete operation.
+ */
+ public function testChangeModifyDelete() {
+ $lines = array(
+ "version: 1",
+ "",
+ "dn: uid=test,dc=example,dc=com",
+ "changeType: modify",
+ "delete: uid",
+ "uid: uid1",
+ "uid: uid2"
+ );
+
+ $importer = new Importer();
+ $tasks = $importer->getTasks($lines);
+ $this->assertEquals(1, sizeof($tasks));
+ $task = $tasks[0];
+ $this->assertEquals(MultiTask::class, get_class($task));
+ $subtasks = $task->getTasks();
+ $this->assertEquals(1, sizeof($subtasks));
+ $subTask = $subtasks[0];
+ $this->assertEquals(DeleteAttributesTask::class, get_class($subTask));
+ $this->assertEquals($subTask->getDn(), 'uid=test,dc=example,dc=com');
+ $attributes = $subTask->getAttributes();
+ $this->assertEquals(1, sizeof($attributes));
+ $this->assertEquals(2, sizeof($attributes['uid']));
+ $this->assertTrue(in_array('uid1', $attributes['uid']));
+ $this->assertTrue(in_array('uid2', $attributes['uid']));
+ }
+
+ /**
+ * Change entry with modify changetype and delete operation.
+ */
+ public function testChangeModifyDeleteAll() {
+ $lines = array(
+ "version: 1",
+ "",
+ "dn: uid=test,dc=example,dc=com",
+ "changeType: modify",
+ "delete: uid",
+ );
+
+ $importer = new Importer();
+ $tasks = $importer->getTasks($lines);
+ $this->assertEquals(1, sizeof($tasks));
+ $task = $tasks[0];
+ $this->assertEquals(MultiTask::class, get_class($task));
+ $subtasks = $task->getTasks();
+ $this->assertEquals(1, sizeof($subtasks));
+ $subTask = $subtasks[0];
+ $this->assertEquals(DeleteAttributesTask::class, get_class($subTask));
+ $this->assertEquals($subTask->getDn(), 'uid=test,dc=example,dc=com');
+ $attributes = $subTask->getAttributes();
+ $this->assertTrue(empty($attributes));
+ }
+
+ /**
+ * Change entry with modify changetype and replace operation.
+ */
+ public function testChangeModifyReplace() {
+ $lines = array(
+ "version: 1",
+ "",
+ "dn: uid=test,dc=example,dc=com",
+ "changeType: modify",
+ "replace: uid",
+ "uid: uid1",
+ "uid: uid2",
+ );
+
+ $importer = new Importer();
+ $tasks = $importer->getTasks($lines);
+ $this->assertEquals(1, sizeof($tasks));
+ $task = $tasks[0];
+ $this->assertEquals(MultiTask::class, get_class($task));
+ $subtasks = $task->getTasks();
+ $this->assertEquals(1, sizeof($subtasks));
+ $subTask = $subtasks[0];
+ $this->assertEquals(ReplaceAttributesTask::class, get_class($subTask));
+ $this->assertEquals($subTask->getDn(), 'uid=test,dc=example,dc=com');
+ $attributes = $subTask->getAttributes();
+ $this->assertEquals(1, sizeof($attributes));
+ $this->assertEquals(2, sizeof($attributes['uid']));
+ $this->assertTrue(in_array('uid1', $attributes['uid']));
+ $this->assertTrue(in_array('uid2', $attributes['uid']));
+ }
+
}