Start of implementation of Import and Export using LDIF
This commit is contained in:
parent
ded1f74285
commit
4c8bd1c81f
@ -168,6 +168,11 @@ class Attribute implements \Countable, \ArrayAccess
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function addValue(string $value): void
|
||||
{
|
||||
$this->values->push($value);
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return $this->values->count();
|
||||
|
@ -50,7 +50,7 @@ class Factory
|
||||
*/
|
||||
public static function create(string $attribute,array $values): Attribute
|
||||
{
|
||||
$class = Arr::get(self::map,$attribute,Attribute::class);
|
||||
$class = Arr::get(self::map,strtolower($attribute),Attribute::class);
|
||||
Log::debug(sprintf('%s:Creating LDAP Attribute [%s] as [%s]',static::LOGKEY,$attribute,$class));
|
||||
|
||||
return new $class($attribute,$values);
|
||||
|
53
app/Classes/LDAP/Export.php
Normal file
53
app/Classes/LDAP/Export.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP;
|
||||
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use LdapRecord\Query\Collection;
|
||||
|
||||
/**
|
||||
* Export Class
|
||||
*
|
||||
* This abstract classes provides all the common methods and variables for the
|
||||
* export classes.
|
||||
*/
|
||||
abstract class Export
|
||||
{
|
||||
// Line Break
|
||||
protected string $br = "\r\n";
|
||||
|
||||
// Item(s) being Exported
|
||||
protected Collection $items;
|
||||
|
||||
// Type of export
|
||||
protected const type = 'Unknown';
|
||||
|
||||
public function __construct(Collection $items)
|
||||
{
|
||||
$this->items = $items;
|
||||
}
|
||||
|
||||
abstract public function __toString(): string;
|
||||
|
||||
protected function header()
|
||||
{
|
||||
$output = '';
|
||||
|
||||
$output .= sprintf('# %s %s',__(static::type.' for'),($x=$this->items->first())).$this->br;
|
||||
$output .= sprintf('# %s: %s (%s)',
|
||||
__('Server'),
|
||||
$x->getConnection()->getConfiguration()->get('name'),
|
||||
$x->getConnection()->getLdapConnection()->getHost()).$this->br;
|
||||
//$output .= sprintf('# %s: %s',__('Search Scope'),$this->scope).$this->br;
|
||||
//$output .= sprintf('# %s: %s',__('Search Filter'),$this->entry->dn).$this->br;
|
||||
$output .= sprintf('# %s: %s',__('Total Entries'),$this->items->count()).$this->br;
|
||||
$output .= '#'.$this->br;
|
||||
$output .= sprintf('# %s %s (%s) on %s',__('Generated by'),config('app.name'),config('app.url'),date('F j, Y g:i a')).$this->br;
|
||||
$output .= sprintf('# %s %s',__('Exported by'),Auth::user() ?: 'Anonymous').$this->br;
|
||||
$output .= sprintf('# %s: %s',__('Version'),config('app.version')).$this->br;
|
||||
|
||||
$output .= $this->br;
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
78
app/Classes/LDAP/Export/LDIF.php
Normal file
78
app/Classes/LDAP/Export/LDIF.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Export;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
use App\Classes\LDAP\Export;
|
||||
|
||||
/**
|
||||
* Export from LDAP using an LDIF format
|
||||
*/
|
||||
class LDIF extends Export
|
||||
{
|
||||
// The maximum length of the ldif line
|
||||
private int $line_length = 76;
|
||||
protected const type = 'LDIF Export';
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$result = parent::header();
|
||||
$result .= 'version: 1';
|
||||
$result .= $this->br;
|
||||
|
||||
$c = 1;
|
||||
foreach ($this->items as $o) {
|
||||
if ($c > 1)
|
||||
$result .= $this->br;
|
||||
|
||||
$title = (string)$o;
|
||||
if (strlen($title) > $this->line_length)
|
||||
$title = Str::of($title)->limit($this->line_length-3-5,'...'.substr($title,-5));
|
||||
|
||||
$result .= sprintf('# %s %s: %s',__('Entry'),$c++,$title).$this->br;
|
||||
|
||||
// Display DN
|
||||
$result .= $this->multiLineDisplay(
|
||||
Str::isAscii($o)
|
||||
? sprintf('dn: %s',$o)
|
||||
: sprintf('dn:: %s',base64_encode($o))
|
||||
,$this->br);
|
||||
|
||||
// Display Attributes
|
||||
foreach ($o->getObjects() as $ao) {
|
||||
foreach ($ao->values as $value) {
|
||||
$result .= $this->multiLineDisplay(
|
||||
Str::isAscii($value)
|
||||
? sprintf('%s: %s',$ao->name,$value)
|
||||
: sprintf('%s:: %s',$ao->name,base64_encode($value))
|
||||
,$this->br);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to wrap LDIF lines
|
||||
*
|
||||
* @param string $str The line to be wrapped if needed.
|
||||
*/
|
||||
private function multiLineDisplay(string $str,string $br): string
|
||||
{
|
||||
$length_string = strlen($str);
|
||||
$length_max = $this->line_length;
|
||||
|
||||
$output = '';
|
||||
while ($length_string > $length_max) {
|
||||
$output .= substr($str,0,$length_max).$br;
|
||||
$str = ' '.substr($str,$length_max);
|
||||
$length_string = strlen($str);
|
||||
}
|
||||
|
||||
$output .= $str.$br;
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
79
app/Classes/LDAP/Import.php
Normal file
79
app/Classes/LDAP/Import.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
use App\Exceptions\Import\GeneralException;
|
||||
use App\Exceptions\Import\ObjectExistsException;
|
||||
use App\Ldap\Entry;
|
||||
|
||||
/**
|
||||
* Import Class
|
||||
*
|
||||
* This abstract classes provides all the common methods and variables for the
|
||||
* import classes.
|
||||
*/
|
||||
abstract class Import
|
||||
{
|
||||
// Valid LDIF commands
|
||||
protected const LDAP_IMPORT_ADD = 1;
|
||||
protected const LDAP_IMPORT_DELETE = 2;
|
||||
protected const LDAP_IMPORT_MODRDN = 3;
|
||||
protected const LDAP_IMPORT_MODDN = 4;
|
||||
protected const LDAP_IMPORT_MODIFY = 5;
|
||||
|
||||
protected const LDAP_ACTIONS = [
|
||||
'add' => self::LDAP_IMPORT_ADD,
|
||||
'delete' => self::LDAP_IMPORT_DELETE,
|
||||
'modrdn' => self::LDAP_IMPORT_MODRDN,
|
||||
'moddn' => self::LDAP_IMPORT_MODDN,
|
||||
'modify' => self::LDAP_IMPORT_MODIFY,
|
||||
];
|
||||
|
||||
// The import data to process
|
||||
protected string $input;
|
||||
// The attributes the server knows about
|
||||
protected Collection $server_attributes;
|
||||
|
||||
public function __construct(string $input) {
|
||||
$this->input = $input;
|
||||
$this->server_attributes = config('server')->schema('attributetypes');
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to commit an entry and return the result.
|
||||
*
|
||||
* @param Entry $o
|
||||
* @param int $action
|
||||
* @return Collection
|
||||
* @throws GeneralException
|
||||
* @throws ObjectExistsException
|
||||
*/
|
||||
final protected function commit(Entry $o,int $action): Collection
|
||||
{
|
||||
switch ($action) {
|
||||
case static::LDAP_IMPORT_ADD:
|
||||
try {
|
||||
$o->save();
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return collect([
|
||||
'dn'=>$o->getDN(),
|
||||
'result'=>sprintf('%d: %s (%s)',
|
||||
($x=$e->getDetailedError())->getErrorCode(),
|
||||
$x->getErrorMessage(),
|
||||
$x->getDiagnosticMessage(),
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
return collect(['dn'=>$o->getDN(),'result'=>__('Created')]);
|
||||
|
||||
default:
|
||||
throw new GeneralException('Unhandled action during commit: '.$action);
|
||||
}
|
||||
}
|
||||
|
||||
abstract public function process(): Collection;
|
||||
}
|
233
app/Classes/LDAP/Import/LDIF.php
Normal file
233
app/Classes/LDAP/Import/LDIF.php
Normal file
@ -0,0 +1,233 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\LDAP\Import;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Nette\NotImplementedException;
|
||||
|
||||
use App\Classes\LDAP\Import;
|
||||
use App\Exceptions\Import\{GeneralException,VersionException};
|
||||
use App\Ldap\Entry;
|
||||
|
||||
/**
|
||||
* Import LDIF to LDAP using an LDIF format
|
||||
*
|
||||
* The LDIF spec is described by RFC2849
|
||||
* http://www.ietf.org/rfc/rfc2849.txt
|
||||
*/
|
||||
class LDIF extends Import
|
||||
{
|
||||
private const LOGKEY = 'ILF';
|
||||
|
||||
public function process(): Collection
|
||||
{
|
||||
$c = 0;
|
||||
$action = NULL;
|
||||
$attribute = NULL;
|
||||
$base64encoded = FALSE;
|
||||
$o = NULL;
|
||||
$value = '';
|
||||
$version = NULL;
|
||||
$result = collect();
|
||||
|
||||
// @todo When renaming DNs, the hotlink should point to the new entry on success, or the old entry on failure.
|
||||
foreach (preg_split('/(\r?\n|\r)/',$this->input) as $line) {
|
||||
$c++;
|
||||
Log::debug(sprintf('%s: LDIF Line [%s]',self::LOGKEY,$line));
|
||||
$line = trim($line);
|
||||
|
||||
// If the line starts with a comment, ignore it
|
||||
if (preg_match('/^#/',$line))
|
||||
continue;
|
||||
|
||||
// If we have a blank line, then that completes this command
|
||||
if (! $line) {
|
||||
if (! is_null($o)) {
|
||||
// Add the last attribute;
|
||||
$o->addAttribute($attribute,$base64encoded ? base64_decode($value) : $value);
|
||||
|
||||
Log::debug(sprintf('%s: Committing Entry [%s]',self::LOGKEY,$o->getDN()));
|
||||
|
||||
// Commit
|
||||
$result->push($this->commit($o,$action));
|
||||
$result->last()->put('line',$c);
|
||||
|
||||
$o = NULL;
|
||||
$action = NULL;
|
||||
$base64encoded = FALSE;
|
||||
$attribute = NULL;
|
||||
$value = '';
|
||||
|
||||
// Else its a blank line
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$m = [];
|
||||
preg_match('/^([a-zA-Z0-9;-]+)(:+)\s+(.*)$/',$line,$m);
|
||||
|
||||
switch ($x=Arr::get($m,1)) {
|
||||
case 'changetype':
|
||||
if ($m[2] !== ':')
|
||||
throw new GeneralException(sprintf('ChangeType cannot be base64 encoded set at [%d]. (line %d)',$version,$c));
|
||||
|
||||
switch ($m[3]) {
|
||||
// if (preg_match('/^changetype:[ ]*(delete|add|modrdn|moddn|modify)/i',$lines[0])) {
|
||||
default:
|
||||
throw new NotImplementedException(sprintf('Unknown change type [%s]? (line %d)',$m[3],$c));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'version':
|
||||
if (! is_null($version))
|
||||
throw new VersionException(sprintf('Version has already been set at [%d]. (line %d)',$version,$c));
|
||||
|
||||
if ($m[2] !== ':')
|
||||
throw new VersionException(sprintf('Version cannot be base64 encoded set at [%d]. (line %d)',$version,$c));
|
||||
|
||||
$version = (int)$m[3];
|
||||
break;
|
||||
|
||||
// Treat it as an attribute
|
||||
default:
|
||||
// If $m is NULL, then this is the 2nd (or more) line of a base64 encoded value
|
||||
if (! $m) {
|
||||
$value .= $line;
|
||||
Log::debug(sprintf('%s: Attribute [%s] adding [%s] (%d)',self::LOGKEY,$attribute,$line,$c));
|
||||
|
||||
// add to last attr value
|
||||
continue 2;
|
||||
}
|
||||
|
||||
// We are ready to create the entry or add the attribute
|
||||
if ($attribute) {
|
||||
if ($attribute === 'dn') {
|
||||
if (! is_null($o))
|
||||
throw new GeneralException(sprintf('Previous Entry not complete? (line %d)',$c));
|
||||
|
||||
$dn = $base64encoded ? base64_decode($value) : $value;
|
||||
Log::debug(sprintf('%s: Creating new entry:',self::LOGKEY,$dn));
|
||||
//$o = Entry::find($dn);
|
||||
|
||||
// If it doesnt exist, we'll create it
|
||||
//if (! $o) {
|
||||
$o = new Entry;
|
||||
$o->setDn($dn);
|
||||
//}
|
||||
|
||||
$action = self::LDAP_IMPORT_ADD;
|
||||
|
||||
} else {
|
||||
Log::debug(sprintf('%s: Adding Attribute [%s] value [%s] (%d)',self::LOGKEY,$attribute,$value,$c));
|
||||
|
||||
if ($value)
|
||||
$o->addAttribute($attribute,$base64encoded ? base64_decode($value) : $value);
|
||||
else
|
||||
throw new GeneralException(sprintf('Attribute has no value [%s] (line %d)',$attribute,$c));
|
||||
}
|
||||
}
|
||||
|
||||
// Start of a new attribute
|
||||
$base64encoded = ($m[2] === '::');
|
||||
// @todo Need to parse attributes with ';' options
|
||||
$attribute = $m[1];
|
||||
$value = $m[3];
|
||||
|
||||
Log::debug(sprintf('%s: New Attribute [%s] with [%s] (%d)',self::LOGKEY,$attribute,$value,$c));
|
||||
}
|
||||
|
||||
if ($version !== 1)
|
||||
throw new VersionException('LDIF import cannot handle version: '.($version ?: __('NOT DEFINED')));
|
||||
}
|
||||
|
||||
// We may still have a pending action
|
||||
if ($action) {
|
||||
// Add the last attribute;
|
||||
$o->addAttribute($attribute,$base64encoded ? base64_decode($value) : $value);
|
||||
|
||||
Log::debug(sprintf('%s: Committing Entry [%s]',self::LOGKEY,$o->getDN()));
|
||||
|
||||
// Commit
|
||||
$result->push($this->commit($o,$action));
|
||||
$result->last()->put('line',$c);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function readEntry() {
|
||||
static $haveVersion = false;
|
||||
|
||||
if ($lines = $this->nextLines()) {
|
||||
|
||||
$server = $this->getServer();
|
||||
|
||||
# The first line should be the DN
|
||||
if (preg_match('/^dn:/',$lines[0])) {
|
||||
list($text,$dn) = $this->getAttrValue(array_shift($lines));
|
||||
|
||||
# The second line should be our changetype
|
||||
if (preg_match('/^changetype:[ ]*(delete|add|modrdn|moddn|modify)/i',$lines[0])) {
|
||||
$attrvalue = $this->getAttrValue($lines[0]);
|
||||
$changetype = $attrvalue[1];
|
||||
array_shift($lines);
|
||||
|
||||
} else
|
||||
$changetype = 'add';
|
||||
|
||||
$this->template = new Template($this->server_id,null,null,$changetype);
|
||||
|
||||
switch ($changetype) {
|
||||
case 'add':
|
||||
$rdn = get_rdn($dn);
|
||||
$container = $server->getContainer($dn);
|
||||
|
||||
$this->template->setContainer($container);
|
||||
$this->template->accept();
|
||||
|
||||
$this->getAddDetails($lines);
|
||||
$this->template->setRDNAttributes($rdn);
|
||||
|
||||
return $this->template;
|
||||
|
||||
break;
|
||||
|
||||
case 'modify':
|
||||
if (! $server->dnExists($dn))
|
||||
return $this->error(sprintf('%s %s',_('DN does not exist'),$dn),$lines);
|
||||
|
||||
$this->template->setDN($dn);
|
||||
$this->template->accept(false,true);
|
||||
|
||||
return $this->getModifyDetails($lines);
|
||||
|
||||
break;
|
||||
|
||||
case 'moddn':
|
||||
case 'modrdn':
|
||||
if (! $server->dnExists($dn))
|
||||
return $this->error(sprintf('%s %s',_('DN does not exist'),$dn),$lines);
|
||||
|
||||
$this->template->setDN($dn);
|
||||
$this->template->accept();
|
||||
|
||||
return $this->getModRDNAttributes($lines);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if (! $server->dnExists($dn))
|
||||
return $this->error(_('Unkown change type'),$lines);
|
||||
}
|
||||
|
||||
} else
|
||||
return $this->error(_('A valid dn line is required'),$lines);
|
||||
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
}
|
7
app/Exceptions/Import/AttributeException.php
Normal file
7
app/Exceptions/Import/AttributeException.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions\Import;
|
||||
|
||||
use Exception;
|
||||
|
||||
class AttributeException extends Exception {}
|
7
app/Exceptions/Import/GeneralException.php
Normal file
7
app/Exceptions/Import/GeneralException.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions\Import;
|
||||
|
||||
use Exception;
|
||||
|
||||
class GeneralException extends Exception {}
|
7
app/Exceptions/Import/ObjectExistsException.php
Normal file
7
app/Exceptions/Import/ObjectExistsException.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions\Import;
|
||||
|
||||
use Exception;
|
||||
|
||||
class ObjectExistsException extends Exception {}
|
7
app/Exceptions/Import/VersionException.php
Normal file
7
app/Exceptions/Import/VersionException.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions\Import;
|
||||
|
||||
use Exception;
|
||||
|
||||
class VersionException extends Exception {}
|
@ -8,19 +8,38 @@ use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use LdapRecord\Exceptions\InsufficientAccessException;
|
||||
use LdapRecord\LdapRecordException;
|
||||
use LdapRecord\Query\ObjectNotFoundException;
|
||||
|
||||
use App\Classes\LDAP\{Attribute,Server};
|
||||
use App\Classes\LDAP\Import\LDIF as LDIFImport;
|
||||
use App\Classes\LDAP\Export\LDIF as LDIFExport;
|
||||
use App\Exceptions\Import\{GeneralException,VersionException};
|
||||
use App\Exceptions\InvalidUsage;
|
||||
use App\Http\Requests\EntryRequest;
|
||||
use App\Http\Requests\{EntryRequest,ImportRequest};
|
||||
use App\Ldap\Entry;
|
||||
use App\View\Components\AttributeType;
|
||||
use Nette\NotImplementedException;
|
||||
|
||||
class HomeController extends Controller
|
||||
{
|
||||
private function bases()
|
||||
{
|
||||
$base = Server::baseDNs() ?: collect();
|
||||
|
||||
return $base->transform(function($item) {
|
||||
return [
|
||||
'title'=>$item->getRdn(),
|
||||
'item'=>$item->getDNSecure(),
|
||||
'lazy'=>TRUE,
|
||||
'icon'=>'fa-fw fas fa-sitemap',
|
||||
'tooltip'=>$item->getDn(),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug Page
|
||||
*
|
||||
@ -49,6 +68,22 @@ class HomeController extends Controller
|
||||
->with('page_actions',$page_actions);
|
||||
}
|
||||
|
||||
public function entry_export(Request $request,string $id)
|
||||
{
|
||||
$dn = Crypt::decryptString($id);
|
||||
|
||||
$result = (new Entry)
|
||||
->query()
|
||||
//->cache(Carbon::now()->addSeconds(Config::get('ldap.cache.time')))
|
||||
//->select(['*'])
|
||||
->setDn($dn)
|
||||
->recursive()
|
||||
->get();
|
||||
|
||||
return view('fragment.export')
|
||||
->with('result',new LDIFExport($result));
|
||||
}
|
||||
|
||||
public function entry_newattr(string $id)
|
||||
{
|
||||
$x = new AttributeType(new Attribute($id,[]),TRUE);
|
||||
@ -76,20 +111,8 @@ class HomeController extends Controller
|
||||
->withInput()
|
||||
->with('note',__('No attributes changed'));
|
||||
|
||||
$base = Server::baseDNs() ?: collect();
|
||||
|
||||
$bases = $base->transform(function($item) {
|
||||
return [
|
||||
'title'=>$item->getRdn(),
|
||||
'item'=>$item->getDNSecure(),
|
||||
'lazy'=>TRUE,
|
||||
'icon'=>'fa-fw fas fa-sitemap',
|
||||
'tooltip'=>$item->getDn(),
|
||||
];
|
||||
});
|
||||
|
||||
return view('frames.update')
|
||||
->with('bases',$bases)
|
||||
return view('update')
|
||||
->with('bases',$this->bases())
|
||||
->with('dn',$dn)
|
||||
->with('o',$o);
|
||||
}
|
||||
@ -103,18 +126,6 @@ class HomeController extends Controller
|
||||
*/
|
||||
public function entry_update(EntryRequest $request)
|
||||
{
|
||||
$base = Server::baseDNs() ?: collect();
|
||||
|
||||
$bases = $base->transform(function($item) {
|
||||
return [
|
||||
'title'=>$item->getRdn(),
|
||||
'item'=>$item->getDNSecure(),
|
||||
'lazy'=>TRUE,
|
||||
'icon'=>'fa-fw fas fa-sitemap',
|
||||
'tooltip'=>$item->getDn(),
|
||||
];
|
||||
});
|
||||
|
||||
$dn = Crypt::decryptString($request->dn);
|
||||
|
||||
$o = config('server')->fetch($dn);
|
||||
@ -168,51 +179,75 @@ class HomeController extends Controller
|
||||
*/
|
||||
public function home()
|
||||
{
|
||||
$base = Server::baseDNs() ?: collect();
|
||||
|
||||
$bases = $base->transform(function($item) {
|
||||
return [
|
||||
'title'=>$item->getRdn(),
|
||||
'item'=>$item->getDNSecure(),
|
||||
'lazy'=>TRUE,
|
||||
'icon'=>'fa-fw fas fa-sitemap',
|
||||
'tooltip'=>$item->getDn(),
|
||||
];
|
||||
});
|
||||
|
||||
if (old('dn'))
|
||||
return view('frame')
|
||||
->with('subframe','dn')
|
||||
->with('bases',$bases)
|
||||
->with('bases',$this->bases())
|
||||
->with('o',config('server')->fetch($dn=Crypt::decryptString(old('dn'))))
|
||||
->with('dn',$dn);
|
||||
|
||||
elseif (old('frame'))
|
||||
return view('frame')
|
||||
->with('subframe',old('frame'))
|
||||
->with('bases',$bases);
|
||||
->with('bases',$this->bases());
|
||||
|
||||
else
|
||||
return view('home')
|
||||
->with('bases',$bases)
|
||||
->with('bases',$this->bases())
|
||||
->with('server',config('ldap.connections.default.name'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the incoming LDIF file or LDIF text
|
||||
*
|
||||
* @param ImportRequest $request
|
||||
* @param string $type
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Foundation\Application
|
||||
* @throws GeneralException
|
||||
* @throws VersionException
|
||||
*/
|
||||
public function import(ImportRequest $request,string $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'ldif':
|
||||
$import = new LDIFImport($x=($request->text ?: $request->file->get()));
|
||||
break;
|
||||
|
||||
default:
|
||||
abort(404,'Unknown import type: '.$type);
|
||||
}
|
||||
|
||||
try {
|
||||
$result = $import->process();
|
||||
|
||||
} catch (NotImplementedException $e) {
|
||||
abort(555,$e->getMessage());
|
||||
|
||||
} catch (\Exception $e) {
|
||||
abort(598,$e->getMessage());
|
||||
}
|
||||
|
||||
return view('frame')
|
||||
->with('subframe','import_result')
|
||||
->with('bases',$this->bases())
|
||||
->with('result',$result)
|
||||
->with('ldif',htmlspecialchars($x));
|
||||
}
|
||||
|
||||
public function import_frame()
|
||||
{
|
||||
return view('frames.import');
|
||||
}
|
||||
|
||||
/**
|
||||
* LDAP Server INFO
|
||||
*
|
||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
||||
* @throws ObjectNotFoundException
|
||||
*/
|
||||
public function info()
|
||||
{
|
||||
// Load our attributes
|
||||
$s = config('server');
|
||||
$s->schema('objectclasses');
|
||||
$s->schema('attributetypes');
|
||||
|
||||
return view('frames.info')
|
||||
->with('s',$s);
|
||||
->with('s',config('server'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
22
app/Http/Requests/ImportRequest.php
Normal file
22
app/Http/Requests/ImportRequest.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class ImportRequest extends FormRequest
|
||||
{
|
||||
public function authorize()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'frame' => 'required|string|in:import',
|
||||
'file' => 'nullable|extensions:ldif|required_without:text',
|
||||
'text'=> 'nullable|prohibits:file|string|min:16',
|
||||
];
|
||||
}
|
||||
}
|
@ -2,21 +2,50 @@
|
||||
|
||||
namespace App\Ldap;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use LdapRecord\Support\Arr;
|
||||
use LdapRecord\Models\Model;
|
||||
use LdapRecord\Query\Model\Builder;
|
||||
|
||||
use App\Classes\LDAP\Attribute;
|
||||
use App\Classes\LDAP\Attribute\Factory;
|
||||
use App\Classes\LDAP\Export\LDIF;
|
||||
use App\Exceptions\Import\AttributeException;
|
||||
|
||||
class Entry extends Model
|
||||
{
|
||||
private Collection $objects;
|
||||
private bool $noObjectAttributes = FALSE;
|
||||
|
||||
/* OVERRIDES */
|
||||
|
||||
public function __construct(array $attributes = [])
|
||||
{
|
||||
$this->objects = collect();
|
||||
|
||||
parent::__construct($attributes);
|
||||
}
|
||||
|
||||
public function discardChanges(): static
|
||||
{
|
||||
parent::discardChanges();
|
||||
|
||||
// If we are discharging changes, we need to reset our $objects;
|
||||
$this->objects = $this->getAttributesAsObjects($this->attributes);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function overrides getAttributes to use our collection of Attribute objects instead of the models attributes.
|
||||
*
|
||||
* @return array
|
||||
* @note $this->attributes may not be updated with changes
|
||||
*/
|
||||
public function getAttributes(): array
|
||||
{
|
||||
return $this->getAttributesAsObjects()->toArray();
|
||||
return $this->objects->map(function($item) { return $item->values->toArray(); })->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -24,57 +53,80 @@ class Entry extends Model
|
||||
*/
|
||||
protected function originalIsEquivalent(string $key): bool
|
||||
{
|
||||
if (! array_key_exists($key, $this->original)) {
|
||||
return false;
|
||||
$key = $this->normalizeAttributeKey($key);
|
||||
|
||||
if ((! array_key_exists($key, $this->original)) && (! $this->objects->has($key))) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
$current = $this->attributes[$key];
|
||||
$original = $this->original[$key];
|
||||
$original = $this->objects->get($key)->values;
|
||||
|
||||
if ($current === $original) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//dump(['key'=>$key,'current'=>$current,'original'=>$this->original[$key],'objectvalue'=>$this->getAttributeAsObject($key)->isDirty()]);
|
||||
return ! $this->getAttributeAsObject($key)->isDirty();
|
||||
return ! $this->getObject($key)->isDirty();
|
||||
}
|
||||
|
||||
public function getOriginal(): array
|
||||
public static function query(bool $noattrs=false): Builder
|
||||
{
|
||||
static $result = NULL;
|
||||
$o = new static;
|
||||
|
||||
if (is_null($result)) {
|
||||
$result = collect();
|
||||
if ($noattrs)
|
||||
$o->noObjectAttributes();
|
||||
|
||||
// @todo Optimise this foreach with getAttributes()
|
||||
foreach (parent::getOriginal() as $attribute => $value) {
|
||||
// If the attribute name has language tags
|
||||
$matches = [];
|
||||
if (preg_match('/^([a-zA-Z]+)(;([a-zA-Z-;]+))+/',$attribute,$matches)) {
|
||||
$attribute = $matches[1];
|
||||
return $o->newQuery();
|
||||
}
|
||||
|
||||
// If the attribute doesnt exist we'll create it
|
||||
$o = Arr::get($result,$attribute,Factory::create($attribute,[]));
|
||||
$o->setLangTag($matches[3],$value);
|
||||
/**
|
||||
* As attribute values are updated, or new ones created, we need to mirror that
|
||||
* into our $objects
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setAttribute(string $key, mixed $value): static
|
||||
{
|
||||
parent::setAttribute($key,$value);
|
||||
|
||||
} else {
|
||||
$o = Factory::create($attribute,$value);
|
||||
}
|
||||
$key = $this->normalizeAttributeKey($key);
|
||||
|
||||
if (! $result->has($attribute)) {
|
||||
// Set the rdn flag
|
||||
if (preg_match('/^'.$attribute.'=/i',$this->dn))
|
||||
$o->setRDN();
|
||||
if ((! $this->objects->get($key)) && $value) {
|
||||
$o = new Attribute($key,[]);
|
||||
$o->value = $value;
|
||||
|
||||
// Set required flag
|
||||
$o->required_by(collect($this->getAttribute('objectclass')));
|
||||
$this->objects->put($key,$o);
|
||||
|
||||
$result->put($attribute,$o);
|
||||
}
|
||||
}
|
||||
} elseif ($this->objects->get($key)) {
|
||||
$this->objects->get($key)->value = $this->attributes[$key];
|
||||
}
|
||||
|
||||
return $result->toArray();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* We'll shadow $this->attributes to $this->objects - a collection of Attribute objects
|
||||
*
|
||||
* Using the objects, it'll make it easier to work with attribute values
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function setRawAttributes(array $attributes = []): static
|
||||
{
|
||||
parent::setRawAttributes($attributes);
|
||||
|
||||
// We only set our objects on DN entries (otherwise we might get into a recursion loop if this is the schema DN)
|
||||
if ($this->dn && (! in_array($this->dn,Arr::get($this->attributes,'subschemasubentry',[])))) {
|
||||
$this->objects = $this->getAttributesAsObjects($this->attributes);
|
||||
|
||||
} else {
|
||||
$this->objects = collect();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/* ATTRIBUTES */
|
||||
@ -92,88 +144,89 @@ class Entry extends Model
|
||||
|
||||
/* METHODS */
|
||||
|
||||
/**
|
||||
* Get an attribute as an object
|
||||
*
|
||||
* @param string $key
|
||||
* @return Attribute|null
|
||||
*/
|
||||
public function getAttributeAsObject(string $key): Attribute|null
|
||||
public function addAttribute(string $key,mixed $value): void
|
||||
{
|
||||
return Arr::get($this->getAttributesAsObjects(),$key);
|
||||
$key = $this->normalizeAttributeKey($key);
|
||||
|
||||
if (config('server')->schema('attributetypes')->has($key) === FALSE)
|
||||
throw new AttributeException('Schema doesnt have attribute [%s]',$key);
|
||||
|
||||
if ($x=$this->objects->get($key)) {
|
||||
$x->addValue($value);
|
||||
|
||||
} else {
|
||||
$this->objects->put($key,Attribute\Factory::create($key,Arr::wrap($value)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert all our attribute values into an array of Objects
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return Collection
|
||||
*/
|
||||
protected function getAttributesAsObjects(): Collection
|
||||
protected function getAttributesAsObjects(array $attributes): Collection
|
||||
{
|
||||
static $result = NULL;
|
||||
$result = collect();
|
||||
|
||||
if (is_null($result)) {
|
||||
$result = collect();
|
||||
foreach ($attributes as $attribute => $value) {
|
||||
// If the attribute name has language tags
|
||||
$matches = [];
|
||||
if (preg_match('/^([a-zA-Z]+)(;([a-zA-Z-;]+))+/',$attribute,$matches)) {
|
||||
$attribute = $matches[1];
|
||||
|
||||
foreach (parent::getAttributes() as $attribute => $value) {
|
||||
// If the attribute name has language tags
|
||||
$matches = [];
|
||||
if (preg_match('/^([a-zA-Z]+)(;([a-zA-Z-;]+))+/',$attribute,$matches)) {
|
||||
$attribute = $matches[1];
|
||||
// If the attribute doesnt exist we'll create it
|
||||
$o = Arr::get($result,$attribute,Factory::create($attribute,[]));
|
||||
$o->setLangTag($matches[3],$value);
|
||||
|
||||
// If the attribute doesnt exist we'll create it
|
||||
$o = Arr::get($result,$attribute,Factory::create($attribute,[]));
|
||||
$o->setLangTag($matches[3],$value);
|
||||
|
||||
} else {
|
||||
$o = Factory::create($attribute,$value);
|
||||
}
|
||||
|
||||
if (! $result->has($attribute)) {
|
||||
// Set the rdn flag
|
||||
if (preg_match('/^'.$attribute.'=/i',$this->dn))
|
||||
$o->setRDN();
|
||||
|
||||
// Set required flag
|
||||
$o->required_by(collect($this->getAttribute('objectclass')));
|
||||
|
||||
// Store our original value to know if this attribute has changed
|
||||
if ($x=Arr::get($this->original,$attribute))
|
||||
$o->oldValues($x);
|
||||
|
||||
$result->put($attribute,$o);
|
||||
}
|
||||
} else {
|
||||
$o = Factory::create($attribute,$value);
|
||||
}
|
||||
|
||||
$sort = collect(config('ldap.attr_display_order',[]))->transform(function($item) { return strtolower($item); });
|
||||
if (! $result->has($attribute)) {
|
||||
// Set the rdn flag
|
||||
if (preg_match('/^'.$attribute.'=/i',$this->dn))
|
||||
$o->setRDN();
|
||||
|
||||
// Order the attributes
|
||||
$result = $result->sortBy([function(Attribute $a,Attribute $b) use ($sort): int {
|
||||
if ($a === $b)
|
||||
return 0;
|
||||
// Set required flag
|
||||
$o->required_by(collect($this->getAttribute('objectclass')));
|
||||
|
||||
// Check if $a/$b are in the configuration to be sorted first, if so get it's key
|
||||
$a_key = $sort->search($a->name_lc);
|
||||
$b_key = $sort->search($b->name_lc);
|
||||
// Store our original value to know if this attribute has changed
|
||||
if ($x=Arr::get($this->original,$attribute))
|
||||
$o->oldValues($x);
|
||||
|
||||
// If the keys were not in the sort list, set the key to be the count of elements (ie: so it is last to be sorted)
|
||||
if ($a_key === FALSE)
|
||||
$a_key = $sort->count()+1;
|
||||
|
||||
if ($b_key === FALSE)
|
||||
$b_key = $sort->count()+1;
|
||||
|
||||
// Case where neither $a, nor $b are in ldap.attr_display_order, $a_key = $b_key = one greater than num elements.
|
||||
// So we sort them alphabetically
|
||||
if ($a_key === $b_key)
|
||||
return strcasecmp($a->name,$b->name);
|
||||
|
||||
// Case where at least one attribute or its friendly name is in $attrs_display_order
|
||||
// return -1 if $a before $b in $attrs_display_order
|
||||
return ($a_key < $b_key) ? -1 : 1;
|
||||
} ]);
|
||||
$result->put($attribute,$o);
|
||||
}
|
||||
}
|
||||
|
||||
$sort = collect(config('ldap.attr_display_order',[]))->transform(function($item) { return strtolower($item); });
|
||||
|
||||
// Order the attributes
|
||||
$result = $result->sortBy([function(Attribute $a,Attribute $b) use ($sort): int {
|
||||
if ($a === $b)
|
||||
return 0;
|
||||
|
||||
// Check if $a/$b are in the configuration to be sorted first, if so get it's key
|
||||
$a_key = $sort->search($a->name_lc);
|
||||
$b_key = $sort->search($b->name_lc);
|
||||
|
||||
// If the keys were not in the sort list, set the key to be the count of elements (ie: so it is last to be sorted)
|
||||
if ($a_key === FALSE)
|
||||
$a_key = $sort->count()+1;
|
||||
|
||||
if ($b_key === FALSE)
|
||||
$b_key = $sort->count()+1;
|
||||
|
||||
// Case where neither $a, nor $b are in ldap.attr_display_order, $a_key = $b_key = one greater than num elements.
|
||||
// So we sort them alphabetically
|
||||
if ($a_key === $b_key)
|
||||
return strcasecmp($a->name,$b->name);
|
||||
|
||||
// Case where at least one attribute or its friendly name is in $attrs_display_order
|
||||
// return -1 if $a before $b in $attrs_display_order
|
||||
return ($a_key < $b_key) ? -1 : 1;
|
||||
} ]);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@ -208,11 +261,31 @@ class Entry extends Model
|
||||
*/
|
||||
public function getInternalAttributes(): Collection
|
||||
{
|
||||
return collect($this->getAttributes())->filter(function($item) {
|
||||
return $this->objects->filter(function($item) {
|
||||
return $item->is_internal;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an attribute as an object
|
||||
*
|
||||
* @param string $key
|
||||
* @return Attribute|null
|
||||
*/
|
||||
public function getObject(string $key): Attribute|null
|
||||
{
|
||||
return $this->objects->get($this->normalizeAttributeKey($key));
|
||||
}
|
||||
|
||||
public function getObjects(): Collection
|
||||
{
|
||||
// In case we havent built our objects yet (because they werent available while determining the schema DN)
|
||||
if ((! $this->objects->count()) && $this->attributes)
|
||||
$this->objects = $this->getAttributesAsObjects($this->attributes);
|
||||
|
||||
return $this->objects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of attributes without any values
|
||||
*
|
||||
@ -230,11 +303,46 @@ class Entry extends Model
|
||||
*/
|
||||
public function getVisibleAttributes(): Collection
|
||||
{
|
||||
return collect($this->getAttributes())->filter(function($item) {
|
||||
return $this->objects->filter(function($item) {
|
||||
return ! $item->is_internal;
|
||||
});
|
||||
}
|
||||
|
||||
public function hasAttribute(int|string $key): bool
|
||||
{
|
||||
return $this->objects->has($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export this record
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $scope
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function export(string $method,string $scope): string
|
||||
{
|
||||
// @todo To implement
|
||||
switch ($scope) {
|
||||
case 'base':
|
||||
case 'one':
|
||||
case 'sub':
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \Exception('Export scope unknown:'.$scope);
|
||||
}
|
||||
|
||||
switch ($method) {
|
||||
case 'ldif':
|
||||
return new LDIF(collect($this));
|
||||
|
||||
default:
|
||||
throw new \Exception('Export method not implemented:'.$method);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an icon for a DN based on objectClass
|
||||
*
|
||||
@ -300,4 +408,16 @@ class Entry extends Model
|
||||
// Default
|
||||
return 'fa-fw fas fa-cog';
|
||||
}
|
||||
|
||||
/**
|
||||
* Dont convert our $this->attributes to $this->objects when creating a new Entry::class
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function noObjectAttributes(): static
|
||||
{
|
||||
$this->noObjectAttributes = TRUE;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Performs the export of data from the LDAP server
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
* @subpackage Page
|
||||
*/
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
require './common.php';
|
||||
require LIBDIR.'export_functions.php';
|
||||
|
||||
# Prevent script from bailing early for long search
|
||||
@set_time_limit(0);
|
||||
|
||||
$request = array();
|
||||
$request['file'] = get_request('save_as_file') ? true : false;
|
||||
$request['exporter'] = new Exporter($app['server']->getIndex(),get_request('exporter_id','REQUEST'));
|
||||
$request['export'] = $request['exporter']->getTemplate();
|
||||
$types = $request['export']->getType();
|
||||
|
||||
# send the header
|
||||
if ($request['file']) {
|
||||
$obStatus = ob_get_status();
|
||||
if (isset($obStatus['type']) && $obStatus['type'] && $obStatus['status'])
|
||||
ob_end_clean();
|
||||
|
||||
header('Content-type: application/download');
|
||||
header(sprintf('Content-Disposition: inline; filename="%s.%s"','export',$types['extension'].($request['export']->isCompressed() ? '.gz' : '')));
|
||||
echo $request['export']->export();
|
||||
die();
|
||||
|
||||
} else {
|
||||
print '<span style="font-size: 14px; font-family: courier;"><pre>';
|
||||
echo htmlspecialchars($request['export']->export());
|
||||
print '</pre></span>';
|
||||
}
|
||||
?>
|
@ -1,48 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Displays a form to allow the user to upload and import
|
||||
* an LDIF file.
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
* @subpackage Page
|
||||
*/
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
require './common.php';
|
||||
|
||||
if (! ini_get('file_uploads'))
|
||||
error(_('Your PHP.INI does not have file_uploads = ON. Please enable file uploads in PHP.'),'error','index.php');
|
||||
|
||||
$request['page'] = new PageRender($app['server']->getIndex(),get_request('template','REQUEST',false,'none'));
|
||||
$request['page']->drawTitle(sprintf('<b>%s</b>',_('Import')));
|
||||
$request['page']->drawSubTitle(sprintf('%s: <b>%s</b>',_('Server'),$app['server']->getName()));
|
||||
|
||||
echo '<form action="cmd.php" method="post" class="new_value" enctype="multipart/form-data">';
|
||||
echo '<div>';
|
||||
printf('<input type="hidden" name="server_id" value="%s" />',$app['server']->getIndex());
|
||||
echo '<input type="hidden" name="cmd" value="import" />';
|
||||
echo '</div>';
|
||||
|
||||
echo '<table class="forminput" border="0" style="margin-left: auto; margin-right: auto;">';
|
||||
|
||||
echo '<tr><td colspan="2"> </td></tr>';
|
||||
echo '<tr>';
|
||||
printf('<td>%s</td>',_('Select an LDIF file'));
|
||||
echo '<td>';
|
||||
echo '<input type="file" name="ldif_file" />';
|
||||
echo '</td></tr>';
|
||||
|
||||
printf('<tr><td> </td><td class="small"><b>%s %s</b></td></tr>',_('Maximum file size'),ini_get('upload_max_filesize'));
|
||||
|
||||
echo '<tr><td colspan="2"> </td></tr>';
|
||||
printf('<tr><td>%s</td></tr>',_('Or paste your LDIF here'));
|
||||
echo '<tr><td colspan="2"><textarea name="ldif" rows="20" cols="100"></textarea></td></tr>';
|
||||
echo '<tr><td colspan="2"> </td></tr>';
|
||||
printf('<tr><td> </td><td class="small"><input type="checkbox" name="continuous_mode" value="1" />%s</td></tr>',
|
||||
_("Don't stop on errors"));
|
||||
printf('<tr><td> </td><td><input type="submit" value="%s" /></td></tr>',_('Proceed >>'));
|
||||
echo '</table>';
|
||||
echo '</form>';
|
||||
?>
|
@ -1,643 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Classes and functions for export data from LDAP
|
||||
*
|
||||
* These classes provide differnet export formats.
|
||||
*
|
||||
* @author The phpLDAPadmin development team
|
||||
* @package phpLDAPadmin
|
||||
* @see export.php and export_form.php
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exporter Class
|
||||
*
|
||||
* This class serves as a top level exporter class, which will return
|
||||
* the correct Export class.
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
* @subpackage Export
|
||||
*/
|
||||
class Exporter {
|
||||
# Server ID that the export is linked to
|
||||
private $server_id;
|
||||
# Exporter Type
|
||||
private $template_id;
|
||||
private $template;
|
||||
|
||||
public function __construct($server_id,$template_id) {
|
||||
$this->server_id = $server_id;
|
||||
$this->template_id = $template_id;
|
||||
|
||||
$this->accept();
|
||||
}
|
||||
|
||||
static function types() {
|
||||
$type = array();
|
||||
|
||||
$details = ExportCSV::getType();
|
||||
$type[$details['type']] = $details;
|
||||
$details = ExportDSML::getType();
|
||||
$type[$details['type']] = $details;
|
||||
$details = ExportLDIF::getType();
|
||||
$type[$details['type']] = $details;
|
||||
$details = ExportVCARD::getType();
|
||||
$type[$details['type']] = $details;
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
private function accept() {
|
||||
switch($this->template_id) {
|
||||
case 'CSV':
|
||||
$this->template = new ExportCSV();
|
||||
break;
|
||||
|
||||
case 'DSML':
|
||||
$this->template = new ExportDSML();
|
||||
break;
|
||||
|
||||
case 'LDIF':
|
||||
$this->template = new ExportLDIF();
|
||||
break;
|
||||
|
||||
case 'VCARD':
|
||||
$this->template = new ExportVCARD();
|
||||
break;
|
||||
|
||||
default:
|
||||
system_message(array(
|
||||
'title'=>sprintf('%s %s',_('Unknown Export Type'),$this->template_id),
|
||||
'body'=>_('phpLDAPadmin has not been configured for that export type'),
|
||||
'type'=>'warn'),'index.php');
|
||||
die();
|
||||
}
|
||||
|
||||
$this->template->accept();
|
||||
}
|
||||
|
||||
public function getTemplate() {
|
||||
return $this->template;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export Class
|
||||
*
|
||||
* This abstract classes provides all the common methods and variables for the
|
||||
* custom export classes.
|
||||
*
|
||||
* @package phpLDAPadmin
|
||||
* @subpackage Export
|
||||
*/
|
||||
abstract class Export {
|
||||
# Line Break
|
||||
protected $br;
|
||||
# Compress the output
|
||||
protected $compress;
|
||||
# Export Results
|
||||
protected $results;
|
||||
protected $resultsdata;
|
||||
protected $items = 0;
|
||||
|
||||
/**
|
||||
* Return this LDAP Server object
|
||||
*
|
||||
* @return object DataStore Server
|
||||
*/
|
||||
protected function getServer() {
|
||||
return $_SESSION[APPCONFIG]->getServer($this->getServerID());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the LDAP server ID
|
||||
*
|
||||
* @return int Server ID
|
||||
*/
|
||||
protected function getServerID() {
|
||||
return get_request('server_id','REQUEST');
|
||||
}
|
||||
|
||||
public function accept() {
|
||||
$server = $this->getServer();
|
||||
|
||||
# Get the data to be exported
|
||||
$query = array();
|
||||
$base = get_request('dn','REQUEST');
|
||||
$query['baseok'] = true;
|
||||
$query['filter'] = get_request('filter','REQUEST',false,'objectclass=*');
|
||||
$query['scope'] = get_request('scope','REQUEST',false,'base');
|
||||
$query['deref'] = $_SESSION[APPCONFIG]->getValue('deref','export');
|
||||
$query['size_limit'] = 0;
|
||||
$attrs = get_request('attributes','REQUEST');
|
||||
|
||||
$attrs = preg_replace('/\s+/','',$attrs);
|
||||
if ($attrs)
|
||||
$query['attrs'] = explode(',',$attrs);
|
||||
else
|
||||
$query['attrs'] = array('*');
|
||||
|
||||
if (get_request('sys_attr')) {
|
||||
if (! in_array('*',$query['attrs']))
|
||||
array_push($query['attrs'],'*');
|
||||
array_push($query['attrs'],'+');
|
||||
}
|
||||
|
||||
if (! $base)
|
||||
$bases = $server->getBaseDN();
|
||||
else
|
||||
$bases = array($base);
|
||||
|
||||
foreach ($bases as $base) {
|
||||
$query['base'] = $base;
|
||||
|
||||
$time_start = utime();
|
||||
$this->results[$base] = $server->query($query,null);
|
||||
$time_end = utime();
|
||||
|
||||
usort($this->results[$base],'pla_compare_dns');
|
||||
$this->resultsdata[$base]['time'] = round($time_end-$time_start,2);
|
||||
|
||||
# If no result, there is a something wrong
|
||||
if (! $this->results[$base] && $server->getErrorNum(null))
|
||||
system_message(array(
|
||||
'title'=>_('Encountered an error while performing search.'),
|
||||
'body'=>ldap_error_msg($server->getErrorMessage(null),$server->getErrorNum(null)),
|
||||
'type'=>'error'));
|
||||
|
||||
$this->items += count($this->results[$base]);
|
||||
}
|
||||
|
||||
$this->resultsdata['scope'] = $query['scope'];
|
||||
$this->resultsdata['filter'] = $query['filter'];
|
||||
$this->resultsdata['attrs'] = $query['attrs'];
|
||||
|
||||
# Other settings
|
||||
switch (get_request('format','POST',false,'unix')) {
|
||||
case 'win':
|
||||
$this->br = "\r\n";
|
||||
break;
|
||||
|
||||
case 'mac':
|
||||
$this->br = "\r";
|
||||
break;
|
||||
|
||||
case 'unix':
|
||||
default:
|
||||
$this->br = "\n";
|
||||
}
|
||||
|
||||
if (get_request('compress','REQUEST') == 'on')
|
||||
$this->compress = true;
|
||||
}
|
||||
|
||||
public function isCompressed() {
|
||||
return $this->compress;
|
||||
}
|
||||
|
||||
protected function getHeader() {
|
||||
$server = $this->getServer();
|
||||
$type = $this->getType();
|
||||
|
||||
$output = '';
|
||||
|
||||
$output .= sprintf('# %s %s %s%s',$type['description'],_('for'),implode('|',array_keys($this->results)),$this->br);
|
||||
$output .= sprintf('# %s: %s (%s)%s',_('Server'),$server->getName(),$server->getValue('server','host'),$this->br);
|
||||
$output .= sprintf('# %s: %s%s',_('Search Scope'),$this->resultsdata['scope'],$this->br);
|
||||
$output .= sprintf('# %s: %s%s',_('Search Filter'),$this->resultsdata['filter'],$this->br);
|
||||
$output .= sprintf('# %s: %s%s',_('Total Entries'),$this->items,$this->br);
|
||||
$output .= sprintf('#%s',$this->br);
|
||||